diff options
author | Sebastian Thiel <byronimo@gmail.com> | 2010-11-23 17:40:41 +0100 |
---|---|---|
committer | Sebastian Thiel <byronimo@gmail.com> | 2010-11-23 18:03:35 +0100 |
commit | 5bd7d44ff7e51105e3e277aee109a45c42590572 (patch) | |
tree | ea60a64f3b545158442746a695b4c51766bb6f6e | |
parent | 9ccd777c386704911734ae4c33a922a5682ac6c8 (diff) | |
download | gitpython-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.rst | 1 | ||||
-rw-r--r-- | repo/fun.py | 62 | ||||
-rw-r--r-- | test/test_repo.py | 23 |
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 |