File Coverage

blib/lib/Dist/Zilla/Plugin/GenerateFile/FromShareDir.pm
Criterion Covered Total %
statement 56 58 96.5
branch 12 16 75.0
condition n/a
subroutine 13 14 92.8
pod 0 4 0.0
total 81 92 88.0


line stmt bran cond sub pod time code
1 6     6   9399380 use strict;
  6         8  
  6         172  
2 6     6   22 use warnings;
  6         7  
  6         331  
3             package Dist::Zilla::Plugin::GenerateFile::FromShareDir; # git description: v0.012-6-g2cf801b
4             # vim: set ts=8 sts=4 sw=4 tw=115 et :
5             # ABSTRACT: Create files in the repository or in the build, based on a template located in a dist sharedir
6             # KEYWORDS: plugin distribution generate create file sharedir template
7              
8             our $VERSION = '0.013';
9              
10 6     6   20 use Moose;
  6         7  
  6         40  
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 6     6   27680 use MooseX::SlurpyConstructor 1.2;
  6         90877  
  6         27  
21 6     6   148465 use Moose::Util 'find_meta';
  6         12  
  6         41  
22 6     6   1653 use File::ShareDir 'dist_file';
  6         4115  
  6         446  
23 6     6   28 use Path::Tiny 0.04;
  6         140  
  6         252  
24 6     6   25 use Encode;
  6         9  
  6         382  
25 6     6   26 use Moose::Util::TypeConstraints 'enum';
  6         8  
  6         44  
26 6     6   1805 use namespace::autoclean;
  6         8  
  6         39  
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 6     6 0 234598 my $self = shift;
113              
114 6         10 my $file_path;
115 6 100       223 if ($self->dist eq $self->zilla->name)
116             {
117 1 50       50 if (my $sharedir = $self->zilla->_share_dir_map->{dist}) {
118 1         616 $file_path = path($sharedir, $self->source_filename)->stringify;
119             }
120             }
121             else
122             {
123             # this should die if the file does not exist
124 5         278 $file_path = dist_file($self->dist, $self->source_filename);
125             }
126              
127 6         630 $self->log_debug([ 'using template in %s', $file_path ]);
128              
129 6         1517 my $content = path($file_path)->slurp_raw;
130 6         1484 $content = Encode::decode($self->encoding, $content, Encode::FB_CROAK());
131              
132 6         3971 require Dist::Zilla::File::InMemory;
133 6         361789 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 6 100       2425 if ($self->location eq 'build')
140             {
141 5 100       177 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         6 $self->log('nonsensical and impossible combination of configs: -location = build, -phase = release');
147 1         365 return;
148             }
149              
150 4         31 $self->add_file($file);
151             }
152             else
153             {
154             # root eq $self->location
155 1         6 $self->add_repo_file($file);
156             }
157 5         3898 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             if ($file->can('is_bytes') and $file->is_bytes)
169             {
170             $self->log_debug([ '%s has \'bytes\' encoding, skipping...', $file->name ]);
171             next;
172             }
173             $self->munge_file($file);
174             }
175             };
176              
177             sub munge_file
178             {
179 7     7 0 433 my ($self, $file) = @_;
180              
181 7 100       22 return unless $file->name eq $self->filename;
182 5         30 $self->log_debug([ 'updating contents of %s in memory', $file->name ]);
183              
184 5         1350 my $content = $self->fill_in_string(
185             $file->content,
186             {
187             $self->_extra_args, # must be first
188             dist => \($self->zilla),
189             plugin => \$self,
190             },
191             );
192              
193             # older Dist::Zilla wrote out all files :raw, so we need to encode manually here.
194 5 50       1572 $content = Encode::encode($self->encoding, $content, Encode::FB_CROAK()) if not $file->can('encoded_content');
195              
196 5         20 $file->content($content);
197             }
198              
199             sub after_build
200             {
201 6     6 0 161472 my $self = shift;
202 6 100       284 $self->write_repo_files if $self->phase eq 'build';
203             }
204              
205             sub after_release
206             {
207 0     0 0   my $self = shift;
208 0 0         $self->write_repo_files if $self->phase eq 'release';
209             }
210              
211             __PACKAGE__->meta->make_immutable;
212              
213             __END__
214              
215             =pod
216              
217             =encoding UTF-8
218              
219             =for stopwords sharedir
220              
221             =head1 NAME
222              
223             Dist::Zilla::Plugin::GenerateFile::FromShareDir - Create files in the repository or in the build, based on a template located in a dist sharedir
224              
225             =head1 VERSION
226              
227             version 0.013
228              
229             =head1 SYNOPSIS
230              
231             In your F<dist.ini>:
232              
233             [GenerateFile::FromShareDir]
234             -dist = Dist::Zilla::PluginBundle::Author::ME
235             -source_filename = my_data_template.txt
236             -destination_filename = examples/my_data.txt
237             key1 = value to pass to template
238             key2 = another value to pass to template
239              
240             =head1 DESCRIPTION
241              
242             Generates a file in your dist, indicated by C<-destination_file>, based on the
243             L<Text::Template> located in the C<-source_file> of C<-dist>'s
244             L<distribution sharedir|File::ShareDir>. Any extra config values are passed
245             along to the template, in addition to C<$zilla> and C<$plugin> objects.
246              
247             I expect that usually the C<-dist> that contains the template will be either a
248             plugin bundle, so you can generate a custom-tailored file in your dist, or a
249             plugin that subclasses this one. (Otherwise, you can just as easily use
250             L<[GatherDir::Template]|Dist::Zilla::Plugin::GatherDir::Template>
251             or L<[GenerateFile]|Dist::Zilla::Plugin::GenerateFile>
252             to generate the file directly, without needing a sharedir.)
253              
254             =for Pod::Coverage::TrustPod gather_files
255             munge_file
256             after_build
257             after_release
258              
259             =head1 OPTIONS
260              
261             All unrecognized keys/values will be passed to the template as is.
262             Recognized options are:
263              
264             =head2 C<-dist>
265              
266             The distribution name to use when finding the sharedir (see L<File::ShareDir>
267             and L<Dist::Zilla::Plugin::ShareDir>). Defaults to the dist corresponding to
268             the running plugin.
269              
270             =head2 C<-destination_filename> or C<-filename>
271              
272             The filename to generate in the distribution being built. Required.
273              
274             =head2 C<-source_filename>
275              
276             The filename in the sharedir to use to generate the new file. Defaults to the
277             same filename and path as C<-destination_file>.
278              
279             =head2 C<-encoding>
280              
281             The encoding of the source file; will also be used for the encoding of the
282             destination file. Defaults to UTF-8.
283              
284             =head2 C<-location>
285              
286             default: C<build>
287              
288             The target location of the generated file. When C<build>, the file is added to
289             the distribution in the normal file gathering phase. When C<root>, the file is
290             instead written to the source repository.
291              
292             =head2 C<-phase>
293              
294             Only relevant when C<-location = root>. When C<build> (the default), the file
295             is written on every build operation. When C<release>, it is only written after
296             the distribution is released.
297              
298             =head1 SEE ALSO
299              
300             =for stopwords templated
301              
302             =over 4
303              
304             =item *
305              
306             L<File::ShareDir>
307              
308             =item *
309              
310             L<Dist::Zilla::Plugin::ShareDir>
311              
312             =item *
313              
314             L<Text::Template>
315              
316             =item *
317              
318             L<[GatherDir::Template]|Dist::Zilla::Plugin::GatherDir::Template> - gather a file from the dist, and then pass it through a template
319              
320             =item *
321              
322             L<[GenerateFile]|Dist::Zilla::Plugin::GenerateFile> - generate a (possibly-templated) file purely based on data in F<dist.ini>
323              
324             =back
325              
326             =head1 SUPPORT
327              
328             Bugs may be submitted through L<the RT bug tracker|https://rt.cpan.org/Public/Dist/Display.html?Name=Dist-Zilla-Plugin-GenerateFile-FromShareDir>
329             (or L<bug-Dist-Zilla-Plugin-GenerateFile-FromShareDir@rt.cpan.org|mailto:bug-Dist-Zilla-Plugin-GenerateFile-FromShareDir@rt.cpan.org>).
330              
331             There is also a mailing list available for users of this distribution, at
332             L<http://dzil.org/#mailing-list>.
333              
334             There is also an irc channel available for users of this distribution, at
335             L<C<#distzilla> on C<irc.perl.org>|irc://irc.perl.org/#distzilla>.
336              
337             I am also usually active on irc, as 'ether' at C<irc.perl.org>.
338              
339             =head1 AUTHOR
340              
341             Karen Etheridge <ether@cpan.org>
342              
343             =head1 CONTRIBUTORS
344              
345             =for stopwords Dave Rolsky Kent Fredric
346              
347             =over 4
348              
349             =item *
350              
351             Dave Rolsky <autarch@urth.org>
352              
353             =item *
354              
355             Kent Fredric <kentfredric@gmail.com>
356              
357             =back
358              
359             =head1 COPYRIGHT AND LICENCE
360              
361             This software is copyright (c) 2013 by Karen Etheridge.
362              
363             This is free software; you can redistribute it and/or modify it under
364             the same terms as the Perl 5 programming language system itself.
365              
366             =cut