Newer
Older
TIASDataHub / tests / test_repo.py
"""本リポジトリの場所と git の状態.

SPEC_03「版の作成」: 未コミットの変更がある状態では版を作らない.

git の状態は `tmp_path` に作った使い捨ての git リポジトリで確かめる
(本リポジトリの状態に依存しない).
"""

import subprocess
import tomllib
from pathlib import Path

import pytest

from tiasdata.repo import find_repo_root, read_repo_state


def _git(root: Path, *args: str) -> str:
    completed = subprocess.run(
        [
            "git",
            "-c",
            "user.name=test",
            "-c",
            "user.email=test@example.invalid",
            "-c",
            "commit.gpgsign=false",
            "-c",
            "core.autocrlf=false",
            "-C",
            str(root),
            *args,
        ],
        capture_output=True,
        text=True,
        check=True,
    )
    return completed.stdout


@pytest.fixture
def git_repo(tmp_path: Path) -> Path:
    root = tmp_path / "repo"
    root.mkdir()
    _git(root, "init", "-q")
    (root / "a.txt").write_bytes(b"a\n")
    (root / ".gitignore").write_bytes(b"ignored.txt\n")
    _git(root, "add", "a.txt", ".gitignore")
    _git(root, "commit", "-q", "-m", "init")
    return root


def test_find_repo_root_is_tiasdata_project() -> None:
    root = find_repo_root()
    data = tomllib.loads((root / "pyproject.toml").read_text(encoding="utf-8"))
    assert data["project"]["name"] == "tiasdata"
    assert (root / "datasets").is_dir()


def test_clean_repo(git_repo: Path) -> None:
    state = read_repo_state(git_repo)
    assert state.commit == _git(git_repo, "rev-parse", "HEAD").strip()
    assert len(state.commit) == 40
    assert state.uncommitted == 0


def test_modified_file_is_uncommitted(git_repo: Path) -> None:
    (git_repo / "a.txt").write_bytes(b"changed\n")
    assert read_repo_state(git_repo).uncommitted == 1


def test_untracked_file_is_uncommitted(git_repo: Path) -> None:
    # 定義ファイルを追加しただけでコミットしていない場合も止める
    (git_repo / "datasets").mkdir()
    (git_repo / "datasets" / "new.toml").write_bytes(b"")
    (git_repo / "b.txt").write_bytes(b"")
    assert read_repo_state(git_repo).uncommitted == 2


def test_staged_file_is_uncommitted(git_repo: Path) -> None:
    (git_repo / "c.txt").write_bytes(b"c\n")
    _git(git_repo, "add", "c.txt")
    assert read_repo_state(git_repo).uncommitted == 1


def test_ignored_file_is_not_counted(git_repo: Path) -> None:
    (git_repo / "ignored.txt").write_bytes(b"x")
    assert read_repo_state(git_repo).uncommitted == 0


def test_not_a_git_repo_is_value_error_without_path(tmp_path: Path) -> None:
    directory = tmp_path / "not_repo_zz"
    directory.mkdir()
    with pytest.raises(ValueError) as exc:
        read_repo_state(directory)
    message = str(exc.value)
    assert "not_repo_zz" not in message
    assert str(tmp_path) not in message
    assert "\n" not in message