File Coverage

blib/lib/Path/Naive.pm
Criterion Covered Total %
statement 47 47 100.0
branch 30 32 93.7
condition 26 30 86.6
subroutine 10 10 100.0
pod 7 7 100.0
total 120 126 95.2


line stmt bran cond sub pod time code
1             package Path::Naive;
2              
3             our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
4             our $DATE = '2020-02-07'; # DATE
5             our $DIST = 'Path-Naive'; # DIST
6             our $VERSION = '0.042'; # VERSION
7              
8 1     1   58275 use strict;
  1         10  
  1         25  
9 1     1   4 use warnings;
  1         2  
  1         20  
10              
11 1     1   4 use Exporter;
  1         1  
  1         548  
12             our @ISA = qw(Exporter);
13             our @EXPORT_OK = qw(
14             abs_path
15             concat_path
16             concat_and_normalize_path
17             normalize_path
18             is_abs_path
19             is_rel_path
20             split_path
21             );
22              
23             sub abs_path {
24 8     8 1 2271 my ($path, $base) = @_;
25              
26 8 100 100     51 die "Please specify path (first arg)" unless defined $path && length $path;
27 5 50 33     16 die "Please specify base (second arg)" unless defined $base && length $base;
28 5 100       9 die "base must be absolute" unless is_abs_path($base);
29 4         8 concat_and_normalize_path($base, $path);
30             }
31              
32             sub is_abs_path {
33 14     14 1 2927 my $path = shift;
34 14 100 100     59 die "Please specify path" unless defined $path && length $path;
35 11 100       56 $path =~ m!\A/! ? 1:0;
36             }
37              
38             sub is_rel_path {
39 5     5 1 3126 my $path = shift;
40 5 100 100     33 die "Please specify path" unless defined $path && length $path;
41 2 100       12 $path =~ m!\A/! ? 0:1;
42             }
43              
44             sub normalize_path {
45 41     41 1 2898 my $path = shift;
46 41         61 my @elems0 = split_path($path);
47 38         81 my $is_abs = $path =~ m!\A/!;
48 38         41 my @elems;
49 38         68 while (@elems0) {
50 92         106 my $elem = shift @elems0;
51 92 100 100     189 next if $elem eq '.' && (@elems || @elems0 || $is_abs);
      100        
52 74 100 100     197 do { pop @elems; next } if $elem eq '..' &&
  12   100     15  
  12         22  
53             (@elems>1 && $elems[-1] ne '..' ||
54             @elems==1 && $elems[-1] ne '..' && $elems[-1] ne '.' && @elems0 ||
55             $is_abs);
56 62         110 push @elems, $elem;
57             }
58 38 100       197 ($is_abs ? "/" : "") . join("/", @elems);
59             }
60              
61             sub split_path {
62 54     54 1 3285 my $path = shift;
63 54 100 100     217 die "Please specify path" unless defined $path && length $path;
64 48         339 grep {length} split qr!/+!, $path;
  125         261  
65             }
66              
67             sub concat_path {
68 27 100   27 1 3163 die "Please specify at least two paths" unless @_ > 1;
69 21         25 my $i = 0;
70 21         26 my $res = $_[0];
71 21         24 for (@_) {
72 44 50 33     111 die "Please specify path (#$i)" unless defined && length;
73 44 100       67 next unless $i++;
74 23 100       52 if (m!\A/!) {
75 6         9 $res = $_;
76             } else {
77 17 100       50 $res .= ($res =~ m!/\z! ? "" : "/") . $_;
78             }
79             }
80 21         58 $res;
81             }
82              
83             sub concat_and_normalize_path {
84 16     16 1 2886 normalize_path(concat_path(@_));
85             }
86              
87             1;
88             # ABSTRACT: Yet another abstract, Unix-like path manipulation routines
89              
90             __END__