about summary refs log tree commit diff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/nix-build.in28
-rwxr-xr-xscripts/nix-channel.in143
-rwxr-xr-xscripts/nix-copy-closure.in10
-rwxr-xr-xscripts/nix-generate-patches.in10
-rwxr-xr-xscripts/nix-pull.in4
-rwxr-xr-xscripts/nix-push.in2
6 files changed, 121 insertions, 76 deletions
diff --git a/scripts/nix-build.in b/scripts/nix-build.in
index b36ec0208b41..35b186bb715d 100755
--- a/scripts/nix-build.in
+++ b/scripts/nix-build.in
@@ -14,6 +14,10 @@ my @instArgs = ();
 my @buildArgs = ();
 my @exprs = ();
 
+my $shell = $ENV{SHELL} || "/bin/sh";
+my $envCommand = "p=\$PATH; source \$stdenv/setup; PATH=\$PATH:\$p; exec $shell";
+my @envExclude = ();
+
 
 my $tmpDir = tempdir("nix-build.XXXXXX", CLEANUP => 1, TMPDIR => 1)
     or die "cannot create a temporary directory";
@@ -41,7 +45,12 @@ Flags:
   --drv-link NAME: create symlink NAME instead of `derivation'
   --no-out-link: do not create the `result' symlink
   --out-link / -o NAME: create symlink NAME instead of `result'
-  --attr ATTR: select a specific attribution from the Nix expression
+  --attr / -A ATTR: select a specific attribute from the Nix expression
+  
+  --run-env: build dependencies of the specified derivation, then start a
+      shell with the environment of the derivation
+  --command: command to run with `--run-env'
+  --exclude: regexp specifying dependencies to be excluded by `--run-env'
 
 Any additional flags are passed to `nix-store'.
 EOF
@@ -125,6 +134,18 @@ EOF
         $runEnv = 1;
     }
     
+    elsif ($arg eq "--command") {
+        $n++;
+        die "$0: `$arg' requires an argument\n" unless $n < scalar @ARGV;
+        $envCommand = $ARGV[$n];
+    }
+
+    elsif ($arg eq "--exclude") {
+        $n++;
+        die "$0: `$arg' requires an argument\n" unless $n < scalar @ARGV;
+        push @envExclude, $ARGV[$n];
+    }
+
     elsif (substr($arg, 0, 1) eq "-") {
         push @buildArgs, $arg;
     }
@@ -155,7 +176,8 @@ foreach my $expr (@exprs) {
         my $drv = derivationFromPath($drvPath);
 
         # Build or fetch all dependencies of the derivation.
-        system("$Nix::Config::binDir/nix-store -r @buildArgs @{$drv->{inputDrvs}} @{$drv->{inputSrcs}} > /dev/null") == 0
+        my @inputDrvs = grep { my $x = $_; (grep { $x =~ $_ } @envExclude) == 0 } @{$drv->{inputDrvs}};
+        system("$Nix::Config::binDir/nix-store -r @buildArgs @inputDrvs @{$drv->{inputSrcs}} > /dev/null") == 0
             or die "$0: failed to build all dependencies\n";
 
         # Set the environment.
@@ -168,7 +190,7 @@ foreach my $expr (@exprs) {
         # convenience, source $stdenv/setup to setup additional
         # environment variables.  Also don't lose the current $PATH
         # directories.
-        exec($ENV{SHELL}, "-c", "p=\$PATH; source \$stdenv/setup; PATH=\$PATH:\$p; exec $ENV{SHELL}");
+        exec($ENV{SHELL}, "-c", $envCommand);
         die;
     }
 
diff --git a/scripts/nix-channel.in b/scripts/nix-channel.in
index ebfc246cfa30..524ffa656451 100755
--- a/scripts/nix-channel.in
+++ b/scripts/nix-channel.in
@@ -1,6 +1,8 @@
 #! @perl@ -w @perlFlags@
 
 use strict;
+use File::Basename;
+use File::Path qw(make_path);
 use Nix::Config;
 
 my $manifestDir = $Nix::Config::manifestDir;
@@ -11,67 +13,67 @@ my $channelCache = "$Nix::Config::stateDir/channel-cache";
 mkdir $channelCache, 0755 unless -e $channelCache;
 $ENV{'NIX_DOWNLOAD_CACHE'} = $channelCache if -W $channelCache;
 
-
 # Figure out the name of the `.nix-channels' file to use.
-my $home = $ENV{"HOME"};
-die '$HOME not set' unless defined $home;
+my $home = $ENV{"HOME"} or die '$HOME not set\n';
 my $channelsList = "$home/.nix-channels";
-
 my $nixDefExpr = "$home/.nix-defexpr";
-    
 
-my @channels;
+# Figure out the name of the channels profile.
+my $userName = getpwuid($<) or die "cannot figure out user name";
+my $profile = "$Nix::Config::stateDir/profiles/per-user/$userName/channels";
+make_path(dirname $profile, mode => 0755);
+    
+my %channels;
 
 
-# Reads the list of channels from the file $channelsList;
+# Reads the list of channels.
 sub readChannels {
     return if (!-f $channelsList);
     open CHANNELS, "<$channelsList" or die "cannot open `$channelsList': $!";
     while (<CHANNELS>) {
         chomp;
         next if /^\s*\#/;
-        push @channels, $_;
+        my ($url, $name) = split ' ', $_;
+        $url =~ s/\/*$//; # remove trailing slashes
+        $name = basename $url unless defined $name;
+        $channels{$name} = $url;
     }
     close CHANNELS;
 }
 
 
-# Writes the list of channels to the file $channelsList;
+# Writes the list of channels.
 sub writeChannels {
     open CHANNELS, ">$channelsList" or die "cannot open `$channelsList': $!";
-    foreach my $url (@channels) {
-        print CHANNELS "$url\n";
+    foreach my $name (keys %channels) {
+        print CHANNELS "$channels{$name} $name\n";
     }
     close CHANNELS;
 }
 
 
-# Adds a channel to the file $channelsList;
+# Adds a channel.
 sub addChannel {
-    my $url = shift;
+    my ($url, $name) = @_;
     readChannels;
-    foreach my $url2 (@channels) {
-        return if $url eq $url2;
-    }
-    push @channels, $url;
+    $channels{$name} = $url;
     writeChannels;
 }
 
 
-# Remove a channel from the file $channelsList;
+# Remove a channel.
 sub removeChannel {
-    my $url = shift;
-    my @left = ();
+    my ($name) = @_;
     readChannels;
-    foreach my $url2 (@channels) {
-        push @left, $url2 if $url ne $url2;
-    }
-    @channels = @left;
+    delete $channels{$name};
     writeChannels;
+
+    system("$Nix::Config::binDir/nix-env --profile '$profile' -e '$name'") == 0
+        or die "cannot remove channel `$name'";
 }
 
 
-# Fetch Nix expressions and pull cache manifests from the subscribed
+# Fetch Nix expressions and pull manifests from the subscribed
 # channels.
 sub update {
     readChannels;
@@ -82,64 +84,62 @@ sub update {
     # Do we have write permission to the manifests directory?
     die "$0: you do not have write permission to `$manifestDir'!\n" unless -W $manifestDir;
 
-    # Pull cache manifests.
-    foreach my $url (@channels) {
-        #print "pulling cache manifest from `$url'\n";
+    # Download each channel.
+    my $exprs = "";
+    foreach my $name (keys %channels) {
+        my $url = $channels{$name};
+        my $origUrl = "$url/MANIFEST";
+
+        # Check if $url is a redirect.  If so, follow it now to ensure
+        # consistency if the redirection is changed between
+        # downloading the manifest and the tarball.
+        my $headers = `$Nix::Config::curl --silent --head '$url'`;
+        die "$0: unable to check `$url'\n" if $? != 0;
+        $headers =~ s/\r//g;
+        $url = $1 if $headers =~ /^Location:\s*(.*)\s*$/m;
+        
+        # Pull the channel manifest.
+        $ENV{'NIX_ORIG_URL'} = $origUrl;
         system("$Nix::Config::binDir/nix-pull", "--skip-wrong-store", "$url/MANIFEST") == 0
-            or die "cannot pull cache manifest from `$url'";
-    }
-
-    # Create a Nix expression that fetches and unpacks the channel Nix
-    # expressions.
-
-    my $inputs = "[";
-    foreach my $url (@channels) {
-        $url =~ /\/([^\/]+)\/?$/;
-        my $channelName = $1;
-        $channelName = "unnamed" unless defined $channelName;
+            or die "cannot pull manifest from `$url'\n";
 
+        # Download the channel tarball.
         my $fullURL = "$url/nixexprs.tar.bz2";
-        print "downloading Nix expressions from `$fullURL'...\n";
-        $ENV{"PRINT_PATH"} = 1;
-        $ENV{"QUIET"} = 1;
-        my ($hash, $path) = `$Nix::Config::binDir/nix-prefetch-url '$fullURL'`;
+        print STDERR "downloading Nix expressions from `$fullURL'...\n";
+        my ($hash, $path) = `PRINT_PATH=1 QUIET=1 $Nix::Config::binDir/nix-prefetch-url '$fullURL'`;
         die "cannot fetch `$fullURL'" if $? != 0;
         chomp $path;
-        $inputs .= '"' . $channelName . '"' . " " . $path . " ";
-    }
-    $inputs .= "]";
 
-    # Figure out a name for the GC root.
-    my $userName = getpwuid($<);
-    die "who ARE you? go away" unless defined $userName;
+        # If the URL contains a version number, append it to the name
+        # attribute (so that "nix-env -q" on the channels profile
+        # shows something useful).
+        my $cname = $name;
+        $cname .= $1 if basename($url) =~ /(-\d.*)$/;
 
-    my $rootFile = "$Nix::Config::stateDir/gcroots/per-user/$userName/channels";
-    
-    # Build the Nix expression.
-    print "unpacking channel Nix expressions...\n";
-    my $outPath = `\\
-        $Nix::Config::binDir/nix-build --out-link '$rootFile' --drv-link '$rootFile'.tmp \\
-        '<nix/unpack-channel.nix>' \\
-        --argstr system @system@ --arg inputs '$inputs'`
-        or die "cannot unpack the channels";
-    chomp $outPath;
+        $exprs .= "'f: f { name = \"$cname\"; channelName = \"$name\"; src = builtins.storePath \"$path\"; }' ";
+    }
 
-    unlink "$rootFile.tmp";
+    # Unpack the channel tarballs into the Nix store and install them
+    # into the channels profile.
+    print STDERR "unpacking channels...\n";
+    system("$Nix::Config::binDir/nix-env --profile '$profile' " .
+           "-f '<nix/unpack-channel.nix>' -i -E $exprs --quiet") == 0
+           or die "cannot unpack the channels";
 
     # Make the channels appear in nix-env.
     unlink $nixDefExpr if -l $nixDefExpr; # old-skool ~/.nix-defexpr
     mkdir $nixDefExpr or die "cannot create directory `$nixDefExpr'" if !-e $nixDefExpr;
     my $channelLink = "$nixDefExpr/channels";
     unlink $channelLink; # !!! not atomic
-    symlink($outPath, $channelLink) or die "cannot symlink `$channelLink' to `$outPath'";
+    symlink($profile, $channelLink) or die "cannot symlink `$channelLink' to `$profile'";
 }
 
 
 sub usageError {
     print STDERR <<EOF;
 Usage:
-  nix-channel --add URL
-  nix-channel --remove URL
+  nix-channel --add URL [CHANNEL-NAME]
+  nix-channel --remove CHANNEL-NAME
   nix-channel --list
   nix-channel --update
 EOF
@@ -154,22 +154,29 @@ while (scalar @ARGV) {
     my $arg = shift @ARGV;
 
     if ($arg eq "--add") {
-        usageError if scalar @ARGV != 1;
-        addChannel (shift @ARGV);
+        usageError if scalar @ARGV < 1 || scalar @ARGV > 2;
+        my $url = shift @ARGV;
+        my $name = shift @ARGV;
+        unless (defined $name) {
+            $name = basename $url;
+            $name =~ s/-unstable//;
+            $name =~ s/-stable//;
+        }
+        addChannel($url, $name);
         last;
     }
 
     if ($arg eq "--remove") {
         usageError if scalar @ARGV != 1;
-        removeChannel (shift @ARGV);
+        removeChannel(shift @ARGV);
         last;
     }
 
     if ($arg eq "--list") {
         usageError if scalar @ARGV != 0;
         readChannels;
-        foreach my $url (@channels) {
-            print "$url\n";
+        foreach my $name (keys %channels) {
+            print "$name $channels{$name}\n";
         }
         last;
     }
diff --git a/scripts/nix-copy-closure.in b/scripts/nix-copy-closure.in
index 1ed24d285208..12a83cff979c 100755
--- a/scripts/nix-copy-closure.in
+++ b/scripts/nix-copy-closure.in
@@ -23,6 +23,8 @@ my $sign = 0;
 my $compressor = "";
 my $decompressor = "";
 
+my $progressViewer = "";
+
 my $toMode = 1;
 
 my $includeOutputs = 0;
@@ -60,6 +62,9 @@ while (@ARGV) {
     elsif ($arg eq "--include-outputs") {
         $includeOutputs = 1;
     }
+    elsif ($arg eq "--show-progress") {
+        $progressViewer = "@pv@";
+    }
     elsif ($arg eq "--dry-run") {
         $dryRun = 1;
     }
@@ -76,7 +81,7 @@ openSSHConnection $sshHost or die "$0: unable to start SSH\n";
 
 
 if ($toMode) { # Copy TO the remote machine.
-    Nix::CopyClosure::copyTo($sshHost, [ @sshOpts ], [ @storePaths ], $compressor, $decompressor, $includeOutputs, $dryRun, $sign);
+    Nix::CopyClosure::copyTo($sshHost, [ @sshOpts ], [ @storePaths ], $compressor, $decompressor, $includeOutputs, $dryRun, $sign, $progressViewer);
 }
 
 else { # Copy FROM the remote machine.
@@ -101,9 +106,10 @@ else { # Copy FROM the remote machine.
         print STDERR "copying ", scalar @missing, " missing paths from ‘$sshHost’...\n";
         $compressor = "| $compressor" if $compressor ne "";
         $decompressor = "$decompressor |" if $decompressor ne "";
+	$progressViewer = "$progressViewer |" if $progressViewer ne "";
         unless ($dryRun) {
             my $extraOpts = $sign ? "--sign" : "";
-            system("set -f; ssh $sshHost @sshOpts 'nix-store --export $extraOpts @missing $compressor' | $decompressor $Nix::Config::binDir/nix-store --import > /dev/null") == 0
+            system("set -f; ssh $sshHost @sshOpts 'nix-store --export $extraOpts @missing $compressor' | $progressViewer $decompressor $Nix::Config::binDir/nix-store --import > /dev/null") == 0
                 or die "copying store paths from remote machine `$sshHost' failed: $?";
         }
     }
diff --git a/scripts/nix-generate-patches.in b/scripts/nix-generate-patches.in
index 4cb843382b52..969af916d8e6 100755
--- a/scripts/nix-generate-patches.in
+++ b/scripts/nix-generate-patches.in
@@ -39,4 +39,14 @@ generatePatches \%srcNarFiles, \%dstNarFiles, \%srcPatches, \%dstPatches,
 
 propagatePatches \%srcPatches, \%dstNarFiles, \%dstPatches;
 
+# Optionally add all new patches to the manifest in $NIX_ALL_PATCHES.
+my $allPatchesFile = $ENV{"NIX_ALL_PATCHES"};
+if (defined $allPatchesFile) {
+    my (%dummy, %allPatches);
+    readManifest("$patchesPath/all-patches", \%dummy, \%allPatches)
+        if -f $allPatchesFile;
+    copyPatches \%dstPatches, \%allPatches;
+    writeManifest($allPatchesFile, {}, \%allPatches, 0);
+}
+
 writeManifest $dstManifest, \%dstNarFiles, \%dstPatches;
diff --git a/scripts/nix-pull.in b/scripts/nix-pull.in
index 136a5c9fa4bd..8d5db2f57c68 100755
--- a/scripts/nix-pull.in
+++ b/scripts/nix-pull.in
@@ -50,7 +50,7 @@ sub processURL {
     my $manifest;
 
     # First see if a bzipped manifest is available.
-    if (system("$Nix::Config::curl --fail --silent --head '$url'.bz2 > /dev/null") == 0) {
+    if (system("$Nix::Config::curl --fail --silent --location --head '$url'.bz2 > /dev/null") == 0) {
         print "fetching list of Nix archives at `$url.bz2'...\n";
         $manifest = downloadFile "$url.bz2";
     }
@@ -72,7 +72,7 @@ sub processURL {
 
     my $urlFile = "$manifestDir/$baseName-$hash.url";
     open URL, ">$urlFile" or die "cannot create `$urlFile'";
-    print URL "$url";
+    print URL ($ENV{'NIX_ORIG_URL'} || $url);
     close URL;
     
     my $finalPath = "$manifestDir/$baseName-$hash.nixmanifest";
diff --git a/scripts/nix-push.in b/scripts/nix-push.in
index 1e0918abd6ac..a1c02190bd6c 100755
--- a/scripts/nix-push.in
+++ b/scripts/nix-push.in
@@ -103,7 +103,7 @@ foreach my $storePath (@storePaths) {
     # Construct a Nix expression that creates a Nix archive.
     my $nixexpr = 
         "(import <nix/nar.nix> " .
-        "{ storePath = builtins.storePath \"$storePath\"; system = \"@system@\"; hashAlgo = \"$hashAlgo\"; }) ";
+        "{ storePath = builtins.storePath \"$storePath\"; hashAlgo = \"$hashAlgo\"; }) ";
     
     print NIX $nixexpr;
 }