about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2006-09-21T18·54+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2006-09-21T18·54+0000
commit0bd5eb71a0a23b27a02af591ba46e4cf2c34aa04 (patch)
tree46e32a4eee45d30bcb2d5f780fe9ccd3bb41552d
parent4e91d8621f6620f8b15535002309882fd7794a1f (diff)
* `nix-install-package --url': install from a URL (NIX-12).
* `nix-install-package --help' (NIX-9).
* `nix-install-package --non-interactive': don't prompt or pause.
* Tests for nix-install-package.
* Security fixes: filter the values obtained from the nixpkg.

-rw-r--r--scripts/nix-install-package.in124
-rw-r--r--scripts/nix-pack-closure.in2
-rw-r--r--scripts/nix-unpack-closure.in2
-rw-r--r--tests/Makefile.am4
-rw-r--r--tests/common.sh.in15
-rw-r--r--tests/init.sh6
-rw-r--r--tests/install-package.sh21
-rw-r--r--tests/nix-pull.sh10
-rw-r--r--tests/referrers.sh2
-rw-r--r--tests/user-envs.sh3
10 files changed, 152 insertions, 37 deletions
diff --git a/scripts/nix-install-package.in b/scripts/nix-install-package.in
index 7959070c0a..4f5b0087fe 100644
--- a/scripts/nix-install-package.in
+++ b/scripts/nix-install-package.in
@@ -3,28 +3,107 @@
 use strict;
 use POSIX qw(tmpnam);
 
-my $pkgFile = $ARGV[0];
-die unless defined $pkgFile;
+
+sub usageError {
+    print STDERR <<EOF;
+Usage: nix-install-package (FILE | --url URL)
+
+Install a Nix Package (.nixpkg) either directly from FILE or by
+downloading it from URL.
+
+Flags:
+  --profile / -p LINK: install into the specified profile
+  --non-interactive: don't run inside a new terminal XXX
+EOF
+    ; # '
+    exit 1;
+}
+
+
+# Parse the command line arguments.
+my @args = @ARGV;
+usageError if scalar @args == 0;
+
+my $source;
+my $fromURL = 0;
+my @extraNixEnvArgs = ();
+my $interactive = 1;
+
+while (scalar @args) {
+    my $arg = shift @args;
+    if ($arg eq "--help") {
+        usageError;
+    }
+    elsif ($arg eq "--url") {
+        $fromURL = 1;
+    }
+    elsif ($arg eq "--profile" || $arg eq "-p") {
+        my $profile = shift @args;
+        usageError if !defined $profile;
+        push @extraNixEnvArgs, "-p", $profile;
+    }
+    elsif ($arg eq "--non-interactive") {
+        $interactive = 0;
+    }
+    else {
+        $source = $arg;
+    }
+}
+
+usageError unless defined $source;
 
 
 # Re-execute in a terminal, if necessary, so that if we're executed
 # from a web browser, the user gets to see us.
-if (!defined $ENV{"NIX_HAVE_TERMINAL"}) {
+if ($interactive && !defined $ENV{"NIX_HAVE_TERMINAL"}) {
     $ENV{"NIX_HAVE_TERMINAL"} = "1";
     $ENV{"LD_LIBRARY_PATH"} = "";
-    foreach my $term ("konsole", "gnome-terminal", "xterm") {
-        exec($term, "-e", "@shell@", "-c", "@bindir@/nix-install-package '$pkgFile' || read");
+    foreach my $term ("xterm", "konsole", "gnome-terminal", "xterm") {
+        exec($term, "-e", "@bindir@/nix-install-package", @ARGV);
     }
     die "cannot execute `xterm'";
 }
 
 
+my $tmpDir;
+do { $tmpDir = tmpnam(); }
+until mkdir $tmpDir, 0777;
+END { if (defined $tmpDir) { my $x = $?; system ("@coreutils@/rm", "-rf", $tmpDir); $? = $x; } }
+
+
+sub barf {
+    my $msg = shift;
+    print "$msg\n";
+    <STDIN> if $interactive;
+    exit 1;
+}
+
+
+# Download the package description, if necessary.
+my $pkgFile = $source;
+if ($fromURL) {
+    $pkgFile = "$tmpDir/tmp.nixpkg";
+    system ("@curl@", "--silent", $source, "-o", $pkgFile) == 0
+        or barf "curl failed: $?";
+}
+
+
 # Read and parse the package file.
-open PKGFILE, "<$pkgFile" or die "cannot open `$pkgFile': $!";
+open PKGFILE, "<$pkgFile" or barf "cannot open `$pkgFile': $!";
 my $contents = <PKGFILE>;
 close PKGFILE;
 
-$contents =~ /^\s*(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)/ or die "invalid package contents";
+my $urlRE = "(?: [a-zA-Z][a-zA-Z0-9\+\-\.]*\:[a-zA-Z0-9\%\/\?\:\@\&\=\+\$\,\-\_\.\!\~\*\']+ )";
+my $nameRE = "(?: [A-Za-z0-9\+\-\.\_\?\=]+ )"; # see checkStoreName()
+my $systemRE = "(?: [A-Za-z0-9\+\-\_]+ )";
+my $pathRE = "(?: \/ [\/A-Za-z0-9\+\-\.\_\?\=]* )";
+
+# Note: $pathRE doesn't check that whether we're looking at a valid
+# store path.  We'll let nix-env do that.
+
+$contents =~
+    / ^ \s* (\S+) \s+ ($urlRE) \s+ ($nameRE) \s+ ($systemRE) \s+ ($pathRE) \s+ ($pathRE) /x
+    or barf "invalid package contents";
 my $version = $1;
 my $manifestURL = $2;
 my $drvName = $3;
@@ -32,22 +111,29 @@ my $system = $4;
 my $drvPath = $5;
 my $outPath = $6;
 
-die "invalid package version `$version'" unless $version eq "NIXPKG1";
+barf "invalid package version `$version'" unless $version eq "NIXPKG1";
 
 
-# Ask confirmation.
-print "Do you want to install `$drvName' (Y/N)? ";
-my $reply = <STDIN>;
-chomp $reply;
-exit if $reply ne "y" && $reply ne "Y";
+if ($interactive) {
+    # Ask confirmation.
+    print "Do you want to install `$drvName' (Y/N)? ";
+    my $reply = <STDIN>;
+    chomp $reply;
+    exit if $reply ne "y" && $reply ne "Y";
+}
+
 
 print "\nPulling manifests...\n";
-system "@bindir@/nix-pull '$manifestURL'";
-die if $? != 0;
+system ("@bindir@/nix-pull", $manifestURL) == 0
+    or barf "nix-pull failed: $?";
+
 
 print "\nInstalling package...\n";
-system "@bindir@/nix-env -i '$outPath'";
-die if $? != 0;
+system ("@bindir@/nix-env", "--install", $outPath, @extraNixEnvArgs) == 0
+    or barf "nix-env failed: $?";
+
 
-print "\nInstallation succeeded! Press Enter to continue.\n";
-<STDIN>;
+if ($interactive) {
+    print "\nInstallation succeeded! Press Enter to continue.\n";
+    <STDIN>;
+}
diff --git a/scripts/nix-pack-closure.in b/scripts/nix-pack-closure.in
index 97de927bfc..a29f120215 100644
--- a/scripts/nix-pack-closure.in
+++ b/scripts/nix-pack-closure.in
@@ -17,7 +17,7 @@ $binDir = "@bindir@" unless defined $binDir;
 my $tmpDir;
 do { $tmpDir = tmpnam(); }
 until mkdir $tmpDir, 0777;
-END { system "@coreutils@/rm -rf '$tmpDir'"; }
+END { my $x = $?; system ("@coreutils@/rm", "-rf", $tmpDir); $? = $x; }
 mkdir "$tmpDir/contents", 0777 or die;
 mkdir "$tmpDir/references", 0777 or die;
 mkdir "$tmpDir/derivers", 0777 or die;
diff --git a/scripts/nix-unpack-closure.in b/scripts/nix-unpack-closure.in
index 2c9b4873af..01e8ee30d2 100644
--- a/scripts/nix-unpack-closure.in
+++ b/scripts/nix-unpack-closure.in
@@ -15,7 +15,7 @@ $binDir = "@bindir@" unless defined $binDir;
 my $tmpDir;
 do { $tmpDir = tmpnam(); }
 until mkdir $tmpDir, 0777;
-END { system "@coreutils@/rm -rf '$tmpDir'"; }
+END { my $x = $?; system ("@coreutils@/rm", "-rf", $tmpDir); $? = $x; }
 
 
 # Unpack the NAR archive on standard input.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index d55d0690d6..b19802d87b 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -3,7 +3,7 @@ TESTS_ENVIRONMENT = $(SHELL) -e
 extra1 = $(shell pwd)/test-tmp/shared
 
 simple.sh: simple.nix
-dependencies.sh gc.sh nix-push.sh nix-pull.in logging.sh nix-build.sh: dependencies.nix
+dependencies.sh gc.sh nix-push.sh nix-pull.in logging.sh nix-build.sh install-package.sh: dependencies.nix
 locking.sh: locking.nix
 parallel.sh: parallel.nix
 build-hook.sh: build-hook.nix
@@ -19,7 +19,7 @@ TESTS = init.sh hash.sh lang.sh add.sh simple.sh dependencies.sh \
   locking.sh parallel.sh build-hook.sh substitutes.sh substitutes2.sh \
   fallback.sh nix-push.sh gc.sh gc-concurrent.sh verify.sh nix-pull.sh \
   referrers.sh user-envs.sh logging.sh nix-build.sh misc.sh fixed.sh \
-  gc-runtime.sh
+  gc-runtime.sh install-package.sh
 
 XFAIL_TESTS =
 
diff --git a/tests/common.sh.in b/tests/common.sh.in
index 12162649e4..ca4c62d914 100644
--- a/tests/common.sh.in
+++ b/tests/common.sh.in
@@ -47,3 +47,18 @@ export nixhash=$TOP/src/nix-hash/nix-hash
 readLink() {
     ls -l "$1" | sed 's/.*->\ //'
 }
+
+clearStore() {
+    echo "clearing store..."
+    chmod -R +w "$NIX_STORE_DIR"
+    rm -rf "$NIX_STORE_DIR"
+    mkdir "$NIX_STORE_DIR"
+    rm -rf "$NIX_DB_DIR"
+    mkdir "$NIX_DB_DIR"
+    $nixstore --init
+}
+
+clearProfiles() {
+    profiles="$NIX_STATE_DIR"/profiles
+    rm -f $profiles/*
+}
diff --git a/tests/init.sh b/tests/init.sh
index 73d15fd3ad..160cb6b0a9 100644
--- a/tests/init.sh
+++ b/tests/init.sh
@@ -21,9 +21,12 @@ mkdir $NIX_BIN_DIR
 ln -s $nixstore $NIX_BIN_DIR/
 ln -s $nixinstantiate $NIX_BIN_DIR/
 ln -s $nixhash $NIX_BIN_DIR/
+ln -s $nixenv $NIX_BIN_DIR/
 ln -s $TOP/scripts/nix-prefetch-url $NIX_BIN_DIR/
 ln -s $TOP/scripts/nix-collect-garbage $NIX_BIN_DIR/
 ln -s $TOP/scripts/nix-build $NIX_BIN_DIR/
+ln -s $TOP/scripts/nix-install-package $NIX_BIN_DIR/
+ln -s $TOP/scripts/nix-pull $NIX_BIN_DIR/
 ln -s $bzip2_bin_test/bzip2 $NIX_BIN_DIR/
 ln -s $bzip2_bin_test/bunzip2 $NIX_BIN_DIR/
 mkdir $NIX_BIN_DIR/nix
@@ -52,8 +55,9 @@ for i in \
     $NIX_BIN_DIR/nix-prefetch-url \
     $NIX_BIN_DIR/nix-collect-garbage \
     $NIX_BIN_DIR/nix-build \
+    $NIX_BIN_DIR/nix-install-package \
+    $NIX_BIN_DIR/nix-pull \
     ; do
-    echo "$REAL_BIN_DIR"
     sed < $i > $i.tmp \
         -e "s^$REAL_BIN_DIR^$NIX_BIN_DIR^" \
         -e "s^$REAL_LIBEXEC_DIR^$NIX_LIBEXEC_DIR^" \
diff --git a/tests/install-package.sh b/tests/install-package.sh
new file mode 100644
index 0000000000..89d1d71f32
--- /dev/null
+++ b/tests/install-package.sh
@@ -0,0 +1,21 @@
+source common.sh
+
+# Note: this test expects to be run *after* nix-push.sh.
+
+drvPath=$($nixinstantiate ./dependencies.nix)
+outPath=$($nixstore -q $drvPath)
+
+clearStore
+clearProfiles
+
+cat > $TEST_ROOT/foo.nixpkg <<EOF
+NIXPKG1 file://$TEST_ROOT/manifest simple $system $drvPath $outPath
+EOF
+
+$NIX_BIN_DIR/nix-install-package --non-interactive -p $profiles/test $TEST_ROOT/foo.nixpkg
+test "$($nixenv -p $profiles/test -q '*' | wc -l)" -eq 1
+
+clearProfiles
+
+$NIX_BIN_DIR/nix-install-package --non-interactive -p $profiles/test --url file://$TEST_ROOT/foo.nixpkg
+test "$($nixenv -p $profiles/test -q '*' | wc -l)" -eq 1
diff --git a/tests/nix-pull.sh b/tests/nix-pull.sh
index ddbe0f97f3..a847510ceb 100644
--- a/tests/nix-pull.sh
+++ b/tests/nix-pull.sh
@@ -1,15 +1,5 @@
 source common.sh
 
-clearStore () {
-    echo "clearing store..."
-    chmod -R +w "$NIX_STORE_DIR"
-    rm -rf "$NIX_STORE_DIR"
-    mkdir "$NIX_STORE_DIR"
-    rm -rf "$NIX_DB_DIR"
-    mkdir "$NIX_DB_DIR"
-    $nixstore --init
-}
-
 pullCache () {
     echo "pulling cache..."
     $PERL -w -I$TOP/scripts $TOP/scripts/nix-pull file://$TEST_ROOT/manifest
diff --git a/tests/referrers.sh b/tests/referrers.sh
index 2f8a1a465e..4d2aaab5a2 100644
--- a/tests/referrers.sh
+++ b/tests/referrers.sh
@@ -3,7 +3,7 @@ source common.sh
 # This takes way to long on Cygwin (because process creation is so slow...).
 if test "$system" = i686-cygwin; then exit 0; fi
 
-max=5000
+max=2500
 
 reference=$NIX_STORE_DIR/abcdef
 touch $reference
diff --git a/tests/user-envs.sh b/tests/user-envs.sh
index b1ba0ccc16..614c30ceb3 100644
--- a/tests/user-envs.sh
+++ b/tests/user-envs.sh
@@ -1,7 +1,6 @@
 source common.sh
 
-profiles="$NIX_STATE_DIR"/profiles
-rm -f $profiles/*
+clearProfiles
 
 # Query installed: should be empty.
 test "$($nixenv -p $profiles/test -q '*' | wc -l)" -eq 0