view release on metacpan or search on metacpan
lib/App/Nrepo.pm view on Meta::CPAN
=item C<tag>
=back
For each actions required options see its appropriate method below
=cut
sub go {
my ( $self, $action, @args ) = @_;
$self->_validate_config();
my $dispatch = {
'add-file' => \&add_file,
'del-file' => \&del_file,
'clean' => \&clean,
'init' => \&init,
'list' => \&list,
'mirror' => \&mirror,
'tag' => \&tag,
};
lib/App/Nrepo.pm view on Meta::CPAN
|| $self->logger->log_and_croak(
level => 'error',
message => "ERROR: ${action} not supported."
);
$dispatch->{$action}->( $self, @args );
exit(0);
}
sub _validate_config {
my $self = shift;
# If data_dir is relative, lets expand it based on cwd
$self->config->{'data_dir'} =
File::Spec->rel2abs( $self->config->{data_dir} );
$self->logger->log_and_croak(
level => 'error',
message => sprintf "datadir does not exist: %s",
$self->config->{data_dir},
lib/App/Nrepo.pm view on Meta::CPAN
$repo, $param, $self->config->{repo}->{$repo}->{$param},
);
}
}
}
}
}
sub _get_plugin {
my $self = shift;
my %o = validate(
@_,
{
type => { type => SCALAR, },
options => { options => HASHREF, },
}
);
my $plugin;
for my $p (
Module::Pluggable::Object->new(
lib/App/Nrepo.pm view on Meta::CPAN
}
$self->logger->log_and_croak(
level => 'error',
message => "Failed to find a plugin for type: $o{'type'}"
) unless $plugin;
return $plugin;
}
sub _get_repo_dir {
my $self = shift;
my %o = validate(
@_,
{
repo => { type => SCALAR },
tag => { type => SCALAR, default => 'head', },
}
);
my $data_dir = $self->config->{data_dir};
my $tag_style = $self->config->{tag_style};
my $repo = $o{'repo'};
lib/App/Nrepo.pm view on Meta::CPAN
=item C<force>
Boolean to enable force overwriting an existing file in the repository
=back
=cut
sub add_file {
my $self = shift;
my %o = validate(
@_,
{
'repo' => { type => SCALAR },
'arch' => { type => SCALAR },
'file' => { type => SCALAR | ARRAYREF },
'force' => { type => BOOLEAN, default => 0 },
},
);
my $options = {
repo => $o{'repo'},
lib/App/Nrepo.pm view on Meta::CPAN
=item C<file>
The filename to be removed to the repository
=back
=cut
sub del_file {
my $self = shift;
my %o = validate(
@_,
{
'repo' => { type => SCALAR },
'arch' => { type => SCALAR },
'file' => { type => SCALAR | ARRAYREF },
},
);
my $options = {
repo => $o{'repo'},
arches => $self->config->{'repo'}->{ $o{'repo'} }->{'arch'},
lib/App/Nrepo.pm view on Meta::CPAN
The name of the repository as reflected in the config
If 'all' is supplied it will perform this action on all repositories in config
=back
=cut
sub clean {
my $self = shift;
my %o = validate(
@_,
{
repo => { type => SCALAR, },
arch => { type => SCALAR, optional => 1 },
force => { type => BOOLEAN, optional => 1, },
}
);
if ( $o{'repo'} eq 'all' ) {
my %options = %o;
lib/App/Nrepo.pm view on Meta::CPAN
=item C<repo>
The name of the repository as reflected in the config
=back
=cut
sub init {
my $self = shift;
my %o = validate(
@_,
{
repo => { type => SCALAR, },
arch => { type => SCALAR, optional => 1 },
}
);
my $options = {
repo => $o{'repo'},
arches => $self->config->{'repo'}->{ $o{'repo'} }->{'arch'},
lib/App/Nrepo.pm view on Meta::CPAN
By default we just use the manifests information about size of packages to determine if the local file
is valid. If you want to have checksums used enable this boolean flag.
With this enabled updating a mirror can take quite a long time
=back
=cut
sub mirror {
my $self = shift;
my %o = validate(
@_,
{
'repo' => { type => SCALAR },
'force' => { type => BOOLEAN, default => 0 },
'arch' => { type => SCALAR, optional => 1 },
'checksums' => { type => SCALAR, optional => 1 },
}
);
if ( $o{'repo'} eq 'all' ) {
lib/App/Nrepo.pm view on Meta::CPAN
=item C<force>
Force will overwrite a pre existing dest-tag location
=back
=cut
sub tag {
my $self = shift;
my %o = validate(
@_,
{
'repo' => { type => SCALAR },
'tag' => { type => SCALAR },
'src-tag' => { type => SCALAR, default => 'head' },
'symlink' => { type => BOOLEAN, default => 0 },
'force' => { type => BOOLEAN, default => 0 },
},
);
lib/App/Nrepo/Plugin/Base.pm view on Meta::CPAN
$self->logger->log_and_croak(
level => 'error',
message => "Failed to remove path: ${dir}"
) if -d $dir;
$self->logger->debug("removed path: ${dir}");
return 1;
}
return 0;
}
sub validate_arch {
my $self = shift;
my $arch = shift;
my $matched;
for my $a ( @{ $self->arches() } ) {
$matched++ if $a eq $arch;
}
return $matched;
}
sub validate_file {
my $self = shift;
my %o = validate(
@_,
{
filename => { type => SCALAR },
check => { type => SCALAR },
value => { type => SCALAR },
}
);
# If theres no file, its not valid
return 0 unless -f $o{'filename'};
# If force is enabled, its not valid
return 0 if $self->force();
# Check against size
if ( $o{'check'} eq 'size' ) {
return $self->_validate_file_size( $o{'filename'}, $o{'value'} );
}
# Check against sha
elsif ( $o{'check'} eq 'sha' ) {
return $self->_validate_file_sha( $o{'filename'}, $o{'value'} );
}
# Check against sha256
elsif ( $o{'check'} eq 'sha256' ) {
return $self->_validate_file_sha256( $o{'filename'}, $o{'value'} );
}
else {
$self->logger->log_and_croak(
level => 'error',
message => "unknown validation check type: $o{'check'}"
);
}
}
sub _validate_file_size {
my $self = shift;
my $file = shift;
my $size = shift;
my @stats = stat($file);
my $file_size = $stats[7];
return $file_size eq $size ? 1 : undef;
}
sub _validate_file_sha {
my $self = shift;
my $file = shift;
my $checksum = shift;
my $sha = Digest::SHA->new('sha1');
$sha->addfile($file);
return $sha->hexdigest eq $checksum ? 1 : undef;
}
sub _validate_file_sha256 {
my $self = shift;
my $file = shift;
my $checksum = shift;
my $sha = Digest::SHA->new('sha256');
$sha->addfile($file);
return $sha->hexdigest eq $checksum ? 1 : undef;
}
sub mirror {
lib/App/Nrepo/Plugin/Base.pm view on Meta::CPAN
else {
for my $a ( @{ $self->arches() } ) {
$self->init_arch($a);
}
}
}
sub tag {
my $self = shift;
my %o = validate(
@_,
{
src_tag => { type => SCALAR },
src_dir => { type => SCALAR },
dest_tag => { type => SCALAR },
dest_dir => { type => SCALAR },
symlink => { type => BOOLEAN, default => 0 },
hard_tag_regex => { type => SCALAR, optional => 1 },
}
);
lib/App/Nrepo/Plugin/Base.pm view on Meta::CPAN
"tag: repo: %s couldnt link src_dir: %s to dst_dir: %s: $!",
$self->repo(), $o{'src_dir'}, $o{'dest_dir'}
),
);
}
}
}
sub download_binary_file {
my $self = shift;
my %o = validate(
@_,
{
url => { type => SCALAR },
dest => { type => SCALAR },
retry_limit => { type => SCALAR, default => 3 },
}
);
$self->logger->debug(
sprintf(
'download_binary_file: repo: %s url: %s dest: %s',
$self->repo(), $o{url}, $o{dest},
)
);
# HTTP::Tiny's mirror function does not seem to validate the file if its locally present in any way
unlink $o{dest} if -f $o{dest};
my $retry_count = 0;
my $retry_limit = $o{retry_limit};
my $success;
while ( !$success && $retry_count <= $retry_limit ) {
my $t0 = [gettimeofday];
my $res = $self->http->mirror( $o{'url'}, $o{'dest'} );
my $elapsed = tv_interval($t0);
lib/App/Nrepo/Plugin/Yum.pm view on Meta::CPAN
# Make sure dir exists
$self->make_dir($dest_dir);
# Check if we have the local file
my $download;
if ( $type eq 'repomd' ) {
$download++;
}
elsif (
!$self->validate_file(
filename => $dest_file,
check => $m->{'validate'}->{'type'},
value => $m->{'validate'}->{'value'},
)
)
{
$download++;
}
# Grab the file
if ($download) {
$self->download_binary_file( url => $m_url, dest => $dest_file );
}
lib/App/Nrepo/Plugin/Yum.pm view on Meta::CPAN
$data->{'size'}->{'type'} = 'size';
$data->{'size'}->{'value'} = $c->text;
}
}
# For some reason i have found a few repomd.xml files that do NOT
# have a size attribute ...specifically updateinfo type
# so as a work around we will try size if checksums is not enabled
# however for that file we'll revert to checksums if size is not available
if ( !$self->checksums() && $data->{'size'} ) {
$data->{'validate'} = $data->{'size'};
}
else {
$data->{'validate'} = $data->{'checksum'};
}
$self->logger->log_and_croak(
level => 'error',
message => "repomd xml not valid: $file"
) unless $data->{'location'};
push @files, $data;
}
return \@files;
}
lib/App/Nrepo/Plugin/Yum.pm view on Meta::CPAN
size => {
type => 'size',
value => $s->getAttribute('package'),
},
checksum => {
type => $c->getAttribute('type'),
value => $c->textContent,
},
};
if ( !$self->checksums() && $data->{'size'} ) {
$data->{'validate'} = $data->{'size'};
}
else {
$data->{'validate'} = $data->{'checksum'};
}
push @{$packages}, $data;
}
my $elapsed = tv_interval($t0);
$self->logger->debug(
sprintf( 'parse_primary: file: %s took: %s seconds', $dest_file, $elapsed )
);
return $packages;
}
sub get_packages {
my $self = shift;
my %o = validate(
@_,
{
arch => { type => SCALAR },
packages => { type => ARRAYREF },
}
);
my $arch = $o{'arch'};
my $base_dir = File::Spec->catdir( $self->dir(), $arch );
lib/App/Nrepo/Plugin/Yum.pm view on Meta::CPAN
my $p_url = join( '/', ( $self->url, $location ) );
$p_url =~ s/%ARCH%/$arch/;
my $dest_file = File::Spec->catfile( $base_dir, $location );
my $dest_dir = dirname($dest_file);
# Make sure dir exists
$self->make_dir($dest_dir);
# Check if we have the local file
if (
!$self->validate_file(
filename => $dest_file,
check => $package->{'validate'}->{'type'},
value => $package->{'validate'}->{'value'},
)
)
{
$self->logger->notice(
sprintf(
'get_packages: repo: %s arch: %s package: %s',
$self->repo(), $arch, $location
)
);
$self->download_binary_file( url => $p_url, dest => $dest_file );
lib/App/Nrepo/Plugin/Yum.pm view on Meta::CPAN
'get_packages: repo: %s arch: %s package: %s skipping as its deemed up to date',
$self->repo(), $arch, $location
)
);
}
}
}
sub clean_files {
my $self = shift;
my %o = validate(
@_,
{
arch => { type => SCALAR },
files => { type => HASHREF },
}
);
my $arch = $o{'arch'};
my $base_dir = File::Spec->catdir( $self->dir(), $arch );
lib/App/Nrepo/Plugin/Yum.pm view on Meta::CPAN
},
$base_dir,
);
}
sub add_file {
my $self = shift;
my $arch = shift;
my $files = shift;
unless ( $self->validate_arch($arch) ) {
$self->logger->log_and_croak(
level => 'error',
message => sprintf 'add_file: arch: %s is not in config for repo: %s',
$arch, $self->repo()
);
}
my $package_dir =
File::Spec->catdir( $self->dir(), $arch, $self->packages_dir() );
$self->make_dir($package_dir) unless -d $package_dir;
lib/App/Nrepo/Plugin/Yum.pm view on Meta::CPAN
$self->init_arch($arch);
}
sub del_file {
my $self = shift;
my $arch = shift;
my $files = shift;
unless ( $self->validate_arch($arch) ) {
$self->logger->log_and_croak(
level => 'error',
message => sprintf 'del_file: arch: %s is not in config for repo: %s',
$arch, $self->repo()
);
}
for my $file ( @${files} ) {
my $filename = basename($file);
my $dest_file =