summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Thiel <byronimo@gmail.com>2009-11-30 11:11:41 +0100
committerSebastian Thiel <byronimo@gmail.com>2009-11-30 11:11:41 +0100
commitbac518bfa621a6d07e3e4d9f9b481863a98db293 (patch)
tree2a9cd29bef215d8c8e64410585c636a7cb4ca68a
parent4f7255c2c1d9e54fc2f6390ad3e0be504e4099d3 (diff)
downloadgitpython-bac518bfa621a6d07e3e4d9f9b481863a98db293.tar.gz
Generalized custom reference creation down to SymbolicReference level. 'Reference' implementation now shares all the code from the SymbolicReference base. This implementation allows to create any reference you'd like without requireing git calls
-rw-r--r--lib/git/refs.py111
-rw-r--r--test/git/test_refs.py14
2 files changed, 90 insertions, 35 deletions
diff --git a/lib/git/refs.py b/lib/git/refs.py
index f75d5ed7..208ce880 100644
--- a/lib/git/refs.py
+++ b/lib/git/refs.py
@@ -20,6 +20,8 @@ class SymbolicReference(object):
A typical example for a symbolic reference is HEAD.
"""
__slots__ = ("repo", "path")
+ _common_path_default = ""
+ _id_attribute_ = "name"
def __init__(self, repo, path):
self.repo = repo
@@ -231,6 +233,79 @@ class SymbolicReference(object):
return SymbolicReference(repo, path)
raise ValueError("Could not find symbolic reference type suitable to handle path %r" % path)
+
+ @classmethod
+ def _to_full_path(cls, repo, path):
+ full_ref_path = path
+ if not cls._common_path_default:
+ return full_ref_path
+ if not path.startswith(cls._common_path_default+"/"):
+ full_ref_path = '%s/%s' % (cls._common_path_default, path)
+ return full_ref_path
+
+ @classmethod
+ def delete(cls, repo, path):
+ """Delete the reference at the given path
+
+ ``repo``
+ Repository to delete the reference from
+
+ ``path``
+ Short or full path pointing to the reference, i.e. refs/myreference
+ or just "myreference", hence 'refs/' is implied.
+ """
+ full_ref_path = cls._to_full_path(repo, path)
+ abs_path = os.path.join(repo.path, full_ref_path)
+ if os.path.exists(abs_path):
+ os.remove(abs_path)
+
+ @classmethod
+ def _create(cls, repo, path, resolve, reference, force):
+ """internal method used to create a new symbolic reference.
+ If resolve is False,, the reference will be taken as is, creating
+ a proper symbolic reference. Otherwise it will be resolved to the
+ corresponding object and a detached symbolic reference will be created
+ instead"""
+ full_ref_path = cls._to_full_path(repo, path)
+
+ abs_ref_path = os.path.join(repo.path, full_ref_path)
+ if not force and os.path.isfile(abs_ref_path):
+ raise OSError("Reference at %s does already exist" % full_ref_path)
+
+ ref = cls(repo, full_ref_path)
+ target = reference
+ if resolve:
+ target = Object.new(repo, reference)
+
+ ref.reference = target
+ return ref
+
+ @classmethod
+ def create(cls, repo, path, reference='HEAD', force=False ):
+ """
+ Create a new symbolic reference, hence a reference pointing to another
+ reference.
+ ``repo``
+ Repository to create the reference in
+
+ ``path``
+ full path at which the new symbolic reference is supposed to be
+ created at, i.e. "NEW_HEAD" or "symrefs/my_new_symref"
+
+ ``reference``
+ The reference to which the new symbolic reference should point to
+
+ ``force``
+ if True, force creation even if a symbolic reference with that name already exists.
+ Raise OSError otherwise
+
+ Returns
+ Newly created symbolic Reference
+
+ Note
+ This does not alter the current HEAD, index or Working Tree
+ """
+ return cls._create(repo, path, False, reference, force)
class Reference(SymbolicReference, LazyMixin, Iterable):
@@ -240,7 +315,6 @@ class Reference(SymbolicReference, LazyMixin, Iterable):
"""
__slots__ = tuple()
_common_path_default = "refs"
- _id_attribute_ = "name"
def __init__(self, repo, path):
"""
@@ -368,13 +442,6 @@ class Reference(SymbolicReference, LazyMixin, Iterable):
@classmethod
- def _to_full_path(cls, repo, path):
- full_ref_path = path
- if not path.startswith(cls._common_path_default+"/"):
- full_ref_path = '%s/%s' % (cls._common_path_default, path)
- return full_ref_path
-
- @classmethod
def create(cls, repo, path, commit='HEAD', force=False ):
"""
Create a new reference.
@@ -400,33 +467,7 @@ class Reference(SymbolicReference, LazyMixin, Iterable):
Note
This does not alter the current HEAD, index or Working Tree
"""
- full_ref_path = cls._to_full_path(repo, path)
-
- abs_ref_path = os.path.join(repo.path, full_ref_path)
- if not force and os.path.isfile(abs_ref_path):
- raise OSError("Reference at %s does already exist" % full_ref_path)
-
- obj = Object.new(repo, commit)
- ref = cls(repo, full_ref_path)
- ref.reference = obj
-
- return ref
-
- @classmethod
- def delete(cls, repo, path):
- """Delete the reference at the given path
-
- ``repo``
- Repository to delete the reference from
-
- ``path``
- Short or full path pointing to the reference, i.e. refs/myreference
- or just "myreference", hence 'refs/' is implied.
- """
- full_ref_path = cls._to_full_path(repo, path)
- abs_path = os.path.join(repo.path, full_ref_path)
- if os.path.exists(abs_path):
- os.remove(abs_path)
+ return cls._create(repo, path, True, commit, force)
class HEAD(SymbolicReference):
diff --git a/test/git/test_refs.py b/test/git/test_refs.py
index 132ec2d9..30c08081 100644
--- a/test/git/test_refs.py
+++ b/test/git/test_refs.py
@@ -239,6 +239,7 @@ class TestRefs(TestBase):
full_ref = 'refs/%s' % partial_ref
ref = Reference.create(rw_repo, partial_ref)
assert ref.path == full_ref
+ assert ref.object == rw_repo.head.commit
self.failUnlessRaises(OSError, Reference.create, rw_repo, full_ref)
Reference.delete(rw_repo, full_ref)
@@ -246,10 +247,23 @@ class TestRefs(TestBase):
# recreate the reference using a full_ref
ref = Reference.create(rw_repo, full_ref)
assert ref.path == full_ref
+ assert ref.object == rw_repo.head.commit
# recreate using force
ref = Reference.create(rw_repo, partial_ref, 'HEAD~1', force=True)
assert ref.path == full_ref
+ assert ref.object == rw_repo.head.commit.parents[0]
+
+ # create symbolic refs
+ symref_path = "symrefs/sym"
+ symref = SymbolicReference.create(rw_repo, symref_path, cur_head.reference)
+ assert symref.path == symref_path
+ assert symref.reference == cur_head.reference
+
+ self.failUnlessRaises(OSError, SymbolicReference.create, rw_repo, symref_path, cur_head.reference)
+ SymbolicReference.delete(rw_repo, symref_path)
+ # would raise if the symref wouldn't have been deleted
+ symref = SymbolicReference.create(rw_repo, symref_path, cur_head.reference)
# test symbolic references which are not at default locations like HEAD
# or FETCH_HEAD - they may also be at spots in refs of course