/[soft]/rpm/urpmi/branches/2/urpm.pm
ViewVC logotype

Annotation of /rpm/urpmi/branches/2/urpm.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2780 - (hide annotations) (download)
Mon Jan 23 20:14:40 2012 UTC (12 years, 3 months ago) by tv
Original Path: rpm/urpmi/trunk/urpm.pm
File size: 14733 byte(s)
6.43.1
1 dmorgan 1928 package urpm;
2    
3     # $Id: urpm.pm 271301 2010-11-22 00:50:49Z eugeni $
4    
5     no warnings 'utf8';
6     use strict;
7     use File::Find ();
8     use urpm::msg;
9     use urpm::download;
10     use urpm::util;
11     use urpm::sys;
12     use urpm::cfg;
13     use urpm::md5sum;
14    
15 tv 2780 our $VERSION = '6.43.1';
16 dmorgan 1928 our @ISA = qw(URPM Exporter);
17     our @EXPORT_OK = ('file_from_local_url', 'file_from_local_medium', 'is_local_medium');
18    
19     use URPM;
20     use URPM::Resolve;
21    
22     #- this violently overrides is_arch_compat() to always return true.
23     sub shunt_ignorearch {
24     eval q( sub URPM::Package::is_arch_compat { 1 } );
25     }
26    
27     sub xml_info_policies() { qw(never on-demand update-only always) }
28    
29     sub default_options {
30     {
31     'split-level' => 1,
32     'split-length' => 8,
33     'verify-rpm' => 1,
34     'post-clean' => 1,
35     'xml-info' => 'on-demand',
36     'max-round-robin-tries' => 5,
37     'max-round-robin-probes' => 2,
38     'days-between-mirrorlist-update' => 5,
39     'nb-of-new-unrequested-pkgs-between-auto-select-orphans-check' => 10,
40     };
41     }
42    
43     #- create a new urpm object.
44     sub new {
45     my ($class) = @_;
46     my $self;
47     $self = bless {
48     # from URPM
49     depslist => [],
50     provides => {},
51     obsoletes => {},
52    
53     media => undef,
54     options => {},
55    
56     fatal => sub { printf STDERR "%s\n", $_[1]; exit($_[0]) },
57     error => sub { printf STDERR "%s\n", $_[0] },
58     info => sub { printf "%s\n", $_[0] }, #- displayed unless --quiet
59     log => sub { printf "%s\n", $_[0] }, #- displayed if --verbose
60     print => sub { printf "%s\n", $_[0] }, #- always displayed, enable to redirect output for eg: installer
61     }, $class;
62    
63     set_files($self, '');
64     $self->set_nofatal(1);
65     $self;
66     }
67    
68     sub new_parse_cmdline {
69     my ($class) = @_;
70     my $urpm = $class->new;
71     urpm::args::parse_cmdline(urpm => $urpm);
72     get_global_options($urpm);
73     $urpm;
74     }
75    
76     sub _add2hash { my ($a, $b) = @_; while (my ($k, $v) = each %{$b || {}}) { defined $a->{$k} or $a->{$k} = $v } $a }
77    
78     sub get_global_options {
79     my ($urpm) = @_;
80    
81     my $config = urpm::cfg::load_config($urpm->{config})
82     or $urpm->{fatal}(6, $urpm::cfg::err);
83    
84     if (my $global = $config->{global}) {
85     _add2hash($urpm->{options}, $global);
86     }
87     #- remember global options for write_config
88     $urpm->{global_config} = $config->{global};
89    
90     _add2hash($urpm->{options}, default_options());
91     }
92    
93     sub prefer_rooted {
94     my ($root, $file) = @_;
95     -e "$root$file" ? "$root$file" : $file;
96     }
97    
98     sub init_cache_dir {
99     my ($urpm, $dir) = @_;
100    
101     mkdir $dir, 0755; # try to create it
102    
103     -d $dir && ! -l $dir or $urpm->{fatal}(1, N("fail to create directory %s", $dir));
104     -o $dir && -w $dir or $urpm->{fatal}(1, N("invalid owner for directory %s", $dir));
105    
106     mkdir "$dir/partial";
107     mkdir "$dir/rpms";
108    
109     $dir;
110     }
111     sub userdir_prefix {
112     my ($_urpm) = @_;
113     '/tmp/.urpmi-';
114     }
115     sub userdir {
116     #mdkonline uses userdir because it runs as user
117     my ($urpm) = @_;
118     $< or return;
119    
120     my $dir = ($urpm->{urpmi_root} || '') . userdir_prefix($urpm) . $<;
121     init_cache_dir($urpm, $dir);
122     }
123     sub ensure_valid_cachedir {
124     my ($urpm) = @_;
125     if (my $dir = userdir($urpm)) {
126     $urpm->{cachedir} = $dir;
127     }
128     -w "$urpm->{cachedir}/partial" or $urpm->{fatal}(1, N("Can not download packages into %s", "$urpm->{cachedir}/partial"));
129     }
130     sub valid_cachedir {
131     my ($urpm) = @_;
132     userdir($urpm) || $urpm->{cachedir};
133     }
134    
135     sub is_temporary_file {
136     my ($urpm, $f) = @_;
137    
138     begins_with($f, $urpm->{cachedir});
139     }
140    
141     sub set_env {
142     my ($urpm, $env) = @_;
143     -d $env or $urpm->{fatal}(8, N("Environment directory %s does not exist", $env));
144     print N("using specific environment on %s\n", $env);
145     #- setting new environment.
146     $urpm->{config} = "$env/urpmi.cfg";
147     if (cat_($urpm->{config}) =~ /^\s*virtual\s*$/m) {
148     print "dropping virtual from $urpm->{config}\n";
149     system(q(perl -pi -e 's/^\s*virtual\s*$//' ) . $urpm->{config});
150     }
151     $urpm->{mediacfgdir} = "$env/mediacfg.d";
152     $urpm->{skiplist} = "$env/skip.list";
153     $urpm->{instlist} = "$env/inst.list";
154     $urpm->{prefer_list} = "$env/prefer.list";
155     $urpm->{prefer_vendor_list} = "$env/prefer.vendor.list";
156     $urpm->{statedir} = $env;
157     $urpm->{env_rpmdb} = "$env/rpmdb.cz";
158     $urpm->{env_dir} = $env;
159     }
160    
161     sub set_files {
162     my ($urpm, $urpmi_root) = @_;
163    
164     $urpmi_root and $urpmi_root = file2absolute_file($urpmi_root);
165    
166     my %h = (
167     config => "$urpmi_root/etc/urpmi/urpmi.cfg",
168     mediacfgdir => "$urpmi_root/etc/urpmi/mediacfg.d",
169     skiplist => prefer_rooted($urpmi_root, '/etc/urpmi/skip.list'),
170     instlist => prefer_rooted($urpmi_root, '/etc/urpmi/inst.list'),
171     prefer_list => prefer_rooted($urpmi_root, '/etc/urpmi/prefer.list'),
172     prefer_vendor_list =>
173     prefer_rooted($urpmi_root, '/etc/urpmi/prefer.vendor.list'),
174     private_netrc => "$urpmi_root/etc/urpmi/netrc",
175     statedir => "$urpmi_root/var/lib/urpmi",
176     cachedir => "$urpmi_root/var/cache/urpmi",
177     root => $urpmi_root,
178     $urpmi_root ? (urpmi_root => $urpmi_root) : (),
179     );
180     $urpm->{$_} = $h{$_} foreach keys %h;
181    
182     create_var_lib_rpm($urpm, %h);
183    
184     # policy is too use chroot environment only for --urpmi-root, not for --root:
185     if ($urpmi_root && -e "$urpmi_root/etc/rpm/macros") {
186     URPM::loadmacrosfile("$urpmi_root/etc/rpm/macros");
187     }
188     }
189    
190     sub create_var_lib_rpm {
191     my ($urpm, %h) = @_;
192     require File::Path;
193     File::Path::mkpath([ $h{statedir},
194     (map { "$h{cachedir}/$_" } qw(partial rpms)),
195     dirname($h{config}),
196     "$urpm->{root}/var/lib/rpm",
197     "$urpm->{root}/var/tmp",
198     ]);
199     }
200    
201     sub modify_rpm_macro {
202     my ($name, $to_remove, $to_add) = @_;
203    
204     my $val = URPM::expand('%' . $name);
205     $val =~ s/$to_remove/$to_add/ or $val = join(' ', grep { $_ } $val, $to_add);
206     URPM::add_macro("$name $val");
207     }
208    
209     sub set_tune_rpm {
210     my ($urpm, $para) = @_;
211    
212     my %h = map { $_ => 1 } map {
213     if ($_ eq 'all') {
214     ('nofsync', 'private');
215     } else {
216     $_;
217     }
218     } split(',', $para);
219    
220     $urpm->{tune_rpm} = \%h;
221     }
222    
223     sub tune_rpm {
224     my ($urpm) = @_;
225    
226     if ($urpm->{tune_rpm}{nofsync}) {
227     modify_rpm_macro('__dbi_other', 'fsync', 'nofsync');
228     }
229     if ($urpm->{tune_rpm}{private}) {
230     urpm::sys::clean_rpmdb_shared_regions($urpm->{root});
231     modify_rpm_macro('__dbi_other', 'usedbenv', 'private');
232     }
233     }
234    
235     sub _blist_pkg_to_urls {
236     my ($blist, @pkgs) = @_;
237     my $base_url = $blist->{medium}{url} . '/';
238     map { $base_url . $_->filename } @pkgs;
239     }
240     sub blist_pkg_to_url {
241     my ($blist, $pkg) = @_;
242     my ($url) = _blist_pkg_to_urls($blist, $pkg);
243     $url;
244     }
245     sub blist_to_urls {
246     my ($blist) = @_;
247     _blist_pkg_to_urls($blist, values %{$blist->{pkgs}});
248     }
249     sub blist_to_filenames {
250     my ($blist) = @_;
251     map { $_->filename } values %{$blist->{pkgs}};
252     }
253    
254     sub protocol_from_url {
255     my ($url) = @_;
256     $url =~ m!^(\w+)(_[^:]*)?:! && $1;
257     }
258     sub file_from_local_url {
259     my ($url) = @_;
260     $url =~ m!^(?:removable[^:]*:/|file:/)?(/.*)! && $1;
261     }
262     sub file_from_local_medium {
263     my ($medium, $o_url) = @_;
264     my $url = $o_url || $medium->{url};
265     if ($url =~ m!^cdrom://(.*)!) {
266     my $rel = $1;
267     $medium->{mntpoint} or do { require Carp; Carp::confess("cdrom is not mounted yet!\n") };
268     "$medium->{mntpoint}/$rel";
269     } else {
270     file_from_local_url($url);
271     }
272     }
273     sub is_local_url {
274     my ($url) = @_;
275     file_from_local_url($url) || is_cdrom_url($url);
276     }
277     sub is_local_medium {
278     my ($medium) = @_;
279     is_local_url($medium->{url});
280     }
281     sub is_cdrom_url {
282     my ($url) = @_;
283     protocol_from_url($url) eq 'cdrom';
284     }
285    
286     sub db_open_or_die_ {
287     my ($urpm, $b_write_perm) = @_;
288     my $db;
289     if ($urpm->{env_rpmdb}) {
290     #- URPM has same methods as URPM::DB and empty URPM will be seen as empty URPM::DB.
291     $db = new URPM;
292     $db->parse_synthesis($urpm->{env_rpmdb});
293     } else {
294     $db = db_open_or_die($urpm, $urpm->{root}, $b_write_perm);
295     }
296     $db;
297     }
298    
299     # please use higher level function db_open_or_die_()
300     sub db_open_or_die {
301     my ($urpm, $root, $b_write_perm) = @_;
302    
303     $urpm->{debug} and $urpm->{debug}("opening rpmdb (root=$root, write=$b_write_perm)");
304    
305     my $db = URPM::DB::open($root, $b_write_perm || 0)
306     or $urpm->{fatal}(9, N("unable to open rpmdb"));
307    
308     $db;
309     }
310    
311     #- register local packages for being installed, keep track of source.
312     sub register_rpms {
313     my ($urpm, @files) = @_;
314     my ($start, $id, $error, %requested);
315    
316     #- examine each rpm and build the depslist for them using current
317     #- depslist and provides environment.
318     $start = @{$urpm->{depslist}};
319     foreach (@files) {
320     /\.(?:rpm|spec)$/ or $error = 1, $urpm->{error}(N("invalid rpm file name [%s]", $_)), next;
321    
322     #- if that's an URL, download.
323     if (protocol_from_url($_)) {
324     my $basename = basename($_);
325     unlink "$urpm->{cachedir}/partial/$basename";
326     $urpm->{log}(N("retrieving rpm file [%s] ...", $_));
327     if (urpm::download::sync_url($urpm, $_, quiet => 1)) {
328     $urpm->{log}(N("...retrieving done"));
329     $_ = "$urpm->{cachedir}/partial/$basename";
330     } else {
331     $urpm->{error}(N("...retrieving failed: %s", $@));
332     unlink "$urpm->{cachedir}/partial/$basename";
333     next;
334     }
335     } else {
336     -r $_ or $error = 1, $urpm->{error}(N("unable to access rpm file [%s]", $_)), next;
337     }
338    
339     if (/\.spec$/) {
340     my $pkg = URPM::spec2srcheader($_)
341     or $error = 1, $urpm->{error}(N("unable to parse spec file %s [%s]", $_, $!)), next;
342     $id = @{$urpm->{depslist}};
343     $urpm->{depslist}[$id] = $pkg;
344     $pkg->set_id($id); #- sets internal id to the depslist id.
345     $urpm->{source}{$id} = $_;
346     } else {
347     ($id) = $urpm->parse_rpm($_);
348     my $pkg = defined $id && $urpm->{depslist}[$id];
349     $pkg or $error = 1, $urpm->{error}(N("unable to register rpm file")), next;
350     $pkg->arch eq 'src' || $pkg->is_arch_compat
351     or $error = 1, $urpm->{error}(N("Incompatible architecture for rpm [%s]", $_)), next;
352     $urpm->{source}{$id} = $_;
353     }
354     }
355     $error and $urpm->{fatal}(2, N("error registering local packages"));
356     defined $id && $start <= $id and @requested{($start .. $id)} = (1) x ($id-$start+1);
357    
358     #- distribute local packages to distant nodes directly in cache of each machine.
359     if (@files && $urpm->{parallel_handler}) {
360     $urpm->{parallel_handler}->parallel_register_rpms($urpm, @files);
361     }
362    
363     %requested;
364     }
365    
366     #- checks whether the delta RPM represented by $pkg is installable wrt the
367     #- RPM DB on $root. For this, it extracts the rpm version to which the
368     #- delta applies from the delta rpm filename itself. So naming conventions
369     #- do matter :)
370     sub is_delta_installable {
371     my ($urpm, $pkg, $root) = @_;
372     $pkg->flag_installed or return 0;
373     my $f = $pkg->filename;
374     my $n = $pkg->name;
375     my ($v_match) = $f =~ /^\Q$n\E-(.*)_.+\.delta\.rpm$/;
376     my $db = db_open_or_die($urpm, $root);
377     my $v_installed;
378     $db->traverse(sub {
379     my ($p) = @_;
380     $p->name eq $n and $v_installed = $p->version . '-' . $p->release;
381     });
382     $v_match eq $v_installed;
383     }
384    
385     #- extract package that should be installed instead of upgraded,
386     #- installing instead of upgrading is useful
387     #- - for inst.list (cf flag disable_obsolete)
388     #- sources is a hash of id -> source rpm filename.
389     sub extract_packages_to_install {
390     my ($urpm, $sources, $_state) = @_;
391     my %inst;
392    
393     foreach (keys %$sources) {
394     my $pkg = $urpm->{depslist}[$_] or next;
395     $pkg->flag_disable_obsolete
396     and $inst{$pkg->id} = delete $sources->{$pkg->id};
397     }
398    
399     \%inst;
400     }
401    
402     #- deprecated
403     sub install { require urpm::install; &urpm::install::install }
404    
405     #- deprecated
406     sub parallel_remove { &urpm::parallel::remove }
407    
408     #- get reason of update for packages to be updated
409     #- use all update medias if none given
410     sub get_updates_description {
411     my ($urpm, @update_medias) = @_;
412     my %update_descr;
413     my ($cur, $section);
414    
415     @update_medias or @update_medias = urpm::media::non_ignored_media($urpm, 'update');
416    
417     foreach my $medium (@update_medias) {
418     # fix not taking into account the last %package token of each descrptions file: '%package dummy'
419     foreach (cat_utf8(urpm::media::statedir_descriptions($urpm, $medium)),
420     ($::env ? cat_utf8("$::env/descriptions") : ()), '%package dummy') {
421     /^%package +(.+)/ and do {
422     # fixes not parsing descriptions file when MU adds itself the security source:
423     if (exists $cur->{importance} && !member($cur->{importance}, qw(security bugfix))) {
424     $cur->{importance} = 'normal';
425     }
426     $update_descr{$medium->{name}}{$_} = $cur foreach @{$cur->{pkgs} || []};
427     $cur = { pkgs => [ split /\s/, $1 ] };
428     $section = 'pkg';
429     next;
430     };
431     /^Updated?: +(.+)/ && $section eq 'pkg' and do { $cur->{updated} = $1; next };
432     /^Importance: +(.+)/ && $section eq 'pkg' and do { $cur->{importance} = $1; next };
433     /^(ID|URL): +(.+)/ && $section eq 'pkg' and do { $cur->{$1} = $2; next };
434     /^%(pre|description)/ and do { $section = $1; next };
435     $section =~ /^(pre|description)\z/ and $cur->{$1} .= $_;
436     }
437     }
438     \%update_descr;
439     }
440    
441     sub error_restricted ($) {
442     my ($urpm) = @_;
443     $urpm->{fatal}(2, N("This operation is forbidden while running in restricted mode"));
444     }
445    
446     sub DESTROY {}
447    
448     1;
449    
450     __END__
451    
452     =head1 NAME
453    
454     urpm - Mageia perl tools to handle the urpmi database
455    
456     =head1 DESCRIPTION
457    
458     C<urpm> is used by urpmi executables to manipulate packages and media
459     on a Mageia Linux distribution.
460    
461     =head2 The urpm class
462    
463     =over 4
464    
465     =item urpm->new()
466    
467     The constructor creates a new urpm object. It's a blessed hash that
468     contains fields from C<URPM>, and also the following fields:
469    
470     B<source>: { id => src_rpm_file|spec_file }
471    
472     B<media>: [ {
473     start => int, end => int, name => string, url => string,
474     virtual => bool, media_info_dir => string, with_synthesis => string,
475     no-media-info => bool,
476     iso => string, downloader => string,
477     ignore => bool, update => bool, modified => bool, really_modified => bool,
478     unknown_media_info => bool,
479     } ],
480    
481     =back
482    
483     =head1 SEE ALSO
484    
485     The C<URPM> package is used to manipulate at a lower level synthesis and rpm
486     files.
487    
488     =head1 COPYRIGHT
489    
490     Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 MandrakeSoft SA
491    
492     Copyright (C) 2005-2010 Mandriva SA
493    
494     This program is free software; you can redistribute it and/or modify
495     it under the terms of the GNU General Public License as published by
496     the Free Software Foundation; either version 2, or (at your option)
497     any later version.
498    
499     This program is distributed in the hope that it will be useful,
500     but WITHOUT ANY WARRANTY; without even the implied warranty of
501     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
502     GNU General Public License for more details.
503    
504     You should have received a copy of the GNU General Public License
505     along with this program; if not, write to the Free Software
506     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
507    
508     =cut
509    
510     # ex: set ts=8 sts=4 sw=4 noet:

  ViewVC Help
Powered by ViewVC 1.1.30