summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Thiel <byronimo@gmail.com>2009-10-23 16:07:45 +0200
committerSebastian Thiel <byronimo@gmail.com>2009-10-23 16:07:45 +0200
commit9b9776e88f7abb59cebac8733c04cccf6eee1c60 (patch)
treef7bc7af48ddb55eafde1d1c91d8014ec595208fa
parent1047b41e2e925617474e2e7c9927314f71ce7365 (diff)
downloadgitpython-9b9776e88f7abb59cebac8733c04cccf6eee1c60.tar.gz
Refs can now set the reference they are pointing to in a controlled fashion by writing their ref file directly
-rw-r--r--TODO10
-rw-r--r--lib/git/refs.py48
-rw-r--r--test/git/test_refs.py18
3 files changed, 60 insertions, 16 deletions
diff --git a/TODO b/TODO
index 6d548a15..c2cc804b 100644
--- a/TODO
+++ b/TODO
@@ -67,15 +67,7 @@ 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'
-* Reference Objects should be able to set the commit they are pointing to, making
- the commit property read-write. Tags are a special case of this and would need
- to be handled as well !
-* Ability to create new heads and tags in the Repository ( but using the respective
- Reference Type ), i.e. Head.create(repo, name, commit = 'HEAD') or
- TagReference.create(repo, name
-* Ability to rename references and tagsre
-* Ability to remove references and tags
-* Ability to checkout a reference -
+ - same with adjusting references directly
* Check whether we are the active reference HEAD.commit == self.commit
Remote
diff --git a/lib/git/refs.py b/lib/git/refs.py
index 0efee52e..47c37af6 100644
--- a/lib/git/refs.py
+++ b/lib/git/refs.py
@@ -65,8 +65,7 @@ class Reference(LazyMixin, Iterable):
return '/'.join(tokens[2:])
- @property
- def object(self):
+ def _get_object(self):
"""
Returns
The object our ref currently refers to. Refs can be cached, they will
@@ -76,17 +75,54 @@ class Reference(LazyMixin, Iterable):
# Our path will be resolved to the hexsha which will be used accordingly
return Object.new(self.repo, self.path)
- @property
- def commit(self):
+ def _set_object(self, ref, type=None):
"""
+ 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
- Commit object the head points to
+ Object we have set. This is used internally only to reduce the amount
+ of calls to 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
+
+ object = property(_get_object, _set_object, doc="Return the object our ref currently refers to")
+
+ def _set_commit(self, commit):
+ """
+ Set ourselves to point to the given commit.
+
+ Raise
+ ValueError if commit does not actually point to a commit
+ """
+ self._set_object(commit, type="commit")
+
+ def _get_commit(self):
+ """
+ Returns
+ Commit object the reference points to
"""
commit = self.object
if commit.type != "commit":
raise TypeError("Object of reference %s did not point to a commit" % self)
return commit
+ commit = property(_get_commit, _set_commit, doc="Return Commit object the reference points to")
+
@classmethod
def iter_items(cls, repo, common_path = None, **kwargs):
"""
@@ -244,7 +280,7 @@ class SymbolicReference(object):
try:
tokens = fp.readline().rstrip().split(' ')
if tokens[0] != 'ref:':
- raise TypeError("%s is a detached symbolic reference as it points to %r" % tokens[0])
+ raise TypeError("%s is a detached symbolic reference as it points to %r" % (self, tokens[0]))
return Reference.from_path(self.repo, tokens[1])
finally:
fp.close()
diff --git a/test/git/test_refs.py b/test/git/test_refs.py
index 88e8a21a..696b95c7 100644
--- a/test/git/test_refs.py
+++ b/test/git/test_refs.py
@@ -181,4 +181,20 @@ class TestRefs(TestBase):
self.failUnlessRaises(AssertionError, getattr, remote, 'refs')
# END for each remote
- self.fail("set commit using ref.commit = that")
+ # change where the active head points to
+ if cur_head.is_detached:
+ cur_head.reference = rw_repo.heads[0]
+
+ head = cur_head.reference
+ old_commit = head.commit
+ head.commit = old_commit.parents[0]
+ assert head.commit == old_commit.parents[0]
+ assert head.commit == cur_head.commit
+ head.commit = old_commit
+
+ # setting a non-commit as commit fails, but succeeds as object
+ head_tree = head.commit.tree
+ self.failUnlessRaises(TypeError, 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