One installation per project, and no login to reach it
Two things a local install should not have asked for. `fluksio serve` now signs you in. Logging in to your own machine was a formality — the password was printed by the same process that would have checked it, and the database it authenticates against sits in the directory the token goes into — so `serve` mints the token itself and says where it put it. `fluksio login` is left for an engine somewhere else. And an installation is `.fluksio` beside the code, found the way `.git` is, rather than one `~/.fluksio` for the machine. A repository with its own venv was already getting its own engine; it now gets its own flows, run history and token too, instead of three repositories sharing one database and fighting over one port. `--global` asks for the shared one, `--data-dir` still names any directory, and when both exist the banner says which you are looking at and how to reach the other. The directory ignores itself from within — a `.gitignore` of `*`, the way uv writes one into `.venv` — because it holds a credential and a database, and neither belongs in anybody's history. The token is written mode 600. A login an older version wrote to ~/.config/fluksio is still read, so nothing that worked stops working. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ue1tkFWB1bcGy3aWhCKpU
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
"""Which installation a command is for, and where its token lives.
|
||||
|
||||
A repository with its own venv gets its own engine, so "which one" is a fact
|
||||
about the working directory rather than about the machine.
|
||||
"""
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from fluksio.sdk import client
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def elsewhere(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> Path:
|
||||
"""A working directory with no installation above it."""
|
||||
monkeypatch.chdir(tmp_path)
|
||||
monkeypatch.setenv("XDG_CONFIG_HOME", str(tmp_path / "xdg"))
|
||||
monkeypatch.setattr(client, "GLOBAL_DATA_DIR", tmp_path / "home" / ".fluksio")
|
||||
return tmp_path
|
||||
|
||||
|
||||
def test_a_project_local_installation_is_found_from_below(elsewhere: Path):
|
||||
(elsewhere / ".fluksio").mkdir()
|
||||
deep = elsewhere / "src" / "pkg" / "sub"
|
||||
deep.mkdir(parents=True)
|
||||
|
||||
assert client.find_data_dir(deep) == elsewhere / ".fluksio"
|
||||
assert client.config_path(client.data_dir(deep)).parent.name == ".fluksio"
|
||||
|
||||
|
||||
def test_the_nearest_one_wins(elsewhere: Path):
|
||||
"""An installation inside another belongs to the directory it is in."""
|
||||
(elsewhere / ".fluksio").mkdir()
|
||||
inner = elsewhere / "inner"
|
||||
(inner / ".fluksio").mkdir(parents=True)
|
||||
|
||||
assert client.find_data_dir(inner) == inner / ".fluksio"
|
||||
|
||||
|
||||
def test_with_none_above_it_the_shared_one_answers(elsewhere: Path):
|
||||
assert client.find_data_dir() is None
|
||||
assert client.data_dir() == elsewhere / "home" / ".fluksio"
|
||||
|
||||
|
||||
def test_a_token_is_written_only_for_its_owner(elsewhere: Path):
|
||||
path = client.write_config("http://127.0.0.1:8000", "abc", elsewhere / ".fluksio")
|
||||
|
||||
assert json.loads(path.read_text()) == {
|
||||
"url": "http://127.0.0.1:8000",
|
||||
"token": "abc",
|
||||
}
|
||||
# It is a credential sitting in somebody's project directory.
|
||||
assert path.stat().st_mode & 0o077 == 0
|
||||
# And one nothing can commit by accident.
|
||||
assert (path.parent / ".gitignore").read_text().endswith("*\n")
|
||||
|
||||
|
||||
def test_the_credential_beside_the_data_is_the_one_used(elsewhere: Path):
|
||||
client.write_config("http://127.0.0.1:8131", "local", elsewhere / ".fluksio")
|
||||
|
||||
assert client._stored()["token"] == "local"
|
||||
|
||||
|
||||
def test_a_login_from_before_installations_were_local_still_works(elsewhere: Path):
|
||||
"""`fluksio login` wrote to XDG once; that must not stop answering."""
|
||||
legacy = client._legacy_config_path()
|
||||
legacy.parent.mkdir(parents=True)
|
||||
legacy.write_text(json.dumps({"url": "http://elsewhere:8000", "token": "old"}))
|
||||
|
||||
assert client._stored()["token"] == "old"
|
||||
|
||||
|
||||
def test_a_local_credential_wins_over_the_legacy_one(elsewhere: Path):
|
||||
legacy = client._legacy_config_path()
|
||||
legacy.parent.mkdir(parents=True)
|
||||
legacy.write_text(json.dumps({"url": "http://elsewhere:8000", "token": "old"}))
|
||||
client.write_config("http://127.0.0.1:8131", "local", elsewhere / ".fluksio")
|
||||
|
||||
assert client._stored()["token"] == "local"
|
||||
|
||||
|
||||
def test_ignoring_itself_leaves_an_existing_gitignore_alone(elsewhere: Path):
|
||||
directory = elsewhere / ".fluksio"
|
||||
directory.mkdir()
|
||||
(directory / ".gitignore").write_text("mine\n")
|
||||
|
||||
client.ignore_self(directory)
|
||||
|
||||
assert (directory / ".gitignore").read_text() == "mine\n"
|
||||
Reference in New Issue
Block a user