- a/Tools/ChangeLog +18 lines
Lines 1-3 a/Tools/ChangeLog_sec1
1
2011-11-18  Ryosuke Niwa  <rniwa@webkit.org>
2
3
        ChangeLog should be able to parse annotated changelogs
4
        https://bugs.webkit.org/show_bug.cgi?id=72703
5
6
        Reviewed by NOBODY (OOPS!).
7
8
        Make parse_entries_from_file aware of svn blame annotation such as "100000 ossy@webkit.org ",
9
        and extract the revision number for each entry.
10
11
        Also add a support to extract "svn blame" result from svn/git checkout to scm classes.
12
13
        * Scripts/webkitpy/common/checkout/changelog.py:
14
        * Scripts/webkitpy/common/checkout/changelog_unittest.py:
15
        * Scripts/webkitpy/common/checkout/scm/git.py:
16
        * Scripts/webkitpy/common/checkout/scm/scm.py:
17
        * Scripts/webkitpy/common/checkout/scm/svn.py:
18
1
2011-11-17  Raphael Kubo da Costa  <kubo@profusion.mobi>
19
2011-11-17  Raphael Kubo da Costa  <kubo@profusion.mobi>
2
20
3
        [EFL] Clean up the use of DATA_DIR in the buildsystem
21
        [EFL] Clean up the use of DATA_DIR in the buildsystem
- a/Tools/Scripts/webkitpy/common/checkout/changelog.py -7 / +35 lines
Lines 110-118 class ChangeLogEntry(object): a/Tools/Scripts/webkitpy/common/checkout/changelog.py_sec1
110
    # e.g. git-svn-id: http://svn.webkit.org/repository/webkit/trunk@96161 268f45cc-cd09-0410-ab3c-d52691b4dbfc
110
    # e.g. git-svn-id: http://svn.webkit.org/repository/webkit/trunk@96161 268f45cc-cd09-0410-ab3c-d52691b4dbfc
111
    svn_id_regexp = r'git-svn-id: http://svn.webkit.org/repository/webkit/trunk@(?P<svnid>\d+) '
111
    svn_id_regexp = r'git-svn-id: http://svn.webkit.org/repository/webkit/trunk@(?P<svnid>\d+) '
112
112
113
    def __init__(self, contents, committer_list=CommitterList()):
113
    def __init__(self, contents, committer_list=CommitterList(), revision=None):
114
        self._contents = contents
114
        self._contents = contents
115
        self._committer_list = committer_list
115
        self._committer_list = committer_list
116
        self._revision = revision
116
        self._parse_entry()
117
        self._parse_entry()
117
118
118
    @staticmethod
119
    @staticmethod
Lines 167-172 class ChangeLogEntry(object): a/Tools/Scripts/webkitpy/common/checkout/changelog.py_sec2
167
168
168
        self._touched_files = re.findall(self.touched_files_regexp, self._contents, re.MULTILINE)
169
        self._touched_files = re.findall(self.touched_files_regexp, self._contents, re.MULTILINE)
169
170
171
    def revision(self):
172
        return self._revision
173
170
    def author_name(self):
174
    def author_name(self):
171
        return self._author_name
175
        return self._author_name
172
176
Lines 237-242 class ChangeLog(object): a/Tools/Scripts/webkitpy/common/checkout/changelog.py_sec3
237
            entry_lines.append(line)
241
            entry_lines.append(line)
238
        return None # We never found a date line!
242
        return None # We never found a date line!
239
243
244
    svn_blame_regexp = re.compile(r'^(\s*(?P<revision>\d+) [^ ]+)\s(?P<line>.*?\n)')
245
246
    @staticmethod
247
    def _sepearate_revision_and_line(line):
248
        match = ChangeLog.svn_blame_regexp.match(line)
249
        if not match:
250
            return None, line
251
        return int(match.group('revision')), match.group('line')
252
240
    @staticmethod
253
    @staticmethod
241
    def parse_entries_from_file(changelog_file):
254
    def parse_entries_from_file(changelog_file):
242
        """changelog_file must be a file-like object which returns
255
        """changelog_file must be a file-like object which returns
Lines 244-263 class ChangeLog(object): a/Tools/Scripts/webkitpy/common/checkout/changelog.py_sec4
244
        to pass file objects to this class."""
257
        to pass file objects to this class."""
245
        date_line_regexp = re.compile(ChangeLogEntry.date_line_regexp)
258
        date_line_regexp = re.compile(ChangeLogEntry.date_line_regexp)
246
        rolled_over_regexp = re.compile(ChangeLogEntry.rolled_over_regexp)
259
        rolled_over_regexp = re.compile(ChangeLogEntry.rolled_over_regexp)
247
        entry_lines = []
260
248
        # The first line should be a date line.
261
        # The first line should be a date line.
249
        first_line = changelog_file.readline()
262
        revision, first_line = ChangeLog._sepearate_revision_and_line(changelog_file.readline())
250
        assert(isinstance(first_line, unicode))
263
        assert(isinstance(first_line, unicode))
251
        if not date_line_regexp.match(first_line):
264
        if not date_line_regexp.match(ChangeLog.svn_blame_regexp.sub('', first_line)):
252
            raise StopIteration
265
            raise StopIteration
253
        entry_lines.append(first_line)
254
266
267
        entry_lines = [first_line]
268
        revisions_in_entry = {revision: 1} if revision != None else None
255
        for line in changelog_file:
269
        for line in changelog_file:
256
            if date_line_regexp.match(line) or rolled_over_regexp.match(line):
270
            if revisions_in_entry:
271
                revision, line = ChangeLog._sepearate_revision_and_line(line)
272
273
            if rolled_over_regexp.match(line):
274
                break
275
276
            if date_line_regexp.match(line):
277
                most_probable_revision = max(revisions_in_entry, key=revisions_in_entry.__getitem__) if revisions_in_entry else None
257
                # Remove the extra newline at the end
278
                # Remove the extra newline at the end
258
                yield ChangeLogEntry(''.join(entry_lines[:-1]))
279
                yield ChangeLogEntry(''.join(entry_lines[:-1]), revision=most_probable_revision)
259
                entry_lines = []
280
                entry_lines = []
281
                revisions_in_entry = {revision: 0}
282
260
            entry_lines.append(line)
283
            entry_lines.append(line)
284
            if revisions_in_entry:
285
                revisions_in_entry[revision] = revisions_in_entry.get(revision, 0) + 1
286
287
        most_probable_revision = max(revisions_in_entry, key=revisions_in_entry.__getitem__) if revisions_in_entry else None
288
        yield ChangeLogEntry(''.join(entry_lines[:-1]), revision=most_probable_revision)
261
289
262
    def latest_entry(self):
290
    def latest_entry(self):
263
        # ChangeLog files are always UTF-8, we read them in as such to support Reviewers with unicode in their names.
291
        # ChangeLog files are always UTF-8, we read them in as such to support Reviewers with unicode in their names.
- a/Tools/Scripts/webkitpy/common/checkout/changelog_unittest.py +46 lines
Lines 251-256 class ChangeLogTest(unittest.TestCase): a/Tools/Scripts/webkitpy/common/checkout/changelog_unittest.py_sec1
251
        self.assertEquals(parsed_entries[7].reviewer_text(), None)
251
        self.assertEquals(parsed_entries[7].reviewer_text(), None)
252
        self.assertEquals(parsed_entries[8].reviewer_text(), 'Darin Adler')
252
        self.assertEquals(parsed_entries[8].reviewer_text(), 'Darin Adler')
253
253
254
    def test_parse_log_entries_from_annotated_file(self):
255
        changelog_file = StringIO(u'''100000 ossy@webkit.org 2011-11-11  Csaba Osztrogon\u00e1c  <ossy@webkit.org>
256
100000 ossy@webkit.org 
257
100000 ossy@webkit.org         100,000 !!!
258
100000 ossy@webkit.org 
259
100000 ossy@webkit.org         Reviewed by Zoltan Herczeg.
260
100000 ossy@webkit.org 
261
100000 ossy@webkit.org         * ChangeLog: Point out revision 100,000.
262
100000 ossy@webkit.org
263
93798 ap@apple.com 2011-08-25  Alexey Proskuryakov  <ap@apple.com>
264
93798 ap@apple.com 
265
93798 ap@apple.com         Fix build when GCC 4.2 is not installed.
266
93798 ap@apple.com 
267
93798 ap@apple.com         * gtest/xcode/Config/CompilerVersion.xcconfig: Copied from Source/WebCore/Configurations/CompilerVersion.xcconfig.
268
93798 ap@apple.com         * gtest/xcode/Config/General.xcconfig:
269
93798 ap@apple.com         Use the same compiler version as other projects do.
270
93798 ap@apple.com
271
99491 andreas.kling@nokia.com 2011-11-03  Andreas Kling  <kling@webkit.org>
272
99491 andreas.kling@nokia.com 
273
99190 andreas.kling@nokia.com         Unreviewed build fix, sigh.
274
99190 andreas.kling@nokia.com 
275
99190 andreas.kling@nokia.com         * css/CSSFontFaceRule.h:
276
99190 andreas.kling@nokia.com         * css/CSSMutableStyleDeclaration.h:
277
99190 andreas.kling@nokia.com 
278
99190 andreas.kling@nokia.com 2011-11-03  Andreas Kling  <kling@webkit.org>
279
99190 andreas.kling@nokia.com 
280
99187 andreas.kling@nokia.com         Unreviewed build fix, out-of-line StyleSheet::parentStyleSheet()
281
99187 andreas.kling@nokia.com         again since there's a cycle in the includes between CSSRule/StyleSheet.
282
99187 andreas.kling@nokia.com 
283
99187 andreas.kling@nokia.com         * css/StyleSheet.cpp:
284
99187 andreas.kling@nokia.com         (WebCore::StyleSheet::parentStyleSheet):
285
99187 andreas.kling@nokia.com         * css/StyleSheet.h:
286
99187 andreas.kling@nokia.com 
287
''')
288
        parsed_entries = list(ChangeLog.parse_entries_from_file(changelog_file))
289
        self.assertEquals(parsed_entries[0].revision(), 100000)
290
        self.assertEquals(parsed_entries[0].reviewer_text(), "Zoltan Herczeg")
291
        self.assertEquals(parsed_entries[0].author_name(), u"Csaba Osztrogon\u00e1c")
292
        self.assertEquals(parsed_entries[0].author_email(), "ossy@webkit.org")
293
        self.assertEquals(parsed_entries[1].revision(), 93798)
294
        self.assertEquals(parsed_entries[1].author_name(), "Alexey Proskuryakov")
295
        self.assertEquals(parsed_entries[2].revision(), 99190)
296
        self.assertEquals(parsed_entries[2].author_name(), "Andreas Kling")
297
        self.assertEquals(parsed_entries[3].revision(), 99187)
298
        self.assertEquals(parsed_entries[3].author_name(), "Andreas Kling")
299
254
    def _assert_parse_reviewer_text_and_list(self, text, expected_reviewer_text, expected_reviewer_text_list=None):
300
    def _assert_parse_reviewer_text_and_list(self, text, expected_reviewer_text, expected_reviewer_text_list=None):
255
        reviewer_text, reviewer_text_list = ChangeLogEntry._parse_reviewer_text(text)
301
        reviewer_text, reviewer_text_list = ChangeLogEntry._parse_reviewer_text(text)
256
        self.assertEquals(reviewer_text, expected_reviewer_text)
302
        self.assertEquals(reviewer_text, expected_reviewer_text)
- a/Tools/Scripts/webkitpy/common/checkout/scm/git.py +3 lines
Lines 401-406 class Git(SCM, SVNRepository): a/Tools/Scripts/webkitpy/common/checkout/scm/git.py_sec1
401
    def last_svn_commit_log(self):
401
    def last_svn_commit_log(self):
402
        return self.run(['git', 'svn', 'log', '--limit=1'])
402
        return self.run(['git', 'svn', 'log', '--limit=1'])
403
403
404
    def svn_blame(self, path):
405
        return self.run(['git', 'svn', 'blame', path])
406
404
    # Git-specific methods:
407
    # Git-specific methods:
405
    def _branch_ref_exists(self, branch_ref):
408
    def _branch_ref_exists(self, branch_ref):
406
        return self.run(['git', 'show-ref', '--quiet', '--verify', branch_ref], return_exit_code=True) == 0
409
        return self.run(['git', 'show-ref', '--quiet', '--verify', branch_ref], return_exit_code=True) == 0
- a/Tools/Scripts/webkitpy/common/checkout/scm/scm.py +3 lines
Lines 218-223 class SCM: a/Tools/Scripts/webkitpy/common/checkout/scm/scm.py_sec1
218
    def last_svn_commit_log(self):
218
    def last_svn_commit_log(self):
219
        self._subclass_must_implement()
219
        self._subclass_must_implement()
220
220
221
    def svn_blame(self, path):
222
        self._subclass_must_implement()
223
221
    # Subclasses must indicate if they support local commits,
224
    # Subclasses must indicate if they support local commits,
222
    # but the SCM baseclass will only call local_commits methods when this is true.
225
    # but the SCM baseclass will only call local_commits methods when this is true.
223
    @staticmethod
226
    @staticmethod
- a/Tools/Scripts/webkitpy/common/checkout/scm/svn.py +3 lines
Lines 350-355 class SVN(SCM, SVNRepository): a/Tools/Scripts/webkitpy/common/checkout/scm/svn.py_sec1
350
        # http://svnbook.red-bean.com/en/1.0/ch03s03.html
350
        # http://svnbook.red-bean.com/en/1.0/ch03s03.html
351
        return self.svn_commit_log('BASE')
351
        return self.svn_commit_log('BASE')
352
352
353
    def svn_blame(self, path):
354
        return self._run_svn(['blame', path])
355
353
    def propset(self, pname, pvalue, path):
356
    def propset(self, pname, pvalue, path):
354
        dir, base = os.path.split(path)
357
        dir, base = os.path.split(path)
355
        return self._run_svn(['pset', pname, pvalue, base], cwd=dir)
358
        return self._run_svn(['pset', pname, pvalue, base], cwd=dir)

Return to Bug 72703