@@ -161,15 +161,61 @@ def dereference_recursive(cls, repo: "Repo", ref_path: Union[PathLike, None]) ->
161
161
return hexsha
162
162
# END recursive dereferencing
163
163
164
+ @staticmethod
165
+ def _check_ref_name_valid (ref_path : PathLike ) -> None :
166
+ # Based on the rules described in https://git-scm.com/docs/git-check-ref-format/#_description
167
+ previous : Union [str , None ] = None
168
+ one_before_previous : Union [str , None ] = None
169
+ for c in str (ref_path ):
170
+ if c in " ~^:?*[\\ " :
171
+ raise ValueError (
172
+ f"Invalid reference '{ ref_path } ': references cannot contain spaces, tildes (~), carets (^),"
173
+ f" colons (:), question marks (?), asterisks (*), open brackets ([) or backslashes (\\ )"
174
+ )
175
+ elif c == "." :
176
+ if previous is None or previous == "/" :
177
+ raise ValueError (
178
+ f"Invalid reference '{ ref_path } ': references cannot start with a period (.) or contain '/.'"
179
+ )
180
+ elif previous == "." :
181
+ raise ValueError (f"Invalid reference '{ ref_path } ': references cannot contain '..'" )
182
+ elif c == "/" :
183
+ if previous == "/" :
184
+ raise ValueError (f"Invalid reference '{ ref_path } ': references cannot contain '//'" )
185
+ elif previous is None :
186
+ raise ValueError (
187
+ f"Invalid reference '{ ref_path } ': references cannot start with forward slashes '/'"
188
+ )
189
+ elif c == "{" and previous == "@" :
190
+ raise ValueError (f"Invalid reference '{ ref_path } ': references cannot contain '@{{'" )
191
+ elif ord (c ) < 32 or ord (c ) == 127 :
192
+ raise ValueError (f"Invalid reference '{ ref_path } ': references cannot contain ASCII control characters" )
193
+
194
+ one_before_previous = previous
195
+ previous = c
196
+
197
+ if previous == "." :
198
+ raise ValueError (f"Invalid reference '{ ref_path } ': references cannot end with a period (.)" )
199
+ elif previous == "/" :
200
+ raise ValueError (f"Invalid reference '{ ref_path } ': references cannot end with a forward slash (/)" )
201
+ elif previous == "@" and one_before_previous is None :
202
+ raise ValueError (f"Invalid reference '{ ref_path } ': references cannot be '@'" )
203
+ elif any ([component .endswith (".lock" ) for component in str (ref_path ).split ("/" )]):
204
+ raise ValueError (
205
+ f"Invalid reference '{ ref_path } ': references cannot have slash-separated components that end with"
206
+ f" '.lock'"
207
+ )
208
+
164
209
@classmethod
165
210
def _get_ref_info_helper (
166
211
cls , repo : "Repo" , ref_path : Union [PathLike , None ]
167
212
) -> Union [Tuple [str , None ], Tuple [None , str ]]:
168
213
"""Return: (str(sha), str(target_ref_path)) if available, the sha the file at
169
214
rela_path points to, or None. target_ref_path is the reference we
170
215
point to, or None"""
171
- if ".." in str (ref_path ):
172
- raise ValueError (f"Invalid reference '{ ref_path } '" )
216
+ if ref_path :
217
+ cls ._check_ref_name_valid (ref_path )
218
+
173
219
tokens : Union [None , List [str ], Tuple [str , str ]] = None
174
220
repodir = _git_dir (repo , ref_path )
175
221
try :
0 commit comments