import subprocess from pathlib import Path import pytest import tools.sync.wiki_git as wiki_git @pytest.mark.parametrize( "value", ["", "../master", "-main", "a..b", "a b", "a.lock", "a/@{x", "a//b"] ) def test_invalid_branch_configuration_is_rejected(monkeypatch, value): monkeypatch.setenv("EXPECTED_GITEA_BRANCH", value) with pytest.raises(RuntimeError, match="EXPECTED_GITEA_BRANCH"): wiki_git.expected_branch() @pytest.mark.parametrize( "url", [ "git@git.kemt.fei.tuke.sk:jp170na/zpwiki.git", "ssh://git@git.kemt.fei.tuke.sk/jp170na/zpwiki.git", "https://git.kemt.fei.tuke.sk/jp170na/zpwiki", ], ) def test_repository_identity_from_transport_url(url): assert wiki_git.repository_from_url(url) == "jp170na/zpwiki" def test_real_git_fetch_fast_forward_and_local_change_protection(tmp_path, monkeypatch): run = subprocess.run def git(root, *args): return run( ["git", "-C", str(root), *args], capture_output=True, text=True, check=True ).stdout.strip() bare, author, checkout = (tmp_path / name for name in ("remote.git", "author", "checkout")) run(["git", "init", "--bare", str(bare)], check=True, capture_output=True) run(["git", "clone", str(bare), str(author)], check=True, capture_output=True) git(author, "checkout", "-b", "master") git(author, "config", "user.name", "Sync test") git(author, "config", "user.email", "sync@example.test") (author / "README.md").write_text("old") git(author, "add", ".") git(author, "commit", "-m", "initial") git(author, "push", "origin", "master") run(["git", "clone", str(bare), str(checkout)], check=True, capture_output=True) git(checkout, "remote", "set-url", "origin", "git@example.test:KEMT/zpwiki.git") (author / "README.md").write_text("new") git(author, "commit", "-am", "update") git(author, "push", "origin", "master") wanted = git(author, "rev-parse", "HEAD") # Exercise real Git fetch/merge against a local bare remote. Only transport # is redirected, so the production origin/branch validation still runs. def local_transport(args, **kw): if args[:2] == ["git", "fetch"]: args = [str(bare) if arg == "origin" else arg for arg in args] return run(args, **kw) monkeypatch.setattr(wiki_git.subprocess, "run", local_transport) wiki_git.update_wiki(checkout) assert git(checkout, "rev-parse", "HEAD") == wanted assert (checkout / "README.md").read_text() == "new" (checkout / "untracked.md").write_text("local notes") with pytest.raises(RuntimeError, match="lokálne zmeny"): wiki_git.update_wiki(checkout) (checkout / "untracked.md").unlink() (checkout / "README.md").write_text("local modification") with pytest.raises(RuntimeError, match="lokálne zmeny"): wiki_git.update_wiki(checkout) assert (checkout / "README.md").read_text() == "local modification" git(checkout, "restore", "README.md") monkeypatch.setenv("EXPECTED_GITEA_BRANCH", "other") with pytest.raises(RuntimeError, match="Aktívna Git vetva"): wiki_git.update_wiki(checkout) monkeypatch.setenv("EXPECTED_GITEA_BRANCH", "master") monkeypatch.setenv("EXPECTED_GITEA_REPOSITORY", "OTHER/zpwiki") with pytest.raises(RuntimeError, match="origin nezodpovedá"): wiki_git.update_wiki(checkout) monkeypatch.setenv("EXPECTED_GITEA_REPOSITORY", "KEMT/zpwiki") git(checkout, "config", "user.name", "Local author") git(checkout, "config", "user.email", "local@example.test") (checkout / "local.md").write_text("local commit") git(checkout, "add", "local.md") git(checkout, "commit", "-m", "local") local_head = git(checkout, "rev-parse", "HEAD") (author / "README.md").write_text("remote update") git(author, "commit", "-am", "remote") git(author, "push", "origin", "master") with pytest.raises(RuntimeError, match="Git operácia merge zlyhala"): wiki_git.update_wiki(checkout) assert git(checkout, "rev-parse", "HEAD") == local_head assert (checkout / "local.md").read_text() == "local commit" def test_upstream_sync_rejects_wrong_destination_before_any_write(tmp_path, monkeypatch): root = tmp_path / "wiki" (root / ".git").mkdir(parents=True) monkeypatch.setenv("SYNC_UPSTREAM_FORK", "1") seen = [] def run(args, **kwargs): seen.append(args) output = {"remote": "git@git.kemt.fei.tuke.sk:KEMT/zpwiki.git", "branch": "master", "status": ""}.get(args[1], "") return subprocess.CompletedProcess(args, 0, stdout=output, stderr="") monkeypatch.setattr(wiki_git.subprocess, "run", run) with pytest.raises(RuntimeError, match="restricted"): wiki_git.update_wiki(root) assert len(seen) == 3 assert all(args[0] == "git" for args in seen)