File Coverage

blib/lib/Dancer/FileUtils.pm
Criterion Covered Total %
statement 69 83 83.1
branch 10 24 41.6
condition 2 2 100.0
subroutine 21 22 95.4
pod 6 9 66.6
total 108 140 77.1


line stmt bran cond sub pod time code
1             package Dancer::FileUtils;
2             our $AUTHORITY = 'cpan:SUKRIA';
3             #ABSTRACT: helper providing file utilities
4             $Dancer::FileUtils::VERSION = '1.3521';
5 195     195   136070 use strict;
  195         477  
  195         5525  
6 195     195   1064 use warnings;
  195         379  
  195         4830  
7              
8 195     195   92732 use IO::File;
  195         1567003  
  195         21268  
9              
10 195     195   1574 use File::Basename ();
  195         454  
  195         3705  
11 195     195   1027 use File::Spec;
  195         405  
  195         5146  
12 195     195   145694 use File::Temp qw(tempfile);
  195         2161682  
  195         12101  
13              
14 195     195   1522 use Carp;
  195         458  
  195         9557  
15 195     195   1219 use Cwd 'realpath';
  195         451  
  195         7860  
16              
17 195     195   3089 use Dancer::Exception qw(:all);
  195         487  
  195         23049  
18              
19 195     195   1763 use base 'Exporter';
  195         451  
  195         20325  
20 195     195   1352 use vars '@EXPORT_OK';
  195         456  
  195         163559  
21              
22             @EXPORT_OK = qw(
23             dirname open_file path read_file_content read_glob_content
24             path_or_empty set_file_mode normalize_path
25             atomic_write
26             );
27              
28             # path should not verify paths
29             # just normalize
30             sub path {
31 2520     2520 1 9134 my @parts = @_;
32 2520         20527 my $path = File::Spec->catfile(@parts);
33              
34 2520         7474 return normalize_path($path);
35             }
36              
37             sub path_or_empty {
38 1     1 0 370 my @parts = @_;
39 1         4 my $path = path(@parts);
40              
41             # return empty if it doesn't exist
42 1 50       16 return -e $path ? $path : '';
43             }
44              
45 12     12 1 772 sub dirname { File::Basename::dirname(@_) }
46              
47             sub set_file_mode {
48 143     143 1 403 my $fh = shift;
49              
50 143         3187 require Dancer::Config;
51 143   100     811 my $charset = Dancer::Config::setting('charset') || 'utf-8';
52 143     2   2671 binmode $fh, ":encoding($charset)";
  2         15  
  2         5  
  2         37  
53              
54 143         19615 return $fh;
55             }
56              
57             sub open_file {
58 140     140 1 575 my ( $mode, $filename ) = @_;
59              
60 140 50       8541 open my $fh, $mode, $filename
61             or raise core_fileutils => "$! while opening '$filename' using mode '$mode'";
62              
63 140         1000 return set_file_mode($fh);
64             }
65              
66             sub read_file_content {
67 60 50   60 1 2856189 my $file = shift or return;
68 60         469 my $fh = open_file( '<', $file );
69              
70             return wantarray ?
71 60 100       318 read_glob_content($fh) :
72             scalar read_glob_content($fh);
73             }
74              
75             sub read_glob_content {
76 64     64 1 4115 my $fh = shift;
77              
78             # we don't want to do that as we'll encode the stuff later
79             # binmode $fh;
80              
81 64         2523 my @content = <$fh>;
82 64         2386 close $fh;
83              
84 64 100       865 return wantarray ? @content : join '', @content;
85             }
86              
87             sub normalize_path {
88             # this is a revised version of what is described in
89             # http://www.linuxjournal.com/content/normalizing-path-names-bash
90             # by Mitch Frazier
91 2530 50   2530 0 12526 my $path = shift or return;
92 2530         7935 my $seqregex = qr{
93             [^/]* # anything without a slash
94             /\.\./ # that is accompanied by two dots as such
95             }x;
96              
97 2530         6393 $path =~ s{/\./}{/}g;
98 2530         10757 while ( $path =~ s{$seqregex}{} ) {}
99              
100 2530         3258147 return $path;
101             }
102              
103             # !! currently unused
104             # Undo UNC special-casing catfile-voodoo on cygwin
105             sub _trim_UNC {
106 0     0   0 my @args = @_;
107              
108             # if we're using cygwin
109 0 0       0 if ( $^O eq 'cygwin' ) {
110             # no @args, no problem
111 0 0       0 @args or return;
112              
113 0         0 my ( $slashes, $part, @parts) = ( 0, undef, @args );
114              
115             # start pulling part from @parts
116 0         0 while ( defined ( $part = shift @parts ) ) {
117 0 0       0 last if $part;
118 0         0 $slashes++;
119             }
120              
121             # count slashes in $part
122 0         0 $slashes += ( $part =~ s/^[\/\\]+// );
123              
124 0 0       0 if ( $slashes == 2 ) {
125 0         0 return ( '/' . $part, @parts );
126             } else {
127 0         0 my $slashstr = '';
128 0         0 $slashstr .= '/' for ( 1 .. $slashes );
129              
130 0         0 return ( $slashstr . $part, @parts );
131             }
132             }
133              
134 0         0 return @args;
135             }
136              
137             sub atomic_write {
138 4     4 0 16442 my ($path, $file, $data) = @_;
139 4         19 my ($fh, $filename) = tempfile("tmpXXXXXXXXX", DIR => $path);
140 3         1073 set_file_mode($fh);
141 3         22 print $fh $data;
142 3 50       194 close $fh or die "Can't close '$file': $!\n";
143 3 50       285 rename($filename, $file) or die "Can't move '$filename' to '$file'";
144             }
145              
146             1;
147              
148             __END__