[Bug] A failed native merge wipes every file in the deck folder except deck.md #670
Labels
No labels
accepted
bug
declined
docs
duplicate
enhancement
good first issue
in-progress
needs-info
privacy
security
triage
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
LibreKAT/Ocideck#670
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What happens
In
tabs_provider_git_native.dart, theresolvecallback ofmirror.mergeRemotefalls back to keeping our own side when it cannot merge:The comment is right about the danger and wrong about the remedy.
native_git_mirror_io.dartdoesdeckAbs.delete(recursive: true)and then writes exactly the files it was handed, so a fallback of{deck.md: ourBytes}does not 'keep our side as it was' — it keeps one file and removes the rest of the deck folder.What is lost
data/*.jsonanddata/*.csv: the linked chart data. The deck reopens with the reference intact and the numbers gone.deck.user-notes.json.How to reach it
The fallback fires whenever any of base / ours / theirs fails to parse or is refused by the import gate (
gated()returns null). A deck that trips the safety scanner therefore costs you your chart data on top of the refusal — two unrelated penalties for one event.Why this is filed separately
It predates the notes work: the chart-data half has been reachable since linked chart data landed. #541 widens the blast radius but did not create it, and fixing it properly means changing what
mergeRemote/_writeAllpromise about files the resolver did not mention — a contract question, not a one-line patch.Suggested direction
Either have the resolver receive (and be able to pass back) the other files in the deck folder, or make
_writeAlladditive with an explicit delete list instead of clearing the folder first. The second matches how the REST plane already works (commitFiles(upserts:, deletes:)), which is an argument for making the two planes agree rather than inventing a third rule.Regression guard
A native-mirror test that puts a chart data file and a notes file in the deck folder, forces the fallback (unparseable
theirBytes), and asserts both survive.Aanvulling na een tweede lezing — de titel is te smal en het risico groter dan hierboven staat.
Het treft niet alleen de faaltak. Ook een geslaagde native merge verwijdert
<deckDir>/data/*.json. De resolver bouwtmerge.mergeduit de driedeck.md's en hydrateert alleen de notities, duschartDataFilesOflevert niets, dus die bestanden staan niet in wat er teruggegeven wordt — endeckAbs.delete(recursive: true)ruimt ze op. Elke merge tussen twee auteurs kost dus de cijfers van elke gekoppelde grafiek, zonder melding.En het is sinds vandaag goedkoper te repareren dan hierboven staat.
withRepoChartDataneemt dezelfdeRepoFileReaderalswithRepoUserNotes, enresolveRepoDeckMerge(PR voor #541) heeft nu per kant een lezer. De hydratatie van de grafiekdata is daarmee vrijwel dezelfde regel als die van de notities; wat nog een plek moet krijgen is waar de melding over ontbrekende bronnen heen gaat op dit pad.Dat neemt de contractvraag over
mergeRemote/_writeAllniet weg — bestanden die de resolver niet noemt, verdwijnen, en dat blijft de eigenlijke fout. Maar het maakt de tussenstap klein genoeg om niet op die contractwijziging te hoeven wachten.De regressietest moet dus twee gevallen dekken, niet één: de gelukte merge én de fallback.
Opgepakt. Tak:
fix/native-merge-deckmap-670. Reikwijdte:lib/services/git/deck_repo_serializer.dart,lib/services/git/native_git_mirror_io.dart,lib/services/git/native_git_mirror_api.dart,lib/state/tabs_provider_git_native.dart, plus een regressietest voor beide gevallen (gelukte merge én fallback).Opgelost in
48349fa7+93fa64b6(PR #676), op main sindsb6f95825.De oorzaak lag een stap eerder dan we allebei dachten. Het native openpad riep
withRepoSidecarshelemaal niet aan — dat deed alleen het REST-pad. Er stond dus een deck in de editor dat zijn eigen lagen niet kende, en omdat elke schrijfweg de deckmap vervangt, ruimde de eerstvolgende gewone opslag ze al op. Geen merge nodig, geen botsing, geen melding. Jouw aanvulling zag terecht dat ook een geslaagde merge de cijfers kostte; het was nog een slag breder dan dat.Drie plekken gerepareerd: openen hydrateert nu net als het REST-pad, samenvoegen doet dat per kant, en de terugvalweg houdt onze hele kant vast in plaats van alleen
deck.md— git's tekst-merge is daar al over de map gegaan, dus die sidecars kunnen conflictmarkeringen dragen.De contractvraag ging mee, langs jouw tweede voorstel.
mergeRemotebeloofde dat wat de resolver niet noemt weg mag; die volledigheid kón hij niet waarmaken. Nu bijwerken:filesschrijven,deletesverwijderen, de rest laten staan — hetzelfde alscommitFiles(upserts:, deletes:)op het REST-vlak.commitDeckblijft wél vervangen, want daar kent de app de hele set écht; die asymmetrie staat uitgeschreven in GIT_STORAGE §9.7.Regressietest: de twee gevallen die je vroeg, plus de gewone opslag zonder merge. Eén opmerking daarbij, want hij is leerzaam: mijn eerste versie van de terugval-test toetste tegen de origin en stond daardoor onterecht groen — bij
clean: falsewordt er niets gepusht, dus de origin bewijst daar niets. Hij toetst nu de clone, en dat is ook de plek die ertoe doet: dát is de werkkopie waar de editor uit leest.Wat er níét in zat: de ink-sidecar en het zegel reizen nog steeds niet mee naar git (§9.1); daar verandert dit niets aan. En een grafiekbestand van een dia die de merge weghaalde blijft nu als wees achter in plaats van opgeruimd te worden — een achtergebleven bestand in ruil voor geen dataverlies, dezelfde afweging als op het REST-vlak.