Revision history for App-makefilepl2cpanfile
0.06 Wed Sep 30 07:44:13 PM EDT 2026
[ Security ]
Reading a Makefile.PL with many unclosed dependency blocks
(PREREQ_PM, prereqs, recommends and the other META spec 1.x keys)
took time proportional to the square of its size: 50,000 unclosed
recommends blocks took over a minute on Perl 5.26. Dependency blocks
are now found by matching braces in one pass, so reading takes time
in proportion to the size of the file
[ Documentation ]
The documentation now states that reading is linear in the size of
the input, and that an unmatched brace inside a string or comment
within a dependency list can hide its entries. The limitation on
lists nested more than four braces deep is gone: lists are read at
any depth
[ Enhancements ]
Minimum Perl is now 5.26, set by the test dependencies:
Test::Permissions needs Params::Validate::Strict (5.26), and
Test::Mockingbird needs 5.16.3. The code itself still needs only
5.14, but the 5.14 declared in 0.05 was already wrong: its test
dependencies could not be installed on 5.14
New test dependency: Test::Permissions, replacing the private copy in
t/lib
The core modules Carp, Fcntl and Getopt::Long are now declared as
dependencies
[ Testing ]
Permission tests probe the directory that holds their fixtures, and
their skip messages say why chmod cannot revoke access (for
example root, Windows, or a filesystem that ignores permissions)
Files and directories are locked with Test::Permissions' with_revoked,
which restores the mode even if a check dies; three tests used to
leave a mode-0 file behind
Tests that dependency lists are read at every nesting depth, and
timing tests for more shapes of unclosed dependency blocks
CI: the minimum-version job runs Perl 5.26 instead of 5.14, in its
own workflow (u26.yml)
0.05 Fri Sep 25 05:01:10 PM EDT 2026
[ Enhancements ]
Version ranges (e.g. '>= 1.2, < 2.0') are kept and written to the
cpanfile; previously they were silently dropped, losing upper bounds
Support the conflicts relationship (in prereqs blocks, existing develop
blocks and the META spec 1.x layout)
New read_makefile() function and content argument to generate(), so
one read of Makefile.PL can feed several calls
--check now exits with status 1 when modules are missing, so CI can
fail on it
[ Bug Fixes ]
Recognise legacy top-level recommends => { ... } blocks (META spec 1.x
style, e.g. directly under META_MERGE) and emit them as runtime
recommends in the generated cpanfile; previously they were ignored
Likewise handle top-level suggests => { ... } blocks, emitted as
runtime suggests
Likewise handle the other META spec 1.x top-level keys: requires,
build_requires, configure_requires and conflicts; they were ignored
recommends/suggests blocks nested inside prereqs => { ... } remain
phase-scoped and are not duplicated into runtime
Read every entry on a line; previously only the first was kept, so
PREREQ_PM => { 'A' => 0, 'B' => 0 } silently lost B
Validate the whole version value instead of its numeric prefix:
'1e3' is no longer truncated to '1' nor '1.0-TRIAL' to '1.0', and
v-strings such as 'v1.2.3' and MIN_PERL_VERSION => 'v5.10.0' are no
longer dropped
Versions with no digit ('.', '_') or with non-ASCII digits are treated
as no minimum instead of being written to the cpanfile
Treat 'v0', 'v0.0.0' and MIN_PERL_VERSION '0.0' as zero, like '0'
Require matching quotes around module names: "A'B" was misread as a
different module (B, or A in an existing cpanfile)
Ignore dependency hashes commented out on one line, at any level
(including phases and relationships inside prereqs blocks), and
commented-out entries in an existing cpanfile's develop block
Only accept ASCII module names, as CPAN requires
A comment at the end of a line now goes to the last entry that is
kept; it was lost when the last entry had an invalid name
--check reads Makefile.PL once, so it always checks the same text
that was converted
generate() no longer changes the caller's $@ or $!
generate() no longer creates empty develop recommends/suggests hashes
as a side effect of checking for existing develop tools
A filehandle or other reference passed as makefile is refused with
"Cannot read" instead of failing inside Path::Tiny
An empty home directory from File::HomeDir falls back to the default
develop tools instead of dying
Config file: YAML::Tiny errors are now reported as the documented
"Failed to parse" message; a directory, device or FIFO at the config
path is treated as no config (a FIFO previously blocked forever); a
config path that cannot be examined (e.g. permission denied) croaks
instead of silently using the defaults
--diff never writes the cpanfile; with no existing cpanfile it shows
a diff against an empty file
A directory (or other non-regular file) named cpanfile is refused;
previously the new text was moved inside it and success reported
A failed write (disk full, failed rename) no longer leaves a stray
temporary file such as cpanfile164662728368918 in the project
directory; the previous cpanfile is kept and nothing else remains
[ Security ]
Validate versions carried over from an existing cpanfile's develop
block; a crafted version ending in a backslash could inject code into
the regenerated cpanfile. Invalid versions are dropped with a warning
Strip control characters and Unicode bidirectional overrides
("Trojan Source", CVE-2021-42574) from comments copied to the cpanfile
The command-line tool refuses to read or write a cpanfile that is a
symbolic link; a cloned repository could otherwise make it overwrite
(or create) any file the user can write, such as ~/.bashrc
Escape control and direction-override characters in warnings and
errors, so text from a hostile file cannot send escape sequences to
the terminal to hide or forge messages
Fix regular expressions that were quadratic on hostile input (an
existing cpanfile with many unclosed develop blocks, and comments
with long runs of spaces) and could stall the tool for minutes
An I/O error in a directory whose name contains "utf" or "decode" is
no longer mistaken for an encoding error and hidden
[ Packaging ]
Licence metadata is now gpl_2 (it was "GPL", published as
"open_source"); the command-line tool's documentation now states the
same GPL2 terms as the module and the LICENSE file
Minimum Perl is now 5.14 (the code uses s///r and the /a modifier;
5.10 was declared but could not compile it)
Path::Tiny 0.034 or later is required
The module no longer imports functions into its own namespace
(Load, Dump, home, path, croak, carp, Readonly were callable as
App::makefilepl2cpanfile::...), and no longer loads autodie
Test::Mockingbird 0.13 required for the tests; removed unused
dependencies (List::Util and six test modules); author-test modules
declared as develop prerequisites
[ Documentation ]
Rewrote the POD: examples, encoding rules, common pitfalls, input
domains, API specifications, formal specification and state diagram
[ Testing ]
Added t/data-flow.t and t/domain.t; extended function, unit,
integration and edge-case tests
New test dependencies: Capture::Tiny, Module::CPANfile,
Test::Without::Module
0.04 Sun Aug 2 12:59:14 PM EDT 2026
[ Bug Fixes ]
Gracefully handle Makefile.PL files containing invalid UTF-8 bytes: fall back to
raw-byte read and emit a carp warning rather than dying; true I/O errors
(EIO, ENOENT, etc.) are still propagated to the caller
0.03 Wed Jul 22 20:12:54 EDT 2026
[ Enhancements ]
Extract parse_prereqs() as a public API function
Preserve inline comments from Makefile.PL entries in generated cpanfile
Parse structured prereqs => { phase => { rel => { ... } } } blocks,
including those nested under META_MERGE
Extract recommends and suggests relationships into cpanfile output
Support brace nesting up to four levels deep in dependency blocks
Replace File::Slurp with Path::Tiny throughout
Add Carp (croak/carp) in place of die/warn in library code
Add Readonly constants for phase map, phase order, and develop defaults
Guard against directories being passed as the makefile path
[ Security ]
Validate YAML config keys and values against strict patterns to prevent cpanfile code injection
Save $1/$2 before inner validation regex to prevent capture-variable clobber in develop-block merge
Add word-boundary anchors to MIN_PERL_VERSION extraction pattern
Use possessive quantifiers in all brace-extraction and module-name regexes to eliminate backtracking
[ Performance ]
Replace grep with List::Util::any (short-circuits) for develop-phase presence check
Replace each with keys in _load_develop_config to avoid stale iterator cursor
Add '0' short-circuit to _has_version to avoid looks_like_number call for zero versions
[ Tests ]
Add t/parse_prereqs.t, t/error_paths.t, t/locales.t, t/extended_tests.t
0.02 Mon Mar 30 19:22:57 EDT 2026
Added which tool created it
Ignore comments in Makefile.PL
Improved handling of version set to '0'
Improved error handling
With_develop now defaults to 1.
Handle on develop being in quotes
0.01 Fri Jan 2 21:38:25 EST 2026
First draft
Keyboard Shortcuts
Global
s
Focus search bar
?
Bring up this help dialog
GitHub
gp
Go to pull requests
gi
Go to GitHub issues (only if GitHub is preferred repository)