@@ -224,12 +224,30 @@ def _set_reference(self, ref):
224224 # END end try string
225225 # END try commit attribute
226226
227+ # maintain the orig-head if we are currently checked-out
228+ head = HEAD (self .repo )
229+ try :
230+ if head .ref == self :
231+ try :
232+ # TODO: implement this atomically, if we fail below, orig_head is at an incorrect spot
233+ # Enforce the creation of ORIG_HEAD
234+ SymbolicReference .create (self .repo , head .orig_head ().name , self .commit , force = True )
235+ except ValueError :
236+ pass
237+ #END exception handling
238+ # END if we are checked-out
239+ except TypeError :
240+ pass
241+ # END handle detached heads
242+
227243 # if we are writing a ref, use symbolic ref to get the reflog and more
228244 # checking
229- # Otherwise we detach it and have to do it manually
245+ # Otherwise we detach it and have to do it manually. Besides, this works
246+ # recursively automaitcally, but should be replaced with a python implementation
247+ # soon
230248 if write_value .startswith ('ref:' ):
231249 self .repo .git .symbolic_ref (self .path , write_value [5 :])
232- return
250+ return
233251 # END non-detached handling
234252
235253 path = self ._abs_path ()
@@ -243,10 +261,10 @@ def _set_reference(self, ref):
243261 finally :
244262 fp .close ()
245263 # END writing
246-
247- reference = property (_get_reference , _set_reference , doc = "Returns the Reference we point to" )
248264
249- # alias
265+
266+ # aliased reference
267+ reference = property (_get_reference , _set_reference , doc = "Returns the Reference we point to" )
250268 ref = reference
251269
252270 def is_valid (self ):
@@ -553,7 +571,6 @@ def _set_object(self, ref):
553571
554572 :note:
555573 TypeChecking is done by the git command"""
556- # check for existence, touch it if required
557574 abs_path = self ._abs_path ()
558575 existed = True
559576 if not isfile (abs_path ):
@@ -618,13 +635,35 @@ class HEAD(SymbolicReference):
618635 """Special case of a Symbolic Reference as it represents the repository's
619636 HEAD reference."""
620637 _HEAD_NAME = 'HEAD'
638+ _ORIG_HEAD_NAME = 'ORIG_HEAD'
621639 __slots__ = tuple ()
622640
623641 def __init__ (self , repo , path = _HEAD_NAME ):
624642 if path != self ._HEAD_NAME :
625643 raise ValueError ("HEAD instance must point to %r, got %r" % (self ._HEAD_NAME , path ))
626644 super (HEAD , self ).__init__ (repo , path )
627645
646+ def orig_head (self ):
647+ """:return: SymbolicReference pointing at the ORIG_HEAD, which is maintained
648+ to contain the previous value of HEAD"""
649+ return SymbolicReference (self .repo , self ._ORIG_HEAD_NAME )
650+
651+ def _set_reference (self , ref ):
652+ """If someone changes the reference through us, we must manually update
653+ the ORIG_HEAD if we are detached. The underlying implementation can only
654+ handle un-detached heads as it has to check whether the current head
655+ is the checked-out one"""
656+ if self .is_detached :
657+ prev_commit = self .commit
658+ super (HEAD , self )._set_reference (ref )
659+ SymbolicReference .create (self .repo , self ._ORIG_HEAD_NAME , prev_commit , force = True )
660+ else :
661+ super (HEAD , self )._set_reference (ref )
662+ # END handle detached mode
663+
664+ # aliased reference
665+ reference = property (SymbolicReference ._get_reference , _set_reference , doc = "Returns the Reference we point to" )
666+ ref = reference
628667
629668 def reset (self , commit = 'HEAD' , index = True , working_tree = False ,
630669 paths = None , ** kwargs ):
0 commit comments