summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Thiel <byronimo@gmail.com>2010-11-23 17:40:41 +0100
committerSebastian Thiel <byronimo@gmail.com>2010-11-23 18:03:35 +0100
commit5bd7d44ff7e51105e3e277aee109a45c42590572 (patch)
treeea60a64f3b545158442746a695b4c51766bb6f6e
parent9ccd777c386704911734ae4c33a922a5682ac6c8 (diff)
downloadgitpython-5bd7d44ff7e51105e3e277aee109a45c42590572.tar.gz
repo.rev_parse: Added support for simple log parsing - dates are not yet supported, mainly because I don't need it
-rw-r--r--doc/source/changes.rst1
-rw-r--r--repo/fun.py62
-rw-r--r--test/test_repo.py23
3 files changed, 73 insertions, 13 deletions
diff --git a/doc/source/changes.rst b/doc/source/changes.rst
index de872e2d..725dc931 100644
--- a/doc/source/changes.rst
+++ b/doc/source/changes.rst
@@ -5,6 +5,7 @@ Changelog
0.3.2 Beta 2
============
* Added reflog support ( reading and writing )
+* Repo.rev_parse now supports the [ref]@{n} syntax, where n is the number of steps to look into the reference's past
0.3.2 Beta 1
============
diff --git a/repo/fun.py b/repo/fun.py
index a684730b..7b842c38 100644
--- a/repo/fun.py
+++ b/repo/fun.py
@@ -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,24 @@ 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
+
+ entry = ref.log()[revlog_index]
+ 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
diff --git a/test/test_repo.py b/test/test_repo.py
index 59a1f6bf..820fed26 100644
--- a/test/test_repo.py
+++ b/test/test_repo.py
@@ -467,11 +467,12 @@ class TestRepo(TestBase):
def test_rev_parse(self):
rev_parse = self.rorepo.rev_parse
- # try special case: This one failed beforehand
+ # try special case: This one failed at some point, make sure its fixed
assert rev_parse("33ebe").hexsha == "33ebe7acec14b25c5f84f35a664803fcab2f7781"
# start from reference
num_resolved = 0
+
for ref in Reference.iter_items(self.rorepo):
path_tokens = ref.path.split("/")
for pt in range(len(path_tokens)):
@@ -546,9 +547,25 @@ class TestRepo(TestBase):
# missing starting brace
self.failUnlessRaises(ValueError, rev_parse, '0.1.4^tree}')
+ # REVLOG
+ #######
+ head = self.rorepo.head
+
+ # need to specify a ref when using the @ syntax
+ self.failUnlessRaises(BadObject, rev_parse, "%s@{0}" % head.commit.hexsha)
+
+ # uses HEAD.ref by default
+ assert rev_parse('@{0}') == head.commit
+ if not head.is_detached:
+ assert rev_parse('%s@{0}' % head.ref.name) == head.ref.commit
+ #END operate on non-detached head
+
+ # the last position
+ assert rev_parse('@{1}') != head.commit
+
+ # currently, nothing more is supported
+ self.failUnlessRaises(NotImplementedError, rev_parse, "@{1 week ago}")
- # cannot handle rev-log for now
- self.failUnlessRaises(ValueError, rev_parse, "hi@there")
def test_repo_odbtype(self):
target_type = GitDB