66
77import re
88import time
9-
9+ from git . utils import Iterable
1010from git .actor import Actor
11- from tree import Tree
1211import git .diff as diff
1312import git .stats as stats
13+ from tree import Tree
1414import 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 ):
0 commit comments