Title: [101901] trunk/Tools
Revision
101901
Author
[email protected]
Date
2011-12-02 20:59:22 -0800 (Fri, 02 Dec 2011)

Log Message

ChangeLog should be able to parse annotated changelogs
https://bugs.webkit.org/show_bug.cgi?id=72703

Reviewed by Eric Seidel.

Make parse_entries_from_file aware of svn blame annotation such as "100000 [email protected] ",
and extract the revision number for each entry.

Also add a support to extract "svn blame" result from svn/git checkout to scm classes.

* Scripts/webkitpy/common/checkout/changelog.py:
* Scripts/webkitpy/common/checkout/changelog_unittest.py:
* Scripts/webkitpy/common/checkout/scm/git.py:
* Scripts/webkitpy/common/checkout/scm/scm.py:
* Scripts/webkitpy/common/checkout/scm/svn.py:

Modified Paths

Diff

Modified: trunk/Tools/ChangeLog (101900 => 101901)


--- trunk/Tools/ChangeLog	2011-12-03 04:54:22 UTC (rev 101900)
+++ trunk/Tools/ChangeLog	2011-12-03 04:59:22 UTC (rev 101901)
@@ -1,3 +1,21 @@
+2011-12-02  Ryosuke Niwa  <[email protected]>
+
+        ChangeLog should be able to parse annotated changelogs
+        https://bugs.webkit.org/show_bug.cgi?id=72703
+
+        Reviewed by Eric Seidel.
+
+        Make parse_entries_from_file aware of svn blame annotation such as "100000 [email protected] ",
+        and extract the revision number for each entry.
+
+        Also add a support to extract "svn blame" result from svn/git checkout to scm classes.
+
+        * Scripts/webkitpy/common/checkout/changelog.py:
+        * Scripts/webkitpy/common/checkout/changelog_unittest.py:
+        * Scripts/webkitpy/common/checkout/scm/git.py:
+        * Scripts/webkitpy/common/checkout/scm/scm.py:
+        * Scripts/webkitpy/common/checkout/scm/svn.py:
+
 2011-12-02  Eric Seidel  <[email protected]>
 
         Enable parallel testing for Win and Gtk bots

Modified: trunk/Tools/Scripts/webkitpy/common/checkout/changelog.py (101900 => 101901)


--- trunk/Tools/Scripts/webkitpy/common/checkout/changelog.py	2011-12-03 04:54:22 UTC (rev 101900)
+++ trunk/Tools/Scripts/webkitpy/common/checkout/changelog.py	2011-12-03 04:59:22 UTC (rev 101901)
@@ -111,9 +111,10 @@
     # e.g. git-svn-id: http://svn.webkit.org/repository/webkit/trunk@96161 268f45cc-cd09-0410-ab3c-d52691b4dbfc
     svn_id_regexp = r'git-svn-id: http://svn.webkit.org/repository/webkit/trunk@(?P<svnid>\d+) '
 
-    def __init__(self, contents, committer_list=CommitterList()):
+    def __init__(self, contents, committer_list=CommitterList(), revision=None):
         self._contents = contents
         self._committer_list = committer_list
+        self._revision = revision
         self._parse_entry()
 
     @staticmethod
@@ -186,6 +187,9 @@
     def author_text(self):
         return self._author_text
 
+    def revision(self):
+        return self._revision
+
     def author_name(self):
         return self._authors[0]['name']
 
@@ -259,28 +263,52 @@
             entry_lines.append(line)
         return None # We never found a date line!
 
+    svn_blame_regexp = re.compile(r'^(\s*(?P<revision>\d+) [^ ]+)\s(?P<line>.*?\n)')
+
     @staticmethod
+    def _separate_revision_and_line(line):
+        match = ChangeLog.svn_blame_regexp.match(line)
+        if not match:
+            return None, line
+        return int(match.group('revision')), match.group('line')
+
+    @staticmethod
     def parse_entries_from_file(changelog_file):
         """changelog_file must be a file-like object which returns
         unicode strings.  Use codecs.open or StringIO(unicode())
         to pass file objects to this class."""
         date_line_regexp = re.compile(ChangeLogEntry.date_line_regexp)
         rolled_over_regexp = re.compile(ChangeLogEntry.rolled_over_regexp)
-        entry_lines = []
+
         # The first line should be a date line.
-        first_line = changelog_file.readline()
+        revision, first_line = ChangeLog._separate_revision_and_line(changelog_file.readline())
         assert(isinstance(first_line, unicode))
-        if not date_line_regexp.match(first_line):
+        if not date_line_regexp.match(ChangeLog.svn_blame_regexp.sub('', first_line)):
             raise StopIteration
-        entry_lines.append(first_line)
 
+        entry_lines = [first_line]
+        revisions_in_entry = {revision: 1} if revision != None else None
         for line in changelog_file:
-            if date_line_regexp.match(line) or rolled_over_regexp.match(line):
+            if revisions_in_entry:
+                revision, line = ChangeLog._separate_revision_and_line(line)
+
+            if rolled_over_regexp.match(line):
+                break
+
+            if date_line_regexp.match(line):
+                most_probable_revision = max(revisions_in_entry, key=revisions_in_entry.__getitem__) if revisions_in_entry else None
                 # Remove the extra newline at the end
-                yield ChangeLogEntry(''.join(entry_lines[:-1]))
+                yield ChangeLogEntry(''.join(entry_lines[:-1]), revision=most_probable_revision)
                 entry_lines = []
+                revisions_in_entry = {revision: 0}
+
             entry_lines.append(line)
+            if revisions_in_entry:
+                revisions_in_entry[revision] = revisions_in_entry.get(revision, 0) + 1
 
+        most_probable_revision = max(revisions_in_entry, key=revisions_in_entry.__getitem__) if revisions_in_entry else None
+        yield ChangeLogEntry(''.join(entry_lines[:-1]), revision=most_probable_revision)
+
     def latest_entry(self):
         # ChangeLog files are always UTF-8, we read them in as such to support Reviewers with unicode in their names.
         changelog_file = codecs.open(self.path, "r", "utf-8")

Modified: trunk/Tools/Scripts/webkitpy/common/checkout/changelog_unittest.py (101900 => 101901)


--- trunk/Tools/Scripts/webkitpy/common/checkout/changelog_unittest.py	2011-12-03 04:54:22 UTC (rev 101900)
+++ trunk/Tools/Scripts/webkitpy/common/checkout/changelog_unittest.py	2011-12-03 04:59:22 UTC (rev 101901)
@@ -251,6 +251,52 @@
         self.assertEquals(parsed_entries[7].reviewer_text(), None)
         self.assertEquals(parsed_entries[8].reviewer_text(), 'Darin Adler')
 
+    def test_parse_log_entries_from_annotated_file(self):
+        changelog_file = StringIO(u'''100000 [email protected] 2011-11-11  Csaba Osztrogon\u00e1c  <[email protected]>
+100000 [email protected] 
+100000 [email protected]         100,000 !!!
+100000 [email protected] 
+100000 [email protected]         Reviewed by Zoltan Herczeg.
+100000 [email protected] 
+100000 [email protected]         * ChangeLog: Point out revision 100,000.
+100000 [email protected]
+93798 [email protected] 2011-08-25  Alexey Proskuryakov  <[email protected]>
+93798 [email protected] 
+93798 [email protected]         Fix build when GCC 4.2 is not installed.
+93798 [email protected] 
+93798 [email protected]         * gtest/xcode/Config/CompilerVersion.xcconfig: Copied from Source/WebCore/Configurations/CompilerVersion.xcconfig.
+93798 [email protected]         * gtest/xcode/Config/General.xcconfig:
+93798 [email protected]         Use the same compiler version as other projects do.
+93798 [email protected]
+99491 [email protected] 2011-11-03  Andreas Kling  <[email protected]>
+99491 [email protected] 
+99190 [email protected]         Unreviewed build fix, sigh.
+99190 [email protected] 
+99190 [email protected]         * css/CSSFontFaceRule.h:
+99190 [email protected]         * css/CSSMutableStyleDeclaration.h:
+99190 [email protected] 
+99190 [email protected] 2011-11-03  Andreas Kling  <[email protected]>
+99190 [email protected] 
+99187 [email protected]         Unreviewed build fix, out-of-line StyleSheet::parentStyleSheet()
+99187 [email protected]         again since there's a cycle in the includes between CSSRule/StyleSheet.
+99187 [email protected] 
+99187 [email protected]         * css/StyleSheet.cpp:
+99187 [email protected]         (WebCore::StyleSheet::parentStyleSheet):
+99187 [email protected]         * css/StyleSheet.h:
+99187 [email protected] 
+''')
+        parsed_entries = list(ChangeLog.parse_entries_from_file(changelog_file))
+        self.assertEquals(parsed_entries[0].revision(), 100000)
+        self.assertEquals(parsed_entries[0].reviewer_text(), "Zoltan Herczeg")
+        self.assertEquals(parsed_entries[0].author_name(), u"Csaba Osztrogon\u00e1c")
+        self.assertEquals(parsed_entries[0].author_email(), "[email protected]")
+        self.assertEquals(parsed_entries[1].revision(), 93798)
+        self.assertEquals(parsed_entries[1].author_name(), "Alexey Proskuryakov")
+        self.assertEquals(parsed_entries[2].revision(), 99190)
+        self.assertEquals(parsed_entries[2].author_name(), "Andreas Kling")
+        self.assertEquals(parsed_entries[3].revision(), 99187)
+        self.assertEquals(parsed_entries[3].author_name(), "Andreas Kling")
+
     def _assert_parse_reviewer_text_and_list(self, text, expected_reviewer_text, expected_reviewer_text_list=None):
         reviewer_text, reviewer_text_list = ChangeLogEntry._parse_reviewer_text(text)
         self.assertEquals(reviewer_text, expected_reviewer_text)

Modified: trunk/Tools/Scripts/webkitpy/common/checkout/scm/git.py (101900 => 101901)


--- trunk/Tools/Scripts/webkitpy/common/checkout/scm/git.py	2011-12-03 04:54:22 UTC (rev 101900)
+++ trunk/Tools/Scripts/webkitpy/common/checkout/scm/git.py	2011-12-03 04:59:22 UTC (rev 101901)
@@ -401,6 +401,9 @@
     def last_svn_commit_log(self):
         return self.run(['git', 'svn', 'log', '--limit=1'])
 
+    def svn_blame(self, path):
+        return self.run(['git', 'svn', 'blame', path])
+
     # Git-specific methods:
     def _branch_ref_exists(self, branch_ref):
         return self.run(['git', 'show-ref', '--quiet', '--verify', branch_ref], return_exit_code=True) == 0

Modified: trunk/Tools/Scripts/webkitpy/common/checkout/scm/scm.py (101900 => 101901)


--- trunk/Tools/Scripts/webkitpy/common/checkout/scm/scm.py	2011-12-03 04:54:22 UTC (rev 101900)
+++ trunk/Tools/Scripts/webkitpy/common/checkout/scm/scm.py	2011-12-03 04:59:22 UTC (rev 101901)
@@ -218,6 +218,9 @@
     def last_svn_commit_log(self):
         self._subclass_must_implement()
 
+    def svn_blame(self, path):
+        self._subclass_must_implement()
+
     # Subclasses must indicate if they support local commits,
     # but the SCM baseclass will only call local_commits methods when this is true.
     @staticmethod

Modified: trunk/Tools/Scripts/webkitpy/common/checkout/scm/svn.py (101900 => 101901)


--- trunk/Tools/Scripts/webkitpy/common/checkout/scm/svn.py	2011-12-03 04:54:22 UTC (rev 101900)
+++ trunk/Tools/Scripts/webkitpy/common/checkout/scm/svn.py	2011-12-03 04:59:22 UTC (rev 101901)
@@ -350,6 +350,9 @@
         # http://svnbook.red-bean.com/en/1.0/ch03s03.html
         return self.svn_commit_log('BASE')
 
+    def svn_blame(self, path):
+        return self._run_svn(['blame', path])
+
     def propset(self, pname, pvalue, path):
         dir, base = os.path.split(path)
         return self._run_svn(['pset', pname, pvalue, base], cwd=dir)
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to