summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Thiel <byronimo@gmail.com>2009-11-03 17:44:13 +0100
committerSebastian Thiel <byronimo@gmail.com>2009-11-03 17:44:13 +0100
commit572ace094208c28ab1a8641aedb038456d13f70b (patch)
tree9bb6197273dc9976bce5bd789a657f408fc1b77e
parent0c4269a21b9edf8477f2fee139d5c1b260ebc4f8 (diff)
downloadgitpython-572ace094208c28ab1a8641aedb038456d13f70b.tar.gz
Now using git-update-ref and git-symbolic-ref to update references with reflog support. This should be manually implemented though for more performance, what it does is relatively easy
-rw-r--r--TODO12
-rw-r--r--lib/git/refs.py38
-rw-r--r--test/git/test_refs.py6
3 files changed, 26 insertions, 30 deletions
diff --git a/TODO b/TODO
index 5fa2477d..0fe33050 100644
--- a/TODO
+++ b/TODO
@@ -80,11 +80,12 @@ Index
Refs
-----
-* When adjusting the reference of a symbolic reference, the ref log might need
- adjustments as well. This is not critical, but would make things totally 'right'
- - same with adjusting references directly
- !! - Could simply rewrite it using git-update-ref which works nicely for symbolic
- and for normal refs !!
+* For performance reasons it would be good to reimplement git-update-ref to be
+ fully equivalent to what the command does. Currently it does some checking and
+ handles symbolic refs as well as normal refs, updating the reflog if required.
+* I have read that refs can be symbolic refs as well which would imply the need
+ to possibly dereference them. This makes sense as they originally where possibly
+ a symbolic link
* Check whether we are the active reference HEAD.reference == this_ref
- NO: The reference dosnt need to know - in fact it does not know about the
main HEAD, so it may not use it. This is to be done in client code only.
@@ -92,6 +93,7 @@ Refs
* Reference.from_path may return a symbolic reference although it is not related
to the reference type. Split that up into two from_path on each of the types,
and provide a general method outside of the type that tries both.
+* Making the reflog available might be useful actually.
Remote
------
diff --git a/lib/git/refs.py b/lib/git/refs.py
index 84347057..cd36a052 100644
--- a/lib/git/refs.py
+++ b/lib/git/refs.py
@@ -13,7 +13,8 @@ from utils import LazyMixin, Iterable
class Reference(LazyMixin, Iterable):
"""
- Represents a named reference to any object
+ Represents a named reference to any object. Subclasses may apply restrictions though,
+ i.e. Heads can only point to commits.
"""
__slots__ = ("repo", "path")
_common_path_default = "refs"
@@ -75,30 +76,16 @@ class Reference(LazyMixin, Iterable):
# Our path will be resolved to the hexsha which will be used accordingly
return Object.new(self.repo, self.path)
- def _set_object(self, ref, type=None):
+ def _set_object(self, ref):
"""
Set our reference to point to the given ref. It will be converted
to a specific hexsha.
- ``type``
- If not None, string type of that the object must have, other we raise
- a type error. Only used internally
-
- Returns
- Object we have set. This is used internally only to reduce the amount
- of calls to the git command
+ Note:
+ TypeChecking is done by the git command
"""
- obj = Object.new(self.repo, ref)
- if type is not None and obj.type != type:
- raise TypeError("Reference %r cannot point to object of type %r" % (self,obj.type))
-
- full_ref_path = os.path.join(self.repo.path, self.path)
- fp = open(full_ref_path, "w")
- try:
- fp.write(str(obj))
- finally:
- fp.close()
- return obj
+ # do it safely by specifying the old value
+ self.repo.git.update_ref(self.path, ref, self._get_object().sha)
object = property(_get_object, _set_object, doc="Return the object our ref currently refers to")
@@ -109,7 +96,7 @@ class Reference(LazyMixin, Iterable):
Raise
ValueError if commit does not actually point to a commit
"""
- self._set_object(commit, type="commit")
+ self._set_object(commit)
def _get_commit(self):
"""
@@ -327,6 +314,15 @@ class SymbolicReference(object):
raise ValueError("Could not extract object from %s" % ref)
# END end try string
# END try commit attribute
+
+ # if we are writing a ref, use symbolic ref to get the reflog and more
+ # checking
+ # Otherwise we detach it and have to do it manually
+ if write_value.startswith('ref:'):
+ self.repo.git.symbolic_ref(self.name, write_value[5:])
+ return
+ # END non-detached handling
+
fp = open(self._get_path(), "w")
try:
fp.write(write_value)
diff --git a/test/git/test_refs.py b/test/git/test_refs.py
index 0a70af1f..f7f4f71a 100644
--- a/test/git/test_refs.py
+++ b/test/git/test_refs.py
@@ -200,11 +200,9 @@ class TestRefs(TestBase):
# setting a non-commit as commit fails, but succeeds as object
head_tree = head.commit.tree
- self.failUnlessRaises(TypeError, setattr, head, 'commit', head_tree)
+ self.failUnlessRaises(GitCommandError, setattr, head, 'commit', head_tree)
assert head.commit == old_commit # and the ref did not change
- head.object = head_tree
- assert head.object == head_tree
- self.failUnlessRaises(TypeError, getattr, head, 'commit') # object is a tree, not a commit
+ self.failUnlessRaises(GitCommandError, setattr, head, 'object', head_tree)
# set the commit directly using the head. This would never detach the head
assert not cur_head.is_detached