Diff
Modified: trunk/Tools/Scripts/libraries/webkitscmpy/setup.py (293174 => 293175)
--- trunk/Tools/Scripts/libraries/webkitscmpy/setup.py 2022-04-21 17:10:24 UTC (rev 293174)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/setup.py 2022-04-21 17:16:37 UTC (rev 293175)
@@ -29,7 +29,7 @@
setup(
name='webkitscmpy',
- version='4.10.0',
+ version='4.11.0',
description='Library designed to interact with git and svn repositories.',
long_description=readme(),
classifiers=[
Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/__init__.py (293174 => 293175)
--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/__init__.py 2022-04-21 17:10:24 UTC (rev 293174)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/__init__.py 2022-04-21 17:16:37 UTC (rev 293175)
@@ -46,7 +46,7 @@
"Please install webkitcorepy with `pip install webkitcorepy --extra-index-url <package index URL>`"
)
-version = Version(4, 10, 0)
+version = Version(4, 11, 0)
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 (293174 => 293175)
--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/mocks/local/git.py 2022-04-21 17:10:24 UTC (rev 293174)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/mocks/local/git.py 2022-04-21 17:16:37 UTC (rev 293175)
@@ -78,6 +78,7 @@
self.staged = {}
self.modified = {}
+ self.revert_message = None
self.has_git_lfs = False
@@ -473,6 +474,22 @@
cwd=self.path,
generator=lambda *args, **kwargs: self.commit(amend=True),
), mocks.Subprocess.Route(
+ self.executable, 'revert', '--no-commit', re.compile(r'.+'),
+ cwd=self.path,
+ generator=lambda *args, **kwargs: self.revert(commit_hashes=[args[3]], no_commit=True),
+ ), mocks.Subprocess.Route(
+ self.executable, 'revert', '--continue', '--no-edit',
+ cwd=self.path,
+ generator=lambda *args, **kwargs: self.revert(revert_continue=True),
+ ), mocks.Subprocess.Route(
+ self.executable, 'revert', '--abort',
+ cwd=self.path,
+ generator=lambda *args, **kwargs: self.revert(revert_abort=True),
+ ), mocks.Subprocess.Route(
+ self.executable, 'restore', '--staged', re.compile(r'.+'),
+ cwd=self.path,
+ generator=lambda *args, **kwargs: self.restore(args[3], staged=True),
+ ), mocks.Subprocess.Route(
self.executable, 'add', re.compile(r'.+'),
cwd=self.path,
generator=lambda *args, **kwargs: self.add(args[2]),
@@ -497,6 +514,10 @@
cwd=self.path,
generator=lambda *args, **kwargs: self.delete_branch(args[3]),
), mocks.Subprocess.Route(
+ self.executable, 'branch', re.compile(r'.+'), re.compile(r'.+'),
+ cwd=self.path,
+ generator=lambda *args, **kwargs: self.move_branch(args[2], args[3]),
+ ), mocks.Subprocess.Route(
self.executable, 'push', re.compile(r'.+'), re.compile(r'.+'),
cwd=self.path,
generator=lambda *args, **kwargs: self.push(args[2], args[3].split(':')[0]),
@@ -640,6 +661,9 @@
return result
def checkout(self, something, create=False, force=False):
+ if something in self.modified:
+ del self.modified[something]
+ return mocks.ProcessCompletion(returncode=0, stdout='Updated 1 path from the index')
commit = self.find(something)
if create:
if commit:
@@ -890,6 +914,69 @@
self.staged = {}
return mocks.ProcessCompletion(returncode=0)
+ def revert(self, commit_hashes=[], no_commit=False, revert_continue=False, revert_abort=False):
+ if revert_continue:
+ if not self.staged:
+ return mocks.ProcessCompletion(returncode=1, stdout='error: no cherry-pick or revert in progress\nfatal: revert failed')
+ self.staged = {}
+ self.head = Commit(
+ branch=self.branch, repository_id=self.head.repository_id,
+ timestamp=int(time.time()),
+ identifier=self.head.identifier + 1 if self.head.branch_point else 1,
+ branch_point=self.head.branch_point or self.head.identifier,
+ message=self.revert_message
+ )
+ self.head.author = Contributor(self.config()['user.name'], [self.config()['user.email']])
+ self.head.hash = hashlib.sha256(string_utils.encode(self.head.message)).hexdigest()[:40]
+ self.commits[self.branch].append(self.head)
+ self.revert_message = None
+ return mocks.ProcessCompletion(returncode=0)
+
+ if revert_abort:
+ if not self.staged:
+ return mocks.ProcessCompletion(returncode=1, stdout='error: no cherry-pick or revert in progress\nfatal: revert failed')
+ self.staged = {}
+ self.revert_message = None
+ return mocks.ProcessCompletion(returncode=0)
+
+ if self.modified:
+ return mocks.ProcessCompletion(returncode=1, stdout='error: your local changes would be overwritten by revert.')
+
+ is_reverted_something = False
+ for hash in commit_hashes:
+ commit_revert = self.find(hash)
+ if not no_commit:
+ self.head = Commit(
+ branch=self.branch, repository_id=self.head.repository_id,
+ timestamp=int(time.time()),
+ identifier=self.head.identifier + 1 if self.head.branch_point else 1,
+ branch_point=self.head.branch_point or self.head.identifier,
+ message='Revert "{}"\n\nThis reverts commit {}'.format(commit_revert.message.splitlines()[0], hash)
+ )
+ self.head.author = Contributor(self.config()['user.name'], [self.config()['user.email']])
+ self.head.hash = hashlib.sha256(string_utils.encode(self.head.message)).hexdigest()[:40]
+ self.commits[self.branch].append(self.head)
+ else:
+ self.staged['{}/some_file'.format(hash)] = 'modified'
+ self.staged['{}/ChangeLog'.format(hash)] = 'modified'
+ # git revert only generate one commit message
+ self.revert_message = 'Revert "{}"\n\nThis reverts commit {}'.format(commit_revert.message.splitlines()[0], hash)
+
+ is_reverted_something = True
+ if not is_reverted_something:
+ return mocks.ProcessCompletion(returncode=1, stdout='On branch {}\nnothing to commit, working tree clean'.format(self.branch))
+
+ return mocks.ProcessCompletion(returncode=0)
+
+ def restore(self, file, staged=False):
+ if staged:
+ if file in self.staged:
+ self.modified[file] = self.staged[file]
+ del self.staged[file]
+ return mocks.ProcessCompletion(returncode=0)
+ return mocks.ProcessCompletion(returncode=0)
+ return mocks.ProcessCompletion(returncode=1)
+
def add(self, file):
if file not in self.modified:
return mocks.ProcessCompletion(returncode=128, stdout="fatal: pathspec '{}' did not match any files\n".format(file))
Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/__init__.py (293174 => 293175)
--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/__init__.py 2022-04-21 17:10:24 UTC (rev 293174)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/__init__.py 2022-04-21 17:16:37 UTC (rev 293175)
@@ -38,6 +38,7 @@
from .log import Log
from .pull import Pull
from .pull_request import PullRequest
+from .revert import Revert
from .setup_git_svn import SetupGitSvn
from .setup import Setup
@@ -73,7 +74,7 @@
)
subparsers = parser.add_subparsers(help='sub-command help')
- programs = [Blame, Branch, Canonicalize, Checkout, Clean, Find, Info, Land, Log, Pull, PullRequest, Setup, InstallGitLFS, Credentials]
+ programs = [Blame, Branch, Canonicalize, Checkout, Clean, Find, Info, Land, Log, Pull, PullRequest, Revert, Setup, InstallGitLFS, Credentials]
if subversion:
programs.append(SetupGitSvn)
Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/pull_request.py (293174 => 293175)
--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/pull_request.py 2022-04-21 17:10:24 UTC (rev 293174)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/pull_request.py 2022-04-21 17:16:37 UTC (rev 293175)
@@ -119,11 +119,7 @@
return title[:-5].rstrip() if title.endswith('(Part') else title
@classmethod
- def main(cls, args, repository, **kwargs):
- if not isinstance(repository, local.Git):
- sys.stderr.write("Can only '{}' on a native Git repository\n".format(cls.name))
- return 1
-
+ def check_pull_request_args(cls, repository, args):
if not args.technique:
args.technique = repository.config()['webkitscmpy.pull-request']
if args.history is None:
@@ -134,15 +130,18 @@
).get(repository.config()['webkitscmpy.history'])
if args.history and repository.config()['webkitscmpy.history'] == 'never':
sys.stderr.write('History retention was requested, but repository configuration forbids it\n')
- return 1
+ return False
+ return True
+ @classmethod
+ def pull_request_branch_point(cls, repository, args, **kwargs):
if repository.branch in repository.DEFAULT_BRANCHES or repository.PROD_BRANCHES.match(repository.branch):
if Branch.main(args, repository, why="'{}' is not a pull request branch".format(repository.branch), **kwargs):
sys.stderr.write("Abandoning pushing pull-request because '{}' could not be created\n".format(args.issue))
- return 1
+ return None
elif args.issue and repository.branch != args.issue:
sys.stderr.write("Creating a pull-request for '{}' but we're on '{}'\n".format(args.issue, repository.branch))
- return 1
+ return None
# FIXME: Source remote will not always be origin
source_remote = 'origin'
@@ -153,12 +152,22 @@
'remotes/{}/{}'.format(source_remote, branch_point.branch),
], cwd=repository.root_path).returncode:
sys.stderr.write("Failed to match '{}' to it's remote '{}'\n".format(branch_point.branch, source_remote))
- return 1
+ return None
+ return branch_point
- result = cls.create_commit(args, repository, **kwargs)
- if result:
- return result
+ @classmethod
+ def find_existing_pull_request(cls, repository, remote):
+ existing_pr = None
+ for pr in remote.pull_requests.find(opened=None, head=repository.branch):
+ existing_pr = pr
+ if existing_pr.opened:
+ break
+ return existing_pr
+ @classmethod
+ def create_pull_request(cls, repository, args, branch_point):
+ # FIXME: Source remote will not always be origin
+ source_remote = 'origin'
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))
@@ -177,10 +186,7 @@
existing_pr = None
if remote_repo.pull_requests:
- for pr in remote_repo.pull_requests.find(opened=None, head=repository.branch):
- existing_pr = pr
- if existing_pr.opened:
- break
+ existing_pr = cls.find_existing_pull_request(repository, remote_repo)
if existing_pr and not existing_pr.opened and not args.defaults and (args.defaults is False or Terminal.choose(
"'{}' is already associated with '{}', which is closed.\nWould you like to create a new pull-request?".format(
repository.branch, existing_pr,
@@ -304,3 +310,21 @@
print(pr.url)
return 0
+
+ @classmethod
+ def main(cls, args, repository, **kwargs):
+ if not isinstance(repository, local.Git):
+ sys.stderr.write("Can only '{}' on a native Git repository\n".format(cls.name))
+ return 1
+ if not cls.check_pull_request_args(repository, args):
+ return 1
+
+ branch_point = cls.pull_request_branch_point(repository, args, **kwargs)
+ if not branch_point:
+ return 1
+
+ result = cls.create_commit(args, repository, **kwargs)
+ if result:
+ return result
+
+ return cls.create_pull_request(repository, args, branch_point)
Added: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/revert.py (0 => 293175)
--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/revert.py (rev 0)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/revert.py 2022-04-21 17:16:37 UTC (rev 293175)
@@ -0,0 +1,146 @@
+# Copyright (C) 2022 Apple Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import logging
+import re
+import sys
+
+from .command import Command
+from .branch import Branch
+from .pull_request import PullRequest
+
+from webkitbugspy import Tracker
+from webkitcorepy import arguments, run, Terminal
+from webkitscmpy import local, log, remote
+
+
+class Revert(Command):
+ name = 'revert'
+ help = 'Revert provided list of commits and create a pull-request with this revert commit'
+
+ @classmethod
+ def parser(cls, parser, loggers=None):
+ PullRequest.parser(parser, loggers=loggers)
+ # Only allow revert one commit one time, because git automatically generate mesaage will only contain one commit information
+ parser.add_argument(
+ 'commit',
+ help='git hash, svn revision or identifer you want to revert'
+ )
+
+ @classmethod
+ def revert_commit(cls, args, repository, **kwargs):
+ # Check if there are any outstanding changes:
+ if repository.modified():
+ sys.stderr.write('Please commit your changes or stash them before you revert commit: {}'.format(args.commit))
+ return 1
+ # Make sure we have the commit that user want to revert
+ try:
+ commit = repository.find(args.commit, include_log=False)
+ except (local.Scm.Exception, ValueError) as exception:
+ # ValueErrors and Scm exceptions usually contain enough information to be displayed
+ # to the user as an error
+ sys.stderr.write('Could not find "{}"'.format(args.commit) + '\n')
+ return 1
+
+ result = run([repository.executable(), 'revert', '--no-commit'] + [commit.hash], cwd=repository.root_path, capture_output=True)
+ if result.returncode:
+ # git revert will output nothing if this commit is already reverted
+ if not result.stdout.strip():
+ sys.stderr.write('The commits you spiecfied seems already be reverted.')
+ return 2
+ # print out
+ sys.stderr.write(result.stdout.decode('utf-8'))
+ sys.stderr.write(result.stderr.decode('utf-8'))
+ sys.stderr.write('If you have merge conflicts, after resolving them, please use git-webkit pfr to publish your pull request')
+ return 1
+ # restore all ChangeLog changes, we should not revert those entries
+ modifiled_files = repository.modified()
+ if not modifiled_files:
+ sys.stderr.write('Failed to detect any diff after revert.')
+ return 1
+ for file in modifiled_files:
+ if 'ChangeLog' in file:
+ result = run([repository.executable(), 'restore', '--staged', file], cwd=repository.root_path)
+ if result.returncode:
+ sys.stderr.write('Failed to restore staged file: {}'.format(file))
+ run([repository.executable(), 'revert', '--abort'], cwd=repository.root_path)
+ return 1
+
+ result = run([repository.executable(), 'checkout', file], cwd=repository.root_path)
+ if result.returncode:
+ sys.stderr.write('Failed to checkout file: {}'.format(file))
+ run([repository.executable(), 'revert', '--abort'], cwd=repository.root_path)
+ return 1
+
+ result = run([repository.executable(), 'revert', '--continue', '--no-edit'], cwd=repository.root_path)
+ if result.returncode:
+ run([repository.executable(), 'revert', '--abort'], cwd=repository.root_path)
+ sys.stderr.write('Failed revert commit')
+ return 1
+ log.info('Reverted {}'.format(commit.hash))
+ return 0
+
+ @classmethod
+ def add_comment_to_reverted_commit_bug_tracker(cls, repository, args):
+ # FIXME: Source remote will not always be origin
+ source_remote = 'origin'
+ rmt = repository.remote(name=source_remote)
+ if not rmt:
+ sys.stderr.write("'{}' doesn't have a recognized remote\n".format(repository.root_path))
+ return 1
+ if not rmt.pull_requests:
+ sys.stderr.write("'{}' cannot generate pull-requests\n".format(rmt.url))
+ return 1
+
+ revert_pr = PullRequest.find_existing_pull_request(repository, rmt)
+
+ commit = repository.find(args.commit, include_log=True)
+ for line in commit.message.split():
+ tracker = Tracker.from_string(line)
+ if tracker:
+ tracker.add_comment('Reverted by {}'.format(revert_pr.link))
+ continue
+ return 0
+
+ @classmethod
+ def main(cls, args, repository, **kwargs):
+ if not isinstance(repository, local.Git):
+ sys.stderr.write("Can only '{}' on a native Git repository\n".format(cls.name))
+ return 1
+
+ if not PullRequest.check_pull_request_args(repository, args):
+ return 1
+
+ branch_point = PullRequest.pull_request_branch_point(repository, args, **kwargs)
+ if not branch_point:
+ return 1
+
+ result = cls.revert_commit(args, repository, **kwargs)
+ if result:
+ return result
+
+ result = PullRequest.create_pull_request(repository, args, branch_point)
+ if result:
+ return result
+
+ log.info('Adding comment for reverted commits...')
+ return cls.add_comment_to_reverted_commit_bug_tracker(repository, args)
Added: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/revert_unittest.py (0 => 293175)
--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/revert_unittest.py (rev 0)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/revert_unittest.py 2022-04-21 17:16:37 UTC (rev 293175)
@@ -0,0 +1,152 @@
+# Copyright (C) 2022 Apple Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import logging
+import os
+
+from mock import patch
+from webkitbugspy import Tracker, User, bugzilla, radar, mocks as bmocks
+from webkitcorepy import OutputCapture, testing, log as wcplog
+from webkitcorepy.mocks import Terminal as MockTerminal, Environment
+from webkitscmpy import Contributor, Commit, PullRequest, local, program, mocks, remote, log as wsplog
+
+
+class TestRevert(testing.PathTestCase):
+
+ basepath = 'mock/repository'
+ BUGZILLA = 'https://bugs.example.com'
+
+ def setUp(self):
+ super(TestRevert, self).setUp()
+ os.mkdir(os.path.join(self.path, '.git'))
+ 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():
+
+ result = program.main(
+ args=('revert', 'd8bce26fa65c6fc8f39c17927abb77f69fab82fc', '-i', 'pr-branch', '-v', '--no-history'),
+ path=self.path,
+ )
+ self.assertEqual(0, result)
+ self.assertDictEqual(repo.modified, dict())
+ self.assertDictEqual(repo.staged, dict())
+ self.assertEqual(True, 'Revert "Patch Series"' in repo.head.message)
+ self.assertEqual(local.Git(self.path).remote().pull_requests.get(1).draft, False)
+
+ self.assertEqual(
+ captured.stdout.getvalue(),
+ "Created the local development branch 'eng/pr-branch'\n"
+ "Created 'PR 1 | Revert \"Patch Series\"'!\n"
+ "https://github.example.com/WebKit/WebKit/pull/1\n",
+ )
+ self.assertEqual(captured.stderr.getvalue(), '')
+ log = captured.root.log.getvalue().splitlines()
+ self.assertEqual(
+ [line for line in log if 'Mock process' not in line], [
+ "Creating the local development branch 'eng/pr-branch'...",
+ ' Found 1 commit...',
+ 'Reverted d8bce26fa65c6fc8f39c17927abb77f69fab82fc',
+ "Rebasing 'eng/pr-branch' on 'main'...",
+ "Rebased 'eng/pr-branch' on 'main!'",
+ " Found 1 commit...",
+ "Pushing 'eng/pr-branch' to 'fork'...",
+ "Syncing 'main' to remote 'fork'",
+ "Creating pull-request for 'eng/pr-branch'...",
+ 'Adding comment for reverted commits...'
+ ],
+ )
+
+ def test_modified(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():
+
+ repo.modified = {
+ 'a.py': """diff --git a/a.py b/a.py
+index 05e8751..0bf3c85 100644
+--- a/test
++++ b/test
+@@ -1,3 +1,4 @@
++1111
+ aaaa
+ cccc
+ bbbb
+"""
+ }
+ result = program.main(
+ args=('revert', 'd8bce26fa65c6fc8f39c17927abb77f69fab82fc', '-i', 'pr-branch', '-v'),
+ path=self.path,
+ )
+ self.assertEqual(1, result)
+
+ 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():
+
+ result = program.main(
+ args=('revert', 'd8bce26fa65c6fc8f39c17927abb77f69fab82fc', '-i', 'pr-branch', '-v'),
+ path=self.path,
+ )
+ self.assertEqual(0, result)
+ result = program.main(
+ args=('pull-request', '-v', '--no-history'),
+ path=self.path,
+ )
+ self.assertEqual(0, result)
+
+ self.assertEqual(
+ captured.stdout.getvalue(),
+ "Created the local development branch 'eng/pr-branch'\n"
+ "Created 'PR 1 | Revert \"Patch Series\"'!\n"
+ "https://github.example.com/WebKit/WebKit/pull/1\n"
+ "Updated 'PR 1 | Revert \"Patch Series\"'!\n"
+ "https://github.example.com/WebKit/WebKit/pull/1\n",
+ )
+ self.assertEqual(captured.stderr.getvalue(), '')
+ log = captured.root.log.getvalue().splitlines()
+ self.assertEqual(
+ [line for line in log if 'Mock process' not in line], [
+ "Creating the local development branch 'eng/pr-branch'...",
+ ' Found 1 commit...',
+ 'Reverted d8bce26fa65c6fc8f39c17927abb77f69fab82fc',
+ "Rebasing 'eng/pr-branch' on 'main'...",
+ "Rebased 'eng/pr-branch' on 'main!'",
+ " Found 1 commit...",
+ "Pushing 'eng/pr-branch' to 'fork'...",
+ "Syncing 'main' to remote 'fork'",
+ "Creating 'eng/pr-branch-1' as a reference branch",
+ "Creating pull-request for 'eng/pr-branch'...",
+ 'Adding comment for reverted commits...',
+ ' Found 1 commit...',
+ 'Using committed changes...',
+ "Rebasing 'eng/pr-branch' on 'main'...",
+ "Rebased 'eng/pr-branch' on 'main!'",
+ ' Found 1 commit...',
+ "Checking PR labels for 'merging-blocked'...",
+ "Pushing 'eng/pr-branch' to 'fork'...",
+ "Syncing 'main' to remote 'fork'",
+ "Updating pull-request for 'eng/pr-branch'..."
+ ],
+ )
Modified: trunk/metadata/contributors.json (293174 => 293175)
--- trunk/metadata/contributors.json 2022-04-21 17:10:24 UTC (rev 293174)
+++ trunk/metadata/contributors.json 2022-04-21 17:16:37 UTC (rev 293175)
@@ -7103,6 +7103,7 @@
"[email protected]",
"[email protected]"
],
+ "github" : "facetothefate",
"name" : "Zhifei Fang",
"nicks" : [
"zhifei_fang",