use
Carp
qw(carp croak confess)
;
our
$VERSION
=
'2.01'
;
sub
AUTOLOAD {
my
$constname
;
our
$AUTOLOAD
;
(
$constname
=
$AUTOLOAD
) =~ s/.*:://;
croak
"&ALPM::constant not defined"
if
$constname
eq
'constant'
;
my
(
$error
,
$val
) = constant(
$constname
);
if
(
$error
) { croak
$error
; }
{
no
strict
'refs'
;
*$AUTOLOAD
=
sub
{
$val
};
}
goto
&$AUTOLOAD
;
}
XSLoader::load(
'ALPM'
,
$VERSION
);
our
$_Transaction
;
our
@GET_SET_OPTS
=
qw{ root dbpath cachedirs logfile usesyslog
noupgrades noextracts ignorepkgs ignoregrps
logcb dlcb totaldlcb fetchcb usedelta arch }
;
our
%_IS_SETOPTION
= (
map
{ (
$_
=> 1 ) }
@GET_SET_OPTS
);
our
%_IS_GETOPTION
= (
map
{ (
$_
=> 1 ) }
@GET_SET_OPTS
,
qw/ lockfile localdb syncdbs /
);
our
%_TRANS_FLAGS
= (
'nodeps'
=> PM_TRANS_FLAG_NODEPS(),
'force'
=> PM_TRANS_FLAG_FORCE(),
'nosave'
=> PM_TRANS_FLAG_NOSAVE(),
'nodepver'
=> PM_TRANS_FLAG_NODEPVERSION(),
'cascade'
=> PM_TRANS_FLAG_CASCADE(),
'recurse'
=> PM_TRANS_FLAG_RECURSE(),
'dbonly'
=> PM_TRANS_FLAG_DBONLY(),
'alldeps'
=> PM_TRANS_FLAG_ALLDEPS(),
'dlonly'
=> PM_TRANS_FLAG_DOWNLOADONLY(),
'noscriptlet'
=> PM_TRANS_FLAG_NOSCRIPTLET(),
'noconflicts'
=> PM_TRANS_FLAG_NOCONFLICTS(),
'needed'
=> PM_TRANS_FLAG_NEEDED(),
'allexplicit'
=> PM_TRANS_FLAG_ALLEXPLICIT(),
'unneeded'
=> PM_TRANS_FLAG_UNNEEDED(),
'recurseall'
=> PM_TRANS_FLAG_RECURSEALL(),
'nolock'
=> PM_TRANS_FLAG_NOLOCK(),
);
_initialize();
END { _release() };
sub
import
{
croak
'Invalid arguments to import function'
if
(
@_
== 0 );
return
if
(
@_
== 1 );
my
(
$class
) =
shift
;
if
(
@_
== 1) {
my
$arg
=
shift
;
croak
<<'END_ERROR' if ( ref $arg );
A single argument to ALPM's import must be a hash or a path to a
pacman.conf file
END_ERROR
$class
->load_config(
$arg
);
return
;
}
croak
q{Multiple options to ALPM's import must be a hash}
unless
(
@_
% 2 == 0 );
$class
->set_options(
@_
);
return
;
}
sub
get_opt
{
croak
'Invalid arguments to get_opt'
if
(
@_
!= 2 );
my
(
$class
,
$optname
) =
@_
;
croak
'Option name must be provided'
unless
defined
$optname
;
croak
qq{Unknown libalpm option "$optname"}
unless
(
$_IS_GETOPTION
{
$optname
} );
my
$method_name
=
"alpm_option_get_$optname"
;
my
$func_ref
=
$ALPM::
{
$method_name
};
die
"Internal error: $method_name should be defined in ALPM.xs"
unless
defined
$func_ref
;
my
$result
=
eval
{
$func_ref
->() };
if
(
$EVAL_ERROR
) {
croak $1
if
(
$EVAL_ERROR
=~ /^(ALPM .*) at .*? line \d+[.]$/ );
croak
$EVAL_ERROR
;
}
return
$result
;
}
sub
set_opt
{
croak
'Not enough arguments to set_opt'
if
(
@_
< 3 );
my
(
$class
,
$optname
,
$optval
) =
@_
;
croak
'Option name must be provided'
unless
defined
$optname
;
$optname
=
lc
$optname
;
unless
(
$_IS_SETOPTION
{
$optname
} ) {
carp
qq{Given option "$optname" is not settable or unknown}
;
return
;
}
my
$method_name
=
"alpm_option_set_$optname"
;
my
$func_ref
=
$ALPM::
{
$method_name
};
die
"Internal error: $method_name should be defined in ALPM.xs"
unless
defined
$func_ref
;
my
$func_arg
;
if
(
substr
(
$optname
, -1 ) eq
's'
) {
$func_arg
= ( !
defined
$optval
? [ ]
:
ref
$optval
eq
'ARRAY'
?
$optval
: ( [
$optval
,
@_
[ 3 ..
$#_
] ] ));
}
else
{
$func_arg
=
$optval
;
}
eval
{
$func_ref
->(
$func_arg
) };
if
(
$EVAL_ERROR
) {
$EVAL_ERROR
=~ s/ at .*? line \d+[.]\n//;
croak
$EVAL_ERROR
;
}
}
sub
get_options
{
my
$class
=
shift
;
if
(
@_
== 0 ) {
return
%{
$class
->get_options_ref};
}
return
@{
$class
->get_options_ref(
@_
)};
}
sub
get_options_ref
{
my
$class
=
shift
;
return
[
map
{
$class
->get_opt(
$_
) }
@_
]
if
(
@_
> 0 );
my
$opts
= {};
for
my
$optname
(
keys
%_IS_GETOPTION
) {
$opts
->{
$optname
} =
$class
->get_opt(
$optname
);
}
return
$opts
;
}
sub
set_options
{
croak
'Invalid arguments to set_options'
if
@_
< 2;
my
$class
=
shift
;
my
%options
;
if
(
@_
% 2 == 0 ) {
%options
=
@_
; }
else
{
eval
{
%options
= %{
shift
()} }
or croak
'Argument to set_options must be either a hash or hashref'
;
}
for
my
$optname
(
keys
%options
) {
eval
{
$class
->set_opt(
$optname
,
$options
{
$optname
} ) };
if
(
$EVAL_ERROR
) {
$EVAL_ERROR
=~ s/ at .*? line \d+\n//;
croak
"$EVAL_ERROR (for $optname)"
;
}
}
return
1;
}
sub
register
{
my
$class
=
shift
;
croak
'Supply a repository name and a base URL to start it at'
if
@_
!= 2;
my
(
$sync_name
,
$sync_url
) =
@_
;
croak
'You must supply a URL for the database'
unless
$sync_url
;
$sync_url
=~ s/\
$repo
\b/
$sync_name
/g;
if
(
$sync_url
=~ /\
$arch
\b/ ) {
my
$arch
= ALPM->get_opt(
'arch'
);
if
( !
$arch
||
$arch
eq
'auto'
) {
chomp
(
$arch
= `uname -m` );
die
'Failed to call uname to expand $arch'
if
$? != 0
}
$sync_url
=~ s/\
$arch
\b/
$arch
/g;
}
my
$new_db
= _db_register_sync(
$sync_name
);
$new_db
->add_url(
$sync_url
);
return
$new_db
;
}
sub
localdb
{
my
$class
=
shift
;
return
$class
->get_opt(
'localdb'
);
}
sub
syncdbs
{
my
$class
=
shift
;
return
@{
$class
->get_opt(
'syncdbs'
) };
}
sub
dbs
{
my
$class
=
shift
;
return
(
$class
->localdb,
$class
->syncdbs );
}
sub
db
{
croak
'Not enough arguments to ALPM::repodb()'
if
(
@_
< 2 );
my
(
$class
,
$repo_name
) =
@_
;
my
(
$found
) =
grep
{
$_
->name eq
$repo_name
}
$class
->dbs;
return
$found
;
}
sub
search
{
my
(
$class
,
@search_strs
) =
@_
;
return
(
map
{
$_
->search(
@search_strs
) }
$class
->databases );
}
sub
unregister_all_dbs
{
_db_unregister_all();
}
sub
load_config
{
my
(
$class
,
$cfg_path
) =
@_
;
my
$loader
= ALPM::LoadConfig->new;
eval
{
$loader
->load_file(
$cfg_path
) };
croak
$EVAL_ERROR
.
"Config file parse error"
if
(
$EVAL_ERROR
);
return
1;
}
sub
load_pkgfile
{
croak
'load_pkgfile() must have at least a filename as argument'
if
(
@_
< 1 );
if
(
eval
{
$_
[0]->isa( __PACKAGE__ ) } ) {
shift
@_
;
}
my
$package_path
=
shift
;
my
$pkgobj
=
eval
{ _pkg_load(
$package_path
) };
return
$pkgobj
unless
$@;
$@ =~ s/ at .*? line \d+[.]\n\z//;
croak $@;
}
sub
trans
{
croak
'trans() must be called as a class method'
unless
(
@_
);
my
$class
=
shift
;
croak
'arguments to trans method must be a hash'
unless
(
@_
% 2 == 0 );
my
%trans_opts
=
@_
;
my
$trans_flags
= 0;
if
(
exists
$trans_opts
{flags} ) {
for
my
$flag
(
split
/\s+/,
$trans_opts
{flags} ) {
croak
qq{unknown transaction flag "$flag"}
unless
exists
$_TRANS_FLAGS
{
$flag
};
$trans_flags
|=
$_TRANS_FLAGS
{
$flag
};
}
}
eval
{
_trans_init(
$trans_flags
,
$trans_opts
{event},
$trans_opts
{conv},
$trans_opts
{progress});
};
if
(
$EVAL_ERROR
) {
die
"$EVAL_ERROR\n"
unless
(
$EVAL_ERROR
=~ /\AALPM Error:/ );
$EVAL_ERROR
=~ s/ at .*? line \d+[.]\n//;
croak
$EVAL_ERROR
;
}
my
$t
= ALPM::Transaction->new(
%trans_opts
);
$_Transaction
=
$t
;
weaken
$_Transaction
;
return
$t
;
}
my
@_OPT_NAMES
=
sort
keys
%ALPM::_IS_GETOPTION
;
sub
TIEHASH
{
my
$class
=
shift
;
bless
{
'KEY_ITER'
=> 0 },
$class
;
}
sub
DESTROY
{
1;
}
sub
EXISTS
{
return
exists
$ALPM::_IS_GETOPTION
{
$_
[1] };
}
sub
DELETE
{
my
(
$self
,
$key
) =
@_
;
$self
->set_opt(
$key
,
undef
);
}
sub
CLEAR
{
croak
'You cannot empty this tied hash'
;
}
sub
FETCH
{
my
(
$self
,
$key
) =
@_
;
return
$self
->get_opt(
$key
);
}
sub
STORE
{
my
(
$self
,
$key
,
$value
) =
@_
;
return
$self
->set_opt(
$key
,
$value
);
}
sub
FIRSTKEY
{
my
(
$self
) =
@_
;
$self
->{KEY_ITER} = 1;
return
$_OPT_NAMES
[0];
}
sub
NEXTKEY
{
my
(
$self
) =
@_
;
return
(
$self
->{KEY_ITER} <
scalar
@_OPT_NAMES
?
$_OPT_NAMES
[
$self
->{KEY_ITER}++ ]
:
undef
);
}
1;