Title: [269117] trunk/Tools
Revision
269117
Author
[email protected]
Date
2020-10-28 13:06:50 -0700 (Wed, 28 Oct 2020)

Log Message

[webkitscmpy] Support finding commit by tag
https://bugs.webkit.org/show_bug.cgi?id=218212
<rdar://problem/70700121>

Reviewed by Dewei Zhu.

* Scripts/libraries/webkitscmpy/webkitscmpy/__init__.py: Bump version.
* Scripts/libraries/webkitscmpy/webkitscmpy/local/git.py:
(Git.commit): Find a commit referred to by a provided tag.
* Scripts/libraries/webkitscmpy/webkitscmpy/local/scm.py:
(Scm.find): Find a commit by tag, if applicable.
(Scm.commit):
* Scripts/libraries/webkitscmpy/webkitscmpy/local/svn.py:
(Svn.info): Pull information by tag, support non-standard branches.
(Svn._cache_revisions): Support non-standard branches.
(Svn._branch_for): Return the non-standard branch name for tags.
(Svn.commit): Find a commit referred to by a provided tag.
* Scripts/libraries/webkitscmpy/webkitscmpy/mocks/local/git.py:
(Git): Support tags.
* Scripts/libraries/webkitscmpy/webkitscmpy/mocks/local/svn.py:
(Svn.__init__): Support tags.
(Svn.tags): Tags are simply specialized branches, return the names of those tags
based on the commit mapping.
* Scripts/libraries/webkitscmpy/webkitscmpy/test/find_unittest.py:
* Scripts/libraries/webkitscmpy/webkitscmpy/test/git_unittest.py:
(TestGit):
(TestGit.test_tag):
* Scripts/libraries/webkitscmpy/webkitscmpy/test/svn_unittest.py:
(TestSvn):
(TestSvn.test_tag):

Modified Paths

Diff

Modified: trunk/Tools/ChangeLog (269116 => 269117)


--- trunk/Tools/ChangeLog	2020-10-28 20:01:28 UTC (rev 269116)
+++ trunk/Tools/ChangeLog	2020-10-28 20:06:50 UTC (rev 269117)
@@ -1,5 +1,38 @@
 2020-10-28  Jonathan Bedard  <[email protected]>
 
+        [webkitscmpy] Support finding commit by tag
+        https://bugs.webkit.org/show_bug.cgi?id=218212
+        <rdar://problem/70700121>
+
+        Reviewed by Dewei Zhu.
+
+        * Scripts/libraries/webkitscmpy/webkitscmpy/__init__.py: Bump version.
+        * Scripts/libraries/webkitscmpy/webkitscmpy/local/git.py:
+        (Git.commit): Find a commit referred to by a provided tag.
+        * Scripts/libraries/webkitscmpy/webkitscmpy/local/scm.py:
+        (Scm.find): Find a commit by tag, if applicable.
+        (Scm.commit):
+        * Scripts/libraries/webkitscmpy/webkitscmpy/local/svn.py:
+        (Svn.info): Pull information by tag, support non-standard branches.
+        (Svn._cache_revisions): Support non-standard branches.
+        (Svn._branch_for): Return the non-standard branch name for tags.
+        (Svn.commit): Find a commit referred to by a provided tag.
+        * Scripts/libraries/webkitscmpy/webkitscmpy/mocks/local/git.py:
+        (Git): Support tags.
+        * Scripts/libraries/webkitscmpy/webkitscmpy/mocks/local/svn.py:
+        (Svn.__init__): Support tags.
+        (Svn.tags): Tags are simply specialized branches, return the names of those tags
+        based on the commit mapping.
+        * Scripts/libraries/webkitscmpy/webkitscmpy/test/find_unittest.py:
+        * Scripts/libraries/webkitscmpy/webkitscmpy/test/git_unittest.py:
+        (TestGit):
+        (TestGit.test_tag):
+        * Scripts/libraries/webkitscmpy/webkitscmpy/test/svn_unittest.py:
+        (TestSvn):
+        (TestSvn.test_tag):
+
+2020-10-28  Jonathan Bedard  <[email protected]>
+
         [webkitflaskpy] Create shared library for WebKit's flask tooling
         https://bugs.webkit.org/show_bug.cgi?id=218257
         <rdar://problem/70736269>

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/__init__.py (269116 => 269117)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/__init__.py	2020-10-28 20:01:28 UTC (rev 269116)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/__init__.py	2020-10-28 20:06:50 UTC (rev 269117)
@@ -46,7 +46,7 @@
         "Please install webkitcorepy with `pip install webkitcorepy --extra-index-url <package index URL>`"
     )
 
-version = Version(0, 2, 5)
+version = Version(0, 2, 6)
 
 AutoInstall.register(Package('dateutil', Version(2, 8, 1), pypi_name='python-dateutil'))
 

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/local/git.py (269116 => 269117)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/local/git.py	2020-10-28 20:01:28 UTC (rev 269116)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/local/git.py	2020-10-28 20:06:50 UTC (rev 269117)
@@ -151,10 +151,13 @@
         result = [branch.lstrip(' *') for branch in filter(lambda branch: '->' not in branch, branch.stdout.splitlines())]
         return sorted(set(['/'.join(branch.split('/')[2:]) if branch.startswith('remotes/origin/') else branch for branch in result]))
 
-    def commit(self, hash=None, revision=None, identifier=None, branch=None):
+    def commit(self, hash=None, revision=None, identifier=None, branch=None, tag=None):
         if revision and not self.is_svn:
             raise self.Exception('This git checkout does not support SVN revisions')
         elif revision:
+            if hash:
+                raise ValueError('Cannot define both hash and revision')
+
             revision = Commit._parse_revision(revision, do_assert=True)
             revision_log = run(
                 [self.executable(), 'svn', 'find-rev', 'r{}'.format(revision)],
@@ -175,6 +178,8 @@
                 raise ValueError('Cannot define both revision and identifier')
             if hash:
                 raise ValueError('Cannot define both hash and identifier')
+            if tag:
+                raise ValueError('Cannot define both tag and identifier')
 
             parsed_branch_point, identifier, parsed_branch = Commit._parse_identifier(identifier, do_assert=True)
             if parsed_branch:
@@ -213,12 +218,15 @@
             if identifier < 0:
                 identifier = None
 
-        elif branch:
+        elif branch or tag:
             if hash:
-                raise ValueError('Cannot define both branch and hash')
-            log = run([self.executable(), 'log', branch, '-1'], cwd=self.root_path, capture_output=True, encoding='utf-8')
+                raise ValueError('Cannot define both tag/branch and hash')
+            if branch and tag:
+                raise ValueError('Cannot define both tag and branch')
+
+            log = run([self.executable(), 'log', branch or tag, '-1'], cwd=self.root_path, capture_output=True, encoding='utf-8')
             if log.returncode:
-                raise self.Exception("Failed to retrieve commit information for '{}'".format(branch))
+                raise self.Exception("Failed to retrieve commit information for '{}'".format(branch or tag))
 
         else:
             hash = Commit._parse_hash(hash, do_assert=True)

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/local/scm.py (269116 => 269117)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/local/scm.py	2020-10-28 20:01:28 UTC (rev 269116)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/local/scm.py	2020-10-28 20:06:50 UTC (rev 269117)
@@ -120,6 +120,9 @@
         elif argument in self.branches:
             result = self.commit(branch=argument)
 
+        elif argument in self.tags:
+            result = self.commit(tag=argument)
+
         else:
             if offset:
                 raise ValueError("'~' offsets are not supported for revisions and identifiers")
@@ -140,7 +143,7 @@
             branch=result.branch,
         )
 
-    def commit(self, hash=None, revision=None, identifier=None, branch=None):
+    def commit(self, hash=None, revision=None, identifier=None, branch=None, tag=None):
         raise NotImplementedError()
 
     def prioritize_branches(self, branches):

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/local/svn.py (269116 => 269117)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/local/svn.py	2020-10-28 20:01:28 UTC (rev 269116)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/local/svn.py	2020-10-28 20:06:50 UTC (rev 269117)
@@ -69,9 +69,17 @@
             self._metadata_cache = dict(version=str(self.CACHE_VERSION))
 
     @decorators.Memoize(cached=False)
-    def info(self, branch=None, revision=None):
+    def info(self, branch=None, revision=None, tag=None):
+        if tag and branch:
+            raise ValueError('Cannot specify both branch and tag')
+        if tag and revision:
+            raise ValueError('Cannot specify both branch and tag')
+
         revision = Commit._parse_revision(revision)
-        additional_args = ['^/branches/{}'.format(branch)] if branch and branch != self.default_branch else []
+        if branch and branch != self.default_branch and '/' not in branch:
+            branch = 'branches/{}'.format(branch)
+        additional_args = ['^/{}'.format(branch)] if branch and branch != self.default_branch else []
+        additional_args += ['^/tags/{}'.format(tag)] if tag else []
         additional_args += ['-r', str(revision)] if revision else []
 
         info_result = run([self.executable(), 'info'] + additional_args, cwd=self.root_path, capture_output=True, encoding='utf-8')
@@ -137,9 +145,12 @@
             did_warn = False
             count = 0
             log = None
-            candidate_index = -1 if is_default_branch else len(self._metadata_cache[self.default_branch])
 
-            branch_arg = '^/{}{}'.format('' if is_default_branch else 'branches/', branch)
+            if is_default_branch or '/' in branch:
+                branch_arg = '^/{}'.format(branch)
+            else:
+                branch_arg = '^/branches/{}'.format(branch)
+
             kwargs = dict()
             if sys.version_info >= (3, 0):
                 kwargs = dict(encoding='utf-8')
@@ -238,9 +249,14 @@
         if len(partial) <= 3:
             raise self.Exception('Malformed set  of edited files')
         partial = partial[2:].split(' ')[0]
-        return partial.split('/')[2 if partial.startswith('/branches') else 1]
+        candidate = partial.split('/')[2 if partial.startswith('/branches') else 1]
 
-    def commit(self, hash=None, revision=None, identifier=None, branch=None):
+        # Tags are a unique case for SVN, because they're treated as branches in native SVN
+        if candidate == 'tags':
+            return partial[1:].rstrip('/')
+        return candidate
+
+    def commit(self, hash=None, revision=None, identifier=None, branch=None, tag=None):
         if hash:
             raise ValueError('SVN does not support Git hashes')
 
@@ -248,6 +264,8 @@
         if identifier is not None:
             if revision:
                 raise ValueError('Cannot define both revision and identifier')
+            if tag:
+                raise ValueError('Cannot define both tag and identifier')
 
             parsed_branch_point, identifier, parsed_branch = Commit._parse_identifier(identifier, do_assert=True)
             if parsed_branch:
@@ -286,15 +304,23 @@
         elif revision:
             if branch:
                 raise ValueError('Cannot define both branch and revision')
+            if tag:
+                raise ValueError('Cannot define both tag and revision')
             revision = Commit._parse_revision(revision, do_assert=True)
             branch = self._branch_for(revision)
             info = self.info(cached=True, branch=branch, revision=revision)
 
         else:
-            branch = branch or self.branch
-            info = self.info(branch=branch)
+            if branch and tag:
+                raise ValueError('Cannot define both branch and tag')
+
+            branch = None if tag else branch or self.branch
+            info = self.info(tag=tag) if tag else self.info(branch=branch)
             if not info:
-                raise self.Exception("'{}' is not a recognized branch".format(branch))
+                raise self.Exception("'{}' is not a recognized {}".format(
+                    tag or branch,
+                    'tag' if tag else 'branch',
+                ))
             revision = int(info['Last Changed Rev'])
             if branch != self.default_branch:
                 branch = self._branch_for(revision)
@@ -324,7 +350,11 @@
         if branch_point and parsed_branch_point and branch_point != parsed_branch_point:
             raise ValueError("Provided 'branch_point' does not match branch point of specified branch")
 
-        branch_arg = '^/{}{}'.format('' if branch == self.default_branch else 'branches/', branch)
+        if branch == self.default_branch or '/' in branch:
+            branch_arg = '^/{}'.format(branch)
+        else:
+            branch_arg = '^/branches/{}'.format(branch)
+
         log = run(
             [self.executable(), 'log', '-l', '1', '-r', str(revision), branch_arg], cwd=self.root_path,
             capture_output=True, encoding='utf-8',

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/mocks/local/git.py (269116 => 269117)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/mocks/local/git.py	2020-10-28 20:01:28 UTC (rev 269116)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/mocks/local/git.py	2020-10-28 20:06:50 UTC (rev 269117)
@@ -43,7 +43,7 @@
         self.detached = detached or False
 
         self.branches = branches or []
-        self.tags = tags or []
+        self.tags = tags or {}
 
         try:
             self.executable = local.Git.executable()
@@ -119,6 +119,9 @@
             ),
         ]
 
+        self.tags['tag-1'] = self.commits['branch-a'][-1]
+        self.tags['tag-2'] = self.commits['branch-b'][-1]
+
         if git_svn:
             git_svn_routes = [
                 mocks.Subprocess.Route(
@@ -222,7 +225,7 @@
                 cwd=self.path,
                 generator=lambda *args, **kwargs: mocks.ProcessCompletion(
                     returncode=0,
-                    stdout='\n'.join(self.tags) + '\n',
+                    stdout='\n'.join(sorted(self.tags.keys())) + '\n',
                 ),
             ), mocks.Subprocess.Route(
                 self.executable, 'rev-parse', '--abbrev-ref', 'origin/HEAD',
@@ -319,6 +322,8 @@
             return self.commits[self.branch][-1]
         if something in self.commits.keys():
             return self.commits[something][-1]
+        if something in self.tags.keys():
+            return self.tags[something]
 
         something = str(something)
         if '..' in something:

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/mocks/local/svn.py (269116 => 269117)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/mocks/local/svn.py	2020-10-28 20:01:28 UTC (rev 269116)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/mocks/local/svn.py	2020-10-28 20:06:50 UTC (rev 269117)
@@ -45,13 +45,12 @@
             date=datetime.fromtimestamp(commit.timestamp).strftime('%Y-%m-%d %H:%M:%S {} (%a, %d %b %Y)'.format(cls.UTC_OFFSET)),
         )
 
-    def __init__(self, path='/.invalid-svn', branch=None, remote=None, branches=None, tags=None):
+    def __init__(self, path='/.invalid-svn', branch=None, remote=None, branches=None):
         self.path = path
         self.branch = branch or 'trunk'
         self.remote = remote or 'https://svn.mock.org/repository/{}'.format(os.path.basename(path))
 
         self.branches = branches or []
-        self.tags = tags or []
         self.connected = True
 
         try:
@@ -120,6 +119,28 @@
             ),
         ]
 
+        self.commits['tags/tag-1'] = [
+            self.commits['branch-a'][0],
+            self.commits['branch-a'][1], Commit(
+                identifier='2.3@tags/tag-1',
+                revision=9,
+                author=contributor,
+                timestamp=1601668100,
+                message='9th commit\n',
+            ),
+        ]
+        self.commits['tags/tag-2'] = [
+            self.commits['branch-b'][0],
+            self.commits['branch-b'][1],
+            self.commits['branch-b'][2], Commit(
+                identifier='2.4@tags/tag-2',
+                revision=10,
+                author=contributor,
+                timestamp=1601669100,
+                message='10th commit\n',
+            ),
+        ]
+
         super(Svn, self).__init__(
             mocks.Subprocess.Route(
                 '/usr/bin/which', 'svn',
@@ -130,7 +151,7 @@
             ), mocks.Subprocess.Route(
                 self.executable, 'info',
                 cwd=self.path,
-                generator=lambda *args, **kwargs: self._info(cwd=kwargs.get('cwd',''))
+                generator=lambda *args, **kwargs: self._info(cwd=kwargs.get('cwd', ''))
             ), mocks.Subprocess.Route(
                 self.executable, 'info', self.BRANCH_RE,
                 cwd=self.path,
@@ -140,7 +161,7 @@
                 cwd=self.path,
                 generator=lambda *args, **kwargs: mocks.ProcessCompletion(
                     returncode=0,
-                    stdout='/\n'.join(sorted(set(self.branches) | set(self.commits.keys()) - {'trunk'})) + '/\n',
+                    stdout='/\n'.join(sorted(set(self.branches) | set(self.commits.keys()) - {'trunk'} - self.tags)) + '/\n',
                 ) if self.connected else mocks.ProcessCompletion(returncode=1),
             ), mocks.Subprocess.Route(
                 self.executable, 'list', '^/tags',
@@ -147,7 +168,7 @@
                 cwd=self.path,
                 generator=lambda *args, **kwargs: mocks.ProcessCompletion(
                     returncode=0,
-                    stdout='/\n'.join(self.tags) + '/\n',
+                    stdout='/\n'.join([tag[len('tags/'):] for tag in sorted(self.tags)]) + '/\n',
                 ) if self.connected else mocks.ProcessCompletion(returncode=1),
             ), mocks.Subprocess.Route(
                 self.executable, 'log', '-v', '-q', self.remote, '-r', re.compile(r'\d+'),
@@ -160,7 +181,7 @@
                         '    M /{branch}/ChangeLog\n'
                         '    M /{branch}/file.cpp\n'.format(
                             line=self.log_line(self.find(revision=args[6])),
-                            branch='trunk' if self.find(revision=args[6]).branch == 'trunk' else 'branches/{}'.format(self.find(revision=args[6]).branch)
+                            branch=self.find(revision=args[6]).branch if self.find(revision=args[6]).branch.split('/')[0] in ['trunk', 'tags'] else 'branches/{}'.format(self.find(revision=args[6]).branch)
                         ),
                 ) if self.connected and self.find(revision=args[6]) else mocks.ProcessCompletion(returncode=1),
             ), mocks.Subprocess.Route(
@@ -195,6 +216,10 @@
             ),
         )
 
+    @property
+    def tags(self):
+        return set(branch for branch in self.commits.keys() if branch.startswith('tags'))
+
     def _info(self, branch=None, revision=None, cwd=''):
         commit = self.find(branch=branch, revision=revision)
         if not commit:

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/find_unittest.py (269116 => 269117)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/find_unittest.py	2020-10-28 20:01:28 UTC (rev 269116)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/find_unittest.py	2020-10-28 20:06:50 UTC (rev 269117)
@@ -166,3 +166,19 @@
                 branch='main',
                 message='4th commit\nsvn-id: https://svn.webkit.orgrepository/repository/trunk@4 268f45cc-cd09-0410-ab3c-d52691b4dbfc',
             ))
+
+    def test_tag_svn(self):
+        with mocks.local.Git(), mocks.local.Svn(self.path), MockTime, OutputCapture() as captured:
+            self.assertEqual(0, program.main(
+                args=('find', 'tag-1', '-q'),
+                path=self.path,
+            ))
+        self.assertEqual(captured.stdout.getvalue(), '2.3@tags/tag-1 | r9 | 9th commit\n')
+
+    def test_tag_git(self):
+        with mocks.local.Git(self.path, git_svn=True), mocks.local.Svn(), MockTime, OutputCapture() as captured:
+            self.assertEqual(0, program.main(
+                args=('find', 'tag-1', '-q'),
+                path=self.path,
+            ))
+        self.assertEqual(captured.stdout.getvalue(), '2.2@branch-a | 621652add7fc, r7 | 7th commit\n')

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/git_unittest.py (269116 => 269117)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/git_unittest.py	2020-10-28 20:01:28 UTC (rev 269116)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/git_unittest.py	2020-10-28 20:06:50 UTC (rev 269117)
@@ -63,7 +63,7 @@
             )
 
     def test_tags(self):
-        with mocks.local.Git(self.path, tags=('tag-1', 'tag-2')):
+        with mocks.local.Git(self.path):
             self.assertEqual(
                 local.Git(self.path).tags,
                 ['tag-1', 'tag-2'],
@@ -196,7 +196,7 @@
 
     def test_branches_priority(self):
         for mock in [mocks.local.Git(self.path), mocks.local.Git(self.path, git_svn=True)]:
-            with mocks.local.Git(self.path):
+            with mock:
                 self.assertEqual(
                     'main',
                     local.Git(self.path).prioritize_branches(['main', 'branch-a', 'dev/12345', 'safari-610-branch', 'safari-610.1-branch'])
@@ -216,3 +216,11 @@
                     'branch-a',
                     local.Git(self.path).prioritize_branches(['branch-a', 'dev/12345'])
                 )
+
+    def test_tag(self):
+        for mock in [mocks.local.Git(self.path), mocks.local.Git(self.path, git_svn=True)]:
+            with mock:
+                self.assertEqual(
+                    '621652add7fc416099bd2063366cc38ff61afe36',
+                    local.Git(self.path).commit(tag='tag-1').hash,
+                )

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/svn_unittest.py (269116 => 269117)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/svn_unittest.py	2020-10-28 20:01:28 UTC (rev 269116)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/svn_unittest.py	2020-10-28 20:06:50 UTC (rev 269117)
@@ -61,7 +61,7 @@
             )
 
     def test_tags(self):
-        with mocks.local.Svn(self.path, tags=('tag-1', 'tag-2')):
+        with mocks.local.Svn(self.path):
             self.assertEqual(
                 local.Svn(self.path).tags,
                 ['tag-1', 'tag-2'],
@@ -107,7 +107,7 @@
 
             # Out-of-bounds commit
             with self.assertRaises(local.Svn.Exception):
-                self.assertEqual(None, local.Svn(self.path).commit(revision=10))
+                self.assertEqual(None, local.Svn(self.path).commit(revision=11))
 
     def test_commit_from_branch(self):
         with mocks.local.Svn(self.path), OutputCapture():
@@ -196,3 +196,7 @@
                     local.Svn(dirname).commit(revision=3)
         finally:
             shutil.rmtree(dirname)
+
+    def test_tag(self):
+        with mocks.local.Svn(self.path), OutputCapture():
+            self.assertEqual(9, local.Svn(self.path).commit(tag='tag-1').revision)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to