git-annex-duplicates/git_annex_duplicates.py
2026-09-04 14:20:10 +02:00

90 lines
2.1 KiB
Python

import collections
import subprocess
from pathlib import Path
import click
def collect_files(exclude, directories):
# build command
find_cmd = [
"git",
"annex",
"find",
"--include",
"*",
"--format=${key}:${file}\n",
*directories,
]
for e in exclude:
find_cmd += ["--exclude", e]
# run
result = subprocess.run(find_cmd, capture_output=True)
# collect output
files = collections.defaultdict(list)
for l in result.stdout.decode("utf-8").split("\n"):
if l == "":
continue
key, file = l.split(":", maxsplit=1)
files[key].append(file)
return files
def print_files(fs):
for f in fs:
print(f)
def resolve_parent(p):
return p.parent.resolve() / p.stem
@click.command()
@click.option("--exclude", multiple=True, default=[])
@click.option("--across", is_flag=True, default=False)
@click.argument(
"directories",
nargs=-1,
default=["."],
type=click.Path(exists=True, file_okay=False, path_type=Path),
)
def main(exclude, across, directories):
if across and len(directories) < 2:
raise click.UsageError("--across requires at least two directories")
directories = [d.resolve() for d in directories] # for is_relative_to()
files = collect_files(exclude, directories)
for k in files:
if len(files[k]) > 1:
if not across:
print_files(files[k])
print()
else:
# A file is a duplicate across the directories iff it's in more than one
# directory.
count = 0
found_across = False
for directory in directories:
if any(
resolve_parent(Path(f)).is_relative_to(directory)
for f in files[k]
):
count += 1
if count > 1:
found_across = True
break
if found_across:
print_files(files[k])
print()
if __name__ == "__main__":
main()