From 19bcfb8231d1dfc5db4e798ea0a35d00fe7d7ca5 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 9 Apr 2008 10:06:16 +0000 Subject: [PATCH] * A tool for generating the closure of a set of top-level RPM packages from the "primary.xml.gz" file of Fedora and OpenSUSE distributions. Analogous to the Deb closure generator. * Image for Fedora 8. svn path=/nixpkgs/trunk/; revision=11510 --- pkgs/build-support/vm/default.nix | 7 ++ pkgs/build-support/vm/rpm/rpm-closure.nix | 52 ++++++++++++++ pkgs/build-support/vm/rpm/rpm-closure.pl | 88 +++++++++++++++++++++++ 3 files changed, 147 insertions(+) create mode 100644 pkgs/build-support/vm/rpm/rpm-closure.nix create mode 100644 pkgs/build-support/vm/rpm/rpm-closure.pl diff --git a/pkgs/build-support/vm/default.nix b/pkgs/build-support/vm/default.nix index dfbabcdb2d0..e01c34c5ac6 100644 --- a/pkgs/build-support/vm/default.nix +++ b/pkgs/build-support/vm/default.nix @@ -539,6 +539,13 @@ rec { rpms = import ./rpm/fedora-5-i386.nix {inherit fetchurl;}; }; + fedora8i386 = fillDiskWithRPMs { + name = "fedora-8-i386"; + fullName = "Fedora 8 (i386)"; + size = 1024; + rpms = import (import ./rpm/rpm-closure.nix).rpmsFedora8i386 {inherit fetchurl;}; + }; + ubuntu710i386 = fillDiskWithDebs { name = "ubuntu-7.10-gutsy-i386"; fullName = "Ubuntu 7.10 Gutsy (i386)"; diff --git a/pkgs/build-support/vm/rpm/rpm-closure.nix b/pkgs/build-support/vm/rpm/rpm-closure.nix new file mode 100644 index 00000000000..a420bbb9880 --- /dev/null +++ b/pkgs/build-support/vm/rpm/rpm-closure.nix @@ -0,0 +1,52 @@ +with import ../../../.. {}; + +rec { + + rpmClosureGenerator = + {name, packages, urlPrefix, toplevel}: + runCommand "${name}.nix" {buildInputs = [perl perlXMLSimple];} '' + gunzip < ${packages} > ./packages.xml + perl -w ${./rpm-closure.pl} \ + ./packages.xml ${urlPrefix} ${toString toplevel} > $out + ''; + + + commonFedoraPackages = [ + "autoconf" + "automake" + "basesystem" + "bzip2" + "curl" + "diffutils" + "fedora-release" + "findutils" + "gawk" + "gcc-c++" + "gzip" + "make" + "patch" + "perl" + "pkgconfig" + "rpm" + "rpm-build" + "tar" + "unzip" + ]; + + + # Fedora 8, i386. + + packagesFedora8i386 = fetchurl { + url = mirror://fedora/linux/releases/8/Fedora/i386/os/repodata/primary.xml.gz; + sha256 = "0vr9345rrk0vhs4pc9cjp8npdkqz0xqyirv84vhyfn533m9ws36f"; + }; + + rpmsFedora8i386 = rpmClosureGenerator { + name = "fedora-8-i386"; + packages = packagesFedora8i386; + urlPrefix = mirror://fedora/linux/releases/8/Fedora/i386/os; + toplevel = [commonFedoraPackages]; + }; + + +} diff --git a/pkgs/build-support/vm/rpm/rpm-closure.pl b/pkgs/build-support/vm/rpm/rpm-closure.pl new file mode 100644 index 00000000000..9b44b9747df --- /dev/null +++ b/pkgs/build-support/vm/rpm/rpm-closure.pl @@ -0,0 +1,88 @@ +use strict; +use XML::Simple; + +my $packagesFile = shift @ARGV; +my $urlPrefix = shift @ARGV; +my @toplevelPkgs = @ARGV; + +my $xml = XMLin($packagesFile, ForceArray => ['package', 'rpm:entry', 'file'], KeyAttr => ['name']) or die; +my $pkgs = $xml->{'package'}; + +print STDERR "file contains $xml->{packages} packages\n"; + + +my %provides; +foreach my $pkgName (keys %{$pkgs}) { + #print STDERR "looking at $pkgName\n"; + my $pkg = $pkgs->{$pkgName}; + my $provides = $pkg->{format}->{'rpm:provides'}->{'rpm:entry'} or die; + foreach my $req (keys %{$provides}) { + #print STDERR " provides $req\n"; + #die "multiple provides for $req" if defined $provides{$req}; + $provides{$req} = $pkgName; + } + if (defined $pkg->{format}->{file}) { + foreach my $file (@{$pkg->{format}->{file}}) { + #print STDERR " provides file $file\n"; + $provides{$file} = $pkgName; + } + } +} + + +my %donePkgs; +my @needed = (); + +sub closePackage { + my $pkgName = shift; + + return if defined $donePkgs{$pkgName}; + $donePkgs{$pkgName} = 1; + + print STDERR ">>> $pkgName\n"; + + my $pkg = $pkgs->{$pkgName} or die "package $pkgName doesn't exist"; + + my $requires = $pkg->{format}->{'rpm:requires'}->{'rpm:entry'} or die; + + my @deps = (); + foreach my $req (keys %{$requires}) { + next if $req =~ /^rpmlib\(/; + print STDERR " needs $req\n"; + my $provider = $provides{$req}; + if (!defined $provider) { + print STDERR " WARNING: no provider for $req\n"; + next; + } + print STDERR " satisfied by $provider\n"; + push @deps, $provider; + } + + closePackage($_) foreach @deps; + + push @needed, $pkgName; +} + + +foreach my $pkgName (@toplevelPkgs) { + closePackage $pkgName; +} + + +# Generate the output Nix expression. +print "# This is a generated file. Do not modify!\n"; +print "# Following are the RPM packages constituting the closure of: @toplevelPkgs\n\n"; +print "{fetchurl}:\n\n"; +print "[\n\n"; + +foreach my $pkgName (@needed) { + my $pkg = $pkgs->{$pkgName}; + die if $pkg->{checksum}->{type} ne "sha"; + print " (fetchurl {\n"; + print " url = $urlPrefix/$pkg->{location}->{href};\n"; + print " sha1 = \"$pkg->{checksum}->{content}\";\n"; + print " })\n"; + print "\n"; +} + +print "]\n";