summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Thiel <byronimo@gmail.com>2009-11-26 11:49:58 +0100
committerSebastian Thiel <byronimo@gmail.com>2009-11-26 12:09:23 +0100
commitaaeb986f3a09c1353bdf50ab23cca8c53c397831 (patch)
tree6f0575dab0a2cd04558d854cc62d99e1fe93bd0f
parent9c92df685d6c600a0a3324dff08a4d00d829a4f5 (diff)
downloadgitpython-aaeb986f3a09c1353bdf50ab23cca8c53c397831.tar.gz
SymbolicReferences can now be at any path within the repository, there is no restriction anymore.
Added a test to assure the git commands can handle it
-rw-r--r--lib/git/cmd.py2
-rw-r--r--lib/git/index.py6
-rw-r--r--lib/git/refs.py37
-rw-r--r--test/git/test_refs.py30
4 files changed, 48 insertions, 27 deletions
diff --git a/lib/git/cmd.py b/lib/git/cmd.py
index bccfb611..6ee8f355 100644
--- a/lib/git/cmd.py
+++ b/lib/git/cmd.py
@@ -344,7 +344,7 @@ class Git(object):
"""
tokens = header_line.split()
if len(tokens) != 3:
- raise ValueError("SHA named %s could not be resolved" % tokens[0] )
+ raise ValueError("SHA named %s could not be resolved, git returned: %r" % (tokens[0], header_line.strip()) )
if len(tokens[0]) != 40:
raise ValueError("Failed to parse header: %r" % header_line)
return (tokens[0], tokens[1], int(tokens[2]))
diff --git a/lib/git/index.py b/lib/git/index.py
index 61307bb8..f4aa26c7 100644
--- a/lib/git/index.py
+++ b/lib/git/index.py
@@ -1039,10 +1039,6 @@ class IndexFile(LazyMixin, diff.Diffable):
If None, all paths in the index will be checked out. Otherwise an iterable
of relative or absolute paths or a single path pointing to files or directories
in the index is expected.
- The command will raise of files or directories do not exist in the index
- ( as opposed to the original git command who ignores them ). Additionally
- this command allows to checkout directories which is an extension to git-update-index.
-
``force``
If True, existing files will be overwritten even if they contain local modifications.
@@ -1064,6 +1060,8 @@ class IndexFile(LazyMixin, diff.Diffable):
Raise CheckoutError
If at least one file failed to be checked out. This is a summary,
hence it will checkout as many files as it can anyway.
+ If one of files or directories do not exist in the index
+ ( as opposed to the original git command who ignores them ).
Raise GitCommandError if error lines could not be parsed - this truly is
an exceptional state
"""
diff --git a/lib/git/refs.py b/lib/git/refs.py
index b0996878..3d9fa226 100644
--- a/lib/git/refs.py
+++ b/lib/git/refs.py
@@ -43,7 +43,7 @@ class Reference(LazyMixin, Iterable):
return '<git.%s "%s">' % (self.__class__.__name__, self.path)
def __eq__(self, other):
- return self.path == other.path and self.object == other.object
+ return self.path == other.path
def __ne__(self, other):
return not ( self == other )
@@ -203,34 +203,29 @@ class SymbolicReference(object):
A typical example for a symbolic reference is HEAD.
"""
- __slots__ = ("repo", "name")
+ __slots__ = ("repo", "path")
- def __init__(self, repo, name):
- if '/' in name:
- # NOTE: Actually they can be looking like ordinary refs. Theoretically we handle this
- # case incorrectly
- raise ValueError("SymbolicReferences are not located within a directory, got %s" % name)
- # END error handling
+ def __init__(self, repo, path):
self.repo = repo
- self.name = name
+ self.path = path
def __str__(self):
- return self.name
+ return self.path
def __repr__(self):
- return '<git.%s "%s">' % (self.__class__.__name__, self.name)
+ return '<git.%s "%s">' % (self.__class__.__name__, self.path)
def __eq__(self, other):
- return self.name == other.name
+ return self.path == other.path
def __ne__(self, other):
return not ( self == other )
def __hash__(self):
- return hash(self.name)
+ return hash(self.path)
def _get_path(self):
- return join_path_native(self.repo.path, self.name)
+ return join_path_native(self.repo.path, self.path)
def _get_commit(self):
"""
@@ -311,7 +306,7 @@ class SymbolicReference(object):
# 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:])
+ self.repo.git.symbolic_ref(self.path, write_value[5:])
return
# END non-detached handling
@@ -346,6 +341,10 @@ class SymbolicReference(object):
Return
Instance of SymbolicReference or HEAD
depending on the given path
+
+ Note
+ It enforces that symbolic refs in git are only found in the
+ root of the .git repository, never within a folder.
"""
if not path:
raise ValueError("Cannot create Symbolic Reference from %r" % path)
@@ -366,10 +365,10 @@ class HEAD(SymbolicReference):
_HEAD_NAME = 'HEAD'
__slots__ = tuple()
- def __init__(self, repo, name=_HEAD_NAME):
- if name != self._HEAD_NAME:
- raise ValueError("HEAD instance must point to %r, got %r" % (self._HEAD_NAME, name))
- super(HEAD, self).__init__(repo, name)
+ def __init__(self, repo, path=_HEAD_NAME):
+ if path != self._HEAD_NAME:
+ raise ValueError("HEAD instance must point to %r, got %r" % (self._HEAD_NAME, path))
+ super(HEAD, self).__init__(repo, path)
def reset(self, commit='HEAD', index=True, working_tree = False,
diff --git a/test/git/test_refs.py b/test/git/test_refs.py
index 8fa30aa1..1eceb162 100644
--- a/test/git/test_refs.py
+++ b/test/git/test_refs.py
@@ -10,6 +10,7 @@ from git import *
import git.refs as refs
from git.objects.tag import TagObject
from itertools import chain
+import os
class TestRefs(TestBase):
@@ -63,7 +64,7 @@ class TestRefs(TestBase):
types_found = set()
for ref in self.rorepo.refs:
types_found.add(type(ref))
- assert len(types_found) == 3
+ assert len(types_found) == 4
@with_rw_repo('0.1.6')
def test_head_reset(self, rw_repo):
@@ -233,7 +234,30 @@ class TestRefs(TestBase):
self.failUnlessRaises(GitCommandError, far_away_head.checkout)
assert active_branch == active_branch.checkout(force=True)
+ # 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"
+ symref = SymbolicReference(rw_repo, symbol_ref_path)
+ assert symref.path == symbol_ref_path
+ symbol_ref_abspath = os.path.join(rw_repo.path, symref.path)
+
+ # set it
+ symref.reference = new_head
+ assert symref.reference == new_head
+ assert os.path.isfile(symbol_ref_abspath)
+ assert symref.commit == new_head.commit
+
# test ref listing - assure we have packed refs
- rw_repo.git.pack_refs(all=True)
- assert rw_repo.heads
+ rw_repo.git.pack_refs(all=True, prune=True)
+ heads = rw_repo.heads
+ assert heads
+ assert new_head in heads
+ assert active_branch in heads
assert rw_repo.tags
+
+ # NOTE: It appears git-cat-file cannot resolve refs which are packed !
+ # At least it fails here for some reason
+ # Couldn't reproduce the bug in a simple example though ... lets see.
+ self.failUnlessRaises(ValueError, getattr, new_head, 'commit')
+ self.failUnlessRaises(ValueError, getattr, symref, "commit")
+