diff --git a/git_refs.py b/git_refs.py index 02b98cba..e2b62ab2 100644 --- a/git_refs.py +++ b/git_refs.py @@ -23,6 +23,8 @@ R_CHANGES = 'refs/changes/' R_HEADS = 'refs/heads/' R_TAGS = 'refs/tags/' R_PUB = 'refs/published/' +R_WORKTREE = 'refs/worktree/' +R_WORKTREE_M = R_WORKTREE + 'm/' R_M = 'refs/remotes/m/' 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 import progress from repo_trace import IsTrace, Trace -from git_refs import GitRefs, HEAD, R_HEADS, R_TAGS, R_PUB, R_M +from git_refs import GitRefs, HEAD, R_HEADS, R_TAGS, R_PUB, R_M, R_WORKTREE_M from pyversion import is_python3 if is_python3(): @@ -2741,10 +2741,19 @@ class Project(object): os.makedirs(self.objdir) self.bare_objdir.init() - # Enable per-worktree config file support if possible. This is more a - # nice-to-have feature for users rather than a hard requirement. - if self.use_git_worktrees and git_require((2, 19, 0)): - self.EnableRepositoryExtension('worktreeConfig') + if self.use_git_worktrees: + # Set up the m/ space to point to the worktree-specific ref space. + # We'll update the worktree-specific ref space on each checkout. + if self.manifest.branch: + self.bare_git.symbolic_ref( + '-m', 'redirecting to worktree scope', + R_M + self.manifest.branch, + R_WORKTREE_M + self.manifest.branch) + + # Enable per-worktree config file support if possible. This is more a + # nice-to-have feature for users rather than a hard requirement. + if git_require((2, 19, 0)): + self.EnableRepositoryExtension('worktreeConfig') # If we have a separate directory to hold refs, initialize it as well. if self.objdir != self.gitdir: @@ -2879,25 +2888,37 @@ class Project(object): def _InitMRef(self): if self.manifest.branch: - self._InitAnyMRef(R_M + self.manifest.branch) + if self.use_git_worktrees: + # We can't update this ref with git worktrees until it exists. + # We'll wait until the initial checkout to set it. + if not os.path.exists(self.worktree): + return + + base = R_WORKTREE_M + active_git = self.work_git + else: + base = R_M + active_git = self.bare_git + + self._InitAnyMRef(base + self.manifest.branch, active_git) def _InitMirrorHead(self): - self._InitAnyMRef(HEAD) + self._InitAnyMRef(HEAD, self.bare_git) - def _InitAnyMRef(self, ref): + def _InitAnyMRef(self, ref, active_git): cur = self.bare_ref.symref(ref) if self.revisionId: if cur != '' or self.bare_ref.get(ref) != self.revisionId: msg = 'manifest set to %s' % self.revisionId dst = self.revisionId + '^0' - self.bare_git.UpdateRef(ref, dst, message=msg, detach=True) + active_git.UpdateRef(ref, dst, message=msg, detach=True) else: remote = self.GetRemote(self.remote.name) dst = remote.ToLocal(self.revisionExpr) if cur != dst: msg = 'manifest set to %s' % self.revisionExpr - self.bare_git.symbolic_ref('-m', msg, ref, dst) + active_git.symbolic_ref('-m', msg, ref, dst) def _CheckDirReference(self, srcdir, destdir, share_refs): # Git worktrees don't use symlinks to share at all. @@ -3028,6 +3049,8 @@ class Project(object): with open(os.path.join(git_worktree_path, 'gitdir'), 'w') as fp: print(os.path.relpath(dotgit, git_worktree_path), file=fp) + self._InitMRef() + def _InitWorkTree(self, force_sync=False, submodules=False): realdotgit = os.path.join(self.worktree, '.git') tmpdotgit = realdotgit + '.tmp'