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

Skip to content

Commit 7ba46b8

Browse files
committed
Fixed issue with commit traversal due to missing visit_once in the traversal method, improved code performance by disabling the visit-once flag by default for trees, which by nature are not recursive
1 parent 2740d2c commit 7ba46b8

File tree

4 files changed

+22
-5
lines changed

4 files changed

+22
-5
lines changed

lib/git/objects/tree.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,14 @@ def blobs(self):
181181
return [ i for i in self if i.type == "blob" ]
182182

183183

184+
def traverse( self, predicate = lambda i,d: True,
185+
prune = lambda i,d: False, depth = -1, branch_first=True,
186+
visit_once = False, ignore_self=1 ):
187+
"""For documentation, see utils.Traversable.traverse
188+
189+
Trees are set to visist_once = False to gain more performance in the traversal"""
190+
return super(Tree, self).traverse(predicate, prune, depth, branch_first, visit_once, ignore_self)
191+
184192
# List protocol
185193
def __getslice__(self,i,j):
186194
return self._cache[i:j]

lib/git/objects/utils.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,14 @@ def traverse( self, predicate = lambda i,d: True,
113113
``branch_first``
114114
if True, items will be returned branch first, otherwise depth first
115115
116+
``visit_once``
117+
if True, items will only be returned once, although they might be encountered
118+
several times. Loops are prevented that way.
119+
116120
``ignore_self``
117121
if True, self will be ignored and automatically pruned from
118122
the result. Otherwise it will be the first item to be returned"""
123+
visited = set()
119124
stack = Deque()
120125
stack.append( ( 0 ,self ) ) # self is always depth level 0
121126

@@ -132,6 +137,12 @@ def addToStack( stack, lst, branch_first, dpth ):
132137
while stack:
133138
d, item = stack.pop() # depth of item, item
134139

140+
if visit_once and item in visited:
141+
continue
142+
143+
if visit_once:
144+
visited.add(item)
145+
135146
if prune( item, d ):
136147
continue
137148

test/git/test_commit.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@ def test_traversal(self):
6868
assert bfirst.next() == p10
6969

7070
# at some point, both iterations should stop
71-
assert list(dfirst)[-1] == first
7271
assert list(bfirst)[-1] == first
73-
72+
stoptraverse = self.rorepo.commit("254d04aa3180eb8b8daf7b7ff25f010cd69b4e7d").traverse()
73+
list(stoptraverse)
7474

7575
# ignore self
7676
assert start.traverse(ignore_self=False).next() == start

test/git/test_performance.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,7 @@ def test_commit_traversal(self):
4343
st = time()
4444
for c in self.rorepo.commit('0.1.6').traverse(branch_first=False):
4545
num_commits += 1
46-
#if c.message == "initial project":
47-
# raise "stop"
4846
self._query_commit_info(c)
4947
# END for each traversed commit
5048
elapsed_time = time() - st
51-
print "Traversed %i Commits in %s [s] ( %f objs/s )" % (num_commits, elapsed_time, num_commits/elapsed_time)
49+
print "Traversed %i Commits in %s [s] ( %f commits/s )" % (num_commits, elapsed_time, num_commits/elapsed_time)

0 commit comments

Comments
 (0)