diff --git a/src/sdlc_hub/core/cli.py b/src/sdlc_hub/core/cli.py index 761b364..9693ee3 100644 --- a/src/sdlc_hub/core/cli.py +++ b/src/sdlc_hub/core/cli.py @@ -31,6 +31,12 @@ def main(argv=None) -> int: p.add_argument("path") args = ap.parse_args(argv) + if (problem := paths.home_problem()): + print(problem, file=sys.stderr) + return 2 + if (warning := paths.home_warning()): + print(warning, file=sys.stderr) + if args.cmd == "agent": from . import release names = [m.name for m in registry.agent_modules()] diff --git a/src/sdlc_hub/core/paths.py b/src/sdlc_hub/core/paths.py index 10ea4d1..59fb68f 100644 --- a/src/sdlc_hub/core/paths.py +++ b/src/sdlc_hub/core/paths.py @@ -10,6 +10,27 @@ def home() -> Path: return Path(os.environ.get("SDLC_HUB_HOME", str(Path.home() / ".local" / "share" / "sdlc-hub"))) +def legacy_home() -> Path: + """Каталог данных под прежним именем (до переименования в sdlc-hub).""" + return Path.home() / ".local" / "share" / "jira-hub" + + +def home_problem() -> "str | None": + """Текст отказа, если данные лежат только под прежним именем; при заданном SDLC_HUB_HOME проверки нет.""" + if os.environ.get("SDLC_HUB_HOME") or home().exists() or not legacy_home().exists(): + return None + return ("каталог данных хаба лежит под прежним именем ~/.local/share/jira-hub; перенесите его: " + "bash scripts/cutover.sh (или mv ~/.local/share/jira-hub ~/.local/share/sdlc-hub при остановленном хабе)") + + +def home_warning() -> "str | None": + """Предупреждение, если существуют оба каталога (SDLC_HUB_HOME не задан).""" + if os.environ.get("SDLC_HUB_HOME") or not (home().exists() and legacy_home().exists()): + return None + return ("есть и ~/.local/share/sdlc-hub, и ~/.local/share/jira-hub: работаю с новым, " + "прежний каталог ~/.local/share/jira-hub можно удалить после проверки") + + def db_path() -> Path: return home() / "hub.sqlite" diff --git a/tests/conftest.py b/tests/conftest.py index 55ca5a5..d3ac10d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -13,6 +13,12 @@ from sdlc_hub.modules.jira import project_fields from sdlc_hub.modules.jira import projects as jira_projects +@pytest.fixture(autouse=True) +def _isolated_home(monkeypatch, tmp_path_factory): + """HOME — во временный каталог: на результат не влияют реальные ~/.local/share/{jira,sdlc}-hub разработчика.""" + monkeypatch.setenv("HOME", str(tmp_path_factory.mktemp("home"))) + + @pytest.fixture def open_db(): """Фабрика соединений: open_db() — база в памяти, open_db(path) — файл. Все закрываются после теста.""" diff --git a/tests/test_cli.py b/tests/test_cli.py index 51bdcf1..168f641 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -2,6 +2,8 @@ import json import os from pathlib import Path +import pytest + from sdlc_hub.core import api, cli, paths, release, settings FIXTURE = Path(__file__).parent / "fixtures" / "config.example.json" @@ -103,3 +105,34 @@ def test_agent_publish_migrates_old_layout(tmp_path, monkeypatch, capsys): assert cli.main(["agent", "publish", str(new)]) == 1 # v13 < v14: «только вверх» видит прежнюю публикацию assert not (rel / "agent.py").exists() and not (rel / "manifest.json").exists() assert json.loads((rel / "jira" / "manifest.json").read_text(encoding="utf-8"))["version"] == 14 + + +def _homes(monkeypatch, tmp_path, legacy=True, new=False): + monkeypatch.delenv("SDLC_HUB_HOME", raising=False) + monkeypatch.setenv("HOME", str(tmp_path)) + share = tmp_path / ".local" / "share" + if legacy: (share / "jira-hub").mkdir(parents=True) + if new: (share / "sdlc-hub").mkdir(parents=True) + return share + + +@pytest.mark.parametrize("argv", [["serve"], ["tokens"], ["mcp", "jira"], ["agent", "publish", "x.py"]]) +def test_legacy_home_refused(monkeypatch, tmp_path, capsys, argv): + share = _homes(monkeypatch, tmp_path) + assert cli.main(argv) == 2 + err = capsys.readouterr().err + assert "~/.local/share/jira-hub" in err and "scripts/cutover.sh" in err + assert not (share / "sdlc-hub").exists() + assert sorted(p.name for p in (share / "jira-hub").iterdir()) == [] + + +def test_both_homes_warn(monkeypatch, tmp_path, capsys): + _homes(monkeypatch, tmp_path, new=True) + cli.main(["tokens"]) + assert "прежний каталог ~/.local/share/jira-hub можно удалить" in capsys.readouterr().err + + +def test_env_home_skips_legacy_check(monkeypatch, tmp_path, capsys): + _homes(monkeypatch, tmp_path) + monkeypatch.setenv("SDLC_HUB_HOME", str(tmp_path / "x")) + assert cli.main(["tokens"]) == 0