summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Thiel <byronimo@gmail.com>2009-11-26 18:16:13 +0100
committerSebastian Thiel <byronimo@gmail.com>2009-11-26 18:16:13 +0100
commitaccfe361443b3cdb8ea43ca0ccb8fbb2fa202e12 (patch)
treea7786d8ac7fa5772506d9020f0221997991f1b28
parent7ef66a66dc52dcdf44cebe435de80634e1beb268 (diff)
downloadgitpython-accfe361443b3cdb8ea43ca0ccb8fbb2fa202e12.tar.gz
tree: added traversal method, adjusted tests
Fixed critical bug in object code: IndexObjects now use their path as hashkey, not the data\!
-rw-r--r--lib/git/objects/base.py8
-rw-r--r--lib/git/objects/tree.py50
-rw-r--r--lib/git/objects/utils.py2
-rw-r--r--test/git/test_base.py16
-rw-r--r--test/git/test_index.py11
-rw-r--r--test/git/test_tree.py2
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"