summaryrefslogtreecommitdiff
path: root/git/repo
diff options
context:
space:
mode:
authorPeter Jones <pjones@redhat.com>2017-06-26 14:54:28 -0400
committerSebastian Thiel <byronimo@gmail.com>2017-07-01 13:59:17 +0200
commitaec58a9d386d4199374139cd1fc466826ac3d2cf (patch)
tree81e24d83a4e95410fd63b986dc420f8d488fce66 /git/repo
parent4bd708d41090fbe00acb41246eb22fa8b5632967 (diff)
downloadgitpython-aec58a9d386d4199374139cd1fc466826ac3d2cf.tar.gz
Repo: handle worktrees better
This makes Repo("foo") work when foo/.git is a file of the form created by "git worktree add", i.e. it's a text file that says: gitdir: /home/me/project/.git/worktrees/bar and where /home/me/project/.git/ is the nominal gitdir, but /home/me/project/.git/worktrees/bar has this worktree's HEAD etc and a "gitdir" file that contains the path of foo/.git . Signed-off-by: Peter Jones <pjones@redhat.com>
Diffstat (limited to 'git/repo')
-rw-r--r--git/repo/base.py11
-rw-r--r--git/repo/fun.py22
2 files changed, 29 insertions, 4 deletions
diff --git a/git/repo/base.py b/git/repo/base.py
index 2f67a341..28bb2a5d 100644
--- a/git/repo/base.py
+++ b/git/repo/base.py
@@ -32,7 +32,7 @@ from git.remote import Remote, add_progress, to_progress_instance
from git.util import Actor, finalize_process, decygpath, hex_to_bin
import os.path as osp
-from .fun import rev_parse, is_git_dir, find_submodule_git_dir, touch
+from .fun import rev_parse, is_git_dir, find_submodule_git_dir, touch, find_worktree_git_dir
import gc
import gitdb
@@ -138,10 +138,15 @@ class Repo(object):
self._working_tree_dir = os.getenv('GIT_WORK_TREE', os.path.dirname(self.git_dir))
break
- sm_gitpath = find_submodule_git_dir(osp.join(curpath, '.git'))
+ dotgit = osp.join(curpath, '.git')
+ sm_gitpath = find_submodule_git_dir(dotgit)
if sm_gitpath is not None:
self.git_dir = osp.normpath(sm_gitpath)
- sm_gitpath = find_submodule_git_dir(osp.join(curpath, '.git'))
+
+ sm_gitpath = find_submodule_git_dir(dotgit)
+ if sm_gitpath is None:
+ sm_gitpath = find_worktree_git_dir(dotgit)
+
if sm_gitpath is not None:
self.git_dir = _expand_path(sm_gitpath)
self._working_tree_dir = curpath
diff --git a/git/repo/fun.py b/git/repo/fun.py
index 39e55880..6aefd9d6 100644
--- a/git/repo/fun.py
+++ b/git/repo/fun.py
@@ -1,5 +1,6 @@
"""Package with general repository related functions"""
import os
+import stat
from string import digits
from git.compat import xrange
@@ -17,7 +18,7 @@ from git.cmd import Git
__all__ = ('rev_parse', 'is_git_dir', 'touch', 'find_submodule_git_dir', 'name_to_object', 'short_to_long', 'deref_tag',
- 'to_commit')
+ 'to_commit', 'find_worktree_git_dir')
def touch(filename):
@@ -47,6 +48,25 @@ def is_git_dir(d):
return False
+def find_worktree_git_dir(dotgit):
+ """Search for a gitdir for this worktree."""
+ try:
+ statbuf = os.stat(dotgit)
+ except OSError:
+ return None
+ if not stat.S_ISREG(statbuf.st_mode):
+ return None
+
+ try:
+ lines = open(dotgit, 'r').readlines()
+ for key, value in [line.strip().split(': ') for line in lines]:
+ if key == 'gitdir':
+ return value
+ except ValueError:
+ pass
+ return None
+
+
def find_submodule_git_dir(d):
"""Search for a submodule repo."""
if is_git_dir(d):