diff --git a/configure.ac b/configure.ac
index 77cd3ad15..8c0f0f26d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -256,8 +256,8 @@ fi
# Whether to use the Boehm garbage collector.
AC_ARG_ENABLE(gc, AC_HELP_STRING([--enable-gc],
- [enable garbage collection in the Nix expression evaluator (requires Boehm GC) [default=no]]),
- gc=$enableval, gc=no)
+ [enable garbage collection in the Nix expression evaluator (requires Boehm GC) [default=yes]]),
+ gc=$enableval, gc=yes)
if test "$gc" = yes; then
PKG_CHECK_MODULES([BDW_GC], [bdw-gc])
CXXFLAGS="$BDW_GC_CFLAGS $CXXFLAGS"
diff --git a/doc/manual/advanced-topics/cores-vs-jobs.xml b/doc/manual/advanced-topics/cores-vs-jobs.xml
index eba645faf..4d58ac7c5 100644
--- a/doc/manual/advanced-topics/cores-vs-jobs.xml
+++ b/doc/manual/advanced-topics/cores-vs-jobs.xml
@@ -36,8 +36,8 @@ to , unless
equals 0, in which case NIX_BUILD_CORES
will be the total number of cores in the system.
-The total number of consumed cores is a simple multiplication,
- * NIX_BUILD_CORES.
+The maximum number of consumed cores is a simple multiplication,
+ * NIX_BUILD_CORES.
The balance on how to set these two independent variables depends
upon each builder's workload and hardware. Here are a few example
diff --git a/doc/manual/advanced-topics/post-build-hook.xml b/doc/manual/advanced-topics/post-build-hook.xml
index 3dc43ee79..08a7a772f 100644
--- a/doc/manual/advanced-topics/post-build-hook.xml
+++ b/doc/manual/advanced-topics/post-build-hook.xml
@@ -5,7 +5,7 @@
version="5.0"
>
-Using the
+Using the
Uploading to an S3-compatible binary cache after each build
diff --git a/doc/manual/command-ref/env-common.xml b/doc/manual/command-ref/env-common.xml
index 6a3aaae71..696d68c34 100644
--- a/doc/manual/command-ref/env-common.xml
+++ b/doc/manual/command-ref/env-common.xml
@@ -122,7 +122,7 @@ $ mount -o bind /mnt/otherdisk/nix /nix
NIX_LOG_DIR
Overrides the location of the Nix log directory
- (default prefix/log/nix).
+ (default prefix/var/log/nix).
diff --git a/doc/manual/command-ref/opt-common.xml b/doc/manual/command-ref/opt-common.xml
index b8a2f260e..6a8107be9 100644
--- a/doc/manual/command-ref/opt-common.xml
+++ b/doc/manual/command-ref/opt-common.xml
@@ -243,9 +243,10 @@
name value
This option is accepted by
- nix-env, nix-instantiate and
- nix-build. When evaluating Nix expressions, the
- expression evaluator will automatically try to call functions that
+ nix-env, nix-instantiate,
+ nix-shell and nix-build.
+ When evaluating Nix expressions, the expression evaluator will
+ automatically try to call functions that
it encounters. It can automatically call functions for which every
argument has a default value
(e.g., { argName ?
diff --git a/flake.nix b/flake.nix
index a16ef4656..307a879bb 100644
--- a/flake.nix
+++ b/flake.nix
@@ -51,9 +51,7 @@
});
configureFlags =
- [
- "--enable-gc"
- ] ++ lib.optionals stdenv.isLinux [
+ lib.optionals stdenv.isLinux [
"--with-sandbox-shell=${sh}/bin/busybox"
];
@@ -173,8 +171,6 @@
buildInputs = tarballDeps ++ buildDeps;
- configureFlags = "--enable-gc";
-
postUnpack = ''
(cd $sourceRoot && find . -type f) | cut -c3- > $sourceRoot/.dist-files
cat $sourceRoot/.dist-files
@@ -219,7 +215,7 @@
in
runCommand "nix-binary-tarball-${version}"
- { nativeBuildInputs = lib.optional (system != "aarch64-linux") shellcheck;
+ { #nativeBuildInputs = lib.optional (system != "aarch64-linux") shellcheck;
meta.description = "Distribution-independent Nix bootstrap binaries for ${system}";
}
''
@@ -372,7 +368,7 @@
x86_64-linux = "${self.hydraJobs.build.x86_64-linux}";
}
EOF
- su - alice -c 'nix upgrade-nix -vvv --nix-store-paths-url file:///tmp/paths.nix'
+ su - alice -c 'nix --experimental-features nix-command upgrade-nix -vvv --nix-store-paths-url file:///tmp/paths.nix'
(! [ -L /home/alice/.profile-1-link ])
su - alice -c 'PAGER= nix-store -qR ${self.hydraJobs.build.x86_64-linux}'
@@ -381,6 +377,7 @@
umount /nix
'');
+ /*
# Check whether we can still evaluate all of Nixpkgs.
tests.evalNixpkgs =
import (nixpkgs + "/pkgs/top-level/make-tarball.nix") {
@@ -389,6 +386,7 @@
pkgs = nixpkgsFor.x86_64-linux;
officialRelease = false;
};
+ */
# Check whether we can still evaluate NixOS.
tests.evalNixOS =
@@ -422,7 +420,7 @@
tests.remoteBuilds
tests.nix-copy-closure
tests.binaryTarball
- tests.evalNixpkgs
+ #tests.evalNixpkgs
tests.evalNixOS
installerScript
];
diff --git a/src/libexpr/attr-path.cc b/src/libexpr/attr-path.cc
index 832235cfd..843585631 100644
--- a/src/libexpr/attr-path.cc
+++ b/src/libexpr/attr-path.cc
@@ -93,4 +93,36 @@ Value * findAlongAttrPath(EvalState & state, const string & attrPath,
}
+Pos findDerivationFilename(EvalState & state, Value & v, std::string what)
+{
+ Value * v2;
+ try {
+ auto dummyArgs = state.allocBindings(0);
+ v2 = findAlongAttrPath(state, "meta.position", *dummyArgs, v);
+ } catch (Error &) {
+ throw Error("package '%s' has no source location information", what);
+ }
+
+ // FIXME: is it possible to extract the Pos object instead of doing this
+ // toString + parsing?
+ auto pos = state.forceString(*v2);
+
+ auto colon = pos.rfind(':');
+ if (colon == std::string::npos)
+ throw Error("cannot parse meta.position attribute '%s'", pos);
+
+ std::string filename(pos, 0, colon);
+ unsigned int lineno;
+ try {
+ lineno = std::stoi(std::string(pos, colon + 1));
+ } catch (std::invalid_argument & e) {
+ throw Error("cannot parse line number '%s'", pos);
+ }
+
+ Symbol file = state.symbols.create(filename);
+
+ return { file, lineno, 0 };
+}
+
+
}
diff --git a/src/libexpr/attr-path.hh b/src/libexpr/attr-path.hh
index 1eae64625..fcccc39c8 100644
--- a/src/libexpr/attr-path.hh
+++ b/src/libexpr/attr-path.hh
@@ -12,4 +12,7 @@ MakeError(AttrPathNotFound, Error);
Value * findAlongAttrPath(EvalState & state, const string & attrPath,
Bindings & autoArgs, Value & vIn);
+/* Heuristic to find the filename and lineno or a nix value. */
+Pos findDerivationFilename(EvalState & state, Value & v, std::string what);
+
}
diff --git a/src/libutil/args.cc b/src/libutil/args.cc
index ba15ea571..ad7a268fc 100644
--- a/src/libutil/args.cc
+++ b/src/libutil/args.cc
@@ -178,6 +178,19 @@ Strings argvToStrings(int argc, char * * argv)
return args;
}
+Strings editorFor(Pos pos)
+{
+ auto editor = getEnv("EDITOR", "cat");
+ auto args = tokenizeString(editor);
+ if (pos.line > 0 && (
+ editor.find("emacs") != std::string::npos ||
+ editor.find("nano") != std::string::npos ||
+ editor.find("vim") != std::string::npos))
+ args.push_back(fmt("+%d", pos.line));
+ args.push_back(pos.file);
+ return args;
+}
+
std::string renderLabels(const Strings & labels)
{
std::string res;
diff --git a/src/libutil/args.hh b/src/libutil/args.hh
index b960a55a8..59d427ee6 100644
--- a/src/libutil/args.hh
+++ b/src/libutil/args.hh
@@ -5,6 +5,7 @@
#include
#include "util.hh"
+#include "nixexpr.hh"
namespace nix {
@@ -241,6 +242,9 @@ public:
Strings argvToStrings(int argc, char * * argv);
+/* Helper function to generate args that invoke $EDITOR on filename:lineno */
+Strings editorFor(Pos pos);
+
/* Helper function for rendering argument labels. */
std::string renderLabels(const Strings & labels);
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index 747b31cff..0902c3783 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -1572,7 +1572,11 @@ std::unique_ptr createInterruptCallback(std::function
AutoCloseFD createUnixDomainSocket(const Path & path, mode_t mode)
{
- AutoCloseFD fdSocket = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
+ AutoCloseFD fdSocket = socket(PF_UNIX, SOCK_STREAM
+ #ifdef SOCK_CLOEXEC
+ | SOCK_CLOEXEC
+ #endif
+ , 0);
if (!fdSocket)
throw SysError("cannot create Unix domain socket");
diff --git a/src/nix/doctor.cc b/src/nix/doctor.cc
index 98260127b..5f76d0019 100644
--- a/src/nix/doctor.cc
+++ b/src/nix/doctor.cc
@@ -1,11 +1,17 @@
+#include
+
#include "command.hh"
+#include "logging.hh"
#include "serve-protocol.hh"
#include "shared.hh"
#include "store-api.hh"
+#include "util.hh"
#include "worker-protocol.hh"
using namespace nix;
+namespace {
+
std::string formatProtocol(unsigned int proto)
{
if (proto) {
@@ -16,19 +22,30 @@ std::string formatProtocol(unsigned int proto)
return "unknown";
}
+bool checkPass(const std::string & msg) {
+ logger->log(ANSI_GREEN "[PASS] " ANSI_NORMAL + msg);
+ return true;
+}
+
+bool checkFail(const std::string & msg) {
+ logger->log(ANSI_RED "[FAIL] " ANSI_NORMAL + msg);
+ return false;
+}
+
+}
+
struct CmdDoctor : StoreCommand
{
bool success = true;
std::string description() override
{
- return "check your system for potential problems";
+ return "check your system for potential problems and print a PASS or FAIL for each check.";
}
void run(ref store) override
{
- std::cout << "Store uri: " << store->getUri() << std::endl;
- std::cout << std::endl;
+ logger->log("Running checks against store uri: " + store->getUri());
auto type = getStoreType();
@@ -51,15 +68,14 @@ struct CmdDoctor : StoreCommand
dirs.insert(dirOf(canonPath(dir + "/nix-env", true)));
if (dirs.size() != 1) {
- std::cout << "Warning: multiple versions of nix found in PATH." << std::endl;
- std::cout << std::endl;
+ std::stringstream ss;
+ ss << "Multiple versions of nix found in PATH:\n";
for (auto & dir : dirs)
- std::cout << " " << dir << std::endl;
- std::cout << std::endl;
- return false;
+ ss << " " << dir << "\n";
+ return checkFail(ss.str());
}
- return true;
+ return checkPass("PATH contains only one nix version.");
}
bool checkProfileRoots(ref store)
@@ -82,17 +98,17 @@ struct CmdDoctor : StoreCommand
}
if (!dirs.empty()) {
- std::cout << "Warning: found profiles outside of " << settings.nixStateDir << "/profiles." << std::endl;
- std::cout << "The generation this profile points to might not have a gcroot and could be" << std::endl;
- std::cout << "garbage collected, resulting in broken symlinks." << std::endl;
- std::cout << std::endl;
+ std::stringstream ss;
+ ss << "Found profiles outside of " << settings.nixStateDir << "/profiles.\n"
+ << "The generation this profile points to might not have a gcroot and could be\n"
+ << "garbage collected, resulting in broken symlinks.\n\n";
for (auto & dir : dirs)
- std::cout << " " << dir << std::endl;
- std::cout << std::endl;
- return false;
+ ss << " " << dir << "\n";
+ ss << "\n";
+ return checkFail(ss.str());
}
- return true;
+ return checkPass("All profiles are gcroots.");
}
bool checkStoreProtocol(unsigned int storeProto)
@@ -102,17 +118,16 @@ struct CmdDoctor : StoreCommand
: PROTOCOL_VERSION;
if (clientProto != storeProto) {
- std::cout << "Warning: protocol version of this client does not match the store." << std::endl;
- std::cout << "While this is not necessarily a problem it's recommended to keep the client in" << std::endl;
- std::cout << "sync with the daemon." << std::endl;
- std::cout << std::endl;
- std::cout << "Client protocol: " << formatProtocol(clientProto) << std::endl;
- std::cout << "Store protocol: " << formatProtocol(storeProto) << std::endl;
- std::cout << std::endl;
- return false;
+ std::stringstream ss;
+ ss << "Warning: protocol version of this client does not match the store.\n"
+ << "While this is not necessarily a problem it's recommended to keep the client in\n"
+ << "sync with the daemon.\n\n"
+ << "Client protocol: " << formatProtocol(clientProto) << "\n"
+ << "Store protocol: " << formatProtocol(storeProto) << "\n\n";
+ return checkFail(ss.str());
}
- return true;
+ return checkPass("Client protocol matches store protocol.");
}
};
diff --git a/src/nix/edit.cc b/src/nix/edit.cc
index 632a99d11..ca410cd1f 100644
--- a/src/nix/edit.cc
+++ b/src/nix/edit.cc
@@ -31,45 +31,17 @@ struct CmdEdit : InstallableCommand
auto v = installable->toValue(*state);
- Value * v2;
- try {
- auto dummyArgs = state->allocBindings(0);
- v2 = findAlongAttrPath(*state, "meta.position", *dummyArgs, *v);
- } catch (Error &) {
- throw Error("package '%s' has no source location information", installable->what());
- }
-
- auto pos = state->forceString(*v2);
- debug("position is %s", pos);
-
- auto colon = pos.rfind(':');
- if (colon == std::string::npos)
- throw Error("cannot parse meta.position attribute '%s'", pos);
-
- std::string filename(pos, 0, colon);
- int lineno;
- try {
- lineno = std::stoi(std::string(pos, colon + 1));
- } catch (std::invalid_argument & e) {
- throw Error("cannot parse line number '%s'", pos);
- }
-
- auto editor = getEnv("EDITOR", "cat");
-
- auto args = tokenizeString(editor);
-
- if (editor.find("emacs") != std::string::npos ||
- editor.find("nano") != std::string::npos ||
- editor.find("vim") != std::string::npos)
- args.push_back(fmt("+%d", lineno));
-
- args.push_back(filename);
+ Pos pos = findDerivationFilename(*state, *v, installable->what());
stopProgressBar();
+ auto args = editorFor(pos);
+
execvp(args.front().c_str(), stringsToCharPtrs(args).data());
- throw SysError("cannot run editor '%s'", editor);
+ std::string command;
+ for (const auto &arg : args) command += " '" + arg + "'";
+ throw SysError("cannot run command%s", command);
}
};
diff --git a/src/nix/repl.cc b/src/nix/repl.cc
index 0fa1594cc..2b4d1a2c4 100644
--- a/src/nix/repl.cc
+++ b/src/nix/repl.cc
@@ -22,6 +22,7 @@ extern "C" {
#include "shared.hh"
#include "eval.hh"
#include "eval-inline.hh"
+#include "attr-path.hh"
#include "store-api.hh"
#include "common-eval-args.hh"
#include "get-drvs.hh"
@@ -440,6 +441,7 @@ bool NixRepl::processLine(string line)
<< " = Bind expression to variable\n"
<< " :a Add attributes from resulting set to scope\n"
<< " :b Build derivation\n"
+ << " :e Open the derivation in $EDITOR\n"
<< " :i Build derivation, then install result into current profile\n"
<< " :l Load Nix expression and add it to scope\n"
<< " :p Evaluate and print expression recursively\n"
@@ -466,6 +468,34 @@ bool NixRepl::processLine(string line)
reloadFiles();
}
+ else if (command == ":e" || command == ":edit") {
+ Value v;
+ evalString(arg, v);
+
+ Pos pos;
+
+ if (v.type == tPath || v.type == tString) {
+ PathSet context;
+ auto filename = state.coerceToString(noPos, v, context);
+ pos.file = state.symbols.create(filename);
+ } else if (v.type == tLambda) {
+ pos = v.lambda.fun->pos;
+ } else {
+ // assume it's a derivation
+ pos = findDerivationFilename(state, v, arg);
+ }
+
+ // Open in EDITOR
+ auto args = editorFor(pos);
+ auto editor = args.front();
+ args.pop_front();
+ runProgram(editor, args);
+
+ // Reload right after exiting the editor
+ state.resetFileCache();
+ reloadFiles();
+ }
+
else if (command == ":t") {
Value v;
evalString(arg, v);
diff --git a/tests/nix-copy-closure.nix b/tests/nix-copy-closure.nix
index 7c4bdaded..9c9d119b7 100644
--- a/tests/nix-copy-closure.nix
+++ b/tests/nix-copy-closure.nix
@@ -11,10 +11,10 @@ makeTest (let pkgA = pkgs.cowsay; pkgB = pkgs.wget; pkgC = pkgs.hello; in {
nodes =
{ client =
- { config, pkgs, ... }:
+ { config, lib, pkgs, ... }:
{ virtualisation.writableStore = true;
virtualisation.pathsInNixDB = [ pkgA ];
- nix.binaryCaches = [ ];
+ nix.binaryCaches = lib.mkForce [ ];
};
server =
diff --git a/tests/remote-builds.nix b/tests/remote-builds.nix
index a53f9bfcd..153956619 100644
--- a/tests/remote-builds.nix
+++ b/tests/remote-builds.nix
@@ -42,7 +42,7 @@ in
builder2 = builder;
client =
- { config, pkgs, ... }:
+ { config, lib, pkgs, ... }:
{ nix.maxJobs = 0; # force remote building
nix.distributedBuilds = true;
nix.buildMachines =
@@ -61,7 +61,7 @@ in
];
virtualisation.writableStore = true;
virtualisation.pathsInNixDB = [ config.system.build.extraUtils ];
- nix.binaryCaches = [ ];
+ nix.binaryCaches = lib.mkForce [ ];
programs.ssh.extraConfig = "ConnectTimeout 30";
};
};
diff --git a/tests/setuid.nix b/tests/setuid.nix
index d79d071df..6f2f7d392 100644
--- a/tests/setuid.nix
+++ b/tests/setuid.nix
@@ -12,7 +12,7 @@ makeTest {
machine =
{ config, lib, pkgs, ... }:
{ virtualisation.writableStore = true;
- nix.binaryCaches = [ ];
+ nix.binaryCaches = lib.mkForce [ ];
nix.nixPath = [ "nixpkgs=${lib.cleanSource pkgs.path}" ];
virtualisation.pathsInNixDB = [ pkgs.stdenv pkgs.pkgsi686Linux.stdenv ];
};