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'),