Skip to content

v0.7.0 - comparing two versions, and a manifest that can't escape

Latest

Choose a tag to compare

@Synerdy Synerdy released this 01 Sep 23:18
· 11 commits to master since this release

Comparing two backup versions

modsx:diff has always compared your application against a version. Give it a second version and the application drops out of the comparison entirely:

php artisan modsx:diff Blog 0002 0004

The version named first is the baseline in both forms, so modsx:diff Blog 0002 and modsx:diff Blog 0002 0004 ask the same question from the same starting point — only the other side moves. Swapping the two arguments gives the same comparison seen from the other end: what was added becomes what is gone.

The wording follows. Against the application, the useful frame is what a restore would do next:

Added (restore would delete)
Modified (restore would overwrite)
Removed (restore would bring back)

Between two versions no restore is in sight, so describing those numbers by an action nobody asked for would simply be untrue:

Added (only in 0004)
Modified (differs between the two)
Removed (only in 0002)

Your working tree is not read at all in this mode, so the answer is the same whatever state the application happens to be in. --summary and --json work here too; the JSON carries from and to in place of version, which is how a script tells the two modes apart by shape alone.

A manifest can no longer place files outside the project

modsx:import takes a version number and a list of paths out of a manifest that somebody else wrote, and checked neither.

A version of ../../.. and a path of ../../escaped each wrote outside the project root. Both were reproduced before being fixed, rather than assumed — and ZipArchive::extractTo() was verified not to be the way in, since it sanitises entry names itself.

The version is now validated in the one place it becomes a path, and a manifest path is refused if it escapes with .., is absolute, or carries a drive letter.

If you only ever import archives you exported yourself, none of this was reachable. It starts to matter the moment an archive arrives from anywhere else.

A generator's options no longer need --

php artisan modsx:make component blog.alert --view      # now
php artisan modsx:make component blog.alert -- --view   # before

Anything else used to be refused with Symfony's The "--view" option does not exist — a message that says nothing about the separator you forgot. Which is easy to forget: --resource, -m, --view and --api come up constantly.

modsx:make answers to one option of its own, --dry-run. It now sorts the raw tokens itself and passes everything else to the generator, which is also why a generator from any package needs nothing declared. Writing -- still works, and remains the way to reach a generator option that collides with ours.

The cost, stated plainly: a misspelling of --dry-run is no longer caught by Symfony. It is checked for by name instead, and answered with Did you mean --dry-run? rather than forwarded to a generator that would blame itself.

An exported archive is named after its module

Blog-0002.zip, not 0002.zip — which said nothing at all once the file had been moved or mailed anywhere.

modsx:prune removes both names, so an archive written under the old one is still swept along with the version it belongs to, rather than left behind for good.

modsx:backuplist counts files and archived migrations

A version has held both since 0.3.0, so listing its directories alone described less than half of what was in it.

Version   Created               Directories   Files   Archived   Comment
0002      2026-09-01T21:14:07             3       2          1   before the rewrite

Also

  • modsx:backup names the files it did find when a module has files but no directories, instead of reporting the module as missing. It still refuses: a module is a set of directories, and the unclaimed-file check rests on that.
  • public/build joins the default exclude list, so a compiled asset bundle is not walked while looking for a module's directories.
  • CI rebuilds docs/ and fails if it differs from what is committed, and checks that the two READMEs keep the same headings, the same number of code blocks and the same number of table rows.

Upgrading

While Modsx is on 0.x, this release will not arrive with a plain composer update. Ask for it by name:

composer require --dev synerdy/modsx:^0.7

Composer treats anything below 1.0.0 with pre-release caution: there, ^0.6.1 means >=0.6.1 <0.7.0, putting the minor where the major normally sits. So composer update stays on the minor you installed — by design, not by accident — and composer why-not synerdy/modsx 0.7.0 will tell you as much.

The one thing to check before upgrading: if anything of yours refers to an exported archive by filename, it is Blog-0002.zip now.