Commit Graph

2 Commits

Author SHA1 Message Date
andrew 92e5326437 Fix dedup apply lock-hang, mawk-broken tag passes; add track delete, fix button/select CSS
confirm_and_apply no longer marks candidates confirmed before their apply
job actually succeeds (a stuck/skipped_lock run was silently vanishing
confirmed deletes without deleting anything), switches the fuzzy pass to
--apply-pairs to avoid a full rescan on every confirm, and adds a job
timeout so a hung subprocess can't hold the global pipeline lock forever.

dedup-library.sh's Pass 2-4 use gawk-only features (gensub, POSIX interval
regex) but were running under mawk (Debian's default awk) in the deployed
image, throwing silent syntax errors on every run -- switched those
invocations to gawk explicitly and added it to the Dockerfile.

Also: per-track delete button on the library list/detail pages, and two
CSS fixes (the primary button's hover gradient was getting clobbered by
the base .btn:hover rule's plain background, and the select dropdown
arrow had no background-size so it rendered oversized).
2026-07-09 09:12:02 -06:00
andrew 270c9c0ed1 Add manual fix / manual import services and routers
library_edit.update_track_fields: single-track tag edits via `beet modify
-y -m` (subprocess with an argument list, not beets.library.Library
in-process -- an arg-list subprocess has no shell-injection surface to
avoid in the first place, and correctly reuses beets' own configured
path-format/move logic rather than reimplementing it against a hand-built
Library object with guessed config). Every changed field gets a
manual_fix_audit row with old/new values; triggers a Navidrome rescan
afterward if anything changed. Uses "genres" (plural) as the field name,
matching this deployment's actual beets column and every existing script's
convention, not the generic beets docs' singular "genre".

genre_fix.set_artist_genre and retag.retag_from_url wrap the existing
fix-genre.sh and fix-track-metadata.py as callable services rather than
reimplementing their per-format mutagen tag-writing logic.

manual_import: ties pipeline_runner.run_import_track to the manual_imports
table, mirrors import-track.sh's own argument-count-based disambiguation
(0/1/2 args), plus import-me/ listing and upload-with-path-traversal-guard.

routers/library.py + routers/import_.py: browsable library list, a track
detail/edit page (tag edit, artist-wide genre override, retag-from-URL
forms), and the import page (upload + trigger). Minimal templates for now,
Task 9 covers full UI polish.

Verified update_track_fields end-to-end against a REAL beets library (not
mocked): generated a tagged FLAC with ffmpeg/metaflac, imported it via a
real `beet import`, edited artist+title through the service, and confirmed
the file was physically moved to the new path-template location, tags were
rewritten on disk, the DB updated, and both changes landed correctly in
manual_fix_audit. Also verified the full app boots with the new routers
registered and all four new routes correctly redirect to login when
unauthenticated.
2026-07-08 14:01:35 -06:00