from __future__ import annotations import os import unittest from pkgmgr.actions.review import ReviewError from tests.integration.test_review import git, write from tests.integration.test_review_hardening import MODULE, ReviewRepoCase INVISIBLE = "".join( map( chr, ( *range(0x202A, 0x202F), *range(0x2066, 0x206A), *range(0x200B, 0x2010), 0x061C, 0xFEFF, ), ) ) RLO, LRI, ZWSP, BOM = map(chr, (0x202E, 0x2066, 0x200B, 0xFEFF)) HIDDEN = "
  • Index entry {} is marked {}: its worktree changes are not shown.
  • " ATTRIBUTE_BINARY = ( "{} is shown as binary because {}, not because of its content: " "run git diff --text to see it." ) UNSET = "a gitattributes entry unsets its diff attribute" DRIVER = "its gitattributes diff driver {0} sets diff.{0}.binary" def marks(text: str) -> str: return "".join(f"<U+{ord(char):04X}>" for char in text) class TestReviewConcealment(ReviewRepoCase): def test_replace_objects_cannot_mask_the_index(self) -> None: evil = self._object("blob", "print('evil')\n") benign = self._object("blob", "print('staged')\n") git(self.repo, "update-index", "--cacheinfo", f"100644,{evil},app.py") git(self.repo, "replace", evil, benign) git(self.repo, "update-index", "--skip-worktree", "app.py") git(self.repo, "update-index", "--assume-unchanged", "lib.py") write(self._path("lib.py"), b"print('hidden')\n") html = self._render(None, []) self.assertIn("print('evil')", html) self.assertNotIn("print('staged')", html) self.assertIn(HIDDEN.format("app.py", "skip-worktree"), html) self.assertIn(HIDDEN.format("lib.py", "assume-unchanged"), html) def test_ignored_submodule_change_is_shown(self) -> None: sub = self._submodule(self.repo, "sub", "\tignore = all\n") git(sub, "commit", "--allow-empty", "-m", "two") new = git(sub, "rev-parse", "HEAD") git(self.repo, "update-index", "--cacheinfo", f"160000,{new},sub") gitmodules = self._render(None, []) write(self._path(".gitmodules"), MODULE.format("sub", "").encode()) git(self.repo, "config", "diff.ignoreSubmodules", "all") config = self._render(None, []) for source, html in (("gitmodules", gitmodules), ("config", config)): with self.subTest(source=source): self.assertIn(f"Subproject commit {new}", html) def test_attribute_binary_is_warned(self) -> None: write(self._path(".gitattributes"), b"*.txt -diff\n") write(self._path(".git", "info", "attributes"), b"*.md binary\n") write(self._path("plain.txt"), b"plain text\n") write(self._path("readme.md"), b"# readme\n") write(self._path("image.bin"), b"\x00\x01binary\n") git(self.repo, "add", ".gitattributes", "plain.txt", "readme.md", "image.bin") html = self._render(None, []) self.assertIn('data-path="image.bin"', html) for path in ("plain.txt", "readme.md"): self.assertIn(f"
  • {ATTRIBUTE_BINARY.format(path, UNSET)}
  • ", html) for path in ("image.bin", "new.txt"): self.assertNotIn(f"{path} is shown as binary", html) def test_binary_diff_driver_is_warned(self) -> None: write(self._path(".gitattributes"), b"*.dat diff=opaque\n*.bin diff=plain\n") git(self.repo, "config", "diff.opaque.binary", "yes") write(self._path("data.dat"), b"text data\n") write(self._path("image.bin"), b"\x00\x01binary\n") git(self.repo, "add", ".gitattributes", "data.dat", "image.bin") html = self._render(None, []) self.assertIn('data-path="image.bin"', html) warning = ATTRIBUTE_BINARY.format("data.dat", DRIVER.format("opaque")) self.assertIn(f"
  • {warning}
  • ", html) self.assertNotIn("image.bin is shown as binary", html) def test_base_resolves_the_branch_not_a_shadow(self) -> None: head = git(self.repo, "rev-parse", "HEAD") git(self.repo, "update-ref", "refs/tags/main", head) tag_shadow = self._render("main", []) write(self._path(".git", "main"), f"{head}\n".encode()) dir_shadow = self._render("main", []) for html in (tag_shadow, dir_shadow): self.assertIn('id="commits" data-commits="1"', html) self.assertIn("
    Base
    refs/heads/main @ ", html) def test_base_refuses_ambiguous_and_other_refs(self) -> None: head = git(self.repo, "rev-parse", "HEAD") git(self.repo, "update-ref", "refs/remotes/main", head) git(self.repo, "update-ref", "refs/tags/v1", head) cases = { "main": "ambiguous base ref", "refs/tags/v1": "unknown base ref", "HEAD~1": "unknown base ref", head: "unknown base ref", } for base, message in cases.items(): with ( self.subTest(base=base), self.assertRaisesRegex(ReviewError, message), ): self._render(base, []) def test_invisible_characters_are_marked(self) -> None: tree = git(self.repo, "rev-parse", "HEAD^{tree}") message = f"fix{RLO}: subject\n\nbody{LRI}text" commit = git(self.repo, "commit-tree", tree, "-p", "HEAD", "-m", message) git(self.repo, "update-ref", "HEAD", commit) write(self._path(f"evil{RLO}txt.py"), f"code{ZWSP}line{BOM}\n".encode()) note = os.path.join(self.root, "note.txt") write(note, f"note{INVISIBLE}\n".encode()) html = self._render("main", [note]) for char in INVISIBLE: self.assertNotIn(char, html, f"U+{ord(char):04X}") self.assertIn(f"fix{marks(RLO)}: subject", html) self.assertIn(f"body{marks(LRI)}text", html) self.assertIn(f"evil{marks(RLO)}txt.py", html) self.assertIn(f"code{marks(ZWSP)}line{marks(BOM)}", html) self.assertIn(f"note{marks(INVISIBLE)}", html) if __name__ == "__main__": unittest.main()