summaryrefslogtreecommitdiffstats
path: root/t/gendistrib
diff options
context:
space:
mode:
Diffstat (limited to 't/gendistrib')
-rwxr-xr-xt/gendistrib407
1 files changed, 407 insertions, 0 deletions
diff --git a/t/gendistrib b/t/gendistrib
new file mode 100755
index 00000000..e0457505
--- /dev/null
+++ b/t/gendistrib
@@ -0,0 +1,407 @@
+#!/usr/bin/perl
+
+(our $VERSION) = q(Id: gendistrib 20724 2006-11-30 13:13:27Z rafael ) =~ /(\d+)/;
+
+use strict;
+use Cwd;
+use MDV::Distribconf::Build;
+use Getopt::Long;
+
+sub usage () {
+ require Pod::Usage;
+ Pod::Usage::pod2usage({ '-verbose' => 1 });
+ exit 0;
+}
+
+my %urpmfiles;
+my %old;
+
+GetOptions(
+ 'blind' => \my $blind,
+ 'clean' => \my $clean,
+ 'hdlists=s' => \$urpmfiles{hdlists},
+ 'help|h' => \&usage,
+ 'mediacfg=s' => \$urpmfiles{mediacfg},
+ 'nobadrpm' => \my $nobadrpm,
+ 'noemptymedia' => \my $noemptymedia,
+ 'nomd5sum' => \my $nomd5sum,
+ 'skipmissingdir' => \my $skipmissingdir,
+ 's' => \my $nooutput,
+ 'v|version' => sub { warn "$0 version $VERSION\n"; exit 0 },
+
+# old stuff
+ 'chkdep' => \$old{chkdep},
+ 'compss=s' => \$old{compss},
+ 'depslist=s' => \$old{depslist},
+ 'noclean' => \$old{noclean},
+ 'provides=s' => \$old{provides},
+ 'headersdir=s' => \$old{headersdir},
+ 'nomediainfo' => \$old{nomediainfo},
+);
+
+foreach (qw(chkdep compss depslist noclean headersdir provides nomediainfo)) {
+ $old{$_} and warn "--$_ is obsolete (not used anymore)\n";
+}
+
+@ARGV == 1 or usage();
+my ($root) = @ARGV;
+
+my $distrib = MDV::Distribconf::Build->new($root);
+
+$distrib->loadtree or die "$root does not seem to be a distribution tree\n";
+
+if (defined($urpmfiles{mediacfg})) {
+ $distrib->parse_mediacfg($urpmfiles{mediacfg}) or die "Can't read $urpmfiles{mediacfg}\n";
+} elsif (defined($urpmfiles{hdlists})) {
+ $distrib->parse_hdlists($urpmfiles{hdlists}) or die "Can't read $urpmfiles{hdlists}\n";
+} else {
+ $distrib->parse_mediacfg || $distrib->parse_hdlists or die "Can't read the distrib config\n";
+}
+
+my $destinfodir = $distrib->getfullpath(undef, "infodir");
+$urpmfiles{version} = $distrib->getfullpath(undef, "VERSION"),
+
+# Error which are fatale
+my @fatal = qw(SAME_INDEX);
+push @fatal, 'MISSING_MEDIADIR' if !$skipmissingdir;
+my @IGNORE = qw(MISSING_INDEX);
+my @fatalerrors; # fatales error show at the end
+$distrib->check(sub {
+ my %info = @_;
+ grep { $_ eq $info{errcode} } @IGNORE and next;
+ if (grep { $_ eq $info{errcode} } @fatal) {
+ push(@fatalerrors, "$info{level}: $info{message}");
+ } else {
+ printf STDERR "$info{level}: $info{message}\n" unless $nooutput;
+ }
+ }
+);
+
+if (@fatalerrors) {
+ printf STDERR <<EOF;
+
+A fatal error has been detected, continueing is likely to produce an invalid
+tree. (Missing directories can be ignored with --skipmissingdir.)
+Fix the error in media.cfg and retry:
+
+EOF
+ print STDERR "$_\n" foreach @fatalerrors;
+ print STDERR "\n";
+ exit(1);
+}
+
+my @hdlists;
+foreach my $m ($distrib->listmedia) {
+ my $path = $distrib->getfullpath($m, 'path');
+ -d $path or next; # this has been checked earlier
+
+ push @hdlists, {
+ media => $m,
+ dir => $distrib->getpath($m, 'path'),
+ path => $path,
+ descr => $distrib->getvalue($m, 'name'),
+ hdlist2 => $distrib->getfullpath($m, 'hdlist'),
+ synthesis2 => $distrib->getfullpath($m, 'synthesis'),
+ pubkey2 => $distrib->getfullpath($m, 'pubkey'),
+ hdlist => "$path/media_info/hdlist.cz",
+ synthesis => "$path/media_info/synthesis.hdlist" . $distrib->getvalue($m, 'synthesis-suffix'),
+ pubkey => "$path/media_info/pubkey",
+ noneedrebuild => $blind || $clean ? 0 : $distrib->check_index_sync($m, 'formedia'),
+ };
+}
+
+if (!-d $destinfodir) {
+ mkdir $destinfodir, 0755
+ or die qq(Can't create directory "$destinfodir": $!\n);
+}
+
+my $infodir = $distrib->getfullpath(undef, 'infodir');
+
+foreach my $d ($infodir, map { "$_->{path}/media_info" } @hdlists) {
+ if (! -d $d) {
+ mkdir $d, 0755 or die qq(Can't create directory "$d": $!\n);
+ }
+}
+
+foreach my $e (@hdlists) {
+ if ($e->{dir} =~ /%\{ARCH\}/) {
+ die "sorry, %{ARCH} not supported anymore\n";
+ }
+ @{$e->{files}} = glob("$root/$e->{dir}/*.rpm") or do {
+ print STDERR "unable to find rpm files in $e->{dir}\n" unless $nooutput;
+ next;
+ };
+}
+
+if ($noemptymedia) {
+ if (grep { @{$_->{files}} == 0 } @hdlists) {
+ die "Empty media were found, stopping\n";
+ }
+}
+
+my $synthesis_filter = $distrib->getvalue(undef, 'synthesis-filter');
+my $xml_info_filter = $distrib->getvalue(undef, 'xml-info-filter');
+foreach my $e (grep { !$_->{noneedrebuild} } @hdlists) {
+ print STDERR qq(building hdlist & synthesis for medium "$e->{descr}"\n) unless $nooutput;
+ my $file_deps = "$destinfodir/file-deps";
+ my $options = join(' ',
+ '--allow-empty-media',
+ $nooutput ? '--quiet' : (),
+ $clean ? '--clean' : (),
+ $nobadrpm ? '--no-bad-rpm' : (),
+ $nomd5sum ? "--no-md5sum" : (),
+ $distrib->getvalue($e->{media}, 'xml-info') ? '--xml-info' : (),
+ $synthesis_filter ? "--synthesis-filter '$synthesis_filter'" : (),
+ $xml_info_filter ? "--xml-info-filter '$xml_info_filter'" : (),
+ -e $file_deps ? "--file-deps $file_deps" : (),
+ );
+ my $cmd = "genhdlist2 $options $e->{path}";
+ print "running $cmd\n" unless $nooutput;
+ system($cmd) == 0 or die "$cmd failed\n";
+}
+
+foreach my $e (@hdlists) {
+ hdlist_alternate_location($e->{hdlist2}, $e->{hdlist});
+ hdlist_alternate_location($e->{synthesis2}, $e->{synthesis});
+ $e->{pubkey2} =~ s/ /_/g; # workaround MDV::Distribconf issue
+ hdlist_alternate_location($e->{pubkey2}, $e->{pubkey});
+}
+
+if (grep { ! $_->{noneedrebuild} } @hdlists) {
+
+ if (-f $destinfodir . '/media.cfg') {
+ if (! -f "$destinfodir/hdlists" ||
+ (stat($distrib->getfullpath(undef, 'infodir') . '/media.cfg'))[9] >
+ (stat($destinfodir . '/hdlists'))[9]) {
+ print STDERR "Write hdlists file\n" unless $nooutput;
+ $distrib->write_hdlists($destinfodir . '/hdlists')
+ or print STDERR "Can't write $destinfodir/hdlists file\n";
+ }
+ }
+}
+if (grep { !$_->{noneedrebuild} } @hdlists) {
+ unlink "$destinfodir/MD5SUM"; #- safety cleaning
+ unless ($nomd5sum) {
+ # this MD5SUM is mostly obsolete, but is still needed up to 2007.1
+ # (and even on cooker for existing urpmi.cfg)
+ require File::Glob;
+ require Digest::MD5;
+ my $md5sum;
+ my $cwd = getcwd();
+ chdir($destinfodir);
+ foreach my $fn (glob("hdlist_*"), glob("synthesis*")) {
+ open(my $fh, '<', $fn) or die "Can't open '$fn': $!";
+ binmode($fh);
+ $md5sum .= Digest::MD5->new->addfile($fh)->hexdigest . " $fn\n";
+ }
+ chdir($cwd);
+ open my $md5sumfh, '>', "$destinfodir/MD5SUM" or die "Can't create $destinfodir/MD5SUM: $!\n";
+ print $md5sumfh $md5sum if $md5sum;
+ }
+
+ print STDERR "Calculating size of medias\n" unless $nooutput;
+ foreach my $e (@hdlists) {
+ my $size = 0;
+ foreach (@{$e->{files} || []}) {
+ $size += (stat($_))[7];
+ }
+ my $blk = 1;
+ my $showsize = $size;
+ my @unit = (' ', qw(k m g));
+ while (@unit) {
+ my $u = shift(@unit);
+ if ($size / $blk < 1) {
+ last;
+ }
+ $showsize = sprintf('%d%s', $size / $blk, $u);
+ $blk *= 1024;
+ }
+ $distrib->setvalue($e->{media}, 'size', $showsize);
+ }
+
+ print STDERR "Rewriting media.cfg file\n" unless $nooutput;
+ $distrib->write_mediacfg($urpmfiles{mediacfg});
+
+ print STDERR "Building version file\n" unless $nooutput;
+ $distrib->write_version($urpmfiles{version});
+}
+
+sub hdlist_alternate_location {
+ my ($alternate, $main) = @_;
+
+ if (! -e $main) {
+ print STDERR "missing $main, not creating alternate location $alternate\n";
+ } elsif (inode($alternate) == inode($main)) {
+ # ok
+ } else {
+ if (-l $alternate) {
+ print STDERR "bad alternate location " . readlink($alternate) . ", replacing it\n";
+ unlink $alternate;
+ } elsif (-e $alternate) {
+ print STDERR "replacing existing plain file $alternate with a symlink\n";
+ unlink $alternate;
+ }
+ print STDERR qq(link alternate location $alternate\n) unless $nooutput;
+ relative_symlink($main, $alternate);
+ }
+}
+
+sub inode {
+ my ($f) = @_;
+ (stat($f))[1];
+}
+
+sub relative_symlink {
+ my ($src, $dest) = @_;
+
+ # cleanup
+ foreach ($src, $dest) {
+ s!//!/!g;
+ s!/\./!/!g;
+ }
+
+ my @src = split('/', $src);
+ my @dest = split('/', $dest);
+ pop @dest;
+
+ while (@src && @dest && $src[0] eq $dest[0]) {
+ shift @src;
+ shift @dest;
+ }
+ symlink join('/', ('..') x @dest, @src), $dest;
+}
+
+__END__
+
+=head1 NAME
+
+gendistrib - generates a mirror tree for a distribution
+
+=head1 SYNOPSIS
+
+ gendistrib [options] directory
+
+=head1 OPTIONS
+
+=over 4
+
+=item --blind
+
+Always rebuild indexes, without checking whether it's needed.
+
+=item --clean
+
+Force rebuild of indexes from scratch.
+
+=item --hdlists file
+
+Path of the F<hdlists> file (defaults to F<media/media_info/hdlists>). This is
+deprecated; if gendistrib finds a F<media.cfg> file, it will use it and ignore
+the F<hdlists> file unless this option is given.
+
+=item --mediacfg file
+
+Use the specified F<media.cfg> file (defaults to F<media/media_info/media.cfg>).
+
+=item --nobadrpm
+
+Don't abort when encountering bad rpms.
+
+=item --noemptymedia
+
+Stop and abort if an empty media is found.
+
+=item --nomd5sum
+
+Don't generate MD5SUM files.
+
+=item --skipmissingdir
+
+If a media dir is missing, ignore it instead of aborting.
+
+=item -s
+
+Silent mode.
+
+=back
+
+=head1 DESCRIPTION
+
+F<gendistrib> is a tool that helps to generate the structure of a Mandriva
+RPM repository, compatible with Mandriva tools (F<urpmi>, F<rpmdrake>,
+etc.)
+
+=head2 General Structure of a Repository
+
+A typical repository, under a root directory F</ROOT/>, has the following
+structure:
+
+ ROOT/ - media/
+ |- contrib/
+ | `- media_info/
+ |- main/
+ | `- media_info/
+ `- media_info/
+
+In this example, we have two media, called I<main> and I<contrib>. The
+RPMs packages are placed in the F<main> and F<contrib> subdirectories.
+Repository metadata is contained in the top-level F<media_info> directory.
+Per-media metadata are contained in the F<main/media_info> and
+F<contrib/media_info> subdirectories.
+
+=head2 Configuration of the distribution tree
+
+Before using F<gendistrib>, you must create a file F<media_info/media.cfg>
+to describe your repository. (An empty file will work, but this isn't
+recommended.) The syntax of this file is reminiscent of F<.ini> files.
+
+A first section C<[media_info]> contains global information about the
+repository:
+
+ [media_info]
+ version=2006.0
+ branch=Cooker
+ arch=i586
+
+Then, supply one section per media.
+
+ [main]
+ hdlist=hdlist_main.cz
+ name=Main
+
+Here, the C<hdlist> parameter specifies what will be the name of the
+hdlist file in the top-level F<media_info> directory. C<name> is a human
+readable label for the media.
+
+=head2 Operation
+
+F<gendistrib> should be passed the F<ROOT> directory as parameter. It will
+then generate the hdlist and synthesis files and all other files needed
+for proper repository operation.
+
+=head1 SEE ALSO
+
+genhdlist2(1), and MDV::Distribconf(3) for description of the format of the
+F<media.cfg> file.
+
+=head1 COPYRIGHT
+
+Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 MandrakeSoft SA
+
+Copyright (C) 2005, 2006 Mandriva SA
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+=cut