| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  |  | 
| 2 |  |  |  |  |  |  | package Module::Which::P5Path; | 
| 3 |  |  |  |  |  |  | $Module::Which::P5Path::VERSION = '0.04'; | 
| 4 | 1 |  |  | 1 |  | 847 | use 5.006; | 
|  | 1 |  |  |  |  | 4 |  | 
|  | 1 |  |  |  |  | 44 |  | 
| 5 | 1 |  |  | 1 |  | 6 | use strict; | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 35 |  | 
| 6 | 1 |  |  | 1 |  | 5 | use warnings; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 73 |  | 
| 7 |  |  |  |  |  |  |  | 
| 8 |  |  |  |  |  |  | require Exporter; | 
| 9 |  |  |  |  |  |  |  | 
| 10 |  |  |  |  |  |  | our @ISA = qw(Exporter); | 
| 11 |  |  |  |  |  |  | our @EXPORT_OK = qw(path_to_p5path path_to_p5 p5path_to_path); | 
| 12 |  |  |  |  |  |  |  | 
| 13 | 1 |  |  | 1 |  | 5 | use Config; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 894 |  | 
| 14 |  |  |  |  |  |  | require File::Spec::Unix; # qw(splitdir catdir); | 
| 15 |  |  |  |  |  |  | require File::Spec; | 
| 16 |  |  |  |  |  |  |  | 
| 17 |  |  |  |  |  |  | # NOTE. To map config vars to their values, like this | 
| 18 |  |  |  |  |  |  | #    ('archlib', 'perlpath') => ( $Config{archlib}, $Config{perlpath} ) | 
| 19 |  |  |  |  |  |  | # we only need the expression "@Config{@_}". | 
| 20 |  |  |  |  |  |  |  | 
| 21 |  |  |  |  |  |  | # my @vars = _purge_vars('a', 'b', 'c') | 
| 22 |  |  |  |  |  |  | # Purges a list of Config variable names by eliminating those with | 
| 23 |  |  |  |  |  |  | # false and duplicate values. The original order is preserved. | 
| 24 |  |  |  |  |  |  | sub _purge_vars { | 
| 25 | 5 |  |  | 5 |  | 7 | my @vars; | 
| 26 |  |  |  |  |  |  | my %h; | 
| 27 | 5 |  |  |  |  | 49 | for my $val (@Config{@_}) { | 
| 28 | 60 |  |  |  |  | 183 | my $var = shift @_; | 
| 29 | 60 | 100 |  |  |  | 318 | next unless $val; # skip undefs and '' | 
| 30 | 40 | 100 |  |  |  | 10908 | unless ($h{$val}++) { # keep only the first occurrence of a value | 
| 31 | 25 |  |  |  |  | 63 | push @vars, $var; | 
| 32 |  |  |  |  |  |  | } | 
| 33 |  |  |  |  |  |  | } | 
| 34 |  |  |  |  |  |  | return @vars | 
| 35 | 5 |  |  |  |  | 83 | } | 
| 36 |  |  |  |  |  |  |  | 
| 37 |  |  |  |  |  |  | sub _is_windows { | 
| 38 | 8 |  |  | 8 |  | 189 | return $^O =~ /^(MSWin32|cygwin)/i; | 
| 39 |  |  |  |  |  |  | } | 
| 40 |  |  |  |  |  |  |  | 
| 41 |  |  |  |  |  |  | sub _is_case_tolerant { | 
| 42 | 0 |  |  | 0 |  | 0 | return $^O =~ /^(MSWin32|cygwin)/i; | 
| 43 |  |  |  |  |  |  | } | 
| 44 |  |  |  |  |  |  | # it would make sense to use File::Spec->case_tolerant | 
| 45 |  |  |  |  |  |  | # which should return 1 for Windows and Cygwin | 
| 46 |  |  |  |  |  |  | # but it does not in Cygwin. | 
| 47 |  |  |  |  |  |  |  | 
| 48 |  |  |  |  |  |  | # tells whether a path lies under a directory path | 
| 49 |  |  |  |  |  |  | # (it just checks to see if ... | 
| 50 |  |  |  |  |  |  | # | 
| 51 |  |  |  |  |  |  | # NOTE. include (?i) in pattern below when case_tolerant | 
| 52 |  |  |  |  |  |  |  | 
| 53 |  |  |  |  |  |  | # turns 'blib\lib' into 'blib[\\/]lib' | 
| 54 |  |  |  |  |  |  | #   and 'a/b\c'    into 'a[\\/]b[\\/]c' | 
| 55 |  |  |  |  |  |  | sub _win_re { | 
| 56 | 0 |  |  | 0 |  | 0 | my $p = shift; | 
| 57 | 0 | 0 |  |  |  | 0 | $p =~ s!([\\/])|(.)! $1?'[\\\\/]':"\Q$2" !ge; | 
|  | 0 |  |  |  |  | 0 |  | 
| 58 | 0 |  |  |  |  | 0 | return $p | 
| 59 |  |  |  |  |  |  | } | 
| 60 |  |  |  |  |  |  | # is(_win_pattern('blib\lib'), 'blib[\\/]lib'); | 
| 61 |  |  |  |  |  |  | # is(_win_pattern('a/b\c'), 'a[\\/]b[\\/]c'); | 
| 62 |  |  |  |  |  |  | # is(_win_pattern('dir/f.pl'), 'dir[\\/]f\.pl'); | 
| 63 |  |  |  |  |  |  |  | 
| 64 |  |  |  |  |  |  | sub _is_under { | 
| 65 | 8 |  |  | 8 |  | 13 | my $path = shift; | 
| 66 | 8 |  |  |  |  | 11 | my $dir = shift; | 
| 67 | 8 | 50 |  |  |  | 18 | return $path =~ /^\Q$dir\E/ unless _is_windows; | 
| 68 |  |  |  |  |  |  | # windows is: case tolerant and accepts '\\' or '/' | 
| 69 | 0 |  |  |  |  | 0 | my $dir_re = _win_re($dir); | 
| 70 | 0 |  |  |  |  | 0 | return $path =~ /(?i)^$dir_re/ | 
| 71 |  |  |  |  |  |  | } | 
| 72 |  |  |  |  |  |  |  | 
| 73 |  |  |  |  |  |  | sub _parent { | 
| 74 | 0 |  |  | 0 |  | 0 | my $path = shift; | 
| 75 | 0 |  |  |  |  | 0 | my @path = File::Spec::Unix->splitdir($path); | 
| 76 | 0 |  |  |  |  | 0 | pop @path; | 
| 77 | 0 |  |  |  |  | 0 | return File::Spec::Unix->catdir(@path) | 
| 78 |  |  |  |  |  |  | } | 
| 79 |  |  |  |  |  |  |  | 
| 80 |  |  |  |  |  |  | # this computes a relative path from an absolute WHEN | 
| 81 |  |  |  |  |  |  | # we know that the base is a descendant of the path | 
| 82 |  |  |  |  |  |  | # (so we don't need to handle '.', '..' and the like) | 
| 83 |  |  |  |  |  |  | # like File::Spec->abs2rel() is able to do | 
| 84 |  |  |  |  |  |  | sub _abs2rel { | 
| 85 | 3 |  |  | 3 |  | 6 | my $path = shift; | 
| 86 | 3 |  |  |  |  | 6 | my $base = shift; | 
| 87 | 3 |  |  |  |  | 30 | my @path = File::Spec::Unix->splitdir($path); | 
| 88 | 3 |  |  |  |  | 14 | my $base_nodes = File::Spec::Unix->splitdir($base); | 
| 89 | 3 |  |  |  |  | 10 | splice @path, 0, $base_nodes; | 
| 90 | 3 |  |  |  |  | 25 | return File::Spec::Unix->catdir(@path); | 
| 91 |  |  |  |  |  |  | } | 
| 92 |  |  |  |  |  |  |  | 
| 93 |  |  |  |  |  |  | # my ($p5path, $p5base) = _resolve_path($path, @ivars); | 
| 94 |  |  |  |  |  |  | # my $p5path = _resolve_path($path, @ivars); | 
| 95 |  |  |  |  |  |  | sub _resolve_path { | 
| 96 | 5 |  |  | 5 |  | 9 | my $path = shift; | 
| 97 | 5 | 100 |  |  |  | 12 | unless ($path) { | 
| 98 | 1 | 50 |  |  |  | 4 | return ($path, '') if wantarray; | 
| 99 | 1 |  |  |  |  | 5 | return $path | 
| 100 |  |  |  |  |  |  | } | 
| 101 |  |  |  |  |  |  |  | 
| 102 | 4 |  |  |  |  | 13 | my @vars = @_; | 
| 103 | 4 |  |  |  |  | 11 | for (@vars) { | 
| 104 | 8 |  |  |  |  | 53 | my $p5p = $Config{$_}; | 
| 105 | 8 | 100 |  |  |  | 28 | if (_is_under($path, $p5p)) { | 
| 106 | 3 |  |  |  |  | 9 | my $p5base = '${' . $_ . '}/'; | 
| 107 |  |  |  |  |  |  | #my $p5path = $p5base . File::Spec::Unix->abs2rel($path, $Config{$_}); | 
| 108 | 3 |  |  |  |  | 9 | my $p5path = $p5base . _abs2rel($path, $p5p); | 
| 109 | 3 | 100 |  |  |  | 12 | return ($p5path, $p5base) if wantarray; | 
| 110 | 2 |  |  |  |  | 38 | return $p5path | 
| 111 |  |  |  |  |  |  | } | 
| 112 |  |  |  |  |  |  | } | 
| 113 | 1 | 50 |  |  |  | 4 | return ($path, _parent($path)) if wantarray; # !FIXME: I don't like this! | 
| 114 | 1 |  |  |  |  | 10 | return $path # no resolution against given vars | 
| 115 |  |  |  |  |  |  | } | 
| 116 |  |  |  |  |  |  |  | 
| 117 |  |  |  |  |  |  | our @DEFAULT_IVARS = qw( | 
| 118 |  |  |  |  |  |  | installarchlib archlib installprivlib privlib | 
| 119 |  |  |  |  |  |  | installsitearch installsitelib sitelib sitelib_stem | 
| 120 |  |  |  |  |  |  | installvendorarch installvendorlib vendorlib vendorlib_stem | 
| 121 |  |  |  |  |  |  | ); | 
| 122 |  |  |  |  |  |  |  | 
| 123 |  |  |  |  |  |  | # ($p5path, $p5base) = path_to_p5($path) | 
| 124 |  |  |  |  |  |  | # $p5path = path_to_p5($path, include => \@IVARS) | 
| 125 |  |  |  |  |  |  | sub path_to_p5 { | 
| 126 | 5 |  |  | 5 | 1 | 1170 | my $path = shift; | 
| 127 | 5 |  |  |  |  | 14 | my %options = @_; | 
| 128 | 5 |  | 50 |  |  | 378 | my $ivars = $options{install_vars} || \@DEFAULT_IVARS; | 
| 129 | 5 |  |  |  |  | 14 | my @ivars = _purge_vars(@$ivars); | 
| 130 | 5 |  |  |  |  | 17 | return _resolve_path($path, @ivars); | 
| 131 |  |  |  |  |  |  | } | 
| 132 |  |  |  |  |  |  |  | 
| 133 |  |  |  |  |  |  | # $p5path = path_to_p5path($path); | 
| 134 |  |  |  |  |  |  | # $p5path = path_to_p5path($path, include => \@IVARS); | 
| 135 |  |  |  |  |  |  | sub path_to_p5path { | 
| 136 | 3 |  |  | 3 | 1 | 4179 | return scalar path_to_p5(@_); | 
| 137 |  |  |  |  |  |  | } | 
| 138 |  |  |  |  |  |  |  | 
| 139 |  |  |  |  |  |  | sub p5path_to_path { | 
| 140 | 3 |  |  | 3 | 1 | 6 | my $path = shift; | 
| 141 | 3 |  |  |  |  | 17 | $path =~ s/^\$\{(\w+)\}/$Config{$1}/; | 
| 142 | 3 |  |  |  |  | 18 | return $path | 
| 143 |  |  |  |  |  |  |  | 
| 144 |  |  |  |  |  |  | } | 
| 145 |  |  |  |  |  |  |  | 
| 146 |  |  |  |  |  |  | 1; | 
| 147 |  |  |  |  |  |  |  | 
| 148 |  |  |  |  |  |  | __END__ |