OLD | NEW |
---|---|
1 # coding=utf8 | 1 # coding=utf8 |
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 """Manages a project checkout. | 5 """Manages a project checkout. |
6 | 6 |
7 Includes support for svn, git-svn and git. | 7 Includes support for svn, git-svn and git. |
8 """ | 8 """ |
9 | 9 |
10 import ConfigParser | 10 import ConfigParser |
(...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
564 # There is no reason to not hardcode origin. | 564 # There is no reason to not hardcode origin. |
565 self.remote = 'origin' | 565 self.remote = 'origin' |
566 # There is no reason to not hardcode master. | 566 # There is no reason to not hardcode master. |
567 self.master_branch = 'master' | 567 self.master_branch = 'master' |
568 | 568 |
569 def prepare(self, revision): | 569 def prepare(self, revision): |
570 """Resets the git repository in a clean state. | 570 """Resets the git repository in a clean state. |
571 | 571 |
572 Checks it out if not present and deletes the working branch. | 572 Checks it out if not present and deletes the working branch. |
573 """ | 573 """ |
574 assert self.git_url | |
574 assert self.remote_branch | 575 assert self.remote_branch |
575 assert self.git_url | 576 |
577 self._check_call_git( | |
578 ['cache', 'populate', self.git_url], timeout=FETCH_TIMEOUT) | |
rmistry
2014/02/25 13:23:14
Disclaimer: I have never used git cache before.
D
| |
579 cache_path = self._check_output_git( | |
580 ['cache', 'exists', self.git_url]).strip() | |
576 | 581 |
577 if not os.path.isdir(self.project_path): | 582 if not os.path.isdir(self.project_path): |
578 # Clone the repo if the directory is not present. | 583 # Clone the repo if the directory is not present. |
579 logging.info( | |
580 'Checking out %s in %s', self.project_name, self.project_path) | |
581 self._check_call_git( | 584 self._check_call_git( |
582 ['clone', self.git_url, '-b', self.remote_branch, self.project_path], | 585 ['clone', '--shared', cache_path, self.project_path], |
583 cwd=None, timeout=FETCH_TIMEOUT) | 586 cwd=None, timeout=FETCH_TIMEOUT) |
584 else: | |
585 # Throw away all uncommitted changes in the existing checkout. | |
586 self._check_call_git(['checkout', self.remote_branch]) | |
587 self._check_call_git( | |
588 ['reset', '--hard', '--quiet', | |
589 '%s/%s' % (self.remote, self.remote_branch)]) | |
590 | 587 |
591 if revision: | 588 if not revision: |
592 try: | 589 revision = self.remote_branch |
593 # Look if the commit hash already exist. If so, we can skip a | |
594 # 'git fetch' call. | |
595 revision = self._check_output_git(['rev-parse', revision]) | |
596 except subprocess.CalledProcessError: | |
597 self._check_call_git( | |
598 ['fetch', self.remote, self.remote_branch, '--quiet']) | |
599 revision = self._check_output_git(['rev-parse', revision]) | |
600 self._check_call_git(['checkout', '--force', '--quiet', revision]) | |
601 else: | |
602 branches, active = self._branches() | |
603 if active != self.master_branch: | |
604 self._check_call_git( | |
605 ['checkout', '--force', '--quiet', self.master_branch]) | |
606 self._sync_remote_branch() | |
607 | 590 |
608 if self.working_branch in branches: | 591 self._check_call_git(['fetch', self.remote, revision]) |
609 self._call_git(['branch', '-D', self.working_branch]) | 592 |
593 self._check_call_git(['checkout', '--force', '--quiet', revision]) | |
594 self._call_git(['clean', '-fdx']) | |
595 | |
596 branches, _ = self._branches() | |
597 if self.working_branch in branches: | |
598 self._call_git(['branch', '-D', self.working_branch]) | |
599 | |
610 return self._get_head_commit_hash() | 600 return self._get_head_commit_hash() |
611 | 601 |
612 def _sync_remote_branch(self): | |
613 """Syncs the remote branch.""" | |
614 # We do a 'git pull origin master:refs/remotes/origin/master' instead of | |
615 # 'git pull origin master' because from the manpage for git-pull: | |
616 # A parameter <ref> without a colon is equivalent to <ref>: when | |
617 # pulling/fetching, so it merges <ref> into the current branch without | |
618 # storing the remote branch anywhere locally. | |
619 remote_tracked_path = 'refs/remotes/%s/%s' % ( | |
620 self.remote, self.remote_branch) | |
621 self._check_call_git( | |
622 ['pull', self.remote, | |
623 '%s:%s' % (self.remote_branch, remote_tracked_path), | |
624 '--quiet']) | |
625 | |
626 def _get_head_commit_hash(self): | 602 def _get_head_commit_hash(self): |
627 """Gets the current revision (in unicode) from the local branch.""" | 603 """Gets the current revision (in unicode) from the local branch.""" |
628 return unicode(self._check_output_git(['rev-parse', 'HEAD']).strip()) | 604 return unicode(self._check_output_git(['rev-parse', 'HEAD']).strip()) |
629 | 605 |
630 def apply_patch(self, patches, post_processors=None, verbose=False): | 606 def apply_patch(self, patches, post_processors=None, verbose=False): |
631 """Applies a patch on 'working_branch' and switches to it. | 607 """Applies a patch on 'working_branch' and switches to it. |
632 | 608 |
633 Also commits the changes on the local branch. | 609 Also commits the changes on the local branch. |
634 | 610 |
635 Ignores svn properties and raise an exception on unexpected ones. | 611 Ignores svn properties and raise an exception on unexpected ones. |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
717 assert sorted(patches.filenames) == sorted(found_files), ( | 693 assert sorted(patches.filenames) == sorted(found_files), ( |
718 sorted(patches.filenames), sorted(found_files)) | 694 sorted(patches.filenames), sorted(found_files)) |
719 | 695 |
720 def commit(self, commit_message, user): | 696 def commit(self, commit_message, user): |
721 """Commits, updates the commit message and pushes.""" | 697 """Commits, updates the commit message and pushes.""" |
722 assert self.commit_user | 698 assert self.commit_user |
723 assert isinstance(commit_message, unicode) | 699 assert isinstance(commit_message, unicode) |
724 current_branch = self._check_output_git( | 700 current_branch = self._check_output_git( |
725 ['rev-parse', '--abbrev-ref', 'HEAD']).strip() | 701 ['rev-parse', '--abbrev-ref', 'HEAD']).strip() |
726 assert current_branch == self.working_branch | 702 assert current_branch == self.working_branch |
727 | 703 |
728 commit_cmd = ['commit', '--amend', '-m', commit_message] | 704 commit_cmd = ['commit', '--amend', '-m', commit_message] |
729 if user and user != self.commit_user: | 705 if user and user != self.commit_user: |
730 # We do not have the first or last name of the user, grab the username | 706 # We do not have the first or last name of the user, grab the username |
731 # from the email and call it the original author's name. | 707 # from the email and call it the original author's name. |
732 # TODO(rmistry): Do not need the below if user is already in | 708 # TODO(rmistry): Do not need the below if user is already in |
733 # "Name <email>" format. | 709 # "Name <email>" format. |
734 name = user.split('@')[0] | 710 name = user.split('@')[0] |
735 commit_cmd.extend(['--author', '%s <%s>' % (name, user)]) | 711 commit_cmd.extend(['--author', '%s <%s>' % (name, user)]) |
736 self._check_call_git(commit_cmd) | 712 self._check_call_git(commit_cmd) |
737 | 713 |
738 # Push to the remote repository. | 714 # Push to the remote repository. |
739 self._check_call_git( | 715 self._check_call_git( |
740 ['push', 'origin', '%s:%s' % (self.working_branch, self.remote_branch), | 716 ['push', 'origin', '%s:%s' % (self.working_branch, self.remote_branch), |
741 '--force', '--quiet']) | 717 '--force', '--quiet']) |
742 # Get the revision after the push. | 718 # Get the revision after the push. |
743 revision = self._get_head_commit_hash() | 719 revision = self._get_head_commit_hash() |
744 # Switch back to the remote_branch and sync it. | 720 # Switch back to the remote_branch and sync it. |
745 self._check_call_git(['checkout', self.remote_branch]) | 721 self._check_call_git(['checkout', self.remote_branch]) |
746 self._sync_remote_branch() | 722 self._sync_remote_branch() |
rmistry
2014/02/24 23:17:04
You removed this method but the call still exists,
agable
2014/02/24 23:24:20
Correct, this patchset does not represent any end-
rmistry
2014/02/25 13:23:14
The method call was here to make sure that the bra
| |
747 # Delete the working branch since we are done with it. | 723 # Delete the working branch since we are done with it. |
748 self._check_call_git(['branch', '-D', self.working_branch]) | 724 self._check_call_git(['branch', '-D', self.working_branch]) |
749 | 725 |
750 return revision | 726 return revision |
751 | 727 |
752 def _check_call_git(self, args, **kwargs): | 728 def _check_call_git(self, args, **kwargs): |
753 kwargs.setdefault('cwd', self.project_path) | 729 kwargs.setdefault('cwd', self.project_path) |
754 kwargs.setdefault('stdout', self.VOID) | 730 kwargs.setdefault('stdout', self.VOID) |
755 kwargs.setdefault('timeout', GLOBAL_TIMEOUT) | 731 kwargs.setdefault('timeout', GLOBAL_TIMEOUT) |
756 return subprocess2.check_call_out(['git'] + args, **kwargs) | 732 return subprocess2.check_call_out(['git'] + args, **kwargs) |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
825 def revisions(self, rev1, rev2): | 801 def revisions(self, rev1, rev2): |
826 return self.checkout.revisions(rev1, rev2) | 802 return self.checkout.revisions(rev1, rev2) |
827 | 803 |
828 @property | 804 @property |
829 def project_name(self): | 805 def project_name(self): |
830 return self.checkout.project_name | 806 return self.checkout.project_name |
831 | 807 |
832 @property | 808 @property |
833 def project_path(self): | 809 def project_path(self): |
834 return self.checkout.project_path | 810 return self.checkout.project_path |
OLD | NEW |