diff options
author | Sebastian Thiel <byronimo@gmail.com> | 2010-11-24 17:51:22 +0100 |
---|---|---|
committer | Sebastian Thiel <byronimo@gmail.com> | 2010-11-24 17:51:22 +0100 |
commit | c946bf260d3f7ca54bffb796a82218dce0eb703f (patch) | |
tree | 5b8ebe421280b187f856af7e3e9a76a9b47d548d | |
parent | 264ba6f54f928da31a037966198a0849325b3732 (diff) | |
download | gitpython-c946bf260d3f7ca54bffb796a82218dce0eb703f.tar.gz |
Added tests for creation and adjustments of reference, verifying the log gets written
-rw-r--r-- | refs/reference.py | 30 | ||||
-rw-r--r-- | refs/symbolic.py | 14 | ||||
-rw-r--r-- | test/test_refs.py | 73 |
3 files changed, 82 insertions, 35 deletions
diff --git a/refs/reference.py b/refs/reference.py index e7cdfdee..c44ebf00 100644 --- a/refs/reference.py +++ b/refs/reference.py @@ -37,6 +37,36 @@ class Reference(SymbolicReference, LazyMixin, Iterable): def __str__(self): return self.name + def set_object(self, object, msg = None): + """Special version which checks if the head-log needs an update as well""" + oldbinsha = None + if msg is not None: + head = self.repo.head + if not head.is_detached and head.ref == self: + oldbinsha = self.commit.binsha + #END handle commit retrieval + #END handle message is set + + super(Reference, self).set_object(object, msg) + + if oldbinsha is not None: + # /* from refs.c in git-source + # * Special hack: If a branch is updated directly and HEAD + # * points to it (may happen on the remote side of a push + # * for example) then logically the HEAD reflog should be + # * updated too. + # * A generic solution implies reverse symref information, + # * but finding all symrefs pointing to the given branch + # * would be rather costly for this rare event (the direct + # * update of a branch) to be worth it. So let's cheat and + # * check with HEAD only which should cover 99% of all usage + # * scenarios (even 100% of the default ones). + # */ + self.repo.head.log_append(oldbinsha, msg) + #END check if the head + + # NOTE: Don't have to overwrite properties as the will only work without a the log + @property def name(self): """:return: (shortest) Name of this reference - it may contain path components""" diff --git a/refs/symbolic.py b/refs/symbolic.py index 83dbafd2..cdd6158a 100644 --- a/refs/symbolic.py +++ b/refs/symbolic.py @@ -175,7 +175,8 @@ class SymbolicReference(object): def set_commit(self, commit, msg = None): """As set_object, but restricts the type of object to be a Commit :raise ValueError: If commit is not a Commit object or doesn't point to - a commit""" + a commit + :return: self""" # check the type - assume the best if it is a base-string invalid_type = False if isinstance(commit, Object): @@ -197,6 +198,8 @@ class SymbolicReference(object): # we leave strings to the rev-parse method below self.set_object(commit, msg) + return self + def set_object(self, object, msg = None): """Set the object we point to, possibly dereference our symbolic reference first. @@ -206,7 +209,8 @@ class SymbolicReference(object): will be dereferenced beforehand to obtain the object they point to :param msg: If not None, the message will be used in the reflog entry to be written. Otherwise the reflog is not altered - :note: plain SymbolicReferences may not actually point to objects by convention""" + :note: plain SymbolicReferences may not actually point to objects by convention + :return: self""" if isinstance(object, SymbolicReference): object = object.object #END resolve references @@ -222,7 +226,7 @@ class SymbolicReference(object): return self.set_reference(object, msg) # set the commit on our reference - self._get_reference().set_object(object, msg) + return self._get_reference().set_object(object, msg) commit = property(_get_commit, set_commit, doc="Query or set commits directly") object = property(_get_object, set_object, doc="Return the object our ref currently refers to") @@ -250,6 +254,8 @@ class SymbolicReference(object): The previous commit of the entry will be the commit we point to now. See also: log_append() + + :return: self :note: This symbolic reference will not be dereferenced. For that, see ``set_object(...)``""" write_value = None @@ -297,6 +303,8 @@ class SymbolicReference(object): self.log_append(oldbinsha, msg) #END handle reflog + return self + # aliased reference reference = property(_get_reference, set_reference, doc="Returns the Reference we point to") diff --git a/test/test_refs.py b/test/test_refs.py index fefce6be..3ad4dad2 100644 --- a/test/test_refs.py +++ b/test/test_refs.py @@ -96,38 +96,46 @@ class TestRefs(TestBase): # END for each head # verify REFLOG gets altered - if False: - head = rwrepo.head - orig_head = head.orig_head() - cur_head = head.ref - cur_commit = cur_head.commit - pcommit = cur_head.commit.parents[0].parents[0] - head.ref = pcommit # detach head - assert orig_head.commit == cur_commit - - # even if we set it through its reference - chaning the ref - # will adjust the orig_head, which still points to cur_commit - head.ref = cur_head - assert orig_head.commit == pcommit - assert head.commit == cur_commit == cur_head.commit - - cur_head.commit = pcommit - assert head.commit == pcommit - assert orig_head.commit == cur_commit - - # with automatic dereferencing - head.commit = cur_commit - assert orig_head.commit == pcommit - - # changing branches which are not checked out doesn't affect the ORIG_HEAD - other_head = Head.create(rwrepo, 'mynewhead', pcommit) - assert other_head.commit == pcommit - assert orig_head.commit == pcommit - other_head.commit = pcommit.parents[0] - assert orig_head.commit == pcommit - - # TODO: Need changing a ref changes HEAD reflog as well if it pointed to it - + head = rwrepo.head + cur_head = head.ref + cur_commit = cur_head.commit + pcommit = cur_head.commit.parents[0].parents[0] + hlog_len = len(head.log()) + blog_len = len(cur_head.log()) + head.set_reference(pcommit, 'detached head') + # one new log-entry + thlog = head.log() + assert len(thlog) == hlog_len + 1 + assert thlog[-1].oldhexsha == cur_commit.hexsha + assert thlog[-1].newhexsha == pcommit.hexsha + + # the ref didn't change though + assert len(cur_head.log()) == blog_len + + # head changes once again, cur_head doesn't change + head.set_reference(cur_head, 'reattach head') + assert len(head.log()) == hlog_len+2 + assert len(cur_head.log()) == blog_len + + # adjusting the head-ref also adjust the head, so both reflogs are + # altered + cur_head.set_commit(pcommit, 'changing commit') + assert len(cur_head.log()) == blog_len+1 + assert len(head.log()) == hlog_len+3 + + + # with automatic dereferencing + head.set_commit(cur_commit, 'change commit once again') + assert len(head.log()) == hlog_len+4 + assert len(cur_head.log()) == blog_len+2 + + # a new branch has just a single entry + other_head = Head.create(rwrepo, 'mynewhead', pcommit, msg='new head created') + log = other_head.log() + assert len(log) == 1 + assert log[0].oldhexsha == pcommit.NULL_HEX_SHA + assert log[0].newhexsha == pcommit.hexsha + def test_refs(self): types_found = set() @@ -509,4 +517,5 @@ class TestRefs(TestBase): # delete deletes the reflog # create creates a new entry # set_reference and set_commit and set_object use the reflog if message is given + # if there is no actual head-change, don't do anything self.fail() |