line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# Copyright © 2009-2013 David Caldwell and Jim Radford. |
2
|
|
|
|
|
|
|
# |
3
|
|
|
|
|
|
|
# This library is free software; you can redistribute it and/or modify |
4
|
|
|
|
|
|
|
# it under the same terms as Perl itself, either Perl version 5.12.4 or, |
5
|
|
|
|
|
|
|
# at your option, any later version of Perl 5 you may have available. |
6
|
|
|
|
|
|
|
|
7
|
3
|
|
|
3
|
|
86736
|
package File::HashCache; use warnings; use strict; |
|
3
|
|
|
3
|
|
9
|
|
|
3
|
|
|
|
|
90
|
|
|
3
|
|
|
|
|
17
|
|
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
141
|
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
our $VERSION = '1.0.2'; |
10
|
|
|
|
|
|
|
|
11
|
3
|
|
|
3
|
|
16
|
use List::Util qw(max); |
|
3
|
|
|
|
|
10
|
|
|
3
|
|
|
|
|
403
|
|
12
|
3
|
|
|
3
|
|
16
|
use Digest::MD5 qw(md5_hex); |
|
3
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
163
|
|
13
|
3
|
|
|
3
|
|
15
|
use File::Basename; |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
307
|
|
14
|
3
|
|
|
3
|
|
3520
|
use File::Slurp qw(read_file write_file); |
|
3
|
|
|
|
|
94063
|
|
|
3
|
|
|
|
|
290
|
|
15
|
3
|
|
|
3
|
|
3959
|
use JSON qw(to_json from_json); |
|
3
|
|
|
|
|
99925
|
|
|
3
|
|
|
|
|
20
|
|
16
|
|
|
|
|
|
|
|
17
|
23
|
50
|
|
23
|
0
|
43
|
sub max_timestamp(@) { max map { (stat $_)[9] || 0 } @_ } # Obviously 9 is mtime |
|
32
|
|
|
|
|
1025
|
|
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
# DEPRECATED. This has been subsumed by the concatenation code--It's easier |
20
|
|
|
|
|
|
|
# to deal with and doesn't make you use a weird dialect of Javscript in your |
21
|
|
|
|
|
|
|
# code. **This is only here for backwards compatibility. Do Not Use.** |
22
|
|
|
|
|
|
|
sub pound_include($;$); |
23
|
|
|
|
|
|
|
sub pound_include($;$) { |
24
|
12
|
|
|
12
|
0
|
27
|
my ($text, $referrer) = @_; |
25
|
12
|
|
|
|
|
25
|
my ($line, @deps) = (0); |
26
|
12
|
|
|
|
|
45
|
return (join('', map { $line++; |
|
41
|
|
|
|
|
47
|
|
27
|
41
|
|
|
|
|
52
|
$_ .= "\n"; |
28
|
41
|
100
|
|
|
|
99
|
if (/^#include\s+"([^"]+)"/) { |
29
|
4
|
0
|
|
|
|
21
|
my $included = read_file(my $name=$1) or die "include '$1' not found".($referrer?" at $referrer\n":"\n"); |
|
|
50
|
|
|
|
|
|
30
|
3
|
|
|
|
|
268
|
($_, my @new_deps) = pound_include($included, $name); |
31
|
3
|
|
|
|
|
11
|
push @deps, $name, @new_deps; |
32
|
|
|
|
|
|
|
} |
33
|
40
|
|
|
|
|
103
|
$_; |
34
|
|
|
|
|
|
|
} split(/\n/, $text)), |
35
|
|
|
|
|
|
|
@deps); |
36
|
|
|
|
|
|
|
} |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
sub hash { |
39
|
20
|
|
|
20
|
1
|
2018751
|
my ($config, @name) = @_; |
40
|
|
|
|
|
|
|
|
41
|
20
|
|
|
|
|
34
|
my ($dir,@base,$ext); |
42
|
20
|
|
|
|
|
53
|
for my $name (@name) { |
43
|
25
|
|
|
|
|
998
|
my ($_base, $_dir, $_ext) = fileparse $name, qr/\.[^.]+/; |
44
|
25
|
|
|
|
|
135
|
$_ext =~ s/^\.//; |
45
|
25
|
100
|
66
|
|
|
176
|
$_ext eq ($ext //= $_ext) or die "extentions should be the same when concatenating"; |
46
|
24
|
|
66
|
|
|
176
|
$dir //= $_dir; # Not quite right but works in most cases. |
47
|
24
|
|
|
|
|
71
|
push @base, $_base; |
48
|
|
|
|
|
|
|
} |
49
|
19
|
|
|
|
|
53
|
my $base = join '-', @base; |
50
|
19
|
|
|
|
|
43
|
my $name = "$dir$base.$ext"; # canonical version of the name in the single case, and a merged version in the multiple case |
51
|
|
|
|
|
|
|
|
52
|
19
|
|
|
|
|
42
|
my $script; |
53
|
19
|
50
|
100
|
|
|
277
|
if ( !($script = $config->{cache}->{$name}) |
|
5
|
|
66
|
|
|
32
|
|
54
|
|
|
|
|
|
|
|| ! -f $script->{path} |
55
|
|
|
|
|
|
|
|| max_timestamp(@{$script->{deps}}) > $script->{timestamp}) { |
56
|
|
|
|
|
|
|
|
57
|
19
|
|
|
|
|
52
|
my @deps = @name; |
58
|
19
|
|
|
|
|
40
|
my $processed = join("\n", map { scalar read_file($_) } @name); |
|
23
|
|
|
|
|
509
|
|
59
|
19
|
|
|
|
|
2000
|
my $process_ext = $config->{"process_$ext"}; |
60
|
19
|
100
|
|
|
|
30
|
for my $process (@{ref($process_ext) eq 'CODE' ? [$process_ext] : $process_ext}) { |
|
19
|
|
|
|
|
84
|
|
61
|
24
|
|
|
|
|
512
|
($processed, my @new_deps) = $process->($processed); |
62
|
23
|
|
|
|
|
74
|
push @deps, @new_deps; |
63
|
|
|
|
|
|
|
} |
64
|
|
|
|
|
|
|
|
65
|
18
|
|
|
|
|
105
|
my $hash = md5_hex($processed); |
66
|
18
|
|
|
|
|
192
|
$config->{cache}->{$name} = $script = { deps => \@deps, |
67
|
|
|
|
|
|
|
name => "$base-$hash.$ext", |
68
|
|
|
|
|
|
|
path => "$config->{cache_dir}/$base-$hash.$ext", |
69
|
|
|
|
|
|
|
hash => $hash, |
70
|
|
|
|
|
|
|
timestamp => max_timestamp(@deps) }; |
71
|
18
|
100
|
|
|
|
306
|
if (! -f $script->{path}) { |
72
|
2
|
|
|
|
|
17
|
mkdir $config->{cache_dir}; |
73
|
2
|
50
|
|
|
|
15
|
write_file($script->{path}, { atomic => 1 }, $processed) or die "couldn't cache $script->{path}"; |
74
|
2
|
50
|
|
|
|
703
|
write_file($config->{cache_file}, { atomic => 1 }, to_json($config->{cache}, {pretty => 1})) or warn "Couldn't save cache control file"; |
75
|
|
|
|
|
|
|
} |
76
|
|
|
|
|
|
|
} |
77
|
18
|
|
|
|
|
861
|
$script->{name}; |
78
|
|
|
|
|
|
|
} |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
sub new { |
81
|
5
|
|
|
5
|
1
|
1002976
|
my $class = shift; |
82
|
5
|
|
|
|
|
85
|
my $config = bless { cache_dir => '.hashcache', |
83
|
|
|
|
|
|
|
@_, |
84
|
|
|
|
|
|
|
}, $class; |
85
|
5
|
|
33
|
|
|
75
|
$config->{cache_file} ||= "$config->{cache_dir}/cache.json"; |
86
|
5
|
50
|
|
|
|
172
|
$config->{cache} = from_json( read_file($config->{cache_file}) ) if -f $config->{cache_file}; |
87
|
5
|
|
|
|
|
9502
|
my $cache_file_version = 1; |
88
|
|
|
|
|
|
|
# On mismatched versions, just clear out the cache: |
89
|
5
|
50
|
50
|
|
|
72
|
$config->{cache} = { VERSION => $cache_file_version } unless $config->{cache} && ($config->{cache}->{VERSION} || 0) == $cache_file_version; |
|
|
|
33
|
|
|
|
|
90
|
5
|
|
|
|
|
30
|
$config; |
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
1; |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
__END__ |