diff options
-rw-r--r-- | lib/git/objects/tree.py | 8 | ||||
-rw-r--r-- | lib/git/objects/utils.py | 11 | ||||
-rw-r--r-- | test/git/test_commit.py | 4 | ||||
-rw-r--r-- | test/git/test_performance.py | 4 |
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) |