File Coverage

blib/lib/Dist/Zilla/Plugin/GenerateFile/FromShareDir.pm
Criterion Covered Total %
statement 60 64 93.7
branch 16 24 66.6
condition 1 3 33.3
subroutine 13 14 92.8
pod 0 4 0.0
total 90 109 82.5


line stmt bran cond sub pod time code
1 5     5   16375804 use strict;
  5         16  
  5         210  
2 5     5   36 use warnings;
  5         15  
  5         443  
3             package Dist::Zilla::Plugin::GenerateFile::FromShareDir; # git description: v0.014-9-g84393db
4             # vim: set ts=8 sts=2 sw=2 tw=115 et :
5             # ABSTRACT: Create files in the repository or build, using a sharedir template
6             # KEYWORDS: plugin distribution generate create file sharedir template
7              
8             our $VERSION = '0.015';
9              
10 5     5   43 use Moose;
  5         11  
  5         55  
11             with (
12             'Dist::Zilla::Role::FileGatherer',
13             'Dist::Zilla::Role::FileMunger',
14             'Dist::Zilla::Role::TextTemplate',
15             'Dist::Zilla::Role::RepoFileInjector' => { -version => '0.006' },
16             'Dist::Zilla::Role::AfterBuild',
17             'Dist::Zilla::Role::AfterRelease',
18             );
19              
20 5     5   39731 use MooseX::SlurpyConstructor 1.2;
  5         128995  
  5         34  
21 5     5   202262 use Moose::Util 'find_meta';
  5         16  
  5         49  
22 5     5   2048 use File::ShareDir 'dist_file';
  5         21875  
  5         541  
23 5     5   44 use Path::Tiny 0.04;
  5         157  
  5         291  
24 5     5   41 use Encode;
  5         13  
  5         455  
25 5     5   40 use Moose::Util::TypeConstraints 'enum';
  5         15  
  5         62  
26 5     5   2713 use namespace::autoclean;
  5         14  
  5         129  
27              
28             has dist => (
29             is => 'ro', isa => 'Str',
30             init_arg => '-dist',
31             lazy => 1,
32             default => sub { (my $dist = find_meta(shift)->name) =~ s/::/-/g; $dist },
33             );
34              
35             has filename => (
36             init_arg => '-destination_filename',
37             is => 'ro', isa => 'Str',
38             required => 1,
39             );
40              
41             has source_filename => (
42             init_arg => '-source_filename',
43             is => 'ro', isa => 'Str',
44             lazy => 1,
45             default => sub { shift->filename },
46             );
47              
48             has encoding => (
49             init_arg => '-encoding',
50             is => 'ro', isa => 'Str',
51             lazy => 1,
52             default => 'UTF-8',
53             );
54              
55             has location => (
56             is => 'ro', isa => enum([ qw(build root) ]),
57             lazy => 1,
58             default => 'build',
59             init_arg => '-location',
60             );
61              
62             has phase => (
63             is => 'ro', isa => enum([ qw(build release) ]),
64             lazy => 1,
65             default => 'build',
66             init_arg => '-phase',
67             );
68              
69             has _extra_args => (
70             isa => 'HashRef[Str]',
71             init_arg => undef,
72             lazy => 1,
73             default => sub { {} },
74             traits => ['Hash'],
75             handles => { _extra_args => 'elements' },
76             slurpy => 1,
77             );
78              
79             around BUILDARGS => sub
80             {
81             my $orig = shift;
82             my $class = shift;
83              
84             my $args = $class->$orig(@_);
85             $args->{'-destination_filename'} = delete $args->{'-filename'} if exists $args->{'-filename'};
86              
87             return $args;
88             };
89              
90             around dump_config => sub
91             {
92             my ($orig, $self) = @_;
93             my $config = $self->$orig;
94              
95             $config->{+__PACKAGE__} = {
96             # XXX FIXME - it seems META.* does not like the leading - in field
97             # names! something is wrong with the serialization process.
98             'dist' => $self->dist,
99             'encoding' => $self->encoding,
100             'source_filename' => $self->source_filename,
101             'destination_filename' => $self->filename,
102             'location' => $self->location,
103             $self->location eq 'root' ? ( 'phase' => $self->phase ) : (),
104             blessed($self) ne __PACKAGE__ ? ( version => $VERSION ) : (),
105             $self->_extra_args,
106             };
107             return $config;
108             };
109              
110             sub gather_files
111             {
112 5     5 0 320886 my $self = shift;
113              
114 5         19 my $file_path = eval { dist_file($self->dist, $self->source_filename) };
  5         239  
115              
116 5 100       1672 if (not $file_path) {
117 1 50       49 if ($self->dist eq $self->zilla->name) {
118 1 50       64 if (my $sharedir = $self->zilla->_share_dir_map->{dist}) {
119 1         984 $file_path = path($self->zilla->root, $sharedir, $self->source_filename)->stringify;
120             }
121             }
122              
123 1 50       70 $self->log_fatal('cannot find sharedir!') if not defined $file_path;
124             }
125              
126 5 50       84 $self->log_fatal([ 'cannot find %s', $file_path ]) if not -e $file_path;
127              
128 5         67 $self->log_debug([ 'using template in %s', $file_path ]);
129 5         1877 my $content = path($file_path)->slurp_raw;
130 5         1603 $content = Encode::decode($self->encoding, $content, Encode::FB_CROAK());
131              
132 5         4617 require Dist::Zilla::File::InMemory;
133 5         461787 my $file = Dist::Zilla::File::InMemory->new(
134             name => $self->filename,
135             encoding => $self->encoding, # only used in Dist::Zilla 5.000+
136             content => $content,
137             );
138              
139 5 100       3597 if ($self->location eq 'build')
140             {
141 4 100       181 if ($self->phase eq 'release')
142             {
143             # we can't generate a file only in the release without doing it now,
144             # which would add it for all builds. Consequently this config combo is
145             # nonsensical and suggests the user is misunderstanding something.
146 1         22 $self->log('nonsensical and impossible combination of configs: -location = build, -phase = release');
147 1         496 return;
148             }
149              
150 3         26 $self->add_file($file);
151             }
152             else
153             {
154             # root eq $self->location
155 1         10 $self->add_repo_file($file);
156             }
157 4         4366 return;
158             }
159              
160             around munge_files => sub
161             {
162             my ($orig, $self, @args) = @_;
163              
164             return $self->$orig(@args) if $self->location eq 'build';
165              
166             for my $file ($self->_repo_files)
167             {
168             $self->munge_file($file);
169             }
170             };
171              
172             sub munge_file
173             {
174 6     6 0 497 my ($self, $file) = @_;
175              
176 6 100       27 return unless $file->name eq $self->filename;
177              
178 4 50 33     45 if ($file->can('is_bytes') and $file->is_bytes)
179             {
180 0         0 $self->log_debug([ '%s has \'bytes\' encoding, skipping...', $file->name ]);
181 0         0 return;
182             }
183              
184 4         180 $self->log_debug([ 'updating contents of %s in memory', $file->name ]);
185              
186 4         1657 my $content = $self->fill_in_string(
187             $file->content,
188             {
189             $self->_extra_args, # must be first
190             dist => \($self->zilla),
191             plugin => \$self,
192             },
193             );
194              
195             # older Dist::Zilla wrote out all files :raw, so we need to encode manually here.
196 4 50       2161 $content = Encode::encode($self->encoding, $content, Encode::FB_CROAK()) if not $file->can('encoded_content');
197              
198 4         28 $file->content($content);
199             }
200              
201             sub after_build
202             {
203 5     5 0 85273 my $self = shift;
204 5 100       239 $self->write_repo_files if $self->phase eq 'build';
205             }
206              
207             sub after_release
208             {
209 0     0 0   my $self = shift;
210 0 0         $self->write_repo_files if $self->phase eq 'release';
211             }
212              
213             __PACKAGE__->meta->make_immutable;
214              
215             __END__
216              
217             =pod
218              
219             =encoding UTF-8
220              
221             =for stopwords sharedir
222              
223             =head1 NAME
224              
225             Dist::Zilla::Plugin::GenerateFile::FromShareDir - Create files in the repository or build, using a sharedir template
226              
227             =head1 VERSION
228              
229             version 0.015
230              
231             =head1 SYNOPSIS
232              
233             In your F<dist.ini>:
234              
235             [GenerateFile::FromShareDir]
236             -dist = Dist::Zilla::PluginBundle::Author::ME
237             -source_filename = my_data_template.txt
238             -destination_filename = examples/my_data.txt
239             key1 = value to pass to template
240             key2 = another value to pass to template
241              
242             =head1 DESCRIPTION
243              
244             Generates a file in your distribution, indicated by C<-destination_file>, based on the
245             L<Text::Template> located in the C<-source_file> of C<-dist>'s
246             L<distribution sharedir|File::ShareDir>. Any extra config values are passed
247             along to the template, in addition to C<$zilla> and C<$plugin> objects.
248              
249             I expect that usually the C<-dist> that contains the template will be either a
250             plugin bundle, so you can generate a custom-tailored file in your distribution, or a
251             plugin that subclasses this one. (Otherwise, you can just as easily use
252             L<[GatherDir::Template]|Dist::Zilla::Plugin::GatherDir::Template>
253             or L<[GenerateFile]|Dist::Zilla::Plugin::GenerateFile>
254             to generate the file directly, without needing a sharedir.)
255              
256             =for Pod::Coverage::TrustPod gather_files
257             munge_file
258             after_build
259             after_release
260              
261             =head1 OPTIONS
262              
263             All unrecognized keys/values will be passed to the template as is.
264             Recognized options are:
265              
266             =head2 C<-dist>
267              
268             The distribution name to use when finding the sharedir (see L<File::ShareDir>
269             and L<Dist::Zilla::Plugin::ShareDir>). Defaults to the distribution corresponding to
270             the running plugin.
271              
272             =head2 C<-destination_filename> or C<-filename>
273              
274             The filename to generate in the distribution being built. Required.
275              
276             =head2 C<-source_filename>
277              
278             The filename in the sharedir to use to generate the new file. Defaults to the
279             same filename and path as C<-destination_file>.
280              
281             =head2 C<-encoding>
282              
283             The encoding of the source file; will also be used for the encoding of the
284             destination file. Defaults to UTF-8.
285              
286             =head2 C<-location>
287              
288             default: C<build>
289              
290             The target location of the generated file. When C<build>, the file is added to
291             the distribution in the normal file gathering phase. When C<root>, the file is
292             instead written to the source repository.
293              
294             =head2 C<-phase>
295              
296             Only relevant when C<-location = root>. When C<build> (the default), the file
297             is written on every build operation. When C<release>, it is only written after
298             the distribution is released.
299              
300             =head1 SEE ALSO
301              
302             =for stopwords templated
303              
304             =over 4
305              
306             =item *
307              
308             L<File::ShareDir>
309              
310             =item *
311              
312             L<Dist::Zilla::Plugin::ShareDir>
313              
314             =item *
315              
316             L<Text::Template>
317              
318             =item *
319              
320             L<[GatherDir::Template]|Dist::Zilla::Plugin::GatherDir::Template> - gather a file from the dist, and then pass it through a template
321              
322             =item *
323              
324             L<[GenerateFile]|Dist::Zilla::Plugin::GenerateFile> - generate a (possibly-templated) file purely based on data in F<dist.ini>
325              
326             =back
327              
328             =head1 SUPPORT
329              
330             Bugs may be submitted through L<the RT bug tracker|https://rt.cpan.org/Public/Dist/Display.html?Name=Dist-Zilla-Plugin-GenerateFile-FromShareDir>
331             (or L<bug-Dist-Zilla-Plugin-GenerateFile-FromShareDir@rt.cpan.org|mailto:bug-Dist-Zilla-Plugin-GenerateFile-FromShareDir@rt.cpan.org>).
332              
333             There is also a mailing list available for users of this distribution, at
334             L<http://dzil.org/#mailing-list>.
335              
336             There is also an irc channel available for users of this distribution, at
337             L<C<#distzilla> on C<irc.perl.org>|irc://irc.perl.org/#distzilla>.
338              
339             I am also usually active on irc, as 'ether' at C<irc.perl.org> and C<irc.freenode.org>.
340              
341             =head1 AUTHOR
342              
343             Karen Etheridge <ether@cpan.org>
344              
345             =head1 CONTRIBUTORS
346              
347             =for stopwords Dave Rolsky Kent Fredric
348              
349             =over 4
350              
351             =item *
352              
353             Dave Rolsky <autarch@urth.org>
354              
355             =item *
356              
357             Kent Fredric <kentfredric@gmail.com>
358              
359             =back
360              
361             =head1 COPYRIGHT AND LICENCE
362              
363             This software is copyright (c) 2013 by Karen Etheridge.
364              
365             This is free software; you can redistribute it and/or modify it under
366             the same terms as the Perl 5 programming language system itself.
367              
368             =cut