fix(cli,mine): shell-quote project_dir in resume hints

The "Skipped. Run mempalace mine <dir>" hint after declining the init
prompt and the "Re-run mempalace mine <dir> to resume" hint after a
Ctrl-C interruption both interpolated project_dir without shell-quoting.
A path containing spaces or metacharacters produced a copy-paste-broken
command.

Both spots now use shlex.quote(project_dir). Adds regression tests
covering each hint with a path that contains a space.
This commit is contained in:
Igor Lins e Silva
2026-04-25 01:10:17 -03:00
parent 23d534f8f3
commit 8faf0042b5
4 changed files with 50 additions and 2 deletions
+23
View File
@@ -281,6 +281,29 @@ def test_maybe_run_mine_yes_and_auto_mine_fully_noninteractive(tmp_path):
mock_mine.assert_called_once()
def test_maybe_run_mine_decline_quotes_path_with_spaces(tmp_path, capsys):
"""The resume hint must shell-quote the project dir so paths with
spaces / metacharacters produce a copy-paste-safe command."""
from mempalace.cli import _maybe_run_mine_after_init
spaced_dir = tmp_path / "my project dir"
spaced_dir.mkdir()
args = argparse.Namespace(dir=str(spaced_dir), yes=False, auto_mine=False)
cfg = _fake_cfg(tmp_path)
with (
patch("mempalace.miner.mine"),
patch("mempalace.miner.scan_project", return_value=[]),
patch("builtins.input", return_value="n"),
):
_maybe_run_mine_after_init(args, cfg)
out = capsys.readouterr().out
# shlex.quote wraps paths with spaces in single quotes.
assert f"mempalace mine '{spaced_dir}'" in out
# And the bare unquoted form is NOT printed (would break paste).
assert f"mempalace mine {spaced_dir} " not in out
assert f"mempalace mine {spaced_dir}`" not in out
def test_maybe_run_mine_eof_on_stdin_treated_as_decline(tmp_path, capsys):
"""Piped / non-interactive stdin (EOFError) declines without crashing."""
from mempalace.cli import _maybe_run_mine_after_init
+24
View File
@@ -653,6 +653,30 @@ def test_mine_keyboard_interrupt_prints_summary_and_exits_130(tmp_path, capsys):
assert "upserted idempotently" in out
def test_mine_keyboard_interrupt_quotes_path_with_spaces_in_resume_hint(tmp_path, capsys):
"""Resume hint must shell-quote the project dir so a path containing
spaces / metacharacters yields a copy-paste-safe `mempalace mine ...`
command. Otherwise users on a path like "My Project" hit a broken
invocation when they re-run after Ctrl-C."""
import pytest
from unittest.mock import patch
project_root = tmp_path / "my project"
project_root.mkdir()
_make_minable_project(project_root, n_files=2)
palace_path = project_root / "palace"
def fake_process_file(*args, **kwargs):
raise KeyboardInterrupt
with patch("mempalace.miner.process_file", side_effect=fake_process_file):
with pytest.raises(SystemExit):
mine(str(project_root), str(palace_path))
out = capsys.readouterr().out
assert f"mempalace mine '{project_root}'" in out
def test_mine_cleans_up_pid_file_on_interrupt(tmp_path):
"""Our own PID entry in mine.pid is removed in the finally clause."""
import pytest