@@ -14,8 +14,10 @@ from __future__ import print_function
1414import argparse
1515import json
1616import os
17+ import re
1718import sys
1819
20+
1921from functools import reduce
2022
2123sys .path .append (os .path .dirname (__file__ ))
@@ -32,7 +34,8 @@ sys.path.append(os.path.join(SCRIPT_DIR, 'swift_build_support'))
3234from 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
96119def 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