source: ProjectBuilder/devel/rpmbootstrap/bin/rpmbootstrap@ 1531

Last change on this file since 1531 was 1531, checked in by Bruno Cornec, 12 years ago

rpmbootstrap: Add support for stop-on-error. Expand out VE paths. Error out if no packages are defined for the OS version since that indicates something is badly wrong. Track the packages that we install so that we can re-install them with the vendor's tool. Don't mount proc if it is already mounted. Only process repo files under yum.repos.d. In comment for now: Include all the packages installed during bootstrapping in the list of packages to re-install for yum and zypper. If you don't do this for yum, you end up with the generic fedora release file which doesn't match the pattern expected to determine the version. If you don't do this for zypper, then /etc/passwd isn't created, which creates failures later. Remove the zypper repository before adding, just adding fails since it already exists. Hack to fix up the yum.repos.d files again after the yum install since centos 6 mangles them during install. Report on broken packages listed for installation at the end so the warning isn't hidden. (Eric Anderson)

File size: 18.5 KB
Line 
1#!/usr/bin/perl -w
2#
3# rpmbootstrap application, a debootstrap like for RPM distros
4#
5# $Id$
6#
7# Copyright B. Cornec 2010
8# Provided under the GPL v2
9
10# Syntax: see at end
11
12use strict 'vars';
13use Getopt::Long qw(:config auto_abbrev no_ignore_case);
14use Data::Dumper;
15use English;
16use LWP::UserAgent;
17use File::Basename;
18use File::Copy;
19use File::Find;
20use ProjectBuilder::Version;
21use ProjectBuilder::Base;
22use ProjectBuilder::Env;
23use ProjectBuilder::Conf;
24use ProjectBuilder::Distribution;
25
26# Global variables
27my %opts; # CLI Options
28
29=pod
30
31=head1 NAME
32
33rpmbootstrap - creates a chrooted RPM based distribution a la debootstrap, aka Virtual Environment (VE)
34
35=head1 DESCRIPTION
36
37rpmbootstrap creates a chroot environment (Virtual Environment or VE)
38with a minimal distribution in it, suited for building packages for example.
39It's very much like debootstrap but for RPM based distribution.
40It aims at supporting all distributions supported by project-builder.org
41(RHEL, RH, Fedora, OpeSUSE, SLES, Mandriva, ...)
42
43It is inspired by work done by Steve Kemp for rinse (http://www.steve.org.uk/),
44and similar to mock or febootstrap, but fully integrated with project-builder.org
45(which also supports rinse and mock). Contrary to these, rpmbootstrap creates
46an environment where the packages commands are usable after build, as described
47hereafter.
48
49rpmbootstrap works in 2 phases. The first one is used to download all
50the required packages to have a working package management system in the
51chroot working. This list of packages is stored in /etc/pb/pb.conf under
52the rbsmindep parameter (aka rpmbootstrap minimal dependencies). Once the
53packages have been downloaded from the mirror, they are extracted with
54rpm2cpio. At that point you should be able to use yum on Fedora, urpmi
55on Mandriva/Mageia and zypper on OpenSuSE.
56The second phase uses exactly the previous mentioned tools to install
57exactly the same package list to have a coherent RPM db at the end.
58
59rpmbootstrap has additional options to execute a post-install script
60(-s) or to add packages (-a). Then pb can use the chroot to perform even
61more actions in it.
62
63=head1 SYNOPSIS
64
65rpmbootstrap [-vhmqpdk][-s script][-i iso][-a pkg1[,pkg2,...]] distribution-version-arch [target-dir] [mirror [script]]
66
67rpmbootstrap [--verbose][--help][--man][--quiet][--print-rpms][--download-only]
68[--keep][--script script][--iso iso][--add pkg1,[pkg2,...]] distribution-version-arch [target-dir] [mirror [script]]
69
70=head1 OPTIONS
71
72=over 4
73
74=item B<-v|--verbose>
75
76Print a brief help message and exits.
77
78=item B<-h|--help>
79
80Print a brief help message and exits.
81
82=item B<--man>
83
84Prints the manual page and exits.
85
86=item B<-q|--quiet>
87
88Do not print any output.
89
90=item B<-p|--print-rpms>
91
92Print the packages to be installed, and exit.
93Note that a target directory must be specified so rpmbootstrap can determine
94which packages should be installed, and to resolve dependencies.
95The target directory will be deleted.
96
97=item B<-d|--download-only>
98
99Download packages, but don't perform installation.
100
101=item B<-k|--keep>
102
103Keep packages in the cache dir for later reuse. By default remove them.
104
105=item B<-s|--script script>
106
107Name of the script you want to execute on the related VEs after the installation.
108It is executed in host environment.
109You can use the chroot command to execute actions in the VE.
110
111=item B<-i|--iso iso_image>
112
113Name of the ISO image of the distribution you want to install on the related VE.
114
115=item B<-a|--add pkg1[,pkg2,...]>
116
117Additional packages to add from the distribution you want to install on the related VE
118at the end of the chroot build.
119
120=item B<--no-stop-on-error>
121
122Continue through errors with best effort.
123
124=back
125
126=head1 ARGUMENTS
127
128=over 4
129
130=item B<distribution-version-arch>
131
132Full name of the distribution that needs to be installed in the VE. E.g. fedora-11-x86_64.
133
134=item B<target-dir>
135
136This is the target directory under which the VE will be created.
137Created on the fly if needed.
138If none is given use the default directory hosting VE for project-builder.org
139(Cf: vepath parameter in $HOME/.pbrc)
140
141=back
142
143=head1 EXAMPLE
144
145To setup a Fedora 12 distribution with an i386 architecture issue:
146
147rpmbootstrap fedora-12-i386 /tmp/fedora/12/i386
148
149=head1 WEB SITES
150
151The main Web site of the project is available at L<http://www.project-builder.org/>.
152Bug reports should be filled using the trac instance of the project at L<http://trac.project-builder.org/>.
153
154=head1 USER MAILING LIST
155
156Cf: L<http://www.mondorescue.org/sympa/info/pb-announce> for announces and
157L<http://www.mondorescue.org/sympa/info/pb-devel> for the development of the pb project.
158
159=head1 CONFIGURATION FILE
160
161Uses Project-Builder.org configuration file (/etc/pb/pb.conf or /usr/local/etc/pb/pb.conf)
162
163=head1 AUTHORS
164
165The Project-Builder.org team L<http://trac.project-builder.org/> lead by Bruno Cornec L<mailto:bruno@project-builder.org>.
166
167=head1 COPYRIGHT
168
169Project-Builder.org is distributed under the GPL v2.0 license
170described in the file C<COPYING> included with the distribution.
171
172=cut
173
174# ---------------------------------------------------------------------------
175
176$Global::pb_stop_on_error = 1;
177my ($projectbuilderver,$projectbuilderrev) = pb_version_init();
178my $appname = "rpmbootstrap";
179$ENV{'PBPROJ'} = $appname;
180
181# Initialize the syntax string
182
183pb_syntax_init("$appname Version $projectbuilderver-$projectbuilderrev\n");
184pb_temp_init();
185
186GetOptions("help|?|h" => \$opts{'h'},
187 "man|m" => \$opts{'man'},
188 "verbose|v+" => \$opts{'v'},
189 "quiet|q" => \$opts{'q'},
190 "log-files|l=s" => \$opts{'l'},
191 "script|s=s" => \$opts{'s'},
192 "print-rpms|p" => \$opts{'p'},
193 "download-only|d" => \$opts{'d'},
194 "keep|k" => \$opts{'k'},
195 "iso|i=s" => \$opts{'i'},
196 "add|a=s" => \$opts{'a'},
197 "version|V=s" => \$opts{'V'},
198 "stop-on-error!" => \$Global::pb_stop_on_error,
199) || pb_syntax(-1,0);
200
201if (defined $opts{'h'}) {
202 pb_syntax(0,1);
203}
204if (defined $opts{'man'}) {
205 pb_syntax(0,2);
206}
207if (defined $opts{'v'}) {
208 $pbdebug = $opts{'v'};
209}
210if (defined $opts{'q'}) {
211 $pbdebug=-1;
212}
213if (defined $opts{'l'}) {
214 open(pbLOG,"> $opts{'l'}") || die "Unable to log to $opts{'l'}: $!";
215 $pbLOG = \*pbLOG;
216 $pbdebug = 0 if ($pbdebug == -1);
217}
218pb_log_init($pbdebug, $pbLOG);
219#pb_display_init("text","");
220
221#if (defined $opts{'s'}) {
222#$pbscript = $opts{'s'};
223#}
224#if (defined $opts{'i'}) {
225#$iso = $opts{'i'};
226#}
227
228# Get VE name
229$ENV{'PBV'} = shift @ARGV;
230die pb_syntax(-1,1) if (not defined $ENV{'PBV'});
231
232die "Needs to be run as root" if ($EFFECTIVE_USER_ID != 0);
233
234#
235# Initialize distribution info from pb conf file
236#
237pb_log(0,"Starting VE build for $ENV{'PBV'}\n");
238my $pbos = pb_distro_get_context($ENV{'PBV'});
239
240#
241# Check target dir
242# Create if not existent and use default if none given
243#
244pb_env_init_pbrc(); # to get content of HOME/.pbrc
245my $vepath = shift @ARGV;
246
247#
248# Check for command requirements
249#
250my ($req,$opt) = pb_conf_get_if("oscmd","oscmdopt");
251pb_check_requirements($req,$opt,$appname);
252
253if (not defined $vepath) {
254 my ($vestdpath) = pb_conf_get("vepath");
255 $vepath = pb_path_expand("$vestdpath->{'default'}/$pbos->{'name'}/$pbos->{'version'}/$pbos->{'arch'}") if (defined $vestdpath->{'default'});
256}
257
258die pb_log(0,"No target-dir specified and no default vepath found in $ENV{'PBETC'}\n") if (not defined $vepath);
259
260pb_mkdir_p($vepath) if (! -d $vepath);
261
262#
263# Get the package list to download, store them in a cache directory
264#
265my ($rbscachedir) = pb_conf_get_if("cachedir");
266my ($pkgs,$mirror) = pb_distro_get_param($pbos,pb_conf_get("rbsmindep","rbsmirrorsrv"));
267die "No packages defined for $pbos->{name}-$pbos->{version}-$pbos->{arch}" unless $pkgs =~ /\w/;
268
269my $cachedir = "/var/cache/rpmbootstrap";
270$cachedir = $rbscachedir->{'default'} if (defined $rbscachedir->{'default'});
271$cachedir = $rbscachedir->{$appname} if (defined $rbscachedir->{$appname});
272
273# Point to the right subdir and create it if needed
274$cachedir .= "/$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}";
275pb_mkdir_p($cachedir) if (! -d $cachedir);
276
277# Get the complete package name from the mirror
278#
279my $ua = LWP::UserAgent->new;
280$ua->timeout(10);
281$ua->env_proxy;
282
283die "No mirror defined for $pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}" if ((not defined $mirror) || ($mirror =~ /^\t*$/));
284pb_log(0,"Downloading package list from $mirror ...\n");
285my $response = $ua->get($mirror);
286if (! $response->is_success) {
287 if ($mirror =~ /i386/) {
288 # Some distro have an i586 or i686 mirror dir instead for i386
289 warn "Unable to download packages from $mirror for $pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}.";
290 $mirror =~ s|/i386/|/i586/|;
291 $response = $ua->get($mirror);
292 if (! $response->is_success) {
293 die "Unable to download packages from $mirror for $pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}";
294 }
295 }
296}
297pb_log(3,"Mirror $mirror gave answer: ".Dumper($response->dump(maxlength => 0))."\n");
298
299# Try to find where the repodata structure is for later usage
300my $repo = $mirror;
301my $found = 0;
302if ($pbos->{'install'} =~ /yum/) {
303 my $response1;
304 while ($found == 0) {
305 $response1 = $ua->get("$repo/repodata");
306 pb_log(2,"REPO analyzed: $repo\n");
307 if (! $response1->is_success) {
308 $repo = dirname($repo);
309
310 # There is a limit to the loop, when / is reached and nothing found
311 my ($scheme, $account, $host, $port, $path) = pb_get_uri($repo);
312 die "Unable to find the repodata structure of the mirror $mirror\nPlease check the URL or warn the dev team.\n" if (($path =~ /^[\/]+$/) || ($path =~ /^$/));
313
314 # / not reached, so looping
315 next;
316 } else {
317 # repodata found $repo is correct
318 $found = 1;
319 pb_log(2,"REPO found: $repo\n");
320 last;
321 }
322 }
323}
324
325# Manages architectures specificities
326my $parch = $pbos->{'arch'};
327$parch = "i[3456]86" if ($pbos->{'arch'} eq "i386");
328
329# Get the list of packages and their URL in this hash
330my %url;
331foreach my $l (split(/\n/,$response->as_string())) {
332 # Find a href ref in first pos
333 if ($l =~ /<a href="([^<>]*)">([^<>]*)<\/a>/i) {
334 my $url = $1;
335 my $pkg = $1;
336 my $desc = $2;
337 pb_log(3,"Found desc URL $desc: ");
338 # find an rpm package ref name-ver-tag.arch.rpm
339 if ($pkg =~ /(.+)-([^-]+)-([^-]+)\.(noarch|$parch)\.rpm$/) {
340 pb_log(3,"package ($1 + $2 + $3 + $4)\n");
341 $url{$1} = "$mirror/$url";
342 } else {
343 pb_log(3,"not a package\n");
344 }
345 }
346}
347
348#
349# Prepare early the yum cache env for the VE in order to copy in it packages on the fly
350#
351my $oscachedir = "/tmp";
352my $osupdcachedir;
353my $osupdname = "";
354
355if ($pbos->{'install'} =~ /yum/) {
356 $oscachedir = "$vepath/var/cache/yum/core/packages/";
357 $osupdcachedir = "$vepath/var/cache/yum/updates-released/packages/";
358 $osupdname = "YUM";
359 # Recent Fedora release use a new yum cache dir
360 if (($pbos->{'name'} eq "fedora") && ($pbos->{'version'} > 8)) {
361 $oscachedir = "$vepath/var/cache/yum/$pbos->{'arch'}/$pbos->{'version'}/fedora/packages";
362 $osupdcachedir = "$vepath/var/cache/yum/$pbos->{'arch'}/$pbos->{'version'}/updates/packages";
363 $osupdcachedir = "$vepath/var/cache/yum/updates-released/packages/";
364 }
365} elsif ($pbos->{'install'} =~ /zypper/) {
366 $oscachedir = "$vepath/var/cache/zypp/packages/opensuse/suse/$pbos->{'arch'}";
367 $osupdname = "Zypper";
368} elsif ($pbos->{'install'} =~ /urpmi/) {
369 $oscachedir = "$vepath/var/cache/urpmi/rpms";
370 $osupdname = "URPMI";
371}
372pb_log(1,"Setting up $osupdname cache in VE\n");
373pb_mkdir_p($oscachedir);
374pb_mkdir_p($osupdcachedir) if (defined $osupdcachedir);
375
376# For each package to process, get it, put it in the cache dir
377# and extract it in the target dir. If not asked to keep, remove it
378# Just download if asked so.
379
380my $warning = 0;
381my $lwpkg ="";
382my @installed_packages;
383
384foreach my $p (split(/,/,$pkgs)) {
385 pb_log(1,"Processing package $p ...\n");
386 # Just print packages names if asked so.
387 if (defined $url{$p}) {
388 if ($opts{'p'}) {
389 pb_log(0,"$url{$p}\n");
390 next;
391 } else {
392 # Now download if not already in cache
393 my $p1 = basename($url{$p});
394 if (! -f "$cachedir/$p1") {
395 pb_system("wget --quiet -O $cachedir/$p1 $url{$p}","Downloading package $p1 ...");
396 } else {
397 pb_log(1,"Package $p1 already in cache\n");
398 }
399
400 # End if download only
401 if ($opts{'d'}) {
402 next;
403 }
404
405 #
406 # Copy the cached .RPM files into the oscachedir directory, so that os doesn't need to download them again.
407 #
408 pb_log(1,"Link package into $oscachedir\n");
409 copy("$cachedir/$p1",$oscachedir) if (defined $oscachedir);
410 symlink("$oscachedir/$p1","$osupdcachedir/p1") if (defined $osupdcachedir);
411
412 # And extract it to the finale dir
413 pb_system("cd $vepath ; rpm2cpio $cachedir/$p1 | cpio -ivdum","Extracting package $p1 into $vepath");
414
415 # Remove cached package if not asked to keep
416 if (! $opts{'k'}) {
417 unlink("$cachedir/$p1");
418 }
419 push(@installed_packages, $p);
420 }
421 } else {
422 pb_log(0,"WARNING: unable to find URL for $p\n");
423 $warning++;
424 $lwpkg .= " $p";
425 }
426}
427
428if ($warning ge 1) {
429pb_log(0,"$warning WARNINGS found.\nMaybe you should review your package list for $pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}\nand remove$lwpkg\n");
430}
431
432# Stop here if we just print
433if ($opts{'p'}) {
434 exit(0);
435}
436
437# Now executes the VE finalization steps required for it to work correctly
438pb_log(0,"VE post configuration\n");
439
440# yum needs that distro-release package be installed, so force it
441if ($pbos->{'install'} =~ /yum/) {
442 my $ddir = $pbos->{'name'};
443 foreach my $p1 (<$cachedir/($ddir|redhat)-release-*.rpm>) {
444 copy("$cachedir/$p1","$vepath/tmp");
445 pb_system("chroot $vepath rpm -ivh --force --nodeps /tmp/$p1","Forcing RPM installation of $p1");
446 unlink("$vepath/tmp/$p1");
447 }
448}
449#
450# Make sure there is a resolv.conf file present, such that DNS lookups succeed.
451#
452pb_log(1,"Creating resolv.conf\n");
453pb_mkdir_p("$vepath/etc");
454copy("/etc/resolv.conf","$vepath/etc/");
455
456#
457# BUGFIX:
458#
459if ((($pbos->{'name'} eq "centos") || ($pbos->{'name'} eq "rhel")) && ($pbos->{'version'} eq "5")) {
460 pb_log(1,"BUGFIX for centos-5\n");
461 pb_mkdir_p("$vepath/usr/lib/python2.4/site-packages/urlgrabber.skx");
462 foreach my $i (<$vepath/usr/lib/python2.4/site-packages/urlgrabber/keepalive.*>) {
463 move($i,"$vepath/usr/lib/python2.4/site-packages/urlgrabber.skx/");
464 }
465}
466
467#
468# /proc needed
469#
470pb_mkdir_p("$vepath/proc");
471pb_system("mount -o bind /proc $vepath/proc","Mounting /proc") unless (-d "$vepath/proc/$$";);
472
473#
474# Some devices may be needed
475#
476pb_mkdir_p("$vepath/dev");
477chmod 0755,"$vepath/dev";
478pb_system("mknod -m 644 $vepath/dev/random c 1 8","Creating $vepath/dev/random") if (! -c "$vepath/dev/random");
479pb_system("mknod -m 644 $vepath/dev/urandom c 1 9","Creating $vepath/dev/urandom") if (! -c "$vepath/dev/urandom");
480pb_system("mknod -m 666 $vepath/dev/zero c 1 5","Creating $vepath/dev/zero") if (! -c "$vepath/dev/zero");
481pb_system("mknod -m 666 $vepath/dev/null c 1 3","Creating $vepath/dev/null") if (! -c "$vepath/dev/null");
482
483my $minipkglist;
484
485pb_log(1,"Adapting $osupdname repository entries\n");
486if ($pbos->{'install'} =~ /yum/) {
487 #
488 # Force the architecture for yum
489 # The goal is to allow i386 chroot on x86_64
490 #
491 # FIX: Not sufficient to have yum working
492 # mirrorlist is not usable
493 # $releasever also needs to be filtered
494 # yum.conf as well
495 foreach my $i (<$vepath/etc/yum.repos.d/*.repo>,"$vepath/etc/yum.conf") {
496 pb_system("sed -i -e 's/\$basearch/$pbos->{'arch'}/g' $i","","quiet");
497 pb_system("sed -i -e 's/\$releasever/$pbos->{'version'}/g' $i","","quiet");
498 pb_system("sed -i -e 's/^mirrorlist/#mirrorlist/' $i","","quiet");
499 # rather use neutral separators here
500 pb_system("sed -i -e 's|^#baseurl.*\$|baseurl=$repo|' $i","","quiet");
501 }
502 $minipkglist = "ldconfig yum passwd vim-minimal dhclient authconfig";
503 # TODO
504 # $minipkglist = join(" ", "ldconfig yum passwd vim-minimal dhclient authconfig", @installed_packages);
505} elsif ($pbos->{'install'} =~ /zypper/) {
506 pb_mkdir_p("$vepath/etc/zypp/repos.d");
507 open(REPO,"> $vepath/etc/zypp/repos.d/$pbos->{'name'}-$pbos->{'version'}") || die "Unable to create repo file";
508 my $baseurl = dirname(dirname($mirror));
509 # Setup the repo
510 if ($pbos->{'version'} eq "10.2") {
511 pb_system("chroot $vepath /bin/bash -c \"yes | /usr/bin/zypper sa $baseurl $pbos->{'name'}-$pbos->{'version'}\"","Bootstrapping Zypper");
512 } else {
513 pb_system("chroot $vepath /bin/bash -c \"/usr/bin/zypper rr $pbos->{'name'}-$pbos->{'version'}\"","Bootstrapping Zypper",undef,1); # don't care if remove fails if add succeeds.
514 pb_system("chroot $vepath /bin/bash -c \"/usr/bin/zypper ar $baseurl $pbos->{'name'}-$pbos->{'version'}\"","Bootstrapping Zypper");
515 }
516 #print REPO << "EOF";
517#[opensuse]
518#name=$pbos->{'name'}-$pbos->{'version'}
519#baseurl=$baseurl
520#enabled=1
521#gpgcheck=1
522#
523#EOF
524 close(REPO);
525 $minipkglist = "zypper";
526 # TODO: Re-installing packages missing and necessary on opensuse 11.4 to get /etc/passwd created.
527 # $minipkglist = join(" ", "zypper", @installed_packages);
528} elsif ($pbos->{'install'} =~ /urpmi/) {
529 # Setup the repo
530 my $baseurl = dirname(dirname(dirname($mirror)));
531 pb_system("chroot $vepath /bin/bash -c \"urpmi.addmedia --distrib $baseurl\"","Bootstrapping URPMI");
532 # TODO here too ?
533 $minipkglist = "ldconfig urpmi passwd vim-minimal dhcp-client";
534}
535
536#
537# Run "install the necessary modules".
538# No need for sudo here
539#
540$pbos->{'install'} =~ s/sudo//g;
541pb_system("chroot $vepath /bin/bash -c \"$pbos->{'install'} $minipkglist \"","Bootstrapping OS by running $pbos->{'install'} $minipkglist");
542
543# CentOS6 will replace the yum.repos.d files; oddly it will leave the yum.conf file alone and make the new one ".rpmnew"
544if (($pbos->{'name'} eq "centos") && ($pbos->{'version'} =~ /^6.*/)) {
545 pb_log(0,"Fixing $pbos->{'name'} $pbos->{'version'} bug for yum conf files");
546 foreach my $from (<$vepath/etc/yum.repos.d/*.rpmorig>) {
547 my $to = $from;
548 $to =~ s/.rpmorig$//;
549 pb_system("mv $from $to", "Recover $from");
550 }
551}
552
553#
554# make 'passwd' work.
555#
556pb_log(1,"Authfix\n");
557pb_system("chroot $vepath /bin/bash -c \"if [ -x /usr/bin/authconfig ]; then /usr/bin/authconfig --enableshadow --update; fi\"","Calling authconfig");
558
559# Installed additional packages we were asked to
560if (defined $opts{'a'}) {
561 $opts{'a'} =~ s/,/ /g;
562 pb_system("chroot $vepath /bin/bash -c \"$pbos->{'install'} $opts{'a'} \"","Adding packages to OS by running $pbos->{'install'} $opts{'a'}");
563}
564
565#
566# Clean up
567#
568pb_log(1,"Cleaning up\n");
569if ($pbos->{'install'} =~ /yum/) {
570 pb_system("chroot $vepath /usr/bin/yum clean all","Cleaning yum");
571}
572pb_system("umount $vepath/proc","Unmounting /proc");
573find(\&unlink_old_conf, $vepath);
574
575# Executes post-install step if asked for
576if ($opts{'s'}) {
577 pb_system("$opts{'s'} $vepath","Executing the post-install script: $opts{'s'} $vepath");
578}
579
580if ($warning > 0) {
581 pb_log(0,"\n\n\n\n$warning WARNINGS found.\nMaybe you should review your package list for $pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}\nand remove$lwpkg\n");
582 pb_log(0,"waiting 60 seconds to give you a chance to notice.\n");
583 sleep(60);
584}
585
586# Function for File::Find
587sub unlink_old_conf {
588
589 unlink($_) if ($_ =~ /\.rpmorig$/);
590 unlink($_) if ($_ =~ /\.rpmnew$/);
591}
Note: See TracBrowser for help on using the repository browser.