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

Skip to content

Commit 0d638bf

Browse files
committed
Initially put SymbolicRef as base class of Reference, which theoretically is how it should be, but many tests are still failing as the implementation is not yet there
1 parent aaeb986 commit 0d638bf

File tree

1 file changed

+161
-185
lines changed

1 file changed

+161
-185
lines changed

lib/git/refs.py

Lines changed: 161 additions & 185 deletions
Original file line numberDiff line numberDiff line change
@@ -10,192 +10,8 @@
1010
from objects.utils import get_object_type_by_name
1111
from utils import LazyMixin, Iterable, join_path, join_path_native, to_native_path_linux
1212

13-
class Reference(LazyMixin, Iterable):
14-
"""
15-
Represents a named reference to any object. Subclasses may apply restrictions though,
16-
i.e. Heads can only point to commits.
17-
"""
18-
__slots__ = ("repo", "path")
19-
_common_path_default = "refs"
20-
_id_attribute_ = "name"
21-
22-
def __init__(self, repo, path):
23-
"""
24-
Initialize this instance
25-
``repo``
26-
Our parent repository
27-
28-
``path``
29-
Path relative to the .git/ directory pointing to the ref in question, i.e.
30-
refs/heads/master
31-
32-
"""
33-
if not path.startswith(self._common_path_default):
34-
raise ValueError("Cannot instantiate %s from path %s" % ( self.__class__.__name__, path ))
35-
36-
self.repo = repo
37-
self.path = path
38-
39-
def __str__(self):
40-
return self.name
41-
42-
def __repr__(self):
43-
return '<git.%s "%s">' % (self.__class__.__name__, self.path)
44-
45-
def __eq__(self, other):
46-
return self.path == other.path
47-
48-
def __ne__(self, other):
49-
return not ( self == other )
50-
51-
def __hash__(self):
52-
return hash(self.path)
53-
54-
@property
55-
def name(self):
56-
"""
57-
Returns
58-
(shortest) Name of this reference - it may contain path components
59-
"""
60-
# first two path tokens are can be removed as they are
61-
# refs/heads or refs/tags or refs/remotes
62-
tokens = self.path.split('/')
63-
if len(tokens) < 3:
64-
return self.path # could be refs/HEAD
65-
66-
return '/'.join(tokens[2:])
67-
68-
def _get_object(self):
69-
"""
70-
Returns
71-
The object our ref currently refers to. Refs can be cached, they will
72-
always point to the actual object as it gets re-created on each query
73-
"""
74-
# have to be dynamic here as we may be a tag which can point to anything
75-
# Our path will be resolved to the hexsha which will be used accordingly
76-
return Object.new(self.repo, self.path)
77-
78-
def _set_object(self, ref):
79-
"""
80-
Set our reference to point to the given ref. It will be converted
81-
to a specific hexsha.
82-
83-
Note:
84-
TypeChecking is done by the git command
85-
"""
86-
# do it safely by specifying the old value
87-
self.repo.git.update_ref(self.path, ref, self._get_object().sha)
88-
89-
object = property(_get_object, _set_object, doc="Return the object our ref currently refers to")
90-
91-
def _set_commit(self, commit):
92-
"""
93-
Set ourselves to point to the given commit.
94-
95-
Raise
96-
ValueError if commit does not actually point to a commit
97-
"""
98-
self._set_object(commit)
99-
100-
def _get_commit(self):
101-
"""
102-
Returns
103-
Commit object the reference points to
104-
"""
105-
commit = self.object
106-
if commit.type != "commit":
107-
raise TypeError("Object of reference %s did not point to a commit, but to %r" % (self, commit))
108-
return commit
109-
110-
commit = property(_get_commit, _set_commit, doc="Return Commit object the reference points to")
111-
112-
@classmethod
113-
def iter_items(cls, repo, common_path = None, **kwargs):
114-
"""
115-
Find all refs in the repository
116-
117-
``repo``
118-
is the Repo
119-
120-
``common_path``
121-
Optional keyword argument to the path which is to be shared by all
122-
returned Ref objects.
123-
Defaults to class specific portion if None assuring that only
124-
refs suitable for the actual class are returned.
125-
126-
Returns
127-
git.Reference[]
128-
129-
List is lexigraphically sorted
130-
The returned objects represent actual subclasses, such as Head or TagReference
131-
"""
132-
if common_path is None:
133-
common_path = cls._common_path_default
134-
135-
rela_paths = set()
136-
137-
# walk loose refs
138-
# Currently we do not follow links
139-
for root, dirs, files in os.walk(join_path_native(repo.path, common_path)):
140-
for f in files:
141-
abs_path = to_native_path_linux(join_path(root, f))
142-
rela_paths.add(abs_path.replace(to_native_path_linux(repo.path) + '/', ""))
143-
# END for each file in root directory
144-
# END for each directory to walk
145-
146-
# read packed refs
147-
packed_refs_path = join_path_native(repo.path, 'packed-refs')
148-
if os.path.isfile(packed_refs_path):
149-
fp = open(packed_refs_path, 'r')
150-
try:
151-
for line in fp.readlines():
152-
if line.startswith('#'):
153-
continue
154-
# 439689865b9c6e2a0dad61db22a0c9855bacf597 refs/heads/hello
155-
line = line.rstrip()
156-
first_space = line.find(' ')
157-
if first_space == -1:
158-
continue
159-
160-
rela_path = line[first_space+1:]
161-
if rela_path.startswith(common_path):
162-
rela_paths.add(rela_path)
163-
# END relative path matches common path
164-
# END for each line in packed-refs
165-
finally:
166-
fp.close()
167-
# END packed refs reading
168-
169-
# return paths in sorted order
170-
for path in sorted(rela_paths):
171-
if path.endswith('/HEAD'):
172-
continue
173-
# END skip remote heads
174-
yield cls.from_path(repo, path)
175-
# END for each sorted relative refpath
176-
177-
178-
@classmethod
179-
def from_path(cls, repo, path):
180-
"""
181-
Return
182-
Instance of type Reference, Head, or Tag
183-
depending on the given path
184-
"""
185-
if not path:
186-
raise ValueError("Cannot create Reference from %r" % path)
187-
188-
for ref_type in (Head, RemoteReference, TagReference, Reference):
189-
try:
190-
return ref_type(repo, path)
191-
except ValueError:
192-
pass
193-
# END exception handling
194-
# END for each type to try
195-
raise ValueError("Could not find reference type suitable to handle path %r" % path)
196-
19713

198-
class SymbolicReference(object):
14+
class SymbolicReference(object):
19915
"""
20016
Represents a special case of a reference such that this reference is symbolic.
20117
It does not point to a specific commit, but to another Head, which itself
@@ -224,6 +40,15 @@ def __ne__(self, other):
22440
def __hash__(self):
22541
return hash(self.path)
22642

43+
@property
44+
def name(self):
45+
"""
46+
Returns
47+
In case of symbolic references, the shortest assumable name
48+
is the path itself.
49+
"""
50+
return self.path
51+
22752
def _get_path(self):
22853
return join_path_native(self.repo.path, self.path)
22954

@@ -356,6 +181,157 @@ def from_path(cls, repo, path):
356181
return SymbolicReference(repo, path)
357182

358183
raise ValueError("Could not find symbolic reference type suitable to handle path %r" % path)
184+
185+
186+
class Reference(SymbolicReference, LazyMixin, Iterable):
187+
"""
188+
Represents a named reference to any object. Subclasses may apply restrictions though,
189+
i.e. Heads can only point to commits.
190+
"""
191+
__slots__ = tuple()
192+
_common_path_default = "refs"
193+
_id_attribute_ = "name"
194+
195+
def __init__(self, repo, path):
196+
"""
197+
Initialize this instance
198+
``repo``
199+
Our parent repository
200+
201+
``path``
202+
Path relative to the .git/ directory pointing to the ref in question, i.e.
203+
refs/heads/master
204+
205+
"""
206+
if not path.startswith(self._common_path_default):
207+
raise ValueError("Cannot instantiate %s from path %s" % ( self.__class__.__name__, path ))
208+
super(Reference, self).__init__(repo, path)
209+
210+
211+
def __str__(self):
212+
return self.name
213+
214+
def _get_object(self):
215+
"""
216+
Returns
217+
The object our ref currently refers to. Refs can be cached, they will
218+
always point to the actual object as it gets re-created on each query
219+
"""
220+
# have to be dynamic here as we may be a tag which can point to anything
221+
# Our path will be resolved to the hexsha which will be used accordingly
222+
return Object.new(self.repo, self.path)
223+
224+
def _set_object(self, ref):
225+
"""
226+
Set our reference to point to the given ref. It will be converted
227+
to a specific hexsha.
228+
229+
Note:
230+
TypeChecking is done by the git command
231+
"""
232+
# do it safely by specifying the old value
233+
self.repo.git.update_ref(self.path, ref, self._get_object().sha)
234+
235+
object = property(_get_object, _set_object, doc="Return the object our ref currently refers to")
236+
237+
@property
238+
def name(self):
239+
"""
240+
Returns
241+
(shortest) Name of this reference - it may contain path components
242+
"""
243+
# first two path tokens are can be removed as they are
244+
# refs/heads or refs/tags or refs/remotes
245+
tokens = self.path.split('/')
246+
if len(tokens) < 3:
247+
return self.path # could be refs/HEAD
248+
return '/'.join(tokens[2:])
249+
250+
@classmethod
251+
def iter_items(cls, repo, common_path = None, **kwargs):
252+
"""
253+
Find all refs in the repository
254+
255+
``repo``
256+
is the Repo
257+
258+
``common_path``
259+
Optional keyword argument to the path which is to be shared by all
260+
returned Ref objects.
261+
Defaults to class specific portion if None assuring that only
262+
refs suitable for the actual class are returned.
263+
264+
Returns
265+
git.Reference[]
266+
267+
List is lexigraphically sorted
268+
The returned objects represent actual subclasses, such as Head or TagReference
269+
"""
270+
if common_path is None:
271+
common_path = cls._common_path_default
272+
273+
rela_paths = set()
274+
275+
# walk loose refs
276+
# Currently we do not follow links
277+
for root, dirs, files in os.walk(join_path_native(repo.path, common_path)):
278+
for f in files:
279+
abs_path = to_native_path_linux(join_path(root, f))
280+
rela_paths.add(abs_path.replace(to_native_path_linux(repo.path) + '/', ""))
281+
# END for each file in root directory
282+
# END for each directory to walk
283+
284+
# read packed refs
285+
packed_refs_path = join_path_native(repo.path, 'packed-refs')
286+
if os.path.isfile(packed_refs_path):
287+
fp = open(packed_refs_path, 'r')
288+
try:
289+
for line in fp.readlines():
290+
if line.startswith('#'):
291+
continue
292+
# 439689865b9c6e2a0dad61db22a0c9855bacf597 refs/heads/hello
293+
line = line.rstrip()
294+
first_space = line.find(' ')
295+
if first_space == -1:
296+
continue
297+
298+
rela_path = line[first_space+1:]
299+
if rela_path.startswith(common_path):
300+
rela_paths.add(rela_path)
301+
# END relative path matches common path
302+
# END for each line in packed-refs
303+
finally:
304+
fp.close()
305+
# END packed refs reading
306+
307+
# return paths in sorted order
308+
for path in sorted(rela_paths):
309+
if path.endswith('/HEAD'):
310+
continue
311+
# END skip remote heads
312+
yield cls.from_path(repo, path)
313+
# END for each sorted relative refpath
314+
315+
316+
@classmethod
317+
def from_path(cls, repo, path):
318+
"""
319+
Return
320+
Instance of type Reference, Head, or Tag
321+
depending on the given path
322+
"""
323+
if not path:
324+
raise ValueError("Cannot create Reference from %r" % path)
325+
326+
for ref_type in (Head, RemoteReference, TagReference, Reference):
327+
try:
328+
return ref_type(repo, path)
329+
except ValueError:
330+
pass
331+
# END exception handling
332+
# END for each type to try
333+
raise ValueError("Could not find reference type suitable to handle path %r" % path)
334+
359335

360336
class HEAD(SymbolicReference):
361337
"""

0 commit comments

Comments
 (0)