diff --git a/archivebox/cli/archivebox_version.py b/archivebox/cli/archivebox_version.py index 7c882fab..4922d151 100755 --- a/archivebox/cli/archivebox_version.py +++ b/archivebox/cli/archivebox_version.py @@ -133,6 +133,23 @@ def _binary_record_matches_runtime(installed, lib_dir: Path) -> bool: return True +def _binary_row_dedupe_key( + *, + display_name: str, + valid: bool, + version: str, + provider: str, + abspath: str, +) -> tuple[str, str, str, str]: + if not valid: + return (display_name, "", "", "") + try: + resolved_abspath = Path(abspath).expanduser().resolve(strict=False).as_posix() + except Exception: + resolved_abspath = abspath + return (display_name, provider, version, resolved_abspath) + + @enforce_types def version( quiet: bool = False, @@ -231,10 +248,12 @@ def version( subtitle="Full version info is only available when inside a collection [light_slate_blue]DATA DIR[/light_slate_blue]", ), ) - prnt() + prnt() prnt("[pale_green1][i] Binary Dependencies:[/pale_green1]") failures = [] + seen_failures: set[str] = set() + seen_rows: set[tuple[str, str, str, str]] = set() from archivebox.plugins.discovery import get_enabled_plugins from abx_dl.config import get_required_binary_requests @@ -352,8 +371,20 @@ def version( else: rendered_path = "[grey53]not installed[/grey53]" status = "[red]X[/red]" if plugin_enabled else "[grey53]-[/grey53]" - if plugin_enabled: + if plugin_enabled and display_name not in seen_failures: failures.append(display_name) + seen_failures.add(display_name) + + row_key = _binary_row_dedupe_key( + display_name=display_name, + valid=valid, + version=version_str if valid else "-", + provider=provider if valid else "-", + abspath=abspath, + ) + if row_key in seen_rows: + continue + seen_rows.add(row_key) emit_row( { diff --git a/archivebox/tests/test_cli_version.py b/archivebox/tests/test_cli_version.py index 33abaa12..99e71516 100644 --- a/archivebox/tests/test_cli_version.py +++ b/archivebox/tests/test_cli_version.py @@ -9,6 +9,7 @@ import re import tempfile from pathlib import Path from archivebox.config.paths import tmp_dir_socket_path_is_short_enough +from archivebox.cli.archivebox_version import _binary_row_dedupe_key from archivebox.tests.conftest import run_archivebox_cmd @@ -30,6 +31,60 @@ def _extract_location_path(output: str, key: str) -> Path: raise AssertionError(f"Did not find a {key} location line in output:\n{output}") +def test_binary_row_dedupe_key_keeps_distinct_paths_visible(tmp_path): + first_path = tmp_path / "lib" / "env" / "bin" / "node" + second_path = tmp_path / "other" / "bin" / "node" + first_path.parent.mkdir(parents=True) + second_path.parent.mkdir(parents=True) + + first = _binary_row_dedupe_key( + display_name="node", + valid=True, + version="26.0.0", + provider="env", + abspath=str(first_path), + ) + repeat = _binary_row_dedupe_key( + display_name="node", + valid=True, + version="26.0.0", + provider="env", + abspath=str(first_path), + ) + different_path = _binary_row_dedupe_key( + display_name="node", + valid=True, + version="26.0.0", + provider="env", + abspath=str(second_path), + ) + + assert repeat == first + assert different_path != first + + +def test_binary_row_dedupe_key_collapses_enabled_and_disabled_plugin_references(tmp_path): + binary_path = tmp_path / "bin" / "node" + binary_path.parent.mkdir(parents=True) + + enabled_reference = _binary_row_dedupe_key( + display_name="node", + valid=True, + version="26.0.0", + provider="env", + abspath=str(binary_path), + ) + disabled_reference = _binary_row_dedupe_key( + display_name="node", + valid=True, + version="26.0.0", + provider="env", + abspath=str(binary_path), + ) + + assert disabled_reference == enabled_reference + + def test_version_quiet_outputs_version_number(tmp_path): """Test that version --quiet outputs just the version number.""" result = run_archivebox_cmd(["version", "--quiet"]) diff --git a/etc/package.json b/etc/package.json index 3ab0ccdf..7912ac0d 100644 --- a/etc/package.json +++ b/etc/package.json @@ -1,6 +1,6 @@ { "name": "archivebox", - "version": "0.9.35rc45", + "version": "0.9.35rc46", "repository": "github:ArchiveBox/ArchiveBox", "license": "MIT", "dependencies": { diff --git a/pyproject.toml b/pyproject.toml index a04e00ff..3524a0d6 100755 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "archivebox" -version = "0.9.35rc45" +version = "0.9.35rc46" requires-python = ">=3.13" description = "Self-hosted internet archiving solution." authors = [{name = "Nick Sweeting", email = "pyproject.toml@archivebox.io"}] diff --git a/uv.lock b/uv.lock index 9d91968b..e31619e0 100644 --- a/uv.lock +++ b/uv.lock @@ -124,7 +124,7 @@ wheels = [ [[package]] name = "archivebox" -version = "0.9.35rc45" +version = "0.9.35rc46" source = { editable = "." } dependencies = [ { name = "abx-dl", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },