Repository navigation
fix(locallibrary): let sync go ahead after a merge that took in the whole source - #518
Queued
botandbang wants to merge 3 commits into
Queued
botandbang wants to merge 3 commits into
botandbang wants to merge 3 commits into
Conversation
…hole source A merge recorded only the target's new state, so the two drives still compared as diverged and the sync the docs suggest next was refused. A merge that leaves nothing of the source out now records the source's state in the target's lineage first, and its plan lists the tracks both drives have that differ. Undoing the merge takes that record back out.
SizeCompared with main. KiB are 1,024 bytes.
|
bnb
previously approved these changes
Nov 9, 2026
Rust coverageFrom run 614. Both are held to the thresholds in .cargo/config.toml.
|
… allocation budget Planning a merge fingerprinted the source and compared every matched track by formatting each field and building analysis keys, which took the 500-track merge plan 25% over its allocation budget. Planning now stamps the source's database files from the scan it already makes, and the fingerprint is taken only when the merge is applied. Analysis files are compared by size, since their times differ between any two drives exported apart, and their keys are built in one reused buffer. track_field_changes formats only the fields that differ, which also cuts what comparing two 2,000-track libraries allocates by a quarter, so that budget is lowered to match.
bnb
previously approved these changes
Nov 9, 2026
… costs Comparing tracks formats only the fields that differ, so checking two 500-track drives allocates 2.1% less: 205,609 on CI against a limit of 210,117, past the 1% tolerance the ratchet allows.
bnb
approved these changes
Nov 9, 2026
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What and why
The docs say that when both drives changed, you
mergeand thensync(commands.md:307).mergerecorded only the target's new state and the source's id (merge.rs:982, commit.rs:416), so the source's fingerprint never entered the target's lineage,has_heldstayed false (device.rs:227) and the drives still compared as diverged (compare.rs:401). The nextsyncrefused.Added to the merge plan:
differing_tracks: source tracks the target already has whose details (the fieldsdiffcompares), file path, or analysis files (the size of the DAT, EXT and 2EX, since their modification times differ between any two drives exported apart) differ. The target's versions stay, so a later sync copies them over the source's. The CLI lists them under the new-track count.takes_in_source: whether the merge leaves nothing of the source out. That means the whole library is selected (no--only), playlists are merged (not--playlists none), every source track is new or matched (none skipped for a missing file, an unsafe path or details too long), and history lists come along or the target has them already. The CLI says either way what the sync after it will do.Changed:
merged_in. The target then counts as having been through the source's state, so compare calls it newer andsynccopies it over the source. The record is only written as part of applying a plan that already listed the differing tracks.commit::Optionshas aheldentry for that record.merged_inrecords made after that backup was taken, so an undone merge leaves the drives diverged instead of letting a sync overwrite the source with the pre-merge target.compare's lists, so--allshows all of them (it showed 15 before).loclib-model'strack_field_changesis public, so the merge plan compares tracks the waydiffdoes.track_field_changesformats only the fields that differ, and analysis keys are built in one reused buffer. That keeps the 500-track merge plan within its allocation budget, and it cuts what comparing two 2,000-track libraries allocates by a quarter, socompare.2k's limits come down to 51,034 allocations and 5,589,600 bytes.docs/commands.md: the merge-then-sync workflow passes--historyand says which merges leave the drives diverged. The RPC schema and TypeScript types are regenerated for the new plan fields and lineage op.Added: a changelog line in
apps/locallibrary/changes/loc-235-merge-records-source.md.Fixes LOC-235
How it was tested
merge::diverged::a_merge_that_takes_in_the_source_lets_sync_go_ahead(hegel) syncs drive A onto B, exports a different new track to each, and maybe edits a shared track's comment on A, so the two compare as diverged. For each of five outcomes it then plans a merge of A into B and either stops there, applies it whole, applies it for one playlist, applies it with--playlists none, or applies it and undoes it. A whole merge's plan lists the edited track (and only it) as differing and says it takes in the source. After a whole merge, B compares newer,syncgoes ahead, and A ends up with B's library files. In every other case the drives still compare as diverged andsyncrefuses withdiverged.With the lineage record turned off, the whole merge leaves the drives diverged, which is the bug, and the test fails there. With the undo cleanup turned off, the undone merge still compares newer and the test fails there too. With both in, it passes, along with every
mergetest andprops_merge.The
locallibrary,locallibrary-cliandloclib-modelsuites pass (4058 tests).cargo fmt --check, workspace clippy, clippy with--no-default-features, and clippy forx86_64-pc-windows-gnuare clean.cargo coverage --workspaceon macOS: lines 98.34%, functions 97.70%, regions 97.02% (gates 96.8, 96.2, 95.3).tools/hegel-coverage.sh: lines 97.12%, functions 96.50%, regions 95.66%. Those runs were before the merge plan's lists moved into the shared helper, a change that only removed an unreached line. After it, the tests reach every new line in merge.rs, commit.rs, backup.rs and render.rs.Checklist
apps/locallibrary/changes/loc-235-merge-records-source.mdhas a changelog linedocs/and--helpstill say what the code does (apps/locallibrary/docs/rpc/too)