package urpm;
# $Id$
no warnings 'utf8';
use strict;
use File::Find ();
use urpm::msg;
use urpm::download;
use urpm::util;
use urpm::sys;
use urpm::cfg;
use MDV::Distribconf;
our $VERSION = '4.8.23';
our @ISA = qw(URPM);
use URPM;
use URPM::Resolve;
BEGIN {
# this doesn't work for perls >= 5.9.4
if ($ENV{DEBUG_URPMI}) {
require encoding::warnings;
encoding::warnings->import;
}
}
#- this violently overrides is_arch_compat() to always return true.
sub shunt_ignorearch {
eval q( sub URPM::Package::is_arch_compat { 1 } );
}
#- create a new urpm object.
sub new {
my ($class) = @_;
my $self;
$self = bless {
# from URPM
depslist => [],
provides => {},
config => "/etc/urpmi/urpmi.cfg",
skiplist => "/etc/urpmi/skip.list",
instlist => "/etc/urpmi/inst.list",
statedir => "/var/lib/urpmi",
cachedir => "/var/cache/urpmi",
media => undef,
options => {},
#- sync: first argument is options hashref, others are urls to fetch.
sync => sub { $self->sync_webfetch(@_) },
fatal => sub { printf STDERR "%s\n", $_[1]; exit($_[0]) },
error => sub { printf STDERR "%s\n", $_[0] },
log => sub { printf "%s\n", $_[0] },
ui_msg => sub {
$self->{log}($_[0]);
ref $self->{ui} && ref $self->{ui}{msg} and $self->{ui}{msg}->($_[1]);
},
}, $class;
$self->set_nofatal(1);
$self;
}
#- syncing algorithms.
sub sync_webfetch {
my $urpm = shift;
my $options = shift;
my %files;
#- currently ftp and http protocols are managed by curl or wget,
#- ssh and rsync protocols are managed by rsync *AND* ssh.
foreach (@_) {
/^([^:_]*)[^:]*:/ or die N("unknown protocol defined for %s", $_);
push @{$files{$1}}, $_;
}
if ($files{removable} || $files{file}) {
eval {
sync_file($options, @{$files{removable} || []}, @{$files{file} || []});
};
$urpm->{fatal}(10, $@) if $@;
delete @files{qw(removable file)};
}
for my $cpt (qw(wget-options curl-options rsync-options)) {
$options->{$cpt} = $urpm->{options}{$cpt} if defined $urpm->{options}{$cpt};
}
if ($files{ftp} || $files{http} || $files{https}) {
my @webfetch = qw(curl wget);
my @available_webfetch = grep { -x "/usr/bin/$_" || -x "/bin/$_" } @webfetch;
#- use user default downloader if provided and available
my $option_downloader = $urpm->{options}{downloader}; #- cmd-line switch
if (!$option_downloader && $options->{media}) { #- per-media config
(my $m) = grep { $_->{name} eq $options->{media} } @{$urpm->{media}};
ref $m && $m->{downloader} and $option_downloader = $m->{downloader};
}
#- global config
!$option_downloader && exists $urpm->{global_config}{downloader}
and $option_downloader = $urpm->{global_config}{downloader};
my ($preferred) = grep { $_ eq $option_downloader } @available_webfetch;
#- else first downloader of @webfetch is the default one
$preferred ||= $available_webfetch[0];
if ($option_downloader ne $preferred && $option_downloader && !our $webfetch_not_available) {
$urpm->{log}(N("%s is not available, falling back on %s", $option_downloader, $preferred));
$webfetch_not_available = 1;
}
if ($preferred eq 'curl') {
sync_curl($options, @{$files{ftp} || []}, @{$files{http} || []}, @{$files{https} || []});
} elsif ($preferred eq 'wget') {
sync_wget($options, @{$files{ftp} || []}, @{$files{http} || []}, @{$files{https} || []});
} else {
die N("no webfetch found, supported webfetch are: %s\n", join(", ", @webfetch));
}
delete @files{qw(ftp http https)};
}
if ($files{rsync}) {
sync_rsync($options, @{$files{rsync} || []});
delete $files{rsync};
}
if ($files{ssh}) {
my @ssh_files;
foreach (@{$files{ssh} || []}) {
m|^ssh://([^/]*)(.*)| and push @ssh_files, "$1:$2";
}
sync_ssh($options, @ssh_files);
delete $files{ssh};
}
%files and die N("unable to handle protocol: %s", join ', ', keys %files);
}
our @PER_MEDIA_OPT = qw(
downloader
hdlist
ignore
key-ids
list
md5sum
noreconfigure
priority
removable
static
synthesis
update
verify-rpm
virtual
with_hdlist
);
#- Loads /etc/urpmi/urpmi.cfg and performs basic checks.
#- Does not handle old format: <name> <url> [with <path_hdlist>]
#- options :
#- - nocheck_access : don't check presence of hdlist and other files
sub read_config {
my ($urpm, %options) = @_;
return if $urpm->{media}; #- media already loaded
$urpm->{media} = [];
my $config = urpm::cfg::load_config($urpm->{config})
or $urpm->{fatal}(6, $urpm::cfg::err);
#- global options
if ($config->{''}) {
foreach my $opt (qw(
allow-force
allow-nodeps
auto
compress
downloader
default-media
excludedocs
excludepath
fuzzy
ignoresize
keep
key-ids
limit-rate
nopubkey
norebuild
post-clean
pre-clean
priority-upgrade
prohibit-remove
repackage
resume
retry
split-length
split-level
strict-arch
verify-rpm
curl-options
rsync-options
wget-options
)) {
if (defined $config->{''}{$opt} && !exists $urpm->{options}{$opt}) {
$urpm->{options}{$opt} = $config->{''}{$opt};
}
}
}
#- per-media options
foreach my $m (grep { $_ ne '' } keys %$config) {
my $medium = { name => $m, clear_url => $config->{$m}{url} };
foreach my $opt (@PER_MEDIA_OPT) {
defined $config->{$m}{$opt} and $medium->{$opt} = $config->{$m}{$opt};
}
$urpm->probe_medium($medium, %options) and push @{$urpm->{media}}, $medium;
}
eval { require urpm::ldap; urpm::ldap::load_ldap_media($urpm, %options) };
#- load default values
foreach (qw(post-clean verify-rpm)) {
exists $urpm->{options}{$_} or $urpm->{options}{$_} = 1;
}
$urpm->{media} = [ sort { $a->{priority} <=> $b->{priority} } @{$urpm->{media}} ];
#- remember if an hdlist or list file is already used
my %filelists;
foreach (@{$urpm->{media}}) {
foreach my $filetype (qw(hdlist list)) {
if ($_->{$filetype}) {
exists($filelists{$filetype}{$_->{$filetype}})
and $_->{ignore} = 1,
$urpm->{error}(
$filetype eq 'hdlist'
? N("medium \"%s\" trying to use an already used hdlist, medium ignored", $_->{name})
: N("medium \"%s\" trying to use an already used list, medium ignored", $_->{name})
);
$filelists{$filetype}{$_->{$filetype}} = undef;
}
}
}
#- check the presence of hdlist and list files if necessary.
unless ($options{nocheck_access}) {
foreach (@{$urpm->{media}}) {
$_->{ignore} and next;
-r "$urpm->{statedir}/$_->{hdlist}" || -r "$urpm->{statedir}/synthesis.$_->{hdlist}" && $_->{synthesis}
or $_->{ignore} = 1,
$urpm->{error}(N("unable to access hdlist file of \"%s\", medium ignored", $_->{name}));
$_->{list} && -r "$urpm->{statedir}/$_->{list}" || defined $_->{url}
or $_->{ignore} = 1,
$urpm->{error}(N("unable to access list file of \"%s\", medium ignored", $_->{name}));
}
}
#- read MD5 sums (usually not in urpmi.cfg but in a separate file)
my $md5sum = $urpm->open_safe("<", "$urpm->{statedir}/MD5SUM");
if ($md5sum) {
local $_;
while (<$md5sum>) {
|