@@ -224,12 +224,30 @@ def _set_reference(self, ref):
224
224
# END end try string
225
225
# END try commit attribute
226
226
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
+
227
243
# if we are writing a ref, use symbolic ref to get the reflog and more
228
244
# 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
230
248
if write_value .startswith ('ref:' ):
231
249
self .repo .git .symbolic_ref (self .path , write_value [5 :])
232
- return
250
+ return
233
251
# END non-detached handling
234
252
235
253
path = self ._abs_path ()
@@ -243,10 +261,10 @@ def _set_reference(self, ref):
243
261
finally :
244
262
fp .close ()
245
263
# END writing
246
-
247
- reference = property (_get_reference , _set_reference , doc = "Returns the Reference we point to" )
248
264
249
- # alias
265
+
266
+ # aliased reference
267
+ reference = property (_get_reference , _set_reference , doc = "Returns the Reference we point to" )
250
268
ref = reference
251
269
252
270
def is_valid (self ):
@@ -553,7 +571,6 @@ def _set_object(self, ref):
553
571
554
572
:note:
555
573
TypeChecking is done by the git command"""
556
- # check for existence, touch it if required
557
574
abs_path = self ._abs_path ()
558
575
existed = True
559
576
if not isfile (abs_path ):
@@ -618,13 +635,35 @@ class HEAD(SymbolicReference):
618
635
"""Special case of a Symbolic Reference as it represents the repository's
619
636
HEAD reference."""
620
637
_HEAD_NAME = 'HEAD'
638
+ _ORIG_HEAD_NAME = 'ORIG_HEAD'
621
639
__slots__ = tuple ()
622
640
623
641
def __init__ (self , repo , path = _HEAD_NAME ):
624
642
if path != self ._HEAD_NAME :
625
643
raise ValueError ("HEAD instance must point to %r, got %r" % (self ._HEAD_NAME , path ))
626
644
super (HEAD , self ).__init__ (repo , path )
627
645
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
628
667
629
668
def reset (self , commit = 'HEAD' , index = True , working_tree = False ,
630
669
paths = None , ** kwargs ):
0 commit comments