Skip to content

Commit 6acec35

Browse files
committed
renamed find_all to list_all, changed commit to use iterable interface in preparation for command changes
1 parent f4fa1cb commit 6acec35

File tree

6 files changed

+70
-54
lines changed

6 files changed

+70
-54
lines changed

Diff for: CHANGES

+11-3
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@
22
CHANGES
33
=======
44

5-
0.1.X
5+
0.2
66
=====
7-
( Future Release )
87
General
98
-------
109
* file mode in Tree, Blob and Diff objects now is an int compatible to definintiions
@@ -19,7 +18,16 @@ General
1918
* from_string and list_from_string methods are now private and were renamed to
2019
_from_string and _list_from_string respectively. As part of the private API, they
2120
may change without prior notice.
22-
21+
* Renamed all find_all methods to list_items - this method is part of the Iterable interface
22+
that also provides a more efficients and more responsive iter_items method
23+
24+
Item Iteration
25+
--------------
26+
* Previously one would return and process multiple items as list only which can
27+
hurt performance and memory consumption and reduce response times.
28+
iter_items method provide an iterator that will return items on demand as parsed
29+
from a stream. This way any amount of objects can be handled.
30+
2331
objects Package
2432
----------------
2533
* blob, tree, tag and commit module have been moved to new objects package. This should

Diff for: lib/git/objects/commit.py

+39-32
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@
66

77
import re
88
import time
9-
9+
from git.utils import Iterable
1010
from git.actor import Actor
11-
from tree import Tree
1211
import git.diff as diff
1312
import git.stats as stats
13+
from tree import Tree
1414
import base
1515

16-
class Commit(base.Object):
16+
class Commit(base.Object, Iterable):
1717
"""
1818
Wraps a git Commit object.
1919
@@ -81,7 +81,7 @@ def _set_cache_(self, attr):
8181
We set all values at once.
8282
"""
8383
if attr in self.__slots__:
84-
temp = Commit.find_all(self.repo, self.id, max_count=1)[0]
84+
temp = Commit.list_items(self.repo, self.id, max_count=1)[0]
8585
self.parents = temp.parents
8686
self.tree = temp.tree
8787
self.author = temp.author
@@ -120,15 +120,15 @@ def count(cls, repo, ref, path=''):
120120
return len(repo.git.rev_list(ref, '--', path).strip().splitlines())
121121

122122
@classmethod
123-
def find_all(cls, repo, ref, path='', **kwargs):
123+
def iter_items(cls, repo, ref, path='', **kwargs):
124124
"""
125125
Find all commits matching the given criteria.
126126
127127
``repo``
128128
is the Repo
129129
130130
``ref``
131-
is the ref from which to begin (SHA1 or name)
131+
is the ref from which to begin (SHA1, Head or name)
132132
133133
``path``
134134
is an optinal path, if set only Commits that include the path
@@ -146,49 +146,56 @@ def find_all(cls, repo, ref, path='', **kwargs):
146146
options.update(kwargs)
147147

148148
output = repo.git.rev_list(ref, '--', path, **options)
149-
return cls._list_from_string(repo, output)
149+
return cls._iter_from_stream(repo, iter(output.splitlines(False)))
150150

151151
@classmethod
152-
def _list_from_string(cls, repo, text):
152+
def _iter_from_stream(cls, repo, stream):
153153
"""
154154
Parse out commit information into a list of Commit objects
155155
156156
``repo``
157157
is the Repo
158158
159-
``text``
160-
is the text output from the git-rev-list command (raw format)
159+
``stream``
160+
output stream from the git-rev-list command (raw format)
161161
162162
Returns
163-
git.Commit[]
163+
iterator returning Commit objects
164164
"""
165-
lines =text.splitlines(False)
166-
commits = []
167-
168-
while lines:
169-
id = lines.pop(0).split()[1]
170-
tree = lines.pop(0).split()[1]
165+
for line in stream:
166+
id = line.split()[1]
167+
assert line.split()[0] == "commit"
168+
tree = stream.next().split()[1]
171169

172170
parents = []
173-
while lines and lines[0].startswith('parent'):
174-
parents.append(lines.pop(0).split()[-1])
175-
# END while there are parent lines
176-
author, authored_date = cls._actor(lines.pop(0))
177-
committer, committed_date = cls._actor(lines.pop(0))
171+
next_line = None
172+
for parent_line in stream:
173+
if not parent_line.startswith('parent'):
174+
next_line = parent_line
175+
break
176+
# END abort reading parents
177+
parents.append(parent_line.split()[-1])
178+
# END for each parent line
179+
180+
author, authored_date = cls._actor(next_line)
181+
committer, committed_date = cls._actor(stream.next())
178182

179-
# free line
180-
lines.pop(0)
183+
# empty line
184+
stream.next()
181185

182186
message_lines = []
183-
while lines and not lines[0].startswith('commit'):
184-
message_lines.append(lines.pop(0).strip())
187+
next_line = None
188+
for msg_line in stream:
189+
if not msg_line.startswith(' '):
190+
break
191+
# END abort message reading
192+
message_lines.append(msg_line.strip())
185193
# END while there are message lines
186-
message = '\n'.join(message_lines[:-1]) # last line is empty
187-
188-
commits.append(Commit(repo, id=id, parents=parents, tree=tree, author=author, authored_date=authored_date,
189-
committer=committer, committed_date=committed_date, message=message))
190-
# END while lines
191-
return commits
194+
message = '\n'.join(message_lines)
195+
196+
yield Commit(repo, id=id, parents=parents, tree=tree, author=author, authored_date=authored_date,
197+
committer=committer, committed_date=committed_date, message=message)
198+
# END for each line in stream
192199

193200
@classmethod
194201
def diff(cls, repo, a, b=None, paths=None):

Diff for: lib/git/refs.py

+8-8
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ def name(self):
7373
return '/'.join(tokens[2:])
7474

7575
@classmethod
76-
def find_all(cls, repo, common_path = "refs", **kwargs):
76+
def list_items(cls, repo, common_path = "refs", **kwargs):
7777
"""
7878
Find all refs in the repository
7979
@@ -158,14 +158,14 @@ def commit(self):
158158
return self.object
159159

160160
@classmethod
161-
def find_all(cls, repo, common_path = "refs/heads", **kwargs):
161+
def list_items(cls, repo, common_path = "refs/heads", **kwargs):
162162
"""
163163
Returns
164164
git.Head[]
165165
166-
For more documentation, please refer to git.base.Ref.find_all
166+
For more documentation, please refer to git.base.Ref.list_items
167167
"""
168-
return super(Head,cls).find_all(repo, common_path, **kwargs)
168+
return super(Head,cls).list_items(repo, common_path, **kwargs)
169169

170170
def __repr__(self):
171171
return '<git.Head "%s">' % self.name
@@ -181,7 +181,7 @@ class TagRef(Ref):
181181
This tag object will always point to a commit object, but may carray additional
182182
information in a tag object::
183183
184-
tagref = TagRef.find_all(repo)[0]
184+
tagref = TagRef.list_items(repo)[0]
185185
print tagref.commit.message
186186
if tagref.tag is not None:
187187
print tagref.tag.message
@@ -215,14 +215,14 @@ def tag(self):
215215
return None
216216

217217
@classmethod
218-
def find_all(cls, repo, common_path = "refs/tags", **kwargs):
218+
def list_items(cls, repo, common_path = "refs/tags", **kwargs):
219219
"""
220220
Returns
221221
git.Tag[]
222222
223-
For more documentation, please refer to git.base.Ref.find_all
223+
For more documentation, please refer to git.base.Ref.list_items
224224
"""
225-
return super(TagRef,cls).find_all(repo, common_path, **kwargs)
225+
return super(TagRef,cls).list_items(repo, common_path, **kwargs)
226226

227227

228228
# provide an alias

Diff for: lib/git/repo.py

+9-8
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ def heads(self):
102102
Returns
103103
``git.Head[]``
104104
"""
105-
return Head.find_all(self)
105+
return Head.list_items(self)
106106

107107
# alias heads
108108
branches = heads
@@ -115,7 +115,7 @@ def tags(self):
115115
Returns
116116
``git.Tag[]``
117117
"""
118-
return Tag.find_all(self)
118+
return Tag.list_items(self)
119119

120120
def blame(self, commit, file):
121121
"""
@@ -221,7 +221,7 @@ def commits(self, start='master', path='', max_count=10, skip=0):
221221
options = {'max_count': max_count,
222222
'skip': skip}
223223

224-
return Commit.find_all(self, start, path, **options)
224+
return Commit.list_items(self, start, path, **options)
225225

226226
def commits_between(self, frm, to):
227227
"""
@@ -237,7 +237,7 @@ def commits_between(self, frm, to):
237237
Returns
238238
``git.Commit[]``
239239
"""
240-
return reversed(Commit.find_all(self, "%s..%s" % (frm, to)))
240+
return reversed(Commit.list_items(self, "%s..%s" % (frm, to)))
241241

242242
def commits_since(self, start='master', path='', since='1970-01-01'):
243243
"""
@@ -259,7 +259,7 @@ def commits_since(self, start='master', path='', since='1970-01-01'):
259259
"""
260260
options = {'since': since}
261261

262-
return Commit.find_all(self, start, path, **options)
262+
return Commit.list_items(self, start, path, **options)
263263

264264
def commit_count(self, start='master', path=''):
265265
"""
@@ -296,7 +296,7 @@ def commit(self, id=None, path = ''):
296296
id = self.active_branch
297297
options = {'max_count': 1}
298298

299-
commits = Commit.find_all(self, id, path, **options)
299+
commits = Commit.list_items(self, id, path, **options)
300300

301301
if not commits:
302302
raise ValueError, "Invalid identifier %s, or given path '%s' too restrictive" % ( id, path )
@@ -313,7 +313,7 @@ def commit_deltas_from(self, other_repo, ref='master', other_ref='master'):
313313
other_repo_refs = other_repo.git.rev_list(other_ref, '--').strip().splitlines()
314314

315315
diff_refs = list(set(other_repo_refs) - set(repo_refs))
316-
return map(lambda ref: Commit.find_all(other_repo, ref, max_count=1)[0], diff_refs)
316+
return map(lambda ref: Commit.list_items(other_repo, ref, max_count=1)[0], diff_refs)
317317

318318
def tree(self, treeish=None):
319319
"""
@@ -364,7 +364,8 @@ def log(self, commit='master', path=None, **kwargs):
364364
if path:
365365
arg.append(path)
366366
commits = self.git.log(*arg, **options)
367-
return Commit._list_from_string(self, commits)
367+
print commits.splitlines(False)
368+
return list(Commit._iter_from_stream(self, iter(commits.splitlines())))
368369

369370
def diff(self, a, b, *paths):
370371
"""

Diff for: lib/git/utils.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,13 @@ def list_items(cls, repo, *args, **kwargs):
7575
Returns:
7676
list(Item,...) list of item instances
7777
"""
78-
return list(cls.iter_items, repo, *args, **kwargs)
78+
return list(cls.iter_items(repo, *args, **kwargs))
7979

8080

8181
@classmethod
8282
def iter_items(cls, repo, *args, **kwargs):
8383
"""
84-
For more information about the arguments, see find_all
84+
For more information about the arguments, see list_items
8585
Return:
8686
iterator yielding Items
8787
"""

Diff for: test/git/test_commit.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ def test_rev_list_bisect_all(self, git):
216216
bisect_all=True)
217217
assert_true(git.called)
218218

219-
commits = Commit._list_from_string(self.repo, revs)
219+
commits = Commit._iter_from_stream(self.repo, iter(revs.splitlines(False)))
220220
expected_ids = (
221221
'cf37099ea8d1d8c7fbf9b6d12d7ec0249d3acb8b',
222222
'33ebe7acec14b25c5f84f35a664803fcab2f7781',

0 commit comments

Comments
 (0)