aboutsummaryrefslogtreecommitdiffstats
path: root/Rpmdrake/pkg.pm
diff options
context:
space:
mode:
authorThierry Vignaud <tv@mandriva.org>2007-02-20 11:37:58 +0000
committerThierry Vignaud <tv@mandriva.org>2007-02-20 11:37:58 +0000
commitf84a32b0127c148a0ff2df94f41b7f778f63207f (patch)
tree4c8a6d85595710984d7d288bd4e4237aa63186e8 /Rpmdrake/pkg.pm
parentce4e679eedac1e439937806e351fb1b8e5cb0d33 (diff)
downloadrpmdrake-f84a32b0127c148a0ff2df94f41b7f778f63207f.tar
rpmdrake-f84a32b0127c148a0ff2df94f41b7f778f63207f.tar.gz
rpmdrake-f84a32b0127c148a0ff2df94f41b7f778f63207f.tar.bz2
rpmdrake-f84a32b0127c148a0ff2df94f41b7f778f63207f.tar.xz
rpmdrake-f84a32b0127c148a0ff2df94f41b7f778f63207f.zip
split out package listing/installing into Rpmdrake::pkg
Diffstat (limited to 'Rpmdrake/pkg.pm')
-rwxr-xr-xRpmdrake/pkg.pm702
1 files changed, 702 insertions, 0 deletions
diff --git a/Rpmdrake/pkg.pm b/Rpmdrake/pkg.pm
new file mode 100755
index 00000000..d99ee2bd
--- /dev/null
+++ b/Rpmdrake/pkg.pm
@@ -0,0 +1,702 @@
+package Rpmdrake::pkg;
+#*****************************************************************************
+#
+# Copyright (c) 2002 Guillaume Cottenceau
+# Copyright (c) 2002-2007 Thierry Vignaud <tvignaud@mandriva.com>
+# Copyright (c) 2003, 2004, 2005 MandrakeSoft SA
+# Copyright (c) 2005-2007 Mandriva SA
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2, as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#*****************************************************************************
+#
+# $Id$
+
+use strict;
+use MDK::Common::Func 'any';
+use lib qw(/usr/lib/libDrakX);
+use common;
+use POSIX qw(_exit);
+use URPM;
+use utf8;
+use Rpmdrake::gurpm;
+use Rpmdrake::formatting;
+use Rpmdrake::rpmnew;
+
+use rpmdrake;
+use urpm::lock;
+use urpm::install;
+use urpm::signature;
+use urpm::get_pkgs;
+use urpm::select;
+
+
+use Exporter;
+our @ISA = qw(Exporter);
+our @EXPORT = qw(extract_header find_installed_version formatlistpkg get_pkgs open_db parse_compssUsers_flat perform_installation perform_removal run_rpm $db);
+
+use mygtk2 qw(gtknew);
+use ugtk2 qw(:all);
+use Gtk2::Pango;
+use Gtk2::Gdk::Keysyms;
+
+our $db;
+
+sub parse_compssUsers_flat() {
+ my (%compssUsers, $category);
+ my $compss = '/var/lib/urpmi/compssUsers.flat';
+ -r $compss or $compss = '/usr/share/rpmdrake/compssUsers.flat.default';
+ -r $compss or do {
+ print STDERR "No compssUsers.flat file found\n";
+ return undef;
+ };
+ foreach (cat_($compss)) {
+ s/#.*//;
+ /^\s*$/ and next;
+ if (/^\S/) {
+ if (/^(.+?) \[icon=.+?\] \[path=(.+?)\]/) {
+ $category = translate($2) . '|' . translate($1);
+ } else {
+ print STDERR "Malformed category in compssUsers.flat: <$_>\n";
+ }
+ } elsif (/^\t(\d) (\S+)\s*$/) {
+ $category or print STDERR "Entry without category <$_>\n";
+ push @{$compssUsers{$2}}, $category . ($1 <= 3 ? '|' . N("Other") : '');
+ }
+ }
+ \%compssUsers;
+}
+
+sub run_rpm {
+ foreach (qw(LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT LC_IDENTIFICATION LC_ALL)) {
+ local $ENV{$_} = $ENV{$_} . '.UTF-8' if !/UTF-8/;
+ }
+ my @l = map { to_utf8($_) } `@_`;
+ wantarray() ? @l : join('', @l);
+}
+
+
+sub extract_header {
+ my ($pkg, $urpm) = @_;
+ my $chg_prepro = sub {
+ #- preprocess changelog for faster TextView insert reaction
+ [ map { [ "$_\n", if_(/^\*/, { 'weight' => Gtk2::Pango->PANGO_WEIGHT_BOLD }) ] } split("\n", $_[0]) ];
+ };
+ my $name = urpm_name($pkg->{pkg});
+ if ($pkg->{pkg}->flag_installed && !$pkg->{pkg}->flag_upgrade) {
+ add2hash($pkg, { files => [ split /\n/, chomp_(scalar(run_rpm("rpm -ql $name"))) || N("(none)") ],
+ changelog => $chg_prepro->(scalar(run_rpm("rpm -q --changelog $name"))) });
+ } else {
+ my ($p, $medium) = ($pkg->{pkg}, pkg2medium($pkg->{pkg}, $urpm));
+ my $hdlist = urpm::media::any_hdlist($urpm, $medium);
+ $hdlist =~ s!^file:/+!!;
+ if (-r $hdlist) {
+ my $packer;
+ require MDV::Packdrakeng;
+ eval { $packer = MDV::Packdrakeng->open(archive => $hdlist, quiet => 1) } or do {
+ warn "Warning, hdlist $hdlist seems corrupted ($@)\n";
+ goto header_non_available;
+ };
+ my ($headersdir, $retries);
+ while (!-d $headersdir && $retries < 5) {
+ $headersdir = chomp_(`mktemp -d /tmp/rpmdrake.XXXXXXXX`);
+ $retries++;
+ -d $headersdir or warn qq(Could not create temporary directory "$headersdir");
+ }
+ -d $headersdir or do {
+ warn "Warning, could not extract header!";
+ goto header_non_available;
+ };
+ $packer->extract($headersdir, $p->header_filename);
+ $p->update_header("$headersdir/" . $p->header_filename) or do {
+ warn "Warning, could not extract header!";
+ goto header_non_available;
+ };
+ rm_rf($headersdir);
+ add2hash($pkg, { summary => rpm_summary($p->summary), description => rpm_description($p->description) });
+ add2hash($pkg, {
+ files => scalar($p->files) ? [ $p->files ] : [ N("(none)") ],
+ changelog => $chg_prepro->(join("\n", mapn { "* " . localtime2changelog($_[2]) . " $_[0]\n\n$_[1]\n" }
+ [ $p->changelog_name ], [ $p->changelog_text ], [ $p->changelog_time ])) });
+ $p->pack_header;
+ } else {
+ header_non_available:
+ add2hash($pkg, { summary => $p->summary || N("(Not available)"), description => undef });
+ }
+ }
+}
+
+my %options;
+
+sub open_db {
+ my ($o_force) = @_;
+ my $host;
+ log::explanations("opening the RPM database");
+ if ($options{parallel} && ((undef, $host) = @{$options{parallel}})) {
+ my $done if 0;
+ my $dblocation = "/var/cache/urpmi/distantdb/$host";
+ if (!$done || $o_force) {
+ print "syncing db from $host to $dblocation...";
+ mkdir_p "$dblocation/var/lib/rpm";
+ system "rsync -Sauz -e ssh $host:/var/lib/rpm/ $dblocation/var/lib/rpm";
+ $? == 0 or die "Couldn't sync db from $host to $dblocation";
+ $done = 1;
+ print "done.\n";
+ }
+ $db = URPM::DB::open($dblocation) or die "Couldn't open RPM DB";
+ } else {
+ $db = URPM::DB::open or die "Couldn't open RPM DB";
+ }
+}
+
+
+sub find_installed_version {
+ my ($p) = @_;
+ my @version;
+ $db->traverse_tag('name', [ $p->name ], sub { push @version, $_[0]->version . '-' . $_[0]->release });
+ @version ? join(',', sort @version) : N("(none)");
+}
+
+sub formatlistpkg { join("\n", sort { uc($a) cmp uc($b) } @_) }
+
+
+# -=-=-=---=-=-=---=-=-=-- install packages -=-=-=---=-=-=---=-=-=-
+
+
+sub get_pkgs {
+ my ($urpm, $opts) = @_;
+ my $update_name = 'update_source';
+ my %update_descr;
+ my @update_medias;
+ my $w = $::main_window;
+
+ my $error_happened;
+ my $fatal_handler = sub {
+ $error_happened = 1;
+ interactive_msg(N("Fatal error"),
+ N("A fatal error occurred: %s.", $_[1]));
+ myexit(-1) if 0; #FIXME
+ };
+
+ Rpmdrake::gurpm::init(1 ? N("Please wait") : N("Package installation..."), N("Initializing..."), transient => $::w->{real_window});
+ my $_guard = before_leaving { Rpmdrake::gurpm::end() };
+
+ if (!$urpm) {
+ $urpm ||= urpm->new;
+ $urpm->{fatal} = $fatal_handler;
+ my $media = ref $::options{media} ? join(',', @{$::options{media}}) : '';
+ urpm::media::configure($urpm, media => $media);
+ if ($error_happened) {
+ touch('/etc/urpmi/urpmi.cfg');
+ exec('edit-urpm-sources.pl');
+ }
+ }
+ my $_lock = urpm::lock::urpmi_db($urpm);
+ my $statedir = $urpm->{statedir};
+ @update_medias = grep { !$_->{ignore} && $_->{update} } @{$urpm->{media}};
+
+
+ $urpm->{fatal} = $fatal_handler;
+ if (member($::default_list_mode, qw(all_updates security bugfix normal))) {
+ unless ($::options{'no-media-update'}) {
+ if (@update_medias > 0) {
+ if (!$opts->{skip_updating_mu}) {
+ $::options{'no-confirmation'} or interactive_msg_with_banner(N("Confirmation"),
+N("I need to contact the mirror to get latest update packages.
+Please check that your network is currently running.
+
+Is it ok to continue?"), yesno => 1) or myexit(-1);
+ urpm::media::select_media($urpm, map { $_->{name} } @update_medias);
+ update_sources($urpm, noclean => 1, banner => $::isEmbedded);
+ }
+ } else {
+ if (any { $_->{update} } @{$urpm->{media}}) {
+ interactive_msg(N("Already existing update media"),
+N("You already have at least one update medium configured, but
+all of them are currently disabled. You should run the Software
+Media Manager to enable at least one (check it in the Enabled?
+column).
+
+Then, restart %s.", $rpmdrake::myname_update));
+ myexit(-1);
+ }
+ mu_retry_another_mirror:
+ my ($mirror) = choose_mirror(if_(exists $w->{real_window}, transient => $w->{real_window}));
+ my $m = ref($mirror) ? $mirror->{url} : '';
+ $m or interactive_msg(N("How to choose manually your mirror"),
+N("You may also choose your desired mirror manually: to do so,
+launch the Software Media Manager, and then add a `Security
+updates' medium.
+
+Then, restart %s.", $rpmdrake::myname_update)), myexit(-1);
+ add_medium_and_check(
+ $urpm, {},
+ $update_name, make_url_mirror($m), 'media_info/synthesis.hdlist.cz', update => 1,
+ );
+ @update_medias = { name => $update_name }; #- hack to simulate a medium for parsing of descriptions
+ }
+ }
+ }
+
+ Rpmdrake::gurpm::label(N("Reading updates description"));
+ Rpmdrake::gurpm::progress(0.05);
+ my ($cur, $section);
+ #- parse the description file
+ foreach my $medium (@update_medias) {
+ foreach (cat_("$statedir/descriptions.$medium->{name}")) {
+ /^%package +(.+)/ and do {
+ my @pkg_list = split /\s+/, $1;
+ exists $cur->{importance} && $cur->{importance} !~ /^(?:security|bugfix)\z/
+ and $cur->{importance} = 'normal';
+ $update_descr{$_} = $cur foreach @{$cur->{pkgs} || []};
+ $cur = { pkgs => \@pkg_list, medium => $medium->{name} };
+ $section = 'pkg';
+ next;
+ };
+ /^%(pre|description)/ and do { $section = $1; next };
+ /^Updated?: +(.+)/ && $section eq 'pkg'
+ and do { $cur->{update} = $1; next };
+ /^Importance: +(.+)/ && $section eq 'pkg'
+ and do { $cur->{importance} = $1; next };
+ /^(ID|URL): +(.+)/ && $section eq 'pkg'
+ and do { $cur->{$1} = $2; next };
+ $section =~ /^(pre|description)\z/ and $cur->{$1} .= $_;
+ }
+ }
+
+ my $_unused = N("Please wait, finding available packages...");
+
+ # find out installed packages:
+
+ #$urpm = urpm->new;
+ #$urpm->read_config;
+ my $level = 0.05;
+ my $total = @{$urpm->{depslist}};
+ Rpmdrake::gurpm::label(N("Please wait, listing base packages..."));
+ Rpmdrake::gurpm::progress($level);
+
+ my ($count, $prev_stage, $new_stage, $limit);
+
+ my $reset_update = sub { undef $prev_stage; $count = 0; $limit = $_[0] };
+ my $update = sub {
+ $count++;
+ $new_stage = $level+($limit-$level)*$count/$total;
+ if ($prev_stage + 0.01 < $new_stage) {
+ $prev_stage = $new_stage;
+ Rpmdrake::gurpm::progress($new_stage);
+ }
+ };
+
+ my @base = ("basesystem", split /,\s*/, $urpm->{global_config}{'prohibit-remove'});
+ my (%base, %basepackages);
+ my $db = $db;
+ my $sig_handler = sub { undef $db; exit 3 };
+ local $SIG{INT} = $sig_handler;
+ local $SIG{QUIT} = $sig_handler;
+ $reset_update->(0.33);
+ while (defined(local $_ = shift @base)) {
+ exists $basepackages{$_} and next;
+ $db->traverse_tag(m|^/| ? 'path' : 'whatprovides', [ $_ ], sub {
+ $update->();
+ push @{$basepackages{$_}}, urpm_name($_[0]);
+ push @base, $_[0]->requires_nosense;
+ });
+ }
+ foreach (values %basepackages) {
+ my $n = @$_; #- count number of times it's provided
+ foreach (@$_) {
+ $base{$_} = \$n;
+ }
+ }
+ Rpmdrake::gurpm::label(N("Please wait, finding installed packages..."));
+ Rpmdrake::gurpm::progress($level = 0.33);
+ $reset_update->(0.66);
+ my %installed_pkgs;
+ $db->traverse(sub {
+ my ($pkg) = @_;
+ $update->();
+ my $fullname = urpm_name($pkg);
+ #- Extract summary and description since they'll be lost when the header is packed
+ $installed_pkgs{$fullname} = {
+ selected => 0, pkg => $pkg, urpm_name => urpm_name($pkg),
+ summary => rpm_summary($pkg->summary),
+ description => rpm_description($pkg->description),
+ } if !($installed_pkgs{$fullname} && $installed_pkgs{$fullname}{description});
+ if (my $name = $base{$fullname}) {
+ $installed_pkgs{$fullname}{base} = \$name;
+ $pkg->set_flag_base(1) if $$name == 1;
+ }
+ $pkg->pack_header;
+ });
+ my $group;
+ if ($::options{parallel} && (($group) = @{$::options{parallel}})) {
+ urpm::media::configure($urpm, parallel => $group);
+ }
+
+ # find out availlable packages:
+
+ #$urpm = urpm->new;
+ $urpm->{state} = {};
+ my %installable_pkgs;
+ my %updates;
+
+ Rpmdrake::gurpm::label(N("Please wait, finding available packages..."));
+ Rpmdrake::gurpm::progress($level = 0.66);
+
+ @update_medias = grep { !$_->{ignore} && $_->{update} } @{$urpm->{media}};
+ check_update_media_version($urpm, @update_medias);
+
+ my $requested = {};
+ my $state = {};
+ $urpm->request_packages_to_upgrade(
+ $db,
+ $state,
+ $requested,
+ start => 0,
+ end => $#{$urpm->{depslist}},
+ );
+ $urpm->compute_installed_flags($db); # TODO/FIXME: not for updates
+ $urpm->{depslist}[$_]->set_flag_installed foreach keys %$requested; #- pretend it's installed
+ $urpm->{rpmdrake_state} = $state; #- Don't forget it
+ Rpmdrake::gurpm::progress($level = 0.7);
+
+ my %pkg_sel = map { $_ => 1 } @{$::options{'pkg-sel'} || []};
+ my %pkg_nosel = map { $_ => 1 } @{$::options{'pkg-nosel'} || []};
+ my @updates_media_names = map { $_->{name} } @update_medias;
+ $reset_update->(1);
+ foreach my $pkg (@{$urpm->{depslist}}) {
+ $update->();
+ $pkg->flag_upgrade or next;
+ my $selected = 0;
+
+ if (member(pkg2medium($pkg, $urpm)->{name}, @updates_media_names) && $pkg->flag_installed) { # TODO/FIXME: for updates
+ any { $pkg->id >= $_->{start} && $pkg->id <= $_->{end} } @update_medias or next;
+ if ($::options{'pkg-sel'} || $::options{'pkg-nosel'}) {
+ my $n = urpm_name($pkg);
+ $pkg_sel{$n} || $pkg_nosel{$n} or next;
+ $pkg_sel{$n} and $selected = 1;
+ } else {
+ # selecting updates by default:
+ $selected = 1;
+ }
+ $updates{urpm_name($pkg)} = { selected => $selected, pkg => $pkg };
+ } else {
+ $installable_pkgs{urpm_name($pkg)} = { selected => $selected, pkg => $pkg };
+ }
+ }
+ if ($::options{'pkg-sel'} && $::options{'pkg-nosel'}) {
+ push @{$::options{'pkg-nosel'}}, @{$::options{'pkg-sel'}};
+ delete $::options{'pkg-sel'};
+ }
+
+ $_->{pkg}->set_flag_installed foreach values %installed_pkgs;
+
+ +{ urpm => $urpm,
+ installed => \%installed_pkgs,
+ installable => \%installable_pkgs,
+ updates => \%updates,
+ update_descr => \%update_descr,
+ };
+}
+
+
+sub perform_installation { #- (partially) duplicated from /usr/sbin/urpmi :-(
+ my ($urpm, $pkgs) = @_;
+
+ my $fatal_msg;
+ my @error_msgs;
+ my %Readmes;
+ my $statusbar_msg_id;
+ local $urpm->{fatal} = sub { printf STDERR "Fatal: %s\n", $_[1]; $fatal_msg = $_[1]; goto fatal_error };
+ local $urpm->{error} = sub { printf STDERR "Error: %s\n", $_[0]; push @error_msgs, $_[0] };
+
+ my $w = $::main_window;
+ $w->set_sensitive(0);
+
+ my $group;
+ if ($::options{parallel} && (($group) = @{$::options{parallel}})) {
+ my $pkgs = join(' ', map { if_($_->flag_requested, urpm_name($_)) } @{$urpm->{depslist}});
+ system("urpmi -v --X --parallel $group $pkgs");
+ if ($? == 0) {
+ $statusbar_msg_id = statusbar_msg(
+ #N("Everything installed successfully"),
+ N("All requested packages were installed successfully."),
+ );
+ } else {
+ interactive_msg(
+ N("Problem during installation"),
+ N("There was a problem during the installation:\n\n%s", join("\n", @error_msgs)),
+ scroll => 1,
+ );
+ }
+ open_db('force_sync');
+ $w->set_sensitive(1);
+ return 0;
+ }
+
+ my $_lock = urpm::lock::urpmi_db($urpm);
+ my $_rpm_lock = urpm::lock::rpm_db($urpm, 'exclusive');
+ my %pkgs = map { $_->id => undef } grep { $_->flag_selected } @{$urpm->{depslist}};
+ my ($local_sources, $list, $local_to_removes) = urpm::get_pkgs::selected2list($urpm,
+ \%pkgs,
+ clean_all => 1,
+ );
+ my $distant_number = scalar keys %pkgs;
+ if (!$local_sources && (!$list || !@$list)) {
+ interactive_msg(
+ N("Unable to get source packages."),
+ N("Unable to get source packages, sorry. %s",
+ @error_msgs ? N("\n\nError(s) reported:\n%s", join("\n", @error_msgs)) : ''),
+ scroll => 1,
+ );
+ goto return_with_error;
+ }
+ foreach (@$local_to_removes) {
+ unlink $_;
+ }
+
+ my @pkgs = map { scalar($_->fullname) } sort(grep { $_->flag_selected } @{$urpm->{depslist}});#{ $a->name cmp $b->name } @{$urpm->{depslist}}[keys %{$state->{selected}}];
+ @{$urpm->{ask_remove}} = sort urpm::select::removed_packages($urpm, $urpm->{state});
+ my @to_remove = grep { $_ } map { if_($pkgs->{$_}{selected}, $pkgs->{$_}{urpm_name}) } keys %$pkgs;
+
+ my $r = join "\n", urpm::select::translate_why_removed($urpm, $urpm->{state}, @to_remove);
+
+ my $install_count = int(@pkgs);
+ my $to_install = $install_count ?
+ #-PO: in singular form, we use %2\$
+ P("To satisfy dependencies, the following package is going to be installed:\n%2\$s\n", "To satisfy dependencies, the following %d packages are going to be installed:\n%s\n", $install_count, $install_count,
+ formatlistpkg(map { s!.*/!!; $_ } @pkgs)) : '';
+ my $remove_count = scalar(@to_remove);
+ interactive_msg(($to_install ? N("Confirmation") : N("Some packages need to be removed")),
+ ($r ?
+ (!$to_install ? join("\n\n", P("Remove one package?", "Remove %d packages?", $remove_count, $remove_count), $r) :
+ P("The following package has to be removed for others to be upgraded:", "The following packages have to be removed for others to be upgraded:", $remove_count) . join("\n\n", $r, if_($to_install, $to_install)) . N("Is it ok to continue?"))
+ : $to_install),
+ scroll => 1,
+ yesno => 1) or do {
+ $w->set_sensitive(1);
+ return 'canceled';
+ };
+
+ Rpmdrake::gurpm::init(1 ? N("Please wait") : N("Package installation..."), N("Initializing..."), transient => $::w->{real_window});
+ my $distant_progress;
+ my $canceled;
+ my %sources = $urpm->download_source_packages(
+ $local_sources,
+ $list,
+ force_local => 1, # removed in urpmi 4.8.7
+ ask_for_medium => sub {
+ interactive_msg(
+ N("Change medium"),
+ N("Please insert the medium named \"%s\" on device [%s]", $_[0], $_[1]),
+ yesno => 1, text => { no => N("Cancel"), yes => N("Ok") },
+ );
+ },
+ callback => sub {
+ my ($mode, $file, $percent) = @_;
+ if ($mode eq 'start') {
+ Rpmdrake::gurpm::label(N("Downloading package `%s' (%s/%s)...",
+ basename($file), ++$distant_progress, $distant_number));
+ Rpmdrake::gurpm::validate_cancel(but(N("Cancel")), sub { $canceled = 1 });
+ } elsif ($mode eq 'progress') {
+ Rpmdrake::gurpm::progress($percent/100);
+ } elsif ($mode eq 'end') {
+ Rpmdrake::gurpm::progress(1);
+ Rpmdrake::gurpm::invalidate_cancel();
+ }
+ $canceled and return 'canceled';
+ },
+ );
+ $canceled and goto return_with_error;
+ Rpmdrake::gurpm::invalidate_cancel_forever();
+
+ my %sources_install = %{$urpm->extract_packages_to_install(\%sources, $urpm->{rpmdrake_state}) || {}};
+ my @rpms_install = grep { !/\.src\.rpm$/ } values %sources_install;
+ my @rpms_upgrade = grep { !/\.src\.rpm$/ } values %sources;
+
+ if (!$::options{'no-verify-rpm'}) {
+ Rpmdrake::gurpm::label(N("Verifying package signatures..."));
+ my $total = @rpms_install + @rpms_upgrade;
+ my $progress;
+ my @invalid_sources = urpm::signature::check($urpm,
+ \%sources_install, \%sources,
+ translate => 1, basename => 1,
+ callback => sub {
+ Rpmdrake::gurpm::progress(++$progress/$total);
+ },
+ );
+ if (@invalid_sources) {
+ local $::main_window = $Rpmdrake::gurpm::mainw->{real_window};
+ interactive_msg(
+ N("Warning"),
+ N("The following packages have bad signatures:\n\n%s\n\nDo you want to continue installation?",
+ join("\n", sort @invalid_sources)), yesno => 1, if_(@invalid_sources > 10, scroll => 1),
+ ) or goto return_with_error;
+ }
+ }
+
+ my $_guard = before_leaving { urpm::removable::try_umounting_removables($urpm) };
+
+ my $something_installed;
+ if (@rpms_install || @rpms_upgrade || @to_remove) {
+ if (my @missing = grep { m|^/| && ! -e $_ } @rpms_install, @rpms_upgrade) {
+ interactive_msg(
+ N("Installation failed"),
+ N("Installation failed, some files are missing:\n%s\n\nYou may want to update your media database.",
+ join "\n", map { " $_" } @missing) .
+ (@error_msgs ? N("\n\nError(s) reported:\n%s", join("\n", @error_msgs)) : ''),
+ if_(@error_msgs > 1, scroll => 1),
+ );
+ goto return_with_error;
+ }
+ my $progress_nb;
+ my $total_nb = scalar grep { m|^/| } @rpms_install, @rpms_upgrade;
+ my $callback_inst = sub {
+ my ($urpm, $type, $id, $subtype, $amount, $total) = @_;
+ my $pkg = defined $id ? $urpm->{depslist}[$id] : undef;
+ if ($subtype eq 'start') {
+ if ($type eq 'trans') {
+ Rpmdrake::gurpm::label(@rpms_install ? N("Preparing packages installation...") : N("Preparing..."));
+ } elsif (defined $pkg) {
+ $something_installed = 1;
+ Rpmdrake::gurpm::label(N("Installing package `%s' (%s/%s)...", $pkg->name, ++$progress_nb, $total_nb));
+ }
+ } elsif ($subtype eq 'progress') {
+ Rpmdrake::gurpm::progress($total ? $amount/$total : 1);
+ }
+ };
+ my $fh;
+ my @errors = urpm::install::install($urpm,
+ \@to_remove,
+ \%sources_install,
+ \%sources,
+ post_clean_cache => $urpm->{options}{'post-clean'},
+ callback_open => sub {
+ my ($_data, $_type, $id) = @_;
+ my $f = $sources_install{$id} || $sources{$id};
+ open $fh, $f or $urpm->{error}(N("unable to access rpm file [%s]", $f));
+ return fileno $fh;
+ },
+ callback_inst => $callback_inst,
+ callback_trans => $callback_inst,
+ callback_close => sub {
+ my ($urpm, undef, $pkgid) = @_;
+ return unless defined $pkgid;
+ my $pkg = $urpm->{depslist}[$pkgid];
+ my $fullname = $pkg->fullname;
+ my $trtype = (any { /\Q$fullname/ } values %sources_install) ? 'install' : '(update|upgrade)';
+ foreach ($pkg->files) { /\bREADME(\.$trtype)?\.urpmi$/ and $Readmes{$_} = $fullname }
+ close $fh;
+ },
+ );
+ Rpmdrake::gurpm::end();
+
+ if (@errors || @error_msgs) {
+ interactive_msg(
+ N("Problem during installation"),
+ N("There was a problem during the installation:\n\n%s",
+ join("\n", @errors, @error_msgs)),
+ if_(@errors + @error_msgs > 1, scroll => 1),
+ );
+ $w->set_sensitive(1);
+ return !$something_installed;
+ }
+
+ my %pkg2rpmnew;
+ foreach my $u (@rpms_upgrade) {
+ $u =~ m|/([^/]+-[^-]+-[^-]+)\.[^\./]+\.rpm$|
+ and $pkg2rpmnew{$1} = [ grep { m|^/etc| && (-r "$_.rpmnew" || -r "$_.rpmsave") }
+ map { chomp_($_) } run_rpm("rpm -ql $1") ];
+ }
+ dialog_rpmnew(N("The installation is finished; everything was installed correctly.
+
+Some configuration files were created as `.rpmnew' or `.rpmsave',
+you may now inspect some in order to take actions:"),
+ %pkg2rpmnew)
+ and $statusbar_msg_id = statusbar_msg(N("All requested packages were installed successfully."));
+ if (keys %Readmes) { #- display the README*.urpmi files
+ interactive_packtable(
+ N("Upgrade information"),
+ $w->{real_window},
+ N("These packages come with upgrade information"),
+ [ map {
+ my $fullname = $_;
+ [ gtkpack__(
+ gtknew('HBox'),
+ gtkset_selectable(gtknew('Label', text => $Readmes{$fullname}),1),
+ ),
+ gtksignal_connect(
+ gtknew('Button', text => N("Upgrade information about this package")),
+ clicked => sub {
+ interactive_msg(
+ N("Upgrade information about package %s", $Readmes{$fullname}),
+ (join '' => formatAlaTeX(scalar cat_($fullname))),
+ scroll => 1,
+ );
+ },
+ ),
+ ] } keys %Readmes ],
+ [ gtknew('Button', text => N("Ok"), clicked => sub { Gtk2->main_quit }) ]
+ );
+ }
+ } else {
+ Rpmdrake::gurpm::end();
+ interactive_msg(N("Error"),
+ N("Unrecoverable error: no package found for installation, sorry."));
+ }
+
+ $w->set_sensitive(1);
+ statusbar_msg_remove($statusbar_msg_id); #- XXX maybe remove this
+ return !($something_installed || scalar(@to_remove));
+
+ fatal_error:
+ Rpmdrake::gurpm::end();
+ interactive_msg(N("Installation failed"),
+ N("There was a problem during the installation:\n\n%s", $fatal_msg));
+ return_with_error:
+ Rpmdrake::gurpm::end();
+ $w->set_sensitive(1);
+ return 1;
+}
+
+
+# -=-=-=---=-=-=---=-=-=-- remove packages -=-=-=---=-=-=---=-=-=-
+
+sub perform_removal {
+ my ($urpm, $pkgs) = @_;
+ my @toremove = map { if_($pkgs->{$_}{selected}, $pkgs->{$_}{urpm_name}) } keys %$pkgs;
+ my @results;
+ slow_func_statusbar(
+ N("Please wait, removing packages..."),
+ $::main_window->{real_window},
+ sub {
+ @results = $::options{parallel}
+ ? urpm::parallel::remove($urpm, \@toremove)
+ : urpm::install::install($urpm, \@toremove, {}, {});
+ open_db('force_sync');
+ },
+ );
+ if (@results) {
+ interactive_msg(
+ N("Problem during removal"),
+ N("There was a problem during the removal of packages:\n\n%s", join("\n", @results)),
+ if_(@results > 1, scroll => 1),
+ );
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+1;