git-annex-duplicates/test/test_cli.py
2026-09-04 14:29:51 +02:00

166 lines
3.8 KiB
Python

import subprocess
from unittest.mock import Mock
import pytest
from click.testing import CliRunner
import git_annex_duplicates
@pytest.fixture
def invoke_cli():
runner = CliRunner()
def invoke(args=None):
return runner.invoke(
git_annex_duplicates.main,
args,
prog_name="git-annex-duplicates",
)
return invoke
def mock_git_annex(monkeypatch, output):
run = Mock(
return_value=subprocess.CompletedProcess(
args=[],
returncode=0,
stdout=output.encode(),
stderr=b"",
)
)
monkeypatch.setattr(git_annex_duplicates.subprocess, "run", run)
return run
def test_help_lists_cli_options(invoke_cli):
result = invoke_cli(["--help"])
assert result.exit_code == 0
assert "Usage: git-annex-duplicates [OPTIONS] [DIRECTORIES]..." in result.output
assert "--exclude TEXT" in result.output
assert "--across" in result.output
def test_default_directory_and_duplicate_output(invoke_cli, monkeypatch, tmp_path):
monkeypatch.chdir(tmp_path)
run = mock_git_annex(
monkeypatch,
"key-a:photos/first.jpg\n"
"key-b:only-once.txt\n"
"key-a:backup/first.jpg\n"
"key-c:one.txt\n"
"key-c:two.txt\n",
)
result = invoke_cli()
assert result.exit_code == 0
assert result.output == (
"photos/first.jpg\n"
"backup/first.jpg\n"
"\n"
"one.txt\n"
"two.txt\n"
"\n"
)
run.assert_called_once_with(
[
"git",
"annex",
"find",
"--include",
"*",
"--format=${key}:${file}\n",
tmp_path,
],
capture_output=True,
check=True,
)
def test_directories_and_repeated_excludes_are_passed_to_git_annex(
invoke_cli, monkeypatch, tmp_path
):
first = tmp_path / "first"
second = tmp_path / "second"
first.mkdir()
second.mkdir()
run = mock_git_annex(monkeypatch, "")
result = invoke_cli(
[
"--exclude",
"*.iso",
"--exclude",
"archive/**",
str(first),
str(second),
],
)
assert result.exit_code == 0
assert result.output == ""
run.assert_called_once_with(
[
"git",
"annex",
"find",
"--include",
"*",
"--format=${key}:${file}\n",
first,
second,
"--exclude",
"*.iso",
"--exclude",
"archive/**",
],
capture_output=True,
check=True,
)
def test_across_only_reports_duplicates_in_different_directories(
invoke_cli, monkeypatch, tmp_path
):
first = tmp_path / "first"
second = tmp_path / "second"
first.mkdir()
second.mkdir()
monkeypatch.chdir(tmp_path)
mock_git_annex(
monkeypatch,
"same-first:first/one.txt\n"
"same-first:first/two.txt\n"
"across:first/shared.txt\n"
"across:second/shared.txt\n"
"same-second:second/one.txt\n"
"same-second:second/two.txt\n",
)
result = invoke_cli(["--across", str(first), str(second)])
assert result.exit_code == 0
assert result.output == "first/shared.txt\nsecond/shared.txt\n\n"
def test_across_requires_two_directories(invoke_cli, tmp_path):
directory = tmp_path / "only"
directory.mkdir()
result = invoke_cli(["--across", str(directory)])
assert result.exit_code == 2
assert "Error: --across requires at least two directories" in result.output
def test_rejects_a_missing_directory(invoke_cli, tmp_path):
missing = tmp_path / "missing"
result = invoke_cli([str(missing)])
assert result.exit_code == 2
assert "Directory" in result.output
assert "does not exist" in result.output