nex_docus/backend/tests/test_git_service.py

79 lines
2.7 KiB
Python

import subprocess
from pathlib import Path
import pytest
from app.services.git_service import GitService
def run_git(cwd: Path, *args: str) -> str:
result = subprocess.run(["git", *args], cwd=cwd, capture_output=True, text=True, check=True)
return result.stdout.strip()
def commit_file(cwd: Path, relative_path: str, content: str, message: str) -> None:
target = cwd / relative_path
target.parent.mkdir(parents=True, exist_ok=True)
target.write_text(content, encoding="utf-8")
run_git(cwd, "add", ".")
run_git(cwd, "-c", "user.name=Test", "-c", "user.email=test@example.com", "commit", "-m", message)
@pytest.fixture
def git_fixture(tmp_path: Path):
remote = tmp_path / "remote.git"
local = tmp_path / "local"
seed = tmp_path / "seed"
remote.mkdir()
local.mkdir()
seed.mkdir()
run_git(remote, "init", "--bare", "-b", "main")
run_git(seed, "init", "-b", "main")
commit_file(seed, "docs/one.md", "one", "initial")
commit_file(seed, "other.txt", "other", "other")
run_git(seed, "remote", "add", "origin", str(remote))
run_git(seed, "push", "-u", "origin", "main")
run_git(local, "clone", "-b", "main", str(remote), ".")
return remote, local, seed
@pytest.mark.asyncio
async def test_directory_push_only_changes_selected_directory(git_fixture):
remote, local, _ = git_fixture
service = GitService()
(local / "docs/one.md").write_text("updated", encoding="utf-8")
(local / "other.txt").write_text("local-only", encoding="utf-8")
ok, message = await service.push(local, str(remote), sub_path="docs")
assert ok, message
assert run_git(local, "remote", "get-url", "origin") == str(remote)
check = Path(local.parent / "check")
run_git(local.parent, "clone", "-b", "main", str(remote), str(check))
assert (check / "docs/one.md").read_text(encoding="utf-8") == "updated"
assert (check / "other.txt").read_text(encoding="utf-8") == "other"
@pytest.mark.asyncio
async def test_whole_push_rejects_remote_ahead(git_fixture):
remote, local, seed = git_fixture
service = GitService()
commit_file(seed, "other.txt", "remote-update", "remote update")
run_git(seed, "push", "origin", "main")
(local / "docs/one.md").write_text("local-update", encoding="utf-8")
ok, message = await service.push(local, str(remote))
assert not ok
assert "先执行整库拉取" in message
@pytest.mark.asyncio
async def test_credentials_are_not_written_to_remote_url(git_fixture):
remote, local, _ = git_fixture
service = GitService()
ok, message = await service.pull(local, str(remote), username="user", token="secret")
assert ok, message
assert "secret" not in run_git(local, "remote", "get-url", "origin")