File Coverage

blib/lib/File/ShareDir/Install.pm
Criterion Covered Total %
statement 89 96 92.7
branch 40 54 74.0
condition 20 33 60.6
subroutine 16 16 100.0
pod 3 3 100.0
total 168 202 83.1


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