File Coverage

RelDir.pm
Criterion Covered Total %
statement 58 65 89.2
branch 26 30 86.6
condition 2 2 100.0
subroutine 8 8 100.0
pod 4 4 100.0
total 98 109 89.9


line stmt bran cond sub pod time code
1             #
2             #===============================================================================
3             #
4             # FILE: RelDir.pm
5             #
6             # DESCRIPTION: This module provides a mechanism to determine the relative
7             # path between two directory names.
8             #
9             # FILES: ---
10             # BUGS: ---
11             # NOTES: ---
12             # AUTHOR: (Dave Roberts),
13             # COMPANY:
14             # VERSION: 1.0
15             # CREATED: 15/04/2010 20:30:39 GMT
16             # REVISION: $Revision: 1.0 $
17             #===============================================================================
18              
19 1     1   1989 use strict;
  1         2  
  1         37  
20 1     1   6 use warnings;
  1         2  
  1         45  
21             package File::RelDir;
22 1     1   6 use Carp;
  1         2  
  1         886  
23             require Exporter;
24              
25             our @ISA = qw(Exporter);
26             our %EXPORT_TAGS = ( 'all' => [ qw( ) ] );
27             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
28             our @EXPORT = qw(
29            
30             );
31              
32             our $VERSION = "0.1";
33             sub Version {
34 2     2 1 10 return $VERSION;
35             }
36              
37             sub New {
38 18 50   18 1 48 if ($#_ != 1){
39 0         0 printf "_ %s\n",$#_;
40 0         0 carp "Usage: File::Repl->New(\$dir)";
41             }
42 18         20 my $class = shift;
43 18         15 my($r);
44 18         40 $r->{dira} = $_[0];
45 18         198 ($r->{patha},$r->{w32a})=&_dc($r->{dira});
46 18         42 bless $r, $class;
47 18         48 return $r;
48             }
49              
50             sub _dc { # Directory Check - sanity check the directory name
51 52     52   58 my($dir) = @_;
52 52         112 my($c) = $dir =~ s/\\/\//g; # use forward slash as directory seperator
53 52 100       143 if ($c>0){
    100          
54 7         25 return $dir,1; # return win32 status if \ directory seperators
55             }elsif ($dir =~ m/^[a-z]{1}:/){
56 15         84 return $dir,2; # return win32 status if drive letter leads path
57             }else{
58 30         93 return $dir,0;
59             }
60 0         0 carp "sub _dc failed";
61             }
62              
63             sub Path {
64 34     34 1 39 my($r,$dirb,$w);
65 34 50       78 if ( scalar(@_) eq 2 ) {
66 34         59 ($r,$dirb) =@_;
67             }else{
68 0         0 carp "Usage: \$ref->Path(\$dir)";
69             }
70 34         61 $r->{dirb} = $dirb;
71 34         70 ($r->{pathb},$r->{w32b})=&_dc($r->{dirb});
72             # Set windows flag - drives case insensitive testing
73 34   100     164 $w = $r->{w32a} || $r->{w32b} || 0;
74              
75             # split both paths by dir seperators
76 34         44 my(@dira,@dirb,$i,$j,$relpath);
77 34         133 @dira = split(/\//,$r->{patha});
78 34         107 @dirb = split(/\//,$r->{pathb});
79 34 100       80 unless( $dira[0] eq $dirb[0] ){
80 10         14 my($err) = "different file systems or not absolute paths";
81             # for unix these values will be null ("")
82             # for win32 a drive letter (need to deal with case differences here
83             #if ( $dira[0] =~ m/^[a-z]{1}:$/i ){ # test logic for a drive letter
84 10 50       42 if ( $dira[0] =~ m/^[a-z]{1}:$/i ){ # test logic for a drive letter
85 10 100       31 unless (lc($dira[0]) eq lc($dirb[0])){
86 2         400 carp $err;
87 2         23 return 0;
88             }
89             }else{
90 0         0 carp $err;
91 0         0 return 0;
92             }
93             }
94 32         46 my($min) = $#dira;
95 32 100       66 $min = $#dirb if ($#dirb < $min);
96 32         35 $j=-1;
97              
98 32         62 for($i=0;$i<=$min;$i++){
99 122 100       312 if (($w == 0) & ($dira[$i] eq $dirb[$i])){
    100          
100             # print "segment $i identical ( $dira[$i] eq $dirb[$i] )\n";
101 39         78 $j=$i;
102             }elsif (($w >= 1) & (lc($dira[$i]) eq lc($dirb[$i]))){
103             # print "segment $i identical ( $dira[$i] eq $dirb[$i] )\n";
104 54         102 $j=$i;
105             }else{
106             #print "segment $i differ\n";
107 29         33 last;
108             }
109             }
110 32 50       68 if ($j >= 0){
111 32         40 $i = $#dira - $j;
112 32 100       58 $relpath = "." if ($i == 0);
113 32 100       107 $relpath = sprintf "../" x $i unless ($i == 0);
114 32         75 for ($i=$j+1;$i<=$#dirb;$i++){
115 49 100       132 $relpath .= "/" unless ($relpath =~ m/\/$/);
116 49         125 $relpath .= $dirb[$i];
117             }
118              
119             }else{
120 0         0 carp "different file systems or not absolute paths";
121             }
122 32 100       77 $relpath =~ s/\//\\/g if ($r->{w32a} == 1);
123 32         265 return $relpath;
124              
125             }
126              
127             sub Diff ($$) {
128             # provide a relartive pathname from direcrtory a to directory b
129 12     12 1 23 my ($dira, $dirb) = @_;
130 12         27 my($ref)=File::RelDir->New($dira);
131 12         24 return $ref->Path($dirb);
132             }
133             1;
134              
135             __END__