diff options
-rwxr-xr-x | gurpmi2 | 5 | ||||
-rw-r--r-- | urpm.pm | 209 | ||||
-rw-r--r-- | urpm/get_pkgs.pm | 218 | ||||
-rwxr-xr-x | urpmi | 5 | ||||
-rwxr-xr-x | urpmq | 5 |
5 files changed, 229 insertions, 213 deletions
@@ -15,6 +15,7 @@ use gurpmi; use urpm::install; use urpm::media; use urpm::signature; +use urpm::get_pkgs; use Gtk2; #- GUI globals @@ -210,7 +211,7 @@ sub do_install_2 () { sub do_install_3 () { wait_label(N("Package installation...")); - my ($local_sources, $list) = $urpm->get_source_packages($state->{selected}); + my ($local_sources, $list) = urpm::get_pkgs::selected2list($urpm, $state->{selected}); $local_sources || $list or $urpm->{fatal}(3, N("unable to get source packages, aborting")); my %sources = %$local_sources; my %error_sources; @@ -240,7 +241,7 @@ sub do_install_3 () { foreach my $set (@{$state->{transaction} || []}) { my (@transaction_list, %transaction_sources); urpm::install::prepare_transaction($urpm, $set, $list, \%sources, \@transaction_list, \%transaction_sources); - $urpm->download_packages_of_distant_media( + urpm::get_pkgs::download_packages_of_distant_media($urpm, \@transaction_list, \%transaction_sources, \%error_sources, @@ -369,146 +369,6 @@ sub resolve_dependencies { $need_restart; } -#- select sources for selected packages, -#- according to keys of the packages hash. -#- returns a list of lists containing the source description for each rpm, -#- matching the exact number of registered media; ignored media being -#- associated to a null list. -sub get_source_packages { - my ($urpm, $packages, %options) = @_; - my (%protected_files, %local_sources, %fullname2id); - - #- build association hash to retrieve id and examine all list files. - foreach (keys %$packages) { - foreach (split /\|/, $_) { - if ($urpm->{source}{$_}) { - $protected_files{$local_sources{$_} = $urpm->{source}{$_}} = undef; - } else { - $fullname2id{$urpm->{depslist}[$_]->fullname} = $_ . ''; - } - } - } - - #- examine each medium to search for packages. - #- now get rpm file name in hdlist to match list file. - my %file2fullnames; - foreach my $pkg (@{$urpm->{depslist} || []}) { - $file2fullnames{$pkg->filename}{$pkg->fullname} = undef; - } - - #- examine the local repository, which is trusted (no gpg or pgp signature check but md5 is now done). - my $dh = urpm::sys::opendir_safe($urpm, "$urpm->{cachedir}/rpms"); - if ($dh) { - while (defined(my $filename = readdir $dh)) { - my $filepath = "$urpm->{cachedir}/rpms/$filename"; - if (-d $filepath) { - } elsif ($options{clean_all} || ! -s _) { - unlink $filepath; #- this file should be removed or is already empty. - } else { - if (keys(%{$file2fullnames{$filename} || {}}) > 1) { - $urpm->{error}(N("there are multiple packages with the same rpm filename \"%s\"", $filename)); - } elsif (keys(%{$file2fullnames{$filename} || {}}) == 1) { - my ($fullname) = keys(%{$file2fullnames{$filename} || {}}); - if (defined(my $id = delete $fullname2id{$fullname})) { - $local_sources{$id} = $filepath; - } else { - $options{clean_other} && ! exists $protected_files{$filepath} and unlink $filepath; - } - } else { - $options{clean_other} && ! exists $protected_files{$filepath} and unlink $filepath; - } - } - } - closedir $dh; - } - - if ($options{clean_all}) { - #- clean download directory, do it here even if this is not the best moment. - urpm::sys::clean_dir("$urpm->{cachedir}/partial"); - } - - my ($error, @list_error, @list, %examined); - - foreach my $medium (@{$urpm->{media} || []}) { - my (%sources, %list_examined, $list_warning); - - if (urpm::media::is_valid_medium($medium) && !$medium->{ignore}) { - #- always prefer a list file if available. - if ($medium->{list}) { - if (-r urpm::media::statedir_list($urpm, $medium)) { - foreach (cat_(urpm::media::statedir_list($urpm, $medium))) { - chomp; - if (my ($filename) = m!([^/]*\.rpm)$!) { - if (keys(%{$file2fullnames{$filename} || {}}) > 1) { - $urpm->{error}(N("there are multiple packages with the same rpm filename \"%s\"", $filename)); - next; - } elsif (keys(%{$file2fullnames{$filename} || {}}) == 1) { - my ($fullname) = keys(%{$file2fullnames{$filename} || {}}); - if (defined(my $id = $fullname2id{$fullname})) { - if (!/\.delta\.rpm$/ || $urpm->is_delta_installable($urpm->{depslist}[$id], $options{root})) { - $sources{$id} = "$medium->{url}/$filename"; - } - } - $list_examined{$fullname} = $examined{$fullname} = undef; - } - } else { - chomp; - $error = 1; - $urpm->{error}(N("unable to correctly parse [%s] on value \"%s\"", urpm::media::statedir_list($urpm, $medium), $_)); - last; - } - } - } else { - # list file exists but isn't readable - # report error only if no result found, list files are only readable by root - push @list_error, N("unable to access list file of \"%s\", medium ignored", $medium->{name}); - $< and push @list_error, " " . N("(retry as root?)"); - next; - } - } - if (defined $medium->{url}) { - foreach ($medium->{start} .. $medium->{end}) { - my $pkg = $urpm->{depslist}[$_]; - my $fi = $pkg->filename; - if (keys(%{$file2fullnames{$fi} || {}}) > 1) { - $urpm->{error}(N("there are multiple packages with the same rpm filename \"%s\"", $fi)); - next; - } elsif (keys(%{$file2fullnames{$fi} || {}}) == 1) { - my ($fullname) = keys(%{$file2fullnames{$fi} || {}}); - unless (exists($list_examined{$fullname})) { - ++$list_warning; - if (defined(my $id = $fullname2id{$fullname})) { - if ($fi !~ /\.delta\.rpm$/ || $urpm->is_delta_installable($urpm->{depslist}[$id], $options{root})) { - $sources{$id} = "$medium->{url}/" . $fi; - } - } - $examined{$fullname} = undef; - } - } - } - $list_warning && $medium->{list} && -r urpm::media::statedir_list($urpm, $medium) && -f _ - and $urpm->{error}(N("medium \"%s\" uses an invalid list file: - mirror is probably not up-to-date, trying to use alternate method", $medium->{name})); - } elsif (!%list_examined) { - $error = 1; - $urpm->{error}(N("medium \"%s\" does not define any location for rpm files", $medium->{name})); - } - } - push @list, \%sources; - } - - #- examine package list to see if a package has not been found. - foreach (grep { ! exists($examined{$_}) } keys %fullname2id) { - # print list errors only once if any - $urpm->{error}($_) foreach @list_error; - @list_error = (); - $error = 1; - $urpm->{error}(N("package %s is not found.", $_)); - } - - $error ? @{[]} : (\%local_sources, \@list); -} - #- checks whether the delta RPM represented by $pkg is installable wrt the #- RPM DB on $root. For this, it extracts the rpm version to which the #- delta applies from the delta rpm filename itself. So naming conventions @@ -534,9 +394,10 @@ sub download_source_packages { my %sources = %$local_sources; my %error_sources; + require urpm::get_pkgs; urpm::sys::lock_urpmi_db($urpm, 'exclusive') if !$options{nolock}; urpm::removable::copy_packages_of_removable_media($urpm, $list, \%sources, $options{ask_for_medium}) or return; - $urpm->download_packages_of_distant_media($list, \%sources, \%error_sources, %options); + urpm::get_pkgs::download_packages_of_distant_media($urpm, $list, \%sources, \%error_sources, %options); urpm::sys::unlock_urpmi_db($urpm) unless $options{nolock}; %sources, %error_sources; @@ -548,72 +409,6 @@ sub exlock_urpmi_db { urpm::sys::lock_urpmi_db($urpm, 'exclusive'); } -# TODO verify that files are downloaded from the right corresponding media -#- options: quiet, callback, -sub download_packages_of_distant_media { - my ($urpm, $list, $sources, $error_sources, %options) = @_; - - #- get back all ftp and http accessible rpm files into the local cache - foreach my $n (0..$#$list) { - my %distant_sources; - - #- ignore media that contain nothing for the current set of files - values %{$list->[$n]} or next; - - #- examine all files to know what can be indexed on multiple media. - while (my ($i, $url) = each %{$list->[$n]}) { - #- the given URL is trusted, so the file can safely be ignored. - defined $sources->{$i} and next; - my $local_file = file_from_local_url($url); - if ($local_file && $local_file =~ /\.rpm$/) { - if (-r $local_file) { - $sources->{$i} = $local_file; - } else { - $error_sources->{$i} = $local_file; - } - } elsif ($url =~ m!^([^:]*):/(.*/([^/]*\.rpm))\Z!) { - $distant_sources{$i} = "$1:/$2"; #- will download now - } else { - $urpm->{error}(N("malformed URL: [%s]", $url)); - } - } - - #- download files from the current medium. - if (%distant_sources) { - $urpm->{log}(N("retrieving rpm files from medium \"%s\"...", $urpm->{media}[$n]{name})); - if (urpm::download::sync($urpm, $urpm->{media}[$n], [ values %distant_sources ], - quiet => $options{quiet}, resume => $urpm->{options}{resume}, callback => $options{callback})) { - $urpm->{log}(N("...retrieving done")); - } else { - $urpm->{error}(N("...retrieving failed: %s", $@)); - } - #- clean files that have not been downloaded, but keep in mind - #- there have been problems downloading them at least once, this - #- is necessary to keep track of failing downloads in order to - #- present the error to the user. - foreach my $i (keys %distant_sources) { - my ($filename) = $distant_sources{$i} =~ m|/([^/]*\.rpm)$|; - if ($filename && -s "$urpm->{cachedir}/partial/$filename" && - URPM::verify_rpm("$urpm->{cachedir}/partial/$filename", nosignatures => 1)) - { - #- it seems the the file has been downloaded correctly and has been checked to be valid. - unlink "$urpm->{cachedir}/rpms/$filename"; - urpm::util::move("$urpm->{cachedir}/partial/$filename", "$urpm->{cachedir}/rpms/$filename"); - -r "$urpm->{cachedir}/rpms/$filename" and $sources->{$i} = "$urpm->{cachedir}/rpms/$filename"; - } - unless ($sources->{$i}) { - $error_sources->{$i} = $distant_sources{$i}; - } - } - } - } - - #- clean failed download which have succeeded. - delete @$error_sources{keys %$sources}; - - 1; -} - #- extract package that should be installed instead of upgraded, #- sources is a hash of id -> source rpm filename. sub extract_packages_to_install { diff --git a/urpm/get_pkgs.pm b/urpm/get_pkgs.pm new file mode 100644 index 00000000..29a3ce1f --- /dev/null +++ b/urpm/get_pkgs.pm @@ -0,0 +1,218 @@ +package urpm::get_pkgs; + +# $Id$ + +use urpm::msg; +use urpm::sys; +use urpm::util; +use urpm::media; +use urpm 'file_from_local_url'; + + +#- select sources for selected packages, +#- according to keys of the packages hash. +#- returns a list of lists containing the source description for each rpm, +#- matching the exact number of registered media; ignored media being +#- associated to a null list. +sub selected2list { + my ($urpm, $packages, %options) = @_; + my (%protected_files, %local_sources, %fullname2id); + + #- build association hash to retrieve id and examine all list files. + foreach (keys %$packages) { + foreach (split /\|/, $_) { + if ($urpm->{source}{$_}) { + $protected_files{$local_sources{$_} = $urpm->{source}{$_}} = undef; + } else { + $fullname2id{$urpm->{depslist}[$_]->fullname} = $_ . ''; + } + } + } + + #- examine each medium to search for packages. + #- now get rpm file name in hdlist to match list file. + my %file2fullnames; + foreach my $pkg (@{$urpm->{depslist} || []}) { + $file2fullnames{$pkg->filename}{$pkg->fullname} = undef; + } + + #- examine the local repository, which is trusted (no gpg or pgp signature check but md5 is now done). + my $dh = urpm::sys::opendir_safe($urpm, "$urpm->{cachedir}/rpms"); + if ($dh) { + while (defined(my $filename = readdir $dh)) { + my $filepath = "$urpm->{cachedir}/rpms/$filename"; + if (-d $filepath) { + } elsif ($options{clean_all} || ! -s _) { + unlink $filepath; #- this file should be removed or is already empty. + } else { + if (keys(%{$file2fullnames{$filename} || {}}) > 1) { + $urpm->{error}(N("there are multiple packages with the same rpm filename \"%s\"", $filename)); + } elsif (keys(%{$file2fullnames{$filename} || {}}) == 1) { + my ($fullname) = keys(%{$file2fullnames{$filename} || {}}); + if (defined(my $id = delete $fullname2id{$fullname})) { + $local_sources{$id} = $filepath; + } else { + $options{clean_other} && ! exists $protected_files{$filepath} and unlink $filepath; + } + } else { + $options{clean_other} && ! exists $protected_files{$filepath} and unlink $filepath; + } + } + } + closedir $dh; + } + + if ($options{clean_all}) { + #- clean download directory, do it here even if this is not the best moment. + urpm::sys::clean_dir("$urpm->{cachedir}/partial"); + } + + my ($error, @list_error, @list, %examined); + + foreach my $medium (@{$urpm->{media} || []}) { + my (%sources, %list_examined, $list_warning); + + if (urpm::media::is_valid_medium($medium) && !$medium->{ignore}) { + #- always prefer a list file if available. + if ($medium->{list}) { + if (-r urpm::media::statedir_list($urpm, $medium)) { + foreach (cat_(urpm::media::statedir_list($urpm, $medium))) { + chomp; + if (my ($filename) = m!([^/]*\.rpm)$!) { + if (keys(%{$file2fullnames{$filename} || {}}) > 1) { + $urpm->{error}(N("there are multiple packages with the same rpm filename \"%s\"", $filename)); + next; + } elsif (keys(%{$file2fullnames{$filename} || {}}) == 1) { + my ($fullname) = keys(%{$file2fullnames{$filename} || {}}); + if (defined(my $id = $fullname2id{$fullname})) { + if (!/\.delta\.rpm$/ || $urpm->is_delta_installable($urpm->{depslist}[$id], $options{root})) { + $sources{$id} = "$medium->{url}/$filename"; + } + } + $list_examined{$fullname} = $examined{$fullname} = undef; + } + } else { + chomp; + $error = 1; + $urpm->{error}(N("unable to correctly parse [%s] on value \"%s\"", urpm::media::statedir_list($urpm, $medium), $_)); + last; + } + } + } else { + # list file exists but isn't readable + # report error only if no result found, list files are only readable by root + push @list_error, N("unable to access list file of \"%s\", medium ignored", $medium->{name}); + $< and push @list_error, " " . N("(retry as root?)"); + next; + } + } + if (defined $medium->{url}) { + foreach ($medium->{start} .. $medium->{end}) { + my $pkg = $urpm->{depslist}[$_]; + my $fi = $pkg->filename; + if (keys(%{$file2fullnames{$fi} || {}}) > 1) { + $urpm->{error}(N("there are multiple packages with the same rpm filename \"%s\"", $fi)); + next; + } elsif (keys(%{$file2fullnames{$fi} || {}}) == 1) { + my ($fullname) = keys(%{$file2fullnames{$fi} || {}}); + unless (exists($list_examined{$fullname})) { + ++$list_warning; + if (defined(my $id = $fullname2id{$fullname})) { + if ($fi !~ /\.delta\.rpm$/ || $urpm->is_delta_installable($urpm->{depslist}[$id], $options{root})) { + $sources{$id} = "$medium->{url}/" . $fi; + } + } + $examined{$fullname} = undef; + } + } + } + $list_warning && $medium->{list} && -r urpm::media::statedir_list($urpm, $medium) && -f _ + and $urpm->{error}(N("medium \"%s\" uses an invalid list file: + mirror is probably not up-to-date, trying to use alternate method", $medium->{name})); + } elsif (!%list_examined) { + $error = 1; + $urpm->{error}(N("medium \"%s\" does not define any location for rpm files", $medium->{name})); + } + } + push @list, \%sources; + } + + #- examine package list to see if a package has not been found. + foreach (grep { ! exists($examined{$_}) } keys %fullname2id) { + # print list errors only once if any + $urpm->{error}($_) foreach @list_error; + @list_error = (); + $error = 1; + $urpm->{error}(N("package %s is not found.", $_)); + } + + $error ? @{[]} : (\%local_sources, \@list); +} + +# TODO verify that files are downloaded from the right corresponding media +#- options: quiet, callback, +sub download_packages_of_distant_media { + my ($urpm, $list, $sources, $error_sources, %options) = @_; + + #- get back all ftp and http accessible rpm files into the local cache + foreach my $n (0..$#$list) { + my %distant_sources; + + #- ignore media that contain nothing for the current set of files + values %{$list->[$n]} or next; + + #- examine all files to know what can be indexed on multiple media. + while (my ($i, $url) = each %{$list->[$n]}) { + #- the given URL is trusted, so the file can safely be ignored. + defined $sources->{$i} and next; + my $local_file = file_from_local_url($url); + if ($local_file && $local_file =~ /\.rpm$/) { + if (-r $local_file) { + $sources->{$i} = $local_file; + } else { + $error_sources->{$i} = $local_file; + } + } elsif ($url =~ m!^([^:]*):/(.*/([^/]*\.rpm))\Z!) { + $distant_sources{$i} = "$1:/$2"; #- will download now + } else { + $urpm->{error}(N("malformed URL: [%s]", $url)); + } + } + + #- download files from the current medium. + if (%distant_sources) { + $urpm->{log}(N("retrieving rpm files from medium \"%s\"...", $urpm->{media}[$n]{name})); + if (urpm::download::sync($urpm, $urpm->{media}[$n], [ values %distant_sources ], + quiet => $options{quiet}, resume => $urpm->{options}{resume}, callback => $options{callback})) { + $urpm->{log}(N("...retrieving done")); + } else { + $urpm->{error}(N("...retrieving failed: %s", $@)); + } + #- clean files that have not been downloaded, but keep in mind + #- there have been problems downloading them at least once, this + #- is necessary to keep track of failing downloads in order to + #- present the error to the user. + foreach my $i (keys %distant_sources) { + my ($filename) = $distant_sources{$i} =~ m|/([^/]*\.rpm)$|; + if ($filename && -s "$urpm->{cachedir}/partial/$filename" && + URPM::verify_rpm("$urpm->{cachedir}/partial/$filename", nosignatures => 1)) + { + #- it seems the the file has been downloaded correctly and has been checked to be valid. + unlink "$urpm->{cachedir}/rpms/$filename"; + urpm::util::move("$urpm->{cachedir}/partial/$filename", "$urpm->{cachedir}/rpms/$filename"); + -r "$urpm->{cachedir}/rpms/$filename" and $sources->{$i} = "$urpm->{cachedir}/rpms/$filename"; + } + unless ($sources->{$i}) { + $error_sources->{$i} = $distant_sources{$i}; + } + } + } + } + + #- clean failed download which have succeeded. + delete @$error_sources{keys %$sources}; + + 1; +} + +1; @@ -25,6 +25,7 @@ use urpm::args; use urpm::msg; use urpm::install; use urpm::media; +use urpm::get_pkgs; use urpm::signature; use urpm::util qw(untaint difference2 member); @@ -581,7 +582,7 @@ if (@root_only) { message_input("$msg:\n$p\n$msg2" . N(" (Y/n) "), $force && $yesexpr, boolean => 1) =~ /[$noexpr]/ and exit 0; } -my ($local_sources, $list) = $urpm->get_source_packages( +my ($local_sources, $list) = urpm::get_pkgs::selected2list($urpm, $state->{selected}, clean_all => $clean, clean_other => !$noclean && $urpm->{options}{'pre-clean'}, @@ -629,7 +630,7 @@ foreach my $set (@{$state->{transaction} || []}) { urpm::install::prepare_transaction($urpm, $set, $list, \%sources, \@transaction_list, \%transaction_sources); #- first, filter out what is really needed to download for this small transaction. - $urpm->download_packages_of_distant_media( + urpm::get_pkgs::download_packages_of_distant_media($urpm, \@transaction_list, \%transaction_sources, \%error_sources, @@ -28,6 +28,7 @@ use urpm::args; use urpm::msg; use urpm::sys; use urpm::media; +use urpm::get_pkgs; #- default options. $urpm::args::options = { use_provides => 1 }; @@ -311,7 +312,7 @@ if ($urpm::args::options{list_aliases}) { || $urpm::args::options{list_files} || $urpm::args::options{changelog}) { - my ($local_sources, $list) = $urpm->get_source_packages($state->{selected}); + my ($local_sources, $list) = urpm::get_pkgs::selected2list($urpm, $state->{selected}); if ($urpm::args::options{info} || $urpm::args::options{list_files} || $urpm::args::options{changelog} || $urpm::args::options{summary}) { @@ -343,7 +344,7 @@ if ($urpm::args::options{list_aliases}) { }; $packer->extract($tmp_header_dir, @headers); } elsif (!%downloads) { - $urpm->download_packages_of_distant_media($list, \%downloads, my $error = {}); + urpm::get_pkgs::download_packages_of_distant_media($urpm, $list, \%downloads, my $error = {}); warn "missing file $_\n" foreach values %$error; } } |