File Coverage

blib/lib/File/ShareDir/Install.pm
Criterion Covered Total %
statement 91 98 92.8
branch 40 54 74.0
condition 20 33 60.6
subroutine 17 17 100.0
pod 3 3 100.0
total 171 205 83.4


line stmt bran cond sub pod time code
1             package File::ShareDir::Install; # git description: v0.11-16-gbf1b753
2             # ABSTRACT: Install shared files
3              
4 3     3   527859 use 5.008;
  3         41  
5 3     3   15 use strict;
  3         6  
  3         57  
6 3     3   13 use warnings;
  3         4  
  3         103  
7              
8 3     3   18 use Carp ();
  3         5  
  3         68  
9              
10 3     3   18 use File::Spec;
  3         6  
  3         65  
11 3     3   1259 use IO::Dir;
  3         58518  
  3         4665  
12              
13             our $VERSION = '0.12';
14              
15             our @DIRS;
16             our %ALREADY;
17              
18             require Exporter;
19              
20             our @ISA = qw( Exporter );
21             our @EXPORT = qw( install_share delete_share );
22             our @EXPORT_OK = qw( postamble install_share delete_share );
23             our $INCLUDE_DOTFILES = 0;
24             our $INCLUDE_DOTDIRS = 0;
25              
26             #####################################################################
27             sub install_share
28             {
29 6 50   6 1 3391 my $dir = @_ ? pop : 'share';
30 6 100       18 my $type = @_ ? shift : 'dist';
31 6 50 33     55 unless ( defined $type and
32             ( $type =~ /^(module|dist)$/ ) ) {
33 0         0 Carp::confess "Illegal or invalid share dir type '$type'";
34             }
35              
36 6 50 66     28 if( $type eq 'dist' and @_ ) {
37 0         0 Carp::confess "Too many parameters to install_share";
38             }
39              
40 6         18 my $def = _mk_def( $type );
41 6         24 _add_module( $def, $_[0] );
42              
43 6         16 _add_dir( $def, $dir );
44             }
45              
46              
47             #####################################################################
48             sub delete_share
49             {
50 2 50   2 1 12 my $dir = @_ ? pop : '';
51 2 50       5 my $type = @_ ? shift : 'dist';
52 2 50 33     13 unless ( defined $type and
53             ( $type =~ /^(module|dist)$/ ) ) {
54 0         0 Carp::confess "Illegal or invalid share dir type '$type'";
55             }
56              
57 2 50 66     9 if( $type eq 'dist' and @_ ) {
58 0         0 Carp::confess "Too many parameters to delete_share";
59             }
60              
61 2         6 my $def = _mk_def( "delete-$type" );
62 2         6 _add_module( $def, $_[0] );
63 2         5 _add_dir( $def, $dir );
64             }
65              
66              
67              
68             #
69             # Build a task definition
70             sub _mk_def
71             {
72 8     8   19 my( $type ) = @_;
73 8         26 return { type=>$type,
74             dotfiles => $INCLUDE_DOTFILES,
75             dotdirs => $INCLUDE_DOTDIRS
76             };
77             }
78              
79             #
80             # Add the module to a task definition
81             sub _add_module
82             {
83 8     8   21 my( $def, $class ) = @_;
84 8 100       69 if( $def->{type} =~ /module$/ ) {
85 4         18 my $module = _CLASS( $class );
86 4 50       13 unless ( defined $module ) {
87 0         0 Carp::confess "Missing or invalid module name '$_[0]'";
88             }
89 4         10 $def->{module} = $module;
90             }
91             }
92              
93             #
94             # Add directories to a task definition
95             # Save the definition
96             sub _add_dir
97             {
98 8     8   18 my( $def, $dir ) = @_;
99              
100 8 100       22 $dir = [ $dir ] unless ref $dir;
101              
102 8         15 my $del = 0;
103 8 100       25 $del = 1 if $def->{type} =~ /^delete-/;
104              
105 8         17 foreach my $d ( @$dir ) {
106 9 50 33     128 unless ( $del or (defined $d and -d $d) ) {
      66        
107 0         0 Carp::confess "Illegal or missing directory '$d'";
108             }
109 9 50 66     45 if( not $del and $ALREADY{ $d }++ ) {
110 0         0 Carp::confess "Directory '$d' is already being installed";
111             }
112 9         38 push @DIRS, { %$def };
113 9         42 $DIRS[-1]{dir} = $d;
114             }
115             }
116              
117              
118             #####################################################################
119             # Build the postamble section
120             sub postamble
121             {
122 3     3 1 362658 my $self = shift;
123              
124 3         25 my @ret; # = $self->SUPER::postamble( @_ );
125 3         39 foreach my $def ( @DIRS ) {
126 9         55 push @ret, __postamble_share_dir( $self, $def );
127             }
128 3         42 return join "\n", @ret;
129             }
130              
131             #####################################################################
132             sub __postamble_share_dir
133             {
134 9     9   42 my( $self, $def ) = @_;
135              
136 9         75 my $dir = $def->{dir};
137              
138 9         31 my( $idir );
139              
140 9 100       128 if( $def->{type} eq 'delete-dist' ) {
    100          
    100          
141 1         6 $idir = File::Spec->catdir( _dist_dir(), $dir );
142             }
143             elsif( $def->{type} eq 'delete-module' ) {
144 2         10 $idir = File::Spec->catdir( _module_dir( $def ), $dir );
145             }
146             elsif ( $def->{type} eq 'dist' ) {
147 3         33 $idir = _dist_dir();
148             }
149             else { # delete-share and share
150 3         20 $idir = _module_dir( $def );
151             }
152              
153 9         27 my @cmds;
154 9 100       69 if( $def->{type} =~ /^delete-/ ) {
155 3         12 @cmds = "\$(RM_RF) $idir";
156             }
157             else {
158 6         45 my $autodir = '$(INST_LIB)';
159 6         85 my $pm_to_blib = $self->oneliner(<
160             pm_to_blib({\@ARGV}, '$autodir')
161             CODE
162              
163 6         322 my $files = {};
164 6         56 _scan_share_dir( $files, $idir, $dir, $def );
165             @cmds = $self->split_command( $pm_to_blib,
166 6         478 map { ($self->quote_literal($_) => $self->quote_literal($files->{$_})) } sort keys %$files );
  20         461  
167             }
168              
169 9         670 my $r = join '', map { "\t\$(NOECHO) $_\n" } @cmds;
  9         46  
170              
171             # use Data::Dumper;
172             # die Dumper $files;
173             # Set up the install
174 9         61 return "config::\n$r";
175             }
176              
177             # Get the per-dist install directory.
178             # We depend on the Makefile for most of the info
179             sub _dist_dir
180             {
181 4     4   72 return File::Spec->catdir( '$(INST_LIB)',
182             qw( auto share dist ),
183             '$(DISTNAME)'
184             );
185             }
186              
187             # Get the per-module install directory
188             # We depend on the Makefile for most of the info
189             sub _module_dir
190             {
191 5     5   18 my( $def ) = @_;
192 5         33 my $module = $def->{module};
193 5         48 $module =~ s/::/-/g;
194 5         68 return File::Spec->catdir( '$(INST_LIB)',
195             qw( auto share module ),
196             $module
197             );
198             }
199              
200             sub _scan_share_dir
201             {
202 10     10   49 my( $files, $idir, $dir, $def ) = @_;
203 10 50       133 my $dh = IO::Dir->new( $dir ) or die "Unable to read $dir: $!";
204 10         1326 my $entry;
205 10         57 while( defined( $entry = $dh->read ) ) {
206 54 50       1302 next if $entry =~ /(~|,v|#)$/;
207 54         523 my $full = File::Spec->catfile( $dir, $entry );
208 54 100       1059 if( -f $full ) {
    50          
209 25 100 100     243 next if not $def->{dotfiles} and $entry =~ /^\./;
210 20         231 $files->{ $full } = File::Spec->catfile( $idir, $entry );
211             }
212             elsif( -d $full ) {
213 29 100       113 if( $def->{dotdirs} ) {
214 8 100 100     58 next if $entry eq '.' or $entry eq '..' or
      66        
215             $entry =~ /^\.(svn|git|cvs)$/;
216             }
217             else {
218 21 100       192 next if $entry =~ /^\./;
219             }
220 4         69 _scan_share_dir( $files, File::Spec->catdir( $idir, $entry ), $full, $def );
221             }
222             }
223             }
224              
225              
226             #####################################################################
227             # Cloned from Params::Util::_CLASS
228             sub _CLASS ($) {
229             (
230 4 50 33 4   43 defined $_[0]
231             and
232             ! ref $_[0]
233             and
234             $_[0] =~ m/^[^\W\d]\w*(?:::\w+)*$/s
235             ) ? $_[0] : undef;
236             }
237              
238             1;
239              
240             __END__