Skip to content

Commit e40b5f0

Browse files
committed
index.write_tree: fixed bug that would cause the written tree not to contain any of our changes entries as it would in fact write a possibly cached tree stored in our extension data.It was solved by simply ignoring that extension data when writing the index for tree creation. A test was added for this as well
1 parent c5f92b1 commit e40b5f0

File tree

3 files changed

+25
-2
lines changed

3 files changed

+25
-2
lines changed

lib/git/diff.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ def diff(self, other=Index, paths=None, create_patch=False, **kwargs):
3939
``other``
4040
Is the item to compare us with.
4141
If None, we will be compared to the working tree.
42+
If Treeish, it will be compared against the respective tree
4243
If Index ( type ), it will be compared against the index.
4344
It defaults to Index to assure the method will not by-default fail
4445
on bare repositories.

lib/git/index.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ def from_base(cls, base):
191191
Instance of type BaseIndexEntry
192192
"""
193193
time = struct.pack(">LL", 0, 0)
194-
return IndexEntry((base.mode, base.sha, base.stage, base.path, time, time, 1, 1, 1, 1, 0))
194+
return IndexEntry((base.mode, base.sha, base.stage, base.path, time, time, 0, 0, 0, 0, 0))
195195

196196
@classmethod
197197
def from_blob(cls, blob):
@@ -352,6 +352,10 @@ def _read_from_stream(self, stream):
352352

353353
# the footer contains extension data and a sha on the content so far
354354
# Keep the extension footer,and verify we have a sha in the end
355+
# Extension data format is:
356+
# 4 bytes ID
357+
# 4 bytes length of chunk
358+
# repeated 0 - N times
355359
self._extension_data = stream.read(~0)
356360
assert len(self._extension_data) > 19, "Index Footer was not at least a sha on content as it was only %i bytes in size" % len(self._extension_data)
357361

@@ -733,9 +737,23 @@ def write_tree(self, missing_ok=False):
733737
index_path = self._index_path()
734738
tmp_index_mover = _TemporaryFileSwap(index_path)
735739

740+
# IMPORTANT: If we have TREE extension data, it will actually
741+
# ignore the index and write the stored tree instead. Hence we
742+
# temporarily forget about it, and in fact I don't know what git
743+
# uses it for
744+
stored_ext_data = None
745+
if self._extension_data and self._extension_data[:4] == 'TREE':
746+
stored_ext_data = self._extension_data
747+
self._extension_data = ''
748+
# END extension data special handling
749+
736750
self.write(index_path)
737751
tree_sha = self.repo.git.write_tree(missing_ok=missing_ok)
738752

753+
if stored_ext_data:
754+
self._extension_data = stored_ext_data
755+
# END reset stored exstension data
756+
739757
return Tree(self.repo, tree_sha, 0, '')
740758

741759
def _process_diff_args(self, args):

test/git/test_index.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import shutil
1515
from stat import *
1616

17-
1817
class TestTree(TestBase):
1918

2019
def __init__(self, *args):
@@ -464,13 +463,18 @@ def mixed_iterator():
464463
full_index_entry = IndexEntry.from_base(BaseIndexEntry((0120000, entries[0].sha, 0, entries[0].path)))
465464
entry_key = index.get_entries_key(full_index_entry)
466465
index.reset(new_commit)
466+
467467
assert entry_key not in index.entries
468468
index.entries[entry_key] = full_index_entry
469469
index.write()
470470
index.update() # force reread of entries
471471
new_entry = index.entries[entry_key]
472472
assert S_ISLNK(new_entry.mode)
473473

474+
# a tree created from this should contain the symlink
475+
tree = index.write_tree(True)
476+
assert fake_symlink_relapath in tree
477+
474478
# checkout the fakelink, should be a link then
475479
assert not S_ISLNK(os.stat(fake_symlink_path)[ST_MODE])
476480
os.remove(fake_symlink_path)

0 commit comments

Comments
 (0)