Skip to content

v0.9.3 - The Third Review Round: `gc` Re-reads Refs Before Deleting, the Windows Hash Cache Sees In-Place Edits, and a Release Pre-flight

Choose a tag to compare

@github-actions github-actions released this 15 Oct 03:33
· 41 commits to main since this release

What's Changed in v0.9.3

Three independent reviews (GLM-5.3, Gemini, DeepSeek) went over 0.9.2. Every finding was reproduced
or refuted before anything changed; the fixes carry tests that fail without them. The suite is 1074
tests, also run on Linux (Debian under WSL), and the directory-listing question was measured against a
real Seafile server (CE 13.0.28, scratch library).

The two that mattered

  • Full gc deleted the old packs without re-reading the refs. A writer that ignored the lock and
    pushed while gc was repacking had its pack deleted and its ref left naming nothing. The refs are
    read again after the upload is verified; a change deletes nothing and says so.
  • On Windows the payload hash cache could vouch for a changed file. st_ctime is the creation
    time there and never moves, so a same-size in-place edit with the modification time put back was
    trusted and the old hash recorded. The key now holds NTFS's change time. The first run on Windows
    hashes every large payload file once more.

Fixed

  • A reaped-but-present expired lock ticket was rewritten fresh by renew(), putting a stalled holder
    back ahead of the peer that took over. It is LEASE_LOST when a live peer is behind it.
  • get_file_bytes enforced its cap only against a declared Content-Length; a chunked body was
    buffered whole. It is bounded as it is read.
  • A remote ref file whose content was an option (--stdin) reached git merge-base's argv.
  • Deleting a nested ref could remove a sibling created a moment earlier (the empty-parent prune).
  • --payload-gc --payload-delete re-reads the refs every 25 deletions or 10 s and stops on a change.
  • A file name that is not UTF-8 aborted an --exclude run; a name with a newline or a leading "
    made restore verification refuse; a vault lock that could not be written leaked its descriptor and
    left an empty lock file; --code-remote with --no-push was silently ignored.
  • Git's English messages are now forced (LC_MESSAGES=C) where the tool reads them.
  • A failed branch-delete rollback was reported as "(deleted)".
  • Plain unlock deleted a live local holder's ticket; it now refuses.

Decided

  • A lock-ignoring writer's lost last-writer-wins race is not rescued by a gc grace period; it
    stays documented. Every writer must use the helper.
  • The default conversion of an existing vault to payload mode is announced, and now repeated as the
    last line of the run on stdout and stderr.

Added and removed

  • tools/release_check.py answers before the tag exists what the release job answers after it.
  • The warning for the retired seafile.locksettle / seafile.gcmaxmib keys is gone.
  • Documents named tests that did not exist; a guard now fails on any test_... a document names that
    is not defined. DESIGN and USER_GUIDE now say what the code does about the ref read-back, the
    size-only pack proof, a token over plain HTTP, Trap 2's direction and LFS storage.

The full list is in CHANGELOG.md.


Full Changelog: v0.9.2...v0.9.3