@@ -161,15 +161,61 @@ def dereference_recursive(cls, repo: "Repo", ref_path: Union[PathLike, None]) ->
161161return 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
165210def _get_ref_info_helper (
166211cls ,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+
173219tokens :Union [None ,List [str ],Tuple [str ,str ]]= None
174220repodir = _git_dir (repo ,ref_path )
175221try :