App-Nrepo

 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 =



( run in 0.435 second using v1.01-cache-2.11-cpan-4d50c553e7e )