App-makefilepl2cpanfile
view release on metacpan or search on metacpan
### Parse\_Prereqs
```perl
parse_prereqs : (Str ⪠{â¥}) -> DepMap
parse_prereqs(s) ==
if s = ⥠⨠is_ref(s) then â
else simple(s') ââ structured(s') ââ legacy(s')
where s' == s with every '#' comment removed
simple(s) == â { {PHASE_MAP(k) ⦠{requires ⦠pairs(b)}}
| k â {PREREQ_PM, BUILD_REQUIRES, TEST_REQUIRES, CONFIGURE_REQUIRES},
b â blocks(k, s) }
structured(s) == â { {p ⦠{r ⦠pairs(b)}}
| P â blocks(prereqs, s), (p ⦠(r ⦠b)) â P, p â Phase, r â Rel }
legacy(s) == â { {first(LEGACY(k)) ⦠{second(LEGACY(k)) ⦠pairs(b)}}
| k â dom LEGACY, b â blocks(k, s),
¬ (â P â blocks(prereqs, s) ⢠b â P) }
pairs(b) == { m ⦠⨠if v â Requirement then v else 0, comment(m, b) â©
| ('m' => v) â b, m â ModName }
-- comment(m, b): the line's comment if m is the last valid entry on it
post â p ⦠R â result ⢠R â â
â§ (â r ⦠M â R ⢠M â â
)
â§ no I/O â§ no warnings
```
### Generate
```perl
Args â [ content : Str ⪠{â¥}; makefile : Str; existing : Str; with_develop : ð¹ ]
generate : Args à Env ⸠Str
pre (a.content â ⥠⨠string(a.makefile) â dom E.fs â§ regular(a.makefile) â§ readable(a.makefile))
â§ (a.with_develop â cfg(E) â dom E.fs ⨠¬ regular(cfg(E)) ⨠yaml_ok(cfg(E)))
generate(a, E) ==
let content == if a.content â ⥠then a.content else decode_utf8_or_raw(E.fs(a.makefile))
deps == parse_prereqs(content)
kept == { r ⦠{ m ⦠⨠if v â Requirement then v else 0, ⥠⩠}
| (r m v) â develop_entries(a.existing) \ comments, m â ModName }
dev == deps ââ {develop ⦠kept}
listed == â { dom(dev(develop)(r)) | r â Rel }
tools == if E.home = ⥠⨠E.home = "" ⨠¬ regular(cfg(E)) then DEFAULT_DEVELOP
else valid_entries(yaml(cfg(E)).develop)
final == if a.with_develop
then dev ââ {develop ⦠{requires ⦠{ m ⦠â¨v, â¥â© | (m ⦠v) â tools, m â listed }}}
else dev
in emit(final, min_perl(content))
post result â Str
â§ prefix(result, HEADER â "\n") â§ last(result) = '\n' ⧠¬ suffix(result, "\n\n")
â§ Eâ² = E -- nothing is written
â§ $@â² = $@ â§ $!â² = $! â§ $_â² = $_
-- every value from a file or the environment in a message is
-- printable(v): control and bidi characters as \x{..}
-- Failure cases (the function dies):
a.content = ⥠⧠(¬ regular(a.makefile) ⨠¬ readable(a.makefile)) â croak("Cannot read '" â a.makefile â "'")
a.with_develop â§ regular(cfg(E)) ⧠¬ yaml_ok(cfg(E)) â croak("Failed to parse " â cfg(E) â ": " â err)
a.with_develop â§ stat(cfg(E)) fails with errno â {ENOENT, ENOTDIR} â croak("Failed to parse " â cfg(E) â ": " â errno)
```
## State Diagram
The module keeps no state between calls: every call starts at START and
ends at RETURN or at an error. The diagram shows the states that one
call to `generate()` passes through. `parse_prereqs()` is the single
step PARSE.
```perl
+-------+
| START | generate(%args) is called
+-------+
|
| makefile is a readable regular file?
|---- no ------------------------------------> [DIE] croak "Cannot read '...'"
| yes
v
+------------+ read as UTF-8
| READ_UTF8 |---- decode error --> +-----------+ carp "invalid UTF-8"
+------------+ | READ_RAW | (read the raw bytes)
| \ +-----------+
| \ |---- raw read fails --> [DIE] error passed on
| \---- other I/O error --------------------------> [DIE] error passed on
| ok |
v |
+------------+ <-------------------------+
| PARSE | parse_prereqs(content); find MIN_PERL_VERSION
+------------+ (pure: no I/O, no warnings)
|
| existing has an on 'develop' section?
|---- no ----------------------------+
| yes |
v |
+------------+ copy entries; drop |
| MERGE | bad names; carp and |
+------------+ drop bad versions |
| |
+<-----------------------------------+
|
| with_develop true?
|---- no ----------------------------------------------+
| yes |
v |
+------------+ no home dir, or config path missing |
| CONFIG | or not a regular file -------> DEFAULTS |
+------------+ | |
| config is a regular file | |
|---- stat/read/YAML error --> [DIE] croak "Failed to parse ..."
v | |
+------------+ no develop: key --> carp --> DEFAULTS |
| VALIDATE | bad name --> carp, skip entry |
+------------+ bad version --> carp, version 0 |
| | |
v v |
+------------+ <---------------------------------+ |
| INJECT | add tools not already in develop |
+------------+ |
| |
v |
( run in 0.598 second using v1.01-cache-2.11-cpan-28bccf0f6e5 )