Skip to content

Releases: teylabs/mod

v0.12.6

Choose a tag to compare

@jaspertey jaspertey released this 03 Nov 18:59
f10be5e

Fixed

  • Applying a maintenance plan is about 2–5× faster again, most on large lineages. Two costs grew with the size of the plan:
    • Every per-file check re-hashed the whole prepared journal, which holds every original and target file. So an apply hashed the journal once per file, and time grew with the square of the file count. The hash is now reused while the journal's stat signature (device, inode, size, mtime, ctime) is unchanged and both its times are before the second the hash was taken, git's racy-clean rule. So an edit in the same second as the hash, one that keeps the size, one that puts the old mtime back, or a file swapped in by rename is hashed again and refused, as before.
    • Inspecting a checkout listed a file's parent directory once per file for the case-alias check. Each inspection now lists each directory once, through its own DirectoryListings that ends with it. Every write path, and the freshness check before applying (a new inspection), lists afresh, so an alias that appears after inspection is still refused before anything is written.
    • Measured on a synthetic lineage (400-byte files, 50 per directory): 200 files, install apply 2.9s → 1.2s and upgrade 4.4s → 2.0s; 1,000 files, install 39s → 11s and upgrade 66s → 13s.

What's Changed

  • Reuse the verified journal hash and list each directory once per inspection (0.12.6) by @jaspertey in #236

Full Changelog: v0.12.5...v0.12.6

v0.11.7

Choose a tag to compare

@jaspertey jaspertey released this 03 Nov 18:59
c6c88fd

Fixed

  • Applying a maintenance plan is about 2–5× faster again, most on large lineages. Two costs grew with the size of the plan:
    • Every per-file check re-hashed the whole prepared journal, which holds every original and target file. So an apply hashed the journal once per file, and time grew with the square of the file count. The hash is now reused while the journal's stat signature (device, inode, size, mtime, ctime) is unchanged and both its times are before the second the hash was taken, git's racy-clean rule. So an edit in the same second as the hash, one that keeps the size, one that puts the old mtime back, or a file swapped in by rename is hashed again and refused, as before.
    • Inspecting a checkout listed a file's parent directory once per file for the case-alias check. Each inspection now lists each directory once, through its own DirectoryListings that ends with it. Every write path, and the freshness check before applying (a new inspection), lists afresh, so an alias that appears after inspection is still refused before anything is written.
    • Measured on a synthetic lineage (400-byte files, 50 per directory): 200 files, install apply 2.9s → 1.2s and upgrade 4.4s → 2.0s; 1,000 files, install 39s → 11s and upgrade 66s → 13s.

What's Changed

  • Reuse the verified journal hash and list each directory once per inspection (0.11.x, 0.11.7) by @jaspertey in #237

Full Changelog: v0.11.6...v0.11.7

v0.12.5

Choose a tag to compare

@jaspertey jaspertey released this 29 Oct 23:54
8146506

Fixed

  • A rolled-back apply leaves no maintenance file behind (a regression in 0.12.4). The append-only progress log (journal-<hash>.progress) outlived a failed or interrupted apply, so a caller that rolls back by restoring the files and removing the journal, as tey/kit does, left the log behind and the checkout differed from before.
    • Closing the claim now removes the log, so it survives only a real process death, the crash it exists for. A resume is still exact without it: files already at their target bytes reconcile.
    • A log whose journal is gone is stale. It's swept on the next prepare and never resumed from.

What's Changed

  • Release 0.12.5: remove the progress log when the claim closes; sweep stale logs by @jaspertey in #235

Full Changelog: v0.12.4...v0.12.5

v0.12.4

Choose a tag to compare

@jaspertey jaspertey released this 29 Oct 23:18
49f5f15

Fixed

  • Applying a maintenance plan is about 5× faster. Each file used to run the full checkout inspection twice: the claim check, then again when its completion was recorded. So an apply re-read every declared file about twice per file, and rewrote the whole journal, with fsync, once per file. A 154-file lineage spent about 1–3 minutes in that loop.
    • The full freshness check now runs once before the file loop and again before finalization.
    • Per file, only cheap checks run: the exclusive claim is held, the owner and the journal are unchanged, and the file still matches its planned bytes right before it's written. A drifted file aborts with the journal resumable.
    • Completed files go to an append-only progress log beside the journal (journal-<hash>.progress). Each line is fsynced before the next file is written, so a crash resumes exactly, and a torn last line is ignored. The log is removed once the lineage is recorded.
    • Files already at the target bytes are reconciled without being recorded.
    • Measured on two real apps' core lineage (154 files): about 56–99s down to 12–16s wall-clock, and about 37s down to 8s user CPU.

What's Changed

Full Changelog: v0.12.3...v0.12.4

v0.12.3

Choose a tag to compare

@jaspertey jaspertey released this 29 Oct 07:05
f65f63c

Fixed

  • The case-collision refusal names both paths: Case alias or collision at declared path resources/js/pages/Auth: the checkout already has resources/js/pages/auth., so the app knows what to rename (#225).

What's Changed

Full Changelog: v0.12.2...v0.12.3

v0.11.6

Choose a tag to compare

@jaspertey jaspertey released this 29 Oct 23:50
650a42f

Fixed

  • A rolled-back apply leaves no maintenance file behind (a regression in 0.11.5). The append-only progress log (journal-<hash>.progress) outlived a failed or interrupted apply, so a caller that rolls back by restoring the files and removing the journal, as tey/kit does, left the log behind and the checkout differed from before.
    • Closing the claim now removes the log, so it survives only a real process death, the crash it exists for. A resume is still exact without it: files already at their target bytes reconcile.
    • A log whose journal is gone is stale. It's swept on the next prepare and never resumed from.

What's Changed

  • Remove the progress log when the claim closes; sweep logs whose journal is gone (0.11.x) by @jaspertey in #234

Full Changelog: v0.11.5...v0.11.6

v0.11.5

Choose a tag to compare

@jaspertey jaspertey released this 29 Oct 23:15
9338d33

Fixed

  • Applying a maintenance plan is about 5× faster. Each file used to run the full checkout inspection twice: the claim check, then again when its completion was recorded. So an apply re-read every declared file about twice per file, and rewrote the whole journal, with fsync, once per file. A 154-file lineage spent about 1–3 minutes in that loop.
    • The full freshness check now runs once before the file loop and again before finalization.
    • Per file, only cheap checks run: the exclusive claim is held, the owner and the journal are unchanged, and the file still matches its planned bytes right before it's written. A drifted file aborts with the journal resumable.
    • Completed files go to an append-only progress log beside the journal (journal-<hash>.progress). Each line is fsynced before the next file is written, so a crash resumes exactly, and a torn last line is ignored. The log is removed once the lineage is recorded.
    • Files already at the target bytes are reconciled without being recorded.
    • Measured on two real apps' core lineage (154 files): about 56–99s down to 12–16s wall-clock, and about 37s down to 8s user CPU.

What's Changed

  • Check freshness once per apply, not per file; record progress append-only (0.11.x) by @jaspertey in #230
  • Release 0.11.5 by @jaspertey in #231

Full Changelog: v0.11.4...v0.11.5

v0.11.4

Choose a tag to compare

@jaspertey jaspertey released this 29 Oct 06:46
a8e1af9

Fixed

  • The case-collision refusal names both paths: Case alias or collision at declared path resources/js/pages/Auth: the checkout already has resources/js/pages/auth., so the app knows what to rename (#225).

What's Changed

Full Changelog: v0.11.3...v0.11.4

v0.12.2

Choose a tag to compare

@jaspertey jaspertey released this 28 Oct 05:12
adc1c27

Headline

Installed records are portable: no absolute checkout path, and a fresh clone (CI, another worktree, a teammate) can plan and apply.

Fixed

  • Committed installed records work in any checkout of the app. A record stores its root as . instead of the absolute path of the checkout that wrote it, so a clone, CI or another worktree no longer fails with Unknown, foreign or mismatched installed artifact., and no local path is committed. A record written before 0.12.2 is read anywhere and rewritten on the next update. The app id, lineage and artifact fingerprint still refuse a foreign record (#207).
  • The first update in a fresh clone no longer fails with Maintenance data requires an unlinked regular file. When .mod-maintenance/ holds only committed installed records, Mod creates the git-ignored owner.json and lock itself. A linked owner.json is still refused, and unknown content is still reported (#207).

Same fix as 0.11.3 on the 0.11 line. Fresh-install check from a real git clone: plan, apply, upgrade plan, apply; owner.json and lock created; root "." with no local path.


What's Changed

Full Changelog: v0.12.1...v0.12.2

v0.12.1

Choose a tag to compare

@jaspertey jaspertey released this 28 Oct 01:14
99d5dec

Headline

A file the host already brought to the new release is unchanged, not a conflict, so claim followed by an update no longer blocks.

Fixed

  • An owned file whose bytes already equal the new target is unchanged, not a conflict, even when it differs from its recorded original (the host applied the change itself, or took the release's bytes after claiming the file). Nothing is written, the update isn't blocked, and the installed record takes the target, so the original advances. A file that differs from both the original and the target is still a conflict (#216).

Also: tests compare real paths for Laravel 13.39's FileViewFinder realpath change. Fresh-install check: a new Laravel 13.39 app on PHP 8.5 passes mod:install and mod:list, and the install-A, host-writes-B, upgrade script plans unchanged with nothing written (it plans conflict on 0.12.0).


What's Changed

Full Changelog: v0.12.0...v0.12.1