示例#1
0
 def _ensure_bug_url(self, state):
     if not state.get("bug_id"):
         return
     bug_id = state.get("bug_id")
     changelogs = self.cached_lookup(state, "changelogs")
     for changelog_path in changelogs:
         changelog = ChangeLog(changelog_path)
         if not changelog.latest_entry().bug_id():
             changelog.set_short_description_and_bug_url(
                 self.cached_lookup(state, "bug_title"),
                 self._tool.bugs.bug_url_for_bug_id(bug_id))
 def _assert_message_for_revert_output(self, args, expected_entry):
     changelog_contents = u"%s\n%s" % (changelog_unittest.ChangeLogTest._new_entry_boilerplate, changelog_unittest.ChangeLogTest._example_changelog)
     changelog_path = self._write_tmp_file_with_contents(changelog_contents.encode("utf-8"))
     changelog = ChangeLog(changelog_path)
     changelog.update_with_unreviewed_message(PrepareChangeLogForRevert._message_for_revert(*args))
     actual_entry = changelog.latest_entry()
     os.remove(changelog_path)
     self.assertEqual(actual_entry.contents(), expected_entry)
     self.assertEqual(actual_entry.reviewer_text(), None)
     # These checks could be removed to allow this to work on other entries:
     self.assertEqual(actual_entry.author_name(), "Eric Seidel")
     self.assertEqual(actual_entry.author_email(), "*****@*****.**")
 def run(self, state):
     # FIXME: For now we disable this check when a user is driving the script
     # this check is too draconian (and too poorly tested) to foist upon users.
     if not self._options.non_interactive:
         return
     for changelog_path in self.cached_lookup(state, "changelogs"):
         changelog_entry = ChangeLog(changelog_path).latest_entry()
         if self._has_valid_reviewer(changelog_entry):
             continue
         reviewer_text = changelog_entry.reviewer_text()
         if reviewer_text:
             log("%s found in %s does not appear to be a valid reviewer according to committers.py." % (reviewer_text, changelog_path))
         error('%s neither lists a valid reviewer nor contains the string "Unreviewed" or "Rubber stamp" (case insensitive).' % changelog_path)
示例#4
0
 def run(self, state):
     # FIXME: For now we disable this check when a user is driving the script
     # this check is too draconian (and too poorly tested) to foist upon users.
     if not self._options.non_interactive:
         return
     # FIXME: We should figure out how to handle the current working
     #        directory issue more globally.
     os.chdir(self._tool.scm().checkout_root)
     for changelog_path in self._tool.checkout().modified_changelogs(self._options.git_commit, self._options.squash):
         changelog_entry = ChangeLog(changelog_path).latest_entry()
         if self._has_valid_reviewer(changelog_entry):
             continue
         reviewer_text = changelog_entry.reviewer_text()
         if reviewer_text:
             log("%s found in %s does not appear to be a valid reviewer according to committers.py." % (reviewer_text, changelog_path))
         error('%s neither lists a valid reviewer nor contains the string "Unreviewed" or "Rubber stamp" (case insensitive).' % changelog_path)
示例#5
0
    def commit_message_for_this_commit(self, git_commit, changed_files=None):
        changelog_paths = self.modified_changelogs(git_commit, changed_files)
        if not len(changelog_paths):
            raise ScriptError(message="Found no modified ChangeLogs, cannot create a commit message.\n"
                              "All changes require a ChangeLog.  See:\n %s" % urls.contribution_guidelines)

        changelog_messages = []
        for changelog_path in changelog_paths:
            log("Parsing ChangeLog: %s" % changelog_path)
            changelog_entry = ChangeLog(changelog_path).latest_entry()
            if not changelog_entry:
                raise ScriptError(message="Failed to parse ChangeLog: %s" % os.path.abspath(changelog_path))
            changelog_messages.append(changelog_entry.contents())

        # FIXME: We should sort and label the ChangeLog messages like commit-log-editor does.
        return CommitMessage("".join(changelog_messages).splitlines())
示例#6
0
 def _latest_entry_for_changelog_at_revision(self, changelog_path, revision):
     changelog_contents = self._scm.contents_at_revision(changelog_path, revision)
     # contents_at_revision returns a byte array (str()), but we know
     # that ChangeLog files are utf-8.  parse_latest_entry_from_file
     # expects a file-like object which vends unicode(), so we decode here.
     changelog_file = StringIO.StringIO(changelog_contents.decode("utf-8"))
     return ChangeLog.parse_latest_entry_from_file(changelog_file)
示例#7
0
 def _latest_entry_for_changelog_at_revision(self, changelog_path, revision):
     changelog_contents = self._scm.contents_at_revision(changelog_path, revision)
     # contents_at_revision returns a byte array (str()), but we know
     # that ChangeLog files are utf-8.  parse_latest_entry_from_file
     # expects a file-like object which vends unicode(), so we decode here.
     # Old revisions of Sources/WebKit/wx/ChangeLog have some invalid utf8 characters.
     changelog_file = StringIO.StringIO(changelog_contents.decode("utf-8", "ignore"))
     return ChangeLog.parse_latest_entry_from_file(changelog_file)
示例#8
0
 def analyze(self):
     for path in self._changelog_paths:
         self._set_filename(self._filesystem.relpath(path, self._scm.checkout_root))
         with self._filesystem.open_text_file_for_reading(path) as changelog:
             self._print_status('Parsing entries...')
             number_of_parsed_entries = self._analyze_entries(ChangeLog.parse_entries_from_file(changelog), path)
         self._print_status('Done (%d entries)' % number_of_parsed_entries)
     print
     self._summary['contributors'] = len(self._contributors_statistics)
     self._summary['contributors_with_reviews'] = sum([1 for contributor in self._contributors_statistics.values() if contributor['reviews']['total']])
     self._summary['contributors_without_reviews'] = self._summary['contributors'] - self._summary['contributors_with_reviews']
示例#9
0
    def test_parse_log_entries_from_annotated_file(self):
        # Note that there are trailing spaces on some of the lines intentionally.
        changelog_file = StringIO(
            u"100000 [email protected] 2011-11-11  Csaba Osztrogon\u00e1c  <*****@*****.**>\n"
            u"100000 [email protected]\n"
            u"100000 [email protected]         100,000 !!!\n"
            u"100000 [email protected] \n"
            u"100000 [email protected]         Reviewed by Zoltan Herczeg.\n"
            u"100000 [email protected] \n"
            u"100000 [email protected]         * ChangeLog: Point out revision 100,000.\n"
            u"100000 [email protected] \n"
            u"93798 [email protected] 2011-08-25  Alexey Proskuryakov  <*****@*****.**>\n"
            u"93798 [email protected] \n"
            u"93798 [email protected]         Fix build when GCC 4.2 is not installed.\n"
            u"93798 [email protected] \n"
            u"93798 [email protected]         * gtest/xcode/Config/CompilerVersion.xcconfig: Copied from Source/WebCore/Configurations/CompilerVersion.xcconfig.\n"
            u"93798 [email protected]         * gtest/xcode/Config/General.xcconfig:\n"
            u"93798 [email protected]         Use the same compiler version as other projects do.\n"
            u"93798 [email protected]\n"
            u"99491 [email protected] 2011-11-03  Andreas Kling  <*****@*****.**>\n"
            u"99491 [email protected] \n"
            u"99190 [email protected]         Unreviewed build fix, sigh.\n"
            u"99190 [email protected] \n"
            u"99190 [email protected]         * css/CSSFontFaceRule.h:\n"
            u"99190 [email protected]         * css/CSSMutableStyleDeclaration.h:\n"
            u"99190 [email protected]\n"
            u"99190 [email protected] 2011-11-03  Andreas Kling  <*****@*****.**>\n"
            u"99190 [email protected] \n"
            u"99187 [email protected]         Unreviewed build fix, out-of-line StyleSheet::parentStyleSheet()\n"
            u"99187 [email protected]         again since there's a cycle in the includes between CSSRule/StyleSheet.\n"
            u"99187 [email protected] \n"
            u"99187 [email protected]         * css/StyleSheet.cpp:\n"
            u"99187 [email protected]         (WebCore::StyleSheet::parentStyleSheet):\n"
            u"99187 [email protected]         * css/StyleSheet.h:\n"
            u"99187 [email protected] \n")

        parsed_entries = list(
            ChangeLog.parse_entries_from_file(changelog_file))
        self.assertEqual(parsed_entries[0].revision(), 100000)
        self.assertEqual(parsed_entries[0].reviewer_text(), "Zoltan Herczeg")
        self.assertEqual(parsed_entries[0].author_name(),
                         u"Csaba Osztrogon\u00e1c")
        self.assertEqual(parsed_entries[0].author_email(), "*****@*****.**")
        self.assertEqual(parsed_entries[1].revision(), 93798)
        self.assertEqual(parsed_entries[1].author_name(),
                         "Alexey Proskuryakov")
        self.assertEqual(parsed_entries[2].revision(), 99190)
        self.assertEqual(parsed_entries[2].author_name(), "Andreas Kling")
        self.assertEqual(parsed_entries[3].revision(), 99187)
        self.assertEqual(parsed_entries[3].author_name(), "Andreas Kling")
 def run(self, state):
     # This could move to prepare-ChangeLog by adding a --revert= option.
     self._tool.executive.run_and_throw_if_fail(
         self._tool.deprecated_port().prepare_changelog_command(),
         cwd=self._tool.scm().checkout_root)
     changelog_paths = self._tool.checkout().modified_changelogs(
         git_commit=None)
     bug_url = self._tool.bugs.bug_url_for_bug_id(
         state["bug_id"]) if state["bug_id"] else None
     message = self._message_for_revert(state["revision_list"],
                                        state["reason"], bug_url)
     for changelog_path in changelog_paths:
         # FIXME: Seems we should prepare the message outside of changelogs.py and then just pass in
         # text that we want to use to replace the reviewed by line.
         ChangeLog(changelog_path).update_with_unreviewed_message(message)
示例#11
0
 def analyze(self):
     for path in self._changelog_paths:
         self._set_filename(
             self._filesystem.relpath(path, self._scm.checkout_root))
         with self._filesystem.open_text_file_for_reading(
                 path) as changelog:
             self._print_status('Parsing entries...')
             number_of_parsed_entries = self._analyze_entries(
                 ChangeLog.parse_entries_from_file(changelog), path)
         self._print_status('Done (%d entries)' % number_of_parsed_entries)
     print
     self._summary['contributors'] = len(self._contributors_statistics)
     self._summary['contributors_with_reviews'] = sum([
         1 for contributor in self._contributors_statistics.values()
         if contributor['reviews']['total']
     ])
     self._summary['contributors_without_reviews'] = self._summary[
         'contributors'] - self._summary['contributors_with_reviews']
示例#12
0
    def run(self, state):
        bug_id = state.get("bug_id")
        if not bug_id and state.get("patch"):
            bug_id = state.get("patch").bug_id()

        reviewer = self._options.reviewer
        if not reviewer:
            if not bug_id:
                log("No bug id provided and --reviewer= not provided.  Not updating ChangeLogs with reviewer.")
                return
            reviewer = self._guess_reviewer_from_bug(bug_id)

        if not reviewer:
            log("Failed to guess reviewer from bug %s and --reviewer= not provided.  Not updating ChangeLogs with reviewer." % bug_id)
            return

        os.chdir(self._tool.scm().checkout_root)
        for changelog_path in self._tool.checkout().modified_changelogs(self._options.git_commit, self._options.squash):
            ChangeLog(changelog_path).set_reviewer(reviewer)
示例#13
0
 def _ensure_bug_url(self, state):
     if not state.get("bug_id"):
         return
     bug_id = state.get("bug_id")
     changelogs = self.cached_lookup(state, "changelogs")
     for changelog_path in changelogs:
         changelog = ChangeLog(changelog_path, self._tool.filesystem)
         if not changelog.latest_entry():
             _log.error('Invalid ChangeLog at: {}'.format(changelog_path))
             sys.exit(1)
         if not changelog.latest_entry().bug_id():
             changelog.set_short_description_and_bug_url(
                 self.cached_lookup(state, "bug_title"),
                 self._tool.bugs.bug_url_for_bug_id(bug_id))
示例#14
0
    def test_latest_entry_parse(self):
        changelog_contents = u"%s\n%s" % (self._example_entry,
                                          self._example_changelog)
        changelog_file = StringIO(changelog_contents)
        latest_entry = ChangeLog.parse_latest_entry_from_file(changelog_file)
        self.assertEqual(latest_entry.contents(), self._example_entry)
        self.assertEqual(latest_entry.author_name(), "Peter Kasting")
        self.assertEqual(latest_entry.author_email(), "*****@*****.**")
        self.assertEqual(latest_entry.reviewer_text(),
                         u"Fr\u00e9d\u00e9ric Wang")
        touched_files = [
            "DumpRenderTree/win/DumpRenderTree.vcproj",
            "DumpRenderTree/win/ImageDiff.vcproj",
            "DumpRenderTree/win/TestNetscapePlugin/TestNetscapePlugin.vcproj"
        ]
        self.assertEqual(latest_entry.touched_files(), touched_files)
        self.assertEqual(latest_entry.touched_functions(),
                         dict((f, []) for f in touched_files))

        self.assertTrue(latest_entry.reviewer()
                        )  # Make sure that our UTF8-based lookup of Tor works.
    def run(self, state):
        bug_id = state.get("bug_id")
        if not bug_id and state.get("patch"):
            bug_id = state.get("patch").bug_id()

        reviewer = self._options.reviewer
        if not reviewer:
            if not bug_id:
                log("No bug id provided and --reviewer= not provided.  Not updating ChangeLogs with reviewer.")
                return
            reviewer = self._guess_reviewer_from_bug(bug_id)

        if not reviewer:
            log("Failed to guess reviewer from bug %s and --reviewer= not provided.  Not updating ChangeLogs with reviewer." % bug_id)
            return

        # cached_lookup("changelogs") is always absolute paths.
        for changelog_path in self.cached_lookup(state, "changelogs"):
            ChangeLog(changelog_path).set_reviewer(reviewer)

        # Tell the world that we just changed something on disk so that the cached diff is invalidated.
        self.did_modify_checkout(state)
示例#16
0
    def _resolve_existing_entry(self, changelog_path):
        # When this is called, the top entry in the ChangeLog was just created
        # by prepare-ChangeLog, as an clean updated version of the one below it.
        with self._tool.filesystem.open_text_file_for_reading(changelog_path) as changelog_file:
            entries_gen = ChangeLog.parse_entries_from_file(changelog_file)
            entries = zip(entries_gen, range(2))

        if not len(entries):
            raise Exception("Expected to find at least two ChangeLog entries in %s but found none." % changelog_path)
        if len(entries) == 1:
            # If we get here, it probably means we've just rolled over to a
            # new CL file, so we don't have anything to resolve.
            return

        (new_entry, _), (old_entry, _) = entries
        final_entry = self._merge_entries(old_entry, new_entry)

        changelog = ChangeLog(changelog_path, self._tool.filesystem)
        changelog.delete_entries(2)
        changelog.prepend_text(final_entry)
示例#17
0
    def _resolve_existing_entry(self, changelog_path):
        # When this is called, the top entry in the ChangeLog was just created
        # by prepare-ChangeLog, as an clean updated version of the one below it.
        with self._tool.filesystem.open_text_file_for_reading(changelog_path) as changelog_file:
            entries_gen = ChangeLog.parse_entries_from_file(changelog_file)
            entries = zip(entries_gen, range(2))

        if not len(entries):
            raise Exception("Expected to find at least two ChangeLog entries in %s but found none." % changelog_path)
        if len(entries) == 1:
            # If we get here, it probably means we've just rolled over to a
            # new CL file, so we don't have anything to resolve.
            return

        (new_entry, _), (old_entry, _) = entries
        final_entry = self._merge_entries(old_entry, new_entry)

        changelog = ChangeLog(changelog_path, self._tool.filesystem)
        changelog.delete_entries(2)
        changelog.prepend_text(final_entry)
示例#18
0
 def _latest_entry_for_changelog_at_revision(self, changelog_path, revision):
     changelog_contents = self._scm.contents_at_revision(changelog_path, revision)
     return ChangeLog.parse_latest_entry_from_file(StringIO.StringIO(changelog_contents))
示例#19
0
 def test_parse_log_entries_from_changelog(self):
     changelog_file = StringIO(self._example_changelog)
     parsed_entries = list(
         ChangeLog.parse_entries_from_file(changelog_file))
     self.assertEqual(len(parsed_entries), 9)
     self.assertEqual(
         parsed_entries[0].date_line(),
         u"2009-08-17  Fr\u00e9d\u00e9ric Wang  <*****@*****.**>")
     self.assertEqual(parsed_entries[0].date(), "2009-08-17")
     self.assertEqual(parsed_entries[0].reviewer_text(), "David Levin")
     self.assertEqual(parsed_entries[0].is_touched_files_text_clean(),
                      False)
     self.assertIsNone(parsed_entries[0].bug_description())
     self.assertEqual(parsed_entries[1].date_line(),
                      "2009-08-16  David Kilzer  <*****@*****.**>")
     self.assertEqual(parsed_entries[1].date(), "2009-08-16")
     self.assertEqual(parsed_entries[1].author_email(),
                      "*****@*****.**")
     self.assertEqual(parsed_entries[1].bug_description(),
                      "Backed out r47343 which was mistakenly committed")
     self.assertEqual(
         parsed_entries[1].touched_files_text(),
         "        * Scripts/bugzilla-tool:\n        * Scripts/modules/scm.py:\n"
     )
     self.assertEqual(parsed_entries[1].is_touched_files_text_clean(), True)
     self.assertEqual(parsed_entries[2].reviewer_text(), "Mark Rowe")
     self.assertEqual(parsed_entries[2].touched_files(),
                      ["DumpRenderTree/mac/DumpRenderTreeWindow.mm"])
     self.assertEqual(
         parsed_entries[2].touched_functions(), {
             "DumpRenderTree/mac/DumpRenderTreeWindow.mm":
             ["-[DumpRenderTreeWindow close]"]
         })
     self.assertEqual(parsed_entries[2].is_touched_files_text_clean(),
                      False)
     self.assertIsNone(parsed_entries[2].bug_description())
     self.assertEqual(parsed_entries[3].author_name(), "Benjamin Poulain")
     self.assertEqual(parsed_entries[3].touched_files(), [
         "platform/cf/KURLCFNet.cpp", "platform/mac/KURLMac.mm",
         "WebCoreSupport/ChromeClientEfl.cpp", "ewk/ewk_private.h",
         "ewk/ewk_view.cpp"
     ])
     self.assertEqual(
         parsed_entries[3].touched_functions(), {
             "platform/cf/KURLCFNet.cpp": [
                 "WebCore::createCFURLFromBuffer",
                 "WebCore::KURL::createCFURL"
             ],
             "platform/mac/KURLMac.mm": [
                 "WebCore::KURL::operator NSURL *",
                 "WebCore::KURL::createCFURL"
             ],
             "WebCoreSupport/ChromeClientEfl.cpp":
             ["WebCore::ChromeClientEfl::closeWindowSoon"],
             "ewk/ewk_private.h": [],
             "ewk/ewk_view.cpp": []
         })
     self.assertEqual(
         parsed_entries[3].bug_description(),
         "[Mac] ResourceRequest's nsURLRequest() does not differentiate null and empty URLs with CFNetwork"
     )
     self.assertEqual(parsed_entries[4].reviewer_text(), "David Hyatt")
     self.assertIsNone(parsed_entries[4].bug_description())
     self.assertEqual(parsed_entries[5].reviewer_text(), "Adam Roben")
     self.assertIsNone(parsed_entries[5].bug_description())
     self.assertEqual(parsed_entries[6].reviewer_text(), "Tony Chang")
     self.assertIsNone(parsed_entries[6].bug_description())
     self.assertIsNone(parsed_entries[7].reviewer_text())
     self.assertEqual(parsed_entries[7].bug_description(),
                      "Unreviewed warning fix.")
     self.assertEqual(parsed_entries[8].reviewer_text(), 'Darin Adler')
     self.assertEqual(
         parsed_entries[8].bug_description(),
         'Resolve regular and visited link style in a single pass')
 def run(self, state):
     self._tool.executive.run_and_throw_if_fail(self._tool.port().prepare_changelog_command())
     changelog_paths = self._tool.checkout().modified_changelogs(git_commit=None)
     for changelog_path in changelog_paths:
         ChangeLog(changelog_path).update_with_unreviewed_message("Rolled DEPS.\n\n")