@@ -161,15 +161,61 @@ def dereference_recursive(cls, repo: "Repo", ref_path: Union[PathLike, None]) ->
161161 return hexsha
162162 # END recursive dereferencing
163163
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+
164209 @classmethod
165210 def _get_ref_info_helper (
166211 cls , repo : "Repo" , ref_path : Union [PathLike , None ]
167212 ) -> Union [Tuple [str , None ], Tuple [None , str ]]:
168213 """Return: (str(sha), str(target_ref_path)) if available, the sha the file at
169214 rela_path points to, or None. target_ref_path is the reference we
170215 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+
173219 tokens : Union [None , List [str ], Tuple [str , str ]] = None
174220 repodir = _git_dir (repo , ref_path )
175221 try :
0 commit comments