about summary refs log blame commit diff
path: root/scripts/nix-pull.in
blob: 4cb6409d77424b4b56bf542feaa861e302186d71 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11

                   
           
               
                     
 




                                  
                                                 
 


                                         
         
         
 
                   

              






                                 
                        


                                                            
                                                                                           

                                        

                                    
                       
 



                      

                            























































                                                                           

         
                       


     
 
                 
 
 

                                                                        
                                                                  


                      
          
                
          





                                       

 


                            
 

                                            

                                            
 
 

                                           
                               
                                           
#! /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"; }