Skip to content

Commit c946bf2

Browse files
committed
Added tests for creation and adjustments of reference, verifying the log gets written
1 parent 264ba6f commit c946bf2

File tree

3 files changed

+82
-35
lines changed

3 files changed

+82
-35
lines changed

‎refs/reference.py

+30
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,36 @@ def __init__(self, repo, path):
3737
def __str__(self):
3838
return self.name
3939

40+
def set_object(self, object, msg = None):
41+
"""Special version which checks if the head-log needs an update as well"""
42+
oldbinsha = None
43+
if msg is not None:
44+
head = self.repo.head
45+
if not head.is_detached and head.ref == self:
46+
oldbinsha = self.commit.binsha
47+
#END handle commit retrieval
48+
#END handle message is set
49+
50+
super(Reference, self).set_object(object, msg)
51+
52+
if oldbinsha is not None:
53+
# /* from refs.c in git-source
54+
# * Special hack: If a branch is updated directly and HEAD
55+
# * points to it (may happen on the remote side of a push
56+
# * for example) then logically the HEAD reflog should be
57+
# * updated too.
58+
# * A generic solution implies reverse symref information,
59+
# * but finding all symrefs pointing to the given branch
60+
# * would be rather costly for this rare event (the direct
61+
# * update of a branch) to be worth it. So let's cheat and
62+
# * check with HEAD only which should cover 99% of all usage
63+
# * scenarios (even 100% of the default ones).
64+
# */
65+
self.repo.head.log_append(oldbinsha, msg)
66+
#END check if the head
67+
68+
# NOTE: Don't have to overwrite properties as the will only work without a the log
69+
4070
@property
4171
def name(self):
4272
""":return: (shortest) Name of this reference - it may contain path components"""

‎refs/symbolic.py

+11-3
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,8 @@ def _get_commit(self):
175175
def set_commit(self, commit, msg = None):
176176
"""As set_object, but restricts the type of object to be a Commit
177177
:raise ValueError: If commit is not a Commit object or doesn't point to
178-
a commit"""
178+
a commit
179+
:return: self"""
179180
# check the type - assume the best if it is a base-string
180181
invalid_type = False
181182
if isinstance(commit, Object):
@@ -197,6 +198,8 @@ def set_commit(self, commit, msg = None):
197198
# we leave strings to the rev-parse method below
198199
self.set_object(commit, msg)
199200

201+
return self
202+
200203

201204
def set_object(self, object, msg = None):
202205
"""Set the object we point to, possibly dereference our symbolic reference first.
@@ -206,7 +209,8 @@ def set_object(self, object, msg = None):
206209
will be dereferenced beforehand to obtain the object they point to
207210
:param msg: If not None, the message will be used in the reflog entry to be
208211
written. Otherwise the reflog is not altered
209-
:note: plain SymbolicReferences may not actually point to objects by convention"""
212+
:note: plain SymbolicReferences may not actually point to objects by convention
213+
:return: self"""
210214
if isinstance(object, SymbolicReference):
211215
object = object.object
212216
#END resolve references
@@ -222,7 +226,7 @@ def set_object(self, object, msg = None):
222226
return self.set_reference(object, msg)
223227

224228
# set the commit on our reference
225-
self._get_reference().set_object(object, msg)
229+
return self._get_reference().set_object(object, msg)
226230

227231
commit = property(_get_commit, set_commit, doc="Query or set commits directly")
228232
object = property(_get_object, set_object, doc="Return the object our ref currently refers to")
@@ -250,6 +254,8 @@ def set_reference(self, ref, msg = None):
250254
The previous commit of the entry will be the commit we point to now.
251255
252256
See also: log_append()
257+
258+
:return: self
253259
:note: This symbolic reference will not be dereferenced. For that, see
254260
``set_object(...)``"""
255261
write_value = None
@@ -297,6 +303,8 @@ def set_reference(self, ref, msg = None):
297303
self.log_append(oldbinsha, msg)
298304
#END handle reflog
299305

306+
return self
307+
300308

301309
# aliased reference
302310
reference = property(_get_reference, set_reference, doc="Returns the Reference we point to")

‎test/test_refs.py

+41-32
Original file line numberDiff line numberDiff line change
@@ -96,38 +96,46 @@ def test_heads(self, rwrepo):
9696
# END for each head
9797

9898
# verify REFLOG gets altered
99-
if False:
100-
head = rwrepo.head
101-
orig_head = head.orig_head()
102-
cur_head = head.ref
103-
cur_commit = cur_head.commit
104-
pcommit = cur_head.commit.parents[0].parents[0]
105-
head.ref = pcommit # detach head
106-
assert orig_head.commit == cur_commit
107-
108-
# even if we set it through its reference - chaning the ref
109-
# will adjust the orig_head, which still points to cur_commit
110-
head.ref = cur_head
111-
assert orig_head.commit == pcommit
112-
assert head.commit == cur_commit == cur_head.commit
113-
114-
cur_head.commit = pcommit
115-
assert head.commit == pcommit
116-
assert orig_head.commit == cur_commit
117-
118-
# with automatic dereferencing
119-
head.commit = cur_commit
120-
assert orig_head.commit == pcommit
121-
122-
# changing branches which are not checked out doesn't affect the ORIG_HEAD
123-
other_head = Head.create(rwrepo, 'mynewhead', pcommit)
124-
assert other_head.commit == pcommit
125-
assert orig_head.commit == pcommit
126-
other_head.commit = pcommit.parents[0]
127-
assert orig_head.commit == pcommit
128-
129-
# TODO: Need changing a ref changes HEAD reflog as well if it pointed to it
130-
99+
head = rwrepo.head
100+
cur_head = head.ref
101+
cur_commit = cur_head.commit
102+
pcommit = cur_head.commit.parents[0].parents[0]
103+
hlog_len = len(head.log())
104+
blog_len = len(cur_head.log())
105+
head.set_reference(pcommit, 'detached head')
106+
# one new log-entry
107+
thlog = head.log()
108+
assert len(thlog) == hlog_len + 1
109+
assert thlog[-1].oldhexsha == cur_commit.hexsha
110+
assert thlog[-1].newhexsha == pcommit.hexsha
111+
112+
# the ref didn't change though
113+
assert len(cur_head.log()) == blog_len
114+
115+
# head changes once again, cur_head doesn't change
116+
head.set_reference(cur_head, 'reattach head')
117+
assert len(head.log()) == hlog_len+2
118+
assert len(cur_head.log()) == blog_len
119+
120+
# adjusting the head-ref also adjust the head, so both reflogs are
121+
# altered
122+
cur_head.set_commit(pcommit, 'changing commit')
123+
assert len(cur_head.log()) == blog_len+1
124+
assert len(head.log()) == hlog_len+3
125+
126+
127+
# with automatic dereferencing
128+
head.set_commit(cur_commit, 'change commit once again')
129+
assert len(head.log()) == hlog_len+4
130+
assert len(cur_head.log()) == blog_len+2
131+
132+
# a new branch has just a single entry
133+
other_head = Head.create(rwrepo, 'mynewhead', pcommit, msg='new head created')
134+
log = other_head.log()
135+
assert len(log) == 1
136+
assert log[0].oldhexsha == pcommit.NULL_HEX_SHA
137+
assert log[0].newhexsha == pcommit.hexsha
138+
131139

132140
def test_refs(self):
133141
types_found = set()
@@ -509,4 +517,5 @@ def test_todo(self):
509517
# delete deletes the reflog
510518
# create creates a new entry
511519
# set_reference and set_commit and set_object use the reflog if message is given
520+
# if there is no actual head-change, don't do anything
512521
self.fail()

0 commit comments

Comments
 (0)