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

Side by Side Diff: trychange.py

Issue 184343003: Now trychange can store patches in a Git repo (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: nit Created 6 years, 9 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
« scm.py ('K') | « tests/trychange_unittest.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 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 """Client-side script to send a try job to the try server. It communicates to 6 """Client-side script to send a try job to the try server. It communicates to
7 the try server by either writting to a svn repository or by directly connecting 7 the try server by either writting to a svn/git repository or by directly
8 to the server by HTTP. 8 connecting to the server by HTTP.
9 """ 9 """
10 10
11 import datetime 11 import datetime
12 import errno 12 import errno
13 import getpass 13 import getpass
14 import itertools 14 import itertools
15 import json 15 import json
16 import logging 16 import logging
17 import optparse 17 import optparse
18 import os 18 import os
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
63 premade diff file on the local drive: 63 premade diff file on the local drive:
64 %(prog)s --email user@example.com 64 %(prog)s --email user@example.com
65 --svn_repo svn://svn.chromium.org/chrome-try/try --diff foo.diff 65 --svn_repo svn://svn.chromium.org/chrome-try/try --diff foo.diff
66 66
67 Running only on a 'mac' slave with revision 123 and clobber first; specify 67 Running only on a 'mac' slave with revision 123 and clobber first; specify
68 manually the 3 source files to use for the try job: 68 manually the 3 source files to use for the try job:
69 %(prog)s --bot mac --revision 123 --clobber -f src/a.cc -f src/a.h 69 %(prog)s --bot mac --revision 123 --clobber -f src/a.cc -f src/a.h
70 -f include/b.h 70 -f include/b.h
71 """ 71 """
72 72
73 GIT_PATCH_DIR_BASENAME = os.path.join('git-try', 'patches-git')
73 74
74 def DieWithError(message): 75 def DieWithError(message):
75 print >> sys.stderr, message 76 print >> sys.stderr, message
76 sys.exit(1) 77 sys.exit(1)
77 78
78 79
79 def RunCommand(args, error_ok=False, error_message=None, **kwargs): 80 def RunCommand(args, error_ok=False, error_message=None, **kwargs):
80 try: 81 try:
81 return subprocess2.check_output(args, shell=False, **kwargs) 82 return subprocess2.check_output(args, shell=False, **kwargs)
82 except subprocess2.CalledProcessError, e: 83 except subprocess2.CalledProcessError, e:
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 """Set default settings based on the gcl-style settings from the repository. 158 """Set default settings based on the gcl-style settings from the repository.
158 159
159 The settings in the self.options object will only be set if no previous 160 The settings in the self.options object will only be set if no previous
160 value exists (i.e. command line flags to the try command will override the 161 value exists (i.e. command line flags to the try command will override the
161 settings in codereview.settings). 162 settings in codereview.settings).
162 """ 163 """
163 settings = { 164 settings = {
164 'port': self.GetCodeReviewSetting('TRYSERVER_HTTP_PORT'), 165 'port': self.GetCodeReviewSetting('TRYSERVER_HTTP_PORT'),
165 'host': self.GetCodeReviewSetting('TRYSERVER_HTTP_HOST'), 166 'host': self.GetCodeReviewSetting('TRYSERVER_HTTP_HOST'),
166 'svn_repo': self.GetCodeReviewSetting('TRYSERVER_SVN_URL'), 167 'svn_repo': self.GetCodeReviewSetting('TRYSERVER_SVN_URL'),
168 'git_repo': self.GetCodeReviewSetting('TRYSERVER_GIT_URL'),
167 'project': self.GetCodeReviewSetting('TRYSERVER_PROJECT'), 169 'project': self.GetCodeReviewSetting('TRYSERVER_PROJECT'),
170 # primarily for revision=auto
171 'revision': self.GetCodeReviewSetting('TRYSERVER_REVISION'),
168 'root': self.GetCodeReviewSetting('TRYSERVER_ROOT'), 172 'root': self.GetCodeReviewSetting('TRYSERVER_ROOT'),
169 'patchlevel': self.GetCodeReviewSetting('TRYSERVER_PATCHLEVEL'), 173 'patchlevel': self.GetCodeReviewSetting('TRYSERVER_PATCHLEVEL'),
170 } 174 }
171 logging.info('\n'.join(['%s: %s' % (k, v) 175 logging.info('\n'.join(['%s: %s' % (k, v)
172 for (k, v) in settings.iteritems() if v])) 176 for (k, v) in settings.iteritems() if v]))
173 for (k, v) in settings.iteritems(): 177 for (k, v) in settings.iteritems():
174 # Avoid overwriting options already set using command line flags. 178 # Avoid overwriting options already set using command line flags.
175 if v and getattr(self.options, k) is None: 179 if v and getattr(self.options, k) is None:
176 setattr(self.options, k, v) 180 setattr(self.options, k, v)
177 181
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 283
280 The files in the list should either be absolute paths or relative to the 284 The files in the list should either be absolute paths or relative to the
281 given root. 285 given root.
282 """ 286 """
283 return scm.SVN.GenerateDiff(self.files, self.checkout_root, full_move=True, 287 return scm.SVN.GenerateDiff(self.files, self.checkout_root, full_move=True,
284 revision=self.diff_against) 288 revision=self.diff_against)
285 289
286 290
287 class GIT(SCM): 291 class GIT(SCM):
288 """Gathers the options and diff for a git checkout.""" 292 """Gathers the options and diff for a git checkout."""
293
289 def __init__(self, *args, **kwargs): 294 def __init__(self, *args, **kwargs):
290 SCM.__init__(self, *args, **kwargs) 295 SCM.__init__(self, *args, **kwargs)
291 self.checkout_root = scm.GIT.GetCheckoutRoot(self.checkout_root) 296 self.checkout_root = scm.GIT.GetCheckoutRoot(self.checkout_root)
292 if not self.options.name: 297 if not self.options.name:
293 self.options.name = scm.GIT.GetPatchName(self.checkout_root) 298 self.options.name = scm.GIT.GetPatchName(self.checkout_root)
294 if not self.options.email: 299 if not self.options.email:
295 self.options.email = scm.GIT.GetEmail(self.checkout_root) 300 self.options.email = scm.GIT.GetEmail(self.checkout_root)
296 if not self.diff_against: 301 if not self.diff_against:
297 self.diff_against = scm.GIT.GetUpstreamBranch(self.checkout_root) 302 self.diff_against = scm.GIT.GetUpstreamBranch(self.checkout_root)
298 if not self.diff_against: 303 if not self.diff_against:
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 399
395 bot_spec.extend(_ApplyTestFilter(options.testfilter, new_style)) 400 bot_spec.extend(_ApplyTestFilter(options.testfilter, new_style))
396 401
397 except ImportError: 402 except ImportError:
398 pass 403 pass
399 404
400 return bot_spec 405 return bot_spec
401 406
402 407
403 def _ParseSendChangeOptions(bot_spec, options): 408 def _ParseSendChangeOptions(bot_spec, options):
404 """Parse common options passed to _SendChangeHTTP and _SendChangeSVN.""" 409 """Parse common options passed to _SendChangeHTTP, _SendChangeSVN and
410 _SendChangeGit."""
agable 2014/03/04 21:45:59 nit: multiline docstring formatting.
nodir 2014/03/04 22:51:19 Done.
405 values = [ 411 values = [
406 ('user', options.user), 412 ('user', options.user),
407 ('name', options.name), 413 ('name', options.name),
408 ] 414 ]
409 if options.email: 415 if options.email:
410 values.append(('email', options.email)) 416 values.append(('email', options.email))
411 if options.revision: 417 if options.revision:
412 values.append(('revision', options.revision)) 418 values.append(('revision', options.revision))
413 if options.clobber: 419 if options.clobber:
414 values.append(('clobber', 'true')) 420 values.append(('clobber', 'true'))
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
465 str(e.args))) 471 str(e.args)))
466 if not connection: 472 if not connection:
467 raise NoTryServerAccess('%s is unaccessible.' % url) 473 raise NoTryServerAccess('%s is unaccessible.' % url)
468 logging.info('Reading response...') 474 logging.info('Reading response...')
469 response = connection.read() 475 response = connection.read()
470 logging.info('Done') 476 logging.info('Done')
471 if response != 'OK': 477 if response != 'OK':
472 raise NoTryServerAccess('%s is unaccessible. Got:\n%s' % (url, response)) 478 raise NoTryServerAccess('%s is unaccessible. Got:\n%s' % (url, response))
473 479
474 480
481 def _PrepareDescriptionAndPatchFiles(description, options, callback):
482 """Create temporary files with description and patch, execute the callback
483 and delete the files.
484
485 Args:
agable 2014/03/04 21:45:59 Should be a complete list of args, not just the co
nodir 2014/03/04 22:51:19 Done.
486 callback: a function with signature (patch_filename, description_filename),
487 executed between birth and death of temporary files.
488 """
489
490 # Create a temporary file and put description into it
agable 2014/03/04 21:45:59 nit: sentence-like comments should have periods.
nodir 2014/03/04 22:51:19 Done.
491 with tempfile.NamedTemporaryFile() as description_file:
492 description_file.write(description)
493 description_file.flush()
494
495 # Create a temporary directory, put a uniquely named file in it with the
496 # diff content
497 temp_dir = tempfile.mkdtemp()
498 try:
499 current_time = str(datetime.datetime.now()).replace(':', '.')
500 file_name = '%s.%s.%s.diff' % (Escape(options.user),
501 Escape(options.name), current_time)
502 full_patch_filename = os.path.join(temp_dir, file_name)
503 with open(full_patch_filename, 'wb') as f:
504 f.write(options.diff)
505
506 callback(full_patch_filename, description_file.name)
507 finally:
508 shutil.rmtree(temp_dir, True)
509
510
475 def _SendChangeSVN(bot_spec, options): 511 def _SendChangeSVN(bot_spec, options):
476 """Send a change to the try server by committing a diff file on a subversion 512 """Send a change to the try server by committing a diff file on a subversion
477 server.""" 513 server."""
478 if not options.svn_repo: 514 if not options.svn_repo:
479 raise NoTryServerAccess('Please use the --svn_repo option to specify the' 515 raise NoTryServerAccess('Please use the --svn_repo option to specify the'
480 ' try server svn repository to connect to.') 516 ' try server svn repository to connect to.')
481 517
482 values = _ParseSendChangeOptions(bot_spec, options) 518 values = _ParseSendChangeOptions(bot_spec, options)
483 description = ''.join("%s=%s\n" % (k, v) for k, v in values) 519 description = ''.join("%s=%s\n" % (k, v) for k, v in values)
484 logging.info('Sending by SVN') 520 logging.info('Sending by SVN')
485 logging.info(description) 521 logging.info(description)
486 logging.info(options.svn_repo) 522 logging.info(options.svn_repo)
487 logging.info(options.diff) 523 logging.info(options.diff)
488 if options.dry_run: 524 if options.dry_run:
489 return 525 return
490 526
491 # Create a temporary directory, put a uniquely named file in it with the diff 527 def send(patch_filename, description_filename):
492 # content and svn import that. 528 """Send the patch file to SVN repo with commit message from the
493 temp_dir = tempfile.mkdtemp() 529 description file"""
494 temp_file = tempfile.NamedTemporaryFile() 530 if sys.platform == "cygwin":
495 try: 531 # Small chromium-specific issue here:
532 # git-try uses /usr/bin/python on cygwin but svn.bat will be used
533 # instead of /usr/bin/svn by default. That causes bad things(tm) since
534 # Windows' svn.exe has no clue about cygwin paths. Hence force to use
535 # the cygwin version in this particular context.
536 exe = "/usr/bin/svn"
537 else:
538 exe = "svn"
539 patch_dir = os.path.dirname(patch_filename)
540 command = [exe, 'import', '-q', patch_dir, options.svn_repo, '--file',
541 description_filename]
542 if scm.SVN.AssertVersion("1.5")[0]:
543 command.append('--no-ignore')
544
496 try: 545 try:
497 # Description
498 temp_file.write(description)
499 temp_file.flush()
500
501 # Diff file
502 current_time = str(datetime.datetime.now()).replace(':', '.')
503 file_name = (Escape(options.user) + '.' + Escape(options.name) +
504 '.%s.diff' % current_time)
505 full_path = os.path.join(temp_dir, file_name)
506 with open(full_path, 'wb') as f:
507 f.write(options.diff)
508
509 # Committing it will trigger a try job.
510 if sys.platform == "cygwin":
511 # Small chromium-specific issue here:
512 # git-try uses /usr/bin/python on cygwin but svn.bat will be used
513 # instead of /usr/bin/svn by default. That causes bad things(tm) since
514 # Windows' svn.exe has no clue about cygwin paths. Hence force to use
515 # the cygwin version in this particular context.
516 exe = "/usr/bin/svn"
517 else:
518 exe = "svn"
519 command = [exe, 'import', '-q', temp_dir, options.svn_repo, '--file',
520 temp_file.name]
521 if scm.SVN.AssertVersion("1.5")[0]:
522 command.append('--no-ignore')
523
524 subprocess2.check_call(command) 546 subprocess2.check_call(command)
525 except subprocess2.CalledProcessError, e: 547 except subprocess2.CalledProcessError, e:
526 raise NoTryServerAccess(str(e)) 548 raise NoTryServerAccess(str(e))
527 finally: 549
528 temp_file.close() 550 _PrepareDescriptionAndPatchFiles(description, options, send)
529 shutil.rmtree(temp_dir, True) 551
552
553 def _GetPatchGitRepo(git_url):
554 """Get a path to a Git repo with patches with latest changes,
555 associated with the given url.
556
557 Store patches in .git/git-try/patches-git directory, a git repo. If it
558 doesn't exist yet or its origin URL is different, then clean up and clone it.
559 If it existed before, then pull changes.
560
561 Does not support SVN repo.
562
563 Returns a path to the directory with patches.
564 """
565 git_dir = scm.GIT.GetGitDir(os.getcwd())
566 patch_dir = os.path.join(git_dir, GIT_PATCH_DIR_BASENAME)
567
568 logging.info('Looking for git repo for patches')
569 # Is there already a repo with the expected url or should we clone?
570 clone = True
571 if os.path.exists(patch_dir) and scm.GIT.IsInsideWorkTree(patch_dir):
572 existing_url = scm.GIT.Capture(
573 ['config', '--local', 'remote.origin.url'],
574 cwd=patch_dir)
575 clone = existing_url != git_url
576
577 if clone:
578 if os.path.exists(patch_dir):
579 logging.info('Cleaning up')
580 shutil.rmtree(patch_dir, True)
581 logging.info('Cloning patch repo')
582 scm.GIT.Capture(['clone', git_url, GIT_PATCH_DIR_BASENAME], cwd=git_dir)
583 else:
584 if scm.GIT.IsWorkTreeDirty(patch_dir):
585 logging.info('Work dir is dirty: hard reset!')
586 scm.GIT.Capture(['reset', '--hard'], cwd=patch_dir)
587 logging.info('Updating patch repo')
588 scm.GIT.Capture(['pull', 'origin', 'master'], cwd=patch_dir)
589
590 return patch_dir
591
592
593 def _SendChangeGit(bot_spec, options):
594 """Send a change to the try server by committing a diff file to a GIT repo"""
595 if not options.git_repo:
596 raise NoTryServerAccess('Please use the --git_repo option to specify the '
597 'try server git repository to connect to.')
598
599 values = _ParseSendChangeOptions(bot_spec, options)
600 comment_subject = '%s.%s' % (options.user, options.name)
601 comment_body = ''.join("%s=%s\n" % (k, v) for k, v in values)
602 description = '%s\n\n%s' % (comment_subject, comment_body)
603 logging.info('Sending by GIT')
604 logging.info(description)
605 logging.info(options.git_repo)
606 logging.info(options.diff)
607 if options.dry_run:
608 return
609
610 patch_dir = _GetPatchGitRepo(options.git_repo)
611 assert scm.GIT.IsInsideWorkTree(patch_dir)
612 assert not scm.GIT.IsWorkTreeDirty(patch_dir)
613
614 def send(patch_filename, description_filename):
615 """Sends the patch file to GIT repo with the description file contents as
616 commit message"""
617 logging.info('Committing patch')
618 target_filename = os.path.join(patch_dir, os.path.basename(patch_filename))
619 target_filename = os.path.abspath(target_filename)
agable 2014/03/04 21:45:59 Combine this into one statement, with indentation
nodir 2014/03/04 22:51:19 Done.
620 shutil.copyfile(patch_filename, target_filename)
621 try:
622 scm.GIT.Capture(['add', '-f', target_filename], cwd=patch_dir)
agable 2014/03/04 21:45:59 the generated patch file that is being added into
nodir 2014/03/04 22:51:19 Done.
623 scm.GIT.Capture(['commit', '-F', description_filename], cwd=patch_dir)
624 assert not scm.GIT.IsWorkTreeDirty(patch_dir)
625 logging.info('Pushing patch')
626 scm.GIT.Capture(['push', 'origin', 'HEAD'], cwd=patch_dir)
627 except subprocess2.CalledProcessError, e:
628 scm.GIT.Capture(['reset', '--hard', 'origin/master'], cwd=patch_dir)
629 raise NoTryServerAccess(str(e))
630
631 _PrepareDescriptionAndPatchFiles(description, options, send)
530 632
531 633
532 def PrintSuccess(bot_spec, options): 634 def PrintSuccess(bot_spec, options):
533 if not options.dry_run: 635 if not options.dry_run:
534 text = 'Patch \'%s\' sent to try server' % options.name 636 text = 'Patch \'%s\' sent to try server' % options.name
535 if bot_spec: 637 if bot_spec:
536 text += ': %s' % ', '.join( 638 text += ': %s' % ', '.join(
537 '%s:%s' % (b[0], ','.join(b[1])) for b in bot_spec) 639 '%s:%s' % (b[0], ','.join(b[1])) for b in bot_spec)
538 print(text) 640 print(text)
539 641
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
635 "times to specify multiple builders. ex: " 737 "times to specify multiple builders. ex: "
636 "'-bwin_rel:ui_tests,webkit_unit_tests -bwin_layout'. See " 738 "'-bwin_rel:ui_tests,webkit_unit_tests -bwin_layout'. See "
637 "the try server waterfall for the builders name and the tests " 739 "the try server waterfall for the builders name and the tests "
638 "available. Can also be used to specify gtest_filter, e.g. " 740 "available. Can also be used to specify gtest_filter, e.g. "
639 "-bwin_rel:base_unittests:ValuesTest.*Value")) 741 "-bwin_rel:base_unittests:ValuesTest.*Value"))
640 group.add_option("-B", "--print_bots", action="store_true", 742 group.add_option("-B", "--print_bots", action="store_true",
641 help="Print bots we would use (e.g. from PRESUBMIT.py)" 743 help="Print bots we would use (e.g. from PRESUBMIT.py)"
642 " and exit. Do not send patch. Like --dry_run" 744 " and exit. Do not send patch. Like --dry_run"
643 " but less verbose.") 745 " but less verbose.")
644 group.add_option("-r", "--revision", 746 group.add_option("-r", "--revision",
645 help="Revision to use for the try job; default: the " 747 help="Revision to use for the try job. If 'auto' is "
748 "specified, it is resolved to the revision a patch is "
749 "generated against (Git only). Default: the "
646 "revision will be determined by the try server; see " 750 "revision will be determined by the try server; see "
647 "its waterfall for more info") 751 "its waterfall for more info")
648 group.add_option("-c", "--clobber", action="store_true", 752 group.add_option("-c", "--clobber", action="store_true",
649 help="Force a clobber before building; e.g. don't do an " 753 help="Force a clobber before building; e.g. don't do an "
650 "incremental build") 754 "incremental build")
651 # TODO(maruel): help="Select a specific configuration, usually 'debug' or " 755 # TODO(maruel): help="Select a specific configuration, usually 'debug' or "
652 # "'release'" 756 # "'release'"
653 group.add_option("--target", help=optparse.SUPPRESS_HELP) 757 group.add_option("--target", help=optparse.SUPPRESS_HELP)
654 758
655 group.add_option("--project", 759 group.add_option("--project",
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
721 group.add_option("--use_svn", 825 group.add_option("--use_svn",
722 action="store_const", 826 action="store_const",
723 const=_SendChangeSVN, 827 const=_SendChangeSVN,
724 dest="send_patch", 828 dest="send_patch",
725 help="Use SVN to talk to the try server") 829 help="Use SVN to talk to the try server")
726 group.add_option("-S", "--svn_repo", 830 group.add_option("-S", "--svn_repo",
727 metavar="SVN_URL", 831 metavar="SVN_URL",
728 help="SVN url to use to write the changes in; --use_svn is " 832 help="SVN url to use to write the changes in; --use_svn is "
729 "implied when using --svn_repo") 833 "implied when using --svn_repo")
730 parser.add_option_group(group) 834 parser.add_option_group(group)
835
836 group = optparse.OptionGroup(parser, "Access the try server with Git")
837 group.add_option("--use_git",
838 action="store_const",
839 const=_SendChangeGit,
840 dest="send_patch",
841 help="Use GIT to talk to the try server")
842 group.add_option("-G", "--git_repo",
843 metavar="GIT_URL",
844 help="GIT url to use to write the changes in; --use_git is "
845 "implied when using --git_repo")
846 parser.add_option_group(group)
731 return parser 847 return parser
732 848
733 849
734 def TryChange(argv, 850 def TryChange(argv,
735 change, 851 change,
736 swallow_exception, 852 swallow_exception,
737 prog=None, 853 prog=None,
738 extra_epilog=None): 854 extra_epilog=None):
739 """ 855 """
740 Args: 856 Args:
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
803 if options.files: 919 if options.files:
804 file_list = options.files 920 file_list = options.files
805 elif change: 921 elif change:
806 file_list = [f.LocalPath() for f in change.AffectedFiles()] 922 file_list = [f.LocalPath() for f in change.AffectedFiles()]
807 923
808 if options.upstream_branch: 924 if options.upstream_branch:
809 path += '@' + options.upstream_branch 925 path += '@' + options.upstream_branch
810 # Clear file list so that the correct list will be retrieved from the 926 # Clear file list so that the correct list will be retrieved from the
811 # upstream branch. 927 # upstream branch.
812 file_list = [] 928 file_list = []
813 checkouts.append(GuessVCS(options, path, file_list)) 929
814 checkouts[0].AutomagicalSettings() 930 current_vcs = GuessVCS(options, path, file_list)
931 current_vcs.AutomagicalSettings()
932 vcs_is_git = type(current_vcs) is GIT
933
934 # So far, git_repo doesn't work with SVN
935 if options.git_repo and not vcs_is_git:
agable 2014/03/04 21:45:59 current_vcs.options.git_repo, to ensure settings f
nodir 2014/03/04 22:51:19 AFAIU, SCM/GIT classes do not clone options, so `o
agable 2014/03/05 19:49:50 Yes, that's correct. current_vcs.options === optio
nodir 2014/03/05 20:07:00 Done.
936 parser.error('--git_repo option is supported only for GIT repositories')
937
938 # If revision==auto, resolve it
939 if options.revision and options.revision.lower() == 'auto':
940 if not vcs_is_git:
941 parser.error('--revision=auto is supported only for GIT repositories')
942 options.revision = scm.GIT.Capture(
943 ['rev-parse', current_vcs.diff_against],
944 cwd=path)
945
946 checkouts.append(current_vcs)
815 for item in options.sub_rep: 947 for item in options.sub_rep:
816 # Pass file_list=None because we don't know the sub repo's file list. 948 # Pass file_list=None because we don't know the sub repo's file list.
817 checkout = GuessVCS(options, 949 checkout = GuessVCS(options,
818 os.path.join(checkouts[0].checkout_root, item), 950 os.path.join(current_vcs.checkout_root, item),
819 None) 951 None)
820 if checkout.checkout_root in [c.checkout_root for c in checkouts]: 952 if checkout.checkout_root in [c.checkout_root for c in checkouts]:
821 parser.error('Specified the root %s two times.' % 953 parser.error('Specified the root %s two times.' %
822 checkout.checkout_root) 954 checkout.checkout_root)
823 checkouts.append(checkout) 955 checkouts.append(checkout)
824 956
825 can_http = options.port and options.host 957 can_http = options.port and options.host
826 can_svn = options.svn_repo 958 can_svn = options.svn_repo
959 can_git = options.git_repo
827 # If there was no transport selected yet, now we must have enough data to 960 # If there was no transport selected yet, now we must have enough data to
828 # select one. 961 # select one.
829 if not options.send_patch and not (can_http or can_svn): 962 if not options.send_patch and not (can_http or can_svn or can_git):
830 parser.error('Please specify an access method.') 963 parser.error('Please specify an access method.')
831 964
832 # Convert options.diff into the content of the diff. 965 # Convert options.diff into the content of the diff.
833 if options.url: 966 if options.url:
834 if options.files: 967 if options.files:
835 parser.error('You cannot specify files and --url at the same time.') 968 parser.error('You cannot specify files and --url at the same time.')
836 options.diff = urllib2.urlopen(options.url).read() 969 options.diff = urllib2.urlopen(options.url).read()
837 elif options.diff: 970 elif options.diff:
838 if options.files: 971 if options.files:
839 parser.error('You cannot specify files and --diff at the same time.') 972 parser.error('You cannot specify files and --diff at the same time.')
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
897 1030
898 if options.print_bots: 1031 if options.print_bots:
899 print 'Bots which would be used:' 1032 print 'Bots which would be used:'
900 for bot in bot_spec: 1033 for bot in bot_spec:
901 if bot[1]: 1034 if bot[1]:
902 print ' %s:%s' % (bot[0], ','.join(bot[1])) 1035 print ' %s:%s' % (bot[0], ','.join(bot[1]))
903 else: 1036 else:
904 print ' %s' % (bot[0]) 1037 print ' %s' % (bot[0])
905 return 0 1038 return 0
906 1039
907 # Send the patch. 1040 # Determine sending protocol
908 if options.send_patch: 1041 if options.send_patch:
909 # If forced. 1042 # If forced.
910 options.send_patch(bot_spec, options) 1043 senders = [options.send_patch]
911 PrintSuccess(bot_spec, options) 1044 else:
912 return 0 1045 # Try sending patch using avaialble protocols
913 try: 1046 all_senders = [
914 if can_http: 1047 (_SendChangeHTTP, can_http),
915 _SendChangeHTTP(bot_spec, options) 1048 (_SendChangeSVN, can_svn),
1049 (_SendChangeGit, can_git)
1050 ]
1051 senders = [sender for sender, can in all_senders if can]
1052
1053 # Send the patch.
1054 for sender in senders:
1055 try:
1056 sender(bot_spec, options)
916 PrintSuccess(bot_spec, options) 1057 PrintSuccess(bot_spec, options)
917 return 0 1058 return 0
918 except NoTryServerAccess: 1059 except NoTryServerAccess:
919 if not can_svn: 1060 is_last = sender == senders[-1]
920 raise 1061 if is_last:
921 _SendChangeSVN(bot_spec, options) 1062 raise
922 PrintSuccess(bot_spec, options) 1063 assert False, "Unreachable code"
923 return 0
924 except (InvalidScript, NoTryServerAccess), e: 1064 except (InvalidScript, NoTryServerAccess), e:
925 if swallow_exception: 1065 if swallow_exception:
926 return 1 1066 return 1
927 print >> sys.stderr, e 1067 print >> sys.stderr, e
928 return 1 1068 return 1
929 except (gclient_utils.Error, subprocess2.CalledProcessError), e: 1069 except (gclient_utils.Error, subprocess2.CalledProcessError), e:
930 print >> sys.stderr, e 1070 print >> sys.stderr, e
931 return 1 1071 return 1
932 return 0 1072 return 0
933 1073
934 1074
935 if __name__ == "__main__": 1075 if __name__ == "__main__":
936 fix_encoding.fix_encoding() 1076 fix_encoding.fix_encoding()
937 sys.exit(TryChange(None, None, False)) 1077 sys.exit(TryChange(None, None, False))
OLDNEW
« scm.py ('K') | « tests/trychange_unittest.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698