Chromium Code Reviews| 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 |