use 5.14.0;
use strict;
use warnings;
package Dist::Iller;
# ABSTRACT: A Dist::Zilla & Pod::Weaver preprocessor
our $AUTHORITY = 'cpan:CSSON'; # AUTHORITY
our $VERSION = '0.1411';
use Dist::Iller::Elk;
use Types::Standard qw/Map Str ConsumerOf/;
use Types::Path::Tiny qw/Path/;
use String::CamelCase qw/camelize/;
use Try::Tiny;
use Carp qw/croak/;
use Module::Load qw/load/;
use Safe::Isa qw/$_does/;
use YAML::Tiny;
use Dist::Iller::Prereq;
has docs => (
is => 'ro',
isa => Map[Str, ConsumerOf['Dist::Iller::DocType'] ],
default => sub { +{ } },
traits => ['Hash'],
handles => {
set_doc => 'set',
get_doc => 'get',
doc_keys => 'keys',
doc_kv => 'kv',
},
);
has filepath => (
is => 'ro',
isa => Path,
default => 'iller.yaml',
coerce => 1,
);
sub parse {
my $self = shift;
my $phase = shift;
my $yaml = YAML::Tiny->read($self->filepath->stringify);
DOCTYPE:
for my $document (sort { $a->{'doctype'} cmp $b->{'doctype'} } @{ $yaml }) {
my $doctype_class = sprintf 'Dist::Iller::DocType::%s', camelize($document->{'doctype'});
try {
load $doctype_class;
}
catch {
croak "Can't load $doctype_class: $_";
};
next DOCTYPE if $doctype_class->phase ne $phase;
$self->set_doc($document->{'doctype'}, $doctype_class->new(global => $self->get_doc('global'))->parse($document));
}
if($self->get_doc('dist')) {
$self->get_doc('dist')->add_prereq(Dist::Iller::Prereq->new(
module => __PACKAGE__,
version => __PACKAGE__->VERSION,
phase => 'develop',
relation => 'suggests',
));
DOC:
for my $doc ($self->doc_kv) {
if($doc->[1]->$_does('Dist::Iller::Role::HasPlugins')) {
$self->get_doc('dist')->add_plugins_as_prereqs($doc->[1]->packages_for_plugin, $doc->[1]->all_plugins);
}
for my $included_config ($doc->[1]->all_included_configs) {
$self->get_doc('dist')->add_prereq(Dist::Iller::Prereq->new(
module => $included_config->[0],
version => $included_config->[1],
phase => 'develop',
relation => 'suggests',
));
}
next DOC if $doc->[0] eq 'dist';
next DOC if $doc->[0] eq 'cpanfile';
if($doc->[1]->$_does('Dist::Iller::Role::HasPrereqs')) {
$self->get_doc('dist')->merge_prereqs($doc->[1]->all_prereqs);
}
}
}
if($self->get_doc('cpanfile') && $self->get_doc('dist')) {
$self->get_doc('cpanfile')->merge_prereqs($self->get_doc('dist')->all_prereqs);
}
}
sub generate_files {
my $self = shift;
my $phase = shift;
croak q{'phase' must be either 'before' or 'after'} if !defined $phase || $phase ne 'before' && $phase ne 'after';
for my $doc ($self->doc_kv) {
next if $doc->[1]->phase ne $phase;
$doc->[1]->generate_file;
}
}
__PACKAGE__->meta->make_immutable;
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
Dist::Iller - A Dist::Zilla & Pod::Weaver preprocessor
=begin html
=end html
=head1 VERSION
Version 0.1411, released 2020-01-01.
=head1 SYNOPSIS
# dzil new, but...
$ dzil new -P DistIller::AMintingProvider My::Module
$ cd My/Module
# ...all other commands can be used via iller
$ iller build
=head1 STATUS
This is alpha software. Anything can change at any time.
It is mostly here to document how I build my distributions. It is perfectly fine to use C with a distribution built with C (after a fork, for example).
=head1 DESCRIPTION
Dist::Iller is a L and L preprocessor. It comes with a command line tool (C) which is a C wrapper: When run, it first generates
files specified in C in the current directory and then executes C automatically. (Since C requires that an C is present, C does not work.)
The C key in a document in C matches a camelized class in the C namespace; so C is parsed by L.
=head2 iller.yaml
This is the general syntax of an C file:
---
# This specifies that this yaml document will generate dist.ini.
doctype: dist
# This generates the top part of C. C can be a list or string.
header:
name: My-Module
author: Ex Ample
license: Perl_5
copyright_holder: Ex Ample
copyright_year: 2015
# It is possible to list all prereqs. The groups are specified in CPAN::Meta::Spec.
# Minimum version numbers are optional.
prereqs:
runtime:
requires:
- perl: 5.010001
- Moose
# List all plugins under the 'plugins' key.
# Each +plugin item is a Dist::Zilla> plugin.
# All commands for Dist::Iller is prepended with a +.
plugins:
# Includes all plugins specified in Dist::Iller::Config::My::Config
- +config: My::Config
- +plugin: DistIller::MetaGeneratedBy
- +plugin: AutoVersion
- +plugin: GatherDir
# 'dir' is a parameter for ShareDir
- +plugin: ShareDir
dir: myshare
[...]
---
# Here starts the weaver.ini configuration.
doctype: weaver
plugins:
# Same Dist::Iller::Config as in the 'dist' document
- +config: My::Config
# Use PluginBundles
- +plugin: '@CorePrep'
- +plugin: -SingleEncoding
- +plugin: Name
- +plugin: Version
format: Version %v, released %{YYYY-MM-dd}d.
- +plugin: prelude
+base: Region
- +plugin: List
+base: -Transformer
+in: Elemental
transformer: List
[...]
---
# Here starts the .gitignore configuration
doctype: gitignore
always:
- /.build
- /_build*
- /Build
- MYMETA.*
- '!META.json'
- /.prove
---
# No configuration for .cpanfile, but by having a YAML document for it, it gets generated from
# the prereqs listed in the 'dist' document
doctype: cpanfile
=head2 Rationale
PluginBundles for both L and L have a few downsides:
=over 4
=item *
Mixes code and configuration.
=item *
Not straightforward to remove or replace specific plugins for a certain distribution
=item *
Difficult to insert a plugin before another plugin for a certain distribution.
=item *
PluginBundles can change after a distribution has been released.
=item *
Difficult for others to understand/know which plugins actually were in effect when the distribution was built.
=back
C tries to solve this:
=over 4
=item *
Dist::Iller configs (similar to PluginBundles) has their own C (normally in C) where plugins are specified. See tests and L.
=item *
Since C and C are generated each time C is run, the plugins listed in them are those that were used to build the distribution.
=item *
Remove a plugin:
=back
- +remove_plugin: GatherDir
=over 4
=item *
Insert a plugin:
=back
- +add_plugin: Git::GatherDir
+before: AutoVersion
=over 4
=item *
Replace a plugin:
=back
- +replace_plugin: ShareDir
+with: ShareDir::Tarball
=over 4
=item *
Set more attributes for an already included plugin:
=back
- +extend_plugin: Git::GatherDir
exclude_match:
- examples/.*\.html
=head1 SEE ALSO
=over 4
=item *
L
=item *
L
=item *
L
=back
=head1 SOURCE
L
=head1 HOMEPAGE
L
=head1 AUTHOR
Erik Carlsson
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2021 by Erik Carlsson.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut