@@ -124,28 +124,57 @@ def iter_items(cls, repo, common_path = None, **kwargs):
124124 Defaults to class specific portion if None assuring that only
125125 refs suitable for the actual class are returned.
126126
127- ``kwargs``
128- Additional options given as keyword arguments, will be passed
129- to git-for-each-ref
130-
131127 Returns
132- git.Ref []
128+ git.Reference []
133129
134- List is sorted by committerdate
135- The returned objects are compatible to the Ref base, but represent the
136- actual type, such as Head or Tag
130+ List is lexigraphically sorted
131+ The returned objects represent actual subclasses, such as Head or TagReference
137132 """
138-
139- options = {'sort' : "committerdate" ,
140- 'format' : "%(refname)%00%(objectname)%00%(objecttype)%00%(objectsize)" }
141-
142133 if common_path is None :
143134 common_path = cls ._common_path_default
144135
145- options .update (kwargs )
146-
147- output = repo .git .for_each_ref (common_path , ** options )
148- return cls ._iter_from_stream (repo , iter (output .splitlines ()))
136+ rela_paths = set ()
137+
138+ # walk loose refs
139+ # Currently we do not follow links
140+ for root , dirs , files in os .walk (os .path .join (repo .path , common_path )):
141+ for f in files :
142+ abs_path = os .path .join (root , f )
143+ rela_paths .add (abs_path .replace (repo .path + '/' , "" ))
144+ # END for each file in root directory
145+ # END for each directory to walk
146+
147+ # read packed refs
148+ packed_refs_path = os .path .join (repo .path , 'packed-refs' )
149+ if os .path .isfile (packed_refs_path ):
150+ fp = open (packed_refs_path , 'r' )
151+ try :
152+ for line in fp .readlines ():
153+ if line .startswith ('#' ):
154+ continue
155+ # 439689865b9c6e2a0dad61db22a0c9855bacf597 refs/heads/hello
156+ line = line .rstrip ()
157+ first_space = line .find (' ' )
158+ if first_space == - 1 :
159+ continue
160+
161+ rela_path = line [first_space + 1 :]
162+ if rela_path .startswith (common_path ):
163+ rela_paths .add (rela_path )
164+ # END relative path matches common path
165+ # END for each line in packed-refs
166+ finally :
167+ fp .close ()
168+ # END packed refs reading
169+
170+ # return paths in sorted order
171+ for path in sorted (rela_paths ):
172+ if path .endswith ('/HEAD' ):
173+ continue
174+ # END skip remote heads
175+ yield cls .from_path (repo , path )
176+ # END for each sorted relative refpath
177+
149178
150179 @classmethod
151180 def from_path (cls , repo , path ):
@@ -167,39 +196,6 @@ def from_path(cls, repo, path):
167196 raise ValueError ("Could not find reference type suitable to handle path %r" % path )
168197
169198
170- @classmethod
171- def _iter_from_stream (cls , repo , stream ):
172- """ Parse out ref information into a list of Ref compatible objects
173- Returns git.Ref[] list of Ref objects """
174- heads = []
175-
176- for line in stream :
177- heads .append (cls ._from_string (repo , line ))
178-
179- return heads
180-
181- @classmethod
182- def _from_string (cls , repo , line ):
183- """ Create a new Ref instance from the given string.
184- Format
185- name: [a-zA-Z_/]+
186- <null byte>
187- id: [0-9A-Fa-f]{40}
188- Returns git.Head """
189- full_path , hexsha , type_name , object_size = line .split ("\x00 " )
190-
191- # No, we keep the object dynamic by allowing it to be retrieved by
192- # our path on demand - due to perstent commands it is fast.
193- # This reduces the risk that the object does not match
194- # the changed ref anymore in case it changes in the meanwhile
195- return cls .from_path (repo , full_path )
196-
197- # obj = get_object_type_by_name(type_name)(repo, hexsha)
198- # obj.size = object_size
199- # return cls(repo, full_path, obj)
200-
201-
202-
203199class SymbolicReference (object ):
204200 """
205201 Represents a special case of a reference such that this reference is symbolic.
0 commit comments