PGXN-API
view release on metacpan or search on metacpan
lib/PGXN/API/Sync.pm view on Meta::CPAN
# c: checkum has changed, file will be updated
# s: file size has changed, file will be updated
# t: modtime has changed, file will be updated
# +++++++: New item
}
sub validate_distribution {
my ($self, $fn) = shift->_rel_to_mirror(@_);
my $meta = PGXN::API->instance->read_json_from($fn);
my $zip_path = $self->download_for($meta);
# Validate it against the SHA1 checksum.
say ' Checksumming ', $zip_path if $self->verbose;
if ($self->digest_for($zip_path) ne $meta->{sha1}) {
warn "Checksum verification failed for $fn\n";
return;
}
# Unpack the distribution.
my $zip = $self->unzip($zip_path, $meta) or return;
return { meta => $meta, zip => $zip };
}
sub download_for {
my ($self, $meta) = @_;
my $zip_uri = $self->mirror_uri_templates->{download}->process(
dist => lc $meta->{name},
version => lc $meta->{version},
);
my (undef, @segments) = $zip_uri->path_segments;
return catfile @segments;
}
sub digest_for {
my ($self, $fn) = shift->_rel_to_mirror(@_);
open my $fh, '<:raw', $fn or die "Cannot open $fn: $!\n";
my $sha1 = Digest::SHA1->new;
$sha1->addfile($fh);
return $sha1->hexdigest;
}
sub unzip {
say ' Extracting ', $_[1] if $_[0]->verbose;
my ($self, $zip_path, $meta) = shift->_rel_to_mirror(@_);
my $zip = Archive::Zip->new;
if ($zip->read(rel2abs $zip_path) != AZ_OK) {
warn "Error reading $zip_path\n";
return;
}
my $dist_dir = catdir(
PGXN::API->instance->source_dir,
lc $meta->{name}
);
make_path $dist_dir unless -e $dist_dir && -d _;
foreach my $member ($zip->members) {
my $fn = catfile $dist_dir, split m{/} => $member->fileName;
say " $fn\n" if $self->verbose > 2;
if ($member->isSymbolicLink) {
# Delete exsting so Archive::Zip won't fail to create it.
warn "Cannot unlink $fn: $!\n" if -e $fn && !unlink $fn;
} else {
# Make sure the member is readable by everyone.
$member->unixFileAttributes( $member->isDirectory ? 0755 : 0644 );
}
if ($member->extractToFileNamed($fn) != AZ_OK) {
warn "Error extracting $fn from $zip_path\n";
next;
}
}
return $zip;
}
sub _rel_to_mirror {
return shift, catfile(+PGXN::API->instance->mirror_root, shift), @_;
}
__PACKAGE__->meta->make_immutable(inline_destructor => 0);
1;
__END__
=head1 Name
PGXN::API::Sync - Sync from a PGXN mirror and update the index
=head1 Synopsis
use PGXN::API::Sync;
PGXN::API::Sync->new(
source => $source,
rsync_path => $rsync_path,
verbose => $verbose,
)->run;
=head1 Description
This module provides the implementation for L<pgxn_api_sync>, the command-line
utility for syncing to a PGXN mirror and creating the API. It syncs to the
specified PGXN rsync source URL, which should be a PGXN mirror server, and
then verifies and unpacks newly-uploaded distributions and hands them off to
L<PGXN::API::Indexer> to index.
=head1 Class Interface
=head2 Constructor
=head3 C<new>
my $sync = PGXN::API::Sync->new(%params);
Creates and returns a new PGXN::API::Sync object. The supported parameters
are:
( run in 2.157 seconds using v1.01-cache-2.11-cpan-71847e10f99 )