diff options
Diffstat (limited to 'lib/git/repo.py')
-rw-r--r-- | lib/git/repo.py | 50 |
1 files changed, 37 insertions, 13 deletions
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 |