OLD | NEW |
---|---|
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/git repository or by directly | 7 the try server by either writting to a svn/git repository or by directly |
8 connecting to the server by HTTP. | 8 connecting to the server by HTTP. |
9 """ | 9 """ |
10 | 10 |
(...skipping 493 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
504 path = os.path.join(temp_dir, name) | 504 path = os.path.join(temp_dir, name) |
505 if contents is not None: | 505 if contents is not None: |
506 with open(path, 'wb') as f: | 506 with open(path, 'wb') as f: |
507 f.write(contents) | 507 f.write(contents) |
508 yield path | 508 yield path |
509 finally: | 509 finally: |
510 shutil.rmtree(temp_dir, True) | 510 shutil.rmtree(temp_dir, True) |
511 | 511 |
512 | 512 |
513 @contextlib.contextmanager | 513 @contextlib.contextmanager |
514 def _PrepareDescriptionAndPatchFiles(description, options, use_username=True): | 514 def _PrepareDescriptionAndPatchFiles(description, options, use_username=True): |
nodir
2014/04/11 23:58:20
This is because of rebase on https://codereview.ch
| |
515 """Creates temporary files with description and patch. | 515 """Creates temporary files with description and patch. |
516 | 516 |
517 __enter__ called on the return value returns a tuple of patch_filename and | 517 __enter__ called on the return value returns a tuple of patch_filename and |
518 description_filename. | 518 description_filename. |
519 | 519 |
520 Args: | 520 Args: |
521 description: contents of description file. | 521 description: contents of description file. |
522 options: patchset options object. Must have attributes: user, | 522 options: patchset options object. Must have attributes: user, |
523 name (of patch) and diff (contents of patch). | 523 name (of patch) and diff (contents of patch). |
524 use_username: specifies if username must be included in the patch_filename. | 524 use_username: specifies if username must be included in the patch_filename. |
nodir
2014/04/11 23:58:20
because of rebase
| |
525 """ | 525 """ |
526 current_time = str(datetime.datetime.now()).replace(':', '.') | 526 current_time = str(datetime.datetime.now()).replace(':', '.') |
527 patch_basename = '%s.%s.diff' % (Escape(options.name), current_time) | 527 patch_basename = '%s.%s.diff' % (Escape(options.name), current_time) |
528 if use_username: | 528 if use_username: |
529 patch_basename = '%s.%s' % (Escape(options.user), patch_basename) | 529 patch_basename = '%s.%s' % (Escape(options.user), patch_basename) |
nodir
2014/04/11 23:58:20
because of rebase
| |
530 with _TempFilename('description', description) as description_filename: | 530 with _TempFilename('description', description) as description_filename: |
531 with _TempFilename(patch_basename, options.diff) as patch_filename: | 531 with _TempFilename(patch_basename, options.diff) as patch_filename: |
532 yield patch_filename, description_filename | 532 yield patch_filename, description_filename |
533 | 533 |
534 | 534 |
535 def _SendChangeSVN(bot_spec, options): | 535 def _SendChangeSVN(bot_spec, options): |
536 """Send a change to the try server by committing a diff file on a subversion | 536 """Send a change to the try server by committing a diff file on a subversion |
537 server.""" | 537 server.""" |
538 if not options.svn_repo: | 538 if not options.svn_repo: |
539 raise NoTryServerAccess('Please use the --svn_repo option to specify the' | 539 raise NoTryServerAccess('Please use the --svn_repo option to specify the' |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
606 if scm.GIT.IsWorkTreeDirty(patch_dir): | 606 if scm.GIT.IsWorkTreeDirty(patch_dir): |
607 logging.info('Work dir is dirty: hard reset!') | 607 logging.info('Work dir is dirty: hard reset!') |
608 scm.GIT.Capture(['reset', '--hard'], cwd=patch_dir) | 608 scm.GIT.Capture(['reset', '--hard'], cwd=patch_dir) |
609 logging.info('Updating patch repo') | 609 logging.info('Updating patch repo') |
610 scm.GIT.Capture(['pull', 'origin', 'master'], cwd=patch_dir) | 610 scm.GIT.Capture(['pull', 'origin', 'master'], cwd=patch_dir) |
611 | 611 |
612 return os.path.abspath(patch_dir) | 612 return os.path.abspath(patch_dir) |
613 | 613 |
614 | 614 |
615 def _SendChangeGit(bot_spec, options): | 615 def _SendChangeGit(bot_spec, options): |
616 """Send a change to the try server by committing a diff file to a GIT repo""" | 616 """Sends a change to the try server by committing a diff file to a GIT repo. |
617 | |
618 Creates a temp orphan branch, commits patch.diff, creates a ref pointing to | |
619 that commit, deletes the temp branch, checks master out, adds 'ref' file | |
620 containing the name of the new ref, pushes master and the ref to the origin. | |
621 """ | |
622 | |
617 if not options.git_repo: | 623 if not options.git_repo: |
618 raise NoTryServerAccess('Please use the --git_repo option to specify the ' | 624 raise NoTryServerAccess('Please use the --git_repo option to specify the ' |
619 'try server git repository to connect to.') | 625 'try server git repository to connect to.') |
620 | 626 |
621 values = _ParseSendChangeOptions(bot_spec, options) | 627 values = _ParseSendChangeOptions(bot_spec, options) |
622 comment_subject = '%s.%s' % (options.user, options.name) | 628 comment_subject = '%s.%s' % (options.user, options.name) |
623 comment_body = ''.join("%s=%s\n" % (k, v) for k, v in values) | 629 comment_body = ''.join("%s=%s\n" % (k, v) for k, v in values) |
624 description = '%s\n\n%s' % (comment_subject, comment_body) | 630 description = '%s\n\n%s' % (comment_subject, comment_body) |
625 logging.info('Sending by GIT') | 631 logging.info('Sending by GIT') |
626 logging.info(description) | 632 logging.info(description) |
627 logging.info(options.git_repo) | 633 logging.info(options.git_repo) |
628 logging.info(options.diff) | 634 logging.info(options.diff) |
629 if options.dry_run: | 635 if options.dry_run: |
630 return | 636 return |
631 | 637 |
632 patch_dir = _GetPatchGitRepo(options.git_repo) | 638 patch_dir = _GetPatchGitRepo(options.git_repo) |
633 def patch_git(*args): | 639 def patch_git(*args): |
634 return scm.GIT.Capture(list(args), cwd=patch_dir) | 640 return scm.GIT.Capture(list(args), cwd=patch_dir) |
635 def add_and_commit(filename, comment_filename): | 641 def add_and_commit(filename, comment_filename): |
636 patch_git('add', filename) | 642 patch_git('add', filename) |
637 patch_git('commit', '-F', comment_filename) | 643 patch_git('commit', '-F', comment_filename) |
638 | 644 |
639 assert scm.GIT.IsInsideWorkTree(patch_dir) | 645 assert scm.GIT.IsInsideWorkTree(patch_dir) |
640 assert not scm.GIT.IsWorkTreeDirty(patch_dir) | 646 assert not scm.GIT.IsWorkTreeDirty(patch_dir) |
641 | 647 |
642 with _PrepareDescriptionAndPatchFiles(description, options, | 648 with _PrepareDescriptionAndPatchFiles(description, options, |
643 use_username=False) as ( | 649 use_username=False) as ( |
644 patch_filename, description_filename): | 650 patch_filename, description_filename): |
nodir
2014/04/11 23:58:20
because of rebase
| |
645 logging.info('Committing patch') | 651 logging.info('Committing patch') |
646 target_branch = 'refs/patches/%s/%s' % ( | 652 |
653 temp_branch = 'tmp_patch' | |
654 target_ref = 'refs/patches/%s/%s' % ( | |
647 Escape(options.user), | 655 Escape(options.user), |
648 os.path.basename(patch_filename).replace(' ','-')) | 656 os.path.basename(patch_filename).replace(' ','-')) |
649 target_filename = os.path.join(patch_dir, 'patch.diff') | 657 target_filename = os.path.join(patch_dir, 'patch.diff') |
650 branch_file = os.path.join(patch_dir, GIT_BRANCH_FILE) | 658 branch_file = os.path.join(patch_dir, GIT_BRANCH_FILE) |
659 | |
660 patch_git('checkout', 'master') | |
651 try: | 661 try: |
662 # Try deleting an existing temp branch, if any. | |
663 try: | |
664 patch_git('branch', '-D', temp_branch) | |
665 logging.debug('Deleted an existing temp branch.') | |
666 except subprocess2.CalledProcessError: | |
667 pass | |
652 # Create a new branch and put the patch there. | 668 # Create a new branch and put the patch there. |
653 patch_git('checkout', '--orphan', target_branch) | 669 patch_git('checkout', '--orphan', temp_branch) |
654 patch_git('reset') | 670 patch_git('reset') |
655 patch_git('clean', '-f') | 671 patch_git('clean', '-f') |
656 shutil.copyfile(patch_filename, target_filename) | 672 shutil.copyfile(patch_filename, target_filename) |
657 add_and_commit(target_filename, description_filename) | 673 add_and_commit(target_filename, description_filename) |
658 assert not scm.GIT.IsWorkTreeDirty(patch_dir) | 674 assert not scm.GIT.IsWorkTreeDirty(patch_dir) |
659 | 675 |
660 # Update the branch file in the master | 676 # Create a ref and point it to the commit referenced by temp_branch. |
677 patch_git('update-ref', target_ref, temp_branch) | |
678 | |
679 # Delete the temp ref. | |
661 patch_git('checkout', 'master') | 680 patch_git('checkout', 'master') |
681 patch_git('branch', '-D', temp_branch) | |
662 | 682 |
683 # Update the branch file in the master. | |
663 def update_branch(): | 684 def update_branch(): |
664 with open(branch_file, 'w') as f: | 685 with open(branch_file, 'w') as f: |
665 f.write(target_branch) | 686 f.write(target_ref) |
666 add_and_commit(branch_file, description_filename) | 687 add_and_commit(branch_file, description_filename) |
667 | 688 |
668 update_branch() | 689 update_branch() |
669 | 690 |
670 # Push master and target_branch to origin. | 691 # Push master and target_ref to origin. |
671 logging.info('Pushing patch') | 692 logging.info('Pushing patch') |
672 for attempt in xrange(_GIT_PUSH_ATTEMPTS): | 693 for attempt in xrange(_GIT_PUSH_ATTEMPTS): |
673 try: | 694 try: |
674 patch_git('push', 'origin', 'master', target_branch) | 695 patch_git('push', 'origin', 'master', target_ref) |
675 except subprocess2.CalledProcessError as e: | 696 except subprocess2.CalledProcessError as e: |
676 is_last = attempt == _GIT_PUSH_ATTEMPTS - 1 | 697 is_last = attempt == _GIT_PUSH_ATTEMPTS - 1 |
677 if is_last: | 698 if is_last: |
678 raise NoTryServerAccess(str(e)) | 699 raise NoTryServerAccess(str(e)) |
679 # Fetch, reset, update branch file again. | 700 # Fetch, reset, update branch file again. |
680 patch_git('fetch', 'origin') | 701 patch_git('fetch', 'origin') |
681 patch_git('reset', '--hard', 'origin/master') | 702 patch_git('reset', '--hard', 'origin/master') |
682 update_branch() | 703 update_branch() |
683 except subprocess2.CalledProcessError, e: | 704 except subprocess2.CalledProcessError, e: |
684 # Restore state. | 705 # Restore state. |
(...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1124 return 1 | 1145 return 1 |
1125 except (gclient_utils.Error, subprocess2.CalledProcessError), e: | 1146 except (gclient_utils.Error, subprocess2.CalledProcessError), e: |
1126 print >> sys.stderr, e | 1147 print >> sys.stderr, e |
1127 return 1 | 1148 return 1 |
1128 return 0 | 1149 return 0 |
1129 | 1150 |
1130 | 1151 |
1131 if __name__ == "__main__": | 1152 if __name__ == "__main__": |
1132 fix_encoding.fix_encoding() | 1153 fix_encoding.fix_encoding() |
1133 sys.exit(TryChange(None, None, False)) | 1154 sys.exit(TryChange(None, None, False)) |
OLD | NEW |