summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/git/objects/tree.py8
-rw-r--r--lib/git/objects/utils.py11
-rw-r--r--test/git/test_commit.py4
-rw-r--r--test/git/test_performance.py4
4 files changed, 22 insertions, 5 deletions
diff --git a/lib/git/objects/tree.py b/lib/git/objects/tree.py
index e6fa3f18..c80450fc 100644
--- a/lib/git/objects/tree.py
+++ b/lib/git/objects/tree.py
@@ -181,6 +181,14 @@ class Tree(base.IndexObject, diff.Diffable, utils.Traversable):
return [ i for i in self if i.type == "blob" ]
+ def traverse( self, predicate = lambda i,d: True,
+ prune = lambda i,d: False, depth = -1, branch_first=True,
+ visit_once = False, ignore_self=1 ):
+ """For documentation, see utils.Traversable.traverse
+
+ Trees are set to visist_once = False to gain more performance in the traversal"""
+ return super(Tree, self).traverse(predicate, prune, depth, branch_first, visit_once, ignore_self)
+
# List protocol
def __getslice__(self,i,j):
return self._cache[i:j]
diff --git a/lib/git/objects/utils.py b/lib/git/objects/utils.py
index a3c6edc7..a9c25da2 100644
--- a/lib/git/objects/utils.py
+++ b/lib/git/objects/utils.py
@@ -113,9 +113,14 @@ class Traversable(object):
``branch_first``
if True, items will be returned branch first, otherwise depth first
+ ``visit_once``
+ if True, items will only be returned once, although they might be encountered
+ several times. Loops are prevented that way.
+
``ignore_self``
if True, self will be ignored and automatically pruned from
the result. Otherwise it will be the first item to be returned"""
+ visited = set()
stack = Deque()
stack.append( ( 0 ,self ) ) # self is always depth level 0
@@ -132,6 +137,12 @@ class Traversable(object):
while stack:
d, item = stack.pop() # depth of item, item
+ if visit_once and item in visited:
+ continue
+
+ if visit_once:
+ visited.add(item)
+
if prune( item, d ):
continue
diff --git a/test/git/test_commit.py b/test/git/test_commit.py
index bb2b22ee..e757e148 100644
--- a/test/git/test_commit.py
+++ b/test/git/test_commit.py
@@ -68,9 +68,9 @@ class TestCommit(TestBase):
assert bfirst.next() == p10
# at some point, both iterations should stop
- assert list(dfirst)[-1] == first
assert list(bfirst)[-1] == first
-
+ stoptraverse = self.rorepo.commit("254d04aa3180eb8b8daf7b7ff25f010cd69b4e7d").traverse()
+ list(stoptraverse)
# ignore self
assert start.traverse(ignore_self=False).next() == start
diff --git a/test/git/test_performance.py b/test/git/test_performance.py
index 5081bce8..e1dfc42c 100644
--- a/test/git/test_performance.py
+++ b/test/git/test_performance.py
@@ -43,9 +43,7 @@ class TestPerformance(TestBase):
st = time()
for c in self.rorepo.commit('0.1.6').traverse(branch_first=False):
num_commits += 1
- #if c.message == "initial project":
- # raise "stop"
self._query_commit_info(c)
# END for each traversed commit
elapsed_time = time() - st
- print "Traversed %i Commits in %s [s] ( %f objs/s )" % (num_commits, elapsed_time, num_commits/elapsed_time)
+ print "Traversed %i Commits in %s [s] ( %f commits/s )" % (num_commits, elapsed_time, num_commits/elapsed_time)