| 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 |