Title: [293175] trunk
Revision
293175
Author
[email protected]
Date
2022-04-21 10:16:37 -0700 (Thu, 21 Apr 2022)

Log Message

[git-webkit] Add revert command (237663)
https://bugs.webkit.org/show_bug.cgi?id=237663
rdar://90039948

Reviewed by Jonathan Bedard.

* Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/pull_request.py: Break the pull request creation into serval differnt funtions so that other action can reuse it easily.
(PullRequest):
(PullRequest.check_pull_request_args):
(PullRequest.pull_request_branch_point):
(PullRequest.create_pull_request):
(PullRequest.main):
* Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/revert.py: Added.
(Revert):
(Revert.parser):
(Revert.revert_commit):
(Revert.main):

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

Modified Paths

Added Paths

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",
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to