@@ -42,9 +42,13 @@ def short_to_long(odb, hexsha):
4242 # END exception handling
4343
4444
45- def name_to_object (repo , name ):
46- """:return: object specified by the given name, hexshas ( short and long )
47- as well as references are supported"""
45+ def name_to_object (repo , name , return_ref = False ):
46+ """
47+ :return: object specified by the given name, hexshas ( short and long )
48+ as well as references are supported
49+ :param return_ref: if name specifies a reference, we will return the reference
50+ instead of the object. Otherwise it will raise BadObject
51+ """
4852 hexsha = None
4953
5054 # is it a hexsha ? Try the most common ones, which is 7 to 40
@@ -59,12 +63,20 @@ def name_to_object(repo, name):
5963 for base in ('%s' , 'refs/%s' , 'refs/tags/%s' , 'refs/heads/%s' , 'refs/remotes/%s' , 'refs/remotes/%s/HEAD' ):
6064 try :
6165 hexsha = SymbolicReference .dereference_recursive (repo , base % name )
66+ if return_ref :
67+ return SymbolicReference (repo , base % name )
68+ #END handle symbolic ref
6269 break
6370 except ValueError :
6471 pass
6572 # END for each base
6673 # END handle hexsha
67-
74+
75+ # didn't find any ref, this is an error
76+ if return_ref :
77+ raise BadObject ("Couldn't find reference named %r" % name )
78+ #END handle return ref
79+
6880 # tried everything ? fail
6981 if hexsha is None :
7082 raise BadObject (name )
@@ -101,9 +113,6 @@ def rev_parse(repo, rev):
101113 :note: Currently there is no access to the rev-log, rev-specs may only contain
102114 topological tokens such ~ and ^.
103115 :raise BadObject: if the given revision could not be found"""
104- if '@' in rev :
105- raise ValueError ("There is no rev-log support yet" )
106-
107116
108117 # colon search mode ?
109118 if rev .startswith (':/' ):
@@ -112,22 +121,37 @@ def rev_parse(repo, rev):
112121 # END handle search
113122
114123 obj = None
124+ ref = None
115125 output_type = "commit"
116126 start = 0
117127 parsed_to = 0
118128 lr = len (rev )
119129 while start < lr :
120- if rev [start ] not in "^~:" :
130+ if rev [start ] not in "^~:@ " :
121131 start += 1
122132 continue
123133 # END handle start
124134
135+ token = rev [start ]
136+
125137 if obj is None :
126138 # token is a rev name
127- obj = name_to_object (repo , rev [:start ])
139+ if start == 0 :
140+ ref = repo .head .ref
141+ else :
142+ if token == '@' :
143+ ref = name_to_object (repo , rev [:start ], return_ref = True )
144+ else :
145+ obj = name_to_object (repo , rev [:start ])
146+ #END handle token
147+ #END handle refname
148+
149+ if ref is not None :
150+ obj = ref .commit
151+ #END handle ref
128152 # END initialize obj on first token
129153
130- token = rev [ start ]
154+
131155 start += 1
132156
133157 # try to parse {type}
@@ -153,6 +177,24 @@ def rev_parse(repo, rev):
153177 # cannot do anything for non-tags
154178 pass
155179 # END handle tag
180+ elif token == '@' :
181+ # try single int
182+ assert ref is not None , "Requre Reference to access reflog"
183+ revlog_index = None
184+ try :
185+ # transform reversed index into the format of our revlog
186+ revlog_index = - (int (output_type )+ 1 )
187+ except ValueError :
188+ # TODO: Try to parse the other date options, using parse_date
189+ # maybe
190+ raise NotImplementedError ("Support for additional @{...} modes not implemented" )
191+ #END handle revlog index
192+
193+ entry = ref .log ()[revlog_index ]
194+ obj = Object .new_from_sha (repo , hex_to_bin (entry .newhexsha ))
195+
196+ # make it pass the following checks
197+ output_type = None
156198 else :
157199 raise ValueError ("Invalid output type: %s ( in %s )" % (output_type , rev ))
158200 # END handle output type
0 commit comments