diff options
author | Sebastian Thiel <byronimo@gmail.com> | 2009-11-30 10:37:05 +0100 |
---|---|---|
committer | Sebastian Thiel <byronimo@gmail.com> | 2009-11-30 10:37:05 +0100 |
commit | 4f7255c2c1d9e54fc2f6390ad3e0be504e4099d3 (patch) | |
tree | 6d40b3c9108d0728a047e8cc12632059451f0e01 | |
parent | 8775b6417b95865349a59835c673a88a541f3e13 (diff) | |
download | gitpython-4f7255c2c1d9e54fc2f6390ad3e0be504e4099d3.tar.gz |
ref: Added general method to create and delete any reference pointing to any object. They are only constrained to be located in the refs/ directory
-rw-r--r-- | lib/git/refs.py | 71 | ||||
-rw-r--r-- | test/git/test_refs.py | 17 |
2 files changed, 86 insertions, 2 deletions
diff --git a/lib/git/refs.py b/lib/git/refs.py index 338d1c36..f75d5ed7 100644 --- a/lib/git/refs.py +++ b/lib/git/refs.py @@ -178,9 +178,14 @@ class SymbolicReference(object): if write_value.startswith('ref:'): self.repo.git.symbolic_ref(self.path, write_value[5:]) return - # END non-detached handling + # END non-detached handling - fp = open(self._get_path(), "w") + path = self._get_path() + directory = os.path.dirname(path) + if not os.path.isdir(directory): + os.makedirs(directory) + + fp = open(path, "w") try: fp.write(write_value) finally: @@ -362,6 +367,68 @@ class Reference(SymbolicReference, LazyMixin, Iterable): raise ValueError("Could not find reference type suitable to handle path %r" % path) + @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. + ``repo`` + Repository to create the reference in + + ``path`` + The relative path of the reference, i.e. 'new_branch' or + feature/feature1. The path prefix 'refs/' is implied if not + given explicitly + + ``commit`` + Commit to which the new reference should point, defaults to the + current HEAD + + ``force`` + if True, force creation even if a reference with that name already exists. + Raise OSError otherwise + + Returns + Newly created Reference + + 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) + + class HEAD(SymbolicReference): """ Special case of a Symbolic Reference as it represents the repository's diff --git a/test/git/test_refs.py b/test/git/test_refs.py index 606346cf..132ec2d9 100644 --- a/test/git/test_refs.py +++ b/test/git/test_refs.py @@ -234,6 +234,23 @@ class TestRefs(TestBase): self.failUnlessRaises(GitCommandError, far_away_head.checkout) assert active_branch == active_branch.checkout(force=True) + # test reference creation + partial_ref = 'sub/ref' + full_ref = 'refs/%s' % partial_ref + ref = Reference.create(rw_repo, partial_ref) + assert ref.path == full_ref + + self.failUnlessRaises(OSError, Reference.create, rw_repo, full_ref) + Reference.delete(rw_repo, full_ref) + + # recreate the reference using a full_ref + ref = Reference.create(rw_repo, full_ref) + assert ref.path == full_ref + + # recreate using force + ref = Reference.create(rw_repo, partial_ref, 'HEAD~1', force=True) + assert ref.path == full_ref + # test symbolic references which are not at default locations like HEAD # or FETCH_HEAD - they may also be at spots in refs of course symbol_ref_path = "refs/symbol_ref" |