diff options
-rwxr-xr-x | Rpmdrake/pkg.pm | 702 | ||||
-rwxr-xr-x | rpmdrake | 658 |
2 files changed, 704 insertions, 656 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; @@ -63,13 +63,10 @@ BEGIN { #- for mcc } use rpmdrake; -use urpm::lock; -use urpm::install; -use Rpmdrake::gurpm; use Rpmdrake::rpmnew; use Rpmdrake::formatting; -use urpm::signature; -use urpm::get_pkgs; +use Rpmdrake::pkg; +use urpm::media; use urpm::select; #- This is needed because text printed by Gtk2 will always be encoded @@ -115,7 +112,6 @@ if ($MODE eq 'remove') { use mygtk2 qw(gtknew); #- do not import anything else, especially gtkadd() which conflicts with ugtk2 one use ugtk2 qw(:all); -use Gtk2::Pango; use Gtk2::Gdk::Keysyms; $MODE eq 'update' || $options{root} and require_root_capability(); @@ -299,111 +295,6 @@ sub ctreefy { join('|', map { translate($_) } split m|/|, $_[0]); } -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 }); - } - } -} - -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"; - } - URPM::DB::open($dblocation) or die "Couldn't open RPM DB"; - } else { - URPM::DB::open or die "Couldn't open RPM DB"; - } -} - my $db = open_db(); sub do_search($$$$$$$) { @@ -507,25 +398,6 @@ sub do_search($$$$$$$) { } } -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) } @_) } - -sub format_header { - my ($str) = @_; - '<big>' . escape_text_for_TextView_markup_format($str) . '</big>'; -} - -sub format_field { - my ($str) = @_; - '<b>' . escape_text_for_TextView_markup_format($str) . '</b>'; -} - package Gtk2::Mdv::TextView; sub new { @@ -1369,532 +1241,6 @@ Do you really want to install all the selected packages?"), yesno => 1) ask_browse_tree_info_given_widgets_for_rpmdrake($options); } -# -=-=-=---=-=-=---=-=-=-- install packages -=-=-=---=-=-=---=-=-=- - - -sub get_pkgs { - my ($urpm, $opts) = @_; - my $update_name = 'update_source'; - my %update_descr; - my @update_medias; - - 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] }; - - $w->{rwindow}->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->{rwindow}->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->{rwindow}->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->{rwindow}->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->{rwindow}->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->{rwindow}->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..."), - $w->{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; - } -} - # -=-=-=---=-=-=---=-=-=-- main -=-=-=---=-=-=---=-=-=- |