Skip to content

Commit d2d9197

Browse files
committed
Tree-Writing now works after fixing an off-by-one error
1 parent 69dd875 commit d2d9197

File tree

4 files changed

+42
-20
lines changed

4 files changed

+42
-20
lines changed

lib/git/index/base.py

+11-10
Original file line numberDiff line numberDiff line change
@@ -889,40 +889,41 @@ def _flush_stdin_and_wait(cls, proc, ignore_stdout = False):
889889

890890
@default_index
891891
def checkout(self, paths=None, force=False, fprogress=lambda *args: None, **kwargs):
892-
"""
893-
Checkout the given paths or all files from the version known to the index into
892+
"""Checkout the given paths or all files from the version known to the index into
894893
the working tree.
894+
895+
:note: Be sure you have written pending changes using the ``write`` method
896+
in case you have altered the enties dictionary directly
895897
896-
``paths``
898+
:param paths:
897899
If None, all paths in the index will be checked out. Otherwise an iterable
898900
of relative or absolute paths or a single path pointing to files or directories
899901
in the index is expected.
900902
901-
``force``
903+
:param force:
902904
If True, existing files will be overwritten even if they contain local modifications.
903905
If False, these will trigger a CheckoutError.
904906
905-
``fprogress``
907+
:param fprogress:
906908
see Index.add_ for signature and explanation.
907909
The provided progress information will contain None as path and item if no
908910
explicit paths are given. Otherwise progress information will be send
909911
prior and after a file has been checked out
910912
911-
``**kwargs``
913+
:param **kwargs:
912914
Additional arguments to be pasesd to git-checkout-index
913915
914-
Returns
916+
:return:
915917
iterable yielding paths to files which have been checked out and are
916918
guaranteed to match the version stored in the index
917919
918-
Raise CheckoutError
920+
:raise CheckoutError:
919921
If at least one file failed to be checked out. This is a summary,
920922
hence it will checkout as many files as it can anyway.
921923
If one of files or directories do not exist in the index
922924
( as opposed to the original git command who ignores them ).
923925
Raise GitCommandError if error lines could not be parsed - this truly is
924-
an exceptional state
925-
"""
926+
an exceptional state"""
926927
args = ["--index"]
927928
if force:
928929
args.append("--force")

lib/git/index/fun.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -168,11 +168,11 @@ def write_tree_from_cache(entries, odb, sl, si=0):
168168
xi = ci
169169
while xi < end:
170170
oentry = entries[xi]
171-
xi += 1
172-
orbound = oentry.path.find('/')
171+
orbound = oentry.path.find('/', si)
173172
if orbound == -1 or oentry.path[si:orbound] != base:
174173
break
175174
# END abort on base mismatch
175+
xi += 1
176176
# END find common base
177177

178178
# enter recursion

test/git/test_index.py

+24-7
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
from test.testlib import *
88
from git import *
9+
from git.index.util import TemporaryFileSwap
910
import inspect
1011
import os
1112
import sys
@@ -94,23 +95,24 @@ def _cmp_tree_index(self, tree, index):
9495
raise AssertionError( "CMP Failed: Missing entries in index: %s, missing in tree: %s" % (bset-iset, iset-bset) )
9596
# END assertion message
9697

97-
def test_index_file_from_tree(self):
98+
@with_rw_repo('0.1.6')
99+
def test_index_file_from_tree(self, rw_repo):
98100
common_ancestor_sha = "5117c9c8a4d3af19a9958677e45cda9269de1541"
99101
cur_sha = "4b43ca7ff72d5f535134241e7c797ddc9c7a3573"
100102
other_sha = "39f85c4358b7346fee22169da9cad93901ea9eb9"
101103

102104
# simple index from tree
103-
base_index = IndexFile.from_tree(self.rorepo, common_ancestor_sha)
105+
base_index = IndexFile.from_tree(rw_repo, common_ancestor_sha)
104106
assert base_index.entries
105107
self._cmp_tree_index(common_ancestor_sha, base_index)
106108

107109
# merge two trees - its like a fast-forward
108-
two_way_index = IndexFile.from_tree(self.rorepo, common_ancestor_sha, cur_sha)
110+
two_way_index = IndexFile.from_tree(rw_repo, common_ancestor_sha, cur_sha)
109111
assert two_way_index.entries
110112
self._cmp_tree_index(cur_sha, two_way_index)
111113

112114
# merge three trees - here we have a merge conflict
113-
three_way_index = IndexFile.from_tree(self.rorepo, common_ancestor_sha, cur_sha, other_sha)
115+
three_way_index = IndexFile.from_tree(rw_repo, common_ancestor_sha, cur_sha, other_sha)
114116
assert len(list(e for e in three_way_index.entries.values() if e.stage != 0))
115117

116118

@@ -476,7 +478,7 @@ def mixed_iterator():
476478
fake_symlink_relapath = "my_fake_symlink"
477479
link_target = "/etc/that"
478480
fake_symlink_path = self._make_file(fake_symlink_relapath, link_target, rw_repo)
479-
fake_entry = BaseIndexEntry((0120000, null_hex_sha, 0, fake_symlink_relapath))
481+
fake_entry = BaseIndexEntry((0120000, null_bin_sha, 0, fake_symlink_relapath))
480482
entries = index.reset(new_commit).add([fake_entry], fprogress=self._fprogress_add)
481483
self._assert_fprogress(entries)
482484
assert entries[0].hexsha != null_hex_sha
@@ -497,6 +499,7 @@ def mixed_iterator():
497499
# a tree created from this should contain the symlink
498500
tree = index.write_tree()
499501
assert fake_symlink_relapath in tree
502+
index.write() # flush our changes for the checkout
500503

501504
# checkout the fakelink, should be a link then
502505
assert not S_ISLNK(os.stat(fake_symlink_path)[ST_MODE])
@@ -569,5 +572,19 @@ def make_paths():
569572
for filenum in range(len(paths)):
570573
assert index.entry_key(str(filenum), 0) in index.entries
571574

572-
def test_compare_write_tree(self):
573-
self.fail("compare git-write-tree with python implementation, must have same output")
575+
@with_rw_repo('HEAD')
576+
def test_compare_write_tree(self, rw_repo):
577+
def write_tree(index):
578+
tree_sha = index.repo.git.write_tree(missing_ok=True)
579+
return Tree(index.repo, tree_sha, 0, '')
580+
# END git cmd write tree
581+
582+
# write all trees and compare them
583+
for commit in rw_repo.head.commit.traverse():
584+
index = rw_repo.index.reset(commit)
585+
orig_tree = commit.tree
586+
new_git_tree = write_tree(index)
587+
assert new_git_tree == orig_tree
588+
assert index.write_tree() == orig_tree
589+
# END for each commit
590+

test/testlib/helper.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
66

77
import os
8+
import sys
89
from git import Repo, Remote, GitCommandError
910
from unittest import TestCase
1011
import tempfile
@@ -105,7 +106,10 @@ def repo_creator(self):
105106
os.chdir(rw_repo.working_dir)
106107
try:
107108
return func(self, rw_repo)
108-
finally:
109+
except:
110+
print >> sys.stderr, "Keeping repo after failure: %s" % repo_dir
111+
raise
112+
else:
109113
os.chdir(prev_cwd)
110114
rw_repo.git.clear_cache()
111115
shutil.rmtree(repo_dir, onerror=_rmtree_onerror)

0 commit comments

Comments
 (0)