File Coverage

blib/lib/File/ConfigDir/Install.pm
Criterion Covered Total %
statement 88 104 84.6
branch 22 56 39.2
condition 5 20 25.0
subroutine 17 19 89.4
pod 4 4 100.0
total 136 203 67.0


line stmt bran cond sub pod time code
1             package File::ConfigDir::Install;
2              
3 2     2   126767 use warnings;
  2         4  
  2         64  
4 2     2   8 use strict;
  2         2  
  2         59  
5 2     2   6 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
  2         6  
  2         136  
6              
7 2     2   9 use Carp qw(confess);
  2         2  
  2         109  
8 2     2   7 use Config;
  2         3  
  2         69  
9 2     2   7 use Cwd;
  2         2  
  2         105  
10 2     2   9 use Exporter ();
  2         2  
  2         37  
11             require File::Basename;
12             require File::Spec;
13 2     2   830 use IO::Dir ();
  2         25898  
  2         2546  
14              
15             =head1 NAME
16              
17             File::ConfigDir::Install - Install (into) configuration directories
18              
19             =cut
20              
21             $VERSION = '0.001';
22             @ISA = qw(Exporter);
23             @EXPORT = qw(install_config);
24             @EXPORT_OK = qw(install_config postamble constants install);
25             %EXPORT_TAGS = (
26             ALL => [@EXPORT_OK],
27             CONFIG => [qw(install_config)],
28             MY => [qw(postamble constants install)],
29             );
30              
31             our @DIRS;
32             our %ALREADY;
33             our $INCLUDE_DOTFILES = 0;
34             our $INCLUDE_DOTDIRS = 0;
35              
36             sub install_config
37             {
38 1 50   1 1 164 my $dir = @_ ? pop : 'etc';
39              
40             # confess "Illegal or invalid config dir type '$type'" unless defined $type and $type =~ /^(system|core|local|...)$/;
41              
42             # if( $type eq 'dist' and @_ ) {
43             # confess "Too many parameters to install_share";
44             # }
45              
46 1         4 my $def = _mk_def();
47 1         3 _add_dir( $def, $dir );
48             }
49              
50             #
51             # Build a task definition
52 1     1   5 sub _mk_def { { dotfiles => $INCLUDE_DOTFILES, dotdirs => $INCLUDE_DOTDIRS } }
53              
54             #
55             #
56             # Add directories to a task definition
57             # Save the definition
58             sub _add_dir
59             {
60 1     1   2 my ( $def, $dir ) = @_;
61              
62 1 50       4 $dir = [$dir] unless ref $dir;
63              
64 1         2 foreach my $d (@$dir)
65             {
66 1 50       3 defined $d or confess "Missing directory";
67 1 50       13 -d $d or confess "Illegal directory specification: '$d'";
68 1 50       5 $ALREADY{$d}++ and confess "Directory '$d' is already being installed";
69 1         9 push @DIRS, {%$def, dir => $d};
70             }
71             }
72              
73             my $Curdir = File::Spec->curdir;
74              
75             sub constants
76             {
77 1     1 1 14606 my $self = shift;
78 1         16 my $m = $self->ExtUtils::MY::constants(@_);
79              
80 1         498 my $installetc = File::Spec->catdir($Config{installprefix}, "etc");
81 1   33     7 $self->{INST_ETC} ||= File::Spec->catdir($Curdir, qw(blib etc));
82 1   33     10 $self->{INSTALLETC} ||= $installetc;
83 1   50     6 $self->{INSTALLSITEETC} ||= '$(INSTALLETC)';
84 1 50 33     11 $self->{INSTALLVENDORETC} ||= $Config{usevendorprefix} ? '$(INSTALLETC)' : '';
85              
86 1         3 my @m = map { "$_ = $self->{$_}" } qw(INST_ETC);
  1         5  
87 1         3 push @m, map { "$_ = $self->{$_}\nDEST$_ = \$(DESTDIR)\$($_)" } qw(INSTALLETC INSTALLSITEETC INSTALLVENDORETC);
  3         41  
88              
89 1         8 join("\n", $m, @m);
90             }
91              
92             sub _unix_install_wrapper
93             {
94 1     1   3 my($self, %attribs) = @_;
95 1         18 my $m = $self->ExtUtils::MY::install(@_);
96              
97 1         154 my ($ppi, $psi, $pvi);
98 1 50       25 $m =~ m/(pure_perl_install :: all.*?^$)/ms and $ppi = $1;
99 1 50       19 $m =~ m/(pure_site_install :: all.*?^$)/ms and $psi = $1;
100 1 50       18 $m =~ m/(pure_vendor_install :: all.*?^$)/ms and $pvi = $1;
101              
102 1         3 $ppi =~ s/"\$\(INST_BIN\)" "\$\(DESTINSTALLBIN\)" \\/"\$\(INST_BIN\)" "\$\(DESTINSTALLBIN\)" \\\n\t\t"\$\(INST_ETC\)" "\$\(DESTINSTALLETC\)" \\/ms;
103 1         2 $psi =~ s/"\$\(INST_BIN\)" "\$\(DESTINSTALLSITEBIN\)" \\/"\$\(INST_BIN\)" "\$\(DESTINSTALLSITEBIN\)" \\\n\t\t"\$\(INST_ETC\)" "\$\(DESTINSTALLSITEETC\)" \\/ms;
104 1         2 $pvi =~ s/"\$\(INST_BIN\)" "\$\(DESTINSTALLVENDORBIN\)" \\/"\$\(INST_BIN\)" "\$\(DESTINSTALLVENDORBIN\)" \\\n\t\t"\$\(INST_ETC\)" "\$\(DESTINSTALLVENDORETC\)" \\/ms;
105              
106 1 50       24 $m =~ s/(pure_perl_install :: all.*?^$)/$ppi/ms and $ppi = $1;
107 1 50       23 $m =~ s/(pure_site_install :: all.*?^$)/$psi/ms and $psi = $1;
108 1 50       18 $m =~ s/(pure_vendor_install :: all.*?^$)/$pvi/ms and $pvi = $1;
109              
110 1         6 $m;
111             }
112              
113             sub _inject_eu_mm_vms_install_wrapper
114             {
115 0     0   0 my($self, %attribs) = @_;
116 0         0 my $m = $self->ExtUtils::MY::install(@_);
117              
118 0         0 my ($ppi, $psi, $pvi);
119 0 0       0 $m =~ m/(pure_perl_install :: all.*?^$)/ms and $ppi = $1;
120 0 0       0 $m =~ m/(pure_site_install :: all.*?^$)/ms and $psi = $1;
121 0 0       0 $m =~ m/(pure_vendor_install :: all.*?^$)/ms and $pvi = $1;
122              
123 0         0 $ppi =~ s/"\$\(INST_BIN\)" "\$\(DESTINSTALLBIN\)" \\/"\$\(INST_BIN\)" "\$\(DESTINSTALLBIN\)" \\\n\t\t"\$\(INST_ETC\)" "\$\(DESTINSTALLETC\)" \\/ms;
124 0         0 $psi =~ s/"\$\(INST_BIN\)" "\$\(DESTINSTALLSITEBIN\)" \\/"\$\(INST_BIN\)" "\$\(DESTINSTALLSITEBIN\)" \\\n\t\t"\$\(INST_ETC\)" "\$\(DESTINSTALLSITEETC\)" \\/ms;
125 0         0 $pvi =~ s/"\$\(INST_BIN\)" "\$\(DESTINSTALLVENDORBIN\)" \\/"\$\(INST_BIN\)" "\$\(DESTINSTALLVENDORBIN\)" \\\n\t\t"\$\(INST_ETC\)" "\$\(DESTINSTALLVENDORETC\)" \\/ms;
126              
127 0 0       0 $m =~ s/(pure_perl_install :: all.*?^$)/$ppi/ms and $ppi = $1;
128 0 0       0 $m =~ s/(pure_site_install :: all.*?^$)/$psi/ms and $psi = $1;
129 0 0       0 $m =~ s/(pure_vendor_install :: all.*?^$)/$pvi/ms and $pvi = $1;
130              
131 0         0 $m;
132             }
133              
134             sub install
135             {
136 1 50   1 1 71067 defined $INC{'ExtUtils/MM_VMS.pm'} and return _vms_install_wrapper(@_);
137 1 50       13 defined $INC{'ExtUtils/MM_Unix.pm'} and _unix_install_wrapper(@_);
138             }
139              
140             #####################################################################
141             # Build the postamble section
142             sub postamble
143             {
144 1     1 1 694 my $self = shift;
145 1         3 join "\n", map { __postamble_etc_dir( $self, $_ ) } @DIRS;
  1         4  
146             }
147              
148             #####################################################################
149             sub __postamble_etc_dir
150             {
151 1     1   3 my ( $self, $def ) = @_;
152              
153 1         4 my $dir = $def->{dir};
154 1         13 my $idir = File::Spec->catdir( '$(INST_ETC)' );
155              
156 1         2 my @cmds;
157 1         4 my $autodir = '$(INST_ETC)';
158 1         10 my $perl_cfg_to_blib = $self->oneliner( <
159             pm_to_blib({\@ARGV}, '$autodir')
160             CODE
161              
162 1         48 my $files = {};
163 1         3 _scan_etc_dir( $files, $idir, $dir, $def );
164 1         53 @cmds = $self->split_command( $perl_cfg_to_blib, %$files );
165              
166 1         41 my $r = join '', map { "\t\$(NOECHO) $_\n" } @cmds;
  1         4  
167              
168 1         7 return "config::\n$r";
169             }
170              
171             # Get the per-dist install directory.
172             # We depend on the Makefile for most of the info
173             sub _dist_dir
174             {
175 0     0   0 return ;
176             }
177              
178             sub _scan_etc_dir
179             {
180 1     1   2 my( $files, $idir, $dir, $def ) = @_;
181 1 50       18 my $dh = IO::Dir->new( $dir ) or die "Unable to read $dir: $!";
182 1         88 my $entry;
183             # XXX use FFR, if available
184 1         4 while( defined( $entry = $dh->read ) ) {
185 3 50       39 next if $entry =~ /(~|,v|#)$/;
186 3         19 my $full = File::Spec->catfile( $dir, $entry );
187 3 100       41 if( -f $full ) {
    50          
188 1 50 33     10 next if not $def->{dotfiles} and $entry =~ /^\./;
189 1         8 $files->{ $full } = File::Spec->catfile( $idir, $entry );
190             }
191             elsif( -d $full ) {
192 2 50       10 if( $def->{dotdirs} ) {
193 0 0 0     0 next if $entry eq '.' or $entry eq '..' or
      0        
194             $entry =~ /^\.(svn|git|cvs)$/;
195             }
196             else {
197 2 50       10 next if $entry =~ /^\./;
198             }
199 0           _scan_etc_dir( $files, File::Spec->catdir( $idir, $entry ), $full );
200             }
201             }
202             }
203              
204             1;
205             =head1 SYNOPSIS
206              
207             use ExtUtils::MakeMaker;
208             use File::ConfigDir::Install;
209              
210             install_config 'etc';
211              
212             WriteMakefile( ... ); # As you normaly would
213              
214             package MY;
215             use File::ConfigDir::Install qw(:MY);
216              
217             =head1 DESCRIPTION
218              
219             File::ConfigDir::Install allows you to install configuration files from a
220             distribution.
221              
222             =head1 EXPORT
223              
224             =head2 :CONFIG
225              
226             This tag contains the functions for configration stage of Makefile.PL
227              
228             =head3 install_config
229              
230             This function allows adding directories to be scanned for (config-)files
231             which will be installed in a later stage.
232              
233             =head2 :MY
234              
235             =head3 postamble
236              
237             Wrapper around ExtUtils::MY::postamble to inject a "config::" target into
238             Makefile
239              
240             =head3 install
241              
242             Wrapper around ExtUtils::MY::install to inject install rules for config
243             files. Injected rules are
244              
245             =over 4
246              
247             =item perl
248              
249             add C<< "$(INST_ETC)" "$(DESTINSTALLETC)" >> to C
250             target,
251              
252             =item site
253              
254             add C<< "$(INST_ETC)" "$(DESTINSTALLSITEETC)" >> to C
255             target,
256              
257             =item vendor
258              
259             and add C<< "$(INST_ETC)" "$(DESTINSTALLVENDORETC)" >> to C
260             target.
261              
262             =back
263              
264             =head3 constants
265              
266             Wrapper around ExtUtils::MY::constants to inject install constants for config
267             files.
268              
269             =head1 AUTHOR
270              
271             Jens Rehsack, C<< >>
272              
273             =head1 LIMITATIONS
274              
275             This early stage version has some limitations
276              
277             =over 4
278              
279             =item *
280              
281             It is not trivially possible to mix this with other MakeMaker extensions
282             overloading C, C or C, respectively.
283              
284             A reasonable solution (I, L ?) is required ...
285              
286             =item *
287              
288             Target directory is limited to static guess from one of
289             L, L or
290             L, respectively.
291              
292             A reasonable way to override might be more packager- and user-friendly.
293              
294             =item *
295              
296             No VMS support
297              
298             Needs to be hacked ...
299              
300             =back
301              
302             =head1 BUGS
303              
304             Please report any bugs or feature requests to
305             C, or through the web interface at
306             L.
307             I will be notified, and then you'll automatically be notified of progress
308             on your bug as I make changes.
309              
310             =head1 SUPPORT
311              
312             You can find documentation for this module with the perldoc command.
313              
314             perldoc File::ConfigDir::Install
315              
316             You can also look for information at:
317              
318             =over 4
319              
320             =item * RT: CPAN's request tracker (report bugs here)
321              
322             L
323              
324             =item * AnnoCPAN: Annotated CPAN documentation
325              
326             L
327              
328             =item * CPAN Ratings
329              
330             L
331              
332             =item * Search CPAN
333              
334             L
335              
336             =back
337              
338             =head1 ACKNOWLEDGEMENTS
339              
340             =head1 LICENSE AND COPYRIGHT
341              
342             Copyright 2014 Jens Rehsack.
343              
344             This program is free software; you can redistribute it and/or modify it
345             under the terms of either: the GNU General Public License as published
346             by the Free Software Foundation; or the Artistic License.
347              
348             See L for more information.
349              
350             =cut