fix(nix): let the install-method stamp name a home-manager install
detect_install_method reads the stamp against an allowlist. The allowlist held "nixos" but not "home-manager", and a stamp that names home-manager gave "unknown". The managed path (step 3) returned the correct name, so the gap was invisible: it appeared only for an install that carries a stamp. An install with the value "unknown" gets "hermes update" as its update guidance. That command is the one command a managed install refuses, so the user gets a dead end. The test for this was also environment-dependent. It called the real get_project_root(), and it passed here only because this worktree carries no stamp. A checkout from the curl installer carries a "git" stamp, and the assertion then failed for the contributor and not for us. The test now detects against a temporary install tree. The new test stamps each managed system and asserts the value that comes back. With the allowlist reverted, the home-manager case fails with "assert 'unknown' == 'home-manager'". The nixos case passes, because that name was already in the allowlist.
This commit is contained in:
@@ -425,7 +425,8 @@ def _install_method_project_root(project_root: Optional[Path] = None) -> Path:
|
||||
|
||||
|
||||
def detect_install_method(project_root: Optional[Path] = None) -> str:
|
||||
"""Detect how Hermes was installed: 'apt', 'docker', 'nix', 'nixos', 'git', or 'unknown'.
|
||||
"""Detect how Hermes was installed: 'apt', 'docker', 'nix', 'nixos',
|
||||
'home-manager', 'git', or 'unknown'.
|
||||
|
||||
Resolution order:
|
||||
1. Code-scoped stamp ``<install tree>/.install_method`` (next to the
|
||||
@@ -473,7 +474,10 @@ def detect_install_method(project_root: Optional[Path] = None) -> str:
|
||||
# generic Debian/Ubuntu APT signal. If another APT-managed distribution is
|
||||
# added, give it a distinct install method or make update-command selection
|
||||
# platform-aware instead of silently reusing Termux's `pkg` command.
|
||||
supported_methods = {"apt", "docker", "nix", "nixos", "git", "unknown"}
|
||||
# "home-manager" is here because step 3 can return it. A stamp must name
|
||||
# every method that this function returns. Without it, the stamp of a
|
||||
# home-manager install gives "unknown".
|
||||
supported_methods = {"apt", "docker", "nix", "nixos", "home-manager", "git", "unknown"}
|
||||
|
||||
# 1. Code-scoped stamp — authoritative, immune to shared $HERMES_HOME.
|
||||
try:
|
||||
|
||||
@@ -79,20 +79,45 @@ def test_env_var_wins_over_the_marker(hermes_home, monkeypatch):
|
||||
|
||||
@pytest.mark.parametrize("managed_value", ["nixos", "home-manager"])
|
||||
def test_managed_install_names_its_system_and_offers_an_update(
|
||||
hermes_home, monkeypatch, managed_value
|
||||
hermes_home, monkeypatch, tmp_path, managed_value
|
||||
):
|
||||
"""The message names the system, so the user knows what owns the install."""
|
||||
monkeypatch.setenv("HERMES_MANAGED", managed_value)
|
||||
|
||||
# This test uses an install tree of its own. The real checkout can carry
|
||||
# a stamp from the install shape of the contributor. A stamp answers
|
||||
# first, and detection never reaches the managed state under test.
|
||||
install_tree = tmp_path / "install"
|
||||
install_tree.mkdir()
|
||||
|
||||
assert managed_value in config_mod.format_managed_message("set model")
|
||||
assert "set model" in config_mod.format_managed_message("set model")
|
||||
assert config_mod.get_managed_update_command()
|
||||
assert config_mod.detect_install_method(config_mod.get_project_root()) == managed_value
|
||||
assert config_mod.detect_install_method(install_tree) == managed_value
|
||||
# `hermes update` cannot run on a managed install, so the advice must not
|
||||
# name it.
|
||||
assert config_mod.recommended_update_command() != "hermes update"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("managed_value", ["nixos", "home-manager"])
|
||||
def test_a_stamp_can_name_every_managed_system(
|
||||
hermes_home, monkeypatch, tmp_path, managed_value
|
||||
):
|
||||
"""A stamp must give back every value that detection can return.
|
||||
|
||||
Detection reads the stamp against an allowlist. A managed system that is
|
||||
absent from that allowlist gives "unknown". The update guidance then
|
||||
names a command that the managed guard refuses.
|
||||
"""
|
||||
monkeypatch.delenv("HERMES_MANAGED", raising=False)
|
||||
install_tree = tmp_path / "install"
|
||||
install_tree.mkdir()
|
||||
|
||||
config_mod.stamp_install_method(managed_value, project_root=install_tree)
|
||||
|
||||
assert config_mod.detect_install_method(install_tree) == managed_value
|
||||
|
||||
|
||||
def test_unmanaged_install_offers_no_update_command(hermes_home, monkeypatch):
|
||||
monkeypatch.delenv("HERMES_MANAGED", raising=False)
|
||||
assert config_mod.get_managed_update_command() is None
|
||||
|
||||
Reference in New Issue
Block a user