Repository navigation
Releases: teylabs/mod
Release list
v0.12.5
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
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 (port of #230) by @jaspertey in #232
- Release 0.12.4 by @jaspertey in #233
Full Changelog: v0.12.3...v0.12.4
v0.12.3
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
- Name both paths in the case-collision refusal by @jaspertey in #226
- Release 0.12.3 by @jaspertey in #229
Full Changelog: v0.12.2...v0.12.3
v0.11.6
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
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
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
- Name both paths in the case-collision refusal (0.11.x) by @jaspertey in #227
- Release 0.11.4 by @jaspertey in #228
Full Changelog: v0.11.3...v0.11.4
v0.12.2
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 withUnknown, 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-ignoredowner.jsonandlockitself. A linkedowner.jsonis 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
- Let any checkout of an app use its committed installed records by @jaspertey in #222
- Release 0.12.2 by @jaspertey in #224
Full Changelog: v0.12.1...v0.12.2
v0.12.1
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 aconflict, 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
- Plan an owned file already at the target as unchanged by @jaspertey in #217
- Release 0.12.1 by @jaspertey in #220
Full Changelog: v0.12.0...v0.12.1
v0.11.3
Headline
Installed records are portable: they no longer store an 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 withUnknown, foreign or mismatched installed artifact., and no local path is committed. A record written before 0.11.3 (0.12.2 on the main line) 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-ignoredowner.jsonandlockitself. A linkedowner.jsonis still refused, and unknown content is still reported (#207).
Fresh-install check from a real git clone + composer install: plan creates, apply completes, an upgrade plan replaces, apply completes; owner.json and lock are created; the record has root "." with no local path. Foreign records are still refused by app id, lineage-hash filename and artifact fingerprint.
What's Changed
- Let any checkout of an app use its committed installed records (0.11.x) by @jaspertey in #221
- Release 0.11.3 by @jaspertey in #223
Full Changelog: v0.11.2...v0.11.3
v0.11.2
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 aconflict, 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).
Maintenance release on the 0.11 line: the same fix as 0.12.1, for hosts on tey/mod ^0.11 (tey/kit). Fresh-install check: a new Laravel 13.39 app on PHP 8.5 requiring this branch 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.11.1).
What's Changed
- Plan an owned file already at the target as unchanged (0.11.x) by @jaspertey in #219
Full Changelog: v0.11.1...v0.11.2