/[soft]/rpm/urpmi/branches/1/gurpmi2
ViewVC logotype

Annotation of /rpm/urpmi/branches/1/gurpmi2

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1928 - (hide annotations) (download)
Tue Sep 13 20:44:28 2011 UTC (12 years, 7 months ago) by dmorgan
Original Path: rpm/urpmi/trunk/gurpmi2
File size: 15204 byte(s)
Import urpmi
1 dmorgan 1928 #!/usr/bin/perl
2    
3     #- Copyright (C) 2005 MandrakeSoft SA
4     #- Copyright (C) 2005-2010 Mandriva SA
5    
6     use strict;
7    
8     BEGIN { #- set up a safe path and environment
9     $ENV{PATH} = "/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin";
10     delete @ENV{qw(ENV BASH_ENV IFS CDPATH)};
11     }
12    
13     use gurpmi;
14     use urpm::install;
15     use urpm::media;
16     use urpm::signature;
17     use urpm::get_pkgs;
18     use urpm::msg;
19     use urpm::util;
20     use urpm::select;
21     use urpm::main_loop;
22     use Gtk2;
23    
24     #- default options.
25     our $allow_medium_change = 0;
26     our $auto_select = 0;
27     our $force = 0;
28     our $test = 0;
29     our $use_provides = 1;
30    
31     my $progressbar_size = 450;
32    
33     #- GUI globals
34     my ($mainw, $mainbox);
35    
36     #- Replaces the contents of the main window with the specified box
37     #- (avoids popup multiplication)
38     sub change_mainw {
39     $mainw->remove($mainbox);
40     ($mainbox) = @_;
41     $mainw->add($mainbox);
42     $mainw->show_all;
43     }
44    
45     sub sync () {
46     $mainw->show;
47     Gtk2->main_iteration while Gtk2->events_pending;
48     }
49    
50     #- sets the window to a please-wait message
51     sub wait_label {
52     my ($o_text) = @_;
53     my $wait_vbox = Gtk2::VBox->new(0, 5);
54     my $wait_label = Gtk2::Label->new($o_text || N("Please wait..."));
55     $wait_label->set_alignment(0.5, 0.5);
56     $wait_vbox->pack_start($wait_label, 1, 1, 0);
57     change_mainw($wait_vbox);
58     sync();
59     }
60    
61     my @all_rpms = gurpmi::parse_command_line();
62    
63     $> and fatal(N("Must be root"));
64    
65     #- Now, the graphical stuff.
66    
67     Gtk2->init;
68     Gtk2->croak_execeptions;
69    
70     my $title = $::auto_select ? N("Distribution Upgrade") : N("Packages installation");
71    
72     #- Create main window
73    
74     $mainw = Gtk2::Window->new('toplevel');
75     $::main_window = $mainw;
76     $mainw->set_border_width(12);
77     $mainw->set_title($title);
78     $mainw->signal_connect(destroy => \&quit);
79     $mainw->set_position('center');
80     $mainw->set_default_size($progressbar_size, 60);
81     $mainw->set_type_hint('dialog'); # for matchbox window manager during install
82     $mainw->set_modal(1); # for matchbox window manager during install
83     $mainbox = Gtk2::VBox->new(0, 5);
84     $mainw->add($mainbox);
85    
86     #- Performs installation
87    
88     my $urpm = configure_urpm();
89     my $state = {};
90     my %requested = $urpm->register_rpms(@all_rpms);
91     if (@gurpmi::names) {
92     urpm::select::search_packages($urpm, \%requested, [ @gurpmi::names ],
93     use_provides => $use_provides,
94     ) || $force or exit 1;
95     }
96    
97     wait_label(N("Preparing packages installation..."));
98    
99     #- return value is true if program should be restarted (in order to take care of important
100     #- packages being upgraded (problably urpmi and perl-URPM, but maybe rpm too, and glibc also ?).
101     my $restart_itself = urpm::select::resolve_dependencies($urpm,
102     $state,
103     \%requested,
104     callback_choices => \&ask_choice,
105     auto_select => $::auto_select,
106     priority_upgrade => $urpm->{options}{'priority-upgrade'},
107     );
108     my @ask_unselect = urpm::select::unselected_packages($urpm, $state);
109     @ask_unselect
110     ? ask_continue(N(
111     "Some requested packages cannot be installed:\n%s\nContinue installation anyway?",
112     urpm::select::translate_why_unselected($urpm, $state, @ask_unselect)
113     ), \&do_install)
114     : do_install();
115    
116     $mainw->show_all;
117     Gtk2->main;
118    
119     my ($rpm_lock, $urpmi_lock);
120    
121     #- Creates and configure an urpm object for this application to use.
122     sub configure_urpm() {
123     my $urpm;
124     {
125     local @ARGV = @ARGV;
126     $urpm = urpm->new_parse_cmdline;
127     }
128    
129     $urpm->{fatal} = sub {
130     printf STDERR "%s\n", $_[1];
131     Gtk2::MessageDialog->new($mainw, [qw(modal destroy-with-parent)], 'error', 'ok', Locale::gettext::iconv($_[1], undef, 'UTF-8'))->run;
132     quit();
133     exit $_[0];
134     };
135     $urpm->{log} = sub { printf "%s\n", $_[0] };
136     $urpm->{error} = sub {
137     my ($message) = @_;
138     printf STDERR "%s\n", $message;
139    
140     if (my $download_errors = delete $urpm->{download_errors}) {
141     $message = join("\n", @$download_errors, $message);
142     }
143     my $nb_lines = $message =~ tr/\n/\n/;
144     my $w;
145     if ($nb_lines > 30) {
146     $w = Gtk2::Dialog->new(N("Warning"), $mainw, [qw(modal destroy-with-parent)], N("Ok"), 'ok');
147     $w->vbox->add(my $f = Gtk2::Frame->new);
148     my $sw = create_scrolled_window(my $text = Gtk2::TextView->new);
149     $sw->set_border_width(2);
150     $f->add($sw);
151     $text->get_buffer->set_text($message);
152     $text->set_editable(0);
153     $_->show foreach $f, $sw, $text;
154     $w->set_size_request(400, 400);
155     $w->set_default_response('ok');
156     } else {
157     $w = Gtk2::MessageDialog->new($mainw, [qw(modal destroy-with-parent)], 'warning', 'ok', $message);
158     }
159     $w->run;
160     $w->destroy;
161     };
162     urpm::select::set_priority_upgrade_option($urpm, $gurpmi::options{previous_priority_upgrade});
163     $rpm_lock = urpm::lock::rpm_db($urpm, 'exclusive');
164     $urpmi_lock = urpm::lock::urpmi_db($urpm);
165     urpm::media::configure($urpm,
166     media => $gurpmi::options{media},
167     searchmedia => $gurpmi::options{searchmedia},
168     update => $::update,
169     );
170     $urpm->{options}{'verify-rpm'} = 0 if $gurpmi::options{'no-verify-rpm'};
171     $urpm;
172     }
173    
174     #- Callback for choices
175     sub ask_choice {
176     my (undef, undef, undef, $choices) = @_;
177     return $choices->[0] if $gurpmi::options{auto};
178     my $radio;
179     my @radios = map {
180     $radio = Gtk2::RadioButton->new_with_label(
181     $radio ? $radio->get_group : undef,
182     (scalar $_->fullname) . " : " . $_->summary
183     . ($_->flag_installed ? N(" (to upgrade)") : '')
184     . ($_->flag_upgrade ? N(" (to install)") : '')
185     );
186     } @$choices;
187     my $d = Gtk2::Dialog->new(N("Package choice"), $mainw, [], N("_Cancel") => 0, N("_Ok") => 1);
188     my $label = Gtk2::Label->new(N("One of the following packages is needed:"));
189     $label->set_alignment(0.5, 0.5);
190     $d->vbox->pack_start($label, 1, 1, 0);
191     $d->vbox->pack_start($_, 1, 1, 0) foreach @radios;
192     my $n = 0;
193     $d->signal_connect(response => sub {
194     if ($_[1] == 1) { #- "ok"
195     foreach (@radios) { last if $_->get_active; ++$n }
196     }
197     $d->destroy;
198     exit(1) if $_[1] == 0; #- "cancel"
199     });
200     $radios[0]->set_active(1);
201     $d->set_default_response(1); # defaults to ok
202     $d->show_all;
203     $d->run;
204     $choices->[$n];
205     }
206    
207     sub ask_continue {
208     my ($msg, $nextclosure) = @_;
209     my $vbox = Gtk2::VBox->new(0, 5);
210     $vbox->pack_start(new_label($msg), 1, 1, 0);
211     $urpm->{log}($msg);
212     my $continue_button = Gtk2::Button->new(but(N("_Ok")));
213     my $quit_button = Gtk2::Button->new(but(N("_Abort")));
214     $quit_button->signal_connect(clicked => sub { $urpm->{log}("=> cancel"); &quit(); exit 1 });
215     $continue_button->signal_connect(clicked => sub { $urpm->{log}("=> ok"); goto &$nextclosure });
216     add_button_box($vbox, $quit_button, $continue_button);
217     change_mainw($vbox);
218     # default is to continue, but according to some HIG, warning should reverse the choise and defaults to abort
219     $mainw->set_focus($continue_button); # also set_default should be called but it gives a warning!
220     }
221    
222     sub ask_continue_if_no_auto {
223     my ($msg, $nextclosure) = @_;
224     if ($gurpmi::options{auto}) {
225     $urpm->{log}($msg);
226     $urpm->{log}("=> ok(auto)");
227     goto &$nextclosure;
228     } else {
229     ask_continue($msg, $nextclosure);
230     }
231     }
232    
233     sub ask_continue_blocking {
234     my ($msg) = @_;
235     my $w = Gtk2::MessageDialog->new($mainw, [qw(modal destroy-with-parent)], 'question', 'yes-no', $msg);
236     my $answer = $w->run;
237     $w->destroy;
238     $urpm->{log}($msg . " => " . $answer);
239     exit(1) if $answer eq 'no';
240     1;
241     }
242    
243     sub do_install {
244     wait_label();
245     my @ask_remove = urpm::select::removed_packages($urpm, $state);
246     @ask_remove
247     ? ask_continue_if_no_auto(N(
248     "The following packages have to be removed for others to be upgraded:\n%s\nContinue installation anyway?",
249     urpm::select::translate_why_removed($urpm, $state, @ask_remove)
250     ), \&do_install_2)
251     : goto &do_install_2;
252     }
253    
254     sub do_install_2 () {
255     my @to_install;
256     my $sum;
257     foreach my $pkg (sort { $a->name cmp $b->name } @{$urpm->{depslist}}[keys %{$state->{selected}}]) {
258     if ($pkg->arch ne 'src') {
259     push @to_install, scalar $pkg->fullname;
260     $sum += $pkg->size;
261     }
262     }
263     $urpm->{nb_install} = @to_install;
264     @to_install > 1
265     ? ask_continue_if_no_auto(
266     (scalar(@to_install) == 1 ?
267     N("To satisfy dependencies, the following package is going to be installed:")
268     : N("To satisfy dependencies, the following packages are going to be installed:"))
269     . join("\n", '', @to_install, '')
270     . P("(%d package, %d MB)", "(%d packages, %d MB)", scalar(@to_install), scalar(@to_install), toMb($sum)),
271     , \&do_install_3)
272     : goto \&do_install_3;
273     }
274    
275     sub do_install_3 () {
276     wait_label($title);
277     my ($local_sources, $blists) = urpm::get_pkgs::selected2local_and_blists($urpm, $state->{selected});
278     $local_sources || $blists or $urpm->{fatal}(3, N("unable to get source packages, aborting"));
279     my $vbox = Gtk2::VBox->new(0, 5);
280    
281     my $global_label = gtk_new_Label_Left("<b>$title</b>");
282     $global_label->set_use_markup(1);
283     $vbox->pack_start($global_label, 0, 0, 0);
284    
285     my $global_progressbar = Gtk2::ProgressBar->new;
286     $vbox->pack_start($global_progressbar, 0, 0, 0);
287    
288     my $progress_label = gtk_new_Label_Left('-');
289     $vbox->pack_start($progress_label, 1, 1, 0);
290    
291    
292     my $progressbar = Gtk2::ProgressBar->new;
293     $progressbar->set_size_request($progressbar_size, -1);
294     $vbox->pack_start($progressbar, 0, 0, 0);
295    
296     change_mainw($vbox);
297     my ($progress_nb, $download_nb);
298     my $set_progressbar = sub {
299     my ($local_ratio) = @_;
300     if ($progress_nb || $download_nb) { # this happens when computing transaction
301     $global_progressbar->set_fraction(($download_nb + $progress_nb - 1 + $local_ratio) / 2 / $urpm->{nb_install});
302     }
303     $progressbar->set_fraction($local_ratio);
304     };
305     my $callback_inst = sub {
306     my ($urpm, $type, $id, $subtype, $amount, $total) = @_;
307     my $pkg = defined $id ? $urpm->{depslist}[$id] : undef;
308     if ($subtype eq 'start') {
309     if ($type eq 'trans') {
310     $progress_label->set_label(N("Preparing..."));
311     } elsif ($pkg) {
312     $progress_nb++;
313     $download_nb = max($download_nb, $progress_nb);
314     $set_progressbar->(0);
315     $progress_label->set_label(
316     N("Installing package `%s' (%s/%s)...", $pkg->name, $progress_nb, $urpm->{nb_install})
317     );
318     }
319     } elsif ($subtype eq 'progress') {
320     $set_progressbar->($amount / $total);
321     }
322     sync();
323     };
324    
325     my $exit_code = urpm::main_loop::run($urpm, $state, scalar(@gurpmi::names), \@ask_unselect, \%requested, {
326     bad_signature => sub {
327     my ($msg, $msg2) = @_;
328     $urpm->{log}("$msg\n$msg2");
329     ask_continue_blocking("$msg\n$msg2");
330     },
331     copy_removable => sub {
332     #FIXME: use use hal to wait-for/mount cdroms:
333     my $w = Gtk2::MessageDialog->new($mainw, [qw(modal destroy-with-parent)], 'warning', 'ok-cancel',
334     N("Please insert the medium named \"%s\"", $_[0])
335     );
336     my $response = $w->run;
337     $w->destroy;
338     exit 1 if $response eq 'cancel';
339     1;
340     },
341     trans_log => sub {
342     my ($mode, $file, $percent, $_total, $_eta, $_speed) = @_;
343    
344     urpm::download::sync_logger(@_);
345    
346     if (member($mode, 'start', 'progress')) {
347     $file =~ s|/*\s*$||; $file =~ s|.*/||;
348     $progress_label->set_label(N("Downloading package `%s'...", $file) . "\n" . &urpm::download::progress_text);
349     }
350     if ($mode eq 'start') {
351     $download_nb++;
352     $set_progressbar->(0);
353     select(undef, undef, undef, 0.1); #- hackish
354     } elsif ($mode eq 'progress') {
355     $set_progressbar->($percent / 100);
356     } elsif ($mode eq 'end') {
357     $set_progressbar->(1);
358     } elsif ($mode eq 'error') {
359     #- error is 3rd argument, saved in $percent
360     push @{$urpm->{download_errors}}, N("...retrieving failed: %s", $percent);
361     }
362     sync();
363     },
364     ask_yes_or_no => \&ask_yes_or_no,
365    
366     completed => sub {
367     $urpmi_lock->unlock;
368     $rpm_lock->unlock;
369     urpm::removable::try_umounting_removables($urpm);
370     $vbox = Gtk2::VBox->new(0, 5);
371     $progress_label = Gtk2::Label->new('-');
372     return 0 if $gurpmi::options{auto};
373     my $sw = create_scrolled_window($progress_label);
374     $sw->set_size_request(500, 200);
375     $vbox->pack_start($sw, 1, 1, 0);
376     my $quit_button = Gtk2::Button->new(but(N("_Done")));
377     $quit_button->signal_connect(clicked => \&quit);
378     add_button_box($vbox, $quit_button);
379     change_mainw($vbox);
380     $mainw->set_focus($quit_button);
381     },
382     need_restart => sub {
383     return if $gurpmi::options{auto};
384     my ($need_restart_formatted) = @_;
385     my $w = Gtk2::MessageDialog->new($mainw, [qw(modal destroy-with-parent)], 'warning', 'ok',
386     join("\n", values %$need_restart_formatted)
387     );
388     $w->run;
389     $w->destroy;
390     },
391     missing_files_summary => sub {
392     my ($error_sources) = @_;
393     $progress_label->set_label(N("Installation failed, some files are missing:\n%s\nYou may want to update your urpmi database",
394     join("\n", map { s|([^:]*://[^/:\@]*:)[^/:\@]*(\@.*)|$1xxxx$2|; " $_" }
395     values %$error_sources)));
396     },
397     trans_error_summary => sub {
398     my ($_nok, $errors) = @_;
399     $progress_label->set_label(N("Installation failed:") . "\n" . join("\n", map { "\t$_" } @$errors));
400     },
401     # TODO: use urpmi strings:
402     already_installed_or_not_installable => sub {
403     my ($_msg1, $_msg2) = @_;
404     $progress_label->set_label(N("The package(s) are already installed"));
405     },
406     success_summary => sub { $progress_label->set_label(N("Installation finished")) },
407     callback_report_uninst => sub { $progress_label->set_label(N("removing %s", $_[0])) },
408     inst => $callback_inst,
409     trans => $callback_inst,
410     }
411     );
412    
413     #- restart gurpmi if needed, keep command line for that.
414     if ($restart_itself && !$exit_code) {
415     print N("restarting urpmi"), "\n";
416     #- it seems to work correctly with exec instead of system, provided
417     #- added --previous-priority-upgrade to allow checking if yet if
418     #- priority-upgrade list has changed. and make sure we don't uselessly restart
419     @ARGV = ('--previous-priority-upgrade=' . $urpm->{options}{'priority-upgrade'},
420     grep { !/^--no-priority-upgrade$|--previous-priority-upgrade=/ } @ARGV);
421     exec $0, @ARGV;
422     }
423     exit $exit_code;
424     }
425    
426     sub ask_yes_or_no {
427     my ($_title, $msg) = @_;
428     # MessageDialogs have no titles unless using 'secondary-text'
429     my $w = Gtk2::MessageDialog->new($mainw, [qw(modal destroy-with-parent)], 'warning', 'yes-no', $msg);
430     my $response = $w->run;
431     $w->destroy;
432     $response eq 'yes';
433     }
434    
435     sub gtk_new_Label_Left {
436     my ($text) = @_;
437     my $w = Gtk2::Label->new($text);
438     $w->set_alignment(0, 0);
439     $w;
440     }

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.30