File Coverage

blib/lib/Remote/Use.pm
Criterion Covered Total %
statement 18 115 15.6
branch 0 48 0.0
condition 0 35 0.0
subroutine 6 11 54.5
pod 0 4 0.0
total 24 213 11.2


line stmt bran cond sub pod time code
1             package Remote::Use;
2 1     1   31070 use strict;
  1         2  
  1         44  
3 1     1   6 use warnings;
  1         2  
  1         31  
4              
5 1     1   5 use File::Path;
  1         6  
  1         82  
6 1     1   5 use File::Spec;
  1         2  
  1         20  
7 1     1   6 use File::Basename;
  1         2  
  1         130  
8              
9 1     1   5 use Scalar::Util qw{reftype};
  1         1  
  1         3181  
10              
11             our $VERSION = '0.04';
12              
13             # Receives s.t. like 'Remote/Use.pm' and returns 'Remote::Use'
14             sub filename2modname {
15 0     0 0   my $config = shift;
16              
17 0           my $confid = $config;
18 0           $confid =~ s{/}{::}g;
19 0           $confid =~ s{\.pm$}{};
20 0           return $confid;
21             }
22              
23             # Evaluates the ppmdf file as perl code.
24             # The resulting hash is set as the attribute 'cache'
25             # of the Remote::Use object
26             sub setinstallation {
27 0     0 0   my $self = shift;
28            
29 0           $self->{cache} = {};
30 0 0         if (-e $self->{ppmdf}) {
31 0 0         if (open(my $f, $self->{ppmdf})) {
32 0           local $/ = undef;
33 0           my $s = <$f>;
34 0           my @s = eval $s;
35 0 0         die "Error evaluating cache file: $@" if $@;
36 0           $self->{cache} = { @s };
37             }
38             }
39             }
40              
41             sub import {
42 0     0     my $module = shift;
43 0           my %arg = @_;
44              
45 0           my $config = $arg{config};
46              
47             # Set the code handler in @INC so that we can later manage "use Module"
48             # via Remote::Use::INC
49              
50 0           my $self = $module->new();
51 0           push @INC, $self;
52              
53             # If the 'config' option is used we take the
54             # arguments from the configuration package
55 0 0 0       if (defined($config) && -r $config) {
56 0           eval {
57 0           require $config;
58             };
59 0 0         die "Error in $config: $@" if $@;
60              
61 0           my $confid = $arg{package};
62            
63 0 0         $confid = filename2modname($config) unless defined($confid);
64              
65             # The $confid package must have defined
66             # the 'getarg' method
67            
68 0           $self->{confid} = $confid;
69 0           %arg = $confid->getarg($self);
70             }
71              
72             # host is the machine where to look for
73 0           my $host = $arg{host};
74 0 0         die "Provide a host" unless defined $host;
75 0           delete $arg{host};
76 0           $self->{host} = $host;
77              
78             # The 'prefix' attribute is the path where files and libraries
79             # will be installed. If not provided it will be set to s.t. like
80             # /home/myname/perl5lib
81              
82 0 0         my $perl5lib = "$ENV{HOME}/perl5lib" if $ENV{HOME};
83 0 0 0       $perl5lib = "$ENV{USERPROFILE}/perl5lib" if !$perl5lib && $ENV{USERPROFILE};
84              
85 0   0       my $prefix = $self->{prefix} = ($arg{prefix} || $perl5lib || File::Spec->tmpdir);
86 0 0         die "Provide a prefix directory" unless defined $prefix;
87 0           delete $arg{prefix};
88              
89             # Create the directory if it does not exists
90 0 0         mkpath($prefix) unless -d $prefix;
91 0           unshift @INC, "$prefix/files";
92              
93 0           my $ppmdf = $arg{ppmdf};
94 0 0         die "Provide a .installed.modules filename (ppmdf argument)" unless defined $ppmdf;
95 0           delete $arg{ppmdf};
96 0           $self->{ppmdf} = $ppmdf;
97              
98             # Opens and evaluates the ppmdf file. It sets the attribute 'cache'
99 0           $self->setinstallation;
100              
101             # What application shall we use: rsync? wget? ...
102 0           my $command = $arg{command};
103 0 0         die "Provide a command" unless defined $command;
104 0           $self->{command} = $command;
105 0           delete $arg{command};
106              
107 0           $self->{$_} = $arg{$_} for keys(%arg);
108             }
109              
110             sub Remote::Use::INC {
111 0     0 0   my ($self, $filename) = @_;
112              
113 0 0         if ($filename =~ m{^[\w/\\]+\.pm$}) {
114 0           my $prefix = $self->{prefix}; # prefix path where the file will be stored ('/tmp/perl5lib')
115 0           my $host = $self->{host}; # the 'host part' defining where the server is ('orion:')
116              
117 0           my $command = $self->{command}; # rsync, scp, wget, etc. Options included
118              
119             # options required by $command that go after the $host$sourcefile part
120 0   0       my $commandoptions = $self->{commandoptions} || '';
121              
122             # an entry for some $filename is like:
123             # 'IO/Tty.pm' => { dir => '/usr/local/lib/perl/5.8.8', files => [
124             # '/usr/local/lib/perl/5.8.8/auto/IO/Tty/Tty.so',
125             # '/usr/local/lib/perl/5.8.8/auto/IO/Tty/Tty.bs',
126             # '/usr/local/lib/perl/5.8.8/IO/Tty.pm' ] },
127 0           my %files;
128 0           my $entry = $self->{cache}{$filename};
129 0 0 0       %files = %{$entry} if $entry && (reftype($entry) eq 'HASH');
  0            
130              
131             # No files, nothing to download
132 0 0         return unless %files;
133              
134 0           my $remoteprefix = quotemeta($files{dir});
135 0           delete $files{dir};
136              
137 0           my $f = $files{files};
138 0           delete $files{files};
139              
140 0           my $conf = $self->{confid}; # configuration package name
141              
142 0           my @files;
143 0 0 0       @files= @$f if $f && (reftype($f) eq 'ARRAY');
144 0           for (@files) {
145 0           my $url = "$host$_"; # s.t. like 'orion:/usr/local/lib/perl/5.8.8/auto/IO/Tty/Tty.so'
146 0           my $file = $_; # s.t. like '/usr/local/lib/perl/5.8.8/auto/IO/Tty/Tty.so'
147 0           $file =~ s{^$remoteprefix}{$prefix/files/}; # s.t. like '/tmp/perl5lib/files/auto/IO/Tty/Tty.so'
148              
149             # If the configuration package defines a 'prefiles' method, use it to obtain
150             # the final name of the file:
151 0 0 0       $file = $conf->prefiles($url, $file, $self) if $conf && ($conf->can('prefiles'));
152              
153 0           my $path = dirname($file); # s.t. like ''/tmp/perl5lib/files/auto/IO/Tty/'
154 0 0         mkpath($path) unless -d $path;
155              
156             # grab the $url and store it in $file
157 0           system("$command $url $commandoptions $file");
158              
159             # If the configuration package defines a 'postfiles' method, use it
160             # to do any required modifications to the file (changing its mod access for example)
161 0 0 0       $conf->postfiles($file, $self) if ($conf && $conf->can('postfiles'));
162             }
163              
164             # Find if there are alternative families of files (bin, man, etc.)
165 0           my @families = keys %files;
166 0           for (@families) {
167 0           my $f = $files{$_}; # [ '/usr/local/bin/eyapp', '/usr/local/bin/treereg' ]
168 0           my @files; # ( '/usr/local/bin/eyapp', '/usr/local/bin/treereg' )
169 0 0 0       @files = @$f if $f && (reftype($f) eq 'ARRAY');
170              
171 0           for my $b (@files) {
172 0           my $url = "$host$b"; # 'orion:/usr/local/bin/eyapp'
173 0           my $file = $b; # name in the client:
174 0           $file =~ s{^.*/}{$prefix/$_/}; # /tmp/perl5lib/bin/eyapp
175              
176 0           my $pre = "pre$_";
177 0 0 0       $file = $conf->$pre($url, $file, $self) if ($conf && $conf->can($pre));
178              
179 0           my $path = dirname($file);
180 0 0         mkpath($path) unless -d $path;
181              
182 0           system("$command $url $commandoptions $file");
183              
184 0           my $post = "post$_";
185 0 0 0       $conf->$post($file, $self) if ($conf && $conf->can($post));
186             }
187             }
188              
189 0           open my $fh, '<', "$prefix/files/$filename";
190 0           return $fh;
191             }
192              
193 0           return undef;
194             }
195              
196             sub new {
197 0     0 0   my $this = shift;
198 0   0       my $class = ref($this) || $this;
199              
200 0           return bless { @_ }, $class;
201             }
202              
203             1;
204             __END__