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.3520';
5 195     195   142633 use strict;
  195         410  
  195         5746  
6 195     195   981 use warnings;
  195         420  
  195         4737  
7              
8 195     195   94346 use IO::File;
  195         1602607  
  195         21423  
9              
10 195     195   1572 use File::Basename ();
  195         431  
  195         4837  
11 195     195   985 use File::Spec;
  195         407  
  195         5147  
12 195     195   149622 use File::Temp qw(tempfile);
  195         2237478  
  195         12657  
13              
14 195     195   1535 use Carp;
  195         476  
  195         9747  
15 195     195   1204 use Cwd 'realpath';
  195         444  
  195         8616  
16              
17 195     195   2957 use Dancer::Exception qw(:all);
  195         438  
  195         23812  
18              
19 195     195   1419 use base 'Exporter';
  195         459  
  195         21546  
20 195     195   1402 use vars '@EXPORT_OK';
  195         503  
  195         170627  
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 9441 my @parts = @_;
32 2520         20496 my $path = File::Spec->catfile(@parts);
33              
34 2520         7329 return normalize_path($path);
35             }
36              
37             sub path_or_empty {
38 1     1 0 487 my @parts = @_;
39 1         4 my $path = path(@parts);
40              
41             # return empty if it doesn't exist
42 1 50       17 return -e $path ? $path : '';
43             }
44              
45 12     12 1 756 sub dirname { File::Basename::dirname(@_) }
46              
47             sub set_file_mode {
48 143     143 1 378 my $fh = shift;
49              
50 143         2839 require Dancer::Config;
51 143   100     750 my $charset = Dancer::Config::setting('charset') || 'utf-8';
52 143     2   2877 binmode $fh, ":encoding($charset)";
  2         14  
  2         3  
  2         35  
53              
54 143         19206 return $fh;
55             }
56              
57             sub open_file {
58 140     140 1 534 my ( $mode, $filename ) = @_;
59              
60 140 50       8461 open my $fh, $mode, $filename
61             or raise core_fileutils => "$! while opening '$filename' using mode '$mode'";
62              
63 140         990 return set_file_mode($fh);
64             }
65              
66             sub read_file_content {
67 60 50   60 1 2896044 my $file = shift or return;
68 60         326 my $fh = open_file( '<', $file );
69              
70             return wantarray ?
71 60 100       309 read_glob_content($fh) :
72             scalar read_glob_content($fh);
73             }
74              
75             sub read_glob_content {
76 64     64 1 5018 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         2527 my @content = <$fh>;
82 64         2148 close $fh;
83              
84 64 100       826 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 11218 my $path = shift or return;
92 2530         7794 my $seqregex = qr{
93             [^/]* # anything without a slash
94             /\.\./ # that is accompanied by two dots as such
95             }x;
96              
97 2530         6188 $path =~ s{/\./}{/}g;
98 2530         10885 while ( $path =~ s{$seqregex}{} ) {}
99              
100 2530         3270478 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 17451 my ($path, $file, $data) = @_;
139 4         19 my ($fh, $filename) = tempfile("tmpXXXXXXXXX", DIR => $path);
140 3         1011 set_file_mode($fh);
141 3         21 print $fh $data;
142 3 50       199 close $fh or die "Can't close '$file': $!\n";
143 3 50       330 rename($filename, $file) or die "Can't move '$filename' to '$file'";
144             }
145              
146             1;
147              
148             __END__