Commit c7e31a1
committed
feat(vxcore): add folder-bundle import (paths, id oracle, journaled attach)
Adds the vxcore half of "Import Folder -> Shared folder from VNote": attach a
folder bundle produced by the share feature to an existing bundled notebook
while preserving ids, timestamps, tags and attachments VERBATIM. This is
deliberately NOT vxcore_folder_import, which regenerates ids and timestamps
and therefore destroys the very identity (tag associations, history) the
import exists to keep.
New public API:
vxcore_folder_get_import_paths Destination resolution. Mirrors
vxcore_folder_get_share_paths, including
the full root-to-destination index
reachability walk, with one deliberate
difference: the notebook ROOT is a legal
destination.
vxcore_notebook_collect_node_ids The authoritative id oracle. Walks the
on-disk vx.json tree and NEVER consults
SQLite: bundled notebooks index lazily,
so a store miss proves nothing. Folder
and file ids are returned in ONE
namespace, root included, because a
cross-kind collision is just as fatal as
a same-kind one and `uuid UNIQUE` is
per-table.
vxcore_folder_attach_imported The journaled commit: publish content,
publish metadata, insert-only store
transaction, ATOMIC parent vx.json
replace (the commit point), then one
folder.created event.
vxcore_notebook_recover_imports Replays or rolls back an interrupted
import. Called on notebook open BEFORE
anything rebuilds the metadata store, so
a rolled-back import cannot leave rows a
later rebuild would resurrect.
Supporting changes:
- MetadataStore/SqliteMetadataStore/FileDb gain InsertFolder/InsertFile,
which use a plain INSERT rather than the existing INSERT OR REPLACE. The
upsert would silently REPLACE a colliding row and cascade-delete its
associations while reporting success; import must fail closed instead.
- AttachImportedFolder re-verifies id uniqueness against the on-disk walk
itself, since the caller releases its lock between check and call and the
store cannot detect a cross-kind collision at all.
- SaveFolderConfigAtomic writes a temp file, flushes it to stable storage and
renames it over the live file. The existing in-place rewrite would destroy
the destination parent's index if interrupted at the commit point.
Note the deliberate deviation from the existing import path: attach emits a
single folder.created for the imported root. Descendant creations are NOT
replayed; consumers reload the subtree from the parent.
Covered by tests/test_folder_import_bundle.cpp (13 cases), which constructs
crash states by hand at each journal phase -- the only way to test a crash
without crashing.1 parent 9b359e7 commit c7e31a1
12 files changed
Lines changed: 2159 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
300 | 300 | | |
301 | 301 | | |
302 | 302 | | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
303 | 450 | | |
304 | 451 | | |
305 | 452 | | |
| |||
0 commit comments