Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit accfe36

Browse files
committed
tree: added traversal method, adjusted tests
Fixed critical bug in object code: IndexObjects now use their path as hashkey, not the data\!
1 parent 7ef66a6 commit accfe36

File tree

6 files changed

+38
-51
lines changed

6 files changed

+38
-51
lines changed

lib/git/objects/base.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,14 @@ def __init__(self, repo, sha, mode=None, path=None):
173173
if isinstance(mode, basestring):
174174
self.mode = self._mode_str_to_int(mode)
175175

176+
def __hash__(self):
177+
"""
178+
Returns
179+
Hash of our path as index items are uniquely identifyable by path, not
180+
by their data !
181+
"""
182+
return hash(self.path)
183+
176184
def _set_cache_(self, attr):
177185
if attr in IndexObject.__slots__:
178186
# they cannot be retrieved lateron ( not without searching for them )

lib/git/objects/tree.py

Lines changed: 10 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import base
1010
import binascii
1111
import git.diff as diff
12+
import utils
1213
from git.utils import join_path
1314

1415
def sha_to_hex(sha):
@@ -17,7 +18,8 @@ def sha_to_hex(sha):
1718
assert len(hexsha) == 40, "Incorrect length of sha1 string: %d" % hexsha
1819
return hexsha
1920

20-
class Tree(base.IndexObject, diff.Diffable):
21+
22+
class Tree(base.IndexObject, diff.Diffable, utils.Traversable):
2123
"""
2224
Tress represent a ordered list of Blobs and other Trees. Hence it can be
2325
accessed like a list.
@@ -48,6 +50,13 @@ class Tree(base.IndexObject, diff.Diffable):
4850
def __init__(self, repo, sha, mode=0, path=None):
4951
super(Tree, self).__init__(repo, sha, mode, path)
5052

53+
@classmethod
54+
def _get_intermediate_items(cls, index_object):
55+
if index_object.type == "tree":
56+
return index_object._cache
57+
return tuple()
58+
59+
5160
def _set_cache_(self, attr):
5261
if attr == "_cache":
5362
# Set the data when we need it
@@ -154,46 +163,7 @@ def __div__(self, file):
154163

155164
def __repr__(self):
156165
return '<git.Tree "%s">' % self.sha
157-
158-
@classmethod
159-
def _iter_recursive(cls, repo, tree, cur_depth, max_depth, predicate, prune ):
160-
161-
for obj in tree:
162-
if predicate(obj):
163-
yield obj
164-
if obj.type == "tree" and ( max_depth < 0 or cur_depth+1 <= max_depth ) and not prune(obj):
165-
for recursive_obj in cls._iter_recursive( repo, obj, cur_depth+1, max_depth, predicate, prune ):
166-
yield recursive_obj
167-
# END for each recursive object
168-
# END if we may enter recursion
169-
# END for each object
170-
171-
def traverse(self, max_depth=-1, predicate = lambda i: True, prune = lambda t: False):
172-
"""
173-
Returns
174-
175-
Iterator to traverse the tree recursively up to the given level.
176-
The traversal is depth-first.
177-
The iterator returns Blob and Tree objects with paths relative to their
178-
repository.
179-
180-
``max_depth``
181-
182-
if -1, the whole tree will be traversed
183-
if 0, only the first level will be traversed which is the same as
184-
the default non-recursive iterator
185-
186-
``predicate``
187-
188-
If predicate(item) returns True, item will be returned by iterator
189-
190-
``prune``
191166

192-
If prune(tree) returns True, the traversal will not continue into the
193-
given tree object.
194-
"""
195-
return self._iter_recursive( self.repo, self, 0, max_depth, predicate, prune )
196-
197167
@property
198168
def trees(self):
199169
"""

lib/git/objects/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ def addToStack( stack, lst, branch_first, dpth ):
134134

135135
while stack:
136136
d, item = stack.pop() # depth of item, item
137-
137+
138138
if item in visited:
139139
continue
140140

test/git/test_base.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@
1616

1717
class TestBase(TestBase):
1818

19-
type_tuples = ( ("blob", "8741fc1d09d61f02ffd8cded15ff603eff1ec070"),
20-
("tree", "3a6a5e3eeed3723c09f1ef0399f81ed6b8d82e79"),
21-
("commit", "4251bd59fb8e11e40c40548cba38180a9536118c"),
22-
("tag", "e56a60e8e9cd333cfba0140a77cd12b0d9398f10") )
19+
type_tuples = ( ("blob", "8741fc1d09d61f02ffd8cded15ff603eff1ec070", "blob.py"),
20+
("tree", "3a6a5e3eeed3723c09f1ef0399f81ed6b8d82e79", "directory"),
21+
("commit", "4251bd59fb8e11e40c40548cba38180a9536118c", None),
22+
("tag", "e56a60e8e9cd333cfba0140a77cd12b0d9398f10", None) )
2323

2424
def test_base_object(self):
2525
# test interface of base object classes
@@ -29,8 +29,12 @@ def test_base_object(self):
2929
s = set()
3030
num_objs = 0
3131
num_index_objs = 0
32-
for obj_type, (typename, hexsha) in zip(types, self.type_tuples):
33-
item = obj_type(self.rorepo,hexsha)
32+
for obj_type, (typename, hexsha, path) in zip(types, self.type_tuples):
33+
item = None
34+
if path is None:
35+
item = obj_type(self.rorepo,hexsha)
36+
else:
37+
item = obj_type(self.rorepo,hexsha, 0, path)
3438
num_objs += 1
3539
assert item.sha == hexsha
3640
assert item.type == typename

test/git/test_index.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,16 @@ def _cmp_tree_index(self, tree, index):
8383
tree = self.rorepo.commit(tree).tree
8484

8585
num_blobs = 0
86-
for blob in tree.traverse(predicate = lambda e: e.type == "blob"):
86+
blist = list()
87+
for blob in tree.traverse(predicate = lambda e: e.type == "blob", branch_first=False):
8788
assert (blob.path,0) in index.entries
88-
num_blobs += 1
89+
blist.append(blob)
8990
# END for each blob in tree
90-
assert num_blobs == len(index.entries)
91+
if len(blist) != len(index.entries):
92+
iset = set(k[0] for k in index.entries.keys())
93+
bset = set(b.path for b in blist)
94+
raise AssertionError( "CMP Failed: Missing entries in index: %s, missing in tree: %s" % (bset-iset, iset-bset) )
95+
# END assertion message
9196

9297
def test_index_file_from_tree(self):
9398
common_ancestor_sha = "5117c9c8a4d3af19a9958677e45cda9269de1541"

test/git/test_tree.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def test_traverse(self):
2929
# limit recursion level to 0 - should be same as default iteration
3030
assert all_items
3131
assert 'CHANGES' in root
32-
assert len(list(root)) == len(list(root.traverse(max_depth=0)))
32+
assert len(list(root)) == len(list(root.traverse(depth=1)))
3333

3434
# only choose trees
3535
trees_only = lambda i: i.type == "tree"

0 commit comments

Comments
 (0)