from pathlib import Path import datetime as dt from curator import cli def test_parse_config_line_format(tmp_path: Path) -> None: config_path = tmp_path / "inventory.toml" config_path.write_text( """ [curator] version = "1.0" last_switch = "" [copr] copr.fedorainfracloud.org/user/repo [dnf] git vim [brew] wget [flatpak] org.mozilla.firefox [rpm-ostree] podman [nix] nixpkgs#git [dotfiles] ".bashrc" = ".bashrc" [options] backup = true backup_dir = "backup" """.strip() ) config = cli.parse_config(config_path) assert config.copr == ["copr.fedorainfracloud.org/user/repo"] assert config.packages == ["git", "vim"] assert config.brew_packages == ["wget"] assert config.flatpak_refs == ["org.mozilla.firefox"] assert config.rpm_ostree_packages == ["podman"] assert config.nix_packages == ["nixpkgs#git"] assert config.dotfiles == {".bashrc": ".bashrc"} assert config.options["backup"] is True def test_parse_config_legacy_format(tmp_path: Path) -> None: config_path = tmp_path / "inventory.toml" config_path.write_text( """ [dnf] git vim [brew] wget [flatpak] org.mozilla.firefox [rpm-ostree] podman [nix] nixpkgs#git [variables] EDITOR = "nvim" [copr] copr.fedorainfracloud.org/user/repo [dotfiles] ".bashrc" = ".bashrc" """.strip() ) config = cli.parse_config(config_path) assert config.packages == ["git", "vim"] assert config.brew_packages == ["wget"] assert config.flatpak_refs == ["org.mozilla.firefox"] assert config.rpm_ostree_packages == ["podman"] assert config.nix_packages == ["nixpkgs#git"] assert config.copr == ["copr.fedorainfracloud.org/user/repo"] assert config.dotfiles == {".bashrc": ".bashrc"} assert config.variables == {"EDITOR": "nvim"} def test_diff_items() -> None: added, removed = cli.diff_items(["a", "b"], ["b", "c"]) assert added == ["a"] assert removed == ["c"] def test_update_last_switch_creates_backup(tmp_path: Path) -> None: config_dir = tmp_path config_path = config_dir / "inventory.toml" config_path.write_text( """ [curator] version = "1.0" last_switch = "" """.strip() ) options = {"backup": True, "backup_dir": "backup"} cli.update_last_switch(config_path, options) lines = [line.strip() for line in config_path.read_text().splitlines() if line.strip()] last_switch_line = [line for line in lines if line.startswith("last_switch")] assert last_switch_line, "last_switch should be written" ts_str = last_switch_line[0].split("=", 1)[1].strip().strip('"') dt.datetime.fromisoformat(ts_str) backup_dir = config_dir / "backup" backups = list(backup_dir.iterdir()) assert backups, "expected a backup of inventory.toml to be created" assert any(path.name.startswith("inventory.toml.") for path in backups) def test_reset_previous_config(tmp_path: Path, monkeypatch) -> None: rollback = tmp_path / "inventory.toml.rollback" rollback.write_text("prev") def fake_get_paths(): return tmp_path, tmp_path / "inventory.toml", tmp_path / "inventory.toml.last", rollback monkeypatch.setattr(cli, "get_paths", fake_get_paths) cli.reset_previous_config() assert not rollback.exists() def test_update_section_entries_rewrites_section(tmp_path: Path) -> None: config_path = tmp_path / "inventory.toml" config_path.write_text( """ [dnf] git [copr] copr.fedorainfracloud.org/user/repo [brew] wget """.strip() ) cli.update_section_entries(config_path, "dnf", ["vim", "curl", "vim"]) cli.update_section_entries(config_path, "copr", ["copr.fedorainfracloud.org/user/repo", "copr.fedorainfracloud.org/another/repo"]) content = config_path.read_text().strip().splitlines() dnf_index = content.index("[dnf]") assert content[dnf_index + 1 : dnf_index + 3] == ["curl", "vim"] assert "[copr]" in content copr_index = content.index("[copr]") assert content[copr_index + 1 : copr_index + 3] == [ "copr.fedorainfracloud.org/another/repo", "copr.fedorainfracloud.org/user/repo", ] def test_merge_section_entries_preserves_spacing(tmp_path: Path) -> None: config_path = tmp_path / "inventory.toml" config_path.write_text( """ [dnf] git [brew] wget """.strip() ) cli.merge_section_entries(config_path, "dnf", {"vim"}, set()) lines = config_path.read_text().splitlines() assert "" in lines, "expected to keep a blank line between sections" dnf_index = lines.index("[dnf]") brew_index = lines.index("[brew]") assert lines[dnf_index + 1 : dnf_index + 3] == ["git", "vim"] assert lines[brew_index - 1] == "" def test_apply_environment_variables(tmp_path: Path, monkeypatch) -> None: curator_dir = tmp_path / "curator" curator_dir.mkdir() env_home = tmp_path / "xdg" monkeypatch.setenv("XDG_CONFIG_HOME", str(env_home)) config = cli.empty_config() config.variables = {"EDITOR": "nvim", "WITH_SPACE": "some value"} config.options["backup"] = False written, removed = cli.apply_environment_variables(config, curator_dir) env_file = env_home / "environment.d" / "20-curator.conf" assert env_file.exists() lines = env_file.read_text().splitlines() assert "EDITOR=nvim" in lines assert 'WITH_SPACE="some value"' in lines assert written == {"EDITOR": "nvim", "WITH_SPACE": "some value"} assert removed == set() def test_apply_environment_variables_removes_file_when_empty(tmp_path: Path, monkeypatch) -> None: curator_dir = tmp_path / "curator" curator_dir.mkdir() env_home = tmp_path / "xdg" env_dir = env_home / "environment.d" env_dir.mkdir(parents=True, exist_ok=True) env_file = env_dir / "20-curator.conf" env_file.write_text("OLD=1\n") monkeypatch.setenv("XDG_CONFIG_HOME", str(env_home)) config = cli.empty_config() config.options["backup"] = False variables, removed = cli.apply_environment_variables(config, curator_dir) assert not env_file.exists() assert variables == {} assert removed == {"OLD"} def test_env_command_eval_outputs_exports(tmp_path: Path, monkeypatch, capsys) -> None: curator_dir = tmp_path / "curator" curator_dir.mkdir() env_file = curator_dir / "inventory.toml" env_file.write_text( """ [variables] EDITOR = "nvim" """.strip() ) env_home = tmp_path / "xdg" env_dir = env_home / "environment.d" env_dir.mkdir(parents=True, exist_ok=True) env_conf = env_dir / "20-curator.conf" env_conf.write_text("OLD=1\n") monkeypatch.setenv("XDG_CONFIG_HOME", str(env_home)) def fake_get_paths(): return curator_dir, env_file, curator_dir / "last", curator_dir / "rollback" def fail_apply_environment_variables(*_args, **_kwargs): raise AssertionError("apply_environment_variables should not be called in eval-only mode") monkeypatch.setattr(cli, "get_paths", fake_get_paths) monkeypatch.setattr(cli, "apply_environment_variables", fail_apply_environment_variables) cli.env_command(eval_only=True) out = capsys.readouterr().out.strip().splitlines() assert out == ["export EDITOR=nvim", "unset OLD"]