forked from lix-project/lix
* `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.
This commit is contained in:
parent
4e91d8621f
commit
0bd5eb71a0
|
@ -3,28 +3,107 @@
|
||||||
use strict;
|
use strict;
|
||||||
use POSIX qw(tmpnam);
|
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
|
# Re-execute in a terminal, if necessary, so that if we're executed
|
||||||
# from a web browser, the user gets to see us.
|
# 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{"NIX_HAVE_TERMINAL"} = "1";
|
||||||
$ENV{"LD_LIBRARY_PATH"} = "";
|
$ENV{"LD_LIBRARY_PATH"} = "";
|
||||||
foreach my $term ("konsole", "gnome-terminal", "xterm") {
|
foreach my $term ("xterm", "konsole", "gnome-terminal", "xterm") {
|
||||||
exec($term, "-e", "@shell@", "-c", "@bindir@/nix-install-package '$pkgFile' || read");
|
exec($term, "-e", "@bindir@/nix-install-package", @ARGV);
|
||||||
}
|
}
|
||||||
die "cannot execute `xterm'";
|
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.
|
# 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>;
|
my $contents = <PKGFILE>;
|
||||||
close 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 $version = $1;
|
||||||
my $manifestURL = $2;
|
my $manifestURL = $2;
|
||||||
my $drvName = $3;
|
my $drvName = $3;
|
||||||
|
@ -32,22 +111,29 @@ my $system = $4;
|
||||||
my $drvPath = $5;
|
my $drvPath = $5;
|
||||||
my $outPath = $6;
|
my $outPath = $6;
|
||||||
|
|
||||||
die "invalid package version `$version'" unless $version eq "NIXPKG1";
|
barf "invalid package version `$version'" unless $version eq "NIXPKG1";
|
||||||
|
|
||||||
|
|
||||||
# Ask confirmation.
|
if ($interactive) {
|
||||||
print "Do you want to install `$drvName' (Y/N)? ";
|
# Ask confirmation.
|
||||||
my $reply = <STDIN>;
|
print "Do you want to install `$drvName' (Y/N)? ";
|
||||||
chomp $reply;
|
my $reply = <STDIN>;
|
||||||
exit if $reply ne "y" && $reply ne "Y";
|
chomp $reply;
|
||||||
|
exit if $reply ne "y" && $reply ne "Y";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
print "\nPulling manifests...\n";
|
print "\nPulling manifests...\n";
|
||||||
system "@bindir@/nix-pull '$manifestURL'";
|
system ("@bindir@/nix-pull", $manifestURL) == 0
|
||||||
die if $? != 0;
|
or barf "nix-pull failed: $?";
|
||||||
|
|
||||||
|
|
||||||
print "\nInstalling package...\n";
|
print "\nInstalling package...\n";
|
||||||
system "@bindir@/nix-env -i '$outPath'";
|
system ("@bindir@/nix-env", "--install", $outPath, @extraNixEnvArgs) == 0
|
||||||
die if $? != 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>;
|
||||||
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ $binDir = "@bindir@" unless defined $binDir;
|
||||||
my $tmpDir;
|
my $tmpDir;
|
||||||
do { $tmpDir = tmpnam(); }
|
do { $tmpDir = tmpnam(); }
|
||||||
until mkdir $tmpDir, 0777;
|
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/contents", 0777 or die;
|
||||||
mkdir "$tmpDir/references", 0777 or die;
|
mkdir "$tmpDir/references", 0777 or die;
|
||||||
mkdir "$tmpDir/derivers", 0777 or die;
|
mkdir "$tmpDir/derivers", 0777 or die;
|
||||||
|
|
|
@ -15,7 +15,7 @@ $binDir = "@bindir@" unless defined $binDir;
|
||||||
my $tmpDir;
|
my $tmpDir;
|
||||||
do { $tmpDir = tmpnam(); }
|
do { $tmpDir = tmpnam(); }
|
||||||
until mkdir $tmpDir, 0777;
|
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.
|
# Unpack the NAR archive on standard input.
|
||||||
|
|
|
@ -3,7 +3,7 @@ TESTS_ENVIRONMENT = $(SHELL) -e
|
||||||
extra1 = $(shell pwd)/test-tmp/shared
|
extra1 = $(shell pwd)/test-tmp/shared
|
||||||
|
|
||||||
simple.sh: simple.nix
|
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
|
locking.sh: locking.nix
|
||||||
parallel.sh: parallel.nix
|
parallel.sh: parallel.nix
|
||||||
build-hook.sh: build-hook.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 \
|
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 \
|
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 \
|
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 =
|
XFAIL_TESTS =
|
||||||
|
|
||||||
|
|
|
@ -47,3 +47,18 @@ export nixhash=$TOP/src/nix-hash/nix-hash
|
||||||
readLink() {
|
readLink() {
|
||||||
ls -l "$1" | sed 's/.*->\ //'
|
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/*
|
||||||
|
}
|
||||||
|
|
|
@ -21,9 +21,12 @@ mkdir $NIX_BIN_DIR
|
||||||
ln -s $nixstore $NIX_BIN_DIR/
|
ln -s $nixstore $NIX_BIN_DIR/
|
||||||
ln -s $nixinstantiate $NIX_BIN_DIR/
|
ln -s $nixinstantiate $NIX_BIN_DIR/
|
||||||
ln -s $nixhash $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-prefetch-url $NIX_BIN_DIR/
|
||||||
ln -s $TOP/scripts/nix-collect-garbage $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-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/bzip2 $NIX_BIN_DIR/
|
||||||
ln -s $bzip2_bin_test/bunzip2 $NIX_BIN_DIR/
|
ln -s $bzip2_bin_test/bunzip2 $NIX_BIN_DIR/
|
||||||
mkdir $NIX_BIN_DIR/nix
|
mkdir $NIX_BIN_DIR/nix
|
||||||
|
@ -52,8 +55,9 @@ for i in \
|
||||||
$NIX_BIN_DIR/nix-prefetch-url \
|
$NIX_BIN_DIR/nix-prefetch-url \
|
||||||
$NIX_BIN_DIR/nix-collect-garbage \
|
$NIX_BIN_DIR/nix-collect-garbage \
|
||||||
$NIX_BIN_DIR/nix-build \
|
$NIX_BIN_DIR/nix-build \
|
||||||
|
$NIX_BIN_DIR/nix-install-package \
|
||||||
|
$NIX_BIN_DIR/nix-pull \
|
||||||
; do
|
; do
|
||||||
echo "$REAL_BIN_DIR"
|
|
||||||
sed < $i > $i.tmp \
|
sed < $i > $i.tmp \
|
||||||
-e "s^$REAL_BIN_DIR^$NIX_BIN_DIR^" \
|
-e "s^$REAL_BIN_DIR^$NIX_BIN_DIR^" \
|
||||||
-e "s^$REAL_LIBEXEC_DIR^$NIX_LIBEXEC_DIR^" \
|
-e "s^$REAL_LIBEXEC_DIR^$NIX_LIBEXEC_DIR^" \
|
||||||
|
|
21
tests/install-package.sh
Normal file
21
tests/install-package.sh
Normal file
|
@ -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
|
|
@ -1,15 +1,5 @@
|
||||||
source common.sh
|
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 () {
|
pullCache () {
|
||||||
echo "pulling cache..."
|
echo "pulling cache..."
|
||||||
$PERL -w -I$TOP/scripts $TOP/scripts/nix-pull file://$TEST_ROOT/manifest
|
$PERL -w -I$TOP/scripts $TOP/scripts/nix-pull file://$TEST_ROOT/manifest
|
||||||
|
|
|
@ -3,7 +3,7 @@ source common.sh
|
||||||
# This takes way to long on Cygwin (because process creation is so slow...).
|
# This takes way to long on Cygwin (because process creation is so slow...).
|
||||||
if test "$system" = i686-cygwin; then exit 0; fi
|
if test "$system" = i686-cygwin; then exit 0; fi
|
||||||
|
|
||||||
max=5000
|
max=2500
|
||||||
|
|
||||||
reference=$NIX_STORE_DIR/abcdef
|
reference=$NIX_STORE_DIR/abcdef
|
||||||
touch $reference
|
touch $reference
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
source common.sh
|
source common.sh
|
||||||
|
|
||||||
profiles="$NIX_STATE_DIR"/profiles
|
clearProfiles
|
||||||
rm -f $profiles/*
|
|
||||||
|
|
||||||
# Query installed: should be empty.
|
# Query installed: should be empty.
|
||||||
test "$($nixenv -p $profiles/test -q '*' | wc -l)" -eq 0
|
test "$($nixenv -p $profiles/test -q '*' | wc -l)" -eq 0
|
||||||
|
|
Loading…
Reference in a new issue