#! /usr/bin/perl -w use strict; use IPC::Open2; use POSIX qw(tmpnam); my $tmpdir; do { $tmpdir = tmpnam(); } until mkdir $tmpdir, 0777; my $manifest = "$tmpdir/manifest"; my $conffile = "@sysconfdir@/nix/prebuilts.conf"; #END { unlink $manifest; rmdir $tmpdir; } my @srcpaths; my @subs; my @sucs; my $fullexpr = "["; my $first = 1; open CONFFILE, "<$conffile"; while () { chomp; if (/^\s*(\S+)\s*(\#.*)?$/) { my $url = $1; $url =~ s/\/$//; print "obtaining list of Nix archives at $url...\n"; system "wget '$url'/MANIFEST -O '$manifest' 2> /dev/null"; # !!! escape if ($?) { die "`wget' failed"; } open MANIFEST, "<$manifest"; my $inside = 0; my $storepath; my $narname; my $hash; my @preds; while () { chomp; s/\#.*$//g; next if (/^$/); if (!$inside) { if (/^\{$/) { $inside = 1; undef $storepath; undef $narname; undef $hash; @preds = (); } else { die "bad line: $_"; } } else { if (/^\}$/) { $inside = 0; my $fullurl = "$url/$narname"; print "$storepath\n"; # Construct a Fix expression that fetches and unpacks a # Nix archive from the network. my $fetch = "App(IncludeFix(\"fetchurl/fetchurl.fix\"), " . "[(\"url\", \"$fullurl\"), (\"md5\", \"$hash\")])"; my $fixexpr = "App(IncludeFix(\"nar/unnar.fix\"), " . "[ (\"nar\", $fetch)" . ", (\"outPath\", \"$storepath\")" . "])"; if (!$first) { $fullexpr .= "," }; $first = 0; $fullexpr .= $fixexpr; # !!! O(n^2)? push @srcpaths, $storepath; foreach my $p (@preds) { push @sucs, $p; push @sucs, $storepath; } } elsif (/^\s*StorePath:\s*(\/\S+)\s*$/) { $storepath = $1; } elsif (/^\s*NarName:\s*(\S+)\s*$/) { $narname = $1; } elsif (/^\s*MD5:\s*(\S+)\s*$/) { $hash = $1; } elsif (/^\s*SuccOf:\s*(\/\S+)\s*$/) { push @preds, $1; } else { die "bad line: $_"; } } } close MANIFEST; } } $fullexpr .= "]"; # Instantiate Nix expressions from the Fix expressions we created above. print STDERR "running fix...\n"; my $pid = open2(\*READ, \*WRITE, "fix -") or die "cannot run fix"; print WRITE $fullexpr; close WRITE; my $i = 0; while () { chomp; die unless /^\//; my $subpath = $_; die unless ($i < scalar @srcpaths); my $srcpath = $srcpaths[$i++]; push @subs, $srcpath; push @subs, $subpath; print "$srcpath $subpath\n"; } waitpid $pid, 0; $? == 0 or die "fix failed"; # Register all substitutes. print STDERR "registering substitutes...\n"; print "@subs\n"; system "nix --substitute @subs"; if ($?) { die "`nix --substitute' failed"; } # Register all successors. print STDERR "registering successors...\n"; print "@sucs\n"; system "nix --successor -vvvv @sucs"; if ($?) { die "`nix --successor' failed"; }