refactor(update): replace custom dep install with make install

_run_upgrade now runs `git pull && git fetch --tags && make install`
instead of the bespoke _install_system_deps function. make install is
idempotent, handles all platforms, installs system deps (transmission-
daemon, p7zip), rebuilds the Python package, and updates the CLI shim.

Remove the now-unnecessary uv binary pre-check (make install locates
it) and its stale test.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Justin Bollinger
2026-04-25 19:40:43 -04:00
parent a0af055f33
commit dc9d52d758
2 changed files with 8 additions and 66 deletions

View File

@@ -946,27 +946,8 @@ def ascii_art():
)
def _install_system_deps():
"""Best-effort install of system dependencies after an upgrade."""
import subprocess
import sys
plat = sys.platform
if plat == "darwin":
if subprocess.run(["which", "brew"], capture_output=True).returncode == 0:
print(" Installing/updating system dependencies via Homebrew...")
subprocess.run(["brew", "install", "transmission-cli", "p7zip"])
else:
print(" [!] Homebrew not found — install transmission-cli and p7zip manually.")
elif plat.startswith("linux"):
print(" Installing/updating system dependencies via apt-get...")
subprocess.run(["sudo", "apt-get", "install", "-y", "transmission-daemon", "p7zip-full"])
else:
print(f" [!] Unknown platform '{plat}' — install transmission-daemon and p7zip manually.")
def _run_upgrade():
"""Run `git pull && make clean && make && make install` in the repo root."""
"""Run `git pull && git fetch --tags && make install` in the repo root."""
import subprocess
print()
@@ -981,27 +962,16 @@ def _run_upgrade():
if git_root_result.returncode != 0:
print(
"\n Could not find a git repository to upgrade from."
"\n Run manually: git pull && git fetch --tags && uv sync --reinstall-package hate_crack\n"
"\n Run manually: git pull && git fetch --tags && make install\n"
)
raise SystemExit(1)
repo_root = git_root_result.stdout.strip()
# Locate the uv binary. It may not be in PATH when running as root or via sudo.
import shutil
uv = shutil.which("uv") or os.path.expanduser("~/.local/bin/uv")
if not os.path.isfile(uv):
print(
"\n Could not find the uv binary."
"\n Run manually: git pull && git fetch --tags && uv sync --reinstall-package hate_crack\n"
)
raise SystemExit(1)
result = subprocess.run(
# git fetch --tags ensures new release tags are visible to setuptools-scm.
# uv sync --reinstall-package forces hate_crack to be rebuilt from
# current source so setuptools-scm generates the correct version.
f"git pull && git fetch --tags && {uv} sync --reinstall-package hate_crack",
# make install handles system deps (transmission-daemon, p7zip) and
# reinstalls the Python package and CLI shim.
"git pull && git fetch --tags && make install",
shell=True,
cwd=repo_root,
)
@@ -1009,7 +979,6 @@ def _run_upgrade():
print("\n Upgrade failed. Check the output above for errors.\n")
raise SystemExit(1)
_install_system_deps()
print("\n Upgrade complete. Please restart hate_crack.\n")
raise SystemExit(0)

View File

@@ -151,18 +151,14 @@ class TestCheckForUpdates:
hc_module, "REQUESTS_AVAILABLE", True
), patch("builtins.input", return_value="y"), patch(
"subprocess.run", side_effect=[git_root_proc, make_proc]
) as mock_run, patch("shutil.which", return_value="/usr/local/bin/uv"), patch(
"os.path.isfile", return_value=True
), patch.object(hc_module, "_install_system_deps"), pytest.raises(
SystemExit
):
) as mock_run, pytest.raises(SystemExit):
mock_requests.get.return_value = mock_resp
hc_module.check_for_updates()
assert mock_run.call_count == 2
make_cmd = mock_run.call_args_list[1][0][0]
assert "git pull" in make_cmd
assert "uv sync --reinstall-package hate_crack" in make_cmd
assert "make install" in make_cmd
assert mock_run.call_args_list[1][1]["cwd"] == "/fake/repo"
output = capsys.readouterr().out
assert "Upgrade complete" in output
@@ -220,14 +216,6 @@ class TestCheckForUpdates:
class TestRunUpgrade:
"""Tests for _run_upgrade() called directly via --update flag."""
@pytest.fixture(autouse=True)
def mock_uv(self):
"""Patch shutil.which and os.path.isfile so uv is always 'found'."""
with patch("shutil.which", return_value="/usr/local/bin/uv"), patch(
"os.path.isfile", return_value=True
):
yield
def test_run_upgrade_success(self, hc_module, capsys):
git_root_proc = MagicMock()
git_root_proc.returncode = 0
@@ -237,7 +225,6 @@ class TestRunUpgrade:
make_proc.returncode = 0
with patch("subprocess.run", side_effect=[git_root_proc, make_proc]) as mock_run, \
patch.object(hc_module, "_install_system_deps"), \
pytest.raises(SystemExit) as exc:
hc_module._run_upgrade()
@@ -245,7 +232,7 @@ class TestRunUpgrade:
assert mock_run.call_count == 2
make_cmd = mock_run.call_args_list[1][0][0]
assert "git pull" in make_cmd
assert "uv sync --reinstall-package hate_crack" in make_cmd
assert "make install" in make_cmd
assert mock_run.call_args_list[1][1]["cwd"] == "/fake/repo"
output = capsys.readouterr().out
assert "Upgrade complete" in output
@@ -277,20 +264,6 @@ class TestRunUpgrade:
output = capsys.readouterr().out
assert "Run manually" in output
def test_run_upgrade_uv_not_found(self, hc_module, capsys):
git_root_proc = MagicMock()
git_root_proc.returncode = 0
git_root_proc.stdout = "/fake/repo\n"
with patch("subprocess.run", return_value=git_root_proc), patch(
"shutil.which", return_value=None
), patch("os.path.isfile", return_value=False), pytest.raises(SystemExit) as exc:
hc_module._run_upgrade()
assert exc.value.code == 1
output = capsys.readouterr().out
assert "uv binary" in output
def test_upgrade_prompt_ctrl_c_continues(self, hc_module, capsys):
mock_resp = MagicMock()
mock_resp.json.return_value = {"tag_name": "v99.0.0"}