Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(67)

Side by Side Diff: gclient_scm.py

Issue 549733002: Fix gclient branch ref mangling and allow --force branch switches. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: lint Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | scm.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 """Gclient-specific SCM-specific operations.""" 5 """Gclient-specific SCM-specific operations."""
6 6
7 from __future__ import print_function 7 from __future__ import print_function
8 8
9 import errno 9 import errno
10 import logging 10 import logging
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after
362 rev_str = ' at %s' % revision 362 rev_str = ' at %s' % revision
363 files = [] if file_list is not None else None 363 files = [] if file_list is not None else None
364 364
365 printed_path = False 365 printed_path = False
366 verbose = [] 366 verbose = []
367 if options.verbose: 367 if options.verbose:
368 self.Print('_____ %s%s' % (self.relpath, rev_str), timestamp=False) 368 self.Print('_____ %s%s' % (self.relpath, rev_str), timestamp=False)
369 verbose = ['--verbose'] 369 verbose = ['--verbose']
370 printed_path = True 370 printed_path = True
371 371
372 if revision.startswith('refs/'): 372 remote_ref = scm.GIT.RefToRemoteRef(revision, self.remote)
373 if remote_ref:
374 # Rewrite remote refs to their local equivalents.
375 revision = ''.join(remote_ref)
373 rev_type = "branch" 376 rev_type = "branch"
374 elif revision.startswith(self.remote + '/'): 377 elif revision.startswith('refs/'):
375 # Rewrite remote refs to their local equivalents. 378 # Local branch? We probably don't want to support, since DEPS should
376 revision = 'refs/remotes/' + revision 379 # always specify branches as they are in the upstream repo.
377 rev_type = "branch" 380 rev_type = "branch"
378 else: 381 else:
379 # hash is also a tag, only make a distinction at checkout 382 # hash is also a tag, only make a distinction at checkout
380 rev_type = "hash" 383 rev_type = "hash"
381 384
382 mirror = self._GetMirror(url, options) 385 mirror = self._GetMirror(url, options)
383 if mirror: 386 if mirror:
384 url = mirror.mirror_path 387 url = mirror.mirror_path
385 388
386 if (not os.path.exists(self.checkout_path) or 389 if (not os.path.exists(self.checkout_path) or
387 (os.path.isdir(self.checkout_path) and 390 (os.path.isdir(self.checkout_path) and
388 not os.path.exists(os.path.join(self.checkout_path, '.git')))): 391 not os.path.exists(os.path.join(self.checkout_path, '.git')))):
389 if mirror: 392 if mirror:
390 self._UpdateMirror(mirror, options) 393 self._UpdateMirror(mirror, options)
391 try: 394 try:
392 self._Clone(revision, url, options) 395 self._Clone(revision, url, options)
393 except subprocess2.CalledProcessError: 396 except subprocess2.CalledProcessError:
394 self._DeleteOrMove(options.force) 397 self._DeleteOrMove(options.force)
395 self._Clone(revision, url, options) 398 self._Clone(revision, url, options)
396 if deps_revision and deps_revision.startswith('branch-heads/'):
397 deps_branch = deps_revision.replace('branch-heads/', '')
398 self._Capture(['branch', deps_branch, deps_revision])
399 self._Checkout(options, deps_branch, quiet=True)
400 if file_list is not None: 399 if file_list is not None:
401 files = self._Capture(['ls-files']).splitlines() 400 files = self._Capture(['ls-files']).splitlines()
402 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) 401 file_list.extend([os.path.join(self.checkout_path, f) for f in files])
403 if not verbose: 402 if not verbose:
404 # Make the output a little prettier. It's nice to have some whitespace 403 # Make the output a little prettier. It's nice to have some whitespace
405 # between projects when cloning. 404 # between projects when cloning.
406 self.Print('') 405 self.Print('')
407 return self._Capture(['rev-parse', '--verify', 'HEAD']) 406 return self._Capture(['rev-parse', '--verify', 'HEAD'])
408 407
409 if not managed: 408 if not managed:
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
444 443
445 # Cases: 444 # Cases:
446 # 0) HEAD is detached. Probably from our initial clone. 445 # 0) HEAD is detached. Probably from our initial clone.
447 # - make sure HEAD is contained by a named ref, then update. 446 # - make sure HEAD is contained by a named ref, then update.
448 # Cases 1-4. HEAD is a branch. 447 # Cases 1-4. HEAD is a branch.
449 # 1) current branch is not tracking a remote branch (could be git-svn) 448 # 1) current branch is not tracking a remote branch (could be git-svn)
450 # - try to rebase onto the new hash or branch 449 # - try to rebase onto the new hash or branch
451 # 2) current branch is tracking a remote branch with local committed 450 # 2) current branch is tracking a remote branch with local committed
452 # changes, but the DEPS file switched to point to a hash 451 # changes, but the DEPS file switched to point to a hash
453 # - rebase those changes on top of the hash 452 # - rebase those changes on top of the hash
454 # 3) current branch is tracking a remote branch w/or w/out changes, 453 # 3) current branch is tracking a remote branch w/or w/out changes, and
455 # no switch 454 # no DEPS switch
456 # - see if we can FF, if not, prompt the user for rebase, merge, or stop 455 # - see if we can FF, if not, prompt the user for rebase, merge, or stop
457 # 4) current branch is tracking a remote branch, switches to a different 456 # 4) current branch is tracking a remote branch, but DEPS switches to a
458 # remote branch 457 # different remote branch, and
459 # - exit 458 # a) current branch has no local changes, and --force:
459 # - checkout new branch
460 # b) current branch has local changes, and --force and --reset:
461 # - checkout new branch
462 # c) otherwise exit
460 463
461 # GetUpstreamBranch returns something like 'refs/remotes/origin/master' for 464 # GetUpstreamBranch returns something like 'refs/remotes/origin/master' for
462 # a tracking branch 465 # a tracking branch
463 # or 'master' if not a tracking branch (it's based on a specific rev/hash) 466 # or 'master' if not a tracking branch (it's based on a specific rev/hash)
464 # or it returns None if it couldn't find an upstream 467 # or it returns None if it couldn't find an upstream
465 if cur_branch is None: 468 if cur_branch is None:
466 upstream_branch = None 469 upstream_branch = None
467 current_type = "detached" 470 current_type = "detached"
468 logging.debug("Detached HEAD") 471 logging.debug("Detached HEAD")
469 else: 472 else:
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
527 upstream_branch = revision 530 upstream_branch = revision
528 self._AttemptRebase(upstream_branch, files, options, 531 self._AttemptRebase(upstream_branch, files, options,
529 printed_path=printed_path, merge=options.merge) 532 printed_path=printed_path, merge=options.merge)
530 printed_path = True 533 printed_path = True
531 elif rev_type == 'hash': 534 elif rev_type == 'hash':
532 # case 2 535 # case 2
533 self._AttemptRebase(upstream_branch, files, options, 536 self._AttemptRebase(upstream_branch, files, options,
534 newbase=revision, printed_path=printed_path, 537 newbase=revision, printed_path=printed_path,
535 merge=options.merge) 538 merge=options.merge)
536 printed_path = True 539 printed_path = True
537 elif revision.replace('heads', 'remotes/' + self.remote) != upstream_branch: 540 elif remote_ref and ''.join(remote_ref) != upstream_branch:
538 # case 4 541 # case 4
539 new_base = revision.replace('heads', 'remotes/' + self.remote) 542 new_base = ''.join(remote_ref)
540 if not printed_path: 543 if not printed_path:
541 self.Print('_____ %s%s' % (self.relpath, rev_str), timestamp=False) 544 self.Print('_____ %s%s' % (self.relpath, rev_str), timestamp=False)
542 switch_error = ("Switching upstream branch from %s to %s\n" 545 switch_error = ("Could not switch upstream branch from %s to %s\n"
543 % (upstream_branch, new_base) + 546 % (upstream_branch, new_base) +
544 "Please merge or rebase manually:\n" + 547 "Please use --force or merge or rebase manually:\n" +
545 "cd %s; git rebase %s\n" % (self.checkout_path, new_base) + 548 "cd %s; git rebase %s\n" % (self.checkout_path, new_base) +
546 "OR git checkout -b <some new branch> %s" % new_base) 549 "OR git checkout -b <some new branch> %s" % new_base)
547 raise gclient_utils.Error(switch_error) 550 force_switch = False
551 if options.force:
552 try:
553 self._CheckClean(rev_str)
554 # case 4a
555 force_switch = True
556 except gclient_utils.Error as e:
557 if options.reset:
558 # case 4b
559 force_switch = True
560 else:
561 switch_error = '%s\n%s' % (e.message, switch_error)
562 if force_switch:
563 self.Print("Switching upstream branch from %s to %s" %
564 (upstream_branch, new_base))
565 switch_branch = 'gclient_' + remote_ref[1]
566 self._Capture(['branch', '-f', switch_branch, new_base])
567 self._Checkout(options, switch_branch, force=True, quiet=True)
568 else:
569 # case 4c
570 raise gclient_utils.Error(switch_error)
548 else: 571 else:
549 # case 3 - the default case 572 # case 3 - the default case
550 if files is not None: 573 if files is not None:
551 files = self._Capture(['diff', upstream_branch, '--name-only']).split() 574 files = self._Capture(['diff', upstream_branch, '--name-only']).split()
552 if verbose: 575 if verbose:
553 self.Print('Trying fast-forward merge to branch : %s' % upstream_branch) 576 self.Print('Trying fast-forward merge to branch : %s' % upstream_branch)
554 try: 577 try:
555 merge_args = ['merge'] 578 merge_args = ['merge']
556 if options.merge: 579 if options.merge:
557 merge_args.append('--ff') 580 merge_args.append('--ff')
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after
863 except: 886 except:
864 traceback.print_exc(file=self.out_fh) 887 traceback.print_exc(file=self.out_fh)
865 raise 888 raise
866 finally: 889 finally:
867 if os.listdir(tmp_dir): 890 if os.listdir(tmp_dir):
868 self.Print('_____ removing non-empty tmp dir %s' % tmp_dir) 891 self.Print('_____ removing non-empty tmp dir %s' % tmp_dir)
869 gclient_utils.rmtree(tmp_dir) 892 gclient_utils.rmtree(tmp_dir)
870 if template_dir: 893 if template_dir:
871 gclient_utils.rmtree(template_dir) 894 gclient_utils.rmtree(template_dir)
872 self._UpdateBranchHeads(options, fetch=True) 895 self._UpdateBranchHeads(options, fetch=True)
873 self._Checkout(options, revision.replace('refs/heads/', ''), quiet=True) 896 remote_ref = scm.GIT.RefToRemoteRef(revision, self.remote)
897 self._Checkout(options, ''.join(remote_ref or revision), quiet=True)
874 if self._GetCurrentBranch() is None: 898 if self._GetCurrentBranch() is None:
875 # Squelch git's very verbose detached HEAD warning and use our own 899 # Squelch git's very verbose detached HEAD warning and use our own
876 self.Print( 900 self.Print(
877 ('Checked out %s to a detached HEAD. Before making any commits\n' 901 ('Checked out %s to a detached HEAD. Before making any commits\n'
878 'in this repo, you should use \'git checkout <branch>\' to switch to\n' 902 'in this repo, you should use \'git checkout <branch>\' to switch to\n'
879 'an existing branch or use \'git checkout %s -b <branch>\' to\n' 903 'an existing branch or use \'git checkout %s -b <branch>\' to\n'
880 'create a new branch for your work.') % (revision, self.remote)) 904 'create a new branch for your work.') % (revision, self.remote))
881 905
882 def _AskForData(self, prompt, options): 906 def _AskForData(self, prompt, options):
883 if options.jobs > 1: 907 if options.jobs > 1:
(...skipping 692 matching lines...) Expand 10 before | Expand all | Expand 10 after
1576 new_command.append('--force') 1600 new_command.append('--force')
1577 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: 1601 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]:
1578 new_command.extend(('--accept', 'theirs-conflict')) 1602 new_command.extend(('--accept', 'theirs-conflict'))
1579 elif options.manually_grab_svn_rev: 1603 elif options.manually_grab_svn_rev:
1580 new_command.append('--force') 1604 new_command.append('--force')
1581 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: 1605 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]:
1582 new_command.extend(('--accept', 'postpone')) 1606 new_command.extend(('--accept', 'postpone'))
1583 elif command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: 1607 elif command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]:
1584 new_command.extend(('--accept', 'postpone')) 1608 new_command.extend(('--accept', 'postpone'))
1585 return new_command 1609 return new_command
OLDNEW
« no previous file with comments | « no previous file | scm.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698