eval-only option

This commit is contained in:
randogoth 2026-01-01 20:45:46 +02:00
parent 3969251220
commit fd7ff14ac6
3 changed files with 26 additions and 18 deletions

View file

@ -124,9 +124,11 @@ Apply environment variables defined in `[variables]` and propagate them to syste
```bash ```bash
curator env curator env
# then, to update this shell: # then, to update this shell:
eval "$(curator env --eval)" eval "$(curator env --eval-only)"
``` ```
Use `curator env --eval-only` in shell init files if you want each shell to export the current `[variables]` values without touching `environment.d` or systemd/DBus.
## Configuration ## Configuration
### inventory.toml ### inventory.toml
@ -243,7 +245,7 @@ PAGER = "less -R"
Notes: Notes:
- Values are imported into the user systemd and DBus environments during `curator switch` or `curator env`. - Values are imported into the user systemd and DBus environments during `curator switch` or `curator env`.
- To update a currently running shell, run `eval "$(curator env --eval)"` after applying. - To update a currently running shell, run `eval "$(curator env --eval-only)"` after applying.
- Later shell init files (e.g., `.bashrc`, `.zshrc`) can still override these values. - Later shell init files (e.g., `.bashrc`, `.zshrc`) can still override these values.
#### `[dotfiles]` #### `[dotfiles]`

View file

@ -1146,18 +1146,20 @@ def apply_inline_updates(entry_args: list[str], add: bool) -> None:
log_success(f"Updated section [{section}] in {curator_toml}") log_success(f"Updated section [{section}] in {curator_toml}")
def env_command(eval_mode: bool = False) -> None: def env_command(eval_only: bool = False) -> None:
curator_dir, curator_toml, _, _ = get_paths() curator_dir, curator_toml, _, _ = get_paths()
if not curator_toml.exists(): if not curator_toml.exists():
log_error("inventory.toml not found. Run 'curator init' first.") log_error("inventory.toml not found. Run 'curator init' first.")
sys.exit(1) sys.exit(1)
config = parse_config(curator_toml) config = parse_config(curator_toml)
variables, removed_keys = apply_environment_variables( if eval_only:
config, curator_dir, quiet=eval_mode, propagate=True env_home = Path(os.environ.get("XDG_CONFIG_HOME", Path.home() / ".config")).expanduser()
) env_file = env_home / "environment.d" / "20-curator.conf"
existing_keys = _read_environment_file_keys(env_file)
variables = {k.strip(): str(v) for k, v in config.variables.items() if k.strip()}
removed_keys = existing_keys - set(variables)
if eval_mode:
exports: list[str] = [] exports: list[str] = []
for key, value in sorted(variables.items()): for key, value in sorted(variables.items()):
exports.append(f"export {key}={_format_env_value(value)}") exports.append(f"export {key}={_format_env_value(value)}")
@ -1167,8 +1169,9 @@ def env_command(eval_mode: bool = False) -> None:
print("\n".join(exports)) print("\n".join(exports))
return return
apply_environment_variables(config, curator_dir, propagate=True)
log_info("To update your current shell now, run:") log_info("To update your current shell now, run:")
print(' eval "$(curator env --eval)"') print(' eval "$(curator env --eval-only)"')
def status_command() -> None: def status_command() -> None:
@ -1290,9 +1293,9 @@ def build_parser() -> argparse.ArgumentParser:
remove_parser.add_argument("entries", nargs="+", help="Entries in the form section:value") remove_parser.add_argument("entries", nargs="+", help="Entries in the form section:value")
env_parser = subparsers.add_parser("env", help="Apply environment variables immediately") env_parser = subparsers.add_parser("env", help="Apply environment variables immediately")
env_parser.add_argument( env_parser.add_argument(
"--eval", "--eval-only",
action="store_true", action="store_true",
help='Print export/unset statements for the current shell (use with: eval "$(curator env --eval)")', help='Print export/unset statements for the current shell only (use with: eval "$(curator env --eval-only)")',
) )
subparsers.add_parser("status", help="Show current configuration status") subparsers.add_parser("status", help="Show current configuration status")
subparsers.add_parser("help", help="Show help message") subparsers.add_parser("help", help="Show help message")
@ -1316,7 +1319,7 @@ def main(argv: list[str] | None = None) -> None:
elif args.command == "remove": elif args.command == "remove":
apply_inline_updates(args.entries, add=False) apply_inline_updates(args.entries, add=False)
elif args.command == "env": elif args.command == "env":
env_command(eval_mode=args.eval) env_command(eval_only=args.eval_only)
elif args.command == "status": elif args.command == "status":
status_command() status_command()
elif args.command == "help": elif args.command == "help":

View file

@ -239,21 +239,24 @@ def test_env_command_eval_outputs_exports(tmp_path: Path, monkeypatch, capsys) -
""" """
[variables] [variables]
EDITOR = "nvim" EDITOR = "nvim"
OLD = "1"
""".strip() """.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(): def fake_get_paths():
return curator_dir, env_file, curator_dir / "last", curator_dir / "rollback" return curator_dir, env_file, curator_dir / "last", curator_dir / "rollback"
def fake_apply_environment_variables(config, path, quiet=False, propagate=False): def fail_apply_environment_variables(*_args, **_kwargs):
assert quiet is True raise AssertionError("apply_environment_variables should not be called in eval-only mode")
assert propagate is True
return {"EDITOR": "nvim"}, {"OLD"}
monkeypatch.setattr(cli, "get_paths", fake_get_paths) monkeypatch.setattr(cli, "get_paths", fake_get_paths)
monkeypatch.setattr(cli, "apply_environment_variables", fake_apply_environment_variables) monkeypatch.setattr(cli, "apply_environment_variables", fail_apply_environment_variables)
cli.env_command(eval_mode=True) cli.env_command(eval_only=True)
out = capsys.readouterr().out.strip().splitlines() out = capsys.readouterr().out.strip().splitlines()
assert out == ["export EDITOR=nvim", "unset OLD"] assert out == ["export EDITOR=nvim", "unset OLD"]