Skip to content

Commit 1085a7c

Browse files
authored
Merge pull request #2128 from meliezer/fix-worktree-git-dir
Fix Repo() autodiscovery in linked worktrees when GIT_DIR is set
2 parents b7f5fde + 4c6ec60 commit 1085a7c

2 files changed

Lines changed: 58 additions & 0 deletions

File tree

git/repo/base.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,28 @@ def __init__(
242242
# It's important to normalize the paths, as submodules will otherwise
243243
# initialize their repo instances with paths that depend on path-portions
244244
# that will not exist after being removed. It's just cleaner.
245+
if (
246+
osp.isfile(osp.join(curpath, "gitdir"))
247+
and osp.isfile(osp.join(curpath, "commondir"))
248+
and osp.isfile(osp.join(curpath, "HEAD"))
249+
):
250+
git_dir = curpath
251+
252+
if "GIT_WORK_TREE" in os.environ:
253+
self._working_tree_dir = os.getenv("GIT_WORK_TREE")
254+
else:
255+
# Linked worktree administrative directories store the path to the
256+
# worktree's .git file in their gitdir file (without "gitdir: " prefix).
257+
with open(osp.join(git_dir, "gitdir")) as fp:
258+
worktree_gitfile = fp.read().strip()
259+
260+
if not osp.isabs(worktree_gitfile):
261+
worktree_gitfile = osp.normpath(osp.join(git_dir, worktree_gitfile))
262+
263+
self._working_tree_dir = osp.dirname(worktree_gitfile)
264+
265+
break
266+
245267
if is_git_dir(curpath):
246268
git_dir = curpath
247269
# from man git-config : core.worktree

test/test_repo.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,6 +1148,42 @@ def test_git_work_tree_env(self, rw_dir):
11481148
self.assertEqual(r.working_tree_dir, repo_dir)
11491149
self.assertEqual(r.working_dir, repo_dir)
11501150

1151+
@with_rw_directory
1152+
def test_git_work_tree_env_in_linked_worktree(self, rw_dir):
1153+
"""Check that Repo() autodiscovers a linked worktree when GIT_DIR is set."""
1154+
git = Git(rw_dir)
1155+
if git.version_info[:3] < (2, 5, 1):
1156+
raise RuntimeError("worktree feature unsupported (test needs git 2.5.1 or later)")
1157+
1158+
rw_master = self.rorepo.clone(join_path_native(rw_dir, "master_repo"))
1159+
branch = rw_master.create_head("bbbbbbbb")
1160+
worktree_path = join_path_native(rw_dir, "worktree_repo")
1161+
if Git.is_cygwin():
1162+
worktree_path = cygpath(worktree_path)
1163+
1164+
rw_master.git.worktree("add", worktree_path, branch.name)
1165+
1166+
git_dir = Git(worktree_path).rev_parse("--git-dir")
1167+
1168+
patched_env = dict(os.environ)
1169+
patched_env["GIT_DIR"] = git_dir
1170+
patched_env.pop("GIT_WORK_TREE", None)
1171+
patched_env.pop("GIT_COMMON_DIR", None)
1172+
1173+
with mock.patch.dict(os.environ, patched_env, clear=True):
1174+
old_cwd = os.getcwd()
1175+
try:
1176+
os.chdir(worktree_path)
1177+
1178+
explicit = Repo(os.getcwd())
1179+
autodiscovered = Repo()
1180+
1181+
self.assertTrue(osp.samefile(explicit.working_tree_dir, worktree_path))
1182+
self.assertTrue(osp.samefile(autodiscovered.working_tree_dir, worktree_path))
1183+
self.assertTrue(osp.samefile(autodiscovered.working_tree_dir, explicit.working_tree_dir))
1184+
finally:
1185+
os.chdir(old_cwd)
1186+
11511187
@with_rw_directory
11521188
def test_rebasing(self, rw_dir):
11531189
r = Repo.init(rw_dir)

0 commit comments

Comments
 (0)