143 lines
		
	
	
	
		
			2.8 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			143 lines
		
	
	
	
		
			2.8 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
| #! /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 (<CONFFILE>) {
 | |
| 
 | |
|     chomp;
 | |
|     if (/^\s*(\S+)\s*(\#.*)?$/) {
 | |
|         my $url = $1;
 | |
| 	$url =~ s/\/$//;
 | |
| 
 | |
|         print "obtaining list of Nix archives at $url...\n";
 | |
| 
 | |
|         system "wget --cache=off '$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 (<MANIFEST>) {
 | |
| 	    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 (<READ>) {
 | |
|     chomp;
 | |
|     die unless /^\//;
 | |
|     my $subpath = $_;
 | |
|     die unless ($i < scalar @srcpaths);
 | |
|     my $srcpath = $srcpaths[$i++];
 | |
|     push @subs, $srcpath;
 | |
|     push @subs, $subpath;
 | |
| }
 | |
| 
 | |
| waitpid $pid, 0;
 | |
| $? == 0 or die "fix failed";
 | |
| 
 | |
| 
 | |
| # Register all substitutes.
 | |
| print STDERR "registering substitutes...\n";
 | |
| system "nix --substitute @subs";
 | |
| if ($?) { die "`nix --substitute' failed"; }
 | |
| 
 | |
| 
 | |
| # Register all successors.
 | |
| print STDERR "registering successors...\n";
 | |
| system "nix --successor @sucs";
 | |
| if ($?) { die "`nix --successor' failed"; }
 |