diff --git a/.gitignore b/.gitignore
index e10c75418..e3186fa76 100644
--- a/.gitignore
+++ b/.gitignore
@@ -47,7 +47,7 @@ perl/Makefile.config
/src/libexpr/nix.tbl
# /src/libstore/
-/src/libstore/*.gen.hh
+*.gen.*
/src/nix/nix
diff --git a/Makefile.config.in b/Makefile.config.in
index fe609ce06..e7a12089a 100644
--- a/Makefile.config.in
+++ b/Makefile.config.in
@@ -37,6 +37,7 @@ prefix = @prefix@
sandbox_shell = @sandbox_shell@
storedir = @storedir@
sysconfdir = @sysconfdir@
+system = @system@
doc_generate = @doc_generate@
xmllint = @xmllint@
xsltproc = @xsltproc@
diff --git a/doc/manual/command-ref/nix-store.xml b/doc/manual/command-ref/nix-store.xml
index 113a3c2e4..1ddb5408d 100644
--- a/doc/manual/command-ref/nix-store.xml
+++ b/doc/manual/command-ref/nix-store.xml
@@ -360,7 +360,6 @@ EOF
-
bytes
@@ -407,14 +406,6 @@ the Nix store not reachable via file system references from a set of
-
-
- This operation performs an actual garbage
- collection. All dead paths are removed from the
- store. This is the default.
-
-
-
By default, all unreachable paths are deleted. The following
@@ -444,10 +435,10 @@ and keep-derivations
variables in the Nix configuration file.
-With , the collector prints the total
-number of freed bytes when it finishes (or when it is interrupted).
-With , it prints the number of bytes that
-would be freed.
+By default, the collector prints the total number of freed bytes
+when it finishes (or when it is interrupted). With
+, it prints the number of bytes that would
+be freed.
@@ -1148,7 +1139,7 @@ the information that Nix considers important. For instance,
timestamps are elided because all files in the Nix store have their
timestamp set to 0 anyway. Likewise, all permissions are left out
except for the execute bit, because all files in the Nix store have
-644 or 755 permission.
+444 or 555 permission.
Also, a NAR archive is canonical, meaning
that “equal” paths always produce the same NAR archive. For instance,
diff --git a/local.mk b/local.mk
index 55f85a044..d254c10fe 100644
--- a/local.mk
+++ b/local.mk
@@ -6,9 +6,11 @@ dist-files += configure config.h.in perl/configure
clean-files += Makefile.config
-GLOBAL_CXXFLAGS += -I . -I src -I src/libutil -I src/libstore -I src/libmain -I src/libexpr -I src/nix -Wno-deprecated-declarations
+GLOBAL_CXXFLAGS += -Wno-deprecated-declarations
$(foreach i, config.h $(call rwildcard, src/lib*, *.hh), \
$(eval $(call install-file-in, $(i), $(includedir)/nix, 0644)))
$(GCH) $(PCH): src/libutil/util.hh config.h
+
+GCH_CXXFLAGS = -I src/libutil
diff --git a/mk/precompiled-headers.mk b/mk/precompiled-headers.mk
index 1a727ba1b..1c0452dc2 100644
--- a/mk/precompiled-headers.mk
+++ b/mk/precompiled-headers.mk
@@ -8,14 +8,14 @@ GCH = $(buildprefix)precompiled-headers.h.gch
$(GCH): precompiled-headers.h
@rm -f $@
@mkdir -p "$(dir $@)"
- $(trace-gen) $(CXX) -x c++-header -o $@ $< $(GLOBAL_CXXFLAGS)
+ $(trace-gen) $(CXX) -x c++-header -o $@ $< $(GLOBAL_CXXFLAGS) $(GCH_CXXFLAGS)
PCH = $(buildprefix)precompiled-headers.h.pch
$(PCH): precompiled-headers.h
@rm -f $@
@mkdir -p "$(dir $@)"
- $(trace-gen) $(CXX) -x c++-header -o $@ $< $(GLOBAL_CXXFLAGS)
+ $(trace-gen) $(CXX) -x c++-header -o $@ $< $(GLOBAL_CXXFLAGS) $(GCH_CXXFLAGS)
clean-files += $(GCH) $(PCH)
diff --git a/release.nix b/release.nix
index 9b591229a..65b035957 100644
--- a/release.nix
+++ b/release.nix
@@ -12,52 +12,64 @@ let
builtins.readFile ./.version
+ (if officialRelease then "" else "pre${toString nix.revCount}_${nix.shortRev}");
+ # Create a "vendor" directory that contains the crates listed in
+ # Cargo.lock. This allows Nix to be built without network access.
+ vendoredCrates' =
+ let
+ lockFile = builtins.fromTOML (builtins.readFile nix-rust/Cargo.lock);
+
+ files = map (pkg: import {
+ url = "https://crates.io/api/v1/crates/${pkg.name}/${pkg.version}/download";
+ sha256 = lockFile.metadata."checksum ${pkg.name} ${pkg.version} (registry+https://github.com/rust-lang/crates.io-index)";
+ }) (builtins.filter (pkg: pkg.source or "" == "registry+https://github.com/rust-lang/crates.io-index") lockFile.package);
+
+ in pkgs.runCommand "cargo-vendor-dir" {}
+ ''
+ mkdir -p $out/vendor
+
+ cat > $out/vendor/config < "$dir/.cargo-checksum.json"
+
+ # Clean up some cruft from the winapi crates. FIXME: find
+ # a way to remove winapi* from our dependencies.
+ if [[ $dir =~ /winapi ]]; then
+ find $dir -name "*.a" -print0 | xargs -0 rm -f --
+ fi
+
+ mv "$dir" $out/vendor/
+
+ rm -rf $out/vendor/tmp
+ '') files)}
+ '';
+
jobs = rec {
- # Create a "vendor" directory that contains the crates listed in
- # Cargo.lock. This allows Nix to be built without network access.
vendoredCrates =
- let
- lockFile = builtins.fromTOML (builtins.readFile nix-rust/Cargo.lock);
-
- files = map (pkg: import {
- url = "https://crates.io/api/v1/crates/${pkg.name}/${pkg.version}/download";
- sha256 = lockFile.metadata."checksum ${pkg.name} ${pkg.version} (registry+https://github.com/rust-lang/crates.io-index)";
- }) (builtins.filter (pkg: pkg.source or "" == "registry+https://github.com/rust-lang/crates.io-index") lockFile.package);
-
- in pkgs.runCommand "cargo-vendor-dir" {}
+ with pkgs;
+ runCommand "vendored-crates" {}
''
- mkdir -p $out/vendor
-
- cat > $out/vendor/config < "$dir/.cargo-checksum.json"
-
- # Clean up some cruft from the winapi crates. FIXME: find
- # a way to remove winapi* from our dependencies.
- if [[ $dir =~ /winapi ]]; then
- find $dir -name "*.a" -print0 | xargs -0 rm -f --
- fi
-
- mv "$dir" $out/vendor/
-
- rm -rf $out/vendor/tmp
- '') files)}
+ mkdir -p $out/nix-support
+ name=nix-vendored-crates-${version}
+ fn=$out/$name.tar.xz
+ tar cvfJ $fn -C ${vendoredCrates'} vendor \
+ --owner=0 --group=0 --mode=u+rw,uga+r \
+ --transform "s,vendor,$name,"
+ echo "file crates-tarball $fn" >> $out/nix-support/hydra-build-products
'';
-
build = pkgs.lib.genAttrs systems (system:
let pkgs = import nixpkgs { inherit system; }; in
@@ -89,7 +101,7 @@ let
patchelf --set-rpath $out/lib:${stdenv.cc.cc.lib}/lib $out/lib/libboost_thread.so.*
''}
- ln -sfn ${vendoredCrates}/vendor/ nix-rust/vendor
+ ln -sfn ${vendoredCrates'}/vendor/ nix-rust/vendor
(cd perl; autoreconf --install --force --verbose)
'';
diff --git a/scripts/install-multi-user.sh b/scripts/install-multi-user.sh
index 13762cba3..a0f1deb98 100644
--- a/scripts/install-multi-user.sh
+++ b/scripts/install-multi-user.sh
@@ -13,12 +13,12 @@ set -o pipefail
# however tracking which bits came from which would be impossible.
readonly ESC='\033[0m'
-readonly BOLD='\033[38;1m'
-readonly BLUE='\033[38;34m'
-readonly BLUE_UL='\033[38;4;34m'
-readonly GREEN='\033[38;32m'
-readonly GREEN_UL='\033[38;4;32m'
-readonly RED='\033[38;31m'
+readonly BOLD='\033[1m'
+readonly BLUE='\033[34m'
+readonly BLUE_UL='\033[4;34m'
+readonly GREEN='\033[32m'
+readonly GREEN_UL='\033[4;32m'
+readonly RED='\033[31m'
readonly NIX_USER_COUNT="32"
readonly NIX_BUILD_GROUP_ID="30000"
@@ -567,7 +567,7 @@ install_from_extracted_nix() {
cd "$EXTRACTED_NIX_PATH"
_sudo "to copy the basic Nix files to the new store at $NIX_ROOT/store" \
- rsync -rlpt ./store/* "$NIX_ROOT/store/"
+ rsync -rlpt --chmod=-w ./store/* "$NIX_ROOT/store/"
if [ -d "$NIX_INSTALLED_NIX" ]; then
echo " Alright! We have our first nix at $NIX_INSTALLED_NIX"
diff --git a/scripts/install.in b/scripts/install.in
index 4500fd54a..6709f00d4 100644
--- a/scripts/install.in
+++ b/scripts/install.in
@@ -36,6 +36,7 @@ tarball="$tmpDir/$(basename "$tmpDir/nix-@nixVersion@-$system.tar.xz")"
require_util curl "download the binary tarball"
require_util tar "unpack the binary tarball"
+require_util xz "unpack the binary tarball"
echo "downloading Nix @nixVersion@ binary tarball for $system from '$url' to '$tmpDir'..."
curl -L "$url" -o "$tarball" || oops "failed to download '$url'"
diff --git a/src/build-remote/build-remote.cc b/src/build-remote/build-remote.cc
index 69d1c6f7e..00340b787 100644
--- a/src/build-remote/build-remote.cc
+++ b/src/build-remote/build-remote.cc
@@ -17,7 +17,7 @@
#include "store-api.hh"
#include "derivations.hh"
#include "local-store.hh"
-#include "legacy.hh"
+#include "../nix/legacy.hh"
using namespace nix;
using std::cin;
diff --git a/src/libexpr/attr-path.cc b/src/libexpr/attr-path.cc
index 06b472d8b..76d101b98 100644
--- a/src/libexpr/attr-path.cc
+++ b/src/libexpr/attr-path.cc
@@ -32,15 +32,13 @@ static Strings parseAttrPath(const string & s)
}
-Value * findAlongAttrPath(EvalState & state, const string & attrPath,
+std::pair findAlongAttrPath(EvalState & state, const string & attrPath,
Bindings & autoArgs, Value & vIn)
{
Strings tokens = parseAttrPath(attrPath);
- Error attrError =
- Error(format("attribute selection path '%1%' does not match expression") % attrPath);
-
Value * v = &vIn;
+ Pos pos = noPos;
for (auto & attr : tokens) {
@@ -70,8 +68,9 @@ Value * findAlongAttrPath(EvalState & state, const string & attrPath,
Bindings::iterator a = v->attrs->find(state.symbols.create(attr));
if (a == v->attrs->end())
- throw Error(format("attribute '%1%' in selection path '%2%' not found") % attr % attrPath);
+ throw AttrPathNotFound("attribute '%1%' in selection path '%2%' not found", attr, attrPath);
v = &*a->value;
+ pos = *a->pos;
}
else if (apType == apIndex) {
@@ -82,14 +81,15 @@ Value * findAlongAttrPath(EvalState & state, const string & attrPath,
% attrPath % showType(*v));
if (attrIndex >= v->listSize())
- throw Error(format("list index %1% in selection path '%2%' is out of range") % attrIndex % attrPath);
+ throw AttrPathNotFound("list index %1% in selection path '%2%' is out of range", attrIndex, attrPath);
v = v->listElems()[attrIndex];
+ pos = noPos;
}
}
- return v;
+ return {v, pos};
}
@@ -98,9 +98,9 @@ Pos findDerivationFilename(EvalState & state, Value & v, std::string what)
Value * v2;
try {
auto dummyArgs = state.allocBindings(0);
- v2 = findAlongAttrPath(state, "meta.position", *dummyArgs, v);
+ v2 = findAlongAttrPath(state, "meta.position", *dummyArgs, v).first;
} catch (Error &) {
- throw Error("package '%s' has no source location information", what);
+ throw NoPositionInfo("package '%s' has no source location information", what);
}
// FIXME: is it possible to extract the Pos object instead of doing this
diff --git a/src/libexpr/attr-path.hh b/src/libexpr/attr-path.hh
index 716e5ba27..fce160da7 100644
--- a/src/libexpr/attr-path.hh
+++ b/src/libexpr/attr-path.hh
@@ -7,7 +7,10 @@
namespace nix {
-Value * findAlongAttrPath(EvalState & state, const string & attrPath,
+MakeError(AttrPathNotFound, Error);
+MakeError(NoPositionInfo, Error);
+
+std::pair findAlongAttrPath(EvalState & state, const string & attrPath,
Bindings & autoArgs, Value & vIn);
/* Heuristic to find the filename and lineno or a nix value. */
diff --git a/src/libexpr/attr-set.cc b/src/libexpr/attr-set.cc
index 0785897d2..b1d61a285 100644
--- a/src/libexpr/attr-set.cc
+++ b/src/libexpr/attr-set.cc
@@ -43,6 +43,12 @@ Value * EvalState::allocAttr(Value & vAttrs, const Symbol & name)
}
+Value * EvalState::allocAttr(Value & vAttrs, const std::string & name)
+{
+ return allocAttr(vAttrs, symbols.create(name));
+}
+
+
void Bindings::sort()
{
std::sort(begin(), end());
diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh
index eac53b894..1485dc7fe 100644
--- a/src/libexpr/eval.hh
+++ b/src/libexpr/eval.hh
@@ -272,6 +272,7 @@ public:
Env & allocEnv(size_t size);
Value * allocAttr(Value & vAttrs, const Symbol & name);
+ Value * allocAttr(Value & vAttrs, const std::string & name);
Bindings * allocBindings(size_t capacity);
@@ -367,7 +368,7 @@ struct EvalSettings : Config
"Prefixes of URIs that builtin functions such as fetchurl and fetchGit are allowed to fetch."};
Setting traceFunctionCalls{this, false, "trace-function-calls",
- "Emit log messages for each function entry and exit at the 'vomit' log level (-vvvv)"};
+ "Emit log messages for each function entry and exit at the 'vomit' log level (-vvvv)."};
};
extern EvalSettings evalSettings;
diff --git a/src/libexpr/function-trace.cc b/src/libexpr/function-trace.cc
index af1486f78..c6057b384 100644
--- a/src/libexpr/function-trace.cc
+++ b/src/libexpr/function-trace.cc
@@ -1,4 +1,5 @@
#include "function-trace.hh"
+#include "logging.hh"
namespace nix {
diff --git a/src/libexpr/local.mk b/src/libexpr/local.mk
index 8a9b3c2ea..a4ccab376 100644
--- a/src/libexpr/local.mk
+++ b/src/libexpr/local.mk
@@ -6,6 +6,8 @@ libexpr_DIR := $(d)
libexpr_SOURCES := $(wildcard $(d)/*.cc) $(wildcard $(d)/primops/*.cc) $(d)/lexer-tab.cc $(d)/parser-tab.cc
+libexpr_CXXFLAGS += -I src/libutil -I src/libstore -I src/libmain -I src/libexpr
+
libexpr_LIBS = libutil libstore libnixrust
libexpr_LDFLAGS =
diff --git a/src/libexpr/primops/fromTOML.cc b/src/libexpr/primops/fromTOML.cc
index a84e569e9..c43324dbb 100644
--- a/src/libexpr/primops/fromTOML.cc
+++ b/src/libexpr/primops/fromTOML.cc
@@ -1,7 +1,7 @@
#include "primops.hh"
#include "eval-inline.hh"
-#include "cpptoml/cpptoml.h"
+#include "../../cpptoml/cpptoml.h"
namespace nix {
diff --git a/src/libmain/local.mk b/src/libmain/local.mk
index 0c80f5a0a..a8eed6c65 100644
--- a/src/libmain/local.mk
+++ b/src/libmain/local.mk
@@ -6,6 +6,8 @@ libmain_DIR := $(d)
libmain_SOURCES := $(wildcard $(d)/*.cc)
+libmain_CXXFLAGS += -I src/libutil -I src/libstore
+
libmain_LDFLAGS = $(OPENSSL_LIBS)
libmain_LIBS = libstore libutil
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index 9c6aedfa5..527d7ac42 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -6,6 +6,7 @@
#include "archive.hh"
#include "affinity.hh"
#include "builtins.hh"
+#include "builtins/buildenv.hh"
#include "download.hh"
#include "finally.hh"
#include "compression.hh"
@@ -1397,7 +1398,7 @@ void DerivationGoal::tryToBuild()
few seconds and then retry this goal. */
PathSet lockFiles;
for (auto & outPath : drv->outputPaths())
- lockFiles.insert(worker.store.toRealPath(worker.store.printStorePath(outPath)));
+ lockFiles.insert(worker.store.Store::toRealPath(outPath));
if (!outputLocks.lockPaths(lockFiles, "", false)) {
worker.waitForAWhile(shared_from_this());
@@ -1428,7 +1429,7 @@ void DerivationGoal::tryToBuild()
for (auto & i : drv->outputs) {
if (worker.store.isValidPath(i.second.path)) continue;
debug("removing invalid path '%s'", worker.store.printStorePath(i.second.path));
- deletePath(worker.store.toRealPath(worker.store.printStorePath(i.second.path)));
+ deletePath(worker.store.Store::toRealPath(i.second.path));
}
/* Don't do a remote build if the derivation has the attribute
@@ -1685,7 +1686,7 @@ void DerivationGoal::buildDone()
/* Delete unused redirected outputs (when doing hash rewriting). */
for (auto & i : redirectedOutputs)
- deletePath(worker.store.toRealPath(worker.store.printStorePath(i.second)));
+ deletePath(worker.store.Store::toRealPath(i.second));
/* Delete the chroot (if we were using one). */
autoDelChroot.reset(); /* this runs the destructor */
@@ -1904,7 +1905,7 @@ void DerivationGoal::startBuilder()
concatStringsSep(", ", parsedDrv->getRequiredSystemFeatures()),
worker.store.printStorePath(drvPath),
settings.thisSystem,
- concatStringsSep(", ", settings.systemFeatures));
+ concatStringsSep(", ", settings.systemFeatures));
if (drv->isBuiltin())
preloadNSS();
@@ -2071,7 +2072,7 @@ void DerivationGoal::startBuilder()
environment using bind-mounts. We put it in the Nix store
to ensure that we can create hard-links to non-directory
inputs in the fake Nix store in the chroot (see below). */
- chrootRootDir = worker.store.toRealPath(worker.store.printStorePath(drvPath)) + ".chroot";
+ chrootRootDir = worker.store.Store::toRealPath(drvPath) + ".chroot";
deletePath(chrootRootDir);
/* Clean up the chroot directory automatically. */
@@ -2464,7 +2465,7 @@ void DerivationGoal::initTmpDir() {
auto hash = hashString(htSHA256, i.first);
string fn = ".attr-" + hash.to_string(Base32, false);
Path p = tmpDir + "/" + fn;
- writeFile(p, i.second);
+ writeFile(p, rewriteStrings(i.second, inputRewrites));
chownToBuilder(p);
env[i.first + "Path"] = tmpDirInSandbox + "/" + fn;
}
@@ -2550,7 +2551,7 @@ static std::regex shVarName("[A-Za-z_][A-Za-z0-9_]*");
void DerivationGoal::writeStructuredAttrs()
{
- auto & structuredAttrs = parsedDrv->getStructuredAttrs();
+ auto structuredAttrs = parsedDrv->getStructuredAttrs();
if (!structuredAttrs) return;
auto json = *structuredAttrs;
@@ -2916,7 +2917,7 @@ void DerivationGoal::addDependency(const StorePath & path)
#if __linux__
- Path source = worker.store.toRealPath(worker.store.printStorePath(path));
+ Path source = worker.store.Store::toRealPath(path);
Path target = chrootRootDir + worker.store.printStorePath(path);
debug("bind-mounting %s -> %s", target, source);
@@ -3578,7 +3579,7 @@ void DerivationGoal::registerOutputs()
if (needsHashRewrite()) {
auto r = redirectedOutputs.find(i.second.path);
if (r != redirectedOutputs.end()) {
- auto redirected = worker.store.toRealPath(worker.store.printStorePath(r->second));
+ auto redirected = worker.store.Store::toRealPath(r->second);
if (buildMode == bmRepair
&& redirectedBadOutputs.count(i.second.path)
&& pathExists(redirected))
@@ -3671,7 +3672,7 @@ void DerivationGoal::registerOutputs()
BuildError("hash mismatch in fixed-output derivation '%s':\n wanted: %s\n got: %s",
worker.store.printStorePath(dest), h.to_string(SRI), h2.to_string(SRI)));
- Path actualDest = worker.store.toRealPath(worker.store.printStorePath(dest));
+ Path actualDest = worker.store.Store::toRealPath(dest);
if (worker.store.isValidPath(dest))
std::rethrow_exception(delayedException);
diff --git a/src/libstore/builtins.hh b/src/libstore/builtins.hh
index 87d6ce665..66597e456 100644
--- a/src/libstore/builtins.hh
+++ b/src/libstore/builtins.hh
@@ -6,7 +6,6 @@ namespace nix {
// TODO: make pluggable.
void builtinFetchurl(const BasicDerivation & drv, const std::string & netrcData);
-void builtinBuildenv(const BasicDerivation & drv);
void builtinUnpackChannel(const BasicDerivation & drv);
}
diff --git a/src/libstore/builtins/buildenv.cc b/src/libstore/builtins/buildenv.cc
index 096593886..1b802d908 100644
--- a/src/libstore/builtins/buildenv.cc
+++ b/src/libstore/builtins/buildenv.cc
@@ -1,4 +1,4 @@
-#include "builtins.hh"
+#include "buildenv.hh"
#include
#include
@@ -7,16 +7,14 @@
namespace nix {
-typedef std::map Priorities;
-
-// FIXME: change into local variables.
-
-static Priorities priorities;
-
-static unsigned long symlinks;
+struct State
+{
+ std::map priorities;
+ unsigned long symlinks = 0;
+};
/* For each activated package, create symlinks */
-static void createLinks(const Path & srcDir, const Path & dstDir, int priority)
+static void createLinks(State & state, const Path & srcDir, const Path & dstDir, int priority)
{
DirEntries srcFiles;
@@ -67,7 +65,7 @@ static void createLinks(const Path & srcDir, const Path & dstDir, int priority)
auto res = lstat(dstFile.c_str(), &dstSt);
if (res == 0) {
if (S_ISDIR(dstSt.st_mode)) {
- createLinks(srcFile, dstFile, priority);
+ createLinks(state, srcFile, dstFile, priority);
continue;
} else if (S_ISLNK(dstSt.st_mode)) {
auto target = canonPath(dstFile, true);
@@ -77,8 +75,8 @@ static void createLinks(const Path & srcDir, const Path & dstDir, int priority)
throw SysError(format("unlinking '%1%'") % dstFile);
if (mkdir(dstFile.c_str(), 0755) == -1)
throw SysError(format("creating directory '%1%'"));
- createLinks(target, dstFile, priorities[dstFile]);
- createLinks(srcFile, dstFile, priority);
+ createLinks(state, target, dstFile, state.priorities[dstFile]);
+ createLinks(state, srcFile, dstFile, priority);
continue;
}
} else if (errno != ENOENT)
@@ -90,7 +88,7 @@ static void createLinks(const Path & srcDir, const Path & dstDir, int priority)
auto res = lstat(dstFile.c_str(), &dstSt);
if (res == 0) {
if (S_ISLNK(dstSt.st_mode)) {
- auto prevPriority = priorities[dstFile];
+ auto prevPriority = state.priorities[dstFile];
if (prevPriority == priority)
throw Error(
"packages '%1%' and '%2%' have the same priority %3%; "
@@ -109,67 +107,30 @@ static void createLinks(const Path & srcDir, const Path & dstDir, int priority)
}
createSymlink(srcFile, dstFile);
- priorities[dstFile] = priority;
- symlinks++;
+ state.priorities[dstFile] = priority;
+ state.symlinks++;
}
}
-typedef std::set FileProp;
-
-static FileProp done;
-static FileProp postponed = FileProp{};
-
-static Path out;
-
-static void addPkg(const Path & pkgDir, int priority)
+void buildProfile(const Path & out, Packages && pkgs)
{
- if (!done.insert(pkgDir).second) return;
- createLinks(pkgDir, out, priority);
+ State state;
- try {
- for (const auto & p : tokenizeString>(
- readFile(pkgDir + "/nix-support/propagated-user-env-packages"), " \n"))
- if (!done.count(p))
- postponed.insert(p);
- } catch (SysError & e) {
- if (e.errNo != ENOENT && e.errNo != ENOTDIR) throw;
- }
-}
+ std::set done, postponed;
-struct Package {
- Path path;
- bool active;
- int priority;
- Package(Path path, bool active, int priority) : path{path}, active{active}, priority{priority} {}
-};
+ auto addPkg = [&](const Path & pkgDir, int priority) {
+ if (!done.insert(pkgDir).second) return;
+ createLinks(state, pkgDir, out, priority);
-typedef std::vector Packages;
-
-void builtinBuildenv(const BasicDerivation & drv)
-{
- auto getAttr = [&](const string & name) {
- auto i = drv.env.find(name);
- if (i == drv.env.end()) throw Error("attribute '%s' missing", name);
- return i->second;
- };
-
- out = getAttr("out");
- createDirs(out);
-
- /* Convert the stuff we get from the environment back into a
- * coherent data type. */
- Packages pkgs;
- auto derivations = tokenizeString(getAttr("derivations"));
- while (!derivations.empty()) {
- /* !!! We're trusting the caller to structure derivations env var correctly */
- auto active = derivations.front(); derivations.pop_front();
- auto priority = stoi(derivations.front()); derivations.pop_front();
- auto outputs = stoi(derivations.front()); derivations.pop_front();
- for (auto n = 0; n < outputs; n++) {
- auto path = derivations.front(); derivations.pop_front();
- pkgs.emplace_back(path, active != "false", priority);
+ try {
+ for (const auto & p : tokenizeString>(
+ readFile(pkgDir + "/nix-support/propagated-user-env-packages"), " \n"))
+ if (!done.count(p))
+ postponed.insert(p);
+ } catch (SysError & e) {
+ if (e.errNo != ENOENT && e.errNo != ENOTDIR) throw;
}
- }
+ };
/* Symlink to the packages that have been installed explicitly by the
* user. Process in priority order to reduce unnecessary
@@ -189,13 +150,42 @@ void builtinBuildenv(const BasicDerivation & drv)
*/
auto priorityCounter = 1000;
while (!postponed.empty()) {
- auto pkgDirs = postponed;
- postponed = FileProp{};
+ std::set pkgDirs;
+ postponed.swap(pkgDirs);
for (const auto & pkgDir : pkgDirs)
addPkg(pkgDir, priorityCounter++);
}
- printError("created %d symlinks in user environment", symlinks);
+ debug("created %d symlinks in user environment", state.symlinks);
+}
+
+void builtinBuildenv(const BasicDerivation & drv)
+{
+ auto getAttr = [&](const string & name) {
+ auto i = drv.env.find(name);
+ if (i == drv.env.end()) throw Error("attribute '%s' missing", name);
+ return i->second;
+ };
+
+ Path out = getAttr("out");
+ createDirs(out);
+
+ /* Convert the stuff we get from the environment back into a
+ * coherent data type. */
+ Packages pkgs;
+ auto derivations = tokenizeString(getAttr("derivations"));
+ while (!derivations.empty()) {
+ /* !!! We're trusting the caller to structure derivations env var correctly */
+ auto active = derivations.front(); derivations.pop_front();
+ auto priority = stoi(derivations.front()); derivations.pop_front();
+ auto outputs = stoi(derivations.front()); derivations.pop_front();
+ for (auto n = 0; n < outputs; n++) {
+ auto path = derivations.front(); derivations.pop_front();
+ pkgs.emplace_back(path, active != "false", priority);
+ }
+ }
+
+ buildProfile(out, std::move(pkgs));
createSymlink(getAttr("manifest"), out + "/manifest.nix");
}
diff --git a/src/libstore/builtins/buildenv.hh b/src/libstore/builtins/buildenv.hh
new file mode 100644
index 000000000..0a37459b0
--- /dev/null
+++ b/src/libstore/builtins/buildenv.hh
@@ -0,0 +1,21 @@
+#pragma once
+
+#include "derivations.hh"
+#include "store-api.hh"
+
+namespace nix {
+
+struct Package {
+ Path path;
+ bool active;
+ int priority;
+ Package(Path path, bool active, int priority) : path{path}, active{active}, priority{priority} {}
+};
+
+typedef std::vector Packages;
+
+void buildProfile(const Path & out, Packages && pkgs);
+
+void builtinBuildenv(const BasicDerivation & drv);
+
+}
diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc
index 205b90e55..973ddc86a 100644
--- a/src/libstore/derivations.cc
+++ b/src/libstore/derivations.cc
@@ -65,7 +65,7 @@ bool BasicDerivation::isBuiltin() const
StorePath writeDerivation(ref store,
- const Derivation & drv, const string & name, RepairFlag repair)
+ const Derivation & drv, std::string_view name, RepairFlag repair)
{
auto references = cloneStorePathSet(drv.inputSrcs);
for (auto & i : drv.inputDrvs)
@@ -73,8 +73,8 @@ StorePath writeDerivation(ref store,
/* Note that the outputs of a derivation are *not* references
(that can be missing (of course) and should not necessarily be
held during a garbage collection). */
- string suffix = name + drvExtension;
- string contents = drv.unparse(*store, false);
+ auto suffix = std::string(name) + drvExtension;
+ auto contents = drv.unparse(*store, false);
return settings.readOnlyMode
? store->computeStorePathForText(suffix, contents, references)
: store->addTextToStore(suffix, contents, references, repair);
diff --git a/src/libstore/derivations.hh b/src/libstore/derivations.hh
index c2df66229..7222d25e5 100644
--- a/src/libstore/derivations.hh
+++ b/src/libstore/derivations.hh
@@ -79,7 +79,7 @@ class Store;
/* Write a derivation to the Nix store, and return its path. */
StorePath writeDerivation(ref store,
- const Derivation & drv, const string & name, RepairFlag repair = NoRepair);
+ const Derivation & drv, std::string_view name, RepairFlag repair = NoRepair);
/* Read a derivation from a file. */
Derivation readDerivation(const Store & store, const Path & drvPath);
diff --git a/src/libstore/download.cc b/src/libstore/download.cc
index 149c84765..5967d0425 100644
--- a/src/libstore/download.cc
+++ b/src/libstore/download.cc
@@ -390,6 +390,7 @@ struct CurlDownloader : public Downloader
case CURLE_SSL_CACERT_BADFILE:
case CURLE_TOO_MANY_REDIRECTS:
case CURLE_WRITE_ERROR:
+ case CURLE_UNSUPPORTED_PROTOCOL:
err = Misc;
break;
default: // Shut up warnings
diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc
index a8945996e..7e97f3c22 100644
--- a/src/libstore/globals.cc
+++ b/src/libstore/globals.cc
@@ -20,13 +20,6 @@ namespace nix {
must be deleted and recreated on startup.) */
#define DEFAULT_SOCKET_PATH "/daemon-socket/socket"
-/* chroot-like behavior from Apple's sandbox */
-#if __APPLE__
- #define DEFAULT_ALLOWED_IMPURE_PREFIXES "/System/Library /usr/lib /dev /bin/sh"
-#else
- #define DEFAULT_ALLOWED_IMPURE_PREFIXES ""
-#endif
-
Settings settings;
static GlobalConfig::Register r1(&settings);
@@ -68,7 +61,12 @@ Settings::Settings()
sandboxPaths = tokenizeString("/bin/sh=" SANDBOX_SHELL);
#endif
- allowedImpureHostPrefixes = tokenizeString(DEFAULT_ALLOWED_IMPURE_PREFIXES);
+
+/* chroot-like behavior from Apple's sandbox */
+#if __APPLE__
+ sandboxPaths = tokenizeString("/System/Library/Frameworks /System/Library/PrivateFrameworks /bin/sh /bin/bash /private/tmp /private/var/tmp /usr/lib");
+ allowedImpureHostPrefixes = tokenizeString("/System/Library /usr/lib /dev /bin/sh");
+#endif
}
void loadConfFile()
diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh
index 782870547..3aa3653f3 100644
--- a/src/libstore/globals.hh
+++ b/src/libstore/globals.hh
@@ -311,12 +311,7 @@ public:
Setting printMissing{this, true, "print-missing",
"Whether to print what paths need to be built or downloaded."};
- Setting preBuildHook{this,
-#if __APPLE__
- nixLibexecDir + "/nix/resolve-system-dependencies",
-#else
- "",
-#endif
+ Setting preBuildHook{this, "",
"pre-build-hook",
"A program to run just before a build to set derivation-specific build settings."};
diff --git a/src/libstore/http-binary-cache-store.cc b/src/libstore/http-binary-cache-store.cc
index d4ae36662..011794c62 100644
--- a/src/libstore/http-binary-cache-store.cc
+++ b/src/libstore/http-binary-cache-store.cc
@@ -163,10 +163,11 @@ static RegisterStoreImplementation regStore([](
const std::string & uri, const Store::Params & params)
-> std::shared_ptr
{
+ static bool forceHttp = getEnv("_NIX_FORCE_HTTP") == "1";
if (std::string(uri, 0, 7) != "http://" &&
std::string(uri, 0, 8) != "https://" &&
- (getEnv("_NIX_FORCE_HTTP_BINARY_CACHE_STORE") != "1" || std::string(uri, 0, 7) != "file://")
- ) return 0;
+ (!forceHttp || std::string(uri, 0, 7) != "file://"))
+ return 0;
auto store = std::make_shared(params, uri);
store->init();
return store;
diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc
index cd2e86f29..ae7513ad8 100644
--- a/src/libstore/local-store.cc
+++ b/src/libstore/local-store.cc
@@ -298,9 +298,7 @@ void LocalStore::openDB(State & state, bool create)
/* Open the Nix database. */
string dbPath = dbDir + "/db.sqlite";
auto & db(state.db);
- if (sqlite3_open_v2(dbPath.c_str(), &db.db,
- SQLITE_OPEN_READWRITE | (create ? SQLITE_OPEN_CREATE : 0), 0) != SQLITE_OK)
- throw Error(format("cannot open Nix database '%1%'") % dbPath);
+ state.db = SQLite(dbPath, create);
#ifdef __CYGWIN__
/* The cygwin version of sqlite3 has a patch which calls
@@ -312,11 +310,6 @@ void LocalStore::openDB(State & state, bool create)
SetDllDirectoryW(L"");
#endif
- if (sqlite3_busy_timeout(db, 60 * 60 * 1000) != SQLITE_OK)
- throwSQLiteError(db, "setting timeout");
-
- db.exec("pragma foreign_keys = 1");
-
/* !!! check whether sqlite has been built with foreign key
support */
@@ -350,7 +343,7 @@ void LocalStore::openDB(State & state, bool create)
/* Initialise the database schema, if necessary. */
if (create) {
- const char * schema =
+ static const char schema[] =
#include "schema.sql.gen.hh"
;
db.exec(schema);
@@ -1275,7 +1268,7 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair)
else
hashSink = std::make_unique(info->narHash.type, storePathToHash(printStorePath(info->path)));
- dumpPath(toRealPath(printStorePath(i)), *hashSink);
+ dumpPath(Store::toRealPath(i), *hashSink);
auto current = hashSink->finish();
if (info->narHash != nullHash && info->narHash != current.first) {
diff --git a/src/libstore/local.mk b/src/libstore/local.mk
index ac68c2342..91acef368 100644
--- a/src/libstore/local.mk
+++ b/src/libstore/local.mk
@@ -31,7 +31,8 @@ ifeq ($(HAVE_SECCOMP), 1)
libstore_LDFLAGS += -lseccomp
endif
-libstore_CXXFLAGS = \
+libstore_CXXFLAGS += \
+ -I src/libutil -I src/libstore \
-DNIX_PREFIX=\"$(prefix)\" \
-DNIX_STORE_DIR=\"$(storedir)\" \
-DNIX_DATA_DIR=\"$(datadir)\" \
diff --git a/src/libstore/nar-info-disk-cache.cc b/src/libstore/nar-info-disk-cache.cc
index 907645d86..442541330 100644
--- a/src/libstore/nar-info-disk-cache.cc
+++ b/src/libstore/nar-info-disk-cache.cc
@@ -78,12 +78,7 @@ public:
state->db = SQLite(dbPath);
- if (sqlite3_busy_timeout(state->db, 60 * 60 * 1000) != SQLITE_OK)
- throwSQLiteError(state->db, "setting timeout");
-
- // We can always reproduce the cache.
- state->db.exec("pragma synchronous = off");
- state->db.exec("pragma main.journal_mode = truncate");
+ state->db.isCache();
state->db.exec(schema);
diff --git a/src/libstore/nar-info-disk-cache.hh b/src/libstore/nar-info-disk-cache.hh
index 878acbb87..04de2c5eb 100644
--- a/src/libstore/nar-info-disk-cache.hh
+++ b/src/libstore/nar-info-disk-cache.hh
@@ -10,7 +10,7 @@ class NarInfoDiskCache
public:
typedef enum { oValid, oInvalid, oUnknown } Outcome;
- virtual ~NarInfoDiskCache() { };
+ virtual ~NarInfoDiskCache() { }
virtual void createCache(const std::string & uri, const Path & storeDir,
bool wantMassQuery, int priority) = 0;
diff --git a/src/libstore/parsed-derivations.cc b/src/libstore/parsed-derivations.cc
index d0f289a0f..45c033c66 100644
--- a/src/libstore/parsed-derivations.cc
+++ b/src/libstore/parsed-derivations.cc
@@ -1,5 +1,7 @@
#include "parsed-derivations.hh"
+#include
+
namespace nix {
ParsedDerivation::ParsedDerivation(StorePath && drvPath, BasicDerivation & drv)
@@ -9,13 +11,15 @@ ParsedDerivation::ParsedDerivation(StorePath && drvPath, BasicDerivation & drv)
auto jsonAttr = drv.env.find("__json");
if (jsonAttr != drv.env.end()) {
try {
- structuredAttrs = nlohmann::json::parse(jsonAttr->second);
+ structuredAttrs = std::make_unique(nlohmann::json::parse(jsonAttr->second));
} catch (std::exception & e) {
throw Error("cannot process __json attribute of '%s': %s", drvPath.to_string(), e.what());
}
}
}
+ParsedDerivation::~ParsedDerivation() { }
+
std::optional ParsedDerivation::getStringAttr(const std::string & name) const
{
if (structuredAttrs) {
diff --git a/src/libstore/parsed-derivations.hh b/src/libstore/parsed-derivations.hh
index cec868754..f4df5dd54 100644
--- a/src/libstore/parsed-derivations.hh
+++ b/src/libstore/parsed-derivations.hh
@@ -1,6 +1,6 @@
#include "derivations.hh"
-#include
+#include
namespace nix {
@@ -8,15 +8,17 @@ class ParsedDerivation
{
StorePath drvPath;
BasicDerivation & drv;
- std::optional structuredAttrs;
+ std::unique_ptr structuredAttrs;
public:
ParsedDerivation(StorePath && drvPath, BasicDerivation & drv);
- const std::optional & getStructuredAttrs() const
+ ~ParsedDerivation();
+
+ const nlohmann::json * getStructuredAttrs() const
{
- return structuredAttrs;
+ return structuredAttrs.get();
}
std::optional getStringAttr(const std::string & name) const;
diff --git a/src/libstore/profiles.cc b/src/libstore/profiles.cc
index dae3f2d32..2bef51878 100644
--- a/src/libstore/profiles.cc
+++ b/src/libstore/profiles.cc
@@ -256,4 +256,22 @@ string optimisticLockProfile(const Path & profile)
}
+Path getDefaultProfile()
+{
+ Path profileLink = getHome() + "/.nix-profile";
+ try {
+ if (!pathExists(profileLink)) {
+ replaceSymlink(
+ getuid() == 0
+ ? settings.nixStateDir + "/profiles/default"
+ : fmt("%s/profiles/per-user/%s/profile", settings.nixStateDir, getUserName()),
+ profileLink);
+ }
+ return absPath(readLink(profileLink), dirOf(profileLink));
+ } catch (Error &) {
+ return profileLink;
+ }
+}
+
+
}
diff --git a/src/libstore/profiles.hh b/src/libstore/profiles.hh
index 5fa1533de..78645d8b6 100644
--- a/src/libstore/profiles.hh
+++ b/src/libstore/profiles.hh
@@ -64,4 +64,8 @@ void lockProfile(PathLocks & lock, const Path & profile);
rebuilt. */
string optimisticLockProfile(const Path & profile);
+/* Resolve ~/.nix-profile. If ~/.nix-profile doesn't exist yet, create
+ it. */
+Path getDefaultProfile();
+
}
diff --git a/src/libstore/sandbox-defaults.sb b/src/libstore/sandbox-defaults.sb
index 0299d1ee4..351037822 100644
--- a/src/libstore/sandbox-defaults.sb
+++ b/src/libstore/sandbox-defaults.sb
@@ -71,6 +71,12 @@
(literal "/dev/zero")
(subpath "/dev/fd"))
+; Allow pseudo-terminals.
+(allow file*
+ (literal "/dev/ptmx")
+ (regex #"^/dev/pty[a-z]+")
+ (regex #"^/dev/ttys[0-9]+"))
+
; Does nothing, but reduces build noise.
(allow file* (literal "/dev/dtracehelper"))
@@ -85,3 +91,7 @@
(literal "/etc")
(literal "/var")
(literal "/private/var/tmp"))
+
+; This is used by /bin/sh on macOS 10.15 and later.
+(allow file*
+ (literal "/private/var/select/sh"))
diff --git a/src/libstore/sqlite.cc b/src/libstore/sqlite.cc
index a061d64f3..eb1daafc5 100644
--- a/src/libstore/sqlite.cc
+++ b/src/libstore/sqlite.cc
@@ -25,11 +25,16 @@ namespace nix {
throw SQLiteError("%s: %s (in '%s')", fs.s, sqlite3_errstr(exterr), path);
}
-SQLite::SQLite(const Path & path)
+SQLite::SQLite(const Path & path, bool create)
{
if (sqlite3_open_v2(path.c_str(), &db,
- SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0) != SQLITE_OK)
+ SQLITE_OPEN_READWRITE | (create ? SQLITE_OPEN_CREATE : 0), 0) != SQLITE_OK)
throw Error(format("cannot open SQLite database '%s'") % path);
+
+ if (sqlite3_busy_timeout(db, 60 * 60 * 1000) != SQLITE_OK)
+ throwSQLiteError(db, "setting timeout");
+
+ exec("pragma foreign_keys = 1");
}
SQLite::~SQLite()
@@ -42,6 +47,12 @@ SQLite::~SQLite()
}
}
+void SQLite::isCache()
+{
+ exec("pragma synchronous = off");
+ exec("pragma main.journal_mode = truncate");
+}
+
void SQLite::exec(const std::string & stmt)
{
retrySQLite([&]() {
@@ -94,6 +105,16 @@ SQLiteStmt::Use & SQLiteStmt::Use::operator () (const std::string & value, bool
return *this;
}
+SQLiteStmt::Use & SQLiteStmt::Use::operator () (const unsigned char * data, size_t len, bool notNull)
+{
+ if (notNull) {
+ if (sqlite3_bind_blob(stmt, curArg++, data, len, SQLITE_TRANSIENT) != SQLITE_OK)
+ throwSQLiteError(stmt.db, "binding argument");
+ } else
+ bind();
+ return *this;
+}
+
SQLiteStmt::Use & SQLiteStmt::Use::operator () (int64_t value, bool notNull)
{
if (notNull) {
diff --git a/src/libstore/sqlite.hh b/src/libstore/sqlite.hh
index bd012d9b9..fd04c9b07 100644
--- a/src/libstore/sqlite.hh
+++ b/src/libstore/sqlite.hh
@@ -5,8 +5,8 @@
#include "types.hh"
-class sqlite3;
-class sqlite3_stmt;
+struct sqlite3;
+struct sqlite3_stmt;
namespace nix {
@@ -15,13 +15,16 @@ struct SQLite
{
sqlite3 * db = 0;
SQLite() { }
- SQLite(const Path & path);
+ SQLite(const Path & path, bool create = true);
SQLite(const SQLite & from) = delete;
SQLite& operator = (const SQLite & from) = delete;
SQLite& operator = (SQLite && from) { db = from.db; from.db = 0; return *this; }
~SQLite();
operator sqlite3 * () { return db; }
+ /* Disable synchronous mode, set truncate journal mode. */
+ void isCache();
+
void exec(const std::string & stmt);
};
@@ -52,6 +55,7 @@ struct SQLiteStmt
/* Bind the next parameter. */
Use & operator () (const std::string & value, bool notNull = true);
+ Use & operator () (const unsigned char * data, size_t len, bool notNull = true);
Use & operator () (int64_t value, bool notNull = true);
Use & bind(); // null
diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc
index b043feb0a..b9e894a9a 100644
--- a/src/libstore/store-api.cc
+++ b/src/libstore/store-api.cc
@@ -441,7 +441,9 @@ string Store::makeValidityRegistration(const StorePathSet & paths,
void Store::pathInfoToJSON(JSONPlaceholder & jsonOut, const StorePathSet & storePaths,
- bool includeImpureInfo, bool showClosureSize, AllowInvalidFlag allowInvalid)
+ bool includeImpureInfo, bool showClosureSize,
+ Base hashBase,
+ AllowInvalidFlag allowInvalid)
{
auto jsonList = jsonOut.list();
@@ -453,7 +455,7 @@ void Store::pathInfoToJSON(JSONPlaceholder & jsonOut, const StorePathSet & store
auto info = queryPathInfo(storePath);
jsonPath
- .attr("narHash", info->narHash.to_string())
+ .attr("narHash", info->narHash.to_string(hashBase))
.attr("narSize", info->narSize);
{
@@ -741,12 +743,7 @@ std::string Store::showPaths(const StorePathSet & paths)
string showPaths(const PathSet & paths)
{
- string s;
- for (auto & i : paths) {
- if (s.size() != 0) s += ", ";
- s += "'" + i + "'";
- }
- return s;
+ return concatStringsSep(", ", quoteStrings(paths));
}
diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh
index e0484de13..0fa59be6a 100644
--- a/src/libstore/store-api.hh
+++ b/src/libstore/store-api.hh
@@ -561,6 +561,7 @@ public:
each path is included. */
void pathInfoToJSON(JSONPlaceholder & jsonOut, const StorePathSet & storePaths,
bool includeImpureInfo, bool showClosureSize,
+ Base hashBase = Base32,
AllowInvalidFlag allowInvalid = DisallowInvalid);
/* Return the size of the closure of the specified path, that is,
@@ -676,6 +677,11 @@ public:
return storePath;
}
+ Path toRealPath(const StorePath & storePath)
+ {
+ return toRealPath(printStorePath(storePath));
+ }
+
virtual void createUser(const std::string & userName, uid_t userId)
{ }
diff --git a/src/libutil/hash.hh b/src/libutil/hash.hh
index ffa43ecf5..ea9fca3e7 100644
--- a/src/libutil/hash.hh
+++ b/src/libutil/hash.hh
@@ -80,6 +80,18 @@ struct Hash
or base-64. By default, this is prefixed by the hash type
(e.g. "sha256:"). */
std::string to_string(Base base = Base32, bool includeType = true) const;
+
+ std::string gitRev() const
+ {
+ assert(type == htSHA1);
+ return to_string(Base16, false);
+ }
+
+ std::string gitShortRev() const
+ {
+ assert(type == htSHA1);
+ return std::string(to_string(Base16, false), 0, 7);
+ }
};
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index 012f1d071..332c1c43a 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -97,10 +97,10 @@ void replaceEnv(std::map newEnv)
}
-Path absPath(Path path, Path dir)
+Path absPath(Path path, std::optional dir)
{
if (path[0] != '/') {
- if (dir == "") {
+ if (!dir) {
#ifdef __GNU__
/* GNU (aka. GNU/Hurd) doesn't have any limitation on path
lengths and doesn't define `PATH_MAX'. */
@@ -116,7 +116,7 @@ Path absPath(Path path, Path dir)
free(buf);
#endif
}
- path = dir + "/" + path;
+ path = *dir + "/" + path;
}
return canonPath(path);
}
@@ -478,6 +478,17 @@ Path createTempDir(const Path & tmpRoot, const Path & prefix,
}
+std::pair createTempFile(const Path & prefix)
+{
+ Path tmpl(getEnv("TMPDIR").value_or("/tmp") + "/" + prefix + ".XXXXXX");
+ // Strictly speaking, this is UB, but who cares...
+ AutoCloseFD fd(mkstemp((char *) tmpl.c_str()));
+ if (!fd)
+ throw SysError("creating temporary file '%s'", tmpl);
+ return {std::move(fd), tmpl};
+}
+
+
std::string getUserName()
{
auto pw = getpwuid(geteuid());
@@ -1205,28 +1216,6 @@ template StringSet tokenizeString(std::string_view s, const string & separators)
template vector tokenizeString(std::string_view s, const string & separators);
-string concatStringsSep(const string & sep, const Strings & ss)
-{
- string s;
- for (auto & i : ss) {
- if (s.size() != 0) s += sep;
- s += i;
- }
- return s;
-}
-
-
-string concatStringsSep(const string & sep, const StringSet & ss)
-{
- string s;
- for (auto & i : ss) {
- if (s.size() != 0) s += sep;
- s += i;
- }
- return s;
-}
-
-
string chomp(const string & s)
{
size_t i = s.find_last_not_of(" \n\r\t");
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index 0b55c6788..fb9a7ed38 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -48,7 +48,7 @@ void clearEnv();
/* Return an absolutized path, resolving paths relative to the
specified directory, or the current directory otherwise. The path
is also canonicalised. */
-Path absPath(Path path, Path dir = "");
+Path absPath(Path path, std::optional dir = {});
/* Canonicalise a path by removing all `.' or `..' components and
double or trailing slashes. Optionally resolves all symlink
@@ -124,10 +124,6 @@ void deletePath(const Path & path);
void deletePath(const Path & path, unsigned long long & bytesFreed);
-/* Create a temporary directory. */
-Path createTempDir(const Path & tmpRoot = "", const Path & prefix = "nix",
- bool includePid = true, bool useGlobalCounter = true, mode_t mode = 0755);
-
std::string getUserName();
/* Return $HOME or the user's home directory from /etc/passwd. */
@@ -207,6 +203,14 @@ public:
};
+/* Create a temporary directory. */
+Path createTempDir(const Path & tmpRoot = "", const Path & prefix = "nix",
+ bool includePid = true, bool useGlobalCounter = true, mode_t mode = 0755);
+
+/* Create a temporary file, returning a file handle and its path. */
+std::pair createTempFile(const Path & prefix = "nix");
+
+
class Pipe
{
public:
@@ -347,8 +351,26 @@ template C tokenizeString(std::string_view s, const string & separators
/* Concatenate the given strings with a separator between the
elements. */
-string concatStringsSep(const string & sep, const Strings & ss);
-string concatStringsSep(const string & sep, const StringSet & ss);
+template
+string concatStringsSep(const string & sep, const C & ss)
+{
+ string s;
+ for (auto & i : ss) {
+ if (s.size() != 0) s += sep;
+ s += i;
+ }
+ return s;
+}
+
+
+/* Add quotes around a collection of strings. */
+template Strings quoteStrings(const C & c)
+{
+ Strings res;
+ for (auto & s : c)
+ res.push_back("'" + s + "'");
+ return res;
+}
/* Remove trailing whitespace from a string. */
@@ -426,6 +448,13 @@ void ignoreException();
+/* Tree formatting. */
+constexpr char treeConn[] = "├───";
+constexpr char treeLast[] = "└───";
+constexpr char treeLine[] = "│ ";
+constexpr char treeNull[] = " ";
+
+
/* Truncate a string to 'width' printable characters. If 'filterAll'
is true, all ANSI escape sequences are filtered out. Otherwise,
some escape sequences (such as colour setting) are copied but not
@@ -444,10 +473,11 @@ string base64Decode(const string & s);
/* Get a value for the specified key from an associate container, or a
default value if the key doesn't exist. */
template
-std::optional get(const T & map, const std::string & key)
+std::optional get(const T & map, const typename T::key_type & key)
{
auto i = map.find(key);
- return i == map.end() ? std::optional() : i->second;
+ if (i == map.end()) return {};
+ return std::optional(i->second);
}
@@ -551,4 +581,31 @@ extern PathFilter defaultPathFilter;
AutoCloseFD createUnixDomainSocket(const Path & path, mode_t mode);
+// A Rust/Python-like enumerate() iterator adapter.
+// Borrowed from http://reedbeta.com/blog/python-like-enumerate-in-cpp17.
+template ())),
+ typename = decltype(std::end(std::declval()))>
+constexpr auto enumerate(T && iterable)
+{
+ struct iterator
+ {
+ size_t i;
+ TIter iter;
+ bool operator != (const iterator & other) const { return iter != other.iter; }
+ void operator ++ () { ++i; ++iter; }
+ auto operator * () const { return std::tie(i, *iter); }
+ };
+
+ struct iterable_wrapper
+ {
+ T iterable;
+ auto begin() { return iterator{ 0, std::begin(iterable) }; }
+ auto end() { return iterator{ 0, std::end(iterable) }; }
+ };
+
+ return iterable_wrapper{ std::forward(iterable) };
+}
+
+
}
diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc
index 27ec7d0fe..0a058a31b 100755
--- a/src/nix-build/nix-build.cc
+++ b/src/nix-build/nix-build.cc
@@ -16,7 +16,7 @@
#include "get-drvs.hh"
#include "common-eval-args.hh"
#include "attr-path.hh"
-#include "legacy.hh"
+#include "../nix/legacy.hh"
using namespace nix;
using namespace std::string_literals;
@@ -314,7 +314,7 @@ static void _main(int argc, char * * argv)
state->eval(e, vRoot);
for (auto & i : attrPaths) {
- Value & v(*findAlongAttrPath(*state, i, *autoArgs, vRoot));
+ Value & v(*findAlongAttrPath(*state, i, *autoArgs, vRoot).first);
state->forceValue(v);
getDerivations(*state, v, "", *autoArgs, drvs, false);
}
diff --git a/src/nix-channel/nix-channel.cc b/src/nix-channel/nix-channel.cc
index 1b337a712..a2639579d 100755
--- a/src/nix-channel/nix-channel.cc
+++ b/src/nix-channel/nix-channel.cc
@@ -2,7 +2,7 @@
#include "globals.hh"
#include "download.hh"
#include "store-api.hh"
-#include "legacy.hh"
+#include "../nix/legacy.hh"
#include
#include
diff --git a/src/nix-collect-garbage/nix-collect-garbage.cc b/src/nix-collect-garbage/nix-collect-garbage.cc
index d4060ac93..aa5ada3a6 100644
--- a/src/nix-collect-garbage/nix-collect-garbage.cc
+++ b/src/nix-collect-garbage/nix-collect-garbage.cc
@@ -2,7 +2,7 @@
#include "profiles.hh"
#include "shared.hh"
#include "globals.hh"
-#include "legacy.hh"
+#include "../nix/legacy.hh"
#include
#include
diff --git a/src/nix-copy-closure/nix-copy-closure.cc b/src/nix-copy-closure/nix-copy-closure.cc
index f87035760..b10184718 100755
--- a/src/nix-copy-closure/nix-copy-closure.cc
+++ b/src/nix-copy-closure/nix-copy-closure.cc
@@ -1,6 +1,6 @@
#include "shared.hh"
#include "store-api.hh"
-#include "legacy.hh"
+#include "../nix/legacy.hh"
using namespace nix;
diff --git a/src/nix-daemon/nix-daemon.cc b/src/nix-daemon/nix-daemon.cc
index 134898561..e68d1b1be 100644
--- a/src/nix-daemon/nix-daemon.cc
+++ b/src/nix-daemon/nix-daemon.cc
@@ -6,7 +6,7 @@
#include "globals.hh"
#include "derivations.hh"
#include "finally.hh"
-#include "legacy.hh"
+#include "../nix/legacy.hh"
#include "daemon.hh"
#include
diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc
index 106dfe0b6..1a2bb42a3 100644
--- a/src/nix-env/nix-env.cc
+++ b/src/nix-env/nix-env.cc
@@ -13,7 +13,7 @@
#include "json.hh"
#include "value-to-json.hh"
#include "xml-writer.hh"
-#include "legacy.hh"
+#include "../nix/legacy.hh"
#include
#include
@@ -178,7 +178,7 @@ static void loadDerivations(EvalState & state, Path nixExprPath,
Value vRoot;
loadSourceExpr(state, nixExprPath, vRoot);
- Value & v(*findAlongAttrPath(state, pathPrefix, autoArgs, vRoot));
+ Value & v(*findAlongAttrPath(state, pathPrefix, autoArgs, vRoot).first);
getDerivations(state, v, pathPrefix, autoArgs, elems, true);
@@ -408,7 +408,7 @@ static void queryInstSources(EvalState & state,
Value vRoot;
loadSourceExpr(state, instSource.nixExprPath, vRoot);
for (auto & i : args) {
- Value & v(*findAlongAttrPath(state, i, *instSource.autoArgs, vRoot));
+ Value & v(*findAlongAttrPath(state, i, *instSource.autoArgs, vRoot).first);
getDerivations(state, v, "", *instSource.autoArgs, elems, true);
}
break;
@@ -1428,21 +1428,8 @@ static int _main(int argc, char * * argv)
if (globals.profile == "")
globals.profile = getEnv("NIX_PROFILE").value_or("");
- if (globals.profile == "") {
- Path profileLink = getHome() + "/.nix-profile";
- try {
- if (!pathExists(profileLink)) {
- replaceSymlink(
- getuid() == 0
- ? settings.nixStateDir + "/profiles/default"
- : fmt("%s/profiles/per-user/%s/profile", settings.nixStateDir, getUserName()),
- profileLink);
- }
- globals.profile = absPath(readLink(profileLink), dirOf(profileLink));
- } catch (Error &) {
- globals.profile = profileLink;
- }
- }
+ if (globals.profile == "")
+ globals.profile = getDefaultProfile();
op(globals, opFlags, opArgs);
diff --git a/src/nix-env/user-env.cc b/src/nix-env/user-env.cc
index 717431b7a..f852916d8 100644
--- a/src/nix-env/user-env.cc
+++ b/src/nix-env/user-env.cc
@@ -15,6 +15,8 @@ namespace nix {
DrvInfos queryInstalled(EvalState & state, const Path & userEnv)
{
DrvInfos elems;
+ if (pathExists(userEnv + "/manifest.json"))
+ throw Error("profile '%s' is incompatible with 'nix-env'; please use 'nix profile' instead", userEnv);
Path manifestFile = userEnv + "/manifest.nix";
if (pathExists(manifestFile)) {
Value v;
diff --git a/src/nix-instantiate/nix-instantiate.cc b/src/nix-instantiate/nix-instantiate.cc
index 5a886d69d..6c99d1181 100644
--- a/src/nix-instantiate/nix-instantiate.cc
+++ b/src/nix-instantiate/nix-instantiate.cc
@@ -9,7 +9,7 @@
#include "util.hh"
#include "store-api.hh"
#include "common-eval-args.hh"
-#include "legacy.hh"
+#include "../nix/legacy.hh"
#include