/[soft]/rpm/urpmi/trunk/gurpmi2
ViewVC logotype

Contents of /rpm/urpmi/trunk/gurpmi2

Parent Directory Parent Directory | Revision Log Revision Log


Revision 8305 - (show annotations) (download)
Fri May 17 10:30:31 2013 UTC (10 years, 10 months ago) by tv
File size: 13530 byte(s)
do not popup errors at end in auto mode
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";
10 delete @ENV{qw(ENV BASH_ENV IFS CDPATH)};
11 }
12
13 use gurpmi;
14 use gurpm::RPMProgressDialog;
15 use urpm::install;
16 use urpm::media;
17 use urpm::signature;
18 use urpm::get_pkgs;
19 use urpm::msg;
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 # For other distros w/o exception support:
32 eval { Glib->enable_exceptions2 };
33 if (my $err = $@) {
34 warn "Error: $err\n";
35 }
36
37 #- GUI globals
38 my $mainw;
39
40 my @all_rpms = gurpmi::parse_command_line();
41
42 $> and fatal(N("Must be root"));
43
44 #- Now, the graphical stuff.
45
46 Gtk2->init;
47
48 #- Initialize urpm
49
50 my $urpm;
51 {
52 local @ARGV = @ARGV;
53 $urpm = urpm->new_parse_cmdline;
54 }
55
56 #- Create main window
57
58 $mainw = gurpm::RPMProgressDialog->new($urpm, \&quit);
59
60 #- Performs installation
61
62 configure_urpm($urpm);
63
64 my $state = {};
65 my %requested = $urpm->register_rpms(@all_rpms);
66 if (@gurpmi::names) {
67 urpm::select::search_packages($urpm, \%requested, [ @gurpmi::names ],
68 use_provides => $use_provides,
69 ) || $force or exit 1;
70 }
71
72 $mainw->label(N("Preparing packages installation..."));
73
74 #- return value is true if program should be restarted (in order to take care of important
75 #- packages being upgraded (problably urpmi and perl-URPM, but maybe rpm too, and glibc also ?).
76 my $restart_itself = urpm::select::resolve_dependencies($urpm,
77 $state,
78 \%requested,
79 callback_choices => \&ask_choice,
80 auto_select => $::auto_select,
81 priority_upgrade => $urpm->{options}{'priority-upgrade'},
82 );
83 my @ask_unselect = urpm::select::unselected_packages($state);
84
85 # If there are some unselected packages, designate that we are going to return nonzero code.
86 if (@ask_unselect) {
87 my $unselect_msg = N("Some requested packages cannot be installed:\n%s",
88 urpm::select::translate_why_unselected($urpm, $state, @ask_unselect));
89 $urpm::postponed_msg .= $unselect_msg . "\n";
90 $urpm::postponed_code = 17;
91 }
92
93 @ask_unselect
94 ? ask_continue(N(
95 "Some requested packages cannot be installed:\n%s\nContinue installation anyway?",
96 urpm::select::translate_why_unselected($urpm, $state, @ask_unselect)
97 ), \&do_install)
98 : do_install();
99
100 $mainw->show_all;
101 Gtk2->main;
102
103 my ($rpm_lock, $urpmi_lock);
104
105 sub ask_warn {
106 my ($message) = @_;
107 printf STDERR "%s\n", $message;
108
109 if (my $download_errors = delete $urpm->{download_errors}) {
110 $message = join("\n", @$download_errors, $message);
111 }
112 my $nb_lines = $message =~ tr/\n/\n/;
113 my $w;
114 if ($nb_lines > 30 || $message =~ /^transaction is too small/) {
115 $w = Gtk2::Dialog->new(N("Warning"), $mainw, [qw(modal destroy-with-parent)], N("Ok"), 'ok');
116 $w->vbox->add(my $f = Gtk2::Frame->new);
117 my $sw = create_scrolled_window(my $text = Gtk2::TextView->new);
118 $sw->set_border_width(2);
119 $text->set_wrap_mode('word');
120 $f->add($sw);
121 $text->get_buffer->set_text($message);
122 $text->set_editable(0);
123 $_->show foreach $f, $sw, $text;
124 $w->set_size_request(400, 400);
125 $w->set_default_response('ok');
126 } else {
127 $w = Gtk2::MessageDialog->new($mainw, [qw(modal destroy-with-parent)], 'warning', 'ok', $message);
128 }
129 $w->run;
130 $w->destroy;
131 }
132
133 #- Creates and configure an urpm object for this application to use.
134 sub configure_urpm {
135 my ($urpm) = @_;
136
137 $urpm->{fatal} = sub {
138 printf STDERR "%s\n", $_[1];
139 Gtk2::MessageDialog->new($mainw, [qw(modal destroy-with-parent)], 'error', 'ok', Locale::gettext::iconv($_[1], undef, 'UTF-8'))->run;
140 quit();
141 exit $_[0];
142 };
143 $urpm->{log} = sub { printf "%s\n", $_[0] };
144 $urpm->{error} = \&ask_warn;
145 urpm::select::set_priority_upgrade_option($urpm, $gurpmi::options{previous_priority_upgrade});
146 $rpm_lock = urpm::lock::rpm_db($urpm, 'exclusive');
147 $urpmi_lock = urpm::lock::urpmi_db($urpm);
148 urpm::media::configure($urpm,
149 media => $gurpmi::options{media},
150 searchmedia => $gurpmi::options{searchmedia},
151 update => $::update,
152 );
153 $urpm->{options}{'verify-rpm'} = 0 if $gurpmi::options{'no-verify-rpm'};
154 }
155
156 #- Callback for choices
157 sub ask_choice {
158 my (undef, undef, undef, $choices) = @_;
159 return $choices->[0] if $gurpmi::options{auto};
160 my $radio;
161 my @radios = map {
162 $radio = Gtk2::RadioButton->new_with_label(
163 $radio ? $radio->get_group : undef,
164 (scalar $_->fullname) . " : " . $_->summary
165 . ($_->flag_installed ? N(" (to upgrade)") : '')
166 . ($_->flag_upgrade ? N(" (to install)") : '')
167 );
168 } @$choices;
169 my $d = Gtk2::Dialog->new(N("Package choice"), $mainw, [], N("_Cancel") => 0, N("_Ok") => 1);
170 my $label = Gtk2::Label->new(N("One of the following packages is needed:"));
171 $label->set_alignment(0.5, 0.5);
172 $d->vbox->pack_start($label, 1, 1, 0);
173 $d->vbox->pack_start($_, 1, 1, 0) foreach @radios;
174 my $n = 0;
175 $d->signal_connect(response => sub {
176 if ($_[1] == 1) { #- "ok"
177 foreach (@radios) { last if $_->get_active; ++$n }
178 }
179 $d->destroy;
180 exit(1) if $_[1] == 0; #- "cancel"
181 });
182 $radios[0]->set_active(1);
183 $d->set_default_response(1); # defaults to ok
184 $d->show_all;
185 $d->run;
186 $choices->[$n];
187 }
188
189 sub ask_continue {
190 my ($msg, $nextclosure, $o_list, $o_end_msg) = @_;
191 my $vbox = Gtk2::VBox->new(0, 5);
192 $vbox->pack_start(new_label($msg), 1, 1, 0);
193 $urpm->{log}($msg);
194 warn ">> o_list='$o_list'\n";
195 if ($o_end_msg) {
196 $vbox->pack_start(new_label($o_list), 1, 1, 0);
197 $vbox->pack_start(new_label($o_end_msg), 1, 1, 0);
198 }
199 my $continue_button = Gtk2::Button->new(but(N("_Ok")));
200 my $quit_button = Gtk2::Button->new(but(N("_Abort")));
201 $quit_button->signal_connect(clicked => sub { $urpm->{log}("=> cancel"); &quit(); exit 1 });
202 $continue_button->signal_connect(clicked => sub { $urpm->{log}("=> ok"); goto &$nextclosure });
203 add_button_box($vbox, $quit_button, $continue_button);
204 $mainw->change_widget($vbox);
205 # default is to continue, but according to some HIG, warning should reverse the choise and defaults to abort
206 $mainw->set_focus($continue_button); # also set_default should be called but it gives a warning!
207 }
208
209 sub ask_continue_if_no_auto {
210 my ($msg, $nextclosure, $o_list, $o_end_msg) = @_;
211 if ($gurpmi::options{auto}) {
212 $urpm->{log}($msg);
213 $urpm->{log}("=> ok(auto)");
214 goto &$nextclosure;
215 } else {
216 ask_continue($msg, $nextclosure, $o_list, $o_end_msg);
217 }
218 }
219
220 sub ask_continue_blocking {
221 my ($msg) = @_;
222 my $w = Gtk2::MessageDialog->new($mainw, [qw(modal destroy-with-parent)], 'question', 'yes-no', $msg);
223 my $answer = $w->run;
224 $w->destroy;
225 $urpm->{log}($msg . " => " . $answer);
226 exit(1) if $answer eq 'no';
227 1;
228 }
229
230 sub do_install {
231 $mainw->label;
232 my @ask_remove = urpm::select::removed_packages($state);
233 @ask_remove
234 ? ask_continue_if_no_auto(N(
235 "The following packages have to be removed for others to be upgraded:\n%s\nContinue installation anyway?",
236 urpm::select::translate_why_removed($urpm, $state, @ask_remove)
237 ), \&do_install_2)
238 : goto &do_install_2;
239 }
240
241 sub do_install_2 () {
242 my @to_install = map { scalar $_->fullname } @{$urpm->{depslist}}[sort { $a <=> $b } keys %{$state->{selected}}]; # sorted by medium for format_selected_packages
243 $urpm->{nb_install} = @to_install;
244 my ($size, $filesize) = $urpm->selected_size_filesize($state);
245 my $msg2 = $size >= 0 ?
246 N("%s of additional disk space will be used.", formatXiB($size)) :
247 N("%s of disk space will be freed.", formatXiB(-$size));
248 my $msg2_ = $filesize ? "\n" . N("%s of packages will be retrieved.", formatXiB($filesize)) . "\n" : '';
249 my $msg3 = P("Proceed with the installation of one package?",
250 "Proceed with the installation of the %d packages?",
251 $urpm->{nb_install}, $urpm->{nb_install});
252 @to_install > 1
253 ? ask_continue_if_no_auto(
254 (scalar(@to_install) == 1 ?
255 N("To satisfy dependencies, the following package is going to be installed:")
256 : N("To satisfy dependencies, the following packages are going to be installed:")),
257 \&do_install_3,
258 join("\n", sort @to_install),
259 $msg2 . $msg2_ . $msg3)
260 : goto \&do_install_3;
261 }
262
263 sub do_install_3 () {
264 $mainw->label($mainw->title);
265 my ($local_sources, $blists) = urpm::get_pkgs::selected2local_and_blists($urpm, $state->{selected});
266 $local_sources || $blists or $urpm->{fatal}(3, N("unable to get source packages, aborting"));
267
268 $mainw->init_progressbar;
269
270 my @errors;
271 local $urpm->{error} = sub { warn "@_\n"; push @errors, @_ };
272
273 my $exit_code;
274 $exit_code = urpm::main_loop::run($urpm, $state, scalar(@gurpmi::names), \@ask_unselect, {
275 bad_signature => sub {
276 my ($msg, $msg2) = @_;
277 $urpm->{log}("$msg\n$msg2");
278 ask_continue_blocking("$msg\n$msg2");
279 },
280 copy_removable => sub {
281 #FIXME: use use udisks to wait-for/mount cdroms:
282 my $w = Gtk2::MessageDialog->new($mainw, [qw(modal destroy-with-parent)], 'warning', 'ok-cancel',
283 N("Please insert the medium named \"%s\"", $_[0])
284 );
285 my $response = $w->run;
286 $w->destroy;
287 exit 1 if $response eq 'cancel';
288 1;
289 },
290 trans_log => \&gurpm::RPMProgressDialog::callback_download,
291 post_download => sub {
292 if ($mainw->canceled) {
293 $exit_code = 10;
294 goto return_with_exit_code;
295 }
296 $mainw->invalidate_cancel_forever;
297 },
298
299 ask_yes_or_no => \&ask_yes_or_no,
300
301 completed => sub {
302 if (@errors && !$gurpmi::options{auto}) {
303 ask_warn(N("An error occurred:") . "\n\n" . join("\n", @errors));
304 }
305
306 $urpmi_lock->unlock;
307 $rpm_lock->unlock;
308 urpm::removable::try_umounting_removables($urpm);
309 my $vbox = Gtk2::VBox->new(0, 5); # FIXME: should it be change_widget???
310 my $progress_label = Gtk2::Label->new('-'); # TEST ME
311 return 0 if $gurpmi::options{auto};
312 my $sw = create_scrolled_window($progress_label);
313 $sw->set_size_request(500, 200);
314 $vbox->pack_start($sw, 1, 1, 0);
315 my $quit_button = Gtk2::Button->new(but(N("_Done")));
316 $quit_button->signal_connect(clicked => \&quit);
317 add_button_box($vbox, $quit_button);
318 $mainw->change_widget($vbox);
319 $mainw->set_focus($quit_button);
320 },
321 need_restart => sub {
322 return if $gurpmi::options{auto};
323 my ($need_restart_formatted) = @_;
324 my $w = Gtk2::MessageDialog->new($mainw, [qw(modal destroy-with-parent)], 'warning', 'ok',
325 join("\n", values %$need_restart_formatted)
326 );
327 $w->run;
328 $w->destroy;
329 },
330 missing_files_summary => sub {
331 my ($error_sources) = @_;
332 $mainw->set_progresslabel(N("Installation failed, some files are missing:\n%s",
333 join("\n", map { s|([^:]*://[^/:\@]*:)[^/:\@]*(\@.*)|$1xxxx$2|; " $_" }
334 values %$error_sources))
335 . "\n" . N("You may want to update your urpmi database."));
336 },
337 trans_error_summary => sub {
338 my ($_nok, $errors) = @_;
339 $mainw->set_progresslabel(N("Installation failed:") . "\n" . join("\n", map { "\t$_" } @$errors));
340 },
341 # TODO: use urpmi strings:
342 already_installed_or_not_installable => sub {
343 my ($_msg1, $_msg2) = @_;
344 $mainw->set_progresslabel(N("The package(s) are already installed"));
345 },
346 success_summary => sub { $mainw->set_progresslabel(N("Installation finished")) },
347 pre_check_sig => \&gurpm::RPMProgressDialog::callback_pre_check_sig,
348 uninst => \&gurpm::RPMProgressDialog::callback_inst,
349 inst => \&gurpm::RPMProgressDialog::callback_inst,
350 trans => \&gurpm::RPMProgressDialog::callback_inst,
351 }
352 );
353
354 # Merge postponed exit code to the result of package installation.
355 $exit_code ||= $urpm::postponed_code;
356
357 #- restart gurpmi if needed, keep command line for that.
358 if ($restart_itself && !$exit_code) {
359 print N("restarting urpmi"), "\n";
360 #- it seems to work correctly with exec instead of system, provided
361 #- added --previous-priority-upgrade to allow checking if yet if
362 #- priority-upgrade list has changed. and make sure we don't uselessly restart
363 @ARGV = ('--previous-priority-upgrade=' . $urpm->{options}{'priority-upgrade'},
364 grep { !/^--no-priority-upgrade$|--previous-priority-upgrade=/ } @ARGV);
365 exec $0, @ARGV;
366 }
367
368 return_with_exit_code:
369 # Show postponed message before exiting
370 $urpm->{error}->($urpm::postponed_msg) if $urpm::postponed_code != 0;
371
372 exit $exit_code;
373 }
374
375 sub ask_yes_or_no {
376 my ($_title, $msg) = @_;
377 # MessageDialogs have no titles unless using 'secondary-text'
378 my $w = Gtk2::MessageDialog->new($mainw, [qw(modal destroy-with-parent)], 'warning', 'yes-no', $msg);
379 my $response = $w->run;
380 $w->destroy;
381 $response eq 'yes';
382 }
383
384

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.30