6
6
7
7
import re
8
8
import time
9
-
9
+ from git . utils import Iterable
10
10
from git .actor import Actor
11
- from tree import Tree
12
11
import git .diff as diff
13
12
import git .stats as stats
13
+ from tree import Tree
14
14
import base
15
15
16
- class Commit (base .Object ):
16
+ class Commit (base .Object , Iterable ):
17
17
"""
18
18
Wraps a git Commit object.
19
19
@@ -81,7 +81,7 @@ def _set_cache_(self, attr):
81
81
We set all values at once.
82
82
"""
83
83
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 ]
85
85
self .parents = temp .parents
86
86
self .tree = temp .tree
87
87
self .author = temp .author
@@ -120,15 +120,15 @@ def count(cls, repo, ref, path=''):
120
120
return len (repo .git .rev_list (ref , '--' , path ).strip ().splitlines ())
121
121
122
122
@classmethod
123
- def find_all (cls , repo , ref , path = '' , ** kwargs ):
123
+ def iter_items (cls , repo , ref , path = '' , ** kwargs ):
124
124
"""
125
125
Find all commits matching the given criteria.
126
126
127
127
``repo``
128
128
is the Repo
129
129
130
130
``ref``
131
- is the ref from which to begin (SHA1 or name)
131
+ is the ref from which to begin (SHA1, Head or name)
132
132
133
133
``path``
134
134
is an optinal path, if set only Commits that include the path
@@ -146,49 +146,56 @@ def find_all(cls, repo, ref, path='', **kwargs):
146
146
options .update (kwargs )
147
147
148
148
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 )) )
150
150
151
151
@classmethod
152
- def _list_from_string (cls , repo , text ):
152
+ def _iter_from_stream (cls , repo , stream ):
153
153
"""
154
154
Parse out commit information into a list of Commit objects
155
155
156
156
``repo``
157
157
is the Repo
158
158
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)
161
161
162
162
Returns
163
- git. Commit[]
163
+ iterator returning Commit objects
164
164
"""
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 ]
171
169
172
170
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 ())
178
182
179
- # free line
180
- lines . pop ( 0 )
183
+ # empty line
184
+ stream . next ( )
181
185
182
186
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 ())
185
193
# 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
192
199
193
200
@classmethod
194
201
def diff (cls , repo , a , b = None , paths = None ):
0 commit comments