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

Side by Side Diff: gclient_scm.py

Issue 3353018: Make gclient_scm_test much more silent (Closed)
Patch Set: gclient_scm_test can now be run Created 10 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
« no previous file with comments | « PRESUBMIT.py ('k') | gclient_utils.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) 2010 The Chromium Authors. All rights reserved. 1 # Copyright (c) 2010 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 import logging 7 import logging
8 import os 8 import os
9 import posixpath 9 import posixpath
10 import re 10 import re
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 " branch.") 251 " branch.")
252 elif upstream_branch.startswith('refs/remotes'): 252 elif upstream_branch.startswith('refs/remotes'):
253 current_type = "branch" 253 current_type = "branch"
254 else: 254 else:
255 raise gclient_utils.Error('Invalid Upstream: %s' % upstream_branch) 255 raise gclient_utils.Error('Invalid Upstream: %s' % upstream_branch)
256 256
257 # Update the remotes first so we have all the refs. 257 # Update the remotes first so we have all the refs.
258 backoff_time = 5 258 backoff_time = 5
259 for _ in range(10): 259 for _ in range(10):
260 try: 260 try:
261 remote_output, remote_err = scm.GIT.Capture( 261 remote_output = scm.GIT.Capture(
262 ['remote'] + verbose + ['update'], 262 ['remote'] + verbose + ['update'],
263 self.checkout_path, 263 cwd=self.checkout_path)
264 print_error=False)
265 break 264 break
266 except gclient_utils.CheckCallError, e: 265 except gclient_utils.CheckCallError, e:
267 # Hackish but at that point, git is known to work so just checking for 266 # Hackish but at that point, git is known to work so just checking for
268 # 502 in stderr should be fine. 267 # 502 in stderr should be fine.
269 if '502' in e.stderr: 268 if '502' in e.stderr:
270 options.stdout.write(str(e) + '\n') 269 options.stdout.write(str(e) + '\n')
271 options.stdout.write('Sleeping %.1f seconds and retrying...\n' % 270 options.stdout.write('Sleeping %.1f seconds and retrying...\n' %
272 backoff_time) 271 backoff_time)
273 time.sleep(backoff_time) 272 time.sleep(backoff_time)
274 backoff_time *= 1.3 273 backoff_time *= 1.3
275 continue 274 continue
276 raise 275 raise
277 276
278 if verbose: 277 if verbose:
279 options.stdout.write(remote_output.strip() + '\n') 278 options.stdout.write(remote_output)
280 # git remote update prints to stderr when used with --verbose
281 options.stdout.write(remote_err.strip() + '\n')
282 279
283 # This is a big hammer, debatable if it should even be here... 280 # This is a big hammer, debatable if it should even be here...
284 if options.force or options.reset: 281 if options.force or options.reset:
285 self._Run(['reset', '--hard', 'HEAD'], options) 282 self._Run(['reset', '--hard', 'HEAD'], options)
286 283
287 if current_type == 'detached': 284 if current_type == 'detached':
288 # case 0 285 # case 0
289 self._CheckClean(rev_str) 286 self._CheckClean(rev_str)
290 self._CheckDetachedHead(rev_str, options) 287 self._CheckDetachedHead(rev_str, options)
291 self._Capture(['checkout', '--quiet', '%s^0' % revision]) 288 self._Capture(['checkout', '--quiet', '%s^0' % revision])
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
324 "cd %s; git rebase %s\n" % (self.checkout_path, new_base) + 321 "cd %s; git rebase %s\n" % (self.checkout_path, new_base) +
325 "OR git checkout -b <some new branch> %s" % new_base) 322 "OR git checkout -b <some new branch> %s" % new_base)
326 raise gclient_utils.Error(switch_error) 323 raise gclient_utils.Error(switch_error)
327 else: 324 else:
328 # case 3 - the default case 325 # case 3 - the default case
329 files = self._Capture(['diff', upstream_branch, '--name-only']).split() 326 files = self._Capture(['diff', upstream_branch, '--name-only']).split()
330 if verbose: 327 if verbose:
331 options.stdout.write('Trying fast-forward merge to branch : %s\n' % 328 options.stdout.write('Trying fast-forward merge to branch : %s\n' %
332 upstream_branch) 329 upstream_branch)
333 try: 330 try:
334 merge_output, merge_err = scm.GIT.Capture(['merge', '--ff-only', 331 merge_output = scm.GIT.Capture(['merge', '--ff-only', upstream_branch],
335 upstream_branch], 332 cwd=self.checkout_path)
336 self.checkout_path,
337 print_error=False)
338 except gclient_utils.CheckCallError, e: 333 except gclient_utils.CheckCallError, e:
339 if re.match('fatal: Not possible to fast-forward, aborting.', e.stderr): 334 if re.match('fatal: Not possible to fast-forward, aborting.', e.stderr):
340 if not printed_path: 335 if not printed_path:
341 options.stdout.write('\n_____ %s%s\n' % (self.relpath, rev_str)) 336 options.stdout.write('\n_____ %s%s\n' % (self.relpath, rev_str))
342 printed_path = True 337 printed_path = True
343 while True: 338 while True:
344 try: 339 try:
345 # TODO(maruel): That can't work. 340 # TODO(maruel): That can't work with --jobs.
346 action = str(raw_input("Cannot fast-forward merge, attempt to " 341 action = str(raw_input("Cannot fast-forward merge, attempt to "
347 "rebase? (y)es / (q)uit / (s)kip : ")) 342 "rebase? (y)es / (q)uit / (s)kip : "))
348 except ValueError: 343 except ValueError:
349 gclient_utils.Error('Invalid Character') 344 gclient_utils.Error('Invalid Character')
350 continue 345 continue
351 if re.match(r'yes|y', action, re.I): 346 if re.match(r'yes|y', action, re.I):
352 self._AttemptRebase(upstream_branch, files, options, 347 self._AttemptRebase(upstream_branch, files, options,
353 printed_path=printed_path) 348 printed_path=printed_path)
354 printed_path = True 349 printed_path = True
355 break 350 break
(...skipping 19 matching lines...) Expand all
375 # Some other problem happened with the merge 370 # Some other problem happened with the merge
376 logging.error("Error during fast-forward merge in %s!" % self.relpath) 371 logging.error("Error during fast-forward merge in %s!" % self.relpath)
377 options.stdout.write(e.stderr + '\n') 372 options.stdout.write(e.stderr + '\n')
378 raise 373 raise
379 else: 374 else:
380 # Fast-forward merge was successful 375 # Fast-forward merge was successful
381 if not re.match('Already up-to-date.', merge_output) or verbose: 376 if not re.match('Already up-to-date.', merge_output) or verbose:
382 if not printed_path: 377 if not printed_path:
383 options.stdout.write('\n_____ %s%s\n' % (self.relpath, rev_str)) 378 options.stdout.write('\n_____ %s%s\n' % (self.relpath, rev_str))
384 printed_path = True 379 printed_path = True
385 print merge_output.strip() 380 options.stdout.write(merge_output)
386 if merge_err:
387 options.stdout.write('Merge produced error output:\n%s\n' %
388 merge_err.strip())
389 if not verbose: 381 if not verbose:
390 # Make the output a little prettier. It's nice to have some 382 # Make the output a little prettier. It's nice to have some
391 # whitespace between projects when syncing. 383 # whitespace between projects when syncing.
392 options.stdout.write('\n') 384 options.stdout.write('\n')
393 385
394 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) 386 file_list.extend([os.path.join(self.checkout_path, f) for f in files])
395 387
396 # If the rebase generated a conflict, abort and ask user to fix 388 # If the rebase generated a conflict, abort and ask user to fix
397 if self._IsRebasing(): 389 if self._IsRebasing():
398 raise gclient_utils.Error('\n____ %s%s\n' 390 raise gclient_utils.Error('\n____ %s%s\n'
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
523 rebase_cmd = ['rebase'] 515 rebase_cmd = ['rebase']
524 if options.verbose: 516 if options.verbose:
525 rebase_cmd.append('--verbose') 517 rebase_cmd.append('--verbose')
526 if newbase: 518 if newbase:
527 rebase_cmd.extend(['--onto', newbase]) 519 rebase_cmd.extend(['--onto', newbase])
528 rebase_cmd.append(upstream) 520 rebase_cmd.append(upstream)
529 if branch: 521 if branch:
530 rebase_cmd.append(branch) 522 rebase_cmd.append(branch)
531 523
532 try: 524 try:
533 rebase_output, rebase_err = scm.GIT.Capture(rebase_cmd, 525 rebase_output = scm.GIT.Capture(rebase_cmd, cwd=self.checkout_path)
534 self.checkout_path,
535 print_error=False)
536 except gclient_utils.CheckCallError, e: 526 except gclient_utils.CheckCallError, e:
537 if re.match(r'cannot rebase: you have unstaged changes', e.stderr) or \ 527 if (re.match(r'cannot rebase: you have unstaged changes', e.stderr) or
538 re.match(r'cannot rebase: your index contains uncommitted changes', 528 re.match(r'cannot rebase: your index contains uncommitted changes',
539 e.stderr): 529 e.stderr)):
540 while True: 530 while True:
541 rebase_action = str(raw_input("Cannot rebase because of unstaged " 531 rebase_action = str(raw_input("Cannot rebase because of unstaged "
542 "changes.\n'git reset --hard HEAD' ?\n" 532 "changes.\n'git reset --hard HEAD' ?\n"
543 "WARNING: destroys any uncommitted " 533 "WARNING: destroys any uncommitted "
544 "work in your current branch!" 534 "work in your current branch!"
545 " (y)es / (q)uit / (s)how : ")) 535 " (y)es / (q)uit / (s)how : "))
546 if re.match(r'yes|y', rebase_action, re.I): 536 if re.match(r'yes|y', rebase_action, re.I):
547 self._Run(['reset', '--hard', 'HEAD'], options) 537 self._Run(['reset', '--hard', 'HEAD'], options)
548 # Should this be recursive? 538 # Should this be recursive?
549 rebase_output, rebase_err = scm.GIT.Capture(rebase_cmd, 539 rebase_output = scm.GIT.Capture(rebase_cmd, cwd=self.checkout_path)
550 self.checkout_path)
551 break 540 break
552 elif re.match(r'quit|q', rebase_action, re.I): 541 elif re.match(r'quit|q', rebase_action, re.I):
553 raise gclient_utils.Error("Please merge or rebase manually\n" 542 raise gclient_utils.Error("Please merge or rebase manually\n"
554 "cd %s && git " % self.checkout_path 543 "cd %s && git " % self.checkout_path
555 + "%s" % ' '.join(rebase_cmd)) 544 + "%s" % ' '.join(rebase_cmd))
556 elif re.match(r'show|s', rebase_action, re.I): 545 elif re.match(r'show|s', rebase_action, re.I):
557 options.stdout.write('\n%s\n' % e.stderr.strip()) 546 options.stdout.write('\n%s\n' % e.stderr.strip())
558 continue 547 continue
559 else: 548 else:
560 gclient_utils.Error("Input not recognized") 549 gclient_utils.Error("Input not recognized")
561 continue 550 continue
562 elif re.search(r'^CONFLICT', e.stdout, re.M): 551 elif re.search(r'^CONFLICT', e.stdout, re.M):
563 raise gclient_utils.Error("Conflict while rebasing this branch.\n" 552 raise gclient_utils.Error("Conflict while rebasing this branch.\n"
564 "Fix the conflict and run gclient again.\n" 553 "Fix the conflict and run gclient again.\n"
565 "See 'man git-rebase' for details.\n") 554 "See 'man git-rebase' for details.\n")
566 else: 555 else:
567 options.stdout.write(e.stdout.strip() + '\n') 556 options.stdout.write(e.stdout.strip() + '\n')
568 options.stdout.write('Rebase produced error output:\n%s\n' % 557 options.stdout.write('Rebase produced error output:\n%s\n' %
569 e.stderr.strip()) 558 e.stderr.strip())
570 raise gclient_utils.Error("Unrecognized error, please merge or rebase " 559 raise gclient_utils.Error("Unrecognized error, please merge or rebase "
571 "manually.\ncd %s && git " % 560 "manually.\ncd %s && git " %
572 self.checkout_path 561 self.checkout_path
573 + "%s" % ' '.join(rebase_cmd)) 562 + "%s" % ' '.join(rebase_cmd))
574 563
575 print rebase_output.strip() 564 options.stdout.write(rebase_output)
576 if rebase_err:
577 options.stdout.write('Rebase produced error output:\n%s\n' %
578 rebase_err.strip())
579 if not options.verbose: 565 if not options.verbose:
580 # Make the output a little prettier. It's nice to have some 566 # Make the output a little prettier. It's nice to have some
581 # whitespace between projects when syncing. 567 # whitespace between projects when syncing.
582 options.stdout.write('\n') 568 options.stdout.write('\n')
583 569
584 @staticmethod 570 @staticmethod
585 def _CheckMinVersion(min_version): 571 def _CheckMinVersion(min_version):
586 (ok, current_version) = scm.GIT.AssertVersion(min_version) 572 (ok, current_version) = scm.GIT.AssertVersion(min_version)
587 if not ok: 573 if not ok:
588 raise gclient_utils.Error('git version %s < minimum required %s' % 574 raise gclient_utils.Error('git version %s < minimum required %s' %
589 (current_version, min_version)) 575 (current_version, min_version))
590 576
591 def _IsRebasing(self): 577 def _IsRebasing(self):
592 # Check for any of REBASE-i/REBASE-m/REBASE/AM. Unfortunately git doesn't 578 # Check for any of REBASE-i/REBASE-m/REBASE/AM. Unfortunately git doesn't
593 # have a plumbing command to determine whether a rebase is in progress, so 579 # have a plumbing command to determine whether a rebase is in progress, so
594 # for now emualate (more-or-less) git-rebase.sh / git-completion.bash 580 # for now emualate (more-or-less) git-rebase.sh / git-completion.bash
595 g = os.path.join(self.checkout_path, '.git') 581 g = os.path.join(self.checkout_path, '.git')
596 return ( 582 return (
597 os.path.isdir(os.path.join(g, "rebase-merge")) or 583 os.path.isdir(os.path.join(g, "rebase-merge")) or
598 os.path.isdir(os.path.join(g, "rebase-apply"))) 584 os.path.isdir(os.path.join(g, "rebase-apply")))
599 585
600 def _CheckClean(self, rev_str): 586 def _CheckClean(self, rev_str):
601 # Make sure the tree is clean; see git-rebase.sh for reference 587 # Make sure the tree is clean; see git-rebase.sh for reference
602 try: 588 try:
603 scm.GIT.Capture(['update-index', '--ignore-submodules', '--refresh'], 589 scm.GIT.Capture(['update-index', '--ignore-submodules', '--refresh'],
604 self.checkout_path, print_error=False) 590 cwd=self.checkout_path)
605 except gclient_utils.CheckCallError: 591 except gclient_utils.CheckCallError:
606 raise gclient_utils.Error('\n____ %s%s\n' 592 raise gclient_utils.Error('\n____ %s%s\n'
607 '\tYou have unstaged changes.\n' 593 '\tYou have unstaged changes.\n'
608 '\tPlease commit, stash, or reset.\n' 594 '\tPlease commit, stash, or reset.\n'
609 % (self.relpath, rev_str)) 595 % (self.relpath, rev_str))
610 try: 596 try:
611 scm.GIT.Capture(['diff-index', '--cached', '--name-status', '-r', 597 scm.GIT.Capture(['diff-index', '--cached', '--name-status', '-r',
612 '--ignore-submodules', 'HEAD', '--'], self.checkout_path, 598 '--ignore-submodules', 'HEAD', '--'],
613 print_error=False) 599 cwd=self.checkout_path)
614 except gclient_utils.CheckCallError: 600 except gclient_utils.CheckCallError:
615 raise gclient_utils.Error('\n____ %s%s\n' 601 raise gclient_utils.Error('\n____ %s%s\n'
616 '\tYour index contains uncommitted changes\n' 602 '\tYour index contains uncommitted changes\n'
617 '\tPlease commit, stash, or reset.\n' 603 '\tPlease commit, stash, or reset.\n'
618 % (self.relpath, rev_str)) 604 % (self.relpath, rev_str))
619 605
620 def _CheckDetachedHead(self, rev_str, options): 606 def _CheckDetachedHead(self, rev_str, options):
621 # HEAD is detached. Make sure it is safe to move away from (i.e., it is 607 # HEAD is detached. Make sure it is safe to move away from (i.e., it is
622 # reference by a commit). If not, error out -- most likely a rebase is 608 # reference by a commit). If not, error out -- most likely a rebase is
623 # in progress, try to detect so we can give a better error. 609 # in progress, try to detect so we can give a better error.
624 try: 610 try:
625 _, _ = scm.GIT.Capture( 611 scm.GIT.Capture(['name-rev', '--no-undefined', 'HEAD'],
626 ['name-rev', '--no-undefined', 'HEAD'], 612 cwd=self.checkout_path)
627 self.checkout_path,
628 print_error=False)
629 except gclient_utils.CheckCallError: 613 except gclient_utils.CheckCallError:
630 # Commit is not contained by any rev. See if the user is rebasing: 614 # Commit is not contained by any rev. See if the user is rebasing:
631 if self._IsRebasing(): 615 if self._IsRebasing():
632 # Punt to the user 616 # Punt to the user
633 raise gclient_utils.Error('\n____ %s%s\n' 617 raise gclient_utils.Error('\n____ %s%s\n'
634 '\tAlready in a conflict, i.e. (no branch).\n' 618 '\tAlready in a conflict, i.e. (no branch).\n'
635 '\tFix the conflict and run gclient again.\n' 619 '\tFix the conflict and run gclient again.\n'
636 '\tOr to abort run:\n\t\tgit-rebase --abort\n' 620 '\tOr to abort run:\n\t\tgit-rebase --abort\n'
637 '\tSee man git-rebase for details.\n' 621 '\tSee man git-rebase for details.\n'
638 % (self.relpath, rev_str)) 622 % (self.relpath, rev_str))
639 # Let's just save off the commit so we can proceed. 623 # Let's just save off the commit so we can proceed.
640 name = ('saved-by-gclient-' + 624 name = ('saved-by-gclient-' +
641 self._Capture(['rev-parse', '--short', 'HEAD'])) 625 self._Capture(['rev-parse', '--short', 'HEAD']))
642 self._Capture(['branch', name]) 626 self._Capture(['branch', name])
643 options.stdout.write( 627 options.stdout.write(
644 '\n_____ found an unreferenced commit and saved it as \'%s\'\n' % 628 '\n_____ found an unreferenced commit and saved it as \'%s\'\n' %
645 name) 629 name)
646 630
647 def _GetCurrentBranch(self): 631 def _GetCurrentBranch(self):
648 # Returns name of current branch or None for detached HEAD 632 # Returns name of current branch or None for detached HEAD
649 branch = self._Capture(['rev-parse', '--abbrev-ref=strict', 'HEAD']) 633 branch = self._Capture(['rev-parse', '--abbrev-ref=strict', 'HEAD'])
650 if branch == 'HEAD': 634 if branch == 'HEAD':
651 return None 635 return None
652 return branch 636 return branch
653 637
654 def _Capture(self, args): 638 def _Capture(self, args):
655 return gclient_utils.CheckCall(['git'] + args, 639 return gclient_utils.CheckCall(
656 cwd=self.checkout_path)[0].strip() 640 ['git'] + args, cwd=self.checkout_path, print_error=False)[0].strip()
657 641
658 def _Run(self, args, options, **kwargs): 642 def _Run(self, args, options, **kwargs):
659 kwargs.setdefault('cwd', self.checkout_path) 643 kwargs.setdefault('cwd', self.checkout_path)
660 gclient_utils.CheckCallAndFilterAndHeader(['git'] + args, 644 gclient_utils.CheckCallAndFilterAndHeader(['git'] + args,
661 always=options.verbose, stdout=options.stdout, **kwargs) 645 always=options.verbose, stdout=options.stdout, **kwargs)
662 646
663 647
664 class SVNWrapper(SCMWrapper): 648 class SVNWrapper(SCMWrapper):
665 """ Wrapper for SVN """ 649 """ Wrapper for SVN """
666 650
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
963 947
964 This method returns a new list to be used as a command.""" 948 This method returns a new list to be used as a command."""
965 new_command = command[:] 949 new_command = command[:]
966 if revision: 950 if revision:
967 new_command.extend(['--revision', str(revision).strip()]) 951 new_command.extend(['--revision', str(revision).strip()])
968 # --force was added to 'svn update' in svn 1.5. 952 # --force was added to 'svn update' in svn 1.5.
969 if ((options.force or options.manually_grab_svn_rev) and 953 if ((options.force or options.manually_grab_svn_rev) and
970 scm.SVN.AssertVersion("1.5")[0]): 954 scm.SVN.AssertVersion("1.5")[0]):
971 new_command.append('--force') 955 new_command.append('--force')
972 return new_command 956 return new_command
OLDNEW
« no previous file with comments | « PRESUBMIT.py ('k') | gclient_utils.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698