Title: [293187] trunk/Tools
Revision
293187
Author
[email protected]
Date
2022-04-21 13:57:31 -0700 (Thu, 21 Apr 2022)

Log Message

[git-webkit] Allow caller to specify remote for PR
https://bugs.webkit.org/show_bug.cgi?id=239452
<rdar://problem/91897384>

Reviewed by Dewei Zhu.

* Tools/Scripts/libraries/webkitscmpy/setup.py: Bump version.
* Tools/Scripts/libraries/webkitscmpy/webkitscmpy/__init__.py: Ditto.
* Tools/Scripts/libraries/webkitscmpy/webkitscmpy/mocks/local/git.py:
(Git.__init__): Allow caller to define remotes.
* Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/pull_request.py:
(PullRequest.parser): Add '--remote' option.
(PullRequest.main): Allow options to specify the remote we're making a PR against.
* Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/revert.py:
(Revert.add_comment_to_reverted_commit_bug_tracker): Derive remote from argument.
* Tools/Scripts/libraries/webkitscmpy/webkitscmpy/remote/git_hub.py:
(GitHub.PRGenerator.find): Support finding PRs if label doesn't contain username.
(GitHub.PRGenerator.create): Error 422 is a validation error, usually caused by another PR pointing to the same branch.
(GitHub.PRGenerator.update): Extract error message for more actionable errors.
* Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/clean_unittest.py:
(TestClean.test_clean_pr): Add fork remote.
* Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/pull_request_unittest.py:
* Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/revert_unittest.py:

Canonical link: https://commits.webkit.org/249863@main

Modified Paths

Diff

Modified: trunk/Tools/ChangeLog (293186 => 293187)


--- trunk/Tools/ChangeLog	2022-04-21 20:51:37 UTC (rev 293186)
+++ trunk/Tools/ChangeLog	2022-04-21 20:57:31 UTC (rev 293187)
@@ -1,5 +1,31 @@
 2022-04-21  Jonathan Bedard  <[email protected]>
 
+        [git-webkit] Allow caller to specify remote for PR
+        https://bugs.webkit.org/show_bug.cgi?id=239452
+        <rdar://problem/91897384>
+
+        Reviewed by Dewei Zhu.
+
+        * Scripts/libraries/webkitscmpy/setup.py: Bump version.
+        * Scripts/libraries/webkitscmpy/webkitscmpy/__init__.py: Ditto.
+        * Scripts/libraries/webkitscmpy/webkitscmpy/mocks/local/git.py:
+        (Git.__init__): Allow caller to define remotes.
+        * Scripts/libraries/webkitscmpy/webkitscmpy/program/pull_request.py:
+        (PullRequest.parser): Add '--remote' option.
+        (PullRequest.main): Allow options to specify the remote we're making a PR against.
+        * Scripts/libraries/webkitscmpy/webkitscmpy/program/revert.py:
+        (Revert.add_comment_to_reverted_commit_bug_tracker): Derive remote from argument.
+        * Scripts/libraries/webkitscmpy/webkitscmpy/remote/git_hub.py:
+        (GitHub.PRGenerator.find): Support finding PRs if label doesn't contain username.
+        (GitHub.PRGenerator.create): Error 422 is a validation error, usually caused by another PR pointing to the same branch.
+        (GitHub.PRGenerator.update): Extract error message for more actionable errors.
+        * Scripts/libraries/webkitscmpy/webkitscmpy/test/clean_unittest.py:
+        (TestClean.test_clean_pr): Add fork remote.
+        * Scripts/libraries/webkitscmpy/webkitscmpy/test/pull_request_unittest.py:
+        * Scripts/libraries/webkitscmpy/webkitscmpy/test/revert_unittest.py:
+
+2022-04-21  Jonathan Bedard  <[email protected]>
+
         [Merge-Queue] Don't close bugs associated with test gardening
         https://bugs.webkit.org/show_bug.cgi?id=239604
         <rdar://problem/92093456>

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/setup.py (293186 => 293187)


--- trunk/Tools/Scripts/libraries/webkitscmpy/setup.py	2022-04-21 20:51:37 UTC (rev 293186)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/setup.py	2022-04-21 20:57:31 UTC (rev 293187)
@@ -29,7 +29,7 @@
 
 setup(
     name='webkitscmpy',
-    version='4.11.0',
+    version='4.11.1',
     description='Library designed to interact with git and svn repositories.',
     long_description=readme(),
     classifiers=[

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/__init__.py (293186 => 293187)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/__init__.py	2022-04-21 20:51:37 UTC (rev 293186)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/__init__.py	2022-04-21 20:57:31 UTC (rev 293187)
@@ -46,7 +46,7 @@
         "Please install webkitcorepy with `pip install webkitcorepy --extra-index-url <package index URL>`"
     )
 
-version = Version(4, 11, 0)
+version = Version(4, 11, 1)
 
 AutoInstall.register(Package('fasteners', Version(0, 15, 0)))
 AutoInstall.register(Package('jinja2', Version(2, 11, 3)))

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


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/mocks/local/git.py	2022-04-21 20:51:37 UTC (rev 293186)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/mocks/local/git.py	2022-04-21 20:57:31 UTC (rev 293187)
@@ -50,7 +50,7 @@
         self, path='/.invalid-git', datafile=None,
         remote=None, tags=None,
         detached=None, default_branch='main',
-        git_svn=False,
+        git_svn=False, remotes=None,
     ):
         self.path = path
         self.default_branch = default_branch
@@ -74,6 +74,10 @@
 
         self.head = self.commits[self.default_branch][-1]
         self.remotes = {'origin/{}'.format(branch): commits[-1] for branch, commits in self.commits.items()}
+        for name in (remotes or {}).keys():
+            for branch, commits in self.commits.items():
+                self.remotes['{}/{}'.format(name, branch)] = commits[-1]
+
         self.tags = {}
 
         self.staged = {}
@@ -106,6 +110,14 @@
                         remote=self.remote,
                         branch=self.default_branch,
                     ))
+                for name, url in (remotes or {}).items():
+                    config.write(
+                        '[remote "{name}"]\n'
+                        '\turl = {url}\n'
+                        '\tfetch = +refs/heads/*:refs/remotes/{name}/*\n'.format(
+                            name=name, url=""
+                        )
+                    )
                 if git_svn:
                     domain = 'webkit.org'
                     if self.remote.startswith('https://'):

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/pull_request.py (293186 => 293187)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/pull_request.py	2022-04-21 20:51:37 UTC (rev 293186)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/pull_request.py	2022-04-21 20:57:31 UTC (rev 293187)
@@ -77,6 +77,10 @@
             '--draft', dest='draft', action='', default=None,
             help='Mark a pull request as a draft when creating it',
         )
+        parser.add_argument(
+            '--remote', dest='remote', type=str, default=None,
+            help='Make a pull request against a specific remote',
+        )
 
     @classmethod
     def create_commit(cls, args, repository, **kwargs):
@@ -143,8 +147,12 @@
             sys.stderr.write("Creating a pull-request for '{}' but we're on '{}'\n".format(args.issue, repository.branch))
             return None
 
-        # FIXME: Source remote will not always be origin
-        source_remote = 'origin'
+        # FIXME: We can do better by infering the remote from the branch point, if it's not specified
+        source_remote = args.remote or 'origin'
+        if not repository.config().get('remote.{}.url'.format(source_remote)):
+            sys.stderr.write("'{}' is not a remote in this repository\n".format(source_remote))
+            return None
+
         branch_point = Branch.branch_point(repository)
         if run([
             repository.executable(), 'branch', '-f',
@@ -166,8 +174,12 @@
 
     @classmethod
     def create_pull_request(cls, repository, args, branch_point):
-        # FIXME: Source remote will not always be origin
-        source_remote = 'origin'
+        # FIXME: We can do better by infering the remote from the branch point, if it's not specified
+        source_remote = args.remote or 'origin'
+        if not repository.config().get('remote.{}.url'.format(source_remote)):
+            sys.stderr.write("'{}' is not a remote in this repository\n".format(source_remote))
+            return 1
+
         rebasing = args.rebase or (args.rebase is None and repository.config().get('pull.rebase'))
         if rebasing:
             log.info("Rebasing '{}' on '{}'...".format(repository.branch, branch_point.branch))
@@ -204,7 +216,16 @@
                 labels.remove(cls.BLOCKED_LABEL)
                 pr_issue.set_labels([])
 
-        target = 'fork' if isinstance(remote_repo, remote.GitHub) else source_remote
+        if isinstance(remote_repo, remote.GitHub):
+            target = 'fork' if source_remote == 'origin' else '{}-fork'.format(source_remote)
+            if not repository.config().get('remote.{}.url'.format(target)):
+                sys.stderr.write("'{}' is not a remote in this repository. Have you run `{} setup` yet?\n".format(
+                    source_remote, os.path.basename(sys.argv[0]),
+                ))
+                return 1
+        else:
+            target = source_remote
+
         log.info("Pushing '{}' to '{}'...".format(repository.branch, target))
         if run([repository.executable(), 'push', '-f', target, repository.branch], cwd=repository.root_path).returncode:
             sys.stderr.write("Failed to push '{}' to '{}' (alias of '{}')\n".format(repository.branch, target, repository.url(name=target)))
@@ -212,7 +233,7 @@
             sys.stderr.write("your checkout may not have permission to push to '{}'\n".format(repository.url(name=target)))
             return 1
 
-        if rebasing and target == 'fork' and repository.config().get('webkitscmpy.update-fork', 'false') == 'true':
+        if rebasing and target.endswith('fork') and repository.config().get('webkitscmpy.update-fork', 'false') == 'true':
             log.info("Syncing '{}' to remote '{}'".format(branch_point.branch, target))
             if run([repository.executable(), 'push', target, '{branch}:{branch}'.format(branch=branch_point.branch)], cwd=repository.root_path).returncode:
                 sys.stderr.write("Failed to sync '{}' to '{}.' Error is non fatal, continuing...\n".format(branch_point.branch, target))

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/revert.py (293186 => 293187)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/revert.py	2022-04-21 20:51:37 UTC (rev 293186)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/revert.py	2022-04-21 20:57:31 UTC (rev 293187)
@@ -101,8 +101,7 @@
 
     @classmethod
     def add_comment_to_reverted_commit_bug_tracker(cls, repository, args):
-        # FIXME: Source remote will not always be origin
-        source_remote = 'origin'
+        source_remote = args.remote or 'origin'
         rmt = repository.remote(name=source_remote)
         if not rmt:
             sys.stderr.write("'{}' doesn't have a recognized remote\n".format(repository.root_path))

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/remote/git_hub.py (293186 => 293187)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/remote/git_hub.py	2022-04-21 20:51:37 UTC (rev 293186)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/remote/git_hub.py	2022-04-21 20:57:31 UTC (rev 293187)
@@ -73,21 +73,30 @@
             assert opened in (True, False, None)
 
             user, _ = self.repository.credentials()
-            data = "" params=dict(
-                state={
-                    None: 'all',
-                    True: 'open',
-                    False: 'closed',
-                }.get(opened),
-                base=base,
-                head='{}:{}'.format(user, head) if user and head else head,
-            ))
-            for datum in data or []:
-                if base and datum['base']['ref'] != base:
+            heads = [head]
+            if user and head:
+                heads.insert(0, '{}:{}'.format(user, head))
+            for qhead in heads:
+                data = "" params=dict(
+                    state={
+                        None: 'all',
+                        True: 'open',
+                        False: 'closed',
+                    }.get(opened),
+                    base=base,
+                    head=qhead,
+                ))
+                if not data:
                     continue
-                if head and not datum['head']['ref'].endswith(head.split(':')[-1]):
-                    continue
-                yield self.PullRequest(datum)
+                for datum in data or []:
+                    if base and datum['base']['ref'] != base:
+                        continue
+                    if head and not datum['head']['ref'].endswith(head.split(':')[-1]):
+                        continue
+                    if datum.get('head', {}).get('repo', {}).get('owner', {}).get('login', None) not in (user, None):
+                        continue
+                    yield self.PullRequest(datum)
+                break
 
         def create(self, head, title, body=None, commits=None, base=None, draft=None):
             draft = False if draft is None else draft
@@ -112,8 +121,15 @@
                     draft=draft,
                 ),
             )
+            if response.status_code == 422:
+                sys.stderr.write('Validation failed when creating pull request\n')
+                sys.stderr.write('Does a pull request against this branch already exist?\n')
+                return None
             if response.status_code // 100 != 2:
                 sys.stderr.write("Request to '{}' returned status code '{}'\n".format(url, response.status_code))
+                message = response.json().get('message')
+                if message:
+                    sys.stderr.write('Message: {}\n'.format(message))
                 sys.stderr.write(Tracker.REFRESH_TOKEN_PROMPT)
                 return None
             result = self.PullRequest(response.json())
@@ -158,6 +174,9 @@
                 return pull_request
             if response.status_code // 100 != 2:
                 sys.stderr.write("Request to '{}' returned status code '{}'\n".format(url, response.status_code))
+                message = response.json().get('message')
+                if message:
+                    sys.stderr.write('Message: {}\n'.format(message))
                 sys.stderr.write(Tracker.REFRESH_TOKEN_PROMPT)
                 return None
             data = ""

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/clean_unittest.py (293186 => 293187)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/clean_unittest.py	2022-04-21 20:51:37 UTC (rev 293186)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/clean_unittest.py	2022-04-21 20:57:31 UTC (rev 293187)
@@ -70,7 +70,10 @@
             self.assertNotIn('branch-a', repo.commits)
 
     def test_clean_pr(self):
-        with OutputCapture(), mocks.remote.GitHub() as remote, mocks.local.Git(self.path, remote='https://{}'.format(remote.remote)) as repo, mocks.local.Svn():
+        with OutputCapture(), mocks.remote.GitHub() as remote, mocks.local.Git(
+            self.path, remote='https://{}'.format(remote.remote),
+            remotes=dict(fork='https://{}/Contributor/WebKit'.format(remote.hosts[0])),
+        ) as repo, mocks.local.Svn():
             repo.staged['added.txt'] = 'added'
             self.assertEqual(0, program.main(
                 args=('pull-request', '-i', 'pr-branch'),

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/pull_request_unittest.py (293186 => 293187)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/pull_request_unittest.py	2022-04-21 20:51:37 UTC (rev 293186)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/pull_request_unittest.py	2022-04-21 20:57:31 UTC (rev 293187)
@@ -328,8 +328,10 @@
     Found 1 commit...""")
 
     def test_github(self):
-        with OutputCapture(level=logging.INFO) as captured, mocks.remote.GitHub() as remote, \
-                mocks.local.Git(self.path, remote='https://{}'.format(remote.remote)) as repo, mocks.local.Svn():
+        with OutputCapture(level=logging.INFO) as captured, mocks.remote.GitHub() as remote, mocks.local.Git(
+            self.path, remote='https://{}'.format(remote.remote),
+            remotes=dict(fork='https://{}/Contributor/WebKit'.format(remote.hosts[0])),
+        ) as repo, mocks.local.Svn():
 
             repo.staged['added.txt'] = 'added'
             self.assertEqual(0, program.main(
@@ -361,8 +363,10 @@
         )
 
     def test_github_draft(self):
-        with OutputCapture(level=logging.INFO) as captured, mocks.remote.GitHub() as remote, \
-                mocks.local.Git(self.path, remote='https://{}'.format(remote.remote)) as repo, mocks.local.Svn():
+        with OutputCapture(level=logging.INFO) as captured, mocks.remote.GitHub() as remote, mocks.local.Git(
+            self.path, remote='https://{}'.format(remote.remote),
+            remotes=dict(fork='https://{}/Contributor/WebKit'.format(remote.hosts[0])),
+        ) as repo, mocks.local.Svn():
 
             repo.staged['added.txt'] = 'added'
             self.assertEqual(0, program.main(
@@ -396,7 +400,10 @@
     def test_github_update(self):
         with mocks.remote.GitHub(labels={
             'merging-blocked': dict(color='c005E5', description='Applied to prevent a change from being merged'),
-        }) as remote, mocks.local.Git(self.path, remote='https://{}'.format(remote.remote)) as repo, mocks.local.Svn():
+        }) as remote, mocks.local.Git(
+            self.path, remote='https://{}'.format(remote.remote),
+            remotes=dict(fork='https://{}/Contributor/WebKit'.format(remote.hosts[0])),
+        ) as repo, mocks.local.Svn():
             with OutputCapture():
                 repo.staged['added.txt'] = 'added'
                 self.assertEqual(0, program.main(
@@ -440,7 +447,10 @@
         )
 
     def test_github_append(self):
-        with mocks.remote.GitHub() as remote, mocks.local.Git(self.path, remote='https://{}'.format(remote.remote)) as repo, mocks.local.Svn():
+        with mocks.remote.GitHub() as remote, mocks.local.Git(
+            self.path, remote='https://{}'.format(remote.remote),
+            remotes=dict(fork='https://{}/Contributor/WebKit'.format(remote.hosts[0])),
+        ) as repo, mocks.local.Svn():
             with OutputCapture():
                 repo.staged['added.txt'] = 'added'
                 self.assertEqual(0, program.main(
@@ -478,7 +488,10 @@
         )
 
     def test_github_reopen(self):
-        with mocks.remote.GitHub() as remote, mocks.local.Git(self.path, remote='https://{}'.format(remote.remote)) as repo, mocks.local.Svn():
+        with mocks.remote.GitHub() as remote, mocks.local.Git(
+            self.path, remote='https://{}'.format(remote.remote),
+            remotes=dict(fork='https://{}/Contributor/WebKit'.format(remote.hosts[0])),
+        ) as repo, mocks.local.Svn():
             with OutputCapture():
                 repo.staged['added.txt'] = 'added'
                 self.assertEqual(0, program.main(
@@ -530,7 +543,10 @@
                 BUGS_EXAMPLE_COM_PASSWORD='password',
             )), patch(
                 'webkitbugspy.Tracker._trackers', [bugzilla.Tracker(self.BUGZILLA)],
-        ), mocks.local.Git(self.path, remote='https://{}'.format(remote.remote)) as repo, mocks.local.Svn():
+        ), mocks.local.Git(
+            self.path, remote='https://{}'.format(remote.remote),
+            remotes=dict(fork='https://{}/Contributor/WebKit'.format(remote.hosts[0])),
+        ) as repo, mocks.local.Svn():
 
             repo.commits['eng/pr-branch'] = [Commit(
                 hash='06de5d56554e693db72313f4ca1fb969c30b8ccb',
@@ -589,7 +605,10 @@
                 BUGS_EXAMPLE_COM_PASSWORD='password',
             )), patch(
                 'webkitbugspy.Tracker._trackers', [bugzilla.Tracker(self.BUGZILLA)],
-        ), mocks.local.Git(self.path, remote='https://{}'.format(remote.remote)) as repo, mocks.local.Svn():
+        ), mocks.local.Git(
+            self.path, remote='https://{}'.format(remote.remote),
+            remotes=dict(fork='https://{}/Contributor/WebKit'.format(remote.hosts[0])),
+        ) as repo, mocks.local.Svn():
 
             Tracker.instance().issue(1).close(why='Looks like we will not get to this')
             repo.commits['eng/pr-branch'] = [Commit(

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/revert_unittest.py (293186 => 293187)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/revert_unittest.py	2022-04-21 20:51:37 UTC (rev 293186)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/revert_unittest.py	2022-04-21 20:57:31 UTC (rev 293187)
@@ -41,8 +41,10 @@
         os.mkdir(os.path.join(self.path, '.svn'))
 
     def test_github(self):
-        with OutputCapture(level=logging.INFO) as captured, mocks.remote.GitHub() as remote, \
-                mocks.local.Git(self.path, remote='https://{}'.format(remote.remote)) as repo, mocks.local.Svn():
+        with OutputCapture(level=logging.INFO) as captured, mocks.remote.GitHub() as remote, mocks.local.Git(
+            self.path, remote='https://{}'.format(remote.remote),
+            remotes=dict(fork='https://{}/Contributor/WebKit'.format(remote.hosts[0])),
+        ) as repo, mocks.local.Svn():
 
             result = program.main(
                 args=('revert', 'd8bce26fa65c6fc8f39c17927abb77f69fab82fc', '-i', 'pr-branch', '-v', '--no-history'),
@@ -102,8 +104,10 @@
         self.assertEqual(captured.stderr.getvalue(), 'Please commit your changes or stash them before you revert commit: d8bce26fa65c6fc8f39c17927abb77f69fab82fc')
 
     def test_update(self):
-        with OutputCapture(level=logging.INFO) as captured, mocks.remote.GitHub() as remote, \
-                mocks.local.Git(self.path, remote='https://{}'.format(remote.remote)) as repo, mocks.local.Svn():
+        with OutputCapture(level=logging.INFO) as captured, mocks.remote.GitHub() as remote, mocks.local.Git(
+            self.path, remote='https://{}'.format(remote.remote),
+            remotes=dict(fork='https://{}/Contributor/WebKit'.format(remote.hosts[0])),
+        ) as repo, mocks.local.Svn():
 
             result = program.main(
                 args=('revert', 'd8bce26fa65c6fc8f39c17927abb77f69fab82fc', '-i', 'pr-branch', '-v'),
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to