summaryrefslogtreecommitdiffstats
path: root/project.py
diff options
context:
space:
mode:
authorShawn O. Pearce <sop@google.com>2009-05-29 18:38:17 -0700
committerShawn O. Pearce <sop@google.com>2009-05-29 18:45:20 -0700
commit3c8dea1f8d7c4257d080f9f34159cdb2fffb81e6 (patch)
tree2a5e48ce93bc913076034f88f8878e4bfffef4dc /project.py
parent8ad8a0e61d919e76f521f3124c91bd46fbaa84e2 (diff)
downloadgit-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.py180
1 files changed, 89 insertions, 91 deletions
diff --git a/project.py b/project.py
index cab47152..e094b5d6 100644
--- a/project.py
+++ b/project.py
@@ -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