Skip to content

Commit f386f9b

Browse files
committed
[utils] Cross repositories pull request test support (#4583)
* [utils] Cross repositories pull request test support
1 parent de74c5a commit f386f9b

File tree

1 file changed

+45
-9
lines changed

1 file changed

+45
-9
lines changed

utils/update-checkout

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@ from __future__ import print_function
1414
import argparse
1515
import json
1616
import os
17+
import re
1718
import sys
1819

20+
1921
from functools import reduce
2022

2123
sys.path.append(os.path.dirname(__file__))
@@ -32,7 +34,8 @@ sys.path.append(os.path.join(SCRIPT_DIR, 'swift_build_support'))
3234
from swift_build_support import shell # noqa (E402)
3335

3436

35-
def update_single_repository(repo_path, branch, reset_to_remote, should_clean):
37+
def update_single_repository(repo_path, branch, reset_to_remote, should_clean,
38+
cross_repos_pr):
3639
if not os.path.isdir(repo_path):
3740
return
3841

@@ -43,8 +46,16 @@ def update_single_repository(repo_path, branch, reset_to_remote, should_clean):
4346
if should_clean:
4447
shell.call(['git', 'clean', '-fdx'],
4548
echo=True)
46-
shell.call(['git', 'reset', '--hard', 'HEAD'],
47-
echo=True)
49+
shell.call(['git', 'submodule', 'foreach', '--recursive', 'git',
50+
'clean', '-fdx'], echo=True)
51+
shell.call(['git', 'submodule', 'foreach', '--recursive', 'git',
52+
'reset', '--hard', 'HEAD'], echo=True)
53+
status = shell.call(['git', 'reset', '--hard', 'HEAD'],
54+
echo=True)
55+
if status:
56+
print("Please, commit your changes.")
57+
print(status)
58+
exit(1)
4859

4960
if branch:
5061
status = shell.capture(['git', 'status', '--porcelain', '-uno'],
@@ -65,17 +76,19 @@ def update_single_repository(repo_path, branch, reset_to_remote, should_clean):
6576
# Prior to Git 2.6, this is the way to do a "git pull
6677
# --rebase" that respects rebase.autostash. See
6778
# http://stackoverflow.com/a/30209750/125349
68-
shell.call(["git", "rebase", "FETCH_HEAD"], echo=True)
79+
if not cross_repos_pr:
80+
shell.call(["git", "rebase", "FETCH_HEAD"], echo=True)
6981
shell.call(["git", "submodule", "update", "--recursive"],
7082
echo=True)
7183

7284

73-
def update_all_repositories(args, config, scheme_name):
85+
def update_all_repositories(args, config, scheme_name, cross_repos_pr):
7486
repo_branch = scheme_name
7587
for repo_name in config['repos'].keys():
7688
if repo_name in args.skip_repository_list:
7789
print("--- Skipping '" + repo_name + "' ---")
7890
continue
91+
repo_path = os.path.join(SWIFT_SOURCE_ROOT, repo_name)
7992
if scheme_name:
8093
# This loop is only correct, since we know that each alias set has
8194
# unique contents. This is checked by verify config. Thus the first
@@ -85,12 +98,22 @@ def update_all_repositories(args, config, scheme_name):
8598
if scheme_name not in v['aliases']:
8699
continue
87100
repo_branch = v['repos'][repo_name]
101+
remote_repo_id = config['repos'][repo_name]['remote']['id']
102+
if remote_repo_id in cross_repos_pr:
103+
pr_id = cross_repos_pr[remote_repo_id]
104+
repo_branch = "ci_pr_{0}".format(pr_id)
105+
with shell.pushd(repo_path, dry_run=False, echo=False):
106+
shell.capture(["git", "branch", "-D", repo_branch],
107+
echo=True, allow_non_zero_exit=True)
108+
shell.call(["git", "fetch", "origin",
109+
"pull/{0}/merge:{1}"
110+
.format(pr_id, repo_branch)], echo=True)
88111
break
89-
90-
update_single_repository(os.path.join(SWIFT_SOURCE_ROOT, repo_name),
112+
update_single_repository(repo_path,
91113
repo_branch,
92114
args.reset_to_remote,
93-
args.clean)
115+
args.clean,
116+
cross_repos_pr)
94117

95118

96119
def obtain_additional_swift_sources(
@@ -209,17 +232,30 @@ By default, updates your checkouts of Swift, SourceKit, LLDB, and SwiftPM.""")
209232
"--config",
210233
default=os.path.join(SCRIPT_DIR, "update-checkout-config.json"),
211234
help="Configuration file to use")
235+
parser.add_argument(
236+
"--github-comment",
237+
help="""Check out related pull requests referenced in the given
238+
free-form GitHub-style comment.""",
239+
metavar='GITHUB-COMMENT',
240+
dest='github_comment')
212241
args = parser.parse_args()
213242

214243
clone = args.clone
215244
clone_with_ssh = args.clone_with_ssh
216245
skip_history = args.skip_history
217246
scheme = args.scheme
247+
github_comment = args.github_comment
218248

219249
with open(args.config) as f:
220250
config = json.load(f)
221251
validate_config(config)
222252

253+
cross_repos_pr = {}
254+
if github_comment:
255+
repos_with_pr = re.findall(r'apple/[-a-zA-Z0-9_]+#\d+', github_comment)
256+
print("Found related pull requests:", str(repos_with_pr))
257+
cross_repos_pr = dict(pr.split('#') for pr in repos_with_pr)
258+
223259
if clone or clone_with_ssh:
224260
# If branch is None, default to using the default branch alias
225261
# specified by our configuration file.
@@ -230,7 +266,7 @@ By default, updates your checkouts of Swift, SourceKit, LLDB, and SwiftPM.""")
230266
config, clone_with_ssh, scheme, skip_history,
231267
args.skip_repository_list)
232268

233-
update_all_repositories(args, config, scheme)
269+
update_all_repositories(args, config, scheme, cross_repos_pr)
234270

235271
return 0
236272

0 commit comments

Comments
 (0)