Alien-Build-Plugin-Fetch-Cache
view release on metacpan or search on metacpan
lib/Alien/Build/Plugin/Fetch/Cache.pm view on Meta::CPAN
package Alien::Build::Plugin::Fetch::Cache;
use strict;
use warnings;
use 5.010001;
use Alien::Build::Plugin;
use URI 1.71;
use Path::Tiny 0.100 ();
use Sereal 3.015 qw( encode_sereal decode_sereal );
use Digest::MD5;
use File::Glob qw( bsd_glob );
# ABSTRACT: Alien::Build plugin to cache files downloaded from the internet
our $VERSION = '0.05'; # VERSION
sub _local_file
{
my($uri) = @_;
Path::Tiny
->new(bsd_glob '~/.alienbuild/plugin_fetch_cache')
->child($uri->scheme)
->child($uri->host)
->child($uri->path)
->child('meta');
}
sub init
{
my($self, $meta) = @_;
$meta->around_hook(
fetch => sub {
my($orig, $build, $url) = @_;
my $local_file;
my $cache_url = $url // $build->meta_prop->{start_url};
if($cache_url && $cache_url !~ m!^/! && $cache_url !~ m!^file:!)
{
my $uri = URI->new($cache_url);
$local_file = _local_file($uri);
if(-r $local_file)
{
$build->log("using cached response for $uri");
return decode_sereal($local_file->slurp_raw);
}
}
my $res = $orig->($build, $url);
if(defined $local_file)
{
$local_file->parent->mkpath;
if($res->{type} eq 'file')
{
my $md5 = Digest::MD5->new;
if($res->{content})
{
$md5->add($res->{content});
}
else
{
open my $fh, '<', $res->{path};
$md5->addfile($fh);
close $fh;
}
my $data = Path::Tiny->new(bsd_glob '~/.alienbuild/plugin_fetch_cache/payload')
->child($md5->hexdigest)
->child($res->{filename});
$data->parent->mkpath;
my $res2 = {
type => 'file',
filename => $res->{filename},
path => $data->stringify,
protocol => $res->{protocol},
};
if($res->{content})
{
$data->spew_raw($res->{content});
}
elsif($res->{path})
{
Path::Tiny->new($res->{path})->copy($data);
}
else
{
die "got a file without contant or path";
}
$local_file->spew_raw( encode_sereal $res2 );
}
elsif($res->{type} =~ /^(list|html|dir_listing)$/)
{
$local_file->spew_raw( encode_sereal $res );
}
}
$res;
}
);
if($ENV{ALIEN_BUILD_PLUGIN_FETCH_CACHE_PRECACHE})
{
$meta->around_hook(
prefer => sub {
my($orig, $build, @rest) = @_;
my $ret = $orig->($build, @rest);
if($ret->{type} eq 'list')
{
foreach my $file (@{ $ret->{list} })
{
my $url = $file->{url};
if($url && $url !~ m!^/! && $url !~ m!^file:!)
{
my $local_file = _local_file(URI->new($url));
next if -f $local_file;
$build->log("precacheing $url");
$build->fetch($url);
}
}
}
$ret;
},
);
}
}
( run in 0.682 second using v1.01-cache-2.11-cpan-f5b5a18a01a )