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)