File Coverage

blib/lib/Dist/Zilla/Plugin/RPM.pm
Criterion Covered Total %
statement 40 87 45.9
branch 0 16 0.0
condition 2 6 33.3
subroutine 12 17 70.5
pod 0 3 0.0
total 54 129 41.8


line stmt bran cond sub pod time code
1             package Dist::Zilla::Plugin::RPM;
2             # ABSTRACT: Build an RPM from your Dist::Zilla release
3              
4 1     1   2688940 use Moose;
  1         3  
  1         7  
5 1     1   6678 use Moose::Autobox;
  1         168806  
  1         6  
6 1     1   642 use Moose::Util::TypeConstraints;
  1         2  
  1         10  
7 1     1   2207 use Path::Tiny;
  1         2  
  1         60  
8 1     1   6 use namespace::autoclean;
  1         2  
  1         9  
9              
10             our $VERSION = '0.015'; # VERSION
11              
12             with 'Dist::Zilla::Role::Releaser',
13             'Dist::Zilla::Role::FilePruner';
14              
15             has spec_file => (
16             is => 'ro',
17             isa => 'Str',
18             default => 'build/dist.spec',
19             );
20              
21             has build => (
22             is => 'ro',
23             isa => enum([qw/source all/]),
24             default => 'all',
25             );
26              
27             has sign => (
28             is => 'ro',
29             isa => 'Bool',
30             default => 0,
31             );
32              
33             has ignore_build_deps => (
34             is => 'ro',
35             isa => 'Bool',
36             default => 0,
37             );
38              
39             has push_packages => ( is => 'ro', isa => 'Bool', default => 0 );
40             has push_command => ( is => 'ro', isa => 'Str', default => 'rhnpush -s' );
41              
42 1         2 use constant _CoercedRegexp => do {
43 1         6 my $tc = subtype as 'RegexpRef';
44 1         1490 coerce $tc, from 'Str', via { qr/$_/ };
  1         85  
45 1         822 $tc;
46 1     1   236 };
  1         3  
47              
48             has push_ignore_packages => (
49             is => 'ro', isa => _CoercedRegexp, coerce => 1, default => '.src.rpm$' );
50              
51 1     1   7 use Carp;
  1         2  
  1         58  
52 1     1   6 use File::Temp ();
  1         2  
  1         16  
53 1     1   541 use Path::Class qw(dir);
  1         12137  
  1         51  
54 1     1   9 use Text::Template ();
  1         2  
  1         15  
55 1     1   719 use IPC::Run;
  1         21652  
  1         1132  
56              
57             sub prune_files {
58 0     0 0 0 my($self) = @_;
59 0         0 my $spec = $self->spec_file;
60 0         0 for my $file ($self->zilla->files->flatten) {
61 0 0       0 if ($file->name eq $self->spec_file) {
62 0         0 $self->zilla->prune_file($file);
63             }
64             }
65 0         0 return;
66             }
67              
68             has '_rpmbuild_options' => (
69             is => 'ro', isa => 'ArrayRef[Str]', lazy => 1,
70             default => sub {
71             my $self = shift;
72             return( [
73             $self->sign ? '--sign' : (),
74             $self->ignore_build_deps ? '--nodeps' : (),
75             ] );
76             },
77             );
78              
79             has '_rpmbuild_stage' => (
80             is => 'ro', isa => 'Str', lazy => 1,
81             default => sub {
82             my $self = shift;
83              
84             if ($self->build eq 'source') {
85             return('-bs');
86             } elsif ($self->build eq 'all') {
87             return('-ba');
88             }
89              
90             $self->log_fatal(q{invalid build type }.$self->build);
91             },
92             );
93              
94             has '_rpmbuild_command' => (
95             is => 'ro',
96             isa => 'ArrayRef[Str]',
97             lazy => 1,
98             default => sub {
99             my $self = shift;
100             return( [
101             'rpmbuild',
102             $self->_rpmbuild_stage,
103             @{$self->_rpmbuild_options},
104             $self->_tmpspecfile->stringify,
105             ] );
106             },
107             );
108              
109             has '_tmpdir' => (
110             is => 'ro', isa => 'File::Temp::Dir', lazy => 1,
111             default => sub {
112             my $self = shift;
113             return File::Temp->newdir();
114             },
115             );
116              
117             has '_tmpspecfile' => (
118             is => 'ro', isa => 'Path::Class::File', lazy => 1,
119             default => sub {
120             my $self = shift;
121             return dir($self->_tmpdir)->file($self->zilla->name . '.spec');
122             },
123             );
124              
125             sub _write_spec {
126 0     0   0 my ($self, $archive) = @_;
127 0         0 my $fh = $self->_tmpspecfile->openw();
128 0         0 $fh->print($self->mk_spec($archive));
129 0         0 $fh->flush;
130 0         0 $fh->close;
131 0         0 return;
132             }
133              
134             has '_sourcedir' => (
135             is => 'ro', isa => 'Str', lazy => 1,
136             default => sub {
137             my $self = shift;
138             my $sourcedir = qx/rpm --eval '%{_sourcedir}'/
139             or $self->log_fatal(q{couldn't determine RPM sourcedir});
140             $sourcedir =~ s/[\r\n]+$//;
141             $sourcedir .= '/';
142              
143             unless( -d $sourcedir) {
144             $sourcedir = "$self->_tmpdir";
145             }
146              
147             return($sourcedir);
148             },
149             );
150              
151             sub release {
152 0     0 0 0 my($self,$archive) = @_;
153              
154 0         0 $self->_write_spec($archive);
155              
156 0 0       0 if(! -f $archive ) {
157 0         0 $self->log_fatal('archive '.$archive.' does not exist!');
158             }
159              
160 0 0       0 system('cp',$archive,$self->_sourcedir)
161             && $self->log_fatal('cp failed');
162              
163 0 0       0 if ($ENV{DZIL_PLUGIN_RPM_TEST}) {
164 0         0 $self->log("test: would have executed ".join(' ', @{$self->_rpmbuild_command}));
  0         0  
165 0         0 return;
166             }
167              
168 0         0 $self->_execute_rpmbuild;
169 0         0 $self->log('RPMs build: '.join(', ', @{$self->_packages_build} ));
  0         0  
170              
171 0 0       0 if( $self->push_packages ) {
172 0         0 $self->_execute_push_command;
173             }
174              
175 0         0 return;
176             }
177              
178             has '_packages_build' => ( is => 'ro', isa => 'ArrayRef[Str]', lazy => 1,
179             default => sub { [] }
180             );
181              
182             sub _execute_rpmbuild {
183 0     0   0 my $self = shift;
184 0         0 my ($in, $out, $err);
185 0         0 my $lang = $ENV{'LANG'};
186 0         0 $ENV{'LANG'} = 'C';
187 0         0 $self->log('building RPM...');
188 0 0       0 IPC::Run::run( $self->_rpmbuild_command, \$in, \$out, \$err )
189             or $self->log_fatal('rpmbuild failed: '.$err);
190 0         0 foreach my $line ( split(/\n/, $out ) ) {
191 0 0       0 if( $line =~ m/^Wrote: (.*)$/) {
192 0         0 push(@{$self->_packages_build}, $1);
  0         0  
193             }
194             }
195 0         0 $ENV{'LANG'} = $lang;
196 0         0 return;
197             }
198              
199             has _packages_to_push => (
200             is => 'ro', isa => 'ArrayRef[Str]', lazy => 1,
201             default => sub {
202             my $self = shift;
203             my $regex = $self->push_ignore_packages;
204             return( [ grep { $_ !~ m/$regex/ } @{$self->_packages_build} ] );
205             },
206             );
207              
208             has _push_command => (
209             is => 'ro', isa => 'ArrayRef', lazy => 1,
210             default => sub {
211             my $self = shift;
212             return( [ split(/ /, $self->push_command) ] );
213             },
214             );
215              
216             sub _execute_push_command {
217 0     0   0 my $self = shift;
218 0         0 my ($in, $out, $err);
219              
220 0         0 $in = join("\n", @{$self->_packages_to_push});
  0         0  
221              
222 0         0 $self->log('pushing packages: '.join(', ', @{$self->_packages_to_push}));
  0         0  
223 0 0       0 IPC::Run::run( $self->_push_command, \$in, \$out, $err )
224             or $self->log_fatal('push command failed: '.$err);
225              
226 0         0 return;
227             }
228              
229             sub mk_spec {
230 1     1 0 53151 my($self,$archive) = @_;
231 1   33     27 my $t = Text::Template->new(
232             TYPE => 'FILE',
233             SOURCE => path($self->zilla->root)->child($self->spec_file),
234             DELIMITERS => [ '<%', '%>' ],
235             ) || $self->log_fatal($Text::Template::ERROR);
236 1   33     358 return $t->fill_in(
237             HASH => {
238             zilla => \($self->zilla),
239             archive => \$archive,
240             },
241             ) || $self->log_fatal($Text::Template::ERROR);
242             }
243              
244             __PACKAGE__->meta->make_immutable;
245              
246              
247             1;
248              
249             __END__
250              
251             =pod
252              
253             =encoding UTF-8
254              
255             =head1 NAME
256              
257             Dist::Zilla::Plugin::RPM - Build an RPM from your Dist::Zilla release
258              
259             =head1 VERSION
260              
261             version 0.015
262              
263             =head1 SYNOPSIS
264              
265             In your dist.ini:
266              
267             [RPM]
268             spec_file = build/dist.spec
269             sign = 1
270             ignore_build_deps = 0
271              
272             push_packages = 0
273             push_command = rhnpush -s
274             push_ignore_packages = .src.rpm$
275              
276             After adding the [RPM] section to the dist.ini file, the mkrpmspec command will be available. Running this command allow you to make the dzil.spec file from the template. Then dzil release will build the RPM file.
277              
278             It keeps track of build RPM files and can be used to push generated
279             packages into a repository.
280              
281             =head1 DESCRIPTION
282              
283             This plugin is a Releaser for Dist::Zilla that builds an RPM of your
284             distribution.
285              
286             =head1 ATTRIBUTES
287              
288             =over
289              
290             =item spec_file (default: "build/dist.spec")
291              
292             The spec file to use to build the RPM.
293              
294             The spec file is run through L<Text::Template|Text::Template> before calling
295             rpmbuild, so you can substitute values from Dist::Zilla into the final output.
296             The template uses <% %> tags (like L<Mason|Mason>) as delimiters to avoid
297             conflict with standard spec file markup.
298              
299             Two variables are available in the template:
300              
301             =over
302              
303             =item $zilla
304              
305             The main Dist::Zilla object
306              
307             =item $archive
308              
309             The filename of the release tarball
310              
311             =back
312              
313             =item sign (default: False)
314              
315             If set to a true value, rpmbuild will be called with the --sign option.
316              
317             =back
318              
319             =over
320              
321             =item ignore_build_deps (default: False)
322              
323             If set to a true value, rpmbuild will be called with the --nodeps option.
324              
325             =item push_packages (default: false)
326              
327             This allowes you to specify a command to push your generated RPM packages to a
328             repository. RPM filenames are writen one-per-line to stdin. If push_packages
329             is set to 1, it will execute the push_command on the generated RPMs. By default
330             the source packages will be excluded.
331              
332             =item push_command (default: rhnpush -s)
333              
334             Command used to push packages.
335              
336             =item push_ignore_packages (default: .src.rpm$)
337              
338             A regular expression for packages which should NOT be pushed.
339              
340             =back
341              
342             =head1 SAMPLE SPEC FILE TEMPLATE
343              
344             Name: <% $zilla->name %>
345             Version: <% (my $v = $zilla->version) =~ s/^v//; $v %>
346             Release: 1
347              
348             Summary: <% $zilla->abstract %>
349             License: GPL+ or Artistic
350             Group: Applications/CPAN
351             BuildArch: noarch
352             URL: <% $zilla->license->url %>
353             Source: <% $archive %>
354            
355             BuildRoot: %{_tmppath}/%{name}-%{version}-BUILD
356            
357             %description
358             <% $zilla->abstract %>
359            
360             %prep
361             %setup -q
362            
363             %build
364             perl Makefile.PL
365             make test
366            
367             %install
368             if [ "%{buildroot}" != "/" ] ; then
369             rm -rf %{buildroot}
370             fi
371             make install DESTDIR=%{buildroot}
372             find %{buildroot} | sed -e 's#%{buildroot}##' > %{_tmppath}/filelist
373            
374             %clean
375             if [ "%{buildroot}" != "/" ] ; then
376             rm -rf %{buildroot}
377             fi
378            
379             %files -f %{_tmppath}/filelist
380             %defattr(-,root,root)
381              
382             =head1 SEE ALSO
383              
384             L<Dist::Zilla|Dist::Zilla>
385              
386             =head1 AUTHOR
387              
388             Vincent Lequertier <vi.le@autistici.org>
389              
390             =head1 COPYRIGHT AND LICENSE
391              
392             This software is copyright (c) 2017 by vincent Lequertier, Stephen Clouse.
393              
394             This is free software; you can redistribute it and/or modify it under
395             the same terms as the Perl 5 programming language system itself.
396              
397             =cut