ALPM

 view release on metacpan or  search on metacpan

Makefile.PL  view on Meta::CPAN

use warnings;
use strict;

# Avoid useless FAIL reports from CPAN Testers...
require DynaLoader;
unless(DynaLoader::dl_findfile('-lalpm')){
    print STDERR "ERROR: pacman/libalpm must be installed to compile ALPM!\n";
    exit 0;
}

sub MY::postamble {
    return <<'END_MAKE';
ALPM.xs: xs/DB.xs xs/Package.xs xs/Options.xs
END_MAKE
}

my %meta = ('resources' => { 'repository' => 'http://github.com/andrewgregory/perl-alpm' });
WriteMakefile(
	'NAME' => 'ALPM',
	'VERSION_FROM' => 'lib/ALPM.pm',
	'LICENSE' => 'perl',

alpm_xs.h  view on Meta::CPAN

/* String constants to use for log levels (instead of bitflags) */
extern const char * log_lvl_error;
extern const char * log_lvl_warning;
extern const char * log_lvl_debug;
extern const char * log_lvl_function;
extern const char * log_lvl_unknown;

/* CALLBACKS ****************************************************************/

#define DEF_SET_CALLBACK( CBTYPE )                                  \
    if ( ! SvOK(callback) && cb_ ## CBTYPE ## _sub != NULL ) {      \
        SvREFCNT_dec( cb_ ## CBTYPE ## _sub );                      \
        alpm_option_set_ ## CBTYPE ## cb( NULL );                   \
        cb_ ## CBTYPE ## _sub = NULL;                               \
    }                                                               \
    else {                                                          \
        if ( !SvROK(callback)                                       \
             || SvTYPE( SvRV(callback) ) != SVt_PVCV ) {            \
            croak( "value for %scb option must be a code reference", \
                   #CBTYPE );                                       \
        }                                                           \
        if ( cb_ ## CBTYPE ## _sub ) {                              \
            sv_setsv( cb_ ## CBTYPE ## _sub, callback );            \
        }                                                           \
        else {                                                      \
            cb_ ## CBTYPE ## _sub = newSVsv(callback);              \
            alpm_option_set_ ## CBTYPE ## cb                        \
                ( cb_ ## CBTYPE ## _wrapper );                      \
        }                                                           \
    }

#define DEF_GET_CALLBACK( CBTYPE )                          \
    RETVAL = ( cb_ ## CBTYPE ## _sub == NULL                \
               ? &PL_sv_undef : cb_ ## CBTYPE ## _sub );

void cb_log_wrapper ( alpm_loglevel_t level, const char * format, va_list args );
void cb_dl_wrapper ( const char *filename, off_t xfered, off_t total );
void cb_totaldl_wrapper ( off_t total );
int  cb_fetch_wrapper ( const char *url, const char *localpath, int force );

/* TRANSACTIONS ************************************************************/

/* This macro is used inside alpm_trans_init.
   CB_NAME is one of the transaction callback types (event, conv, progress).

   * [CB_NAME]_sub is the argument to the trans_init XSUB.
   * [CB_NAME]_func is a variable to hold the function pointer to pass
     to the real C ALPM function.
   * cb_trans_[CB_NAME]_wrapper is the name of the C wrapper function which
     calls the perl sub stored in the global variable:
   * cb_trans_[CB_NAME]_sub.
*/
#define UPDATE_TRANS_CALLBACK( CB_NAME )                                \
    if ( SvOK( CB_NAME ## _sub ) ) {                                    \
        if ( SvTYPE( SvRV( CB_NAME ## _sub ) ) != SVt_PVCV ) {          \
            croak( "Callback arguments must be code references" );      \
        }                                                               \
        if ( cb_trans_ ## CB_NAME ## _sub ) {                           \
            sv_setsv( cb_trans_ ## CB_NAME ## _sub, CB_NAME ## _sub );   \
        }                                                               \
        else {                                                          \
            cb_trans_ ## CB_NAME ## _sub = newSVsv( CB_NAME ## _sub );  \
        }                                                               \
        CB_NAME ## _func = cb_trans_ ## CB_NAME ## _wrapper;            \
    }                                                                   \
    else if ( cb_trans_ ## CB_NAME ## _sub != NULL ) {                  \
        /* If no event callback was provided for this new transaction,  \
           and an event callback is active, then remove the old callback. */ \
        SvREFCNT_dec( cb_trans_ ## CB_NAME ## _sub );                   \
        cb_trans_ ## CB_NAME ## _sub = NULL;                            \
    }

void cb_trans_event_wrapper ( alpm_transevt_t event,
                              void *arg_one, void *arg_two );
void cb_trans_conv_wrapper ( alpm_transconv_t type,
                             void *arg_one, void *arg_two, void *arg_three,
                             int *result );
void cb_trans_progress_wrapper ( alpm_transprog_t type,
                                 const char * desc,
                                 int item_progress,

lib/ALPM.pm  view on Meta::CPAN


our $VERSION;
BEGIN {
	$VERSION = '3.06';
	require XSLoader;
	XSLoader::load(__PACKAGE__, $VERSION);
}

## PUBLIC METHODS ##

sub dbs
{
	my($self) = @_;
	return ($self->localdb, $self->syncdbs);
}

sub db
{
	my($self, $name) = @_;
	for my $db ($self->dbs){
		return $db if($db->name eq $name);
	}
	return undef;
}

sub search
{
	my($self, @qry) = @_;
	return map { $_->search(@qry) } $self->dbs;
}

1;

lib/ALPM/Conf.pm  view on Meta::CPAN

	require Carp;
	require ALPM;
}

## Private functions.

# These options are implemented in pacman, not libalpm, and are ignored.
my @NULL_OPTS = qw{HoldPkg SyncFirst CleanMethod XferCommand
	TotalDownload VerbosePkgLists};

sub _null
{
	1;
}

my $COMMENT_MATCH = qr/ \A \s* [#] /xms;
my $SECTION_MATCH = qr/ \A \s* \[ ([^\]]+) \] \s* \z /xms;
my $FIELD_MATCH = qr/ \A \s* ([^=\s]+) (?: \s* = \s* ([^\n]*))? /xms;
sub _mkparser
{
	my($path, $hooks) = @_;
	sub {
		local $_ = shift;
		s/^\s+//; s/\s+$//; # trim whitespace
		return unless(length);

		# Call the appropriate hook for each type of token...
		if(/$COMMENT_MATCH/){
			;
		}elsif(/$SECTION_MATCH/){
			$hooks->{'section'}->($1);
		}elsif(/$FIELD_MATCH/){

lib/ALPM/Conf.pm  view on Meta::CPAN

			if(length $val){
				my $apply = $hooks->{'field'}{$name};
				$apply->($val) if($apply);
			}
		}else{
			die "Invalid line in config file, not a comment, section, or field\n";
		}
	};
}

sub _parse
{
	my($path, $hooks) = @_;

	my $parser = _mkparser($path, $hooks);
	my $line;
	open my $if, '<', $path or die "open $path: $!\n";
	eval {
		while(<$if>){
			chomp;
			$line = $_;

lib/ALPM/Conf.pm  view on Meta::CPAN

	if($err){
		# Print the offending file and line number along with any errors...
		# (This is why we use dies with newlines, for cascading error msgs)
		die "$@$path:$. $line\n"
	}
	return;
}

## Public methods.

sub new
{
	my($class, $path) = @_;
	bless { 'path' => $path }, $class;
}

sub custom_fields
{
	my($self, %cfields) = @_;
	if(grep { ref $_ ne 'CODE' } values %cfields){
		Carp::croak('Hash argument must have coderefs as values' )
	}
	$self->{'cfields'} = \%cfields;
	return;
}

sub _mlisthooks
{
	my($dbsref, $sectref) = @_;

	# Setup hooks for 'Include'ed file parsers...
	return {
		'section' => sub {
			my $file = shift;
			die q{Section declaration is not allowed in Include-ed file\n($file)\n};
		},
		'field' => {
			'Server' => sub { _addmirror($dbsref, shift, $$sectref) }
		},
	 };
}

my %CFGOPTS = (
	'RootDir' => 'root',
	'DBPath' => 'dbpath',
	'CacheDir' => 'cachedirs',
	'GPGDir' => 'gpgdir',
	'LogFile' => 'logfile',

lib/ALPM/Conf.pm  view on Meta::CPAN

	'UseDelta' => 'usedelta',
	'CheckSpace' => 'checkspace',
	'IgnorePkg' => 'ignorepkgs',
	'IgnoreGroup' => 'ignoregrps',
	'NoUpgrade' => 'noupgrades',
	'NoExtract' => 'noextracts',
	'NoPassiveFtp' => 'nopassiveftp',
	'Architecture' => 'arch',
);

sub _confhooks
{
	my($optsref, $sectref) = @_;
	my %hooks;
	while(my($fld, $opt) = each %CFGOPTS){
		$hooks{$fld} = sub { 
			my $val = shift;
			die qq{$fld can only be set in the [options] section\n}
				unless($$sectref eq 'options');
			$optsref->{$opt} = $val;
		};
	 }
	return %hooks;
}

sub _nullhooks
{
	map { ($_ => \&_null) } @_
}

sub _getdb
{
	my($dbs, $name) = @_;

	# The order databases are added must be preserved as must the order of URLs.
	for my $db (@$dbs){
		return $db if($db->{'name'} eq $name);
	}
	my $new = { 'name' => $name };
	push @$dbs, $new;
	return $new;
}

sub _setsiglvl
{
	my($dbs, $sect, $siglvl) = @_;
	my $db = _getdb($dbs, $sect);
	$db->{'siglvl'} = $siglvl;
	return;
}

sub _parse_siglvl
{
	my($str) = @_;
	my $siglvl;

	my $opt;
	for(split /\s+/, $str){
		my @types = qw/pkg db/;

		if(s/^Package//){
			@types = qw/pkg/;

lib/ALPM/Conf.pm  view on Meta::CPAN

		}
	}

	# Check for a blank SigLevel
	unless(defined $opt){
		die "SigLevel was empty\n";
	}
	return $opt;
}

sub _addmirror
{
	my($dbs, $url, $sect) = @_;
	die "Section has not previously been declared, cannot set URL\n" unless($sect);

	my $db = _getdb($dbs, $sect);
	push @{$db->{'mirrors'}}, $url;
	return;
}


sub _setopt
{
	my($alpm, $opt, $valstr) = @_;
	no strict 'refs';
	my $meth = *{"ALPM::set_$opt"}{'CODE'};
	die "The ALPM::set_$opt method is missing" unless($meth);

	my @val = ($opt =~ /s$/ ? map { split } $valstr : $valstr);
	return $meth->($alpm, @val);
}

sub _setarch
{
	my($opts) = @_;
	if(!$opts->{'arch'} || $opts->{'arch'} eq 'auto'){
		chomp ($opts->{'arch'} = `uname -m`);
	}
}

sub _expurls
{
	my($urls, $arch, $repo) = @_;
	for(@$urls){
		s/\$arch/$arch/g;
		s/\$repo/$repo/g;
	}
}

sub _applyopts
{
	my($opts, $dbs) = @_;
	my($root, $dbpath) = delete @{$opts}{'root', 'dbpath'};

	unless($root){
		$root = '/';
		unless($dbpath){
			$dbpath = "$root/var/lib/pacman";
			$dbpath =~ tr{/}{/}s;
		}

lib/ALPM/Conf.pm  view on Meta::CPAN


		_expurls($mirs, $opts->{'arch'}, $r);
		$sl = 'default' if(!$usesl);
		my $x = $alpm->register($r, $sl)
			or die "Failed to register $r database: " . $alpm->strerror;
		$x->add_server($_) for(@$mirs);
	}
	return $alpm;
}

sub parse
{
	my($self) = @_;

	my (%opts, @dbs, $currsect, $defsiglvl);
	my %fldhooks = (
		_confhooks(\%opts, \$currsect),
		_nullhooks(@NULL_OPTS),
		'Server'  => sub { _addmirror(\@dbs, shift, $currsect) },
		'Include' => sub {
			die "Cannot have an Include directive in the [options] section\n"
				if($currsect eq 'options');

			# An include directive spawns its own little parser...
			_parse(shift, _mlisthooks(\@dbs, \$currsect));
		},
		'SigLevel' => sub {
			if($currsect eq 'options'){
				$defsiglvl = _parse_siglvl(shift);
			}else{
				_setsiglvl(\@dbs, $currsect, _parse_siglvl(shift));
			}
		},
		($self->{'cfields'} ? %{$self->{'cfields'}} : ()),
	);

	my %hooks = (
		'field' => \%fldhooks,
		'section' => sub { $currsect = shift; }
	);

	_parse($self->{'path'}, \%hooks);
	return _applyopts(\%opts, \@dbs);
}

## Import magic used for quick scripting.
# e.g: perl -MALPM::Conf=/etc/pacman.conf -le 'print $alpm->root'

sub import
{
	my($pkg, $path) = @_;
	my($dest) = caller;
	return unless($path);

	my $conf = $pkg->new($path);
	my $alpm = $conf->parse;
	no strict 'refs';
	*{"${dest}::alpm"} = \$alpm;
	return;

lib/ALPM/Conf.pod  view on Meta::CPAN

ALPM::Conf - pacman.conf config file parser and ALPM loader

=head1 SYNOPSIS

	use ALPM::Conf;	
	my $conf = ALPM::Conf->new('/etc/pacman.conf');
	my $alpm = $conf->parse;
	
	# Try again with custom fields:
	my $value;
	my %fields = ('CustomField' => sub { $value = shift });
	$conf->custom_fields(%fields);
	$alpm = $conf->parse();
	print "$value\n";

	# When imported with an argument, a conf file is loaded and
	# an alpm instance (named $alpm) is imported into the caller's
	# namespace.
	use ALPM::Conf '/etc/pacman.conf';
	print $alpm->get_arch, "\n";

ppport.h  view on Meta::CPAN

  }
  exit 0;
}

# Scan for possible replacement candidates

my(%replace, %need, %hints, %warnings, %depends);
my $replace = 0;
my($hint, $define, $function);

sub find_api
{
  my $code = shift;
  $code =~ s{
    / (?: \*[^*]*\*+(?:[^$ccs][^*]*\*+)* / | /[^\r\n]*)
  | "[^"\\]*(?:\\.[^"\\]*)*"
  | '[^'\\]*(?:\\.[^'\\]*)*' }{}egsx;
  grep { exists $API{$_} } $code =~ /(\w+)/mg;
}

while (<DATA>) {

ppport.h  view on Meta::CPAN

    else {
      my @new = grep { -f } glob $_
          or warn "'$_' does not exist.\n";
      push @files, grep { !$seen{$_}++ } @new;
    }
  }
}
else {
  eval {
    require File::Find;
    File::Find::find(sub {
      $File::Find::name =~ /($srcext)$/i
          and push @files, $File::Find::name;
    }, '.');
  };
  if ($@) {
    @files = map { glob "*$_" } @srcext;
  }
}

if (!@ARGV || $opt{filter}) {

ppport.h  view on Meta::CPAN

  else {
    info("Looks good");
  }
}

close PATCH if $patch_opened;

exit 0;


sub try_use { eval "use @_;"; return $@ eq '' }

sub mydiff
{
  local *F = shift;
  my($file, $str) = @_;
  my $diff;

  if (exists $opt{diff}) {
    $diff = run_diff($opt{diff}, $file, $str);
  }

  if (!defined $diff and try_use('Text::Diff')) {

ppport.h  view on Meta::CPAN

  }

  if (!defined $diff) {
    error("Cannot generate a diff. Please install Text::Diff or use --copy.");
    return;
  }

  print F $diff;
}

sub run_diff
{
  my($prog, $file, $str) = @_;
  my $tmp = 'dppptemp';
  my $suf = 'aaa';
  my $diff = '';
  local *F;

  while (-e "$tmp.$suf") { $suf++ }
  $tmp = "$tmp.$suf";

ppport.h  view on Meta::CPAN


    unlink $tmp;
  }
  else {
    error("Cannot open '$tmp' for writing: $!");
  }

  return undef;
}

sub rec_depend
{
  my($func, $seen) = @_;
  return () unless exists $depends{$func};
  $seen = {%{$seen||{}}};
  return () if $seen->{$func}++;
  my %s;
  grep !$s{$_}++, map { ($_, rec_depend($_, $seen)) } @{$depends{$func}};
}

sub parse_version
{
  my $ver = shift;

  if ($ver =~ /^(\d+)\.(\d+)\.(\d+)$/) {
    return ($1, $2, $3);
  }
  elsif ($ver !~ /^\d+\.[\d_]+$/) {
    die "cannot parse version '$ver'\n";
  }

ppport.h  view on Meta::CPAN


  if ($r < 5 || ($r == 5 && $v < 6)) {
    if ($s % 10) {
      die "cannot parse version '$ver'\n";
    }
  }

  return ($r, $v, $s);
}

sub format_version
{
  my $ver = shift;

  $ver =~ s/$/000000/;
  my($r,$v,$s) = $ver =~ /(\d+)\.(\d{3})(\d{3})/;

  $v = int $v;
  $s = int $s;

  if ($r < 5 || ($r == 5 && $v < 6)) {

ppport.h  view on Meta::CPAN


    $ver = sprintf "%d.%03d", $r, $v;
    $s > 0 and $ver .= sprintf "_%02d", $s;

    return $ver;
  }

  return sprintf "%d.%d.%d", $r, $v, $s;
}

sub info
{
  $opt{quiet} and return;
  print @_, "\n";
}

sub diag
{
  $opt{quiet} and return;
  $opt{diag} and print @_, "\n";
}

sub warning
{
  $opt{quiet} and return;
  print "*** ", @_, "\n";
}

sub error
{
  print "*** ERROR: ", @_, "\n";
}

my %given_hints;
my %given_warnings;
sub hint
{
  $opt{quiet} and return;
  my $func = shift;
  my $rv = 0;
  if (exists $warnings{$func} && !$given_warnings{$func}++) {
    my $warn = $warnings{$func};
    $warn =~ s!^!*** !mg;
    print "*** WARNING: $func\n", $warn;
    $rv++;
  }
  if ($opt{hints} && exists $hints{$func} && !$given_hints{$func}++) {
    my $hint = $hints{$func};
    $hint =~ s/^/   /mg;
    print "   --- hint for $func ---\n", $hint;
  }
  $rv;
}

sub usage
{
  my($usage) = do { local(@ARGV,$/)=($0); <> } =~ /^=head\d$HS+SYNOPSIS\s*^(.*?)\s*^=/ms;
  my %M = ( 'I' => '*' );
  $usage =~ s/^\s*perl\s+\S+/$^X $0/;
  $usage =~ s/([A-Z])<([^>]+)>/$M{$1}$2$M{$1}/g;

  print <<ENDUSAGE;

Usage: $usage

See perldoc $0 for details.

ENDUSAGE

  exit 2;
}

sub strip
{
  my $self = do { local(@ARGV,$/)=($0); <> };
  my($copy) = $self =~ /^=head\d\s+COPYRIGHT\s*^(.*?)^=\w+/ms;
  $copy =~ s/^(?=\S+)/    /gms;
  $self =~ s/^$HS+Do NOT edit.*?(?=^-)/$copy/ms;
  $self =~ s/^SKIP.*(?=^__DATA__)/SKIP
if (\@ARGV && \$ARGV[0] eq '--unstrip') {
  eval { require Devel::PPPort };
  \$@ and die "Cannot require Devel::PPPort, please install.\\n";
  if (eval \$Devel::PPPort::VERSION < $VERSION) {

ppport.h  view on Meta::CPAN

/* Replace: 1 */
#  define PL_ppaddr                 ppaddr
#  define PL_no_modify              no_modify
/* Replace: 0 */
#endif

#if (PERL_BCDVERSION <= 0x5004005)
/* Replace: 1 */
#  define PL_DBsignal               DBsignal
#  define PL_DBsingle               DBsingle
#  define PL_DBsub                  DBsub
#  define PL_DBtrace                DBtrace
#  define PL_Sv                     Sv
#  define PL_bufend                 bufend
#  define PL_bufptr                 bufptr
#  define PL_compiling              compiling
#  define PL_copline                copline
#  define PL_curcop                 curcop
#  define PL_curstash               curstash
#  define PL_debstash               debstash
#  define PL_defgv                  defgv

t/00-ALPM.t  view on Meta::CPAN

	'cachedirs' => [ "$r/cache/" ], # needs trailing slash
	'noupgrades' => [ 'foo' ],
	'noextracts' => [ 'bar' ],
	'ignorepkgs' => [ 'baz' ],
	'ignoregroups' => [ 'core' ],
	'usesyslog' => 0,
	'deltaratio' => 0.5,
	'checkspace' => 1,
);

sub meth
{
	my $name = shift;
	my $m = *{"ALPM::$name"}{CODE} or die "missing $name method";
	my @ret = eval { $m->($alpm, @_) };
	if($@){ die "method call to $name failed: $@" }
	return (wantarray ? @ret : $ret[0]);
}

for $k (sort keys %opts){
	$v = $opts{$k};

t/02-DB.t  view on Meta::CPAN

use Test::More;

use ALPM::Conf 't/test.conf';
ok $alpm;

sub checkpkgs
{
	my $db = shift;
	my $dbname = $db->name;
	my %set = map { ($_ => 1) } @_;
	for my $p ($db->pkgs){
		my $n = $p->name;
		unless(exists $set{$n}){
			fail "unexpected $n package exists in $dbname";
			return;
		}
		delete $set{$n};
	}
	if(keys %set){
		fail "missing packages in $dbname: " . join q{ }, keys %set;
	}else{
		pass "all expected packages exist in $dbname";
	}
}

sub checkdb
{
	my $dbname = shift;
	my $db = $alpm->db($dbname);
	is $db->name, $dbname, 'dbname matches db() arg';
	checkpkgs($db, @_);
}

$db = $alpm->localdb;
is $db->name, 'local';

t/03-Package.t  view on Meta::CPAN

use Test::More;
use ALPM::Conf 't/test.conf';

sub pkgpath
{
	my($dbname, $pkgname) = @_;
	$db = $alpm->db($dbname);
	$db->update or die $alpm->err;
	my($url) = $db->get_servers;
	$pkg = $db->find($pkgname) or die "$dbname/$pkgname package is missing";
	$url .= q{/} . $pkg->filename;
	print "$url\n";
	if(($url =~ s{^file://}{}) != 1){
		die 'package files are not locally hosted as expected';

t/05-Callbacks.t  view on Meta::CPAN

use Test::More;
use ALPM::Conf 't/test.conf';

ok !defined $alpm->get_logcb;
$cb = sub { print "LOG: @_" };
die 'internal error' unless(ref($cb) eq 'CODE');
$alpm->set_logcb($cb);

$tmp = $alpm->get_logcb($cb);
is ref($tmp), 'CODE';
ok $tmp eq $cb;

$alpm->set_logcb(undef);
ok !defined $alpm->get_logcb;

t/preptests.pl  view on Meta::CPAN

use File::Spec::Functions qw(rel2abs catfile);
use File::Basename qw(dirname);

my $PROG = 'preptests';
my $REPODIR = 'repos';

## Variables inside the test.conf need absolute paths, assigned later.
my ($REPOSHARE, $TESTROOT);
my $TESTCONF = 'test.conf';

sub createconf
{
	my($path, $root, $repos) = @_;
	open my $of, '>', $path
		or die "failed to open t/test.conf file: $!";
	print $of <<"END_CONF";
[options]
RootDir = $root
DBPath = $root/db
CacheDir = $root/cache
LogFile = $root/test.log

t/preptests.pl  view on Meta::CPAN

[$repo]
SigLevel = Optional TrustAll
Server = file://$path

END_CONF
	}

	close $of;
}

sub buildpkgs
{
	chdir 'repos' or die "chdir: $!";
	my @lines = `perl package.pl`;
	chdir '..' or die "chdir: $!";

	if(@?){
		printf STDERR "$PROG: package.pl script failed: code %d\n", $? >> 8;
		exit 1;
	}

	my %repos;
	for (@lines){
		chomp;
		my($r, @rest) = split /\t/;
		push @{$repos{$r}}, join "\t", @rest;
	}

	return \%repos;
}

sub remkdir
{
	my($dir) = @_;
	die "WTF?" if($dir eq '/');
	remove_tree($dir);
	mkdir($dir);
	return;
}

sub mkroot
{
	remkdir($TESTROOT);
	my @dirs = glob("$TESTROOT/{gnupg,cache,{db/{local,cache}}}");
	make_path(@dirs, { mode => 0755 });
}

sub corruptpkg
{
	my $fqp = "$REPOSHARE/simpletest/corruptme-1.0-1-any.pkg.tar.xz";
	unlink $fqp or die "unlink: $!";

	open my $fh, '>', $fqp or die "open: $!";
	print $fh "HAHA PWNED!\n";
	close $fh or die "close: $!";

	return;
}

sub buildrepos
{
	my($sharedir) = @_;
	my $repos = buildpkgs();
	my $wd = getcwd();
	chdir($REPODIR) or die "chdir: $!";

	my %paths;
	for my $r (sort keys %$repos){
		my $rd = "$sharedir/$r";
		make_path("$rd/contents");

t/preptests.pl  view on Meta::CPAN

			exit 1;
		}

		$paths{$r} = $rd;
	}

	chdir $wd or die "chdir: $!";
	return \%paths;
}

sub main
{
	chdir(dirname($0)) or die "chdir: $!";

	$REPOSHARE = rel2abs('repos/share');
	$TESTROOT = rel2abs('root');
	unless(-d $REPOSHARE){
		my $repos = buildrepos($REPOSHARE);
		createconf($TESTCONF, $TESTROOT, $repos);
	}

t/repos/package.pl  view on Meta::CPAN

use File::Find qw(find);
use File::Copy qw(copy);
use Cwd qw(getcwd);
use File::stat;

use warnings;
use strict;

our $PROG='t/package.pl';

sub sumfiles
{
	my($pd) = @_;
	my $sum;
	find(sub { $sum += -s $_ if(-f $_ && !/.PKGINFO/); }, $pd);
	return $sum;
}

sub readpi
{
	my($ipath) = @_;
	unless(-f $ipath && -r $ipath){
		print STDERR "$PROG: $ipath is missing.\n";
		exit 1;
	}

	my %pinfo;
	open my $if, '<', $ipath or die "open: $!";
	while(<$if>){
		my ($name, $val) = split / = /;
		my @vals = split /\s+/, $val;
		$pinfo{$name} = \@vals;
	}
	close $if or die "close: $!";
	return \%pinfo;
}

sub writepi
{
	my($pinfo, $ipath) = @_;

	open my $of, '>', $ipath or die "open: $!";
	while(my($k, $v) = each %$pinfo){
		print $of "$k = @$v\n";
	}
	close $of or die "close: $!";
	return;
}

sub updatepi
{
	my($pi, $pd) = @_;
	$pi->{'builddate'} = [ time ];
	$pi->{'size'} = [ sumfiles($pd) ];
	$pi->{'packager'} = [ 'ALPM Module' ];
	return;
}

sub remkdir
{
	my($d) = @_;
	if(-d $d){
		system 'rm' => ('-r', $d);
		if($?){
			printf STDERR "$PROG: rm -r $d failed: error code %d\n", $? >> 8;
			exit 1;
		}
	}
	unless(mkdir $d){
		print STDERR "$PROG: mkdir $d failed: $!\n";
		exit 1;
	}
	return;
}

sub mktmpdir
{
	my($base) = @_;
	remkdir("$base/tmp");
	return "$base/tmp";
}

sub pkgfname
{
	my($pi) = @_;
	return sprintf '%s-%s-%s.pkg.tar.xz',
		map { $_->[0] } @{$pi}{qw/pkgname pkgver arch/};
}

sub buildpkg
{
	my($pi, $pd, $td) = @_;

	my $parentd = dirname($td);
	remkdir($td);
	system 'cp' => ('-R', $pd, $parentd);
	if($?){
		print STDERR "$PROG: failed to cp $pd to $parentd\n";
		exit 1;
	}

t/repos/package.pl  view on Meta::CPAN

	system qq{bsdtar -cf - .PKGINFO * | xz -z > ../$fname};
	if($?){
		printf STDERR "$PROG: xz returned %d\n", $? >> 8;
		exit 1;
	}
	chdir $oldwd or die "chdir: $!";

	return "$parentd/$fname";
}

sub dirsin
{
	my($p) = @_;
	opendir my $dh, $p or die "opendir $p: $!";
	my @dirs = grep { !/^[.]/ && -d "$p/$_" } readdir $dh;
	closedir $dh;
	return @dirs;
}

sub readrepos
{
	my($based) = @_;
	my %rpkgs;
	for my $r (dirsin($based)){
		next if($r eq 'tmp');
		push @{$rpkgs{$r}}, dirsin("$based/$r");
	}
	return \%rpkgs;
}

sub findbuilt
{
	my($pi, $pd, $td) = @_;

	unless(-f "$pd/.PKGINFO"){
		print STDERR "$PROG: $pd/.PKGINFO is missing\n";
		exit 1;
	}

	return undef unless(-d $td);
	my $fname = pkgfname($pi);

t/repos/repoadd.pl  view on Meta::CPAN

#!/usr/bin/env perl

use warnings;
use strict;

my $PROG = 'repoadd.pl';

package PkgFile;

sub fromPath { my $self = bless {}, shift; $self->{'path'} = shift; $self; }

sub info
{
	my($self) = @_;
	return $self->{'info'} if($self->{'info'});

	if(-e '.PKGINFO'){
		print STDERR "PROG: .PKGINFO already exists in current dir, please delete it.\n";
		exit 1;
	}

	my $path = $self->{'path'};

t/repos/repoadd.pl  view on Meta::CPAN

		$name =~ s/^pkg//;
		push @{$pi{$name}}, $val;
	}

	close $if;
	unlink '.PKGINFO';
	$pi{'version'} = delete $pi{'ver'};
	return $self->{'info'} = \%pi;
}

sub fileName
{
	my($self) = @_;
	my $fn = $self->{'path'};
	$fn =~ s{.*/}{};
	return $fn;
}

package DBDir;

our @DescFields = qw{filename name base version desc groups
	csize isize url license arch builddate packager replaces};
our @DepFields = qw/depends provides conflicts optdepends/;

sub fromPath
{
	my $self = bless {}, shift;
	$self->{'dir'} = shift;
	$self;
}

sub writeFile
{
	my($self, $path, $data) = @_;

	open my $of, '>', $path or die "open: $!";
	while(my($k, $v) = each %$data){
		my $str = join "\n", @$v;
		my $uck = uc $k;
		print $of "%$uck%\n$str\n\n";
	}
	close $of or die "close: $!";
	$self;
}

sub addEntry
{
	my($self, $pkg) = @_;

	my $pi = $pkg->info;
	my $name = join q{-}, map { $_->[0] } @{$pi}{qw/name version/};

	my $dir = "$self->{'dir'}/$name";
	if(-d $dir){
		system 'rm' => '-r', "$dir";
		if($?){

t/repos/repoadd.pl  view on Meta::CPAN


	$pi->{'filename'} = [ $pkg->fileName ];
	for my $fld (@DescFields){
		$pi->{$fld} = [] unless($pi->{$fld});
	}
	$self->writeFile("$dir/desc", $pi);
}

package main;

sub usage
{
	print STDERR "usage: $PROG [repo dir path] [package path]\n";
	exit 2;
}

sub main
{
	usage() if(@_ != 2);
	my($dbname, $pkgpath) = @_;

	my $dbdir = "$dbname/contents";
	unless(-d $dbdir){
		print STDERR "$PROG: dir named $dbname must exist in current directory\n";
		exit 1;
	}
	unless(-f $pkgpath){



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