diff options
-rw-r--r-- | lib/git/repo.py | 20 | ||||
-rw-r--r-- | test/git/test_repo.py | 40 |
2 files changed, 46 insertions, 14 deletions
diff --git a/lib/git/repo.py b/lib/git/repo.py index 5a1af920..e9dfabcd 100644 --- a/lib/git/repo.py +++ b/lib/git/repo.py @@ -71,7 +71,8 @@ class Repo(object): # precompiled regex re_whitespace = re.compile(r'\s+') re_hexsha_only = re.compile('^[0-9A-Fa-f]{40}$') - re_hexsha_shortened = re.compile('^[0-9A-Fa-f]{7:40}$') + re_hexsha_shortened = re.compile('^[0-9A-Fa-f]{7,40}$') + re_hexsha_domain = re.compile('^[0-9A-Fa-f]{1,40}$') re_author_committer_start = re.compile(r'^(author|committer)') re_tab_full_line = re.compile(r'^\t(.*)$') @@ -724,7 +725,7 @@ class Repo(object): def name_to_object(name): hexsha = None - # is it a hexsha ? + # is it a hexsha ? Try the most common ones, which is 7 to 40 if self.re_hexsha_shortened.match(name): if len(name) != 40: # find long sha for short sha @@ -744,6 +745,11 @@ class Repo(object): # tried everything ? fail if hexsha is None: + # it could also be a very short ( less than 7 ) hexsha, which + # wasnt tested in the first run + if len(name) < 7 and self.re_hexsha_domain.match(name): + raise NotImplementedError() + # END try short name raise BadObject(name) # END assert hexsha was found @@ -806,7 +812,7 @@ class Repo(object): # END exception handling elif output_type in ('', 'blob'): if obj.type == 'tag': - obj = deref_tag(tag) + obj = deref_tag(obj) else: # cannot do anything for non-tags pass @@ -815,8 +821,9 @@ class Repo(object): raise ValueError("Invalid output type: %s ( in %s )" % (output_type, rev)) # END handle output type - if obj.type != output_type: - raise ValueError("Could not accomodate requested object type %s, got %s" % (output_type, obj.type)) + # empty output types don't require any specific type, its just about dereferencing tags + if output_type and obj.type != output_type: + raise ValueError("Could not accomodate requested object type %r, got %s" % (output_type, obj.type)) # END verify ouput type start = end+1 # skip brace @@ -849,12 +856,13 @@ class Repo(object): parsed_to = start # handle hiererarchy walk try: - obj = to_commit(obj) if token == "~": + obj = to_commit(obj) for item in xrange(num): obj = obj.parents[0] # END for each history item to walk elif token == "^": + obj = to_commit(obj) # must be n'th parent if num: obj = obj.parents[num-1] diff --git a/test/git/test_repo.py b/test/git/test_repo.py index 89c7f6b5..b2891378 100644 --- a/test/git/test_repo.py +++ b/test/git/test_repo.py @@ -381,6 +381,9 @@ class TestRepo(TestBase): def _assert_rev_parse_types(self, name, rev_obj): rev_parse = self.rorepo.rev_parse + if rev_obj.type == 'tag': + rev_obj = rev_obj.object + # tree and blob type obj = rev_parse(name + '^{tree}') assert obj == rev_obj.tree @@ -439,9 +442,6 @@ class TestRepo(TestBase): 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): @@ -461,29 +461,53 @@ class TestRepo(TestBase): # END for each reference assert num_resolved + # it works with tags ! + tag = self._assert_rev_parse('0.1.4') + assert tag.type == 'tag' + # try full sha directly ( including type conversion ) + assert tag.object == rev_parse(tag.object.hexsha) + self._assert_rev_parse_types(tag.object.hexsha, tag.object) # multiple tree types result in the same tree: HEAD^{tree}^{tree}:CHANGES + rev = '0.1.4^{tree}^{tree}' + assert rev_parse(rev) == tag.object.tree + assert rev_parse(rev+':CHANGES') == tag.object.tree['CHANGES'] + # try to get parents from first revision - it should fail as no such revision # exists + first_rev = "33ebe7acec14b25c5f84f35a664803fcab2f7781" + commit = rev_parse(first_rev) + assert len(commit.parents) == 0 + assert commit.hexsha == first_rev + self.failUnlessRaises(BadObject, rev_parse, first_rev+"~") + self.failUnlessRaises(BadObject, rev_parse, first_rev+"^") + + # short SHA1 + commit2 = rev_parse(first_rev[:20]) + assert commit2 == commit + commit2 = rev_parse(first_rev[:5]) + assert commit2 == commit + # todo: dereference tag into a blob 0.1.7^{blob} - quite a special one + # needs a tag which points to a blob - # dereference tag using ^{} notation - # ref^0 returns commit being pointed to, same with ref~0 + # ref^0 returns commit being pointed to, same with ref~0, and ^{} tag = rev_parse('0.1.4') - for token in ('~^'): - assert tag.object == rev_parse('0.1.4%s0' % token) + for token in (('~0', '^0', '^{}')): + assert tag.object == rev_parse('0.1.4%s' % token) # END handle multiple tokens # missing closing brace commit^{tree + self.failUnlessRaises(ValueError, rev_parse, '0.1.4^{tree') # missing starting brace + self.failUnlessRaises(ValueError, rev_parse, '0.1.4^tree}') - # not enough parents ^10 # cannot handle rev-log for now self.failUnlessRaises(ValueError, rev_parse, "hi@there") |