88"""
99from objects .base import Object
1010from objects .util import get_object_type_by_name
11+ from utils import LazyMixin
1112
12- class Ref (object ):
13+ class Ref (LazyMixin ):
1314 """
1415 Represents a named reference to any object
1516 """
16- __slots__ = ("path" , "object" )
17+ __slots__ = ("repo" , " path" , "object" )
1718
18- def __init__ (self , path , object = None ):
19+ def __init__ (self , repo , path , object = None ):
1920 """
2021 Initialize this instance
22+ ``repo``
23+ Our parent repository
2124
2225 ``path``
2326 Path relative to the .git/ directory pointing to the ref in question, i.e.
@@ -26,8 +29,19 @@ def __init__(self, path, object = None):
2629 ``object``
2730 Object instance, will be retrieved on demand if None
2831 """
32+ self .repo = repo
2933 self .path = path
30- self .object = object
34+ if object is not None :
35+ self .object = object
36+
37+ def _set_cache_ (self , attr ):
38+ if attr == "object" :
39+ # have to be dynamic here as we may be a tag which can point to anything
40+ # it uses our path to stay dynamic
41+ type_string = self .repo .git .cat_file (self .path , t = True ).rstrip ()
42+ self .object = get_object_type_by_name (type_string )(self .repo , self .path )
43+ else :
44+ super (Ref , self )._set_cache_ (attr )
3145
3246 def __str__ (self ):
3347 return self .name
@@ -92,19 +106,8 @@ def find_all(cls, repo, common_path = "refs", **kwargs):
92106
93107 @classmethod
94108 def _list_from_string (cls , repo , text ):
95- """
96- Parse out ref information into a list of Ref compatible objects
97-
98- ``repo``
99- is the Repo
100- ``text``
101- is the text output from the git-for-each-ref command
102-
103- Returns
104- git.Ref[]
105-
106- list of Ref objects
107- """
109+ """ Parse out ref information into a list of Ref compatible objects
110+ Returns git.Ref[] list of Ref objects """
108111 heads = []
109112
110113 for line in text .splitlines ():
@@ -114,28 +117,16 @@ def _list_from_string(cls, repo, text):
114117
115118 @classmethod
116119 def _from_string (cls , repo , line ):
117- """
118- Create a new Ref instance from the given string.
119-
120- ``repo``
121- is the Repo
122-
123- ``line``
124- is the formatted ref information
125-
126- Format::
127-
120+ """ Create a new Ref instance from the given string.
121+ Format
128122 name: [a-zA-Z_/]+
129123 <null byte>
130124 id: [0-9A-Fa-f]{40}
131-
132- Returns
133- git.Head
134- """
125+ Returns git.Head """
135126 full_path , hexsha , type_name , object_size = line .split ("\x00 " )
136127 obj = get_object_type_by_name (type_name )(repo , hexsha )
137128 obj .size = object_size
138- return cls (full_path , obj )
129+ return cls (repo , full_path , obj )
139130
140131
141132class Head (Ref ):
@@ -196,24 +187,7 @@ class TagRef(Ref):
196187 print tagref.tag.message
197188 """
198189
199- __slots__ = "tag"
200-
201- def __init__ (self , path , commit_or_tag ):
202- """
203- Initialize a newly instantiated Tag
204-
205- ``path``
206- is the full path to the tag
207-
208- ``commit_or_tag``
209- is the Commit or TagObject that this tag ref points to
210- """
211- super (TagRef , self ).__init__ (path , commit_or_tag )
212- self .tag = None
213-
214- if commit_or_tag .type == "tag" :
215- self .tag = commit_or_tag
216- # END tag object handling
190+ __slots__ = tuple ()
217191
218192 @property
219193 def commit (self ):
@@ -223,8 +197,22 @@ def commit(self):
223197 """
224198 if self .object .type == "commit" :
225199 return self .object
226- # it is a tag object
227- return self .object .object
200+ elif self .object .type == "tag" :
201+ # it is a tag object which carries the commit as an object - we can point to anything
202+ return self .object .object
203+ else :
204+ raise ValueError ( "Tag %s points to a Blob or Tree - have never seen that before" % self )
205+
206+ @property
207+ def tag (self ):
208+ """
209+ Returns
210+ Tag object this tag ref points to or None in case
211+ we are a light weight tag
212+ """
213+ if self .object .type == "tag" :
214+ return self .object
215+ return None
228216
229217 @classmethod
230218 def find_all (cls , repo , common_path = "refs/tags" , ** kwargs ):
0 commit comments