diff options
author | Shawn O. Pearce <sop@google.com> | 2009-05-29 18:38:17 -0700 |
---|---|---|
committer | Shawn O. Pearce <sop@google.com> | 2009-05-29 18:45:20 -0700 |
commit | 3c8dea1f8d7c4257d080f9f34159cdb2fffb81e6 (patch) | |
tree | 2a5e48ce93bc913076034f88f8878e4bfffef4dc /project.py | |
parent | 8ad8a0e61d919e76f521f3124c91bd46fbaa84e2 (diff) | |
download | git-repo-3c8dea1f8d7c4257d080f9f34159cdb2fffb81e6.tar.gz |
Change project.revision to revisionExpr and revisionId
The revisionExpr field now holds an expression from the manifest,
such as "refs/heads/master", while revisionId holds the current
commit-ish SHA-1 of the revisionExpr. Currently that is only
filled in if the manifest points directly to a SHA-1.
Signed-off-by: Shawn O. Pearce <sop@google.com>
Diffstat (limited to 'project.py')
-rw-r--r-- | project.py | 180 |
1 files changed, 89 insertions, 91 deletions
@@ -228,14 +228,23 @@ class Project(object): | |||
228 | gitdir, | 228 | gitdir, |
229 | worktree, | 229 | worktree, |
230 | relpath, | 230 | relpath, |
231 | revision): | 231 | revisionExpr, |
232 | revisionId): | ||
232 | self.manifest = manifest | 233 | self.manifest = manifest |
233 | self.name = name | 234 | self.name = name |
234 | self.remote = remote | 235 | self.remote = remote |
235 | self.gitdir = gitdir | 236 | self.gitdir = gitdir |
236 | self.worktree = worktree | 237 | self.worktree = worktree |
237 | self.relpath = relpath | 238 | self.relpath = relpath |
238 | self.revision = revision | 239 | self.revisionExpr = revisionExpr |
240 | |||
241 | if revisionId is None \ | ||
242 | and revisionExpr \ | ||
243 | and IsId(revisionExpr): | ||
244 | self.revisionId = revisionExpr | ||
245 | else: | ||
246 | self.revisionId = revisionId | ||
247 | |||
239 | self.snapshots = {} | 248 | self.snapshots = {} |
240 | self.copyfiles = [] | 249 | self.copyfiles = [] |
241 | self.config = GitConfig.ForRepository( | 250 | self.config = GitConfig.ForRepository( |
@@ -605,6 +614,23 @@ class Project(object): | |||
605 | for file in self.copyfiles: | 614 | for file in self.copyfiles: |
606 | file._Copy() | 615 | file._Copy() |
607 | 616 | ||
617 | def GetRevisionId(self, all=None): | ||
618 | if self.revisionId: | ||
619 | return self.revisionId | ||
620 | |||
621 | rem = self.GetRemote(self.remote.name) | ||
622 | rev = rem.ToLocal(self.revisionExpr) | ||
623 | |||
624 | if all is not None and rev in all: | ||
625 | return all[rev] | ||
626 | |||
627 | try: | ||
628 | return self.bare_git.rev_parse('--verify', '%s^0' % rev) | ||
629 | except GitError: | ||
630 | raise ManifestInvalidRevisionError( | ||
631 | 'revision %s in %s not found' % (self.revisionExpr, | ||
632 | self.name)) | ||
633 | |||
608 | def Sync_LocalHalf(self, syncbuf): | 634 | def Sync_LocalHalf(self, syncbuf): |
609 | """Perform only the local IO portion of the sync process. | 635 | """Perform only the local IO portion of the sync process. |
610 | Network access is not required. | 636 | Network access is not required. |
@@ -613,19 +639,7 @@ class Project(object): | |||
613 | all = self.bare_ref.all | 639 | all = self.bare_ref.all |
614 | self.CleanPublishedCache(all) | 640 | self.CleanPublishedCache(all) |
615 | 641 | ||
616 | rem = self.GetRemote(self.remote.name) | 642 | revid = self.GetRevisionId(all) |
617 | rev = rem.ToLocal(self.revision) | ||
618 | if rev in all: | ||
619 | revid = all[rev] | ||
620 | elif IsId(rev): | ||
621 | revid = rev | ||
622 | else: | ||
623 | try: | ||
624 | revid = self.bare_git.rev_parse('--verify', '%s^0' % rev) | ||
625 | except GitError: | ||
626 | raise ManifestInvalidRevisionError( | ||
627 | 'revision %s in %s not found' % (self.revision, self.name)) | ||
628 | |||
629 | head = self.work_git.GetHead() | 643 | head = self.work_git.GetHead() |
630 | if head.startswith(R_HEADS): | 644 | if head.startswith(R_HEADS): |
631 | branch = head[len(R_HEADS):] | 645 | branch = head[len(R_HEADS):] |
@@ -649,11 +663,11 @@ class Project(object): | |||
649 | # | 663 | # |
650 | return | 664 | return |
651 | 665 | ||
652 | lost = self._revlist(not_rev(rev), HEAD) | 666 | lost = self._revlist(not_rev(revid), HEAD) |
653 | if lost: | 667 | if lost: |
654 | syncbuf.info(self, "discarding %d commits", len(lost)) | 668 | syncbuf.info(self, "discarding %d commits", len(lost)) |
655 | try: | 669 | try: |
656 | self._Checkout(rev, quiet=True) | 670 | self._Checkout(revid, quiet=True) |
657 | except GitError, e: | 671 | except GitError, e: |
658 | syncbuf.fail(self, e) | 672 | syncbuf.fail(self, e) |
659 | return | 673 | return |
@@ -666,9 +680,8 @@ class Project(object): | |||
666 | return | 680 | return |
667 | 681 | ||
668 | branch = self.GetBranch(branch) | 682 | branch = self.GetBranch(branch) |
669 | merge = branch.LocalMerge | ||
670 | 683 | ||
671 | if not merge: | 684 | if not branch.LocalMerge: |
672 | # The current branch has no tracking configuration. | 685 | # The current branch has no tracking configuration. |
673 | # Jump off it to a deatched HEAD. | 686 | # Jump off it to a deatched HEAD. |
674 | # | 687 | # |
@@ -676,17 +689,17 @@ class Project(object): | |||
676 | "leaving %s; does not track upstream", | 689 | "leaving %s; does not track upstream", |
677 | branch.name) | 690 | branch.name) |
678 | try: | 691 | try: |
679 | self._Checkout(rev, quiet=True) | 692 | self._Checkout(revid, quiet=True) |
680 | except GitError, e: | 693 | except GitError, e: |
681 | syncbuf.fail(self, e) | 694 | syncbuf.fail(self, e) |
682 | return | 695 | return |
683 | self._CopyFiles() | 696 | self._CopyFiles() |
684 | return | 697 | return |
685 | 698 | ||
686 | upstream_gain = self._revlist(not_rev(HEAD), rev) | 699 | upstream_gain = self._revlist(not_rev(HEAD), revid) |
687 | pub = self.WasPublished(branch.name, all) | 700 | pub = self.WasPublished(branch.name, all) |
688 | if pub: | 701 | if pub: |
689 | not_merged = self._revlist(not_rev(rev), pub) | 702 | not_merged = self._revlist(not_rev(revid), pub) |
690 | if not_merged: | 703 | if not_merged: |
691 | if upstream_gain: | 704 | if upstream_gain: |
692 | # The user has published this branch and some of those | 705 | # The user has published this branch and some of those |
@@ -703,24 +716,15 @@ class Project(object): | |||
703 | # strict subset. We can fast-forward safely. | 716 | # strict subset. We can fast-forward safely. |
704 | # | 717 | # |
705 | def _doff(): | 718 | def _doff(): |
706 | self._FastForward(rev) | 719 | self._FastForward(revid) |
707 | self._CopyFiles() | 720 | self._CopyFiles() |
708 | syncbuf.later1(self, _doff) | 721 | syncbuf.later1(self, _doff) |
709 | return | 722 | return |
710 | 723 | ||
711 | # If the upstream switched on us, warn the user. | ||
712 | # | ||
713 | if merge != rev: | ||
714 | syncbuf.info(self, "manifest switched %s...%s", merge, rev) | ||
715 | |||
716 | # Examine the local commits not in the remote. Find the | 724 | # Examine the local commits not in the remote. Find the |
717 | # last one attributed to this user, if any. | 725 | # last one attributed to this user, if any. |
718 | # | 726 | # |
719 | local_changes = self._revlist( | 727 | local_changes = self._revlist(not_rev(revid), HEAD, format='%H %ce') |
720 | not_rev(merge), | ||
721 | HEAD, | ||
722 | format='%H %ce') | ||
723 | |||
724 | last_mine = None | 728 | last_mine = None |
725 | cnt_mine = 0 | 729 | cnt_mine = 0 |
726 | for commit in local_changes: | 730 | for commit in local_changes: |
@@ -738,6 +742,19 @@ class Project(object): | |||
738 | syncbuf.fail(self, _DirtyError()) | 742 | syncbuf.fail(self, _DirtyError()) |
739 | return | 743 | return |
740 | 744 | ||
745 | # If the upstream switched on us, warn the user. | ||
746 | # | ||
747 | if branch.merge != self.revisionExpr: | ||
748 | if branch.merge and self.revisionExpr: | ||
749 | syncbuf.info(self, | ||
750 | 'manifest switched %s...%s', | ||
751 | branch.merge, | ||
752 | self.revisionExpr) | ||
753 | elif branch.merge: | ||
754 | syncbuf.info(self, | ||
755 | 'manifest no longer tracks %s', | ||
756 | branch.merge) | ||
757 | |||
741 | if cnt_mine < len(local_changes): | 758 | if cnt_mine < len(local_changes): |
742 | # Upstream rebased. Not everything in HEAD | 759 | # Upstream rebased. Not everything in HEAD |
743 | # was created by this user. | 760 | # was created by this user. |
@@ -746,25 +763,25 @@ class Project(object): | |||
746 | "discarding %d commits removed from upstream", | 763 | "discarding %d commits removed from upstream", |
747 | len(local_changes) - cnt_mine) | 764 | len(local_changes) - cnt_mine) |
748 | 765 | ||
749 | branch.remote = rem | 766 | branch.remote = self.GetRemote(self.remote.name) |
750 | branch.merge = self.revision | 767 | branch.merge = self.revisionExpr |
751 | branch.Save() | 768 | branch.Save() |
752 | 769 | ||
753 | if cnt_mine > 0: | 770 | if cnt_mine > 0: |
754 | def _dorebase(): | 771 | def _dorebase(): |
755 | self._Rebase(upstream = '%s^1' % last_mine, onto = rev) | 772 | self._Rebase(upstream = '%s^1' % last_mine, onto = revid) |
756 | self._CopyFiles() | 773 | self._CopyFiles() |
757 | syncbuf.later2(self, _dorebase) | 774 | syncbuf.later2(self, _dorebase) |
758 | elif local_changes: | 775 | elif local_changes: |
759 | try: | 776 | try: |
760 | self._ResetHard(rev) | 777 | self._ResetHard(revid) |
761 | self._CopyFiles() | 778 | self._CopyFiles() |
762 | except GitError, e: | 779 | except GitError, e: |
763 | syncbuf.fail(self, e) | 780 | syncbuf.fail(self, e) |
764 | return | 781 | return |
765 | else: | 782 | else: |
766 | def _doff(): | 783 | def _doff(): |
767 | self._FastForward(rev) | 784 | self._FastForward(revid) |
768 | self._CopyFiles() | 785 | self._CopyFiles() |
769 | syncbuf.later1(self, _doff) | 786 | syncbuf.later1(self, _doff) |
770 | 787 | ||
@@ -786,7 +803,7 @@ class Project(object): | |||
786 | if GitCommand(self, cmd, bare=True).Wait() != 0: | 803 | if GitCommand(self, cmd, bare=True).Wait() != 0: |
787 | return None | 804 | return None |
788 | return DownloadedChange(self, | 805 | return DownloadedChange(self, |
789 | remote.ToLocal(self.revision), | 806 | self.GetRevisionId(), |
790 | change_id, | 807 | change_id, |
791 | patch_id, | 808 | patch_id, |
792 | self.bare_git.rev_parse('FETCH_HEAD')) | 809 | self.bare_git.rev_parse('FETCH_HEAD')) |
@@ -810,15 +827,8 @@ class Project(object): | |||
810 | 827 | ||
811 | branch = self.GetBranch(name) | 828 | branch = self.GetBranch(name) |
812 | branch.remote = self.GetRemote(self.remote.name) | 829 | branch.remote = self.GetRemote(self.remote.name) |
813 | branch.merge = self.revision | 830 | branch.merge = self.revisionExpr |
814 | 831 | revid = self.GetRevisionId(all) | |
815 | rev = branch.LocalMerge | ||
816 | if rev in all: | ||
817 | revid = all[rev] | ||
818 | elif IsId(rev): | ||
819 | revid = rev | ||
820 | else: | ||
821 | revid = None | ||
822 | 832 | ||
823 | if head.startswith(R_HEADS): | 833 | if head.startswith(R_HEADS): |
824 | try: | 834 | try: |
@@ -839,7 +849,7 @@ class Project(object): | |||
839 | return True | 849 | return True |
840 | 850 | ||
841 | if GitCommand(self, | 851 | if GitCommand(self, |
842 | ['checkout', '-b', branch.name, rev], | 852 | ['checkout', '-b', branch.name, revid], |
843 | capture_stdout = True, | 853 | capture_stdout = True, |
844 | capture_stderr = True).Wait() == 0: | 854 | capture_stderr = True).Wait() == 0: |
845 | branch.Save() | 855 | branch.Save() |
@@ -900,19 +910,12 @@ class Project(object): | |||
900 | # | 910 | # |
901 | head = all[head] | 911 | head = all[head] |
902 | 912 | ||
903 | rev = self.GetRemote(self.remote.name).ToLocal(self.revision) | 913 | revid = self.GetRevisionId(all) |
904 | if rev in all: | 914 | if head == revid: |
905 | revid = all[rev] | ||
906 | elif IsId(rev): | ||
907 | revid = rev | ||
908 | else: | ||
909 | revid = None | ||
910 | |||
911 | if revid and head == revid: | ||
912 | _lwrite(os.path.join(self.worktree, '.git', HEAD), | 915 | _lwrite(os.path.join(self.worktree, '.git', HEAD), |
913 | '%s\n' % revid) | 916 | '%s\n' % revid) |
914 | else: | 917 | else: |
915 | self._Checkout(rev, quiet=True) | 918 | self._Checkout(revid, quiet=True) |
916 | 919 | ||
917 | return GitCommand(self, | 920 | return GitCommand(self, |
918 | ['branch', '-D', name], | 921 | ['branch', '-D', name], |
@@ -931,7 +934,7 @@ class Project(object): | |||
931 | if cb is None or name != cb: | 934 | if cb is None or name != cb: |
932 | kill.append(name) | 935 | kill.append(name) |
933 | 936 | ||
934 | rev = self.GetRemote(self.remote.name).ToLocal(self.revision) | 937 | rev = self.GetRevisionId(left) |
935 | if cb is not None \ | 938 | if cb is not None \ |
936 | and not self._revlist(HEAD + '...' + rev) \ | 939 | and not self._revlist(HEAD + '...' + rev) \ |
937 | and not self.IsDirty(consider_untracked = False): | 940 | and not self.IsDirty(consider_untracked = False): |
@@ -1081,24 +1084,25 @@ class Project(object): | |||
1081 | 1084 | ||
1082 | def _InitMRef(self): | 1085 | def _InitMRef(self): |
1083 | if self.manifest.branch: | 1086 | if self.manifest.branch: |
1084 | msg = 'manifest set to %s' % self.revision | 1087 | self._InitAnyMRef(R_M + self.manifest.branch) |
1085 | ref = R_M + self.manifest.branch | ||
1086 | cur = self.bare_ref.symref(ref) | ||
1087 | |||
1088 | if IsId(self.revision): | ||
1089 | if cur != '' or self.bare_ref.get(ref) != self.revision: | ||
1090 | dst = self.revision + '^0' | ||
1091 | self.bare_git.UpdateRef(ref, dst, message = msg, detach = True) | ||
1092 | else: | ||
1093 | remote = self.GetRemote(self.remote.name) | ||
1094 | dst = remote.ToLocal(self.revision) | ||
1095 | if cur != dst: | ||
1096 | self.bare_git.symbolic_ref('-m', msg, ref, dst) | ||
1097 | 1088 | ||
1098 | def _InitMirrorHead(self): | 1089 | def _InitMirrorHead(self): |
1099 | dst = self.GetRemote(self.remote.name).ToLocal(self.revision) | 1090 | self._InitAnyMRef(self, HEAD) |
1100 | msg = 'manifest set to %s' % self.revision | 1091 | |
1101 | self.bare_git.SetHead(dst, message=msg) | 1092 | def _InitAnyMRef(self, ref): |
1093 | cur = self.bare_ref.symref(ref) | ||
1094 | |||
1095 | if self.revisionId: | ||
1096 | if cur != '' or self.bare_ref.get(ref) != self.revisionId: | ||
1097 | msg = 'manifest set to %s' % self.revisionId | ||
1098 | dst = self.revisionId + '^0' | ||
1099 | self.bare_git.UpdateRef(ref, dst, message = msg, detach = True) | ||
1100 | else: | ||
1101 | remote = self.GetRemote(self.remote.name) | ||
1102 | dst = remote.ToLocal(self.revisionExpr) | ||
1103 | if cur != dst: | ||
1104 | msg = 'manifest set to %s' % self.revisionExpr | ||
1105 | self.bare_git.symbolic_ref('-m', msg, ref, dst) | ||
1102 | 1106 | ||
1103 | def _InitWorkTree(self): | 1107 | def _InitWorkTree(self): |
1104 | dotgit = os.path.join(self.worktree, '.git') | 1108 | dotgit = os.path.join(self.worktree, '.git') |
@@ -1125,14 +1129,11 @@ class Project(object): | |||
1125 | else: | 1129 | else: |
1126 | raise | 1130 | raise |
1127 | 1131 | ||
1128 | rev = self.GetRemote(self.remote.name).ToLocal(self.revision) | 1132 | _lwrite(os.path.join(dotgit, HEAD), '%s\n' % self.GetRevisionId()) |
1129 | rev = self.bare_git.rev_parse('%s^0' % rev) | ||
1130 | |||
1131 | _lwrite(os.path.join(dotgit, HEAD), '%s\n' % rev) | ||
1132 | 1133 | ||
1133 | cmd = ['read-tree', '--reset', '-u'] | 1134 | cmd = ['read-tree', '--reset', '-u'] |
1134 | cmd.append('-v') | 1135 | cmd.append('-v') |
1135 | cmd.append('HEAD') | 1136 | cmd.append(HEAD) |
1136 | if GitCommand(self, cmd).Wait() != 0: | 1137 | if GitCommand(self, cmd).Wait() != 0: |
1137 | raise GitError("cannot initialize work tree") | 1138 | raise GitError("cannot initialize work tree") |
1138 | self._CopyFiles() | 1139 | self._CopyFiles() |
@@ -1433,7 +1434,8 @@ class MetaProject(Project): | |||
1433 | worktree = worktree, | 1434 | worktree = worktree, |
1434 | remote = RemoteSpec('origin'), | 1435 | remote = RemoteSpec('origin'), |
1435 | relpath = '.repo/%s' % name, | 1436 | relpath = '.repo/%s' % name, |
1436 | revision = 'refs/heads/master') | 1437 | revisionExpr = 'refs/heads/master', |
1438 | revisionId = None) | ||
1437 | 1439 | ||
1438 | def PreSync(self): | 1440 | def PreSync(self): |
1439 | if self.Exists: | 1441 | if self.Exists: |
@@ -1441,7 +1443,8 @@ class MetaProject(Project): | |||
1441 | if cb: | 1443 | if cb: |
1442 | base = self.GetBranch(cb).merge | 1444 | base = self.GetBranch(cb).merge |
1443 | if base: | 1445 | if base: |
1444 | self.revision = base | 1446 | self.revisionExpr = base |
1447 | self.revisionId = None | ||
1445 | 1448 | ||
1446 | @property | 1449 | @property |
1447 | def LastFetch(self): | 1450 | def LastFetch(self): |
@@ -1455,16 +1458,11 @@ class MetaProject(Project): | |||
1455 | def HasChanges(self): | 1458 | def HasChanges(self): |
1456 | """Has the remote received new commits not yet checked out? | 1459 | """Has the remote received new commits not yet checked out? |
1457 | """ | 1460 | """ |
1458 | if not self.remote or not self.revision: | 1461 | if not self.remote or not self.revisionExpr: |
1459 | return False | 1462 | return False |
1460 | 1463 | ||
1461 | all = self.bare_ref.all | 1464 | all = self.bare_ref.all |
1462 | rev = self.GetRemote(self.remote.name).ToLocal(self.revision) | 1465 | revid = self.GetRevisionId(all) |
1463 | if rev in all: | ||
1464 | revid = all[rev] | ||
1465 | else: | ||
1466 | revid = rev | ||
1467 | |||
1468 | head = self.work_git.GetHead() | 1466 | head = self.work_git.GetHead() |
1469 | if head.startswith(R_HEADS): | 1467 | if head.startswith(R_HEADS): |
1470 | try: | 1468 | try: |
@@ -1474,6 +1472,6 @@ class MetaProject(Project): | |||
1474 | 1472 | ||
1475 | if revid == head: | 1473 | if revid == head: |
1476 | return False | 1474 | return False |
1477 | elif self._revlist(not_rev(HEAD), rev): | 1475 | elif self._revlist(not_rev(HEAD), revid): |
1478 | return True | 1476 | return True |
1479 | return False | 1477 | return False |