diff --git a/configure.ac b/configure.ac
index b72b47f00..5af239cbd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -9,14 +9,14 @@ STABLE=0
# Put the revision number in the version.
if test "$STABLE" != "1"; then
- if REVISION=`test -d $srcdir/.svn && svnversion $srcdir 2> /dev/null`; then
+ if REVISION=`test -d $srcdir/.svn && svnversion -n $srcdir 2> /dev/null`; then
VERSION=${VERSION}pre${REVISION}
elif REVISION=`cat $srcdir/svn-revision 2> /dev/null`; then
VERSION=${VERSION}pre${REVISION}
fi
fi
-AC_DEFINE_UNQUOTED(NIX_VERSION, ["$(echo $VERSION)"], [version])
+AC_DEFINE_UNQUOTED(NIX_VERSION, ["$VERSION"], [version])
AC_PREFIX_DEFAULT(/nix)
diff --git a/corepkgs/buildenv/builder.pl.in b/corepkgs/buildenv/builder.pl.in
index 590d31ad6..7b9f0ed7d 100755
--- a/corepkgs/buildenv/builder.pl.in
+++ b/corepkgs/buildenv/builder.pl.in
@@ -13,9 +13,9 @@ mkdir "$out", 0755 || die "error creating $out";
sub readlink_or_StateWrapper;
my $symlinks = 0;
-my %path_state_identifier;
-my %path_runtimeArgs;
+my %path_state_identifier = ();
+my %priorities;
my $nixBinDir = $ENV{"nixBinDir"};
my $nixStore = $ENV{"nixStore"};
@@ -30,13 +30,12 @@ sub createLinks {
my @srcDirParts = split /\// , substr($srcDir, length ($nixStore), length ($srcDir));
my $srcDirRoot = $nixStore . "/" . $srcDirParts[1];
# print "srcDirRoot $srcDirRoot \n";
- my $pkgStateIdentifier = $path_state_identifier{$srcDirRoot};
- my $pkgRuntimeStateArgs = $path_runtimeArgs{$srcDirRoot};
my $dstDir = shift;
- my $ignoreCollisions = shift;
+ my $priority = shift;
+ my $pkgStateIdentifier = $path_state_identifier{$srcDirRoot}; # We have to look it up each time since recursion can change the $srcDir, but not the identifier
- # print "createLinks $srcDir to $dstDir with iden $pkgStateIdentifier \n";
+ #print "createLinks $srcDir to $dstDir with iden $pkgStateIdentifier \n";
my @srcFiles = glob("$srcDir/*");
@@ -61,7 +60,7 @@ sub createLinks {
#go recursive on directorys
if (-d _) {
- createLinks($srcFile, $dstFile, $ignoreCollisions);
+ createLinks($srcFile, $dstFile, $priority);
}
elsif (-l _) {
@@ -71,16 +70,17 @@ sub createLinks {
}
unlink $dstFile or die "error unlinking `$dstFile': $!";
mkdir $dstFile, 0755 || die "error creating directory `$dstFile': $!";
- createLinks($target, $dstFile, $ignoreCollisions);
- createLinks($srcFile, $dstFile, $ignoreCollisions);
+ createLinks($target, $dstFile, $priority); # !!! <- priority isn't right
+ createLinks($srcFile, $dstFile, $priority);
}
else {
- # print "1STLINK $srcFile to $dstFile with iden $pkgStateIdentifier \n";
+ #print "1ST DIR LINK $srcFile to $dstFile with iden $pkgStateIdentifier \n";
symlink($srcFile, $dstFile) ||
die "error creating link `$dstFile': $!";
+ $priorities{$dstFile} = $priority;
$symlinks++;
}
}
@@ -89,7 +89,7 @@ sub createLinks {
# print "ELSE LINK $srcFile to $dstFile with iden $pkgStateIdentifier \n";
- # if we have .....
+ # if we have a state component with a identifier different then ""
if($pkgStateIdentifier ne "__NOSTATE__" && $pkgStateIdentifier ne ""){
my @pathparts = split /\// , $srcFile;
@@ -112,38 +112,42 @@ sub createLinks {
# We also check with -e if the wrapperscript-file exists, and if is it a symlink (with -l)
if (-l $new_dstFile || -e $new_dstFile) {
- if (!$ignoreCollisions) {
my $target = readlink_or_StateWrapper $new_dstFile;
die "(state) collission between `$srcFile' and `$target' (over $new_dstFile)";
- }
}
sysopen (DSTFILEHANDLE, $new_dstFile, O_RDWR|O_EXCL|O_CREAT, 0755);
printf DSTFILEHANDLE "#! @shell@ \n";
-
- if($pkgRuntimeStateArgs eq "__NOARGS__"){
- printf DSTFILEHANDLE "$nixBinDir/nix-state --run --identifier=$new_stateIdentifier $srcFile \"\$@\" \n";
- }
- else{
- printf DSTFILEHANDLE "$nixBinDir/nix-state --run --identifier=$new_stateIdentifier $srcFile \"\$@\" $pkgRuntimeStateArgs \n";
- } # TODO, maybe first R.T.A. then other args ?
-
+ printf DSTFILEHANDLE "$nixBinDir/nix-state --run --identifier=$new_stateIdentifier $srcFile \"\$@\" \n";
close (DSTFILEHANDLE);
}
- }
- else{
- if (-l $dstFile || -e $dstFile) {
- if (!$ignoreCollisions) {
- my $target = readlink_or_StateWrapper $dstFile;
- die "collission between `$srcFile' and `$target'";
- }
- }
+ }
+ elsif($pkgStateIdentifier ne "__NOSTATE__" && $pkgStateIdentifier eq ""){ #TODO we now dont create symlinks for state packages with a empty identifier
+ #TODO but we must do it if there is no normal non-state pacakge
+ }
+
+ else {
+
+ if (-l $dstFile || -e $dstFile) {
+ my $target = readlink_or_StateWrapper $dstFile;
+ my $prevPriority = $priorities{$dstFile};
+ die ( "Collission between `$srcFile' and `$target'. "
+ . "Suggested solution: use `nix-env --set-flag "
+ . "priority NUMBER PKGNAME' to change the priority of "
+ . "one of the conflicting packages.\n" )
+ if $prevPriority == $priority;
+ next if $prevPriority < $priority;
+ unlink $dstFile or die;
+ }
+
+ # print "2ND LINK $srcFile to $dstFile with iden $pkgStateIdentifier \n";
symlink($srcFile, $dstFile) ||
die "error creating link `$dstFile': $!";
+ $priorities{$dstFile} = $priority;
$symlinks++;
- }
- }
+ }
+ }
}
}
@@ -154,13 +158,13 @@ my %postponed;
sub addPkg;
sub addPkg {
my $pkgDir = shift;
- my $ignoreCollisions = shift;
+ my $priority = shift;
return if (defined $done{$pkgDir});
$done{$pkgDir} = 1;
# print "symlinking $pkgDir\n";
- createLinks("$pkgDir", "$out", $ignoreCollisions);
+ createLinks("$pkgDir", "$out", $priority);
my $propagatedFN = "$pkgDir/nix-support/propagated-user-env-packages";
if (-e $propagatedFN) {
@@ -190,23 +194,39 @@ sub readlink_or_StateWrapper {
return $target
}
-# Symlink to the packages that have been installed explicitly by the user.
-my @storePaths = split ' ', $ENV{"derivations"};
my @stateIdentifiers = split ' ', $ENV{"stateIdentifiers"};
-my @runtimeStateArgs = split ' ', $ENV{"runtimeStateArgs_arg"};
my $si_counter = 0;
-foreach my $pkgDir (@storePaths) { #Commented the sort out
+# Convert the stuff we get from the environment back into a coherent
+# data type.
+my @paths = split ' ', $ENV{"paths"};
+my @active = split ' ', $ENV{"active"};
+my @priority = split ' ', $ENV{"priority"};
- #Link each $pkgDir to a $stateIdentifiers in $path_state_identifier
- $path_state_identifier{$pkgDir} = $stateIdentifiers[$si_counter];
- $path_runtimeArgs{$pkgDir} = $runtimeStateArgs[$si_counter];
+die if scalar @paths != scalar @active;
+die if scalar @paths != scalar @priority;
- # print "SP: $pkgDir \n";
- # print "SI: $path_state_identifier{$pkgDir} \n";
- # print "RT: $path_runtimeArgs{$pkgDir} \n";
-
- addPkg($pkgDir, 0);
+my %pkgs;
+
+for (my $n = 0; $n < scalar @paths; $n++) {
+ $pkgs{$paths[$n]} =
+ { active => $active[$n]
+ , priority => $priority[$n]
+ , stateidentifier => $stateIdentifiers[$n]
+ };
+
+ $path_state_identifier{$paths[$n]} = $stateIdentifiers[$n];
+}
+
+# Symlink to the packages that have been installed explicitly by the
+# user.
+foreach my $pkg (sort (keys %pkgs)) {
+
+ #print "SP: $pkg \n";
+ #print "SI: $pkgs{$pkg}->{stateidentifier} \n";
+ #print "PR: $pkgs{$pkg}->{priority} \n";
+
+ addPkg($pkg, $pkgs{$pkg}->{priority}) if $pkgs{$pkg}->{active} ne "false";
$si_counter++;
}
@@ -215,15 +235,17 @@ foreach my $pkgDir (@storePaths) { #Commented the sort out
# installed by the user (i.e., package X declares that it want Y
# installed as well). We do these later because they have a lower
# priority in case of collisions.
+my $priorityCounter = 1000; # don't care about collisions
while (scalar(keys %postponed) > 0) {
my @pkgDirs = keys %postponed;
%postponed = ();
- foreach my $pkgDir (sort @pkgDirs) {
- addPkg($pkgDir, 1);
+ foreach my $pkgDir (sort @pkgDirs) {
+ addPkg($pkgDir, $priorityCounter++);
}
}
print STDERR "created $symlinks symlinks in user environment\n";
symlink($ENV{"manifest"}, "$out/manifest") or die "cannot create manifest";
+
diff --git a/corepkgs/buildenv/default.nix b/corepkgs/buildenv/default.nix
index 4804304ae..9a90821bd 100644
--- a/corepkgs/buildenv/default.nix
+++ b/corepkgs/buildenv/default.nix
@@ -1,12 +1,16 @@
-{system, derivations, stateIdentifiers, runtimeStateArgs, manifest, nixBinDir, nixStore}:
+{system, derivations, stateIdentifiers, manifest, nixBinDir, nixStore}:
derivation {
name = "user-environment";
system = system;
builder = ./builder.pl;
- derivations = derivations;
- runtimeStateArgs_arg = runtimeStateArgs;
+
stateIdentifiers = stateIdentifiers;
manifest = manifest;
inherit nixBinDir nixStore;
+
+ # !!! grmbl, need structured data for passing this in a clean way.
+ paths = derivations;
+ active = map (x: if x ? meta && x.meta ? active then x.meta.active else "true") derivations;
+ priority = map (x: if x ? meta && x.meta ? priority then x.meta.priority else "5") derivations;
}
diff --git a/doc/manual/installation.xml b/doc/manual/installation.xml
index b9358efd1..2642bca1d 100644
--- a/doc/manual/installation.xml
+++ b/doc/manual/installation.xml
@@ -57,14 +57,15 @@ repository.
To build the parser, very recent versions
of Bison and Flex are required. (This is because Nix needs GLR
support in Bison and reentrancy support in Flex.) For Bison, you need
-version 1.875c or higher (1.875 does not work),
-which can be obtained from the GNU FTP server.
-For Flex, you need version 2.5.31, which is available on SourceForge. Slightly
-older versions may also work, but ancient versions like the ubiquitous
-2.5.4a won't. Note that these are only required if you modify the
-parser or when you are building from the Subversion repository.
+version 2.3 or higher (1.875 does not work),
+which can be obtained from
+the GNU FTP
+server. For Flex, you need version 2.5.33, which is available
+on SourceForge.
+Slightly older versions may also work, but ancient versions like the
+ubiquitous 2.5.4a won't. Note that these are only required if you
+modify the parser or when you are building from the Subversion
+repository.
Nix uses Sleepycat's Berkeley DB and CWI's ATerm library. These
are included in the Nix source distribution. If you build from the
@@ -75,7 +76,7 @@ these packages. Alternatively, if you already have them installed,
you can use configure's
and options to point to their respective
locations. Note that Berkeley DB must be version
-4.4; other versions may not have compatible database formats.
+4.5; other versions may not have compatible database formats.
diff --git a/doc/manual/release-notes.xml b/doc/manual/release-notes.xml
index 4830b323e..da8c47588 100644
--- a/doc/manual/release-notes.xml
+++ b/doc/manual/release-notes.xml
@@ -67,11 +67,22 @@
TODO: nix-env now maintains meta
- info about installed packages in user
- environments.
+ info about installed packages in user environments. to show all meta info.
TODO: nix-env
- .
+ . Specific flags:
+ active, priority,
+ keep.
+
+
+ nix-env -q now has a flag
+ () that causes
+ nix-env to show only those derivations whose
+ output is already in the Nix store or that can be substituted (i.e.,
+ downloaded from somewhere). In other words, it shows the packages
+ that can be installed “quickly”, i.e., don’t need to be built from
+ source.TODO: new built-ins
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 456bc25f3..552b58625 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -616,6 +616,9 @@ static char * deepestStack = (char *) -1; /* for measuring stack usage */
Expr evalExpr2(EvalState & state, Expr e)
{
+ /* When changing this function, make sure that you don't cause a
+ (large) increase in stack consumption! */
+
char x;
if (&x < deepestStack) deepestStack = &x;
diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh
index 420911a87..dabbaa323 100644
--- a/src/libexpr/nixexpr.hh
+++ b/src/libexpr/nixexpr.hh
@@ -12,6 +12,7 @@ namespace nix {
MakeError(EvalError, Error)
MakeError(AssertionError, EvalError)
+MakeError(ThrownError, AssertionError)
MakeError(Abort, EvalError)
MakeError(TypeError, EvalError)
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index fdb77901f..b004a3c26 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -271,6 +271,14 @@ static Expr prim_abort(EvalState & state, const ATermVector & args)
}
+static Expr prim_throw(EvalState & state, const ATermVector & args)
+{
+ PathSet context;
+ throw ThrownError(format("user-thrown exception: `%1%'") %
+ evalString(state, args[0], context));
+}
+
+
/* Return an environment variable. Use with care. */
static Expr prim_getEnv(EvalState & state, const ATermVector & args)
{
@@ -1026,6 +1034,7 @@ void EvalState::addPrimOps()
addPrimOp("isNull", 1, prim_isNull);
addPrimOp("dependencyClosure", 1, prim_dependencyClosure);
addPrimOp("abort", 1, prim_abort);
+ addPrimOp("throw", 1, prim_throw);
addPrimOp("__getEnv", 1, prim_getEnv);
addPrimOp("relativise", 2, prim_relativise);
diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc
index f360b73fe..a902a19df 100644
--- a/src/libstore/local-store.cc
+++ b/src/libstore/local-store.cc
@@ -1466,6 +1466,7 @@ void verifyStore(bool checkContents)
nixDB.enumTable(txn, dbValidPaths, paths);
for (Paths::iterator i = paths.begin(); i != paths.end(); ++i) {
+ checkInterrupt();
if (!pathExists(*i)) {
printMsg(lvlError, format("store path `%1%' disappeared") % *i);
invalidateStorePath(txn, *i);
diff --git a/src/nix-env/help.txt b/src/nix-env/help.txt
index 534d16ad3..b10c4b492 100644
--- a/src/nix-env/help.txt
+++ b/src/nix-env/help.txt
@@ -45,8 +45,14 @@ Upgrade flags:
--eq: "upgrade" if the current version is equal
--always: upgrade regardless of current version
-Query types:
+Query sources:
+ --installed: use installed derivations (default)
+ --available / -a: use derivations available in Nix expression
+
+Query flags:
+
+ --xml: show output in XML format
--status / -s: print installed/present status
--no-name: hide derivation names
--attr / -A: shows the unambiguous attribute name of the
@@ -55,11 +61,10 @@ Query types:
--compare-versions / -c: compare version to available or installed
--drv-path: print path of derivation
--out-path: print path of derivation output
-
-Query sources:
-
- --installed: use installed derivations (default)
- --available / -a: use derivations available in Nix expression
+ --description: print description
+ --meta: print all meta attributes (only with --xml)
+ --prebuilt-only: only show derivations whose prebuilt binaries are
+ available on this machine or are downloadable
Options:
diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc
index 9e6bec730..3a1fbba8b 100644
--- a/src/nix-env/nix-env.cc
+++ b/src/nix-env/nix-env.cc
@@ -163,7 +163,6 @@ static void createUserEnv(EvalState & state, const DrvInfos & elems,
ATermList manifest = ATempty;
ATermList inputs = ATempty;
ATermList stateIdentifiers = ATempty;
- ATermList runtimeStateArgs = ATempty;
for (DrvInfos::const_iterator i = elems.begin();
i != elems.end(); ++i)
{
@@ -195,8 +194,6 @@ static void createUserEnv(EvalState & state, const DrvInfos & elems,
//Insert the new stateIdentifier into the stateIdentifiers Atermlist
stateIdentifiers = ATinsert(stateIdentifiers, makeStr(i->queryStateIdentifier(state)));
- //Insert the new runtime state args into the runtimeStateArgs Atermlist
- runtimeStateArgs = ATinsert(runtimeStateArgs, makeStr(i->queryRuntimeStateArgs(state)));
inputs = ATinsert(inputs, makeStr(i->queryOutPath(state)));
@@ -220,15 +217,13 @@ static void createUserEnv(EvalState & state, const DrvInfos & elems,
Expr topLevel = makeCall(envBuilder, makeAttrs(
ATinsert(
- ATmakeList6(
+ ATmakeList5(
makeBind(toATerm("system"),
makeStr(thisSystem), makeNoPos()),
makeBind(toATerm("derivations"),
makeList(ATreverse(manifest)), makeNoPos()),
makeBind(toATerm("stateIdentifiers"),
makeList(ATreverse(stateIdentifiers)), makeNoPos()),
- makeBind(toATerm("runtimeStateArgs"),
- makeList(ATreverse(runtimeStateArgs)), makeNoPos()),
makeBind(toATerm("manifest"),
makeStr(manifestFile, singleton(manifestFile)), makeNoPos()),
makeBind(toATerm("nixBinDir"),
@@ -536,9 +531,13 @@ static void installDerivations(Globals & globals,
for (DrvInfos::iterator i = installedElems.begin(); i != installedElems.end(); ++i)
{
DrvName drvName(i->name);
+ MetaInfo meta = i->queryMetaInfo(globals.state);
//We may need to share state
- if (!globals.preserveInstalled && newNames.find(drvName.name) != newNames.end()){
+ if (!globals.preserveInstalled &&
+ newNames.find(drvName.name) != newNames.end() &&
+ meta["keep"] != "true"
+ ){
//******** We're gonna check if the component and state indentifiers are the same,
// since we may need to share state in that case.
@@ -709,6 +708,9 @@ static void upgradeDerivations(Globals & globals,
{
DrvName drvName(i->name);
+ MetaInfo meta = i->queryMetaInfo(globals.state);
+ if (meta["keep"] == "true") continue;
+
/* Find the derivation in the input Nix expression with the
same name and satisfying the version constraints specified
by upgradeType. If there are multiple matches, take the
@@ -997,6 +999,8 @@ static void opQuery(Globals & globals,
bool printDrvPath = false;
bool printOutPath = false;
bool printDescription = false;
+ bool printMeta = false;
+ bool prebuiltOnly = false;
bool compareVersions = false;
bool xmlOutput = false;
@@ -1013,8 +1017,10 @@ static void opQuery(Globals & globals,
else if (*i == "--compare-versions" || *i == "-c") compareVersions = true;
else if (*i == "--drv-path") printDrvPath = true;
else if (*i == "--out-path") printOutPath = true;
+ else if (*i == "--meta") printMeta = true;
else if (*i == "--installed") source = sInstalled;
else if (*i == "--available" || *i == "-a") source = sAvailable;
+ else if (*i == "--prebuilt-only" || *i == "-b") prebuiltOnly = true;
else if (*i == "--xml") xmlOutput = true;
else throw UsageError(format("unknown flag `%1%'") % *i);
@@ -1080,6 +1086,12 @@ static void opQuery(Globals & globals,
/* For XML output. */
XMLAttrs attrs;
+
+ if (prebuiltOnly) {
+ if (!store->isValidPath(i->queryOutPath(globals.state)) &&
+ !store->hasSubstitutes(i->queryOutPath(globals.state)))
+ continue;
+ }
if (printStatus) {
bool hasSubs = store->hasSubstitutes(i->queryOutPath(globals.state));
@@ -1167,7 +1179,18 @@ static void opQuery(Globals & globals,
}
if (xmlOutput)
- xml.writeEmptyElement("item", attrs);
+ if (printMeta) {
+ XMLOpenElement item(xml, "item", attrs);
+ MetaInfo meta = i->queryMetaInfo(globals.state);
+ for (MetaInfo::iterator j = meta.begin(); j != meta.end(); ++j) {
+ XMLAttrs attrs2;
+ attrs2["name"] = j->first;
+ attrs2["value"] = j->second;
+ xml.writeEmptyElement("meta", attrs2);
+ }
+ }
+ else
+ xml.writeEmptyElement("item", attrs);
else
table.push_back(columns);
diff --git a/src/nix-setuid-helper/nix-setuid-helper.cc b/src/nix-setuid-helper/nix-setuid-helper.cc
index 37347cd28..26c457fd9 100644
--- a/src/nix-setuid-helper/nix-setuid-helper.cc
+++ b/src/nix-setuid-helper/nix-setuid-helper.cc
@@ -36,7 +36,7 @@ static void secureChown(uid_t uidFrom, gid_t gidFrom,
to. */
throw Error(error);
- if (uidFrom != -1) {
+ if (uidFrom != (uid_t) -1) {
assert(uidFrom != 0);
if (st.st_uid != uidFrom)
throw Error(error);