Skip to content

refactor(locallibrary)!: rekordbox's demo tracks are found by a check and removed by the demos plugin - #247

Merged
botandbang merged 4 commits into
mainfrom
bnb/clean-plugin
Oct 25, 2026
Merged

botandbang merged 4 commits into
mainfrom
bnb/clean-plugin

Conversation

@botandbang

Copy link
Copy Markdown
Contributor

What and why

locallibrary clean (removing the demo tracks rekordbox ships in its collection, which every export puts back on a drive) was a core command with its own plan, apply, render and RPC methods. It's now a first-party plugin, demos, and the first one that contributes a check.

Added:

  • plugins/demos/: the plugin. Its tracks check (on by default, run with check and doctor) reports the demo tracks on a drive as one info finding naming them, fixed by its clean operation. clean has cli = "clean", so locallibrary clean [DRIVE] [--dry-run] [--yes] still works, and it's offered in the player's drive menu and palette like any plugin operation. The demo track list (DEMO_TRACKS) moved here from core. It reads the drive's combined library (both databases) and plans one delete_tracks edit naming the tracks' audio files, each once. A demo track whose file a track of the DJ's also uses stays, with a warning, since the edit names tracks by file. The id is demos rather than clean so plugin list says what it's about, not what it does.
  • The plugin is registered as NEW_PROJECT.md says: its folder in plugins/ and the CLI's dependency on it (build.rs links in every folder there, and the CLI's tests read the shipped plugins from them), docs/plugins.md, the layout in docs/how-it-works.md and a CHANGELOG entry. No area label fits it (locallibrary: plugins already covers plugins/**).
  • Tests: the plugin's own tests over pipes with a fake host, including a Hegel property that clean deletes exactly the files of the demo tracks no other track shares, each once, and the check names exactly those tracks. In the library's tests, demos.rs, props_demos.rs (from props_clean.rs) and props_disk2_demos.rs (from props_disk2_clean.rs) serve the real plugin in process, answer its read with the host's own drive.library, and plan and apply its edits on fixture and drawn drives. That covers both databases, OneLibrary-only tracks and drives, files shared with other tracks, audio outside Contents/, an unreadable OneLibrary or exportExt.pdb, rekordbox's playlist sync, OneLibrary artwork, stale plans and undo.

Changed:

  • delete_tracks edits (crates/locallibrary/src/edit.rs). This is what lets the plugin remove everything clean removed:
    • Deleting a track removes every row of its audio file in each database. Before this, only the last row was deleted, while the file was still deleted along with the plan's tracks_removed, which already counted every row. That left a row pointing at a deleted file.
    • A path may name a track only the drive's other database lists, when OneLibrary has drifted from export.pdb. That track is deleted there, listed in tracks_removed, and its files go. Op::DeleteTracks carries these files as elsewhere, which a database without them leaves alone.
    • Replayed (edits replay, and a refresh's replay step right after its clean), a delete whose tracks are all gone does nothing, noting them, rather than being skipped as an edit selecting nothing.
    • Deleting a playlist with its tracks and packing a drive leave out a track whose file a kept track shares. replace_track refuses a duplicate on the keeper's own file.
  • refresh's first step (clean) is the demos plugin's clean operation, planned and planned again the way a refresh runs any plugin operation (OperationStep::again). Skipped, it says so; without the plugin hosted, it says "the demos plugin isn't there"; with no demo tracks, "no demo samples on the drive". docs/editing.md's list of refresh steps says whose operation it is.
  • The helpers other writes share (removable_files, analysis_files) move from clean.rs to track_files.rs, and open_plus moves to onelibrary.
  • clean's plan is now an edit plan, so it's journaled, its backup reason is "before editing", and its output is the edit plan's.
  • The library's test of a refresh running plugin operations (plugins::jobs) no longer expects a clean step to run, since the demos plugin isn't hosted there: the second operation is still planned again on the drive as the first left it.
  • The labeler's test-plugin glob pointed at crates/locallibrary/examples/test-plugin, which no longer exists. It now points at crates/locallibrary/src/bin/test-plugin.

Removed:

  • From core: clean::plan, clean::apply, CleanPlan, CleanReport, USELESS_TRACKS and unused_lookups (edits prune unused lookup rows themselves). Also api::clean_plan and api::clean_apply, and the tests that only covered them. LineageOp::Clean stays, since drives record it.
  • From the CLI: the clean command and its renderers. The plugin's cli takes its place.
  • From the RPC: clean.plan and clean.apply. Desktop apps use plugins.op.plan {plugin: "demos", operation: "clean", context: {drive}} and plugins.op.apply. docs/rpc was regenerated.

How it was tested

  • cargo fmt --all --check, cargo clippy --workspace --all-targets --locked -- -D warnings, git diff --check: clean.
  • cargo nextest run --locked -p locallibrary -p locallibrary-plugin-demos -p locallibrary-plugin-tracklist: 2132 tests, all passing.
  • cargo nextest run --locked -p locallibrary-cli: 1067 tests, all passing. That includes locallibrary clean through the hosted plugin (cli, drives::sync), refresh running it first and its replay step finding the sample gone (jobs), the check's place in plugin checks and the player's check settings form, and docs/rpc being current (regenerated with LOCALLIBRARY_BLESS=1).
  • I broke the ported assertions on purpose to check that they fail. With the OneLibrary-only rows left out of a delete, demos::a_demo_track_only_onelibrary_lists_goes_too fails. With the plugin no longer leaving out demo tracks that share a file with another track, props_demos::cleaning_removes_exactly_the_demo_tracks and the plugin's own property both fail.
  • cargo clippy -p locallibrary-cli --no-default-features --locked -- -D warnings, cargo deny --locked check advisories bans licenses sources and tools/policy.sh (60/60 policy tests, 41 conftest checks) pass.

New app or plugin

  • I went through Adding an app or plugin and did every step for this kind of project, and Repo checks passes
  • The steps no check sees are done too: CODEOWNERS if someone else reviews it, a changelog line, and READMEs that say what it does

Checklist

  • Tests cover the change
  • For locallibrary: apps/locallibrary/CHANGELOG.md has a line under Unreleased, 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)

… demos plugin's clean

`locallibrary clean` moves out of the library into a first-party plugin, demos, the first that
contributes a check. Its check lists the demo tracks on a drive in `check` and doctor, fixed by its
`clean` operation, which keeps the command's place on the command line and is `refresh`'s first
step. The demo track list lives in the plugin.

The plugin's plan is one `delete_tracks` edit naming the tracks' audio files, so a delete now
removes every row of a named file (two rows can share one, and the file goes with them) and may
name a track only OneLibrary lists, which is deleted there; replayed, one whose tracks are gone
does nothing. Deleting a playlist with its tracks, packing a drive and replacing a track leave
alone a file a kept track shares.

The core clean plan and apply, the CLI command, and the `clean.plan` and `clean.apply` RPC methods
are gone; the helpers other writes share move to track_files.rs and `onelibrary::open_plus`.
# Conflicts:
#	apps/locallibrary/CHANGELOG.md
#	apps/locallibrary/docs/how-it-works.md
#	apps/locallibrary/docs/plugins.md
#	apps/locallibrary/docs/sidecar.md
#	apps/locallibrary/src/plugins.rs
#	apps/locallibrary/tests/it/plugins.rs
#	crates/locallibrary/Cargo.toml
#	crates/locallibrary/tests/it/props_api.rs
@botandbang
botandbang requested a review from bnb as a code owner October 25, 2026 14:57
@github-actions github-actions Bot added documentation Improvements or additions to documentation dependencies Pull requests that update a dependency file locallibrary locallibrary and the loclib-* crates locallibrary: cli The locallibrary command line locallibrary: player The terminal player and its waveforms 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: tracklists Reading tracklists and finding their tracks locallibrary: plugins The plugin protocol, its host and the built-in plugins tests Tests, fixtures and test harnesses tooling Repo config, lint and build tooling, and GitHub settings labels Oct 25, 2026
@github-actions

github-actions Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

Size

Compared with main. KiB are 1,024 bytes.

This pull request main Change
Client JavaScript 619.1 KiB 619.1 KiB 0 B (0%)
Client JavaScript, brotli 204.5 KiB 204.5 KiB 0 B (0%)
Client CSS 87.6 KiB 87.6 KiB 0 B (0%)
Client CSS, brotli 12.5 KiB 12.5 KiB 0 B (0%)

@github-actions

github-actions Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

Rust coverage

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

Tests Lines Functions Regions
All 97.42% (79353/81455) 96.51% (12656/13114) 95.71% (174331/182140)
Hegel property tests alone 95.38% (77689/81455) 93.79% (12299/13114) 93.42% (170159/182140)

bnb
bnb previously approved these changes Oct 25, 2026
@botandbang
botandbang marked this pull request as draft October 25, 2026 18:02
# Conflicts:
#	apps/locallibrary/CHANGELOG.md
#	apps/locallibrary/Cargo.toml
@botandbang
botandbang marked this pull request as ready for review October 25, 2026 18:16
@botandbang
botandbang merged commit 874ca28 into main Oct 25, 2026
92 of 94 checks passed
@botandbang
botandbang deleted the bnb/clean-plugin branch October 25, 2026 19:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file 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: player The terminal player and its waveforms 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: tracklists Reading tracklists and finding their tracks locallibrary locallibrary and the loclib-* crates tests Tests, fixtures and test harnesses tooling Repo config, lint and build tooling, and GitHub settings

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants