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

Contents of /rpm/urpmi/branches/2/gurpmi2

Parent Directory Parent Directory | Revision Log Revision Log


Revision 7881 - (show annotations) (download)
Mon Apr 15 05:51:50 2013 UTC (11 years ago) by tv
File size: 15872 byte(s)
add scrollbar for long one liner messages (mga#5118)
1 #!/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
110 # If there are some unselected packages, designate that we are going to return nonzero code.
111 if (@ask_unselect) {
112 my $unselect_msg = N("Some requested packages cannot be installed:\n%s",
113 urpm::select::translate_why_unselected($urpm, $state, @ask_unselect));
114 $urpm::postponed_msg .= $unselect_msg . "\n";
115 $urpm::postponed_code = 17;
116 }
117
118 @ask_unselect
119 ? ask_continue(N(
120 "Some requested packages cannot be installed:\n%s\nContinue installation anyway?",
121 urpm::select::translate_why_unselected($urpm, $state, @ask_unselect)
122 ), \&do_install)
123 : do_install();
124
125 $mainw->show_all;
126 Gtk2->main;
127
128 my ($rpm_lock, $urpmi_lock);
129
130 #- Creates and configure an urpm object for this application to use.
131 sub configure_urpm() {
132 my $urpm;
133 {
134 local @ARGV = @ARGV;
135 $urpm = urpm->new_parse_cmdline;
136 }
137
138 $urpm->{fatal} = sub {
139 printf STDERR "%s\n", $_[1];
140 Gtk2::MessageDialog->new($mainw, [qw(modal destroy-with-parent)], 'error', 'ok', Locale::gettext::iconv($_[1], undef, 'UTF-8'))->run;
141 quit();
142 exit $_[0];
143 };
144 $urpm->{log} = sub { printf "%s\n", $_[0] };
145 $urpm->{error} = sub {
146 my ($message) = @_;
147 printf STDERR "%s\n", $message;
148
149 if (my $download_errors = delete $urpm->{download_errors}) {
150 $message = join("\n", @$download_errors, $message);
151 }
152 my $nb_lines = $message =~ tr/\n/\n/;
153 my $w;
154 if ($nb_lines > 30 || $message =~ /^transaction is too small/) {
155 $w = Gtk2::Dialog->new(N("Warning"), $mainw, [qw(modal destroy-with-parent)], N("Ok"), 'ok');
156 $w->vbox->add(my $f = Gtk2::Frame->new);
157 my $sw = create_scrolled_window(my $text = Gtk2::TextView->new);
158 $sw->set_border_width(2);
159 $text->set_wrap_mode('word');
160 $f->add($sw);
161 $text->get_buffer->set_text($message);
162 $text->set_editable(0);
163 $_->show foreach $f, $sw, $text;
164 $w->set_size_request(400, 400);
165 $w->set_default_response('ok');
166 } else {
167 $w = Gtk2::MessageDialog->new($mainw, [qw(modal destroy-with-parent)], 'warning', 'ok', $message);
168 }
169 $w->run;
170 $w->destroy;
171 };
172 urpm::select::set_priority_upgrade_option($urpm, $gurpmi::options{previous_priority_upgrade});
173 $rpm_lock = urpm::lock::rpm_db($urpm, 'exclusive');
174 $urpmi_lock = urpm::lock::urpmi_db($urpm);
175 urpm::media::configure($urpm,
176 media => $gurpmi::options{media},
177 searchmedia => $gurpmi::options{searchmedia},
178 update => $::update,
179 );
180 $urpm->{options}{'verify-rpm'} = 0 if $gurpmi::options{'no-verify-rpm'};
181 $urpm;
182 }
183
184 #- Callback for choices
185 sub ask_choice {
186 my (undef, undef, undef, $choices) = @_;
187 return $choices->[0] if $gurpmi::options{auto};
188 my $radio;
189 my @radios = map {
190 $radio = Gtk2::RadioButton->new_with_label(
191 $radio ? $radio->get_group : undef,
192 (scalar $_->fullname) . " : " . $_->summary
193 . ($_->flag_installed ? N(" (to upgrade)") : '')
194 . ($_->flag_upgrade ? N(" (to install)") : '')
195 );
196 } @$choices;
197 my $d = Gtk2::Dialog->new(N("Package choice"), $mainw, [], N("_Cancel") => 0, N("_Ok") => 1);
198 my $label = Gtk2::Label->new(N("One of the following packages is needed:"));
199 $label->set_alignment(0.5, 0.5);
200 $d->vbox->pack_start($label, 1, 1, 0);
201 $d->vbox->pack_start($_, 1, 1, 0) foreach @radios;
202 my $n = 0;
203 $d->signal_connect(response => sub {
204 if ($_[1] == 1) { #- "ok"
205 foreach (@radios) { last if $_->get_active; ++$n }
206 }
207 $d->destroy;
208 exit(1) if $_[1] == 0; #- "cancel"
209 });
210 $radios[0]->set_active(1);
211 $d->set_default_response(1); # defaults to ok
212 $d->show_all;
213 $d->run;
214 $choices->[$n];
215 }
216
217 sub ask_continue {
218 my ($msg, $nextclosure) = @_;
219 my $vbox = Gtk2::VBox->new(0, 5);
220 $vbox->pack_start(new_label($msg), 1, 1, 0);
221 $urpm->{log}($msg);
222 my $continue_button = Gtk2::Button->new(but(N("_Ok")));
223 my $quit_button = Gtk2::Button->new(but(N("_Abort")));
224 $quit_button->signal_connect(clicked => sub { $urpm->{log}("=> cancel"); &quit(); exit 1 });
225 $continue_button->signal_connect(clicked => sub { $urpm->{log}("=> ok"); goto &$nextclosure });
226 add_button_box($vbox, $quit_button, $continue_button);
227 change_mainw($vbox);
228 # default is to continue, but according to some HIG, warning should reverse the choise and defaults to abort
229 $mainw->set_focus($continue_button); # also set_default should be called but it gives a warning!
230 }
231
232 sub ask_continue_if_no_auto {
233 my ($msg, $nextclosure) = @_;
234 if ($gurpmi::options{auto}) {
235 $urpm->{log}($msg);
236 $urpm->{log}("=> ok(auto)");
237 goto &$nextclosure;
238 } else {
239 ask_continue($msg, $nextclosure);
240 }
241 }
242
243 sub ask_continue_blocking {
244 my ($msg) = @_;
245 my $w = Gtk2::MessageDialog->new($mainw, [qw(modal destroy-with-parent)], 'question', 'yes-no', $msg);
246 my $answer = $w->run;
247 $w->destroy;
248 $urpm->{log}($msg . " => " . $answer);
249 exit(1) if $answer eq 'no';
250 1;
251 }
252
253 sub do_install {
254 wait_label();
255 my @ask_remove = urpm::select::removed_packages($urpm, $state);
256 @ask_remove
257 ? ask_continue_if_no_auto(N(
258 "The following packages have to be removed for others to be upgraded:\n%s\nContinue installation anyway?",
259 urpm::select::translate_why_removed($urpm, $state, @ask_remove)
260 ), \&do_install_2)
261 : goto &do_install_2;
262 }
263
264 sub do_install_2 () {
265 my @to_install;
266 my $sum;
267 foreach my $pkg (sort { $a->name cmp $b->name } @{$urpm->{depslist}}[keys %{$state->{selected}}]) {
268 if ($pkg->arch ne 'src') {
269 push @to_install, scalar $pkg->fullname;
270 $sum += $pkg->size;
271 }
272 }
273 $urpm->{nb_install} = @to_install;
274 @to_install > 1
275 ? ask_continue_if_no_auto(
276 (scalar(@to_install) == 1 ?
277 N("To satisfy dependencies, the following package is going to be installed:")
278 : N("To satisfy dependencies, the following packages are going to be installed:"))
279 . join("\n", '', @to_install, '')
280 . P("(%d package, %d MB)", "(%d packages, %d MB)", scalar(@to_install), scalar(@to_install), toMb($sum)),
281 , \&do_install_3)
282 : goto \&do_install_3;
283 }
284
285 sub do_install_3 () {
286 wait_label($title);
287 my ($local_sources, $blists) = urpm::get_pkgs::selected2local_and_blists($urpm, $state->{selected});
288 $local_sources || $blists or $urpm->{fatal}(3, N("unable to get source packages, aborting"));
289 my $vbox = Gtk2::VBox->new(0, 5);
290
291 my $global_label = gtk_new_Label_Left("<b>$title</b>");
292 $global_label->set_use_markup(1);
293 $vbox->pack_start($global_label, 0, 0, 0);
294
295 my $global_progressbar = Gtk2::ProgressBar->new;
296 $vbox->pack_start($global_progressbar, 0, 0, 0);
297
298 my $progress_label = gtk_new_Label_Left('-');
299 $vbox->pack_start($progress_label, 1, 1, 0);
300
301
302 my $progressbar = Gtk2::ProgressBar->new;
303 $progressbar->set_size_request($progressbar_size, -1);
304 $vbox->pack_start($progressbar, 0, 0, 0);
305
306 change_mainw($vbox);
307 my ($progress_nb, $download_nb);
308 my $set_progressbar = sub {
309 my ($local_ratio) = @_;
310 if ($progress_nb || $download_nb) { # this happens when computing transaction
311 $global_progressbar->set_fraction(($download_nb + $progress_nb - 1 + $local_ratio) / 2 / $urpm->{nb_install});
312 }
313 $progressbar->set_fraction($local_ratio);
314 };
315 my $callback_inst = sub {
316 my ($urpm, $type, $id, $subtype, $amount, $total) = @_;
317 my $pkg = defined $id ? $urpm->{depslist}[$id] : undef;
318 if ($subtype eq 'start') {
319 if ($type eq 'trans') {
320 $progress_label->set_label(N("Preparing..."));
321 } elsif ($pkg) {
322 $progress_nb++;
323 $download_nb = max($download_nb, $progress_nb);
324 $set_progressbar->(0);
325 $progress_label->set_label(
326 N("Installing package `%s' (%s/%s)...", $pkg->name, $progress_nb, $urpm->{nb_install})
327 );
328 }
329 } elsif ($subtype eq 'progress') {
330 $set_progressbar->($amount / $total);
331 }
332 sync();
333 };
334
335 my $exit_code = urpm::main_loop::run($urpm, $state, scalar(@gurpmi::names), \@ask_unselect, \%requested, {
336 bad_signature => sub {
337 my ($msg, $msg2) = @_;
338 $urpm->{log}("$msg\n$msg2");
339 ask_continue_blocking("$msg\n$msg2");
340 },
341 copy_removable => sub {
342 #FIXME: use use hal to wait-for/mount cdroms:
343 my $w = Gtk2::MessageDialog->new($mainw, [qw(modal destroy-with-parent)], 'warning', 'ok-cancel',
344 N("Please insert the medium named \"%s\"", $_[0])
345 );
346 my $response = $w->run;
347 $w->destroy;
348 exit 1 if $response eq 'cancel';
349 1;
350 },
351 trans_log => sub {
352 my ($mode, $file, $percent, $_total, $_eta, $_speed) = @_;
353
354 urpm::download::sync_logger(@_);
355
356 if (member($mode, 'start', 'progress')) {
357 $file =~ s|/*\s*$||; $file =~ s|.*/||;
358 $progress_label->set_label(N("Downloading package `%s'...", $file) . "\n" . &urpm::download::progress_text);
359 }
360 if ($mode eq 'start') {
361 $download_nb++;
362 $set_progressbar->(0);
363 select(undef, undef, undef, 0.1); #- hackish
364 } elsif ($mode eq 'progress') {
365 $set_progressbar->($percent / 100);
366 } elsif ($mode eq 'end') {
367 $set_progressbar->(1);
368 } elsif ($mode eq 'error') {
369 #- error is 3rd argument, saved in $percent
370 push @{$urpm->{download_errors}}, N("...retrieving failed: %s", $percent);
371 }
372 sync();
373 },
374 ask_yes_or_no => \&ask_yes_or_no,
375
376 completed => sub {
377 $urpmi_lock->unlock;
378 $rpm_lock->unlock;
379 urpm::removable::try_umounting_removables($urpm);
380 $vbox = Gtk2::VBox->new(0, 5);
381 $progress_label = Gtk2::Label->new('-');
382 return 0 if $gurpmi::options{auto};
383 my $sw = create_scrolled_window($progress_label);
384 $sw->set_size_request(500, 200);
385 $vbox->pack_start($sw, 1, 1, 0);
386 my $quit_button = Gtk2::Button->new(but(N("_Done")));
387 $quit_button->signal_connect(clicked => \&quit);
388 add_button_box($vbox, $quit_button);
389 change_mainw($vbox);
390 $mainw->set_focus($quit_button);
391 },
392 need_restart => sub {
393 return if $gurpmi::options{auto};
394 my ($need_restart_formatted) = @_;
395 my $w = Gtk2::MessageDialog->new($mainw, [qw(modal destroy-with-parent)], 'warning', 'ok',
396 join("\n", values %$need_restart_formatted)
397 );
398 $w->run;
399 $w->destroy;
400 },
401 missing_files_summary => sub {
402 my ($error_sources) = @_;
403 $progress_label->set_label(N("Installation failed, some files are missing:\n%s\nYou may want to update your urpmi database",
404 join("\n", map { s|([^:]*://[^/:\@]*:)[^/:\@]*(\@.*)|$1xxxx$2|; " $_" }
405 values %$error_sources)));
406 },
407 trans_error_summary => sub {
408 my ($_nok, $errors) = @_;
409 $progress_label->set_label(N("Installation failed:") . "\n" . join("\n", map { "\t$_" } @$errors));
410 },
411 # TODO: use urpmi strings:
412 already_installed_or_not_installable => sub {
413 my ($_msg1, $_msg2) = @_;
414 $progress_label->set_label(N("The package(s) are already installed"));
415 },
416 success_summary => sub { $progress_label->set_label(N("Installation finished")) },
417 callback_report_uninst => sub { $progress_label->set_label(N("removing %s", $_[0])) },
418 inst => $callback_inst,
419 trans => $callback_inst,
420 }
421 );
422
423 # Merge postponed exit code to the result of package installation.
424 $exit_code ||= $urpm::postponed_code;
425
426 #- restart gurpmi if needed, keep command line for that.
427 if ($restart_itself && !$exit_code) {
428 print N("restarting urpmi"), "\n";
429 #- it seems to work correctly with exec instead of system, provided
430 #- added --previous-priority-upgrade to allow checking if yet if
431 #- priority-upgrade list has changed. and make sure we don't uselessly restart
432 @ARGV = ('--previous-priority-upgrade=' . $urpm->{options}{'priority-upgrade'},
433 grep { !/^--no-priority-upgrade$|--previous-priority-upgrade=/ } @ARGV);
434 exec $0, @ARGV;
435 }
436
437 # Show postponed message before exiting
438 $urpm->{error}->($urpm::postponed_msg) if $urpm::postponed_code != 0;
439
440 exit $exit_code;
441 }
442
443 sub ask_yes_or_no {
444 my ($_title, $msg) = @_;
445 # MessageDialogs have no titles unless using 'secondary-text'
446 my $w = Gtk2::MessageDialog->new($mainw, [qw(modal destroy-with-parent)], 'warning', 'yes-no', $msg);
447 my $response = $w->run;
448 $w->destroy;
449 $response eq 'yes';
450 }
451
452 sub gtk_new_Label_Left {
453 my ($text) = @_;
454 my $w = Gtk2::Label->new($text);
455 $w->set_alignment(0, 0);
456 $w;
457 }

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.30