Title: [285890] trunk/Tools
Revision
285890
Author
jbed...@apple.com
Date
2021-11-16 14:55:52 -0800 (Tue, 16 Nov 2021)

Log Message

[git-webkit] Mark landed changes as merged
https://bugs.webkit.org/show_bug.cgi?id=233056
<rdar://problem/85351564>

Reviewed by Dewei Zhu.

For BitBucket and GitHub to recognize a pull-request as merged, the target
branch must be updated with the exact commit to be merged as the merge occurs.

* Scripts/libraries/webkitscmpy/setup.py: Bump version.
* Scripts/libraries/webkitscmpy/webkitscmpy/__init__.py: Ditto.
* Scripts/libraries/webkitscmpy/webkitscmpy/program/land.py:
(Land.main): Update source branch when merging commits to target branch.
* Scripts/libraries/webkitscmpy/webkitscmpy/remote/bitbucket.py:
(BitBucket.PRGenerator.update): Only delete values if they exist.
* Scripts/libraries/webkitscmpy/webkitscmpy/test/land_unittest.py:
(TestLand):
(TestLandGitHub):
(TestLandBitBucket):

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

Modified Paths

Diff

Modified: trunk/Tools/ChangeLog (285889 => 285890)


--- trunk/Tools/ChangeLog	2021-11-16 22:53:58 UTC (rev 285889)
+++ trunk/Tools/ChangeLog	2021-11-16 22:55:52 UTC (rev 285890)
@@ -1,3 +1,25 @@
+2021-11-12  Jonathan Bedard  <jbed...@apple.com>
+
+        [git-webkit] Mark landed changes as merged
+        https://bugs.webkit.org/show_bug.cgi?id=233056
+        <rdar://problem/85351564>
+
+        Reviewed by Dewei Zhu.
+
+        For BitBucket and GitHub to recognize a pull-request as merged, the target
+        branch must be updated with the exact commit to be merged as the merge occurs.
+
+        * Scripts/libraries/webkitscmpy/setup.py: Bump version.
+        * Scripts/libraries/webkitscmpy/webkitscmpy/__init__.py: Ditto.
+        * Scripts/libraries/webkitscmpy/webkitscmpy/program/land.py:
+        (Land.main): Update source branch when merging commits to target branch.
+        * Scripts/libraries/webkitscmpy/webkitscmpy/remote/bitbucket.py:
+        (BitBucket.PRGenerator.update): Only delete values if they exist.
+        * Scripts/libraries/webkitscmpy/webkitscmpy/test/land_unittest.py:
+        (TestLand):
+        (TestLandGitHub):
+        (TestLandBitBucket):
+
 2021-11-16  Chris Dumez  <cdu...@apple.com>
 
         Crash under WebKit::WebPageProxy::commitProvisionalPage()

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/land.py (285889 => 285890)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/land.py	2021-11-16 22:53:58 UTC (rev 285889)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/land.py	2021-11-16 22:55:52 UTC (rev 285890)
@@ -27,9 +27,10 @@
 from .canonicalize import Canonicalize
 from .command import Command
 from .branch import Branch
+from .pull_request import PullRequest
 from argparse import Namespace
 from webkitcorepy import arguments, run, string_utils, Terminal
-from webkitscmpy import local, log
+from webkitscmpy import local, log, remote
 
 
 class Land(Command):
@@ -75,11 +76,12 @@
             sys.stderr.write("Cannot 'land' on a canonical SVN repository that is not configured as git-svn\n")
             return 1
 
-        if not Branch.editable(repository.branch, repository=repository):
+        source_branch = repository.branch
+        if not Branch.editable(source_branch, repository=repository):
             sys.stderr.write("Can only 'land' editable branches\n")
             return 1
         branch_point = Branch.branch_point(repository)
-        commits = list(repository.commits(begin=dict(hash=branch_point.hash), end=dict(branch=repository.branch)))
+        commits = list(repository.commits(begin=dict(hash=branch_point.hash), end=dict(branch=source_branch)))
         if not commits:
             sys.stderr.write('Failed to find commits to land\n')
             return 1
@@ -87,11 +89,11 @@
         pull_request = None
         rmt = repository.remote()
         if rmt and rmt.pull_requests:
-            candidates = list(rmt.pull_requests.find(opened=True, head=repository.branch))
+            candidates = list(rmt.pull_requests.find(opened=True, head=source_branch))
             if len(candidates) == 1:
                 pull_request = candidates[0]
             elif candidates:
-                sys.stderr.write("Multiple pull-request match '{}'\n".format(repository.branch))
+                sys.stderr.write("Multiple pull-request match '{}'\n".format(source_branch))
 
         if pull_request and args.review:
             if pull_request.blockers:
@@ -118,17 +120,17 @@
                     '--env-filter', "GIT_AUTHOR_DATE='{date}';GIT_COMMITTER_DATE='{date}'".format(
                         date='{} -{}'.format(int(time.time()), repository.gmtoffset())
                     ), '--msg-filter', 'sed "s/NOBODY (OO*PP*S!*)/{}/g"'.format(string_utils.join([p.name for p in pull_request.approvers])),
-                    '{}...{}'.format(repository.branch, branch_point.hash),
+                    '{}...{}'.format(source_branch, branch_point.hash),
                 ], cwd=repository.root_path, env={'FILTER_BRANCH_SQUELCH_WARNING': '1'}, capture_output=True).returncode:
                     sys.stderr.write('Failed to set reviewers\n')
                     return 1
-                commits = list(repository.commits(begin=dict(hash=branch_point.hash), end=dict(branch=repository.branch)))
+                commits = list(repository.commits(begin=dict(hash=branch_point.hash), end=dict(branch=source_branch)))
                 if not commits:
                     sys.stderr.write('Failed to find commits after setting reviewers\n')
                     return 1
 
         elif not pull_request:
-            sys.stderr.write("Failed to find pull-request associated with '{}'\n".format(repository.branch))
+            sys.stderr.write("Failed to find pull-request associated with '{}'\n".format(source_branch))
 
         if not args.oops and any([cls.OOPS_RE.search(commit.message) for commit in commits]):
             sys.stderr.write("Found '(OOPS!)' message in commit messages, please resolve before committing\n")
@@ -135,27 +137,26 @@
             return 1
 
         if not args.oops:
-            for line in repository.diff_lines(branch_point.hash, repository.branch):
+            for line in repository.diff_lines(branch_point.hash, source_branch):
                 if cls.OOPS_RE.search(line):
                     sys.stderr.write("Found '(OOPS!)' in commit diff, please resolve before committing\n")
                     return 1
 
         target = pull_request.base if pull_request else branch_point.branch
-        log.warning("Rebasing '{}' from '{}' to '{}'...".format(repository.branch, branch_point.branch, target))
+        log.warning("Rebasing '{}' from '{}' to '{}'...".format(source_branch, branch_point.branch, target))
         if repository.fetch(branch=target, remote=cls.REMOTE):
             sys.stderr.write("Failed to fetch '{}' from '{}'\n".format(target, cls.REMOTE))
             return 1
-        if repository.rebase(target=target, base=branch_point.branch, head=repository.branch):
-            sys.stderr.write("Failed to rebase '{}' onto '{}', please resolve conflicts\n".format(repository.branch, target))
+        if repository.rebase(target=target, base=branch_point.branch, head=source_branch):
+            sys.stderr.write("Failed to rebase '{}' onto '{}', please resolve conflicts\n".format(source_branch, target))
             return 1
-        log.warning("Rebased '{}' from '{}' to '{}'!".format(repository.branch, branch_point.branch, target))
+        log.warning("Rebased '{}' from '{}' to '{}'!".format(source_branch, branch_point.branch, target))
 
-        if run([repository.executable(), 'branch', '-f', target, repository.branch], cwd=repository.root_path).returncode:
+        if run([repository.executable(), 'branch', '-f', target, source_branch], cwd=repository.root_path).returncode:
             sys.stderr.write("Failed to move '{}' ref\n".format(target))
             return 1
 
         if identifier_template:
-            source = repository.branch
             repository.checkout(target)
             if Canonicalize.main(Namespace(
                 identifier=True, remote=cls.REMOTE, number=len(commits),
@@ -162,10 +163,13 @@
             ), repository, identifier_template=identifier_template):
                 sys.stderr.write("Failed to embed identifiers to '{}'\n".format(target))
                 return 1
-            if run([repository.executable(), 'branch', '-f', source, target], cwd=repository.root_path).returncode:
+            if run([repository.executable(), 'branch', '-f', source_branch, target], cwd=repository.root_path).returncode:
                 sys.stderr.write("Failed to move '{}' ref to the canonicalized head of '{}'\n".format(source, target))
                 return -1
 
+        # Need to compute the remote source
+        remote_target = 'fork' if isinstance(rmt, remote.GitHub) else 'origin'
+
         if canonical_svn:
             if run([repository.executable(), 'svn', 'fetch'], cwd=repository.root_path).returncode:
                 sys.stderr.write("Failed to update subversion refs\n".format(target))
@@ -181,17 +185,41 @@
             latest = original
             while original.hash == latest.hash:
                 if time.time() - started > cls.MIRROR_TIMEOUT:
-                    sys.stderr.write("Timed out waiting for the git-svn mirror, '{}' landed but not closed\n".format(pull_request or repository.branch))
+                    sys.stderr.write("Timed out waiting for the git-svn mirror, '{}' landed but not closed\n".format(pull_request or source_branch))
                     return 1
                 log.warning('    Verifying mirror processesed change')
                 time.sleep(5)
                 run([repository.executable(), 'pull'], cwd=repository.root_path)
-                original = repository.find('HEAD', include_log=False, include_identifier=False)
+                latest = repository.find('HEAD', include_log=False, include_identifier=False)
+            if pull_request:
+                run([repository.executable(), 'branch', '-f', source_branch, target], cwd=repository.root_path)
+                commits = list(repository.commits(begin=dict(argument='{}~{}'.format(source_branch, len(commits))), end=dict(branch=source_branch)))
+                run([repository.executable(), 'push', '-f', remote_target, source_branch], cwd=repository.root_path)
+                rmt.pull_requests.update(
+                    pull_request=pull_request,
+                    title=PullRequest.title_for(commits),
+                    commits=commits,
+                    base=branch_point.branch,
+                    head=source_branch,
+                )
 
         else:
+            if pull_request:
+                log.warning("Updating '{}' to match landing commits...".format(pull_request))
+                commits = list(repository.commits(begin=dict(argument='{}~{}'.format(source_branch, len(commits))), end=dict(branch=source_branch)))
+                run([repository.executable(), 'push', '-f', remote_target, source_branch], cwd=repository.root_path)
+                rmt.pull_requests.update(
+                    pull_request=pull_request,
+                    title=PullRequest.title_for(commits),
+                    commits=commits,
+                    base=branch_point.branch,
+                    head=source_branch,
+                )
+
             if run([repository.executable(), 'push', cls.REMOTE, target], cwd=repository.root_path).returncode:
                 sys.stderr.write("Failed to push '{}' to '{}'\n".format(target, cls.REMOTE))
                 return 1
+            repository.checkout(target)
 
         commit = repository.commit(branch=target, include_log=False)
         if identifier_template and commit.identifier:
@@ -202,6 +230,8 @@
 
         if pull_request:
             pull_request.comment(land_message)
-            pull_request.close()
 
+        if args.defaults or Terminal.choose("Delete branch '{}'?".format(source_branch), default='Yes') == 'Yes':
+            run([repository.executable(), 'branch', '-D', source_branch], cwd=repository.root_path)
+            run([repository.executable(), 'push', remote_target, '--delete', source_branch], cwd=repository.root_path)
         return 0

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/remote/bitbucket.py (285889 => 285890)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/remote/bitbucket.py	2021-11-16 22:53:58 UTC (rev 285889)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/remote/bitbucket.py	2021-11-16 22:55:52 UTC (rev 285890)
@@ -202,8 +202,8 @@
             if response.status_code // 100 != 2:
                 return None
             data = ""
-            del data['author']
-            del data['participants']
+            data.pop('author', None)
+            data.pop('participants', None)
             data.update(to_change)
 
             response = requests.put(pr_url, json=data)

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/land_unittest.py (285889 => 285890)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/land_unittest.py	2021-11-16 22:53:58 UTC (rev 285889)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/land_unittest.py	2021-11-16 22:55:52 UTC (rev 285890)
@@ -90,7 +90,7 @@
         self.assertEqual(captured.stdout.getvalue(), '')
 
     def test_default(self):
-        with OutputCapture() as captured, repository(self.path, has_oops=False), mocks.local.Svn():
+        with OutputCapture() as captured, repository(self.path, has_oops=False), mocks.local.Svn(), MockTerminal.input('n'):
             self.assertEqual(0, program.main(
                 args=('land',),
                 path=self.path,
@@ -109,10 +109,14 @@
             captured.stderr.getvalue(),
             "Failed to find pull-request associated with 'eng/example'\n",
         )
-        self.assertEqual(captured.stdout.getvalue(), 'Landed a5fe8afe9bf7d07158fcd9e9732ff02a712db2fd!\n')
+        self.assertEqual(
+            captured.stdout.getvalue(),
+            'Landed a5fe8afe9bf7d07158fcd9e9732ff02a712db2fd!\n'
+            "Delete branch 'eng/example'? (Yes/No): \n",
+        )
 
     def test_canonicalize(self):
-        with OutputCapture() as captured, repository(self.path, has_oops=False), mocks.local.Svn():
+        with OutputCapture() as captured, repository(self.path, has_oops=False), mocks.local.Svn(), MockTerminal.input('n'):
             self.assertEqual(0, program.main(
                 args=('land',),
                 path=self.path,
@@ -145,7 +149,8 @@
             captured.stdout.getvalue(),
             'Rewrite a5fe8afe9bf7d07158fcd9e9732ff02a712db2fd (1/1) (--- seconds passed, remaining --- predicted)\n'
             '1 commit successfully canonicalized!\n'
-            'Landed https://commits.webkit.org/6@main (a5fe8afe9bf7d07158fcd9e9732ff02a712db2fd)!\n',
+            'Landed https://commits.webkit.org/6@main (a5fe8afe9bf7d07158fcd9e9732ff02a712db2fd)!\n'
+            "Delete branch 'eng/example'? (Yes/No): \n",
         )
 
     def test_no_svn_canonical_svn(self):
@@ -163,8 +168,7 @@
         self.assertEqual(captured.stdout.getvalue(), '')
 
     def test_svn(self):
-        self.maxDiff = None
-        with MockTime, OutputCapture() as captured, repository(self.path, has_oops=False, git_svn=True), mocks.local.Svn():
+        with MockTime, OutputCapture() as captured, repository(self.path, has_oops=False, git_svn=True), mocks.local.Svn(), MockTerminal.input('n'):
             self.assertEqual(0, program.main(
                 args=('land',),
                 path=self.path, canonical_svn=True,
@@ -186,7 +190,8 @@
         )
         self.assertEqual(
             captured.stdout.getvalue(),
-            'Landed a5fe8afe9bf7d07158fcd9e9732ff02a712db2fd!\n',
+            'Landed a5fe8afe9bf7d07158fcd9e9732ff02a712db2fd!\n'
+            "Delete branch 'eng/example'? (Yes/No): \n",
         )
 
 
@@ -281,7 +286,7 @@
         self.assertEqual(captured.stdout.getvalue(), '')
 
     def test_insert_review(self):
-        with OutputCapture() as captured, MockTerminal.input('y'), self.webserver(approved=True) as remote, \
+        with OutputCapture() as captured, MockTerminal.input('y', 'n'), self.webserver(approved=True) as remote, \
                 repository(self.path, has_oops=True, remote='https://{}'.format(remote.remote)), mocks.local.Svn():
             self.assertEqual(0, program.main(
                 args=('land',),
@@ -302,6 +307,7 @@
                 'Setting Ricky Reviewer as reviewer',
                 "Rebasing 'eng/example' from 'main' to 'main'...",
                 "Rebased 'eng/example' from 'main' to 'main'!",
+                "Updating 'PR 1 | Example Change' to match landing commits...",
             ],
         )
         self.assertEqual(captured.stderr.getvalue(), '')
@@ -308,7 +314,8 @@
         self.assertEqual(
             captured.stdout.getvalue(),
             "Set 'Ricky Reviewer' as your reviewer? (Yes/No): \n"
-            'Landed a5fe8afe9bf7d07158fcd9e9732ff02a712db2fd!\n',
+            'Landed a5fe8afe9bf7d07158fcd9e9732ff02a712db2fd!\n'
+            "Delete branch 'eng/example'? (Yes/No): \n",
         )
 
 
@@ -406,7 +413,7 @@
         self.assertEqual(captured.stdout.getvalue(), '')
 
     def test_insert_review(self):
-        with OutputCapture() as captured, MockTerminal.input('y'), self.webserver(approved=True) as remote, repository(
+        with OutputCapture() as captured, MockTerminal.input('y', 'n'), self.webserver(approved=True) as remote, repository(
                 self.path, has_oops=True, remote='ssh://git@{}/{}/{}.git'.format(
                     remote.hosts[0], remote.project.split('/')[1], remote.project.split('/')[3],
                 )), mocks.local.Svn():
@@ -429,6 +436,7 @@
                 'Setting Ricky Reviewer as reviewer',
                 "Rebasing 'eng/example' from 'main' to 'main'...",
                 "Rebased 'eng/example' from 'main' to 'main'!",
+                "Updating 'PR 1 | Example Change' to match landing commits...",
             ],
         )
         self.assertEqual(captured.stderr.getvalue(), '')
@@ -435,5 +443,6 @@
         self.assertEqual(
             captured.stdout.getvalue(),
             "Set 'Ricky Reviewer' as your reviewer? (Yes/No): \n"
-            'Landed a5fe8afe9bf7d07158fcd9e9732ff02a712db2fd!\n',
+            'Landed a5fe8afe9bf7d07158fcd9e9732ff02a712db2fd!\n'
+            "Delete branch 'eng/example'? (Yes/No): \n",
         )
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to