On Mon, 2002-01-28 at 15:48, John Summerfield wrote: > I've seen the question asked, but I don't recall a good answer. > > Does anyone have a reliable script that will take a package set (as > from the original CD collection) and merge in an updates tree, removing > old versions of packages? Why, yes. Here is one that we use. It needs rpm-perl to be installed to operate properly. Thanks. Peter
#!/usr/bin/perl -w # # $Id: overlay.pl,v 1.5 2002/01/25 00:57:21 pzb Exp $ # # Overlays a set of RPMS on another directory of RPMs deleting old # versions as necessary. # # Licensed under the GPL # use File::Basename; use RPM::Header; $arches = "alpha axp noarch"; while ($ARGV[0] =~ /^--/) { $_ = shift; chomp; $arches = shift if /--arches/; $linkdir = shift if /--linkdir/; $passcond = shift if /--passcond/; $pkglist = shift if /--pkglist/; } $basedir = shift; $patchdir = join " ", @ARGV; $notupdated = 0; if ($patchdir eq "" || $basedir eq "") { print STDERR "Usage: overlay basedir patchdir\n"; exit 0; } @archlist = split / /, $arches; foreach (@archlist) { $validarch{$_} = 1; } sub rpm_fullname { local($rpm) = @_; return basename($rpm->source_name()); return $rpm->{"NAME"} . "-" . $rpm->{"VERSION"} . "-" . $rpm->{"RELEASE"} . "." . &rpm_arch($rpm) . ".rpm"; } sub rpm_arch { local($rpm) = @_; return $rpm->is_source() ? "src" : $rpm->{"ARCH"}; } sub make_rpmlist { local($dirs) = @_; local($dirhandle, $file, $dir); local(@allfiles, @rpmlist); @rpmlist = (); foreach $dir (split ' ', $dirs) { opendir $dirhandle, $dir or die "Couldn't open", $dir; $file = readdir $dirhandle; while (defined($file)) { $basename = $file; $file = $dir . "/" . $file; if ((substr $basename, 0, 1) eq ".") { } elsif (-d $file) { push @rpmlist, make_rpmlist($file); } elsif (substr($file, -4) eq ".rpm") { $allfiles[++$#allfiles] = $file; } $file = readdir $dirhandle; } closedir $dirhandle; } foreach $file (@allfiles) { $rpmlist[++$#rpmlist] = new RPM::Header $file; } return @rpmlist; } sub make_rpmlist_from_file { local($pfile) = @_; local(@rpmlist); @rpmlist = (); open PKGLIST, $pfile or die "Error opening file"; while (<PKGLIST>) { chomp; $rpmlist[++$#rpmlist] = new RPM::Header $_; } close PKGLIST; return @rpmlist; } # Format: name <TAB> arch <TAB> EVR <TAB> fullname <TAB> source rpm <TAB> filename <CRLF> $oldpipe=$|; $|=1; print STDOUT "Getting new rpm info"; if ($pkglist and -r $pkglist) { @patchrpms = &make_rpmlist_from_file($pkglist); } else { @patchrpms = &make_rpmlist($patchdir); } print STDOUT "\nGetting original rpm info"; @oldrpms = &make_rpmlist($basedir); print STDOUT "\n"; $|=$oldpipe; foreach (@oldrpms) { $rpm = $_; print STDERR "WARNING: " .$rpm->{"name"}."(".&rpm_arch($rpm).") already found!\n" if (exists $baserpms{$rpm->{"name"},&rpm_arch($rpm)}); $baserpms{$rpm->{"name"},&rpm_arch($rpm)} = $rpm; } foreach $rpm (@patchrpms) { $name = $rpm->{'name'}; $arch = &rpm_arch($rpm); next if (!exists $validarch{$arch}); if (exists $baserpms{$name,$arch}) { $rpmcmp = $rpm->cmpver($baserpms{$name,$arch}); if ($rpmcmp == 1) { print "Updating $name($arch)\n"; system("rm " . $baserpms{$name,$arch}->source_name()); $newname = $basedir."/".&rpm_fullname($rpm); $sysres = system("cp -p " . $rpm->source_name() . " " . $newname); if ($linkdir) { $linkname = $linkdir."/".&rpm_fullname($rpm); system("ln $newname $linkname"); } # Make new object to change the ->source_name() $baserpms{$name,$arch}= new RPM::Header $newname if ($sysres == 0); } elsif ($rpmcmp == -1) { print "Not updating $name($arch) - old package\n"; $notupdated++ unless ($passcond eq "passlt"); } elsif ($rpmcmp == 0) { print "Not updating $name($arch) - same version found\n"; $notupdated++ unless ($passcond eq "passeq" or $passcond eq "passlt"); } else { print "RPM version comparision failed -- unknown return: $rpmcmp"; exit 255; } } else { print "Adding $name($arch)\n"; $newname = $basedir."/".&rpm_fullname($rpm); $sysres = system("cp -p " . $rpm->source_name() . " " . $newname); if ($linkdir) { $linkname = $linkdir."/".&rpm_fullname($rpm); system("ln $newname $linkname"); } # Make new object to change the ->source_name() $baserpms{$name,$arch} = new RPM::Header $newname if ($sysres == 0); } } exit $notupdated;