From 979d5bdc3ebe45998a76dbbaff46c33d4e59683b Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sun, 9 Feb 2020 02:28:34 -0500 Subject: add experimental git worktree support This provides initial support for using git worktrees internally instead of our own ad-hoc symlink tree. It's been lightly tested which is why it's not currently exposed via --help. When people opt-in to worktrees in an existing repo client checkout, no projects are migrated. Instead, only new projects will use the worktree method. This allows for limited testing/opting in without having to completely blow things away or get a second checkout. Bug: https://crbug.com/gerrit/11486 Change-Id: Ic3ff891b30940a6ba497b406b2a387e0a8517ed8 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/254075 Tested-by: Mike Frysinger Reviewed-by: Mike Frysinger --- manifest_xml.py | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) (limited to 'manifest_xml.py') diff --git a/manifest_xml.py b/manifest_xml.py index 7f38d8c3..41628003 100644 --- a/manifest_xml.py +++ b/manifest_xml.py @@ -146,9 +146,17 @@ class XmlManifest(object): gitdir=os.path.join(repodir, 'repo/.git'), worktree=os.path.join(repodir, 'repo')) - self.manifestProject = MetaProject(self, 'manifests', - gitdir=os.path.join(repodir, 'manifests.git'), - worktree=os.path.join(repodir, 'manifests')) + mp = MetaProject(self, 'manifests', + gitdir=os.path.join(repodir, 'manifests.git'), + worktree=os.path.join(repodir, 'manifests')) + self.manifestProject = mp + + # This is a bit hacky, but we're in a chicken & egg situation: all the + # normal repo settings live in the manifestProject which we just setup + # above, so we couldn't easily query before that. We assume Project() + # init doesn't care if this changes afterwards. + if mp.config.GetBoolean('repo.worktree'): + mp.use_git_worktrees = True self._Unload() @@ -427,6 +435,10 @@ class XmlManifest(object): def IsMirror(self): return self.manifestProject.config.GetBoolean('repo.mirror') + @property + def UseGitWorktrees(self): + return self.manifestProject.config.GetBoolean('repo.worktree') + @property def IsArchive(self): return self.manifestProject.config.GetBoolean('repo.archive') @@ -873,8 +885,10 @@ class XmlManifest(object): groups = self._ParseGroups(groups) if parent is None: - relpath, worktree, gitdir, objdir = self.GetProjectPaths(name, path) + relpath, worktree, gitdir, objdir, use_git_worktrees = \ + self.GetProjectPaths(name, path) else: + use_git_worktrees = False relpath, worktree, gitdir, objdir = \ self.GetSubprojectPaths(parent, name, path) @@ -903,6 +917,7 @@ class XmlManifest(object): upstream=upstream, parent=parent, dest_branch=dest_branch, + use_git_worktrees=use_git_worktrees, **extra_proj_attrs) for n in node.childNodes: @@ -918,6 +933,7 @@ class XmlManifest(object): return project def GetProjectPaths(self, name, path): + use_git_worktrees = False relpath = path if self.IsMirror: worktree = None @@ -926,8 +942,15 @@ class XmlManifest(object): else: worktree = os.path.join(self.topdir, path).replace('\\', '/') gitdir = os.path.join(self.repodir, 'projects', '%s.git' % path) - objdir = os.path.join(self.repodir, 'project-objects', '%s.git' % name) - return relpath, worktree, gitdir, objdir + # We allow people to mix git worktrees & non-git worktrees for now. + # This allows for in situ migration of repo clients. + if os.path.exists(gitdir) or not self.UseGitWorktrees: + objdir = os.path.join(self.repodir, 'project-objects', '%s.git' % name) + else: + use_git_worktrees = True + gitdir = os.path.join(self.repodir, 'worktrees', '%s.git' % name) + objdir = gitdir + return relpath, worktree, gitdir, objdir, use_git_worktrees def GetProjectsWithName(self, name): return self._projects.get(name, []) -- cgit v1.2.3-54-g00ecf