Skip to content

feat(locallibrary): open a snapshot as a read-only folder with store browse - #468

Open
botandbang wants to merge 4 commits into
mainfrom
bnb/store-browse
Open

botandbang wants to merge 4 commits into
mainfrom
bnb/store-browse

Conversation

@botandbang

@botandbang botandbang commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

locallibrary store browse <snapshot> opens a past version of a drive as an ordinary folder, laid out as the drive was, so it can be opened, played or dragged into another app with nothing copied. The folder goes when the command stops. macOS and Linux only: on Windows the command says it isn't available, since links there take administrator rights.

Added

  • store browse <snapshot> [--to DIR] [--keep]. It makes the view in a temporary folder, or in a new or empty folder given with --to, says where it is, and waits for Ctrl-C, SIGTERM or a closed terminal. --keep leaves it open.
  • store views, listing open views and any broken links, and store unbrowse [DIR], removing one or all of them.
  • crates/locallibrary/src/view.rs. A file is a hard link when the view is on the store's volume and a symlink otherwise. An app treats a hard link by its own name and extension, while macOS follows a symlink to the hash-named stored file and opens it as text. A file the store has lost shows as a broken symlink and is named.
  • views.json and views.lock in the store, optional and never copied, recording open views so one left by a crash is still found. store browse and store info warn about open views. store unbrowse refuses any folder that isn't recorded.
  • Property tests in props_view.rs and props_cli_view.rs, on real temporary folders: the tree matches the snapshot, in-place writes fail and leave the object's hash unchanged, nothing can be saved into a view, and closing removes everything the view made.
  • "View" in GLOSSARY.md, a section in docs/store.md, and a row in docs/commands.md and the README.

Changed

  • Stored files are read-only from when they're written (Store::keep_object, which import_file, import_bytes, offsite::fetch_object and peer fetches now share). Files from older versions change only when a view links them. store copy leaves a copy's files as they were, since a read-only file can block rename and delete on a network share.
  • A view's folders are read-only too, so an app that saves through a temp file and a rename fails, rather than leaving an edit that goes with the view.
  • store unbrowse deletes only links, read-only files and folders. A writable file someone put in a view stays and is reported.
  • store prune and library prune warn when they remove a snapshot a view shows, and go ahead. Hard links keep working and hold their space until the view is removed. Symlinks to files nothing else uses break.
  • The echo example plugin copies bytes instead of calling fs::copy, which carried a stored file's read-only permissions onto its copy and refused the next write to it. docs/plugins.md says so for plugin authors.
  • Tests that damaged a stored file by writing over it now delete it first, since that write is what this refuses. The damage and the assertions are unchanged. They're in store/tests.rs, tests/common/mod.rs (rot), store/copy.rs, props_offsite.rs, props_store.rs, peers.rs, props_peers.rs, props_cli_changes.rs and drives/store.rs.

Removed

  • The copies of "make the folder, rename into place" in offsite::fetch_object and peers::fetch.

STORE_FORMAT stays 1. Something that changes a file's permissions back can still write to it, and an app that follows a symlink and replaces the stored file gets through too. store verify finds both, and docs/store.md says so.

Needs the all-os label: the Windows paths couldn't be built on the machine this was written on.

Part of LOC-211.

…browse

store browse lays a snapshot out as its drive tree in a folder of links into the store, with
nothing copied, and removes it when the command stops. store views lists what's open and
store unbrowse removes what a crash or --keep left.

Files in the store are now read-only: a write through a link would leave a file under a hash that
isn't its content. Older files change when a view links them, so no store is walked to make one
view. STORE_FORMAT stays 1.
@botandbang
botandbang requested a review from bnb as a code owner November 5, 2026 21:24
@botandbang botandbang added the all-os Run the macOS and Windows checks on this pull request label Nov 5, 2026
@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: 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 5, 2026
@github-actions

github-actions Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Size

Compared with main. KiB are 1,024 bytes.

This pull request main Change
Client JavaScript 810.1 KiB 810.1 KiB 0 B (0%)
Client JavaScript, brotli 274.4 KiB 274.4 KiB 0 B (0%)
Client CSS 99.6 KiB 99.6 KiB 0 B (0%)
Client CSS, brotli 14.4 KiB 14.4 KiB 0 B (0%)

bnb
bnb previously approved these changes Nov 5, 2026
@github-actions

github-actions Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Rust coverage

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

Tests Lines Functions Regions
All 98.13% (92037/93789) 97.63% (15101/15467) 96.79% (204218/210989)
Hegel property tests alone 97.47% (91413/93789) 96.95% (14995/15467) 95.99% (202518/210989)

# Conflicts:
#	apps/locallibrary/GLOSSARY.md
@linear-code

linear-code Bot commented Nov 7, 2026

Copy link
Copy Markdown

LOC-211

# Conflicts:
#	apps/locallibrary/GLOSSARY.md
#	crates/locallibrary/src/store.rs

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

all-os Run the macOS and Windows checks on this pull request 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 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