diff options
-rw-r--r-- | lib/git/objects/base.py | 8 | ||||
-rw-r--r-- | lib/git/objects/tree.py | 50 | ||||
-rw-r--r-- | lib/git/objects/utils.py | 2 | ||||
-rw-r--r-- | test/git/test_base.py | 16 | ||||
-rw-r--r-- | test/git/test_index.py | 11 | ||||
-rw-r--r-- | test/git/test_tree.py | 2 |
6 files changed, 38 insertions, 51 deletions
diff --git a/lib/git/objects/base.py b/lib/git/objects/base.py index c7bf5bf2..ddd03400 100644 --- a/lib/git/objects/base.py +++ b/lib/git/objects/base.py @@ -173,6 +173,14 @@ class IndexObject(Object): if isinstance(mode, basestring): self.mode = self._mode_str_to_int(mode) + def __hash__(self): + """ + Returns + Hash of our path as index items are uniquely identifyable by path, not + by their data ! + """ + return hash(self.path) + def _set_cache_(self, attr): if attr in IndexObject.__slots__: # they cannot be retrieved lateron ( not without searching for them ) diff --git a/lib/git/objects/tree.py b/lib/git/objects/tree.py index d070c0d3..e6fa3f18 100644 --- a/lib/git/objects/tree.py +++ b/lib/git/objects/tree.py @@ -9,6 +9,7 @@ import blob import base import binascii import git.diff as diff +import utils from git.utils import join_path def sha_to_hex(sha): @@ -17,7 +18,8 @@ def sha_to_hex(sha): assert len(hexsha) == 40, "Incorrect length of sha1 string: %d" % hexsha return hexsha -class Tree(base.IndexObject, diff.Diffable): + +class Tree(base.IndexObject, diff.Diffable, utils.Traversable): """ Tress represent a ordered list of Blobs and other Trees. Hence it can be accessed like a list. @@ -48,6 +50,13 @@ class Tree(base.IndexObject, diff.Diffable): def __init__(self, repo, sha, mode=0, path=None): super(Tree, self).__init__(repo, sha, mode, path) + @classmethod + def _get_intermediate_items(cls, index_object): + if index_object.type == "tree": + return index_object._cache + return tuple() + + def _set_cache_(self, attr): if attr == "_cache": # Set the data when we need it @@ -154,46 +163,7 @@ class Tree(base.IndexObject, diff.Diffable): def __repr__(self): return '<git.Tree "%s">' % self.sha - - @classmethod - def _iter_recursive(cls, repo, tree, cur_depth, max_depth, predicate, prune ): - - for obj in tree: - if predicate(obj): - yield obj - if obj.type == "tree" and ( max_depth < 0 or cur_depth+1 <= max_depth ) and not prune(obj): - for recursive_obj in cls._iter_recursive( repo, obj, cur_depth+1, max_depth, predicate, prune ): - yield recursive_obj - # END for each recursive object - # END if we may enter recursion - # END for each object - - def traverse(self, max_depth=-1, predicate = lambda i: True, prune = lambda t: False): - """ - Returns - - Iterator to traverse the tree recursively up to the given level. - The traversal is depth-first. - The iterator returns Blob and Tree objects with paths relative to their - repository. - - ``max_depth`` - - if -1, the whole tree will be traversed - if 0, only the first level will be traversed which is the same as - the default non-recursive iterator - - ``predicate`` - - If predicate(item) returns True, item will be returned by iterator - - ``prune`` - If prune(tree) returns True, the traversal will not continue into the - given tree object. - """ - return self._iter_recursive( self.repo, self, 0, max_depth, predicate, prune ) - @property def trees(self): """ diff --git a/lib/git/objects/utils.py b/lib/git/objects/utils.py index 6c45f039..27caa083 100644 --- a/lib/git/objects/utils.py +++ b/lib/git/objects/utils.py @@ -134,7 +134,7 @@ class Traversable(object): while stack: d, item = stack.pop() # depth of item, item - + if item in visited: continue diff --git a/test/git/test_base.py b/test/git/test_base.py index 497f90fb..ab46ded4 100644 --- a/test/git/test_base.py +++ b/test/git/test_base.py @@ -16,10 +16,10 @@ import tempfile class TestBase(TestBase): - type_tuples = ( ("blob", "8741fc1d09d61f02ffd8cded15ff603eff1ec070"), - ("tree", "3a6a5e3eeed3723c09f1ef0399f81ed6b8d82e79"), - ("commit", "4251bd59fb8e11e40c40548cba38180a9536118c"), - ("tag", "e56a60e8e9cd333cfba0140a77cd12b0d9398f10") ) + type_tuples = ( ("blob", "8741fc1d09d61f02ffd8cded15ff603eff1ec070", "blob.py"), + ("tree", "3a6a5e3eeed3723c09f1ef0399f81ed6b8d82e79", "directory"), + ("commit", "4251bd59fb8e11e40c40548cba38180a9536118c", None), + ("tag", "e56a60e8e9cd333cfba0140a77cd12b0d9398f10", None) ) def test_base_object(self): # test interface of base object classes @@ -29,8 +29,12 @@ class TestBase(TestBase): s = set() num_objs = 0 num_index_objs = 0 - for obj_type, (typename, hexsha) in zip(types, self.type_tuples): - item = obj_type(self.rorepo,hexsha) + for obj_type, (typename, hexsha, path) in zip(types, self.type_tuples): + item = None + if path is None: + item = obj_type(self.rorepo,hexsha) + else: + item = obj_type(self.rorepo,hexsha, 0, path) num_objs += 1 assert item.sha == hexsha assert item.type == typename diff --git a/test/git/test_index.py b/test/git/test_index.py index e6e23ba7..2f4da161 100644 --- a/test/git/test_index.py +++ b/test/git/test_index.py @@ -83,11 +83,16 @@ class TestTree(TestBase): tree = self.rorepo.commit(tree).tree num_blobs = 0 - for blob in tree.traverse(predicate = lambda e: e.type == "blob"): + blist = list() + for blob in tree.traverse(predicate = lambda e: e.type == "blob", branch_first=False): assert (blob.path,0) in index.entries - num_blobs += 1 + blist.append(blob) # END for each blob in tree - assert num_blobs == len(index.entries) + if len(blist) != len(index.entries): + iset = set(k[0] for k in index.entries.keys()) + bset = set(b.path for b in blist) + raise AssertionError( "CMP Failed: Missing entries in index: %s, missing in tree: %s" % (bset-iset, iset-bset) ) + # END assertion message def test_index_file_from_tree(self): common_ancestor_sha = "5117c9c8a4d3af19a9958677e45cda9269de1541" diff --git a/test/git/test_tree.py b/test/git/test_tree.py index e0c1f134..2bfd9922 100644 --- a/test/git/test_tree.py +++ b/test/git/test_tree.py @@ -29,7 +29,7 @@ class TestTree(TestCase): # limit recursion level to 0 - should be same as default iteration assert all_items assert 'CHANGES' in root - assert len(list(root)) == len(list(root.traverse(max_depth=0))) + assert len(list(root)) == len(list(root.traverse(depth=1))) # only choose trees trees_only = lambda i: i.type == "tree" |