1 |
#!/usr/bin/perl |
2 |
|
3 |
# $Id: urpmi 271299 2010-11-21 15:54:30Z peroyvind $ |
4 |
|
5 |
#- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 MandrakeSoft SA |
6 |
#- Copyright (C) 2005-2010 Mandriva SA |
7 |
#- |
8 |
#- This program is free software; you can redistribute it and/or modify |
9 |
#- it under the terms of the GNU General Public License as published by |
10 |
#- the Free Software Foundation; either version 2, or (at your option) |
11 |
#- any later version. |
12 |
#- |
13 |
#- This program is distributed in the hope that it will be useful, |
14 |
#- but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 |
#- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 |
#- GNU General Public License for more details. |
17 |
#- |
18 |
#- You should have received a copy of the GNU General Public License |
19 |
#- along with this program; if not, write to the Free Software |
20 |
#- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
21 |
|
22 |
use strict; |
23 |
use urpm; |
24 |
use urpm::args; |
25 |
use urpm::msg; |
26 |
use urpm::media; |
27 |
use urpm::select; |
28 |
use urpm::util qw(cat_ difference2 find member partition untaint); |
29 |
use urpm::main_loop; |
30 |
|
31 |
#- default options. |
32 |
our $update = 0; |
33 |
our $media = ''; |
34 |
our $searchmedia; |
35 |
our $excludemedia = ''; |
36 |
our $sortmedia = ''; |
37 |
our $allow_medium_change = 0; |
38 |
our $auto_select = 0; |
39 |
our $auto_update = 0; |
40 |
our $no_install = 0; |
41 |
our $no_remove = 0; |
42 |
our $install_src = 0; |
43 |
our $clean = 0; |
44 |
our $noclean = 0; |
45 |
our $force = 0; |
46 |
our $parallel = ''; |
47 |
our $env = ''; |
48 |
our $test = 0; |
49 |
our $all = 0; |
50 |
our $use_provides = 1; |
51 |
our $logfile = ''; |
52 |
our $restricted = 0; |
53 |
our $forcekey = 0; |
54 |
|
55 |
my @files; |
56 |
my @src_files; |
57 |
my @names; |
58 |
my @src_names; |
59 |
|
60 |
$ENV{PATH} = "/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin"; |
61 |
delete @ENV{qw(ENV BASH_ENV IFS CDPATH)}; |
62 |
$ENV{HOME} ||= "/root"; |
63 |
$ENV{USER} ||= "root"; |
64 |
|
65 |
sub usage () { |
66 |
print N("urpmi version %s |
67 |
Copyright (C) 1999-2010 Mandriva. |
68 |
This is free software and may be redistributed under the terms of the GNU GPL. |
69 |
|
70 |
usage: |
71 |
", $urpm::VERSION) . N(" --help - print this help message. |
72 |
") . N(" --media - use only the given media, separated by comma. |
73 |
") . N(" --excludemedia - do not use the given media, separated by comma. |
74 |
") . N(" --update - use only update media. |
75 |
") . N(" --searchmedia - use only the given media to search requested packages. |
76 |
") . N(" --sortmedia - sort media according to substrings separated by comma. |
77 |
") . N(" --synthesis - use the given synthesis instead of urpmi db. |
78 |
") . N(" --auto - non-interactive mode, assume default answers to questions. |
79 |
") . N(" --auto-select - automatically select packages to upgrade the system. |
80 |
") . N(" --auto-update - update media then upgrade the system. |
81 |
") . N(" --no-md5sum - disable MD5SUM file checking. |
82 |
") . N(" --force-key - force update of gpg key. |
83 |
") . N(" --auto-orphans - remove orphans without asking |
84 |
") . N(" --no-suggests - do not auto select \"suggested\" packages. |
85 |
") . N(" --no-uninstall - never ask to uninstall a package, abort the installation. |
86 |
") . N(" --no-install - don't install packages (only download) |
87 |
") . N(" --keep - keep existing packages if possible, reject requested |
88 |
packages that lead to removals. |
89 |
") . N(" --split-level - split in small transaction if more than given packages |
90 |
are going to be installed or upgraded, |
91 |
default is %d. |
92 |
", urpm::default_options()->{'split-level'}) |
93 |
. N(" --split-length - small transaction length, default is %d. |
94 |
", urpm::default_options()->{'split-length'}) |
95 |
. N(" --fuzzy, -y - impose fuzzy search. |
96 |
") . N(" --buildrequires - install the buildrequires of the packages |
97 |
") . N(" --install-src - install only source package (no binaries). |
98 |
") . N(" --clean - remove rpm from cache before anything else. |
99 |
") . N(" --noclean - don't clean rpms from cache. |
100 |
") . N(" --justdb - update only the rpm db, not the filesystem. |
101 |
") . N(" --replacepkgs - force installing packages which are already installed. |
102 |
") . N(" --force - force invocation even if some packages do not exist. |
103 |
") . N(" --allow-nodeps - allow asking user to install packages without |
104 |
dependencies checking. |
105 |
") . N(" --allow-force - allow asking user to install packages without |
106 |
dependencies checking and integrity. |
107 |
") . N(" --allow-suggests - auto select \"suggested\" packages. |
108 |
") . N(" --parallel - distributed urpmi across machines of alias. |
109 |
") . N(" --root - use another root for rpm installation. |
110 |
") . N(" --urpmi-root - use another root for urpmi db & rpm installation. |
111 |
") . N(" --use-distrib - configure urpmi on the fly from a distrib tree, useful |
112 |
to install a chroot with --root option. |
113 |
") . N(" --metalink - generate and use a local metalink. |
114 |
") . N(" --download-all - download all needed packages before trying to install them |
115 |
") . N(" --downloader - program to use to retrieve distant files. |
116 |
known programs: %s |
117 |
", join(', ', urpm::download::ftp_http_downloaders())) |
118 |
. N(" --curl-options - additional options to pass to curl |
119 |
") . N(" --rsync-options- additional options to pass to rsync |
120 |
") . N(" --wget-options - additional options to pass to wget |
121 |
") . N(" --prozilla-options - additional options to pass to prozilla |
122 |
") . N(" --aria2-options - additional options to pass to aria2 |
123 |
") . N(" --limit-rate - limit the download speed. |
124 |
") . N(" --resume - resume transfer of partially-downloaded files |
125 |
(--no-resume disables it, default is disabled). |
126 |
") . N(" --proxy - use specified HTTP proxy, the port number is assumed |
127 |
to be 1080 by default (format is <proxyhost[:port]>). |
128 |
") . N(" --proxy-user - specify user and password to use for proxy |
129 |
authentication (format is <user:password>). |
130 |
") . N(" --bug - output a bug report in directory indicated by |
131 |
next arg. |
132 |
") . N(" --env - use specific environment (typically a bug report). |
133 |
") . N(" --verify-rpm - verify rpm signature before installation |
134 |
(--no-verify-rpm disables it, default is enabled). |
135 |
") . N(" --test - only verify if the installation can be achieved correctly. |
136 |
") . N(" --excludepath - exclude path separated by comma. |
137 |
") . N(" --excludedocs - exclude doc files. |
138 |
") . N(" --ignoresize - don't verify disk space before installation. |
139 |
") . N(" --ignorearch - allow to install rpms for unmatched architectures. |
140 |
") . N(" --noscripts - do not execute package scriptlet(s) |
141 |
") . N(" --replacefiles - ignore file conflicts |
142 |
") . N(" --repackage - Re-package the files before erasing |
143 |
") . N(" --skip - packages which installation should be skipped |
144 |
") . N(" --prefer - packages which should be preferred |
145 |
") . N(" --more-choices - when several packages are found, propose more choices |
146 |
than the default. |
147 |
") . N(" --nolock - don't lock rpm db. |
148 |
") . N(" --strict-arch - upgrade only packages with the same architecture. |
149 |
") . N(" -a - select all matches on command line. |
150 |
") . N(" -p - allow search in provides to find package. |
151 |
") . N(" -P - do not search in provides to find package. |
152 |
") . N(" --quiet, -q - quiet mode. |
153 |
") . N(" --verbose, -v - verbose mode. |
154 |
") . N(" --debug - very verbose mode. |
155 |
") . "\n" . N(" names or rpm files given on command line will be installed. |
156 |
"); |
157 |
exit(1); |
158 |
} |
159 |
|
160 |
# Parse command line |
161 |
my $command_line = join " ", @ARGV; |
162 |
my @ARGVcopy; # keep a copy, in case we have to restart |
163 |
|
164 |
# Expand *.urpmi arguments |
165 |
if (member('--restricted', @ARGV)) { |
166 |
@ARGVcopy = @ARGV; |
167 |
} else { |
168 |
foreach my $a (@ARGV) { |
169 |
if ($a =~ /\.urpmi$/) { |
170 |
open my $fh, '<', $a or do { warn "Can't open $a: $!\n"; next }; |
171 |
push @ARGVcopy, map { chomp; $_ } <$fh>; |
172 |
close $fh; |
173 |
} else { |
174 |
push @ARGVcopy, $a; |
175 |
} |
176 |
} |
177 |
@ARGV = @ARGVcopy; |
178 |
} |
179 |
|
180 |
my $urpm = urpm->new_parse_cmdline or exit(1); |
181 |
|
182 |
if (@ARGV && $auto_select) { |
183 |
print STDERR N("Error: can't use --auto-select along with package list.\n"); |
184 |
exit 1; |
185 |
} |
186 |
|
187 |
# Verify that arguments were given |
188 |
unless (@ARGV || $auto_select || $clean) { |
189 |
if ($options{bug}) { |
190 |
print STDERR N("Error: To generate a bug report, specify the usual command-line arguments |
191 |
along with --bug.\n"); |
192 |
exit 1; |
193 |
} |
194 |
usage(); |
195 |
} |
196 |
|
197 |
my @spec_files; |
198 |
# Process the rest of the arguments |
199 |
foreach (@ARGV) { |
200 |
if (/\.(?:rpm|spec)$/) { |
201 |
if (/\.src\.rpm$/) { |
202 |
push @src_files, $_; |
203 |
} elsif (/\.spec$/) { |
204 |
push @spec_files, $_; |
205 |
} else { |
206 |
push @files, untaint($_); |
207 |
} |
208 |
next; |
209 |
} |
210 |
push @names, $_; |
211 |
} |
212 |
|
213 |
if ($options{buildrequires}) { |
214 |
push @src_names, @names; |
215 |
@names = (); |
216 |
} |
217 |
|
218 |
#- use install_src to promote all names as src package. |
219 |
if ($install_src) { |
220 |
@files and $urpm->{fatal}(1, N("You can't install binary rpm files when using --install-src")); |
221 |
@spec_files and $urpm->{fatal}(1, N("You can't install spec files")); |
222 |
push @src_names, @names; |
223 |
@names = (); |
224 |
#- allow to use --install-src as a non-root user |
225 |
$options{nolock} = 1; |
226 |
} elsif (@spec_files) { |
227 |
if (!$options{buildrequires}) { |
228 |
$urpm->{error}(N("defaulting to --buildrequires")); |
229 |
$options{buildrequires} = 1; |
230 |
} |
231 |
push @src_files, @spec_files; |
232 |
} elsif (@src_files && !$options{buildrequires}) { |
233 |
$urpm->{error}(N("please use --buildrequires or --install-src, defaulting to --buildrequires")); |
234 |
$options{buildrequires} = 1; |
235 |
} |
236 |
|
237 |
#- rurpmi checks |
238 |
if ($restricted) { |
239 |
urpm::error_restricted($urpm) if @files; |
240 |
#- force some options |
241 |
foreach (qw(keep verify-rpm)) { $urpm->{options}{$_} = 1 } |
242 |
#- forbid some other options |
243 |
urpm::error_restricted($urpm) if $urpm->{root} || $options{usedistrib} || $force || $env || $parallel || $options{synthesis} || $auto_update || $options{auto_orphans}; |
244 |
foreach (qw(allow-nodeps allow-force curl-options rsync-options wget-options prozilla-options noscripts)) { |
245 |
urpm::error_restricted($urpm) if $urpm->{options}{$_}; |
246 |
} |
247 |
} |
248 |
|
249 |
#- prepare bug report. |
250 |
my $bug = $options{bug}; |
251 |
if ($bug) { |
252 |
mkdir $bug or $urpm->{fatal}(8, (-d $bug |
253 |
? N("Directory [%s] already exists, please use another directory for bug report or delete it", $bug) |
254 |
: N("Unable to create directory [%s] for bug report", $bug))); |
255 |
#- copy all synthesis file used, along with configuration of urpmi |
256 |
my @list_files = grep { -e $_ } $urpm->{skiplist}, $urpm->{instlist}, |
257 |
$urpm->{prefer_list}, $urpm->{prefer_vendor_list}, '/root/.rpmdrake'; |
258 |
system("cp", "-af", @list_files, $urpm->{config}, $bug) |
259 |
and die N("Copying failed"); |
260 |
#- log everything for bug report. |
261 |
$logfile = "$bug/urpmi.log"; |
262 |
} |
263 |
|
264 |
if ($env) { |
265 |
urpm::set_env($urpm, $env); |
266 |
} else { |
267 |
if ($< != 0 && !$options{debug__do_not_install}) { |
268 |
#- need to be root if binary rpms are to be installed |
269 |
$auto_select || @names || @files and $urpm->{fatal}(1, N("Only superuser is allowed to install packages")); |
270 |
} |
271 |
} |
272 |
|
273 |
unless ($bug || $install_src || $env || $urpm->{options}{'allow-force'} || $urpm->{root}) { |
274 |
require urpm::sys; |
275 |
urpm::sys::check_fs_writable() or $urpm->{fatal}(1, N("Error: %s appears to be mounted read-only. |
276 |
Use --allow-force to force operation.", $urpm::sys::mountpoint)); |
277 |
} |
278 |
|
279 |
unless ($bug || $env || $test) { |
280 |
sys_log("called with: $command_line"); |
281 |
} |
282 |
|
283 |
my ($pid_out, $pid_err); |
284 |
if ($logfile && !$INC{"Devel/Trace.pm"}) { |
285 |
bug_log(scalar localtime(), " urpmi called with $command_line\n"); |
286 |
|
287 |
open(my $SAVEOUT, ">&STDOUT"); select $SAVEOUT; $| = 1; |
288 |
open(my $SAVEERR, ">&STDERR"); select $SAVEERR; $| = 1; |
289 |
|
290 |
#- fork twice to copy stdout and stderr to $logfile |
291 |
unless ($pid_out = open STDOUT, "|-") { |
292 |
select $SAVEOUT; $| = 1; |
293 |
$/ = \1; |
294 |
binmode STDIN, ':raw'; #- since we read character by character, perl must not try to recognise utf8 strings since it really can't |
295 |
while (my $s = <STDIN>) { |
296 |
open my $fh, ">>$logfile"; |
297 |
print $SAVEOUT $s; |
298 |
print $fh $s; |
299 |
} |
300 |
exit 0; |
301 |
} |
302 |
unless ($pid_err = open STDERR, "|-") { |
303 |
select $SAVEERR; $| = 1; |
304 |
$/ = \1; |
305 |
binmode STDIN, ':raw'; #- since we read character by character, perl must not try to recognise utf8 strings since it really can't |
306 |
while (my $s = <STDIN>) { |
307 |
open my $fh, ">>$logfile"; |
308 |
print $SAVEERR $s; |
309 |
print $fh $s; |
310 |
} |
311 |
exit 0; |
312 |
} |
313 |
|
314 |
#- log to SAVEERR instead of STDERR |
315 |
unless ($bug) { |
316 |
$urpm->{fatal} = sub { printf $SAVEERR "%s\n", $_[1]; exit($_[0]) }; |
317 |
$urpm->{error} = sub { printf $SAVEERR "%s\n", $_[0] }; |
318 |
$urpm->{log} = sub { printf $SAVEOUT "%s\n", $_[0] }; |
319 |
} |
320 |
} |
321 |
|
322 |
#- make unbuffered |
323 |
select STDERR; $| = 1; |
324 |
select STDOUT; $| = 1; |
325 |
|
326 |
if ($options{previous_priority_upgrade}) { |
327 |
# we were just restarted |
328 |
# so, no need to update the media again |
329 |
$auto_update = 0; |
330 |
# temporary hack : if we were using an old version of URPM (eg: when |
331 |
# upgrading from 2006), file handles might have leaked, so close them (with |
332 |
# some heuristics.) |
333 |
require urpm::sys; |
334 |
urpm::sys::fix_fd_leak(); |
335 |
# also, clean up rpm db log files, because rpm might have been upgraded |
336 |
urpm::sys::clean_rpmdb_shared_regions('') if !$urpm->{root}; |
337 |
} |
338 |
|
339 |
my $urpmi_lock = !$env && !$options{nolock} && urpm::lock::urpmi_db($urpm, '', wait => $options{wait_lock}); |
340 |
|
341 |
#- should we ignore arch compatibility |
342 |
if ($urpm->{options}{ignorearch}) { urpm::shunt_ignorearch() } |
343 |
|
344 |
if ($urpm->{root}) { |
345 |
$urpm->{options}{'priority-upgrade'} = '' if !$ENV{TESTING_priority_upgrade}; |
346 |
} |
347 |
if ($auto_update && !$bug && !$env) { |
348 |
$urpm->{options}{'auto-update'} = 1; |
349 |
} |
350 |
|
351 |
urpm::media::configure($urpm, |
352 |
excludemedia => $excludemedia, |
353 |
media => $media, |
354 |
parallel => $parallel, |
355 |
searchmedia => $searchmedia, |
356 |
cmdline_skiplist => $options{skip}, |
357 |
sortmedia => $sortmedia, |
358 |
synthesis => $options{synthesis}, |
359 |
update => $update, |
360 |
usedistrib => $options{usedistrib}, |
361 |
probe_with => $options{probe_with}, |
362 |
download_callback => \&urpm::download::sync_logger, |
363 |
nomd5sum => $options{nomd5sum}, |
364 |
); |
365 |
|
366 |
if ($bug) { |
367 |
require urpm::bug_report; |
368 |
urpm::bug_report::rpmdb_to_synthesis($urpm, "$bug/rpmdb.cz"); |
369 |
} |
370 |
|
371 |
urpm::select::set_priority_upgrade_option($urpm, $options{previous_priority_upgrade}); |
372 |
|
373 |
my $state = {}; |
374 |
my %requested = $urpm->register_rpms(@files, @src_files); |
375 |
|
376 |
#- finish bug environment creation. |
377 |
if ($bug) { |
378 |
urpm::bug_report::write_urpmdb($urpm, $bug); |
379 |
urpm::bug_report::copy_requested($urpm, $bug, \%requested); |
380 |
} |
381 |
|
382 |
my $rpm_lock = !$env && !$options{nolock} && urpm::lock::rpm_db($urpm, 'exclusive', wait => $options{wait_lock}); |
383 |
|
384 |
#- search the packages according to the selection given by the user. |
385 |
my $search_result = ''; |
386 |
if (@names) { |
387 |
$search_result = urpm::select::search_packages($urpm, |
388 |
\%requested, [ @names ], |
389 |
all => $all, |
390 |
use_provides => $use_provides, |
391 |
fuzzy => $urpm->{options}{fuzzy}, |
392 |
no_substring => $urpm->{options}{auto}, # do not allow substring match if we can't prompt the user |
393 |
) || $force or exit 1; |
394 |
|
395 |
if (%requested) { |
396 |
$urpm->{log}("found package(s): " . join(" ", map { scalar $urpm->{depslist}[$_]->fullname } |
397 |
map { split /\|/ } keys %requested)); |
398 |
} |
399 |
} |
400 |
if (@src_names) { |
401 |
$search_result = urpm::select::search_packages($urpm, \%requested, [ @src_names ], |
402 |
all => $all, |
403 |
use_provides => $use_provides, |
404 |
fuzzy => $urpm->{options}{fuzzy}, |
405 |
src => 1, |
406 |
) || $force or exit 1; |
407 |
} |
408 |
|
409 |
# callback called to ask user to choose between virtual packages |
410 |
# - $choices is the sorted list of choices |
411 |
# - $prefered is a subset of @$choices (it can be empty) |
412 |
sub ask_choice { |
413 |
my ($urpm, $_db, $_state, $choices, $virtual_pkg_name, $prefered) = @_; |
414 |
|
415 |
my @choices; |
416 |
if ($prefered && @$prefered) { |
417 |
@choices = @$choices; |
418 |
} else { |
419 |
($prefered, my $other) = urpm::select::get_preferred($urpm, $choices, $options{prefer}); |
420 |
@choices = (@$prefered, @$other); |
421 |
} |
422 |
my $prefer = @$prefered && join(',', grep { member($choices[$_-1], @$prefered) } 1 .. @choices); |
423 |
|
424 |
my (@l) = map { |
425 |
my ($name, $summary) = (scalar($_->fullname), translate($_->summary)); |
426 |
$_->flag_installed ? |
427 |
($_->summary ? |
428 |
#-PO: here format is "<package_name>: <summary> (to upgrade)" |
429 |
N("%s: %s (to upgrade)", $name, $summary) : |
430 |
#-PO: here format is "<package_name> (to upgrade)" |
431 |
N("%s (to upgrade)", $name)) : |
432 |
|
433 |
$_->flag_upgrade ? ($_->summary ? |
434 |
#-PO: here format is "<package_name>: <summary> (to install)" |
435 |
N("%s: %s (to install)", $name, $summary) : |
436 |
#-PO: here format is "<package_name> (to install)" |
437 |
N("%s (to install)", $name)) : $name; |
438 |
} @choices; |
439 |
|
440 |
my $n = 1; #- default value. |
441 |
|
442 |
if (@l > 1 && !$urpm->{options}{auto}) { |
443 |
print N("In order to satisfy the '%s' dependency, one of the following packages is needed:", $virtual_pkg_name), "\n"; |
444 |
my $i = 0; |
445 |
foreach (@l) { print " " . ++$i . "- $_\n" } |
446 |
$n = message_input_(N("What is your choice? (1-%d) ", $i), default => $prefer, range_min => 0, range => $i); |
447 |
defined($n) && $n ne "0" or exit 1; # abort. |
448 |
if ($n =~ /\D/) { |
449 |
my @nn = map { $choices[$_ - 1] } grep { !/\D/ } split /[, \t]+/, $n; |
450 |
@nn or exit 1; |
451 |
return @nn; |
452 |
} |
453 |
} |
454 |
$choices[$n - 1]; |
455 |
} |
456 |
|
457 |
#- do the resolution of dependencies between requested package (and auto selection if any). |
458 |
#- handle parallel option if any. |
459 |
#- return value is true if program should be restarted (in order to take care of important |
460 |
#- packages being upgraded (problably urpmi and perl-URPM, but maybe rpm too, and glibc also ?). |
461 |
my $restart_itself; |
462 |
if ($options{replacepkgs}) { |
463 |
urpm::select::select_replacepkgs($urpm, $state, \%requested); |
464 |
} else { |
465 |
$restart_itself = urpm::select::resolve_dependencies($urpm, |
466 |
$state, |
467 |
\%requested, |
468 |
rpmdb => $env && "$env/rpmdb.cz", |
469 |
auto_select => $auto_select, |
470 |
callback_choices => \&ask_choice, |
471 |
install_src => $install_src, |
472 |
keep => $urpm->{options}{keep}, |
473 |
nodeps => $urpm->{options}{'allow-nodeps'} || $urpm->{options}{'allow-force'}, |
474 |
no_suggests => $urpm->{options}{'no-suggests'}, |
475 |
priority_upgrade => $test || $env ? '' : $urpm->{options}{'priority-upgrade'}, |
476 |
); |
477 |
} |
478 |
|
479 |
{ |
480 |
my $msg = urpm::select::translate_already_installed($state); |
481 |
$msg and print "$msg\n"; |
482 |
} |
483 |
|
484 |
my @unselected_uninstalled = @{$state->{unselected_uninstalled} || []}; |
485 |
if (@unselected_uninstalled) { |
486 |
my $list = join "\n", map { $_->name . '-' . $_->version . '-' . $_->release } @unselected_uninstalled; |
487 |
my $msg = @unselected_uninstalled == 1 ? |
488 |
N("The following package cannot be installed because it depends on packages |
489 |
that are older than the installed ones:\n%s",$list) |
490 |
: N("The following packages can't be installed because they depend on packages |
491 |
that are older than the installed ones:\n%s", $list); |
492 |
if ($urpm->{options}{auto}) { |
493 |
print "$msg\n"; |
494 |
} else { |
495 |
my $noexpr = N("Nn"); |
496 |
$msg .= N("\nContinue installation anyway?"); |
497 |
$force || message_input_($msg . N(" (Y/n) "), boolean => 1) !~ /[$noexpr]/ or exit 17; |
498 |
} |
499 |
# Whatever option we selected, the overall installation should fail if some packages are unselected |
500 |
$urpm::postponed_msg .= $msg . "\n"; |
501 |
$urpm::postponed_code = 17; |
502 |
} |
503 |
|
504 |
my @ask_unselect = urpm::select::unselected_packages($urpm, $state); |
505 |
if (@ask_unselect) { |
506 |
my $list = urpm::select::translate_why_unselected($urpm, $state, @ask_unselect); |
507 |
my $msg = @ask_unselect == 1 ? |
508 |
N("A requested package cannot be installed:\n%s",$list) |
509 |
: N("Some requested packages cannot be installed:\n%s", $list); |
510 |
if ($urpm->{options}{auto}) { |
511 |
print "$msg\n"; |
512 |
} else { |
513 |
my $noexpr = N("Nn"); |
514 |
$msg .= N("\nContinue installation anyway?"); |
515 |
$force || message_input_($msg . N(" (Y/n) "), boolean => 1) !~ /[$noexpr]/ or exit 17; |
516 |
} |
517 |
# Whatever option we selected, the overall installation should fail if some packages are unselected |
518 |
$urpm::postponed_msg .= $msg . "\n"; |
519 |
$urpm::postponed_code = 17; |
520 |
} |
521 |
|
522 |
if (my @conflicting_pkgs_msgs = |
523 |
$urpm->{options}{'allow-force'} ? () : urpm::select::removed_packages_msgs($urpm, $state)) { |
524 |
{ |
525 |
my $db = urpm::db_open_or_die_($urpm); |
526 |
urpm::select::find_removed_from_basesystem($urpm, $db, $state, sub { |
527 |
my ($urpm, @pkgs) = @_; |
528 |
foreach (@pkgs) { |
529 |
$urpm->{error}(N("removing package %s will break your system", $_)); |
530 |
} |
531 |
@pkgs and $no_remove = 1; |
532 |
}); |
533 |
} |
534 |
if ($no_remove && !$force) { |
535 |
my $list = join("\n", @conflicting_pkgs_msgs); |
536 |
my $msg = @conflicting_pkgs_msgs == 1 ? |
537 |
N("The installation cannot continue because the following package |
538 |
has to be removed for others to be upgraded:\n%s\n", $list) |
539 |
: N("The installation cannot continue because the following packages |
540 |
have to be removed for others to be upgraded:\n%s\n", $list); |
541 |
print "$msg\n"; |
542 |
exit 17; |
543 |
} |
544 |
|
545 |
my $msg = urpm::select::conflicting_packages_msg_(\@conflicting_pkgs_msgs); |
546 |
if ($test) { |
547 |
$msg = "$msg\n" . N("(test only, removal will not be actually done)"); |
548 |
} |
549 |
if ($urpm->{options}{auto}) { |
550 |
print "$msg\n"; |
551 |
} else { |
552 |
$force || urpm::msg::ask_yes_or_no($msg) or exit 17; |
553 |
} |
554 |
} |
555 |
|
556 |
#- check if there is at least one package to install that |
557 |
#- has not been given by the user. |
558 |
my $ask_user = $env || $search_result eq 'substring'; |
559 |
|
560 |
my @to_install = @{$urpm->{depslist}}[sort { $a <=> $b } keys %{$state->{selected}}]; # sorted by medium for format_selected_packages |
561 |
{ |
562 |
my @binary = grep { $_->arch ne 'src' } @to_install; |
563 |
if ($install_src) { |
564 |
if (@binary && $install_src && !$env) { |
565 |
my $list = join(' ', sort map { $_->name } @binary); |
566 |
$urpm->{fatal}(1, N("You must first call urpmi with --buildrequires to install the following dependencies:\n%s\n", $list)); |
567 |
} |
568 |
} else { |
569 |
@to_install = @binary; |
570 |
} |
571 |
} |
572 |
|
573 |
if (@to_install && $options{auto_orphans}) { |
574 |
urpm::orphans::compute_future_unrequested_orphans($urpm, $state); |
575 |
if (my @orphans = map { scalar $_->fullname } @{$state->{orphans_to_remove}}) { |
576 |
print P("The following orphan package will be removed.", |
577 |
"The following orphan packages will be removed.", scalar(@orphans)) |
578 |
. "\n" . urpm::orphans::add_leading_spaces(join("\n", @orphans) . "\n"); |
579 |
} |
580 |
} |
581 |
|
582 |
#- this cleans up the list of potential orphan packages: |
583 |
#- - if a package is explicitly requested on the command line, then |
584 |
#- we assume the user doesn't want this package to be auto orphaned |
585 |
#- so we remove it from installed-through-deps |
586 |
#- - this also takes care of removing packages from |
587 |
#- installed-through-deps if the package was first installed as a |
588 |
#- dep of another package, then removed and then explicitly installed |
589 |
urpm::orphans::mark_as_requested($urpm, $state, $test); |
590 |
|
591 |
foreach my $pkg (@to_install) { |
592 |
#- reflect change in flag usage, now requested is set whatever a package is selected or not, |
593 |
#- but required is always set (so a required but not requested is a pure dependency). |
594 |
$ask_user ||= !$pkg->flag_requested || $auto_select || $parallel; |
595 |
} |
596 |
$urpm->{nb_install} = @to_install; |
597 |
|
598 |
sub warn_msg { |
599 |
my ($msg) = @_; |
600 |
$urpm->{print}(N("WARNING: %s option is in use. Some strange problems may happen", $msg)); |
601 |
} |
602 |
|
603 |
warn_msg("--allow-force") if $urpm->{options}{'allow-force'}; |
604 |
warn_msg("--allow-nodeps") if $urpm->{options}{'allow-nodeps'}; |
605 |
warn_msg("--force") if $urpm->{options}{force}; |
606 |
warn_msg("--keep") if $urpm->{options}{keep}; |
607 |
|
608 |
if (!$urpm->{options}{auto} && $ask_user && $urpm->{nb_install} || $env && !$options{debug__do_not_install}) { |
609 |
my $msg = $urpm->{nb_install} == 1 ? N("To satisfy dependencies, the following package is going to be installed:") |
610 |
: N("To satisfy dependencies, the following packages are going to be installed:"); |
611 |
if ($test) { |
612 |
$msg = "$msg\n" . N("(test only, installation will not be actually done)"); |
613 |
} |
614 |
my ($size, $filesize) = $urpm->selected_size_filesize($state); |
615 |
|
616 |
my @to_install_formatted = urpm::msg::format_line_selected_packages($urpm, $state, \@to_install); |
617 |
my $msg2 = $size >= 0 ? |
618 |
N("%s of additional disk space will be used.", formatXiB($size)) : |
619 |
N("%s of disk space will be freed.", formatXiB(-$size)); |
620 |
my $msg2_ = $filesize ? N("%s of packages will be retrieved.", formatXiB($filesize)) . "\n" : ''; |
621 |
my $msg3 = P("Proceed with the installation of one package?", |
622 |
"Proceed with the installation of the %d packages?", |
623 |
$urpm->{nb_install}, $urpm->{nb_install}); |
624 |
my $p = join("\n", $msg, @to_install_formatted, $msg2, $msg2_ . $msg3); |
625 |
if ($env && !$options{debug__do_not_install}) { |
626 |
print "$p\n"; |
627 |
exit 0; #- exit now for specific environment. |
628 |
} |
629 |
my $noexpr = N("Nn"); |
630 |
$force || message_input_($p . N(" (Y/n) "), boolean => 1) !~ /[$noexpr]/ or exit 17; |
631 |
} |
632 |
|
633 |
my $exit_code = urpm::main_loop::run($urpm, $state, |
634 |
int(@names || @src_names || @files || @src_files), |
635 |
\@ask_unselect, \%requested, { |
636 |
(!$urpm->{options}{auto} || $allow_medium_change ? (copy_removable => sub { |
637 |
my $msg = N("Please insert the medium named \"%s\"", $_[0]); |
638 |
if ($ENV{DISPLAY} && $::gui) { |
639 |
#- probably run from a drak tool |
640 |
(my $gmessage) = find { -x $_ } '/usr/X11R6/bin/gmessage', '/usr/bin/gmessage'; |
641 |
if ($gmessage) { |
642 |
return system($gmessage, '-buttons', N("Ok") . ':1,' . N("Cancel") . ':0', "\n$msg\n"); |
643 |
} |
644 |
} |
645 |
if (eval { require Hal::Cdroms; 1 }) { |
646 |
print "$msg\n"; |
647 |
Hal::Cdroms->new->wait_for_insert; |
648 |
1; |
649 |
} else { |
650 |
my $msg2 = N("Press Enter when mounted..."); |
651 |
defined message_input_("$msg\n$msg2 "); |
652 |
} |
653 |
}) : ()), |
654 |
trans_log => sub { |
655 |
# my ($mode, $file, $percent, $total, $eta, $speed) = @_; |
656 |
goto &urpm::download::sync_logger; |
657 |
}, |
658 |
bad_signature => sub { |
659 |
my ($msg, $msg2) = @_; |
660 |
#- rurpmi always abort here |
661 |
if ($urpm->{options}{auto} || $restricted) { |
662 |
print "$msg\n"; |
663 |
0; |
664 |
} else { |
665 |
$force || urpm::msg::ask_yes_or_no("$msg$msg2"); |
666 |
} |
667 |
}, |
668 |
ask_yes_or_no => sub { |
669 |
my ($_title, $msg) = @_; # graphical title |
670 |
$force || urpm::msg::ask_yes_or_no($msg); |
671 |
}, |
672 |
need_restart => sub { |
673 |
my ($need_restart_formatted) = @_; |
674 |
print "$_\n" foreach values %$need_restart_formatted; |
675 |
}, |
676 |
message => sub { |
677 |
my ($_title, $msg) = @_; # graphical title |
678 |
print $msg; |
679 |
} |
680 |
}); |
681 |
|
682 |
if ($exit_code == 0 && $auto_select && !$options{auto_orphans} && !$restart_itself) { |
683 |
if (urpm::orphans::check_unrequested_orphans_after_auto_select($urpm)) { |
684 |
if (my $msg = urpm::orphans::get_now_orphans_msg($urpm)) { |
685 |
print "\n", $msg; |
686 |
} |
687 |
} |
688 |
} |
689 |
|
690 |
unless ($env || $options{nolock}) { |
691 |
$urpmi_lock->unlock; |
692 |
$rpm_lock->unlock if $rpm_lock; |
693 |
} |
694 |
|
695 |
unless ($env) { |
696 |
#- try to umount removable device which may have been mounted. |
697 |
urpm::removable::try_umounting_removables($urpm); |
698 |
} |
699 |
|
700 |
# Merge postponed exit code to the result of package installation. |
701 |
$exit_code ||= $urpm::postponed_code; |
702 |
|
703 |
#- restart urpmi if needed, keep command line for that. |
704 |
if ($restart_itself && !$exit_code) { |
705 |
print N("restarting urpmi"), "\n"; |
706 |
#- it seems to work correctly with exec instead of system, provided |
707 |
#- STDOUT or STDERR are not closed before (else no output at all). |
708 |
#- added --previous-priority-upgrade to allow checking if yet if |
709 |
#- priority-upgrade list has changed. and make sure we don't uselessly restart |
710 |
#- renamed bug report dir as /restarted to avoid exit because it already exists |
711 |
#- This permits to have in a same dir bug reports before and after the restart |
712 |
@ARGV = @ARGVcopy; |
713 |
my @arg = ($ARGV[0], map { |
714 |
$ARGV[$_] . ($ARGV[$_ - 1] eq '--bug' ? "/restarted" : ""); |
715 |
} (1 .. $#ARGV)); |
716 |
@arg = ('--previous-priority-upgrade=' . $urpm->{options}{'priority-upgrade'}, |
717 |
grep { !/^--no-priority-upgrade$|--previous-priority-upgrade=/ } @arg); |
718 |
exec $0, @arg; |
719 |
} |
720 |
|
721 |
#- this help flushing correctly by closing this file before (piped on tee). |
722 |
#- but killing them is generally better. |
723 |
if ($pid_err || $pid_out) { |
724 |
kill 15, $pid_err, $pid_out; |
725 |
close STDERR; |
726 |
close STDOUT; |
727 |
} |
728 |
|
729 |
# Show postponed message before exiting |
730 |
print $urpm::postponed_msg if $urpm::postponed_code != 0; |
731 |
|
732 |
exit($exit_code); |