summary refs log tree commit diff
path: root/pkgs/build-support/vm/rpm/rpm-closure.pl
blob: 2878e90a1f255d43fbab76af5a8b6c7d9194d0dd (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
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};
    print STDERR keys %{$pkg->{format}->{'rpm:provides'}}, "\n";
    if (defined $pkg->{format}->{'rpm:provides'}) {
        my $provides = $pkg->{format}->{'rpm:provides'}->{'rpm:entry'};
        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";