Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit d1c40f4

Browse filesBrowse files
committed
worktrees: make non-packed refs also work correctly.
Turns out aec58a9 did the right thing for /packed/ refs, but didn't work correctly on /unpacked/ refs. So this patch gives unpacked refs the same treatment. Without the fix here, the test added will cause this traceback: ====================================================================== ERROR: Check that we find .git as a worktree file and find the worktree ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/pjones/devel/github.com/GitPython/git/test/lib/helper.py", line 92, in wrapper return func(self, path) File "/home/pjones/devel/github.com/GitPython/git/test/test_repo.py", line 938, in test_git_work_tree_dotgit self.assertIsInstance(repo.heads['aaaaaaaa'], Head) File "/home/pjones/devel/github.com/GitPython/git/util.py", line 893, in __getitem__ raise IndexError("No item found with id %r" % (self._prefix + index)) IndexError: No item found with id 'aaaaaaaa' Woops. Things I've learned: - test_remote doesn't work currently if you start on a branch. I think it never did? - Because of 346424d, all *sorts* of stuff in the test suite doesn't work if you name your development branch "packed-refs" (This seems like a bug...) Signed-off-by: Peter Jones <pjones@redhat.com>
1 parent cf8dc25 commit d1c40f4
Copy full SHA for d1c40f4

5 files changed

+45-29Lines changed: 45 additions & 29 deletions

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎git/refs/remote.py‎

Copy file name to clipboardExpand all lines: git/refs/remote.py
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ def delete(cls, repo, *refs, **kwargs):
3636
# are generally ignored in the refs/ folder. We don't though
3737
# and delete remainders manually
3838
for ref in refs:
39+
try:
40+
os.remove(osp.join(repo.common_dir, ref.path))
41+
except OSError:
42+
pass
3943
try:
4044
os.remove(osp.join(repo.git_dir, ref.path))
4145
except OSError:
Collapse file

‎git/refs/symbolic.py‎

Copy file name to clipboardExpand all lines: git/refs/symbolic.py
+20-24Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@
2626
__all__ = ["SymbolicReference"]
2727

2828

29+
def _git_dir(repo, path):
30+
""" Find the git dir that's appropriate for the path"""
31+
name = "%s" % (path,)
32+
if name in ['HEAD', 'ORIG_HEAD', 'FETCH_HEAD', 'index', 'logs']:
33+
return repo.git_dir
34+
return repo.common_dir
35+
36+
2937
class SymbolicReference(object):
3038

3139
"""Represents a special case of a reference such that this reference is symbolic.
@@ -71,16 +79,11 @@ def name(self):
7179

7280
@property
7381
def abspath(self):
74-
return join_path_native(self.repo.git_dir, self.path)
82+
return join_path_native(_git_dir(self.repo, self.path), self.path)
7583

7684
@classmethod
7785
def _get_packed_refs_path(cls, repo):
78-
try:
79-
commondir = open(osp.join(repo.git_dir, 'commondir'), 'rt').readlines()[0].strip()
80-
except (OSError, IOError):
81-
commondir = '.'
82-
repodir = osp.join(repo.git_dir, commondir)
83-
return osp.join(repodir, 'packed-refs')
86+
return osp.join(repo.common_dir, 'packed-refs')
8487

8588
@classmethod
8689
def _iter_packed_refs(cls, repo):
@@ -127,11 +130,12 @@ def dereference_recursive(cls, repo, ref_path):
127130
# END recursive dereferencing
128131

129132
@classmethod
130-
def _get_ref_info_helper(cls, repo, repodir, ref_path):
133+
def _get_ref_info_helper(cls, repo, ref_path):
131134
"""Return: (str(sha), str(target_ref_path)) if available, the sha the file at
132135
rela_path points to, or None. target_ref_path is the reference we
133136
point to, or None"""
134137
tokens = None
138+
repodir = _git_dir(repo, ref_path)
135139
try:
136140
with open(osp.join(repodir, ref_path), 'rt') as fp:
137141
value = fp.read().rstrip()
@@ -169,16 +173,7 @@ def _get_ref_info(cls, repo, ref_path):
169173
"""Return: (str(sha), str(target_ref_path)) if available, the sha the file at
170174
rela_path points to, or None. target_ref_path is the reference we
171175
point to, or None"""
172-
try:
173-
return cls._get_ref_info_helper(repo, repo.git_dir, ref_path)
174-
except ValueError:
175-
try:
176-
commondir = open(osp.join(repo.git_dir, 'commondir'), 'rt').readlines()[0].strip()
177-
except (OSError, IOError):
178-
commondir = '.'
179-
180-
repodir = osp.join(repo.git_dir, commondir)
181-
return cls._get_ref_info_helper(repo, repodir, ref_path)
176+
return cls._get_ref_info_helper(repo, ref_path)
182177

183178
def _get_object(self):
184179
"""
@@ -433,7 +428,7 @@ def delete(cls, repo, path):
433428
or just "myreference", hence 'refs/' is implied.
434429
Alternatively the symbolic reference to be deleted"""
435430
full_ref_path = cls.to_full_path(path)
436-
abs_path = osp.join(repo.git_dir, full_ref_path)
431+
abs_path = osp.join(repo.common_dir, full_ref_path)
437432
if osp.exists(abs_path):
438433
os.remove(abs_path)
439434
else:
@@ -484,8 +479,9 @@ def _create(cls, repo, path, resolve, reference, force, logmsg=None):
484479
a proper symbolic reference. Otherwise it will be resolved to the
485480
corresponding object and a detached symbolic reference will be created
486481
instead"""
482+
git_dir = _git_dir(repo, path)
487483
full_ref_path = cls.to_full_path(path)
488-
abs_ref_path = osp.join(repo.git_dir, full_ref_path)
484+
abs_ref_path = osp.join(git_dir, full_ref_path)
489485

490486
# figure out target data
491487
target = reference
@@ -559,8 +555,8 @@ def rename(self, new_path, force=False):
559555
if self.path == new_path:
560556
return self
561557

562-
new_abs_path = osp.join(self.repo.git_dir, new_path)
563-
cur_abs_path = osp.join(self.repo.git_dir, self.path)
558+
new_abs_path = osp.join(_git_dir(self.repo, new_path), new_path)
559+
cur_abs_path = osp.join(_git_dir(self.repo, self.path), self.path)
564560
if osp.isfile(new_abs_path):
565561
if not force:
566562
# if they point to the same file, its not an error
@@ -594,7 +590,7 @@ def _iter_items(cls, repo, common_path=None):
594590

595591
# walk loose refs
596592
# Currently we do not follow links
597-
for root, dirs, files in os.walk(join_path_native(repo.git_dir, common_path)):
593+
for root, dirs, files in os.walk(join_path_native(repo.common_dir, common_path)):
598594
if 'refs' not in root.split(os.sep): # skip non-refs subfolders
599595
refs_id = [d for d in dirs if d == 'refs']
600596
if refs_id:
@@ -605,7 +601,7 @@ def _iter_items(cls, repo, common_path=None):
605601
if f == 'packed-refs':
606602
continue
607603
abs_path = to_native_path_linux(join_path(root, f))
608-
rela_paths.add(abs_path.replace(to_native_path_linux(repo.git_dir) + '/', ""))
604+
rela_paths.add(abs_path.replace(to_native_path_linux(repo.common_dir) + '/', ""))
609605
# END for each file in root directory
610606
# END for each directory to walk
611607

Collapse file

‎git/remote.py‎

Copy file name to clipboardExpand all lines: git/remote.py
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -652,7 +652,7 @@ def _get_fetch_info_from_stderr(self, proc, progress):
652652
continue
653653

654654
# read head information
655-
with open(osp.join(self.repo.git_dir, 'FETCH_HEAD'), 'rb') as fp:
655+
with open(osp.join(self.repo.common_dir, 'FETCH_HEAD'), 'rb') as fp:
656656
fetch_head_info = [l.decode(defenc) for l in fp.readlines()]
657657

658658
l_fil = len(fetch_info_lines)
Collapse file

‎git/repo/base.py‎

Copy file name to clipboardExpand all lines: git/repo/base.py
+18-4Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ class Repo(object):
7474
working_dir = None
7575
_working_tree_dir = None
7676
git_dir = None
77+
_common_dir = None
7778

7879
# precompiled regex
7980
re_whitespace = re.compile(r'\s+')
@@ -169,17 +170,23 @@ def __init__(self, path=None, odbt=DefaultDBType, search_parent_directories=Fals
169170
# lets not assume the option exists, although it should
170171
pass
171172

173+
try:
174+
common_dir = open(osp.join(self.git_dir, 'commondir'), 'rt').readlines()[0].strip()
175+
self._common_dir = osp.join(self.git_dir, common_dir)
176+
except (OSError, IOError):
177+
self._common_dir = None
178+
172179
# adjust the wd in case we are actually bare - we didn't know that
173180
# in the first place
174181
if self._bare:
175182
self._working_tree_dir = None
176183
# END working dir handling
177184

178-
self.working_dir = self._working_tree_dir or self.git_dir
185+
self.working_dir = self._working_tree_dir or self.common_dir
179186
self.git = self.GitCommandWrapperType(self.working_dir)
180187

181188
# special handling, in special times
182-
args = [osp.join(self.git_dir, 'objects')]
189+
args = [osp.join(self.common_dir, 'objects')]
183190
if issubclass(odbt, GitCmdObjectDB):
184191
args.append(self.git)
185192
self.odb = odbt(*args)
@@ -236,6 +243,13 @@ def working_tree_dir(self):
236243
"""
237244
return self._working_tree_dir
238245

246+
@property
247+
def common_dir(self):
248+
""":return: The git dir that holds everything except possibly HEAD,
249+
FETCH_HEAD, ORIG_HEAD, COMMIT_EDITMSG, index, and logs/ .
250+
"""
251+
return self._common_dir or self.git_dir
252+
239253
@property
240254
def bare(self):
241255
""":return: True if the repository is bare"""
@@ -574,7 +588,7 @@ def _set_alternates(self, alts):
574588
:note:
575589
The method does not check for the existence of the paths in alts
576590
as the caller is responsible."""
577-
alternates_path = osp.join(self.git_dir, 'objects', 'info', 'alternates')
591+
alternates_path = osp.join(self.common_dir, 'objects', 'info', 'alternates')
578592
if not alts:
579593
if osp.isfile(alternates_path):
580594
os.remove(alternates_path)
@@ -932,7 +946,7 @@ def clone(self, path, progress=None, **kwargs):
932946
* All remaining keyword arguments are given to the git-clone command
933947
934948
:return: ``git.Repo`` (the newly cloned repo)"""
935-
return self._clone(self.git, self.git_dir, path, type(self.odb), progress, **kwargs)
949+
return self._clone(self.git, self.common_dir, path, type(self.odb), progress, **kwargs)
936950

937951
@classmethod
938952
def clone_from(cls, url, to_path, progress=None, env=None, **kwargs):
Collapse file

‎git/test/test_repo.py‎

Copy file name to clipboardExpand all lines: git/test/test_repo.py
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -935,6 +935,8 @@ def test_git_work_tree_dotgit(self, rw_dir):
935935
commit = repo.head.commit
936936
self.assertIsInstance(commit, Object)
937937

938+
self.assertIsInstance(repo.heads['aaaaaaaa'], Head)
939+
938940
@with_rw_directory
939941
def test_git_work_tree_env(self, rw_dir):
940942
"""Check that we yield to GIT_WORK_TREE"""

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.