summaryrefslogtreecommitdiff
path: root/repo/fun.py
diff options
context:
space:
mode:
Diffstat (limited to 'repo/fun.py')
-rw-r--r--repo/fun.py69
1 files changed, 58 insertions, 11 deletions
diff --git a/repo/fun.py b/repo/fun.py
index a0f66fe5..c523a3e1 100644
--- a/repo/fun.py
+++ b/repo/fun.py
@@ -1,5 +1,5 @@
"""Package with general repository related functions"""
-
+import os
from gitdb.exc import BadObject
from git.refs import SymbolicReference
from git.objects import Object
@@ -42,9 +42,13 @@ def short_to_long(odb, hexsha):
# END exception handling
-def name_to_object(repo, name):
- """:return: object specified by the given name, hexshas ( short and long )
- as well as references are supported"""
+def name_to_object(repo, name, return_ref=False):
+ """
+ :return: object specified by the given name, hexshas ( short and long )
+ as well as references are supported
+ :param return_ref: if name specifies a reference, we will return the reference
+ instead of the object. Otherwise it will raise BadObject
+ """
hexsha = None
# is it a hexsha ? Try the most common ones, which is 7 to 40
@@ -59,12 +63,20 @@ def name_to_object(repo, name):
for base in ('%s', 'refs/%s', 'refs/tags/%s', 'refs/heads/%s', 'refs/remotes/%s', 'refs/remotes/%s/HEAD'):
try:
hexsha = SymbolicReference.dereference_recursive(repo, base % name)
+ if return_ref:
+ return SymbolicReference(repo, base % name)
+ #END handle symbolic ref
break
except ValueError:
pass
# END for each base
# END handle hexsha
-
+
+ # didn't find any ref, this is an error
+ if return_ref:
+ raise BadObject("Couldn't find reference named %r" % name)
+ #END handle return ref
+
# tried everything ? fail
if hexsha is None:
raise BadObject(name)
@@ -101,9 +113,6 @@ def rev_parse(repo, rev):
:note: Currently there is no access to the rev-log, rev-specs may only contain
topological tokens such ~ and ^.
:raise BadObject: if the given revision could not be found"""
- if '@' in rev:
- raise ValueError("There is no rev-log support yet")
-
# colon search mode ?
if rev.startswith(':/'):
@@ -112,22 +121,37 @@ def rev_parse(repo, rev):
# END handle search
obj = None
+ ref = None
output_type = "commit"
start = 0
parsed_to = 0
lr = len(rev)
while start < lr:
- if rev[start] not in "^~:":
+ if rev[start] not in "^~:@":
start += 1
continue
# END handle start
+ token = rev[start]
+
if obj is None:
# token is a rev name
- obj = name_to_object(repo, rev[:start])
+ if start == 0:
+ ref = repo.head.ref
+ else:
+ if token == '@':
+ ref = name_to_object(repo, rev[:start], return_ref=True)
+ else:
+ obj = name_to_object(repo, rev[:start])
+ #END handle token
+ #END handle refname
+
+ if ref is not None:
+ obj = ref.commit
+ #END handle ref
# END initialize obj on first token
- token = rev[start]
+
start += 1
# try to parse {type}
@@ -153,6 +177,29 @@ def rev_parse(repo, rev):
# cannot do anything for non-tags
pass
# END handle tag
+ elif token == '@':
+ # try single int
+ assert ref is not None, "Requre Reference to access reflog"
+ revlog_index = None
+ try:
+ # transform reversed index into the format of our revlog
+ revlog_index = -(int(output_type)+1)
+ except ValueError:
+ # TODO: Try to parse the other date options, using parse_date
+ # maybe
+ raise NotImplementedError("Support for additional @{...} modes not implemented")
+ #END handle revlog index
+
+ try:
+ entry = ref.log_entry(revlog_index)
+ except IndexError:
+ raise BadObject("Invalid revlog index: %i" % revlog_index)
+ #END handle index out of bound
+
+ obj = Object.new_from_sha(repo, hex_to_bin(entry.newhexsha))
+
+ # make it pass the following checks
+ output_type = None
else:
raise ValueError("Invalid output type: %s ( in %s )" % (output_type, rev))
# END handle output type