Skip to content

fix(locallibrary): keep rekordbox's demo samples out of backups - #495

Queued
botandbang wants to merge 3 commits into
mainfrom
bnb/loc-176-demo-backups
Queued

botandbang wants to merge 3 commits into
mainfrom
bnb/loc-176-demo-backups

Conversation

@botandbang

Copy link
Copy Markdown
Contributor

What and why

Fixes LOC-176.

clean deletes rekordbox's demo samples with an ordinary delete_tracks edit (plugins/demos/src/lib.rs), and a commit backs up every file it deletes (commit.rs). refresh runs clean after every export and every export brings the samples back, so a copy of the same audio went into a new backup each time. The plan also counted that copy (edit.rs), so a drive too full for it refused the clean with no_space. That formula is edit::plan's own. backup::needed_bytes, which the issue names, only serves library writes and doesn't change.

Added

  • delete_unbacked, an edit that deletes tracks as delete_tracks does and leaves their files out of the backup. The journal records it, so edits replay behaves the same way. A journal holding one is version 5, which older builds refuse.
  • library:delete-unbacked, the capability a plugin needs to ask for it. Only built-in plugins can have it, because no backup can bring those files back. edit.plan and edit.apply refuse the edit from any sidecar client.
  • BackupInfo.unbacked: the files a change deleted and left out. drive backups and undo --list count them.
  • unbacked_audio on undo.plan and drive.restore.preview: the tracks that come back without their audio.
  • ADR 0003, and Backup, Demo sample and Unbacked file in the glossary.

Changed

  • The demos plugin's clean uses delete_unbacked, so its backup holds only the databases and its space check counts only those. The plan says so: "delete 1 track(s) (rekordbox's next export brings their files back, undo can't)".
  • A plan leaves files out only when every track it deletes is unbacked. If it also deletes anything else, it backs up everything it deletes.
  • undo and drive restore no longer refuse a backup over audio a change on that drive left out on purpose. missing_audio passes over those tracks and the plan warns about them instead. This also covers older backups that list the samples. Audio gone for any other reason is refused as before.

Removed

  • restore_preview's copy of the missing_audio check (diff.rs). It calls backup::missing_audio now.

What undo can't do any more

Undoing a clean brings back the tracks, their playlist entries and the rows they used, without their audio, analysis or artwork. Those tracks stay without files until rekordbox's next export or another clean. Backups of samples taken by earlier versions stay on the drive until they're pruned as usual. A clean an earlier version recorded in the journal is replayed as it was made, with its files backed up.

How it was tested

Locally on macOS, on this branch merged with main at d7cc328: cargo coverage --workspace passed 4904 of 4904 tests, at 98.38% lines, 97.69% functions and 97.02% regions, against today's gates of 96.8%, 96.2% and 95.3%. cargo clippy --workspace --all-targets -- -D warnings is clean, also for x86_64-pc-windows-gnu, and with -p locallibrary -p locallibrary-cli --no-default-features. cargo doc with -D warnings and the doctests pass, and the contract in apps/locallibrary/docs/rpc is regenerated. An earlier full run under heavy load had one failure, doctor::tests::measured_offsets_are_the_delay_or_say_why_not, which this change doesn't touch and which passed alone and in the coverage run.

Again on main at 2cf2cf9, which only changed web files since: the contract is regenerated, clippy is clean for locallibrary, loclib-plugin, the demos plugin and locallibrary-cli, and their tests that touch cleaning, backups, undo, plugins, the manifest, the journal and the sidecar pass, 1001 of 1003 in one run. The other two timed out while the machine was busy and pass alone: a_drawn_keys_account_type_is_valid_and_broken_in_one_place_is_refused_there in 8.7 s (its limit is 60 s) and the_sound_plugin_measures_tracks in 67.7 s (120 s). Neither reaches this change.

The issue's two conditions run through the real CLI with the plugin hosted, in apps/locallibrary/tests/it/cli.rs:

  • a_refresh_leaves_no_demo_audio_in_a_backup: two exports and two refreshes, with no audio in any backup and no .wav on the drive.
  • clean_and_refresh_run_on_a_drive_too_full_to_copy_the_demo_samples: a sparse sample twice the size of the free space stops neither clean nor refresh, also with an older delete_tracks clean left on the journal. It runs on Unix only, with file writes capped at about 100 MB, so a copy of that sample fails there instead of filling the disk.

crates/locallibrary/tests/it/demos.rs covers edit.plan refusing the edit, the backup's contents, a plain delete_tracks of the same sample still being refused for space, undo saying what it can't restore, and replays. props_demos.rs has a new Hegel property for edits mixing delete_unbacked with other deletes: what the backup holds, the space the plan asks for, and edit.plan refusing the edit. cleaning_removes_exactly_the_demo_tracks now checks what undo says about the tracks that come back without audio, and that it leaves only the planned files changed. only_built_in_plugins_delete_without_a_backup is a Hegel property over drawn capability lists.

The change was broken on purpose 19 ways, one at a time, and at least one test failed each time. With the plugin put back on delete_tracks, which is the bug, 11 fail, including both CLI tests above.

demo_tracks_go_from_both_databases_and_come_back_on_undo asserted the samples' files came back. It's renamed and asserts they don't, since that's the change.

Checklist

  • Tests cover the change
  • For locallibrary: apps/locallibrary/changes/<branch>.md has a changelog line, if people using it will notice
  • The READMEs, docs/ and --help still say what the code does (apps/locallibrary/docs/rpc/ too, for a sidecar change)

Every clean copied the demo audio it deleted into its backup. A refresh runs a clean after each
export, and each export brings the samples back, so copies piled up on the drive, and a drive too
full for the copy couldn't be cleaned at all.

A clean now uses delete_unbacked, which leaves the deleted files out of the backup and out of the
space check. Undo brings the tracks back without their files and says which, in place of the
refusal for a replaced library.

Fixes LOC-176
@botandbang
botandbang requested a review from bnb as a code owner November 7, 2026 18:34
@linear-code

linear-code Bot commented Nov 7, 2026

Copy link
Copy Markdown

LOC-176

@github-actions github-actions Bot added documentation Improvements or additions to documentation locallibrary locallibrary and the loclib-* crates locallibrary: cli The locallibrary command line locallibrary: sidecar The JSON-RPC sidecar and the api module it serves locallibrary: core The core crate, the data model and rekordbox's formats locallibrary: plugins The plugin protocol, its host and the built-in plugins tests Tests, fixtures and test harnesses labels Nov 7, 2026
bnb
bnb previously approved these changes Nov 7, 2026
@github-actions

github-actions Bot commented Nov 7, 2026 •

Copy link
Copy Markdown

Size

Compared with main. KiB are 1,024 bytes.

This pull request main Change
Client JavaScript 798.5 KiB 806.1 KiB -7.5 KiB (-0.9%)
Client JavaScript, brotli 269.5 KiB 272.1 KiB -2.6 KiB (-1%)
Client CSS 98.3 KiB 99.1 KiB -765 B (-0.8%)
Client CSS, brotli 14 KiB 14.2 KiB -200 B (-1.4%)

@github-actions

github-actions Bot commented Nov 7, 2026 •

Copy link
Copy Markdown

Rust coverage

From run 572. Both are held to the thresholds in .cargo/config.toml.

Tests Lines Functions Regions
All 98.06% (90278/92064) 97.54% (14715/15086) 96.72% (200167/206955)
Hegel property tests alone 96.81% (89128/92064) 96.31% (14530/15086) 95.35% (197324/206955)

@botandbang
botandbang added this pull request to the merge queue Nov 7, 2026
Any commits made after this event will not be merged.
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Nov 7, 2026
@botandbang
botandbang added this pull request to the merge queue Nov 9, 2026
Any commits made after this event will not be merged.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation locallibrary: cli The locallibrary command line locallibrary: core The core crate, the data model and rekordbox's formats locallibrary: plugins The plugin protocol, its host and the built-in plugins locallibrary: sidecar The JSON-RPC sidecar and the api module it serves locallibrary locallibrary and the loclib-* crates tests Tests, fixtures and test harnesses

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants