File Coverage

blib/lib/Config/PFiles/Path.pm
Criterion Covered Total %
statement 88 93 94.6
branch 23 26 88.4
condition 10 13 76.9
subroutine 18 18 100.0
pod 1 1 100.0
total 140 151 92.7


line stmt bran cond sub pod time code
1             package Config::PFiles::Path;
2              
3             # ABSTRACT: manipulate PFILES path for IRAF Compatible parameter files
4              
5 11     11   1032728 use 5.008009;
  11         134  
6              
7 11     11   57 use strict;
  11         21  
  11         237  
8 11     11   50 use warnings;
  11         22  
  11         264  
9              
10 11     11   5551 use Symbol ();
  11         9164  
  11         261  
11 11     11   5484 use Sub::Uplevel ();
  11         13847  
  11         442  
12              
13             our $VERSION = '0.04';
14              
15 11     11   11698 use overload '""' => '_export' ;
  11         10089  
  11         66  
16              
17             my %is_mutator
18             = map { $_ => 1 } qw( _append _prepend _replace _remove );
19              
20             our $AUTOLOAD;
21              
22              
23              
24              
25              
26              
27              
28              
29              
30              
31             sub _croak {
32 2     2   13 require Carp;
33 2         58 goto &Carp::croak;
34             }
35              
36             # allow the user to do thing when loading the package
37             sub import {
38              
39 11     11   79 my $package = shift;
40              
41 11 100       8635 return unless @_;
42              
43 5         10 my $method = shift;
44              
45             _croak( "Can't call method '$method' in this context\n" )
46 5 100       29 unless $is_mutator{ "_$method" };
47              
48 4         8 $AUTOLOAD = $method;
49 4         15 Sub::Uplevel::uplevel( 1, \&AUTOLOAD, $package, @_ );
50             }
51              
52             sub AUTOLOAD {
53 124     124   32237 (my $method = our $AUTOLOAD) =~ s/.*:://;
54              
55             # we don't have a DESTROY method, so ignore it.
56 124 100       7275 return if $method =~ /DESTROY/;
57              
58 81         163 my $imethod = '_' . $method;
59              
60 81         117 my $subref = *{Symbol::qualify_to_ref($imethod,__PACKAGE__)}{CODE};
  81         210  
61              
62             # make sure it's an existing method
63 81 50 33     1857 _croak( qq{Can't locate object method "$method" via package "},
64             __PACKAGE__, q{"} )
65             if $method =~ /^_/ || ! defined $subref;
66              
67              
68             # is this an object invocation?
69 81 100 66     349 if ( ref $_[0] && $_[0]->isa(__PACKAGE__) )
70             {
71 61         223 goto &$imethod;
72             }
73              
74             # nope. create default object based on $ENV{PFILES} and replace
75             # the class name in the argument list with the new object
76 20         39 my $package = shift;
77 20         58 my $env = $package->new( $ENV{PFILES} );
78 20         42 unshift @_, $env;
79              
80              
81             # if the method will alter the path, make sure to update $ENV{PFILES}
82             # after it has been run
83 20 100       52 if ( $is_mutator{$imethod} )
84             {
85             # respect calling context
86 17         29 my $wantarray = wantarray();
87              
88             # void
89 17 100       43 if ( ! defined $wantarray )
    50          
90             {
91 13         56 Sub::Uplevel::uplevel( 1, $subref, @_ );
92 13         36 $ENV{PFILES} = $env->_export;
93 13         99 return;
94             }
95              
96             # list
97             elsif ( $wantarray)
98             {
99 4         15 my @results = Sub::Uplevel::uplevel( 1, $subref, @_ );
100 4         10 $ENV{PFILES} = $env->_export;
101 4         31 return @results;
102             }
103              
104             # scalar
105             else
106             {
107 0         0 my $result = Sub::Uplevel::uplevel( 1, $subref, @_ );
108 0         0 $ENV{PFILES} = $env->_export;
109 0         0 return $result;
110             }
111             }
112              
113             # nope, just execute the method
114             else
115             {
116 3         11 goto &$imethod;
117             }
118             }
119              
120             sub new {
121 43     43 1 833 my ( $class, $pfiles ) = @_;
122              
123 43         100 my $self = bless {}, $class;
124              
125 43         124 $self->__init( $pfiles );
126              
127 42         95 return $self;
128             }
129              
130             sub __init {
131 43     43   96 my ( $self, $pfiles ) = @_;
132              
133 43   100     122 $pfiles ||= q{};
134              
135 43         65 my %dirs;
136 43         244 @dirs{ qw( RW RO ) } =
137             $pfiles =~ /^
138             ([^;]*) # grab everything that's not a semicolon (RW)
139             (?:|;(.*)) # and everything that's after a semicolon (RO)
140             $/x;
141              
142             _croak( "illegal path: too many semi-colons: $pfiles\n" )
143 43 100 100     231 if defined $dirs{RO} && $dirs{RO} =~ /;/;
144              
145             # split and store non-empty paths
146 88         470 $self->{$_} = [ grep { $_ ne '' } split( /:/, $dirs{$_} || q{} ) ]
147 42   100     387 for qw( RW RO );
148              
149 42         105 return;
150             }
151              
152             sub __check_set {
153 69     69   121 my ( $dir_set ) = shift;
154              
155 69         97 my $match;
156 69 50       320 unless ( ($match ) = $dir_set =~ /^(RW|RO)$/i )
157             {
158 0         0 local $Carp::CarpLevel = $Carp::CarpLevel + 1;
159 0         0 _croak( "illegal value for directory set: $dir_set\n" )
160             }
161              
162 69         329 return uc($match);
163             }
164              
165             sub _append {
166 7     7   73 my ( $self, $dir_set, @dirs ) = @_;
167              
168 7         13 push @{$self->{__check_set($dir_set)}}, @dirs;
  7         21  
169              
170 7         21 return;
171             }
172              
173             sub _prepend {
174 8     8   101 my ( $self, $dir_set, @dirs ) = @_;
175              
176 8         12 unshift @{$self->{__check_set($dir_set)}}, @dirs;
  8         21  
177              
178 8         25 return;
179             }
180              
181             sub _extract {
182 32     32   72 my ( $self, $dir_set ) = @_;
183              
184 32         37 return @{$self->{__check_set($dir_set)}};
  32         74  
185             }
186              
187             sub _replace {
188 22     22   134 my ( $self, $dir_set, @dirs ) = @_;
189              
190 22         50 $dir_set = __check_set($dir_set);
191              
192 22         37 my @old = @{$self->{$dir_set}};
  22         76  
193              
194 22         62 $self->{$dir_set} = [ @dirs ];
195              
196             return @old
197 22 100       97 if defined wantarray;
198              
199 14         62 return;
200             }
201              
202             sub _remove {
203 11     11   102 my ( $self, $dir_set ) = @_;
204              
205 11         52 return $self->replace( $dir_set );
206             }
207              
208             sub _export {
209 23     23   81 my ( $self ) = @_;
210              
211             # join together the non-empty directories in the sets;
212             my ( $rw, $ro ) =
213 23         85 map { join( q{:}, grep { $_ ne q{} } @{$self->{$_}} ) }
  46         67  
  46         145  
  46         106  
214             qw( RW RO );
215              
216             # construct a rational path
217             return
218 23 100       151 $rw eq q{} ? ";$ro"
    100          
219             : $ro eq q{} ? $rw
220             : "$rw;$ro";
221             }
222              
223              
224             1;
225              
226             #
227             # This file is part of Config-PFiles-Path
228             #
229             # This software is Copyright (c) 2007 by Smithsonian Astrophysical Observatory.
230             #
231             # This is free software, licensed under:
232             #
233             # The GNU General Public License, Version 3, June 2007
234             #
235              
236             __END__