summaryrefslogtreecommitdiffstats
path: root/gurpmi2
diff options
context:
space:
mode:
authorRafael Garcia-Suarez <rgarciasuarez@mandriva.org>2005-01-19 16:50:04 +0000
committerRafael Garcia-Suarez <rgarciasuarez@mandriva.org>2005-01-19 16:50:04 +0000
commit2716b31839a7348862076608fced29d2fa18cff1 (patch)
tree1e2cb133219752ea0b77270f51f7b0db5bfb3614 /gurpmi2
parentdaea81977918d27e0b0b958eed08113720d07f8e (diff)
downloadurpmi-2716b31839a7348862076608fced29d2fa18cff1.tar
urpmi-2716b31839a7348862076608fced29d2fa18cff1.tar.gz
urpmi-2716b31839a7348862076608fced29d2fa18cff1.tar.bz2
urpmi-2716b31839a7348862076608fced29d2fa18cff1.tar.xz
urpmi-2716b31839a7348862076608fced29d2fa18cff1.zip
Split gurpmi in two executables (one of them to be run as root)
Diffstat (limited to 'gurpmi2')
-rwxr-xr-xgurpmi2373
1 files changed, 373 insertions, 0 deletions
diff --git a/gurpmi2 b/gurpmi2
new file mode 100755
index 00000000..04f6b13a
--- /dev/null
+++ b/gurpmi2
@@ -0,0 +1,373 @@
+#!/usr/bin/perl
+
+#- Copyright (C) 2005 Mandrakesoft
+
+use strict;
+use warnings;
+
+BEGIN { #- set up a safe path and environment
+ $ENV{PATH} = "/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin";
+ delete @ENV{qw(ENV BASH_ENV IFS CDPATH)};
+}
+
+#- This is needed because text printed by Gtk2 will always be encoded
+#- in UTF-8; we first check if LC_ALL is defined, because if it is,
+#- changing only LC_COLLATE will have no effect.
+use POSIX qw(setlocale LC_ALL LC_COLLATE);
+use locale;
+BEGIN {
+ my $collation_locale = $ENV{LC_ALL};
+ if ($collation_locale) {
+ $collation_locale =~ /UTF-8/ or setlocale(LC_ALL, "$collation_locale.UTF-8");
+ } else {
+ $collation_locale = setlocale(LC_COLLATE);
+ $collation_locale =~ /UTF-8/ or setlocale(LC_COLLATE, "$collation_locale.UTF-8");
+ }
+}
+
+use urpm;
+use urpm::msg qw(N);
+use Gtk2;
+
+sub usage () {
+ print STDERR <<USAGE;
+gurpmi version $urpm::VERSION
+Usage :
+ gurpmi <rpm> [ <rpm>... ]
+USAGE
+ exit 0;
+}
+
+#- fatal gurpmi initialisation error (*not* fatal urpmi errors)
+sub fatal { print STDERR "$_[0]\n"; exit 1 }
+
+sub quit () { Gtk2->main_quit }
+
+sub but ($) { " $_[0] " }
+
+#- GUI globals
+my ($mainw, $mainbox);
+
+#- Gtk2 helper functions
+
+#- Replaces the contents of the main window with the specified box
+#- (avoids popup multiplication)
+sub change_mainw {
+ $mainw->remove($mainbox);
+ ($mainbox) = @_;
+ $mainw->add($mainbox);
+ $mainw->show_all;
+}
+
+sub add_button_box {
+ my ($vbox, @buttons) = @_;
+ my $hbox = Gtk2::HButtonBox->new;
+ $vbox->pack_start($hbox, 0, 0, 0);
+ $hbox->set_layout('edge');
+ $_->set_alignment(0.5, 0.5), $hbox->add($_) foreach @buttons;
+}
+
+sub sync {
+ $mainw->show;
+ Gtk2->main_iteration while Gtk2->events_pending;
+}
+
+sub new_label {
+ my ($msg) = @_;
+ my $label = Gtk2::Label->new($msg);
+ $label->set_line_wrap(1);
+ $label->set_alignment(0.5, 0.5);
+ if (($msg =~ tr/\n/\n/) > 5) {
+ my $sw = Gtk2::ScrolledWindow->new;
+ $sw->set_policy('never', 'automatic');
+ $sw->add_with_viewport($label);
+ $sw->set_size_request(-1,200);
+ return $sw;
+ } else {
+ return $label;
+ }
+}
+
+#- sets the window to a please-wait message
+sub wait_label {
+ my $wait_vbox = Gtk2::VBox->new(0, 5);
+ my $wait_label = Gtk2::Label->new($_[0] || N("Please wait..."));
+ $wait_label->set_alignment(0.5, 0.5);
+ $wait_vbox->pack_start($wait_label, 1, 1, 0);
+ change_mainw($wait_vbox);
+ sync();
+}
+
+#- Parse command line
+my (@all_rpms);
+foreach (@ARGV) {
+ if (/^-/) {
+ /^--?[hv?]/ and usage;
+ fatal N("Unknown option %s", $_);
+ }
+ push @all_rpms, $_;
+}
+@all_rpms or fatal N("No packages specified");
+
+$> and fatal N("Must be root");
+
+#- Now, the graphical stuff.
+
+Gtk2->init;
+
+#- Create main window
+
+$mainw = Gtk2::Window->new('toplevel');
+$mainw->set_border_width(3);
+$mainw->set_title(N("RPM installation"));
+$mainw->signal_connect(destroy => \&quit);
+$mainw->set_position('center');
+$mainw->set_modal(0);
+$mainbox = Gtk2::VBox->new(0, 5);
+$mainw->add($mainbox);
+
+#- Performs installation
+
+my $urpm = configure_urpm();
+my $state = {};
+my %requested = $urpm->register_rpms(@all_rpms);
+$urpm->resolve_dependencies(
+ $state,
+ \%requested,
+ callback_choices => \&ask_choice,
+);
+my @ask_unselect = $urpm->unselected_packages($state);
+@ask_unselect
+? ask_continue(N(
+ "Some package requested cannot be installed:\n%s\nContinue?",
+ join "\n", $urpm->translate_why_unselected($state, sort @ask_unselect)
+ ), \&do_install)
+: do_install();
+
+
+$mainw->show_all;
+Gtk2->main;
+
+#- Creates and configure an urpm object for this application to use.
+sub configure_urpm {
+ my $urpm = new urpm;
+ $urpm->{fatal} = sub {
+ Gtk2::MessageDialog->new($mainw, [qw(modal destroy-with-parent)], 'error', 'ok', $_[1])->run;
+ quit;
+ exit $_[0];
+ };
+ $urpm->{error} = sub {
+ my $w = Gtk2::MessageDialog->new($mainw, [qw(modal destroy-with-parent)], 'warning', 'ok', $_[0]);
+ $w->run;
+ $w->destroy;
+ };
+ $urpm->exlock_rpm_db;
+ $urpm->shlock_urpmi_db;
+ $urpm->configure;
+ #- default options values
+ exists $urpm->{options}{$_} or $urpm->{options}{$_} = 1 foreach qw(post-clean verify-rpm split-length);
+ $urpm->{options}{'split-level'} = 20 unless exists $urpm->{options}{'split-level'};
+ $urpm;
+}
+
+#- Callback for choices
+sub ask_choice {
+ my (undef, undef, undef, $choices) = @_;
+ my $radio;
+ my @radios = map {
+ $radio = Gtk2::RadioButton->new_with_label(
+ $radio ? $radio->get_group : undef,
+ (scalar $_->fullname) . "\n" . $_->summary
+ . ($_->flag_installed ? N(" (to upgrade)") : '')
+ . ($_->flag_upgrade ? N(" (to install)") : '')
+ );
+ } @$choices;
+ my $vbox = Gtk2::VBox->new(0, 5);
+ my $label = Gtk2::Label->new(N("One of the following packages is needed:"));
+ $label->set_alignment(0.5, 0.5);
+ $vbox->pack_start($label, 1, 1, 0);
+ $vbox->pack_start($_, 1, 1, 0) foreach @radios;
+ my $cancel_button = Gtk2::Button->new(but N("_Cancel"));
+ my $choice_button = Gtk2::Button->new(but N("_Ok"));
+ $cancel_button->signal_connect(clicked => \&quit);
+ $choice_button->signal_connect(clicked => sub {
+ my $n = 0;
+ foreach (@radios) { last if $_->get_active; ++$n }
+ $choices->[$n];
+ });
+ add_button_box($vbox, $cancel_button, $choice_button);
+ change_mainw($vbox);
+ $radios[0]->set_active(1);
+}
+
+sub ask_continue {
+ my ($msg, $nextclosure) = @_;
+ my $vbox = Gtk2::VBox->new(0, 5);
+ $vbox->pack_start(new_label($msg), 1, 1, 0);
+ my $continue_button = Gtk2::Button->new(but N("_Ok"));
+ my $quit_button = Gtk2::Button->new(but N("_Abort"));
+ $quit_button->signal_connect(clicked => \&quit);
+ $continue_button->signal_connect(clicked => sub { goto &$nextclosure });
+ add_button_box($vbox, $quit_button, $continue_button);
+ change_mainw($vbox);
+}
+
+sub ask_continue_blocking {
+ my ($msg) = @_;
+ my $w = Gtk2::MessageDialog->new($mainw, [qw(modal destroy-with-parent)], 'question', 'yes-no', $msg);
+ my $answer = $w->run;
+ $w->destroy;
+ quit if $answer eq 'no';
+}
+
+sub do_install {
+ wait_label;
+ my @ask_remove = $urpm->removed_packages($state);
+ @ask_remove
+ ? ask_continue(N(
+ "The following packages have to be removed for others to be upgraded:\n%s\nContinue?",
+ join "\n", $urpm->translate_why_removed($state, sort @ask_remove)
+ ), \&do_install_2)
+ : goto &do_install_2;
+}
+
+sub do_install_2 {
+ my @to_install;
+ foreach my $pkg (sort { $a->name cmp $b->name } @{$urpm->{depslist}}[keys %{$state->{selected}}]) {
+ $pkg->arch ne 'src' and push @to_install, scalar $pkg->fullname;
+ }
+ $urpm->{nb_install} = @to_install;
+ @to_install > 1
+ ? ask_continue(N(
+ "To satisfy dependencies, the following %d packages are going to be installed:\n%s\n",
+ scalar(@to_install), join "\n", @to_install
+ ), \&do_install_3)
+ : goto \&do_install_3;
+}
+
+sub do_install_3 {
+ wait_label(N("Package installation..."));
+ my ($local_sources, $list) = $urpm->get_source_packages($state->{selected});
+ $local_sources || $list or $urpm->{fatal}(3, N("unable to get source packages, aborting"));
+ my %sources = %$local_sources;
+ my %error_sources;
+ my $vbox = Gtk2::VBox->new(0, 5);
+ my $progress_label = Gtk2::Label->new('-');
+ $vbox->pack_start($progress_label, 1, 1, 0);
+ my $progressbar = Gtk2::ProgressBar->new;
+ $progressbar->set_size_request(300, -1);
+ $vbox->pack_start($progressbar, 0, 0, 0);
+ change_mainw($vbox);
+ $urpm->copy_packages_of_removable_media($list, \%sources,
+ force_local => 1,
+ ask_for_medium => sub {
+ my $w = Gtk2::MessageDialog->new($mainw, [qw(modal destroy-with-parent)], 'warning', 'ok',
+ N("Please insert the medium named \"%s\" on device [%s]", $_[0], $_[1])
+ );
+ $w->run;
+ $w->destroy;
+ }
+ );
+ $urpm->create_transaction(
+ $state,
+ split_level => $urpm->{options}{'split-level'},
+ split_length => $urpm->{options}{'split-length'},
+ );
+ my ($nok, @errors);
+ foreach my $set (@{$state->{transaction} || []}) {
+ my (@transaction_list, %transaction_sources);
+ $urpm->prepare_transaction($set, $list, \%sources, \@transaction_list, \%transaction_sources);
+ $urpm->download_packages_of_distant_media(
+ \@transaction_list,
+ \%transaction_sources,
+ \%error_sources,
+ limit_rate => $urpm->{options}{'limit-rate'},
+ compress => $urpm->{options}{compress},
+ resume => $urpm->{options}{resume},
+ force_local => 1,
+ callback => sub {
+ my ($mode, $file, $percent) = @_;
+ if ($mode eq 'start') {
+ $file =~ s|/*\s*$||; $file =~ s|.*/||;
+ $progress_label->set_label(N("Downloading package `%s'...", $file));
+ select(undef, undef, undef, 0.1); #- hackish
+ } elsif ($mode eq 'progress') {
+ $progressbar->set_fraction($percent / 100);
+ } elsif ($mode eq 'end') {
+ $progressbar->set_fraction(1);
+ }
+ sync();
+ },
+ );
+ my %transaction_sources_install = %{$urpm->extract_packages_to_install(\%transaction_sources) || {}};
+ if (!$urpm->{options}{'verify-rpm'} || grep { $_->{'verify-rpm'} } @{$urpm->{media}}) {
+ my @bad_signatures = $urpm->check_sources_signatures(\%transaction_sources_install, \%transaction_sources, translate => 1);
+ if (@bad_signatures) {
+ ask_continue_blocking(N(
+ "The following packages have bad signatures:\n%s\n\nDo you want to continue installation ?",
+ (join "\n", @bad_signatures)
+ ));
+ }
+ }
+ #- check for local files.
+ if (my @missing = grep { m|^/| && ! -e $_ } values %transaction_sources_install, values %transaction_sources) {
+ $urpm->{error}(N("Installation failed, some files are missing:\n%s\nYou may want to update your urpmi database",
+ join "\n", map { s|([^:]*://[^/:\@]*:)[^/:\@]*(\@.*)|$1xxxx$2|; " $_" } @missing));
+ ++$nok;
+ next;
+ }
+ if (keys(%transaction_sources_install) || keys(%transaction_sources)) {
+ @{$set->{remove} || []} and
+ $progress_label->set_label(N("removing %s", join(' ', @{$set->{remove} || []})));
+ my $progress_nb;
+ my $total_nb = scalar grep { m|^/| } values %transaction_sources_install, values %transaction_sources;
+ my $callback_inst = sub {
+ my ($urpm, $type, $id, $subtype, $amount, $total) = @_;
+ my $pkg = defined $id && $urpm->{depslist}[$id];
+ if ($subtype eq 'start') {
+ if ($type eq 'trans') {
+ $progress_label->set_label(N("Preparing..."));
+ } else {
+ $progress_label->set_label(N("Installing package `%s' (%s/%s)...", $pkg->name, ++$progress_nb, $urpm->{nb_install}));
+ }
+ } elsif ($subtype eq 'progress') {
+ $progressbar->set_fraction($amount / $total);
+ }
+ sync();
+ };
+ my @l = $urpm->install(
+ $set->{remove} || [],
+ \%transaction_sources_install,
+ \%transaction_sources,
+ 'fork' => @{$state->{transaction} || []} > 1, #- fork if multiple transaction
+ translate_message => 1,
+ oldpackage => $state->{oldpackage},
+ callback_inst => $callback_inst,
+ callback_trans => $callback_inst,
+ );
+ if (@l) {
+ $progress_label->set_label(N("Installation failed") . ":\n" . join("\n", map { "\t$_" } @l));
+ ++$nok;
+ push @errors, @l;
+ }
+ }
+ }
+ $vbox = Gtk2::VBox->new(0, 5);
+ $progress_label = Gtk2::Label->new('-');
+ $vbox->pack_start($progress_label, 1, 1, 0);
+ my $quit_button = Gtk2::Button->new(but N("_Done"));
+ $quit_button->signal_connect(clicked => \&quit);
+ add_button_box($vbox, $quit_button);
+ change_mainw($vbox);
+ if (values %error_sources) {
+ $progress_label->set_label(N("Installation failed, some files are missing:\n%s\nYou may want to update your urpmi database",
+ join "\n", map { s|([^:]*://[^/:\@]*:)[^/:\@]*(\@.*)|$1xxxx$2|; " $_" } values %error_sources));
+ } elsif (@{$state->{transaction} || []} == 0 && @ask_unselect == 0) {
+ $progress_label->set_label(N("The package(s) are already installed"));
+ } else {
+ $progress_label->set_label(N("Installation finished"));
+ }
+ $urpm->unlock_urpmi_db;
+ $urpm->unlock_rpm_db;
+ $urpm->try_umounting_removables;
+}