OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2011 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 repository or by directly connecting |
8 to the server by HTTP. | 8 to the server by HTTP. |
9 """ | 9 """ |
10 | 10 |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
86 | 86 |
87 def Escape(name): | 87 def Escape(name): |
88 """Escapes characters that could interfere with the file system or try job | 88 """Escapes characters that could interfere with the file system or try job |
89 parsing. | 89 parsing. |
90 """ | 90 """ |
91 return re.sub(r'[^\w#-]', '_', name) | 91 return re.sub(r'[^\w#-]', '_', name) |
92 | 92 |
93 | 93 |
94 class SCM(object): | 94 class SCM(object): |
95 """Simplistic base class to implement one function: ProcessOptions.""" | 95 """Simplistic base class to implement one function: ProcessOptions.""" |
96 def __init__(self, options, path): | 96 def __init__(self, options, path, file_list): |
97 items = path.split('@') | 97 items = path.split('@') |
98 assert len(items) <= 2 | 98 assert len(items) <= 2 |
99 self.checkout_root = items[0] | 99 self.checkout_root = items[0] |
100 items.append(None) | 100 items.append(None) |
101 self.diff_against = items[1] | 101 self.diff_against = items[1] |
102 self.options = options | 102 self.options = options |
103 # Lazy-load file list from the SCM unless files were specified in options. | 103 # Lazy-load file list from the SCM unless files were specified in options. |
104 self._files = None | 104 self._files = None |
105 self._file_tuples = None | 105 self._file_tuples = None |
106 if self.options.files: | 106 if file_list: |
107 self._files = self.options.files | 107 self._files = file_list |
108 self._file_tuples = [('M', f) for f in self.files] | 108 self._file_tuples = [('M', f) for f in self.files] |
109 self.options.files = None | 109 self.options.files = None |
110 self.codereview_settings = None | 110 self.codereview_settings = None |
111 self.codereview_settings_file = 'codereview.settings' | 111 self.codereview_settings_file = 'codereview.settings' |
112 self.gclient_root = None | 112 self.gclient_root = None |
113 | 113 |
114 def GetFileNames(self): | 114 def GetFileNames(self): |
115 """Return the list of files in the diff.""" | 115 """Return the list of files in the diff.""" |
116 return self.files | 116 return self.files |
117 | 117 |
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
429 | 429 |
430 | 430 |
431 def PrintSuccess(options): | 431 def PrintSuccess(options): |
432 if not options.dry_run: | 432 if not options.dry_run: |
433 text = 'Patch \'%s\' sent to try server' % options.name | 433 text = 'Patch \'%s\' sent to try server' % options.name |
434 if options.bot: | 434 if options.bot: |
435 text += ': %s' % ', '.join(options.bot) | 435 text += ': %s' % ', '.join(options.bot) |
436 print(text) | 436 print(text) |
437 | 437 |
438 | 438 |
439 def GuessVCS(options, path): | 439 def GuessVCS(options, path, file_list): |
440 """Helper to guess the version control system. | 440 """Helper to guess the version control system. |
441 | 441 |
442 NOTE: Very similar to upload.GuessVCS. Doesn't look for hg since we don't | 442 NOTE: Very similar to upload.GuessVCS. Doesn't look for hg since we don't |
443 support it yet. | 443 support it yet. |
444 | 444 |
445 This examines the path directory, guesses which SCM we're using, and | 445 This examines the path directory, guesses which SCM we're using, and |
446 returns an instance of the appropriate class. Exit with an error if we can't | 446 returns an instance of the appropriate class. Exit with an error if we can't |
447 figure it out. | 447 figure it out. |
448 | 448 |
449 Returns: | 449 Returns: |
450 A SCM instance. Exits if the SCM can't be guessed. | 450 A SCM instance. Exits if the SCM can't be guessed. |
451 """ | 451 """ |
452 __pychecker__ = 'no-returnvalues' | 452 __pychecker__ = 'no-returnvalues' |
453 real_path = path.split('@')[0] | 453 real_path = path.split('@')[0] |
454 logging.info("GuessVCS(%s)" % path) | 454 logging.info("GuessVCS(%s)" % path) |
455 # Subversion has a .svn in all working directories. | 455 # Subversion has a .svn in all working directories. |
456 if os.path.isdir(os.path.join(real_path, '.svn')): | 456 if os.path.isdir(os.path.join(real_path, '.svn')): |
457 return SVN(options, path) | 457 return SVN(options, path, file_list) |
458 | 458 |
459 # Git has a command to test if you're in a git tree. | 459 # Git has a command to test if you're in a git tree. |
460 # Try running it, but don't die if we don't have git installed. | 460 # Try running it, but don't die if we don't have git installed. |
461 try: | 461 try: |
462 subprocess2.check_output( | 462 subprocess2.check_output( |
463 ['git', 'rev-parse', '--is-inside-work-tree'], cwd=real_path, | 463 ['git', 'rev-parse', '--is-inside-work-tree'], cwd=real_path, |
464 stderr=subprocess2.VOID) | 464 stderr=subprocess2.VOID) |
465 return GIT(options, path) | 465 return GIT(options, path, file_list) |
466 except subprocess2.CalledProcessError, e: | 466 except subprocess2.CalledProcessError, e: |
467 if e.returncode != errno.ENOENT and e.returncode != 128: | 467 if e.returncode != errno.ENOENT and e.returncode != 128: |
468 # ENOENT == 2 = they don't have git installed. | 468 # ENOENT == 2 = they don't have git installed. |
469 # 128 = git error code when not in a repo. | 469 # 128 = git error code when not in a repo. |
470 logging.warning('Unexpected error code: %s' % e.returncode) | 470 logging.warning('Unexpected error code: %s' % e.returncode) |
471 raise | 471 raise |
472 raise NoTryServerAccess("Could not guess version control system. " | 472 raise NoTryServerAccess("Could not guess version control system. " |
473 "Are you in a working copy directory?") | 473 "Are you in a working copy directory?") |
474 | 474 |
475 | 475 |
(...skipping 16 matching lines...) Expand all Loading... |
492 change, | 492 change, |
493 swallow_exception, | 493 swallow_exception, |
494 prog=None, | 494 prog=None, |
495 extra_epilog=None): | 495 extra_epilog=None): |
496 """ | 496 """ |
497 Args: | 497 Args: |
498 argv: Arguments and options. | 498 argv: Arguments and options. |
499 change: Change instance corresponding to the CL. | 499 change: Change instance corresponding to the CL. |
500 swallow_exception: Whether we raise or swallow exceptions. | 500 swallow_exception: Whether we raise or swallow exceptions. |
501 """ | 501 """ |
502 file_list = [] | |
503 if change: | |
504 file_list = [f.LocalPath() for f in change.AffectedFiles()] | |
505 | |
506 # Parse argv | 502 # Parse argv |
507 parser = optparse.OptionParser(usage=USAGE, | 503 parser = optparse.OptionParser(usage=USAGE, |
508 version=__version__, | 504 version=__version__, |
509 prog=prog) | 505 prog=prog) |
510 epilog = EPILOG % { 'prog': prog } | 506 epilog = EPILOG % { 'prog': prog } |
511 if extra_epilog: | 507 if extra_epilog: |
512 epilog += extra_epilog | 508 epilog += extra_epilog |
513 parser.epilog = epilog | 509 parser.epilog = epilog |
514 # Remove epilog formatting | 510 # Remove epilog formatting |
515 parser.format_epilog = lambda x: parser.epilog | 511 parser.format_epilog = lambda x: parser.epilog |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
562 help="Add a gtest_filter to a test. Use multiple times to " | 558 help="Add a gtest_filter to a test. Use multiple times to " |
563 "specify filters for different tests. (i.e. " | 559 "specify filters for different tests. (i.e. " |
564 "--testfilter base_unittests:ThreadTest.* " | 560 "--testfilter base_unittests:ThreadTest.* " |
565 "--testfilter ui_tests) If you specify any testfilters " | 561 "--testfilter ui_tests) If you specify any testfilters " |
566 "the test results will not be reported in rietveld and " | 562 "the test results will not be reported in rietveld and " |
567 "only tests with filters will run.") | 563 "only tests with filters will run.") |
568 | 564 |
569 parser.add_option_group(group) | 565 parser.add_option_group(group) |
570 | 566 |
571 group = optparse.OptionGroup(parser, "Patch to run") | 567 group = optparse.OptionGroup(parser, "Patch to run") |
572 group.add_option("-f", "--file", default=file_list, dest="files", | 568 group.add_option("-f", "--file", default=[], dest="files", |
573 metavar="FILE", action="append", | 569 metavar="FILE", action="append", |
574 help="Use many times to list the files to include in the " | 570 help="Use many times to list the files to include in the " |
575 "try, relative to the repository root") | 571 "try, relative to the repository root") |
576 group.add_option("--diff", | 572 group.add_option("--diff", |
577 help="File containing the diff to try") | 573 help="File containing the diff to try") |
578 group.add_option("--url", | 574 group.add_option("--url", |
579 help="Url where to grab a patch, e.g. " | 575 help="Url where to grab a patch, e.g. " |
580 "http://example.com/x.diff") | 576 "http://example.com/x.diff") |
581 group.add_option("-R", "--rietveld_url", default="codereview.appspot.com", | 577 group.add_option("-R", "--rietveld_url", default="codereview.appspot.com", |
582 metavar="URL", | 578 metavar="URL", |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
672 if options.issue or options.patchset: | 668 if options.issue or options.patchset: |
673 parser.error('Cannot use both --issue and use a review number url') | 669 parser.error('Cannot use both --issue and use a review number url') |
674 options.issue = int(match.group(2)) | 670 options.issue = int(match.group(2)) |
675 options.rietveld_url = match.group(1) | 671 options.rietveld_url = match.group(1) |
676 | 672 |
677 try: | 673 try: |
678 changed_files = None | 674 changed_files = None |
679 # Always include os.getcwd() in the checkout settings. | 675 # Always include os.getcwd() in the checkout settings. |
680 checkouts = [] | 676 checkouts = [] |
681 path = os.getcwd() | 677 path = os.getcwd() |
| 678 |
| 679 file_list = [] |
| 680 if options.files: |
| 681 file_list = options.files |
| 682 elif change: |
| 683 file_list = [f.LocalPath() for f in change.AffectedFiles()] |
| 684 |
682 if options.upstream_branch: | 685 if options.upstream_branch: |
683 path += '@' + options.upstream_branch | 686 path += '@' + options.upstream_branch |
684 checkouts.append(GuessVCS(options, path)) | 687 # Clear file list so that the correct list will be retrieved from the |
| 688 # upstream branch. |
| 689 file_list = [] |
| 690 checkouts.append(GuessVCS(options, path, file_list)) |
685 checkouts[0].AutomagicalSettings() | 691 checkouts[0].AutomagicalSettings() |
686 for item in options.sub_rep: | 692 for item in options.sub_rep: |
687 checkout = GuessVCS(options, os.path.join(checkouts[0].checkout_root, | 693 checkout = GuessVCS(options, os.path.join(checkouts[0].checkout_root, |
688 item)) | 694 item), file_list) |
689 if checkout.checkout_root in [c.checkout_root for c in checkouts]: | 695 if checkout.checkout_root in [c.checkout_root for c in checkouts]: |
690 parser.error('Specified the root %s two times.' % | 696 parser.error('Specified the root %s two times.' % |
691 checkout.checkout_root) | 697 checkout.checkout_root) |
692 checkouts.append(checkout) | 698 checkouts.append(checkout) |
693 | 699 |
694 can_http = options.port and options.host | 700 can_http = options.port and options.host |
695 can_svn = options.svn_repo | 701 can_svn = options.svn_repo |
696 # If there was no transport selected yet, now we must have enough data to | 702 # If there was no transport selected yet, now we must have enough data to |
697 # select one. | 703 # select one. |
698 if not options.send_patch and not (can_http or can_svn): | 704 if not options.send_patch and not (can_http or can_svn): |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
803 return 1 | 809 return 1 |
804 except (gclient_utils.Error, subprocess2.CalledProcessError), e: | 810 except (gclient_utils.Error, subprocess2.CalledProcessError), e: |
805 print >> sys.stderr, e | 811 print >> sys.stderr, e |
806 return 1 | 812 return 1 |
807 return 0 | 813 return 0 |
808 | 814 |
809 | 815 |
810 if __name__ == "__main__": | 816 if __name__ == "__main__": |
811 fix_encoding.fix_encoding() | 817 fix_encoding.fix_encoding() |
812 sys.exit(TryChange(None, None, False)) | 818 sys.exit(TryChange(None, None, False)) |
OLD | NEW |