OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright 2014 The Chromium Authors. All rights reserved. | 2 # Copyright 2014 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """ | 6 """ |
7 Tool to update all branches to have the latest changes from their upstreams. | 7 Tool to update all branches to have the latest changes from their upstreams. |
8 """ | 8 """ |
9 | 9 |
10 import argparse | 10 import argparse |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
189 | 189 |
190 git.remove_merge_base(branch) | 190 git.remove_merge_base(branch) |
191 git.get_or_create_merge_base(branch) | 191 git.get_or_create_merge_base(branch) |
192 | 192 |
193 return True | 193 return True |
194 | 194 |
195 | 195 |
196 def main(args=None): | 196 def main(args=None): |
197 parser = argparse.ArgumentParser() | 197 parser = argparse.ArgumentParser() |
198 parser.add_argument('--verbose', '-v', action='store_true') | 198 parser.add_argument('--verbose', '-v', action='store_true') |
| 199 parser.add_argument('--keep-going', '-k', action='store_true', |
| 200 help='Keep processing past failed rebases.') |
199 parser.add_argument('--no_fetch', '--no-fetch', '-n', | 201 parser.add_argument('--no_fetch', '--no-fetch', '-n', |
200 action='store_true', | 202 action='store_true', |
201 help='Skip fetching remotes.') | 203 help='Skip fetching remotes.') |
202 opts = parser.parse_args(args) | 204 opts = parser.parse_args(args) |
203 | 205 |
204 if opts.verbose: # pragma: no cover | 206 if opts.verbose: # pragma: no cover |
205 logging.getLogger().setLevel(logging.DEBUG) | 207 logging.getLogger().setLevel(logging.DEBUG) |
206 | 208 |
207 # TODO(iannucci): snapshot all branches somehow, so we can implement | 209 # TODO(iannucci): snapshot all branches somehow, so we can implement |
208 # `git rebase-update --undo`. | 210 # `git rebase-update --undo`. |
(...skipping 29 matching lines...) Expand all Loading... |
238 fetch_remotes(branch_tree) | 240 fetch_remotes(branch_tree) |
239 | 241 |
240 merge_base = {} | 242 merge_base = {} |
241 for branch, parent in branch_tree.iteritems(): | 243 for branch, parent in branch_tree.iteritems(): |
242 merge_base[branch] = git.get_or_create_merge_base(branch, parent) | 244 merge_base[branch] = git.get_or_create_merge_base(branch, parent) |
243 | 245 |
244 logging.debug('branch_tree: %s' % pformat(branch_tree)) | 246 logging.debug('branch_tree: %s' % pformat(branch_tree)) |
245 logging.debug('merge_base: %s' % pformat(merge_base)) | 247 logging.debug('merge_base: %s' % pformat(merge_base)) |
246 | 248 |
247 retcode = 0 | 249 retcode = 0 |
| 250 unrebased_branches = [] |
248 # Rebase each branch starting with the root-most branches and working | 251 # Rebase each branch starting with the root-most branches and working |
249 # towards the leaves. | 252 # towards the leaves. |
250 for branch, parent in git.topo_iter(branch_tree): | 253 for branch, parent in git.topo_iter(branch_tree): |
251 if git.is_dormant(branch): | 254 if git.is_dormant(branch): |
252 print 'Skipping dormant branch', branch | 255 print 'Skipping dormant branch', branch |
253 else: | 256 else: |
254 ret = rebase_branch(branch, parent, merge_base[branch]) | 257 ret = rebase_branch(branch, parent, merge_base[branch]) |
255 if not ret: | 258 if not ret: |
256 retcode = 1 | 259 retcode = 1 |
257 break | 260 |
| 261 if opts.keep_going: |
| 262 print '--keep-going set, continuing with next branch.' |
| 263 unrebased_branches.append(branch) |
| 264 if git.in_rebase(): |
| 265 git.run_with_retcode('rebase', '--abort') |
| 266 if git.in_rebase(): # pragma: no cover |
| 267 print 'Failed to abort rebase. Something is really wrong.' |
| 268 break |
| 269 else: |
| 270 break |
| 271 |
| 272 if unrebased_branches: |
| 273 print |
| 274 print 'The following branches could not be cleanly rebased:' |
| 275 for branch in unrebased_branches: |
| 276 print ' %s' % branch |
258 | 277 |
259 if not retcode: | 278 if not retcode: |
260 remove_empty_branches(branch_tree) | 279 remove_empty_branches(branch_tree) |
261 | 280 |
262 # return_branch may not be there any more. | 281 # return_branch may not be there any more. |
263 if return_branch in git.branches(): | 282 if return_branch in git.branches(): |
264 git.run('checkout', return_branch) | 283 git.run('checkout', return_branch) |
265 git.thaw() | 284 git.thaw() |
266 else: | 285 else: |
267 root_branch = git.root() | 286 root_branch = git.root() |
(...skipping 10 matching lines...) Expand all Loading... |
278 | 297 |
279 return retcode | 298 return retcode |
280 | 299 |
281 | 300 |
282 if __name__ == '__main__': # pragma: no cover | 301 if __name__ == '__main__': # pragma: no cover |
283 try: | 302 try: |
284 sys.exit(main()) | 303 sys.exit(main()) |
285 except KeyboardInterrupt: | 304 except KeyboardInterrupt: |
286 sys.stderr.write('interrupted\n') | 305 sys.stderr.write('interrupted\n') |
287 sys.exit(1) | 306 sys.exit(1) |
OLD | NEW |