77Module containing all ref based objects
88"""
99import os
10- from objects . base import Object
10+ from objects import Object , Commit
1111from objects .utils import get_object_type_by_name
1212from utils import LazyMixin , Iterable
1313
@@ -214,13 +214,36 @@ def __ne__(self, other):
214214 def __hash__ (self ):
215215 return hash (self .name )
216216
217+ def _get_path (self ):
218+ return os .path .join (self .repo .path , self .name )
219+
217220 @property
218- def reference (self ):
221+ def commit (self ):
222+ """
223+ Returns:
224+ Commit object we point to, works for detached and non-detached
225+ SymbolicReferences
226+ """
227+ # we partially reimplement it to prevent unnecessary file access
228+ fp = open (self ._get_path (), 'r' )
229+ value = fp .read ().rstrip ()
230+ fp .close ()
231+ tokens = value .split (" " )
232+
233+ # it is a detached reference
234+ if len (tokens ) == 1 and len (tokens [0 ]) == 40 :
235+ return Commit (self .repo , tokens [0 ])
236+
237+ # must be a head ! Git does not allow symbol refs to other things than heads
238+ # Otherwise it would have detached it
239+ return Head (self .repo , tokens [1 ]).commit
240+
241+ def _get_reference (self ):
219242 """
220243 Returns
221244 Reference Object we point to
222245 """
223- fp = open (os . path . join ( self .repo . path , self . name ), 'r' )
246+ fp = open (self ._get_path ( ), 'r' )
224247 try :
225248 tokens = fp .readline ().rstrip ().split (' ' )
226249 if tokens [0 ] != 'ref:' :
@@ -229,6 +252,41 @@ def reference(self):
229252 finally :
230253 fp .close ()
231254
255+ def _set_reference (self , ref ):
256+ """
257+ Set ourselves to the given ref. It will stay a symbol if the ref is a Head.
258+ Otherwise we try to get a commit from it using our interface.
259+
260+ Strings are allowed but will be checked to be sure we have a commit
261+ """
262+ write_value = None
263+ if isinstance (ref , Head ):
264+ write_value = "ref: %s" % ref .path
265+ elif isinstance (ref , Commit ):
266+ write_value = ref .id
267+ else :
268+ try :
269+ write_value = ref .commit .id
270+ except AttributeError :
271+ sha = str (ref )
272+ try :
273+ obj = Object .new (self .repo , sha )
274+ if obj .type != "commit" :
275+ raise TypeError ("Invalid object type behind sha: %s" % sha )
276+ write_value = obj .id
277+ except Exception :
278+ raise ValueError ("Could not extract object from %s" % ref )
279+ # END end try string
280+ # END try commit attribute
281+ fp = open (self ._get_path (), "w" )
282+ try :
283+ fp .write (write_value )
284+ finally :
285+ fp .close ()
286+ # END writing
287+
288+ reference = property (_get_reference , _set_reference , doc = "Returns the Reference we point to" )
289+
232290 # alias
233291 ref = reference
234292
@@ -251,11 +309,12 @@ class HEAD(SymbolicReference):
251309 Special case of a Symbolic Reference as it represents the repository's
252310 HEAD reference.
253311 """
312+ _HEAD_NAME = 'HEAD'
254313 __slots__ = tuple ()
255314
256- def __init__ (self , repo , name ):
257- if name != 'HEAD' :
258- raise ValueError ("HEAD instance must point to 'HEAD' , got %s " % name )
315+ def __init__ (self , repo , name = _HEAD_NAME ):
316+ if name != self . _HEAD_NAME :
317+ raise ValueError ("HEAD instance must point to %r , got %r " % ( self . _HEAD_NAME , name ) )
259318 super (HEAD , self ).__init__ (repo , name )
260319
261320
0 commit comments