1 |
#!/usr/bin/perl |
2 |
|
3 |
# $Id: urpmq 271299 2010-11-21 15:54:30Z peroyvind $ |
4 |
|
5 |
#- Copyright (C) 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 |
#- this program is based upon urpmi. |
23 |
|
24 |
use strict; |
25 |
|
26 |
use urpm; |
27 |
use urpm::args; |
28 |
use urpm::msg; |
29 |
use urpm::sys; |
30 |
use urpm::util; |
31 |
use urpm::media; |
32 |
use urpm::select; |
33 |
use urpm::get_pkgs; |
34 |
|
35 |
our @files; |
36 |
our @names; |
37 |
our @src_names; |
38 |
|
39 |
sub usage() { |
40 |
print N("urpmq version %s |
41 |
Copyright (C) 2000-2010 Mandriva. |
42 |
This is free software and may be redistributed under the terms of the GNU GPL. |
43 |
|
44 |
usage: |
45 |
", $urpm::VERSION) . N(" --help - print this help message. |
46 |
") . N(" --update - use only update media. |
47 |
") . N(" --media - use only the given media, separated by comma. |
48 |
") . N(" --searchmedia - use only the given media to search requested (or updated) packages. |
49 |
") . N(" --excludemedia - do not use the given media, separated by comma. |
50 |
") . N(" --sortmedia - sort media according to substrings separated by comma. |
51 |
") . N(" --synthesis - use the given synthesis instead of urpmi db. |
52 |
") . N(" --auto-select - automatically select packages to upgrade the system. |
53 |
") . N(" --auto-orphans - list orphans |
54 |
") . N(" --not-available |
55 |
- list installed packages not available on any media. |
56 |
") . N(" --no-suggests - do not auto select \"suggested\" packages. |
57 |
") . N(" --fuzzy - impose fuzzy search (same as -y). |
58 |
") . N(" --keep - keep existing packages if possible, reject requested |
59 |
packages that lead to removals. |
60 |
") . N(" --list - list available packages. |
61 |
") . N(" --list-media - list available media. |
62 |
") . N(" --list-url - list available media and their url. |
63 |
") . N(" --list-nodes - list available nodes when using --parallel. |
64 |
") . N(" --list-aliases - list available parallel aliases. |
65 |
") . N(" --dump-config - dump the config in form of urpmi.addmedia argument. |
66 |
") . N(" --src - next package is a source package (same as -s). |
67 |
") . N(" --sources - print source URLs of selected packages |
68 |
") . N(" --force - force invocation even if some packages do not exist. |
69 |
") . N(" --ignorearch - allow to query rpms for unmatched architectures. |
70 |
") . N(" --parallel - distributed urpmi across machines of alias. |
71 |
") . N(" --root - use another root for rpm installation. |
72 |
") . N(" --urpmi-root - use another root for urpmi db & rpm installation. |
73 |
") . N(" --use-distrib - configure urpmi on the fly from a distrib tree. |
74 |
This permit to querying a distro. |
75 |
") . N(" --wget - use wget to retrieve distant files. |
76 |
") . N(" --curl - use curl to retrieve distant files. |
77 |
") . N(" --prozilla - use prozilla to retrieve distant files. |
78 |
") . N(" --proxy - use specified HTTP proxy, the port number is assumed |
79 |
to be 1080 by default (format is <proxyhost[:port]>). |
80 |
") . N(" --proxy-user - specify user and password to use for proxy |
81 |
authentication (format is <user:password>). |
82 |
") . N(" --env - use specific environment (typically a bug report). |
83 |
") . N(" --changelog - print changelog. |
84 |
") . N(" --conflicts - print conflicts. |
85 |
") . N(" --obsoletes - print obsoletes. |
86 |
") . N(" --provides - print provides. |
87 |
") . N(" --requires - print requires. |
88 |
") . N(" --suggests - print suggests. |
89 |
") . N(" --sourcerpm - print sourcerpm. |
90 |
") . N(" --summary, -S - print summary. |
91 |
") . N(" --verbose, -v - verbose mode. |
92 |
") . N(" --requires-recursive, -d |
93 |
- query package dependencies. |
94 |
") . N(" --whatrequires - reverse search to what requires package. |
95 |
") . N(" --whatrequires-recursive |
96 |
- extended reverse search (includes virtual packages). |
97 |
") . N(" --whatprovides, -p |
98 |
- search in provides to find package. |
99 |
") . N(" -a - select all matches on command line. |
100 |
") . N(" -c - complete output with package to be removed. |
101 |
") . N(" -f - print version, release and arch with name. |
102 |
") . N(" -g - print groups with name also. |
103 |
") . N(" -i - print useful information in human readable form. |
104 |
") . N(" -l - list files in package. |
105 |
") . N(" -m - equivalent to -du |
106 |
") . N(" -r - print version and release with name also. |
107 |
") . N(" -s - next package is a source package (same as --src). |
108 |
") . N(" -u - remove package if a more recent version is already installed. |
109 |
") . N(" -y - impose fuzzy search (same as --fuzzy). |
110 |
") . N(" -Y - like -y, but forces to match case-insensitively. |
111 |
") . "\n" . N(" names or rpm files given on command line are queried. |
112 |
"); |
113 |
exit(1); |
114 |
} |
115 |
|
116 |
sub escape_shell ($) { |
117 |
my ($s) = @_; |
118 |
if ($s =~ /\s|'|"/) { |
119 |
$s =~ s/"/\\"/g; |
120 |
$s = qq("$s"); |
121 |
} else { |
122 |
return $s; |
123 |
} |
124 |
} |
125 |
|
126 |
#- parse arguments list. |
127 |
@ARGV or usage(); |
128 |
my $urpm = urpm->new_parse_cmdline or exit(1); |
129 |
|
130 |
#- we really don't want logs on stdout, and remove verbose if not asked. |
131 |
$urpm->{info} = sub { print STDERR "$_[0]\n" }; |
132 |
$urpm->{log} = sub { print STDERR "$_[0]\n" } if $options{verbose} > 0; |
133 |
|
134 |
my $only_list_name = $options{list} && !($options{version} || $options{release} || $options{arch} || $options{group}); |
135 |
|
136 |
#- improve speed if using any list_... options. |
137 |
$options{nodepslist} = $options{list_aliases} |
138 |
|| $options{list_nodes} |
139 |
|| $options{list_media} |
140 |
|| $options{dump_config} |
141 |
|| $only_list_name # urpmq will parse synthesis only if names.* are not already there |
142 |
|| $options{list_url}; |
143 |
$options{nolock} = 1 if $options{nodepslist}; |
144 |
|
145 |
#- print sub for query. |
146 |
my $pkg_to_string = sub { |
147 |
my ($pkg) = @_; |
148 |
my $str = ''; |
149 |
$options{group} and $str .= $pkg->group . '/'; |
150 |
$str .= $pkg->name; |
151 |
$options{version} and $str .= '-' . $pkg->version; |
152 |
$options{release} and $str .= '-' . $pkg->release; |
153 |
$options{arch} and $str .= '.' . $pkg->arch; |
154 |
$str; |
155 |
}; |
156 |
|
157 |
if ($options{auto_orphans}) { |
158 |
!@names && !@src_names or $urpm->{fatal}(1, N("usage: \"urpmq --auto-orphans\" with no argument")); |
159 |
$options{env} and $urpm->{fatal}(1, N("Can't use %s with %s", '--env', '--auto-orphans')); |
160 |
require urpm::orphans; |
161 |
my $orphans = urpm::orphans::get_orphans($urpm); |
162 |
print "$_\n" foreach sort map { $pkg_to_string->($_) } @$orphans; |
163 |
exit $urpm::postponed_code; |
164 |
} |
165 |
|
166 |
if ($options{env}) { |
167 |
print N("using specific environment on %s\n", $options{env}); |
168 |
#- setting new environment. |
169 |
$urpm->{config} = "$options{env}/urpmi.cfg"; |
170 |
$urpm->{skiplist} = "$options{env}/skip.list"; |
171 |
$urpm->{instlist} = "$options{env}/inst.list"; |
172 |
$urpm->{prefer_list} = "$options{env}/prefer.list"; |
173 |
$urpm->{prefer_vendor_list} = "$options{env}/prefer.vendor.list"; |
174 |
$urpm->{statedir} = $options{env}; |
175 |
} |
176 |
|
177 |
#- should we ignore arch compatibility |
178 |
if ($options{ignorearch}) { urpm::shunt_ignorearch() } |
179 |
|
180 |
my $rpm_lock = |
181 |
($options{upgrade} || $options{not_available}) && !$options{env} && !$options{nolock} |
182 |
&& urpm::lock::rpm_db($urpm, '', wait => $options{wait_lock}); |
183 |
my $urpmi_lock = !$options{nolock} && urpm::lock::urpmi_db($urpm, '', wait => $options{wait_lock}); |
184 |
urpm::media::configure($urpm, |
185 |
nodepslist => $options{nodepslist}, |
186 |
media => $options{media}, |
187 |
searchmedia => $options{searchmedia}, |
188 |
excludemedia => $options{excludemedia}, |
189 |
sortmedia => $options{sortmedia}, |
190 |
synthesis => $options{synthesis}, |
191 |
update => $options{update}, |
192 |
parallel => $options{parallel}, |
193 |
probe_with => $options{probe_with}, |
194 |
usedistrib => $options{usedistrib}, |
195 |
cmdline_skiplist => $options{skip}, |
196 |
); |
197 |
|
198 |
my $state = {}; |
199 |
my %requested; |
200 |
|
201 |
if ($options{list_aliases}) { |
202 |
local $_; |
203 |
open my $parallelfh, "/etc/urpmi/parallel.cfg"; |
204 |
while (<$parallelfh>) { |
205 |
chomp; s/#.*$//; s/^\s*//; s/\s*$//; |
206 |
/\s*([^:]*):/ |
207 |
and print "$1\n"; |
208 |
} |
209 |
close $parallelfh; |
210 |
} elsif ($options{list_nodes}) { |
211 |
$options{parallel} or $urpm->{fatal}(1, N("--list-nodes can only be used with --parallel")); |
212 |
foreach (keys %{$urpm->{parallel_handler}{nodes} || {}}) { |
213 |
print "$_\n"; |
214 |
} |
215 |
exit $urpm::postponed_code; |
216 |
} elsif ($options{list_media} || $options{list_url}) { |
217 |
foreach (@{$urpm->{media}}) { |
218 |
next if $options{list_media} eq 'update' && !$_->{update}; |
219 |
next if $options{list_media} eq 'active' && $_->{ignore}; |
220 |
print $_->{name} . ($options{list_url} ? " $_->{url}" : "") . "\n"; |
221 |
} |
222 |
exit $urpm::postponed_code; |
223 |
} elsif ($options{dump_config}) { |
224 |
foreach (@{$urpm->{media}}) { |
225 |
$_->{update} and print "--update "; |
226 |
$_->{virtual} and print "--virtual "; |
227 |
$_->{mirrorlist} and print "--mirrorlist '$_->{mirrorlist}' "; |
228 |
print escape_shell($_->{name}), " "; |
229 |
print escape_shell($_->{mirrorlist} ? $_->{'with-dir'} : $_->{url}), " " if !$_->{mirrorlist} || $_->{'with-dir'}; |
230 |
$_->{with_synthesis} and print "with " . escape_shell($_->{with_synthesis}); |
231 |
print "\n"; |
232 |
} |
233 |
exit $urpm::postponed_code; |
234 |
} elsif ($options{list}) { |
235 |
!@names && !@src_names or $urpm->{fatal}(1, N("use -l to list files")); |
236 |
|
237 |
if ($only_list_name) { |
238 |
# special code, much faster |
239 |
my @media = urpm::media::non_ignored_media($urpm, $options{update}); |
240 |
my @names_files = grep { -e $_ } map { urpm::media::statedir_names($urpm, $_) } @media; |
241 |
|
242 |
if (@media == @names_files) { |
243 |
$urpm->{log}("using " . join(' ', @names_files)); |
244 |
print sort map { cat_($_) } @names_files; |
245 |
} else { |
246 |
urpm::media::parse_media($urpm, \%options); |
247 |
print sort map { $_->name . "\n" } @{$urpm->{depslist}}; |
248 |
} |
249 |
# we're done now, but we don't exit here so locks are correctly released if needed |
250 |
} else { |
251 |
# use the generic code |
252 |
@{$state->{selected}}{0 .. $#{$urpm->{depslist}}} = (); |
253 |
} |
254 |
} elsif ($options{not_available}) { |
255 |
my %available; |
256 |
foreach my $p (@{$urpm->{depslist}}) { |
257 |
$available{$p->fullname} = 1; |
258 |
} |
259 |
my $db = urpm::db_open_or_die_($urpm); |
260 |
$db->traverse(sub { |
261 |
my ($p) = @_; |
262 |
my $s = $p->fullname; |
263 |
# FIXME Use $pkg_to_string if some options are set but default to this format ? |
264 |
# Magical packages like gpg-pubkey do not have arch and we do not want them |
265 |
$available{$s} || !$p->arch || print "$s\n"; |
266 |
}); |
267 |
} else { |
268 |
%requested = $urpm->register_rpms(@files); |
269 |
|
270 |
my $search_packages = sub { |
271 |
my ($names, %more_options) = @_; |
272 |
|
273 |
urpm::select::search_packages($urpm, |
274 |
\%requested, $names, |
275 |
use_provides => $options{use_provides}, |
276 |
fuzzy => $urpm->{options}{fuzzy}, |
277 |
caseinsensitive => $options{caseinsensitive}, |
278 |
all => $options{all}, |
279 |
%more_options, |
280 |
); |
281 |
}; |
282 |
|
283 |
#- search the packages according to the selection given by the user. |
284 |
if (@names) { |
285 |
$search_packages->(\@names) or $options{force} or exit 1; |
286 |
} |
287 |
if (@src_names) { |
288 |
$search_packages->(\@src_names, src => 1) or $options{force} or exit 1; |
289 |
} |
290 |
|
291 |
#- keep track of choices, don't propagate but mark them selected. |
292 |
my $stop_on_choices = sub { |
293 |
my (undef, undef, $state_, $choices) = @_; |
294 |
$state_->{selected}{join '|', sort { $a <=> $b } map { $_ ? $_->id : () } @$choices} = 0; |
295 |
}; |
296 |
#- open/close of database should be moved here, in order to allow testing |
297 |
#- some bogus case and check for integrity. (note auto_select implies upgrade). |
298 |
if ($options{what_requires}) { |
299 |
#- search for packages that require one of the proposed packages. |
300 |
my (@properties, %requires, %properties, $dep); |
301 |
|
302 |
#- keep in mind the requested id (if given) in order to prefer these packages |
303 |
#- on choices instead of anything other one. |
304 |
@properties = keys %requested; |
305 |
|
306 |
if (@properties) { |
307 |
#- build a requires to packages id hash. |
308 |
foreach my $pkg (@{$urpm->{depslist}}) { |
309 |
foreach ($pkg->requires_nosense) { |
310 |
$requires{$_}{$pkg->id} = undef; |
311 |
} |
312 |
} |
313 |
|
314 |
#- for each dep property evaluated, examine which package will be obsoleted on $db, |
315 |
#- then examine provides that will be removed (which need to be satisfied by another |
316 |
#- package present or by a new package to upgrade), then requires not satisfied and |
317 |
#- finally conflicts that will force a new upgrade or a remove. |
318 |
while (defined ($dep = shift @properties)) { |
319 |
#- take the best package for each choices of same name. |
320 |
my $packages = $urpm->find_candidate_packages($dep); |
321 |
foreach (values %$packages) { |
322 |
my ($best_requested, $best); |
323 |
foreach (@$_) { |
324 |
if ($best_requested || exists $requested{$_->id}) { |
325 |
if ($best_requested && $best_requested != $_) { |
326 |
$_->compare_pkg($best_requested) > 0 and $best_requested = $_; |
327 |
} else { |
328 |
$best_requested = $_; |
329 |
} |
330 |
} elsif ($best && $best != $_) { |
331 |
$_->compare_pkg($best) > 0 and $best = $_; |
332 |
} else { |
333 |
$best = $_; |
334 |
} |
335 |
} |
336 |
|
337 |
#- examine all proposed choices. |
338 |
my $pkg = $best_requested || $best or next; |
339 |
exists $state->{selected}{$pkg->id} and next; |
340 |
$state->{selected}{$pkg->id} = undef; |
341 |
|
342 |
next if !$requested{$dep} && !$options{what_requires_recursive}; |
343 |
|
344 |
#- for all provides of package, look up what is requiring them. |
345 |
foreach ($pkg->provides) { |
346 |
if (my ($n, $s) = /^([^\s\[]*)(?:\[\*\])?\[?([^\s\]]*\s*[^\s\]]*)/) { |
347 |
if (my @l = grep { $_ ne $pkg->name } map { $_->name } $urpm->packages_providing($n)) { |
348 |
#- If another package provides this requirement, |
349 |
#- then don't bother finding stuff that needs it as it will be invalid |
350 |
$urpm->{log}(sprintf "skipping package(s) requiring %s via %s, since %s is also provided by %s", $pkg->name, $n, $n, join(' ', @l)); |
351 |
next; |
352 |
} |
353 |
|
354 |
foreach (map { $urpm->{depslist}[$_] } |
355 |
grep { ! exists $state->{selected}{$_} && ! exists $properties{$_} } |
356 |
keys %{$requires{$n} || {}}) { |
357 |
if (grep { URPM::ranges_overlap("$n $s", $_) } $_->requires) { |
358 |
push @properties, $_->id; |
359 |
$urpm->{debug} and $urpm->{debug}(sprintf "adding package %s (requires %s%s)", $_->name, $pkg->name, $n eq $pkg->name ? '' : " via $n"); |
360 |
$properties{$_->id} = undef; |
361 |
} |
362 |
} |
363 |
} |
364 |
} |
365 |
} |
366 |
} |
367 |
} |
368 |
} elsif ($options{auto_select} || $options{upgrade}) { |
369 |
urpm::select::resolve_dependencies($urpm, $state, \%requested, |
370 |
keep => $options{keep}, |
371 |
rpmdb => $options{env} && "$options{env}/rpmdb.cz", |
372 |
auto_select => $options{auto_select}, |
373 |
no_suggests => $urpm->{options}{'no-suggests'}, |
374 |
callback_choices => $stop_on_choices); |
375 |
$options{deps} or delete @{$state->{selected}}{grep { exists $state->{selected}{$_} && |
376 |
! defined $state->{selected}{$_} } keys %{$state->{selected}}}; |
377 |
} elsif ($options{deps}) { |
378 |
#- only deps required. |
379 |
my $empty_db = URPM->new; #- URPM has same methods as URPM::DB and empty URPM will be seen as empty URPM::DB. |
380 |
$urpm->resolve_requested($empty_db, $state, \%requested, |
381 |
no_suggests => $urpm->{options}{'no-suggests'}, |
382 |
callback_choices => $stop_on_choices, nodeps => 1); |
383 |
} else { |
384 |
$state->{selected} = \%requested; |
385 |
} |
386 |
|
387 |
my %need_xml_info; |
388 |
$need_xml_info{info} = 1 if $options{info} || $options{sourcerpm}; |
389 |
$need_xml_info{files} = 1 if $options{files}; |
390 |
$need_xml_info{changelog} = 1 if $options{changelog}; |
391 |
|
392 |
if ($options{sources} || %need_xml_info) |
393 |
{ |
394 |
my ($local_sources, $blists) = urpm::get_pkgs::selected2local_and_blists($urpm, $state->{selected}); |
395 |
my %xml_info_pkgs; |
396 |
|
397 |
if (%need_xml_info) { |
398 |
# get descriptions of update sources |
399 |
my $updates_descr = urpm::get_updates_description($urpm); |
400 |
|
401 |
foreach my $blist (@$blists) { |
402 |
my $medium = $blist->{medium}; |
403 |
my @pkgs = values %{$blist->{pkgs}} or next; |
404 |
|
405 |
if (my $dir = urpm::file_from_local_url($medium->{url})) { |
406 |
$urpm->{log}("getting information from rpms from $dir"); |
407 |
$local_sources->{$_->id} = "$dir/" . $_->filename foreach @pkgs; |
408 |
} else { |
409 |
foreach my $xml_info (grep { $need_xml_info{$_} } 'info', 'files', 'changelog') { |
410 |
if (my $xml_info_file = urpm::media::any_xml_info($urpm, $medium, $xml_info, $options{verbose} < 0)) { |
411 |
require urpm::xml_info; |
412 |
require urpm::xml_info_pkg; |
413 |
$urpm->{log}("getting information from $xml_info_file"); |
414 |
my %nodes = urpm::xml_info::get_nodes($xml_info, $xml_info_file, [ map { scalar $_->fullname } @pkgs ]); |
415 |
put_in_hash($xml_info_pkgs{$_->id} ||= {}, $nodes{$_->fullname}) foreach @pkgs; |
416 |
} else { |
417 |
my $pkgs_text = join(' ', map { $_->name } @pkgs); |
418 |
if ($xml_info eq 'info') { |
419 |
$urpm->{info}(int(@pkgs) == 1 ? |
420 |
N("no xml info for medium \"%s\", only partial result for package %s", $medium->{name}, $pkgs_text) |
421 |
: N("no xml info for medium \"%s\", only partial result for packages %s", $medium->{name}, $pkgs_text)); |
422 |
} else { |
423 |
$urpm->{error}(int(@pkgs == 1) ? |
424 |
N("no xml info for medium \"%s\", unable to return any result for package %s", $medium->{name}, $pkgs_text) |
425 |
: N("no xml info for medium \"%s\", unable to return any result for packages %s", $medium->{name}, $pkgs_text)); |
426 |
} |
427 |
} |
428 |
} |
429 |
} |
430 |
} |
431 |
foreach (keys %{$state->{selected}}) { |
432 |
foreach my $id (split /\|/, $_) { |
433 |
my $pkg = $urpm->{depslist}[$id] or next; |
434 |
|
435 |
#- even if non-root, search for a header in the global cachedir |
436 |
my $file = $local_sources->{$id}; |
437 |
if (-s $file) { |
438 |
$pkg->update_header($file, keep_all_tags => 1); |
439 |
} elsif ($xml_info_pkgs{$id}) { |
440 |
# using the proxy urpm::xml_info_pkg object |
441 |
$pkg = urpm::xml_info_pkg->new($xml_info_pkgs{$id}, $pkg); |
442 |
} |
443 |
if ($options{info}) { |
444 |
printf "%-12s: %s\n", "Name", $pkg->name; |
445 |
printf "%-12s: %s\n", "Version", $pkg->version; |
446 |
printf "%-12s: %s\n", "Release", $pkg->release; |
447 |
printf "%-12s: %s\n", "Group", $pkg->group; |
448 |
printf "%-12s: %-28s %12s: %s\n", "Size", $pkg->size, "Architecture", $pkg->arch; |
449 |
if ($pkg->sourcerpm || $pkg->buildhost) { |
450 |
if ($pkg->sourcerpm && $pkg->buildhost) { |
451 |
printf "%-12s: %-28s %12s: %s\n", "Source RPM", $pkg->sourcerpm, "Build Host", $pkg->buildhost; |
452 |
} elsif ($pkg->sourcerpm) { |
453 |
$pkg->sourcerpm and printf "%-12s: %s\n", "Source RPM", $pkg->sourcerpm; |
454 |
} else { |
455 |
$pkg->sourcerpm and printf "%-12s: %s\n", "Build Host", $pkg->buildhost; |
456 |
} |
457 |
} |
458 |
$pkg->packager and printf "%-12s: %s\n", "Packager", $pkg->packager; |
459 |
$pkg->url and printf "%-12s: %s\n", "URL", $pkg->url; |
460 |
$pkg->summary and printf "%-12s: %s\n", "Summary", $pkg->summary; |
461 |
|
462 |
my $updesc = do { |
463 |
my $media = URPM::pkg2media($urpm->{media}, $pkg); |
464 |
$media && $updates_descr->{$media->{name}}{$pkg->name}; |
465 |
}; |
466 |
if (my $description = $updesc && $updesc->{description} || $pkg->description) { |
467 |
printf "%-12s:\n%s\n", "Description", $description; |
468 |
} |
469 |
if ($updesc) { |
470 |
$updesc->{updated} |
471 |
and printf "%-20s: %s\n", "Last updated", $updesc->{updated}; |
472 |
$updesc->{importance} |
473 |
and printf "%-20s: %s\n", "Update importance", $updesc->{importance}; |
474 |
$updesc->{pre} |
475 |
and printf "%-20s:\n%s\n", "Reason for update", $updesc->{pre}; |
476 |
} |
477 |
} |
478 |
if ($options{files}) { |
479 |
if ($pkg->files) { |
480 |
print join("\n", $pkg->files) . "\n"; |
481 |
} |
482 |
} |
483 |
if (my @tags = grep { $options{$_} } 'sourcerpm') { |
484 |
print $pkg->name, ': ', $pkg->$_, "\n" foreach @tags; |
485 |
} |
486 |
if ($options{changelog}) { |
487 |
if (my @changelogs = $pkg->changelogs) { |
488 |
foreach (@changelogs) { |
489 |
print "* " . urpm::msg::localtime2changelog($_->{time}) . " $_->{name}\n$_->{text}\n\n"; |
490 |
} |
491 |
} else { |
492 |
print STDERR N("No changelog found\n"); |
493 |
} |
494 |
} |
495 |
} |
496 |
} |
497 |
} elsif ($options{sources}) { |
498 |
print "$_\n" foreach values %$local_sources; |
499 |
print "$_\n" foreach map { urpm::blist_to_urls($_) } @$blists; |
500 |
} |
501 |
exit $urpm::postponed_code; |
502 |
} elsif ($options{summary}) { |
503 |
foreach (keys %{$state->{selected}}) { |
504 |
foreach (split /\|/, $_) { |
505 |
my $pkg = $urpm->{depslist}[$_] or next; |
506 |
printf "%s : %s ( %s%s-%s )\n", $pkg->name, $pkg->summary, ($pkg->epoch ? $pkg->epoch . ':' : ''), $pkg->version, $pkg->release; |
507 |
} |
508 |
} |
509 |
exit $urpm::postponed_code; |
510 |
} elsif (my ($get) = grep { $options{$_} } 'provides', 'requires', 'conflicts', 'obsoletes', 'suggests') { |
511 |
my @l = uniq_ { scalar $_->fullname } map { $urpm->{depslist}[$_] } map { split /\|/, $_ } keys %{$state->{selected}}; |
512 |
foreach my $pkg (@l) { |
513 |
if (@l > 1) { |
514 |
printf "%s: %s\n", $pkg->name, $_ foreach $pkg->$get; |
515 |
} else { |
516 |
print "$_\n" foreach $pkg->$get; |
517 |
} |
518 |
} |
519 |
exit $urpm::postponed_code; |
520 |
} |
521 |
} |
522 |
$urpmi_lock and $urpmi_lock->unlock; |
523 |
$rpm_lock and $rpm_lock->unlock; |
524 |
|
525 |
#- print sub for query. |
526 |
my $query_sub = sub { |
527 |
my ($id) = @_; |
528 |
$pkg_to_string->($urpm->{depslist}[$id]); |
529 |
}; |
530 |
|
531 |
my %hack_only_one; |
532 |
if ($options{complete}) { |
533 |
foreach my $removal (grep { $state->{rejected}{$_}{removed} && !$state->{rejected}{$_}{obsoleted} } |
534 |
keys %{$state->{rejected} || {}}) { |
535 |
print '@removing@' . $removal . "\n"; |
536 |
} |
537 |
foreach my $selected (values %{$state->{selected} || {}}) { |
538 |
if (ref($selected) eq 'HASH' && ref($selected->{unsatisfied}) eq 'ARRAY') { |
539 |
foreach (@{$selected->{unsatisfied}}) { |
540 |
exists $hack_only_one{$_} and next; |
541 |
print '@unsatisfied@' . $_ . "\n"; |
542 |
$hack_only_one{$_} = undef; |
543 |
} |
544 |
} |
545 |
} |
546 |
} |
547 |
foreach my $id (sort { eval { $urpm->{depslist}[$a]->name cmp $urpm->{depslist}[$b]->name } || $a <=> $b } |
548 |
$state->{selected} ? keys %{$state->{selected}} : keys %requested) { |
549 |
my $class = $state->{selected}{$id} || $requested{$id}; |
550 |
if (ref($class) eq 'ARRAY') { |
551 |
foreach my $choices (@{$class || []}) { |
552 |
exists $hack_only_one{$choices} and next; |
553 |
print join('|', map { $query_sub->($_) } @$choices), "\n"; |
554 |
$hack_only_one{$choices} = undef; |
555 |
} |
556 |
} else { |
557 |
print join('|', map { $query_sub->($_) } split '\|', $id), "\n"; |
558 |
} |
559 |
} |
560 |
|
561 |
exit $urpm::postponed_code; |