summaryrefslogtreecommitdiffstats
path: root/git_superproject.py
diff options
context:
space:
mode:
authorGavin Mak <gavinmak@google.com>2026-02-07 00:53:31 +0000
committerLUCI <gerrit-scoped@luci-project-accounts.iam.gserviceaccount.com>2026-03-17 14:30:35 -0700
commit83b8ebdbbed5ec894a2f89eb5e4bcf5d0bb14300 (patch)
treebd84dbdba2f3a8935a4e92704bc2bfee4318be7a /git_superproject.py
parenta0abfd7339536cfba02c112e7ac804bc6252ebdb (diff)
downloadgit-repo-83b8ebdbbed5ec894a2f89eb5e4bcf5d0bb14300.tar.gz
git_superproject: avoid re-initing bare repo
Running sync with reftable on a files-backed workspace fails to re-init the superproject dir with: ``` fatal: could not open '.../.repo/exp-superproject/<hash>-superproject.git/refs/heads' for writing: Is a directory ``` Bug: 476209856 Change-Id: Ie8473d66069aafefa5661bd3ea8e73b2b27c6a38 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/550981 Commit-Queue: Gavin Mak <gavinmak@google.com> Reviewed-by: Mike Frysinger <vapier@google.com> Tested-by: Gavin Mak <gavinmak@google.com>
Diffstat (limited to 'git_superproject.py')
-rw-r--r--git_superproject.py70
1 files changed, 53 insertions, 17 deletions
diff --git a/git_superproject.py b/git_superproject.py
index 1ada173b7..12ac3dec6 100644
--- a/git_superproject.py
+++ b/git_superproject.py
@@ -23,9 +23,11 @@ Examples:
23""" 23"""
24 24
25import functools 25import functools
26import glob
26import hashlib 27import hashlib
27import os 28import os
28import sys 29import sys
30import tempfile
29import time 31import time
30from typing import NamedTuple 32from typing import NamedTuple
31import urllib.parse 33import urllib.parse
@@ -34,6 +36,7 @@ from git_command import git_require
34from git_command import GitCommand 36from git_command import GitCommand
35from git_config import RepoConfig 37from git_config import RepoConfig
36from git_refs import GitRefs 38from git_refs import GitRefs
39import platform_utils
37 40
38 41
39_SUPERPROJECT_GIT_NAME = "superproject.git" 42_SUPERPROJECT_GIT_NAME = "superproject.git"
@@ -215,30 +218,63 @@ class Superproject:
215 """ 218 """
216 if not os.path.exists(self._superproject_path): 219 if not os.path.exists(self._superproject_path):
217 os.mkdir(self._superproject_path) 220 os.mkdir(self._superproject_path)
218 if not self._quiet and not os.path.exists(self._work_git): 221
222 if os.path.exists(self._work_git):
223 return True
224
225 if not self._quiet:
219 print( 226 print(
220 "%s: Performing initial setup for superproject; this might " 227 "%s: Performing initial setup for superproject; this might "
221 "take several minutes." % self._work_git 228 "take several minutes." % self._work_git
222 ) 229 )
223 cmd = ["init", "--bare", self._work_git_name] 230
224 p = GitCommand( 231 tmp_gitdir_prefix = ".tmp-superproject-initgitdir-"
225 None, 232 tmp_gitdir = tempfile.mkdtemp(
226 cmd, 233 prefix=tmp_gitdir_prefix,
227 cwd=self._superproject_path, 234 dir=self._superproject_path,
228 capture_stdout=True,
229 capture_stderr=True,
230 ) 235 )
231 retval = p.Wait() 236 tmp_git_name = os.path.basename(tmp_gitdir)
232 if retval: 237
233 self._LogWarning( 238 try:
234 "git init call failed, command: git {}, " 239 cmd = ["init", "--bare", tmp_git_name]
235 "return code: {}, stderr: {}", 240 p = GitCommand(
241 None,
236 cmd, 242 cmd,
237 retval, 243 cwd=self._superproject_path,
238 p.stderr, 244 capture_stdout=True,
245 capture_stderr=True,
239 ) 246 )
240 return False 247 retval = p.Wait()
241 return True 248 if retval:
249 self._LogWarning(
250 "git init call failed, command: git {}, "
251 "return code: {}, stderr: {}",
252 cmd,
253 retval,
254 p.stderr,
255 )
256 return False
257
258 platform_utils.rename(tmp_gitdir, self._work_git)
259 tmp_gitdir = None
260 return True
261 finally:
262 # Clean up the temporary directory created during the process,
263 # as well as any stale ones left over from previous attempts.
264 if tmp_gitdir and os.path.exists(tmp_gitdir):
265 platform_utils.rmtree(tmp_gitdir)
266
267 age_threshold = 60 * 60 * 24 # 1 day in seconds
268 now = time.time()
269 for tmp_dir in glob.glob(
270 os.path.join(self._superproject_path, f"{tmp_gitdir_prefix}*")
271 ):
272 try:
273 mtime = os.path.getmtime(tmp_dir)
274 if now - mtime > age_threshold:
275 platform_utils.rmtree(tmp_dir)
276 except OSError:
277 pass
242 278
243 def _Fetch(self): 279 def _Fetch(self):
244 """Fetches a superproject for the manifest based on |_remote_url|. 280 """Fetches a superproject for the manifest based on |_remote_url|.