File Coverage

blib/lib/Dist/Zilla.pm
Criterion Covered Total %
statement 165 183 90.1
branch 42 64 65.6
condition 3 5 60.0
subroutine 34 34 100.0
pod 4 5 80.0
total 248 291 85.2


line stmt bran cond sub pod time code
1             package Dist::Zilla 6.037;
2             # ABSTRACT: distribution builder; installer not included!
3              
4 52     52   1166413 use Moose 0.92; # role composition fixes
  52         553945  
  52         542  
5             with 'Dist::Zilla::Role::ConfigDumper';
6              
7 52     52   391670 use Dist::Zilla::Pragmas;
  52         121  
  52         472  
8              
9             # This comment has fün̈n̈ÿ characters.
10              
11 52     52   2118 use MooseX::Types::Moose qw(ArrayRef Bool HashRef Object Str);
  52         65377  
  52         734  
12 52     52   369054 use MooseX::Types::Perl qw(DistName LaxVersionStr);
  52         1887564  
  52         494  
13 52     52   152743 use Moose::Util::TypeConstraints;
  52         121  
  52         376  
14              
15 52     52   129095 use Dist::Zilla::Types qw(Path License ReleaseStatus);
  52         232  
  52         592  
16              
17 52     52   161218 use Log::Dispatchouli 1.100712; # proxy_loggers, quiet_fatal
  52         991572  
  52         2113  
18 52     52   2293 use Dist::Zilla::Path;
  52         114  
  52         465  
19 52     52   19282 use List::Util 1.33 qw(first none);
  52         1318  
  52         5564  
20 52     52   35309 use Software::License 0.104001; # ->program
  52         526109  
  52         2148  
21 52     52   25085 use String::RewritePrefix;
  52         54036  
  52         382  
22 52     52   12047 use Try::Tiny;
  52         139  
  52         4028  
23              
24 52     52   32326 use Dist::Zilla::Prereqs;
  52         736  
  52         2886  
25 52     52   31832 use Dist::Zilla::File::OnDisk;
  52         1087  
  52         2953  
26 52     52   32520 use Dist::Zilla::Role::Plugin;
  52         583  
  52         2635  
27 52     52   31397 use Dist::Zilla::Util;
  52         192  
  52         2508  
28 52     52   395 use Module::Runtime 'require_module';
  52         123  
  52         435  
29              
30 52     52   2857 use namespace::autoclean;
  52         112  
  52         450  
31              
32             #pod =head1 DESCRIPTION
33             #pod
34             #pod Dist::Zilla builds distributions of code to be uploaded to the CPAN. In this
35             #pod respect, it is like L<ExtUtils::MakeMaker>, L<Module::Build>, or
36             #pod L<Module::Install>. Unlike those tools, however, it is not also a system for
37             #pod installing code that has been downloaded from the CPAN. Since it's only run by
38             #pod authors, and is meant to be run on a repository checkout rather than on
39             #pod published, released code, it can do much more than those tools, and is free to
40             #pod make much more ludicrous demands in terms of prerequisites.
41             #pod
42             #pod If you have access to the web, you can learn more and find an interactive
43             #pod tutorial at B<L<dzil.org|https://dzil.org/>>. If not, try
44             #pod L<Dist::Zilla::Tutorial>.
45             #pod
46             #pod =cut
47              
48             has chrome => (
49             is => 'rw',
50             isa => role_type('Dist::Zilla::Role::Chrome'),
51             required => 1,
52             );
53              
54             #pod =attr name
55             #pod
56             #pod The name attribute (which is required) gives the name of the distribution to be
57             #pod built. This is usually the name of the distribution's main module, with the
58             #pod double colons (C<::>) replaced with dashes. For example: C<Dist-Zilla>.
59             #pod
60             #pod =cut
61              
62             has name => (
63             is => 'ro',
64             isa => DistName,
65             lazy => 1,
66             builder => '_build_name',
67             );
68              
69             #pod =attr version
70             #pod
71             #pod This is the version of the distribution to be created.
72             #pod
73             #pod =cut
74              
75             has _version_override => (
76             isa => LaxVersionStr,
77             is => 'ro' ,
78             init_arg => 'version',
79             );
80              
81             # XXX: *clearly* this needs to be really much smarter -- rjbs, 2008-06-01
82             has version => (
83             is => 'rw',
84             isa => LaxVersionStr,
85             lazy => 1,
86             init_arg => undef,
87             builder => '_build_version',
88             );
89              
90             sub _build_name {
91 1     1   3 my ($self) = @_;
92              
93 1         2 my $name;
94 1         1 for my $plugin (@{ $self->plugins_with(-NameProvider) }) {
  1         3  
95 1 50       5 next unless defined(my $this_name = $plugin->provide_name);
96              
97 1 50       8 $self->log_fatal('attempted to set name twice') if defined $name;
98              
99 1         3 $name = $this_name;
100             }
101              
102 1 50       3 $self->log_fatal('no name was ever set') unless defined $name;
103              
104 1         21 $name;
105             }
106              
107             sub _build_version {
108 151     151   437 my ($self) = @_;
109              
110 151         5397 my $version = $self->_version_override;
111              
112 151         350 for my $plugin (@{ $self->plugins_with(-VersionProvider) }) {
  151         615  
113 3 50       26 next unless defined(my $this_version = $plugin->provide_version);
114              
115 3 50       20 $self->log_fatal('attempted to set version twice') if defined $version;
116              
117 3         13 $version = $this_version;
118             }
119              
120 151 50       672 $self->log_fatal('no version was ever set') unless defined $version;
121              
122 151         5739 $version;
123             }
124              
125             #pod =attr release_status
126             #pod
127             #pod This attribute sets the release status to one of the
128             #pod L<CPAN::META::Spec|https://metacpan.org/pod/CPAN::Meta::Spec#release_status>
129             #pod values: 'stable', 'testing' or 'unstable'.
130             #pod
131             #pod If the C<$ENV{RELEASE_STATUS}> environment variable exists, its value will
132             #pod be used as the release status.
133             #pod
134             #pod For backwards compatibility, if C<$ENV{RELEASE_STATUS}> does not exist and
135             #pod the C<$ENV{TRIAL}> variable is true, the release status will be 'testing'.
136             #pod
137             #pod Otherwise, the release status will be set from a
138             #pod L<ReleaseStatusProvider|Dist::Zilla::Role::ReleaseStatusProvider>, if one
139             #pod has been configured.
140             #pod
141             #pod For backwards compatibility, setting C<is_trial> true in F<dist.ini> is
142             #pod equivalent to using a C<ReleaseStatusProvider>. If C<is_trial> is false,
143             #pod it has no effect.
144             #pod
145             #pod Only B<one> C<ReleaseStatusProvider> may be used.
146             #pod
147             #pod If no providers are used, the release status defaults to 'stable' unless there
148             #pod is an "_" character in the version, in which case, it defaults to 'testing'.
149             #pod
150             #pod =cut
151              
152             # release status must be lazy, after files are gathered
153             has release_status => (
154             is => 'ro',
155             isa => ReleaseStatus,
156             lazy => 1,
157             builder => '_build_release_status',
158             );
159              
160             sub _build_release_status {
161 150     150   429 my ($self) = @_;
162              
163             # environment variables override completely
164 150 100       4877 return $self->_release_status_from_env if $self->_release_status_from_env;
165              
166             # other ways of setting status must not conflict
167 143         285 my $status;
168              
169             # dist.ini is equivalent to a release provider if is_trial is true.
170             # If false, though, we want other providers to run or fall back to
171             # the version
172 143 100       4690 $status = 'testing' if $self->_override_is_trial;
173              
174 143         380 for my $plugin (@{ $self->plugins_with(-ReleaseStatusProvider) }) {
  143         598  
175 3 50       23 next unless defined(my $this_status = $plugin->provide_release_status);
176              
177 3 100       53 $self->log_fatal('attempted to set release status twice')
178             if defined $status;
179              
180 2         7 $status = $this_status;
181             }
182              
183 142   66     5948 return $status || ( $self->version =~ /_/ ? 'testing' : 'stable' );
184             }
185              
186             # captures environment variables early during Zilla object construction
187             has _release_status_from_env => (
188             is => 'ro',
189             isa => Str,
190             builder => '_build_release_status_from_env',
191             );
192              
193             sub _build_release_status_from_env {
194 188     188   597987 my ($self) = @_;
195 188 100       1160 return $ENV{RELEASE_STATUS} if $ENV{RELEASE_STATUS};
196 187 100       2058 return $ENV{TRIAL} ? 'testing' : '';
197             }
198              
199             #pod =attr abstract
200             #pod
201             #pod This is a one-line summary of the distribution. If none is given, one will be
202             #pod looked for in the L</main_module> of the dist.
203             #pod
204             #pod =cut
205              
206             has abstract => (
207             is => 'rw',
208             isa => 'Str',
209             lazy => 1,
210             default => sub {
211             my ($self) = @_;
212              
213             unless ($self->main_module) {
214             die "no abstract given and no main_module found; make sure your main module is in ./lib\n";
215             }
216              
217             my $file = $self->main_module;
218             $self->log_debug("extracting distribution abstract from " . $file->name);
219             my $abstract = Dist::Zilla::Util->abstract_from_file($file);
220              
221             if (!defined($abstract)) {
222             my $filename = $file->name;
223             die "Unable to extract an abstract from $filename. Please add the following comment to the file with your abstract:
224             # ABSTRACT: turns baubles into trinkets
225             ";
226             }
227              
228             return $abstract;
229             }
230             );
231              
232             #pod =attr main_module
233             #pod
234             #pod This is the module where Dist::Zilla might look for various defaults, like
235             #pod the distribution abstract. By default, it's derived from the distribution
236             #pod name. If your distribution is Foo-Bar, and F<lib/Foo/Bar.pm> exists,
237             #pod that's the main_module. Otherwise, it's the shortest-named module in the
238             #pod distribution. This may change!
239             #pod
240             #pod You can override the default by specifying the file path explicitly,
241             #pod ie:
242             #pod
243             #pod main_module = lib/Foo/Bar.pm
244             #pod
245             #pod =cut
246              
247             has _main_module_override => (
248             isa => 'Str',
249             is => 'ro' ,
250             init_arg => 'main_module',
251             predicate => '_has_main_module_override',
252             );
253              
254             has main_module => (
255             is => 'ro',
256             isa => 'Dist::Zilla::Role::File',
257             lazy => 1,
258             init_arg => undef,
259             default => sub {
260             my ($self) = @_;
261              
262             my $file;
263             my $guess;
264              
265             if ( $self->_has_main_module_override ) {
266             $file = first { $_->name eq $self->_main_module_override }
267             @{ $self->files };
268             } else {
269             # We're having to guess
270              
271             $guess = $self->name =~ s{-}{/}gr;
272             $guess = "lib/$guess.pm";
273              
274             $file = (first { $_->name eq $guess } @{ $self->files })
275             || (sort { length $a->name <=> length $b->name }
276             grep { $_->name =~ m{\.pm\z} and $_->name =~ m{\Alib/} }
277             @{ $self->files })[0];
278             $self->log("guessing dist's main_module is " . ($file ? $file->name : $guess));
279             }
280              
281             if (not $file) {
282             my @errorlines;
283              
284             push @errorlines, "Unable to find main_module in the distribution";
285             if ($self->_has_main_module_override) {
286             push @errorlines, "'main_module' was specified in dist.ini but the file '" . $self->_main_module_override . "' is not to be found in our dist. ( Did you add it? )";
287             } else {
288             push @errorlines,"We tried to guess '$guess' but no file like that existed";
289             }
290             if (not @{ $self->files }) {
291             push @errorlines, "Upon further inspection we didn't find any files in your dist, did you add any?";
292             } elsif ( none { $_->name =~ m{^lib/.+\.pm\z} } @{ $self->files } ){
293             push @errorlines, "We didn't find any .pm files in your dist, this is probably a problem.";
294             }
295             push @errorlines,"Cannot continue without a main_module";
296             $self->log_fatal( join qq{\n}, @errorlines );
297             }
298             $self->log_debug("dist's main_module is " . $file->name);
299              
300             return $file;
301             },
302             );
303              
304             #pod =attr license
305             #pod
306             #pod This is the L<Software::License|Software::License> object for this dist's
307             #pod license and copyright.
308             #pod
309             #pod It will be created automatically, if possible, with the
310             #pod C<copyright_holder> and C<copyright_year> attributes. If necessary, it will
311             #pod try to guess the license from the POD of the dist's main module.
312             #pod
313             #pod A better option is to set the C<license> name in the dist's config to something
314             #pod understandable, like C<Perl_5>.
315             #pod
316             #pod =cut
317              
318             has license => (
319             is => 'ro',
320             isa => License,
321             lazy => 1,
322             init_arg => 'license_obj',
323             predicate => '_has_license',
324             builder => '_build_license',
325             handles => {
326             copyright_holder => 'holder',
327             copyright_year => 'year',
328             },
329             );
330              
331             sub _build_license {
332 150     150   429 my ($self) = @_;
333              
334 150         4761 my $license_class = $self->_license_class;
335 150         4798 my $copyright_holder = $self->_copyright_holder;
336 150         4961 my $copyright_year = $self->_copyright_year;
337              
338 150         349 my $provided_license;
339              
340 150         289 for my $plugin (@{ $self->plugins_with(-LicenseProvider) }) {
  150         602  
341 1         27 my $this_license = $plugin->provide_license({
342             copyright_holder => $copyright_holder,
343             copyright_year => $copyright_year,
344             });
345              
346 1 50       44 next unless defined $this_license;
347              
348 1 50       4 $self->log_fatal('attempted to set license twice')
349             if defined $provided_license;
350              
351 1         3 $provided_license = $this_license;
352             }
353              
354 150 100       746 return $provided_license if defined $provided_license;
355              
356 149 50       581 if ($license_class) {
357 149         2187 $license_class = String::RewritePrefix->rewrite(
358             {
359             '=' => '',
360             '' => 'Software::License::'
361             },
362             $license_class,
363             );
364             } else {
365 0         0 require Software::LicenseUtils;
366 0         0 my @guess = Software::LicenseUtils->guess_license_from_pod(
367             $self->main_module->content
368             );
369              
370 0 0       0 if (@guess != 1) {
371 0         0 $self->log_fatal(
372             "no license data in config, no %Rights stash,",
373             "couldn't make a good guess at license from Pod; giving up. ",
374             "Perhaps you need to set up a global config file (dzil setup)?"
375             );
376             }
377              
378 0         0 my $filename = $self->main_module->name;
379 0         0 $license_class = $guess[0];
380 0         0 $self->log("based on POD in $filename, guessing license is $guess[0]");
381             }
382              
383 149 50       12883 unless (eval { require_module($license_class) }) {
  149         989  
384 0         0 $self->log_fatal(
385             "could not load class $license_class for license " . $self->_license_class
386             );
387             }
388              
389 149         118790 my $license = $license_class->new({
390             holder => $self->_copyright_holder,
391             year => $self->_copyright_year,
392             program => $self->name,
393             });
394              
395 149         7344 $self->_clear_license_class;
396 149         5822 $self->_clear_copyright_holder;
397 149         5511 $self->_clear_copyright_year;
398              
399 149         3764 return $license;
400             }
401              
402             has _license_class => (
403             is => 'ro',
404             isa => 'Maybe[Str]',
405             lazy => 1,
406             init_arg => 'license',
407             clearer => '_clear_license_class',
408             default => sub {
409             my $stash = $_[0]->stash_named('%Rights');
410             $stash && return $stash->license_class;
411             return;
412             }
413             );
414              
415             has _copyright_holder => (
416             is => 'ro',
417             isa => 'Maybe[Str]',
418             lazy => 1,
419             init_arg => 'copyright_holder',
420             clearer => '_clear_copyright_holder',
421             default => sub {
422             return unless my $stash = $_[0]->stash_named('%Rights');
423             $stash && return $stash->copyright_holder;
424             return;
425             }
426             );
427              
428             has _copyright_year => (
429             is => 'ro',
430             isa => 'Str',
431             lazy => 1,
432             init_arg => 'copyright_year',
433             clearer => '_clear_copyright_year',
434             default => sub {
435             # Oh man. This is a terrible idea! I mean, what if by the code gets run
436             # around like Dec 31, 23:59:59.9 and by the time the default gets called
437             # it's the next year but the default was already set up? Oh man. That
438             # could ruin lives! I guess we could make this a sub to defer the guess,
439             # but think of the performance hit! I guess we'll have to suffer through
440             # this until we can optimize the code to not take .1s to run, right? --
441             # rjbs, 2008-06-13
442             my $stash = $_[0]->stash_named('%Rights');
443             my $year = $stash && $stash->copyright_year;
444             return( $year // (localtime)[5] + 1900 );
445             }
446             );
447              
448             #pod =attr authors
449             #pod
450             #pod This is an arrayref of author strings, like this:
451             #pod
452             #pod [
453             #pod 'Ricardo Signes <rjbs@cpan.org>',
454             #pod 'X. Ample, Jr <example@example.biz>',
455             #pod ]
456             #pod
457             #pod This is likely to change at some point in the near future.
458             #pod
459             #pod =cut
460              
461             has authors => (
462             is => 'ro',
463             isa => ArrayRef[Str],
464             lazy => 1,
465             default => sub {
466             my ($self) = @_;
467              
468             if (my $stash = $self->stash_named('%User')) {
469             return $stash->authors;
470             }
471              
472             my $author = try { $self->copyright_holder };
473             return [ $author ] if length $author;
474              
475             $self->log_fatal(
476             "No %User stash and no copyright holder;",
477             "can't determine dist author; configure author or a %User section",
478             );
479             },
480             );
481              
482             #pod =attr files
483             #pod
484             #pod This is an arrayref of objects implementing L<Dist::Zilla::Role::File> that
485             #pod will, if left in this arrayref, be built into the dist.
486             #pod
487             #pod Non-core code should avoid altering this arrayref, but sometimes there is not
488             #pod other way to change the list of files. In the future, the representation used
489             #pod for storing files B<will be changed>.
490             #pod
491             #pod =cut
492              
493             has files => (
494             is => 'ro',
495             isa => ArrayRef[ role_type('Dist::Zilla::Role::File') ],
496             lazy => 1,
497             init_arg => undef,
498             default => sub { [] },
499             );
500              
501             sub prune_file {
502 22     22 0 57 my ($self, $file) = @_;
503 22         45 my @files = @{ $self->files };
  22         584  
504              
505 22         75 for my $i (0 .. $#files) {
506 52 100       129 next unless $file == $files[ $i ];
507 22         36 splice @{ $self->files }, $i, 1;
  22         547  
508 22         662 return;
509             }
510              
511 0         0 return;
512             }
513              
514             #pod =attr root
515             #pod
516             #pod This is the root directory of the dist, as a L<Path::Tiny>. It will
517             #pod nearly always be the current working directory in which C<dzil> was run.
518             #pod
519             #pod =cut
520              
521             has root => (
522             is => 'ro',
523             isa => Path,
524             coerce => 1,
525             required => 1,
526             );
527              
528             #pod =attr is_trial
529             #pod
530             #pod This attribute tells us whether or not the dist will be a trial release,
531             #pod i.e. whether it has C<release_status> 'testing' or 'unstable'.
532             #pod
533             #pod Do not set this directly, it will be derived from C<release_status>.
534             #pod
535             #pod =cut
536              
537             has is_trial => (
538             is => 'ro',
539             isa => Bool,
540             init_arg => undef,
541             lazy => 1,
542             builder => '_build_is_trial',
543             );
544              
545             has _override_is_trial => (
546             is => 'ro',
547             isa => Bool,
548             init_arg => 'is_trial',
549             default => 0,
550             );
551              
552             sub _build_is_trial {
553 56     56   150 my ($self) = @_;
554 56 100       1744 return $self->release_status =~ /\A(?:testing|unstable)\z/ ? 1 : 0;
555             }
556              
557             #pod =attr plugins
558             #pod
559             #pod This is an arrayref of plugins that have been plugged into this Dist::Zilla
560             #pod object.
561             #pod
562             #pod Non-core code B<must not> alter this arrayref. Public access to this attribute
563             #pod B<may go away> in the future.
564             #pod
565             #pod =cut
566              
567             has plugins => (
568             is => 'ro',
569             isa => 'ArrayRef[Dist::Zilla::Role::Plugin]',
570             init_arg => undef,
571             default => sub { [ ] },
572             );
573              
574             #pod =attr distmeta
575             #pod
576             #pod This is a hashref containing the metadata about this distribution that will be
577             #pod stored in META.yml or META.json. You should not alter the metadata in this
578             #pod hash; use a MetaProvider plugin instead.
579             #pod
580             #pod =cut
581              
582             has distmeta => (
583             is => 'ro',
584             isa => 'HashRef',
585             init_arg => undef,
586             lazy => 1,
587             builder => '_build_distmeta',
588             );
589              
590             sub _build_distmeta {
591 149     149   435 my ($self) = @_;
592              
593 149         28592 require CPAN::Meta::Merge;
594 149         114005 my $meta_merge = CPAN::Meta::Merge->new(default_version => 2);
595 149         30500 my $meta = {};
596              
597 149         316 for (@{ $self->plugins_with(-MetaProvider) }) {
  149         922  
598 13         5655 $meta = $meta_merge->merge($meta, $_->metadata);
599             }
600              
601 149   50     17071 my %meta_main = (
602             'meta-spec' => {
603             version => 2,
604             url => 'https://metacpan.org/pod/CPAN::Meta::Spec',
605             },
606             name => $self->name,
607             version => $self->version,
608             abstract => $self->abstract,
609             author => $self->authors,
610             license => [ $self->license->meta2_name ],
611              
612             release_status => $self->release_status,
613              
614             dynamic_config => 0, # problematic, I bet -- rjbs, 2010-06-04
615             generated_by => $self->_metadata_generator_id
616             . ' version '
617             . ($self->VERSION // '(undef)'),
618             x_generated_by_perl => "$^V", # v5.24.0
619             );
620 148 100       5013 if (my $spdx = $self->license->spdx_expression) {
621 147         1081 $meta_main{x_spdx_expression} = $spdx;
622             }
623              
624 148         873 $meta = $meta_merge->merge($meta, \%meta_main);
625              
626 148         186631 return $meta;
627             }
628              
629 1     1   21 sub _metadata_generator_id { 'Dist::Zilla' }
630              
631             #pod =attr prereqs
632             #pod
633             #pod This is a L<Dist::Zilla::Prereqs> object, which is a thin layer atop
634             #pod L<CPAN::Meta::Prereqs>, and describes the distribution's prerequisites.
635             #pod
636             #pod =method register_prereqs
637             #pod
638             #pod Allows registration of prerequisites; delegates to
639             #pod L<Dist::Zilla::Prereqs/register_prereqs> via our L</prereqs> attribute.
640             #pod
641             #pod =cut
642              
643             has prereqs => (
644             is => 'ro',
645             isa => 'Dist::Zilla::Prereqs',
646             init_arg => undef,
647             lazy => 1,
648             default => sub { Dist::Zilla::Prereqs->new },
649             handles => [ qw(register_prereqs) ],
650             );
651              
652             #pod =method plugin_named
653             #pod
654             #pod my $plugin = $zilla->plugin_named( $plugin_name );
655             #pod
656             #pod =cut
657              
658             sub plugin_named {
659 2027     2027 1 83527 my ($self, $name) = @_;
660 2027     17979   9273 my $plugin = first { $_->plugin_name eq $name } @{ $self->plugins };
  17979         593077  
  2027         57022  
661              
662 2027 100       11049 return $plugin if $plugin;
663 1762         7622 return;
664             }
665              
666             #pod =method plugins_with
667             #pod
668             #pod my $roles = $zilla->plugins_with( -SomeRole );
669             #pod
670             #pod This method returns an arrayref containing all the Dist::Zilla object's plugins
671             #pod that perform the named role. If the given role name begins with a dash, the
672             #pod dash is replaced with "Dist::Zilla::Role::"
673             #pod
674             #pod =cut
675              
676             sub plugins_with {
677 2148     2148 1 5688 my ($self, $role) = @_;
678              
679 2148         9553 $role =~ s/^-/Dist::Zilla::Role::/;
680 2148         3964 my $plugins = [ grep { $_->does($role) } @{ $self->plugins } ];
  30698         1190229  
  2148         70877  
681              
682 2148         90352 return $plugins;
683             }
684              
685             #pod =method find_files
686             #pod
687             #pod my $files = $zilla->find_files( $finder_name );
688             #pod
689             #pod This method will look for a
690             #pod L<FileFinder|Dist::Zilla::Role::FileFinder>-performing plugin with the given
691             #pod name and return the result of calling C<find_files> on it. If no plugin can be
692             #pod found, an exception will be raised.
693             #pod
694             #pod =cut
695              
696             sub find_files {
697 233     233 1 2277 my ($self, $finder_name) = @_;
698              
699 233 50       967 $self->log_fatal("no plugin named $finder_name found")
700             unless my $plugin = $self->plugin_named($finder_name);
701              
702 233 50       1282 $self->log_fatal("plugin $finder_name is not a FileFinder")
703             unless $plugin->does('Dist::Zilla::Role::FileFinder');
704              
705 233         18233 $plugin->find_files;
706             }
707              
708             sub _check_dupe_files {
709 147     147   496 my ($self) = @_;
710              
711 147         473 my %files_named;
712             my @dupes;
713 147         305 for my $file (@{ $self->files }) {
  147         5437  
714 645         1996 my $filename = $file->name;
715 645 50       1950 if (my $seen = $files_named{ $filename }) {
716 0         0 push @{ $seen }, $file;
  0         0  
717 0 0       0 push @dupes, $filename if @{ $seen } == 2;
  0         0  
718             } else {
719 645         2049 $files_named{ $filename } = [ $file ];
720             }
721             }
722              
723 147 50       5611 return unless @dupes;
724              
725 0         0 for my $name (@dupes) {
726             $self->log("attempt to add $name multiple times; added by: "
727 0         0 . join('; ', map { $_->added_by } @{ $files_named{ $name } })
  0         0  
  0         0  
728             );
729             }
730              
731 0         0 Carp::croak("aborting; duplicate files would be produced");
732             }
733              
734             sub _write_out_file {
735 646     646   1873 my ($self, $file, $build_root) = @_;
736              
737             # Okay, this is a bit much, until we have ->debug. -- rjbs, 2008-06-13
738             # $self->log("writing out " . $file->name);
739              
740 646         3033 my $file_path = path($file->name);
741              
742 646         28482 my $to_dir = path($build_root)->child( $file_path->parent );
743 646         76735 my $to = $to_dir->child( $file_path->basename );
744 646 100       28374 $to_dir->mkpath unless -e $to_dir;
745 646 50       176468 die "not a directory: $to_dir" unless -d $to_dir;
746              
747 646 50       15452 Carp::croak("attempted to write $to multiple times") if -e $to;
748              
749 646         33589 path("$to")->spew_raw( $file->encoded_content );
750 646 50       619486 chmod $file->mode, "$to" or die "couldn't chmod $to: $!";
751             }
752              
753             #pod =attr logger
754             #pod
755             #pod This attribute stores a L<Log::Dispatchouli::Proxy> object, used to log
756             #pod messages. By default, a proxy to the dist's L<Chrome|Dist::Zilla::Role::Chrome> is
757             #pod taken.
758             #pod
759             #pod The following methods are delegated from the Dist::Zilla object to the logger:
760             #pod
761             #pod =for :list
762             #pod * log
763             #pod * log_debug
764             #pod * log_fatal
765             #pod
766             #pod =cut
767              
768             has logger => (
769             is => 'ro',
770             isa => 'Log::Dispatchouli::Proxy', # could be duck typed, I guess
771             lazy => 1,
772             handles => [ qw(log log_debug log_fatal) ],
773             default => sub {
774             $_[0]->chrome->logger->proxy({ proxy_prefix => '[DZ] ' })
775             },
776             );
777              
778             around dump_config => sub {
779             my ($orig, $self) = @_;
780             my $config = $self->$orig;
781             $config->{is_trial} = $self->is_trial;
782             return $config;
783             };
784              
785             has _local_stashes => (
786             is => 'ro',
787             isa => HashRef[ Object ],
788             lazy => 1,
789             default => sub { {} },
790             );
791              
792             has _global_stashes => (
793             is => 'ro',
794             isa => HashRef[ Object ],
795             lazy => 1,
796             default => sub { {} },
797             );
798              
799             #pod =method stash_named
800             #pod
801             #pod my $stash = $zilla->stash_named( $name );
802             #pod
803             #pod This method will return the stash with the given name, or undef if none exists.
804             #pod It looks for a local stash (for this dist) first, then falls back to a global
805             #pod stash (from the user's global configuration).
806             #pod
807             #pod =cut
808              
809             sub stash_named {
810 161     161 1 502 my ($self, $name) = @_;
811              
812 161 100       5146 return $self->_local_stashes->{ $name } if $self->_local_stashes->{$name};
813 158         5492 return $self->_global_stashes->{ $name };
814             }
815              
816             __PACKAGE__->meta->make_immutable;
817             1;
818              
819             #pod =head1 STABILITY PROMISE
820             #pod
821             #pod None.
822             #pod
823             #pod I will try not to break things within any major release. Minor releases are
824             #pod not extensively tested before release. In major releases, anything goes,
825             #pod although I will try to publish a complete list of known breaking changes in any
826             #pod major release.
827             #pod
828             #pod If Dist::Zilla was a tool, it would have yellow and black stripes and there
829             #pod would be no L<UL
830             #pod certification|https://en.wikipedia.org/wiki/UL_(safety_organization)> on it.
831             #pod It is nasty, brutish, and large.
832             #pod
833             #pod =head1 SUPPORT
834             #pod
835             #pod There are usually people on C<irc.perl.org> in C<#distzilla>, even if they're
836             #pod idling.
837             #pod
838             #pod The L<Dist::Zilla website|https://dzil.org/> has several valuable resources for
839             #pod learning to use Dist::Zilla.
840             #pod
841             #pod =head1 SEE ALSO
842             #pod
843             #pod =over 4
844             #pod
845             #pod =item *
846             #pod
847             #pod In the Dist::Zilla distribution:
848             #pod
849             #pod =over 4
850             #pod
851             #pod =item *
852             #pod
853             #pod Plugin bundles:
854             #pod L<@Basic|Dist::Zilla::PluginBundle::Basic>,
855             #pod L<@Filter|Dist::Zilla::PluginBundle::Filter>.
856             #pod
857             #pod =item *
858             #pod
859             #pod Major plugins:
860             #pod L<GatherDir|Dist::Zilla::Plugin::GatherDir>,
861             #pod L<Prereqs|Dist::Zilla::Plugin::Prereqs>,
862             #pod L<AutoPrereqs|Dist::Zilla::Plugin::AutoPrereqs>,
863             #pod L<MetaYAML|Dist::Zilla::Plugin::MetaYAML>,
864             #pod L<MetaJSON|Dist::Zilla::Plugin::MetaJSON>,
865             #pod ...
866             #pod
867             #pod =back
868             #pod
869             #pod =item *
870             #pod
871             #pod On the CPAN:
872             #pod
873             #pod =over 4
874             #pod
875             #pod =item *
876             #pod
877             #pod Search for plugins: L<https://metacpan.org/search?q=Dist::Zilla::Plugin::>
878             #pod
879             #pod =item *
880             #pod
881             #pod Search for plugin bundles: L<https://metacpan.org/search?q=Dist::Zilla::PluginBundle::>
882             #pod
883             #pod =back
884             #pod
885             #pod =back
886              
887             __END__
888              
889             =pod
890              
891             =encoding UTF-8
892              
893             =head1 NAME
894              
895             Dist::Zilla - distribution builder; installer not included!
896              
897             =head1 VERSION
898              
899             version 6.037
900              
901             =head1 DESCRIPTION
902              
903             Dist::Zilla builds distributions of code to be uploaded to the CPAN. In this
904             respect, it is like L<ExtUtils::MakeMaker>, L<Module::Build>, or
905             L<Module::Install>. Unlike those tools, however, it is not also a system for
906             installing code that has been downloaded from the CPAN. Since it's only run by
907             authors, and is meant to be run on a repository checkout rather than on
908             published, released code, it can do much more than those tools, and is free to
909             make much more ludicrous demands in terms of prerequisites.
910              
911             If you have access to the web, you can learn more and find an interactive
912             tutorial at B<L<dzil.org|https://dzil.org/>>. If not, try
913             L<Dist::Zilla::Tutorial>.
914              
915             =head1 PERL VERSION
916              
917             This module should work on any version of perl still receiving updates from
918             the Perl 5 Porters. This means it should work on any version of perl
919             released in the last two to three years. (That is, if the most recently
920             released version is v5.40, then this module should work on both v5.40 and
921             v5.38.)
922              
923             Although it may work on older versions of perl, no guarantee is made that the
924             minimum required version will not be increased. The version may be increased
925             for any reason, and there is no promise that patches will be accepted to
926             lower the minimum required perl.
927              
928             =head1 ATTRIBUTES
929              
930             =head2 name
931              
932             The name attribute (which is required) gives the name of the distribution to be
933             built. This is usually the name of the distribution's main module, with the
934             double colons (C<::>) replaced with dashes. For example: C<Dist-Zilla>.
935              
936             =head2 version
937              
938             This is the version of the distribution to be created.
939              
940             =head2 release_status
941              
942             This attribute sets the release status to one of the
943             L<CPAN::META::Spec|https://metacpan.org/pod/CPAN::Meta::Spec#release_status>
944             values: 'stable', 'testing' or 'unstable'.
945              
946             If the C<$ENV{RELEASE_STATUS}> environment variable exists, its value will
947             be used as the release status.
948              
949             For backwards compatibility, if C<$ENV{RELEASE_STATUS}> does not exist and
950             the C<$ENV{TRIAL}> variable is true, the release status will be 'testing'.
951              
952             Otherwise, the release status will be set from a
953             L<ReleaseStatusProvider|Dist::Zilla::Role::ReleaseStatusProvider>, if one
954             has been configured.
955              
956             For backwards compatibility, setting C<is_trial> true in F<dist.ini> is
957             equivalent to using a C<ReleaseStatusProvider>. If C<is_trial> is false,
958             it has no effect.
959              
960             Only B<one> C<ReleaseStatusProvider> may be used.
961              
962             If no providers are used, the release status defaults to 'stable' unless there
963             is an "_" character in the version, in which case, it defaults to 'testing'.
964              
965             =head2 abstract
966              
967             This is a one-line summary of the distribution. If none is given, one will be
968             looked for in the L</main_module> of the dist.
969              
970             =head2 main_module
971              
972             This is the module where Dist::Zilla might look for various defaults, like
973             the distribution abstract. By default, it's derived from the distribution
974             name. If your distribution is Foo-Bar, and F<lib/Foo/Bar.pm> exists,
975             that's the main_module. Otherwise, it's the shortest-named module in the
976             distribution. This may change!
977              
978             You can override the default by specifying the file path explicitly,
979             ie:
980              
981             main_module = lib/Foo/Bar.pm
982              
983             =head2 license
984              
985             This is the L<Software::License|Software::License> object for this dist's
986             license and copyright.
987              
988             It will be created automatically, if possible, with the
989             C<copyright_holder> and C<copyright_year> attributes. If necessary, it will
990             try to guess the license from the POD of the dist's main module.
991              
992             A better option is to set the C<license> name in the dist's config to something
993             understandable, like C<Perl_5>.
994              
995             =head2 authors
996              
997             This is an arrayref of author strings, like this:
998              
999             [
1000             'Ricardo Signes <rjbs@cpan.org>',
1001             'X. Ample, Jr <example@example.biz>',
1002             ]
1003              
1004             This is likely to change at some point in the near future.
1005              
1006             =head2 files
1007              
1008             This is an arrayref of objects implementing L<Dist::Zilla::Role::File> that
1009             will, if left in this arrayref, be built into the dist.
1010              
1011             Non-core code should avoid altering this arrayref, but sometimes there is not
1012             other way to change the list of files. In the future, the representation used
1013             for storing files B<will be changed>.
1014              
1015             =head2 root
1016              
1017             This is the root directory of the dist, as a L<Path::Tiny>. It will
1018             nearly always be the current working directory in which C<dzil> was run.
1019              
1020             =head2 is_trial
1021              
1022             This attribute tells us whether or not the dist will be a trial release,
1023             i.e. whether it has C<release_status> 'testing' or 'unstable'.
1024              
1025             Do not set this directly, it will be derived from C<release_status>.
1026              
1027             =head2 plugins
1028              
1029             This is an arrayref of plugins that have been plugged into this Dist::Zilla
1030             object.
1031              
1032             Non-core code B<must not> alter this arrayref. Public access to this attribute
1033             B<may go away> in the future.
1034              
1035             =head2 distmeta
1036              
1037             This is a hashref containing the metadata about this distribution that will be
1038             stored in META.yml or META.json. You should not alter the metadata in this
1039             hash; use a MetaProvider plugin instead.
1040              
1041             =head2 prereqs
1042              
1043             This is a L<Dist::Zilla::Prereqs> object, which is a thin layer atop
1044             L<CPAN::Meta::Prereqs>, and describes the distribution's prerequisites.
1045              
1046             =head2 logger
1047              
1048             This attribute stores a L<Log::Dispatchouli::Proxy> object, used to log
1049             messages. By default, a proxy to the dist's L<Chrome|Dist::Zilla::Role::Chrome> is
1050             taken.
1051              
1052             The following methods are delegated from the Dist::Zilla object to the logger:
1053              
1054             =over 4
1055              
1056             =item *
1057              
1058             log
1059              
1060             =item *
1061              
1062             log_debug
1063              
1064             =item *
1065              
1066             log_fatal
1067              
1068             =back
1069              
1070             =head1 METHODS
1071              
1072             =head2 register_prereqs
1073              
1074             Allows registration of prerequisites; delegates to
1075             L<Dist::Zilla::Prereqs/register_prereqs> via our L</prereqs> attribute.
1076              
1077             =head2 plugin_named
1078              
1079             my $plugin = $zilla->plugin_named( $plugin_name );
1080              
1081             =head2 plugins_with
1082              
1083             my $roles = $zilla->plugins_with( -SomeRole );
1084              
1085             This method returns an arrayref containing all the Dist::Zilla object's plugins
1086             that perform the named role. If the given role name begins with a dash, the
1087             dash is replaced with "Dist::Zilla::Role::"
1088              
1089             =head2 find_files
1090              
1091             my $files = $zilla->find_files( $finder_name );
1092              
1093             This method will look for a
1094             L<FileFinder|Dist::Zilla::Role::FileFinder>-performing plugin with the given
1095             name and return the result of calling C<find_files> on it. If no plugin can be
1096             found, an exception will be raised.
1097              
1098             =head2 stash_named
1099              
1100             my $stash = $zilla->stash_named( $name );
1101              
1102             This method will return the stash with the given name, or undef if none exists.
1103             It looks for a local stash (for this dist) first, then falls back to a global
1104             stash (from the user's global configuration).
1105              
1106             =head1 STABILITY PROMISE
1107              
1108             None.
1109              
1110             I will try not to break things within any major release. Minor releases are
1111             not extensively tested before release. In major releases, anything goes,
1112             although I will try to publish a complete list of known breaking changes in any
1113             major release.
1114              
1115             If Dist::Zilla was a tool, it would have yellow and black stripes and there
1116             would be no L<UL
1117             certification|https://en.wikipedia.org/wiki/UL_(safety_organization)> on it.
1118             It is nasty, brutish, and large.
1119              
1120             =head1 SUPPORT
1121              
1122             There are usually people on C<irc.perl.org> in C<#distzilla>, even if they're
1123             idling.
1124              
1125             The L<Dist::Zilla website|https://dzil.org/> has several valuable resources for
1126             learning to use Dist::Zilla.
1127              
1128             =head1 SEE ALSO
1129              
1130             =over 4
1131              
1132             =item *
1133              
1134             In the Dist::Zilla distribution:
1135              
1136             =over 4
1137              
1138             =item *
1139              
1140             Plugin bundles:
1141             L<@Basic|Dist::Zilla::PluginBundle::Basic>,
1142             L<@Filter|Dist::Zilla::PluginBundle::Filter>.
1143              
1144             =item *
1145              
1146             Major plugins:
1147             L<GatherDir|Dist::Zilla::Plugin::GatherDir>,
1148             L<Prereqs|Dist::Zilla::Plugin::Prereqs>,
1149             L<AutoPrereqs|Dist::Zilla::Plugin::AutoPrereqs>,
1150             L<MetaYAML|Dist::Zilla::Plugin::MetaYAML>,
1151             L<MetaJSON|Dist::Zilla::Plugin::MetaJSON>,
1152             ...
1153              
1154             =back
1155              
1156             =item *
1157              
1158             On the CPAN:
1159              
1160             =over 4
1161              
1162             =item *
1163              
1164             Search for plugins: L<https://metacpan.org/search?q=Dist::Zilla::Plugin::>
1165              
1166             =item *
1167              
1168             Search for plugin bundles: L<https://metacpan.org/search?q=Dist::Zilla::PluginBundle::>
1169              
1170             =back
1171              
1172             =back
1173              
1174             =head1 AUTHOR
1175              
1176             Ricardo SIGNES 😏 <cpan@semiotic.systems>
1177              
1178             =head1 CONTRIBUTORS
1179              
1180             =for stopwords Ævar Arnfjörð Bjarmason Alastair McGowan-Douglas Alceu Rodrigues de Freitas Junior Alexei Znamensky Alex Vandiver ambs Andrew Rodland Andy Jack Apocalypse ben hengst Bernardo Rechea Branislav Zahradník Brian Fraser Caleb Cushing Chase Whitener Chisel Christian Walde Christopher Bottoms J. Madsen Chris Weyl Cory G Watson csjewell Curtis Brandt Dagfinn Ilmari Mannsåker Damien KRotkine Dan Book Daniel Böhmer Danijel Tasov Dave Lambley O'Neill Rolsky David E. Wheeler Golden H. Adler Steinbrunner Zurborg Davor Cubranic Dimitar Petrov Doug Bell Elvin Aslanov Erik Carlsson Fayland Lam Felix Ostmann Florian Ragwitz Fred Moyer fREW Schmidt gardnerm Gianni Ceccarelli Graham Barr Knop Ollis Grzegorz Rożniecki Håkon Hægland Hans Dieter Pearcey Hunter McMillen Ivan Bessarabov Jakob Voss jantore Jérôme Quelin Jesse Luehrs Vincent JJ Merelo John Napiorkowski jonasbn Jonathan C. Otsuka Rockway Scott Duff Yu Karen Etheridge Kent Fredric Leon Timmermans Lucas Theisen Luc St-Louis Marcel Gruenauer Mark Flickinger Martin McGrath Mary Ehlers Mateu X Matthew Horsfall mauke Michael Conrad G. Schwern Jemmeson Mickey Nasriachi Mike Doherty Mohammad S Anwar Moritz Onken Neil Bowers Nickolay Platonov Nick Tonkin nperez Olivier Mengué Paul Cochrane Paulo Custodio Pedro Melo perlancar (@pc-office) Philippe Bruhat (BooK) raf Randy Stauner reneeb Ricardo Signes robertkrimen Rob Hoelz Robin Smidsrød Roy Ivy III Shawn M Moore Shlomi Fish Shoichi Kaji Smylers Steffen Schwigon Steven Haryanto Tatsuhiko Miyagawa Upasana Shukla Van Bugger Vyacheslav Matjukhin Yanick Champoux Yuval Kogman
1181              
1182             =over 4
1183              
1184             =item *
1185              
1186             Ævar Arnfjörð Bjarmason <avarab@gmail.com>
1187              
1188             =item *
1189              
1190             Alastair McGowan-Douglas <alastair.mcgowan@opusvl.com>
1191              
1192             =item *
1193              
1194             Alceu Rodrigues de Freitas Junior <glasswalk3r@yahoo.com.br>
1195              
1196             =item *
1197              
1198             Alexei Znamensky <russoz@cpan.org>
1199              
1200             =item *
1201              
1202             Alex Vandiver <alexmv@mit.edu>
1203              
1204             =item *
1205              
1206             ambs <ambs@cpan.org>
1207              
1208             =item *
1209              
1210             Andrew Rodland <andrew@hbslabs.com>
1211              
1212             =item *
1213              
1214             Andy Jack <andyjack@cpan.org>
1215              
1216             =item *
1217              
1218             Apocalypse <APOCAL@cpan.org>
1219              
1220             =item *
1221              
1222             ben hengst <ben.hengst@gmail.com>
1223              
1224             =item *
1225              
1226             Bernardo Rechea <brbpub@gmail.com>
1227              
1228             =item *
1229              
1230             Branislav Zahradník <happy.barney@gmail.com>
1231              
1232             =item *
1233              
1234             Brian Fraser <fraserbn@gmail.com>
1235              
1236             =item *
1237              
1238             Caleb Cushing <xenoterracide@gmail.com>
1239              
1240             =item *
1241              
1242             Chase Whitener <cwhitener@gmail.com>
1243              
1244             =item *
1245              
1246             Chisel <chisel@chizography.net>
1247              
1248             =item *
1249              
1250             Christian Walde <walde.christian@googlemail.com>
1251              
1252             =item *
1253              
1254             Christopher Bottoms <molecules@users.noreply.github.com>
1255              
1256             =item *
1257              
1258             Christopher J. Madsen <cjm@cjmweb.net>
1259              
1260             =item *
1261              
1262             Chris Weyl <cweyl@alumni.drew.edu>
1263              
1264             =item *
1265              
1266             Cory G Watson <gphat@onemogin.com>
1267              
1268             =item *
1269              
1270             csjewell <perl@csjewell.fastmail.us>
1271              
1272             =item *
1273              
1274             Curtis Brandt <curtisjbrandt@gmail.com>
1275              
1276             =item *
1277              
1278             Dagfinn Ilmari Mannsåker <ilmari@ilmari.org>
1279              
1280             =item *
1281              
1282             Damien KRotkine <dkrotkine@booking.com>
1283              
1284             =item *
1285              
1286             Dan Book <grinnz@gmail.com>
1287              
1288             =item *
1289              
1290             Daniel Böhmer <post@daniel-boehmer.de>
1291              
1292             =item *
1293              
1294             Danijel Tasov <dt@korn.shell.la>
1295              
1296             =item *
1297              
1298             Dave Lambley <dave@lambley.me.uk>
1299              
1300             =item *
1301              
1302             Dave O'Neill <dmo@dmo.ca>
1303              
1304             =item *
1305              
1306             Dave Rolsky <autarch@urth.org>
1307              
1308             =item *
1309              
1310             David E. Wheeler <david@justatheory.com>
1311              
1312             =item *
1313              
1314             David Golden <dagolden@cpan.org>
1315              
1316             =item *
1317              
1318             David H. Adler <dha@pobox.com>
1319              
1320             =item *
1321              
1322             David Steinbrunner <dsteinbrunner@pobox.com>
1323              
1324             =item *
1325              
1326             David Zurborg <port@david-zurb.org>
1327              
1328             =item *
1329              
1330             Davor Cubranic <cubranic@stat.ubc.ca>
1331              
1332             =item *
1333              
1334             Dimitar Petrov <mitakaa@gmail.com>
1335              
1336             =item *
1337              
1338             Doug Bell <doug@preaction.me>
1339              
1340             =item *
1341              
1342             Elvin Aslanov <rwp.primary@gmail.com>
1343              
1344             =item *
1345              
1346             Erik Carlsson <info@code301.com>
1347              
1348             =item *
1349              
1350             Fayland Lam <fayland@gmail.com>
1351              
1352             =item *
1353              
1354             Felix Ostmann <felix.ostmann@gmail.com>
1355              
1356             =item *
1357              
1358             Florian Ragwitz <rafl@debian.org>
1359              
1360             =item *
1361              
1362             Fred Moyer <fred@redhotpenguin.com>
1363              
1364             =item *
1365              
1366             fREW Schmidt <frioux@gmail.com>
1367              
1368             =item *
1369              
1370             gardnerm <gardnerm@gsicommerce.com>
1371              
1372             =item *
1373              
1374             Gianni Ceccarelli <gianni.ceccarelli@net-a-porter.com>
1375              
1376             =item *
1377              
1378             Graham Barr <gbarr@pobox.com>
1379              
1380             =item *
1381              
1382             Graham Knop <haarg@haarg.org>
1383              
1384             =item *
1385              
1386             Graham Ollis <plicease@cpan.org>
1387              
1388             =item *
1389              
1390             Grzegorz Rożniecki <xaerxess@gmail.com>
1391              
1392             =item *
1393              
1394             Håkon Hægland <hakon.hagland@gmail.com>
1395              
1396             =item *
1397              
1398             Hans Dieter Pearcey <hdp@weftsoar.net>
1399              
1400             =item *
1401              
1402             Hunter McMillen <mcmillhj@gmail.com>
1403              
1404             =item *
1405              
1406             Ivan Bessarabov <ivan@bessarabov.ru>
1407              
1408             =item *
1409              
1410             Jakob Voss <jakob@nichtich.de>
1411              
1412             =item *
1413              
1414             jantore <jantore@32k.org>
1415              
1416             =item *
1417              
1418             Jérôme Quelin <jquelin@gmail.com>
1419              
1420             =item *
1421              
1422             Jesse Luehrs <doy@tozt.net>
1423              
1424             =item *
1425              
1426             Jesse Vincent <jesse@bestpractical.com>
1427              
1428             =item *
1429              
1430             JJ Merelo <jjmerelo@gmail.com>
1431              
1432             =item *
1433              
1434             John Napiorkowski <jjnapiork@cpan.org>
1435              
1436             =item *
1437              
1438             jonasbn <jonasbn@gmail.com>
1439              
1440             =item *
1441              
1442             Jonathan C. Otsuka <djgoku@gmail.com>
1443              
1444             =item *
1445              
1446             Jonathan Rockway <jrockway@cpan.org>
1447              
1448             =item *
1449              
1450             Jonathan Scott Duff <duff@pobox.com>
1451              
1452             =item *
1453              
1454             Jonathan Yu <jawnsy@cpan.org>
1455              
1456             =item *
1457              
1458             Karen Etheridge <ether@cpan.org>
1459              
1460             =item *
1461              
1462             Kent Fredric <kentfredric@gmail.com>
1463              
1464             =item *
1465              
1466             Leon Timmermans <fawaka@gmail.com>
1467              
1468             =item *
1469              
1470             Lucas Theisen <lucastheisen@pastdev.com>
1471              
1472             =item *
1473              
1474             Luc St-Louis <lucs@pobox.com>
1475              
1476             =item *
1477              
1478             Marcel Gruenauer <hanekomu@gmail.com>
1479              
1480             =item *
1481              
1482             Mark Flickinger <mark.flickinger@grantstreet.com>
1483              
1484             =item *
1485              
1486             Martin McGrath <mcgrath.martin@gmail.com>
1487              
1488             =item *
1489              
1490             Mary Ehlers <regina.verb.ae@gmail.com>
1491              
1492             =item *
1493              
1494             Mateu X Hunter <hunter@missoula.org>
1495              
1496             =item *
1497              
1498             Matthew Horsfall <wolfsage@gmail.com>
1499              
1500             =item *
1501              
1502             mauke <l.mai@web.de>
1503              
1504             =item *
1505              
1506             Michael Conrad <mike@nrdvana.net>
1507              
1508             =item *
1509              
1510             Michael G. Schwern <schwern@pobox.com>
1511              
1512             =item *
1513              
1514             Michael Jemmeson <mjemmeson@cpan.org>
1515              
1516             =item *
1517              
1518             Mickey Nasriachi <mickey@cpan.org>
1519              
1520             =item *
1521              
1522             Mike Doherty <mike@mikedoherty.ca>
1523              
1524             =item *
1525              
1526             Mohammad S Anwar <mohammad.anwar@yahoo.com>
1527              
1528             =item *
1529              
1530             Moritz Onken <onken@netcubed.de>
1531              
1532             =item *
1533              
1534             Neil Bowers <neil@bowers.com>
1535              
1536             =item *
1537              
1538             Nickolay Platonov <nickolay@desktop.(none)>
1539              
1540             =item *
1541              
1542             Nick Tonkin <1nickt@users.noreply.github.com>
1543              
1544             =item *
1545              
1546             nperez <nperez@cpan.org>
1547              
1548             =item *
1549              
1550             Olivier Mengué <dolmen@cpan.org>
1551              
1552             =item *
1553              
1554             Paul Cochrane <paul@liekut.de>
1555              
1556             =item *
1557              
1558             Paulo Custodio <pauloscustodio@gmail.com>
1559              
1560             =item *
1561              
1562             Pedro Melo <melo@simplicidade.org>
1563              
1564             =item *
1565              
1566             perlancar (@pc-office) <perlancar@gmail.com>
1567              
1568             =item *
1569              
1570             Philippe Bruhat (BooK) <book@cpan.org>
1571              
1572             =item *
1573              
1574             raf <68724930+rafork@users.noreply.github.com>
1575              
1576             =item *
1577              
1578             Randy Stauner <rwstauner@cpan.org>
1579              
1580             =item *
1581              
1582             reneeb <info@perl-services.de>
1583              
1584             =item *
1585              
1586             Ricardo Signes <rjbs@semiotic.systems>
1587              
1588             =item *
1589              
1590             robertkrimen <robertkrimen@gmail.com>
1591              
1592             =item *
1593              
1594             Rob Hoelz <rob@hoelz.ro>
1595              
1596             =item *
1597              
1598             Robin Smidsrød <robin@smidsrod.no>
1599              
1600             =item *
1601              
1602             Roy Ivy III <rivy@cpan.org>
1603              
1604             =item *
1605              
1606             Shawn M Moore <sartak@gmail.com>
1607              
1608             =item *
1609              
1610             Shlomi Fish <shlomif@shlomifish.org>
1611              
1612             =item *
1613              
1614             Shoichi Kaji <skaji@cpan.org>
1615              
1616             =item *
1617              
1618             Smylers <Smylers@stripey.com>
1619              
1620             =item *
1621              
1622             Steffen Schwigon <ss5@renormalist.net>
1623              
1624             =item *
1625              
1626             Steven Haryanto <stevenharyanto@gmail.com>
1627              
1628             =item *
1629              
1630             Tatsuhiko Miyagawa <miyagawa@bulknews.net>
1631              
1632             =item *
1633              
1634             Upasana Shukla <me@upasana.me>
1635              
1636             =item *
1637              
1638             Van de Bugger <van.de.bugger@gmail.com>
1639              
1640             =item *
1641              
1642             Vyacheslav Matjukhin <mmcleric@yandex-team.ru>
1643              
1644             =item *
1645              
1646             Yanick Champoux <yanick@babyl.dyndns.org>
1647              
1648             =item *
1649              
1650             Yuval Kogman <nothingmuch@woobling.org>
1651              
1652             =back
1653              
1654             =head1 COPYRIGHT AND LICENSE
1655              
1656             This software is copyright (c) 2026 by Ricardo SIGNES.
1657              
1658             This is free software; you can redistribute it and/or modify it under
1659             the same terms as the Perl 5 programming language system itself.
1660              
1661             =cut