| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -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: | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -631,3 +631,39 @@ def test_refs_outside_repo(self): | |||
| 631 | 631 | ref_file.flush() | |
| 632 | 632 | ref_file_name = Path(ref_file.name).name | |
| 633 | 633 | self.assertRaises(BadName, self.rorepo.commit, f"../../{ref_file_name}") | |
| 634 | + | ||
| 635 | + def test_validity_ref_names(self): | ||
| 636 | + check_ref = SymbolicReference._check_ref_name_valid | ||
| 637 | + # Based on the rules specified in https://git-scm.com/docs/git-check-ref-format/#_description | ||
| 638 | + # Rule 1 | ||
| 639 | + self.assertRaises(ValueError, check_ref, ".ref/begins/with/dot") | ||
| 640 | + self.assertRaises(ValueError, check_ref, "ref/component/.begins/with/dot") | ||
| 641 | + self.assertRaises(ValueError, check_ref, "ref/ends/with/a.lock") | ||
| 642 | + self.assertRaises(ValueError, check_ref, "ref/component/ends.lock/with/period_lock") | ||
| 643 | + # Rule 2 | ||
| 644 | + check_ref("valid_one_level_refname") | ||
| 645 | + # Rule 3 | ||
| 646 | + self.assertRaises(ValueError, check_ref, "ref/contains/../double/period") | ||
| 647 | + # Rule 4 | ||
| 648 | + for c in " ~^:": | ||
| 649 | + self.assertRaises(ValueError, check_ref, f"ref/contains/invalid{c}/character") | ||
| 650 | + for code in range(0, 32): | ||
| 651 | + self.assertRaises(ValueError, check_ref, f"ref/contains/invalid{chr(code)}/ASCII/control_character") | ||
| 652 | + self.assertRaises(ValueError, check_ref, f"ref/contains/invalid{chr(127)}/ASCII/control_character") | ||
| 653 | + # Rule 5 | ||
| 654 | + for c in "*?[": | ||
| 655 | + self.assertRaises(ValueError, check_ref, f"ref/contains/invalid{c}/character") | ||
| 656 | + # Rule 6 | ||
| 657 | + self.assertRaises(ValueError, check_ref, "/ref/begins/with/slash") | ||
| 658 | + self.assertRaises(ValueError, check_ref, "ref/ends/with/slash/") | ||
| 659 | + self.assertRaises(ValueError, check_ref, "ref/contains//double/slash/") | ||
| 660 | + # Rule 7 | ||
| 661 | + self.assertRaises(ValueError, check_ref, "ref/ends/with/dot.") | ||
| 662 | + # Rule 8 | ||
| 663 | + self.assertRaises(ValueError, check_ref, "ref/contains@{/at_brace") | ||
| 664 | + # Rule 9 | ||
| 665 | + self.assertRaises(ValueError, check_ref, "@") | ||
| 666 | + # Rule 10 | ||
| 667 | + self.assertRaises(ValueError, check_ref, "ref/contain\\s/backslash") | ||
| 668 | + # Valid reference name should not raise | ||
| 669 | + check_ref("valid/ref/name") | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments