summaryrefslogtreecommitdiffstats
path: root/project.py
diff options
context:
space:
mode:
authorMike Frysinger <vapier@google.com>2020-02-26 23:53:36 -0500
committerDavid Pursehouse <dpursehouse@collab.net>2020-02-29 07:22:08 +0000
commit21b7fbe14d9457400a90683a9bd3febe4b7f8840 (patch)
tree658712eafc8754a4b7e2382d299c8dd207baaf75 /project.py
parentb967f5c17a04d6a01c234427b3b5c9b49dff6ca5 (diff)
downloadgit-repo-21b7fbe14d9457400a90683a9bd3febe4b7f8840.tar.gz
project: fix m/ pseudo ref handling with git worktrees
Since most ref namespaces are shared among all worktrees, trying to set the pseudo m/<branch> in the common git repo ends up clobbering each other when using shared checkouts. For example, in CrOS: <project path="src/third_party/kernel/v3.8" name="chromiumos/third_party/kernel" revision="refs/heads/chromeos-3.8" /> <project path="src/third_party/kernel/v3.10" name="chromiumos/third_party/kernel" revision="refs/heads/chromeos-3.10" /> Trying to set m/master in chromiumos/third_party/kernel.git/ will keep clobbering the other. Instead, when using git worktrees, lets set the m/ pseudo ref to point into the refs/worktree/ namespace which is unique to each git worktree. So we have in the common dir: chromiumos/third_party/kernel.git/: refs/remotes/m/master: ref: refs/worktree/m/master And then in each worktree we point refs/worktree/m/master to the respective manifest revision expression. Now people can use the m/master in each git worktree and have it resolve to the right commit for that worktree. Bug: https://crbug.com/gerrit/12404 Change-Id: I78814bdd5dd67bb13218c4c6ccd64f8a15dd0a52 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/256952 Tested-by: Mike Frysinger <vapier@google.com> Reviewed-by: David Pursehouse <dpursehouse@collab.net>
Diffstat (limited to 'project.py')
-rw-r--r--project.py43
1 files changed, 33 insertions, 10 deletions
diff --git a/project.py b/project.py
index b93dcd58..fe55371e 100644
--- a/project.py
+++ b/project.py
@@ -42,7 +42,7 @@ import platform_utils
42import progress 42import progress
43from repo_trace import IsTrace, Trace 43from repo_trace import IsTrace, Trace
44 44
45from git_refs import GitRefs, HEAD, R_HEADS, R_TAGS, R_PUB, R_M 45from git_refs import GitRefs, HEAD, R_HEADS, R_TAGS, R_PUB, R_M, R_WORKTREE_M
46 46
47from pyversion import is_python3 47from pyversion import is_python3
48if is_python3(): 48if is_python3():
@@ -2741,10 +2741,19 @@ class Project(object):
2741 os.makedirs(self.objdir) 2741 os.makedirs(self.objdir)
2742 self.bare_objdir.init() 2742 self.bare_objdir.init()
2743 2743
2744 # Enable per-worktree config file support if possible. This is more a 2744 if self.use_git_worktrees:
2745 # nice-to-have feature for users rather than a hard requirement. 2745 # Set up the m/ space to point to the worktree-specific ref space.
2746 if self.use_git_worktrees and git_require((2, 19, 0)): 2746 # We'll update the worktree-specific ref space on each checkout.
2747 self.EnableRepositoryExtension('worktreeConfig') 2747 if self.manifest.branch:
2748 self.bare_git.symbolic_ref(
2749 '-m', 'redirecting to worktree scope',
2750 R_M + self.manifest.branch,
2751 R_WORKTREE_M + self.manifest.branch)
2752
2753 # Enable per-worktree config file support if possible. This is more a
2754 # nice-to-have feature for users rather than a hard requirement.
2755 if git_require((2, 19, 0)):
2756 self.EnableRepositoryExtension('worktreeConfig')
2748 2757
2749 # If we have a separate directory to hold refs, initialize it as well. 2758 # If we have a separate directory to hold refs, initialize it as well.
2750 if self.objdir != self.gitdir: 2759 if self.objdir != self.gitdir:
@@ -2879,25 +2888,37 @@ class Project(object):
2879 2888
2880 def _InitMRef(self): 2889 def _InitMRef(self):
2881 if self.manifest.branch: 2890 if self.manifest.branch:
2882 self._InitAnyMRef(R_M + self.manifest.branch) 2891 if self.use_git_worktrees:
2892 # We can't update this ref with git worktrees until it exists.
2893 # We'll wait until the initial checkout to set it.
2894 if not os.path.exists(self.worktree):
2895 return
2896
2897 base = R_WORKTREE_M
2898 active_git = self.work_git
2899 else:
2900 base = R_M
2901 active_git = self.bare_git
2902
2903 self._InitAnyMRef(base + self.manifest.branch, active_git)
2883 2904
2884 def _InitMirrorHead(self): 2905 def _InitMirrorHead(self):
2885 self._InitAnyMRef(HEAD) 2906 self._InitAnyMRef(HEAD, self.bare_git)
2886 2907
2887 def _InitAnyMRef(self, ref): 2908 def _InitAnyMRef(self, ref, active_git):
2888 cur = self.bare_ref.symref(ref) 2909 cur = self.bare_ref.symref(ref)
2889 2910
2890 if self.revisionId: 2911 if self.revisionId:
2891 if cur != '' or self.bare_ref.get(ref) != self.revisionId: 2912 if cur != '' or self.bare_ref.get(ref) != self.revisionId:
2892 msg = 'manifest set to %s' % self.revisionId 2913 msg = 'manifest set to %s' % self.revisionId
2893 dst = self.revisionId + '^0' 2914 dst = self.revisionId + '^0'
2894 self.bare_git.UpdateRef(ref, dst, message=msg, detach=True) 2915 active_git.UpdateRef(ref, dst, message=msg, detach=True)
2895 else: 2916 else:
2896 remote = self.GetRemote(self.remote.name) 2917 remote = self.GetRemote(self.remote.name)
2897 dst = remote.ToLocal(self.revisionExpr) 2918 dst = remote.ToLocal(self.revisionExpr)
2898 if cur != dst: 2919 if cur != dst:
2899 msg = 'manifest set to %s' % self.revisionExpr 2920 msg = 'manifest set to %s' % self.revisionExpr
2900 self.bare_git.symbolic_ref('-m', msg, ref, dst) 2921 active_git.symbolic_ref('-m', msg, ref, dst)
2901 2922
2902 def _CheckDirReference(self, srcdir, destdir, share_refs): 2923 def _CheckDirReference(self, srcdir, destdir, share_refs):
2903 # Git worktrees don't use symlinks to share at all. 2924 # Git worktrees don't use symlinks to share at all.
@@ -3028,6 +3049,8 @@ class Project(object):
3028 with open(os.path.join(git_worktree_path, 'gitdir'), 'w') as fp: 3049 with open(os.path.join(git_worktree_path, 'gitdir'), 'w') as fp:
3029 print(os.path.relpath(dotgit, git_worktree_path), file=fp) 3050 print(os.path.relpath(dotgit, git_worktree_path), file=fp)
3030 3051
3052 self._InitMRef()
3053
3031 def _InitWorkTree(self, force_sync=False, submodules=False): 3054 def _InitWorkTree(self, force_sync=False, submodules=False):
3032 realdotgit = os.path.join(self.worktree, '.git') 3055 realdotgit = os.path.join(self.worktree, '.git')
3033 tmpdotgit = realdotgit + '.tmp' 3056 tmpdotgit = realdotgit + '.tmp'