Skip to content

Commit cfc70fe

Browse files
committed
fix(index): handle adding symlinks to dirs
When expanding directories, check if it is a symlink and don't expand them at all. Previously, we followed symlinks and expanded their contents, which could lead to weird index files. Fixes #302
1 parent 8724dfa commit cfc70fe

File tree

2 files changed

+27
-12
lines changed

2 files changed

+27
-12
lines changed

Diff for: git/index/base.py

+11
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,17 @@ def raise_exc(e):
367367
abs_path = os.path.join(r, path)
368368
# END make absolute path
369369

370+
try:
371+
st = os.lstat(abs_path) # handles non-symlinks as well
372+
except OSError:
373+
# the lstat call may fail as the path may contain globs as well
374+
pass
375+
else:
376+
if S_ISLNK(st.st_mode):
377+
yield abs_path.replace(rs, '')
378+
continue
379+
# end check symlink
380+
370381
# resolve globs if possible
371382
if '?' in path or '*' in path or '[' in path:
372383
for f in self._iter_expand_paths(glob.glob(abs_path)):

Diff for: git/test/test_index.py

+16-12
Original file line numberDiff line numberDiff line change
@@ -542,18 +542,22 @@ def mixed_iterator():
542542

543543
# add symlink
544544
if sys.platform != "win32":
545-
basename = "my_real_symlink"
546-
target = "/etc/that"
547-
link_file = os.path.join(rw_repo.working_tree_dir, basename)
548-
os.symlink(target, link_file)
549-
entries = index.reset(new_commit).add([link_file], fprogress=self._fprogress_add)
550-
self._assert_entries(entries)
551-
self._assert_fprogress(entries)
552-
assert len(entries) == 1 and S_ISLNK(entries[0].mode)
553-
assert S_ISLNK(index.entries[index.entry_key("my_real_symlink", 0)].mode)
554-
555-
# we expect only the target to be written
556-
assert index.repo.odb.stream(entries[0].binsha).read().decode('ascii') == target
545+
for target in ('/etc/nonexisting', '/etc/passwd', '/etc'):
546+
basename = "my_real_symlink"
547+
548+
link_file = os.path.join(rw_repo.working_tree_dir, basename)
549+
os.symlink(target, link_file)
550+
entries = index.reset(new_commit).add([link_file], fprogress=self._fprogress_add)
551+
self._assert_entries(entries)
552+
self._assert_fprogress(entries)
553+
assert len(entries) == 1 and S_ISLNK(entries[0].mode)
554+
assert S_ISLNK(index.entries[index.entry_key("my_real_symlink", 0)].mode)
555+
556+
# we expect only the target to be written
557+
assert index.repo.odb.stream(entries[0].binsha).read().decode('ascii') == target
558+
559+
os.remove(link_file)
560+
# end for each target
557561
# END real symlink test
558562

559563
# add fake symlink and assure it checks-our as symlink

0 commit comments

Comments
 (0)