Add "keep both" option to dedup review

Lets a candidate be marked ignored instead of confirmed/applied; future
scans skip re-flagging the same path pair once it's been ignored, since
a rescan can flip which side ranks as keep/delete without changing the
user's earlier decision that the pair is fine as two copies. Also adds
--apply-pairs to find-fuzzy-dupes.py to apply pre-confirmed pairs
without a full rescan.
This commit is contained in:
andrew
2026-07-09 08:42:14 -06:00
parent 69804a9eb2
commit 9d1eee3337
6 changed files with 215 additions and 19 deletions
+40 -4
View File
@@ -22,11 +22,11 @@
<div class="table-wrap scroll">
<table class="dedup-table">
<colgroup>
<col style="width:2.2rem"><col style="width:7rem"><col style="width:33%">
<col style="width:33%"><col style="width:5rem"><col style="width:5rem">
<col style="width:2.2rem"><col style="width:7rem"><col style="width:30%">
<col style="width:30%"><col style="width:5rem"><col style="width:9rem">
</colgroup>
<thead>
<tr><th></th><th>Pass</th><th>Keep</th><th>Delete</th><th>Size</th><th></th></tr>
<tr><th></th><th>Pass</th><th>Keep</th><th>Delete</th><th>Size</th><th>Action</th></tr>
</thead>
<tbody>
{% for c in candidates %}
@@ -36,11 +36,15 @@
<td class="muted mono path-cell" title="{{ c.keep_path }}">{{ c.keep_display }}</td>
<td class="mono path-cell" title="{{ c.delete_path }}">{{ c.delete_display }}</td>
<td class="muted">{{ (c.delete_size_bytes / 1024 / 1024) | round(1) if c.delete_size_bytes else '?' }} MB</td>
<td>
<td class="actions-cell">
<form method="post" action="/dedup/confirm" class="inline">
<input type="hidden" name="candidate_id" value="{{ c.id }}">
<button type="submit" class="btn btn-sm btn-danger">Delete</button>
</form>
<form method="post" action="/dedup/ignore" class="inline">
<input type="hidden" name="candidate_id" value="{{ c.id }}">
<button type="submit" class="btn btn-sm btn-ghost" title="Keep both copies and never flag this pair again">Keep both</button>
</form>
</td>
</tr>
{% else %}
@@ -57,4 +61,36 @@
{% if candidates %}
<button type="submit" form="bulk-delete-form" class="btn btn-danger">Delete selected</button>
{% endif %}
{% if ignored %}
<h2>Kept both</h2>
<p class="muted" style="margin-top:-0.5rem;">Marked as legitimate alt copies -- future scans skip these pairs.</p>
<div class="table-wrap scroll">
<table class="dedup-table">
<colgroup>
<col style="width:7rem"><col style="width:34%">
<col style="width:34%"><col style="width:5rem"><col style="width:7rem">
</colgroup>
<thead>
<tr><th>Pass</th><th>Keep</th><th>Delete</th><th>Size</th><th></th></tr>
</thead>
<tbody>
{% for c in ignored %}
<tr>
<td><span class="badge badge-muted">{{ c.pass_name }}</span></td>
<td class="muted mono path-cell" title="{{ c.keep_path }}">{{ c.keep_display }}</td>
<td class="muted mono path-cell" title="{{ c.delete_path }}">{{ c.delete_display }}</td>
<td class="muted">{{ (c.delete_size_bytes / 1024 / 1024) | round(1) if c.delete_size_bytes else '?' }} MB</td>
<td>
<form method="post" action="/dedup/unignore" class="inline">
<input type="hidden" name="candidate_id" value="{{ c.id }}">
<button type="submit" class="btn btn-sm btn-ghost">Un-ignore</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
{% endblock %}