Skip to content

v0.9.2 - Times Survive a Restore, `--force-with-lease` Works, and a Directory the Tool Cannot Read No Longer Vanishes From the Snapshot

Choose a tag to compare

@github-actions github-actions released this 14 Oct 18:07
· 30 commits to main since this release

What's Changed in v0.9.2

Two more rounds of independent review went over the snapshot tool: Opus twice on the code (the second
time on code written for this release), and GLM-5.3 and Gemini on the specification. Every finding that
reproduced is fixed with a test that fails without the fix. The suite is 1049 tests; the tool and helper
changes were also run on Linux (Debian under WSL) and against a real Seafile server (CE 13.0.28) in a
scratch library.

The one that mattered most

  • A directory the tool could not read was silently missing from the snapshot. git add prints a
    warning for a directory it cannot open and exits 0, so everything under it was absent and the run
    reported success. The run now stops and names the directory; --exclude leaves it out on purpose.

Added

  • Modification times of git-stored files are restored. A snapshot that pushes to a seafile:// remote
    records them in .seafile-payload/mtimes.json and --restore puts them back (payload files already
    carried theirs). --record-mtimes / --no-record-mtimes; an explicit choice is remembered; a run with
    nothing typed follows the last snapshot. Touching a file without changing it still makes no new snapshot.
  • git push --force-with-lease is supported: a push may rewrite history over exactly the value you
    saw, and is refused as stale info if the remote moved. Updates, deletions and --dry-run.
  • A fetch no longer advertises half a repository. A refs directory that its parent listed and that then
    answers 404 is retried once and then an error.
  • macOS network mounts are recognised by the clock probe.

Fixed in the snapshot tool

  • A restore overwrote and then removed a real git file named <payload file>.part, and certified the tree.
  • A manifest path through a link to .git (tool/hooks/pre-commit) passed the "inside the destination"
    check; a hostile manifest could fill the disk before its sizes were compared.
  • A share whose clock ran 2 to 5 s behind kept a stale hash (the noise floor was wider than the racy
    window); a share that could not be probed fell back to the machine's clock; a same-size edit that put the
    old mtime back was trusted. The cache key now holds the device and the inode change time, unprobed
    shares and other devices get a one-hour margin, and whole-second mtimes are trusted (twice the margin)
    instead of being re-read on every run of a FAT or HFS+ volume.
  • --no-embedded-repos after a capturing run wrote a gitlink naming the vault's own commit; a repository
    inside a repository crashed the run; one with no commit failed every run; a junction that is itself a
    repository was followed out of the tree.
  • --payload-gc decided from a listing that could have skipped a branch (so its objects looked unused),
    and from a decision minutes old. The listing is strict and the refs are read again before the first
    deletion.
  • A pid recycled by an unrelated process blocked every later snapshot on Windows.
  • The weekly report copied the whole vault into the temporary directory and ran on a vault's first run.
  • A manifest path using a code point HFS+ ignores was accepted; flags that would be ignored are refused.

Documentation

  • Corrected: the source is "never written to" (a probe file on a network share), objects are "never
    overwritten", a payload vault can snapshot offline (it cannot), --payload-verify covers every snapshot
    (the newest only), and 0.9.1's claim that the conflict-copy warning missed dotted refs (measured on a
    real server: it did not).
  • Stated: tags must be pushed to be seen by retention; the manifest is one line; a 0.8.8 machine restores a
    payload vault's git tree only, without a warning.

Upgrading from 0.9.1

  • A directory that cannot be read now stops the run: a scheduled job that had been skipping one will fail
    until it is made readable or excluded.
  • --payload-gc stops, deleting nothing, if a ref cannot be read or a push landed while it decided.
  • A vault gets .seafile-payload/mtimes.json on its next pushing run (about 60 bytes a file; about 1.5 MB
    compressed at 100,000 files, uploaded whole each time anything changes). --no-record-mtimes opts out.
  • No file format changed; 0.9.1 vaults and remotes are read as before.

Known gaps

  • The times record is one blob, rewritten whole when any file changes (sharding it is a format change).
  • A nested repository's history, and directory times, are not captured.
  • macOS (NFD names, HFS+, utime on symlinks) is covered by reasoning and CI, not by a Mac here.

The full list, with measurements, is in CHANGELOG.md.


Full Changelog: v0.9.1...v0.9.2