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

Contents of /rpm/urpmi/branches/1/gurpmi2

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3132 - (show annotations) (download)
Wed Feb 29 23:59:36 2012 UTC (8 years, 4 months ago) by tv
File size: 15204 byte(s)
branch

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 @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.28