summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Frysinger <vapier@google.com>2021-12-23 17:36:09 -0500
committerMike Frysinger <vapier@google.com>2022-01-19 17:24:51 +0000
commit67d6cdf2bc752f02cd294abe3a45811c2019de35 (patch)
tree8f1a929cedaa30e4b49382f7fd1d5a1e097a2558
parent152032cca2a77f36e5a0c6943b66fd630c79b0e7 (diff)
downloadgit-repo-67d6cdf2bc752f02cd294abe3a45811c2019de35.tar.gz
project: store objects in project-objects directly
In order to stop sharing objects/ directly between shared projects, we have to fetch the remote objects into project-objects/ manually. So instead of running git operations in the individual project dirs and relying on .git/objects being symlinked to project-objects/, tell git to store any objects it fetches in project-objects/. We do this by leveraging the GIT_OBJECT_DIRECTORY override. This has been in git forever, or at least since v1.7.2 which is what we already hard require. This tells git to save new objects to the specified path no matter where it's being run otherwise. We still otherwise run git in the project-specific dir so that it can find the right set of refs that it wants to compare against, including local refs. For that reason, we also have to leverage GIT_ALTERNATE_OBJECT_DIRECTORIES to tell git where to find objects that are not in the upstream remote. This way git doesn't blow up when it can't find objects only associated with local commits. As it stands right now, the practical result is the same: since we symlink the project objects/ dir to the project-objects/ tree, the default objects dir, the one we set $GIT_OBJECT_DIRECTORY to, and the one we set $GIT_ALTERNATE_OBJECT_DIRECTORIES to are actually all the same. So this commit by itself should be safe. But in a follow up commit, we can replace the symlink with a separate dir and git will keep working. Bug: https://crbug.com/gerrit/15553 Change-Id: Ie4e654aec3e1ee307eee925a54908a2db6a5869f Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/328100 Reviewed-by: Jack Neus <jackneus@google.com> Tested-by: Mike Frysinger <vapier@google.com>
-rw-r--r--git_command.py25
-rw-r--r--project.py9
2 files changed, 27 insertions, 7 deletions
diff --git a/git_command.py b/git_command.py
index 95db91f2..5d73c281 100644
--- a/git_command.py
+++ b/git_command.py
@@ -169,7 +169,8 @@ class GitCommand(object):
169 disable_editor=False, 169 disable_editor=False,
170 ssh_proxy=None, 170 ssh_proxy=None,
171 cwd=None, 171 cwd=None,
172 gitdir=None): 172 gitdir=None,
173 objdir=None):
173 env = self._GetBasicEnv() 174 env = self._GetBasicEnv()
174 175
175 if disable_editor: 176 if disable_editor:
@@ -194,13 +195,24 @@ class GitCommand(object):
194 cwd = project.worktree 195 cwd = project.worktree
195 if not gitdir: 196 if not gitdir:
196 gitdir = project.gitdir 197 gitdir = project.gitdir
198 # Git on Windows wants its paths only using / for reliability.
199 if platform_utils.isWindows():
200 if objdir:
201 objdir = objdir.replace('\\', '/')
202 if gitdir:
203 gitdir = gitdir.replace('\\', '/')
204
205 if objdir:
206 # Set to the place we want to save the objects.
207 env['GIT_OBJECT_DIRECTORY'] = objdir
208 if gitdir:
209 # Allow git to search the original place in case of local or unique refs
210 # that git will attempt to resolve even if we aren't fetching them.
211 env['GIT_ALTERNATE_OBJECT_DIRECTORIES'] = gitdir + '/objects'
197 212
198 command = [GIT] 213 command = [GIT]
199 if bare: 214 if bare:
200 if gitdir: 215 if gitdir:
201 # Git on Windows wants its paths only using / for reliability.
202 if platform_utils.isWindows():
203 gitdir = gitdir.replace('\\', '/')
204 env[GIT_DIR] = gitdir 216 env[GIT_DIR] = gitdir
205 cwd = None 217 cwd = None
206 command.append(cmdv[0]) 218 command.append(cmdv[0])
@@ -234,6 +246,11 @@ class GitCommand(object):
234 dbg += ': export GIT_DIR=%s\n' % env[GIT_DIR] 246 dbg += ': export GIT_DIR=%s\n' % env[GIT_DIR]
235 LAST_GITDIR = env[GIT_DIR] 247 LAST_GITDIR = env[GIT_DIR]
236 248
249 if 'GIT_OBJECT_DIRECTORY' in env:
250 dbg += ': export GIT_OBJECT_DIRECTORY=%s\n' % env['GIT_OBJECT_DIRECTORY']
251 if 'GIT_ALTERNATE_OBJECT_DIRECTORIES' in env:
252 dbg += ': export GIT_ALTERNATE_OBJECT_DIRECTORIES=%s\n' % env['GIT_ALTERNATE_OBJECT_DIRECTORIES']
253
237 dbg += ': ' 254 dbg += ': '
238 dbg += ' '.join(command) 255 dbg += ' '.join(command)
239 if stdin == subprocess.PIPE: 256 if stdin == subprocess.PIPE:
diff --git a/project.py b/project.py
index 8598de36..b70f6d41 100644
--- a/project.py
+++ b/project.py
@@ -2192,8 +2192,10 @@ class Project(object):
2192 retry_cur_sleep = retry_sleep_initial_sec 2192 retry_cur_sleep = retry_sleep_initial_sec
2193 ok = prune_tried = False 2193 ok = prune_tried = False
2194 for try_n in range(retry_fetches): 2194 for try_n in range(retry_fetches):
2195 gitcmd = GitCommand(self, cmd, bare=True, ssh_proxy=ssh_proxy, 2195 gitcmd = GitCommand(
2196 merge_output=True, capture_stdout=quiet or bool(output_redir)) 2196 self, cmd, bare=True, objdir=os.path.join(self.objdir, 'objects'),
2197 ssh_proxy=ssh_proxy,
2198 merge_output=True, capture_stdout=quiet or bool(output_redir))
2197 if gitcmd.stdout and not quiet and output_redir: 2199 if gitcmd.stdout and not quiet and output_redir:
2198 output_redir.write(gitcmd.stdout) 2200 output_redir.write(gitcmd.stdout)
2199 ret = gitcmd.Wait() 2201 ret = gitcmd.Wait()
@@ -2309,7 +2311,8 @@ class Project(object):
2309 cmd.append(str(f)) 2311 cmd.append(str(f))
2310 cmd.append('+refs/tags/*:refs/tags/*') 2312 cmd.append('+refs/tags/*:refs/tags/*')
2311 2313
2312 ok = GitCommand(self, cmd, bare=True).Wait() == 0 2314 ok = GitCommand(
2315 self, cmd, bare=True, objdir=os.path.join(self.objdir, 'objects')).Wait() == 0
2313 platform_utils.remove(bundle_dst, missing_ok=True) 2316 platform_utils.remove(bundle_dst, missing_ok=True)
2314 platform_utils.remove(bundle_tmp, missing_ok=True) 2317 platform_utils.remove(bundle_tmp, missing_ok=True)
2315 return ok 2318 return ok