diff options
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 |
