summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/git/refs.py4
-rw-r--r--lib/git/repo.py50
-rw-r--r--test/git/test_refs.py2
-rw-r--r--test/git/test_repo.py24
4 files changed, 55 insertions, 25 deletions
diff --git a/lib/git/refs.py b/lib/git/refs.py
index a466e419..23d45ed0 100644
--- a/lib/git/refs.py
+++ b/lib/git/refs.py
@@ -808,10 +808,6 @@ class TagReference(Reference):
raise ValueError( "Tag %s points to a Blob or Tree - have never seen that before" % self )
@property
- def tree(self):
- return self.commit.tree
-
- @property
def tag(self):
"""
:return: Tag object this tag ref points to or None in case
diff --git a/lib/git/repo.py b/lib/git/repo.py
index 8e97adee..5a1af920 100644
--- a/lib/git/repo.py
+++ b/lib/git/repo.py
@@ -750,12 +750,31 @@ class Repo(object):
return Object.new_from_sha(self, hex_to_bin(hexsha))
# END object by name
+ def deref_tag(tag):
+ while True:
+ try:
+ tag = tag.object
+ except AttributeError:
+ break
+ # END dereference tag
+ return tag
+
+ def to_commit(obj):
+ if obj.type == 'tag':
+ obj = deref_tag(obj)
+
+ if obj.type != "commit":
+ raise ValueError("Cannot convert object %r to type commit" % obj)
+ # END verify type
+ return obj
+ # END commit converter
+
obj = None
output_type = "commit"
start = 0
parsed_to = 0
lr = len(rev)
- while start < lr and start != -1:
+ while start < lr:
if rev[start] not in "^~:":
start += 1
continue
@@ -781,17 +800,17 @@ class Repo(object):
pass # default
elif output_type == 'tree':
try:
- obj = obj.tree
- except AttributeError:
+ obj = to_commit(obj).tree
+ except (AttributeError, ValueError):
pass # error raised later
# END exception handling
elif output_type in ('', 'blob'):
- while True:
- try:
- obj = obj.object
- except AttributeError:
- break
- # END dereference tag
+ if obj.type == 'tag':
+ obj = deref_tag(tag)
+ else:
+ # cannot do anything for non-tags
+ pass
+ # END handle tag
else:
raise ValueError("Invalid output type: %s ( in %s )" % (output_type, rev))
# END handle output type
@@ -808,17 +827,20 @@ class Repo(object):
# try to parse a number
num = 0
if token != ":":
+ found_digit = False
while start < lr:
if rev[start] in digits:
num = num * 10 + int(rev[start])
start += 1
+ found_digit = True
else:
break
# END handle number
# END number parse loop
# no explicit number given, 1 is the default
- if num == 0:
+ # It could be 0 though
+ if not found_digit:
num = 1
# END set default num
# END number parsing only if non-blob mode
@@ -827,13 +849,15 @@ class Repo(object):
parsed_to = start
# handle hiererarchy walk
try:
+ obj = to_commit(obj)
if token == "~":
for item in xrange(num):
obj = obj.parents[0]
# END for each history item to walk
elif token == "^":
# must be n'th parent
- obj = obj.parents[num-1]
+ if num:
+ obj = obj.parents[num-1]
elif token == ":":
if obj.type != "tree":
obj = obj.tree
@@ -841,10 +865,10 @@ class Repo(object):
obj = obj[rev[start:]]
parsed_to = lr
else:
- raise "Invalid token: %r" % token
+ raise ValueError("Invalid token: %r" % token)
# END end handle tag
except (IndexError, AttributeError):
- raise BadObject("Invalid Revision")
+ raise BadObject("Invalid Revision in %s" % rev)
# END exception handling
# END parse loop
diff --git a/test/git/test_refs.py b/test/git/test_refs.py
index 44a8ed95..b73d574b 100644
--- a/test/git/test_refs.py
+++ b/test/git/test_refs.py
@@ -40,8 +40,6 @@ class TestRefs(TestBase):
assert isinstance( tagobj.tagger_tz_offset, int )
assert tagobj.message
assert tag.object == tagobj
- assert tag.tree.type == 'tree'
- assert tag.tree == tag.commit.tree
# can't assign the object
self.failUnlessRaises(AttributeError, setattr, tag, 'object', tagobj)
# END if we have a tag object
diff --git a/test/git/test_repo.py b/test/git/test_repo.py
index f1609266..89c7f6b5 100644
--- a/test/git/test_repo.py
+++ b/test/git/test_repo.py
@@ -394,7 +394,12 @@ class TestRepo(TestBase):
"""tries multiple different rev-parse syntaxes with the given name
:return: parsed object"""
rev_parse = self.rorepo.rev_parse
- obj = rev_parse(name)
+ orig_obj = rev_parse(name)
+ if orig_obj.type == 'tag':
+ obj = orig_obj.object
+ else:
+ obj = orig_obj
+ # END deref tags by default
# try history
rev = name + "~"
@@ -404,10 +409,9 @@ class TestRepo(TestBase):
# history with number
ni = 11
- history = list()
- citer = obj.traverse()
+ history = [obj.parents[0]]
for pn in range(ni):
- history.append(citer.next())
+ history.append(history[-1].parents[0])
# END get given amount of commits
for pn in range(11):
@@ -430,11 +434,14 @@ class TestRepo(TestBase):
self._assert_rev_parse_types(rev, obj2)
# END for each parent
- return obj
+ return orig_obj
def test_rev_parse(self):
rev_parse = self.rorepo.rev_parse
+ # it works with tags !
+ self._assert_rev_parse('0.1.4')
+
# start from reference
num_resolved = 0
for ref in Reference.iter_items(self.rorepo):
@@ -447,7 +454,6 @@ class TestRepo(TestBase):
num_resolved += 1
except BadObject:
print "failed on %s" % path_section
- raise
# is fine, in case we have something like 112, which belongs to remotes/rname/merge-requests/112
pass
# END exception handling
@@ -467,6 +473,12 @@ class TestRepo(TestBase):
# dereference tag using ^{} notation
+ # ref^0 returns commit being pointed to, same with ref~0
+ tag = rev_parse('0.1.4')
+ for token in ('~^'):
+ assert tag.object == rev_parse('0.1.4%s0' % token)
+ # END handle multiple tokens
+
# missing closing brace commit^{tree
# missing starting brace