From 5987fb7459e42ee970b22a9e7d896fc415321743 Mon Sep 17 00:00:00 2001 From: squalus Date: Tue, 4 Oct 2022 00:47:43 -0700 Subject: [PATCH 001/718] Add fsync-store-paths option - Add recursiveSync function to flush a directory tree to disk - Add AutoCloseFD::startFsync to initiate an asynchronous fsync without waiting for the result - Initiate an asynchronous fsync while extracting NAR files - Implement the fsync-store-paths option in LocalStore --- src/libstore/globals.hh | 7 ++++++ src/libstore/local-store.cc | 23 +++++++++++++++---- src/libutil/archive.cc | 11 ++++++++-- src/libutil/archive.hh | 2 +- src/libutil/filesystem.cc | 44 +++++++++++++++++++++++++++++++++++++ src/libutil/util.cc | 14 +++++++++++- src/libutil/util.hh | 11 ++++++++-- 7 files changed, 102 insertions(+), 10 deletions(-) diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh index 274a15dd7..fd5cce7ad 100644 --- a/src/libstore/globals.hh +++ b/src/libstore/globals.hh @@ -234,6 +234,13 @@ public: default is `true`. )"}; + Setting fsyncStorePaths{this, false, "fsync-store-paths", + R"( + "Whether to call `fsync()` on store paths before registering them, to + flush them to disk. This improves robustness in case of system crashes, + but reduces performance. The default is `false`. + )"}; + Setting useSQLiteWAL{this, !isWSL1(), "use-sqlite-wal", "Whether SQLite should use WAL mode."}; diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index b67668e52..4bbeebc3a 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -1299,7 +1299,7 @@ void LocalStore::addToStore(const ValidPathInfo & info, Source & source, TeeSource wrapperSource { source, hashSink }; - restorePath(realPath, wrapperSource); + restorePath(realPath, wrapperSource, settings.fsyncStorePaths); auto hashResult = hashSink.finish(); @@ -1342,6 +1342,11 @@ void LocalStore::addToStore(const ValidPathInfo & info, Source & source, optimisePath(realPath, repair); // FIXME: combine with hashPath() + if (settings.fsyncStorePaths) { + recursiveSync(realPath); + syncParent(realPath); + } + registerValidPath(info); } @@ -1402,7 +1407,7 @@ StorePath LocalStore::addToStoreFromDump(Source & source0, std::string_view name tempPath = tempDir + "/x"; if (method == FileIngestionMethod::Recursive) - restorePath(tempPath, bothSource); + restorePath(tempPath, bothSource, settings.fsyncStorePaths); else writeFile(tempPath, bothSource); @@ -1434,7 +1439,7 @@ StorePath LocalStore::addToStoreFromDump(Source & source0, std::string_view name StringSource dumpSource { dump }; /* Restore from the NAR in memory. */ if (method == FileIngestionMethod::Recursive) - restorePath(realPath, dumpSource); + restorePath(realPath, dumpSource, settings.fsyncStorePaths); else writeFile(realPath, dumpSource); } else { @@ -1459,6 +1464,12 @@ StorePath LocalStore::addToStoreFromDump(Source & source0, std::string_view name info.narSize = narHash.second; info.references = references; info.ca = FixedOutputHash { .method = method, .hash = hash }; + + if (settings.fsyncStorePaths) { + recursiveSync(realPath); + syncParent(realPath); + } + registerValidPath(info); } @@ -1491,7 +1502,7 @@ StorePath LocalStore::addTextToStore( autoGC(); - writeFile(realPath, s); + writeFile(realPath, s, 0666, settings.fsyncStorePaths); canonicalisePathMetaData(realPath, {}); @@ -1505,6 +1516,10 @@ StorePath LocalStore::addTextToStore( info.narSize = sink.s.size(); info.references = references; info.ca = TextHash { .hash = hash }; + + if (settings.fsyncStorePaths) + syncParent(realPath); + registerValidPath(info); } diff --git a/src/libutil/archive.cc b/src/libutil/archive.cc index 0e2b9d12c..e85fe3d3f 100644 --- a/src/libutil/archive.cc +++ b/src/libutil/archive.cc @@ -306,6 +306,9 @@ struct RestoreSink : ParseSink { Path dstPath; AutoCloseFD fd; + bool startFsync; + + explicit RestoreSink(bool startFsync) : startFsync{startFsync} {} void createDirectory(const Path & path) override { @@ -323,6 +326,10 @@ struct RestoreSink : ParseSink void closeRegularFile() override { + /* Initiate an fsync operation without waiting for the result. The real fsync should be run before registering + a store path, but this is a performance optimization to allow the disk write to start early. */ + if (startFsync) + fd.startFsync(); /* Call close explicitly to make sure the error is checked */ fd.close(); } @@ -367,9 +374,9 @@ struct RestoreSink : ParseSink }; -void restorePath(const Path & path, Source & source) +void restorePath(const Path & path, Source & source, bool startFsync) { - RestoreSink sink; + RestoreSink sink { startFsync }; sink.dstPath = path; parseDump(sink, source); } diff --git a/src/libutil/archive.hh b/src/libutil/archive.hh index e42dea540..64b3501b6 100644 --- a/src/libutil/archive.hh +++ b/src/libutil/archive.hh @@ -95,7 +95,7 @@ struct RetrieveRegularNARSink : ParseSink void parseDump(ParseSink & sink, Source & source); -void restorePath(const Path & path, Source & source); +void restorePath(const Path & path, Source & source, bool startFsync = false); /* Read a NAR from 'source' and write it to 'sink'. */ void copyNAR(Source & source, Sink & sink); diff --git a/src/libutil/filesystem.cc b/src/libutil/filesystem.cc index 3a732cff8..5666fc809 100644 --- a/src/libutil/filesystem.cc +++ b/src/libutil/filesystem.cc @@ -1,6 +1,7 @@ #include #include #include +#include #include "finally.hh" #include "util.hh" @@ -170,4 +171,47 @@ void moveFile(const Path & oldName, const Path & newName) } } +void recursiveSync(const Path & path) +{ + /* If it's a file, just fsync and return */ + auto st = lstat(path); + if (S_ISREG(st.st_mode)) { + AutoCloseFD fd = open(path.c_str(), O_RDONLY, 0); + if (!fd) + throw SysError("opening file '%1%'", path); + fd.fsync(); + return; + } + + /* Otherwise, perform a depth-first traversal of the directory and fsync all the files */ + std::deque dirsToEnumerate; + dirsToEnumerate.push_back(path); + std::vector dirsToFsync; + while (!dirsToEnumerate.empty()) { + auto currentDir = dirsToEnumerate.back(); + dirsToEnumerate.pop_back(); + const auto dirEntries = readDirectory(currentDir); + for (const auto& dirEntry : dirEntries) { + auto entryPath = currentDir + "/" + dirEntry.name; + if (dirEntry.type == DT_DIR) { + dirsToEnumerate.emplace_back(std::move(entryPath)); + } else if (dirEntry.type == DT_REG) { + AutoCloseFD fd = open(entryPath.c_str(), O_RDONLY, 0); + if (!fd) + throw SysError("opening file '%1%'", entryPath); + fd.fsync(); + } + } + dirsToFsync.emplace_back(std::move(currentDir)); + } + + /* fsync all the directories */ + for (auto dir = dirsToFsync.rbegin(); dir != dirsToFsync.rend(); ++dir) { + AutoCloseFD fd = open(dir->c_str(), O_RDONLY, 0); + if (!fd) + throw SysError("opening directory '%1%'", *dir); + fd.fsync(); + } +} + } diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 993dc1cb6..383288667 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -838,7 +839,7 @@ void AutoCloseFD::close() } } -void AutoCloseFD::fsync() +void AutoCloseFD::fsync() const { if (fd != -1) { int result; @@ -853,6 +854,17 @@ void AutoCloseFD::fsync() } +void AutoCloseFD::startFsync() const +{ +#if __linux__ + if (fd != -1) { + /* Ignore failure, since fsync must be run later anyway. This is just a performance optimization. */ + ::sync_file_range(fd, 0, 0, SYNC_FILE_RANGE_WRITE); + } +#endif +} + + AutoCloseFD::operator bool() const { return fd != -1; diff --git a/src/libutil/util.hh b/src/libutil/util.hh index 9b149de80..ea83351a7 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -119,9 +119,12 @@ void writeFile(const Path & path, std::string_view s, mode_t mode = 0666, bool s void writeFile(const Path & path, Source & source, mode_t mode = 0666, bool sync = false); -/* Flush a file's parent directory to disk */ +/* Flush a path's parent directory to disk */ void syncParent(const Path & path); +/* Flush a file or entire directory tree to disk */ +void recursiveSync(const Path & path); + /* Read a line from a file descriptor. */ std::string readLine(int fd); @@ -234,7 +237,11 @@ public: explicit operator bool() const; int release(); void close(); - void fsync(); + /* Perform a blocking fsync operation */ + void fsync() const; + /* Asynchronously flush to disk without blocking, if available on the platform. This is just a performance + * optimization, and fsync must be run later even if this is called. */ + void startFsync() const; }; From dc3ccf02bfd4d359228b54f5c24ae2b6caf6428e Mon Sep 17 00:00:00 2001 From: Brian McGee Date: Mon, 31 Jul 2023 18:40:45 +0100 Subject: [PATCH 002/718] base64Decode: clearer error message when an invalid character is detected Output the offending string in its entirety to provide context. Closes #8479 --- src/libutil/util.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 26f9dc8a8..952015b0c 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -1618,8 +1618,9 @@ std::string base64Decode(std::string_view s) if (c == '\n') continue; char digit = base64DecodeChars[(unsigned char) c]; - if (digit == npos) - throw Error("invalid character in Base64 string: '%c'", c); + if (digit == npos) { + throw Error("invalid character in Base64 string: '%c' in '%s'", c, s.data()); + } bits += 6; d = d << 6 | digit; From ff107d9d03246ea8c15bbea7647e60bba65e9643 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 26 Apr 2024 16:05:03 +0200 Subject: [PATCH 003/718] Input::fetchToStore(): Don't try to substitute Having a narHash doesn't mean that we have the other attributes returned by the fetcher (such as lastModified or rev). For instance, $ nix flake metadata github:NixOS/patchelf/7c2f768bf9601268a4e71c2ebe91e2011918a70f Last modified: 2024-01-15 10:51:22 but $ nix flake metadata github:NixOS/patchelf/7c2f768bf9601268a4e71c2ebe91e2011918a70f?narHash=sha256-PPXqKY2hJng4DBVE0I4xshv/vGLUskL7jl53roB8UdU%3D (does not print a "Last modified") The latter only happens if the store path already exists or is substitutable, which made this impure behaviour unpredictable. Fixes #10601. --- src/libfetchers/fetchers.cc | 18 ------------------ tests/functional/tarball.sh | 3 --- 2 files changed, 21 deletions(-) diff --git a/src/libfetchers/fetchers.cc b/src/libfetchers/fetchers.cc index 0577b8d9d..a92b1e5ed 100644 --- a/src/libfetchers/fetchers.cc +++ b/src/libfetchers/fetchers.cc @@ -167,24 +167,6 @@ std::pair Input::fetchToStore(ref store) const if (!scheme) throw Error("cannot fetch unsupported input '%s'", attrsToJSON(toAttrs())); - /* The tree may already be in the Nix store, or it could be - substituted (which is often faster than fetching from the - original source). So check that. */ - if (getNarHash()) { - try { - auto storePath = computeStorePath(*store); - - store->ensurePath(storePath); - - debug("using substituted/cached input '%s' in '%s'", - to_string(), store->printStorePath(storePath)); - - return {std::move(storePath), *this}; - } catch (Error & e) { - debug("substitution of input '%s' failed: %s", to_string(), e.what()); - } - } - auto [storePath, input] = [&]() -> std::pair { try { auto [accessor, final] = getAccessorUnchecked(store); diff --git a/tests/functional/tarball.sh b/tests/functional/tarball.sh index 062f27ad6..158a73f55 100644 --- a/tests/functional/tarball.sh +++ b/tests/functional/tarball.sh @@ -33,9 +33,6 @@ test_tarball() { nix-build -o $TEST_ROOT/result -E "import (fetchTree file://$tarball)" nix-build -o $TEST_ROOT/result -E "import (fetchTree { type = \"tarball\"; url = file://$tarball; })" nix-build -o $TEST_ROOT/result -E "import (fetchTree { type = \"tarball\"; url = file://$tarball; narHash = \"$hash\"; })" - # Do not re-fetch paths already present - nix-build -o $TEST_ROOT/result -E "import (fetchTree { type = \"tarball\"; url = file:///does-not-exist/must-remain-unused/$tarball; narHash = \"$hash\"; })" - expectStderr 102 nix-build -o $TEST_ROOT/result -E "import (fetchTree { type = \"tarball\"; url = file://$tarball; narHash = \"sha256-xdKv2pq/IiwLSnBBJXW8hNowI4MrdZfW+SYqDQs7Tzc=\"; })" | grep 'NAR hash mismatch in input' [[ $(nix eval --impure --expr "(fetchTree file://$tarball).lastModified") = 1000000000 ]] From b2be6fed8600ee48c05cc9643c101d5eab4a5727 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 23 Apr 2024 16:00:52 +0200 Subject: [PATCH 004/718] Improve support for subflakes Subflakes are flakes in the same tree, accessed in flake inputs via relative paths (e.g. `inputs.foo.url = "path:./subdir"`). Previously these didn't work very well because they would be separately copied to the store, which is inefficient and makes references to parent directories tricky or impossible. Furthermore, they had their own NAR hash in the lock file, which is superfluous since the parent is already locked. Now subflakes are accessed via the accessor of the calling flake. This avoids the unnecessary copy and makes it possible for subflakes to depend on flakes in a parent directory (so long as they're in the same tree). Lock file nodes for relative flake inputs now have a new `parent` field: { "locked": { "path": "./subdir", "type": "path" }, "original": { "path": "./subdir", "type": "path" }, "parent": [ "foo", "bar" ] } which denotes that `./subdir` is to be interpreted relative to the directory of the `bar` input of the `foo` input of the root flake. Extracted from the lazy-trees branch. --- src/libexpr/flake/call-flake.nix | 7 + src/libexpr/flake/flake.cc | 160 +++++++++++++++------- src/libexpr/flake/flakeref.cc | 68 +++++---- src/libexpr/flake/flakeref.hh | 6 +- src/libexpr/flake/lockfile.cc | 9 +- src/libexpr/flake/lockfile.hh | 12 +- src/libexpr/primops/fetchTree.cc | 5 +- src/libfetchers/fetchers.cc | 6 + src/libfetchers/fetchers.hh | 14 +- src/libfetchers/path.cc | 25 +--- src/nix/flake.md | 25 +++- tests/functional/flakes/follow-paths.sh | 25 +++- tests/functional/flakes/relative-paths.sh | 89 ++++++++++++ tests/functional/local.mk | 1 + 14 files changed, 332 insertions(+), 120 deletions(-) create mode 100644 tests/functional/flakes/relative-paths.sh diff --git a/src/libexpr/flake/call-flake.nix b/src/libexpr/flake/call-flake.nix index a411564df..43ecb7f15 100644 --- a/src/libexpr/flake/call-flake.nix +++ b/src/libexpr/flake/call-flake.nix @@ -38,10 +38,17 @@ let (key: node: let + parentNode = allNodes.${getInputByPath lockFile.root node.parent}; + sourceInfo = if overrides ? ${key} then overrides.${key}.sourceInfo + else if node.locked.type == "path" && builtins.substring 0 1 node.locked.path != "/" + then + parentNode.sourceInfo // { + outPath = parentNode.sourceInfo.outPath + ("/" + node.locked.path); + } else # FIXME: remove obsolete node.info. fetchTree (node.info or {} // removeAttrs node.locked ["dir"]); diff --git a/src/libexpr/flake/flake.cc b/src/libexpr/flake/flake.cc index 3af9ef14e..d4cabe68f 100644 --- a/src/libexpr/flake/flake.cc +++ b/src/libexpr/flake/flake.cc @@ -93,12 +93,17 @@ static void expectType(EvalState & state, ValueType type, } static std::map parseFlakeInputs( - EvalState & state, Value * value, const PosIdx pos, - const std::optional & baseDir, InputPath lockRootPath); + EvalState & state, + Value * value, + const PosIdx pos, + InputPath lockRootPath); -static FlakeInput parseFlakeInput(EvalState & state, - const std::string & inputName, Value * value, const PosIdx pos, - const std::optional & baseDir, InputPath lockRootPath) +static FlakeInput parseFlakeInput( + EvalState & state, + const std::string & inputName, + Value * value, + const PosIdx pos, + InputPath lockRootPath) { expectType(state, nAttrs, *value, pos); @@ -122,7 +127,7 @@ static FlakeInput parseFlakeInput(EvalState & state, expectType(state, nBool, *attr.value, attr.pos); input.isFlake = attr.value->boolean(); } else if (attr.name == sInputs) { - input.overrides = parseFlakeInputs(state, attr.value, attr.pos, baseDir, lockRootPath); + input.overrides = parseFlakeInputs(state, attr.value, attr.pos, lockRootPath); } else if (attr.name == sFollows) { expectType(state, nString, *attr.value, attr.pos); auto follows(parseInputPath(attr.value->c_str())); @@ -173,7 +178,7 @@ static FlakeInput parseFlakeInput(EvalState & state, if (!attrs.empty()) throw Error("unexpected flake input attribute '%s', at %s", attrs.begin()->first, state.positions[pos]); if (url) - input.ref = parseFlakeRef(*url, baseDir, true, input.isFlake); + input.ref = parseFlakeRef(*url, {}, true, input.isFlake, true); } if (!input.follows && !input.ref) @@ -183,8 +188,10 @@ static FlakeInput parseFlakeInput(EvalState & state, } static std::map parseFlakeInputs( - EvalState & state, Value * value, const PosIdx pos, - const std::optional & baseDir, InputPath lockRootPath) + EvalState & state, + Value * value, + const PosIdx pos, + InputPath lockRootPath) { std::map inputs; @@ -196,7 +203,6 @@ static std::map parseFlakeInputs( state.symbols[inputAttr.name], inputAttr.value, inputAttr.pos, - baseDir, lockRootPath)); } @@ -232,7 +238,7 @@ static Flake readFlake( auto sInputs = state.symbols.create("inputs"); if (auto inputs = vInfo.attrs()->get(sInputs)) - flake.inputs = parseFlakeInputs(state, inputs->value, inputs->pos, flakePath.parent().path.abs(), lockRootPath); // FIXME + flake.inputs = parseFlakeInputs(state, inputs->value, inputs->pos, lockRootPath); auto sOutputs = state.symbols.create("outputs"); @@ -366,13 +372,29 @@ LockedFlake lockFlake( debug("old lock file: %s", oldLockFile); - std::map overrides; + struct Override + { + FlakeInput input; + SourcePath sourcePath; + std::optional parentPath; // FIXME: rename to inputPathPrefix? + }; + + std::map overrides; std::set explicitCliOverrides; std::set overridesUsed, updatesUsed; std::map, SourcePath> nodePaths; for (auto & i : lockFlags.inputOverrides) { - overrides.insert_or_assign(i.first, FlakeInput { .ref = i.second }); + overrides.emplace( + i.first, + Override { + .input = FlakeInput { .ref = i.second }, + /* Note: any relative overrides + (e.g. `--override-input B/C "path:./foo/bar"`) + are interpreted relative to the top-level + flake. */ + .sourcePath = flake.path, + }); explicitCliOverrides.insert(i.first); } @@ -386,7 +408,7 @@ LockedFlake lockFlake( const InputPath & inputPathPrefix, std::shared_ptr oldNode, const InputPath & lockRootPath, - const Path & parentPath, + const SourcePath & sourcePath, bool trustLock)> computeLocks; @@ -402,7 +424,8 @@ LockedFlake lockFlake( copied. */ std::shared_ptr oldNode, const InputPath & lockRootPath, - const Path & parentPath, + /* The source path of this node's flake. */ + const SourcePath & sourcePath, bool trustLock) { debug("computing lock file node '%s'", printInputPath(inputPathPrefix)); @@ -414,7 +437,12 @@ LockedFlake lockFlake( auto inputPath(inputPathPrefix); inputPath.push_back(id); inputPath.push_back(idOverride); - overrides.insert_or_assign(inputPath, inputOverride); + overrides.emplace(inputPath, + Override { + .input = inputOverride, + .sourcePath = sourcePath, + .parentPath = inputPathPrefix // FIXME: should this be inputPath? + }); } } @@ -446,13 +474,18 @@ LockedFlake lockFlake( auto i = overrides.find(inputPath); bool hasOverride = i != overrides.end(); bool hasCliOverride = explicitCliOverrides.contains(inputPath); - if (hasOverride) { + if (hasOverride) overridesUsed.insert(inputPath); - // Respect the “flakeness” of the input even if we - // override it - i->second.isFlake = input2.isFlake; - } - auto & input = hasOverride ? i->second : input2; + auto input = hasOverride ? i->second.input : input2; + + /* Resolve relative 'path:' inputs relative to + the source path of the overrider. */ + auto overridenSourcePath = hasOverride ? i->second.sourcePath : sourcePath; + + /* Respect the "flakeness" of the input even if we + override it. */ + if (hasOverride) + input.isFlake = input2.isFlake; /* Resolve 'follows' later (since it may refer to an input path we haven't processed yet. */ @@ -468,6 +501,33 @@ LockedFlake lockFlake( assert(input.ref); + auto overridenParentPath = + input.ref->input.isRelative() + ? std::optional(hasOverride ? i->second.parentPath : inputPathPrefix) + : std::nullopt; + + auto resolveRelativePath = [&]() -> std::optional + { + if (auto relativePath = input.ref->input.isRelative()) { + return SourcePath { + overridenSourcePath.accessor, + CanonPath(*relativePath, overridenSourcePath.path.parent().value()) + }; + } else + return std::nullopt; + }; + + /* Get the input flake, resolve 'path:./...' + flakerefs relative to the parent flake. */ + auto getInputFlake = [&]() + { + if (auto resolvedPath = resolveRelativePath()) { + return readFlake(state, *input.ref, *input.ref, *input.ref, *resolvedPath, inputPath); + } else { + return getFlake(state, *input.ref, useRegistries, flakeCache, inputPath); + } + }; + /* Do we have an entry in the existing lock file? And the input is not in updateInputs? */ std::shared_ptr oldLock; @@ -481,6 +541,7 @@ LockedFlake lockFlake( if (oldLock && oldLock->originalRef == *input.ref + && oldLock->parentPath == overridenParentPath && !hasCliOverride) { debug("keeping existing input '%s'", inputPathS); @@ -489,7 +550,10 @@ LockedFlake lockFlake( didn't change and there is no override from a higher level flake. */ auto childNode = make_ref( - oldLock->lockedRef, oldLock->originalRef, oldLock->isFlake); + oldLock->lockedRef, + oldLock->originalRef, + oldLock->isFlake, + oldLock->parentPath); node->inputs.insert_or_assign(id, childNode); @@ -541,11 +605,15 @@ LockedFlake lockFlake( } if (mustRefetch) { - auto inputFlake = getFlake(state, oldLock->lockedRef, false, flakeCache, inputPath); + auto inputFlake = getInputFlake(); nodePaths.emplace(childNode, inputFlake.path.parent()); - computeLocks(inputFlake.inputs, childNode, inputPath, oldLock, lockRootPath, parentPath, false); + computeLocks(inputFlake.inputs, childNode, inputPath, oldLock, lockRootPath, inputFlake.path, false); } else { - computeLocks(fakeInputs, childNode, inputPath, oldLock, lockRootPath, parentPath, true); + // FIXME: sourcePath is wrong here, we + // should pass a lambda that lazily + // fetches the parent flake if needed + // (i.e. getInputFlake()). + computeLocks(fakeInputs, childNode, inputPath, oldLock, lockRootPath, sourcePath, true); } } else { @@ -553,7 +621,9 @@ LockedFlake lockFlake( this input. */ debug("creating new input '%s'", inputPathS); - if (!lockFlags.allowUnlocked && !input.ref->input.isLocked()) + if (!lockFlags.allowUnlocked + && !input.ref->input.isLocked() + && !input.ref->input.isRelative()) throw Error("cannot update unlocked flake input '%s' in pure mode", inputPathS); /* Note: in case of an --override-input, we use @@ -566,17 +636,9 @@ LockedFlake lockFlake( auto ref = (input2.ref && explicitCliOverrides.contains(inputPath)) ? *input2.ref : *input.ref; if (input.isFlake) { - Path localPath = parentPath; - FlakeRef localRef = *input.ref; + auto inputFlake = getInputFlake(); - // If this input is a path, recurse it down. - // This allows us to resolve path inputs relative to the current flake. - if (localRef.input.getType() == "path") - localPath = absPath(*input.ref->input.getSourcePath(), parentPath); - - auto inputFlake = getFlake(state, localRef, useRegistries, flakeCache, inputPath); - - auto childNode = make_ref(inputFlake.lockedRef, ref); + auto childNode = make_ref(inputFlake.lockedRef, ref, true, overridenParentPath); node->inputs.insert_or_assign(id, childNode); @@ -598,17 +660,26 @@ LockedFlake lockFlake( ? std::dynamic_pointer_cast(oldLock) : readLockFile(inputFlake.lockFilePath()).root.get_ptr(), oldLock ? lockRootPath : inputPath, - localPath, + inputFlake.path, false); } else { - auto [storePath, resolvedRef, lockedRef] = fetchOrSubstituteTree( - state, *input.ref, useRegistries, flakeCache); + auto [path, lockedRef] = [&]() -> std::tuple + { + // Handle non-flake 'path:./...' inputs. + if (auto resolvedPath = resolveRelativePath()) { + return {*resolvedPath, *input.ref}; + } else { + auto [storePath, resolvedRef, lockedRef] = fetchOrSubstituteTree( + state, *input.ref, useRegistries, flakeCache); + return {state.rootPath(state.store->toRealPath(storePath)), lockedRef}; + } + }(); - auto childNode = make_ref(lockedRef, ref, false); + auto childNode = make_ref(lockedRef, ref, false, overridenParentPath); - nodePaths.emplace(childNode, state.rootPath(state.store->toRealPath(storePath))); + nodePaths.emplace(childNode, path); node->inputs.insert_or_assign(id, childNode); } @@ -621,9 +692,6 @@ LockedFlake lockFlake( } }; - // Bring in the current ref for relative path resolution if we have it - auto parentPath = flake.path.parent().path.abs(); - nodePaths.emplace(newLockFile.root, flake.path.parent()); computeLocks( @@ -632,7 +700,7 @@ LockedFlake lockFlake( {}, lockFlags.recreateLockFile ? nullptr : oldLockFile.root.get_ptr(), {}, - parentPath, + flake.path, false); for (auto & i : lockFlags.inputOverrides) diff --git a/src/libexpr/flake/flakeref.cc b/src/libexpr/flake/flakeref.cc index 6e4aad64d..bac237a2a 100644 --- a/src/libexpr/flake/flakeref.cc +++ b/src/libexpr/flake/flakeref.cc @@ -51,9 +51,10 @@ FlakeRef parseFlakeRef( const std::string & url, const std::optional & baseDir, bool allowMissing, - bool isFlake) + bool isFlake, + bool allowRelative) { - auto [flakeRef, fragment] = parseFlakeRefWithFragment(url, baseDir, allowMissing, isFlake); + auto [flakeRef, fragment] = parseFlakeRefWithFragment(url, baseDir, allowMissing, isFlake, allowRelative); if (fragment != "") throw Error("unexpected fragment '%s' in flake reference '%s'", fragment, url); return flakeRef; @@ -69,11 +70,25 @@ std::optional maybeParseFlakeRef( } } +static std::pair fromParsedURL( + ParsedURL && parsedURL, + bool isFlake) +{ + auto dir = getOr(parsedURL.query, "dir", ""); + parsedURL.query.erase("dir"); + + std::string fragment; + std::swap(fragment, parsedURL.fragment); + + return std::make_pair(FlakeRef(fetchers::Input::fromURL(parsedURL, isFlake), dir), fragment); +} + std::pair parsePathFlakeRefWithFragment( const std::string & url, const std::optional & baseDir, bool allowMissing, - bool isFlake) + bool isFlake, + bool allowRelative) { std::string path = url; std::string fragment = ""; @@ -90,7 +105,7 @@ std::pair parsePathFlakeRefWithFragment( fragment = percentDecode(url.substr(fragmentStart+1)); } if (pathEnd != std::string::npos && fragmentStart != std::string::npos) { - query = decodeQuery(url.substr(pathEnd+1, fragmentStart-pathEnd-1)); + query = decodeQuery(url.substr(pathEnd + 1, fragmentStart - pathEnd - 1)); } if (baseDir) { @@ -154,6 +169,7 @@ std::pair parsePathFlakeRefWithFragment( .authority = "", .path = flakeRoot, .query = query, + .fragment = fragment, }; if (subdir != "") { @@ -165,9 +181,7 @@ std::pair parsePathFlakeRefWithFragment( if (pathExists(flakeRoot + "/.git/shallow")) parsedURL.query.insert_or_assign("shallow", "1"); - return std::make_pair( - FlakeRef(fetchers::Input::fromURL(parsedURL), getOr(parsedURL.query, "dir", "")), - fragment); + return fromParsedURL(std::move(parsedURL), isFlake); } subdir = std::string(baseNameOf(flakeRoot)) + (subdir.empty() ? "" : "/" + subdir); @@ -176,25 +190,30 @@ std::pair parsePathFlakeRefWithFragment( } } else { - if (!hasPrefix(path, "/")) + if (!allowRelative && !hasPrefix(path, "/")) throw BadURL("flake reference '%s' is not an absolute path", url); - path = canonPath(path + "/" + getOr(query, "dir", "")); } fetchers::Attrs attrs; attrs.insert_or_assign("type", "path"); attrs.insert_or_assign("path", path); - return std::make_pair(FlakeRef(fetchers::Input::fromAttrs(std::move(attrs)), ""), fragment); -}; - + return fromParsedURL({ + .url = path, + .base = path, + .scheme = "path", + .authority = "", + .path = path, + .query = query, + .fragment = fragment + }, isFlake); +} /* Check if 'url' is a flake ID. This is an abbreviated syntax for 'flake:?ref=&rev='. */ std::optional> parseFlakeIdRef( const std::string & url, - bool isFlake -) + bool isFlake) { std::smatch match; @@ -223,32 +242,21 @@ std::optional> parseFlakeIdRef( std::optional> parseURLFlakeRef( const std::string & url, const std::optional & baseDir, - bool isFlake -) + bool isFlake) { - ParsedURL parsedURL; try { - parsedURL = parseURL(url); + return fromParsedURL(parseURL(url), isFlake); } catch (BadURL &) { return std::nullopt; } - - std::string fragment; - std::swap(fragment, parsedURL.fragment); - - auto input = fetchers::Input::fromURL(parsedURL, isFlake); - input.parent = baseDir; - - return std::make_pair( - FlakeRef(std::move(input), getOr(parsedURL.query, "dir", "")), - fragment); } std::pair parseFlakeRefWithFragment( const std::string & url, const std::optional & baseDir, bool allowMissing, - bool isFlake) + bool isFlake, + bool allowRelative) { using namespace fetchers; @@ -259,7 +267,7 @@ std::pair parseFlakeRefWithFragment( } else if (auto res = parseURLFlakeRef(url, baseDir, isFlake)) { return *res; } else { - return parsePathFlakeRefWithFragment(url, baseDir, allowMissing, isFlake); + return parsePathFlakeRefWithFragment(url, baseDir, allowMissing, isFlake, allowRelative); } } diff --git a/src/libexpr/flake/flakeref.hh b/src/libexpr/flake/flakeref.hh index 04c812ed0..ea6c4e4d7 100644 --- a/src/libexpr/flake/flakeref.hh +++ b/src/libexpr/flake/flakeref.hh @@ -75,7 +75,8 @@ FlakeRef parseFlakeRef( const std::string & url, const std::optional & baseDir = {}, bool allowMissing = false, - bool isFlake = true); + bool isFlake = true, + bool allowRelative = false); /** * @param baseDir Optional [base directory](https://nixos.org/manual/nix/unstable/glossary#gloss-base-directory) @@ -90,7 +91,8 @@ std::pair parseFlakeRefWithFragment( const std::string & url, const std::optional & baseDir = {}, bool allowMissing = false, - bool isFlake = true); + bool isFlake = true, + bool allowRelative = false); /** * @param baseDir Optional [base directory](https://nixos.org/manual/nix/unstable/glossary#gloss-base-directory) diff --git a/src/libexpr/flake/lockfile.cc b/src/libexpr/flake/lockfile.cc index d252214dd..2884ca262 100644 --- a/src/libexpr/flake/lockfile.cc +++ b/src/libexpr/flake/lockfile.cc @@ -36,8 +36,9 @@ LockedNode::LockedNode(const nlohmann::json & json) : lockedRef(getFlakeRef(json, "locked", "info")) // FIXME: remove "info" , originalRef(getFlakeRef(json, "original", nullptr)) , isFlake(json.find("flake") != json.end() ? (bool) json["flake"] : true) + , parentPath(json.find("parent") != json.end() ? (std::optional) json["parent"] : std::nullopt) { - if (!lockedRef.input.isLocked()) + if (!lockedRef.input.isLocked() && !lockedRef.input.isRelative()) throw Error("lock file contains unlocked input '%s'", fetchers::attrsToJSON(lockedRef.input.toAttrs())); } @@ -184,6 +185,8 @@ std::pair LockFile::toJSON() const n["locked"] = fetchers::attrsToJSON(lockedNode->lockedRef.toAttrs()); if (!lockedNode->isFlake) n["flake"] = false; + if (lockedNode->parentPath) + n["parent"] = *lockedNode->parentPath; } nodes[key] = std::move(n); @@ -230,7 +233,9 @@ std::optional LockFile::isUnlocked() const for (auto & i : nodes) { if (i == ref(root)) continue; auto node = i.dynamic_pointer_cast(); - if (node && !node->lockedRef.input.isLocked()) + if (node + && !node->lockedRef.input.isLocked() + && !node->lockedRef.input.isRelative()) return node->lockedRef; } diff --git a/src/libexpr/flake/lockfile.hh b/src/libexpr/flake/lockfile.hh index 7e62e6d09..aad805baf 100644 --- a/src/libexpr/flake/lockfile.hh +++ b/src/libexpr/flake/lockfile.hh @@ -38,11 +38,19 @@ struct LockedNode : Node FlakeRef lockedRef, originalRef; bool isFlake = true; + /* The node relative to which relative source paths + (e.g. 'path:../foo') are interpreted. */ + std::optional parentPath; + LockedNode( const FlakeRef & lockedRef, const FlakeRef & originalRef, - bool isFlake = true) - : lockedRef(lockedRef), originalRef(originalRef), isFlake(isFlake) + bool isFlake = true, + std::optional parentPath = {}) + : lockedRef(lockedRef) + , originalRef(originalRef) + , isFlake(isFlake) + , parentPath(parentPath) { } LockedNode(const nlohmann::json & json); diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc index e27f30512..1c5cd4ec2 100644 --- a/src/libexpr/primops/fetchTree.cc +++ b/src/libexpr/primops/fetchTree.cc @@ -31,9 +31,8 @@ void emitTreeAttrs( // FIXME: support arbitrary input attributes. - auto narHash = input.getNarHash(); - assert(narHash); - attrs.alloc("narHash").mkString(narHash->to_string(HashFormat::SRI, true)); + if (auto narHash = input.getNarHash()) + attrs.alloc("narHash").mkString(narHash->to_string(HashFormat::SRI, true)); if (input.getType() == "git") attrs.alloc("submodules").mkBool( diff --git a/src/libfetchers/fetchers.cc b/src/libfetchers/fetchers.cc index 73923907c..73cb4fea3 100644 --- a/src/libfetchers/fetchers.cc +++ b/src/libfetchers/fetchers.cc @@ -141,6 +141,12 @@ bool Input::isLocked() const return scheme && scheme->isLocked(*this); } +std::optional Input::isRelative() const +{ + assert(scheme); + return scheme->isRelative(*this); +} + Attrs Input::toAttrs() const { return attrs; diff --git a/src/libfetchers/fetchers.hh b/src/libfetchers/fetchers.hh index 551be9a1f..66cac7064 100644 --- a/src/libfetchers/fetchers.hh +++ b/src/libfetchers/fetchers.hh @@ -31,11 +31,6 @@ struct Input std::shared_ptr scheme; // note: can be null Attrs attrs; - /** - * path of the parent of this input, used for relative path resolution - */ - std::optional parent; - public: /** * Create an `Input` from a URL. @@ -73,6 +68,12 @@ public: */ bool isLocked() const; + /** + * Only for relative path flakes, i.e. 'path:./foo', returns the + * relative path, i.e. './foo'. + */ + std::optional isRelative() const; + bool operator ==(const Input & other) const; bool contains(const Input & other) const; @@ -220,6 +221,9 @@ struct InputScheme * if there is a mismatch. */ virtual void checkLocks(const Input & specified, const Input & final) const; + + virtual std::optional isRelative(const Input & input) const + { return std::nullopt; } }; void registerInputScheme(std::shared_ptr && fetcher); diff --git a/src/libfetchers/path.cc b/src/libfetchers/path.cc index 68958d559..62500bbcb 100644 --- a/src/libfetchers/path.cc +++ b/src/libfetchers/path.cc @@ -116,31 +116,14 @@ struct PathInputScheme : InputScheme std::pair, Input> getAccessor(ref store, const Input & _input) const override { Input input(_input); - std::string absPath; auto path = getStrAttr(input.attrs, "path"); - if (path[0] != '/') { - if (!input.parent) - throw Error("cannot fetch input '%s' because it uses a relative path", input.to_string()); + auto absPath = getAbsPath(input); - auto parent = canonPath(*input.parent); - - // the path isn't relative, prefix it - absPath = nix::absPath(path, parent); - - // for security, ensure that if the parent is a store path, it's inside it - if (store->isInStore(parent)) { - auto storePath = store->printStorePath(store->toStorePath(parent).first); - if (!isDirOrInDir(absPath, storePath)) - throw BadStorePath("relative path '%s' points outside of its parent's store path '%s'", path, storePath); - } - } else - absPath = path; - - Activity act(*logger, lvlTalkative, actUnknown, fmt("copying '%s'", absPath)); + Activity act(*logger, lvlTalkative, actUnknown, fmt("copying '%s' to the store", absPath)); // FIXME: check whether access to 'path' is allowed. - auto storePath = store->maybeParseStorePath(absPath); + auto storePath = store->maybeParseStorePath(absPath.abs()); if (storePath) store->addTempRoot(*storePath); @@ -149,7 +132,7 @@ struct PathInputScheme : InputScheme if (!storePath || storePath->name() != "source" || !store->isValidPath(*storePath)) { // FIXME: try to substitute storePath. auto src = sinkToSource([&](Sink & sink) { - mtime = dumpPathAndGetMtime(absPath, sink, defaultPathFilter); + mtime = dumpPathAndGetMtime(absPath.abs(), sink, defaultPathFilter); }); storePath = store->addToStoreFromDump(*src, "source"); } diff --git a/src/nix/flake.md b/src/nix/flake.md index 661dd2f73..e60abe5fc 100644 --- a/src/nix/flake.md +++ b/src/nix/flake.md @@ -195,18 +195,29 @@ Currently the `type` attribute can be one of the following: If the flake at *path* is not inside a git repository, the `path:` prefix is implied and can be omitted. - *path* generally must be an absolute path. However, on the command - line, it can be a relative path (e.g. `.` or `./foo`) which is - interpreted as relative to the current directory. In this case, it - must start with `.` to avoid ambiguity with registry lookups - (e.g. `nixpkgs` is a registry lookup; `./nixpkgs` is a relative - path). + If *path* is a relative path (i.e. if it does not start with `/`), + it is interpreted as follows: + + - If *path* is a command line argument, it is interpreted relative + to the current directory. + + - If *path* is used in a `flake.nix`, it is interpreted relative to + the directory containing that `flake.nix`. However, the resolved + path must be in the same tree. For instance, a `flake.nix` in the + root of a tree can use `path:./foo` to access the flake in + subdirectory `foo`, but `path:../bar` is illegal. + + Note that if you omit `path:`, relative paths must start with `.` to + avoid ambiguity with registry lookups (e.g. `nixpkgs` is a registry + lookup; `./nixpkgs` is a relative path). For example, these are valid path flake references: * `path:/home/user/sub/dir` * `/home/user/sub/dir` (if `dir/flake.nix` is *not* in a git repository) - * `./sub/dir` (when used on the command line and `dir/flake.nix` is *not* in a git repository) + * `path:sub/dir` + * `./sub/dir` + * `path:../parent` * `git`: Git repositories. The location of the repository is specified by the attribute `url`. diff --git a/tests/functional/flakes/follow-paths.sh b/tests/functional/flakes/follow-paths.sh index 1afd91bd2..35f52f3ba 100644 --- a/tests/functional/flakes/follow-paths.sh +++ b/tests/functional/flakes/follow-paths.sh @@ -115,7 +115,7 @@ nix flake lock $flakeFollowsA [[ $(jq -c .nodes.B.inputs.foobar $flakeFollowsA/flake.lock) = '"foobar"' ]] jq -r -c '.nodes | keys | .[]' $flakeFollowsA/flake.lock | grep "^foobar$" -# Ensure a relative path is not allowed to go outside the store path +# Check that path: inputs cannot escape from their root. cat > $flakeFollowsA/flake.nix <&1 | grep 'points outside' +expect 1 nix flake lock $flakeFollowsA 2>&1 | grep '/flakeB.*is forbidden in pure evaluation mode' +expect 1 nix flake lock --impure $flakeFollowsA 2>&1 | grep '/flakeB.*does not exist' + +# Test relative non-flake inputs. +cat > $flakeFollowsA/flake.nix < $flakeFollowsA/foo.nix + +git -C $flakeFollowsA add flake.nix foo.nix + +nix flake lock $flakeFollowsA + +[[ $(nix eval --json $flakeFollowsA#e) = 123 ]] # Non-existant follows should print a warning. cat >$flakeFollowsA/flake.nix < $rootFlake/flake.nix < $subflake0/flake.nix < $subflake1/flake.nix < $subflake2/flake.nix < $rootFlake/flake.nix < Date: Fri, 17 May 2024 16:38:01 +0200 Subject: [PATCH 005/718] call-flake.nix: Fix relative path resolution `parentNode.sourceInfo.outPath` does not include the subdir of the parent flake, while `parentNode.outPath` does. So we need to use the latter. --- src/libexpr/flake/call-flake.nix | 2 +- tests/functional/flakes/relative-paths.sh | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libexpr/flake/call-flake.nix b/src/libexpr/flake/call-flake.nix index 43ecb7f15..38dc74ba1 100644 --- a/src/libexpr/flake/call-flake.nix +++ b/src/libexpr/flake/call-flake.nix @@ -47,7 +47,7 @@ let else if node.locked.type == "path" && builtins.substring 0 1 node.locked.path != "/" then parentNode.sourceInfo // { - outPath = parentNode.sourceInfo.outPath + ("/" + node.locked.path); + outPath = parentNode.outPath + ("/" + node.locked.path); } else # FIXME: remove obsolete node.info. diff --git a/tests/functional/flakes/relative-paths.sh b/tests/functional/flakes/relative-paths.sh index cecda44d4..38987d6af 100644 --- a/tests/functional/flakes/relative-paths.sh +++ b/tests/functional/flakes/relative-paths.sh @@ -63,6 +63,10 @@ git -C $rootFlake add flake.nix sub2/flake.nix [[ $(nix eval $subflake2#y) = 15 ]] +# Make sure that this still works after commiting the lock file. +git -C $rootFlake add sub2/flake.lock +[[ $(nix eval $subflake2#y) = 15 ]] + # Make sure there are no content locks for relative path flakes. (! grep "$TEST_ROOT" $subflake2/flake.lock) (! grep "$NIX_STORE_DIR" $subflake2/flake.lock) From 3180671cabeb6a6010057770731e12761ed5666c Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 17 May 2024 19:49:40 +0200 Subject: [PATCH 006/718] Allow the 'url' flake input attribute to be a path literal https://github.com/NixOS/nix/pull/10089#issuecomment-1978133326 --- src/libexpr/flake/flake.cc | 34 +++++++++++++++++------ tests/functional/flakes/relative-paths.sh | 4 +-- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/libexpr/flake/flake.cc b/src/libexpr/flake/flake.cc index d4cabe68f..1401f5dda 100644 --- a/src/libexpr/flake/flake.cc +++ b/src/libexpr/flake/flake.cc @@ -96,14 +96,16 @@ static std::map parseFlakeInputs( EvalState & state, Value * value, const PosIdx pos, - InputPath lockRootPath); + InputPath lockRootPath, + const SourcePath & flakeDir); static FlakeInput parseFlakeInput( EvalState & state, const std::string & inputName, Value * value, const PosIdx pos, - InputPath lockRootPath) + InputPath lockRootPath, + const SourcePath & flakeDir) { expectType(state, nAttrs, *value, pos); @@ -120,14 +122,25 @@ static FlakeInput parseFlakeInput( for (auto & attr : *value->attrs()) { try { if (attr.name == sUrl) { - expectType(state, nString, *attr.value, attr.pos); - url = attr.value->string_view(); + forceTrivialValue(state, *attr.value, pos); + if (attr.value->type() == nString) + url = attr.value->string_view(); + else if (attr.value->type() == nPath) { + auto path = attr.value->path(); + if (path.accessor != flakeDir.accessor) + throw Error("input path '%s' at %s must be in the same source tree as %s", + path, state.positions[attr.pos], flakeDir); + url = "path:" + flakeDir.path.makeRelative(path.path); + } + else + throw Error("expected a string or a path but got %s at %s", + showType(attr.value->type()), state.positions[attr.pos]); attrs.emplace("url", *url); } else if (attr.name == sFlake) { expectType(state, nBool, *attr.value, attr.pos); input.isFlake = attr.value->boolean(); } else if (attr.name == sInputs) { - input.overrides = parseFlakeInputs(state, attr.value, attr.pos, lockRootPath); + input.overrides = parseFlakeInputs(state, attr.value, attr.pos, lockRootPath, flakeDir); } else if (attr.name == sFollows) { expectType(state, nString, *attr.value, attr.pos); auto follows(parseInputPath(attr.value->c_str())); @@ -191,7 +204,8 @@ static std::map parseFlakeInputs( EvalState & state, Value * value, const PosIdx pos, - InputPath lockRootPath) + InputPath lockRootPath, + const SourcePath & flakeDir) { std::map inputs; @@ -203,7 +217,8 @@ static std::map parseFlakeInputs( state.symbols[inputAttr.name], inputAttr.value, inputAttr.pos, - lockRootPath)); + lockRootPath, + flakeDir)); } return inputs; @@ -217,7 +232,8 @@ static Flake readFlake( const SourcePath & rootDir, const InputPath & lockRootPath) { - auto flakePath = rootDir / CanonPath(resolvedRef.subdir) / "flake.nix"; + auto flakeDir = rootDir / CanonPath(resolvedRef.subdir); + auto flakePath = flakeDir / "flake.nix"; // NOTE evalFile forces vInfo to be an attrset because mustBeTrivial is true. Value vInfo; @@ -238,7 +254,7 @@ static Flake readFlake( auto sInputs = state.symbols.create("inputs"); if (auto inputs = vInfo.attrs()->get(sInputs)) - flake.inputs = parseFlakeInputs(state, inputs->value, inputs->pos, lockRootPath); + flake.inputs = parseFlakeInputs(state, inputs->value, inputs->pos, lockRootPath, flakeDir); auto sOutputs = state.symbols.create("outputs"); diff --git a/tests/functional/flakes/relative-paths.sh b/tests/functional/flakes/relative-paths.sh index 38987d6af..3e4c97cc4 100644 --- a/tests/functional/flakes/relative-paths.sh +++ b/tests/functional/flakes/relative-paths.sh @@ -12,7 +12,7 @@ mkdir -p $rootFlake $subflake0 $subflake1 $subflake2 cat > $rootFlake/flake.nix < $subflake2/flake.nix < Date: Fri, 14 Jun 2024 16:30:34 +0200 Subject: [PATCH 007/718] C API: Add nix_clear_err --- src/libutil-c/nix_api_util.cc | 6 ++++++ src/libutil-c/nix_api_util.h | 29 ++++++++++++++++++++++++++--- tests/unit/libutil/nix_api_util.cc | 3 +++ 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/src/libutil-c/nix_api_util.cc b/src/libutil-c/nix_api_util.cc index 0a9b49345..c976b1815 100644 --- a/src/libutil-c/nix_api_util.cc +++ b/src/libutil-c/nix_api_util.cc @@ -57,6 +57,12 @@ nix_err nix_set_err_msg(nix_c_context * context, nix_err err, const char * msg) return err; } +void nix_clear_err(nix_c_context * context) +{ + if (context) + context->last_err_code = NIX_OK; +} + const char * nix_version_get() { return PACKAGE_VERSION; diff --git a/src/libutil-c/nix_api_util.h b/src/libutil-c/nix_api_util.h index e0ca04e69..9a9f1d98d 100644 --- a/src/libutil-c/nix_api_util.h +++ b/src/libutil-c/nix_api_util.h @@ -221,7 +221,9 @@ const char * nix_version_get(); * @param[out] n optional: a pointer to an unsigned int that is set to the * length of the error. * @return nullptr if no error message was ever set, - * a borrowed pointer to the error message otherwise. + * a borrowed pointer to the error message otherwise, which is valid + * until the next call to a Nix function, or until the context is + * destroyed. */ const char * nix_err_msg(nix_c_context * context, const nix_c_context * ctx, unsigned int * n); @@ -282,13 +284,34 @@ nix_err nix_err_code(const nix_c_context * read_context); * * All other use is internal to the API. * - * @param context context to write the error message to, or NULL + * @param context context to write the error message to, required unless C++ exceptions are supported * @param err The error code to set and return - * @param msg The error message to set. + * @param msg The error message to set. This string is copied. * @returns the error code set */ nix_err nix_set_err_msg(nix_c_context * context, nix_err err, const char * msg); +/** + * @brief Clear the error message from a nix context. + * + * This is performed implicitly by all functions that accept a context, so + * this won't be necessary in most cases. + * However, if you want to clear the error message without calling another + * function, you can use this. + * + * Example use case: a higher order function that helps with error handling, + * to make it more robust in the following scenario: + * + * 1. A previous call failed, and the error was caught and handled. + * 2. The context is reused with our error handling helper function. + * 3. The callback passed to the helper function doesn't actually make a call to + * a Nix function. + * 4. The handled error is raised again, from an unrelated call. + * + * This failure can be avoided by clearing the error message after handling it. + */ +void nix_clear_err(nix_c_context * context); + /** * @} */ diff --git a/tests/unit/libutil/nix_api_util.cc b/tests/unit/libutil/nix_api_util.cc index d2999f55b..052d0c533 100644 --- a/tests/unit/libutil/nix_api_util.cc +++ b/tests/unit/libutil/nix_api_util.cc @@ -31,6 +31,9 @@ TEST_F(nix_api_util_context, nix_context_error) } ASSERT_EQ(ctx->last_err_code, NIX_ERR_UNKNOWN); ASSERT_EQ(*ctx->last_err, err_msg_ref); + + nix_clear_err(ctx); + ASSERT_EQ(ctx->last_err_code, NIX_OK); } TEST_F(nix_api_util_context, nix_set_err_msg) From 61381c9964c69afd720264272a0f42d298d6616c Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Fri, 14 Jun 2024 16:36:23 +0200 Subject: [PATCH 008/718] C API: Make nix_err_msg treat NIX_OK as having no message The documentation "solved" this by specifying a precondition, but let's just make it more robust, and not leak irrelevant messages that might linger. We don't clear the message when clearing the status, in order to keep clearing fast; see last_err field doc. --- src/libutil-c/nix_api_util.cc | 2 +- src/libutil-c/nix_api_util_internal.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libutil-c/nix_api_util.cc b/src/libutil-c/nix_api_util.cc index c976b1815..cf468c8cd 100644 --- a/src/libutil-c/nix_api_util.cc +++ b/src/libutil-c/nix_api_util.cc @@ -112,7 +112,7 @@ const char * nix_err_msg(nix_c_context * context, const nix_c_context * read_con { if (context) context->last_err_code = NIX_OK; - if (read_context->last_err) { + if (read_context->last_err && read_context->last_err_code != NIX_OK) { if (n) *n = read_context->last_err->size(); return read_context->last_err->c_str(); diff --git a/src/libutil-c/nix_api_util_internal.h b/src/libutil-c/nix_api_util_internal.h index aa829feaf..7fa4252ac 100644 --- a/src/libutil-c/nix_api_util_internal.h +++ b/src/libutil-c/nix_api_util_internal.h @@ -10,6 +10,7 @@ struct nix_c_context { nix_err last_err_code = NIX_OK; + /** The last error message. Always check last_err_code. This may not have been cleared, so that clearing is fast. */ std::optional last_err = {}; std::optional info = {}; std::string name = ""; From caabdb06d1a8b7d75928b9c35d796a4da5355314 Mon Sep 17 00:00:00 2001 From: "Travis A. Everett" Date: Tue, 2 Jul 2024 20:55:46 -0500 Subject: [PATCH 009/718] preserve early sequoia migration script --- scripts/sequoia-nixbld-user-migration.sh | 36 ++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 scripts/sequoia-nixbld-user-migration.sh diff --git a/scripts/sequoia-nixbld-user-migration.sh b/scripts/sequoia-nixbld-user-migration.sh new file mode 100644 index 000000000..778a95688 --- /dev/null +++ b/scripts/sequoia-nixbld-user-migration.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + +((NEW_NIX_FIRST_BUILD_UID=331)) + +id_available(){ + dscl . list /Users UniqueID | grep -E '\b'"$1"'\b' >/dev/null +} + +change_nixbld_names_and_ids(){ + local name uid next_id + ((next_id=NEW_NIX_FIRST_BUILD_UID)) + echo "Attempting to migrate _nixbld users." + echo "Each _nixbld# user should have its UID moved to $next_id+" + while read -r name uid; do + echo " Checking $name (uid: $uid)" + # iterate for a clean ID + while id_available "$next_id"; do + ((next_id++)) + if ((next_id >= 400)); then + echo "We've hit UID 400 without placing all of your users :(" + echo "You should use the commands in this script as a starting" + echo "point to review your UID-space and manually move the" + echo "remaining users (or delete them, if you don't need them)." + exit 1 + fi + done + + # first 2 are cleanup, it's OK if they aren't here + sudo dscl . delete "/Users/$name" dsAttrTypeNative:_writers_passwd &>/dev/null || true + sudo dscl . change "/Users/$name" NFSHomeDirectory "/private/var/empty 1" "/var/empty" &>/dev/null || true + sudo dscl . change "/Users/$name" UniqueID "$uid" "$next_id" + echo " $name migrated to uid: $next_id" + done < <(dscl . list /Users UniqueID | grep _nixbld | sort -n -k2) +} + +change_nixbld_names_and_ids From 0194f815870ed875b791d60335be920de249a510 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 22 Jul 2024 15:10:47 +0200 Subject: [PATCH 010/718] addToStore(): Do evaluation on the main stack This hopefully avoids the need for all our Boehm GC coroutine workarounds, since the GC roots will be on the main stack of the thread. Fixes #11141. --- src/libstore/local-store.cc | 1 + src/libstore/store-api.cc | 16 +++++++++------- src/libutil/serialise.cc | 8 ++++---- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 819cee345..956a4453d 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -1245,6 +1245,7 @@ StorePath LocalStore::addToStoreFromDump( }); try { got = source.read(dumpBuffer.get() + oldSize, want); + if (!got) break; } catch (EndOfFile &) { inMemory = true; break; diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index 2c4dee518..5d6109bae 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -210,14 +210,16 @@ StorePath Store::addToStore( fsm = FileSerialisationMethod::NixArchive; break; } - auto source = sinkToSource([&](Sink & sink) { - dumpPath(path, sink, fsm, filter); + std::optional storePath; + auto sink = sourceToSink([&](Source & source) { + LengthSource lengthSource(source); + storePath = addToStoreFromDump(lengthSource, name, fsm, method, hashAlgo, references, repair); + if (lengthSource.total >= settings.warnLargePathThreshold) + warn("copied large path '%s' to the store (%s)", path, renderSize(lengthSource.total)); }); - LengthSource lengthSource(*source); - auto storePath = addToStoreFromDump(lengthSource, name, fsm, method, hashAlgo, references, repair); - if (lengthSource.total >= settings.warnLargePathThreshold) - warn("copied large path '%s' to the store (%s)", path, renderSize(lengthSource.total)); - return storePath; + dumpPath(path, *sink, fsm, filter); + sink->finish(); + return storePath.value(); } void Store::addMultipleToStore( diff --git a/src/libutil/serialise.cc b/src/libutil/serialise.cc index 36b99905a..0f2febaed 100644 --- a/src/libutil/serialise.cc +++ b/src/libutil/serialise.cc @@ -243,11 +243,11 @@ std::unique_ptr sourceToSink(std::function fun) if (!coro) { CoroutineContext ctx; coro = coro_t::push_type(VirtualStackAllocator{}, [&](coro_t::pull_type & yield) { - LambdaSource source([&](char *out, size_t out_len) { + LambdaSource source([&](char * out, size_t out_len) { if (cur.empty()) { yield(); if (yield.get()) { - return (size_t)0; + return (size_t) 0; } } @@ -271,12 +271,12 @@ std::unique_ptr sourceToSink(std::function fun) void finish() override { if (!coro) return; - if (!*coro) abort(); + //if (!*coro) abort(); { CoroutineContext ctx; (*coro)(true); } - if (*coro) abort(); + //if (*coro) abort(); } }; From 609df83c011ad74c20cd806e00d59f6ed4a580b5 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 22 Jul 2024 15:18:58 +0200 Subject: [PATCH 011/718] sourceToSink(): Throw EndOfFile --- src/libstore/local-store.cc | 1 - src/libutil/serialise.cc | 9 ++++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 956a4453d..819cee345 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -1245,7 +1245,6 @@ StorePath LocalStore::addToStoreFromDump( }); try { got = source.read(dumpBuffer.get() + oldSize, want); - if (!got) break; } catch (EndOfFile &) { inMemory = true; break; diff --git a/src/libutil/serialise.cc b/src/libutil/serialise.cc index 0f2febaed..d203a01bf 100644 --- a/src/libutil/serialise.cc +++ b/src/libutil/serialise.cc @@ -246,9 +246,8 @@ std::unique_ptr sourceToSink(std::function fun) LambdaSource source([&](char * out, size_t out_len) { if (cur.empty()) { yield(); - if (yield.get()) { - return (size_t) 0; - } + if (yield.get()) + throw EndOfFile("coroutine has finished"); } size_t n = std::min(cur.size(), out_len); @@ -271,12 +270,12 @@ std::unique_ptr sourceToSink(std::function fun) void finish() override { if (!coro) return; - //if (!*coro) abort(); + if (!*coro) abort(); { CoroutineContext ctx; (*coro)(true); } - //if (*coro) abort(); + if (*coro) abort(); } }; From ca0f7db843d2c58bb5ca7b45f2b2aa57273e5f7e Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 22 Jul 2024 15:28:21 +0200 Subject: [PATCH 012/718] Remove hacks to support evaluation from coroutines Since we're not doing this anymore. --- .../src/installation/prerequisites-source.md | 2 - src/libexpr/eval-gc.cc | 132 ------------------ src/libutil/serialise.cc | 58 +------- src/libutil/serialise.hh | 23 --- 4 files changed, 2 insertions(+), 213 deletions(-) diff --git a/doc/manual/src/installation/prerequisites-source.md b/doc/manual/src/installation/prerequisites-source.md index 4aafa6d27..c346a0a4b 100644 --- a/doc/manual/src/installation/prerequisites-source.md +++ b/doc/manual/src/installation/prerequisites-source.md @@ -39,8 +39,6 @@ `pkgconfig` and the Boehm garbage collector, and pass the flag `--enable-gc` to `configure`. - For `bdw-gc` <= 8.2.4 Nix needs a [small patch](https://github.com/NixOS/nix/blob/ac4d2e7b857acdfeac35ac8a592bdecee2d29838/boehmgc-traceable_allocator-public.diff) to be applied. - - The `boost` library of version 1.66.0 or higher. It can be obtained from the official web site . diff --git a/src/libexpr/eval-gc.cc b/src/libexpr/eval-gc.cc index ba19cd74e..4bf48194e 100644 --- a/src/libexpr/eval-gc.cc +++ b/src/libexpr/eval-gc.cc @@ -30,120 +30,6 @@ static void * oomHandler(size_t requested) throw std::bad_alloc(); } -class BoehmGCStackAllocator : public StackAllocator -{ - boost::coroutines2::protected_fixedsize_stack stack{ - // We allocate 8 MB, the default max stack size on NixOS. - // A smaller stack might be quicker to allocate but reduces the stack - // depth available for source filter expressions etc. - std::max(boost::context::stack_traits::default_size(), static_cast(8 * 1024 * 1024))}; - - // This is specific to boost::coroutines2::protected_fixedsize_stack. - // The stack protection page is included in sctx.size, so we have to - // subtract one page size from the stack size. - std::size_t pfss_usable_stack_size(boost::context::stack_context & sctx) - { - return sctx.size - boost::context::stack_traits::page_size(); - } - -public: - boost::context::stack_context allocate() override - { - auto sctx = stack.allocate(); - - // Stacks generally start at a high address and grow to lower addresses. - // Architectures that do the opposite are rare; in fact so rare that - // boost_routine does not implement it. - // So we subtract the stack size. - GC_add_roots(static_cast(sctx.sp) - pfss_usable_stack_size(sctx), sctx.sp); - return sctx; - } - - void deallocate(boost::context::stack_context sctx) override - { - GC_remove_roots(static_cast(sctx.sp) - pfss_usable_stack_size(sctx), sctx.sp); - stack.deallocate(sctx); - } -}; - -static BoehmGCStackAllocator boehmGCStackAllocator; - -/** - * When a thread goes into a coroutine, we lose its original sp until - * control flow returns to the thread. - * While in the coroutine, the sp points outside the thread stack, - * so we can detect this and push the entire thread stack instead, - * as an approximation. - * The coroutine's stack is covered by `BoehmGCStackAllocator`. - * This is not an optimal solution, because the garbage is scanned when a - * coroutine is active, for both the coroutine and the original thread stack. - * However, the implementation is quite lean, and usually we don't have active - * coroutines during evaluation, so this is acceptable. - */ -void fixupBoehmStackPointer(void ** sp_ptr, void * _pthread_id) -{ - void *& sp = *sp_ptr; - auto pthread_id = reinterpret_cast(_pthread_id); - pthread_attr_t pattr; - size_t osStackSize; - // The low address of the stack, which grows down. - void * osStackLimit; - void * osStackBase; - -# ifdef __APPLE__ - osStackSize = pthread_get_stacksize_np(pthread_id); - osStackLimit = pthread_get_stackaddr_np(pthread_id); -# else - if (pthread_attr_init(&pattr)) { - throw Error("fixupBoehmStackPointer: pthread_attr_init failed"); - } -# ifdef HAVE_PTHREAD_GETATTR_NP - if (pthread_getattr_np(pthread_id, &pattr)) { - throw Error("fixupBoehmStackPointer: pthread_getattr_np failed"); - } -# elif HAVE_PTHREAD_ATTR_GET_NP - if (!pthread_attr_init(&pattr)) { - throw Error("fixupBoehmStackPointer: pthread_attr_init failed"); - } - if (!pthread_attr_get_np(pthread_id, &pattr)) { - throw Error("fixupBoehmStackPointer: pthread_attr_get_np failed"); - } -# else -# error "Need one of `pthread_attr_get_np` or `pthread_getattr_np`" -# endif - if (pthread_attr_getstack(&pattr, &osStackLimit, &osStackSize)) { - throw Error("fixupBoehmStackPointer: pthread_attr_getstack failed"); - } - if (pthread_attr_destroy(&pattr)) { - throw Error("fixupBoehmStackPointer: pthread_attr_destroy failed"); - } -# endif - osStackBase = (char *) osStackLimit + osStackSize; - // NOTE: We assume the stack grows down, as it does on all architectures we support. - // Architectures that grow the stack up are rare. - if (sp >= osStackBase || sp < osStackLimit) { // sp is outside the os stack - sp = osStackLimit; - } -} - -/* Disable GC while this object lives. Used by CoroutineContext. - * - * Boehm keeps a count of GC_disable() and GC_enable() calls, - * and only enables GC when the count matches. - */ -class BoehmDisableGC -{ -public: - BoehmDisableGC() - { - GC_disable(); - }; - ~BoehmDisableGC() - { - GC_enable(); - }; -}; - static inline void initGCReal() { /* Initialise the Boehm garbage collector. */ @@ -164,24 +50,6 @@ static inline void initGCReal() GC_set_oom_fn(oomHandler); - StackAllocator::defaultAllocator = &boehmGCStackAllocator; - -// TODO: Remove __APPLE__ condition. -// Comment suggests an implementation that works on darwin and windows -// https://github.com/ivmai/bdwgc/issues/362#issuecomment-1936672196 -# if GC_VERSION_MAJOR >= 8 && GC_VERSION_MINOR >= 2 && GC_VERSION_MICRO >= 4 && !defined(__APPLE__) - GC_set_sp_corrector(&fixupBoehmStackPointer); - - if (!GC_get_sp_corrector()) { - printTalkative("BoehmGC on this platform does not support sp_corrector; will disable GC inside coroutines"); - /* Used to disable GC when entering coroutines on macOS */ - create_coro_gc_hook = []() -> std::shared_ptr { return std::make_shared(); }; - } -# else -# warning \ - "BoehmGC version does not support GC while coroutine exists. GC will be disabled inside coroutines. Consider updating bdw-gc to 8.2.4 or later." -# endif - /* Set the initial heap size to something fairly big (25% of physical RAM, up to a maximum of 384 MiB) so that in most cases we don't need to garbage collect at all. (Collection has a diff --git a/src/libutil/serialise.cc b/src/libutil/serialise.cc index d203a01bf..cd52fbfb4 100644 --- a/src/libutil/serialise.cc +++ b/src/libutil/serialise.cc @@ -171,55 +171,6 @@ size_t StringSource::read(char * data, size_t len) #error Coroutines are broken in this version of Boost! #endif -/* A concrete datatype allow virtual dispatch of stack allocation methods. */ -struct VirtualStackAllocator { - StackAllocator *allocator = StackAllocator::defaultAllocator; - - boost::context::stack_context allocate() { - return allocator->allocate(); - } - - void deallocate(boost::context::stack_context sctx) { - allocator->deallocate(sctx); - } -}; - - -/* This class reifies the default boost coroutine stack allocation strategy with - a virtual interface. */ -class DefaultStackAllocator : public StackAllocator { - boost::coroutines2::default_stack stack; - - boost::context::stack_context allocate() { - return stack.allocate(); - } - - void deallocate(boost::context::stack_context sctx) { - stack.deallocate(sctx); - } -}; - -static DefaultStackAllocator defaultAllocatorSingleton; - -StackAllocator *StackAllocator::defaultAllocator = &defaultAllocatorSingleton; - - -std::shared_ptr (*create_coro_gc_hook)() = []() -> std::shared_ptr { - return {}; -}; - -/* This class is used for entry and exit hooks on coroutines */ -class CoroutineContext { - /* Disable GC when entering the coroutine without the boehm patch, - * since it doesn't find the main thread stack in this case. - * std::shared_ptr performs type-erasure, so it will call the right - * deleter. */ - const std::shared_ptr coro_gc_hook = create_coro_gc_hook(); -public: - CoroutineContext() {}; - ~CoroutineContext() {}; -}; - std::unique_ptr sourceToSink(std::function fun) { struct SourceToSink : FinishSink @@ -241,8 +192,7 @@ std::unique_ptr sourceToSink(std::function fun) cur = in; if (!coro) { - CoroutineContext ctx; - coro = coro_t::push_type(VirtualStackAllocator{}, [&](coro_t::pull_type & yield) { + coro = coro_t::push_type([&](coro_t::pull_type & yield) { LambdaSource source([&](char * out, size_t out_len) { if (cur.empty()) { yield(); @@ -262,7 +212,6 @@ std::unique_ptr sourceToSink(std::function fun) if (!*coro) { abort(); } if (!cur.empty()) { - CoroutineContext ctx; (*coro)(false); } } @@ -272,7 +221,6 @@ std::unique_ptr sourceToSink(std::function fun) if (!coro) return; if (!*coro) abort(); { - CoroutineContext ctx; (*coro)(true); } if (*coro) abort(); @@ -306,8 +254,7 @@ std::unique_ptr sinkToSource( size_t read(char * data, size_t len) override { if (!coro) { - CoroutineContext ctx; - coro = coro_t::pull_type(VirtualStackAllocator{}, [&](coro_t::push_type & yield) { + coro = coro_t::pull_type([&](coro_t::push_type & yield) { LambdaSink sink([&](std::string_view data) { if (!data.empty()) yield(std::string(data)); }); @@ -319,7 +266,6 @@ std::unique_ptr sinkToSource( if (pos == cur.size()) { if (!cur.empty()) { - CoroutineContext ctx; (*coro)(); } cur = coro->get(); diff --git a/src/libutil/serialise.hh b/src/libutil/serialise.hh index 8137db5f4..a795bb088 100644 --- a/src/libutil/serialise.hh +++ b/src/libutil/serialise.hh @@ -557,27 +557,4 @@ struct FramedSink : nix::BufferedSink }; }; -/** - * Stack allocation strategy for sinkToSource. - * Mutable to avoid a boehm gc dependency in libutil. - * - * boost::context doesn't provide a virtual class, so we define our own. - */ -struct StackAllocator { - virtual boost::context::stack_context allocate() = 0; - virtual void deallocate(boost::context::stack_context sctx) = 0; - - /** - * The stack allocator to use in sinkToSource and potentially elsewhere. - * It is reassigned by the initGC() method in libexpr. - */ - static StackAllocator *defaultAllocator; -}; - -/* Disabling GC when entering a coroutine (without the boehm patch). - mutable to avoid boehm gc dependency in libutil. - */ -extern std::shared_ptr (*create_coro_gc_hook)(); - - } From b8684eb44723ad023e74a50c446f77ef56031f18 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 22 Jul 2024 20:03:29 +0200 Subject: [PATCH 013/718] sourceToSink(): Fix abort --- src/libutil/serialise.cc | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/libutil/serialise.cc b/src/libutil/serialise.cc index cd52fbfb4..8fbfe248c 100644 --- a/src/libutil/serialise.cc +++ b/src/libutil/serialise.cc @@ -218,12 +218,8 @@ std::unique_ptr sourceToSink(std::function fun) void finish() override { - if (!coro) return; - if (!*coro) abort(); - { + if (coro && *coro) (*coro)(true); - } - if (*coro) abort(); } }; From 429a197d246782e286fe7d9f6fad0b9daf2941ec Mon Sep 17 00:00:00 2001 From: Ryan Hendrickson Date: Sat, 20 Jul 2024 12:04:25 -0400 Subject: [PATCH 014/718] parser.y: use names where I'll be refactoring --- src/libexpr/parser.y | 72 ++++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index 9ad41c148..256244a75 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -180,22 +180,22 @@ expr_function $$ = me; SET_DOC_POS(me, @1); } - | '{' formals '}' ':' expr_function - { auto me = new ExprLambda(CUR_POS, state->validateFormals($2), $5); + | '{' formals '}' ':' expr_function[body] + { auto me = new ExprLambda(CUR_POS, state->validateFormals($formals), $body); $$ = me; SET_DOC_POS(me, @1); } - | '{' formals '}' '@' ID ':' expr_function + | '{' formals '}' '@' ID ':' expr_function[body] { - auto arg = state->symbols.create($5); - auto me = new ExprLambda(CUR_POS, arg, state->validateFormals($2, CUR_POS, arg), $7); + auto arg = state->symbols.create($ID); + auto me = new ExprLambda(CUR_POS, arg, state->validateFormals($formals, CUR_POS, arg), $body); $$ = me; SET_DOC_POS(me, @1); } - | ID '@' '{' formals '}' ':' expr_function + | ID '@' '{' formals '}' ':' expr_function[body] { - auto arg = state->symbols.create($1); - auto me = new ExprLambda(CUR_POS, arg, state->validateFormals($4, CUR_POS, arg), $7); + auto arg = state->symbols.create($ID); + auto me = new ExprLambda(CUR_POS, arg, state->validateFormals($formals, CUR_POS, arg), $body); $$ = me; SET_DOC_POS(me, @1); } @@ -364,50 +364,50 @@ ind_string_parts ; binds - : binds attrpath '=' expr ';' { - $$ = $1; + : binds[accum] attrpath '=' expr ';' { + $$ = $accum; - auto pos = state->at(@2); - auto exprPos = state->at(@4); + auto pos = state->at(@attrpath); + auto exprPos = state->at(@expr); { auto it = state->lexerState.positionToDocComment.find(pos); if (it != state->lexerState.positionToDocComment.end()) { - $4->setDocComment(it->second); + $expr->setDocComment(it->second); state->lexerState.positionToDocComment.emplace(exprPos, it->second); } } - state->addAttr($$, std::move(*$2), $4, pos); - delete $2; + state->addAttr($$, std::move(*$attrpath), $expr, pos); + delete $attrpath; } - | binds INHERIT attrs ';' - { $$ = $1; - for (auto & [i, iPos] : *$3) { - if ($$->attrs.find(i.symbol) != $$->attrs.end()) - state->dupAttr(i.symbol, iPos, $$->attrs[i.symbol].pos); - $$->attrs.emplace( + | binds[accum] INHERIT attrs ';' + { $$ = $accum; + for (auto & [i, iPos] : *$attrs) { + if ($accum->attrs.find(i.symbol) != $accum->attrs.end()) + state->dupAttr(i.symbol, iPos, $accum->attrs[i.symbol].pos); + $accum->attrs.emplace( i.symbol, ExprAttrs::AttrDef(new ExprVar(iPos, i.symbol), iPos, ExprAttrs::AttrDef::Kind::Inherited)); } - delete $3; + delete $attrs; } - | binds INHERIT '(' expr ')' attrs ';' - { $$ = $1; - if (!$$->inheritFromExprs) - $$->inheritFromExprs = std::make_unique>(); - $$->inheritFromExprs->push_back($4); - auto from = new nix::ExprInheritFrom(state->at(@4), $$->inheritFromExprs->size() - 1); - for (auto & [i, iPos] : *$6) { - if ($$->attrs.find(i.symbol) != $$->attrs.end()) - state->dupAttr(i.symbol, iPos, $$->attrs[i.symbol].pos); - $$->attrs.emplace( + | binds[accum] INHERIT '(' expr ')' attrs ';' + { $$ = $accum; + if (!$accum->inheritFromExprs) + $accum->inheritFromExprs = std::make_unique>(); + $accum->inheritFromExprs->push_back($expr); + auto from = new nix::ExprInheritFrom(state->at(@expr), $accum->inheritFromExprs->size() - 1); + for (auto & [i, iPos] : *$attrs) { + if ($accum->attrs.find(i.symbol) != $accum->attrs.end()) + state->dupAttr(i.symbol, iPos, $accum->attrs[i.symbol].pos); + $accum->attrs.emplace( i.symbol, ExprAttrs::AttrDef( new ExprSelect(iPos, from, i.symbol), iPos, ExprAttrs::AttrDef::Kind::InheritedFrom)); } - delete $6; + delete $attrs; } | { $$ = new ExprAttrs(state->at(@0)); } ; @@ -468,10 +468,10 @@ expr_list ; formals - : formal ',' formals - { $$ = $3; $$->formals.emplace_back(*$1); delete $1; } + : formal ',' formals[accum] + { $$ = $accum; $$->formals.emplace_back(*$formal); delete $formal; } | formal - { $$ = new Formals; $$->formals.emplace_back(*$1); $$->ellipsis = false; delete $1; } + { $$ = new Formals; $$->formals.emplace_back(*$formal); $$->ellipsis = false; delete $formal; } | { $$ = new Formals; $$->ellipsis = false; } | ELLIPSIS From b0a8430e851790ebac4e2324084bd6d86b995316 Mon Sep 17 00:00:00 2001 From: Ryan Hendrickson Date: Sat, 20 Jul 2024 12:04:25 -0400 Subject: [PATCH 015/718] parser.y: move attr doc setting into addAttr --- src/libexpr/parser-state.hh | 11 +++++++++-- src/libexpr/parser.y | 13 +------------ 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/libexpr/parser-state.hh b/src/libexpr/parser-state.hh index 4bb5c9204..c23ef32a5 100644 --- a/src/libexpr/parser-state.hh +++ b/src/libexpr/parser-state.hh @@ -86,7 +86,7 @@ struct ParserState void dupAttr(const AttrPath & attrPath, const PosIdx pos, const PosIdx prevPos); void dupAttr(Symbol attr, const PosIdx pos, const PosIdx prevPos); - void addAttr(ExprAttrs * attrs, AttrPath && attrPath, Expr * e, const PosIdx pos); + void addAttr(ExprAttrs * attrs, AttrPath && attrPath, const ParserLocation & loc, Expr * e, const ParserLocation & exprLoc); Formals * validateFormals(Formals * formals, PosIdx pos = noPos, Symbol arg = {}); Expr * stripIndentation(const PosIdx pos, std::vector>> && es); @@ -110,11 +110,12 @@ inline void ParserState::dupAttr(Symbol attr, const PosIdx pos, const PosIdx pre }); } -inline void ParserState::addAttr(ExprAttrs * attrs, AttrPath && attrPath, Expr * e, const PosIdx pos) +inline void ParserState::addAttr(ExprAttrs * attrs, AttrPath && attrPath, const ParserLocation & loc, Expr * e, const ParserLocation & exprLoc) { AttrPath::iterator i; // All attrpaths have at least one attr assert(!attrPath.empty()); + auto pos = at(loc); // Checking attrPath validity. // =========================== for (i = attrPath.begin(); i + 1 < attrPath.end(); i++) { @@ -179,6 +180,12 @@ inline void ParserState::addAttr(ExprAttrs * attrs, AttrPath && attrPath, Expr * } else { attrs->dynamicAttrs.push_back(ExprAttrs::DynamicAttrDef(i->expr, e, pos)); } + + auto it = lexerState.positionToDocComment.find(pos); + if (it != lexerState.positionToDocComment.end()) { + e->setDocComment(it->second); + lexerState.positionToDocComment.emplace(at(exprLoc), it->second); + } } inline Formals * ParserState::validateFormals(Formals * formals, PosIdx pos, Symbol arg) diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index 256244a75..6386747f5 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -366,18 +366,7 @@ ind_string_parts binds : binds[accum] attrpath '=' expr ';' { $$ = $accum; - - auto pos = state->at(@attrpath); - auto exprPos = state->at(@expr); - { - auto it = state->lexerState.positionToDocComment.find(pos); - if (it != state->lexerState.positionToDocComment.end()) { - $expr->setDocComment(it->second); - state->lexerState.positionToDocComment.emplace(exprPos, it->second); - } - } - - state->addAttr($$, std::move(*$attrpath), $expr, pos); + state->addAttr($$, std::move(*$attrpath), @attrpath, $expr, @expr); delete $attrpath; } | binds[accum] INHERIT attrs ';' From 6e3b9e6a4de7430c8b130a7c87d7f5df68cf6c86 Mon Sep 17 00:00:00 2001 From: Ryan Hendrickson Date: Sat, 20 Jul 2024 12:04:25 -0400 Subject: [PATCH 016/718] parser.y: eliminate conflicts --- src/libexpr/parser.y | 61 ++++++++++++------- .../lang/parse-fail-undef-var-2.err.exp | 2 +- 2 files changed, 39 insertions(+), 24 deletions(-) diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index 6386747f5..2069931e1 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -8,8 +8,8 @@ %parse-param { nix::ParserState * state } %lex-param { void * scanner } %lex-param { nix::ParserState * state } -%expect 1 -%expect-rr 1 +%expect 0 +%expect-rr 0 %code requires { @@ -133,8 +133,8 @@ static Expr * makeCall(PosIdx pos, Expr * fn, Expr * arg) { %type expr_select expr_simple expr_app %type expr_pipe_from expr_pipe_into %type expr_list -%type binds -%type formals +%type binds binds1 +%type formals formal_set %type formal %type attrpath %type attrs @@ -180,22 +180,22 @@ expr_function $$ = me; SET_DOC_POS(me, @1); } - | '{' formals '}' ':' expr_function[body] - { auto me = new ExprLambda(CUR_POS, state->validateFormals($formals), $body); + | formal_set ':' expr_function[body] + { auto me = new ExprLambda(CUR_POS, state->validateFormals($formal_set), $body); $$ = me; SET_DOC_POS(me, @1); } - | '{' formals '}' '@' ID ':' expr_function[body] + | formal_set '@' ID ':' expr_function[body] { auto arg = state->symbols.create($ID); - auto me = new ExprLambda(CUR_POS, arg, state->validateFormals($formals, CUR_POS, arg), $body); + auto me = new ExprLambda(CUR_POS, arg, state->validateFormals($formal_set, CUR_POS, arg), $body); $$ = me; SET_DOC_POS(me, @1); } - | ID '@' '{' formals '}' ':' expr_function[body] + | ID '@' formal_set ':' expr_function[body] { auto arg = state->symbols.create($ID); - auto me = new ExprLambda(CUR_POS, arg, state->validateFormals($formals, CUR_POS, arg), $body); + auto me = new ExprLambda(CUR_POS, arg, state->validateFormals($formal_set, CUR_POS, arg), $body); $$ = me; SET_DOC_POS(me, @1); } @@ -311,11 +311,13 @@ expr_simple /* Let expressions `let {..., body = ...}' are just desugared into `(rec {..., body = ...}).body'. */ | LET '{' binds '}' - { $3->recursive = true; $$ = new ExprSelect(noPos, $3, state->s.body); } + { $3->recursive = true; $3->pos = CUR_POS; $$ = new ExprSelect(noPos, $3, state->s.body); } | REC '{' binds '}' - { $3->recursive = true; $$ = $3; } - | '{' binds '}' - { $$ = $2; } + { $3->recursive = true; $3->pos = CUR_POS; $$ = $3; } + | '{' binds1 '}' + { $2->pos = CUR_POS; $$ = $2; } + | '{' '}' + { $$ = new ExprAttrs(CUR_POS); } | '[' expr_list ']' { $$ = $2; } ; @@ -364,8 +366,13 @@ ind_string_parts ; binds - : binds[accum] attrpath '=' expr ';' { - $$ = $accum; + : binds1 + | { $$ = new ExprAttrs; } + ; + +binds1 + : binds1[accum] attrpath '=' expr ';' + { $$ = $accum; state->addAttr($$, std::move(*$attrpath), @attrpath, $expr, @expr); delete $attrpath; } @@ -398,7 +405,11 @@ binds } delete $attrs; } - | { $$ = new ExprAttrs(state->at(@0)); } + | attrpath '=' expr ';' + { $$ = new ExprAttrs; + state->addAttr($$, std::move(*$attrpath), @attrpath, $expr, @expr); + delete $attrpath; + } ; attrs @@ -456,15 +467,19 @@ expr_list | { $$ = new ExprList; } ; +formal_set + : '{' formals ',' ELLIPSIS '}' { $$ = $formals; $$->ellipsis = true; } + | '{' ELLIPSIS '}' { $$ = new Formals; $$->ellipsis = true; } + | '{' formals ',' '}' { $$ = $formals; $$->ellipsis = false; } + | '{' formals '}' { $$ = $formals; $$->ellipsis = false; } + | '{' '}' { $$ = new Formals; $$->ellipsis = false; } + ; + formals - : formal ',' formals[accum] + : formals[accum] ',' formal { $$ = $accum; $$->formals.emplace_back(*$formal); delete $formal; } | formal - { $$ = new Formals; $$->formals.emplace_back(*$formal); $$->ellipsis = false; delete $formal; } - | - { $$ = new Formals; $$->ellipsis = false; } - | ELLIPSIS - { $$ = new Formals; $$->ellipsis = true; } + { $$ = new Formals; $$->formals.emplace_back(*$formal); delete $formal; } ; formal diff --git a/tests/functional/lang/parse-fail-undef-var-2.err.exp b/tests/functional/lang/parse-fail-undef-var-2.err.exp index 393c454dd..96e87b2aa 100644 --- a/tests/functional/lang/parse-fail-undef-var-2.err.exp +++ b/tests/functional/lang/parse-fail-undef-var-2.err.exp @@ -1,4 +1,4 @@ -error: syntax error, unexpected ':', expecting '}' +error: syntax error, unexpected ':', expecting '}' or ',' at «stdin»:3:13: 2| 3| f = {x, y : ["baz" "bar" z "bat"]}: x + y; From 18db46a6cb72acaae748833b09b428a7794bd9c8 Mon Sep 17 00:00:00 2001 From: Ryan Hendrickson Date: Mon, 22 Jul 2024 11:36:09 -0400 Subject: [PATCH 017/718] parser.y: GLR -> LALR --- src/libexpr/parser-state.hh | 1 + src/libexpr/parser.y | 17 +++++++++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/libexpr/parser-state.hh b/src/libexpr/parser-state.hh index c23ef32a5..8ad0d9ad7 100644 --- a/src/libexpr/parser-state.hh +++ b/src/libexpr/parser-state.hh @@ -20,6 +20,7 @@ struct StringToken operator std::string_view() const { return {p, l}; } }; +// This type must be trivially copyable; see YYLTYPE_IS_TRIVIAL in parser.y. struct ParserLocation { int beginOffset; diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index 2069931e1..f2ccca7fc 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -1,4 +1,4 @@ -%glr-parser +%define api.location.type { ::nix::ParserLocation } %define api.pure %locations %define parse.error verbose @@ -9,7 +9,6 @@ %lex-param { void * scanner } %lex-param { nix::ParserState * state } %expect 0 -%expect-rr 0 %code requires { @@ -27,7 +26,17 @@ #include "eval-settings.hh" #include "parser-state.hh" -#define YYLTYPE ::nix::ParserLocation +// Bison seems to have difficulty growing the parser stack when using C++ with +// a custom location type. This undocumented macro tells Bison that our +// location type is "trivially copyable" in C++-ese, so it is safe to use the +// same memcpy macro it uses to grow the stack that it uses with its own +// default location type. Without this, we get "error: memory exhausted" when +// parsing some large Nix files. Our other options are to increase the initial +// stack size (200 by default) to be as large as we ever want to support (so +// that growing the stack is unnecessary), or redefine the stack-relocation +// macro ourselves (which is also undocumented). +#define YYLTYPE_IS_TRIVIAL 1 + #define YY_DECL int yylex \ (YYSTYPE * yylval_param, YYLTYPE * yylloc_param, yyscan_t yyscanner, nix::ParserState * state) @@ -77,7 +86,7 @@ YY_DECL; using namespace nix; -#define CUR_POS state->at(*yylocp) +#define CUR_POS state->at(yyloc) void yyerror(YYLTYPE * loc, yyscan_t scanner, ParserState * state, const char * error) From dd75711895057328b00f92353730e7f873eafd52 Mon Sep 17 00:00:00 2001 From: Jade Lovelace Date: Fri, 12 Jul 2024 14:56:30 +0200 Subject: [PATCH 018/718] Use std::strong_ordering for version comparison The actual motive here is the avoidance of integer overflow if we were to make these use checked NixInts and retain the subtraction. However, the actual *intent* of this code is a three-way comparison, which can be done with operator<=>, so we should just do *that* instead. Change-Id: I7f9a7da1f3176424b528af6d1b4f1591e4ab26bf --- src/libexpr/primops.cc | 3 ++- src/libstore/names.cc | 8 ++++---- src/libstore/names.hh | 2 +- src/nix-env/nix-env.cc | 22 +++++++++++----------- 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 0b3b19b57..a23583f34 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -4446,7 +4446,8 @@ static void prim_compareVersions(EvalState & state, const PosIdx pos, Value * * { auto version1 = state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.compareVersions"); auto version2 = state.forceStringNoCtx(*args[1], pos, "while evaluating the second argument passed to builtins.compareVersions"); - v.mkInt(compareVersions(version1, version2)); + auto result = compareVersions(version1, version2); + v.mkInt(result < 0 ? -1 : result > 0 ? 1 : 0); } static RegisterPrimOp primop_compareVersions({ diff --git a/src/libstore/names.cc b/src/libstore/names.cc index 277aabf0f..c0e1b1022 100644 --- a/src/libstore/names.cc +++ b/src/libstore/names.cc @@ -94,7 +94,7 @@ static bool componentsLT(const std::string_view c1, const std::string_view c2) } -int compareVersions(const std::string_view v1, const std::string_view v2) +std::strong_ordering compareVersions(const std::string_view v1, const std::string_view v2) { auto p1 = v1.begin(); auto p2 = v2.begin(); @@ -102,11 +102,11 @@ int compareVersions(const std::string_view v1, const std::string_view v2) while (p1 != v1.end() || p2 != v2.end()) { auto c1 = nextComponent(p1, v1.end()); auto c2 = nextComponent(p2, v2.end()); - if (componentsLT(c1, c2)) return -1; - else if (componentsLT(c2, c1)) return 1; + if (componentsLT(c1, c2)) return std::strong_ordering::less; + else if (componentsLT(c2, c1)) return std::strong_ordering::greater; } - return 0; + return std::strong_ordering::equal; } diff --git a/src/libstore/names.hh b/src/libstore/names.hh index d82b99bb4..a6909d545 100644 --- a/src/libstore/names.hh +++ b/src/libstore/names.hh @@ -30,7 +30,7 @@ typedef std::list DrvNames; std::string_view nextComponent(std::string_view::const_iterator & p, const std::string_view::const_iterator end); -int compareVersions(const std::string_view v1, const std::string_view v2); +std::strong_ordering compareVersions(const std::string_view v1, const std::string_view v2); DrvNames drvNamesFromArgs(const Strings & opArgs); } diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index 40c200542..ba2baccee 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -204,15 +204,15 @@ static void loadDerivations(EvalState & state, const SourcePath & nixExprPath, } -static long getPriority(EvalState & state, PackageInfo & drv) +static NixInt getPriority(EvalState & state, PackageInfo & drv) { - return drv.queryMetaInt("priority", 0); + return drv.queryMetaInt("priority", NixInt(0)); } -static long comparePriorities(EvalState & state, PackageInfo & drv1, PackageInfo & drv2) +static std::strong_ordering comparePriorities(EvalState & state, PackageInfo & drv1, PackageInfo & drv2) { - return getPriority(state, drv2) - getPriority(state, drv1); + return getPriority(state, drv2) <=> getPriority(state, drv1); } @@ -280,7 +280,7 @@ std::vector pickNewestOnly(EvalState & state, std::vector matches) auto & oneDrv = match.packageInfo; const auto drvName = DrvName { oneDrv.queryName() }; - long comparison = 1; + std::strong_ordering comparison = std::strong_ordering::greater; const auto itOther = newest.find(drvName.name); @@ -288,9 +288,9 @@ std::vector pickNewestOnly(EvalState & state, std::vector matches) auto & newestDrv = itOther->second.packageInfo; comparison = - oneDrv.querySystem() == newestDrv.querySystem() ? 0 : - oneDrv.querySystem() == settings.thisSystem ? 1 : - newestDrv.querySystem() == settings.thisSystem ? -1 : 0; + oneDrv.querySystem() == newestDrv.querySystem() ? std::strong_ordering::equal : + oneDrv.querySystem() == settings.thisSystem ? std::strong_ordering::greater : + newestDrv.querySystem() == settings.thisSystem ? std::strong_ordering::less : std::strong_ordering::equal; if (comparison == 0) comparison = comparePriorities(state, oneDrv, newestDrv); if (comparison == 0) @@ -625,13 +625,13 @@ static void upgradeDerivations(Globals & globals, continue; DrvName newName(j->queryName()); if (newName.name == drvName.name) { - int d = compareVersions(drvName.version, newName.version); + std::strong_ordering d = compareVersions(drvName.version, newName.version); if ((upgradeType == utLt && d < 0) || (upgradeType == utLeq && d <= 0) || (upgradeType == utEq && d == 0) || upgradeType == utAlways) { - long d2 = -1; + std::strong_ordering d2 = std::strong_ordering::less; if (bestElem != availElems.end()) { d2 = comparePriorities(*globals.state, *bestElem, *j); if (d2 == 0) d2 = compareVersions(bestVersion, newName.version); @@ -902,7 +902,7 @@ static VersionDiff compareVersionAgainstSet( for (auto & i : elems) { DrvName name2(i.queryName()); if (name.name == name2.name) { - int d = compareVersions(name.version, name2.version); + std::strong_ordering d = compareVersions(name.version, name2.version); if (d < 0) { diff = cvGreater; version = name2.version; From e28cb67d41643bf2073e46149e6f5d10d1fd0ef5 Mon Sep 17 00:00:00 2001 From: Jade Lovelace Date: Fri, 5 Jul 2024 15:52:55 +0200 Subject: [PATCH 019/718] libutil: add checked arithmetic tools This is in preparation for adding checked arithmetic to the evaluator. Change-Id: I6e115ce8f5411feda1706624977a4dcd5efd4d13 --- src/libutil/checked-arithmetic.hh | 182 ++++++++++++++++++ src/libutil/meson.build | 1 + .../tests/gtest-with-params.hh | 54 ++++++ tests/unit/libutil/checked-arithmetic.cc | 158 +++++++++++++++ 4 files changed, 395 insertions(+) create mode 100644 src/libutil/checked-arithmetic.hh create mode 100644 tests/unit/libutil-support/tests/gtest-with-params.hh create mode 100644 tests/unit/libutil/checked-arithmetic.cc diff --git a/src/libutil/checked-arithmetic.hh b/src/libutil/checked-arithmetic.hh new file mode 100644 index 000000000..55d6ad205 --- /dev/null +++ b/src/libutil/checked-arithmetic.hh @@ -0,0 +1,182 @@ +#pragma once +/** + * @file Checked arithmetic with classes that make it hard to accidentally make something an unchecked operation. + */ + +#include +#include // IWYU pragma: keep +#include +#include +#include +#include +#include + +namespace nix::checked { + +class DivideByZero : std::exception +{}; + +/** + * Numeric value enforcing checked arithmetic. Performing mathematical operations on such values will return a Result + * type which needs to be checked. + */ +template +struct Checked +{ + using Inner = T; + + // TODO: this must be a "trivial default constructor", which means it + // cannot set the value to NOT DO UB on uninit. + T value; + + Checked() = default; + explicit Checked(T const value) + : value{value} + { + } + Checked(Checked const & other) = default; + Checked(Checked && other) = default; + Checked & operator=(Checked const & other) = default; + + std::strong_ordering operator<=>(Checked const & other) const = default; + std::strong_ordering operator<=>(T const & other) const + { + return value <=> other; + } + + explicit operator T() const + { + return value; + } + + enum class OverflowKind { + NoOverflow, + Overflow, + DivByZero, + }; + + class Result + { + T value; + OverflowKind overflowed_; + + public: + Result(T value, bool overflowed) + : value{value} + , overflowed_{overflowed ? OverflowKind::Overflow : OverflowKind::NoOverflow} + { + } + Result(T value, OverflowKind overflowed) + : value{value} + , overflowed_{overflowed} + { + } + + bool operator==(Result other) const + { + return value == other.value && overflowed_ == other.overflowed_; + } + + std::optional valueChecked() const + { + if (overflowed_ != OverflowKind::NoOverflow) { + return std::nullopt; + } else { + return value; + } + } + + /** + * Returns the result as if the arithmetic were performed as wrapping arithmetic. + * + * \throws DivideByZero if the operation was a divide by zero. + */ + T valueWrapping() const + { + if (overflowed_ == OverflowKind::DivByZero) { + throw DivideByZero{}; + } + return value; + } + + bool overflowed() const + { + return overflowed_ == OverflowKind::Overflow; + } + + bool divideByZero() const + { + return overflowed_ == OverflowKind::DivByZero; + } + }; + + Result operator+(Checked const other) const + { + return (*this) + other.value; + } + Result operator+(T const other) const + { + T result; + bool overflowed = __builtin_add_overflow(value, other, &result); + return Result{result, overflowed}; + } + + Result operator-(Checked const other) const + { + return (*this) - other.value; + } + Result operator-(T const other) const + { + T result; + bool overflowed = __builtin_sub_overflow(value, other, &result); + return Result{result, overflowed}; + } + + Result operator*(Checked const other) const + { + return (*this) * other.value; + } + Result operator*(T const other) const + { + T result; + bool overflowed = __builtin_mul_overflow(value, other, &result); + return Result{result, overflowed}; + } + + Result operator/(Checked const other) const + { + return (*this) / other.value; + } + /** + * Performs a checked division. + * + * If the right hand side is zero, the result is marked as a DivByZero and + * valueWrapping will throw. + */ + Result operator/(T const other) const + { + constexpr T const minV = std::numeric_limits::min(); + + // It's only possible to overflow with signed division since doing so + // requires crossing the two's complement limits by MIN / -1 (since + // two's complement has one more in range in the negative direction + // than in the positive one). + if (std::is_signed() && (value == minV && other == -1)) { + return Result{minV, true}; + } else if (other == 0) { + return Result{0, OverflowKind::DivByZero}; + } else { + T result = value / other; + return Result{result, false}; + } + } +}; + +template +std::ostream & operator<<(std::ostream & ios, Checked v) +{ + ios << v.value; + return ios; +} + +} diff --git a/src/libutil/meson.build b/src/libutil/meson.build index 8552c4c9d..e0299177f 100644 --- a/src/libutil/meson.build +++ b/src/libutil/meson.build @@ -171,6 +171,7 @@ headers = [config_h] + files( 'args/root.hh', 'callback.hh', 'canon-path.hh', + 'checked-arithmetic.hh', 'chunked-vector.hh', 'closure.hh', 'comparator.hh', diff --git a/tests/unit/libutil-support/tests/gtest-with-params.hh b/tests/unit/libutil-support/tests/gtest-with-params.hh new file mode 100644 index 000000000..323a083fe --- /dev/null +++ b/tests/unit/libutil-support/tests/gtest-with-params.hh @@ -0,0 +1,54 @@ +#pragma once +// SPDX-FileCopyrightText: 2014 Emil Eriksson +// +// SPDX-License-Identifier: BSD-2-Clause +// +// The lion's share of this code is copy pasted directly out of RapidCheck +// headers, so the copyright is set accordingly. +/** + * @file Implements the ability to run a RapidCheck test under gtest with changed + * test parameters such as the number of tests to run. This is useful for + * running very large numbers of the extremely cheap property tests. + */ + +#include +#include +#include + +namespace rc::detail { + +using MakeTestParams = TestParams (*)(); + +template +void checkGTestWith(Testable && testable, MakeTestParams makeTestParams) +{ + const auto testInfo = ::testing::UnitTest::GetInstance()->current_test_info(); + detail::TestMetadata metadata; + metadata.id = std::string(testInfo->test_case_name()) + "/" + std::string(testInfo->name()); + metadata.description = std::string(testInfo->name()); + + const auto result = checkTestable(std::forward(testable), metadata, makeTestParams()); + + if (result.template is()) { + const auto success = result.template get(); + if (!success.distribution.empty()) { + printResultMessage(result, std::cout); + std::cout << std::endl; + } + } else { + std::ostringstream ss; + printResultMessage(result, ss); + FAIL() << ss.str() << std::endl; + } +} +} + +#define RC_GTEST_PROP_WITH_PARAMS(TestCase, Name, MakeParams, ArgList) \ + void rapidCheck_propImpl_##TestCase##_##Name ArgList; \ + \ + TEST(TestCase, Name) \ + { \ + ::rc::detail::checkGTestWith(&rapidCheck_propImpl_##TestCase##_##Name, MakeParams); \ + } \ + \ + void rapidCheck_propImpl_##TestCase##_##Name ArgList diff --git a/tests/unit/libutil/checked-arithmetic.cc b/tests/unit/libutil/checked-arithmetic.cc new file mode 100644 index 000000000..75018660d --- /dev/null +++ b/tests/unit/libutil/checked-arithmetic.cc @@ -0,0 +1,158 @@ +#include +#include +#include +#include +#include +#include + +#include + +#include "tests/gtest-with-params.hh" + +namespace rc { +using namespace nix; + +template +struct Arbitrary> +{ + static Gen> arbitrary() + { + return gen::arbitrary(); + } +}; + +} + +namespace nix::checked { + +// Pointer to member function! Mildly gross. +template +using Oper = Checked::Result (Checked::*)(T const other) const; + +template +using ReferenceOper = T (*)(T a, T b); + +/** + * Checks that performing an operation that overflows into an inaccurate result + * has the desired behaviour. + * + * TBig is a type large enough to represent all results of TSmall operations. + */ +template +void checkType(TSmall a_, TSmall b, Oper oper, ReferenceOper reference) +{ + // Sufficient to fit all values + TBig referenceResult = reference(a_, b); + constexpr const TSmall minV = std::numeric_limits::min(); + constexpr const TSmall maxV = std::numeric_limits::max(); + + Checked a{a_}; + auto result = (a.*(oper))(b); + + // Just truncate it to get the in-range result + RC_ASSERT(result.valueWrapping() == static_cast(referenceResult)); + + if (referenceResult > maxV || referenceResult < minV) { + RC_ASSERT(result.overflowed()); + RC_ASSERT(!result.valueChecked().has_value()); + } else { + RC_ASSERT(!result.overflowed()); + RC_ASSERT(result.valueChecked().has_value()); + RC_ASSERT(*result.valueChecked() == referenceResult); + } +} + +/** + * Checks that performing an operation that overflows into an inaccurate result + * has the desired behaviour. + * + * TBig is a type large enough to represent all results of TSmall operations. + */ +template +void checkDivision(TSmall a_, TSmall b) +{ + // Sufficient to fit all values + constexpr const TSmall minV = std::numeric_limits::min(); + + Checked a{a_}; + auto result = a / b; + + if (std::is_signed() && a_ == minV && b == -1) { + // This is the only possible overflow condition + RC_ASSERT(result.valueWrapping() == minV); + RC_ASSERT(result.overflowed()); + } else if (b == 0) { + RC_ASSERT(result.divideByZero()); + RC_ASSERT_THROWS_AS(result.valueWrapping(), nix::checked::DivideByZero); + RC_ASSERT(result.valueChecked() == std::nullopt); + } else { + TBig referenceResult = a_ / b; + auto result_ = result.valueChecked(); + RC_ASSERT(result_.has_value()); + RC_ASSERT(*result_ == referenceResult); + RC_ASSERT(result.valueWrapping() == referenceResult); + } +} + +/** Creates parameters that perform a more adequate number of checks to validate + * extremely cheap tests such as arithmetic tests */ +static rc::detail::TestParams makeParams() +{ + auto const & conf = rc::detail::configuration(); + auto newParams = conf.testParams; + newParams.maxSuccess = 10000; + return newParams; +} + +RC_GTEST_PROP_WITH_PARAMS(Checked, add_unsigned, makeParams, (uint16_t a, uint16_t b)) +{ + checkType(a, b, &Checked::operator+, [](int32_t a, int32_t b) { return a + b; }); +} + +RC_GTEST_PROP_WITH_PARAMS(Checked, add_signed, makeParams, (int16_t a, int16_t b)) +{ + checkType(a, b, &Checked::operator+, [](int32_t a, int32_t b) { return a + b; }); +} + +RC_GTEST_PROP_WITH_PARAMS(Checked, sub_unsigned, makeParams, (uint16_t a, uint16_t b)) +{ + checkType(a, b, &Checked::operator-, [](int32_t a, int32_t b) { return a - b; }); +} + +RC_GTEST_PROP_WITH_PARAMS(Checked, sub_signed, makeParams, (int16_t a, int16_t b)) +{ + checkType(a, b, &Checked::operator-, [](int32_t a, int32_t b) { return a - b; }); +} + +RC_GTEST_PROP_WITH_PARAMS(Checked, mul_unsigned, makeParams, (uint16_t a, uint16_t b)) +{ + checkType(a, b, &Checked::operator*, [](int64_t a, int64_t b) { return a * b; }); +} + +RC_GTEST_PROP_WITH_PARAMS(Checked, mul_signed, makeParams, (int16_t a, int16_t b)) +{ + checkType(a, b, &Checked::operator*, [](int64_t a, int64_t b) { return a * b; }); +} + +RC_GTEST_PROP_WITH_PARAMS(Checked, div_unsigned, makeParams, (uint16_t a, uint16_t b)) +{ + checkDivision(a, b); +} + +RC_GTEST_PROP_WITH_PARAMS(Checked, div_signed, makeParams, (int16_t a, int16_t b)) +{ + checkDivision(a, b); +} + +// Make absolutely sure that we check the special cases if the proptest +// generator does not come up with them. This one is especially important +// because it has very specific pairs required for the edge cases unlike the +// others. +TEST(Checked, div_signed_special_cases) +{ + checkDivision(std::numeric_limits::min(), -1); + checkDivision(std::numeric_limits::min(), 0); + checkDivision(0, 0); +} + +} From 7b6622d73317f0cd093cde96b5898b8af07abea7 Mon Sep 17 00:00:00 2001 From: Jade Lovelace Date: Fri, 12 Jul 2024 16:22:34 +0200 Subject: [PATCH 020/718] language: cleanly ban integer overflows This also bans various sneaking of negative numbers from the language into unsuspecting builtins as was exposed while auditing the consequences of changing the Nix language integer type to a newtype. It's unlikely that this change comprehensively ensures correctness when passing integers out of the Nix language and we should probably add a checked-narrowing function or something similar, but that's out of scope for the immediate change. During the development of this I found a few fun facts about the language: - You could overflow integers by converting from unsigned JSON values. - You could overflow unsigned integers by converting negative numbers into them when going into Nix config, into fetchTree, and into flake inputs. The flake inputs and Nix config cannot actually be tested properly since they both ban thunks, however, we put in checks anyway because it's possible these could somehow be used to do such shenanigans some other way. Note that Lix has banned Nix language integer overflows since the very first public beta, but threw a SIGILL about them because we run with -fsanitize=signed-overflow -fsanitize-undefined-trap-on-error in production builds. Since the Nix language uses signed integers, overflow was simply undefined behaviour, and since we defined that to trap, it did. Trapping on it was a bad UX, but we didn't even entirely notice that we had done this at all until it was reported as a bug a couple of months later (which is, to be fair, that flag working as intended), and it's got enough production time that, aside from code that is IMHO buggy (and which is, in any case, not in nixpkgs) such as https://git.lix.systems/lix-project/lix/issues/445, we don't think anyone doing anything reasonable actually depends on wrapping overflow. Even for weird use cases such as doing funny bit crimes, it doesn't make sense IMO to have wrapping behaviour, since two's complement arithmetic overflow behaviour is so *aggressively* not what you want for *any* kind of mathematics/algorithms. The Nix language exists for package management, a domain where bit crimes are already only dubiously in scope to begin with, and it makes a lot more sense for that domain for the integers to never lose precision, either by throwing errors if they would, or by being arbitrary-precision. Fixes: https://github.com/NixOS/nix/issues/10968 Original-CL: https://gerrit.lix.systems/c/lix/+/1596 Change-Id: I51f253840c4af2ea5422b8a420aa5fafbf8fae75 --- src/libcmd/installable-flake.cc | 4 +- src/libcmd/installable-value.hh | 2 +- src/libexpr-c/nix_api_value.cc | 2 +- src/libexpr/eval-cache.cc | 4 +- src/libexpr/eval.cc | 21 ++-- src/libexpr/get-drvs.cc | 4 +- src/libexpr/json-to-value.cc | 7 +- src/libexpr/lexer.l | 2 +- src/libexpr/nixexpr.hh | 1 + src/libexpr/primops.cc | 102 ++++++++++++------ src/libexpr/primops/fetchTree.cc | 12 ++- src/libexpr/value-to-json.cc | 2 +- src/libexpr/value.hh | 10 +- src/libflake/flake/flake.cc | 22 +++- src/libstore/globals.hh | 10 +- .../lang/eval-fail-fetchTree-negative.err.exp | 8 ++ .../lang/eval-fail-fetchTree-negative.nix | 5 + ...ake-ref-to-string-negative-integer.err.exp | 14 +++ ...l-flake-ref-to-string-negative-integer.nix | 7 ++ .../eval-fail-fromJSON-overflowing.err.exp | 8 ++ .../lang/eval-fail-fromJSON-overflowing.nix | 1 + .../lang/eval-fail-overflowing-add.err.exp | 6 ++ .../lang/eval-fail-overflowing-add.nix | 4 + .../lang/eval-fail-overflowing-div.err.exp | 23 ++++ .../lang/eval-fail-overflowing-div.nix | 7 ++ .../lang/eval-fail-overflowing-mul.err.exp | 16 +++ .../lang/eval-fail-overflowing-mul.nix | 3 + .../lang/eval-fail-overflowing-sub.err.exp | 9 ++ .../lang/eval-fail-overflowing-sub.nix | 4 + tests/unit/libexpr-support/tests/libexpr.hh | 2 +- 30 files changed, 260 insertions(+), 62 deletions(-) create mode 100644 tests/functional/lang/eval-fail-fetchTree-negative.err.exp create mode 100644 tests/functional/lang/eval-fail-fetchTree-negative.nix create mode 100644 tests/functional/lang/eval-fail-flake-ref-to-string-negative-integer.err.exp create mode 100644 tests/functional/lang/eval-fail-flake-ref-to-string-negative-integer.nix create mode 100644 tests/functional/lang/eval-fail-fromJSON-overflowing.err.exp create mode 100644 tests/functional/lang/eval-fail-fromJSON-overflowing.nix create mode 100644 tests/functional/lang/eval-fail-overflowing-add.err.exp create mode 100644 tests/functional/lang/eval-fail-overflowing-add.nix create mode 100644 tests/functional/lang/eval-fail-overflowing-div.err.exp create mode 100644 tests/functional/lang/eval-fail-overflowing-div.nix create mode 100644 tests/functional/lang/eval-fail-overflowing-mul.err.exp create mode 100644 tests/functional/lang/eval-fail-overflowing-mul.nix create mode 100644 tests/functional/lang/eval-fail-overflowing-sub.err.exp create mode 100644 tests/functional/lang/eval-fail-overflowing-sub.nix diff --git a/src/libcmd/installable-flake.cc b/src/libcmd/installable-flake.cc index 8796ad5ba..6c9ee6748 100644 --- a/src/libcmd/installable-flake.cc +++ b/src/libcmd/installable-flake.cc @@ -104,12 +104,12 @@ DerivedPathsWithInfo InstallableFlake::toDerivedPaths() auto drvPath = attr->forceDerivation(); - std::optional priority; + std::optional priority; if (attr->maybeGetAttr(state->sOutputSpecified)) { } else if (auto aMeta = attr->maybeGetAttr(state->sMeta)) { if (auto aPriority = aMeta->maybeGetAttr("priority")) - priority = aPriority->getInt(); + priority = aPriority->getInt().value; } return {{ diff --git a/src/libcmd/installable-value.hh b/src/libcmd/installable-value.hh index 798cb5e1a..60207cd23 100644 --- a/src/libcmd/installable-value.hh +++ b/src/libcmd/installable-value.hh @@ -40,7 +40,7 @@ struct ExtraPathInfoValue : ExtraPathInfo /** * An optional priority for use with "build envs". See Package */ - std::optional priority; + std::optional priority; /** * The attribute path associated with this value. The idea is diff --git a/src/libexpr-c/nix_api_value.cc b/src/libexpr-c/nix_api_value.cc index 845e87935..fa2a9cbe2 100644 --- a/src/libexpr-c/nix_api_value.cc +++ b/src/libexpr-c/nix_api_value.cc @@ -306,7 +306,7 @@ int64_t nix_get_int(nix_c_context * context, const nix_value * value) try { auto & v = check_value_in(value); assert(v.type() == nix::nInt); - return v.integer(); + return v.integer().value; } NIXC_CATCH_ERRS_RES(0); } diff --git a/src/libexpr/eval-cache.cc b/src/libexpr/eval-cache.cc index 26352187e..95b484606 100644 --- a/src/libexpr/eval-cache.cc +++ b/src/libexpr/eval-cache.cc @@ -326,7 +326,7 @@ struct AttrDb case AttrType::Bool: return {{rowId, queryAttribute.getInt(2) != 0}}; case AttrType::Int: - return {{rowId, int_t{queryAttribute.getInt(2)}}}; + return {{rowId, int_t{NixInt{queryAttribute.getInt(2)}}}}; case AttrType::ListOfStrings: return {{rowId, tokenizeString>(queryAttribute.getStr(2), "\t")}}; case AttrType::Missing: @@ -469,7 +469,7 @@ Value & AttrCursor::forceValue() else if (v.type() == nBool) cachedValue = {root->db->setBool(getKey(), v.boolean()), v.boolean()}; else if (v.type() == nInt) - cachedValue = {root->db->setInt(getKey(), v.integer()), int_t{v.integer()}}; + cachedValue = {root->db->setInt(getKey(), v.integer().value), int_t{v.integer()}}; else if (v.type() == nAttrs) ; // FIXME: do something? else diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 746ccab2a..76c54936f 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -1979,7 +1979,7 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v) NixStringContext context; std::vector s; size_t sSize = 0; - NixInt n = 0; + NixInt n{0}; NixFloat nf = 0; bool first = !forceString; @@ -2023,17 +2023,22 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v) if (firstType == nInt) { if (vTmp.type() == nInt) { - n += vTmp.integer(); + auto newN = n + vTmp.integer(); + if (auto checked = newN.valueChecked(); checked.has_value()) { + n = NixInt(*checked); + } else { + state.error("integer overflow in adding %1% + %2%", n, vTmp.integer()).atPos(i_pos).debugThrow(); + } } else if (vTmp.type() == nFloat) { // Upgrade the type from int to float; firstType = nFloat; - nf = n; + nf = n.value; nf += vTmp.fpoint(); } else state.error("cannot add %1% to an integer", showType(vTmp)).atPos(i_pos).withFrame(env, *this).debugThrow(); } else if (firstType == nFloat) { if (vTmp.type() == nInt) { - nf += vTmp.integer(); + nf += vTmp.integer().value; } else if (vTmp.type() == nFloat) { nf += vTmp.fpoint(); } else @@ -2158,7 +2163,7 @@ NixFloat EvalState::forceFloat(Value & v, const PosIdx pos, std::string_view err try { forceValue(v, pos); if (v.type() == nInt) - return v.integer(); + return v.integer().value; else if (v.type() != nFloat) error( "expected a float but found %1%: %2%", @@ -2345,7 +2350,7 @@ BackedStringView EvalState::coerceToString( shell scripting convenience, just like `null'. */ if (v.type() == nBool && v.boolean()) return "1"; if (v.type() == nBool && !v.boolean()) return ""; - if (v.type() == nInt) return std::to_string(v.integer()); + if (v.type() == nInt) return std::to_string(v.integer().value); if (v.type() == nFloat) return std::to_string(v.fpoint()); if (v.type() == nNull) return ""; @@ -2728,9 +2733,9 @@ bool EvalState::eqValues(Value & v1, Value & v2, const PosIdx pos, std::string_v // Special case type-compatibility between float and int if (v1.type() == nInt && v2.type() == nFloat) - return v1.integer() == v2.fpoint(); + return v1.integer().value == v2.fpoint(); if (v1.type() == nFloat && v2.type() == nInt) - return v1.fpoint() == v2.integer(); + return v1.fpoint() == v2.integer().value; // All other types are not compatible with each other. if (v1.type() != v2.type()) return false; diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc index 7041a3932..20963ec91 100644 --- a/src/libexpr/get-drvs.cc +++ b/src/libexpr/get-drvs.cc @@ -246,8 +246,8 @@ NixInt PackageInfo::queryMetaInt(const std::string & name, NixInt def) if (v->type() == nString) { /* Backwards compatibility with before we had support for integer meta fields. */ - if (auto n = string2Int(v->c_str())) - return *n; + if (auto n = string2Int(v->c_str())) + return NixInt{*n}; } return def; } diff --git a/src/libexpr/json-to-value.cc b/src/libexpr/json-to-value.cc index 21074bdd8..9ac56541a 100644 --- a/src/libexpr/json-to-value.cc +++ b/src/libexpr/json-to-value.cc @@ -2,6 +2,7 @@ #include "value.hh" #include "eval.hh" +#include #include #include @@ -101,8 +102,12 @@ public: return true; } - bool number_unsigned(number_unsigned_t val) override + bool number_unsigned(number_unsigned_t val_) override { + if (val_ > std::numeric_limits::max()) { + throw Error("unsigned json number %1% outside of Nix integer range", val_); + } + NixInt::Inner val = val_; rs->value(state).mkInt(val); rs->add(); return true; diff --git a/src/libexpr/lexer.l b/src/libexpr/lexer.l index eb1825b7c..a7e44cb72 100644 --- a/src/libexpr/lexer.l +++ b/src/libexpr/lexer.l @@ -138,7 +138,7 @@ or { return OR_KW; } {INT} { errno = 0; std::optional numMay = string2Int(yytext); if (numMay.has_value()) { - yylval->n = *numMay; + yylval->n = NixInt{*numMay}; } else { throw ParseError(ErrorInfo{ .msg = HintFmt("invalid integer '%1%'", yytext), diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh index 3279e3d48..7868834f1 100644 --- a/src/libexpr/nixexpr.hh +++ b/src/libexpr/nixexpr.hh @@ -107,6 +107,7 @@ struct ExprInt : Expr { Value v; ExprInt(NixInt n) { v.mkInt(n); }; + ExprInt(NixInt::Inner n) { v.mkInt(n); }; Value * maybeThunk(EvalState & state, Env & env) override; COMMON_METHODS }; diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index a23583f34..acc0d6c1c 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -587,9 +587,9 @@ struct CompareValues { try { if (v1->type() == nFloat && v2->type() == nInt) - return v1->fpoint() < v2->integer(); + return v1->fpoint() < v2->integer().value; if (v1->type() == nInt && v2->type() == nFloat) - return v1->integer() < v2->fpoint(); + return v1->integer().value < v2->fpoint(); if (v1->type() != v2->type()) state.error("cannot compare %s with %s", showType(*v1), showType(*v2)).debugThrow(); // Allow selecting a subset of enum values @@ -2677,13 +2677,13 @@ static struct LazyPosAcessors { PrimOp primop_lineOfPos{ .arity = 1, .fun = [] (EvalState & state, PosIdx pos, Value * * args, Value & v) { - v.mkInt(state.positions[PosIdx(args[0]->integer())].line); + v.mkInt(state.positions[PosIdx(args[0]->integer().value)].line); } }; PrimOp primop_columnOfPos{ .arity = 1, .fun = [] (EvalState & state, PosIdx pos, Value * * args, Value & v) { - v.mkInt(state.positions[PosIdx(args[0]->integer())].column); + v.mkInt(state.positions[PosIdx(args[0]->integer().value)].column); } }; @@ -3159,7 +3159,8 @@ static void elemAt(EvalState & state, const PosIdx pos, Value & list, int n, Val /* Return the n-1'th element of a list. */ static void prim_elemAt(EvalState & state, const PosIdx pos, Value * * args, Value & v) { - elemAt(state, pos, *args[0], state.forceInt(*args[1], pos, "while evaluating the second argument passed to builtins.elemAt"), v); + NixInt::Inner elem = state.forceInt(*args[1], pos, "while evaluating the second argument passed to builtins.elemAt").value; + elemAt(state, pos, *args[0], elem, v); } static RegisterPrimOp primop_elemAt({ @@ -3453,10 +3454,12 @@ static RegisterPrimOp primop_all({ static void prim_genList(EvalState & state, const PosIdx pos, Value * * args, Value & v) { - auto len = state.forceInt(*args[1], pos, "while evaluating the second argument passed to builtins.genList"); + auto len_ = state.forceInt(*args[1], pos, "while evaluating the second argument passed to builtins.genList").value; - if (len < 0) - state.error("cannot create list of size %1%", len).atPos(pos).debugThrow(); + if (len_ < 0) + state.error("cannot create list of size %1%", len_).atPos(pos).debugThrow(); + + size_t len = size_t(len_); // More strict than striclty (!) necessary, but acceptable // as evaluating map without accessing any values makes little sense. @@ -3713,9 +3716,17 @@ static void prim_add(EvalState & state, const PosIdx pos, Value * * args, Value if (args[0]->type() == nFloat || args[1]->type() == nFloat) v.mkFloat(state.forceFloat(*args[0], pos, "while evaluating the first argument of the addition") + state.forceFloat(*args[1], pos, "while evaluating the second argument of the addition")); - else - v.mkInt( state.forceInt(*args[0], pos, "while evaluating the first argument of the addition") - + state.forceInt(*args[1], pos, "while evaluating the second argument of the addition")); + else { + auto i1 = state.forceInt(*args[0], pos, "while evaluating the first argument of the addition"); + auto i2 = state.forceInt(*args[1], pos, "while evaluating the second argument of the addition"); + + auto result_ = i1 + i2; + if (auto result = result_.valueChecked(); result.has_value()) { + v.mkInt(*result); + } else { + state.error("integer overflow in adding %1% + %2%", i1, i2).atPos(pos).debugThrow(); + } + } } static RegisterPrimOp primop_add({ @@ -3734,9 +3745,18 @@ static void prim_sub(EvalState & state, const PosIdx pos, Value * * args, Value if (args[0]->type() == nFloat || args[1]->type() == nFloat) v.mkFloat(state.forceFloat(*args[0], pos, "while evaluating the first argument of the subtraction") - state.forceFloat(*args[1], pos, "while evaluating the second argument of the subtraction")); - else - v.mkInt( state.forceInt(*args[0], pos, "while evaluating the first argument of the subtraction") - - state.forceInt(*args[1], pos, "while evaluating the second argument of the subtraction")); + else { + auto i1 = state.forceInt(*args[0], pos, "while evaluating the first argument of the subtraction"); + auto i2 = state.forceInt(*args[1], pos, "while evaluating the second argument of the subtraction"); + + auto result_ = i1 - i2; + + if (auto result = result_.valueChecked(); result.has_value()) { + v.mkInt(*result); + } else { + state.error("integer overflow in subtracting %1% - %2%", i1, i2).atPos(pos).debugThrow(); + } + } } static RegisterPrimOp primop_sub({ @@ -3755,9 +3775,18 @@ static void prim_mul(EvalState & state, const PosIdx pos, Value * * args, Value if (args[0]->type() == nFloat || args[1]->type() == nFloat) v.mkFloat(state.forceFloat(*args[0], pos, "while evaluating the first of the multiplication") * state.forceFloat(*args[1], pos, "while evaluating the second argument of the multiplication")); - else - v.mkInt( state.forceInt(*args[0], pos, "while evaluating the first argument of the multiplication") - * state.forceInt(*args[1], pos, "while evaluating the second argument of the multiplication")); + else { + auto i1 = state.forceInt(*args[0], pos, "while evaluating the first argument of the multiplication"); + auto i2 = state.forceInt(*args[1], pos, "while evaluating the second argument of the multiplication"); + + auto result_ = i1 * i2; + + if (auto result = result_.valueChecked(); result.has_value()) { + v.mkInt(*result); + } else { + state.error("integer overflow in multiplying %1% * %2%", i1, i2).atPos(pos).debugThrow(); + } + } } static RegisterPrimOp primop_mul({ @@ -3784,10 +3813,12 @@ static void prim_div(EvalState & state, const PosIdx pos, Value * * args, Value NixInt i1 = state.forceInt(*args[0], pos, "while evaluating the first operand of the division"); NixInt i2 = state.forceInt(*args[1], pos, "while evaluating the second operand of the division"); /* Avoid division overflow as it might raise SIGFPE. */ - if (i1 == std::numeric_limits::min() && i2 == -1) - state.error("overflow in integer division").atPos(pos).debugThrow(); - - v.mkInt(i1 / i2); + auto result_ = i1 / i2; + if (auto result = result_.valueChecked(); result.has_value()) { + v.mkInt(*result); + } else { + state.error("integer overflow in dividing %1% / %2%", i1, i2).atPos(pos).debugThrow(); + } } } @@ -3802,8 +3833,9 @@ static RegisterPrimOp primop_div({ static void prim_bitAnd(EvalState & state, const PosIdx pos, Value * * args, Value & v) { - v.mkInt(state.forceInt(*args[0], pos, "while evaluating the first argument passed to builtins.bitAnd") - & state.forceInt(*args[1], pos, "while evaluating the second argument passed to builtins.bitAnd")); + auto i1 = state.forceInt(*args[0], pos, "while evaluating the first argument passed to builtins.bitAnd"); + auto i2 = state.forceInt(*args[1], pos, "while evaluating the second argument passed to builtins.bitAnd"); + v.mkInt(i1.value & i2.value); } static RegisterPrimOp primop_bitAnd({ @@ -3817,8 +3849,10 @@ static RegisterPrimOp primop_bitAnd({ static void prim_bitOr(EvalState & state, const PosIdx pos, Value * * args, Value & v) { - v.mkInt(state.forceInt(*args[0], pos, "while evaluating the first argument passed to builtins.bitOr") - | state.forceInt(*args[1], pos, "while evaluating the second argument passed to builtins.bitOr")); + auto i1 = state.forceInt(*args[0], pos, "while evaluating the first argument passed to builtins.bitOr"); + auto i2 = state.forceInt(*args[1], pos, "while evaluating the second argument passed to builtins.bitOr"); + + v.mkInt(i1.value | i2.value); } static RegisterPrimOp primop_bitOr({ @@ -3832,8 +3866,10 @@ static RegisterPrimOp primop_bitOr({ static void prim_bitXor(EvalState & state, const PosIdx pos, Value * * args, Value & v) { - v.mkInt(state.forceInt(*args[0], pos, "while evaluating the first argument passed to builtins.bitXor") - ^ state.forceInt(*args[1], pos, "while evaluating the second argument passed to builtins.bitXor")); + auto i1 = state.forceInt(*args[0], pos, "while evaluating the first argument passed to builtins.bitXor"); + auto i2 = state.forceInt(*args[1], pos, "while evaluating the second argument passed to builtins.bitXor"); + + v.mkInt(i1.value ^ i2.value); } static RegisterPrimOp primop_bitXor({ @@ -3913,13 +3949,19 @@ static RegisterPrimOp primop_toString({ non-negative. */ static void prim_substring(EvalState & state, const PosIdx pos, Value * * args, Value & v) { - int start = state.forceInt(*args[0], pos, "while evaluating the first argument (the start offset) passed to builtins.substring"); + NixInt::Inner start = state.forceInt(*args[0], pos, "while evaluating the first argument (the start offset) passed to builtins.substring").value; if (start < 0) state.error("negative start position in 'substring'").atPos(pos).debugThrow(); - int len = state.forceInt(*args[1], pos, "while evaluating the second argument (the substring length) passed to builtins.substring"); + NixInt::Inner len = state.forceInt(*args[1], pos, "while evaluating the second argument (the substring length) passed to builtins.substring").value; + + // Negative length may be idiomatically passed to builtins.substring to get + // the tail of the string. + if (len < 0) { + len = std::numeric_limits::max(); + } // Special-case on empty substring to avoid O(n) strlen // This allows for the use of empty substrings to efficently capture string context @@ -3962,7 +4004,7 @@ static void prim_stringLength(EvalState & state, const PosIdx pos, Value * * arg { NixStringContext context; auto s = state.coerceToString(pos, *args[0], context, "while evaluating the argument passed to builtins.stringLength"); - v.mkInt(s->size()); + v.mkInt(NixInt::Inner(s->size())); } static RegisterPrimOp primop_stringLength({ diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc index f79b6b7b8..78328701d 100644 --- a/src/libexpr/primops/fetchTree.cc +++ b/src/libexpr/primops/fetchTree.cc @@ -122,9 +122,15 @@ static void fetchTree( } else if (attr.value->type() == nBool) attrs.emplace(state.symbols[attr.name], Explicit{attr.value->boolean()}); - else if (attr.value->type() == nInt) - attrs.emplace(state.symbols[attr.name], uint64_t(attr.value->integer())); - else if (state.symbols[attr.name] == "publicKeys") { + else if (attr.value->type() == nInt) { + auto intValue = attr.value->integer().value; + + if (intValue < 0) { + state.error("negative value given for fetchTree attr %1%: %2%", state.symbols[attr.name], intValue).atPos(pos).debugThrow(); + } + + attrs.emplace(state.symbols[attr.name], uint64_t(intValue)); + } else if (state.symbols[attr.name] == "publicKeys") { experimentalFeatureSettings.require(Xp::VerifiedFetches); attrs.emplace(state.symbols[attr.name], printValueAsJSON(state, true, *attr.value, pos, context).dump()); } diff --git a/src/libexpr/value-to-json.cc b/src/libexpr/value-to-json.cc index f8cc05616..8044fe347 100644 --- a/src/libexpr/value-to-json.cc +++ b/src/libexpr/value-to-json.cc @@ -22,7 +22,7 @@ json printValueAsJSON(EvalState & state, bool strict, switch (v.type()) { case nInt: - out = v.integer(); + out = v.integer().value; break; case nBool: diff --git a/src/libexpr/value.hh b/src/libexpr/value.hh index 257da1d2d..1510abfea 100644 --- a/src/libexpr/value.hh +++ b/src/libexpr/value.hh @@ -8,6 +8,7 @@ #include "value/context.hh" #include "source-path.hh" #include "print-options.hh" +#include "checked-arithmetic.hh" #if HAVE_BOEHMGC #include @@ -73,8 +74,8 @@ class EvalState; class XMLWriter; class Printer; -typedef int64_t NixInt; -typedef double NixFloat; +using NixInt = checked::Checked; +using NixFloat = double; /** * External values must descend from ExternalValueBase, so that @@ -304,6 +305,11 @@ public: return internalType != tUninitialized; } + inline void mkInt(NixInt::Inner n) + { + mkInt(NixInt{n}); + } + inline void mkInt(NixInt n) { finishValue(tInt, { .integer = n }); diff --git a/src/libflake/flake/flake.cc b/src/libflake/flake/flake.cc index 627dfe830..fd1183514 100644 --- a/src/libflake/flake/flake.cc +++ b/src/libflake/flake/flake.cc @@ -140,9 +140,16 @@ static FlakeInput parseFlakeInput(EvalState & state, case nBool: attrs.emplace(state.symbols[attr.name], Explicit { attr.value->boolean() }); break; - case nInt: - attrs.emplace(state.symbols[attr.name], (long unsigned int) attr.value->integer()); + case nInt: { + auto intValue = attr.value->integer().value; + + if (intValue < 0) { + state.error("negative value given for flake input attribute %1%: %2%", state.symbols[attr.name], intValue).debugThrow(); + } + + attrs.emplace(state.symbols[attr.name], uint64_t(intValue)); break; + } default: if (attr.name == state.symbols.create("publicKeys")) { experimentalFeatureSettings.require(Xp::VerifiedFetches); @@ -272,7 +279,7 @@ static Flake readFlake( else if (setting.value->type() == nInt) flake.config.settings.emplace( state.symbols[setting.name], - state.forceInt(*setting.value, setting.pos, "")); + state.forceInt(*setting.value, setting.pos, "").value); else if (setting.value->type() == nBool) flake.config.settings.emplace( state.symbols[setting.name], @@ -904,8 +911,13 @@ static void prim_flakeRefToString( for (const auto & attr : *args[0]->attrs()) { auto t = attr.value->type(); if (t == nInt) { - attrs.emplace(state.symbols[attr.name], - (uint64_t) attr.value->integer()); + auto intValue = attr.value->integer().value; + + if (intValue < 0) { + state.error("negative value given for flake ref attr %1%: %2%", state.symbols[attr.name], intValue).atPos(pos).debugThrow(); + } + + attrs.emplace(state.symbols[attr.name], uint64_t(intValue)); } else if (t == nBool) { attrs.emplace(state.symbols[attr.name], Explicit { attr.value->boolean() }); diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh index 8760c9d14..1ca9f02f5 100644 --- a/src/libstore/globals.hh +++ b/src/libstore/globals.hh @@ -1131,7 +1131,10 @@ public: )"}; Setting maxFree{ - this, std::numeric_limits::max(), "max-free", + // n.b. this is deliberately int64 max rather than uint64 max because + // this goes through the Nix language JSON parser and thus needs to be + // representable in Nix language integers. + this, std::numeric_limits::max(), "max-free", R"( When a garbage collection is triggered by the `min-free` option, it stops as soon as `max-free` bytes are available. The default is @@ -1221,7 +1224,10 @@ public: Setting warnLargePathThreshold{ this, - std::numeric_limits::max(), + // n.b. this is deliberately int64 max rather than uint64 max because + // this goes through the Nix language JSON parser and thus needs to be + // representable in Nix language integers. + std::numeric_limits::max(), "warn-large-path-threshold", R"( Warn when copying a path larger than this number of bytes to the Nix store diff --git a/tests/functional/lang/eval-fail-fetchTree-negative.err.exp b/tests/functional/lang/eval-fail-fetchTree-negative.err.exp new file mode 100644 index 000000000..d9ba1f0b2 --- /dev/null +++ b/tests/functional/lang/eval-fail-fetchTree-negative.err.exp @@ -0,0 +1,8 @@ +error: + … while calling the 'fetchTree' builtin + at /pwd/lang/eval-fail-fetchTree-negative.nix:1:1: + 1| builtins.fetchTree { + | ^ + 2| type = "file"; + + error: negative value given for fetchTree attr owner: -1 diff --git a/tests/functional/lang/eval-fail-fetchTree-negative.nix b/tests/functional/lang/eval-fail-fetchTree-negative.nix new file mode 100644 index 000000000..90bcab5d8 --- /dev/null +++ b/tests/functional/lang/eval-fail-fetchTree-negative.nix @@ -0,0 +1,5 @@ +builtins.fetchTree { + type = "file"; + url = "file://eval-fail-fetchTree-negative.nix"; + owner = -1; +} diff --git a/tests/functional/lang/eval-fail-flake-ref-to-string-negative-integer.err.exp b/tests/functional/lang/eval-fail-flake-ref-to-string-negative-integer.err.exp new file mode 100644 index 000000000..25c8d7eaa --- /dev/null +++ b/tests/functional/lang/eval-fail-flake-ref-to-string-negative-integer.err.exp @@ -0,0 +1,14 @@ +error: + … while calling the 'seq' builtin + at /pwd/lang/eval-fail-flake-ref-to-string-negative-integer.nix:1:16: + 1| let n = -1; in builtins.seq n (builtins.flakeRefToString { + | ^ + 2| type = "github"; + + … while calling the 'flakeRefToString' builtin + at /pwd/lang/eval-fail-flake-ref-to-string-negative-integer.nix:1:32: + 1| let n = -1; in builtins.seq n (builtins.flakeRefToString { + | ^ + 2| type = "github"; + + error: negative value given for flake ref attr repo: -1 diff --git a/tests/functional/lang/eval-fail-flake-ref-to-string-negative-integer.nix b/tests/functional/lang/eval-fail-flake-ref-to-string-negative-integer.nix new file mode 100644 index 000000000..e0208eb25 --- /dev/null +++ b/tests/functional/lang/eval-fail-flake-ref-to-string-negative-integer.nix @@ -0,0 +1,7 @@ +let n = -1; in builtins.seq n (builtins.flakeRefToString { + type = "github"; + owner = "NixOS"; + repo = n; + ref = "23.05"; + dir = "lib"; +}) diff --git a/tests/functional/lang/eval-fail-fromJSON-overflowing.err.exp b/tests/functional/lang/eval-fail-fromJSON-overflowing.err.exp new file mode 100644 index 000000000..a39082b45 --- /dev/null +++ b/tests/functional/lang/eval-fail-fromJSON-overflowing.err.exp @@ -0,0 +1,8 @@ +error: + … while calling the 'fromJSON' builtin + at /pwd/lang/eval-fail-fromJSON-overflowing.nix:1:1: + 1| builtins.fromJSON ''{"attr": 18446744073709551615}'' + | ^ + 2| + + error: unsigned json number 18446744073709551615 outside of Nix integer range diff --git a/tests/functional/lang/eval-fail-fromJSON-overflowing.nix b/tests/functional/lang/eval-fail-fromJSON-overflowing.nix new file mode 100644 index 000000000..6dfbce3f6 --- /dev/null +++ b/tests/functional/lang/eval-fail-fromJSON-overflowing.nix @@ -0,0 +1 @@ +builtins.fromJSON ''{"attr": 18446744073709551615}'' diff --git a/tests/functional/lang/eval-fail-overflowing-add.err.exp b/tests/functional/lang/eval-fail-overflowing-add.err.exp new file mode 100644 index 000000000..6458cf1c9 --- /dev/null +++ b/tests/functional/lang/eval-fail-overflowing-add.err.exp @@ -0,0 +1,6 @@ +error: integer overflow in adding 9223372036854775807 + 1 + at /pwd/lang/eval-fail-overflowing-add.nix:4:8: + 3| b = 1; + 4| in a + b + | ^ + 5| diff --git a/tests/functional/lang/eval-fail-overflowing-add.nix b/tests/functional/lang/eval-fail-overflowing-add.nix new file mode 100644 index 000000000..24258fc20 --- /dev/null +++ b/tests/functional/lang/eval-fail-overflowing-add.nix @@ -0,0 +1,4 @@ +let + a = 9223372036854775807; + b = 1; +in a + b diff --git a/tests/functional/lang/eval-fail-overflowing-div.err.exp b/tests/functional/lang/eval-fail-overflowing-div.err.exp new file mode 100644 index 000000000..8ce07d4d6 --- /dev/null +++ b/tests/functional/lang/eval-fail-overflowing-div.err.exp @@ -0,0 +1,23 @@ +error: + … while calling the 'seq' builtin + at /pwd/lang/eval-fail-overflowing-div.nix:7:4: + 6| b = -1; + 7| in builtins.seq intMin (builtins.seq b (intMin / b)) + | ^ + 8| + + … while calling the 'seq' builtin + at /pwd/lang/eval-fail-overflowing-div.nix:7:25: + 6| b = -1; + 7| in builtins.seq intMin (builtins.seq b (intMin / b)) + | ^ + 8| + + … while calling the 'div' builtin + at /pwd/lang/eval-fail-overflowing-div.nix:7:48: + 6| b = -1; + 7| in builtins.seq intMin (builtins.seq b (intMin / b)) + | ^ + 8| + + error: integer overflow in dividing -9223372036854775808 / -1 diff --git a/tests/functional/lang/eval-fail-overflowing-div.nix b/tests/functional/lang/eval-fail-overflowing-div.nix new file mode 100644 index 000000000..44fbe9d7e --- /dev/null +++ b/tests/functional/lang/eval-fail-overflowing-div.nix @@ -0,0 +1,7 @@ +let + # lol, this has to be written as an expression like this because negative + # numbers use unary negation rather than parsing directly, and 2**63 is out + # of range + intMin = -9223372036854775807 - 1; + b = -1; +in builtins.seq intMin (builtins.seq b (intMin / b)) diff --git a/tests/functional/lang/eval-fail-overflowing-mul.err.exp b/tests/functional/lang/eval-fail-overflowing-mul.err.exp new file mode 100644 index 000000000..f42b39d4d --- /dev/null +++ b/tests/functional/lang/eval-fail-overflowing-mul.err.exp @@ -0,0 +1,16 @@ +error: + … while calling the 'mul' builtin + at /pwd/lang/eval-fail-overflowing-mul.nix:3:10: + 2| a = 4294967297; + 3| in a * a * a + | ^ + 4| + + … while calling the 'mul' builtin + at /pwd/lang/eval-fail-overflowing-mul.nix:3:6: + 2| a = 4294967297; + 3| in a * a * a + | ^ + 4| + + error: integer overflow in multiplying 4294967297 * 4294967297 diff --git a/tests/functional/lang/eval-fail-overflowing-mul.nix b/tests/functional/lang/eval-fail-overflowing-mul.nix new file mode 100644 index 000000000..6081d9c7b --- /dev/null +++ b/tests/functional/lang/eval-fail-overflowing-mul.nix @@ -0,0 +1,3 @@ +let + a = 4294967297; +in a * a * a diff --git a/tests/functional/lang/eval-fail-overflowing-sub.err.exp b/tests/functional/lang/eval-fail-overflowing-sub.err.exp new file mode 100644 index 000000000..66a3a03f8 --- /dev/null +++ b/tests/functional/lang/eval-fail-overflowing-sub.err.exp @@ -0,0 +1,9 @@ +error: + … while calling the 'sub' builtin + at /pwd/lang/eval-fail-overflowing-sub.nix:4:6: + 3| b = 2; + 4| in a - b + | ^ + 5| + + error: integer overflow in subtracting -9223372036854775807 - 2 diff --git a/tests/functional/lang/eval-fail-overflowing-sub.nix b/tests/functional/lang/eval-fail-overflowing-sub.nix new file mode 100644 index 000000000..229b8c6d2 --- /dev/null +++ b/tests/functional/lang/eval-fail-overflowing-sub.nix @@ -0,0 +1,4 @@ +let + a = -9223372036854775807; + b = 2; +in a - b diff --git a/tests/unit/libexpr-support/tests/libexpr.hh b/tests/unit/libexpr-support/tests/libexpr.hh index 54a4a0e9e..045607e87 100644 --- a/tests/unit/libexpr-support/tests/libexpr.hh +++ b/tests/unit/libexpr-support/tests/libexpr.hh @@ -85,7 +85,7 @@ namespace nix { if (arg.type() != nInt) { return false; } - return arg.integer() == v; + return arg.integer().value == v; } MATCHER_P(IsFloatEq, v, fmt("The float is equal to \"%1%\"", v)) { From bf050d9e966534eeb92188da1a93ac459bed0f97 Mon Sep 17 00:00:00 2001 From: Jade Lovelace Date: Fri, 12 Jul 2024 18:20:14 +0200 Subject: [PATCH 021/718] docs: update to define integer overflow Change-Id: Ie8a1b31035f2d27a220e5df2e9e178ec3b39ee68 --- doc/manual/src/language/operators.md | 8 ++++++-- doc/manual/src/language/syntax.md | 7 +++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/doc/manual/src/language/operators.md b/doc/manual/src/language/operators.md index e1c020781..2c2dcc276 100644 --- a/doc/manual/src/language/operators.md +++ b/doc/manual/src/language/operators.md @@ -67,8 +67,12 @@ After evaluating *attrset* and *attrpath*, the computational complexity is O(log ## Arithmetic -Numbers are type-compatible: -Pure integer operations will always return integers, whereas any operation involving at least one floating point number return a floating point number. +Numbers will retain their type unless mixed with other numeric types: +Pure integer operations will always return integers, whereas any operation involving at least one floating point number returns a floating point number. + +Evaluation of the following numeric operations throws an evaluation error: +- Division by zero +- Integer overflow, that is, any operation yielding a result outside of the representable range of [Nix language integers](./syntax.md#number-literal) See also [Comparison] and [Equality]. diff --git a/doc/manual/src/language/syntax.md b/doc/manual/src/language/syntax.md index 6108bacd6..f05935502 100644 --- a/doc/manual/src/language/syntax.md +++ b/doc/manual/src/language/syntax.md @@ -183,6 +183,13 @@ This section covers syntax and semantics of the Nix language. Numbers, which can be *integers* (like `123`) or *floating point* (like `123.43` or `.27e13`). + Integers in the Nix language are 64-bit [two's complement] signed integers, with a range of -9223372036854775808 to 9223372036854775807, inclusive. + + [two's complement]: https://en.wikipedia.org/wiki/Two%27s_complement + + Note that negative numeric literals are actually parsed as unary negation of positive numeric literals. + This means that the minimum integer `-9223372036854775808` cannot be written as-is as a literal, since the positive number `9223372036854775808` is one past the maximum range. + See [arithmetic] and [comparison] operators for semantics. [arithmetic]: ./operators.md#arithmetic From 5878b1475f1c50b42672ed85e7259e7d328920e9 Mon Sep 17 00:00:00 2001 From: Jade Lovelace Date: Thu, 25 Jul 2024 23:06:53 +0200 Subject: [PATCH 022/718] doc: release notes for banning integer overflow Change-Id: Ib75ab5b8b4d879035d7ee7678f9cd0c491a39c0a --- doc/manual/rl-next/ban-integer-overflow.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 doc/manual/rl-next/ban-integer-overflow.md diff --git a/doc/manual/rl-next/ban-integer-overflow.md b/doc/manual/rl-next/ban-integer-overflow.md new file mode 100644 index 000000000..49ecfe4c6 --- /dev/null +++ b/doc/manual/rl-next/ban-integer-overflow.md @@ -0,0 +1,21 @@ +--- +synopsis: Define integer overflow in the Nix language as an error +issues: [10968] +prs: [11188] +--- + +Previously, integer overflow in the Nix language invoked C++ level signed overflow, which was undefined behaviour, but *probably* manifested as wrapping around on overflow. + +Since prior to the public release of Lix, Lix had C++ signed overflow defined to crash the process and nobody noticed this having accidentally removed overflow from the Nix language for three months until it was caught by fiddling around. +Given the significant body of actual Nix code that has been evaluated by Lix in that time, it does not appear that nixpkgs or much of importance depends on integer overflow, so it is safe to turn into an error. + +Some other overflows were fixed: +- `builtins.fromJSON` of values greater than the maximum representable value in a signed 64-bit integer will generate an error. +- `nixConfig` in flakes will no longer accept negative values for configuration options. + +Integer overflow now looks like the following: + +``` +» nix eval --expr '9223372036854775807 + 1' +error: integer overflow in adding 9223372036854775807 + 1 +``` From 6ed67d35ed51905434eba7d4a167b43aa581478f Mon Sep 17 00:00:00 2001 From: Ryan Hendrickson Date: Wed, 31 Jul 2024 17:39:43 -0400 Subject: [PATCH 023/718] docs: add variables; rework scope (#11062) Co-authored-by: Valentin Gagarin --- doc/manual/src/SUMMARY.md.in | 1 + doc/manual/src/language/identifiers.md | 2 +- doc/manual/src/language/scope.md | 32 ++++++++++++++++++-------- doc/manual/src/language/variables.md | 10 ++++++++ 4 files changed, 35 insertions(+), 10 deletions(-) create mode 100644 doc/manual/src/language/variables.md diff --git a/doc/manual/src/SUMMARY.md.in b/doc/manual/src/SUMMARY.md.in index 8739599a0..7661f5f62 100644 --- a/doc/manual/src/SUMMARY.md.in +++ b/doc/manual/src/SUMMARY.md.in @@ -28,6 +28,7 @@ - [Data Types](language/types.md) - [String context](language/string-context.md) - [Syntax and semantics](language/syntax.md) + - [Variables](language/variables.md) - [Identifiers](language/identifiers.md) - [Scoping rules](language/scope.md) - [String interpolation](language/string-interpolation.md) diff --git a/doc/manual/src/language/identifiers.md b/doc/manual/src/language/identifiers.md index c9e981da6..bd58a9b36 100644 --- a/doc/manual/src/language/identifiers.md +++ b/doc/manual/src/language/identifiers.md @@ -22,7 +22,7 @@ A name can be an [identifier](#identifier) or a [string literal](./syntax.md#str > > *name* → *identifier* | *string* -Names are used in [attribute sets](./syntax.md#attrs-literal), [`let` bindings](./syntax.md#let-expressions), and [`inherit`](./syntax.md#inheriting attributes). +Names are used in [attribute sets](./syntax.md#attrs-literal), [`let` bindings](./syntax.md#let-expressions), and [`inherit`](./syntax.md#inheriting-attributes). # Keywords diff --git a/doc/manual/src/language/scope.md b/doc/manual/src/language/scope.md index 5c6aed38d..96c7468eb 100644 --- a/doc/manual/src/language/scope.md +++ b/doc/manual/src/language/scope.md @@ -1,14 +1,28 @@ # Scoping rules -Nix is [statically scoped](https://en.wikipedia.org/wiki/Scope_(computer_science)#Lexical_scope), but with multiple scopes and shadowing rules. +A *scope* in the Nix language is a dictionary keyed by [name](./identifiers.md#names), mapping each name to an expression and a *definition type*. +The definition type is either *explicit* or *implicit*. +Each entry in this dictionary is a *definition*. -* primary scope: explicitly-bound variables - * [`let`](./syntax.md#let-expressions) - * [`inherit`](./syntax.md#inheriting-attributes) - * [function](./syntax.md#functions) arguments +Explicit definitions are created by the following expressions: +- [let-expressions](syntax.md#let-expressions) +- [recursive attribute set literals](syntax.md#recursive-sets) (`rec`) +- [function literals](syntax.md#functions) -* secondary scope: implicitly-bound variables - * [`with`](./syntax.md#with-expressions) +Implicit definitions are only created by [with-expressions](./syntax.md#with-expressions). -Primary scope takes precedence over secondary scope. -See [`with`](./syntax.md#with-expressions) for a detailed example. +Every expression is *enclosed* by a scope. +The outermost expression is enclosed by the [built-in, global scope](./builtins.md), which contains only explicit definitions. +The respective definition types *extend* their enclosing scope by adding new definitions, or replacing existing ones with the same name. +An explicit definition can replace a definition of any type; an implicit definition can only replace another implicit definition. + +Each of the above expressions defines which of its subexpressions are enclosed by the extended scope. +In all other cases, the same scope that encloses an expression is the enclosing scope for its subexpressions. + +The Nix language is [statically scoped](https://en.wikipedia.org/wiki/Scope_(computer_science)#Lexical_scope); +the value of a variable is determined only by the variable's enclosing scope, and not by the dynamic context in which the variable is evaluated. + +> **Note** +> +> Expressions entered into the [Nix REPL](@docroot@/command-ref/new-cli/nix3-repl.md) are enclosed by a scope that can be extended by command line arguments or previous REPL commands. +> These ways of extending scope are not, strictly speaking, part of the Nix language. diff --git a/doc/manual/src/language/variables.md b/doc/manual/src/language/variables.md new file mode 100644 index 000000000..af6aff8a2 --- /dev/null +++ b/doc/manual/src/language/variables.md @@ -0,0 +1,10 @@ +# Variables + +A *variable* is an [identifier](identifiers.md) used as an expression. + +> **Syntax** +> +> *expression* → *identifier* + +A variable must have the same name as a definition in the [scope](./scope.md) that encloses it. +The value of a variable is the value of the corresponding expression in the enclosing scope. From 9e8afc68e554c5c45b8e9f387d4fcf4ac0174a6a Mon Sep 17 00:00:00 2001 From: Ryan Hendrickson Date: Wed, 31 Jul 2024 19:07:57 -0400 Subject: [PATCH 024/718] docs: add language/string-literals.md --- doc/manual/redirects.js | 1 + doc/manual/src/SUMMARY.md.in | 1 + doc/manual/src/language/identifiers.md | 2 +- .../src/language/string-interpolation.md | 4 + doc/manual/src/language/string-literals.md | 189 ++++++++++++++++++ doc/manual/src/language/syntax.md | 172 +--------------- doc/manual/src/language/types.md | 2 +- 7 files changed, 199 insertions(+), 172 deletions(-) create mode 100644 doc/manual/src/language/string-literals.md diff --git a/doc/manual/redirects.js b/doc/manual/redirects.js index beef6ef4a..cb8cd18fa 100644 --- a/doc/manual/redirects.js +++ b/doc/manual/redirects.js @@ -344,6 +344,7 @@ const redirects = { }, "language/syntax.html": { "scoping-rules": "scoping.html", + "string-literal": "string-literals.html", }, "installation/installing-binary.html": { "linux": "uninstall.html#linux", diff --git a/doc/manual/src/SUMMARY.md.in b/doc/manual/src/SUMMARY.md.in index 7661f5f62..eef7d189c 100644 --- a/doc/manual/src/SUMMARY.md.in +++ b/doc/manual/src/SUMMARY.md.in @@ -29,6 +29,7 @@ - [String context](language/string-context.md) - [Syntax and semantics](language/syntax.md) - [Variables](language/variables.md) + - [String literals](language/string-literals.md) - [Identifiers](language/identifiers.md) - [Scoping rules](language/scope.md) - [String interpolation](language/string-interpolation.md) diff --git a/doc/manual/src/language/identifiers.md b/doc/manual/src/language/identifiers.md index bd58a9b36..a4153b588 100644 --- a/doc/manual/src/language/identifiers.md +++ b/doc/manual/src/language/identifiers.md @@ -16,7 +16,7 @@ An *identifier* is an [ASCII](https://en.wikipedia.org/wiki/ASCII) character seq # Names -A name can be an [identifier](#identifier) or a [string literal](./syntax.md#string-literal). +A name can be an [identifier](#identifier) or a [string literal](string-literals.md). > **Syntax** > diff --git a/doc/manual/src/language/string-interpolation.md b/doc/manual/src/language/string-interpolation.md index 1778bdfa0..27780dcbb 100644 --- a/doc/manual/src/language/string-interpolation.md +++ b/doc/manual/src/language/string-interpolation.md @@ -8,6 +8,10 @@ Such a construct is called *interpolated string*, and the expression inside is a [path]: ./types.md#type-path [attribute set]: ./types.md#attribute-set +> **Syntax** +> +> *interpolation_element* → `${` *expression* `}` + ## Examples ### String diff --git a/doc/manual/src/language/string-literals.md b/doc/manual/src/language/string-literals.md new file mode 100644 index 000000000..7605e8c61 --- /dev/null +++ b/doc/manual/src/language/string-literals.md @@ -0,0 +1,189 @@ +# String literals + +A *string literal* represents a [string](types.md#type-string) value. + +> **Syntax** +> +> *expression* → *string* +> +> *string* → `"` ( *string_char*\* [*interpolation_element*][string interpolation] )* *string_char*\* `"` +> +> *string* → `''` ( *indented_string_char*\* [*interpolation_element*][string interpolation] )* *indented_string_char*\* `''` +> +> *string* → *uri* +> +> *string_char* ~ `[^"$\\]|\$(?!\{)|\\.` +> +> *indented_string_char* ~ `[^$']|\$\$|\$(?!\{)|''[$']|''\\.|'(?!')` +> +> *uri* ~ `[A-Za-z][+\-.0-9A-Za-z]*:[!$%&'*+,\-./0-9:=?@A-Z_a-z~]+` + +Strings can be written in three ways. + +The most common way is to enclose the string between double quotes, e.g., `"foo bar"`. +Strings can span multiple lines. +The results of other expressions can be included into a string by enclosing them in `${ }`, a feature known as [string interpolation]. + +[string interpolation]: ./string-interpolation.md + +The following must be escaped to represent them within a string, by prefixing with a backslash (`\`): + +- Double quote (`"`) + +> **Example** +> +> ```nix +> "\"" +> ``` +> +> "\"" + +- Backslash (`\`) + +> **Example** +> +> ```nix +> "\\" +> ``` +> +> "\\" + +- Dollar sign followed by an opening curly bracket (`${`) – "dollar-curly" + +> **Example** +> +> ```nix +> "\${" +> ``` +> +> "\${" + +The newline, carriage return, and tab characters can be written as `\n`, `\r` and `\t`, respectively. + +A "double-dollar-curly" (`$${`) can be written literally. + +> **Example** +> +> ```nix +> "$${" +> ``` +> +> "$\${" + +String values are output on the terminal with Nix-specific escaping. +Strings written to files will contain the characters encoded by the escaping. + +The second way to write string literals is as an *indented string*, which is enclosed between pairs of *double single-quotes* (`''`), like so: + +```nix +'' +This is the first line. +This is the second line. + This is the third line. +'' +``` + +This kind of string literal intelligently strips indentation from +the start of each line. To be precise, it strips from each line a +number of spaces equal to the minimal indentation of the string as a +whole (disregarding the indentation of empty lines). For instance, +the first and second line are indented two spaces, while the third +line is indented four spaces. Thus, two spaces are stripped from +each line, so the resulting string is + +```nix +"This is the first line.\nThis is the second line.\n This is the third line.\n" +``` + +> **Note** +> +> Whitespace and newline following the opening `''` is ignored if there is no non-whitespace text on the initial line. + +> **Warning** +> +> Prefixed tab characters are not stripped. +> +> > **Example** +> > +> > The following indented string is prefixed with tabs: +> > +> > '' +> > all: +> > @echo hello +> > '' +> > +> > "\tall:\n\t\t@echo hello\n" + +Indented strings support [string interpolation]. + +The following must be escaped to represent them in an indented string: + +- `$` is escaped by prefixing it with two single quotes (`''`) + +> **Example** +> +> ```nix +> '' +> ''$ +> '' +> ``` +> +> "$\n" + +- `''` is escaped by prefixing it with one single quote (`'`) + +> **Example** +> +> ```nix +> '' +> ''' +> '' +> ``` +> +> "''\n" + +These special characters are escaped as follows: +- Linefeed (`\n`): `''\n` +- Carriage return (`\r`): `''\r` +- Tab (`\t`): `''\t` + +`''\` escapes any other character. + +A "double-dollar-curly" (`$${`) can be written literally. + +> **Example** +> +> ```nix +> '' +> $${ +> '' +> ``` +> +> "$\${\n" + +Indented strings are primarily useful in that they allow multi-line +string literals to follow the indentation of the enclosing Nix +expression, and that less escaping is typically necessary for +strings representing languages such as shell scripts and +configuration files because `''` is much less common than `"`. +Example: + +```nix +stdenv.mkDerivation { +... +postInstall = + '' + mkdir $out/bin $out/etc + cp foo $out/bin + echo "Hello World" > $out/etc/foo.conf + ${if enableBar then "cp bar $out/bin" else ""} + ''; +... +} +``` + +Finally, as a convenience, *URIs* as defined in appendix B of +[RFC 2396](http://www.ietf.org/rfc/rfc2396.txt) can be written *as +is*, without quotes. For instance, the string +`"http://example.org/foo.tar.bz2"` can also be written as +`http://example.org/foo.tar.bz2`. diff --git a/doc/manual/src/language/syntax.md b/doc/manual/src/language/syntax.md index 6108bacd6..daf073aef 100644 --- a/doc/manual/src/language/syntax.md +++ b/doc/manual/src/language/syntax.md @@ -6,175 +6,7 @@ This section covers syntax and semantics of the Nix language. ### String {#string-literal} - *Strings* can be written in three ways. - - The most common way is to enclose the string between double quotes, e.g., `"foo bar"`. - Strings can span multiple lines. - The results of other expressions can be included into a string by enclosing them in `${ }`, a feature known as [string interpolation]. - - [string interpolation]: ./string-interpolation.md - - The following must be escaped to represent them within a string, by prefixing with a backslash (`\`): - - - Double quote (`"`) - - > **Example** - > - > ```nix - > "\"" - > ``` - > - > "\"" - - - Backslash (`\`) - - > **Example** - > - > ```nix - > "\\" - > ``` - > - > "\\" - - - Dollar sign followed by an opening curly bracket (`${`) – "dollar-curly" - - > **Example** - > - > ```nix - > "\${" - > ``` - > - > "\${" - - The newline, carriage return, and tab characters can be written as `\n`, `\r` and `\t`, respectively. - - A "double-dollar-curly" (`$${`) can be written literally. - - > **Example** - > - > ```nix - > "$${" - > ``` - > - > "$\${" - - String values are output on the terminal with Nix-specific escaping. - Strings written to files will contain the characters encoded by the escaping. - - The second way to write string literals is as an *indented string*, which is enclosed between pairs of *double single-quotes* (`''`), like so: - - ```nix - '' - This is the first line. - This is the second line. - This is the third line. - '' - ``` - - This kind of string literal intelligently strips indentation from - the start of each line. To be precise, it strips from each line a - number of spaces equal to the minimal indentation of the string as a - whole (disregarding the indentation of empty lines). For instance, - the first and second line are indented two spaces, while the third - line is indented four spaces. Thus, two spaces are stripped from - each line, so the resulting string is - - ```nix - "This is the first line.\nThis is the second line.\n This is the third line.\n" - ``` - - > **Note** - > - > Whitespace and newline following the opening `''` is ignored if there is no non-whitespace text on the initial line. - - > **Warning** - > - > Prefixed tab characters are not stripped. - > - > > **Example** - > > - > > The following indented string is prefixed with tabs: - > > - > > '' - > > all: - > > @echo hello - > > '' - > > - > > "\tall:\n\t\t@echo hello\n" - - Indented strings support [string interpolation]. - - The following must be escaped to represent them in an indented string: - - - `$` is escaped by prefixing it with two single quotes (`''`) - - > **Example** - > - > ```nix - > '' - > ''$ - > '' - > ``` - > - > "$\n" - - - `''` is escaped by prefixing it with one single quote (`'`) - - > **Example** - > - > ```nix - > '' - > ''' - > '' - > ``` - > - > "''\n" - - These special characters are escaped as follows: - - Linefeed (`\n`): `''\n` - - Carriage return (`\r`): `''\r` - - Tab (`\t`): `''\t` - - `''\` escapes any other character. - - A "double-dollar-curly" (`$${`) can be written literally. - - > **Example** - > - > ```nix - > '' - > $${ - > '' - > ``` - > - > "$\${\n" - - Indented strings are primarily useful in that they allow multi-line - string literals to follow the indentation of the enclosing Nix - expression, and that less escaping is typically necessary for - strings representing languages such as shell scripts and - configuration files because `''` is much less common than `"`. - Example: - - ```nix - stdenv.mkDerivation { - ... - postInstall = - '' - mkdir $out/bin $out/etc - cp foo $out/bin - echo "Hello World" > $out/etc/foo.conf - ${if enableBar then "cp bar $out/bin" else ""} - ''; - ... - } - ``` - - Finally, as a convenience, *URIs* as defined in appendix B of - [RFC 2396](http://www.ietf.org/rfc/rfc2396.txt) can be written *as - is*, without quotes. For instance, the string - `"http://example.org/foo.tar.bz2"` can also be written as - `http://example.org/foo.tar.bz2`. +See [String literals](string-literals.md). ### Number {#number-literal} @@ -253,7 +85,7 @@ Attribute sets are written enclosed in curly brackets (`{ }`). Attribute names and attribute values are separated by an equal sign (`=`). Each value can be an arbitrary expression, terminated by a semicolon (`;`) -An attribute name is a string without context, and is denoted by a [name] (an [identifier](./identifiers.md#identifiers) or [string literal](#string-literal)). +An attribute name is a string without context, and is denoted by a [name] (an [identifier](./identifiers.md#identifiers) or [string literal](string-literals.md)). [name]: ./identifiers.md#names diff --git a/doc/manual/src/language/types.md b/doc/manual/src/language/types.md index 229756e6b..82184a8b0 100644 --- a/doc/manual/src/language/types.md +++ b/doc/manual/src/language/types.md @@ -45,7 +45,7 @@ The function [`builtins.isBool`](builtins.md#builtins-isBool) can be used to det A _string_ in the Nix language is an immutable, finite-length sequence of bytes, along with a [string context](string-context.md). Nix does not assume or support working natively with character encodings. -String values without string context can be expressed as [string literals](syntax.md#string-literal). +String values without string context can be expressed as [string literals](string-literals.md). The function [`builtins.isString`](builtins.md#builtins-isString) can be used to determine if a value is a string. ### Path {#type-path} From 17318bc70dd0a3712d0a2c94a180dd9f614c97b0 Mon Sep 17 00:00:00 2001 From: Ryan Hendrickson Date: Wed, 31 Jul 2024 19:22:17 -0400 Subject: [PATCH 025/718] docs: fix string literal example formatting --- doc/manual/src/language/string-literals.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/doc/manual/src/language/string-literals.md b/doc/manual/src/language/string-literals.md index 7605e8c61..8f4b75f3e 100644 --- a/doc/manual/src/language/string-literals.md +++ b/doc/manual/src/language/string-literals.md @@ -36,7 +36,7 @@ The following must be escaped to represent them within a string, by prefixing wi > "\"" > ``` > -> "\"" +> "\"" - Backslash (`\`) @@ -46,7 +46,7 @@ The following must be escaped to represent them within a string, by prefixing wi > "\\" > ``` > -> "\\" +> "\\" - Dollar sign followed by an opening curly bracket (`${`) – "dollar-curly" @@ -56,7 +56,7 @@ The following must be escaped to represent them within a string, by prefixing wi > "\${" > ``` > -> "\${" +> "\${" The newline, carriage return, and tab characters can be written as `\n`, `\r` and `\t`, respectively. @@ -68,7 +68,7 @@ A "double-dollar-curly" (`$${`) can be written literally. > "$${" > ``` > -> "$\${" +> "$\${" String values are output on the terminal with Nix-specific escaping. Strings written to files will contain the characters encoded by the escaping. @@ -107,10 +107,11 @@ each line, so the resulting string is > > > > The following indented string is prefixed with tabs: > > -> > '' +> >
''
 > > 	all:
 > > 		@echo hello
 > > ''
+> > 
> > > > "\tall:\n\t\t@echo hello\n" From 617e711820762d27285eb8710ce42d52f6448acd Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 1 Aug 2024 10:41:42 +0200 Subject: [PATCH 026/718] 'build' is now 'build.nix' --- maintainers/upload-release.pl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/maintainers/upload-release.pl b/maintainers/upload-release.pl index 4c4e2bd6f..731988568 100755 --- a/maintainers/upload-release.pl +++ b/maintainers/upload-release.pl @@ -42,7 +42,7 @@ my $flakeUrl = $evalInfo->{flake}; my $flakeInfo = decode_json(`nix flake metadata --json "$flakeUrl"` or die) if $flakeUrl; my $nixRev = ($flakeInfo ? $flakeInfo->{revision} : $evalInfo->{jobsetevalinputs}->{nix}->{revision}) or die; -my $buildInfo = decode_json(fetch("$evalUrl/job/build.x86_64-linux", 'application/json')); +my $buildInfo = decode_json(fetch("$evalUrl/job/build.nix.x86_64-linux", 'application/json')); #print Dumper($buildInfo); my $releaseName = $buildInfo->{nixname}; @@ -91,7 +91,7 @@ sub getStorePath { sub copyManual { my $manual; eval { - $manual = getStorePath("build.x86_64-linux", "doc"); + $manual = getStorePath("build.nix.x86_64-linux", "doc"); }; if ($@) { warn "$@"; @@ -240,12 +240,12 @@ if ($haveDocker) { # Upload nix-fallback-paths.nix. write_file("$tmpDir/fallback-paths.nix", "{\n" . - " x86_64-linux = \"" . getStorePath("build.x86_64-linux") . "\";\n" . - " i686-linux = \"" . getStorePath("build.i686-linux") . "\";\n" . - " aarch64-linux = \"" . getStorePath("build.aarch64-linux") . "\";\n" . - " riscv64-linux = \"" . getStorePath("buildCross.riscv64-unknown-linux-gnu.x86_64-linux") . "\";\n" . - " x86_64-darwin = \"" . getStorePath("build.x86_64-darwin") . "\";\n" . - " aarch64-darwin = \"" . getStorePath("build.aarch64-darwin") . "\";\n" . + " x86_64-linux = \"" . getStorePath("build.nix.x86_64-linux") . "\";\n" . + " i686-linux = \"" . getStorePath("build.nix.i686-linux") . "\";\n" . + " aarch64-linux = \"" . getStorePath("build.nix.aarch64-linux") . "\";\n" . + " riscv64-linux = \"" . getStorePath("buildCross.nix.riscv64-unknown-linux-gnu.x86_64-linux") . "\";\n" . + " x86_64-darwin = \"" . getStorePath("build.nix.x86_64-darwin") . "\";\n" . + " aarch64-darwin = \"" . getStorePath("build.nix.aarch64-darwin") . "\";\n" . "}\n"); # Upload release files to S3. From 30aca6f243d8d5dcdbbfcf2a36bcdefa9d2aeeee Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 1 Aug 2024 10:43:00 +0200 Subject: [PATCH 027/718] Bump version --- .version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.version b/.version index ad2261920..5c18f9195 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -2.24.0 +2.25.0 From b291b61089da1121145d92d6747ad2b18737ad9f Mon Sep 17 00:00:00 2001 From: Ryan Hendrickson Date: Thu, 1 Aug 2024 05:14:49 -0400 Subject: [PATCH 028/718] docs: editorial quibbles (#11232) --- doc/manual/src/language/identifiers.md | 3 ++- doc/manual/src/language/scope.md | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/manual/src/language/identifiers.md b/doc/manual/src/language/identifiers.md index bd58a9b36..861ee3e20 100644 --- a/doc/manual/src/language/identifiers.md +++ b/doc/manual/src/language/identifiers.md @@ -16,13 +16,14 @@ An *identifier* is an [ASCII](https://en.wikipedia.org/wiki/ASCII) character seq # Names -A name can be an [identifier](#identifier) or a [string literal](./syntax.md#string-literal). +A *name* can be written as an [identifier](#identifier) or a [string literal](./syntax.md#string-literal). > **Syntax** > > *name* → *identifier* | *string* Names are used in [attribute sets](./syntax.md#attrs-literal), [`let` bindings](./syntax.md#let-expressions), and [`inherit`](./syntax.md#inheriting-attributes). +Two names are the same if they represent the same sequence of characters, regardless of whether they are written as identifiers or strings. # Keywords diff --git a/doc/manual/src/language/scope.md b/doc/manual/src/language/scope.md index 96c7468eb..9373324e2 100644 --- a/doc/manual/src/language/scope.md +++ b/doc/manual/src/language/scope.md @@ -13,7 +13,7 @@ Implicit definitions are only created by [with-expressions](./syntax.md#with-exp Every expression is *enclosed* by a scope. The outermost expression is enclosed by the [built-in, global scope](./builtins.md), which contains only explicit definitions. -The respective definition types *extend* their enclosing scope by adding new definitions, or replacing existing ones with the same name. +The expressions listed above *extend* their enclosing scope by adding new definitions, or replacing existing ones with the same name. An explicit definition can replace a definition of any type; an implicit definition can only replace another implicit definition. Each of the above expressions defines which of its subexpressions are enclosed by the extended scope. From 9b5b7b796341eca437fe08bb278c49dfbae2deaa Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 1 Aug 2024 16:51:57 +0200 Subject: [PATCH 029/718] Fix the S3 store It was failing with: error: AWS error fetching 'nix-cache-info': The specified bucket does not exist because `S3BinaryCacheStoreImpl` had a `bucketName` field that shadowed the inherited `bucketName from `S3BinaryCacheStoreConfig`. --- src/libstore/s3-binary-cache-store.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/libstore/s3-binary-cache-store.cc b/src/libstore/s3-binary-cache-store.cc index 92ab47cd6..21175b1eb 100644 --- a/src/libstore/s3-binary-cache-store.cc +++ b/src/libstore/s3-binary-cache-store.cc @@ -220,8 +220,6 @@ std::string S3BinaryCacheStoreConfig::doc() struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual S3BinaryCacheStore { - std::string bucketName; - Stats stats; S3Helper s3Helper; From 739418504c4d2f28fb5f45151b1c83707c3571e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Fri, 2 Aug 2024 11:12:06 +0200 Subject: [PATCH 030/718] allow to c api with older c versions In the FFI world we have many tools that are not gcc/clang and therefore not always support the latest C standard. This fixes support with cffi i.e. used in https://github.com/tweag/python-nix --- src/libexpr-c/nix_api_expr.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/libexpr-c/nix_api_expr.h b/src/libexpr-c/nix_api_expr.h index adf8b65b1..1764b49f3 100644 --- a/src/libexpr-c/nix_api_expr.h +++ b/src/libexpr-c/nix_api_expr.h @@ -14,6 +14,16 @@ #include "nix_api_util.h" #include +#ifndef __has_c_attribute +# define __has_c_attribute(x) 0 +#endif + +#if __has_c_attribute(deprecated) +# define NIX_DEPRECATED(msg) [[deprecated(msg)]] +#else +# define NIX_DEPRECATED(msg) +#endif + #ifdef __cplusplus extern "C" { #endif @@ -45,7 +55,7 @@ typedef struct EvalState EvalState; // nix::EvalState * @see nix_value_incref, nix_value_decref */ typedef struct nix_value nix_value; -[[deprecated("use nix_value instead")]] typedef nix_value Value; +NIX_DEPRECATED("use nix_value instead") typedef nix_value Value; // Function prototypes /** From 088fa815d324e9c6fddf2f0358ac9b64ba6d42c7 Mon Sep 17 00:00:00 2001 From: 0x5a4 <54070204+0x5a4@users.noreply.github.com> Date: Thu, 1 Aug 2024 23:37:45 +0200 Subject: [PATCH 031/718] fix: bash mangles flake ref completion --- misc/bash/completion.sh | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/misc/bash/completion.sh b/misc/bash/completion.sh index 9af695f5a..c4ba96cd3 100644 --- a/misc/bash/completion.sh +++ b/misc/bash/completion.sh @@ -12,9 +12,16 @@ function _complete_nix { elif [[ $completion == attrs ]]; then compopt -o nospace fi - else - COMPREPLY+=("$completion") + continue fi + + if [[ "${cur}" =~ "=" ]]; then + # drop everything up to the first =. if a = is included, bash assumes this to be + # an arg=value argument and the completion gets mangled (see #11208) + completion="${completion#*=}" + fi + + COMPREPLY+=("${completion}") done < <(NIX_GET_COMPLETIONS=$cword "${words[@]}" 2>/dev/null) __ltrim_colon_completions "$cur" } From 5a6e28e1667386b6ce4310bb07ed196432d7a9ec Mon Sep 17 00:00:00 2001 From: a-kenji Date: Mon, 5 Aug 2024 01:03:21 +0200 Subject: [PATCH 032/718] docs: installable remove alternate expression flag (#11254) --- src/nix/nix.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/nix/nix.md b/src/nix/nix.md index 56587d0b2..443757a05 100644 --- a/src/nix/nix.md +++ b/src/nix/nix.md @@ -65,7 +65,7 @@ The following types of installable are supported by most commands: - [Nix file](#nix-file), optionally qualified by an attribute path - Specified with `--file`/`-f` - [Nix expression](#nix-expression), optionally qualified by an attribute path - - Specified with `--expr`/`-E` + - Specified with `--expr` For most commands, if no installable is specified, `.` is assumed. That is, Nix will operate on the default flake output attribute of the flake in the current directory. @@ -200,17 +200,17 @@ operate are determined as follows: … ``` - For `-e`/`--expr` and `-f`/`--file`, the derivation output is specified as part of the attribute path: + For `--expr` and `-f`/`--file`, the derivation output is specified as part of the attribute path: ```console $ nix build -f '' 'glibc^dev,static' - $ nix build --impure -E 'import { }' 'glibc^dev,static' + $ nix build --impure --expr 'import { }' 'glibc^dev,static' ``` This syntax is the same even if the actual attribute path is empty: ```console - $ nix build -E 'let pkgs = import { }; in pkgs.glibc' '^dev,static' + $ nix build --impure --expr 'let pkgs = import { }; in pkgs.glibc' '^dev,static' ``` * You can also specify that *all* outputs should be used using the From 2950f9e18af1bd57b566b8c0b4df71022edb3b80 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 5 Aug 2024 11:38:38 +0200 Subject: [PATCH 033/718] Add a VM test for S3BinaryCacheStore Fixes #11238. --- tests/nixos/default.nix | 2 + tests/nixos/nix-copy-closure.nix | 2 +- tests/nixos/s3-binary-cache-store.nix | 63 +++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 tests/nixos/s3-binary-cache-store.nix diff --git a/tests/nixos/default.nix b/tests/nixos/default.nix index c0c7b42fd..66174c928 100644 --- a/tests/nixos/default.nix +++ b/tests/nixos/default.nix @@ -146,4 +146,6 @@ in functional_root = runNixOSTestFor "x86_64-linux" ./functional/as-root.nix; user-sandboxing = runNixOSTestFor "x86_64-linux" ./user-sandboxing; + + s3-binary-cache-store = runNixOSTestFor "x86_64-linux" ./s3-binary-cache-store.nix; } diff --git a/tests/nixos/nix-copy-closure.nix b/tests/nixos/nix-copy-closure.nix index 66cbfb033..b9daa0a1f 100644 --- a/tests/nixos/nix-copy-closure.nix +++ b/tests/nixos/nix-copy-closure.nix @@ -1,6 +1,6 @@ # Test ‘nix-copy-closure’. -{ lib, config, nixpkgs, hostPkgs, ... }: +{ lib, config, nixpkgs, ... }: let pkgs = config.nodes.client.nixpkgs.pkgs; diff --git a/tests/nixos/s3-binary-cache-store.nix b/tests/nixos/s3-binary-cache-store.nix new file mode 100644 index 000000000..015457968 --- /dev/null +++ b/tests/nixos/s3-binary-cache-store.nix @@ -0,0 +1,63 @@ +{ lib, config, nixpkgs, ... }: + +let + pkgs = config.nodes.client.nixpkgs.pkgs; + + pkgA = pkgs.cowsay; + + accessKey = "BKIKJAA5BMMU2RHO6IBB"; + secretKey = "V7f1CwQqAcwo80UEIJEjc5gVQUSSx5ohQ9GSrr12"; + env = "AWS_ACCESS_KEY_ID=${accessKey} AWS_SECRET_ACCESS_KEY=${secretKey}"; + + storeUrl = "s3://my-cache?endpoint=http://server:9000®ion=eu-west-1"; + +in { + name = "nix-copy-closure"; + + nodes = + { server = + { config, lib, pkgs, ... }: + { virtualisation.writableStore = true; + virtualisation.additionalPaths = [ pkgA ]; + environment.systemPackages = [ pkgs.minio-client ]; + nix.extraOptions = "experimental-features = nix-command"; + services.minio = { + enable = true; + region = "eu-west-1"; + rootCredentialsFile = pkgs.writeText "minio-credentials-full" '' + MINIO_ROOT_USER=${accessKey} + MINIO_ROOT_PASSWORD=${secretKey} + ''; + }; + networking.firewall.allowedTCPPorts = [ 9000 ]; + }; + + client = + { config, pkgs, ... }: + { virtualisation.writableStore = true; + nix.extraOptions = "experimental-features = nix-command"; + }; + }; + + testScript = { nodes }: '' + # fmt: off + start_all() + + # Create a binary cache. + server.wait_for_unit("minio") + + server.succeed("mc config host add minio http://localhost:9000 ${accessKey} ${secretKey} --api s3v4") + server.succeed("mc mb minio/my-cache") + + server.succeed("${env} nix copy --to '${storeUrl}' ${pkgA}") + + # Copy a package from the binary cache. + client.fail("nix path-info ${pkgA}") + + client.succeed("${env} nix store info --store '${storeUrl}' >&2") + + client.succeed("${env} nix copy --no-check-sigs --from '${storeUrl}' ${pkgA}") + + client.succeed("nix path-info ${pkgA}") + ''; +} From 547e808a7528e9705fb2fec8014113a483b2006d Mon Sep 17 00:00:00 2001 From: Jeremy Kolb Date: Thu, 27 Jun 2024 15:35:55 -0400 Subject: [PATCH 034/718] nix flake show: add the description if it exists --- src/nix/flake.cc | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 3f9f8f99b..8eb88d708 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -1243,25 +1243,30 @@ struct CmdFlakeShow : FlakeCommand, MixJSON auto showDerivation = [&]() { auto name = visitor.getAttr(state->sName)->getString(); + std::optional description; + if (auto aMeta = visitor.maybeGetAttr(state->sMeta)) { + if (auto aDescription = aMeta->maybeGetAttr(state->sDescription)) + description = aDescription->getString(); + } + if (json) { - std::optional description; - if (auto aMeta = visitor.maybeGetAttr(state->sMeta)) { - if (auto aDescription = aMeta->maybeGetAttr(state->sDescription)) - description = aDescription->getString(); - } j.emplace("type", "derivation"); j.emplace("name", name); if (description) j.emplace("description", *description); } else { - logger->cout("%s: %s '%s'", - headerPrefix, + auto type = attrPath.size() == 2 && attrPathS[0] == "devShell" ? "development environment" : attrPath.size() >= 2 && attrPathS[0] == "devShells" ? "development environment" : attrPath.size() == 3 && attrPathS[0] == "checks" ? "derivation" : attrPath.size() >= 1 && attrPathS[0] == "hydraJobs" ? "derivation" : - "package", - name); + "package"; + if (description) { + logger->cout("%s: %s '%s' - '%s'", headerPrefix, type, name, *description); + } + else { + logger->cout("%s: %s '%s'", headerPrefix, type, name); + } } }; From 07d0527c0c2154c0868e242fb1d0e8da34199eeb Mon Sep 17 00:00:00 2001 From: Jeremy Kolb Date: Mon, 8 Jul 2024 11:56:41 -0400 Subject: [PATCH 035/718] nix flake show: Only print up to the first new line if it exists. --- src/nix/flake.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 8eb88d708..9c6469a08 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -1262,7 +1262,11 @@ struct CmdFlakeShow : FlakeCommand, MixJSON attrPath.size() >= 1 && attrPathS[0] == "hydraJobs" ? "derivation" : "package"; if (description) { - logger->cout("%s: %s '%s' - '%s'", headerPrefix, type, name, *description); + // Handle new lines in descriptions. + auto index = description->find('\n'); + std::string_view sanitized_description(description->data(), index != std::string::npos ? index : description->size()); + + logger->cout("%s: %s '%s' - '%s'", headerPrefix, type, name, sanitized_description); } else { logger->cout("%s: %s '%s'", headerPrefix, type, name); From 59b6aafadb66fcc6b2b7a2a6a72680ef58f684c7 Mon Sep 17 00:00:00 2001 From: Jeremy Kolb Date: Mon, 8 Jul 2024 15:25:17 -0400 Subject: [PATCH 036/718] add tests --- tests/functional/flakes/show.sh | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/functional/flakes/show.sh b/tests/functional/flakes/show.sh index 22e1f4193..2911790de 100755 --- a/tests/functional/flakes/show.sh +++ b/tests/functional/flakes/show.sh @@ -87,3 +87,22 @@ assert show_output.legacyPackages.${builtins.currentSystem}.AAAAAASomeThingsFail assert show_output.legacyPackages.${builtins.currentSystem}.simple.name == "simple"; true ' + +cat >flake.nix< ./show-output.txt +test "$(awk -F '[:] ' '/aNoDescription/{print $NF}' ./show-output.txt)" = "package 'simple'" +test "$(awk -F '[:] ' '/bOneLineDescription/{print $NF}' ./show-output.txt)" = "package 'simple' - 'one line'" +test "$(awk -F '[:] ' '/cMultiLineDescription/{print $NF}' ./show-output.txt)" = "package 'simple' - 'line one'" From f22cf1fd3851ebac8a0a2040428ba9ce92a209c6 Mon Sep 17 00:00:00 2001 From: Jeremy Kolb Date: Mon, 8 Jul 2024 16:31:33 -0400 Subject: [PATCH 037/718] Handle long strings, embedded new lines and empty descriptions --- src/nix/flake.cc | 21 ++++++++++++++++----- tests/functional/flakes/show.sh | 8 +++++++- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 9c6469a08..89a1326fd 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -1261,12 +1261,23 @@ struct CmdFlakeShow : FlakeCommand, MixJSON attrPath.size() == 3 && attrPathS[0] == "checks" ? "derivation" : attrPath.size() >= 1 && attrPathS[0] == "hydraJobs" ? "derivation" : "package"; - if (description) { - // Handle new lines in descriptions. - auto index = description->find('\n'); - std::string_view sanitized_description(description->data(), index != std::string::npos ? index : description->size()); + if (description && !description->empty()) { + // Trim the string and only display the first line of the description. + auto trimmed = nix::trim(*description); + auto newLinePos = trimmed.find('\n'); + auto length = newLinePos != std::string::npos ? newLinePos : trimmed.size(); - logger->cout("%s: %s '%s' - '%s'", headerPrefix, type, name, sanitized_description); + // If the string is too long then resize add ellipses + std::string desc; + if (length > 80) { + trimmed.resize(80); + desc = trimmed.append("..."); + } + else { + desc = trimmed.substr(0, length); + } + + logger->cout("%s: %s '%s' - '%s'", headerPrefix, type, name, desc); } else { logger->cout("%s: %s '%s'", headerPrefix, type, name); diff --git a/tests/functional/flakes/show.sh b/tests/functional/flakes/show.sh index 2911790de..d60adb99f 100755 --- a/tests/functional/flakes/show.sh +++ b/tests/functional/flakes/show.sh @@ -95,9 +95,13 @@ cat >flake.nix< ./show-output.txt test "$(awk -F '[:] ' '/aNoDescription/{print $NF}' ./show-output.txt)" = "package 'simple'" test "$(awk -F '[:] ' '/bOneLineDescription/{print $NF}' ./show-output.txt)" = "package 'simple' - 'one line'" test "$(awk -F '[:] ' '/cMultiLineDescription/{print $NF}' ./show-output.txt)" = "package 'simple' - 'line one'" +test "$(awk -F '[:] ' '/dLongDescription/{print $NF}' ./show-output.txt)" = "package 'simple' - '01234567890123456789012345678901234567890123456789012345678901234567890123456789...'" +test "$(awk -F '[:] ' '/eEmptyDescription/{print $NF}' ./show-output.txt)" = "package 'simple'" From 930818bb1daf97d5751b67fc6399323b3557bb7a Mon Sep 17 00:00:00 2001 From: Jeremy Kolb Date: Thu, 18 Jul 2024 09:42:48 -0400 Subject: [PATCH 038/718] Account for total length of 80 --- src/nix/flake.cc | 4 ++-- tests/functional/flakes/show.sh | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 89a1326fd..48bec08c1 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -1269,8 +1269,8 @@ struct CmdFlakeShow : FlakeCommand, MixJSON // If the string is too long then resize add ellipses std::string desc; - if (length > 80) { - trimmed.resize(80); + if (length > 77) { + trimmed.resize(77); desc = trimmed.append("..."); } else { diff --git a/tests/functional/flakes/show.sh b/tests/functional/flakes/show.sh index d60adb99f..3d91613ee 100755 --- a/tests/functional/flakes/show.sh +++ b/tests/functional/flakes/show.sh @@ -110,5 +110,5 @@ nix flake show > ./show-output.txt test "$(awk -F '[:] ' '/aNoDescription/{print $NF}' ./show-output.txt)" = "package 'simple'" test "$(awk -F '[:] ' '/bOneLineDescription/{print $NF}' ./show-output.txt)" = "package 'simple' - 'one line'" test "$(awk -F '[:] ' '/cMultiLineDescription/{print $NF}' ./show-output.txt)" = "package 'simple' - 'line one'" -test "$(awk -F '[:] ' '/dLongDescription/{print $NF}' ./show-output.txt)" = "package 'simple' - '01234567890123456789012345678901234567890123456789012345678901234567890123456789...'" +test "$(awk -F '[:] ' '/dLongDescription/{print $NF}' ./show-output.txt)" = "package 'simple' - '01234567890123456789012345678901234567890123456789012345678901234567890123456...'" test "$(awk -F '[:] ' '/eEmptyDescription/{print $NF}' ./show-output.txt)" = "package 'simple'" From 9d2d4d11e6fad32d97cb3605614835a16c5b5cdf Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 5 Aug 2024 12:34:05 -0400 Subject: [PATCH 039/718] Split tests, organize more string functions The test split matches PR #8920, so the utility files and tests files are once again to 1-1. The string changes continues what was started in PR #11093. --- src/libexpr/eval-cache.cc | 2 + src/libutil/strings-inline.hh | 41 ++ src/libutil/strings.cc | 13 +- src/libutil/strings.hh | 28 ++ src/libutil/util.cc | 18 - src/libutil/util.hh | 44 +- tests/unit/libutil/file-system.cc | 258 +++++++++++ tests/unit/libutil/meson.build | 5 +- tests/unit/libutil/processes.cc | 17 + tests/unit/libutil/strings.cc | 151 +++++++ tests/unit/libutil/terminal.cc | 60 +++ tests/unit/libutil/tests.cc | 703 ------------------------------ tests/unit/libutil/util.cc | 385 ++++++++++++++++ 13 files changed, 959 insertions(+), 766 deletions(-) create mode 100644 tests/unit/libutil/file-system.cc create mode 100644 tests/unit/libutil/processes.cc create mode 100644 tests/unit/libutil/terminal.cc delete mode 100644 tests/unit/libutil/tests.cc create mode 100644 tests/unit/libutil/util.cc diff --git a/src/libexpr/eval-cache.cc b/src/libexpr/eval-cache.cc index 26352187e..3d77c029e 100644 --- a/src/libexpr/eval-cache.cc +++ b/src/libexpr/eval-cache.cc @@ -4,6 +4,8 @@ #include "eval.hh" #include "eval-inline.hh" #include "store-api.hh" +// Need specialization involving `SymbolStr` just in this one module. +#include "strings-inline.hh" namespace nix::eval_cache { diff --git a/src/libutil/strings-inline.hh b/src/libutil/strings-inline.hh index 10c1b19e6..d254d486d 100644 --- a/src/libutil/strings-inline.hh +++ b/src/libutil/strings-inline.hh @@ -4,6 +4,21 @@ namespace nix { +template +C tokenizeString(std::string_view s, std::string_view separators) +{ + C result; + auto pos = s.find_first_not_of(separators, 0); + while (pos != s.npos) { + auto end = s.find_first_of(separators, pos + 1); + if (end == s.npos) + end = s.size(); + result.insert(result.end(), std::string(s, pos, end - pos)); + pos = s.find_first_not_of(separators, end); + } + return result; +} + template std::string concatStringsSep(const std::string_view sep, const C & ss) { @@ -28,4 +43,30 @@ std::string concatStringsSep(const std::string_view sep, const C & ss) return s; } +template +std::string dropEmptyInitThenConcatStringsSep(const std::string_view sep, const C & ss) +{ + size_t size = 0; + + // TODO? remove to make sure we don't rely on the empty item ignoring behavior, + // or just get rid of this function by understanding the remaining calls. + // for (auto & i : ss) { + // // Make sure we don't rely on the empty item ignoring behavior + // assert(!i.empty()); + // break; + // } + + // need a cast to string_view since this is also called with Symbols + for (const auto & s : ss) + size += sep.size() + std::string_view(s).size(); + std::string s; + s.reserve(size); + for (auto & i : ss) { + if (s.size() != 0) + s += sep; + s += i; + } + return s; +} + } // namespace nix diff --git a/src/libutil/strings.cc b/src/libutil/strings.cc index 7ec618bf4..2bb7f8c0a 100644 --- a/src/libutil/strings.cc +++ b/src/libutil/strings.cc @@ -1,12 +1,15 @@ #include #include "strings-inline.hh" -#include "util.hh" namespace nix { -template std::string concatStringsSep(std::string_view, const Strings &); -template std::string concatStringsSep(std::string_view, const StringSet &); +template std::list tokenizeString(std::string_view s, std::string_view separators); +template std::set tokenizeString(std::string_view s, std::string_view separators); +template std::vector tokenizeString(std::string_view s, std::string_view separators); + +template std::string concatStringsSep(std::string_view, const std::list &); +template std::string concatStringsSep(std::string_view, const std::set &); template std::string concatStringsSep(std::string_view, const std::vector &); typedef std::string_view strings_2[2]; @@ -16,4 +19,8 @@ template std::string concatStringsSep(std::string_view, const strings_3 &); typedef std::string_view strings_4[4]; template std::string concatStringsSep(std::string_view, const strings_4 &); +template std::string dropEmptyInitThenConcatStringsSep(std::string_view, const std::list &); +template std::string dropEmptyInitThenConcatStringsSep(std::string_view, const std::set &); +template std::string dropEmptyInitThenConcatStringsSep(std::string_view, const std::vector &); + } // namespace nix diff --git a/src/libutil/strings.hh b/src/libutil/strings.hh index 3b112c409..6e991e490 100644 --- a/src/libutil/strings.hh +++ b/src/libutil/strings.hh @@ -8,6 +8,18 @@ namespace nix { +/** + * String tokenizer. + * + * See also `basicSplitString()`, which preserves empty strings between separators, as well as at the start and end. + */ +template +C tokenizeString(std::string_view s, std::string_view separators = " \t\n\r"); + +extern template std::list tokenizeString(std::string_view s, std::string_view separators); +extern template std::set tokenizeString(std::string_view s, std::string_view separators); +extern template std::vector tokenizeString(std::string_view s, std::string_view separators); + /** * Concatenate the given strings with a separator between the elements. */ @@ -18,4 +30,20 @@ extern template std::string concatStringsSep(std::string_view, const std::list &); extern template std::string concatStringsSep(std::string_view, const std::vector &); +/** + * Ignore any empty strings at the start of the list, and then concatenate the + * given strings with a separator between the elements. + * + * @deprecated This function exists for historical reasons. You probably just + * want to use `concatStringsSep`. + */ +template +[[deprecated( + "Consider removing the empty string dropping behavior. If acceptable, use concatStringsSep instead.")]] std::string +dropEmptyInitThenConcatStringsSep(const std::string_view sep, const C & ss); + +extern template std::string dropEmptyInitThenConcatStringsSep(std::string_view, const std::list &); +extern template std::string dropEmptyInitThenConcatStringsSep(std::string_view, const std::set &); +extern template std::string dropEmptyInitThenConcatStringsSep(std::string_view, const std::vector &); + } diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 698e181a1..460802be3 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -53,24 +53,6 @@ std::vector stringsToCharPtrs(const Strings & ss) ////////////////////////////////////////////////////////////////////// -template C tokenizeString(std::string_view s, std::string_view separators) -{ - C result; - auto pos = s.find_first_not_of(separators, 0); - while (pos != s.npos) { - auto end = s.find_first_of(separators, pos + 1); - if (end == s.npos) end = s.size(); - result.insert(result.end(), std::string(s, pos, end - pos)); - pos = s.find_first_not_of(separators, end); - } - return result; -} - -template Strings tokenizeString(std::string_view s, std::string_view separators); -template StringSet tokenizeString(std::string_view s, std::string_view separators); -template std::vector tokenizeString(std::string_view s, std::string_view separators); - - std::string chomp(std::string_view 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 877d15279..25128a900 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -28,49 +28,11 @@ std::vector stringsToCharPtrs(const Strings & ss); MakeError(FormatError, Error); -/** - * String tokenizer. - */ -template C tokenizeString(std::string_view s, std::string_view separators = " \t\n\r"); - - -/** - * Ignore any empty strings at the start of the list, and then concatenate the - * given strings with a separator between the elements. - * - * @deprecated This function exists for historical reasons. You probably just - * want to use `concatStringsSep`. - */ -template -[[deprecated("Consider removing the empty string dropping behavior. If acceptable, use concatStringsSep instead.")]] -std::string dropEmptyInitThenConcatStringsSep(const std::string_view sep, const C & ss) -{ - size_t size = 0; - - // TODO? remove to make sure we don't rely on the empty item ignoring behavior, - // or just get rid of this function by understanding the remaining calls. - // for (auto & i : ss) { - // // Make sure we don't rely on the empty item ignoring behavior - // assert(!i.empty()); - // break; - // } - - // need a cast to string_view since this is also called with Symbols - for (const auto & s : ss) size += sep.size() + std::string_view(s).size(); - std::string s; - s.reserve(size); - for (auto & i : ss) { - if (s.size() != 0) s += sep; - s += i; - } - return s; -} - -template -auto concatStrings(Parts && ... parts) +template +auto concatStrings(Parts &&... parts) -> std::enable_if_t<(... && std::is_convertible_v), std::string> { - std::string_view views[sizeof...(parts)] = { parts... }; + std::string_view views[sizeof...(parts)] = {parts...}; return concatStringsSep({}, views); } diff --git a/tests/unit/libutil/file-system.cc b/tests/unit/libutil/file-system.cc new file mode 100644 index 000000000..cfddaae1c --- /dev/null +++ b/tests/unit/libutil/file-system.cc @@ -0,0 +1,258 @@ +#include "util.hh" +#include "types.hh" +#include "file-system.hh" +#include "processes.hh" +#include "terminal.hh" +#include "strings.hh" + +#include +#include +#include + +#include + +#ifdef _WIN32 +# define FS_SEP "\\" +# define FS_ROOT "C:" FS_SEP // Need a mounted one, C drive is likely +#else +# define FS_SEP "/" +# define FS_ROOT FS_SEP +#endif + +#ifndef PATH_MAX +# define PATH_MAX 4096 +#endif + +namespace nix { + +/* ----------- tests for file-system.hh -------------------------------------*/ + +/* ---------------------------------------------------------------------------- + * absPath + * --------------------------------------------------------------------------*/ + +TEST(absPath, doesntChangeRoot) +{ + auto p = absPath(FS_ROOT); + + ASSERT_EQ(p, FS_ROOT); +} + +TEST(absPath, turnsEmptyPathIntoCWD) +{ + char cwd[PATH_MAX + 1]; + auto p = absPath(""); + + ASSERT_EQ(p, getcwd((char *) &cwd, PATH_MAX)); +} + +TEST(absPath, usesOptionalBasePathWhenGiven) +{ + char _cwd[PATH_MAX + 1]; + char * cwd = getcwd((char *) &_cwd, PATH_MAX); + + auto p = absPath("", cwd); + + ASSERT_EQ(p, cwd); +} + +TEST(absPath, isIdempotent) +{ + char _cwd[PATH_MAX + 1]; + char * cwd = getcwd((char *) &_cwd, PATH_MAX); + auto p1 = absPath(cwd); + auto p2 = absPath(p1); + + ASSERT_EQ(p1, p2); +} + +TEST(absPath, pathIsCanonicalised) +{ + auto path = FS_ROOT "some/path/with/trailing/dot/."; + auto p1 = absPath(path); + auto p2 = absPath(p1); + + ASSERT_EQ(p1, FS_ROOT "some" FS_SEP "path" FS_SEP "with" FS_SEP "trailing" FS_SEP "dot"); + ASSERT_EQ(p1, p2); +} + +/* ---------------------------------------------------------------------------- + * canonPath + * --------------------------------------------------------------------------*/ + +TEST(canonPath, removesTrailingSlashes) +{ + auto path = FS_ROOT "this/is/a/path//"; + auto p = canonPath(path); + + ASSERT_EQ(p, FS_ROOT "this" FS_SEP "is" FS_SEP "a" FS_SEP "path"); +} + +TEST(canonPath, removesDots) +{ + auto path = FS_ROOT "this/./is/a/path/./"; + auto p = canonPath(path); + + ASSERT_EQ(p, FS_ROOT "this" FS_SEP "is" FS_SEP "a" FS_SEP "path"); +} + +TEST(canonPath, removesDots2) +{ + auto path = FS_ROOT "this/a/../is/a////path/foo/.."; + auto p = canonPath(path); + + ASSERT_EQ(p, FS_ROOT "this" FS_SEP "is" FS_SEP "a" FS_SEP "path"); +} + +TEST(canonPath, requiresAbsolutePath) +{ + ASSERT_ANY_THROW(canonPath(".")); + ASSERT_ANY_THROW(canonPath("..")); + ASSERT_ANY_THROW(canonPath("../")); + ASSERT_DEATH({ canonPath(""); }, "path != \"\""); +} + +/* ---------------------------------------------------------------------------- + * dirOf + * --------------------------------------------------------------------------*/ + +TEST(dirOf, returnsEmptyStringForRoot) +{ + auto p = dirOf("/"); + + ASSERT_EQ(p, "/"); +} + +TEST(dirOf, returnsFirstPathComponent) +{ + auto p1 = dirOf("/dir/"); + ASSERT_EQ(p1, "/dir"); + auto p2 = dirOf("/dir"); + ASSERT_EQ(p2, "/"); + auto p3 = dirOf("/dir/.."); + ASSERT_EQ(p3, "/dir"); + auto p4 = dirOf("/dir/../"); + ASSERT_EQ(p4, "/dir/.."); +} + +/* ---------------------------------------------------------------------------- + * baseNameOf + * --------------------------------------------------------------------------*/ + +TEST(baseNameOf, emptyPath) +{ + auto p1 = baseNameOf(""); + ASSERT_EQ(p1, ""); +} + +TEST(baseNameOf, pathOnRoot) +{ + auto p1 = baseNameOf("/dir"); + ASSERT_EQ(p1, "dir"); +} + +TEST(baseNameOf, relativePath) +{ + auto p1 = baseNameOf("dir/foo"); + ASSERT_EQ(p1, "foo"); +} + +TEST(baseNameOf, pathWithTrailingSlashRoot) +{ + auto p1 = baseNameOf("/"); + ASSERT_EQ(p1, ""); +} + +TEST(baseNameOf, trailingSlash) +{ + auto p1 = baseNameOf("/dir/"); + ASSERT_EQ(p1, "dir"); +} + +TEST(baseNameOf, trailingSlashes) +{ + auto p1 = baseNameOf("/dir//"); + ASSERT_EQ(p1, "dir"); +} + +TEST(baseNameOf, absoluteNothingSlashNothing) +{ + auto p1 = baseNameOf("//"); + ASSERT_EQ(p1, ""); +} + +/* ---------------------------------------------------------------------------- + * isInDir + * --------------------------------------------------------------------------*/ + +TEST(isInDir, trivialCase) +{ + auto p1 = isInDir("/foo/bar", "/foo"); + ASSERT_EQ(p1, true); +} + +TEST(isInDir, notInDir) +{ + auto p1 = isInDir("/zes/foo/bar", "/foo"); + ASSERT_EQ(p1, false); +} + +// XXX: hm, bug or feature? :) Looking at the implementation +// this might be problematic. +TEST(isInDir, emptyDir) +{ + auto p1 = isInDir("/zes/foo/bar", ""); + ASSERT_EQ(p1, true); +} + +/* ---------------------------------------------------------------------------- + * isDirOrInDir + * --------------------------------------------------------------------------*/ + +TEST(isDirOrInDir, trueForSameDirectory) +{ + ASSERT_EQ(isDirOrInDir("/nix", "/nix"), true); + ASSERT_EQ(isDirOrInDir("/", "/"), true); +} + +TEST(isDirOrInDir, trueForEmptyPaths) +{ + ASSERT_EQ(isDirOrInDir("", ""), true); +} + +TEST(isDirOrInDir, falseForDisjunctPaths) +{ + ASSERT_EQ(isDirOrInDir("/foo", "/bar"), false); +} + +TEST(isDirOrInDir, relativePaths) +{ + ASSERT_EQ(isDirOrInDir("/foo/..", "/foo"), true); +} + +// XXX: while it is possible to use "." or ".." in the +// first argument this doesn't seem to work in the second. +TEST(isDirOrInDir, DISABLED_shouldWork) +{ + ASSERT_EQ(isDirOrInDir("/foo/..", "/foo/."), true); +} + +/* ---------------------------------------------------------------------------- + * pathExists + * --------------------------------------------------------------------------*/ + +TEST(pathExists, rootExists) +{ + ASSERT_TRUE(pathExists(FS_ROOT)); +} + +TEST(pathExists, cwdExists) +{ + ASSERT_TRUE(pathExists(".")); +} + +TEST(pathExists, bogusPathDoesNotExist) +{ + ASSERT_FALSE(pathExists("/schnitzel/darmstadt/pommes")); +} +} diff --git a/tests/unit/libutil/meson.build b/tests/unit/libutil/meson.build index 7f024e6f2..f4f2ae7f9 100644 --- a/tests/unit/libutil/meson.build +++ b/tests/unit/libutil/meson.build @@ -61,11 +61,14 @@ sources = files( 'lru-cache.cc', 'nix_api_util.cc', 'pool.cc', + 'processes.cc', 'references.cc', 'spawn.cc', + 'strings.cc', 'suggestions.cc', - 'tests.cc', + 'terminal.cc', 'url.cc', + 'util.cc', 'xml-writer.cc', ) diff --git a/tests/unit/libutil/processes.cc b/tests/unit/libutil/processes.cc new file mode 100644 index 000000000..9033595e8 --- /dev/null +++ b/tests/unit/libutil/processes.cc @@ -0,0 +1,17 @@ +#include "processes.hh" + +#include + +namespace nix { + +/* ---------------------------------------------------------------------------- + * statusOk + * --------------------------------------------------------------------------*/ + +TEST(statusOk, zeroIsOk) +{ + ASSERT_EQ(statusOk(0), true); + ASSERT_EQ(statusOk(1), false); +} + +} // namespace nix diff --git a/tests/unit/libutil/strings.cc b/tests/unit/libutil/strings.cc index 47a20770e..0bd2fe0a5 100644 --- a/tests/unit/libutil/strings.cc +++ b/tests/unit/libutil/strings.cc @@ -80,4 +80,155 @@ TEST(concatStringsSep, buildSingleString) ASSERT_EQ(concatStringsSep(",", strings), "this"); } +/* ---------------------------------------------------------------------------- + * dropEmptyInitThenConcatStringsSep + * --------------------------------------------------------------------------*/ + +TEST(dropEmptyInitThenConcatStringsSep, empty) +{ + Strings strings; + + ASSERT_EQ(dropEmptyInitThenConcatStringsSep(",", strings), ""); +} + +TEST(dropEmptyInitThenConcatStringsSep, buildCommaSeparatedString) +{ + Strings strings; + strings.push_back("this"); + strings.push_back("is"); + strings.push_back("great"); + + ASSERT_EQ(dropEmptyInitThenConcatStringsSep(",", strings), "this,is,great"); +} + +TEST(dropEmptyInitThenConcatStringsSep, buildStringWithEmptySeparator) +{ + Strings strings; + strings.push_back("this"); + strings.push_back("is"); + strings.push_back("great"); + + ASSERT_EQ(dropEmptyInitThenConcatStringsSep("", strings), "thisisgreat"); +} + +TEST(dropEmptyInitThenConcatStringsSep, buildSingleString) +{ + Strings strings; + strings.push_back("this"); + strings.push_back(""); + + ASSERT_EQ(dropEmptyInitThenConcatStringsSep(",", strings), "this,"); +} + +TEST(dropEmptyInitThenConcatStringsSep, emptyStrings) +{ + Strings strings; + strings.push_back(""); + strings.push_back(""); + + ASSERT_EQ(dropEmptyInitThenConcatStringsSep(",", strings), ""); +} + +/* ---------------------------------------------------------------------------- + * tokenizeString + * --------------------------------------------------------------------------*/ + +TEST(tokenizeString, empty) +{ + Strings expected = {}; + + ASSERT_EQ(tokenizeString(""), expected); +} + +TEST(tokenizeString, oneSep) +{ + Strings expected = {}; + + ASSERT_EQ(tokenizeString(" "), expected); +} + +TEST(tokenizeString, twoSep) +{ + Strings expected = {}; + + ASSERT_EQ(tokenizeString(" \n"), expected); +} + +TEST(tokenizeString, tokenizeSpacesWithDefaults) +{ + auto s = "foo bar baz"; + Strings expected = {"foo", "bar", "baz"}; + + ASSERT_EQ(tokenizeString(s), expected); +} + +TEST(tokenizeString, tokenizeTabsWithDefaults) +{ + auto s = "foo\tbar\tbaz"; + Strings expected = {"foo", "bar", "baz"}; + + ASSERT_EQ(tokenizeString(s), expected); +} + +TEST(tokenizeString, tokenizeTabsSpacesWithDefaults) +{ + auto s = "foo\t bar\t baz"; + Strings expected = {"foo", "bar", "baz"}; + + ASSERT_EQ(tokenizeString(s), expected); +} + +TEST(tokenizeString, tokenizeTabsSpacesNewlineWithDefaults) +{ + auto s = "foo\t\n bar\t\n baz"; + Strings expected = {"foo", "bar", "baz"}; + + ASSERT_EQ(tokenizeString(s), expected); +} + +TEST(tokenizeString, tokenizeTabsSpacesNewlineRetWithDefaults) +{ + auto s = "foo\t\n\r bar\t\n\r baz"; + Strings expected = {"foo", "bar", "baz"}; + + ASSERT_EQ(tokenizeString(s), expected); + + auto s2 = "foo \t\n\r bar \t\n\r baz"; + Strings expected2 = {"foo", "bar", "baz"}; + + ASSERT_EQ(tokenizeString(s2), expected2); +} + +TEST(tokenizeString, tokenizeWithCustomSep) +{ + auto s = "foo\n,bar\n,baz\n"; + Strings expected = {"foo\n", "bar\n", "baz\n"}; + + ASSERT_EQ(tokenizeString(s, ","), expected); +} + +TEST(tokenizeString, tokenizeSepAtStart) +{ + auto s = ",foo,bar,baz"; + Strings expected = {"foo", "bar", "baz"}; + + ASSERT_EQ(tokenizeString(s, ","), expected); +} + +TEST(tokenizeString, tokenizeSepAtEnd) +{ + auto s = "foo,bar,baz,"; + Strings expected = {"foo", "bar", "baz"}; + + ASSERT_EQ(tokenizeString(s, ","), expected); +} + +TEST(tokenizeString, tokenizeSepEmpty) +{ + auto s = "foo,,baz"; + Strings expected = {"foo", "baz"}; + + ASSERT_EQ(tokenizeString(s, ","), expected); +} + } // namespace nix diff --git a/tests/unit/libutil/terminal.cc b/tests/unit/libutil/terminal.cc new file mode 100644 index 000000000..cdeb9fd94 --- /dev/null +++ b/tests/unit/libutil/terminal.cc @@ -0,0 +1,60 @@ +#include "util.hh" +#include "types.hh" +#include "terminal.hh" +#include "strings.hh" + +#include +#include + +#include + +namespace nix { + +/* ---------------------------------------------------------------------------- + * filterANSIEscapes + * --------------------------------------------------------------------------*/ + +TEST(filterANSIEscapes, emptyString) +{ + auto s = ""; + auto expected = ""; + + ASSERT_EQ(filterANSIEscapes(s), expected); +} + +TEST(filterANSIEscapes, doesntChangePrintableChars) +{ + auto s = "09 2q304ruyhr slk2-19024 kjsadh sar f"; + + ASSERT_EQ(filterANSIEscapes(s), s); +} + +TEST(filterANSIEscapes, filtersColorCodes) +{ + auto s = "\u001b[30m A \u001b[31m B \u001b[32m C \u001b[33m D \u001b[0m"; + + ASSERT_EQ(filterANSIEscapes(s, true, 2), " A"); + ASSERT_EQ(filterANSIEscapes(s, true, 3), " A "); + ASSERT_EQ(filterANSIEscapes(s, true, 4), " A "); + ASSERT_EQ(filterANSIEscapes(s, true, 5), " A B"); + ASSERT_EQ(filterANSIEscapes(s, true, 8), " A B C"); +} + +TEST(filterANSIEscapes, expandsTabs) +{ + auto s = "foo\tbar\tbaz"; + + ASSERT_EQ(filterANSIEscapes(s, true), "foo bar baz"); +} + +TEST(filterANSIEscapes, utf8) +{ + ASSERT_EQ(filterANSIEscapes("foobar", true, 5), "fooba"); + ASSERT_EQ(filterANSIEscapes("fóóbär", true, 6), "fóóbär"); + ASSERT_EQ(filterANSIEscapes("fóóbär", true, 5), "fóóbä"); + ASSERT_EQ(filterANSIEscapes("fóóbär", true, 3), "fóó"); + ASSERT_EQ(filterANSIEscapes("f€€bär", true, 4), "f€€b"); + ASSERT_EQ(filterANSIEscapes("f𐍈𐍈bär", true, 4), "f𐍈𐍈b"); +} + +} // namespace nix diff --git a/tests/unit/libutil/tests.cc b/tests/unit/libutil/tests.cc deleted file mode 100644 index 2b73d323b..000000000 --- a/tests/unit/libutil/tests.cc +++ /dev/null @@ -1,703 +0,0 @@ -#include "util.hh" -#include "types.hh" -#include "file-system.hh" -#include "processes.hh" -#include "terminal.hh" - -#include -#include - -#include - -#ifdef _WIN32 -# define FS_SEP "\\" -# define FS_ROOT "C:" FS_SEP // Need a mounted one, C drive is likely -#else -# define FS_SEP "/" -# define FS_ROOT FS_SEP -#endif - -#ifndef PATH_MAX -# define PATH_MAX 4096 -#endif - -namespace nix { - -/* ----------- tests for util.hh ------------------------------------------------*/ - - /* ---------------------------------------------------------------------------- - * absPath - * --------------------------------------------------------------------------*/ - - TEST(absPath, doesntChangeRoot) { - auto p = absPath(FS_ROOT); - - ASSERT_EQ(p, FS_ROOT); - } - - - - - TEST(absPath, turnsEmptyPathIntoCWD) { - char cwd[PATH_MAX+1]; - auto p = absPath(""); - - ASSERT_EQ(p, getcwd((char*)&cwd, PATH_MAX)); - } - - TEST(absPath, usesOptionalBasePathWhenGiven) { - char _cwd[PATH_MAX+1]; - char* cwd = getcwd((char*)&_cwd, PATH_MAX); - - auto p = absPath("", cwd); - - ASSERT_EQ(p, cwd); - } - - TEST(absPath, isIdempotent) { - char _cwd[PATH_MAX+1]; - char* cwd = getcwd((char*)&_cwd, PATH_MAX); - auto p1 = absPath(cwd); - auto p2 = absPath(p1); - - ASSERT_EQ(p1, p2); - } - - - TEST(absPath, pathIsCanonicalised) { - auto path = FS_ROOT "some/path/with/trailing/dot/."; - auto p1 = absPath(path); - auto p2 = absPath(p1); - - ASSERT_EQ(p1, FS_ROOT "some" FS_SEP "path" FS_SEP "with" FS_SEP "trailing" FS_SEP "dot"); - ASSERT_EQ(p1, p2); - } - - /* ---------------------------------------------------------------------------- - * canonPath - * --------------------------------------------------------------------------*/ - - TEST(canonPath, removesTrailingSlashes) { - auto path = FS_ROOT "this/is/a/path//"; - auto p = canonPath(path); - - ASSERT_EQ(p, FS_ROOT "this" FS_SEP "is" FS_SEP "a" FS_SEP "path"); - } - - TEST(canonPath, removesDots) { - auto path = FS_ROOT "this/./is/a/path/./"; - auto p = canonPath(path); - - ASSERT_EQ(p, FS_ROOT "this" FS_SEP "is" FS_SEP "a" FS_SEP "path"); - } - - TEST(canonPath, removesDots2) { - auto path = FS_ROOT "this/a/../is/a////path/foo/.."; - auto p = canonPath(path); - - ASSERT_EQ(p, FS_ROOT "this" FS_SEP "is" FS_SEP "a" FS_SEP "path"); - } - - TEST(canonPath, requiresAbsolutePath) { - ASSERT_ANY_THROW(canonPath(".")); - ASSERT_ANY_THROW(canonPath("..")); - ASSERT_ANY_THROW(canonPath("../")); - ASSERT_DEATH({ canonPath(""); }, "path != \"\""); - } - - /* ---------------------------------------------------------------------------- - * dirOf - * --------------------------------------------------------------------------*/ - - TEST(dirOf, returnsEmptyStringForRoot) { - auto p = dirOf("/"); - - ASSERT_EQ(p, "/"); - } - - TEST(dirOf, returnsFirstPathComponent) { - auto p1 = dirOf("/dir/"); - ASSERT_EQ(p1, "/dir"); - auto p2 = dirOf("/dir"); - ASSERT_EQ(p2, "/"); - auto p3 = dirOf("/dir/.."); - ASSERT_EQ(p3, "/dir"); - auto p4 = dirOf("/dir/../"); - ASSERT_EQ(p4, "/dir/.."); - } - - /* ---------------------------------------------------------------------------- - * baseNameOf - * --------------------------------------------------------------------------*/ - - TEST(baseNameOf, emptyPath) { - auto p1 = baseNameOf(""); - ASSERT_EQ(p1, ""); - } - - TEST(baseNameOf, pathOnRoot) { - auto p1 = baseNameOf("/dir"); - ASSERT_EQ(p1, "dir"); - } - - TEST(baseNameOf, relativePath) { - auto p1 = baseNameOf("dir/foo"); - ASSERT_EQ(p1, "foo"); - } - - TEST(baseNameOf, pathWithTrailingSlashRoot) { - auto p1 = baseNameOf("/"); - ASSERT_EQ(p1, ""); - } - - TEST(baseNameOf, trailingSlash) { - auto p1 = baseNameOf("/dir/"); - ASSERT_EQ(p1, "dir"); - } - - TEST(baseNameOf, trailingSlashes) { - auto p1 = baseNameOf("/dir//"); - ASSERT_EQ(p1, "dir"); - } - - TEST(baseNameOf, absoluteNothingSlashNothing) { - auto p1 = baseNameOf("//"); - ASSERT_EQ(p1, ""); - } - - /* ---------------------------------------------------------------------------- - * isInDir - * --------------------------------------------------------------------------*/ - - TEST(isInDir, trivialCase) { - auto p1 = isInDir("/foo/bar", "/foo"); - ASSERT_EQ(p1, true); - } - - TEST(isInDir, notInDir) { - auto p1 = isInDir("/zes/foo/bar", "/foo"); - ASSERT_EQ(p1, false); - } - - // XXX: hm, bug or feature? :) Looking at the implementation - // this might be problematic. - TEST(isInDir, emptyDir) { - auto p1 = isInDir("/zes/foo/bar", ""); - ASSERT_EQ(p1, true); - } - - /* ---------------------------------------------------------------------------- - * isDirOrInDir - * --------------------------------------------------------------------------*/ - - TEST(isDirOrInDir, trueForSameDirectory) { - ASSERT_EQ(isDirOrInDir("/nix", "/nix"), true); - ASSERT_EQ(isDirOrInDir("/", "/"), true); - } - - TEST(isDirOrInDir, trueForEmptyPaths) { - ASSERT_EQ(isDirOrInDir("", ""), true); - } - - TEST(isDirOrInDir, falseForDisjunctPaths) { - ASSERT_EQ(isDirOrInDir("/foo", "/bar"), false); - } - - TEST(isDirOrInDir, relativePaths) { - ASSERT_EQ(isDirOrInDir("/foo/..", "/foo"), true); - } - - // XXX: while it is possible to use "." or ".." in the - // first argument this doesn't seem to work in the second. - TEST(isDirOrInDir, DISABLED_shouldWork) { - ASSERT_EQ(isDirOrInDir("/foo/..", "/foo/."), true); - - } - - /* ---------------------------------------------------------------------------- - * pathExists - * --------------------------------------------------------------------------*/ - - TEST(pathExists, rootExists) { - ASSERT_TRUE(pathExists(FS_ROOT)); - } - - TEST(pathExists, cwdExists) { - ASSERT_TRUE(pathExists(".")); - } - - TEST(pathExists, bogusPathDoesNotExist) { - ASSERT_FALSE(pathExists("/schnitzel/darmstadt/pommes")); - } - - /* ---------------------------------------------------------------------------- - * dropEmptyInitThenConcatStringsSep - * --------------------------------------------------------------------------*/ - - TEST(dropEmptyInitThenConcatStringsSep, buildCommaSeparatedString) { - Strings strings; - strings.push_back("this"); - strings.push_back("is"); - strings.push_back("great"); - - ASSERT_EQ(dropEmptyInitThenConcatStringsSep(",", strings), "this,is,great"); - } - - TEST(dropEmptyInitThenConcatStringsSep, buildStringWithEmptySeparator) { - Strings strings; - strings.push_back("this"); - strings.push_back("is"); - strings.push_back("great"); - - ASSERT_EQ(dropEmptyInitThenConcatStringsSep("", strings), "thisisgreat"); - } - - TEST(dropEmptyInitThenConcatStringsSep, buildSingleString) { - Strings strings; - strings.push_back("this"); - - ASSERT_EQ(dropEmptyInitThenConcatStringsSep(",", strings), "this"); - } - - /* ---------------------------------------------------------------------------- - * hasPrefix - * --------------------------------------------------------------------------*/ - - TEST(hasPrefix, emptyStringHasNoPrefix) { - ASSERT_FALSE(hasPrefix("", "foo")); - } - - TEST(hasPrefix, emptyStringIsAlwaysPrefix) { - ASSERT_TRUE(hasPrefix("foo", "")); - ASSERT_TRUE(hasPrefix("jshjkfhsadf", "")); - } - - TEST(hasPrefix, trivialCase) { - ASSERT_TRUE(hasPrefix("foobar", "foo")); - } - - /* ---------------------------------------------------------------------------- - * hasSuffix - * --------------------------------------------------------------------------*/ - - TEST(hasSuffix, emptyStringHasNoSuffix) { - ASSERT_FALSE(hasSuffix("", "foo")); - } - - TEST(hasSuffix, trivialCase) { - ASSERT_TRUE(hasSuffix("foo", "foo")); - ASSERT_TRUE(hasSuffix("foobar", "bar")); - } - - /* ---------------------------------------------------------------------------- - * base64Encode - * --------------------------------------------------------------------------*/ - - TEST(base64Encode, emptyString) { - ASSERT_EQ(base64Encode(""), ""); - } - - TEST(base64Encode, encodesAString) { - ASSERT_EQ(base64Encode("quod erat demonstrandum"), "cXVvZCBlcmF0IGRlbW9uc3RyYW5kdW0="); - } - - TEST(base64Encode, encodeAndDecode) { - auto s = "quod erat demonstrandum"; - auto encoded = base64Encode(s); - auto decoded = base64Decode(encoded); - - ASSERT_EQ(decoded, s); - } - - TEST(base64Encode, encodeAndDecodeNonPrintable) { - char s[256]; - std::iota(std::rbegin(s), std::rend(s), 0); - - auto encoded = base64Encode(s); - auto decoded = base64Decode(encoded); - - EXPECT_EQ(decoded.length(), 255); - ASSERT_EQ(decoded, s); - } - - /* ---------------------------------------------------------------------------- - * base64Decode - * --------------------------------------------------------------------------*/ - - TEST(base64Decode, emptyString) { - ASSERT_EQ(base64Decode(""), ""); - } - - TEST(base64Decode, decodeAString) { - ASSERT_EQ(base64Decode("cXVvZCBlcmF0IGRlbW9uc3RyYW5kdW0="), "quod erat demonstrandum"); - } - - TEST(base64Decode, decodeThrowsOnInvalidChar) { - ASSERT_THROW(base64Decode("cXVvZCBlcm_0IGRlbW9uc3RyYW5kdW0="), Error); - } - - /* ---------------------------------------------------------------------------- - * getLine - * --------------------------------------------------------------------------*/ - - TEST(getLine, all) { - { - auto [line, rest] = getLine("foo\nbar\nxyzzy"); - ASSERT_EQ(line, "foo"); - ASSERT_EQ(rest, "bar\nxyzzy"); - } - - { - auto [line, rest] = getLine("foo\r\nbar\r\nxyzzy"); - ASSERT_EQ(line, "foo"); - ASSERT_EQ(rest, "bar\r\nxyzzy"); - } - - { - auto [line, rest] = getLine("foo\n"); - ASSERT_EQ(line, "foo"); - ASSERT_EQ(rest, ""); - } - - { - auto [line, rest] = getLine("foo"); - ASSERT_EQ(line, "foo"); - ASSERT_EQ(rest, ""); - } - - { - auto [line, rest] = getLine(""); - ASSERT_EQ(line, ""); - ASSERT_EQ(rest, ""); - } - } - - /* ---------------------------------------------------------------------------- - * toLower - * --------------------------------------------------------------------------*/ - - TEST(toLower, emptyString) { - ASSERT_EQ(toLower(""), ""); - } - - TEST(toLower, nonLetters) { - auto s = "!@(*$#)(@#=\\234_"; - ASSERT_EQ(toLower(s), s); - } - - // std::tolower() doesn't handle unicode characters. In the context of - // store paths this isn't relevant but doesn't hurt to record this behavior - // here. - TEST(toLower, umlauts) { - auto s = "ÄÖÜ"; - ASSERT_EQ(toLower(s), "ÄÖÜ"); - } - - /* ---------------------------------------------------------------------------- - * string2Float - * --------------------------------------------------------------------------*/ - - TEST(string2Float, emptyString) { - ASSERT_EQ(string2Float(""), std::nullopt); - } - - TEST(string2Float, trivialConversions) { - ASSERT_EQ(string2Float("1.0"), 1.0); - - ASSERT_EQ(string2Float("0.0"), 0.0); - - ASSERT_EQ(string2Float("-100.25"), -100.25); - } - - /* ---------------------------------------------------------------------------- - * string2Int - * --------------------------------------------------------------------------*/ - - TEST(string2Int, emptyString) { - ASSERT_EQ(string2Int(""), std::nullopt); - } - - TEST(string2Int, trivialConversions) { - ASSERT_EQ(string2Int("1"), 1); - - ASSERT_EQ(string2Int("0"), 0); - - ASSERT_EQ(string2Int("-100"), -100); - } - - /* ---------------------------------------------------------------------------- - * renderSize - * --------------------------------------------------------------------------*/ - - TEST(renderSize, misc) { - ASSERT_EQ(renderSize(0, true), " 0.0 KiB"); - ASSERT_EQ(renderSize(100, true), " 0.1 KiB"); - ASSERT_EQ(renderSize(100), "0.1 KiB"); - ASSERT_EQ(renderSize(972, true), " 0.9 KiB"); - ASSERT_EQ(renderSize(973, true), " 1.0 KiB"); // FIXME: should round down - ASSERT_EQ(renderSize(1024, true), " 1.0 KiB"); - ASSERT_EQ(renderSize(1024 * 1024, true), "1024.0 KiB"); - ASSERT_EQ(renderSize(1100 * 1024, true), " 1.1 MiB"); - ASSERT_EQ(renderSize(2ULL * 1024 * 1024 * 1024, true), " 2.0 GiB"); - ASSERT_EQ(renderSize(2100ULL * 1024 * 1024 * 1024, true), " 2.1 TiB"); - } - -#ifndef _WIN32 // TODO re-enable on Windows, once we can start processes - /* ---------------------------------------------------------------------------- - * statusOk - * --------------------------------------------------------------------------*/ - - TEST(statusOk, zeroIsOk) { - ASSERT_EQ(statusOk(0), true); - ASSERT_EQ(statusOk(1), false); - } -#endif - - - /* ---------------------------------------------------------------------------- - * rewriteStrings - * --------------------------------------------------------------------------*/ - - TEST(rewriteStrings, emptyString) { - StringMap rewrites; - rewrites["this"] = "that"; - - ASSERT_EQ(rewriteStrings("", rewrites), ""); - } - - TEST(rewriteStrings, emptyRewrites) { - StringMap rewrites; - - ASSERT_EQ(rewriteStrings("this and that", rewrites), "this and that"); - } - - TEST(rewriteStrings, successfulRewrite) { - StringMap rewrites; - rewrites["this"] = "that"; - - ASSERT_EQ(rewriteStrings("this and that", rewrites), "that and that"); - } - - TEST(rewriteStrings, doesntOccur) { - StringMap rewrites; - rewrites["foo"] = "bar"; - - ASSERT_EQ(rewriteStrings("this and that", rewrites), "this and that"); - } - - /* ---------------------------------------------------------------------------- - * replaceStrings - * --------------------------------------------------------------------------*/ - - TEST(replaceStrings, emptyString) { - ASSERT_EQ(replaceStrings("", "this", "that"), ""); - ASSERT_EQ(replaceStrings("this and that", "", ""), "this and that"); - } - - TEST(replaceStrings, successfulReplace) { - ASSERT_EQ(replaceStrings("this and that", "this", "that"), "that and that"); - } - - TEST(replaceStrings, doesntOccur) { - ASSERT_EQ(replaceStrings("this and that", "foo", "bar"), "this and that"); - } - - /* ---------------------------------------------------------------------------- - * trim - * --------------------------------------------------------------------------*/ - - TEST(trim, emptyString) { - ASSERT_EQ(trim(""), ""); - } - - TEST(trim, removesWhitespace) { - ASSERT_EQ(trim("foo"), "foo"); - ASSERT_EQ(trim(" foo "), "foo"); - ASSERT_EQ(trim(" foo bar baz"), "foo bar baz"); - ASSERT_EQ(trim(" \t foo bar baz\n"), "foo bar baz"); - } - - /* ---------------------------------------------------------------------------- - * chomp - * --------------------------------------------------------------------------*/ - - TEST(chomp, emptyString) { - ASSERT_EQ(chomp(""), ""); - } - - TEST(chomp, removesWhitespace) { - ASSERT_EQ(chomp("foo"), "foo"); - ASSERT_EQ(chomp("foo "), "foo"); - ASSERT_EQ(chomp(" foo "), " foo"); - ASSERT_EQ(chomp(" foo bar baz "), " foo bar baz"); - ASSERT_EQ(chomp("\t foo bar baz\n"), "\t foo bar baz"); - } - - /* ---------------------------------------------------------------------------- - * quoteStrings - * --------------------------------------------------------------------------*/ - - TEST(quoteStrings, empty) { - Strings s = { }; - Strings expected = { }; - - ASSERT_EQ(quoteStrings(s), expected); - } - - TEST(quoteStrings, emptyStrings) { - Strings s = { "", "", "" }; - Strings expected = { "''", "''", "''" }; - ASSERT_EQ(quoteStrings(s), expected); - - } - - TEST(quoteStrings, trivialQuote) { - Strings s = { "foo", "bar", "baz" }; - Strings expected = { "'foo'", "'bar'", "'baz'" }; - - ASSERT_EQ(quoteStrings(s), expected); - } - - TEST(quoteStrings, quotedStrings) { - Strings s = { "'foo'", "'bar'", "'baz'" }; - Strings expected = { "''foo''", "''bar''", "''baz''" }; - - ASSERT_EQ(quoteStrings(s), expected); - } - - /* ---------------------------------------------------------------------------- - * tokenizeString - * --------------------------------------------------------------------------*/ - - TEST(tokenizeString, empty) { - Strings expected = { }; - - ASSERT_EQ(tokenizeString(""), expected); - } - - TEST(tokenizeString, tokenizeSpacesWithDefaults) { - auto s = "foo bar baz"; - Strings expected = { "foo", "bar", "baz" }; - - ASSERT_EQ(tokenizeString(s), expected); - } - - TEST(tokenizeString, tokenizeTabsWithDefaults) { - auto s = "foo\tbar\tbaz"; - Strings expected = { "foo", "bar", "baz" }; - - ASSERT_EQ(tokenizeString(s), expected); - } - - TEST(tokenizeString, tokenizeTabsSpacesWithDefaults) { - auto s = "foo\t bar\t baz"; - Strings expected = { "foo", "bar", "baz" }; - - ASSERT_EQ(tokenizeString(s), expected); - } - - TEST(tokenizeString, tokenizeTabsSpacesNewlineWithDefaults) { - auto s = "foo\t\n bar\t\n baz"; - Strings expected = { "foo", "bar", "baz" }; - - ASSERT_EQ(tokenizeString(s), expected); - } - - TEST(tokenizeString, tokenizeTabsSpacesNewlineRetWithDefaults) { - auto s = "foo\t\n\r bar\t\n\r baz"; - Strings expected = { "foo", "bar", "baz" }; - - ASSERT_EQ(tokenizeString(s), expected); - - auto s2 = "foo \t\n\r bar \t\n\r baz"; - Strings expected2 = { "foo", "bar", "baz" }; - - ASSERT_EQ(tokenizeString(s2), expected2); - } - - TEST(tokenizeString, tokenizeWithCustomSep) { - auto s = "foo\n,bar\n,baz\n"; - Strings expected = { "foo\n", "bar\n", "baz\n" }; - - ASSERT_EQ(tokenizeString(s, ","), expected); - } - - /* ---------------------------------------------------------------------------- - * get - * --------------------------------------------------------------------------*/ - - TEST(get, emptyContainer) { - StringMap s = { }; - auto expected = nullptr; - - ASSERT_EQ(get(s, "one"), expected); - } - - TEST(get, getFromContainer) { - StringMap s; - s["one"] = "yi"; - s["two"] = "er"; - auto expected = "yi"; - - ASSERT_EQ(*get(s, "one"), expected); - } - - TEST(getOr, emptyContainer) { - StringMap s = { }; - auto expected = "yi"; - - ASSERT_EQ(getOr(s, "one", "yi"), expected); - } - - TEST(getOr, getFromContainer) { - StringMap s; - s["one"] = "yi"; - s["two"] = "er"; - auto expected = "yi"; - - ASSERT_EQ(getOr(s, "one", "nope"), expected); - } - - /* ---------------------------------------------------------------------------- - * filterANSIEscapes - * --------------------------------------------------------------------------*/ - - TEST(filterANSIEscapes, emptyString) { - auto s = ""; - auto expected = ""; - - ASSERT_EQ(filterANSIEscapes(s), expected); - } - - TEST(filterANSIEscapes, doesntChangePrintableChars) { - auto s = "09 2q304ruyhr slk2-19024 kjsadh sar f"; - - ASSERT_EQ(filterANSIEscapes(s), s); - } - - TEST(filterANSIEscapes, filtersColorCodes) { - auto s = "\u001b[30m A \u001b[31m B \u001b[32m C \u001b[33m D \u001b[0m"; - - ASSERT_EQ(filterANSIEscapes(s, true, 2), " A" ); - ASSERT_EQ(filterANSIEscapes(s, true, 3), " A " ); - ASSERT_EQ(filterANSIEscapes(s, true, 4), " A " ); - ASSERT_EQ(filterANSIEscapes(s, true, 5), " A B" ); - ASSERT_EQ(filterANSIEscapes(s, true, 8), " A B C" ); - } - - TEST(filterANSIEscapes, expandsTabs) { - auto s = "foo\tbar\tbaz"; - - ASSERT_EQ(filterANSIEscapes(s, true), "foo bar baz" ); - } - - TEST(filterANSIEscapes, utf8) { - ASSERT_EQ(filterANSIEscapes("foobar", true, 5), "fooba"); - ASSERT_EQ(filterANSIEscapes("fóóbär", true, 6), "fóóbär"); - ASSERT_EQ(filterANSIEscapes("fóóbär", true, 5), "fóóbä"); - ASSERT_EQ(filterANSIEscapes("fóóbär", true, 3), "fóó"); - ASSERT_EQ(filterANSIEscapes("f€€bär", true, 4), "f€€b"); - ASSERT_EQ(filterANSIEscapes("f𐍈𐍈bär", true, 4), "f𐍈𐍈b"); - } - -} diff --git a/tests/unit/libutil/util.cc b/tests/unit/libutil/util.cc new file mode 100644 index 000000000..a3f7c720a --- /dev/null +++ b/tests/unit/libutil/util.cc @@ -0,0 +1,385 @@ +#include "util.hh" +#include "types.hh" +#include "file-system.hh" +#include "terminal.hh" +#include "strings.hh" + +#include +#include + +#include + +namespace nix { + +/* ----------- tests for util.hh --------------------------------------------*/ + +/* ---------------------------------------------------------------------------- + * hasPrefix + * --------------------------------------------------------------------------*/ + +TEST(hasPrefix, emptyStringHasNoPrefix) +{ + ASSERT_FALSE(hasPrefix("", "foo")); +} + +TEST(hasPrefix, emptyStringIsAlwaysPrefix) +{ + ASSERT_TRUE(hasPrefix("foo", "")); + ASSERT_TRUE(hasPrefix("jshjkfhsadf", "")); +} + +TEST(hasPrefix, trivialCase) +{ + ASSERT_TRUE(hasPrefix("foobar", "foo")); +} + +/* ---------------------------------------------------------------------------- + * hasSuffix + * --------------------------------------------------------------------------*/ + +TEST(hasSuffix, emptyStringHasNoSuffix) +{ + ASSERT_FALSE(hasSuffix("", "foo")); +} + +TEST(hasSuffix, trivialCase) +{ + ASSERT_TRUE(hasSuffix("foo", "foo")); + ASSERT_TRUE(hasSuffix("foobar", "bar")); +} + +/* ---------------------------------------------------------------------------- + * base64Encode + * --------------------------------------------------------------------------*/ + +TEST(base64Encode, emptyString) +{ + ASSERT_EQ(base64Encode(""), ""); +} + +TEST(base64Encode, encodesAString) +{ + ASSERT_EQ(base64Encode("quod erat demonstrandum"), "cXVvZCBlcmF0IGRlbW9uc3RyYW5kdW0="); +} + +TEST(base64Encode, encodeAndDecode) +{ + auto s = "quod erat demonstrandum"; + auto encoded = base64Encode(s); + auto decoded = base64Decode(encoded); + + ASSERT_EQ(decoded, s); +} + +TEST(base64Encode, encodeAndDecodeNonPrintable) +{ + char s[256]; + std::iota(std::rbegin(s), std::rend(s), 0); + + auto encoded = base64Encode(s); + auto decoded = base64Decode(encoded); + + EXPECT_EQ(decoded.length(), 255); + ASSERT_EQ(decoded, s); +} + +/* ---------------------------------------------------------------------------- + * base64Decode + * --------------------------------------------------------------------------*/ + +TEST(base64Decode, emptyString) +{ + ASSERT_EQ(base64Decode(""), ""); +} + +TEST(base64Decode, decodeAString) +{ + ASSERT_EQ(base64Decode("cXVvZCBlcmF0IGRlbW9uc3RyYW5kdW0="), "quod erat demonstrandum"); +} + +TEST(base64Decode, decodeThrowsOnInvalidChar) +{ + ASSERT_THROW(base64Decode("cXVvZCBlcm_0IGRlbW9uc3RyYW5kdW0="), Error); +} + +/* ---------------------------------------------------------------------------- + * getLine + * --------------------------------------------------------------------------*/ + +TEST(getLine, all) +{ + { + auto [line, rest] = getLine("foo\nbar\nxyzzy"); + ASSERT_EQ(line, "foo"); + ASSERT_EQ(rest, "bar\nxyzzy"); + } + + { + auto [line, rest] = getLine("foo\r\nbar\r\nxyzzy"); + ASSERT_EQ(line, "foo"); + ASSERT_EQ(rest, "bar\r\nxyzzy"); + } + + { + auto [line, rest] = getLine("foo\n"); + ASSERT_EQ(line, "foo"); + ASSERT_EQ(rest, ""); + } + + { + auto [line, rest] = getLine("foo"); + ASSERT_EQ(line, "foo"); + ASSERT_EQ(rest, ""); + } + + { + auto [line, rest] = getLine(""); + ASSERT_EQ(line, ""); + ASSERT_EQ(rest, ""); + } +} + +/* ---------------------------------------------------------------------------- + * toLower + * --------------------------------------------------------------------------*/ + +TEST(toLower, emptyString) +{ + ASSERT_EQ(toLower(""), ""); +} + +TEST(toLower, nonLetters) +{ + auto s = "!@(*$#)(@#=\\234_"; + ASSERT_EQ(toLower(s), s); +} + +// std::tolower() doesn't handle unicode characters. In the context of +// store paths this isn't relevant but doesn't hurt to record this behavior +// here. +TEST(toLower, umlauts) +{ + auto s = "ÄÖÜ"; + ASSERT_EQ(toLower(s), "ÄÖÜ"); +} + +/* ---------------------------------------------------------------------------- + * string2Float + * --------------------------------------------------------------------------*/ + +TEST(string2Float, emptyString) +{ + ASSERT_EQ(string2Float(""), std::nullopt); +} + +TEST(string2Float, trivialConversions) +{ + ASSERT_EQ(string2Float("1.0"), 1.0); + + ASSERT_EQ(string2Float("0.0"), 0.0); + + ASSERT_EQ(string2Float("-100.25"), -100.25); +} + +/* ---------------------------------------------------------------------------- + * string2Int + * --------------------------------------------------------------------------*/ + +TEST(string2Int, emptyString) +{ + ASSERT_EQ(string2Int(""), std::nullopt); +} + +TEST(string2Int, trivialConversions) +{ + ASSERT_EQ(string2Int("1"), 1); + + ASSERT_EQ(string2Int("0"), 0); + + ASSERT_EQ(string2Int("-100"), -100); +} + +/* ---------------------------------------------------------------------------- + * renderSize + * --------------------------------------------------------------------------*/ + +TEST(renderSize, misc) +{ + ASSERT_EQ(renderSize(0, true), " 0.0 KiB"); + ASSERT_EQ(renderSize(100, true), " 0.1 KiB"); + ASSERT_EQ(renderSize(100), "0.1 KiB"); + ASSERT_EQ(renderSize(972, true), " 0.9 KiB"); + ASSERT_EQ(renderSize(973, true), " 1.0 KiB"); // FIXME: should round down + ASSERT_EQ(renderSize(1024, true), " 1.0 KiB"); + ASSERT_EQ(renderSize(1024 * 1024, true), "1024.0 KiB"); + ASSERT_EQ(renderSize(1100 * 1024, true), " 1.1 MiB"); + ASSERT_EQ(renderSize(2ULL * 1024 * 1024 * 1024, true), " 2.0 GiB"); + ASSERT_EQ(renderSize(2100ULL * 1024 * 1024 * 1024, true), " 2.1 TiB"); +} + +/* ---------------------------------------------------------------------------- + * rewriteStrings + * --------------------------------------------------------------------------*/ + +TEST(rewriteStrings, emptyString) +{ + StringMap rewrites; + rewrites["this"] = "that"; + + ASSERT_EQ(rewriteStrings("", rewrites), ""); +} + +TEST(rewriteStrings, emptyRewrites) +{ + StringMap rewrites; + + ASSERT_EQ(rewriteStrings("this and that", rewrites), "this and that"); +} + +TEST(rewriteStrings, successfulRewrite) +{ + StringMap rewrites; + rewrites["this"] = "that"; + + ASSERT_EQ(rewriteStrings("this and that", rewrites), "that and that"); +} + +TEST(rewriteStrings, doesntOccur) +{ + StringMap rewrites; + rewrites["foo"] = "bar"; + + ASSERT_EQ(rewriteStrings("this and that", rewrites), "this and that"); +} + +/* ---------------------------------------------------------------------------- + * replaceStrings + * --------------------------------------------------------------------------*/ + +TEST(replaceStrings, emptyString) +{ + ASSERT_EQ(replaceStrings("", "this", "that"), ""); + ASSERT_EQ(replaceStrings("this and that", "", ""), "this and that"); +} + +TEST(replaceStrings, successfulReplace) +{ + ASSERT_EQ(replaceStrings("this and that", "this", "that"), "that and that"); +} + +TEST(replaceStrings, doesntOccur) +{ + ASSERT_EQ(replaceStrings("this and that", "foo", "bar"), "this and that"); +} + +/* ---------------------------------------------------------------------------- + * trim + * --------------------------------------------------------------------------*/ + +TEST(trim, emptyString) +{ + ASSERT_EQ(trim(""), ""); +} + +TEST(trim, removesWhitespace) +{ + ASSERT_EQ(trim("foo"), "foo"); + ASSERT_EQ(trim(" foo "), "foo"); + ASSERT_EQ(trim(" foo bar baz"), "foo bar baz"); + ASSERT_EQ(trim(" \t foo bar baz\n"), "foo bar baz"); +} + +/* ---------------------------------------------------------------------------- + * chomp + * --------------------------------------------------------------------------*/ + +TEST(chomp, emptyString) +{ + ASSERT_EQ(chomp(""), ""); +} + +TEST(chomp, removesWhitespace) +{ + ASSERT_EQ(chomp("foo"), "foo"); + ASSERT_EQ(chomp("foo "), "foo"); + ASSERT_EQ(chomp(" foo "), " foo"); + ASSERT_EQ(chomp(" foo bar baz "), " foo bar baz"); + ASSERT_EQ(chomp("\t foo bar baz\n"), "\t foo bar baz"); +} + +/* ---------------------------------------------------------------------------- + * quoteStrings + * --------------------------------------------------------------------------*/ + +TEST(quoteStrings, empty) +{ + Strings s = {}; + Strings expected = {}; + + ASSERT_EQ(quoteStrings(s), expected); +} + +TEST(quoteStrings, emptyStrings) +{ + Strings s = {"", "", ""}; + Strings expected = {"''", "''", "''"}; + ASSERT_EQ(quoteStrings(s), expected); +} + +TEST(quoteStrings, trivialQuote) +{ + Strings s = {"foo", "bar", "baz"}; + Strings expected = {"'foo'", "'bar'", "'baz'"}; + + ASSERT_EQ(quoteStrings(s), expected); +} + +TEST(quoteStrings, quotedStrings) +{ + Strings s = {"'foo'", "'bar'", "'baz'"}; + Strings expected = {"''foo''", "''bar''", "''baz''"}; + + ASSERT_EQ(quoteStrings(s), expected); +} + +/* ---------------------------------------------------------------------------- + * get + * --------------------------------------------------------------------------*/ + +TEST(get, emptyContainer) +{ + StringMap s = {}; + auto expected = nullptr; + + ASSERT_EQ(get(s, "one"), expected); +} + +TEST(get, getFromContainer) +{ + StringMap s; + s["one"] = "yi"; + s["two"] = "er"; + auto expected = "yi"; + + ASSERT_EQ(*get(s, "one"), expected); +} + +TEST(getOr, emptyContainer) +{ + StringMap s = {}; + auto expected = "yi"; + + ASSERT_EQ(getOr(s, "one", "yi"), expected); +} + +TEST(getOr, getFromContainer) +{ + StringMap s; + s["one"] = "yi"; + s["two"] = "er"; + auto expected = "yi"; + + ASSERT_EQ(getOr(s, "one", "nope"), expected); +} + +} // namespace nix From 0a00bd07b2421acfb21751a718292affa8c6e837 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 5 Aug 2024 18:56:02 +0200 Subject: [PATCH 040/718] PathSubstitutionGoal: Fix spurious "failed" count in the progress bar It is not an error if queryPathInfo() indicates that a path does not exist in the substituter. Fixes #11198. This was broken in 846869da0ed0580beb7f827b303fef9a8386de37. --- src/libstore/build/substitution-goal.cc | 8 +++++--- src/libstore/build/substitution-goal.hh | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/libstore/build/substitution-goal.cc b/src/libstore/build/substitution-goal.cc index 7deeb4748..0152f1808 100644 --- a/src/libstore/build/substitution-goal.cc +++ b/src/libstore/build/substitution-goal.cc @@ -145,8 +145,10 @@ Goal::Co PathSubstitutionGoal::init() /* None left. Terminate this goal and let someone else deal with it. */ - worker.failedSubstitutions++; - worker.updateProgress(); + if (substituterFailed) { + worker.failedSubstitutions++; + worker.updateProgress(); + } /* Hack: don't indicate failure if there were no substituters. In that case the calling derivation should just do a @@ -158,7 +160,7 @@ Goal::Co PathSubstitutionGoal::init() } -Goal::Co PathSubstitutionGoal::tryToRun(StorePath subPath, nix::ref sub, std::shared_ptr info, bool& substituterFailed) +Goal::Co PathSubstitutionGoal::tryToRun(StorePath subPath, nix::ref sub, std::shared_ptr info, bool & substituterFailed) { trace("all references realised"); diff --git a/src/libstore/build/substitution-goal.hh b/src/libstore/build/substitution-goal.hh index c1de45379..f2cf797e5 100644 --- a/src/libstore/build/substitution-goal.hh +++ b/src/libstore/build/substitution-goal.hh @@ -66,7 +66,7 @@ public: */ Co init() override; Co gotInfo(); - Co tryToRun(StorePath subPath, nix::ref sub, std::shared_ptr info, bool& substituterFailed); + Co tryToRun(StorePath subPath, nix::ref sub, std::shared_ptr info, bool & substituterFailed); Co finished(); /** From 1c5f1de43f3497e47d638bb04fdf0a033de2036d Mon Sep 17 00:00:00 2001 From: Jeremy Kolb Date: Mon, 5 Aug 2024 14:15:14 -0400 Subject: [PATCH 041/718] copy string using filterANSIEscapes and enforce the max length --- src/nix/flake.cc | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 48bec08c1..a5c6ff876 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -17,6 +17,7 @@ #include "eval-cache.hh" #include "markdown.hh" #include "users.hh" +#include "terminal.hh" #include #include @@ -1263,18 +1264,16 @@ struct CmdFlakeShow : FlakeCommand, MixJSON "package"; if (description && !description->empty()) { // Trim the string and only display the first line of the description. + const size_t maxLength = 77; auto trimmed = nix::trim(*description); auto newLinePos = trimmed.find('\n'); - auto length = newLinePos != std::string::npos ? newLinePos : trimmed.size(); + auto length = newLinePos != std::string::npos ? newLinePos : trimmed.length(); - // If the string is too long then resize add ellipses - std::string desc; - if (length > 77) { - trimmed.resize(77); - desc = trimmed.append("..."); - } - else { - desc = trimmed.substr(0, length); + // Resize/sanitize the string and if it's too long add ellipses + std::string desc = filterANSIEscapes(trimmed, false, length); + if (desc.length() > maxLength) { + desc.resize(maxLength); + desc = desc.append("..."); } logger->cout("%s: %s '%s' - '%s'", headerPrefix, type, name, desc); From 9bf6684b08368f850f6c451ec7313da0ae88738e Mon Sep 17 00:00:00 2001 From: Jeremy Kolb Date: Tue, 6 Aug 2024 09:39:42 -0400 Subject: [PATCH 042/718] Use window size --- src/nix/flake.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/nix/flake.cc b/src/nix/flake.cc index a5c6ff876..8ef19e3ea 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -1263,8 +1263,11 @@ struct CmdFlakeShow : FlakeCommand, MixJSON attrPath.size() >= 1 && attrPathS[0] == "hydraJobs" ? "derivation" : "package"; if (description && !description->empty()) { + // Maximum length to print + size_t maxLength = getWindowSize().second; + if (maxLength == 0) + maxLength = 77; // Trim the string and only display the first line of the description. - const size_t maxLength = 77; auto trimmed = nix::trim(*description); auto newLinePos = trimmed.find('\n'); auto length = newLinePos != std::string::npos ? newLinePos : trimmed.length(); From 6c861b9c51b6dece17dbd94e9016d7984159c9a8 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 5 Aug 2024 12:05:29 -0400 Subject: [PATCH 043/718] Factor out `lookupExecutable` and other PATH improvments This ended up motivating a good deal of other infra improvements in order to get Windows right: - `OsString` to complement `std::filesystem::path` - env var code for working with the underlying `OsString`s - Rename `PATHNG_LITERAL` to `OS_STR` - `NativePathTrait` renamed to `OsPathTrait`, given a character template parameter until #9205 is complete. Split `tests.cc` matching split of `util.{cc,hh}` last year. Co-authored-by: Robert Hensing --- .clang-format | 1 + maintainers/flake-module.nix | 3 - src/libutil/environment-variables.cc | 11 +- src/libutil/environment-variables.hh | 11 ++ src/libutil/executable-path.cc | 79 +++++++++++++ src/libutil/executable-path.hh | 64 +++++++++++ src/libutil/file-path-impl.hh | 9 +- src/libutil/file-path.hh | 25 +--- src/libutil/file-system.cc | 23 +++- src/libutil/file-system.hh | 6 + src/libutil/meson.build | 3 + src/libutil/os-string.hh | 43 +++++++ src/libutil/strings-inline.hh | 46 +++++++- src/libutil/strings.cc | 9 ++ src/libutil/strings.hh | 20 ++++ src/libutil/unix/environment-variables.cc | 10 ++ src/libutil/unix/file-path.cc | 10 -- src/libutil/unix/meson.build | 1 + src/libutil/unix/os-string.cc | 21 ++++ src/libutil/util.cc | 1 + src/libutil/windows/environment-variables.cc | 30 ++++- src/libutil/windows/file-path.cc | 12 -- src/libutil/windows/meson.build | 1 + src/libutil/windows/os-string.cc | 24 ++++ src/nix/config-check.cc | 36 ++++-- src/nix/develop.cc | 6 +- src/nix/env.cc | 9 +- src/nix/search.cc | 1 + src/nix/upgrade-nix.cc | 19 ++-- tests/unit/libutil/executable-path.cc | 64 +++++++++++ tests/unit/libutil/meson.build | 1 + tests/unit/libutil/strings.cc | 114 +++++++++++++++++++ 32 files changed, 616 insertions(+), 97 deletions(-) create mode 100644 src/libutil/executable-path.cc create mode 100644 src/libutil/executable-path.hh create mode 100644 src/libutil/os-string.hh create mode 100644 src/libutil/unix/os-string.cc create mode 100644 src/libutil/windows/os-string.cc create mode 100644 tests/unit/libutil/executable-path.cc diff --git a/.clang-format b/.clang-format index 3067583e1..4f191fc18 100644 --- a/.clang-format +++ b/.clang-format @@ -31,3 +31,4 @@ AlwaysBreakBeforeMultilineStrings: true IndentPPDirectives: AfterHash PPIndentWidth: 2 BinPackArguments: false +BreakBeforeTernaryOperators: true diff --git a/maintainers/flake-module.nix b/maintainers/flake-module.nix index be91df536..c3eaf671c 100644 --- a/maintainers/flake-module.nix +++ b/maintainers/flake-module.nix @@ -275,7 +275,6 @@ ''^src/libutil/current-process\.hh$'' ''^src/libutil/english\.cc$'' ''^src/libutil/english\.hh$'' - ''^src/libutil/environment-variables\.cc$'' ''^src/libutil/error\.cc$'' ''^src/libutil/error\.hh$'' ''^src/libutil/exit\.hh$'' @@ -357,7 +356,6 @@ ''^src/libutil/util\.cc$'' ''^src/libutil/util\.hh$'' ''^src/libutil/variant-wrapper\.hh$'' - ''^src/libutil/windows/environment-variables\.cc$'' ''^src/libutil/windows/file-descriptor\.cc$'' ''^src/libutil/windows/file-path\.cc$'' ''^src/libutil/windows/processes\.cc$'' @@ -485,7 +483,6 @@ ''^tests/unit/libutil/pool\.cc'' ''^tests/unit/libutil/references\.cc'' ''^tests/unit/libutil/suggestions\.cc'' - ''^tests/unit/libutil/tests\.cc'' ''^tests/unit/libutil/url\.cc'' ''^tests/unit/libutil/xml-writer\.cc'' ]; diff --git a/src/libutil/environment-variables.cc b/src/libutil/environment-variables.cc index d43197aa0..5947cf742 100644 --- a/src/libutil/environment-variables.cc +++ b/src/libutil/environment-variables.cc @@ -1,20 +1,23 @@ #include "util.hh" #include "environment-variables.hh" -extern char * * environ __attribute__((weak)); +extern char ** environ __attribute__((weak)); namespace nix { std::optional getEnv(const std::string & key) { char * value = getenv(key.c_str()); - if (!value) return {}; + if (!value) + return {}; return std::string(value); } -std::optional getEnvNonEmpty(const std::string & key) { +std::optional getEnvNonEmpty(const std::string & key) +{ auto value = getEnv(key); - if (value == "") return {}; + if (value == "") + return {}; return value; } diff --git a/src/libutil/environment-variables.hh b/src/libutil/environment-variables.hh index e0649adac..879e1f304 100644 --- a/src/libutil/environment-variables.hh +++ b/src/libutil/environment-variables.hh @@ -9,6 +9,7 @@ #include #include "types.hh" +#include "file-path.hh" namespace nix { @@ -17,6 +18,11 @@ namespace nix { */ std::optional getEnv(const std::string & key); +/** + * Like `getEnv`, but using `OsString` to avoid coercions. + */ +std::optional getEnvOs(const OsString & key); + /** * @return a non empty environment variable. Returns nullopt if the env * variable is set to "" @@ -43,6 +49,11 @@ int unsetenv(const char * name); */ int setEnv(const char * name, const char * value); +/** + * Like `setEnv`, but using `OsString` to avoid coercions. + */ +int setEnvOs(const OsString & name, const OsString & value); + /** * Clear the environment. */ diff --git a/src/libutil/executable-path.cc b/src/libutil/executable-path.cc new file mode 100644 index 000000000..1658e3667 --- /dev/null +++ b/src/libutil/executable-path.cc @@ -0,0 +1,79 @@ +#include "environment-variables.hh" +#include "executable-path.hh" +#include "strings-inline.hh" +#include "util.hh" +#include "file-path-impl.hh" + +namespace nix { + +namespace fs = std::filesystem; + +constexpr static const OsStringView path_var_separator{ + &ExecutablePath::separator, + 1, +}; + +ExecutablePath ExecutablePath::load() +{ + // "If PATH is unset or is set to null, the path search is + // implementation-defined." + // https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03 + return ExecutablePath::parse(getEnvOs(OS_STR("PATH")).value_or(OS_STR(""))); +} + +ExecutablePath ExecutablePath::parse(const OsString & path) +{ + auto strings = path.empty() ? (std::list{}) + : basicSplitString, OsString::value_type>(path, path_var_separator); + + std::vector ret; + ret.reserve(strings.size()); + + std::transform( + std::make_move_iterator(strings.begin()), + std::make_move_iterator(strings.end()), + std::back_inserter(ret), + [](auto && str) { + return fs::path{ + str.empty() + // "A zero-length prefix is a legacy feature that + // indicates the current working directory. It + // appears as two adjacent characters + // ("::"), as an initial preceding the rest + // of the list, or as a trailing following + // the rest of the list." + // https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03 + ? OS_STR(".") + : std::move(str), + }; + }); + + return {ret}; +} + +OsString ExecutablePath::render() const +{ + std::vector path2; + for (auto & p : directories) + path2.push_back(p.native()); + return basicConcatStringsSep(path_var_separator, path2); +} + +std::optional +ExecutablePath::find(const OsString & exe, std::function isExecutable) const +{ + // "If the pathname being sought contains a , the search + // through the path prefixes shall not be performed." + // https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03 + assert(OsPathTrait::rfindPathSep(exe) == exe.npos); + + for (auto & dir : directories) { + auto candidate = dir / exe; + if (isExecutable(candidate)) + return std::filesystem::canonical(candidate); + } + + return std::nullopt; +} + +} // namespace nix diff --git a/src/libutil/executable-path.hh b/src/libutil/executable-path.hh new file mode 100644 index 000000000..bcb8d28e8 --- /dev/null +++ b/src/libutil/executable-path.hh @@ -0,0 +1,64 @@ +#pragma once +///@file + +#include "file-system.hh" + +namespace nix { + +struct ExecutablePath +{ + std::vector directories; + + constexpr static const OsString::value_type separator = +#ifdef WIN32 + L';' +#else + ':' +#endif + ; + + /** + * Parse `path` into a list of paths. + * + * On Unix we split on `:`, on Windows we split on `;`. + * + * For Unix, this is according to the POSIX spec for `PATH`. + * https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03 + */ + static ExecutablePath parse(const OsString & path); + + /** + * Load the `PATH` environment variable and `parse` it. + */ + static ExecutablePath load(); + + /** + * Opposite of `parse` + */ + OsString render() const; + + /** + * Search for an executable. + * + * For Unix, this is according to the POSIX spec for `PATH`. + * https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03 + * + * @param exe This must just be a name, and not contain any `/` (or + * `\` on Windows). in case it does, per the spec no lookup should + * be perfomed, and the path (it is not just a file name) as is. + * This is the caller's respsonsibility. + * + * This is a pure function, except for the default `isExecutable` + * argument, which uses the ambient file system to check if a file is + * executable (and exists). + * + * @return path to a resolved executable + */ + std::optional find( + const OsString & exe, + std::function isExecutableFile = isExecutableFileAmbient) const; + + bool operator==(const ExecutablePath &) const = default; +}; + +} // namespace nix diff --git a/src/libutil/file-path-impl.hh b/src/libutil/file-path-impl.hh index 4c90150fd..d7c823fd0 100644 --- a/src/libutil/file-path-impl.hh +++ b/src/libutil/file-path-impl.hh @@ -91,13 +91,10 @@ struct WindowsPathTrait }; -/** - * @todo Revisit choice of `char` or `wchar_t` for `WindowsPathTrait` - * argument. - */ -using NativePathTrait = +template +using OsPathTrait = #ifdef _WIN32 - WindowsPathTrait + WindowsPathTrait #else UnixPathTrait #endif diff --git a/src/libutil/file-path.hh b/src/libutil/file-path.hh index 6589c4060..8e4a88b9d 100644 --- a/src/libutil/file-path.hh +++ b/src/libutil/file-path.hh @@ -1,10 +1,10 @@ #pragma once ///@file -#include #include #include "types.hh" +#include "os-string.hh" namespace nix { @@ -22,39 +22,26 @@ typedef std::set PathSetNG; * * @todo drop `NG` suffix and replace the one in `types.hh`. */ -struct PathViewNG : std::basic_string_view +struct PathViewNG : OsStringView { - using string_view = std::basic_string_view; + using string_view = OsStringView; using string_view::string_view; PathViewNG(const std::filesystem::path & path) - : std::basic_string_view(path.native()) + : OsStringView{path.native()} { } - PathViewNG(const std::filesystem::path::string_type & path) - : std::basic_string_view(path) + PathViewNG(const OsString & path) + : OsStringView{path} { } const string_view & native() const { return *this; } string_view & native() { return *this; } }; -std::string os_string_to_string(PathViewNG::string_view path); - -std::filesystem::path::string_type string_to_os_string(std::string_view s); - std::optional maybePath(PathView path); std::filesystem::path pathNG(PathView path); -/** - * Create string literals with the native character width of paths - */ -#ifndef _WIN32 -# define PATHNG_LITERAL(s) s -#else -# define PATHNG_LITERAL(s) L ## s -#endif - } diff --git a/src/libutil/file-system.cc b/src/libutil/file-system.cc index 060a806fb..156dddf98 100644 --- a/src/libutil/file-system.cc +++ b/src/libutil/file-system.cc @@ -92,7 +92,7 @@ Path canonPath(PathView path, bool resolveSymlinks) arbitrary (but high) limit to prevent infinite loops. */ unsigned int followCount = 0, maxFollow = 1024; - auto ret = canonPathInner( + auto ret = canonPathInner>( path, [&followCount, &temp, maxFollow, resolveSymlinks] (std::string & result, std::string_view & remaining) { @@ -122,7 +122,7 @@ Path canonPath(PathView path, bool resolveSymlinks) Path dirOf(const PathView path) { - Path::size_type pos = NativePathTrait::rfindPathSep(path); + Path::size_type pos = OsPathTrait::rfindPathSep(path); if (pos == path.npos) return "."; return fs::path{path}.parent_path().string(); @@ -135,10 +135,10 @@ std::string_view baseNameOf(std::string_view path) return ""; auto last = path.size() - 1; - while (last > 0 && NativePathTrait::isPathSep(path[last])) + while (last > 0 && OsPathTrait::isPathSep(path[last])) last -= 1; - auto pos = NativePathTrait::rfindPathSep(path, last); + auto pos = OsPathTrait::rfindPathSep(path, last); if (pos == path.npos) pos = 0; else @@ -569,7 +569,7 @@ void replaceSymlink(const Path & target, const Path & link) } void setWriteTime( - const std::filesystem::path & path, + const fs::path & path, time_t accessedTime, time_t modificationTime, std::optional optIsSymlink) @@ -685,4 +685,17 @@ void moveFile(const Path & oldName, const Path & newName) ////////////////////////////////////////////////////////////////////// +bool isExecutableFileAmbient(const fs::path & exe) { + // Check file type, because directory being executable means + // something completely different. + return std::filesystem::is_regular_file(exe) + && access(exe.string().c_str(), +#ifdef WIN32 + 0 // TODO do better +#else + X_OK +#endif + ) == 0; +} + } diff --git a/src/libutil/file-system.hh b/src/libutil/file-system.hh index 4b215162d..5350ceb7e 100644 --- a/src/libutil/file-system.hh +++ b/src/libutil/file-system.hh @@ -263,6 +263,12 @@ std::pair createTempFile(const Path & prefix = "nix"); */ Path defaultTempDir(); +/** + * Interpret `exe` as a location in the ambient file system and return + * whether it exists AND is executable. + */ +bool isExecutableFileAmbient(const std::filesystem::path & exe); + /** * Used in various places. */ diff --git a/src/libutil/meson.build b/src/libutil/meson.build index 8552c4c9d..8ff7ee51f 100644 --- a/src/libutil/meson.build +++ b/src/libutil/meson.build @@ -129,6 +129,7 @@ sources = files( 'english.cc', 'environment-variables.cc', 'error.cc', + 'executable-path.cc', 'exit.cc', 'experimental-features.cc', 'file-content-address.cc', @@ -183,6 +184,7 @@ headers = [config_h] + files( 'english.hh', 'environment-variables.hh', 'error.hh', + 'executable-path.hh', 'exit.hh', 'experimental-features.hh', 'file-content-address.hh', @@ -202,6 +204,7 @@ headers = [config_h] + files( 'lru-cache.hh', 'memory-source-accessor.hh', 'muxable-pipe.hh', + 'os-string.hh', 'pool.hh', 'position.hh', 'posix-source-accessor.hh', diff --git a/src/libutil/os-string.hh b/src/libutil/os-string.hh new file mode 100644 index 000000000..0d75173e5 --- /dev/null +++ b/src/libutil/os-string.hh @@ -0,0 +1,43 @@ +#pragma once +///@file + +#include +#include +#include + +namespace nix { + +/** + * Named because it is similar to the Rust type, except it is in the + * native encoding not WTF-8. + * + * Same as `std::filesystem::path::string_type`, but manually defined to + * avoid including a much more complex header. + */ +using OsString = std::basic_string< +#if defined(_WIN32) && !defined(__CYGWIN__) + wchar_t +#else + char +#endif + >; + +/** + * `std::string_view` counterpart for `OsString`. + */ +using OsStringView = std::basic_string_view; + +std::string os_string_to_string(OsStringView path); + +OsString string_to_os_string(std::string_view s); + +/** + * Create string literals with the native character width of paths + */ +#ifndef _WIN32 +# define OS_STR(s) s +#else +# define OS_STR(s) L##s +#endif + +} diff --git a/src/libutil/strings-inline.hh b/src/libutil/strings-inline.hh index d254d486d..25b8e0ff6 100644 --- a/src/libutil/strings-inline.hh +++ b/src/libutil/strings-inline.hh @@ -4,8 +4,8 @@ namespace nix { -template -C tokenizeString(std::string_view s, std::string_view separators) +template +C basicTokenizeString(std::basic_string_view s, std::basic_string_view separators) { C result; auto pos = s.find_first_not_of(separators, 0); @@ -13,14 +13,42 @@ C tokenizeString(std::string_view s, std::string_view separators) auto end = s.find_first_of(separators, pos + 1); if (end == s.npos) end = s.size(); - result.insert(result.end(), std::string(s, pos, end - pos)); + result.insert(result.end(), std::basic_string(s, pos, end - pos)); pos = s.find_first_not_of(separators, end); } return result; } template -std::string concatStringsSep(const std::string_view sep, const C & ss) +C tokenizeString(std::string_view s, std::string_view separators) +{ + return basicTokenizeString(s, separators); +} + +template +C basicSplitString(std::basic_string_view s, std::basic_string_view separators) +{ + C result; + size_t pos = 0; + while (pos <= s.size()) { + auto end = s.find_first_of(separators, pos); + if (end == s.npos) + end = s.size(); + result.insert(result.end(), std::basic_string(s, pos, end - pos)); + pos = end + 1; + } + + return result; +} + +template +C splitString(std::string_view s, std::string_view separators) +{ + return basicSplitString(s, separators); +} + +template +std::basic_string basicConcatStringsSep(const std::basic_string_view sep, const C & ss) { size_t size = 0; bool tail = false; @@ -28,10 +56,10 @@ std::string concatStringsSep(const std::string_view sep, const C & ss) for (const auto & s : ss) { if (tail) size += sep.size(); - size += std::string_view(s).size(); + size += std::basic_string_view{s}.size(); tail = true; } - std::string s; + std::basic_string s; s.reserve(size); tail = false; for (auto & i : ss) { @@ -43,6 +71,12 @@ std::string concatStringsSep(const std::string_view sep, const C & ss) return s; } +template +std::string concatStringsSep(const std::string_view sep, const C & ss) +{ + return basicConcatStringsSep(sep, ss); +} + template std::string dropEmptyInitThenConcatStringsSep(const std::string_view sep, const C & ss) { diff --git a/src/libutil/strings.cc b/src/libutil/strings.cc index 2bb7f8c0a..60297228e 100644 --- a/src/libutil/strings.cc +++ b/src/libutil/strings.cc @@ -1,6 +1,8 @@ +#include #include #include "strings-inline.hh" +#include "os-string.hh" namespace nix { @@ -8,6 +10,13 @@ template std::list tokenizeString(std::string_view s, std::string_v template std::set tokenizeString(std::string_view s, std::string_view separators); template std::vector tokenizeString(std::string_view s, std::string_view separators); +template std::list splitString(std::string_view s, std::string_view separators); +template std::set splitString(std::string_view s, std::string_view separators); +template std::vector splitString(std::string_view s, std::string_view separators); + +template std::list basicSplitString( + std::basic_string_view s, std::basic_string_view separators); + template std::string concatStringsSep(std::string_view, const std::list &); template std::string concatStringsSep(std::string_view, const std::set &); template std::string concatStringsSep(std::string_view, const std::vector &); diff --git a/src/libutil/strings.hh b/src/libutil/strings.hh index 6e991e490..88b48d770 100644 --- a/src/libutil/strings.hh +++ b/src/libutil/strings.hh @@ -13,6 +13,12 @@ namespace nix { * * See also `basicSplitString()`, which preserves empty strings between separators, as well as at the start and end. */ +template +C basicTokenizeString(std::basic_string_view s, std::basic_string_view separators); + +/** + * Like `basicTokenizeString` but specialized to the default `char` + */ template C tokenizeString(std::string_view s, std::string_view separators = " \t\n\r"); @@ -20,6 +26,20 @@ extern template std::list tokenizeString(std::string_view s, std::s extern template std::set tokenizeString(std::string_view s, std::string_view separators); extern template std::vector tokenizeString(std::string_view s, std::string_view separators); +/** + * Split a string, preserving empty strings between separators, as well as at the start and end. + * + * Returns a non-empty collection of strings. + */ +template +C basicSplitString(std::basic_string_view s, std::basic_string_view separators); +template +C splitString(std::string_view s, std::string_view separators); + +extern template std::list splitString(std::string_view s, std::string_view separators); +extern template std::set splitString(std::string_view s, std::string_view separators); +extern template std::vector splitString(std::string_view s, std::string_view separators); + /** * Concatenate the given strings with a separator between the elements. */ diff --git a/src/libutil/unix/environment-variables.cc b/src/libutil/unix/environment-variables.cc index 9c6fd3b18..cd7c8f5e5 100644 --- a/src/libutil/unix/environment-variables.cc +++ b/src/libutil/unix/environment-variables.cc @@ -9,4 +9,14 @@ int setEnv(const char * name, const char * value) return ::setenv(name, value, 1); } +std::optional getEnvOs(const std::string & key) +{ + return getEnv(key); +} + +int setEnvOs(const OsString & name, const OsString & value) +{ + return setEnv(name.c_str(), value.c_str()); +} + } diff --git a/src/libutil/unix/file-path.cc b/src/libutil/unix/file-path.cc index 294048a2f..cccee86a1 100644 --- a/src/libutil/unix/file-path.cc +++ b/src/libutil/unix/file-path.cc @@ -8,16 +8,6 @@ namespace nix { -std::string os_string_to_string(PathViewNG::string_view path) -{ - return std::string { path }; -} - -std::filesystem::path::string_type string_to_os_string(std::string_view s) -{ - return std::string { s }; -} - std::optional maybePath(PathView path) { return { path }; diff --git a/src/libutil/unix/meson.build b/src/libutil/unix/meson.build index 38e5cd3aa..1c5bf27fb 100644 --- a/src/libutil/unix/meson.build +++ b/src/libutil/unix/meson.build @@ -4,6 +4,7 @@ sources += files( 'file-path.cc', 'file-system.cc', 'muxable-pipe.cc', + 'os-string.cc', 'processes.cc', 'signals.cc', 'users.cc', diff --git a/src/libutil/unix/os-string.cc b/src/libutil/unix/os-string.cc new file mode 100644 index 000000000..8378afde2 --- /dev/null +++ b/src/libutil/unix/os-string.cc @@ -0,0 +1,21 @@ +#include +#include +#include +#include + +#include "file-path.hh" +#include "util.hh" + +namespace nix { + +std::string os_string_to_string(PathViewNG::string_view path) +{ + return std::string{path}; +} + +std::filesystem::path::string_type string_to_os_string(std::string_view s) +{ + return std::string{s}; +} + +} diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 460802be3..db3ed1ddf 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -1,5 +1,6 @@ #include "util.hh" #include "fmt.hh" +#include "file-path.hh" #include #include diff --git a/src/libutil/windows/environment-variables.cc b/src/libutil/windows/environment-variables.cc index 25ab9d63a..525d08c64 100644 --- a/src/libutil/windows/environment-variables.cc +++ b/src/libutil/windows/environment-variables.cc @@ -4,7 +4,30 @@ namespace nix { -int unsetenv(const char *name) +std::optional getEnvOs(const OsString & key) +{ + // Determine the required buffer size for the environment variable value + DWORD bufferSize = GetEnvironmentVariableW(key.c_str(), nullptr, 0); + if (bufferSize == 0) { + return std::nullopt; + } + + // Allocate a buffer to hold the environment variable value + std::wstring value{L'\0', bufferSize}; + + // Retrieve the environment variable value + DWORD resultSize = GetEnvironmentVariableW(key.c_str(), &value[0], bufferSize); + if (resultSize == 0) { + return std::nullopt; + } + + // Resize the string to remove the extra null characters + value.resize(resultSize); + + return value; +} + +int unsetenv(const char * name) { return -SetEnvironmentVariableA(name, nullptr); } @@ -14,4 +37,9 @@ int setEnv(const char * name, const char * value) return -SetEnvironmentVariableA(name, value); } +int setEnvOs(const OsString & name, const OsString & value) +{ + return -SetEnvironmentVariableW(name.c_str(), value.c_str()); +} + } diff --git a/src/libutil/windows/file-path.cc b/src/libutil/windows/file-path.cc index 3114ac4df..7405c426b 100644 --- a/src/libutil/windows/file-path.cc +++ b/src/libutil/windows/file-path.cc @@ -9,18 +9,6 @@ namespace nix { -std::string os_string_to_string(PathViewNG::string_view path) -{ - std::wstring_convert> converter; - return converter.to_bytes(std::filesystem::path::string_type { path }); -} - -std::filesystem::path::string_type string_to_os_string(std::string_view s) -{ - std::wstring_convert> converter; - return converter.from_bytes(std::string { s }); -} - std::optional maybePath(PathView path) { if (path.length() >= 3 && (('A' <= path[0] && path[0] <= 'Z') || ('a' <= path[0] && path[0] <= 'z')) && path[1] == ':' && WindowsPathTrait::isPathSep(path[2])) { diff --git a/src/libutil/windows/meson.build b/src/libutil/windows/meson.build index 00320877f..1c645fe05 100644 --- a/src/libutil/windows/meson.build +++ b/src/libutil/windows/meson.build @@ -4,6 +4,7 @@ sources += files( 'file-path.cc', 'file-system.cc', 'muxable-pipe.cc', + 'os-string.cc', 'processes.cc', 'users.cc', 'windows-async-pipe.cc', diff --git a/src/libutil/windows/os-string.cc b/src/libutil/windows/os-string.cc new file mode 100644 index 000000000..7507f9030 --- /dev/null +++ b/src/libutil/windows/os-string.cc @@ -0,0 +1,24 @@ +#include +#include +#include +#include + +#include "file-path.hh" +#include "file-path-impl.hh" +#include "util.hh" + +namespace nix { + +std::string os_string_to_string(PathViewNG::string_view path) +{ + std::wstring_convert> converter; + return converter.to_bytes(std::filesystem::path::string_type{path}); +} + +std::filesystem::path::string_type string_to_os_string(std::string_view s) +{ + std::wstring_convert> converter; + return converter.from_bytes(std::string{s}); +} + +} diff --git a/src/nix/config-check.cc b/src/nix/config-check.cc index 09d140733..1a6574de2 100644 --- a/src/nix/config-check.cc +++ b/src/nix/config-check.cc @@ -8,6 +8,7 @@ #include "store-api.hh" #include "local-fs-store.hh" #include "worker-protocol.hh" +#include "executable-path.hh" using namespace nix; @@ -39,6 +40,8 @@ void checkInfo(const std::string & msg) { } +namespace fs = std::filesystem; + struct CmdConfigCheck : StoreCommand { bool success = true; @@ -75,11 +78,13 @@ struct CmdConfigCheck : StoreCommand bool checkNixInPath() { - PathSet dirs; + std::set dirs; - for (auto & dir : tokenizeString(getEnv("PATH").value_or(""), ":")) - if (pathExists(dir + "/nix-env")) - dirs.insert(dirOf(canonPath(dir + "/nix-env", true))); + for (auto & dir : ExecutablePath::load().directories) { + auto candidate = dir / "nix-env"; + if (fs::exists(candidate)) + dirs.insert(fs::canonical(candidate).parent_path() ); + } if (dirs.size() != 1) { std::stringstream ss; @@ -94,18 +99,25 @@ struct CmdConfigCheck : StoreCommand bool checkProfileRoots(ref store) { - PathSet dirs; + std::set dirs; - for (auto & dir : tokenizeString(getEnv("PATH").value_or(""), ":")) { - Path profileDir = dirOf(dir); + for (auto & dir : ExecutablePath::load().directories) { + auto profileDir = dir.parent_path(); try { - Path userEnv = canonPath(profileDir, true); + auto userEnv = fs::weakly_canonical(profileDir); - if (store->isStorePath(userEnv) && hasSuffix(userEnv, "user-environment")) { - while (profileDir.find("/profiles/") == std::string::npos && std::filesystem::is_symlink(profileDir)) - profileDir = absPath(readLink(profileDir), dirOf(profileDir)); + auto noContainsProfiles = [&]{ + for (auto && part : profileDir) + if (part == "profiles") return false; + return true; + }; - if (profileDir.find("/profiles/") == std::string::npos) + if (store->isStorePath(userEnv.string()) && hasSuffix(userEnv.string(), "user-environment")) { + while (noContainsProfiles() && std::filesystem::is_symlink(profileDir)) + profileDir = fs::weakly_canonical( + profileDir.parent_path() / fs::read_symlink(profileDir)); + + if (noContainsProfiles()) dirs.insert(dir); } } catch (SystemError &) { diff --git a/src/nix/develop.cc b/src/nix/develop.cc index 92ec3b78a..effc86a0a 100644 --- a/src/nix/develop.cc +++ b/src/nix/develop.cc @@ -415,7 +415,7 @@ struct Common : InstallableCommand, MixProfile if (buildEnvironment.providesStructuredAttrs()) { fixupStructuredAttrs( - PATHNG_LITERAL("sh"), + OS_STR("sh"), "NIX_ATTRS_SH_FILE", buildEnvironment.getAttrsSH(), rewrites, @@ -423,7 +423,7 @@ struct Common : InstallableCommand, MixProfile tmpDir ); fixupStructuredAttrs( - PATHNG_LITERAL("json"), + OS_STR("json"), "NIX_ATTRS_JSON_FILE", buildEnvironment.getAttrsJSON(), rewrites, @@ -447,7 +447,7 @@ struct Common : InstallableCommand, MixProfile const BuildEnvironment & buildEnvironment, const std::filesystem::path & tmpDir) { - auto targetFilePath = tmpDir / PATHNG_LITERAL(".attrs."); + auto targetFilePath = tmpDir / OS_STR(".attrs."); targetFilePath += ext; writeFile(targetFilePath.string(), content); diff --git a/src/nix/env.cc b/src/nix/env.cc index 9db03ca37..832320320 100644 --- a/src/nix/env.cc +++ b/src/nix/env.cc @@ -5,6 +5,7 @@ #include "eval.hh" #include "run.hh" #include "strings.hh" +#include "executable-path.hh" using namespace nix; @@ -95,10 +96,10 @@ struct CmdShell : InstallablesCommand, MixEnvironment } // TODO: split losslessly; empty means . - auto unixPath = tokenizeString(getEnv("PATH").value_or(""), ":"); - unixPath.insert(unixPath.begin(), pathAdditions.begin(), pathAdditions.end()); - auto unixPathString = concatStringsSep(":", unixPath); - setEnv("PATH", unixPathString.c_str()); + auto unixPath = ExecutablePath::load(); + unixPath.directories.insert(unixPath.directories.begin(), pathAdditions.begin(), pathAdditions.end()); + auto unixPathString = unixPath.render(); + setEnvOs(OS_STR("PATH"), unixPathString.c_str()); Strings args; for (auto & arg : command) diff --git a/src/nix/search.cc b/src/nix/search.cc index 7f8504d3f..c8d0b9e96 100644 --- a/src/nix/search.cc +++ b/src/nix/search.cc @@ -10,6 +10,7 @@ #include "eval-cache.hh" #include "attr-path.hh" #include "hilite.hh" +#include "strings-inline.hh" #include #include diff --git a/src/nix/upgrade-nix.cc b/src/nix/upgrade-nix.cc index 7b3357700..9ca3f6087 100644 --- a/src/nix/upgrade-nix.cc +++ b/src/nix/upgrade-nix.cc @@ -8,6 +8,7 @@ #include "attr-path.hh" #include "names.hh" #include "progress-bar.hh" +#include "executable-path.hh" using namespace nix; @@ -102,23 +103,17 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand /* Return the profile in which Nix is installed. */ Path getProfileDir(ref store) { - Path where; - - for (auto & dir : tokenizeString(getEnv("PATH").value_or(""), ":")) - if (pathExists(dir + "/nix-env")) { - where = dir; - break; - } - - if (where == "") + auto whereOpt = ExecutablePath::load().find(OS_STR("nix-env")); + if (!whereOpt) throw Error("couldn't figure out how Nix is installed, so I can't upgrade it"); + auto & where = *whereOpt; printInfo("found Nix in '%s'", where); - if (hasPrefix(where, "/run/current-system")) + if (hasPrefix(where.string(), "/run/current-system")) throw Error("Nix on NixOS must be upgraded via 'nixos-rebuild'"); - Path profileDir = dirOf(where); + Path profileDir = where.parent_path().string(); // Resolve profile to /nix/var/nix/profiles/ link. while (canonPath(profileDir).find("/profiles/") == std::string::npos && std::filesystem::is_symlink(profileDir)) @@ -128,7 +123,7 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand Path userEnv = canonPath(profileDir, true); - if (baseNameOf(where) != "bin" || + if (where.filename() != "bin" || !hasSuffix(userEnv, "user-environment")) throw Error("directory '%s' does not appear to be part of a Nix profile", where); diff --git a/tests/unit/libutil/executable-path.cc b/tests/unit/libutil/executable-path.cc new file mode 100644 index 000000000..8d182357d --- /dev/null +++ b/tests/unit/libutil/executable-path.cc @@ -0,0 +1,64 @@ +#include + +#include "executable-path.hh" + +namespace nix { + +#ifdef WIN32 +# define PATH_VAR_SEP L";" +#else +# define PATH_VAR_SEP ":" +#endif + +#define PATH_ENV_ROUND_TRIP(NAME, STRING_LIT, CXX_LIT) \ + TEST(ExecutablePath, NAME) \ + { \ + OsString s = STRING_LIT; \ + auto v = ExecutablePath::parse(s); \ + EXPECT_EQ(v, (ExecutablePath CXX_LIT)); \ + auto s2 = v.render(); \ + EXPECT_EQ(s2, s); \ + } + +PATH_ENV_ROUND_TRIP(emptyRoundTrip, OS_STR(""), ({})) + +PATH_ENV_ROUND_TRIP( + oneElemRoundTrip, + OS_STR("/foo"), + ({ + OS_STR("/foo"), + })) + +PATH_ENV_ROUND_TRIP( + twoElemsRoundTrip, + OS_STR("/foo" PATH_VAR_SEP "/bar"), + ({ + OS_STR("/foo"), + OS_STR("/bar"), + })) + +PATH_ENV_ROUND_TRIP( + threeElemsRoundTrip, + OS_STR("/foo" PATH_VAR_SEP "." PATH_VAR_SEP "/bar"), + ({ + OS_STR("/foo"), + OS_STR("."), + OS_STR("/bar"), + })) + +TEST(ExecutablePath, elementyElemNormalize) +{ + auto v = ExecutablePath::parse(PATH_VAR_SEP PATH_VAR_SEP PATH_VAR_SEP); + EXPECT_EQ( + v, + (ExecutablePath{{ + OS_STR("."), + OS_STR("."), + OS_STR("."), + OS_STR("."), + }})); + auto s2 = v.render(); + EXPECT_EQ(s2, OS_STR("." PATH_VAR_SEP "." PATH_VAR_SEP "." PATH_VAR_SEP ".")); +} + +} diff --git a/tests/unit/libutil/meson.build b/tests/unit/libutil/meson.build index f4f2ae7f9..83cec13ec 100644 --- a/tests/unit/libutil/meson.build +++ b/tests/unit/libutil/meson.build @@ -52,6 +52,7 @@ sources = files( 'closure.cc', 'compression.cc', 'config.cc', + 'executable-path.cc', 'file-content-address.cc', 'git.cc', 'hash.cc', diff --git a/tests/unit/libutil/strings.cc b/tests/unit/libutil/strings.cc index 0bd2fe0a5..8ceb16767 100644 --- a/tests/unit/libutil/strings.cc +++ b/tests/unit/libutil/strings.cc @@ -1,4 +1,5 @@ #include +#include #include "strings.hh" @@ -231,4 +232,117 @@ TEST(tokenizeString, tokenizeSepEmpty) ASSERT_EQ(tokenizeString(s, ","), expected); } +/* ---------------------------------------------------------------------------- + * splitString + * --------------------------------------------------------------------------*/ + +TEST(splitString, empty) +{ + Strings expected = {""}; + + ASSERT_EQ(splitString("", " \t\n\r"), expected); +} + +TEST(splitString, oneSep) +{ + Strings expected = {"", ""}; + + ASSERT_EQ(splitString(" ", " \t\n\r"), expected); +} + +TEST(splitString, twoSep) +{ + Strings expected = {"", "", ""}; + + ASSERT_EQ(splitString(" \n", " \t\n\r"), expected); +} + +TEST(splitString, tokenizeSpacesWithSpaces) +{ + auto s = "foo bar baz"; + Strings expected = {"foo", "bar", "baz"}; + + ASSERT_EQ(splitString(s, " \t\n\r"), expected); +} + +TEST(splitString, tokenizeTabsWithDefaults) +{ + auto s = "foo\tbar\tbaz"; + // Using it like this is weird, but shows the difference with tokenizeString, which also has this test + Strings expected = {"foo", "bar", "baz"}; + + ASSERT_EQ(splitString(s, " \t\n\r"), expected); +} + +TEST(splitString, tokenizeTabsSpacesWithDefaults) +{ + auto s = "foo\t bar\t baz"; + // Using it like this is weird, but shows the difference with tokenizeString, which also has this test + Strings expected = {"foo", "", "bar", "", "baz"}; + + ASSERT_EQ(splitString(s, " \t\n\r"), expected); +} + +TEST(splitString, tokenizeTabsSpacesNewlineWithDefaults) +{ + auto s = "foo\t\n bar\t\n baz"; + // Using it like this is weird, but shows the difference with tokenizeString, which also has this test + Strings expected = {"foo", "", "", "bar", "", "", "baz"}; + + ASSERT_EQ(splitString(s, " \t\n\r"), expected); +} + +TEST(splitString, tokenizeTabsSpacesNewlineRetWithDefaults) +{ + auto s = "foo\t\n\r bar\t\n\r baz"; + // Using it like this is weird, but shows the difference with tokenizeString, which also has this test + Strings expected = {"foo", "", "", "", "bar", "", "", "", "baz"}; + + ASSERT_EQ(splitString(s, " \t\n\r"), expected); + + auto s2 = "foo \t\n\r bar \t\n\r baz"; + Strings expected2 = {"foo", "", "", "", "", "bar", "", "", "", "", "baz"}; + + ASSERT_EQ(splitString(s2, " \t\n\r"), expected2); +} + +TEST(splitString, tokenizeWithCustomSep) +{ + auto s = "foo\n,bar\n,baz\n"; + Strings expected = {"foo\n", "bar\n", "baz\n"}; + + ASSERT_EQ(splitString(s, ","), expected); +} + +TEST(splitString, tokenizeSepAtStart) +{ + auto s = ",foo,bar,baz"; + Strings expected = {"", "foo", "bar", "baz"}; + + ASSERT_EQ(splitString(s, ","), expected); +} + +TEST(splitString, tokenizeSepAtEnd) +{ + auto s = "foo,bar,baz,"; + Strings expected = {"foo", "bar", "baz", ""}; + + ASSERT_EQ(splitString(s, ","), expected); +} + +TEST(splitString, tokenizeSepEmpty) +{ + auto s = "foo,,baz"; + Strings expected = {"foo", "", "baz"}; + + ASSERT_EQ(splitString(s, ","), expected); +} + +// concatStringsSep sep . splitString sep = id if sep is 1 char +RC_GTEST_PROP(splitString, recoveredByConcatStringsSep, (const std::string & s)) +{ + RC_ASSERT(concatStringsSep("/", splitString(s, "/")) == s); + RC_ASSERT(concatStringsSep("a", splitString(s, "a")) == s); +} + } // namespace nix From 0646b6cd610d901438fb66eadf09708d302e1c66 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Wed, 7 Aug 2024 22:29:56 -0500 Subject: [PATCH 044/718] Update comments / documentation. Co-authored-by: Robert Hensing --- src/libutil/file-system.cc | 1 + src/libutil/file-system.hh | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libutil/file-system.cc b/src/libutil/file-system.cc index 156dddf98..536ae29ab 100644 --- a/src/libutil/file-system.cc +++ b/src/libutil/file-system.cc @@ -688,6 +688,7 @@ void moveFile(const Path & oldName, const Path & newName) bool isExecutableFileAmbient(const fs::path & exe) { // Check file type, because directory being executable means // something completely different. + // `is_regular_file` follows symlinks before checking. return std::filesystem::is_regular_file(exe) && access(exe.string().c_str(), #ifdef WIN32 diff --git a/src/libutil/file-system.hh b/src/libutil/file-system.hh index 5350ceb7e..1ae5fa136 100644 --- a/src/libutil/file-system.hh +++ b/src/libutil/file-system.hh @@ -265,7 +265,7 @@ Path defaultTempDir(); /** * Interpret `exe` as a location in the ambient file system and return - * whether it exists AND is executable. + * whether it resolves to a file that is executable. */ bool isExecutableFileAmbient(const std::filesystem::path & exe); From 00f6db36fd72c9e82e923ce89d0ddb7d2e738528 Mon Sep 17 00:00:00 2001 From: Andrew Marshall Date: Thu, 8 Aug 2024 14:29:40 -0400 Subject: [PATCH 045/718] libstore: fix port binding in __darwinAllowLocalNetworking sandbox In d60c3f7f7c83134b5b4470ed84b6d5ed38e28753, this was changed to close a hole in the sandbox. Unfortunately, this was too restrictive such that it made local port binding fail, thus making derivations that needed `__darwinAllowLocalNetworking` gain nearly nothing, and thus largely fail (as the primary use for it is to enable port binding). This unfortunately does mean that a sandboxed build process can, in coordination with an actor outside the sandbox, escape the sandbox by binding a port and connecting to it externally to send data. I do not see a way around this with my experimentation and understanding of the (quite undocumented) macOS sandbox profile API. Notably it seems not possible to use the sandbox to do any of: - Restrict the remote IP of inbound network requests - Restrict the address being bound to As such, the `(local ip "*:*")` here appears to be functionally no different than `(local ip "localhost:*")` (however it *should* be different than removing the filter entirely, as that would make it also apply to non-IP networking). Doing `(allow network-inbound (require-all (local ip "localhost:*") (remote ip "localhost:*")))` causes listening to fail. Note that `network-inbound` implies `network-bind`. --- src/libstore/unix/build/sandbox-defaults.sb | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libstore/unix/build/sandbox-defaults.sb b/src/libstore/unix/build/sandbox-defaults.sb index 6da01b735..15cd6daf5 100644 --- a/src/libstore/unix/build/sandbox-defaults.sb +++ b/src/libstore/unix/build/sandbox-defaults.sb @@ -49,6 +49,7 @@ R""( (if (param "_ALLOW_LOCAL_NETWORKING") (begin (allow network* (remote ip "localhost:*")) + (allow network-inbound (local ip "*:*")) ; required to bind and listen ; Allow access to /etc/resolv.conf (which is a symlink to ; /private/var/run/resolv.conf). From abbaba91223b47c87d270666d9c1a90ca0f55b34 Mon Sep 17 00:00:00 2001 From: Jeremy Kolb Date: Thu, 8 Aug 2024 14:41:25 -0400 Subject: [PATCH 046/718] Use the window size for the entire length --- src/nix/flake.cc | 40 +++++++++++++++++++++++---------- tests/functional/flakes/show.sh | 4 ++-- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 8ef19e3ea..839085b04 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -1264,22 +1264,38 @@ struct CmdFlakeShow : FlakeCommand, MixJSON "package"; if (description && !description->empty()) { // Maximum length to print - size_t maxLength = getWindowSize().second; - if (maxLength == 0) - maxLength = 77; - // Trim the string and only display the first line of the description. - auto trimmed = nix::trim(*description); + size_t maxLength = getWindowSize().second > 0 ? getWindowSize().second : 80; + + // Trim the description and only use the first line + auto trimmed = trim(*description); auto newLinePos = trimmed.find('\n'); auto length = newLinePos != std::string::npos ? newLinePos : trimmed.length(); - // Resize/sanitize the string and if it's too long add ellipses - std::string desc = filterANSIEscapes(trimmed, false, length); - if (desc.length() > maxLength) { - desc.resize(maxLength); - desc = desc.append("..."); - } + // Sanitize the description and calculate the two parts of the line + // In order to get the length of the printable characters we need to + // filter out escape sequences. + auto beginningOfLine = fmt("%s: %s '%s'", headerPrefix, type, name); + auto beginningOfLineLength = filterANSIEscapes(beginningOfLine, true).length(); + auto restOfLine = fmt(" - '%s'", filterANSIEscapes(trimmed, false, length)); - logger->cout("%s: %s '%s' - '%s'", headerPrefix, type, name, desc); + // If we are already over the maximum length then do not trim + // and don't print the description (preserves existing behavior) + if (beginningOfLineLength >= maxLength) { + logger->cout("%s", beginningOfLine); + } + else { + auto line = beginningOfLine + restOfLine; + // FIXME: Specifying `true` here gives the correct length + // BUT removes colors/bold so something is not quite right here. + line = filterANSIEscapes(line, true, maxLength); + + // NOTE: This test might be incorrect since I get things like: + // 168 or 161 > maxLength. + if (line.length() > maxLength) { + line = line.replace(line.length() - 3, 3, "..."); + } + logger->cout("%s", line); + } } else { logger->cout("%s: %s '%s'", headerPrefix, type, name); diff --git a/tests/functional/flakes/show.sh b/tests/functional/flakes/show.sh index 3d91613ee..0edc450c3 100755 --- a/tests/functional/flakes/show.sh +++ b/tests/functional/flakes/show.sh @@ -110,5 +110,5 @@ nix flake show > ./show-output.txt test "$(awk -F '[:] ' '/aNoDescription/{print $NF}' ./show-output.txt)" = "package 'simple'" test "$(awk -F '[:] ' '/bOneLineDescription/{print $NF}' ./show-output.txt)" = "package 'simple' - 'one line'" test "$(awk -F '[:] ' '/cMultiLineDescription/{print $NF}' ./show-output.txt)" = "package 'simple' - 'line one'" -test "$(awk -F '[:] ' '/dLongDescription/{print $NF}' ./show-output.txt)" = "package 'simple' - '01234567890123456789012345678901234567890123456789012345678901234567890123456...'" -test "$(awk -F '[:] ' '/eEmptyDescription/{print $NF}' ./show-output.txt)" = "package 'simple'" +test "$(awk -F '[:] ' '/dLongDescription/{print $NF}' ./show-output.txt)" = "package 'simple' - '012345678901234567890123456..." +test "$(awk -F '[:] ' '/eEmptyDescription/{print $NF}' ./show-output.txt)" = "package 'simple'" \ No newline at end of file From 3cc2e2a0ac7df557f5cd958a0736ce4eedf5ae07 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Sun, 11 Aug 2024 03:31:44 +0200 Subject: [PATCH 047/718] Edit docs --- doc/manual/rl-next/ban-integer-overflow.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/manual/rl-next/ban-integer-overflow.md b/doc/manual/rl-next/ban-integer-overflow.md index 49ecfe4c6..0e553af76 100644 --- a/doc/manual/rl-next/ban-integer-overflow.md +++ b/doc/manual/rl-next/ban-integer-overflow.md @@ -4,10 +4,10 @@ issues: [10968] prs: [11188] --- -Previously, integer overflow in the Nix language invoked C++ level signed overflow, which was undefined behaviour, but *probably* manifested as wrapping around on overflow. +Previously, integer overflow in the Nix language invoked C++ level signed overflow, which was undefined behaviour, but *usually* manifested as wrapping around on overflow. Since prior to the public release of Lix, Lix had C++ signed overflow defined to crash the process and nobody noticed this having accidentally removed overflow from the Nix language for three months until it was caught by fiddling around. -Given the significant body of actual Nix code that has been evaluated by Lix in that time, it does not appear that nixpkgs or much of importance depends on integer overflow, so it is safe to turn into an error. +Given the significant body of actual Nix code that has been evaluated by Lix in that time, it does not appear that nixpkgs or much of importance depends on integer overflow, so it appears safe to turn into an error. Some other overflows were fixed: - `builtins.fromJSON` of values greater than the maximum representable value in a signed 64-bit integer will generate an error. @@ -16,6 +16,6 @@ Some other overflows were fixed: Integer overflow now looks like the following: ``` -» nix eval --expr '9223372036854775807 + 1' +$ nix eval --expr '9223372036854775807 + 1' error: integer overflow in adding 9223372036854775807 + 1 ``` From f7c86d1a2f4460f58e8a91d004e438e69a3e133c Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Sun, 11 Aug 2024 12:47:35 +0200 Subject: [PATCH 048/718] CONTRIBUTING.md: Add attribution and context rules We've recently had an incident where these rules were not followed, so let's add guidelines to increase the chances of contributors getting this right. Relevant discussion: https://discourse.nixos.org/t/code-attribution-policy/50445/2 --- CONTRIBUTING.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 12423366a..1c9ee9b35 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -52,6 +52,20 @@ Check out the [security policy](https://github.com/NixOS/nix/security/policy). Link related issues to inform interested parties and future contributors about your change. If your pull request closes one or multiple issues, mention that in the description using `Closes: #`, as it will then happen automatically when your change is merged. + * Credit original authors when you're reusing or building on their work. + * Link to relevant changes in other projects, so that others can understand the full context of the change in the future when you or someone else will change or troubleshoot the code. + This is especially important when your change is based on work done in other repositories. + + Example: + ``` + This is based on the work of @user in . + This solution took inspiration from . + + Co-authored-by: User Name + ``` + + Use the `git cherry-pick -x` flag, and amend the commits to link to forks when applicable. + * Make sure to have [a clean history of commits on your branch by using rebase](https://www.digitalocean.com/community/tutorials/how-to-rebase-and-update-a-pull-request). * [Mark the pull request as draft](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/changing-the-stage-of-a-pull-request) if you're not done with the changes. From 70dde8c70c937498f85f1f54372608bac6b1a5c9 Mon Sep 17 00:00:00 2001 From: siddhantCodes Date: Sun, 11 Aug 2024 16:30:59 +0530 Subject: [PATCH 049/718] Use `std::filesystem::path` in build.cc --- src/nix/build.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/nix/build.cc b/src/nix/build.cc index 479100186..da9132d02 100644 --- a/src/nix/build.cc +++ b/src/nix/build.cc @@ -43,22 +43,22 @@ static nlohmann::json builtPathsWithResultToJSON(const std::vector& buildables, LocalFSStore& store2) +static void createOutLinks(const std::filesystem::path& outLink, const std::vector& buildables, LocalFSStore& store2) { for (const auto & [_i, buildable] : enumerate(buildables)) { auto i = _i; std::visit(overloaded { [&](const BuiltPath::Opaque & bo) { - std::string symlink = outLink; + auto symlink = outLink; if (i) symlink += fmt("-%d", i); - store2.addPermRoot(bo.path, absPath(symlink)); + store2.addPermRoot(bo.path, absPath(symlink.string())); }, [&](const BuiltPath::Built & bfd) { for (auto & output : bfd.outputs) { - std::string symlink = outLink; + auto symlink = outLink; if (i) symlink += fmt("-%d", i); if (output.first != "out") symlink += fmt("-%s", output.first); - store2.addPermRoot(output.second, absPath(symlink)); + store2.addPermRoot(output.second, absPath(symlink.string())); } }, }, buildable.path.raw()); From b0b19389821e0ab7aef35684bb91c65717136cce Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Sun, 11 Aug 2024 13:15:58 +0200 Subject: [PATCH 050/718] Urge contributors to read about contributing --- .github/PULL_REQUEST_TEMPLATE.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index d12a4d36c..69da87db7 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,3 +1,22 @@ + + # Motivation From bd4e5a375b62ccc2f3eda22f8fa7f9d57910620f Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Sun, 11 Aug 2024 13:16:36 +0200 Subject: [PATCH 051/718] Refer contributors to the matrix room We were basically sending contributors into the woods with that page. --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 12423366a..9fc119708 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -83,4 +83,4 @@ For larger changes see the [Nix reference manual](https://nix.dev/manual/nix/dev ## Getting help Whenever you're stuck or do not know how to proceed, you can always ask for help. -The appropriate channels to do so can be found on the [NixOS Community](https://nixos.org/community/) page. +We invite you to use our [Matrix room](https://matrix.to/#/#nix-dev:nixos.org) to ask questions. From 2c12a6962eb916fac8ebe0ebf335bb65b1da48b1 Mon Sep 17 00:00:00 2001 From: siddhantCodes Date: Sun, 11 Aug 2024 19:18:04 +0530 Subject: [PATCH 052/718] Remove unused variable --- src/nix/bundle.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/nix/bundle.cc b/src/nix/bundle.cc index 7d9aa7711..e152c26f2 100644 --- a/src/nix/bundle.cc +++ b/src/nix/bundle.cc @@ -117,8 +117,6 @@ struct CmdBundle : InstallableValueCommand }, }); - auto outPathS = store->printStorePath(outPath); - if (!outLink) { auto * attr = vRes->attrs()->get(evalState->sName); if (!attr) From 0abc664a789b2403420041d34695ce4f8e78d1ad Mon Sep 17 00:00:00 2001 From: siddhantCodes Date: Sun, 11 Aug 2024 19:19:46 +0530 Subject: [PATCH 053/718] Use `std::filesystem` in `eval` and `flake` ... ... executables --- src/nix/eval.cc | 8 ++++---- src/nix/flake.cc | 25 +++++++++++++------------ 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/nix/eval.cc b/src/nix/eval.cc index 494735516..f8a9da736 100644 --- a/src/nix/eval.cc +++ b/src/nix/eval.cc @@ -78,14 +78,14 @@ struct CmdEval : MixJSON, InstallableValueCommand, MixReadOnlyOption if (pathExists(*writeTo)) throw Error("path '%s' already exists", *writeTo); - std::function recurse; + std::function recurse; - recurse = [&](Value & v, const PosIdx pos, const Path & path) + recurse = [&](Value & v, const PosIdx pos, const std::filesystem::path & path) { state->forceValue(v, pos); if (v.type() == nString) // FIXME: disallow strings with contexts? - writeFile(path, v.string_view()); + writeFile(path.string(), v.string_view()); else if (v.type() == nAttrs) { if (mkdir(path.c_str() #ifndef _WIN32 // TODO abstract mkdir perms for Windows @@ -98,7 +98,7 @@ struct CmdEval : MixJSON, InstallableValueCommand, MixReadOnlyOption try { if (name == "." || name == "..") throw Error("invalid file name '%s'", name); - recurse(*attr.value, attr.pos, concatStrings(path, "/", name)); + recurse(*attr.value, attr.pos, path / name); } catch (Error & e) { e.addTrace( state->positions[attr.pos], diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 3f9f8f99b..7cfbf48a1 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -18,6 +18,7 @@ #include "markdown.hh" #include "users.hh" +#include #include #include @@ -870,27 +871,27 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand "If you've set '%s' to a string, try using a path instead.", templateDir, templateDirAttr->getAttrPathStr()).debugThrow(); - std::vector changedFiles; - std::vector conflictedFiles; + std::vector changedFiles; + std::vector conflictedFiles; - std::function copyDir; - copyDir = [&](const Path & from, const Path & to) + std::function copyDir; + copyDir = [&](const std::filesystem::path & from, const std::filesystem::path & to) { createDirs(to); for (auto & entry : std::filesystem::directory_iterator{from}) { checkInterrupt(); - auto from2 = entry.path().string(); - auto to2 = to + "/" + entry.path().filename().string(); - auto st = lstat(from2); - if (S_ISDIR(st.st_mode)) + auto from2 = entry.path(); + auto to2 = to / entry.path().filename(); + auto st = entry.symlink_status(); + if (std::filesystem::is_directory(st)) copyDir(from2, to2); - else if (S_ISREG(st.st_mode)) { + else if (std::filesystem::is_regular_file(st)) { auto contents = readFile(from2); if (pathExists(to2)) { auto contents2 = readFile(to2); if (contents != contents2) { - printError("refusing to overwrite existing file '%s'\n please merge it manually with '%s'", to2, from2); + printError("refusing to overwrite existing file '%s'\n please merge it manually with '%s'", to2.string(), from2.string()); conflictedFiles.push_back(to2); } else { notice("skipping identical file: %s", from2); @@ -899,11 +900,11 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand } else writeFile(to2, contents); } - else if (S_ISLNK(st.st_mode)) { + else if (std::filesystem::is_symlink(st)) { auto target = readLink(from2); if (pathExists(to2)) { if (readLink(to2) != target) { - printError("refusing to overwrite existing file '%s'\n please merge it manually with '%s'", to2, from2); + printError("refusing to overwrite existing file '%s'\n please merge it manually with '%s'", to2.string(), from2.string()); conflictedFiles.push_back(to2); } else { notice("skipping identical file: %s", from2); From 8e70f6f85021fb906b81114525cabbb2943d052a Mon Sep 17 00:00:00 2001 From: siddhantCodes Date: Sun, 11 Aug 2024 19:56:06 +0530 Subject: [PATCH 054/718] Use `std::filesystem::path` in `profile.cc` ... ...and `run.cc` --- src/nix/profile.cc | 12 ++++++------ src/nix/run.cc | 13 +++++++------ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/nix/profile.cc b/src/nix/profile.cc index 1096f4386..d751abdb1 100644 --- a/src/nix/profile.cc +++ b/src/nix/profile.cc @@ -122,9 +122,9 @@ struct ProfileManifest ProfileManifest() { } - ProfileManifest(EvalState & state, const Path & profile) + ProfileManifest(EvalState & state, const std::filesystem::path & profile) { - auto manifestPath = profile + "/manifest.json"; + auto manifestPath = profile / "manifest.json"; if (pathExists(manifestPath)) { auto json = nlohmann::json::parse(readFile(manifestPath)); @@ -176,12 +176,12 @@ struct ProfileManifest } } - else if (pathExists(profile + "/manifest.nix")) { + else if (pathExists(profile / "manifest.nix")) { // FIXME: needed because of pure mode; ugly. - state.allowPath(state.store->followLinksToStore(profile)); - state.allowPath(state.store->followLinksToStore(profile + "/manifest.nix")); + state.allowPath(state.store->followLinksToStore(profile.string())); + state.allowPath(state.store->followLinksToStore((profile / "manifest.nix").string())); - auto packageInfos = queryInstalled(state, state.store->followLinksToStore(profile)); + auto packageInfos = queryInstalled(state, state.store->followLinksToStore(profile.string())); for (auto & packageInfo : packageInfos) { ProfileElement element; diff --git a/src/nix/run.cc b/src/nix/run.cc index ec6a4d1e8..dfe7f374f 100644 --- a/src/nix/run.cc +++ b/src/nix/run.cc @@ -11,6 +11,7 @@ #include "source-accessor.hh" #include "progress-bar.hh" #include "eval.hh" +#include #if __linux__ # include @@ -169,7 +170,7 @@ void chrootHelper(int argc, char * * argv) if (!pathExists(storeDir)) { // FIXME: Use overlayfs? - Path tmpDir = createTempDir(); + std::filesystem::path tmpDir = createTempDir(); createDirs(tmpDir + storeDir); @@ -178,16 +179,16 @@ void chrootHelper(int argc, char * * argv) for (auto entry : std::filesystem::directory_iterator{"/"}) { checkInterrupt(); - auto src = entry.path().string(); - Path dst = tmpDir + "/" + entry.path().filename().string(); + auto src = entry.path(); + Path dst = tmpDir / entry.path().filename(); if (pathExists(dst)) continue; - auto st = lstat(src); - if (S_ISDIR(st.st_mode)) { + auto st = entry.symlink_status(); + if (std::filesystem::is_directory(st)) { if (mkdir(dst.c_str(), 0700) == -1) throw SysError("creating directory '%s'", dst); if (mount(src.c_str(), dst.c_str(), "", MS_BIND | MS_REC, 0) == -1) throw SysError("mounting '%s' on '%s'", src, dst); - } else if (S_ISLNK(st.st_mode)) + } else if (std::filesystem::is_symlink(st)) createSymlink(readLink(src), dst); } From d98e06a58130cbfeecbe03a51a829d81e46bea93 Mon Sep 17 00:00:00 2001 From: siddhantCodes Date: Sun, 11 Aug 2024 20:13:47 +0530 Subject: [PATCH 055/718] Use `std::filesystem::path` in more executables --- src/nix-channel/nix-channel.cc | 6 +++--- src/nix-collect-garbage/nix-collect-garbage.cc | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/nix-channel/nix-channel.cc b/src/nix-channel/nix-channel.cc index 9f7f557b5..e2bedcbcb 100644 --- a/src/nix-channel/nix-channel.cc +++ b/src/nix-channel/nix-channel.cc @@ -17,7 +17,7 @@ using namespace nix; typedef std::map Channels; static Channels channels; -static Path channelsList; +static std::filesystem::path channelsList; // Reads the list of channels. static void readChannels() @@ -41,7 +41,7 @@ static void writeChannels() { auto channelsFD = AutoCloseFD{open(channelsList.c_str(), O_WRONLY | O_CLOEXEC | O_CREAT | O_TRUNC, 0644)}; if (!channelsFD) - throw SysError("opening '%1%' for writing", channelsList); + throw SysError("opening '%1%' for writing", channelsList.string()); for (const auto & channel : channels) writeFull(channelsFD.get(), channel.second + " " + channel.first + "\n"); } @@ -165,7 +165,7 @@ static int main_nix_channel(int argc, char ** argv) { // Figure out the name of the `.nix-channels' file to use auto home = getHome(); - channelsList = settings.useXDGBaseDirectories ? createNixStateDir() + "/channels" : home + "/.nix-channels"; + channelsList = settings.useXDGBaseDirectories ? createNixStateDir() + OS_STR("/channels") : home + OS_STR("/.nix-channels"); nixDefExpr = getNixDefExpr(); // Figure out the name of the channels profile. diff --git a/src/nix-collect-garbage/nix-collect-garbage.cc b/src/nix-collect-garbage/nix-collect-garbage.cc index 91209c978..66acd60bc 100644 --- a/src/nix-collect-garbage/nix-collect-garbage.cc +++ b/src/nix-collect-garbage/nix-collect-garbage.cc @@ -21,7 +21,7 @@ bool dryRun = false; * Of course, this makes rollbacks to before this point in time * impossible. */ -void removeOldGenerations(std::string dir) +void removeOldGenerations(std::filesystem::path dir) { if (access(dir.c_str(), R_OK) != 0) return; @@ -81,7 +81,7 @@ static int main_nix_collect_garbage(int argc, char * * argv) }); if (removeOld) { - std::set dirsToClean = { + std::set dirsToClean = { profilesDir(), settings.nixStateDir + "/profiles", dirOf(getDefaultProfile())}; for (auto & dir : dirsToClean) removeOldGenerations(dir); From b64d6aa7b0fcc801d8ee496c41658d9883af37aa Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Sun, 11 Aug 2024 18:07:19 +0200 Subject: [PATCH 056/718] CONTRIBUTING.md: Clarify use of cherry-pick on forks --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1c9ee9b35..da56653b8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -64,7 +64,7 @@ Check out the [security policy](https://github.com/NixOS/nix/security/policy). Co-authored-by: User Name ``` - Use the `git cherry-pick -x` flag, and amend the commits to link to forks when applicable. + When cherry-picking from a different repository, use the `-x` flag, and then amend the commits to turn the hashes into URLs. * Make sure to have [a clean history of commits on your branch by using rebase](https://www.digitalocean.com/community/tutorials/how-to-rebase-and-update-a-pull-request). * [Mark the pull request as draft](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/changing-the-stage-of-a-pull-request) if you're not done with the changes. From 9f6ee93f488c8935b560588ad7ba321d9618f588 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 12 Aug 2024 15:47:02 +0200 Subject: [PATCH 057/718] fetchers::downloadTarball(): Return a cacheable accessor downloadTarball() is used by `-I foo=` etc. fetchToStore() needs the accessor to have a fingerprint to enable caching. Fixes #11271. --- src/libcmd/common-eval-args.cc | 4 +++- src/libexpr/eval.cc | 4 +++- src/libexpr/primops/fetchTree.cc | 6 +++++- src/libfetchers/tarball.cc | 20 ++++++++++++++++++-- src/libfetchers/tarball.hh | 9 ++++++--- 5 files changed, 35 insertions(+), 8 deletions(-) diff --git a/src/libcmd/common-eval-args.cc b/src/libcmd/common-eval-args.cc index fcef92487..ae9994a05 100644 --- a/src/libcmd/common-eval-args.cc +++ b/src/libcmd/common-eval-args.cc @@ -171,7 +171,9 @@ SourcePath lookupFileArg(EvalState & state, std::string_view s, const Path * bas { if (EvalSettings::isPseudoUrl(s)) { auto accessor = fetchers::downloadTarball( - EvalSettings::resolvePseudoUrl(s)).accessor; + state.store, + state.fetchSettings, + EvalSettings::resolvePseudoUrl(s)); auto storePath = fetchToStore(*state.store, SourcePath(accessor), FetchMode::Copy); return state.rootPath(CanonPath(state.store->toRealPath(storePath))); } diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index c9101678c..92320b554 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -3088,7 +3088,9 @@ std::optional EvalState::resolveLookupPathPath(const LookupPath::Pa if (EvalSettings::isPseudoUrl(value)) { try { auto accessor = fetchers::downloadTarball( - EvalSettings::resolvePseudoUrl(value)).accessor; + store, + fetchSettings, + EvalSettings::resolvePseudoUrl(value)); auto storePath = fetchToStore(*store, SourcePath(accessor), FetchMode::Copy); return finish(store->toRealPath(storePath)); } catch (Error & e) { diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc index 78328701d..5d074e623 100644 --- a/src/libexpr/primops/fetchTree.cc +++ b/src/libexpr/primops/fetchTree.cc @@ -507,7 +507,11 @@ static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v // https://github.com/NixOS/nix/issues/4313 auto storePath = unpack - ? fetchToStore(*state.store, fetchers::downloadTarball(*url).accessor, FetchMode::Copy, name) + ? fetchToStore( + *state.store, + fetchers::downloadTarball(state.store, state.fetchSettings, *url), + FetchMode::Copy, + name) : fetchers::downloadFile(state.store, *url, name).storePath; if (expectedHash) { diff --git a/src/libfetchers/tarball.cc b/src/libfetchers/tarball.cc index 457210542..dd4f3b780 100644 --- a/src/libfetchers/tarball.cc +++ b/src/libfetchers/tarball.cc @@ -102,7 +102,7 @@ DownloadFileResult downloadFile( }; } -DownloadTarballResult downloadTarball( +static DownloadTarballResult downloadTarball_( const std::string & url, const Headers & headers) { @@ -202,6 +202,22 @@ DownloadTarballResult downloadTarball( return attrsToResult(infoAttrs); } +ref downloadTarball( + ref store, + const Settings & settings, + const std::string & url) +{ + /* Go through Input::getAccessor() to ensure that the resulting + accessor has a fingerprint. */ + fetchers::Attrs attrs; + attrs.insert_or_assign("type", "tarball"); + attrs.insert_or_assign("url", url); + + auto input = Input::fromAttrs(settings, std::move(attrs)); + + return input.getAccessor(store).first; +} + // An input scheme corresponding to a curl-downloadable resource. struct CurlInputScheme : InputScheme { @@ -353,7 +369,7 @@ struct TarballInputScheme : CurlInputScheme { auto input(_input); - auto result = downloadTarball(getStrAttr(input.attrs, "url"), {}); + auto result = downloadTarball_(getStrAttr(input.attrs, "url"), {}); result.accessor->setPathDisplay("«" + input.to_string() + "»"); diff --git a/src/libfetchers/tarball.hh b/src/libfetchers/tarball.hh index d9bdd123d..2042041d5 100644 --- a/src/libfetchers/tarball.hh +++ b/src/libfetchers/tarball.hh @@ -14,6 +14,8 @@ struct SourceAccessor; namespace nix::fetchers { +struct Settings; + struct DownloadFileResult { StorePath storePath; @@ -40,8 +42,9 @@ struct DownloadTarballResult * Download and import a tarball into the Git cache. The result is the * Git tree hash of the root directory. */ -DownloadTarballResult downloadTarball( - const std::string & url, - const Headers & headers = {}); +ref downloadTarball( + ref store, + const Settings & settings, + const std::string & url); } From 58b03ef1cd73385699e3ea5c46d0dc0d36c3bbcd Mon Sep 17 00:00:00 2001 From: John Ericson Date: Wed, 24 Jul 2024 23:14:36 -0400 Subject: [PATCH 058/718] Move `NIX_BIN_DIR` and all logic using it to the Nix executable itself This is because with the split packages of the Meson build, we simply have no idea what directory the binaries will be installed in when we build the library. In the process of doing so, consolidate and make more sophisticated the logic to cope with a few corner cases (e.g. `NIX_BIN_DIR` exists, but no binaries are inside it). Co-authored-by: Robert Hensing --- doc/manual/rl-next/build-hook-default.md | 22 ++++++++++++++ src/libcmd/repl.cc | 38 +++++++++++------------- src/libcmd/repl.hh | 14 +++++++-- src/libstore/globals.cc | 29 ------------------ src/libstore/globals.hh | 7 +---- src/libstore/local.mk | 1 - src/libstore/meson.build | 2 -- src/libstore/unix/build/hook-instance.cc | 14 +++++++-- src/libutil/executable-path.cc | 18 ++++++++++- src/libutil/executable-path.hh | 15 +++++++++- src/nix-channel/nix-channel.cc | 11 +++---- src/nix/local.mk | 2 ++ src/nix/main.cc | 12 ++++++++ src/nix/meson.build | 19 +++++++++++- src/nix/repl.cc | 23 +++++++++++++- src/nix/self-exe.cc | 38 ++++++++++++++++++++++++ src/nix/self-exe.hh | 31 +++++++++++++++++++ src/nix/upgrade-nix.cc | 5 ++-- src/perl/lib/Nix/Config.pm.in | 1 - src/perl/lib/Nix/Store.pm | 2 +- src/perl/lib/Nix/Store.xs | 5 ---- 21 files changed, 227 insertions(+), 82 deletions(-) create mode 100644 doc/manual/rl-next/build-hook-default.md create mode 100644 src/nix/self-exe.cc create mode 100644 src/nix/self-exe.hh diff --git a/doc/manual/rl-next/build-hook-default.md b/doc/manual/rl-next/build-hook-default.md new file mode 100644 index 000000000..197290536 --- /dev/null +++ b/doc/manual/rl-next/build-hook-default.md @@ -0,0 +1,22 @@ +--- +synopsis: |- + The `build-hook` setting's default is less useful when using `libnixstore` as a library +prs: +- 11178 +--- + +*This is an obscure issue that only affects usage of the `libnixstore` library outside of the Nix executable.* + +As part the ongoing [rewrite of the build system](https://github.com/NixOS/nix/issues/2503) to use [Meson](https://mesonbuild.com/), we are also switching to packaging individual Nix components separately (and building them in separate derivations). +This means that when building `libnixstore` we do not know where the Nix binaries will be installed --- `libnixstore` doesn't know about downstream consumers like the Nix binaries at all. + +*This is also unrelated to the _`post`_-`build-hook`*, which is often used for pushing to a cache.* + +This has a small adverse affect on remote building --- the `build-remote` executable that is specified from the [`build-hook`](@docroot@/command-ref/conf-file.md#conf-build-hook) setting will not be gotten from the (presumed) installation location, but instead looked up on the `PATH`. +This means that other applications linking `libnixstore` that wish to use remote building must arrange for the `nix` command to be on the PATH (or manually overriding `build-hook`) in order for that to work. + +Long term we don't envision this being a downside, because we plan to [get rid of `build-remote` and the build hook setting entirely](https://github.com/NixOS/nix/issues/1221). +There is simply no need to add a second layer of remote-procedure-calling when we want to connect to a remote builder. +The build hook protocol did in principle support custom ways of remote building, but that can also be accomplished with a custom service for the ssh or daemon/ssh-ng protocols, or with a custom [store type](@docroot@/store/types/) i.e. `Store` subclass. + +The Perl bindings no longer expose `getBinDir` either, since they libraries those bindings wrap no longer know the location of installed binaries as described above. diff --git a/src/libcmd/repl.cc b/src/libcmd/repl.cc index efc04b029..e7c43367c 100644 --- a/src/libcmd/repl.cc +++ b/src/libcmd/repl.cc @@ -7,7 +7,6 @@ #include "ansicolor.hh" #include "shared.hh" -#include "config-global.hh" #include "eval.hh" #include "eval-settings.hh" #include "attr-path.hh" @@ -77,10 +76,14 @@ struct NixRepl int displ; StringSet varNames; + RunNix * runNixPtr; + + void runNix(Path program, const Strings & args, const std::optional & input = {}); + std::unique_ptr interacter; NixRepl(const LookupPath & lookupPath, nix::ref store,ref state, - std::function getValues); + std::function getValues, RunNix * runNix); virtual ~NixRepl() = default; ReplExitStatus mainLoop() override; @@ -125,32 +128,16 @@ std::string removeWhitespace(std::string s) NixRepl::NixRepl(const LookupPath & lookupPath, nix::ref store, ref state, - std::function getValues) + std::function getValues, RunNix * runNix = nullptr) : AbstractNixRepl(state) , debugTraceIndex(0) , getValues(getValues) , staticEnv(new StaticEnv(nullptr, state->staticBaseEnv.get())) + , runNixPtr{runNix} , interacter(make_unique(getDataDir() + "/nix/repl-history")) { } -void runNix(Path program, const Strings & args, - const std::optional & input = {}) -{ - auto subprocessEnv = getEnv(); - subprocessEnv["NIX_CONFIG"] = globalConfig.toKeyValue(); - //isInteractive avoid grabling interactive commands - runProgram2(RunOptions { - .program = settings.nixBinDir+ "/" + program, - .args = args, - .environment = subprocessEnv, - .input = input, - .isInteractive = true, - }); - - return; -} - static std::ostream & showDebugTrace(std::ostream & out, const PosTable & positions, const DebugTrace & dt) { if (dt.isError) @@ -833,9 +820,18 @@ void NixRepl::evalString(std::string s, Value & v) } +void NixRepl::runNix(Path program, const Strings & args, const std::optional & input) +{ + if (runNixPtr) + (*runNixPtr)(program, args, input); + else + throw Error("Cannot run '%s', no method of calling the Nix CLI provided", program); +} + + std::unique_ptr AbstractNixRepl::create( const LookupPath & lookupPath, nix::ref store, ref state, - std::function getValues) + std::function getValues, RunNix * runNix) { return std::make_unique( lookupPath, diff --git a/src/libcmd/repl.hh b/src/libcmd/repl.hh index 3fd4b2c39..11d1820f5 100644 --- a/src/libcmd/repl.hh +++ b/src/libcmd/repl.hh @@ -19,9 +19,19 @@ struct AbstractNixRepl typedef std::vector> AnnotatedValues; + using RunNix = void(Path program, const Strings & args, const std::optional & input); + + /** + * @param runNix Function to run the nix CLI to support various + * `:` commands. Optional; if not provided, + * everything else will still work fine, but those commands won't. + */ static std::unique_ptr create( - const LookupPath & lookupPath, nix::ref store, ref state, - std::function getValues); + const LookupPath & lookupPath, + nix::ref store, + ref state, + std::function getValues, + RunNix * runNix = nullptr); static ReplExitStatus runSimple( ref evalState, diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc index 439a6f97c..52ab35b4c 100644 --- a/src/libstore/globals.cc +++ b/src/libstore/globals.cc @@ -64,7 +64,6 @@ Settings::Settings() , nixStateDir(canonPath(getEnvNonEmpty("NIX_STATE_DIR").value_or(NIX_STATE_DIR))) , nixConfDir(canonPath(getEnvNonEmpty("NIX_CONF_DIR").value_or(NIX_CONF_DIR))) , nixUserConfFiles(getUserConfigFiles()) - , nixBinDir(canonPath(getEnvNonEmpty("NIX_BIN_DIR").value_or(NIX_BIN_DIR))) , nixManDir(canonPath(NIX_MAN_DIR)) , nixDaemonSocketFile(canonPath(getEnvNonEmpty("NIX_DAEMON_SOCKET_PATH").value_or(nixStateDir + DEFAULT_SOCKET_PATH))) { @@ -95,34 +94,6 @@ Settings::Settings() 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 - - /* Set the build hook location - - For builds we perform a self-invocation, so Nix has to be self-aware. - That is, it has to know where it is installed. We don't think it's sentient. - - Normally, nix is installed according to `nixBinDir`, which is set at compile time, - but can be overridden. This makes for a great default that works even if this - code is linked as a library into some other program whose main is not aware - that it might need to be a build remote hook. - - However, it may not have been installed at all. For example, if it's a static build, - there's a good chance that it has been moved out of its installation directory. - That makes `nixBinDir` useless. Instead, we'll query the OS for the path to the - current executable, using `getSelfExe()`. - - As a last resort, we resort to `PATH`. Hopefully we find a `nix` there that's compatible. - If you're porting Nix to a new platform, that might be good enough for a while, but - you'll want to improve `getSelfExe()` to work on your platform. - */ - std::string nixExePath = nixBinDir + "/nix"; - if (!pathExists(nixExePath)) { - nixExePath = getSelfExe().value_or("nix"); - } - buildHook = { - nixExePath, - "__build-remote", - }; } void loadConfFile(AbstractConfig & config) diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh index 1ca9f02f5..65c7bf3bc 100644 --- a/src/libstore/globals.hh +++ b/src/libstore/globals.hh @@ -84,11 +84,6 @@ public: */ std::vector nixUserConfFiles; - /** - * The directory where the main programs are stored. - */ - Path nixBinDir; - /** * The directory where the man pages are stored. */ @@ -246,7 +241,7 @@ public: )", {"build-timeout"}}; - Setting buildHook{this, {}, "build-hook", + Setting buildHook{this, {"nix", "__build-remote"}, "build-hook", R"( The path to the helper program that executes remote builds. diff --git a/src/libstore/local.mk b/src/libstore/local.mk index 5dc8f3370..88be6a366 100644 --- a/src/libstore/local.mk +++ b/src/libstore/local.mk @@ -71,7 +71,6 @@ libstore_CXXFLAGS += \ -DNIX_STATE_DIR=\"$(NIX_ROOT)$(localstatedir)/nix\" \ -DNIX_LOG_DIR=\"$(NIX_ROOT)$(localstatedir)/log/nix\" \ -DNIX_CONF_DIR=\"$(NIX_ROOT)$(sysconfdir)/nix\" \ - -DNIX_BIN_DIR=\"$(NIX_ROOT)$(bindir)\" \ -DNIX_MAN_DIR=\"$(NIX_ROOT)$(mandir)\" \ -DLSOF=\"$(NIX_ROOT)$(lsof)\" diff --git a/src/libstore/meson.build b/src/libstore/meson.build index 50b15e15d..d2cc235fd 100644 --- a/src/libstore/meson.build +++ b/src/libstore/meson.build @@ -328,7 +328,6 @@ prefix = get_option('prefix') path_opts = [ # Meson built-ins. 'datadir', - 'bindir', 'mandir', 'libdir', 'includedir', @@ -373,7 +372,6 @@ cpp_str_defines = { 'NIX_STATE_DIR': state_dir / 'nix', 'NIX_LOG_DIR': log_dir, 'NIX_CONF_DIR': sysconfdir / 'nix', - 'NIX_BIN_DIR': bindir, 'NIX_MAN_DIR': mandir, } diff --git a/src/libstore/unix/build/hook-instance.cc b/src/libstore/unix/build/hook-instance.cc index d73d86ff2..4f8492fe9 100644 --- a/src/libstore/unix/build/hook-instance.cc +++ b/src/libstore/unix/build/hook-instance.cc @@ -4,6 +4,7 @@ #include "file-system.hh" #include "child.hh" #include "strings.hh" +#include "executable-path.hh" namespace nix { @@ -16,11 +17,18 @@ HookInstance::HookInstance() if (buildHookArgs.empty()) throw Error("'build-hook' setting is empty"); - auto buildHook = canonPath(buildHookArgs.front()); + std::filesystem::path buildHook = buildHookArgs.front(); buildHookArgs.pop_front(); + try { + buildHook = ExecutablePath::load().findPath(buildHook); + } catch (ExecutableLookupError & e) { + e.addTrace(nullptr, "while resolving the 'build-hook' setting'"); + throw; + } + Strings args; - args.push_back(std::string(baseNameOf(buildHook))); + args.push_back(buildHook.filename().string()); for (auto & arg : buildHookArgs) args.push_back(arg); @@ -59,7 +67,7 @@ HookInstance::HookInstance() if (dup2(builderOut.readSide.get(), 5) == -1) throw SysError("dupping builder's stdout/stderr"); - execv(buildHook.c_str(), stringsToCharPtrs(args).data()); + execv(buildHook.native().c_str(), stringsToCharPtrs(args).data()); throw SysError("executing '%s'", buildHook); }); diff --git a/src/libutil/executable-path.cc b/src/libutil/executable-path.cc index 1658e3667..8005a19be 100644 --- a/src/libutil/executable-path.cc +++ b/src/libutil/executable-path.cc @@ -60,7 +60,7 @@ OsString ExecutablePath::render() const } std::optional -ExecutablePath::find(const OsString & exe, std::function isExecutable) const +ExecutablePath::findName(const OsString & exe, std::function isExecutable) const { // "If the pathname being sought contains a , the search // through the path prefixes shall not be performed." @@ -76,4 +76,20 @@ ExecutablePath::find(const OsString & exe, std::function return std::nullopt; } +fs::path ExecutablePath::findPath(const fs::path & exe, std::function isExecutable) const +{ + // "If the pathname being sought contains a , the search + // through the path prefixes shall not be performed." + // https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03 + if (exe.filename() == exe) { + auto resOpt = findName(exe, isExecutable); + if (resOpt) + return *resOpt; + else + throw ExecutableLookupError("Could not find executable '%s'", exe.native()); + } else { + return exe; + } +} + } // namespace nix diff --git a/src/libutil/executable-path.hh b/src/libutil/executable-path.hh index bcb8d28e8..f46d5e212 100644 --- a/src/libutil/executable-path.hh +++ b/src/libutil/executable-path.hh @@ -5,6 +5,8 @@ namespace nix { +MakeError(ExecutableLookupError, Error); + struct ExecutablePath { std::vector directories; @@ -54,10 +56,21 @@ struct ExecutablePath * * @return path to a resolved executable */ - std::optional find( + std::optional findName( const OsString & exe, std::function isExecutableFile = isExecutableFileAmbient) const; + /** + * Like the `findName` but also allows a file path as input. + * + * This implements the full POSIX spec: if the path is just a name, + * it searches like the above. Otherwise, it returns the path as is. + * If (in the name case) the search fails, an exception is thrown. + */ + std::filesystem::path findPath( + const std::filesystem::path & exe, + std::function isExecutable = isExecutableFileAmbient) const; + bool operator==(const ExecutablePath &) const = default; }; diff --git a/src/nix-channel/nix-channel.cc b/src/nix-channel/nix-channel.cc index 9f7f557b5..878f3c828 100644 --- a/src/nix-channel/nix-channel.cc +++ b/src/nix-channel/nix-channel.cc @@ -7,6 +7,7 @@ #include "eval-settings.hh" // for defexpr #include "users.hh" #include "tarball.hh" +#include "self-exe.hh" #include #include @@ -67,7 +68,7 @@ static void removeChannel(const std::string & name) channels.erase(name); writeChannels(); - runProgram(settings.nixBinDir + "/nix-env", true, { "--profile", profile, "--uninstall", name }); + runProgram(getNixBin("nix-env").string(), true, { "--profile", profile, "--uninstall", name }); } static Path nixDefExpr; @@ -118,7 +119,7 @@ static void update(const StringSet & channelNames) bool unpacked = false; if (std::regex_search(filename, std::regex("\\.tar\\.(gz|bz2|xz)$"))) { - runProgram(settings.nixBinDir + "/nix-build", false, { "--no-out-link", "--expr", "import " + unpackChannelPath + + runProgram(getNixBin("nix-build").string(), false, { "--no-out-link", "--expr", "import " + unpackChannelPath + "{ name = \"" + cname + "\"; channelName = \"" + name + "\"; src = builtins.storePath \"" + filename + "\"; }" }); unpacked = true; } @@ -143,7 +144,7 @@ static void update(const StringSet & channelNames) for (auto & expr : exprs) envArgs.push_back(std::move(expr)); envArgs.push_back("--quiet"); - runProgram(settings.nixBinDir + "/nix-env", false, envArgs); + runProgram(getNixBin("nix-env").string(), false, envArgs); // Make the channels appear in nix-env. struct stat st; @@ -244,7 +245,7 @@ static int main_nix_channel(int argc, char ** argv) case cListGenerations: if (!args.empty()) throw UsageError("'--list-generations' expects no arguments"); - std::cout << runProgram(settings.nixBinDir + "/nix-env", false, {"--profile", profile, "--list-generations"}) << std::flush; + std::cout << runProgram(getNixBin("nix-env").string(), false, {"--profile", profile, "--list-generations"}) << std::flush; break; case cRollback: if (args.size() > 1) @@ -256,7 +257,7 @@ static int main_nix_channel(int argc, char ** argv) } else { envArgs.push_back("--rollback"); } - runProgram(settings.nixBinDir + "/nix-env", false, envArgs); + runProgram(getNixBin("nix-env").string(), false, envArgs); break; } diff --git a/src/nix/local.mk b/src/nix/local.mk index 28b30b586..b57f6b3e2 100644 --- a/src/nix/local.mk +++ b/src/nix/local.mk @@ -26,6 +26,8 @@ endif nix_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libstore) $(INCLUDE_libfetchers) $(INCLUDE_libexpr) $(INCLUDE_libflake) $(INCLUDE_libmain) -I src/libcmd -I doc/manual $(INCLUDE_nix) +nix_CXXFLAGS += -DNIX_BIN_DIR=\"$(NIX_ROOT)$(bindir)\" + nix_LIBS = libexpr libmain libfetchers libflake libstore libutil libcmd nix_LDFLAGS = $(THREAD_LDFLAGS) $(SODIUM_LIBS) $(EDITLINE_LIBS) $(BOOST_LDFLAGS) $(LOWDOWN_LIBS) diff --git a/src/nix/main.cc b/src/nix/main.cc index 9d7d617cc..34de79ac8 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -19,6 +19,7 @@ #include "network-proxy.hh" #include "eval-cache.hh" #include "flake/flake.hh" +#include "self-exe.hh" #include #include @@ -366,6 +367,17 @@ void mainWrapped(int argc, char * * argv) initGC(); flake::initLib(flakeSettings); + /* Set the build hook location + + For builds we perform a self-invocation, so Nix has to be + self-aware. That is, it has to know where it is installed. We + don't think it's sentient. + */ + settings.buildHook.setDefault(Strings { + getNixBin({}).string(), + "__build-remote", + }); + #if __linux__ if (isRootUser()) { try { diff --git a/src/nix/meson.build b/src/nix/meson.build index 7405548de..05bee6a87 100644 --- a/src/nix/meson.build +++ b/src/nix/meson.build @@ -33,6 +33,21 @@ subdir('build-utils-meson/threads') subdir('build-utils-meson/export-all-symbols') +configdata = configuration_data() + +fs = import('fs') + +bindir = get_option('bindir') +if not fs.is_absolute(bindir) + bindir = get_option('prefix') / bindir +endif +configdata.set_quoted('NIX_BIN_DIR', bindir) + +config_h = configure_file( + configuration : configdata, + output : 'config-nix-cli.hh', +) + add_project_arguments( # TODO(Qyriad): Yes this is how the autoconf+Make system did it. # It would be nice for our headers to be idempotent instead. @@ -42,15 +57,17 @@ add_project_arguments( #'-include', 'config-fetchers.hh', '-include', 'config-main.hh', '-include', 'config-cmd.hh', + '-include', 'config-nix-cli.hh', language : 'cpp', ) subdir('build-utils-meson/diagnostics') subdir('build-utils-meson/generate-header') -nix_sources = files( +nix_sources = [config_h] + files( 'add-to-store.cc', 'app.cc', + 'self-exe.cc', 'build.cc', 'bundle.cc', 'cat.cc', diff --git a/src/nix/repl.cc b/src/nix/repl.cc index a2f3e033e..5a570749f 100644 --- a/src/nix/repl.cc +++ b/src/nix/repl.cc @@ -1,12 +1,32 @@ #include "eval.hh" #include "eval-settings.hh" +#include "config-global.hh" #include "globals.hh" #include "command.hh" #include "installable-value.hh" #include "repl.hh" +#include "processes.hh" +#include "self-exe.hh" namespace nix { +void runNix(Path program, const Strings & args, + const std::optional & input = {}) +{ + auto subprocessEnv = getEnv(); + subprocessEnv["NIX_CONFIG"] = globalConfig.toKeyValue(); + //isInteractive avoid grabling interactive commands + runProgram2(RunOptions { + .program = getNixBin(program).string(), + .args = args, + .environment = subprocessEnv, + .input = input, + .isInteractive = true, + }); + + return; +} + struct CmdRepl : RawInstallablesCommand { CmdRepl() { @@ -81,7 +101,8 @@ struct CmdRepl : RawInstallablesCommand lookupPath, openStore(), state, - getValues + getValues, + runNix ); repl->autoArgs = getAutoArgs(*repl->state); repl->initEnv(); diff --git a/src/nix/self-exe.cc b/src/nix/self-exe.cc new file mode 100644 index 000000000..a260bafd5 --- /dev/null +++ b/src/nix/self-exe.cc @@ -0,0 +1,38 @@ +#include "current-process.hh" +#include "file-system.hh" +#include "globals.hh" +#include "self-exe.hh" + +namespace nix { + +namespace fs = std::filesystem; + +fs::path getNixBin(std::optional binaryNameOpt) +{ + auto getBinaryName = [&] { return binaryNameOpt ? *binaryNameOpt : "nix"; }; + + // If the environment variable is set, use it unconditionally + if (auto envOpt = getEnvNonEmpty("NIX_BIN_DIR")) + return fs::path{*envOpt} / std::string{getBinaryName()}; + + // Use some-times avaiable OS tricks to get to the path of this Nix, and try that + if (auto selfOpt = getSelfExe()) { + fs::path path{*selfOpt}; + if (binaryNameOpt) + path = path.parent_path() / std::string{*binaryNameOpt}; + if (fs::exists(path)) + return path; + } + + // If `nix` exists at the hardcoded fallback path, use it. + { + auto path = fs::path{NIX_BIN_DIR} / std::string{getBinaryName()}; + if (fs::exists(path)) + return path; + } + + // return just the name, hoping the exe is on the `PATH` + return getBinaryName(); +} + +} diff --git a/src/nix/self-exe.hh b/src/nix/self-exe.hh new file mode 100644 index 000000000..0772afa67 --- /dev/null +++ b/src/nix/self-exe.hh @@ -0,0 +1,31 @@ +#pragma once +///@file + +#include + +namespace nix { + +/** + * Get a path to the given Nix binary. + * + * Normally, nix is installed according to `NIX_BIN_DIR`, which is set + * at compile time, but can be overridden. + * + * However, it may not have been installed at all. For example, if it's + * a static build, there's a good chance that it has been moved out of + * its installation directory. That makes `NIX_BIN_DIR` useless. + * Instead, we'll query the OS for the path to the current executable, + * using `getSelfExe()`. + * + * As a last resort, we resort to `PATH`. Hopefully we find a `nix` + * there that's compatible. If you're porting Nix to a new platform, + * that might be good enough for a while, but you'll want to improve + * `getSelfExe()` to work on your platform. + * + * @param binary_name the exact binary name we're looking up. Might be + * `nix-*` instead of `nix` for the legacy CLI commands. Optional to use + * current binary name. + */ +std::filesystem::path getNixBin(std::optional binary_name = {}); + +} diff --git a/src/nix/upgrade-nix.cc b/src/nix/upgrade-nix.cc index 9ca3f6087..f54cc59d0 100644 --- a/src/nix/upgrade-nix.cc +++ b/src/nix/upgrade-nix.cc @@ -9,6 +9,7 @@ #include "names.hh" #include "progress-bar.hh" #include "executable-path.hh" +#include "self-exe.hh" using namespace nix; @@ -93,7 +94,7 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand { Activity act(*logger, lvlInfo, actUnknown, fmt("installing '%s' into profile '%s'...", store->printStorePath(storePath), profileDir)); - runProgram(settings.nixBinDir + "/nix-env", false, + runProgram(getNixBin("nix-env").string(), false, {"--profile", profileDir, "-i", store->printStorePath(storePath), "--no-sandbox"}); } @@ -103,7 +104,7 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand /* Return the profile in which Nix is installed. */ Path getProfileDir(ref store) { - auto whereOpt = ExecutablePath::load().find(OS_STR("nix-env")); + auto whereOpt = ExecutablePath::load().findName(OS_STR("nix-env")); if (!whereOpt) throw Error("couldn't figure out how Nix is installed, so I can't upgrade it"); auto & where = *whereOpt; diff --git a/src/perl/lib/Nix/Config.pm.in b/src/perl/lib/Nix/Config.pm.in index 508a15e15..ad51cff3b 100644 --- a/src/perl/lib/Nix/Config.pm.in +++ b/src/perl/lib/Nix/Config.pm.in @@ -5,7 +5,6 @@ use Nix::Store; $version = "@PACKAGE_VERSION@"; -$binDir = Nix::Store::getBinDir; $storeDir = Nix::Store::getStoreDir; %config = (); diff --git a/src/perl/lib/Nix/Store.pm b/src/perl/lib/Nix/Store.pm index 16f2e17c8..f2ae7e88f 100644 --- a/src/perl/lib/Nix/Store.pm +++ b/src/perl/lib/Nix/Store.pm @@ -24,7 +24,7 @@ our @EXPORT = qw( hashPath hashFile hashString convertHash signString checkSignature - getBinDir getStoreDir + getStoreDir setVerbosity ); diff --git a/src/perl/lib/Nix/Store.xs b/src/perl/lib/Nix/Store.xs index f951437c8..172c3500d 100644 --- a/src/perl/lib/Nix/Store.xs +++ b/src/perl/lib/Nix/Store.xs @@ -424,11 +424,6 @@ StoreWrapper::addTempRoot(char * storePath) } -SV * getBinDir() - PPCODE: - XPUSHs(sv_2mortal(newSVpv(settings.nixBinDir.c_str(), 0))); - - SV * getStoreDir() PPCODE: XPUSHs(sv_2mortal(newSVpv(settings.nixStore.c_str(), 0))); From d49e14ba4ad4880a679f7265387ec83d01945b4d Mon Sep 17 00:00:00 2001 From: Jeremy Kolb Date: Mon, 12 Aug 2024 14:49:52 -0400 Subject: [PATCH 059/718] Take ANSI and tree characters into account --- src/nix/flake.cc | 66 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 51 insertions(+), 15 deletions(-) diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 839085b04..fdbadd390 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -1263,6 +1263,46 @@ struct CmdFlakeShow : FlakeCommand, MixJSON attrPath.size() >= 1 && attrPathS[0] == "hydraJobs" ? "derivation" : "package"; if (description && !description->empty()) { + + // Takes a string and returns the # of characters displayed + auto columnLengthOfString = [](std::string_view s) -> unsigned int { + unsigned int columnCount = 0; + for (auto i = s.begin(); i < s.end();) { + // Test first character to determine if it is one of + // treeConn, treeLast, treeLine + if (*i == -30) { + i += 3; + ++columnCount; + } + // Escape sequences + // https://en.wikipedia.org/wiki/ANSI_escape_code + else if (*i == '\e') { + // Eat '[' + if (*(++i) == '[') { + ++i; + // Eat parameter bytes + while(*i >= 0x30 && *i <= 0x3f) ++i; + + // Eat intermediate bytes + while(*i >= 0x20 && *i <= 0x2f) ++i; + + // Eat final byte + if(*i >= 0x40 && *i <= 0x73) ++i; + } + else { + // Eat Fe Escape sequence + if (*i >= 0x40 && *i <= 0x5f) ++i; + } + } + else { + ++i; + ++columnCount; + } + } + + return columnCount; + }; + // Maximum length to print size_t maxLength = getWindowSize().second > 0 ? getWindowSize().second : 80; @@ -1271,29 +1311,25 @@ struct CmdFlakeShow : FlakeCommand, MixJSON auto newLinePos = trimmed.find('\n'); auto length = newLinePos != std::string::npos ? newLinePos : trimmed.length(); - // Sanitize the description and calculate the two parts of the line - // In order to get the length of the printable characters we need to - // filter out escape sequences. auto beginningOfLine = fmt("%s: %s '%s'", headerPrefix, type, name); - auto beginningOfLineLength = filterANSIEscapes(beginningOfLine, true).length(); - auto restOfLine = fmt(" - '%s'", filterANSIEscapes(trimmed, false, length)); + auto line = fmt("%s: %s '%s' - '%s'", headerPrefix, type, name, trimmed.substr(0, length)); // If we are already over the maximum length then do not trim // and don't print the description (preserves existing behavior) - if (beginningOfLineLength >= maxLength) { + if (columnLengthOfString(beginningOfLine) >= maxLength) { logger->cout("%s", beginningOfLine); } + // If the entire line fits then print that + else if (columnLengthOfString(line) < maxLength) { + logger->cout("%s", line); + } + // Otherwise we need to truncate else { - auto line = beginningOfLine + restOfLine; - // FIXME: Specifying `true` here gives the correct length - // BUT removes colors/bold so something is not quite right here. - line = filterANSIEscapes(line, true, maxLength); + auto lineLength = columnLengthOfString(line); + auto chopOff = lineLength - maxLength; + line.resize(line.length() - chopOff); + line = line.replace(line.length() - 3, 3, "..."); - // NOTE: This test might be incorrect since I get things like: - // 168 or 161 > maxLength. - if (line.length() > maxLength) { - line = line.replace(line.length() - 3, 3, "..."); - } logger->cout("%s", line); } } From f22bf867eb41a98441ab44b3667d3abb146ee603 Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Mon, 12 Aug 2024 22:18:14 -0400 Subject: [PATCH 060/718] fix: use SymbolStr in constructor --- src/libexpr/value.hh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libexpr/value.hh b/src/libexpr/value.hh index 257da1d2d..39144fe15 100644 --- a/src/libexpr/value.hh +++ b/src/libexpr/value.hh @@ -325,9 +325,9 @@ public: void mkStringMove(const char * s, const NixStringContext & context); - inline void mkString(const Symbol & s) + inline void mkString(const SymbolStr & s) { - mkString(((const std::string &) s).c_str()); + mkString(s.c_str()); } void mkPath(const SourcePath & path); From 95fe9f5ba18bb5fe025a06cbba0e18740ad101dd Mon Sep 17 00:00:00 2001 From: John Ericson Date: Tue, 9 Jul 2024 14:46:26 -0400 Subject: [PATCH 061/718] Fix Meson installation of the Nix CLI Co-Authored-By: Qyriad --- src/nix/meson.build | 52 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/nix/meson.build b/src/nix/meson.build index 05bee6a87..798c98e33 100644 --- a/src/nix/meson.build +++ b/src/nix/meson.build @@ -192,3 +192,55 @@ this_exe = executable( link_args: linker_export_flags, install : true, ) + +meson.override_find_program('nix', this_exe) + +nix_symlinks = [ + 'nix-build', + 'nix-channel', + 'nix-collect-garbage', + 'nix-copy-closure', + 'nix-daemon', + 'nix-env', + 'nix-hash', + 'nix-instantiate', + 'nix-prefetch-url', + 'nix-shell', + 'nix-store', +] + +foreach linkname : nix_symlinks + install_symlink( + linkname, + # TODO(Qyriad): should these continue to be relative symlinks? + pointing_to : 'nix', + install_dir : get_option('bindir'), + # The 'runtime' tag is what executables default to, which we want to emulate here. + install_tag : 'runtime' + ) + t = custom_target( + command: ['ln', '-sf', fs.name(this_exe), '@OUTPUT@'], + output: linkname, + # TODO(Ericson2314): Don't do this once we have the `meson.override_find_program` working) + build_by_default: true + ) + # TODO(Ericson3214): Dosen't yet work + #meson.override_find_program(linkname, t) +endforeach + +install_symlink( + 'build-remote', + pointing_to : '..' / '..'/ get_option('bindir') / 'nix', + install_dir : get_option('libexecdir') / 'nix', + # The 'runtime' tag is what executables default to, which we want to emulate here. + install_tag : 'runtime' +) + +custom_target( + command: ['ln', '-sf', fs.name(this_exe), '@OUTPUT@'], + output: 'build-remote', + # TODO(Ericson2314): Don't do this once we have the `meson.override_find_program` working) + build_by_default: true +) +# TODO(Ericson3214): Dosen't yet work +#meson.override_find_program(linkname, t) From 4956e7c44c5018c2c73a125913e264558cd638d6 Mon Sep 17 00:00:00 2001 From: Valentin Gagarin Date: Tue, 13 Aug 2024 19:22:32 +0200 Subject: [PATCH 062/718] add cross-references to `nix-path` overriding (#11288) * add cross-references to `nix-path` overriding while this information is already present in the settings, it's more likely to be first accessed through the "lookup path" page, which currently requires following two links to get to the practically important bits. Co-authored-by: Robert Hensing --- doc/manual/src/language/constructs/lookup-path.md | 7 ++----- src/libexpr/primops.cc | 5 ++++- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/manual/src/language/constructs/lookup-path.md b/doc/manual/src/language/constructs/lookup-path.md index 11b9fe88c..a2e80280b 100644 --- a/doc/manual/src/language/constructs/lookup-path.md +++ b/doc/manual/src/language/constructs/lookup-path.md @@ -4,11 +4,8 @@ > > *lookup-path* = `<` *identifier* [ `/` *identifier* ]... `>` -A lookup path is an identifier with an optional path suffix that resolves to a [path value](@docroot@/language/types.md#type-path) if the identifier matches a search path entry. - -The value of a lookup path is determined by [`builtins.nixPath`](@docroot@/language/builtins.md#builtins-nixPath). - -See [`builtins.findFile`](@docroot@/language/builtins.md#builtins-findFile) for details on lookup path resolution. +A lookup path is an identifier with an optional path suffix that resolves to a [path value](@docroot@/language/types.md#type-path) if the identifier matches a search path entry in [`builtins.nixPath`](@docroot@/language/builtins.md#builtins-nixPath). +The algorithm for lookup path resolution is described in the documentation on [`builtins.findFile`](@docroot@/language/builtins.md#builtins-findFile). > **Example** > diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 2de6cbf4b..9de8ff599 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -4857,7 +4857,10 @@ void EvalState::createBaseEnv() addConstant("__nixPath", v, { .type = nList, .doc = R"( - The value of the [`nix-path` configuration setting](@docroot@/command-ref/conf-file.md#conf-nix-path): a list of search path entries used to resolve [lookup paths](@docroot@/language/constructs/lookup-path.md). + A list of search path entries used to resolve [lookup paths](@docroot@/language/constructs/lookup-path.md). + Its value is primarily determined by the [`nix-path` configuration setting](@docroot@/command-ref/conf-file.md#conf-nix-path), which are + - Overridden by the [`NIX_PATH`](@docroot@/command-ref/env-common.md#env-NIX_PATH) environment variable or the `--nix-path` option + - Extended by the [`-I` option](@docroot@/command-ref/opt-common.md#opt-I) or `--extra-nix-path` > **Example** > From 77d84a8d8b82864fcd5dd7de6295ab3fc5f8e120 Mon Sep 17 00:00:00 2001 From: Noam Yorav-Raphael Date: Wed, 14 Aug 2024 14:35:42 +0300 Subject: [PATCH 063/718] /homeless-shelter -> /proc/homeless/shelter This makes it so even root can't create $HOME, for example by running `mkdir -p $HOME/.cache/foo`. --- doc/manual/src/language/derivations.md | 2 +- src/libstore/unix/build/local-derivation-goal.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/manual/src/language/derivations.md b/doc/manual/src/language/derivations.md index 8e3f0f791..c78c7b8c8 100644 --- a/doc/manual/src/language/derivations.md +++ b/doc/manual/src/language/derivations.md @@ -264,7 +264,7 @@ The [`builder`](#attr-builder) is executed as follows: - `PATH` is set to `/path-not-set` to prevent shells from initialising it to their built-in default value. - - `HOME` is set to `/homeless-shelter` to prevent programs from + - `HOME` is set to `/proc/homeless-shelter` to prevent programs from using `/etc/passwd` or the like to find the user's home directory, which could cause impurity. Usually, when `HOME` is set, it is used as the location of the home directory, even if diff --git a/src/libstore/unix/build/local-derivation-goal.cc b/src/libstore/unix/build/local-derivation-goal.cc index d3482df17..f6bbba8b4 100644 --- a/src/libstore/unix/build/local-derivation-goal.cc +++ b/src/libstore/unix/build/local-derivation-goal.cc @@ -102,7 +102,7 @@ void handleDiffHook( } } -const Path LocalDerivationGoal::homeDir = "/homeless-shelter"; +const Path LocalDerivationGoal::homeDir = "/proc/homeless-shelter"; LocalDerivationGoal::~LocalDerivationGoal() From 612fc76020495cefee6a5f5259fd83a531b0ef31 Mon Sep 17 00:00:00 2001 From: bryango Date: Wed, 14 Aug 2024 20:27:12 +0800 Subject: [PATCH 064/718] doc/manual: fix misaligned icons in custom.css (#11296) --- doc/manual/custom.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/manual/custom.css b/doc/manual/custom.css index 9e8e3886f..7af150be3 100644 --- a/doc/manual/custom.css +++ b/doc/manual/custom.css @@ -12,8 +12,8 @@ h1.menu-title::before { } -h1.menu-title { - padding: 0.5em; +.menu-bar { + padding: 0.5em 0em; } .sidebar .sidebar-scrollbox { From cc9fe4dee713717c88b22c8701f9bdffc786baa1 Mon Sep 17 00:00:00 2001 From: Bryan Honof Date: Fri, 2 Aug 2024 00:10:08 +0200 Subject: [PATCH 065/718] Fix a few shellcheck tests Ref nixos/nix#10795 --- maintainers/flake-module.nix | 11 --- tests/functional/signing.sh | 94 +++++++++---------- tests/functional/simple.builder.sh | 7 +- tests/functional/simple.sh | 10 +- tests/functional/ssh-relay.sh | 8 +- tests/functional/store-info.sh | 4 +- tests/functional/structured-attrs.sh | 11 ++- .../functional/substitute-with-invalid-ca.sh | 8 +- tests/functional/suggestions.sh | 2 +- tests/functional/tarball.sh | 44 ++++----- tests/functional/test-infra.sh | 5 +- tests/functional/test-libstoreconsumer.sh | 2 +- tests/functional/timeout.sh | 2 +- 13 files changed, 102 insertions(+), 106 deletions(-) diff --git a/maintainers/flake-module.nix b/maintainers/flake-module.nix index c3eaf671c..0b83e5696 100644 --- a/maintainers/flake-module.nix +++ b/maintainers/flake-module.nix @@ -641,19 +641,8 @@ ''^tests/functional/selfref-gc\.sh$'' ''^tests/functional/shell\.sh$'' ''^tests/functional/shell\.shebang\.sh$'' - ''^tests/functional/signing\.sh$'' ''^tests/functional/simple\.builder\.sh$'' - ''^tests/functional/simple\.sh$'' - ''^tests/functional/ssh-relay\.sh$'' - ''^tests/functional/store-info\.sh$'' - ''^tests/functional/structured-attrs\.sh$'' - ''^tests/functional/substitute-with-invalid-ca\.sh$'' - ''^tests/functional/suggestions\.sh$'' ''^tests/functional/supplementary-groups\.sh$'' - ''^tests/functional/tarball\.sh$'' - ''^tests/functional/test-infra\.sh$'' - ''^tests/functional/test-libstoreconsumer\.sh$'' - ''^tests/functional/timeout\.sh$'' ''^tests/functional/toString-path\.sh$'' ''^tests/functional/user-envs-migration\.sh$'' ''^tests/functional/user-envs-test-case\.sh$'' diff --git a/tests/functional/signing.sh b/tests/functional/signing.sh index 890d1446f..8ec093a48 100755 --- a/tests/functional/signing.sh +++ b/tests/functional/signing.sh @@ -5,108 +5,108 @@ source common.sh clearStoreIfPossible clearCache -nix-store --generate-binary-cache-key cache1.example.org $TEST_ROOT/sk1 $TEST_ROOT/pk1 -pk1=$(cat $TEST_ROOT/pk1) -nix-store --generate-binary-cache-key cache2.example.org $TEST_ROOT/sk2 $TEST_ROOT/pk2 -pk2=$(cat $TEST_ROOT/pk2) +nix-store --generate-binary-cache-key cache1.example.org "$TEST_ROOT"/sk1 "$TEST_ROOT"/pk1 +pk1=$(cat "$TEST_ROOT"/pk1) +nix-store --generate-binary-cache-key cache2.example.org "$TEST_ROOT"/sk2 "$TEST_ROOT"/pk2 +pk2=$(cat "$TEST_ROOT"/pk2) # Build a path. outPath=$(nix-build dependencies.nix --no-out-link --secret-key-files "$TEST_ROOT/sk1 $TEST_ROOT/sk2") # Verify that the path got signed. -info=$(nix path-info --json $outPath) -echo $info | jq -e '.[] | .ultimate == true' +info=$(nix path-info --json "$outPath") +echo "$info" | jq -e '.[] | .ultimate == true' TODO_NixOS # looks like an actual bug? Following line fails on NixOS: -echo $info | jq -e '.[] | .signatures.[] | select(startswith("cache1.example.org"))' -echo $info | jq -e '.[] | .signatures.[] | select(startswith("cache2.example.org"))' +echo "$info" | jq -e '.[] | .signatures.[] | select(startswith("cache1.example.org"))' +echo "$info" | jq -e '.[] | .signatures.[] | select(startswith("cache2.example.org"))' # Test "nix store verify". -nix store verify -r $outPath +nix store verify -r "$outPath" -expect 2 nix store verify -r $outPath --sigs-needed 1 +expect 2 nix store verify -r "$outPath" --sigs-needed 1 -nix store verify -r $outPath --sigs-needed 1 --trusted-public-keys $pk1 +nix store verify -r "$outPath" --sigs-needed 1 --trusted-public-keys "$pk1" -expect 2 nix store verify -r $outPath --sigs-needed 2 --trusted-public-keys $pk1 +expect 2 nix store verify -r "$outPath" --sigs-needed 2 --trusted-public-keys "$pk1" -nix store verify -r $outPath --sigs-needed 2 --trusted-public-keys "$pk1 $pk2" +nix store verify -r "$outPath" --sigs-needed 2 --trusted-public-keys "$pk1 $pk2" nix store verify --all --sigs-needed 2 --trusted-public-keys "$pk1 $pk2" # Build something unsigned. outPath2=$(nix-build simple.nix --no-out-link) -nix store verify -r $outPath +nix store verify -r "$outPath" # Verify that the path did not get signed but does have the ultimate bit. -info=$(nix path-info --json $outPath2) -echo $info | jq -e '.[] | .ultimate == true' -echo $info | jq -e '.[] | .signatures == []' +info=$(nix path-info --json "$outPath2") +echo "$info" | jq -e '.[] | .ultimate == true' +echo "$info" | jq -e '.[] | .signatures == []' # Test "nix store verify". -nix store verify -r $outPath2 +nix store verify -r "$outPath2" -expect 2 nix store verify -r $outPath2 --sigs-needed 1 +expect 2 nix store verify -r "$outPath2" --sigs-needed 1 -expect 2 nix store verify -r $outPath2 --sigs-needed 1 --trusted-public-keys $pk1 +expect 2 nix store verify -r "$outPath2" --sigs-needed 1 --trusted-public-keys "$pk1" # Test "nix store sign". -nix store sign --key-file $TEST_ROOT/sk1 $outPath2 +nix store sign --key-file "$TEST_ROOT"/sk1 "$outPath2" -nix store verify -r $outPath2 --sigs-needed 1 --trusted-public-keys $pk1 +nix store verify -r "$outPath2" --sigs-needed 1 --trusted-public-keys "$pk1" # Build something content-addressed. outPathCA=$(IMPURE_VAR1=foo IMPURE_VAR2=bar nix-build ./fixed.nix -A good.0 --no-out-link) -nix path-info --json $outPathCA | jq -e '.[] | .ca | startswith("fixed:md5:")' +nix path-info --json "$outPathCA" | jq -e '.[] | .ca | startswith("fixed:md5:")' # Content-addressed paths don't need signatures, so they verify # regardless of --sigs-needed. -nix store verify $outPathCA -nix store verify $outPathCA --sigs-needed 1000 +nix store verify "$outPathCA" +nix store verify "$outPathCA" --sigs-needed 1000 # Check that signing a content-addressed path doesn't overflow validSigs -nix store sign --key-file $TEST_ROOT/sk1 $outPathCA -nix store verify -r $outPathCA --sigs-needed 1000 --trusted-public-keys $pk1 +nix store sign --key-file "$TEST_ROOT"/sk1 "$outPathCA" +nix store verify -r "$outPathCA" --sigs-needed 1000 --trusted-public-keys "$pk1" # Copy to a binary cache. -nix copy --to file://$cacheDir $outPath2 +nix copy --to file://"$cacheDir" "$outPath2" # Verify that signatures got copied. -info=$(nix path-info --store file://$cacheDir --json $outPath2) -echo $info | jq -e '.[] | .ultimate == false' -echo $info | jq -e '.[] | .signatures.[] | select(startswith("cache1.example.org"))' -echo $info | expect 4 jq -e '.[] | .signatures.[] | select(startswith("cache2.example.org"))' +info=$(nix path-info --store file://"$cacheDir" --json "$outPath2") +echo "$info" | jq -e '.[] | .ultimate == false' +echo "$info" | jq -e '.[] | .signatures.[] | select(startswith("cache1.example.org"))' +echo "$info" | expect 4 jq -e '.[] | .signatures.[] | select(startswith("cache2.example.org"))' # Verify that adding a signature to a path in a binary cache works. -nix store sign --store file://$cacheDir --key-file $TEST_ROOT/sk2 $outPath2 -info=$(nix path-info --store file://$cacheDir --json $outPath2) -echo $info | jq -e '.[] | .signatures.[] | select(startswith("cache1.example.org"))' -echo $info | jq -e '.[] | .signatures.[] | select(startswith("cache2.example.org"))' +nix store sign --store file://"$cacheDir" --key-file "$TEST_ROOT"/sk2 "$outPath2" +info=$(nix path-info --store file://"$cacheDir" --json "$outPath2") +echo "$info" | jq -e '.[] | .signatures.[] | select(startswith("cache1.example.org"))' +echo "$info" | jq -e '.[] | .signatures.[] | select(startswith("cache2.example.org"))' # Copying to a diverted store should fail due to a lack of signatures by trusted keys. -chmod -R u+w $TEST_ROOT/store0 || true -rm -rf $TEST_ROOT/store0 +chmod -R u+w "$TEST_ROOT"/store0 || true +rm -rf "$TEST_ROOT"/store0 # Fails or very flaky only on GHA + macOS: # expectStderr 1 nix copy --to $TEST_ROOT/store0 $outPath | grepQuiet -E 'cannot add path .* because it lacks a signature by a trusted key' # but this works: -(! nix copy --to $TEST_ROOT/store0 $outPath) +(! nix copy --to "$TEST_ROOT"/store0 "$outPath") # But succeed if we supply the public keys. -nix copy --to $TEST_ROOT/store0 $outPath --trusted-public-keys $pk1 +nix copy --to "$TEST_ROOT"/store0 "$outPath" --trusted-public-keys "$pk1" -expect 2 nix store verify --store $TEST_ROOT/store0 -r $outPath +expect 2 nix store verify --store "$TEST_ROOT"/store0 -r "$outPath" -nix store verify --store $TEST_ROOT/store0 -r $outPath --trusted-public-keys $pk1 -nix store verify --store $TEST_ROOT/store0 -r $outPath --sigs-needed 2 --trusted-public-keys "$pk1 $pk2" +nix store verify --store "$TEST_ROOT"/store0 -r "$outPath" --trusted-public-keys "$pk1" +nix store verify --store "$TEST_ROOT"/store0 -r "$outPath" --sigs-needed 2 --trusted-public-keys "$pk1 $pk2" # It should also succeed if we disable signature checking. -(! nix copy --to $TEST_ROOT/store0 $outPath2) -nix copy --to $TEST_ROOT/store0?require-sigs=false $outPath2 +(! nix copy --to "$TEST_ROOT"/store0 "$outPath2") +nix copy --to "$TEST_ROOT"/store0?require-sigs=false "$outPath2" # But signatures should still get copied. -nix store verify --store $TEST_ROOT/store0 -r $outPath2 --trusted-public-keys $pk1 +nix store verify --store "$TEST_ROOT"/store0 -r "$outPath2" --trusted-public-keys "$pk1" # Content-addressed stuff can be copied without signatures. -nix copy --to $TEST_ROOT/store0 $outPathCA +nix copy --to "$TEST_ROOT"/store0 "$outPathCA" diff --git a/tests/functional/simple.builder.sh b/tests/functional/simple.builder.sh index 569e8ca88..97abf0676 100644 --- a/tests/functional/simple.builder.sh +++ b/tests/functional/simple.builder.sh @@ -1,3 +1,5 @@ +#!/usr/bin/env bash + echo "PATH=$PATH" # Verify that the PATH is empty. @@ -5,7 +7,6 @@ if mkdir foo 2> /dev/null; then exit 1; fi # Set a PATH (!!! impure). export PATH=$goodPath +mkdir "$out" -mkdir $out - -echo "Hello World!" > $out/hello \ No newline at end of file +echo "Hello World!" > "$out"/hello diff --git a/tests/functional/simple.sh b/tests/functional/simple.sh index 86acca0c2..8afa369c2 100755 --- a/tests/functional/simple.sh +++ b/tests/functional/simple.sh @@ -12,7 +12,7 @@ outPath=$(nix-store -rvv "$drvPath") echo "output path is $outPath" -(! [ -w $outPath ]) +[[ ! -w $outPath ]] text=$(cat "$outPath/hello") if test "$text" != "Hello World!"; then exit 1; fi @@ -21,16 +21,16 @@ TODO_NixOS # Directed delete: $outPath is not reachable from a root, so it should # be deleteable. -nix-store --delete $outPath -(! [ -e $outPath/hello ]) +nix-store --delete "$outPath" +[[ ! -e $outPath/hello ]] -outPath="$(NIX_REMOTE=local?store=/foo\&real=$TEST_ROOT/real-store nix-instantiate --readonly-mode hash-check.nix)" +outPath="$(NIX_REMOTE='local?store=/foo&real='"$TEST_ROOT"'/real-store' nix-instantiate --readonly-mode hash-check.nix)" if test "$outPath" != "/foo/lfy1s6ca46rm5r6w4gg9hc0axiakjcnm-dependencies.drv"; then echo "hashDerivationModulo appears broken, got $outPath" exit 1 fi -outPath="$(NIX_REMOTE=local?store=/foo\&real=$TEST_ROOT/real-store nix-instantiate --readonly-mode big-derivation-attr.nix)" +outPath="$(NIX_REMOTE='local?store=/foo&real='"$TEST_ROOT"'/real-store' nix-instantiate --readonly-mode big-derivation-attr.nix)" if test "$outPath" != "/foo/xxiwa5zlaajv6xdjynf9yym9g319d6mn-big-derivation-attr.drv"; then echo "big-derivation-attr.nix hash appears broken, got $outPath. Memory corruption in large drv attr?" exit 1 diff --git a/tests/functional/ssh-relay.sh b/tests/functional/ssh-relay.sh index 059c66434..71b8ae9ab 100755 --- a/tests/functional/ssh-relay.sh +++ b/tests/functional/ssh-relay.sh @@ -2,10 +2,10 @@ source common.sh -echo foo > $TEST_ROOT/hello.sh +echo foo > "$TEST_ROOT"/hello.sh ssh_localhost=ssh://localhost -remote_store=?remote-store=$ssh_localhost +remote_store="?remote-store=$ssh_localhost" store=$ssh_localhost @@ -13,6 +13,6 @@ store+=$remote_store store+=$remote_store store+=$remote_store -out=$(nix store add-path --store "$store" $TEST_ROOT/hello.sh) +out=$(nix store add-path --store "$store" "$TEST_ROOT"/hello.sh) -[ foo = $(< $out) ] +[ foo = "$(< "$out")" ] diff --git a/tests/functional/store-info.sh b/tests/functional/store-info.sh index f37889fbb..beecc2dd9 100755 --- a/tests/functional/store-info.sh +++ b/tests/functional/store-info.sh @@ -8,12 +8,12 @@ STORE_INFO_JSON=$(nix store info --json) echo "$STORE_INFO" | grep "Store URL: ${NIX_REMOTE}" if [[ -v NIX_DAEMON_PACKAGE ]] && isDaemonNewer "2.7.0pre20220126"; then - DAEMON_VERSION=$($NIX_DAEMON_PACKAGE/bin/nix daemon --version | cut -d' ' -f3) + DAEMON_VERSION=$("$NIX_DAEMON_PACKAGE"/bin/nix daemon --version | cut -d' ' -f3) echo "$STORE_INFO" | grep "Version: $DAEMON_VERSION" [[ "$(echo "$STORE_INFO_JSON" | jq -r ".version")" == "$DAEMON_VERSION" ]] fi -expect 127 NIX_REMOTE=unix:$PWD/store nix store info || \ +expect 127 NIX_REMOTE=unix:"$PWD"/store nix store info || \ fail "nix store info on a non-existent store should fail" TODO_NixOS diff --git a/tests/functional/structured-attrs.sh b/tests/functional/structured-attrs.sh index ec1282668..64d136e99 100755 --- a/tests/functional/structured-attrs.sh +++ b/tests/functional/structured-attrs.sh @@ -8,17 +8,19 @@ requireDaemonNewerThan "2.4pre20210712" clearStoreIfPossible -rm -f $TEST_ROOT/result +rm -f "$TEST_ROOT"/result -nix-build structured-attrs.nix -A all -o $TEST_ROOT/result +nix-build structured-attrs.nix -A all -o "$TEST_ROOT"/result -[[ $(cat $TEST_ROOT/result/foo) = bar ]] -[[ $(cat $TEST_ROOT/result-dev/foo) = foo ]] +[[ $(cat "$TEST_ROOT"/result/foo) = bar ]] +[[ $(cat "$TEST_ROOT"/result-dev/foo) = foo ]] export NIX_BUILD_SHELL=$SHELL +# shellcheck disable=SC2016 env NIX_PATH=nixpkgs=shell.nix nix-shell structured-attrs-shell.nix \ --run 'test "3" = "$(jq ".my.list|length" < $NIX_ATTRS_JSON_FILE)"' +# shellcheck disable=SC2016 nix develop -f structured-attrs-shell.nix -c bash -c 'test "3" = "$(jq ".my.list|length" < $NIX_ATTRS_JSON_FILE)"' TODO_NixOS # following line fails. @@ -26,6 +28,7 @@ TODO_NixOS # following line fails. # `nix develop` is a slightly special way of dealing with environment vars, it parses # these from a shell-file exported from a derivation. This is to test especially `outputs` # (which is an associative array in thsi case) being fine. +# shellcheck disable=SC2016 nix develop -f structured-attrs-shell.nix -c bash -c 'test -n "$out"' nix print-dev-env -f structured-attrs-shell.nix | grepQuiet 'NIX_ATTRS_JSON_FILE=' diff --git a/tests/functional/substitute-with-invalid-ca.sh b/tests/functional/substitute-with-invalid-ca.sh index d8af67237..33432e95d 100755 --- a/tests/functional/substitute-with-invalid-ca.sh +++ b/tests/functional/substitute-with-invalid-ca.sh @@ -11,16 +11,16 @@ getRemoteNarInfo () { echo "$cacheDir/$(getHash "$1").narinfo" } -cat < $TEST_HOME/good.txt +cat < "$TEST_HOME"/good.txt I’m a good path EOF -cat < $TEST_HOME/bad.txt +cat < "$TEST_HOME"/bad.txt I’m a bad path EOF -good=$(nix-store --add $TEST_HOME/good.txt) -bad=$(nix-store --add $TEST_HOME/bad.txt) +good=$(nix-store --add "$TEST_HOME"/good.txt) +bad=$(nix-store --add "$TEST_HOME"/bad.txt) nix copy --to "$BINARY_CACHE" "$good" nix copy --to "$BINARY_CACHE" "$bad" nix-collect-garbage >/dev/null 2>&1 diff --git a/tests/functional/suggestions.sh b/tests/functional/suggestions.sh index 8db6f7b97..fbca93da8 100755 --- a/tests/functional/suggestions.sh +++ b/tests/functional/suggestions.sh @@ -37,7 +37,7 @@ NIX_BUILD_STDERR_WITH_NO_CLOSE_SUGGESTION=$(! nix build .\#bar 2>&1 1>/dev/null) [[ ! "$NIX_BUILD_STDERR_WITH_NO_CLOSE_SUGGESTION" =~ "Did you mean" ]] || \ fail "The nix build stderr shouldn’t suggest anything if there’s nothing relevant to suggest" -NIX_EVAL_STDERR_WITH_SUGGESTIONS=$(! nix build --impure --expr '(builtins.getFlake (builtins.toPath ./.)).packages.'$system'.fob' 2>&1 1>/dev/null) +NIX_EVAL_STDERR_WITH_SUGGESTIONS=$(! nix build --impure --expr '(builtins.getFlake (builtins.toPath ./.)).packages.'"$system"'.fob' 2>&1 1>/dev/null) [[ "$NIX_EVAL_STDERR_WITH_SUGGESTIONS" =~ "Did you mean one of fo1, fo2, foo or fooo?" ]] || \ fail "The evaluator should suggest the three closest possiblities" diff --git a/tests/functional/tarball.sh b/tests/functional/tarball.sh index 4d8945625..dee0a98f1 100755 --- a/tests/functional/tarball.sh +++ b/tests/functional/tarball.sh @@ -4,51 +4,51 @@ source common.sh clearStoreIfPossible -rm -rf $TEST_HOME +rm -rf "$TEST_HOME" tarroot=$TEST_ROOT/tarball -rm -rf $tarroot -mkdir -p $tarroot -cp dependencies.nix $tarroot/default.nix -cp config.nix dependencies.builder*.sh $tarroot/ -touch -d '@1000000000' $tarroot $tarroot/* +rm -rf "$tarroot" +mkdir -p "$tarroot" +cp dependencies.nix "$tarroot/default.nix" +cp config.nix dependencies.builder*.sh "$tarroot/" +touch -d '@1000000000' "$tarroot" "$tarroot"/* -hash=$(nix hash path $tarroot) +hash=$(nix hash path "$tarroot") test_tarball() { local ext="$1" local compressor="$2" tarball=$TEST_ROOT/tarball.tar$ext - (cd $TEST_ROOT && GNUTAR_REPRODUCIBLE= tar --mtime=$tarroot/default.nix --owner=0 --group=0 --numeric-owner --sort=name -c -f - tarball) | $compressor > $tarball + (cd "$TEST_ROOT" && GNUTAR_REPRODUCIBLE=1 tar --mtime="$tarroot"/default.nix --owner=0 --group=0 --numeric-owner --sort=name -c -f - tarball) | $compressor > "$tarball" - nix-env -f file://$tarball -qa --out-path | grepQuiet dependencies + nix-env -f file://"$tarball" -qa --out-path | grepQuiet dependencies - nix-build -o $TEST_ROOT/result file://$tarball + nix-build -o "$TEST_ROOT"/result file://"$tarball" - nix-build -o $TEST_ROOT/result '' -I foo=file://$tarball + nix-build -o "$TEST_ROOT"/result '' -I foo=file://"$tarball" - nix-build -o $TEST_ROOT/result -E "import (fetchTarball file://$tarball)" + nix-build -o "$TEST_ROOT"/result -E "import (fetchTarball file://$tarball)" # Do not re-fetch paths already present - nix-build -o $TEST_ROOT/result -E "import (fetchTarball { url = file:///does-not-exist/must-remain-unused/$tarball; sha256 = \"$hash\"; })" + nix-build -o "$TEST_ROOT"/result -E "import (fetchTarball { url = file:///does-not-exist/must-remain-unused/$tarball; sha256 = \"$hash\"; })" - nix-build -o $TEST_ROOT/result -E "import (fetchTree file://$tarball)" - nix-build -o $TEST_ROOT/result -E "import (fetchTree { type = \"tarball\"; url = file://$tarball; })" - nix-build -o $TEST_ROOT/result -E "import (fetchTree { type = \"tarball\"; url = file://$tarball; narHash = \"$hash\"; })" + nix-build -o "$TEST_ROOT"/result -E "import (fetchTree file://$tarball)" + nix-build -o "$TEST_ROOT"/result -E "import (fetchTree { type = \"tarball\"; url = file://$tarball; })" + nix-build -o "$TEST_ROOT"/result -E "import (fetchTree { type = \"tarball\"; url = file://$tarball; narHash = \"$hash\"; })" # Do not re-fetch paths already present - nix-build -o $TEST_ROOT/result -E "import (fetchTree { type = \"tarball\"; url = file:///does-not-exist/must-remain-unused/$tarball; narHash = \"$hash\"; })" - expectStderr 102 nix-build -o $TEST_ROOT/result -E "import (fetchTree { type = \"tarball\"; url = file://$tarball; narHash = \"sha256-xdKv2pq/IiwLSnBBJXW8hNowI4MrdZfW+SYqDQs7Tzc=\"; })" | grep 'NAR hash mismatch in input' + nix-build -o "$TEST_ROOT"/result -E "import (fetchTree { type = \"tarball\"; url = file:///does-not-exist/must-remain-unused/$tarball; narHash = \"$hash\"; })" + expectStderr 102 nix-build -o "$TEST_ROOT"/result -E "import (fetchTree { type = \"tarball\"; url = file://$tarball; narHash = \"sha256-xdKv2pq/IiwLSnBBJXW8hNowI4MrdZfW+SYqDQs7Tzc=\"; })" | grep 'NAR hash mismatch in input' [[ $(nix eval --impure --expr "(fetchTree file://$tarball).lastModified") = 1000000000 ]] nix-instantiate --strict --eval -E "!((import (fetchTree { type = \"tarball\"; url = file://$tarball; narHash = \"$hash\"; })) ? submodules)" >&2 nix-instantiate --strict --eval -E "!((import (fetchTree { type = \"tarball\"; url = file://$tarball; narHash = \"$hash\"; })) ? submodules)" 2>&1 | grep 'true' - nix-instantiate --eval -E '1 + 2' -I fnord=file:///no-such-tarball.tar$ext - nix-instantiate --eval -E 'with ; 1 + 2' -I fnord=file:///no-such-tarball$ext - (! nix-instantiate --eval -E ' 1' -I fnord=file:///no-such-tarball$ext) + nix-instantiate --eval -E '1 + 2' -I fnord=file:///no-such-tarball.tar"$ext" + nix-instantiate --eval -E 'with ; 1 + 2' -I fnord=file:///no-such-tarball"$ext" + (! nix-instantiate --eval -E ' 1' -I fnord=file:///no-such-tarball"$ext") - nix-instantiate --eval -E '' -I fnord=file:///no-such-tarball$ext -I fnord=. + nix-instantiate --eval -E '' -I fnord=file:///no-such-tarball"$ext" -I fnord=. # Ensure that the `name` attribute isn’t accepted as that would mess # with the content-addressing diff --git a/tests/functional/test-infra.sh b/tests/functional/test-infra.sh index d02a11b46..2da26b08c 100755 --- a/tests/functional/test-infra.sh +++ b/tests/functional/test-infra.sh @@ -14,7 +14,7 @@ expect 1 false expect 1 expect 0 false function ret() { - return $1 + return "$1" } # `expect` can call functions, not just executables @@ -48,6 +48,7 @@ expectStderr 1 noisyFalse | grepQuiet NAY # `set -o pipefile` is enabled +# shellcheck disable=SC2317# shellcheck disable=SC2317 pipefailure () { # shellcheck disable=SC2216 true | false | true @@ -55,6 +56,7 @@ pipefailure () { expect 1 pipefailure unset pipefailure +# shellcheck disable=SC2317 pipefailure () { # shellcheck disable=SC2216 false | true | true @@ -82,6 +84,7 @@ expect 1 useUnbound # ! alone unfortunately negates `set -e`, but it works in functions: # shellcheck disable=SC2251 ! true +# shellcheck disable=SC2317 funBang () { ! true } diff --git a/tests/functional/test-libstoreconsumer.sh b/tests/functional/test-libstoreconsumer.sh index d1a1accb6..2adead1c0 100755 --- a/tests/functional/test-libstoreconsumer.sh +++ b/tests/functional/test-libstoreconsumer.sh @@ -5,4 +5,4 @@ source common.sh drv="$(nix-instantiate simple.nix)" cat "$drv" out="$(./test-libstoreconsumer/test-libstoreconsumer "$drv")" -cat "$out/hello" | grep -F "Hello World!" +grep -F "Hello World!" < "$out/hello" diff --git a/tests/functional/timeout.sh b/tests/functional/timeout.sh index f42354538..ae47fdc96 100755 --- a/tests/functional/timeout.sh +++ b/tests/functional/timeout.sh @@ -9,7 +9,7 @@ needLocalStore "see #4813" messages=$(nix-build -Q timeout.nix -A infiniteLoop --timeout 2 2>&1) && status=0 || status=$? -if [ $status -ne 101 ]; then +if [ "$status" -ne 101 ]; then echo "error: 'nix-store' exited with '$status'; should have exited 101" # FIXME: https://github.com/NixOS/nix/issues/4813 From 93f58150c9cd5f2fc9345c2730ce8a6da47dc474 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Tue, 13 Aug 2024 16:15:56 -0400 Subject: [PATCH 066/718] Coarse versions for constituent packages As discussed in our meeting, we should use a simplified version for the libraries without the date or commit hash. This will make rebuilding a lot faster in many cases. Progress on #10379 Co-Authored-By: Robert Hensing --- flake.nix | 19 +++++++++---------- package.nix | 5 ++--- packaging/components.nix | 31 +++++++++++++++++++++++++++---- packaging/dependencies.nix | 5 +---- packaging/hydra.nix | 9 ++++++++- 5 files changed, 47 insertions(+), 22 deletions(-) diff --git a/flake.nix b/flake.nix index 9e8592e3a..638f6b4bd 100644 --- a/flake.nix +++ b/flake.nix @@ -26,12 +26,6 @@ officialRelease = false; - version = lib.fileContents ./.version + versionSuffix; - versionSuffix = - if officialRelease - then "" - else "pre${builtins.substring 0 8 (self.lastModifiedDate or self.lastModified or "19700101")}_${self.shortRev or "dirty"}"; - linux32BitSystems = [ "i686-linux" ]; linux64BitSystems = [ "x86_64-linux" "aarch64-linux" ]; linuxSystems = linux32BitSystems ++ linux64BitSystems; @@ -130,12 +124,16 @@ # without "polluting" the top level "`pkgs`" attrset. # This also has the benefit of providing us with a distinct set of packages # we can iterate over. - nixComponents = lib.makeScope final.nixDependencies.newScope (import ./packaging/components.nix); + nixComponents = lib.makeScope final.nixDependencies.newScope (import ./packaging/components.nix { + inherit (final) lib; + inherit officialRelease; + src = self; + }); # The dependencies are in their own scope, so that they don't have to be # in Nixpkgs top level `pkgs` or `nixComponents`. nixDependencies = lib.makeScope final.newScope (import ./packaging/dependencies.nix { - inherit inputs stdenv versionSuffix; + inherit inputs stdenv; pkgs = final; }); @@ -170,6 +168,7 @@ linux64BitSystems nixpkgsFor self + officialRelease ; }; @@ -253,10 +252,10 @@ dockerImage = let pkgs = nixpkgsFor.${system}.native; - image = import ./docker.nix { inherit pkgs; tag = version; }; + image = import ./docker.nix { inherit pkgs; tag = pkgs.nix.version; }; in pkgs.runCommand - "docker-image-tarball-${version}" + "docker-image-tarball-${pkgs.nix.version}" { meta.description = "Docker image with Nix for ${system}"; } '' mkdir -p $out/nix-support diff --git a/package.nix b/package.nix index a7c8923e8..d41748b7c 100644 --- a/package.nix +++ b/package.nix @@ -47,7 +47,8 @@ , pname ? "nix" -, versionSuffix ? "" +, version +, versionSuffix # Whether to build Nix. Useful to skip for tasks like testing existing pre-built versions of Nix , doBuild ? true @@ -112,8 +113,6 @@ let inherit (lib) fileset; - version = lib.fileContents ./.version + versionSuffix; - # selected attributes with defaults, will be used to define some # things which should instead be gotten via `finalAttrs` in order to # work with overriding. diff --git a/packaging/components.nix b/packaging/components.nix index 870e9ae61..0e8334d10 100644 --- a/packaging/components.nix +++ b/packaging/components.nix @@ -1,11 +1,34 @@ +{ + lib, + src, + officialRelease, +}: + scope: + let inherit (scope) callPackage; + + baseVersion = lib.fileContents ../.version; + + versionSuffix = lib.optionalString (!officialRelease) "pre"; + + fineVersionSuffix = lib.optionalString + (!officialRelease) + "pre${builtins.substring 0 8 (src.lastModifiedDate or src.lastModified or "19700101")}_${src.shortRev or "dirty"}"; + + fineVersion = baseVersion + fineVersionSuffix; in # This becomes the pkgs.nixComponents attribute set { - nix = callPackage ../package.nix { }; + version = baseVersion + versionSuffix; + inherit versionSuffix; + + nix = callPackage ../package.nix { + version = fineVersion; + versionSuffix = fineVersionSuffix; + }; nix-util = callPackage ../src/libutil/package.nix { }; nix-util-c = callPackage ../src/libutil-c/package.nix { }; @@ -34,10 +57,10 @@ in nix-cmd = callPackage ../src/libcmd/package.nix { }; # Will replace `nix` once the old build system is gone. - nix-ng = callPackage ../src/nix/package.nix { }; + nix-ng = callPackage ../src/nix/package.nix { version = fineVersion; }; - nix-internal-api-docs = callPackage ../src/internal-api-docs/package.nix { }; - nix-external-api-docs = callPackage ../src/external-api-docs/package.nix { }; + nix-internal-api-docs = callPackage ../src/internal-api-docs/package.nix { version = fineVersion; }; + nix-external-api-docs = callPackage ../src/external-api-docs/package.nix { version = fineVersion; }; nix-perl-bindings = callPackage ../src/perl/package.nix { }; } diff --git a/packaging/dependencies.nix b/packaging/dependencies.nix index e0737593f..21c48e5cc 100644 --- a/packaging/dependencies.nix +++ b/packaging/dependencies.nix @@ -8,7 +8,6 @@ pkgs, stdenv, - versionSuffix, }: let @@ -73,11 +72,9 @@ let strictDeps = prevAttrs.strictDeps or true; enableParallelBuilding = true; }; - in scope: { - inherit stdenv versionSuffix; - version = lib.fileContents ../.version + versionSuffix; + inherit stdenv; aws-sdk-cpp = (pkgs.aws-sdk-cpp.override { apis = [ "s3" "transfer" ]; diff --git a/packaging/hydra.nix b/packaging/hydra.nix index dbe992476..9752d90e3 100644 --- a/packaging/hydra.nix +++ b/packaging/hydra.nix @@ -6,6 +6,7 @@ , linux64BitSystems , nixpkgsFor , self +, officialRelease }: let inherit (inputs) nixpkgs nixpkgs-regression; @@ -16,7 +17,7 @@ let }; testNixVersions = pkgs: client: daemon: - pkgs.callPackage ../package.nix { + pkgs.nixComponents.callPackage ../package.nix { pname = "nix-tests" + lib.optionalString @@ -28,6 +29,12 @@ let test-daemon = daemon; doBuild = false; + + # This could be more accurate, but a shorter version will match the + # fine version with rev. This functionality is already covered in + # the normal test, so it's fine. + version = pkgs.nixComponents.version; + versionSuffix = pkgs.nixComponents.versionSuffix; }; # Technically we could just return `pkgs.nixComponents`, but for Hydra it's From 34fe2478a2b26569e5e0b244e927d3b50da0056d Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 8 Jul 2024 16:07:06 -0400 Subject: [PATCH 067/718] Build Functional tests with Meson Co-Authored-By: Qyriad Co-authored-by: Robert Hensing --- flake.nix | 4 + meson.build | 1 + packaging/components.nix | 2 + packaging/hydra.nix | 7 +- src/libstore/meson.build | 2 +- src/nix-functional-tests | 1 + tests/functional/.version | 1 + tests/functional/ca/meson.build | 33 +++ tests/functional/common.sh | 3 +- .../{vars-and-functions.sh => functions.sh} | 107 ++----- tests/functional/common/init.sh | 4 +- tests/functional/common/meson.build | 5 + tests/functional/common/paths.sh | 19 +- tests/functional/common/subst-vars.sh.in | 20 +- tests/functional/common/vars.sh | 72 +++++ .../derivation-advanced-attributes.sh | 2 +- tests/functional/dyn-drv/meson.build | 19 ++ tests/functional/flakes/meson.build | 28 ++ tests/functional/git-hashing/meson.build | 8 + .../functional/local-overlay-store/common.sh | 3 +- .../local-overlay-store/meson.build | 18 ++ tests/functional/meson.build | 266 ++++++++++++++++++ tests/functional/nested-sandboxing/command.sh | 2 + tests/functional/nested-sandboxing/runner.nix | 7 +- tests/functional/package.nix | 117 ++++++++ tests/functional/plugins.sh | 9 +- tests/functional/plugins/meson.build | 16 ++ tests/functional/restricted.sh | 3 - .../test-libstoreconsumer/meson.build | 14 + 29 files changed, 678 insertions(+), 115 deletions(-) create mode 120000 src/nix-functional-tests create mode 120000 tests/functional/.version create mode 100644 tests/functional/ca/meson.build rename tests/functional/common/{vars-and-functions.sh => functions.sh} (76%) create mode 100644 tests/functional/common/meson.build create mode 100644 tests/functional/common/vars.sh create mode 100644 tests/functional/dyn-drv/meson.build create mode 100644 tests/functional/flakes/meson.build create mode 100644 tests/functional/git-hashing/meson.build create mode 100644 tests/functional/local-overlay-store/meson.build create mode 100644 tests/functional/meson.build create mode 100644 tests/functional/package.nix create mode 100644 tests/functional/plugins/meson.build create mode 100644 tests/functional/test-libstoreconsumer/meson.build diff --git a/flake.nix b/flake.nix index 638f6b4bd..22ca54118 100644 --- a/flake.nix +++ b/flake.nix @@ -210,6 +210,9 @@ "${nixpkgsPrefix}${pkgName}-${testName}" = test; }) ) + // lib.optionalAttrs (nixpkgs.stdenv.hostPlatform == nixpkgs.stdenv.buildPlatform) { + "${nixpkgsPrefix}nix-functional-tests" = nixpkgs.nixComponents.nix-functional-tests; + } ) // devFlake.checks.${system} or {} ); @@ -323,6 +326,7 @@ ++ lib.optionals havePerl pkgs.nixComponents.nix-perl-bindings.nativeBuildInputs ++ pkgs.nixComponents.nix-internal-api-docs.nativeBuildInputs ++ pkgs.nixComponents.nix-external-api-docs.nativeBuildInputs + ++ pkgs.nixComponents.nix-functional-tests.baseNativeBuildInputs ++ lib.optional (!stdenv.buildPlatform.canExecute stdenv.hostPlatform # Hack around https://github.com/nixos/nixpkgs/commit/bf7ad8cfbfa102a90463433e2c5027573b462479 diff --git a/meson.build b/meson.build index 1554244ab..715a3862d 100644 --- a/meson.build +++ b/meson.build @@ -42,3 +42,4 @@ subproject('nix-fetchers-tests') subproject('nix-expr-test-support') subproject('nix-expr-tests') subproject('nix-flake-tests') +subproject('nix-functional-tests') diff --git a/packaging/components.nix b/packaging/components.nix index 0e8334d10..f14613e8a 100644 --- a/packaging/components.nix +++ b/packaging/components.nix @@ -59,6 +59,8 @@ in # Will replace `nix` once the old build system is gone. nix-ng = callPackage ../src/nix/package.nix { version = fineVersion; }; + nix-functional-tests = callPackage ../src/nix-functional-tests/package.nix { version = fineVersion; }; + nix-internal-api-docs = callPackage ../src/internal-api-docs/package.nix { version = fineVersion; }; nix-external-api-docs = callPackage ../src/external-api-docs/package.nix { version = fineVersion; }; diff --git a/packaging/hydra.nix b/packaging/hydra.nix index 9752d90e3..46b4ff51d 100644 --- a/packaging/hydra.nix +++ b/packaging/hydra.nix @@ -62,6 +62,7 @@ let "nix-main-c" "nix-cmd" "nix-ng" + "nix-functional-tests" ]; in { @@ -75,8 +76,10 @@ in lib.genAttrs linux64BitSystems (system: nixpkgsFor.${system}.static.nixComponents.${pkgName})); buildCross = forAllPackages (pkgName: - forAllCrossSystems (crossSystem: - lib.genAttrs [ "x86_64-linux" ] (system: nixpkgsFor.${system}.cross.${crossSystem}.nixComponents.${pkgName}))); + # Hack to avoid non-evaling package + (if pkgName == "nix-functional-tests" then lib.flip builtins.removeAttrs ["x86_64-w64-mingw32"] else lib.id) + (forAllCrossSystems (crossSystem: + lib.genAttrs [ "x86_64-linux" ] (system: nixpkgsFor.${system}.cross.${crossSystem}.nixComponents.${pkgName})))); buildNoGc = forAllSystems (system: self.packages.${system}.nix.override { enableGC = false; } diff --git a/src/libstore/meson.build b/src/libstore/meson.build index d2cc235fd..8e30845e1 100644 --- a/src/libstore/meson.build +++ b/src/libstore/meson.build @@ -21,7 +21,7 @@ configdata = configuration_data() # TODO rename, because it will conflict with downstream projects configdata.set_quoted('PACKAGE_VERSION', meson.project_version()) -configdata.set_quoted('SYSTEM', host_machine.system()) +configdata.set_quoted('SYSTEM', host_machine.cpu_family() + '-' + host_machine.system()) deps_private_maybe_subproject = [ ] diff --git a/src/nix-functional-tests b/src/nix-functional-tests new file mode 120000 index 000000000..ed0cdf60b --- /dev/null +++ b/src/nix-functional-tests @@ -0,0 +1 @@ +../tests/functional \ No newline at end of file diff --git a/tests/functional/.version b/tests/functional/.version new file mode 120000 index 000000000..b7badcd0c --- /dev/null +++ b/tests/functional/.version @@ -0,0 +1 @@ +../../.version \ No newline at end of file diff --git a/tests/functional/ca/meson.build b/tests/functional/ca/meson.build new file mode 100644 index 000000000..f682ab28f --- /dev/null +++ b/tests/functional/ca/meson.build @@ -0,0 +1,33 @@ +configure_file( + input : 'config.nix.in', + output : 'config.nix', + configuration : test_confdata, +) + +suites += { + 'name': 'ca', + 'deps': [], + 'tests': [ + 'build-with-garbage-path.sh', + 'build.sh', + 'build-cache.sh', + 'concurrent-builds.sh', + 'derivation-json.sh', + 'duplicate-realisation-in-closure.sh', + 'eval-store.sh', + 'gc.sh', + 'import-derivation.sh', + 'new-build-cmd.sh', + 'nix-copy.sh', + 'nix-run.sh', + 'nix-shell.sh', + 'post-hook.sh', + 'recursive.sh', + 'repl.sh', + 'selfref-gc.sh', + 'signatures.sh', + 'substitute.sh', + 'why-depends.sh', + ], + 'workdir': meson.current_build_dir(), +} diff --git a/tests/functional/common.sh b/tests/functional/common.sh index d038aaf59..325fac44c 100644 --- a/tests/functional/common.sh +++ b/tests/functional/common.sh @@ -8,7 +8,8 @@ COMMON_SH_SOURCED=1 functionalTestsDir="$(readlink -f "$(dirname "${BASH_SOURCE[0]-$0}")")" -source "$functionalTestsDir/common/vars-and-functions.sh" +source "$functionalTestsDir/common/vars.sh" +source "$functionalTestsDir/common/functions.sh" source "$functionalTestsDir/common/init.sh" if [[ -n "${NIX_DAEMON_PACKAGE:-}" ]]; then diff --git a/tests/functional/common/vars-and-functions.sh b/tests/functional/common/functions.sh similarity index 76% rename from tests/functional/common/vars-and-functions.sh rename to tests/functional/common/functions.sh index 632c81a82..d05fac4e7 100644 --- a/tests/functional/common/vars-and-functions.sh +++ b/tests/functional/common/functions.sh @@ -1,10 +1,10 @@ -# NOTE: instances of @variable@ are substituted as defined in /mk/templates.mk +# shellcheck shell=bash set -eu -o pipefail -if [[ -z "${COMMON_VARS_AND_FUNCTIONS_SH_SOURCED-}" ]]; then +if [[ -z "${COMMON_FUNCTIONS_SH_SOURCED-}" ]]; then -COMMON_VARS_AND_FUNCTIONS_SH_SOURCED=1 +COMMON_FUNCTIONS_SH_SOURCED=1 isTestOnNixOS() { [[ "${isTestOnNixOS:-}" == 1 ]] @@ -15,64 +15,14 @@ die() { exit 1 } -set +x - -commonDir="$(readlink -f "$(dirname "${BASH_SOURCE[0]-$0}")")" - -source "$commonDir/subst-vars.sh" -# Make sure shellcheck knows all these will be defined by the above generated snippet -: "${bindir?} ${coreutils?} ${dot?} ${SHELL?} ${PAGER?} ${busybox?} ${version?} ${system?} ${BUILD_SHARED_LIBS?}" - -source "$commonDir/paths.sh" -source "$commonDir/test-root.sh" - -test_nix_conf_dir=$TEST_ROOT/etc -test_nix_conf=$test_nix_conf_dir/nix.conf - -export TEST_HOME=$TEST_ROOT/test-home - -if ! isTestOnNixOS; then - export NIX_STORE_DIR - if ! NIX_STORE_DIR=$(readlink -f $TEST_ROOT/store 2> /dev/null); then - # Maybe the build directory is symlinked. - export NIX_IGNORE_SYMLINK_STORE=1 - NIX_STORE_DIR=$TEST_ROOT/store - fi - export NIX_LOCALSTATE_DIR=$TEST_ROOT/var - export NIX_LOG_DIR=$TEST_ROOT/var/log/nix - export NIX_STATE_DIR=$TEST_ROOT/var/nix - export NIX_CONF_DIR=$test_nix_conf_dir - export NIX_DAEMON_SOCKET_PATH=$TEST_ROOT/dSocket - unset NIX_USER_CONF_FILES - export _NIX_TEST_SHARED=$TEST_ROOT/shared - if [[ -n $NIX_STORE ]]; then - export _NIX_TEST_NO_SANDBOX=1 - fi - export _NIX_IN_TEST=$TEST_ROOT/shared - export _NIX_TEST_NO_LSOF=1 - export NIX_REMOTE=${NIX_REMOTE_-} - -fi # ! isTestOnNixOS - -unset NIX_PATH -export HOME=$TEST_HOME -unset XDG_STATE_HOME -unset XDG_DATA_HOME -unset XDG_CONFIG_HOME -unset XDG_CONFIG_DIRS -unset XDG_CACHE_HOME - -export IMPURE_VAR1=foo -export IMPURE_VAR2=bar - -cacheDir=$TEST_ROOT/binary-cache - readLink() { + # TODO fix this + # shellcheck disable=SC2012 ls -l "$1" | sed 's/.*->\ //' } clearProfiles() { - profiles="$HOME"/.local/state/nix/profiles + profiles="$HOME/.local/state/nix/profiles" rm -rf "$profiles" } @@ -105,11 +55,11 @@ doClearStore() { } clearCache() { - rm -rf "$cacheDir" + rm -rf "${cacheDir?}" } clearCacheCache() { - rm -f $TEST_HOME/.cache/nix/binary-cache* + rm -f "$TEST_HOME/.cache/nix/binary-cache"* } startDaemon() { @@ -122,7 +72,7 @@ startDaemon() { return fi # Start the daemon, wait for the socket to appear. - rm -f $NIX_DAEMON_SOCKET_PATH + rm -f "$NIX_DAEMON_SOCKET_PATH" PATH=$DAEMON_PATH nix --extra-experimental-features 'nix-command' daemon & _NIX_TEST_DAEMON_PID=$! export _NIX_TEST_DAEMON_PID @@ -151,14 +101,14 @@ killDaemon() { if [[ "${_NIX_TEST_DAEMON_PID-}" == '' ]]; then return fi - kill $_NIX_TEST_DAEMON_PID + kill "$_NIX_TEST_DAEMON_PID" for i in {0..100}; do - kill -0 $_NIX_TEST_DAEMON_PID 2> /dev/null || break + kill -0 "$_NIX_TEST_DAEMON_PID" 2> /dev/null || break sleep 0.1 done - kill -9 $_NIX_TEST_DAEMON_PID 2> /dev/null || true - wait $_NIX_TEST_DAEMON_PID || true - rm -f $NIX_DAEMON_SOCKET_PATH + kill -9 "$_NIX_TEST_DAEMON_PID" 2> /dev/null || true + wait "$_NIX_TEST_DAEMON_PID" || true + rm -f "$NIX_DAEMON_SOCKET_PATH" # Indicate daemon is stopped unset _NIX_TEST_DAEMON_PID # Restore old nix remote @@ -177,14 +127,11 @@ restartDaemon() { startDaemon } -if [[ $(uname) == Linux ]] && [[ -L /proc/self/ns/user ]] && unshare --user true; then - _canUseSandbox=1 -fi - isDaemonNewer () { [[ -n "${NIX_DAEMON_PACKAGE:-}" ]] || return 0 local requiredVersion="$1" - local daemonVersion=$($NIX_DAEMON_PACKAGE/bin/nix daemon --version | cut -d' ' -f3) + local daemonVersion + daemonVersion=$("$NIX_DAEMON_PACKAGE/bin/nix" daemon --version | cut -d' ' -f3) [[ $(nix eval --expr "builtins.compareVersions ''$daemonVersion'' ''$requiredVersion''") -ge 0 ]] } @@ -237,7 +184,7 @@ expect() { shift "$@" && res=0 || res="$?" # also match "negative" codes, which wrap around to >127 - if [[ $res -ne $expected && $res -ne $[256 + expected] ]]; then + if [[ $res -ne $expected && $res -ne $((256 + expected)) ]]; then echo "Expected exit code '$expected' but got '$res' from command ${*@Q}" >&2 return 1 fi @@ -252,7 +199,7 @@ expectStderr() { shift "$@" 2>&1 && res=0 || res="$?" # also match "negative" codes, which wrap around to >127 - if [[ $res -ne $expected && $res -ne $[256 + expected] ]]; then + if [[ $res -ne $expected && $res -ne $((256 + expected)) ]]; then echo "Expected exit code '$expected' but got '$res' from command ${*@Q}" >&2 return 1 fi @@ -267,7 +214,7 @@ expectStderr() { # error: This error is expected # EOF assertStderr() { - diff -u /dev/stdin <($@ 2>/dev/null 2>&1) + diff -u /dev/stdin <("$@" 2>/dev/null 2>&1) } needLocalStore() { @@ -283,11 +230,9 @@ buggyNeedLocalStore() { enableFeatures() { local features="$1" - sed -i 's/experimental-features .*/& '"$features"'/' "$test_nix_conf_dir"/nix.conf + sed -i 's/experimental-features .*/& '"$features"'/' "${test_nix_conf?}" } -set -x - onError() { set +x echo "$0: test failed at:" >&2 @@ -311,15 +256,15 @@ callerPrefix() { local i file line fn savedFn # Use `caller` for i in $(seq 0 100); do - caller $i > /dev/null || { + caller "$i" > /dev/null || { if [[ -n "${file:-}" ]]; then echo "$file:$line: ${savedFn+in call to $savedFn: }" fi break } - line="$(caller $i | cut -d' ' -f1)" - fn="$(caller $i | cut -d' ' -f2)" - file="$(caller $i | cut -d' ' -f3)" + line="$(caller "$i" | cut -d' ' -f1)" + fn="$(caller "$i" | cut -d' ' -f2)" + file="$(caller "$i" | cut -d' ' -f3)" if [[ $file != "${BASH_SOURCE[0]}" ]]; then echo "$file:$line: ${savedFn+in call to $savedFn: }" return @@ -342,7 +287,7 @@ checkGrepArgs() { for arg in "$@"; do if [[ "$arg" != "${arg//$'\n'/_}" ]]; then echo "$(callerPrefix)newline not allowed in arguments; grep would try each line individually as if connected by an OR operator" >&2 - return -101 + return 155 # = -101 mod 256 fi done } @@ -400,4 +345,4 @@ count() { trap onError ERR -fi # COMMON_VARS_AND_FUNCTIONS_SH_SOURCED +fi # COMMON_FUNCTIONS_SH_SOURCED diff --git a/tests/functional/common/init.sh b/tests/functional/common/init.sh index d33ad5d57..d849c0734 100755 --- a/tests/functional/common/init.sh +++ b/tests/functional/common/init.sh @@ -7,10 +7,10 @@ if isTestOnNixOS; then mkdir -p "$test_nix_conf_dir" "$TEST_HOME" - export NIX_USER_CONF_FILES="$test_nix_conf_dir/nix.conf" + export NIX_USER_CONF_FILES="$test_nix_conf" mkdir -p "$test_nix_conf_dir" "$TEST_HOME" ! test -e "$test_nix_conf" - cat > "$test_nix_conf_dir/nix.conf" < "$test_nix_conf" < /dev/null); then + # Maybe the build directory is symlinked. + export NIX_IGNORE_SYMLINK_STORE=1 + NIX_STORE_DIR=$TEST_ROOT/store + fi + export NIX_LOCALSTATE_DIR=$TEST_ROOT/var + export NIX_LOG_DIR=$TEST_ROOT/var/log/nix + export NIX_STATE_DIR=$TEST_ROOT/var/nix + export NIX_CONF_DIR=$test_nix_conf_dir + export NIX_DAEMON_SOCKET_PATH=$TEST_ROOT/dSocket + unset NIX_USER_CONF_FILES + export _NIX_TEST_SHARED=$TEST_ROOT/shared + if [[ -n $NIX_STORE ]]; then + export _NIX_TEST_NO_SANDBOX=1 + fi + export _NIX_IN_TEST=$TEST_ROOT/shared + export _NIX_TEST_NO_LSOF=1 + export NIX_REMOTE=${NIX_REMOTE_-} + +fi # ! isTestOnNixOS + +unset NIX_PATH +export HOME=$TEST_HOME +unset XDG_STATE_HOME +unset XDG_DATA_HOME +unset XDG_CONFIG_HOME +unset XDG_CONFIG_DIRS +unset XDG_CACHE_HOME + +export IMPURE_VAR1=foo +export IMPURE_VAR2=bar + +# Used in other files +# shellcheck disable=SC2034 +cacheDir=$TEST_ROOT/binary-cache + +if [[ $(uname) == Linux ]] && [[ -L /proc/self/ns/user ]] && unshare --user true; then + _canUseSandbox=1 +fi + +fi # COMMON_VARS_SH_SOURCED diff --git a/tests/functional/derivation-advanced-attributes.sh b/tests/functional/derivation-advanced-attributes.sh index 6c0c76b4c..271f17dc6 100755 --- a/tests/functional/derivation-advanced-attributes.sh +++ b/tests/functional/derivation-advanced-attributes.sh @@ -3,7 +3,7 @@ source common/test-root.sh source common/paths.sh -set -o pipefail +set -eu -o pipefail source characterisation/framework.sh diff --git a/tests/functional/dyn-drv/meson.build b/tests/functional/dyn-drv/meson.build new file mode 100644 index 000000000..3c671d013 --- /dev/null +++ b/tests/functional/dyn-drv/meson.build @@ -0,0 +1,19 @@ +configure_file( + input : 'config.nix.in', + output : 'config.nix', + configuration : test_confdata, +) + +suites += { + 'name': 'dyn-drv', + 'deps': [], + 'tests': [ + 'text-hashed-output.sh', + 'recursive-mod-json.sh', + 'build-built-drv.sh', + 'eval-outputOf.sh', + 'dep-built-drv.sh', + 'old-daemon-error-hack.sh', + ], + 'workdir': meson.current_build_dir(), +} diff --git a/tests/functional/flakes/meson.build b/tests/functional/flakes/meson.build new file mode 100644 index 000000000..8c1afd6ff --- /dev/null +++ b/tests/functional/flakes/meson.build @@ -0,0 +1,28 @@ +suites += { + 'name': 'flakes', + 'deps': [], + 'tests': [ + 'flakes.sh', + 'develop.sh', + 'edit.sh', + 'run.sh', + 'mercurial.sh', + 'circular.sh', + 'init.sh', + 'inputs.sh', + 'follow-paths.sh', + 'bundle.sh', + 'check.sh', + 'unlocked-override.sh', + 'absolute-paths.sh', + 'absolute-attr-paths.sh', + 'build-paths.sh', + 'flake-in-submodule.sh', + 'prefetch.sh', + 'eval-cache.sh', + 'search-root.sh', + 'config.sh', + 'show.sh', + ], + 'workdir': meson.current_build_dir(), +} diff --git a/tests/functional/git-hashing/meson.build b/tests/functional/git-hashing/meson.build new file mode 100644 index 000000000..7486bfb8f --- /dev/null +++ b/tests/functional/git-hashing/meson.build @@ -0,0 +1,8 @@ +suites += { + 'name': 'git-hashing', + 'deps': [], + 'tests': [ + 'simple.sh', + ], + 'workdir': meson.current_build_dir(), +} diff --git a/tests/functional/local-overlay-store/common.sh b/tests/functional/local-overlay-store/common.sh index b171f91f4..27338ea23 100644 --- a/tests/functional/local-overlay-store/common.sh +++ b/tests/functional/local-overlay-store/common.sh @@ -1,4 +1,5 @@ -source ../common/vars-and-functions.sh +source ../common/vars.sh +source ../common/functions.sh TODO_NixOS diff --git a/tests/functional/local-overlay-store/meson.build b/tests/functional/local-overlay-store/meson.build new file mode 100644 index 000000000..6ff5d3169 --- /dev/null +++ b/tests/functional/local-overlay-store/meson.build @@ -0,0 +1,18 @@ +suites += { + 'name': 'local-overlay-store', + 'deps': [], + 'tests': [ + 'check-post-init.sh', + 'redundant-add.sh', + 'build.sh', + 'bad-uris.sh', + 'add-lower.sh', + 'delete-refs.sh', + 'delete-duplicate.sh', + 'gc.sh', + 'verify.sh', + 'optimise.sh', + 'stale-file-handle.sh', + ], + 'workdir': meson.current_build_dir(), +} diff --git a/tests/functional/meson.build b/tests/functional/meson.build new file mode 100644 index 000000000..ebecdd9e8 --- /dev/null +++ b/tests/functional/meson.build @@ -0,0 +1,266 @@ +project('nix-functional-tests', 'cpp', + version : files('.version'), + default_options : [ + 'cpp_std=c++2a', + # TODO(Qyriad): increase the warning level + 'warning_level=1', + 'debug=true', + 'optimization=2', + 'errorlogs=true', # Please print logs for tests that fail + ], + meson_version : '>= 1.3', + license : 'LGPL-2.1-or-later', +) + +fs = import('fs') + +# Need to combine source and build trees +run_command( + 'rsync', + '-a', + '--copy-unsafe-links', + meson.current_source_dir() / '', + meson.current_build_dir() / '', +) +# This current-source-escaping relative is no good because we don't know +# where the build directory will be, therefore we fix it up. Once the +# Make build system is gone, we should think about doing this better. +scripts_dir = fs.relative_to( + meson.current_source_dir() / '..' / '..' / 'scripts', + meson.current_build_dir(), +) +run_command( + 'sed', + '-i', meson.current_build_dir() / 'bash-profile.sh', + '-e', 's^../../scripts^@0@^'.format(scripts_dir), +) + +nix = find_program('nix') +bash = find_program('bash', native : true) +busybox = find_program('busybox', native : true, required : false) +coreutils = find_program('coreutils', native : true) +dot = find_program('dot', native : true, required : false) + +nix_bin_dir = fs.parent(nix.full_path()) + +test_confdata = { + 'bindir': nix_bin_dir, + 'coreutils': fs.parent(coreutils.full_path()), + 'dot': dot.found() ? dot.full_path() : '', + 'bash': bash.full_path(), + 'sandbox_shell': busybox.found() ? busybox.full_path() : '', + 'PACKAGE_VERSION': meson.project_version(), + 'system': host_machine.cpu_family() + '-' + host_machine.system(), +} + +# Just configures `common/vars-and-functions.sh.in`. +# Done as a subdir() so Meson places it under `common` in the build directory as well. +subdir('common') + +config_nix_in = configure_file( + input : 'config.nix.in', + output : 'config.nix', + configuration : test_confdata, +) + +suites = [ + { + 'name' : 'main', + 'deps': [], + 'tests': [ + 'test-infra.sh', + 'gc.sh', + 'nix-collect-garbage-d.sh', + 'remote-store.sh', + 'legacy-ssh-store.sh', + 'lang.sh', + 'lang-gc.sh', + 'characterisation-test-infra.sh', + 'experimental-features.sh', + 'fetchMercurial.sh', + 'gc-auto.sh', + 'user-envs.sh', + 'user-envs-migration.sh', + 'binary-cache.sh', + 'multiple-outputs.sh', + 'nix-build.sh', + 'gc-concurrent.sh', + 'repair.sh', + 'fixed.sh', + 'export-graph.sh', + 'timeout.sh', + 'fetchGitRefs.sh', + 'gc-runtime.sh', + 'tarball.sh', + 'fetchGit.sh', + 'fetchurl.sh', + 'fetchPath.sh', + 'fetchTree-file.sh', + 'simple.sh', + 'referrers.sh', + 'optimise-store.sh', + 'substitute-with-invalid-ca.sh', + 'signing.sh', + 'hash-convert.sh', + 'hash-path.sh', + 'gc-non-blocking.sh', + 'check.sh', + 'nix-shell.sh', + 'check-refs.sh', + 'build-remote-input-addressed.sh', + 'secure-drv-outputs.sh', + 'restricted.sh', + 'fetchGitSubmodules.sh', + 'fetchGitVerification.sh', + 'readfile-context.sh', + 'nix-channel.sh', + 'recursive.sh', + 'dependencies.sh', + 'check-reqs.sh', + 'build-remote-content-addressed-fixed.sh', + 'build-remote-content-addressed-floating.sh', + 'build-remote-trustless-should-pass-0.sh', + 'build-remote-trustless-should-pass-1.sh', + 'build-remote-trustless-should-pass-2.sh', + 'build-remote-trustless-should-pass-3.sh', + 'build-remote-trustless-should-fail-0.sh', + 'build-remote-with-mounted-ssh-ng.sh', + 'nar-access.sh', + 'impure-eval.sh', + 'pure-eval.sh', + 'eval.sh', + 'repl.sh', + 'binary-cache-build-remote.sh', + 'search.sh', + 'logging.sh', + 'export.sh', + 'config.sh', + 'add.sh', + 'chroot-store.sh', + 'filter-source.sh', + 'misc.sh', + 'dump-db.sh', + 'linux-sandbox.sh', + 'supplementary-groups.sh', + 'build-dry.sh', + 'structured-attrs.sh', + 'shell.sh', + 'brotli.sh', + 'zstd.sh', + 'compression-levels.sh', + 'nix-copy-ssh.sh', + 'nix-copy-ssh-ng.sh', + 'post-hook.sh', + 'function-trace.sh', + 'fmt.sh', + 'eval-store.sh', + 'why-depends.sh', + 'derivation-json.sh', + 'derivation-advanced-attributes.sh', + 'import-derivation.sh', + 'nix_path.sh', + 'case-hack.sh', + 'placeholders.sh', + 'ssh-relay.sh', + 'build.sh', + 'build-delete.sh', + 'output-normalization.sh', + 'selfref-gc.sh', + 'db-migration.sh', + 'bash-profile.sh', + 'pass-as-file.sh', + 'nix-profile.sh', + 'suggestions.sh', + 'store-info.sh', + 'fetchClosure.sh', + 'completions.sh', + 'impure-derivations.sh', + 'path-from-hash-part.sh', + 'path-info.sh', + 'toString-path.sh', + 'read-only-store.sh', + 'nested-sandboxing.sh', + 'impure-env.sh', + 'debugger.sh', + 'extra-sandbox-profile.sh', + 'help.sh', + ], + 'workdir': meson.current_build_dir(), + }, +] + +nix_store = dependency('nix-store', required : false) +if nix_store.found() + subdir('test-libstoreconsumer') + suites += { + 'name': 'libstoreconsumer', + 'deps': [ + libstoreconsumer_tester, + ], + 'tests': [ + 'test-libstoreconsumer.sh', + ], + 'workdir': meson.current_build_dir(), + } + +endif + +# Plugin tests require shared libraries support. +nix_expr = dependency('nix-expr', required : false) +if nix_expr.found() and get_option('default_library') != 'static' + subdir('plugins') + suites += { + 'name': 'plugins', + 'deps': [ + libplugintest, + ], + 'tests': [ + 'plugins.sh', + ], + 'workdir': meson.current_build_dir(), + } +endif + +subdir('ca') +subdir('dyn-drv') +subdir('flakes') +subdir('git-hashing') +subdir('local-overlay-store') + +foreach suite : suites + foreach script : suite['tests'] + workdir = suite['workdir'] + prefix = fs.relative_to(workdir, meson.project_build_root()) + + script = script + # Turns, e.g., `tests/functional/flakes/show.sh` into a Meson test target called + # `functional-flakes-show`. + name = fs.replace_suffix(prefix / script, '') + + test( + name, + bash, + args: [ + '-x', + '-e', + '-u', + '-o', 'pipefail', + script, + ], + suite : suite['name'], + env : { + 'TEST_NAME': name, + 'NIX_REMOTE': '', + 'PS4': '+(${BASH_SOURCE[0]-$0}:$LINENO) ', + }, + # some tests take 15+ seconds even on an otherwise idle machine, on a loaded machine + # this can easily drive them to failure. give them more time than default of 30sec + timeout : 300, + # Used for target dependency/ordering tracking, not adding compiler flags or anything. + depends : suite['deps'], + workdir : workdir, + # Won't pass until man pages are generated + should_fail : suite['name'] == 'main' and script == 'help.sh' + ) + endforeach +endforeach diff --git a/tests/functional/nested-sandboxing/command.sh b/tests/functional/nested-sandboxing/command.sh index 69366486c..e9c40a5d9 100644 --- a/tests/functional/nested-sandboxing/command.sh +++ b/tests/functional/nested-sandboxing/command.sh @@ -1,3 +1,5 @@ +set -eu -o pipefail + export NIX_BIN_DIR=$(dirname $(type -p nix)) # TODO Get Nix and its closure more flexibly export EXTRA_SANDBOX="/nix/store $(dirname $NIX_BIN_DIR)" diff --git a/tests/functional/nested-sandboxing/runner.nix b/tests/functional/nested-sandboxing/runner.nix index 9a5822c88..1e79d5065 100644 --- a/tests/functional/nested-sandboxing/runner.nix +++ b/tests/functional/nested-sandboxing/runner.nix @@ -6,7 +6,10 @@ mkDerivation { name = "nested-sandboxing"; busybox = builtins.getEnv "busybox"; EXTRA_SANDBOX = builtins.getEnv "EXTRA_SANDBOX"; - buildCommand = if altitude == 0 then '' + buildCommand = '' + set -x + set -eu -o pipefail + '' + (if altitude == 0 then '' echo Deep enough! > $out '' else '' cp -r ${../common} ./common @@ -20,5 +23,5 @@ mkDerivation { source ./nested-sandboxing/command.sh runNixBuild ${storeFun} ${toString altitude} >> $out - ''; + ''); } diff --git a/tests/functional/package.nix b/tests/functional/package.nix new file mode 100644 index 000000000..205b03614 --- /dev/null +++ b/tests/functional/package.nix @@ -0,0 +1,117 @@ +{ lib +, stdenv +, mkMesonDerivation +, releaseTools + +, meson +, ninja +, pkg-config +, rsync + +, jq +, git +, mercurial +, util-linux + +, nix-store +, nix-expr +, nix-ng + +, rapidcheck +, gtest +, runCommand + +, busybox-sandbox-shell ? null + +# Configuration Options + +, version + +# For running the functional tests against a different pre-built Nix. +, test-daemon ? null +}: + +let + inherit (lib) fileset; +in + +mkMesonDerivation (finalAttrs: { + pname = "nix-functional-tests"; + inherit version; + + workDir = ./.; + fileset = fileset.unions [ + ../../scripts/nix-profile.sh.in + ../../.version + ../../tests/functional + ./. + ]; + + # Hack for sake of the dev shell + passthru.baseNativeBuildInputs = [ + meson + ninja + pkg-config + rsync + + jq + git + mercurial + ] ++ lib.optionals stdenv.hostPlatform.isLinux [ + # For various sandboxing tests that needs a statically-linked shell, + # etc. + busybox-sandbox-shell + # For Overlay FS tests need `mount`, `umount`, and `unshare`. + # TODO use `unixtools` to be precise over which executables instead? + util-linux + ]; + + nativeBuildInputs = finalAttrs.passthru.baseNativeBuildInputs ++ [ + nix-ng + ]; + + buildInputs = [ + nix-store + nix-expr + ]; + + + preConfigure = + # "Inline" .version so it's not a symlink, and includes the suffix. + # Do the meson utils, without modification. + '' + chmod u+w ./.version + echo ${version} > ../../../.version + '' + # TEMP hack for Meson before make is gone, where + # `src/nix-functional-tests` is during the transition a symlink and + # not the actual directory directory. + + '' + cd $(readlink -e $PWD) + echo $PWD | grep tests/functional + ''; + + mesonCheckFlags = [ + "--print-errorlogs" + ]; + + preCheck = + # See https://github.com/NixOS/nix/issues/2523 + # Occurs often in tests since https://github.com/NixOS/nix/pull/9900 + lib.optionalString stdenv.hostPlatform.isDarwin '' + export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES + ''; + + doCheck = true; + + installPhase = '' + touch $out + ''; + + meta = { + platforms = lib.platforms.unix; + }; + +} // lib.optionalAttrs (test-daemon != null) { + NIX_DAEMON_PACKAGE = test-daemon; +}) diff --git a/tests/functional/plugins.sh b/tests/functional/plugins.sh index ab4876df9..fc2d1907c 100755 --- a/tests/functional/plugins.sh +++ b/tests/functional/plugins.sh @@ -2,10 +2,11 @@ source common.sh -if [[ $BUILD_SHARED_LIBS != 1 ]]; then - skipTest "Plugins are not supported" -fi +for ext in so dylib; do + plugin="$PWD/plugins/libplugintest.$ext" + [[ -f "$plugin" ]] && break +done -res=$(nix --option setting-set true --option plugin-files $PWD/plugins/libplugintest* eval --expr builtins.anotherNull) +res=$(nix --option setting-set true --option plugin-files "$plugin" eval --expr builtins.anotherNull) [ "$res"x = "nullx" ] diff --git a/tests/functional/plugins/meson.build b/tests/functional/plugins/meson.build new file mode 100644 index 000000000..3d6b2f0e1 --- /dev/null +++ b/tests/functional/plugins/meson.build @@ -0,0 +1,16 @@ +libplugintest = shared_module( + 'plugintest', + 'plugintest.cc', + cpp_args : [ + # TODO(Qyriad): Yes this is how the autoconf+Make system did it. + # It would be nice for our headers to be idempotent instead. + '-include', 'config-util.hh', + '-include', 'config-store.hh', + # '-include', 'config-fetchers.hh', + '-include', 'config-expr.hh', + ], + dependencies : [ + dependency('nix-expr'), + ], + build_by_default : false, +) diff --git a/tests/functional/restricted.sh b/tests/functional/restricted.sh index 591367e9f..e5fe9c136 100755 --- a/tests/functional/restricted.sh +++ b/tests/functional/restricted.sh @@ -16,9 +16,6 @@ nix-instantiate --restrict-eval ./simple.nix -I src1=simple.nix -I src2=config.n (! nix-instantiate --restrict-eval --eval -E 'builtins.readFile ./simple.nix') nix-instantiate --restrict-eval --eval -E 'builtins.readFile ./simple.nix' -I src=../.. -(! nix-instantiate --restrict-eval --eval -E 'builtins.readDir ../../src/nix-channel') -nix-instantiate --restrict-eval --eval -E 'builtins.readDir ../../src/nix-channel' -I src=../../src - expectStderr 1 nix-instantiate --restrict-eval --eval -E 'let __nixPath = [ { prefix = "foo"; path = ./.; } ]; in builtins.readFile ' | grepQuiet "forbidden in restricted mode" nix-instantiate --restrict-eval --eval -E 'let __nixPath = [ { prefix = "foo"; path = ./.; } ]; in builtins.readFile ' -I src=. diff --git a/tests/functional/test-libstoreconsumer/meson.build b/tests/functional/test-libstoreconsumer/meson.build new file mode 100644 index 000000000..7076127f7 --- /dev/null +++ b/tests/functional/test-libstoreconsumer/meson.build @@ -0,0 +1,14 @@ +libstoreconsumer_tester = executable( + 'test-libstoreconsumer', + 'main.cc', + cpp_args : [ + # TODO(Qyriad): Yes this is how the autoconf+Make system did it. + # It would be nice for our headers to be idempotent instead. + '-include', 'config-util.hh', + '-include', 'config-store.hh', + ], + dependencies : [ + dependency('nix-store'), + ], + build_by_default : false, +) From 6f3045c2a225dca7b1ed8a9c9dc27ab50f575900 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Wed, 14 Aug 2024 15:40:32 -0400 Subject: [PATCH 068/718] Remove unit tests from old build system Now that we can run all tests with Meson, we want developers making code changes to use it. (Only the manual needs to be built with the build system, and that will change shortly.) This reverts commit b0bc2a97bfe007fbc32f584ed9de5e7cb75a521c. --- Makefile | 19 ------------ Makefile.config.in | 1 - configure.ac | 22 -------------- package.nix | 33 +------------------- tests/unit/libexpr-support/local.mk | 23 -------------- tests/unit/libexpr/local.mk | 45 ---------------------------- tests/unit/libfetchers/local.mk | 37 ----------------------- tests/unit/libflake/local.mk | 43 -------------------------- tests/unit/libstore-support/local.mk | 21 ------------- tests/unit/libstore/local.mk | 38 ----------------------- tests/unit/libutil-support/local.mk | 19 ------------ tests/unit/libutil/local.mk | 37 ----------------------- 12 files changed, 1 insertion(+), 337 deletions(-) delete mode 100644 tests/unit/libexpr-support/local.mk delete mode 100644 tests/unit/libexpr/local.mk delete mode 100644 tests/unit/libfetchers/local.mk delete mode 100644 tests/unit/libflake/local.mk delete mode 100644 tests/unit/libstore-support/local.mk delete mode 100644 tests/unit/libstore/local.mk delete mode 100644 tests/unit/libutil-support/local.mk delete mode 100644 tests/unit/libutil/local.mk diff --git a/Makefile b/Makefile index dbf510a3e..b51ae6cc7 100644 --- a/Makefile +++ b/Makefile @@ -38,18 +38,6 @@ makefiles += \ endif endif -ifeq ($(ENABLE_UNIT_TESTS), yes) -makefiles += \ - tests/unit/libutil/local.mk \ - tests/unit/libutil-support/local.mk \ - tests/unit/libstore/local.mk \ - tests/unit/libstore-support/local.mk \ - tests/unit/libfetchers/local.mk \ - tests/unit/libexpr/local.mk \ - tests/unit/libexpr-support/local.mk \ - tests/unit/libflake/local.mk -endif - ifeq ($(ENABLE_FUNCTIONAL_TESTS), yes) ifdef HOST_UNIX makefiles += \ @@ -104,13 +92,6 @@ include mk/lib.mk # These must be defined after `mk/lib.mk`. Otherwise the first rule # incorrectly becomes the default target. -ifneq ($(ENABLE_UNIT_TESTS), yes) -.PHONY: check -check: - @echo "Unit tests are disabled. Configure without '--disable-unit-tests', or avoid calling 'make check'." - @exit 1 -endif - ifneq ($(ENABLE_FUNCTIONAL_TESTS), yes) .PHONY: installcheck installcheck: diff --git a/Makefile.config.in b/Makefile.config.in index 3100d2073..e131484f6 100644 --- a/Makefile.config.in +++ b/Makefile.config.in @@ -12,7 +12,6 @@ ENABLE_BUILD = @ENABLE_BUILD@ ENABLE_DOC_GEN = @ENABLE_DOC_GEN@ ENABLE_FUNCTIONAL_TESTS = @ENABLE_FUNCTIONAL_TESTS@ ENABLE_S3 = @ENABLE_S3@ -ENABLE_UNIT_TESTS = @ENABLE_UNIT_TESTS@ GTEST_LIBS = @GTEST_LIBS@ HAVE_LIBCPUID = @HAVE_LIBCPUID@ HAVE_SECCOMP = @HAVE_SECCOMP@ diff --git a/configure.ac b/configure.ac index 5c22ed176..18d718c07 100644 --- a/configure.ac +++ b/configure.ac @@ -141,18 +141,6 @@ AC_ARG_ENABLE(build, AS_HELP_STRING([--disable-build],[Do not build nix]), ENABLE_BUILD=$enableval, ENABLE_BUILD=yes) AC_SUBST(ENABLE_BUILD) -# Building without unit tests is useful for bootstrapping with a smaller footprint -# or running the tests in a separate derivation. Otherwise, we do compile and -# run them. - -AC_ARG_ENABLE(unit-tests, AS_HELP_STRING([--disable-unit-tests],[Do not build the tests]), - ENABLE_UNIT_TESTS=$enableval, ENABLE_UNIT_TESTS=$ENABLE_BUILD) -AC_SUBST(ENABLE_UNIT_TESTS) - -AS_IF( - [test "$ENABLE_BUILD" == "no" && test "$ENABLE_UNIT_TESTS" == "yes"], - [AC_MSG_ERROR([Cannot enable unit tests when building overall is disabled. Please do not pass '--enable-unit-tests' or do not pass '--disable-build'.])]) - AC_ARG_ENABLE(functional-tests, AS_HELP_STRING([--disable-functional-tests],[Do not build the tests]), ENABLE_FUNCTIONAL_TESTS=$enableval, ENABLE_FUNCTIONAL_TESTS=yes) AC_SUBST(ENABLE_FUNCTIONAL_TESTS) @@ -358,16 +346,6 @@ if test "$gc" = yes; then CFLAGS="$old_CFLAGS" fi -AS_IF([test "$ENABLE_UNIT_TESTS" == "yes"],[ - -# Look for gtest. -PKG_CHECK_MODULES([GTEST], [gtest_main gmock_main]) - -# Look for rapidcheck. -PKG_CHECK_MODULES([RAPIDCHECK], [rapidcheck rapidcheck_gtest]) - -]) - # Look for nlohmann/json. PKG_CHECK_MODULES([NLOHMANN_JSON], [nlohmann_json >= 3.9]) diff --git a/package.nix b/package.nix index d41748b7c..c0d04179d 100644 --- a/package.nix +++ b/package.nix @@ -53,10 +53,6 @@ # Whether to build Nix. Useful to skip for tasks like testing existing pre-built versions of Nix , doBuild ? true -# Run the unit tests as part of the build. See `installUnitTests` for an -# alternative to this. -, doCheck ? __forDefaults.canRunInstalled - # Run the functional tests as part of the build. , doInstallCheck ? test-client != null || __forDefaults.canRunInstalled @@ -89,11 +85,6 @@ # - readline , readlineFlavor ? if stdenv.hostPlatform.isWindows then "readline" else "editline" -# Whether to install unit tests. This is useful when cross compiling -# since we cannot run them natively during the build, but can do so -# later. -, installUnitTests ? doBuild && !__forDefaults.canExecuteHost - # For running the functional tests against a pre-built Nix. Probably # want to use in conjunction with `doBuild = false;`. , test-daemon ? null @@ -117,7 +108,7 @@ let # things which should instead be gotten via `finalAttrs` in order to # work with overriding. attrs = { - inherit doBuild doCheck doInstallCheck; + inherit doBuild doInstallCheck; }; mkDerivation = @@ -133,16 +124,11 @@ in mkDerivation (finalAttrs: let inherit (finalAttrs) - doCheck doInstallCheck ; doBuild = !finalAttrs.dontBuild; - # Either running the unit tests during the build, or installing them - # to be run later, requiresthe unit tests to be built. - buildUnitTests = doCheck || installUnitTests; - in { inherit pname version; @@ -176,8 +162,6 @@ in { ./scripts/local.mk ] ++ lib.optionals enableManual [ ./doc/manual - ] ++ lib.optionals buildUnitTests [ - ./tests/unit ] ++ lib.optionals doInstallCheck [ ./tests/functional ])); @@ -190,8 +174,6 @@ in { # If we are doing just build or just docs, the one thing will use # "out". We only need additional outputs if we are doing both. ++ lib.optional (doBuild && enableManual) "doc" - ++ lib.optional installUnitTests "check" - ++ lib.optional doCheck "testresults" ; nativeBuildInputs = [ @@ -230,9 +212,6 @@ in { ({ inherit readline editline; }.${readlineFlavor}) ] ++ lib.optionals enableMarkdown [ lowdown - ] ++ lib.optionals buildUnitTests [ - gtest - rapidcheck ] ++ lib.optional stdenv.isLinux libseccomp ++ lib.optional stdenv.hostPlatform.isx86_64 libcpuid # There have been issues building these dependencies @@ -247,22 +226,16 @@ in { ); dontBuild = !attrs.doBuild; - doCheck = attrs.doCheck; configureFlags = [ (lib.enableFeature doBuild "build") - (lib.enableFeature buildUnitTests "unit-tests") (lib.enableFeature doInstallCheck "functional-tests") (lib.enableFeature enableManual "doc-gen") (lib.enableFeature enableGC "gc") (lib.enableFeature enableMarkdown "markdown") - (lib.enableFeature installUnitTests "install-unit-tests") (lib.withFeatureAs true "readline-flavor" readlineFlavor) ] ++ lib.optionals (!forDevShell) [ "--sysconfdir=/etc" - ] ++ lib.optionals installUnitTests [ - "--with-check-bin-dir=${builtins.placeholder "check"}/bin" - "--with-check-lib-dir=${builtins.placeholder "check"}/lib" ] ++ lib.optionals (doBuild) [ "--with-boost=${boost}/lib" ] ++ lib.optionals (doBuild && stdenv.isLinux) [ @@ -343,10 +316,6 @@ in { platforms = lib.platforms.unix ++ lib.platforms.windows; mainProgram = "nix"; broken = !(lib.all (a: a) [ - # We cannot run or install unit tests if we don't build them or - # Nix proper (which they depend on). - (installUnitTests -> doBuild) - (doCheck -> doBuild) # The build process for the manual currently requires extracting # data from the Nix executable we are trying to document. (enableManual -> doBuild) diff --git a/tests/unit/libexpr-support/local.mk b/tests/unit/libexpr-support/local.mk deleted file mode 100644 index 0501de33c..000000000 --- a/tests/unit/libexpr-support/local.mk +++ /dev/null @@ -1,23 +0,0 @@ -libraries += libexpr-test-support - -libexpr-test-support_NAME = libnixexpr-test-support - -libexpr-test-support_DIR := $(d) - -ifeq ($(INSTALL_UNIT_TESTS), yes) - libexpr-test-support_INSTALL_DIR := $(checklibdir) -else - libexpr-test-support_INSTALL_DIR := -endif - -libexpr-test-support_SOURCES := \ - $(wildcard $(d)/tests/*.cc) \ - $(wildcard $(d)/tests/value/*.cc) - -libexpr-test-support_CXXFLAGS += $(libexpr-tests_EXTRA_INCLUDES) - -libexpr-test-support_LIBS = \ - libstore-test-support libutil-test-support \ - libexpr libstore libutil - -libexpr-test-support_LDFLAGS := $(THREAD_LDFLAGS) -lrapidcheck diff --git a/tests/unit/libexpr/local.mk b/tests/unit/libexpr/local.mk deleted file mode 100644 index 1617e2823..000000000 --- a/tests/unit/libexpr/local.mk +++ /dev/null @@ -1,45 +0,0 @@ -check: libexpr-tests_RUN - -programs += libexpr-tests - -libexpr-tests_NAME := libnixexpr-tests - -libexpr-tests_ENV := _NIX_TEST_UNIT_DATA=$(d)/data GTEST_OUTPUT=xml:$$testresults/libexpr-tests.xml - -libexpr-tests_DIR := $(d) - -ifeq ($(INSTALL_UNIT_TESTS), yes) - libexpr-tests_INSTALL_DIR := $(checkbindir) -else - libexpr-tests_INSTALL_DIR := -endif - -libexpr-tests_SOURCES := \ - $(wildcard $(d)/*.cc) \ - $(wildcard $(d)/value/*.cc) \ - $(wildcard $(d)/flake/*.cc) - -libexpr-tests_EXTRA_INCLUDES = \ - -I tests/unit/libexpr-support \ - -I tests/unit/libstore-support \ - -I tests/unit/libutil-support \ - $(INCLUDE_libexpr) \ - $(INCLUDE_libexprc) \ - $(INCLUDE_libfetchers) \ - $(INCLUDE_libstore) \ - $(INCLUDE_libstorec) \ - $(INCLUDE_libutil) \ - $(INCLUDE_libutilc) - -libexpr-tests_CXXFLAGS += $(libexpr-tests_EXTRA_INCLUDES) - -libexpr-tests_LIBS = \ - libexpr-test-support libstore-test-support libutil-test-support \ - libexpr libexprc libfetchers libstore libstorec libutil libutilc - -libexpr-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) -lgmock - -ifdef HOST_WINDOWS - # Increase the default reserved stack size to 65 MB so Nix doesn't run out of space - libexpr-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024))) -endif diff --git a/tests/unit/libfetchers/local.mk b/tests/unit/libfetchers/local.mk deleted file mode 100644 index 30aa142a5..000000000 --- a/tests/unit/libfetchers/local.mk +++ /dev/null @@ -1,37 +0,0 @@ -check: libfetchers-tests_RUN - -programs += libfetchers-tests - -libfetchers-tests_NAME = libnixfetchers-tests - -libfetchers-tests_ENV := _NIX_TEST_UNIT_DATA=$(d)/data GTEST_OUTPUT=xml:$$testresults/libfetchers-tests.xml - -libfetchers-tests_DIR := $(d) - -ifeq ($(INSTALL_UNIT_TESTS), yes) - libfetchers-tests_INSTALL_DIR := $(checkbindir) -else - libfetchers-tests_INSTALL_DIR := -endif - -libfetchers-tests_SOURCES := $(wildcard $(d)/*.cc) - -libfetchers-tests_EXTRA_INCLUDES = \ - -I tests/unit/libstore-support \ - -I tests/unit/libutil-support \ - $(INCLUDE_libfetchers) \ - $(INCLUDE_libstore) \ - $(INCLUDE_libutil) - -libfetchers-tests_CXXFLAGS += $(libfetchers-tests_EXTRA_INCLUDES) - -libfetchers-tests_LIBS = \ - libstore-test-support libutil-test-support \ - libfetchers libstore libutil - -libfetchers-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) $(LIBGIT2_LIBS) - -ifdef HOST_WINDOWS - # Increase the default reserved stack size to 65 MB so Nix doesn't run out of space - libfetchers-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024))) -endif diff --git a/tests/unit/libflake/local.mk b/tests/unit/libflake/local.mk deleted file mode 100644 index 590bcf7c0..000000000 --- a/tests/unit/libflake/local.mk +++ /dev/null @@ -1,43 +0,0 @@ -check: libflake-tests_RUN - -programs += libflake-tests - -libflake-tests_NAME := libnixflake-tests - -libflake-tests_ENV := _NIX_TEST_UNIT_DATA=$(d)/data GTEST_OUTPUT=xml:$$testresults/libflake-tests.xml - -libflake-tests_DIR := $(d) - -ifeq ($(INSTALL_UNIT_TESTS), yes) - libflake-tests_INSTALL_DIR := $(checkbindir) -else - libflake-tests_INSTALL_DIR := -endif - -libflake-tests_SOURCES := \ - $(wildcard $(d)/*.cc) \ - $(wildcard $(d)/value/*.cc) \ - $(wildcard $(d)/flake/*.cc) - -libflake-tests_EXTRA_INCLUDES = \ - -I tests/unit/libflake-support \ - -I tests/unit/libstore-support \ - -I tests/unit/libutil-support \ - $(INCLUDE_libflake) \ - $(INCLUDE_libexpr) \ - $(INCLUDE_libfetchers) \ - $(INCLUDE_libstore) \ - $(INCLUDE_libutil) \ - -libflake-tests_CXXFLAGS += $(libflake-tests_EXTRA_INCLUDES) - -libflake-tests_LIBS = \ - libexpr-test-support libstore-test-support libutil-test-support \ - libflake libexpr libfetchers libstore libutil - -libflake-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) -lgmock - -ifdef HOST_WINDOWS - # Increase the default reserved stack size to 65 MB so Nix doesn't run out of space - libflake-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024))) -endif diff --git a/tests/unit/libstore-support/local.mk b/tests/unit/libstore-support/local.mk deleted file mode 100644 index 56dedd825..000000000 --- a/tests/unit/libstore-support/local.mk +++ /dev/null @@ -1,21 +0,0 @@ -libraries += libstore-test-support - -libstore-test-support_NAME = libnixstore-test-support - -libstore-test-support_DIR := $(d) - -ifeq ($(INSTALL_UNIT_TESTS), yes) - libstore-test-support_INSTALL_DIR := $(checklibdir) -else - libstore-test-support_INSTALL_DIR := -endif - -libstore-test-support_SOURCES := $(wildcard $(d)/tests/*.cc) - -libstore-test-support_CXXFLAGS += $(libstore-tests_EXTRA_INCLUDES) - -libstore-test-support_LIBS = \ - libutil-test-support \ - libstore libutil - -libstore-test-support_LDFLAGS := $(THREAD_LDFLAGS) -lrapidcheck diff --git a/tests/unit/libstore/local.mk b/tests/unit/libstore/local.mk deleted file mode 100644 index 8d3d6b0af..000000000 --- a/tests/unit/libstore/local.mk +++ /dev/null @@ -1,38 +0,0 @@ -check: libstore-tests_RUN - -programs += libstore-tests - -libstore-tests_NAME = libnixstore-tests - -libstore-tests_ENV := _NIX_TEST_UNIT_DATA=$(d)/data GTEST_OUTPUT=xml:$$testresults/libstore-tests.xml - -libstore-tests_DIR := $(d) - -ifeq ($(INSTALL_UNIT_TESTS), yes) - libstore-tests_INSTALL_DIR := $(checkbindir) -else - libstore-tests_INSTALL_DIR := -endif - -libstore-tests_SOURCES := $(wildcard $(d)/*.cc) - -libstore-tests_EXTRA_INCLUDES = \ - -I tests/unit/libstore-support \ - -I tests/unit/libutil-support \ - $(INCLUDE_libstore) \ - $(INCLUDE_libstorec) \ - $(INCLUDE_libutil) \ - $(INCLUDE_libutilc) - -libstore-tests_CXXFLAGS += $(libstore-tests_EXTRA_INCLUDES) - -libstore-tests_LIBS = \ - libstore-test-support libutil-test-support \ - libstore libstorec libutil libutilc - -libstore-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) - -ifdef HOST_WINDOWS - # Increase the default reserved stack size to 65 MB so Nix doesn't run out of space - libstore-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024))) -endif diff --git a/tests/unit/libutil-support/local.mk b/tests/unit/libutil-support/local.mk deleted file mode 100644 index 5f7835c9f..000000000 --- a/tests/unit/libutil-support/local.mk +++ /dev/null @@ -1,19 +0,0 @@ -libraries += libutil-test-support - -libutil-test-support_NAME = libnixutil-test-support - -libutil-test-support_DIR := $(d) - -ifeq ($(INSTALL_UNIT_TESTS), yes) - libutil-test-support_INSTALL_DIR := $(checklibdir) -else - libutil-test-support_INSTALL_DIR := -endif - -libutil-test-support_SOURCES := $(wildcard $(d)/tests/*.cc) - -libutil-test-support_CXXFLAGS += $(libutil-tests_EXTRA_INCLUDES) - -libutil-test-support_LIBS = libutil - -libutil-test-support_LDFLAGS := $(THREAD_LDFLAGS) -lrapidcheck diff --git a/tests/unit/libutil/local.mk b/tests/unit/libutil/local.mk deleted file mode 100644 index 404f35cf1..000000000 --- a/tests/unit/libutil/local.mk +++ /dev/null @@ -1,37 +0,0 @@ -check: libutil-tests_RUN - -programs += libutil-tests - -libutil-tests_NAME = libnixutil-tests - -libutil-tests_ENV := _NIX_TEST_UNIT_DATA=$(d)/data GTEST_OUTPUT=xml:$$testresults/libutil-tests.xml - -libutil-tests_DIR := $(d) - -ifeq ($(INSTALL_UNIT_TESTS), yes) - libutil-tests_INSTALL_DIR := $(checkbindir) -else - libutil-tests_INSTALL_DIR := -endif - -libutil-tests_SOURCES := $(wildcard $(d)/*.cc) - -libutil-tests_EXTRA_INCLUDES = \ - -I tests/unit/libutil-support \ - $(INCLUDE_libutil) \ - $(INCLUDE_libutilc) - -libutil-tests_CXXFLAGS += $(libutil-tests_EXTRA_INCLUDES) - -libutil-tests_LIBS = libutil-test-support libutil libutilc - -libutil-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) - -ifdef HOST_WINDOWS - # Increase the default reserved stack size to 65 MB so Nix doesn't run out of space - libutil-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024))) -endif - -check: $(d)/data/git/check-data.sh.test - -$(eval $(call run-test,$(d)/data/git/check-data.sh)) From b41cc1a7555e59d5753bf4f8cbbfa9137107d2fe Mon Sep 17 00:00:00 2001 From: John Ericson Date: Wed, 14 Aug 2024 16:04:35 -0400 Subject: [PATCH 069/718] Make wrapper derivation This ensures just `nix build`-ing the flake doesn't forget to run all tests. One can still specifiy specific attributes to just build one thing. Co-authored-by: Robert Hensing --- .github/workflows/ci.yml | 14 ------ flake.nix | 51 ++++++++++++++------ packaging/components.nix | 6 ++- packaging/everything.nix | 93 ++++++++++++++++++++++++++++++++++++ packaging/hydra.nix | 5 +- tests/functional/package.nix | 6 +-- tests/nixos/quick-build.nix | 6 +-- 7 files changed, 142 insertions(+), 39 deletions(-) create mode 100644 packaging/everything.nix diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4eb9cf10d..9831d0e0e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -195,20 +195,6 @@ jobs: - uses: DeterminateSystems/magic-nix-cache-action@main - run: nix build -L .#hydraJobs.tests.githubFlakes .#hydraJobs.tests.tarballFlakes .#hydraJobs.tests.functional_user - meson_build: - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, macos-latest] - runs-on: ${{ matrix.os }} - steps: - - uses: actions/checkout@v4 - - uses: DeterminateSystems/nix-installer-action@main - - uses: DeterminateSystems/magic-nix-cache-action@main - # Only meson packages that don't have a tests.run derivation. - # Those that have it are already built and tested as part of nix flake check. - - run: nix build -L .#hydraJobs.build.{nix-cmd,nix-main}.$(nix-instantiate --eval --expr builtins.currentSystem | sed -e 's/"//g') - flake_regressions: needs: vm_tests runs-on: ubuntu-22.04 diff --git a/flake.nix b/flake.nix index 22ca54118..cded6c3a9 100644 --- a/flake.nix +++ b/flake.nix @@ -139,11 +139,6 @@ nix = final.nixComponents.nix; - nix_noTests = final.nix.override { - doInstallCheck = false; - doCheck = false; - }; - # See https://github.com/NixOS/nixpkgs/pull/214409 # Remove when fixed in this flake's nixpkgs pre-commit = @@ -222,7 +217,7 @@ # for which we don't apply the full build matrix such as cross or static. inherit (nixpkgsFor.${system}.native) changelog-d; - default = self.packages.${system}.nix; + default = self.packages.${system}.nix-ng; nix-internal-api-docs = nixpkgsFor.${system}.native.nixComponents.nix-internal-api-docs; nix-external-api-docs = nixpkgsFor.${system}.native.nixComponents.nix-external-api-docs; } @@ -230,22 +225,48 @@ // flatMapAttrs { # Components we'll iterate over in the upcoming lambda "nix" = { }; - # Temporarily disabled because GitHub Actions OOM issues. Once - # the old build system is gone and we are back to one build - # system, we should reenable these. - #"nix-util" = { }; - #"nix-store" = { }; - #"nix-fetchers" = { }; + "nix-util" = { }; + "nix-util-c" = { }; + "nix-util-test-support" = { }; + "nix-util-tests" = { }; + + "nix-store" = { }; + "nix-store-c" = { }; + "nix-store-test-support" = { }; + "nix-store-tests" = { }; + + "nix-fetchers" = { }; + "nix-fetchers-tests" = { }; + + "nix-expr" = { }; + "nix-expr-c" = { }; + "nix-expr-test-support" = { }; + "nix-expr-tests" = { }; + + "nix-flake" = { }; + "nix-flake-tests" = { }; + + "nix-main" = { }; + "nix-main-c" = { }; + + "nix-cmd" = { }; + + "nix-cli" = { }; + + "nix-functional-tests" = { supportsCross = false; }; + + "nix-perl-bindings" = { supportsCross = false; }; + "nix-ng" = { }; } - (pkgName: {}: { + (pkgName: { supportsCross ? true }: { # These attributes go right into `packages.`. "${pkgName}" = nixpkgsFor.${system}.native.nixComponents.${pkgName}; "${pkgName}-static" = nixpkgsFor.${system}.static.nixComponents.${pkgName}; } - // flatMapAttrs (lib.genAttrs crossSystems (_: { })) (crossSystem: {}: { + // lib.optionalAttrs supportsCross (flatMapAttrs (lib.genAttrs crossSystems (_: { })) (crossSystem: {}: { # These attributes go right into `packages.`. "${pkgName}-${crossSystem}" = nixpkgsFor.${system}.cross.${crossSystem}.nixComponents.${pkgName}; - }) + })) // flatMapAttrs (lib.genAttrs stdenvs (_: { })) (stdenvName: {}: { # These attributes go right into `packages.`. "${pkgName}-${stdenvName}" = nixpkgsFor.${system}.stdenvs."${stdenvName}Packages".nixComponents.${pkgName}; diff --git a/packaging/components.nix b/packaging/components.nix index f14613e8a..5fc3236cf 100644 --- a/packaging/components.nix +++ b/packaging/components.nix @@ -56,8 +56,7 @@ in nix-cmd = callPackage ../src/libcmd/package.nix { }; - # Will replace `nix` once the old build system is gone. - nix-ng = callPackage ../src/nix/package.nix { version = fineVersion; }; + nix-cli = callPackage ../src/nix/package.nix { version = fineVersion; }; nix-functional-tests = callPackage ../src/nix-functional-tests/package.nix { version = fineVersion; }; @@ -65,4 +64,7 @@ in nix-external-api-docs = callPackage ../src/external-api-docs/package.nix { version = fineVersion; }; nix-perl-bindings = callPackage ../src/perl/package.nix { }; + + # Will replace `nix` once the old build system is gone. + nix-ng = callPackage ../packaging/everything.nix { }; } diff --git a/packaging/everything.nix b/packaging/everything.nix new file mode 100644 index 000000000..8c8ce6611 --- /dev/null +++ b/packaging/everything.nix @@ -0,0 +1,93 @@ +{ + lib, + stdenv, + buildEnv, + + nix-util, + nix-util-c, + nix-util-test-support, + nix-util-tests, + + nix-store, + nix-store-c, + nix-store-test-support, + nix-store-tests, + + nix-fetchers, + nix-fetchers-tests, + + nix-expr, + nix-expr-c, + nix-expr-test-support, + nix-expr-tests, + + nix-flake, + nix-flake-tests, + + nix-main, + nix-main-c, + + nix-cmd, + + nix-cli, + + nix-functional-tests, + + nix-internal-api-docs, + nix-external-api-docs, + + nix-perl-bindings, +}: + +(buildEnv rec { + name = "nix-${nix-cli.version}"; + paths = [ + nix-util + nix-util-c + nix-util-test-support + nix-util-tests + + nix-store + nix-store-c + nix-store-test-support + nix-store-tests + + nix-fetchers + nix-fetchers-tests + + nix-expr + nix-expr-c + nix-expr-test-support + nix-expr-tests + + nix-flake + nix-flake-tests + + nix-main + nix-main-c + + nix-cmd + + nix-cli + + nix-internal-api-docs + nix-external-api-docs + + ] ++ lib.optionals (stdenv.buildPlatform.canExecute stdenv.hostPlatform) [ + nix-perl-bindings + ]; +}).overrideAttrs (_: { + doCheck = true; + doInstallCheck = true; + + checkInputs = [ + # Actually run the unit tests too + nix-util-tests.tests.run + nix-store-tests.tests.run + nix-expr-tests.tests.run + nix-flake-tests.tests.run + ]; + installCheckInputs = [ + nix-functional-tests + ]; +}) diff --git a/packaging/hydra.nix b/packaging/hydra.nix index 46b4ff51d..65978835c 100644 --- a/packaging/hydra.nix +++ b/packaging/hydra.nix @@ -61,8 +61,9 @@ let "nix-main" "nix-main-c" "nix-cmd" - "nix-ng" + "nix-cli" "nix-functional-tests" + "nix-ng" ]; in { @@ -85,7 +86,7 @@ in self.packages.${system}.nix.override { enableGC = false; } ); - buildNoTests = forAllSystems (system: nixpkgsFor.${system}.native.nix_noTests); + buildNoTests = forAllSystems (system: nixpkgsFor.${system}.native.nixComponents.nix-cli); # Toggles some settings for better coverage. Windows needs these # library combinations, and Debian build Nix with GNU readline too. diff --git a/tests/functional/package.nix b/tests/functional/package.nix index 205b03614..277711123 100644 --- a/tests/functional/package.nix +++ b/tests/functional/package.nix @@ -15,7 +15,7 @@ , nix-store , nix-expr -, nix-ng +, nix-cli , rapidcheck , gtest @@ -67,7 +67,7 @@ mkMesonDerivation (finalAttrs: { ]; nativeBuildInputs = finalAttrs.passthru.baseNativeBuildInputs ++ [ - nix-ng + nix-cli ]; buildInputs = [ @@ -105,7 +105,7 @@ mkMesonDerivation (finalAttrs: { doCheck = true; installPhase = '' - touch $out + mkdir $out ''; meta = { diff --git a/tests/nixos/quick-build.nix b/tests/nixos/quick-build.nix index 37169b4e2..57e3b9cdb 100644 --- a/tests/nixos/quick-build.nix +++ b/tests/nixos/quick-build.nix @@ -27,13 +27,13 @@ in }; config = { - passthru.quickBuild = + passthru.quickBuild = let withQuickBuild = extendModules { modules = [{ quickBuild = true; }]; }; in withQuickBuild.config.test; defaults = { pkgs, ... }: { config = lib.mkIf test.config.quickBuild { - nix.package = pkgs.nix_noTests; + nix.package = pkgs.nixComponents.nix-cli; system.forbiddenDependenciesRegexes = [ # This would indicate that the quickBuild feature is broken. @@ -44,4 +44,4 @@ in }; }; }; -} \ No newline at end of file +} From 0fabb348baf923bc10a61bc0dc3315023cba9588 Mon Sep 17 00:00:00 2001 From: "Travis A. Everett" Date: Thu, 18 Jul 2024 09:56:57 -0500 Subject: [PATCH 070/718] add script to migrate macOS 15 Sequoia nixbld UIDs While we don't have any easy way to forcibly notify everyone about the impending breakage (or forcibly migrate the users on their system), this script enables those who do hear about the problem to migrate their systems before they take the macOS update. It should also enable people who only discover it after the update when a build fails to ~fix their installs without a full reinstall. --- scripts/bigsur-nixbld-user-migration.sh | 4 +- scripts/sequoia-nixbld-user-migration.sh | 161 ++++++++++++++++++++--- 2 files changed, 146 insertions(+), 19 deletions(-) mode change 100644 => 100755 scripts/sequoia-nixbld-user-migration.sh diff --git a/scripts/bigsur-nixbld-user-migration.sh b/scripts/bigsur-nixbld-user-migration.sh index 0eb312e07..a2e2f30f0 100755 --- a/scripts/bigsur-nixbld-user-migration.sh +++ b/scripts/bigsur-nixbld-user-migration.sh @@ -2,7 +2,7 @@ ((NEW_NIX_FIRST_BUILD_UID=301)) -id_available(){ +id_unavailable(){ dscl . list /Users UniqueID | grep -E '\b'"$1"'\b' >/dev/null } @@ -15,7 +15,7 @@ change_nixbld_names_and_ids(){ while read -r name uid; do echo " Checking $name (uid: $uid)" # iterate for a clean ID - while id_available "$next_id"; do + while id_unavailable "$next_id"; do ((next_id++)) if ((next_id >= 400)); then echo "We've hit UID 400 without placing all of your users :(" diff --git a/scripts/sequoia-nixbld-user-migration.sh b/scripts/sequoia-nixbld-user-migration.sh old mode 100644 new mode 100755 index 778a95688..9208a3605 --- a/scripts/sequoia-nixbld-user-migration.sh +++ b/scripts/sequoia-nixbld-user-migration.sh @@ -1,36 +1,163 @@ #!/usr/bin/env bash -((NEW_NIX_FIRST_BUILD_UID=331)) +set -x -id_available(){ +((NEW_NIX_FIRST_BUILD_UID=350)) +((TEMP_NIX_FIRST_BUILD_UID=31000)) + +nix_user_n() { + printf "_nixbld%d" "$1" +} + +id_unavailable(){ dscl . list /Users UniqueID | grep -E '\b'"$1"'\b' >/dev/null } -change_nixbld_names_and_ids(){ - local name uid next_id - ((next_id=NEW_NIX_FIRST_BUILD_UID)) - echo "Attempting to migrate _nixbld users." - echo "Each _nixbld# user should have its UID moved to $next_id+" +any_nixbld(){ + dscl . list /Users UniqueID | grep -E '\b_nixbld' >/dev/null +} + +re_create_nixbld_user(){ + local name uid + + name="$1" + uid="$2" + + sudo /usr/bin/dscl . -create "/Users/$name" "UniqueID" "$uid" + sudo /usr/bin/dscl . -create "/Users/$name" "IsHidden" "1" + sudo /usr/bin/dscl . -create "/Users/$name" "NFSHomeDirectory" "/var/empty" + sudo /usr/bin/dscl . -create "/Users/$name" "RealName" "Nix build user $name" + sudo /usr/bin/dscl . -create "/Users/$name" "UserShell" "/sbin/nologin" + sudo /usr/bin/dscl . -create "/Users/$name" "PrimaryGroupID" "30001" +} + +hit_id_cap(){ + echo "We've hit UID 400 without placing all of your users :(" + echo "You should use the commands in this script as a starting" + echo "point to review your UID-space and manually move the" + echo "remaining users (or delete them, if you don't need them)." +} + +# evacuate the role-uid space to simplify final placement logic +temporarily_move_existing_nixbld_uids(){ + local name uid next_id user_n + + ((next_id=TEMP_NIX_FIRST_BUILD_UID)) + + echo "" + echo "Step 1: move existing _nixbld users out of the destination UID range." + while read -r name uid; do - echo " Checking $name (uid: $uid)" # iterate for a clean ID - while id_available "$next_id"; do + while id_unavailable "$next_id"; do ((next_id++)) - if ((next_id >= 400)); then - echo "We've hit UID 400 without placing all of your users :(" + # We really want to get these all placed, but I guess there's + # some risk we iterate forever--so we'll give up after 9k uids. + if ((next_id >= 40000)); then + echo "We've hit UID 40000 without temporarily placing all of your users :(" echo "You should use the commands in this script as a starting" echo "point to review your UID-space and manually move the" - echo "remaining users (or delete them, if you don't need them)." + echo "remaining users to any open UID over 1000." + exit 1 + fi + done + sudo dscl . -create "/Users/$name" UniqueID "$next_id" + echo " Temporarily moved $name from uid $uid -> $next_id" + + done < <(dscl . list /Users UniqueID | grep _nixbld | sort -n -k2) +} + +change_nixbld_uids(){ + local name next_id user_n + + ((next_id=NEW_NIX_FIRST_BUILD_UID)) + ((user_n=1)) + name="$(nix_user_n "$user_n")" + + # we know that we have *some* nixbld users, but macOS may have + # already clobbered the first few users if this system has been + # upgraded + + echo "" + echo "Step 2: re-create missing early _nixbld# users." + + until dscl . read "/Users/$name" &>/dev/null; do + # iterate for a clean ID + while id_unavailable "$next_id"; do + ((next_id++)) + if ((next_id >= 400)); then + hit_id_cap exit 1 fi done - # first 2 are cleanup, it's OK if they aren't here - sudo dscl . delete "/Users/$name" dsAttrTypeNative:_writers_passwd &>/dev/null || true - sudo dscl . change "/Users/$name" NFSHomeDirectory "/private/var/empty 1" "/var/empty" &>/dev/null || true - sudo dscl . change "/Users/$name" UniqueID "$uid" "$next_id" + re_create_nixbld_user "$name" "$next_id" + echo " $name was missing; created with uid: $next_id" + + ((user_n++)) + name="$(nix_user_n "$user_n")" + done + + echo "" + echo "Step 3: relocate remaining _nixbld# UIDs to $next_id+" + + # start at first _nixbld# not re-created above and increment + # until _nixbld doesn't exist + while dscl . read "/Users/$name" &>/dev/null; do + # iterate for a clean ID + while id_unavailable "$next_id"; do + ((next_id++)) + if ((next_id >= 400)); then + hit_id_cap + exit 1 + fi + done + + sudo dscl . -create "/Users/$name" UniqueID "$next_id" echo " $name migrated to uid: $next_id" + + ((user_n++)) + name="$(nix_user_n "$user_n")" + done + + if ((user_n == 1)); then + echo "Didn't find _nixbld1. Perhaps you have single-user Nix?" + exit 1 + else + echo "Migrated $((user_n - 1)) users. If you want to double-check, try:" + echo "dscl . list /Users UniqueID | grep _nixbld | sort -n -k2" + fi +} +needs_migration(){ + local name uid next_id user_n + + ((next_id=NEW_NIX_FIRST_BUILD_UID)) + ((user_n=1)) + + while read -r name uid; do + expected_name="$(nix_user_n "$user_n")" + if [[ "$expected_name" != "$name" ]]; then + return 0 + fi + if [[ "$next_id" != "$uid" ]]; then + return 0 + fi + ((next_id++)) + ((user_n++)) done < <(dscl . list /Users UniqueID | grep _nixbld | sort -n -k2) + return 1 } -change_nixbld_names_and_ids + +if any_nixbld; then + if needs_migration; then + echo "Attempting to migrate _nixbld users." + temporarily_move_existing_nixbld_uids + change_nixbld_uids + else + echo "_nixbld users already appear to be migrated." + fi +else + echo "Didn't find any _nixbld users. Perhaps you have single-user Nix?" + exit 1 +fi From 6068e32aa790fc53e7123d8442282714af45770b Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Thu, 15 Aug 2024 11:36:44 +0200 Subject: [PATCH 071/718] refactor: Extract EvalState::addCallDepth --- src/libexpr/eval-inline.hh | 8 ++++++++ src/libexpr/eval.cc | 19 +------------------ src/libexpr/eval.hh | 20 ++++++++++++++++++++ 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/libexpr/eval-inline.hh b/src/libexpr/eval-inline.hh index 6fa34b062..d5ce238b2 100644 --- a/src/libexpr/eval-inline.hh +++ b/src/libexpr/eval-inline.hh @@ -4,6 +4,7 @@ #include "print.hh" #include "eval.hh" #include "eval-error.hh" +#include "eval-settings.hh" namespace nix { @@ -138,5 +139,12 @@ inline void EvalState::forceList(Value & v, const PosIdx pos, std::string_view e } } +[[gnu::always_inline]] +inline CallDepth EvalState::addCallDepth(const PosIdx pos) { + if (callDepth > settings.maxCallDepth) + error("stack overflow; max-call-depth exceeded").atPos(pos).debugThrow(); + + return CallDepth(callDepth); +}; } diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index c9101678c..0e70ca262 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -1471,26 +1471,9 @@ void ExprLambda::eval(EvalState & state, Env & env, Value & v) v.mkLambda(&env, this); } -namespace { -/** Increments a count on construction and decrements on destruction. - */ -class CallDepth { - size_t & count; -public: - CallDepth(size_t & count) : count(count) { - ++count; - } - ~CallDepth() { - --count; - } -}; -}; - void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value & vRes, const PosIdx pos) { - if (callDepth > settings.maxCallDepth) - error("stack overflow; max-call-depth exceeded").atPos(pos).debugThrow(); - CallDepth _level(callDepth); + auto _level = addCallDepth(pos); auto trace = settings.traceFunctionCalls ? std::make_unique(positions[pos]) diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index ddf5dcf94..9fd31e904 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -41,6 +41,21 @@ namespace eval_cache { class EvalCache; } +/** + * Increments a count on construction and decrements on destruction. + */ +class CallDepth { + size_t & count; + +public: + CallDepth(size_t & count) : count(count) { + ++count; + } + ~CallDepth() { + --count; + } +}; + /** * Function that implements a primop. */ @@ -649,6 +664,11 @@ private: public: + /** + * Check that the call depth is within limits, and increment it, until the returned object is destroyed. + */ + inline CallDepth addCallDepth(const PosIdx pos); + /** * Do a deep equality test between two values. That is, list * elements and attributes are compared recursively. From 72a4d1f52d46f1472b79a04d3af2dee194f13d52 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Thu, 15 Aug 2024 12:29:59 +0200 Subject: [PATCH 072/718] Add :doc support for __functor --- src/libexpr/eval.cc | 14 +++ src/libexpr/eval.hh | 6 ++ tests/functional/repl/doc-functor.expected | 101 +++++++++++++++++++++ tests/functional/repl/doc-functor.in | 10 ++ tests/functional/repl/doc-functor.nix | 101 +++++++++++++++++++++ 5 files changed, 232 insertions(+) create mode 100644 tests/functional/repl/doc-functor.expected create mode 100644 tests/functional/repl/doc-functor.in create mode 100644 tests/functional/repl/doc-functor.nix diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 0e70ca262..b87d96be0 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -616,6 +616,20 @@ std::optional EvalState::getDoc(Value & v) strdup(ss.data()), }; } + if (isFunctor(v)) { + try { + Value & functor = *v.attrs()->find(sFunctor)->value; + Value * vp = &v; + Value partiallyApplied; + callFunction(functor, 1, &vp, partiallyApplied, noPos); + auto _level = addCallDepth(noPos); + return getDoc(partiallyApplied); + } + catch (Error & e) { + e.addTrace(nullptr, "while partially calling '%1%' to retrieve documentation", "__functor"); + throw; + } + } return {}; } diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 9fd31e904..da9dd2087 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -640,6 +640,12 @@ public: const char * doc; }; + /** + * Retrieve the documentation for a value. This will evaluate the value if + * it is a thunk, and it will partially apply __functor if applicable. + * + * @param v The value to get the documentation for. + */ std::optional getDoc(Value & v); private: diff --git a/tests/functional/repl/doc-functor.expected b/tests/functional/repl/doc-functor.expected new file mode 100644 index 000000000..8cb2706ef --- /dev/null +++ b/tests/functional/repl/doc-functor.expected @@ -0,0 +1,101 @@ +Nix +Type :? for help. + +nix-repl> :l doc-functor.nix +Added variables. + +nix-repl> :doc multiplier +Function `__functor`\ + … defined at /path/to/tests/functional/repl/doc-functor.nix:12:23 + + +Multiply the argument by the factor stored in the factor attribute. + +nix-repl> :doc doubler +Function `multiply`\ + … defined at /path/to/tests/functional/repl/doc-functor.nix:5:17 + + +Look, it's just like a function! + +nix-repl> :doc recursive +Function `__functor`\ + … defined at /path/to/tests/functional/repl/doc-functor.nix:77:23 + + +This looks bad, but the docs are ok because of the eta expansion. + +nix-repl> :doc recursive2 +error: + … while partially calling '__functor' to retrieve documentation + + … while calling '__functor' + at /path/to/tests/functional/repl/doc-functor.nix:85:17: + 84| */ + 85| __functor = self: self.__functor self; + | ^ + 86| }; + + … from call site + at /path/to/tests/functional/repl/doc-functor.nix:85:23: + 84| */ + 85| __functor = self: self.__functor self; + | ^ + 86| }; + + (19999 duplicate frames omitted) + + error: stack overflow; max-call-depth exceeded + at /path/to/tests/functional/repl/doc-functor.nix:85:23: + 84| */ + 85| __functor = self: self.__functor self; + | ^ + 86| }; + +nix-repl> :doc diverging +error: + … while partially calling '__functor' to retrieve documentation + + (10000 duplicate frames omitted) + + … while calling '__functor' + at /path/to/tests/functional/repl/doc-functor.nix:97:19: + 96| f = x: { + 97| __functor = self: (f (x + 1)); + | ^ + 98| }; + + error: stack overflow; max-call-depth exceeded + at /path/to/tests/functional/repl/doc-functor.nix:97:26: + 96| f = x: { + 97| __functor = self: (f (x + 1)); + | ^ + 98| }; + +nix-repl> :doc helper +Function `square`\ + … defined at /path/to/tests/functional/repl/doc-functor.nix:36:12 + + +Compute x^2 + +nix-repl> :doc helper2 +Function `__functor`\ + … defined at /path/to/tests/functional/repl/doc-functor.nix:45:23 + + +This is a function that can be overridden. + +nix-repl> :doc lib.helper3 +Function `__functor`\ + … defined at /path/to/tests/functional/repl/doc-functor.nix:45:23 + + +This is a function that can be overridden. + +nix-repl> :doc helper3 +Function `__functor`\ + … defined at /path/to/tests/functional/repl/doc-functor.nix:45:23 + + +This is a function that can be overridden. diff --git a/tests/functional/repl/doc-functor.in b/tests/functional/repl/doc-functor.in new file mode 100644 index 000000000..d2bb57a02 --- /dev/null +++ b/tests/functional/repl/doc-functor.in @@ -0,0 +1,10 @@ +:l doc-functor.nix +:doc multiplier +:doc doubler +:doc recursive +:doc recursive2 +:doc diverging +:doc helper +:doc helper2 +:doc lib.helper3 +:doc helper3 diff --git a/tests/functional/repl/doc-functor.nix b/tests/functional/repl/doc-functor.nix new file mode 100644 index 000000000..f526f453f --- /dev/null +++ b/tests/functional/repl/doc-functor.nix @@ -0,0 +1,101 @@ +rec { + /** + Look, it's just like a function! + */ + multiply = p: q: p * q; + + multiplier = { + factor = 2; + /** + Multiply the argument by the factor stored in the factor attribute. + */ + __functor = self: x: x * self.factor; + }; + + doubler = { + description = "bla"; + /** + Multiply by two. This doc probably won't be rendered because the + returned partial application won't have any reference to this location; + only pointing to the second lambda in the multiply function. + */ + __functor = self: multiply 2; + }; + + makeOverridable = f: { + /** + This is a function that can be overridden. + */ + __functor = self: f; + override = throw "not implemented"; + }; + + /** + Compute x^2 + */ + square = x: x * x; + + helper = makeOverridable square; + + # Somewhat analogous to the Nixpkgs makeOverridable function. + makeVeryOverridable = f: { + /** + This is a function that can be overridden. + */ + __functor = self: arg: f arg // { override = throw "not implemented"; overrideAttrs = throw "not implemented"; }; + override = throw "not implemented"; + }; + + helper2 = makeVeryOverridable square; + + # The RFC might be ambiguous here. The doc comment from makeVeryOverridable + # is "inner" in terms of values, but not inner in terms of expressions. + # Returning the following attribute comment might be allowed. + # TODO: I suppose we could look whether the attribute value expression + # contains a doc, and if not, return the attribute comment anyway? + + /** + Compute x^3 + */ + lib.helper3 = makeVeryOverridable (x: x * x * x); + + /** + Compute x^3... + */ + helper3 = makeVeryOverridable (x: x * x * x); + + + # ------ + + # getDoc traverses a potentially infinite structure in case of __functor, so + # we need to test with recursive inputs and diverging inputs. + + recursive = { + /** + This looks bad, but the docs are ok because of the eta expansion. + */ + __functor = self: x: self x; + }; + + recursive2 = { + /** + Docs probably won't work in this case, because the "partial" application + of self results in an infinite recursion. + */ + __functor = self: self.__functor self; + }; + + diverging = let + /** + Docs probably won't work in this case, because the "partial" application + of self results in an diverging computation that causes a stack overflow. + It's not an infinite recursion because each call is different. + This must be handled by the documentation retrieval logic, as it + reimplements the __functor invocation to be partial. + */ + f = x: { + __functor = self: (f (x + 1)); + }; + in f null; + +} From e225b630621712e407d610109d6e866c06e1e948 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Thu, 15 Aug 2024 13:51:15 +0200 Subject: [PATCH 073/718] doc: Document function application operator --- doc/manual/src/language/operators.md | 22 ++++++++++++++++++++-- doc/manual/src/language/syntax.md | 2 +- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/doc/manual/src/language/operators.md b/doc/manual/src/language/operators.md index 2c2dcc276..ce5b034c6 100644 --- a/doc/manual/src/language/operators.md +++ b/doc/manual/src/language/operators.md @@ -3,7 +3,7 @@ | Name | Syntax | Associativity | Precedence | |----------------------------------------|--------------------------------------------|---------------|------------| | [Attribute selection] | *attrset* `.` *attrpath* \[ `or` *expr* \] | none | 1 | -| Function application | *func* *expr* | left | 2 | +| [Function application] | *func* *expr* | left | 2 | | [Arithmetic negation][arithmetic] | `-` *number* | none | 3 | | [Has attribute] | *attrset* `?` *attrpath* | none | 4 | | List concatenation | *list* `++` *list* | right | 5 | @@ -32,7 +32,7 @@ [string]: ./types.md#type-string [path]: ./types.md#type-path [number]: ./types.md#type-float -[list]: ./types.md#list +[list]: ./types.md#type-list [attribute set]: ./types.md#attribute-set @@ -48,6 +48,22 @@ If the attribute doesn’t exist, return the *expr* after `or` if provided, othe [Attribute selection]: #attribute-selection +## Function application + +> **Syntax** +> +> *func* *expr* + +Apply the callable value *func* to the argument *expr*. Note the absence of a visible operator symbol. +A callable value is either: +- a [user-defined function][function] +- a [built-in][builtins] function +- an attribute set with a [`__functor` attribute](./syntax.md#attr-__functor) + +> **Warning** +> +> This "operator" also separates [list] items, which means that calls in list items must be enclosed by parentheses. + ## Has attribute > **Syntax** @@ -215,3 +231,5 @@ Equivalent to `!`*b1* `||` *b2*. > ``` [Pipe operator]: #pipe-operators +[builtins]: ./builtins.md +[Function application]: #function-application diff --git a/doc/manual/src/language/syntax.md b/doc/manual/src/language/syntax.md index a6a3ea052..506afbea1 100644 --- a/doc/manual/src/language/syntax.md +++ b/doc/manual/src/language/syntax.md @@ -218,7 +218,7 @@ a string), that attribute is simply not added to the set: This will evaluate to `{}` if `foo` evaluates to `false`. -A set that has a `__functor` attribute whose value is callable (i.e. is +A set that has a [`__functor`]{#attr-__functor} attribute whose value is callable (i.e. is itself a function or a set with a `__functor` attribute whose value is callable) can be applied as if it were a function, with the set itself passed in first , e.g., From ce62b766ef976f941b1be8a580afc2c1dc88e17f Mon Sep 17 00:00:00 2001 From: Valentin Gagarin Date: Thu, 15 Aug 2024 15:25:50 +0200 Subject: [PATCH 074/718] fix link from the readme (#11307) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 021e54a3b..ab647e53b 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Full reference documentation can be found in the [Nix manual](https://nix.dev/re ## Building and developing -Follow instructions in the Nix reference manual to [set up a development environment and build Nix from source](https://nix.dev/manual/nix/development/building.html). +Follow instructions in the Nix reference manual to [set up a development environment and build Nix from source](https://nix.dev/manual/nix/development/development/building.html). ## Contributing From 06b18cff2021d7cca21ad013fea6da0c43109032 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Thu, 15 Aug 2024 18:53:42 +0200 Subject: [PATCH 075/718] doc: Edit language/operators Co-authored-by: John Ericson Co-authored-by: Valentin Gagarin --- doc/manual/src/language/operators.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/manual/src/language/operators.md b/doc/manual/src/language/operators.md index ce5b034c6..27444258a 100644 --- a/doc/manual/src/language/operators.md +++ b/doc/manual/src/language/operators.md @@ -54,7 +54,7 @@ If the attribute doesn’t exist, return the *expr* after `or` if provided, othe > > *func* *expr* -Apply the callable value *func* to the argument *expr*. Note the absence of a visible operator symbol. +Apply the callable value *func* to the argument *expr*. Note the absence of any visible operator symbol. A callable value is either: - a [user-defined function][function] - a [built-in][builtins] function @@ -62,7 +62,7 @@ A callable value is either: > **Warning** > -> This "operator" also separates [list] items, which means that calls in list items must be enclosed by parentheses. +> [List][list] items are also separated by whitespace, which means that function calls in list items must be enclosed by parentheses. ## Has attribute From 30af4a9e27cdafd4be6997c9764c5c9b229ea550 Mon Sep 17 00:00:00 2001 From: Michael Gallagher Date: Thu, 15 Aug 2024 17:56:05 -0700 Subject: [PATCH 076/718] nix-daemon.sh profile script: operate under `set -u` in bash see https://github.com/NixOS/nix/commit/d459d3307c7b1b10f6489ed048fff192e7834928 --- scripts/nix-profile-daemon.sh.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/nix-profile-daemon.sh.in b/scripts/nix-profile-daemon.sh.in index eb124c0b5..59c00d491 100644 --- a/scripts/nix-profile-daemon.sh.in +++ b/scripts/nix-profile-daemon.sh.in @@ -52,7 +52,7 @@ elif [ -e /etc/pki/tls/certs/ca-bundle.crt ]; then # Fedora, CentOS else # Fall back to what is in the nix profiles, favouring whatever is defined last. check_nix_profiles() { - if [ -n "$ZSH_VERSION" ]; then + if [ -n "${ZSH_VERSION:-}" ]; then # Zsh by default doesn't split words in unquoted parameter expansion. # Set local_options for these options to be reverted at the end of the function # and shwordsplit to force splitting words in $NIX_PROFILES below. From c4192a66174cb1c67840a97ba7bc0a706a2c1e2a Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Fri, 16 Aug 2024 15:27:53 +0200 Subject: [PATCH 077/718] Add nix::execvpe --- src/libutil/unix/exec.hh | 13 +++++++++++++ src/libutil/unix/meson.build | 1 + src/libutil/unix/processes.cc | 7 +++++++ 3 files changed, 21 insertions(+) create mode 100644 src/libutil/unix/exec.hh diff --git a/src/libutil/unix/exec.hh b/src/libutil/unix/exec.hh new file mode 100644 index 000000000..e6b80889a --- /dev/null +++ b/src/libutil/unix/exec.hh @@ -0,0 +1,13 @@ +#pragma once + +namespace nix { + +/** + * `execvpe` is a GNU extension, so we need to implement it for other POSIX + * platforms. + * + * We use our own implementation unconditionally for consistency. + */ +int execvpe(const char * file0, char * const argv[], char * const envp[]); + +} diff --git a/src/libutil/unix/meson.build b/src/libutil/unix/meson.build index 1c5bf27fb..d36152db9 100644 --- a/src/libutil/unix/meson.build +++ b/src/libutil/unix/meson.build @@ -13,6 +13,7 @@ sources += files( include_dirs += include_directories('.') headers += files( + 'exec.hh', 'monitor-fd.hh', 'signals-impl.hh', ) diff --git a/src/libutil/unix/processes.cc b/src/libutil/unix/processes.cc index c5ce74acc..09acba35a 100644 --- a/src/libutil/unix/processes.cc +++ b/src/libutil/unix/processes.cc @@ -1,5 +1,6 @@ #include "current-process.hh" #include "environment-variables.hh" +#include "executable-path.hh" #include "signals.hh" #include "processes.hh" #include "finally.hh" @@ -419,4 +420,10 @@ bool statusOk(int status) return WIFEXITED(status) && WEXITSTATUS(status) == 0; } +int execvpe(const char * file0, char * const argv[], char * const envp[]) +{ + auto file = ExecutablePath::load().findPath(file0).string(); + return execve(file.c_str(), argv, envp); +} + } From a03bb4455cee010bbfcf7e322b10ec7e35123032 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 3 Jul 2024 16:51:25 +0200 Subject: [PATCH 078/718] Fix SSH invocation when local SHELL misbehaves Setting it to /bin/sh will make it more predictable when users have their favorite shell in SHELL, which might not behave as expected. For instance, a bad rc file could send something to stdout before our LocalCommand gets to write "started". This may help https://github.com/NixOS/nix/issues/11010 --- src/libstore/ssh.cc | 33 ++++++++++++++++++++++++++++++--- tests/nixos/remote-builds.nix | 17 ++++++++++++++++- 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/src/libstore/ssh.cc b/src/libstore/ssh.cc index e5d623adf..b8c5f4d97 100644 --- a/src/libstore/ssh.cc +++ b/src/libstore/ssh.cc @@ -3,6 +3,7 @@ #include "current-process.hh" #include "environment-variables.hh" #include "util.hh" +#include "exec.hh" namespace nix { @@ -44,6 +45,10 @@ void SSHMaster::addCommonSSHOpts(Strings & args) if (compress) args.push_back("-C"); + // We use this to make ssh signal back to us that the connection is established. + // It really does run locally; see createSSHEnv which sets up SHELL to make + // it launch more reliably. The local command runs synchronously, so presumably + // the remote session won't be garbled if the local command is slow. args.push_back("-oPermitLocalCommand=yes"); args.push_back("-oLocalCommand=echo started"); } @@ -56,6 +61,27 @@ bool SSHMaster::isMasterRunning() { return res.first == 0; } +Strings createSSHEnv() +{ + // Copy the environment and set SHELL=/bin/sh + std::map env = getEnv(); + + // SSH will invoke the "user" shell for -oLocalCommand, but that means + // $SHELL. To keep things simple and avoid potential issues with other + // shells, we set it to /bin/sh. + // Technically, we don't need that, and we could reinvoke ourselves to print + // "started". Self-reinvocation is tricky with library consumers, but mostly + // solved; refer to the development history of nixExePath in libstore/globals.cc. + env.insert_or_assign("SHELL", "/bin/sh"); + + Strings r; + for (auto & [k, v] : env) { + r.push_back(k + "=" + v); + } + + return r; +} + std::unique_ptr SSHMaster::startCommand( Strings && command, Strings && extraSshArgs) { @@ -104,8 +130,8 @@ std::unique_ptr SSHMaster::startCommand( } args.splice(args.end(), std::move(command)); - - execvp(args.begin()->c_str(), stringsToCharPtrs(args).data()); + auto env = createSSHEnv(); + nix::execvpe(args.begin()->c_str(), stringsToCharPtrs(args).data(), stringsToCharPtrs(env).data()); // could not exec ssh/bash throw SysError("unable to execute '%s'", args.front()); @@ -172,7 +198,8 @@ Path SSHMaster::startMaster() if (verbosity >= lvlChatty) args.push_back("-v"); addCommonSSHOpts(args); - execvp(args.begin()->c_str(), stringsToCharPtrs(args).data()); + auto env = createSSHEnv(); + nix::execvpe(args.begin()->c_str(), stringsToCharPtrs(args).data(), stringsToCharPtrs(env).data()); throw SysError("unable to execute '%s'", args.front()); }, options); diff --git a/tests/nixos/remote-builds.nix b/tests/nixos/remote-builds.nix index 8ddf6ad02..ab159eaad 100644 --- a/tests/nixos/remote-builds.nix +++ b/tests/nixos/remote-builds.nix @@ -81,6 +81,17 @@ in virtualisation.additionalPaths = [ config.system.build.extraUtils ]; nix.settings.substituters = lib.mkForce [ ]; programs.ssh.extraConfig = "ConnectTimeout 30"; + environment.systemPackages = [ + # `bad-shell` is used to make sure Nix works an environment with a misbehaving shell. + # + # More realistically, a bad shell would still run the command ("echo started") + # but considering that our solution is to avoid this shell (set via $SHELL), we + # don't need to bother with a more functional mock shell. + (pkgs.writeScriptBin "bad-shell" '' + #!${pkgs.runtimeShell} + echo "Hello, I am a broken shell" + '') + ]; }; }; @@ -114,9 +125,13 @@ in 'echo hello world on $(hostname)' >&2 """) + # Check that SSH uses SHELL for LocalCommand, as expected, and check that + # our test setup here is working. The next test will use this bad SHELL. + client.succeed(f"SHELL=$(which bad-shell) ssh -oLocalCommand='true' -oPermitLocalCommand=yes {builder1.name} 'echo hello world' | grep -F 'Hello, I am a broken shell'") + # Perform a build and check that it was performed on the builder. out = client.succeed( - "nix-build ${expr nodes.client 1} 2> build-output", + "SHELL=$(which bad-shell) nix-build ${expr nodes.client 1} 2> build-output", "grep -q Hello build-output" ) builder1.succeed(f"test -e {out}") From 8866d2cd838902d45782541efe08efc1e1f1a2ab Mon Sep 17 00:00:00 2001 From: Cole Helbling Date: Fri, 16 Aug 2024 07:09:27 -0700 Subject: [PATCH 079/718] flake.lock: Update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/63d37ccd2d178d54e7fb691d7ec76000740ea24a?narHash=sha256-7cCC8%2BTdq1%2B3OPyc3%2BgVo9dzUNkNIQfwSDJ2HSi2u3o%3D' (2024-07-21) → 'github:NixOS/nixpkgs/c3d4ac725177c030b1e289015989da2ad9d56af0?narHash=sha256-sqLwJcHYeWLOeP/XoLwAtYjr01TISlkOfz%2BNG82pbdg%3D' (2024-08-15) --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 2ac413a69..b5d0b881c 100644 --- a/flake.lock +++ b/flake.lock @@ -80,11 +80,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1721548954, - "narHash": "sha256-7cCC8+Tdq1+3OPyc3+gVo9dzUNkNIQfwSDJ2HSi2u3o=", + "lastModified": 1723688146, + "narHash": "sha256-sqLwJcHYeWLOeP/XoLwAtYjr01TISlkOfz+NG82pbdg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "63d37ccd2d178d54e7fb691d7ec76000740ea24a", + "rev": "c3d4ac725177c030b1e289015989da2ad9d56af0", "type": "github" }, "original": { From aa3d35c1f4145c9532620a20d6727c2214eab054 Mon Sep 17 00:00:00 2001 From: Cole Helbling Date: Fri, 16 Aug 2024 07:22:30 -0700 Subject: [PATCH 080/718] ci: check that all outputs for all systems can evaluate --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9831d0e0e..3463335b9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,6 +49,7 @@ jobs: done ) & - run: nix --experimental-features 'nix-command flakes' flake check -L + - run: nix --experimental-features 'nix-command flakes' flake show --all-systems --json # Steps to test CI automation in your own fork. # Cachix: From d4aa7d5dc78f65b68b4c5f6c721b6fb3ae045874 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 14 Aug 2024 23:19:22 +0200 Subject: [PATCH 081/718] Use nixosTest.quickBuild behavior by default This wasn't the default behaviour because: > We don't enable this by default to avoid the mostly unnecessary work of > performing an additional build of the package in cases where we build > the package normally anyway, such as in our pre-merge CI. Since we have a componentized build, we've solved the duplication. In the new situation, building both with and without unit tests isn't any slow than just a build with unit tests, so there's no point in using the unit-tested build anymore. By using the otherwise untested build, we reduce the minimum build time towards the NixOS test, at no cost. If you want to run all tests, build all attributes. --- doc/manual/src/development/testing.md | 8 ++--- tests/nixos/default.nix | 13 ++++++-- tests/nixos/quick-build.nix | 47 --------------------------- 3 files changed, 12 insertions(+), 56 deletions(-) delete mode 100644 tests/nixos/quick-build.nix diff --git a/doc/manual/src/development/testing.md b/doc/manual/src/development/testing.md index 3949164d5..a1782d86c 100644 --- a/doc/manual/src/development/testing.md +++ b/doc/manual/src/development/testing.md @@ -276,14 +276,12 @@ To ensure that characterisation testing doesn't make it harder to intentionally We run the functional tests not just in the build, but also in VM tests. This helps us ensure that Nix works correctly on NixOS, and environments that have similar characteristics that are hard to reproduce in a build environment. -The recommended way to run these tests during development is: +These can be run with: ```shell -nix build .#hydraJobs.tests.functional_user.quickBuild +nix build .#hydraJobs.tests.functional_user ``` -The `quickBuild` attribute configures the test to use a `nix` package that's built without integration tests, so that you can iterate on the tests without performing recompilations due to the changed sources for `installCheck`. - Generally, this build is sufficient, but in nightly or CI we also test the attributes `functional_root` and `functional_trusted`, in which the test suite is run with different levels of authorization. ## Integration tests @@ -294,8 +292,6 @@ Because these tests are expensive and require more than what the standard github You can run them manually with `nix build .#hydraJobs.tests.{testName}` or `nix-build -A hydraJobs.tests.{testName}`. -If you are testing a build of `nix` that you haven't compiled yet, you may iterate faster by appending the `quickBuild` attribute: `nix build .#hydraJobs.tests.{testName}.quickBuild`. - ## Installer tests After a one-time setup, the Nix repository's GitHub Actions continuous integration (CI) workflow can test the installer each time you push to a branch. diff --git a/tests/nixos/default.nix b/tests/nixos/default.nix index 66174c928..3fa341ef1 100644 --- a/tests/nixos/default.nix +++ b/tests/nixos/default.nix @@ -4,20 +4,24 @@ let nixos-lib = import (nixpkgs + "/nixos/lib") { }; + noTests = pkg: pkg.overrideAttrs ( + finalAttrs: prevAttrs: { + doCheck = false; + doInstallCheck = false; + }); + # https://nixos.org/manual/nixos/unstable/index.html#sec-calling-nixos-tests runNixOSTestFor = system: test: (nixos-lib.runTest { imports = [ test - - # Add the quickBuild attribute to the check packages - ./quick-build.nix ]; hostPkgs = nixpkgsFor.${system}.native; defaults = { nixpkgs.pkgs = nixpkgsFor.${system}.native; nix.checkAllErrors = false; + nix.package = noTests nixpkgsFor.${system}.native.nix; }; _module.args.nixpkgs = nixpkgs; _module.args.system = system; @@ -29,6 +33,9 @@ let forNix = nixVersion: runNixOSTestFor system { imports = [test]; defaults.nixpkgs.overlays = [(curr: prev: { + # NOTE: noTests pkg might not have been built yet for some older versions of the package + # and in versions before 2.25, the untested build wasn't shared with the tested build yet + # Add noTests here when those versions become irrelevant. nix = (builtins.getFlake "nix/${nixVersion}").packages.${system}.nix; })]; }; diff --git a/tests/nixos/quick-build.nix b/tests/nixos/quick-build.nix deleted file mode 100644 index 57e3b9cdb..000000000 --- a/tests/nixos/quick-build.nix +++ /dev/null @@ -1,47 +0,0 @@ -test@{ lib, extendModules, ... }: -let - inherit (lib) mkOption types; -in -{ - options = { - quickBuild = mkOption { - description = '' - Whether to perform a "quick" build of the Nix package to test. - - When iterating on the functional tests, it's recommended to "set" this - to `true`, so that changes to the functional tests don't require any - recompilation of the package. - You can do so by building the `.quickBuild` attribute on the check package, - e.g: - ```console - nix build .#hydraJobs.functional_user.quickBuild - ``` - - We don't enable this by default to avoid the mostly unnecessary work of - performing an additional build of the package in cases where we build - the package normally anyway, such as in our pre-merge CI. - ''; - type = types.bool; - default = false; - }; - }; - - config = { - passthru.quickBuild = - let withQuickBuild = extendModules { modules = [{ quickBuild = true; }]; }; - in withQuickBuild.config.test; - - defaults = { pkgs, ... }: { - config = lib.mkIf test.config.quickBuild { - nix.package = pkgs.nixComponents.nix-cli; - - system.forbiddenDependenciesRegexes = [ - # This would indicate that the quickBuild feature is broken. - # It could happen if NixOS has a dependency on pkgs.nix instead of - # config.nix.package somewhere. - (builtins.unsafeDiscardStringContext pkgs.nix.outPath) - ]; - }; - }; - }; -} From 4ba57c9eb28952039164d83fcd21f454794fa3fe Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Sat, 17 Aug 2024 02:46:58 -0400 Subject: [PATCH 082/718] ci: use attribute with version for docker --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3463335b9..84e5ab998 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -146,7 +146,7 @@ jobs: with: install_url: https://releases.nixos.org/nix/nix-2.20.3/install - run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV - - run: echo NIX_VERSION="$(nix --experimental-features 'nix-command flakes' eval .\#default.version | tr -d \")" >> $GITHUB_ENV + - run: echo NIX_VERSION="$(nix --experimental-features 'nix-command flakes' eval .\#nix.version | tr -d \")" >> $GITHUB_ENV - uses: cachix/cachix-action@v15 if: needs.check_secrets.outputs.cachix == 'true' with: From 80f20fa4cb75ad48d74047ca060869bb9138f776 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sat, 17 Aug 2024 08:31:41 +0200 Subject: [PATCH 083/718] replace backport github action with mergify The current backport action cannot automerge because the github action bot does not trigger github CI actions. Mergify instead does not have this limitation and can also use a merge queue. On top we have now a declarative configuration to allow contributers to add new tests to required without having access to the github org. An example pull request and backport can be seen here: https://github.com/Mic92/nix-1/pull/4 and here: https://github.com/Mic92/nix-1/pull/5 To complete the setup the mergify app must be enabled for this repository. It's already installed in the nixos organization for nixos-hardware and other repositories. --- .github/workflows/backport.yml | 32 ------------ .mergify.yml | 92 ++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 32 deletions(-) delete mode 100644 .github/workflows/backport.yml create mode 100644 .mergify.yml diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml deleted file mode 100644 index dd110de6c..000000000 --- a/.github/workflows/backport.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: Backport -on: - pull_request_target: - types: [closed, labeled] -permissions: - contents: read -jobs: - backport: - name: Backport Pull Request - permissions: - # for zeebe-io/backport-action - contents: write - pull-requests: write - if: github.repository_owner == 'NixOS' && github.event.pull_request.merged == true && (github.event_name != 'labeled' || startsWith('backport', github.event.label.name)) - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha }} - # required to find all branches - fetch-depth: 0 - - name: Create backport PRs - # should be kept in sync with `version` - uses: zeebe-io/backport-action@v3.0.2 - with: - # Config README: https://github.com/zeebe-io/backport-action#backport-action - github_token: ${{ secrets.GITHUB_TOKEN }} - github_workspace: ${{ github.workspace }} - pull_description: |- - Automatic backport to `${target_branch}`, triggered by a label in #${pull_number}. - # should be kept in sync with `uses` - version: v0.0.5 diff --git a/.mergify.yml b/.mergify.yml new file mode 100644 index 000000000..663c45d92 --- /dev/null +++ b/.mergify.yml @@ -0,0 +1,92 @@ +queue_rules: + - name: default + # all required tests need to go here + merge_conditions: + - check-success=installer + - check-success=installer_test (macos-latest) + - check-success=installer_test (ubuntu-latest) + - check-success=tests (macos-latest) + - check-success=tests (ubuntu-latest) + - check-success=vm_tests + merge_method: rebase + batch_size: 5 + +pull_request_rules: + - name: merge using the merge queue + conditions: + - base=master + - label~=merge-queue|dependencies + actions: + queue: {} + +# The rules below will first create backport pull requests and put those in a merge queue. + + - name: backport patches to 2.18 + conditions: + - label=backport 2.18-maintenance + actions: + backport: + branches: + - 2.18-maintenance + labels: + - merge-queue + + - name: backport patches to 2.19 + conditions: + - label=backport 2.19-maintenance + actions: + backport: + branches: + - 2.19-maintenance + labels: + - merge-queue + + - name: backport patches to 2.20 + conditions: + - label=backport 2.20-maintenance + actions: + backport: + branches: + - 2.20-maintenance + labels: + - merge-queue + + - name: backport patches to 2.21 + conditions: + - label=backport 2.21-maintenance + actions: + backport: + branches: + - 2.21-maintenance + labels: + - merge-queue + + - name: backport patches to 2.22 + conditions: + - label=backport 2.22-maintenance + actions: + backport: + branches: + - 2.22-maintenance + labels: + - merge-queue + + - name: backport patches to 2.23 + conditions: + - label=backport 2.23-maintenance + actions: + backport: + branches: + - 2.23-maintenance + labels: + - merge-queue + + - name: backport patches to 2.24 + conditions: + - label=backport 2.24-maintenance + actions: + backport: + branches: + - "2.24-maintenance" + labels: + - merge-queue From a5f6ee8550b78badffe48993b0a236b7934c1be5 Mon Sep 17 00:00:00 2001 From: shivaraj-bh Date: Wed, 14 Aug 2024 14:57:34 +0530 Subject: [PATCH 084/718] `nix flake show`: Support `meta` attribute for `apps` Metadata information for flake apps will be useful while exploring a flake using `nix flake show` --- src/nix/flake.cc | 12 +++++++++--- src/nix/run.md | 3 +++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 3f9f8f99b..09f41dca8 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -1251,8 +1251,7 @@ struct CmdFlakeShow : FlakeCommand, MixJSON } j.emplace("type", "derivation"); j.emplace("name", name); - if (description) - j.emplace("description", *description); + j.emplace("description", description ? *description : ""); } else { logger->cout("%s: %s '%s'", headerPrefix, @@ -1340,12 +1339,19 @@ struct CmdFlakeShow : FlakeCommand, MixJSON (attrPath.size() == 3 && attrPathS[0] == "apps")) { auto aType = visitor.maybeGetAttr("type"); + std::optional description; + if (auto aMeta = visitor.maybeGetAttr(state->sMeta)) { + if (auto aDescription = aMeta->maybeGetAttr(state->sDescription)) + description = aDescription->getString(); + } if (!aType || aType->getString() != "app") state->error("not an app definition").debugThrow(); if (json) { j.emplace("type", "app"); + if (description) + j.emplace("description", *description); } else { - logger->cout("%s: app", headerPrefix); + logger->cout("%s: app: " ANSI_BOLD "%s" ANSI_NORMAL, headerPrefix, description ? *description : "no description"); } } diff --git a/src/nix/run.md b/src/nix/run.md index 250ea65aa..eb96e6b31 100644 --- a/src/nix/run.md +++ b/src/nix/run.md @@ -80,6 +80,7 @@ An app is specified by a flake output attribute named apps.x86_64-linux.blender_2_79 = { type = "app"; program = "${self.packages.x86_64-linux.blender_2_79}/bin/blender"; + meta.description = "Run Blender, a free and open-source 3D creation suite."; }; ``` @@ -90,4 +91,6 @@ The only supported attributes are: * `program` (required): The full path of the executable to run. It must reside in the Nix store. +* `meta.description` (optional): A description of the app. + )"" From adabca6e4f4a1863344992b51a44f943690ba42d Mon Sep 17 00:00:00 2001 From: shivaraj-bh Date: Fri, 16 Aug 2024 03:12:02 +0530 Subject: [PATCH 085/718] `nix flake check`: Add apps check; Check if formatter is a derivation --- src/nix/flake.cc | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 09f41dca8..10cb6af9b 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -437,14 +437,39 @@ struct CmdFlakeCheck : FlakeCommand auto checkApp = [&](const std::string & attrPath, Value & v, const PosIdx pos) { try { - #if 0 - // FIXME - auto app = App(*state, v); - for (auto & i : app.context) { - auto [drvPathS, outputName] = NixStringContextElem::parse(i); - store->parseStorePath(drvPathS); + Activity act(*logger, lvlInfo, actUnknown, fmt("checking app '%s'", attrPath)); + state->forceAttrs(v, pos, ""); + if (auto attr = v.attrs()->get(state->symbols.create("type"))) + state->forceStringNoCtx(*attr->value, attr->pos, ""); + else + throw Error("app '%s' lacks attribute 'type'", attrPath); + + if (auto attr = v.attrs()->get(state->symbols.create("program"))) { + if (attr->name == state->symbols.create("program")) { + NixStringContext context; + state->forceString(*attr->value, context, attr->pos, ""); + } + } else + throw Error("app '%s' lacks attribute 'program'", attrPath); + + if (auto attr = v.attrs()->get(state->symbols.create("meta"))) { + state->forceAttrs(*attr->value, attr->pos, ""); + if (auto dAttr = attr->value->attrs()->get(state->symbols.create("description"))) + state->forceStringNoCtx(*dAttr->value, dAttr->pos, ""); + else + logWarning({ + .msg = HintFmt("app '%s' lacks attribute 'meta.description'", attrPath), + }); + } else + logWarning({ + .msg = HintFmt("app '%s' lacks attribute 'meta'", attrPath), + }); + + for (auto & attr : *v.attrs()) { + std::string_view name(state->symbols[attr.name]); + if (name != "type" && name != "program" && name != "meta") + throw Error("app '%s' has unsupported attribute '%s'", attrPath, name); } - #endif } catch (Error & e) { e.addTrace(resolve(pos), HintFmt("while checking the app definition '%s'", attrPath)); reportError(e); @@ -629,7 +654,7 @@ struct CmdFlakeCheck : FlakeCommand const auto & attr_name = state->symbols[attr.name]; checkSystemName(attr_name, attr.pos); if (checkSystemType(attr_name, attr.pos)) { - checkApp( + checkDerivation( fmt("%s.%s", name, attr_name), *attr.value, attr.pos); }; From 2ab93fd5fda3f61f6b1560db7da21a34dbd13b7d Mon Sep 17 00:00:00 2001 From: shivaraj-bh Date: Fri, 16 Aug 2024 03:12:24 +0530 Subject: [PATCH 086/718] `nix flake check`: Add functional tests for apps and formatter --- tests/functional/flakes/check.sh | 44 ++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/tests/functional/flakes/check.sh b/tests/functional/flakes/check.sh index 3b83dcafe..27e73444a 100755 --- a/tests/functional/flakes/check.sh +++ b/tests/functional/flakes/check.sh @@ -91,3 +91,47 @@ nix flake check $flakeDir checkRes=$(nix flake check --all-systems --keep-going $flakeDir 2>&1 && fail "nix flake check --all-systems should have failed" || true) echo "$checkRes" | grepQuiet "packages.system-1.default" echo "$checkRes" | grepQuiet "packages.system-2.default" + +cat > $flakeDir/flake.nix < $flakeDir/flake.nix <&1 && fail "nix flake check --all-systems should have failed" || true) +echo "$checkRes" | grepQuiet "unknown-attr" + +cat > $flakeDir/flake.nix <&1 && fail "nix flake check --all-systems should have failed" || true) +echo "$checkRes" | grepQuiet "formatter.system-1" From 9ccad9708eac3593defab8a8f74d3acf1bb60870 Mon Sep 17 00:00:00 2001 From: siddhantCodes Date: Sun, 18 Aug 2024 18:27:20 +0530 Subject: [PATCH 087/718] Don't use `OS_STR` in `nix-channel.cc` --- src/nix-channel/nix-channel.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nix-channel/nix-channel.cc b/src/nix-channel/nix-channel.cc index 52fa3c4f6..56d1d7abb 100644 --- a/src/nix-channel/nix-channel.cc +++ b/src/nix-channel/nix-channel.cc @@ -166,7 +166,7 @@ static int main_nix_channel(int argc, char ** argv) { // Figure out the name of the `.nix-channels' file to use auto home = getHome(); - channelsList = settings.useXDGBaseDirectories ? createNixStateDir() + OS_STR("/channels") : home + OS_STR("/.nix-channels"); + channelsList = settings.useXDGBaseDirectories ? createNixStateDir() + "/channels" : home + "/.nix-channels"; nixDefExpr = getNixDefExpr(); // Figure out the name of the channels profile. From 67de1932774b834377f704d9d358ef3d4951d0ef Mon Sep 17 00:00:00 2001 From: Sandro Date: Sun, 18 Aug 2024 18:44:59 +0200 Subject: [PATCH 088/718] Remove duplicated section (#11324) --- doc/manual/src/release-notes/rl-2.24.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/doc/manual/src/release-notes/rl-2.24.md b/doc/manual/src/release-notes/rl-2.24.md index 5bcc1d79c..08ec65be9 100644 --- a/doc/manual/src/release-notes/rl-2.24.md +++ b/doc/manual/src/release-notes/rl-2.24.md @@ -261,12 +261,6 @@ Author: [**Eelco Dolstra (@edolstra)**](https://github.com/edolstra) -- Improve handling of tarballs that don't consist of a single top-level directory [#11195](https://github.com/NixOS/nix/pull/11195) - - In previous Nix releases, the tarball fetcher (used by `builtins.fetchTarball`) erroneously merged top-level directories into a single directory, and silently discarded top-level files that are not directories. This is no longer the case. - - Author: [**Eelco Dolstra (@edolstra)**](https://github.com/edolstra) - - Setting to warn about large paths [#10778](https://github.com/NixOS/nix/pull/10778) Nix can now warn when evaluation of a Nix expression causes a large From 59db8fd62b5300afbbabb1e8a12d547b336a3bdf Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Sun, 18 Aug 2024 22:35:54 -0400 Subject: [PATCH 089/718] fix: check to see if there are any lines before --- src/nix-build/nix-build.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc index 0ce987d8a..a5b9e1e54 100644 --- a/src/nix-build/nix-build.cc +++ b/src/nix-build/nix-build.cc @@ -163,7 +163,7 @@ static void main_nix_build(int argc, char * * argv) script = argv[1]; try { auto lines = tokenizeString(readFile(script), "\n"); - if (std::regex_search(lines.front(), std::regex("^#!"))) { + if (!lines.empty() && std::regex_search(lines.front(), std::regex("^#!"))) { lines.pop_front(); inShebang = true; for (int i = 2; i < argc; ++i) From 93853833478122a200045e6fc9cf45c532eed80c Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 19 Aug 2024 15:17:13 +0200 Subject: [PATCH 090/718] Revert "Remove unit tests from old build system" `make check` was reverted too soon. The hacking guide wasn't brought up to date with the new workflow, and it's not clear how to use meson for everything. This reverts commit 6f3045c2a225dca7b1ed8a9c9dc27ab50f575900. --- Makefile | 19 ++++++++++++ Makefile.config.in | 1 + configure.ac | 22 ++++++++++++++ package.nix | 33 +++++++++++++++++++- tests/unit/libexpr-support/local.mk | 23 ++++++++++++++ tests/unit/libexpr/local.mk | 45 ++++++++++++++++++++++++++++ tests/unit/libfetchers/local.mk | 37 +++++++++++++++++++++++ tests/unit/libflake/local.mk | 43 ++++++++++++++++++++++++++ tests/unit/libstore-support/local.mk | 21 +++++++++++++ tests/unit/libstore/local.mk | 38 +++++++++++++++++++++++ tests/unit/libutil-support/local.mk | 19 ++++++++++++ tests/unit/libutil/local.mk | 37 +++++++++++++++++++++++ 12 files changed, 337 insertions(+), 1 deletion(-) create mode 100644 tests/unit/libexpr-support/local.mk create mode 100644 tests/unit/libexpr/local.mk create mode 100644 tests/unit/libfetchers/local.mk create mode 100644 tests/unit/libflake/local.mk create mode 100644 tests/unit/libstore-support/local.mk create mode 100644 tests/unit/libstore/local.mk create mode 100644 tests/unit/libutil-support/local.mk create mode 100644 tests/unit/libutil/local.mk diff --git a/Makefile b/Makefile index b51ae6cc7..dbf510a3e 100644 --- a/Makefile +++ b/Makefile @@ -38,6 +38,18 @@ makefiles += \ endif endif +ifeq ($(ENABLE_UNIT_TESTS), yes) +makefiles += \ + tests/unit/libutil/local.mk \ + tests/unit/libutil-support/local.mk \ + tests/unit/libstore/local.mk \ + tests/unit/libstore-support/local.mk \ + tests/unit/libfetchers/local.mk \ + tests/unit/libexpr/local.mk \ + tests/unit/libexpr-support/local.mk \ + tests/unit/libflake/local.mk +endif + ifeq ($(ENABLE_FUNCTIONAL_TESTS), yes) ifdef HOST_UNIX makefiles += \ @@ -92,6 +104,13 @@ include mk/lib.mk # These must be defined after `mk/lib.mk`. Otherwise the first rule # incorrectly becomes the default target. +ifneq ($(ENABLE_UNIT_TESTS), yes) +.PHONY: check +check: + @echo "Unit tests are disabled. Configure without '--disable-unit-tests', or avoid calling 'make check'." + @exit 1 +endif + ifneq ($(ENABLE_FUNCTIONAL_TESTS), yes) .PHONY: installcheck installcheck: diff --git a/Makefile.config.in b/Makefile.config.in index e131484f6..3100d2073 100644 --- a/Makefile.config.in +++ b/Makefile.config.in @@ -12,6 +12,7 @@ ENABLE_BUILD = @ENABLE_BUILD@ ENABLE_DOC_GEN = @ENABLE_DOC_GEN@ ENABLE_FUNCTIONAL_TESTS = @ENABLE_FUNCTIONAL_TESTS@ ENABLE_S3 = @ENABLE_S3@ +ENABLE_UNIT_TESTS = @ENABLE_UNIT_TESTS@ GTEST_LIBS = @GTEST_LIBS@ HAVE_LIBCPUID = @HAVE_LIBCPUID@ HAVE_SECCOMP = @HAVE_SECCOMP@ diff --git a/configure.ac b/configure.ac index 18d718c07..5c22ed176 100644 --- a/configure.ac +++ b/configure.ac @@ -141,6 +141,18 @@ AC_ARG_ENABLE(build, AS_HELP_STRING([--disable-build],[Do not build nix]), ENABLE_BUILD=$enableval, ENABLE_BUILD=yes) AC_SUBST(ENABLE_BUILD) +# Building without unit tests is useful for bootstrapping with a smaller footprint +# or running the tests in a separate derivation. Otherwise, we do compile and +# run them. + +AC_ARG_ENABLE(unit-tests, AS_HELP_STRING([--disable-unit-tests],[Do not build the tests]), + ENABLE_UNIT_TESTS=$enableval, ENABLE_UNIT_TESTS=$ENABLE_BUILD) +AC_SUBST(ENABLE_UNIT_TESTS) + +AS_IF( + [test "$ENABLE_BUILD" == "no" && test "$ENABLE_UNIT_TESTS" == "yes"], + [AC_MSG_ERROR([Cannot enable unit tests when building overall is disabled. Please do not pass '--enable-unit-tests' or do not pass '--disable-build'.])]) + AC_ARG_ENABLE(functional-tests, AS_HELP_STRING([--disable-functional-tests],[Do not build the tests]), ENABLE_FUNCTIONAL_TESTS=$enableval, ENABLE_FUNCTIONAL_TESTS=yes) AC_SUBST(ENABLE_FUNCTIONAL_TESTS) @@ -346,6 +358,16 @@ if test "$gc" = yes; then CFLAGS="$old_CFLAGS" fi +AS_IF([test "$ENABLE_UNIT_TESTS" == "yes"],[ + +# Look for gtest. +PKG_CHECK_MODULES([GTEST], [gtest_main gmock_main]) + +# Look for rapidcheck. +PKG_CHECK_MODULES([RAPIDCHECK], [rapidcheck rapidcheck_gtest]) + +]) + # Look for nlohmann/json. PKG_CHECK_MODULES([NLOHMANN_JSON], [nlohmann_json >= 3.9]) diff --git a/package.nix b/package.nix index c0d04179d..d41748b7c 100644 --- a/package.nix +++ b/package.nix @@ -53,6 +53,10 @@ # Whether to build Nix. Useful to skip for tasks like testing existing pre-built versions of Nix , doBuild ? true +# Run the unit tests as part of the build. See `installUnitTests` for an +# alternative to this. +, doCheck ? __forDefaults.canRunInstalled + # Run the functional tests as part of the build. , doInstallCheck ? test-client != null || __forDefaults.canRunInstalled @@ -85,6 +89,11 @@ # - readline , readlineFlavor ? if stdenv.hostPlatform.isWindows then "readline" else "editline" +# Whether to install unit tests. This is useful when cross compiling +# since we cannot run them natively during the build, but can do so +# later. +, installUnitTests ? doBuild && !__forDefaults.canExecuteHost + # For running the functional tests against a pre-built Nix. Probably # want to use in conjunction with `doBuild = false;`. , test-daemon ? null @@ -108,7 +117,7 @@ let # things which should instead be gotten via `finalAttrs` in order to # work with overriding. attrs = { - inherit doBuild doInstallCheck; + inherit doBuild doCheck doInstallCheck; }; mkDerivation = @@ -124,11 +133,16 @@ in mkDerivation (finalAttrs: let inherit (finalAttrs) + doCheck doInstallCheck ; doBuild = !finalAttrs.dontBuild; + # Either running the unit tests during the build, or installing them + # to be run later, requiresthe unit tests to be built. + buildUnitTests = doCheck || installUnitTests; + in { inherit pname version; @@ -162,6 +176,8 @@ in { ./scripts/local.mk ] ++ lib.optionals enableManual [ ./doc/manual + ] ++ lib.optionals buildUnitTests [ + ./tests/unit ] ++ lib.optionals doInstallCheck [ ./tests/functional ])); @@ -174,6 +190,8 @@ in { # If we are doing just build or just docs, the one thing will use # "out". We only need additional outputs if we are doing both. ++ lib.optional (doBuild && enableManual) "doc" + ++ lib.optional installUnitTests "check" + ++ lib.optional doCheck "testresults" ; nativeBuildInputs = [ @@ -212,6 +230,9 @@ in { ({ inherit readline editline; }.${readlineFlavor}) ] ++ lib.optionals enableMarkdown [ lowdown + ] ++ lib.optionals buildUnitTests [ + gtest + rapidcheck ] ++ lib.optional stdenv.isLinux libseccomp ++ lib.optional stdenv.hostPlatform.isx86_64 libcpuid # There have been issues building these dependencies @@ -226,16 +247,22 @@ in { ); dontBuild = !attrs.doBuild; + doCheck = attrs.doCheck; configureFlags = [ (lib.enableFeature doBuild "build") + (lib.enableFeature buildUnitTests "unit-tests") (lib.enableFeature doInstallCheck "functional-tests") (lib.enableFeature enableManual "doc-gen") (lib.enableFeature enableGC "gc") (lib.enableFeature enableMarkdown "markdown") + (lib.enableFeature installUnitTests "install-unit-tests") (lib.withFeatureAs true "readline-flavor" readlineFlavor) ] ++ lib.optionals (!forDevShell) [ "--sysconfdir=/etc" + ] ++ lib.optionals installUnitTests [ + "--with-check-bin-dir=${builtins.placeholder "check"}/bin" + "--with-check-lib-dir=${builtins.placeholder "check"}/lib" ] ++ lib.optionals (doBuild) [ "--with-boost=${boost}/lib" ] ++ lib.optionals (doBuild && stdenv.isLinux) [ @@ -316,6 +343,10 @@ in { platforms = lib.platforms.unix ++ lib.platforms.windows; mainProgram = "nix"; broken = !(lib.all (a: a) [ + # We cannot run or install unit tests if we don't build them or + # Nix proper (which they depend on). + (installUnitTests -> doBuild) + (doCheck -> doBuild) # The build process for the manual currently requires extracting # data from the Nix executable we are trying to document. (enableManual -> doBuild) diff --git a/tests/unit/libexpr-support/local.mk b/tests/unit/libexpr-support/local.mk new file mode 100644 index 000000000..0501de33c --- /dev/null +++ b/tests/unit/libexpr-support/local.mk @@ -0,0 +1,23 @@ +libraries += libexpr-test-support + +libexpr-test-support_NAME = libnixexpr-test-support + +libexpr-test-support_DIR := $(d) + +ifeq ($(INSTALL_UNIT_TESTS), yes) + libexpr-test-support_INSTALL_DIR := $(checklibdir) +else + libexpr-test-support_INSTALL_DIR := +endif + +libexpr-test-support_SOURCES := \ + $(wildcard $(d)/tests/*.cc) \ + $(wildcard $(d)/tests/value/*.cc) + +libexpr-test-support_CXXFLAGS += $(libexpr-tests_EXTRA_INCLUDES) + +libexpr-test-support_LIBS = \ + libstore-test-support libutil-test-support \ + libexpr libstore libutil + +libexpr-test-support_LDFLAGS := $(THREAD_LDFLAGS) -lrapidcheck diff --git a/tests/unit/libexpr/local.mk b/tests/unit/libexpr/local.mk new file mode 100644 index 000000000..1617e2823 --- /dev/null +++ b/tests/unit/libexpr/local.mk @@ -0,0 +1,45 @@ +check: libexpr-tests_RUN + +programs += libexpr-tests + +libexpr-tests_NAME := libnixexpr-tests + +libexpr-tests_ENV := _NIX_TEST_UNIT_DATA=$(d)/data GTEST_OUTPUT=xml:$$testresults/libexpr-tests.xml + +libexpr-tests_DIR := $(d) + +ifeq ($(INSTALL_UNIT_TESTS), yes) + libexpr-tests_INSTALL_DIR := $(checkbindir) +else + libexpr-tests_INSTALL_DIR := +endif + +libexpr-tests_SOURCES := \ + $(wildcard $(d)/*.cc) \ + $(wildcard $(d)/value/*.cc) \ + $(wildcard $(d)/flake/*.cc) + +libexpr-tests_EXTRA_INCLUDES = \ + -I tests/unit/libexpr-support \ + -I tests/unit/libstore-support \ + -I tests/unit/libutil-support \ + $(INCLUDE_libexpr) \ + $(INCLUDE_libexprc) \ + $(INCLUDE_libfetchers) \ + $(INCLUDE_libstore) \ + $(INCLUDE_libstorec) \ + $(INCLUDE_libutil) \ + $(INCLUDE_libutilc) + +libexpr-tests_CXXFLAGS += $(libexpr-tests_EXTRA_INCLUDES) + +libexpr-tests_LIBS = \ + libexpr-test-support libstore-test-support libutil-test-support \ + libexpr libexprc libfetchers libstore libstorec libutil libutilc + +libexpr-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) -lgmock + +ifdef HOST_WINDOWS + # Increase the default reserved stack size to 65 MB so Nix doesn't run out of space + libexpr-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024))) +endif diff --git a/tests/unit/libfetchers/local.mk b/tests/unit/libfetchers/local.mk new file mode 100644 index 000000000..30aa142a5 --- /dev/null +++ b/tests/unit/libfetchers/local.mk @@ -0,0 +1,37 @@ +check: libfetchers-tests_RUN + +programs += libfetchers-tests + +libfetchers-tests_NAME = libnixfetchers-tests + +libfetchers-tests_ENV := _NIX_TEST_UNIT_DATA=$(d)/data GTEST_OUTPUT=xml:$$testresults/libfetchers-tests.xml + +libfetchers-tests_DIR := $(d) + +ifeq ($(INSTALL_UNIT_TESTS), yes) + libfetchers-tests_INSTALL_DIR := $(checkbindir) +else + libfetchers-tests_INSTALL_DIR := +endif + +libfetchers-tests_SOURCES := $(wildcard $(d)/*.cc) + +libfetchers-tests_EXTRA_INCLUDES = \ + -I tests/unit/libstore-support \ + -I tests/unit/libutil-support \ + $(INCLUDE_libfetchers) \ + $(INCLUDE_libstore) \ + $(INCLUDE_libutil) + +libfetchers-tests_CXXFLAGS += $(libfetchers-tests_EXTRA_INCLUDES) + +libfetchers-tests_LIBS = \ + libstore-test-support libutil-test-support \ + libfetchers libstore libutil + +libfetchers-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) $(LIBGIT2_LIBS) + +ifdef HOST_WINDOWS + # Increase the default reserved stack size to 65 MB so Nix doesn't run out of space + libfetchers-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024))) +endif diff --git a/tests/unit/libflake/local.mk b/tests/unit/libflake/local.mk new file mode 100644 index 000000000..590bcf7c0 --- /dev/null +++ b/tests/unit/libflake/local.mk @@ -0,0 +1,43 @@ +check: libflake-tests_RUN + +programs += libflake-tests + +libflake-tests_NAME := libnixflake-tests + +libflake-tests_ENV := _NIX_TEST_UNIT_DATA=$(d)/data GTEST_OUTPUT=xml:$$testresults/libflake-tests.xml + +libflake-tests_DIR := $(d) + +ifeq ($(INSTALL_UNIT_TESTS), yes) + libflake-tests_INSTALL_DIR := $(checkbindir) +else + libflake-tests_INSTALL_DIR := +endif + +libflake-tests_SOURCES := \ + $(wildcard $(d)/*.cc) \ + $(wildcard $(d)/value/*.cc) \ + $(wildcard $(d)/flake/*.cc) + +libflake-tests_EXTRA_INCLUDES = \ + -I tests/unit/libflake-support \ + -I tests/unit/libstore-support \ + -I tests/unit/libutil-support \ + $(INCLUDE_libflake) \ + $(INCLUDE_libexpr) \ + $(INCLUDE_libfetchers) \ + $(INCLUDE_libstore) \ + $(INCLUDE_libutil) \ + +libflake-tests_CXXFLAGS += $(libflake-tests_EXTRA_INCLUDES) + +libflake-tests_LIBS = \ + libexpr-test-support libstore-test-support libutil-test-support \ + libflake libexpr libfetchers libstore libutil + +libflake-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) -lgmock + +ifdef HOST_WINDOWS + # Increase the default reserved stack size to 65 MB so Nix doesn't run out of space + libflake-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024))) +endif diff --git a/tests/unit/libstore-support/local.mk b/tests/unit/libstore-support/local.mk new file mode 100644 index 000000000..56dedd825 --- /dev/null +++ b/tests/unit/libstore-support/local.mk @@ -0,0 +1,21 @@ +libraries += libstore-test-support + +libstore-test-support_NAME = libnixstore-test-support + +libstore-test-support_DIR := $(d) + +ifeq ($(INSTALL_UNIT_TESTS), yes) + libstore-test-support_INSTALL_DIR := $(checklibdir) +else + libstore-test-support_INSTALL_DIR := +endif + +libstore-test-support_SOURCES := $(wildcard $(d)/tests/*.cc) + +libstore-test-support_CXXFLAGS += $(libstore-tests_EXTRA_INCLUDES) + +libstore-test-support_LIBS = \ + libutil-test-support \ + libstore libutil + +libstore-test-support_LDFLAGS := $(THREAD_LDFLAGS) -lrapidcheck diff --git a/tests/unit/libstore/local.mk b/tests/unit/libstore/local.mk new file mode 100644 index 000000000..8d3d6b0af --- /dev/null +++ b/tests/unit/libstore/local.mk @@ -0,0 +1,38 @@ +check: libstore-tests_RUN + +programs += libstore-tests + +libstore-tests_NAME = libnixstore-tests + +libstore-tests_ENV := _NIX_TEST_UNIT_DATA=$(d)/data GTEST_OUTPUT=xml:$$testresults/libstore-tests.xml + +libstore-tests_DIR := $(d) + +ifeq ($(INSTALL_UNIT_TESTS), yes) + libstore-tests_INSTALL_DIR := $(checkbindir) +else + libstore-tests_INSTALL_DIR := +endif + +libstore-tests_SOURCES := $(wildcard $(d)/*.cc) + +libstore-tests_EXTRA_INCLUDES = \ + -I tests/unit/libstore-support \ + -I tests/unit/libutil-support \ + $(INCLUDE_libstore) \ + $(INCLUDE_libstorec) \ + $(INCLUDE_libutil) \ + $(INCLUDE_libutilc) + +libstore-tests_CXXFLAGS += $(libstore-tests_EXTRA_INCLUDES) + +libstore-tests_LIBS = \ + libstore-test-support libutil-test-support \ + libstore libstorec libutil libutilc + +libstore-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) + +ifdef HOST_WINDOWS + # Increase the default reserved stack size to 65 MB so Nix doesn't run out of space + libstore-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024))) +endif diff --git a/tests/unit/libutil-support/local.mk b/tests/unit/libutil-support/local.mk new file mode 100644 index 000000000..5f7835c9f --- /dev/null +++ b/tests/unit/libutil-support/local.mk @@ -0,0 +1,19 @@ +libraries += libutil-test-support + +libutil-test-support_NAME = libnixutil-test-support + +libutil-test-support_DIR := $(d) + +ifeq ($(INSTALL_UNIT_TESTS), yes) + libutil-test-support_INSTALL_DIR := $(checklibdir) +else + libutil-test-support_INSTALL_DIR := +endif + +libutil-test-support_SOURCES := $(wildcard $(d)/tests/*.cc) + +libutil-test-support_CXXFLAGS += $(libutil-tests_EXTRA_INCLUDES) + +libutil-test-support_LIBS = libutil + +libutil-test-support_LDFLAGS := $(THREAD_LDFLAGS) -lrapidcheck diff --git a/tests/unit/libutil/local.mk b/tests/unit/libutil/local.mk new file mode 100644 index 000000000..404f35cf1 --- /dev/null +++ b/tests/unit/libutil/local.mk @@ -0,0 +1,37 @@ +check: libutil-tests_RUN + +programs += libutil-tests + +libutil-tests_NAME = libnixutil-tests + +libutil-tests_ENV := _NIX_TEST_UNIT_DATA=$(d)/data GTEST_OUTPUT=xml:$$testresults/libutil-tests.xml + +libutil-tests_DIR := $(d) + +ifeq ($(INSTALL_UNIT_TESTS), yes) + libutil-tests_INSTALL_DIR := $(checkbindir) +else + libutil-tests_INSTALL_DIR := +endif + +libutil-tests_SOURCES := $(wildcard $(d)/*.cc) + +libutil-tests_EXTRA_INCLUDES = \ + -I tests/unit/libutil-support \ + $(INCLUDE_libutil) \ + $(INCLUDE_libutilc) + +libutil-tests_CXXFLAGS += $(libutil-tests_EXTRA_INCLUDES) + +libutil-tests_LIBS = libutil-test-support libutil libutilc + +libutil-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) + +ifdef HOST_WINDOWS + # Increase the default reserved stack size to 65 MB so Nix doesn't run out of space + libutil-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024))) +endif + +check: $(d)/data/git/check-data.sh.test + +$(eval $(call run-test,$(d)/data/git/check-data.sh)) From ceae25825fdb39fc973d23e7f0d2e355a6974bc9 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 19 Aug 2024 10:24:38 -0400 Subject: [PATCH 091/718] Update documentation to refer to Meson not Make in most places This is necessary to make the Meson one the default and preferred one. Co-authored-by: Robert Hensing --- doc/manual/src/development/building.md | 88 +++++++++---------- doc/manual/src/development/testing.md | 58 ++++++------ .../src/installation/building-source.md | 21 ++--- maintainers/format.sh | 11 +++ maintainers/local.mk | 11 +-- 5 files changed, 89 insertions(+), 100 deletions(-) create mode 100755 maintainers/format.sh diff --git a/doc/manual/src/development/building.md b/doc/manual/src/development/building.md index 5a5fb3368..dbf080296 100644 --- a/doc/manual/src/development/building.md +++ b/doc/manual/src/development/building.md @@ -34,16 +34,21 @@ $ nix-shell --attr devShells.x86_64-linux.native-clangStdenvPackages To build Nix itself in this shell: ```console -[nix-shell]$ autoreconfPhase -[nix-shell]$ ./configure $configureFlags --prefix=$(pwd)/outputs/out -[nix-shell]$ make -j $NIX_BUILD_CORES +[nix-shell]$ mesonFlags+=" --prefix=$(pwd)/outputs/out" +[nix-shell]$ dontAddPrefix=1 mesonConfigurePhase +[nix-shell]$ ninjaBuildPhase ``` -To install it in `$(pwd)/outputs` and test it: +To test it: ```console -[nix-shell]$ make install -[nix-shell]$ make installcheck -j $NIX_BUILD_CORES +[nix-shell]$ mesonCheckPhase +``` + +To install it in `$(pwd)/outputs`: + +```console +[nix-shell]$ ninjaInstallPhase [nix-shell]$ ./outputs/out/bin/nix --version nix (Nix) 2.12 ``` @@ -85,16 +90,20 @@ $ nix develop .#native-clangStdenvPackages To build Nix itself in this shell: ```console -[nix-shell]$ autoreconfPhase -[nix-shell]$ configurePhase -[nix-shell]$ make -j $NIX_BUILD_CORES OPTIMIZE=0 +[nix-shell]$ mesonConfigurePhase +[nix-shell]$ ninjaBuildPhase ``` -To install it in `$(pwd)/outputs` and test it: +To test it: ```console -[nix-shell]$ make install OPTIMIZE=0 -[nix-shell]$ make installcheck check -j $NIX_BUILD_CORES +[nix-shell]$ mesonCheckPhase +``` + +To install it in `$(pwd)/outputs`: + +```console +[nix-shell]$ ninjaInstallPhase [nix-shell]$ nix --version nix (Nix) 2.12 ``` @@ -110,25 +119,6 @@ $ nix build You can also build Nix for one of the [supported platforms](#platforms). -## Makefile variables - -You may need `profiledir=$out/etc/profile.d` and `sysconfdir=$out/etc` to run `make install`. - -Run `make` with [`-e` / `--environment-overrides`](https://www.gnu.org/software/make/manual/make.html#index-_002de) to allow environment variables to override `Makefile` variables: - -- `ENABLE_BUILD=yes` to enable building the C++ code. -- `ENABLE_DOC_GEN=yes` to enable building the documentation (manual, man pages, etc.). - - The docs can take a while to build, so you may want to disable this for local development. -- `ENABLE_FUNCTIONAL_TESTS=yes` to enable building the functional tests. -- `OPTIMIZE=1` to enable optimizations. -- `libraries=libutil programs=` to only build a specific library. - - This will fail in the linking phase if the other libraries haven't been built, but is useful for checking types. -- `libraries= programs=nix` to only build a specific program. - - This will not work in general, because the programs need the libraries. - ## Platforms Nix can be built for various platforms, as specified in [`flake.nix`]: @@ -175,27 +165,38 @@ Add more [system types](#system-type) to `crossSystems` in `flake.nix` to bootst It is useful to perform multiple cross and native builds on the same source tree, for example to ensure that better support for one platform doesn't break the build for another. -In order to facilitate this, Nix has some support for being built out of tree – that is, placing build artefacts in a different directory than the source code: +Meson thankfully makes this very easy by confining all build products to the build directory --- one simple shares the source directory between multiple build directories, each of which contains the build for Nix to a different platform. -1. Create a directory for the build, e.g. +Nixpkgs's `mesonConfigurePhase` always chooses `build` in the current directory as the name and location of the build. +This makes having multiple build directories slightly more inconvenient. +The good news is that Meson/Ninja seem to cope well with relocating the build directory after it is created. + +Here's how to do that + +1. Configure as usual ```bash - mkdir build + mesonConfigurePhase ``` -2. Run the configure script from that directory, e.g. +2. Rename the build directory ```bash - cd build - ../configure + cd .. # since `mesonConfigurePhase` cd'd inside + mv build build-linux # or whatever name we want + cd build-linux ``` -3. Run make from the source directory, but with the build directory specified, e.g. +3. Build as usual ```bash - make builddir=build + ninjaBuildPhase ``` +> **N.B.** +> [`nixpkgs#335818`](https://github.com/NixOS/nixpkgs/issues/335818) tracks giving `mesonConfigurePhase` proper support for custom build directories. +> When it is fixed, we can simplify these instructions and then remove this notice. + ## System type Nix uses a string with the following format to identify the *system type* or *platform* it runs on: @@ -257,11 +258,8 @@ You can use any of the other supported environments in place of `nix-ccacheStden The `clangd` LSP server is installed by default on the `clang`-based `devShell`s. See [supported compilation environments](#compilation-environments) and instructions how to set up a shell [with flakes](#nix-with-flakes) or in [classic Nix](#classic-nix). -To use the LSP with your editor, you first need to [set up `clangd`](https://clangd.llvm.org/installation#project-setup) by running: - -```console -make compile_commands.json -``` +To use the LSP with your editor, you will want a `compile_commands.json` file telling `clangd` how we are compiling the code. +Meson's configure always produces this inside the build directory. Configure your editor to use the `clangd` from the `.#native-clangStdenvPackages` shell. You can do that either by running it inside the development shell, or by using [nix-direnv](https://github.com/nix-community/nix-direnv) and [the appropriate editor plugin](https://github.com/direnv/direnv/wiki#editor-integration). @@ -276,7 +274,7 @@ Configure your editor to use the `clangd` from the `.#native-clangStdenvPackages You may run the formatters as a one-off using: ```console -make format +./maintainers/format.sh ``` If you'd like to run the formatters before every commit, install the hooks: diff --git a/doc/manual/src/development/testing.md b/doc/manual/src/development/testing.md index a1782d86c..8b8bc568d 100644 --- a/doc/manual/src/development/testing.md +++ b/doc/manual/src/development/testing.md @@ -135,60 +135,52 @@ Functional tests are run during `installCheck` in the `nix` package build, as we ### Running the whole test suite -The whole test suite can be run with: +The whole test suite (functional and unit tests) can be run with: ```shell-session -$ make install && make installcheck -ran test tests/functional/foo.sh... [PASS] -ran test tests/functional/bar.sh... [PASS] -... +$ mesonCheckPhase ``` ### Grouping tests Sometimes it is useful to group related tests so they can be easily run together without running the entire test suite. Each test group is in a subdirectory of `tests`. -For example, `tests/functional/ca/local.mk` defines a `ca` test group for content-addressed derivation outputs. +For example, `tests/functional/ca/meson.build` defines a `ca` test group for content-addressed derivation outputs. That test group can be run like this: ```shell-session -$ make ca.test-group -j50 -ran test tests/functional/ca/nix-run.sh... [PASS] -ran test tests/functional/ca/import-derivation.sh... [PASS] -... -``` - -The test group is defined in Make like this: -```makefile -$(test-group-name)-tests := \ - $(d)/test0.sh \ - $(d)/test1.sh \ - ... - -install-tests-groups += $(test-group-name) +$ meson test --suite ca +ninja: Entering directory `/home/jcericson/src/nix/master/build' +ninja: no work to do. +[1-20/20] 🌑 nix-functional-tests:ca / ca/why-depends 1/20 nix-functional-tests:ca / ca/nix-run OK 0.16s +[2-20/20] 🌒 nix-functional-tests:ca / ca/why-depends 2/20 nix-functional-tests:ca / ca/import-derivation OK 0.17s ``` ### Running individual tests -Individual tests can be run with `make`: +Individual tests can be run with `meson`: ```shell-session -$ make tests/functional/${testName}.sh.test -ran test tests/functional/${testName}.sh... [PASS] +$ meson test ${testName} +ninja: Entering directory `/home/jcericson/src/nix/master/build' +ninja: no work to do. +1/1 nix-functional-tests:main / ${testName} OK 0.41s + +Ok: 1 +Expected Fail: 0 +Fail: 0 +Unexpected Pass: 0 +Skipped: 0 +Timeout: 0 + +Full log written to /home/jcericson/src/nix/master/build/meson-logs/testlog.txt ``` -or without `make`: +or without `meson`, showing the output: ```shell-session -$ ./mk/run-test.sh tests/functional/${testName}.sh -ran test tests/functional/${testName}.sh... [PASS] -``` - -To see the complete output, one can also run: - -```shell-session -$ ./mk/debug-test.sh tests/functional/${testName}.sh +$ TEST_NAME=${testName} NIX_REMOTE='' PS4='+(${BASH_SOURCE[0]-$0}:$LINENO) tests/functional/${testName}.sh +(${testName}.sh:1) foo output from foo +(${testName}.sh:2) bar @@ -254,7 +246,7 @@ It is frequently useful to regenerate the expected output. To do that, rerun the failed test(s) with `_NIX_TEST_ACCEPT=1`. For example: ```bash -_NIX_TEST_ACCEPT=1 make tests/functional/lang.sh.test +_NIX_TEST_ACCEPT=1 meson test lang ``` This convention is shared with the [characterisation unit tests](#characterisation-testing-unit) too. diff --git a/doc/manual/src/installation/building-source.md b/doc/manual/src/installation/building-source.md index 7dad9805a..d35cc18c2 100644 --- a/doc/manual/src/installation/building-source.md +++ b/doc/manual/src/installation/building-source.md @@ -1,31 +1,26 @@ # Building Nix from Source -After cloning Nix's Git repository, issue the following commands: +Nix is built with [Meson](https://mesonbuild.com/). +It is broken up into multiple Meson packages, which are optionally combined in a single project using Meson's [subprojects](https://mesonbuild.com/Subprojects.html) feature. -```console -$ autoreconf -vfi -$ ./configure options... -$ make -$ make install -``` +There are no mandatory extra steps to the building process: +generic Meson installation instructions like [this](https://mesonbuild.com/Quick-guide.html#using-meson-as-a-distro-packager) should work. -Nix requires GNU Make so you may need to invoke `gmake` instead. - -The installation path can be specified by passing the `--prefix=prefix` +The installation path can be specified by passing the `-Dprefix=prefix` to `configure`. The default installation directory is `/usr/local`. You can change this to any location you like. You must have write permission to the *prefix* path. Nix keeps its *store* (the place where packages are stored) in `/nix/store` by default. This can be changed using -`--with-store-dir=path`. +`-Dstore-dir=path`. > **Warning** -> +> > It is best *not* to change the Nix store from its default, since doing > so makes it impossible to use pre-built binaries from the standard > Nixpkgs channels — that is, all packages will need to be built from > source. Nix keeps state (such as its database and log files) in `/nix/var` by -default. This can be changed using `--localstatedir=path`. +default. This can be changed using `-Dlocalstatedir=path`. diff --git a/maintainers/format.sh b/maintainers/format.sh new file mode 100755 index 000000000..a2a6d8b41 --- /dev/null +++ b/maintainers/format.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +if ! type -p pre-commit &>/dev/null; then + echo "format.sh: pre-commit not found. Please use \`nix develop\`."; + exit 1; +fi; +if test -z "$_NIX_PRE_COMMIT_HOOKS_CONFIG"; then + echo "format.sh: _NIX_PRE_COMMIT_HOOKS_CONFIG not set. Please use \`nix develop\`."; + exit 1; +fi; +pre-commit run --config "$_NIX_PRE_COMMIT_HOOKS_CONFIG" --all-files diff --git a/maintainers/local.mk b/maintainers/local.mk index 88d594d67..e81517eda 100644 --- a/maintainers/local.mk +++ b/maintainers/local.mk @@ -3,13 +3,6 @@ print-top-help += echo ' format: Format source code' # This uses the cached .pre-commit-hooks.yaml file +fmt_script := $(d)/format.sh format: - @if ! type -p pre-commit &>/dev/null; then \ - echo "make format: pre-commit not found. Please use \`nix develop\`."; \ - exit 1; \ - fi; \ - if test -z "$$_NIX_PRE_COMMIT_HOOKS_CONFIG"; then \ - echo "make format: _NIX_PRE_COMMIT_HOOKS_CONFIG not set. Please use \`nix develop\`."; \ - exit 1; \ - fi; \ - pre-commit run --config $$_NIX_PRE_COMMIT_HOOKS_CONFIG --all-files + @$(fmt_script) From 2f0db04da08e67f29577c27fae3c0eb758fc0879 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 19 Aug 2024 16:41:40 +0200 Subject: [PATCH 092/718] tests.installer: Load profile with -o unset Tested with an ubuntu case. Might need revision depending on what hydra thinks of the rest. --- tests/installer/default.nix | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/installer/default.nix b/tests/installer/default.nix index 4aed6eae4..7c82045ad 100644 --- a/tests/installer/default.nix +++ b/tests/installer/default.nix @@ -217,10 +217,16 @@ let $ssh < Date: Mon, 19 Aug 2024 16:48:33 +0200 Subject: [PATCH 093/718] Fix doc build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes ``` GEN /home/eelco/Dev/nix-master/outputs/out/share/doc/nix/manual/index.html error: File not found: ../store/types/ ┌─ release-notes/rl-next.md:60:197 │ 60 │ The build hook protocol did in principle support custom ways of remote building, but that can also be accomplished with a custom service for the ssh or daemon/ssh-ng protocols, or with a custom [store type](../store/types/) i.e. `Store` subclass. │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File not found: ../store/types/ Error: One or more incorrect links 2024-08-19 16:47:57 [ERROR] (mdbook::renderer): Renderer exited with non-zero return code. 2024-08-19 16:47:57 [ERROR] (mdbook::utils): Error: Rendering failed 2024-08-19 16:47:57 [ERROR] (mdbook::utils): Caused By: The "linkcheck" renderer failed ``` --- doc/manual/rl-next/build-hook-default.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/manual/rl-next/build-hook-default.md b/doc/manual/rl-next/build-hook-default.md index 197290536..0d5a130c0 100644 --- a/doc/manual/rl-next/build-hook-default.md +++ b/doc/manual/rl-next/build-hook-default.md @@ -17,6 +17,6 @@ This means that other applications linking `libnixstore` that wish to use remote Long term we don't envision this being a downside, because we plan to [get rid of `build-remote` and the build hook setting entirely](https://github.com/NixOS/nix/issues/1221). There is simply no need to add a second layer of remote-procedure-calling when we want to connect to a remote builder. -The build hook protocol did in principle support custom ways of remote building, but that can also be accomplished with a custom service for the ssh or daemon/ssh-ng protocols, or with a custom [store type](@docroot@/store/types/) i.e. `Store` subclass. +The build hook protocol did in principle support custom ways of remote building, but that can also be accomplished with a custom service for the ssh or daemon/ssh-ng protocols, or with a custom [store type](@docroot@/store/types/index.md) i.e. `Store` subclass. The Perl bindings no longer expose `getBinDir` either, since they libraries those bindings wrap no longer know the location of installed binaries as described above. From b52e58903e346a883c62d6af3b406e51e602f471 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Sat, 17 Aug 2024 13:34:45 +0200 Subject: [PATCH 094/718] doc: Manage expectations for eval-cache Incorrectly high expectations lead to frustration for users who stick around to experience how useless it is for e.g. a devShell https://functional.cafe/@arianvp/112976284363120036: > Flakes doesn't have eval caching. It has command line argument > caching. It literally just stores the cli argument you passed > in a sqlite database and yes that's as useless as it sounds > When I discovered flakes had no expression level caching whatsoever > I kind of felt lied to and betrayed. --- doc/manual/src/release-notes/rl-2.4.md | 2 ++ src/libexpr/eval-settings.hh | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/doc/manual/src/release-notes/rl-2.4.md b/doc/manual/src/release-notes/rl-2.4.md index 1201e53b6..dbec5a29d 100644 --- a/doc/manual/src/release-notes/rl-2.4.md +++ b/doc/manual/src/release-notes/rl-2.4.md @@ -141,6 +141,8 @@ more than 2800 commits from 195 contributors since release 2.3. the evaluation cache. This is made possible by the hermetic evaluation model of flakes. + Intermediate results are not cached. + * The new `--offline` flag disables substituters and causes all locally cached tarballs and repositories to be considered up-to-date. diff --git a/src/libexpr/eval-settings.hh b/src/libexpr/eval-settings.hh index 0cfc14c1b..3d412bbbf 100644 --- a/src/libexpr/eval-settings.hh +++ b/src/libexpr/eval-settings.hh @@ -185,7 +185,11 @@ struct EvalSettings : Config )"}; Setting useEvalCache{this, true, "eval-cache", - "Whether to use the flake evaluation cache."}; + R"( + Whether to use the flake evaluation cache. + Certain commands won't have to evaluate when invoked for the second time with a particular version of a flake. + Intermediate results are not cached. + )"}; Setting ignoreExceptionsDuringTry{this, false, "ignore-try", R"( From 3e5bf903413f420c1f997e4b55140761172b8434 Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Fri, 2 Aug 2024 20:02:57 -0400 Subject: [PATCH 095/718] feat: better warning for common SSL errors --- src/libstore/filetransfer.cc | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/libstore/filetransfer.cc b/src/libstore/filetransfer.cc index 5ea8b6f96..58c52acc0 100644 --- a/src/libstore/filetransfer.cc +++ b/src/libstore/filetransfer.cc @@ -54,6 +54,8 @@ struct curlFileTransfer : public FileTransfer bool done = false; // whether either the success or failure function has been called Callback callback; CURL * req = 0; + // buffer to accompany the `req` above + char errbuf[CURL_ERROR_SIZE]; bool active = false; // whether the handle has been added to the multi object std::string statusMsg; @@ -370,6 +372,9 @@ struct curlFileTransfer : public FileTransfer if (writtenToSink) curl_easy_setopt(req, CURLOPT_RESUME_FROM_LARGE, writtenToSink); + curl_easy_setopt(req, CURLOPT_ERRORBUFFER, errbuf); + errbuf[0] = 0; + result.data.clear(); result.bodySize = 0; } @@ -484,8 +489,8 @@ struct curlFileTransfer : public FileTransfer code == CURLE_OK ? "" : fmt(" (curl error: %s)", curl_easy_strerror(code))) : FileTransferError(err, std::move(response), - "unable to %s '%s': %s (%d)", - request.verb(), request.uri, curl_easy_strerror(code), code); + "unable to %s '%s': %s (%d) %s", + request.verb(), request.uri, curl_easy_strerror(code), code, errbuf); /* If this is a transient error, then maybe retry the download after a while. If we're writing to a From 84ea12ad7fbedddf3f9bfc1d7c2159df43b9219b Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 19 Aug 2024 11:02:46 -0400 Subject: [PATCH 096/718] Fix build errors on Windows --- src/libutil/executable-path.cc | 2 +- .../nix-collect-garbage.cc | 4 +- src/nix/eval.cc | 8 +--- src/nix/flake.cc | 43 ++++++++++--------- src/nix/profile.cc | 6 +-- 5 files changed, 31 insertions(+), 32 deletions(-) diff --git a/src/libutil/executable-path.cc b/src/libutil/executable-path.cc index 8005a19be..da71088e7 100644 --- a/src/libutil/executable-path.cc +++ b/src/libutil/executable-path.cc @@ -86,7 +86,7 @@ fs::path ExecutablePath::findPath(const fs::path & exe, std::functionsymbols[attr.name]; try { diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 6d4408718..b7bbb767b 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -25,6 +25,8 @@ #include "strings-inline.hh" +namespace fs = std::filesystem; + using namespace nix; using namespace nix::flake; using json = nlohmann::json; @@ -897,25 +899,26 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand "If you've set '%s' to a string, try using a path instead.", templateDir, templateDirAttr->getAttrPathStr()).debugThrow(); - std::vector changedFiles; - std::vector conflictedFiles; + std::vector changedFiles; + std::vector conflictedFiles; - std::function copyDir; - copyDir = [&](const std::filesystem::path & from, const std::filesystem::path & to) + std::function copyDir; + copyDir = [&](const fs::path & from, const fs::path & to) { - createDirs(to); + fs::create_directories(to); - for (auto & entry : std::filesystem::directory_iterator{from}) { + for (auto & entry : fs::directory_iterator{from}) { checkInterrupt(); auto from2 = entry.path(); auto to2 = to / entry.path().filename(); auto st = entry.symlink_status(); - if (std::filesystem::is_directory(st)) + auto to_st = fs::symlink_status(to2); + if (fs::is_directory(st)) copyDir(from2, to2); - else if (std::filesystem::is_regular_file(st)) { - auto contents = readFile(from2); - if (pathExists(to2)) { - auto contents2 = readFile(to2); + else if (fs::is_regular_file(st)) { + auto contents = readFile(from2.string()); + if (fs::exists(to_st)) { + auto contents2 = readFile(to2.string()); if (contents != contents2) { printError("refusing to overwrite existing file '%s'\n please merge it manually with '%s'", to2.string(), from2.string()); conflictedFiles.push_back(to2); @@ -924,12 +927,12 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand } continue; } else - writeFile(to2, contents); + writeFile(to2.string(), contents); } - else if (std::filesystem::is_symlink(st)) { - auto target = readLink(from2); - if (pathExists(to2)) { - if (readLink(to2) != target) { + else if (fs::is_symlink(st)) { + auto target = fs::read_symlink(from2); + if (fs::exists(to_st)) { + if (fs::read_symlink(to2) != target) { printError("refusing to overwrite existing file '%s'\n please merge it manually with '%s'", to2.string(), from2.string()); conflictedFiles.push_back(to2); } else { @@ -937,7 +940,7 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand } continue; } else - createSymlink(target, to2); + fs::create_symlink(target, to2); } else throw Error("file '%s' has unsupported type", from2); @@ -948,9 +951,9 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand copyDir(templateDir, flakeDir); - if (!changedFiles.empty() && pathExists(flakeDir + "/.git")) { + if (!changedFiles.empty() && fs::exists(std::filesystem::path{flakeDir} / ".git")) { Strings args = { "-C", flakeDir, "add", "--intent-to-add", "--force", "--" }; - for (auto & s : changedFiles) args.push_back(s); + for (auto & s : changedFiles) args.emplace_back(s.string()); runProgram("git", true, args); } auto welcomeText = cursor->maybeGetAttr("welcomeText"); @@ -1275,7 +1278,7 @@ struct CmdFlakeShow : FlakeCommand, MixJSON if (auto aDescription = aMeta->maybeGetAttr(state->sDescription)) description = aDescription->getString(); } - + if (json) { j.emplace("type", "derivation"); j.emplace("name", name); diff --git a/src/nix/profile.cc b/src/nix/profile.cc index d751abdb1..324fd6330 100644 --- a/src/nix/profile.cc +++ b/src/nix/profile.cc @@ -126,8 +126,8 @@ struct ProfileManifest { auto manifestPath = profile / "manifest.json"; - if (pathExists(manifestPath)) { - auto json = nlohmann::json::parse(readFile(manifestPath)); + if (std::filesystem::exists(manifestPath)) { + auto json = nlohmann::json::parse(readFile(manifestPath.string())); auto version = json.value("version", 0); std::string sUrl; @@ -176,7 +176,7 @@ struct ProfileManifest } } - else if (pathExists(profile / "manifest.nix")) { + else if (std::filesystem::exists(profile / "manifest.nix")) { // FIXME: needed because of pure mode; ugly. state.allowPath(state.store->followLinksToStore(profile.string())); state.allowPath(state.store->followLinksToStore((profile / "manifest.nix").string())); From 9243457cb24dd9734bbc8b9c4b532954ca6caba8 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 19 Aug 2024 17:07:22 +0200 Subject: [PATCH 097/718] Fix umount failure Fixes ``` umount: /tmp/nix-shell.i3xRwX/nix-test/local-overlay-store/delete-refs/stores/merged-store/nix/store: filesystem was unmounted, but failed to update userspace mount table. make: *** [mk/lib.mk:93: tests/functional/local-overlay-store/delete-refs.sh.test] Error 16 ``` in a dev shell. Note: this previously worked before we didn't have umount in the dev shell, so we got /run/wrappers/bin/umount. --- tests/functional/local-overlay-store/common.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/functional/local-overlay-store/common.sh b/tests/functional/local-overlay-store/common.sh index 27338ea23..cbdb3a1f7 100644 --- a/tests/functional/local-overlay-store/common.sh +++ b/tests/functional/local-overlay-store/common.sh @@ -69,7 +69,7 @@ mountOverlayfs () { || skipTest "overlayfs is not supported" cleanupOverlay () { - umount "$storeBRoot/nix/store" + umount -n "$storeBRoot/nix/store" rm -r $storeVolume/workdir } trap cleanupOverlay EXIT From 39daa4a0d3e7451680e070d0bff7998ec0aea787 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 19 Aug 2024 17:49:26 +0200 Subject: [PATCH 098/718] withFramedSink(): Don't use a thread to monitor the other side Since withFramedSink() is now used a lot more than in the past (for every addToStore() variant), we were creating a lot of threads, e.g. nix flake show --no-eval-cache --all-systems github:NixOS/nix/afdd12be5e19c0001ff3297dea544301108d298 would create 46418 threads. While threads on Linux are cheap, this is still substantial overhead. So instead, just poll from FramedSink before every write whether there are pending messages from the daemon. This could slightly increase the latency on log messages from the daemon, but not on exceptions (which were only synchronously checked from FramedSink anyway). This speeds up the command above from 19.2s to 17.5s on my machine (a 9% speedup). --- src/libstore/remote-store-connection.hh | 2 +- src/libstore/remote-store.cc | 42 +++++----------------- src/libstore/worker-protocol-connection.cc | 15 +++++--- src/libstore/worker-protocol-connection.hh | 5 +-- src/libutil/serialise.cc | 20 +++++++++++ src/libutil/serialise.hh | 29 +++++++++------ 6 files changed, 61 insertions(+), 52 deletions(-) diff --git a/src/libstore/remote-store-connection.hh b/src/libstore/remote-store-connection.hh index 405120ee9..513bd6838 100644 --- a/src/libstore/remote-store-connection.hh +++ b/src/libstore/remote-store-connection.hh @@ -49,7 +49,7 @@ struct RemoteStore::ConnectionHandle RemoteStore::Connection & operator * () { return *handle; } RemoteStore::Connection * operator -> () { return &*handle; } - void processStderr(Sink * sink = 0, Source * source = 0, bool flush = true); + void processStderr(Sink * sink = 0, Source * source = 0, bool flush = true, bool block = true); void withFramedSink(std::function fun); }; diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index 555936c18..69bbc64fc 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -153,9 +153,9 @@ RemoteStore::ConnectionHandle::~ConnectionHandle() } } -void RemoteStore::ConnectionHandle::processStderr(Sink * sink, Source * source, bool flush) +void RemoteStore::ConnectionHandle::processStderr(Sink * sink, Source * source, bool flush, bool block) { - handle->processStderr(&daemonException, sink, source, flush); + handle->processStderr(&daemonException, sink, source, flush, block); } @@ -926,43 +926,17 @@ void RemoteStore::ConnectionHandle::withFramedSink(std::functionto.flush(); - std::exception_ptr ex; - - /* Handle log messages / exceptions from the remote on a separate - thread. */ - std::thread stderrThread([&]() { - try { - ReceiveInterrupts receiveInterrupts; - processStderr(nullptr, nullptr, false); - } catch (...) { - ex = std::current_exception(); - } - }); - - Finally joinStderrThread([&]() - { - if (stderrThread.joinable()) { - stderrThread.join(); - if (ex) { - try { - std::rethrow_exception(ex); - } catch (...) { - ignoreException(); - } - } - } - }); - - { - FramedSink sink((*this)->to, ex); + FramedSink sink((*this)->to, [&]() { + /* Periodically process stderr messages and exceptions + from the daemon. */ + processStderr(nullptr, nullptr, false, false); + }); fun(sink); sink.flush(); } - stderrThread.join(); - if (ex) - std::rethrow_exception(ex); + processStderr(nullptr, nullptr, false); } } diff --git a/src/libstore/worker-protocol-connection.cc b/src/libstore/worker-protocol-connection.cc index a47dbb689..ae434c7f0 100644 --- a/src/libstore/worker-protocol-connection.cc +++ b/src/libstore/worker-protocol-connection.cc @@ -32,7 +32,8 @@ static Logger::Fields readFields(Source & from) return fields; } -std::exception_ptr WorkerProto::BasicClientConnection::processStderrReturn(Sink * sink, Source * source, bool flush) +std::exception_ptr +WorkerProto::BasicClientConnection::processStderrReturn(Sink * sink, Source * source, bool flush, bool block) { if (flush) to.flush(); @@ -41,6 +42,9 @@ std::exception_ptr WorkerProto::BasicClientConnection::processStderrReturn(Sink while (true) { + if (!block && !from.hasData()) + break; + auto msg = readNum(from); if (msg == STDERR_WRITE) { @@ -95,8 +99,10 @@ std::exception_ptr WorkerProto::BasicClientConnection::processStderrReturn(Sink logger->result(act, type, fields); } - else if (msg == STDERR_LAST) + else if (msg == STDERR_LAST) { + assert(block); break; + } else throw Error("got unknown message type %x from Nix daemon", msg); @@ -130,9 +136,10 @@ std::exception_ptr WorkerProto::BasicClientConnection::processStderrReturn(Sink } } -void WorkerProto::BasicClientConnection::processStderr(bool * daemonException, Sink * sink, Source * source, bool flush) +void WorkerProto::BasicClientConnection::processStderr( + bool * daemonException, Sink * sink, Source * source, bool flush, bool block) { - auto ex = processStderrReturn(sink, source, flush); + auto ex = processStderrReturn(sink, source, flush, block); if (ex) { *daemonException = true; std::rethrow_exception(ex); diff --git a/src/libstore/worker-protocol-connection.hh b/src/libstore/worker-protocol-connection.hh index 9c96195b5..9665067dd 100644 --- a/src/libstore/worker-protocol-connection.hh +++ b/src/libstore/worker-protocol-connection.hh @@ -70,9 +70,10 @@ struct WorkerProto::BasicClientConnection : WorkerProto::BasicConnection virtual void closeWrite() = 0; - std::exception_ptr processStderrReturn(Sink * sink = 0, Source * source = 0, bool flush = true); + std::exception_ptr processStderrReturn(Sink * sink = 0, Source * source = 0, bool flush = true, bool block = true); - void processStderr(bool * daemonException, Sink * sink = 0, Source * source = 0, bool flush = true); + void + processStderr(bool * daemonException, Sink * sink = 0, Source * source = 0, bool flush = true, bool block = true); /** * Establishes connection, negotiating version. diff --git a/src/libutil/serialise.cc b/src/libutil/serialise.cc index 4899134d7..1e30d27b7 100644 --- a/src/libutil/serialise.cc +++ b/src/libutil/serialise.cc @@ -10,6 +10,8 @@ #ifdef _WIN32 # include # include "windows-error.hh" +#else +# include #endif @@ -158,6 +160,24 @@ bool FdSource::good() } +bool FdSource::hasData() +{ + if (BufferedSource::hasData()) return true; + + while (true) { + struct pollfd fds[1]; + fds[0].fd = fd; + fds[0].events = POLLIN; + auto n = poll(fds, 1, 0); + if (n < 0) { + if (errno == EINTR) continue; + throw SysError("polling file descriptor"); + } + return n == 1 && (fds[0].events & POLLIN); + } +} + + size_t StringSource::read(char * data, size_t len) { if (pos == s.size()) throw EndOfFile("end of string reached"); diff --git a/src/libutil/serialise.hh b/src/libutil/serialise.hh index c7290dcef..964b9a30d 100644 --- a/src/libutil/serialise.hh +++ b/src/libutil/serialise.hh @@ -104,6 +104,9 @@ struct BufferedSource : Source size_t read(char * data, size_t len) override; + /** + * Return true if the buffer is not empty. + */ bool hasData(); protected: @@ -162,6 +165,13 @@ struct FdSource : BufferedSource FdSource & operator=(FdSource && s) = default; bool good() override; + + /** + * Return true if the buffer is not empty after a non-blocking + * read. + */ + bool hasData(); + protected: size_t readUnbuffered(char * data, size_t len) override; private: @@ -522,15 +532,16 @@ struct FramedSource : Source /** * Write as chunks in the format expected by FramedSource. * - * The exception_ptr reference can be used to terminate the stream when you - * detect that an error has occurred on the remote end. + * The `checkError` function can be used to terminate the stream when you + * detect that an error has occurred. */ struct FramedSink : nix::BufferedSink { BufferedSink & to; - std::exception_ptr & ex; + std::function checkError; - FramedSink(BufferedSink & to, std::exception_ptr & ex) : to(to), ex(ex) + FramedSink(BufferedSink & to, std::function && checkError) + : to(to), checkError(checkError) { } ~FramedSink() @@ -545,13 +556,9 @@ struct FramedSink : nix::BufferedSink void writeUnbuffered(std::string_view data) override { - /* Don't send more data if the remote has - encountered an error. */ - if (ex) { - auto ex2 = ex; - ex = nullptr; - std::rethrow_exception(ex2); - } + /* Don't send more data if an error has occured. */ + checkError(); + to << data.size(); to(data); }; From 62b9a26f60753af73d08528cf39b80ba7b210cef Mon Sep 17 00:00:00 2001 From: Noam Yorav-Raphael Date: Mon, 19 Aug 2024 20:18:08 +0300 Subject: [PATCH 099/718] Set $HOME=/proc/homeless-shelter on Linux, and /homeless-shelter on OSX. --- doc/manual/src/language/derivations.md | 3 ++- src/libstore/unix/build/local-derivation-goal.cc | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/doc/manual/src/language/derivations.md b/doc/manual/src/language/derivations.md index c78c7b8c8..b57f6bb6a 100644 --- a/doc/manual/src/language/derivations.md +++ b/doc/manual/src/language/derivations.md @@ -264,7 +264,8 @@ The [`builder`](#attr-builder) is executed as follows: - `PATH` is set to `/path-not-set` to prevent shells from initialising it to their built-in default value. - - `HOME` is set to `/proc/homeless-shelter` to prevent programs from + - `HOME` is set to `/proc/homeless-shelter` on Linux and `/homeless-shelter` + on OSX, to prevent programs from using `/etc/passwd` or the like to find the user's home directory, which could cause impurity. Usually, when `HOME` is set, it is used as the location of the home directory, even if diff --git a/src/libstore/unix/build/local-derivation-goal.cc b/src/libstore/unix/build/local-derivation-goal.cc index f6bbba8b4..e1035fbdd 100644 --- a/src/libstore/unix/build/local-derivation-goal.cc +++ b/src/libstore/unix/build/local-derivation-goal.cc @@ -102,7 +102,14 @@ void handleDiffHook( } } +// We want $HOME to be un-creatable in the sandbox. On Linux, +// you can't create anything inside /proc since it's a virtual filesystem. +// On Darwin it seems that `/homeless-shelter` is good enough. +#if __linux__ const Path LocalDerivationGoal::homeDir = "/proc/homeless-shelter"; +#else +const Path LocalDerivationGoal::homeDir = "/homeless-shelter"; +#endif LocalDerivationGoal::~LocalDerivationGoal() From 2926a859a36befed99bcf8f09031869aa71fba54 Mon Sep 17 00:00:00 2001 From: Jeremy Kolb Date: Mon, 19 Aug 2024 14:46:46 -0400 Subject: [PATCH 100/718] Release note for nix flake show change --- .../rl-next/nix-flake-show-description.md | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 doc/manual/rl-next/nix-flake-show-description.md diff --git a/doc/manual/rl-next/nix-flake-show-description.md b/doc/manual/rl-next/nix-flake-show-description.md new file mode 100644 index 000000000..7feb08483 --- /dev/null +++ b/doc/manual/rl-next/nix-flake-show-description.md @@ -0,0 +1,25 @@ +--- +synopsis: Show package descriptions with `nix flake show` +issues: [10977] +prs: [10980] +--- + +`nix flake show` will now display a package's `meta.description` if it exists. If the description does not fit in the terminal it will be truncated to fit the terminal width. If the size of the terminal width is unknown the description will be capped at 80 characters. + +``` +$ nix flake show +└───packages + └───x86_64-linux + ├───builderImage: package 'docker-image-ara-builder-image.tar.gz' - 'Docker image hosting the nix build environment' + └───runnerImage: package 'docker-image-gitlab-runner.tar.gz' - 'Docker image hosting the gitlab-runner executable' +``` + +In a narrower terminal: + +``` +$ nix flake show +└───packages + └───x86_64-linux + ├───builderImage: package 'docker-image-ara-builder-image.tar.gz' - 'Docker image hosting the nix b... + └───runnerImage: package 'docker-image-gitlab-runner.tar.gz' - 'Docker image hosting the gitlab-run... +``` From df36ff0d1e60f59eb3e0442fa335252421ec8057 Mon Sep 17 00:00:00 2001 From: "Travis A. Everett" Date: Tue, 2 Jul 2024 21:02:45 -0500 Subject: [PATCH 101/718] install-darwin: fix _nixbld uids for macOS sequoia Starting in macOS 15 Sequoia, macOS daemon UIDs are encroaching on our default UIDs of 301-332. This commit relocates our range up to avoid clashing with the current UIDs of 301-304 and buy us a little time while still leaving headroom for people installing more than 32 users. --- scripts/bigsur-nixbld-user-migration.sh | 2 +- scripts/install-darwin-multi-user.sh | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/scripts/bigsur-nixbld-user-migration.sh b/scripts/bigsur-nixbld-user-migration.sh index 0eb312e07..bc42e02e6 100755 --- a/scripts/bigsur-nixbld-user-migration.sh +++ b/scripts/bigsur-nixbld-user-migration.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -((NEW_NIX_FIRST_BUILD_UID=301)) +((NEW_NIX_FIRST_BUILD_UID=350)) id_available(){ dscl . list /Users UniqueID | grep -E '\b'"$1"'\b' >/dev/null diff --git a/scripts/install-darwin-multi-user.sh b/scripts/install-darwin-multi-user.sh index 24c9052f9..bd1a54ad8 100644 --- a/scripts/install-darwin-multi-user.sh +++ b/scripts/install-darwin-multi-user.sh @@ -4,7 +4,17 @@ set -eu set -o pipefail # System specific settings -export NIX_FIRST_BUILD_UID="${NIX_FIRST_BUILD_UID:-301}" +# Notes: +# - up to macOS Big Sur we used the same GID/UIDs as Linux (30000:30001-32) +# - we changed UID to 301 because Big Sur updates failed into recovery mode +# we're targeting the 200-400 UID range for role users mentioned in the +# usage note for sysadminctl +# - we changed UID to 350 because Sequoia now uses UIDs 300-304 for its own +# daemon users +# - we changed GID to 350 alongside above just because it hides the nixbld +# group from the Users & Groups settings panel :) +export NIX_FIRST_BUILD_UID="${NIX_FIRST_BUILD_UID:-350}" +export NIX_BUILD_GROUP_ID="${NIX_BUILD_GROUP_ID:-350}" export NIX_BUILD_USER_NAME_TEMPLATE="_nixbld%d" readonly NIX_DAEMON_DEST=/Library/LaunchDaemons/org.nixos.nix-daemon.plist From 75567423fb6163559575c38867cda09b754364d7 Mon Sep 17 00:00:00 2001 From: "Travis A. Everett" Date: Tue, 2 Jul 2024 21:22:35 -0500 Subject: [PATCH 102/718] install-darwin: move nixbld gid to match first UID --- scripts/install-multi-user.sh | 6 ++---- scripts/install-systemd-multi-user.sh | 1 + 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/scripts/install-multi-user.sh b/scripts/install-multi-user.sh index 6aee073e3..a487d459f 100644 --- a/scripts/install-multi-user.sh +++ b/scripts/install-multi-user.sh @@ -23,10 +23,10 @@ readonly RED='\033[31m' # installer allows overriding build user count to speed up installation # as creating each user takes non-trivial amount of time on macos readonly NIX_USER_COUNT=${NIX_USER_COUNT:-32} -readonly NIX_BUILD_GROUP_ID="${NIX_BUILD_GROUP_ID:-30000}" readonly NIX_BUILD_GROUP_NAME="nixbld" # each system specific installer must set these: # NIX_FIRST_BUILD_UID +# NIX_BUILD_GROUP_ID # NIX_BUILD_USER_NAME_TEMPLATE # Please don't change this. We don't support it, because the # default shell profile that comes with Nix doesn't support it. @@ -530,9 +530,7 @@ It seems the build group $NIX_BUILD_GROUP_NAME already exists, but with the UID $primary_group_id. This script can't really handle that right now, so I'm going to give up. -You can fix this by editing this script and changing the -NIX_BUILD_GROUP_ID variable near the top to from $NIX_BUILD_GROUP_ID -to $primary_group_id and re-run. +You can export NIX_BUILD_GROUP_ID=$primary_group_id and re-run. EOF else row " Exists" "Yes" diff --git a/scripts/install-systemd-multi-user.sh b/scripts/install-systemd-multi-user.sh index a62ed7e3a..a79a69990 100755 --- a/scripts/install-systemd-multi-user.sh +++ b/scripts/install-systemd-multi-user.sh @@ -5,6 +5,7 @@ set -o pipefail # System specific settings export NIX_FIRST_BUILD_UID="${NIX_FIRST_BUILD_UID:-30001}" +export NIX_BUILD_GROUP_ID="${NIX_BUILD_GROUP_ID:-30000}" export NIX_BUILD_USER_NAME_TEMPLATE="nixbld%d" readonly SERVICE_SRC=/lib/systemd/system/nix-daemon.service From 03b258bf97f1740b90cdcdcadfa65266180a01a0 Mon Sep 17 00:00:00 2001 From: eldritch horrors Date: Fri, 9 Aug 2024 21:17:52 +0200 Subject: [PATCH 103/718] libutil: rename and optimize closeMostFDs this is only used to close non-stdio files in derivation sandboxes. we may as well encode that in its name, drop the unnecessary integer set, and use close_range to deal with the actual closing of files. not only is this clearer, it also makes sandbox setup on linux fast by 1ms each (cherry-picked and adapted from https://git.lix.systems/lix-project/lix/commit/c7d97802e4f59b8621e67cf62275d6a7fde8fe62) Co-authored-by: Eelco Dolstra Co-authored-by: Cole Helbling Co-authored-by: John Ericson --- .../unix/build/local-derivation-goal.cc | 2 +- src/libutil/file-descriptor.hh | 4 +-- src/libutil/unix/file-descriptor.cc | 30 +++++++++++++++---- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/libstore/unix/build/local-derivation-goal.cc b/src/libstore/unix/build/local-derivation-goal.cc index e1035fbdd..43a9a9191 100644 --- a/src/libstore/unix/build/local-derivation-goal.cc +++ b/src/libstore/unix/build/local-derivation-goal.cc @@ -1993,7 +1993,7 @@ void LocalDerivationGoal::runChild() throw SysError("changing into '%1%'", tmpDir); /* Close all other file descriptors. */ - unix::closeMostFDs({STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO}); + unix::closeExtraFDs(); #if __linux__ linux::setPersonality(drv->platform); diff --git a/src/libutil/file-descriptor.hh b/src/libutil/file-descriptor.hh index be61375f6..bf8354087 100644 --- a/src/libutil/file-descriptor.hh +++ b/src/libutil/file-descriptor.hh @@ -143,10 +143,10 @@ public: namespace unix { /** - * Close all file descriptors except those listed in the given set. + * Close all file descriptors except stdio fds (ie 0, 1, 2). * Good practice in child processes. */ -void closeMostFDs(const std::set & exceptions); +void closeExtraFDs(); /** * Set the close-on-exec flag for the given file descriptor. diff --git a/src/libutil/unix/file-descriptor.cc b/src/libutil/unix/file-descriptor.cc index a3af1623f..f867199c0 100644 --- a/src/libutil/unix/file-descriptor.cc +++ b/src/libutil/unix/file-descriptor.cc @@ -120,14 +120,35 @@ void Pipe::create() ////////////////////////////////////////////////////////////////////// -void unix::closeMostFDs(const std::set & exceptions) +#if __linux__ || __FreeBSD__ +// In future we can use a syscall wrapper, but at the moment musl and older glibc version don't support it. +static int unix_close_range(unsigned int first, unsigned int last, int flags) { + return syscall(SYS_close_range, first, last, (unsigned int)flags); +} +#endif + +void unix::closeExtraFDs() +{ + constexpr int MAX_KEPT_FD = 2; + static_assert(std::max({STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO}) == MAX_KEPT_FD); + +#if __linux__ || __FreeBSD__ + // first try to close_range everything we don't care about. if this + // returns an error with these parameters we're running on a kernel + // that does not implement close_range (i.e. pre 5.9) and fall back + // to the old method. we should remove that though, in some future. + if (unix_close_range(MAX_KEPT_FD + 1, ~0U, 0) == 0) { + return; + } +#endif + #if __linux__ try { for (auto & s : std::filesystem::directory_iterator{"/proc/self/fd"}) { checkInterrupt(); auto fd = std::stoi(s.path().filename()); - if (!exceptions.count(fd)) { + if (fd > MAX_KEPT_FD) { debug("closing leaked FD %d", fd); close(fd); } @@ -142,9 +163,8 @@ void unix::closeMostFDs(const std::set & exceptions) #if HAVE_SYSCONF maxFD = sysconf(_SC_OPEN_MAX); #endif - for (int fd = 0; fd < maxFD; ++fd) - if (!exceptions.count(fd)) - close(fd); /* ignore result */ + for (int fd = MAX_KEPT_FD + 1; fd < maxFD; ++fd) + close(fd); /* ignore result */ } From 3fe1b60c57074ee7aad17e0147f1c53bc83c9a7c Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 21 Aug 2024 16:45:46 +0200 Subject: [PATCH 104/718] Remove dead makeMutable() function This code wasn't being compiled because the #if conditional didn't trigger. Anyway, Nix 0.15 is 15 years old so we don't need to keep this around. --- src/libstore/local-store.cc | 59 ------------------------------------- src/libstore/local-store.hh | 2 -- 2 files changed, 61 deletions(-) diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 819cee345..eeecde6e7 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -42,7 +42,6 @@ # include # include # include -# include #endif #ifdef __CYGWIN__ @@ -366,8 +365,6 @@ LocalStore::LocalStore( have performed the upgrade already. */ curSchema = getSchema(); - if (curSchema < 7) { upgradeStore7(); } - openDB(*state, false); if (curSchema < 8) { @@ -1596,62 +1593,6 @@ std::optional LocalStore::isTrustedClient() } -#if defined(FS_IOC_SETFLAGS) && defined(FS_IOC_GETFLAGS) && defined(FS_IMMUTABLE_FL) - -static void makeMutable(const Path & path) -{ - checkInterrupt(); - - auto st = lstat(path); - - if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode)) return; - - if (S_ISDIR(st.st_mode)) { - for (auto & i : readDirectory(path)) - makeMutable(path + "/" + i.name); - } - - /* The O_NOFOLLOW is important to prevent us from changing the - mutable bit on the target of a symlink (which would be a - security hole). */ - AutoCloseFD fd = open(path.c_str(), O_RDONLY | O_NOFOLLOW -#ifndef _WIN32 - | O_CLOEXEC -#endif - ); - if (fd == INVALID_DESCRIPTOR) { - if (errno == ELOOP) return; // it's a symlink - throw SysError("opening file '%1%'", path); - } - - unsigned int flags = 0, old; - - /* Silently ignore errors getting/setting the immutable flag so - that we work correctly on filesystems that don't support it. */ - if (ioctl(fd, FS_IOC_GETFLAGS, &flags)) return; - old = flags; - flags &= ~FS_IMMUTABLE_FL; - if (old == flags) return; - if (ioctl(fd, FS_IOC_SETFLAGS, &flags)) return; -} - -/* Upgrade from schema 6 (Nix 0.15) to schema 7 (Nix >= 1.3). */ -void LocalStore::upgradeStore7() -{ - if (!isRootUser()) return; - printInfo("removing immutable bits from the Nix store (this may take a while)..."); - makeMutable(realStoreDir); -} - -#else - -void LocalStore::upgradeStore7() -{ -} - -#endif - - void LocalStore::vacuumDB() { auto state(_state.lock()); diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh index a03cfc03b..21848cc4d 100644 --- a/src/libstore/local-store.hh +++ b/src/libstore/local-store.hh @@ -373,8 +373,6 @@ private: void updatePathInfo(State & state, const ValidPathInfo & info); - void upgradeStore6(); - void upgradeStore7(); PathSet queryValidPathsOld(); ValidPathInfo queryPathInfoOld(const Path & path); From efbf4996355f4ce846c38dbeb9b5b7a4b418f322 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 21 Aug 2024 16:50:18 +0200 Subject: [PATCH 105/718] Remove redundant " --- src/libstore/globals.hh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh index 7a307f894..ec0c69851 100644 --- a/src/libstore/globals.hh +++ b/src/libstore/globals.hh @@ -401,9 +401,9 @@ public: Setting fsyncStorePaths{this, false, "fsync-store-paths", R"( - "Whether to call `fsync()` on store paths before registering them, to - flush them to disk. This improves robustness in case of system crashes, - but reduces performance. The default is `false`. + Whether to call `fsync()` on store paths before registering them, to + flush them to disk. This improves robustness in case of system crashes, + but reduces performance. The default is `false`. )"}; Setting useSQLiteWAL{this, !isWSL1(), "use-sqlite-wal", From e8752ca57a92ec31e250d740307423134b96814f Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 21 Aug 2024 17:05:36 +0200 Subject: [PATCH 106/718] Add FIXME --- src/libstore/globals.hh | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh index ec0c69851..e5e7024cb 100644 --- a/src/libstore/globals.hh +++ b/src/libstore/globals.hh @@ -410,6 +410,7 @@ public: "Whether SQLite should use WAL mode."}; #ifndef _WIN32 + // FIXME: remove this option, `fsync-store-paths` is faster. Setting syncBeforeRegistering{this, false, "sync-before-registering", "Whether to call `sync()` before registering a path as valid."}; #endif From 02446918f410b57bd7c1182bc1799639ba798556 Mon Sep 17 00:00:00 2001 From: Noam Yorav-Raphael Date: Wed, 21 Aug 2024 18:29:45 +0300 Subject: [PATCH 107/718] Add changelog for homeless-shelter-to-proc --- doc/manual/rl-next/homeless-shelter-to-proc.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 doc/manual/rl-next/homeless-shelter-to-proc.md diff --git a/doc/manual/rl-next/homeless-shelter-to-proc.md b/doc/manual/rl-next/homeless-shelter-to-proc.md new file mode 100644 index 000000000..4f9519eb4 --- /dev/null +++ b/doc/manual/rl-next/homeless-shelter-to-proc.md @@ -0,0 +1,9 @@ +--- +synopsis: On linux, set $HOME=/proc/homeless-shelter instead of /homeless-shelter +issues: [8313, 11295] +prs: [11300] +--- + +When building, $HOME is set to a non-existing dir. Previously it was always set to `/homeless-shelter`. After a build, the builder verifies that it doesn't exist. In some scenarios (specifically when using the linux sandbox with a single-user installation), it is possible to create the `/homeless-shelter` directory, and some tools will create it, resulting in a build error. + +Now, on Linux, $HOME is set to `/proc/homeless-shelter`. This directory can never be created, since `/proc` is a virtual filesystem. This resolves the issue. From a643c9b1f9270183fd5b0fe49711cf507272101d Mon Sep 17 00:00:00 2001 From: Noam Yorav-Raphael Date: Wed, 21 Aug 2024 19:58:16 +0300 Subject: [PATCH 108/718] Update doc/manual/rl-next/homeless-shelter-to-proc.md Co-authored-by: Eelco Dolstra --- doc/manual/rl-next/homeless-shelter-to-proc.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/manual/rl-next/homeless-shelter-to-proc.md b/doc/manual/rl-next/homeless-shelter-to-proc.md index 4f9519eb4..73213c0df 100644 --- a/doc/manual/rl-next/homeless-shelter-to-proc.md +++ b/doc/manual/rl-next/homeless-shelter-to-proc.md @@ -4,6 +4,6 @@ issues: [8313, 11295] prs: [11300] --- -When building, $HOME is set to a non-existing dir. Previously it was always set to `/homeless-shelter`. After a build, the builder verifies that it doesn't exist. In some scenarios (specifically when using the linux sandbox with a single-user installation), it is possible to create the `/homeless-shelter` directory, and some tools will create it, resulting in a build error. +When building, $HOME is set to a non-existing directory. Previously it was always set to `/homeless-shelter`. Before a build, Nix verifies that it doesn't exist. In some scenarios (specifically when using the Linux sandbox with a single-user installation), it is possible to create the `/homeless-shelter` directory, and some tools will create it, resulting in a build error. Now, on Linux, $HOME is set to `/proc/homeless-shelter`. This directory can never be created, since `/proc` is a virtual filesystem. This resolves the issue. From ce7cf4a2d32d3221eed50f087fe53f17f5c5ca12 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 21 Aug 2024 19:50:24 +0200 Subject: [PATCH 109/718] Update src/libutil/serialise.hh Co-authored-by: John Ericson --- src/libutil/serialise.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libutil/serialise.hh b/src/libutil/serialise.hh index 964b9a30d..36e3e68e3 100644 --- a/src/libutil/serialise.hh +++ b/src/libutil/serialise.hh @@ -533,7 +533,7 @@ struct FramedSource : Source * Write as chunks in the format expected by FramedSource. * * The `checkError` function can be used to terminate the stream when you - * detect that an error has occurred. + * detect that an error has occurred. It does so by throwing an exception. */ struct FramedSink : nix::BufferedSink { From 270c8469d712a232915e736eeecacca696f77a01 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 21 Aug 2024 20:54:02 +0200 Subject: [PATCH 110/718] select() -> poll() for Windows compat --- src/libutil/serialise.cc | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/libutil/serialise.cc b/src/libutil/serialise.cc index 1e30d27b7..056c33531 100644 --- a/src/libutil/serialise.cc +++ b/src/libutil/serialise.cc @@ -165,15 +165,20 @@ bool FdSource::hasData() if (BufferedSource::hasData()) return true; while (true) { - struct pollfd fds[1]; - fds[0].fd = fd; - fds[0].events = POLLIN; - auto n = poll(fds, 1, 0); + fd_set fds; + FD_ZERO(&fds); + FD_SET(fd, &fds); + + struct timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = 0; + + auto n = select(fd + 1, &fds, nullptr, nullptr, &timeout); if (n < 0) { if (errno == EINTR) continue; throw SysError("polling file descriptor"); } - return n == 1 && (fds[0].events & POLLIN); + return FD_ISSET(fd, &fds); } } From fac756fed4c0c5c4c78924ed8ecc900809f8c596 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 21 Aug 2024 21:08:26 +0200 Subject: [PATCH 111/718] Add FIXME --- src/libstore/daemon.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libstore/daemon.cc b/src/libstore/daemon.cc index ef3326cd6..6079eae7b 100644 --- a/src/libstore/daemon.cc +++ b/src/libstore/daemon.cc @@ -402,6 +402,9 @@ static void performOp(TunnelLogger * logger, ref store, logger->startWork(); auto pathInfo = [&]() { // NB: FramedSource must be out of scope before logger->stopWork(); + // FIXME: this means that if there is an error + // half-way through, the client will keep sending + // data, since we haven't sent it the error yet. auto [contentAddressMethod, hashAlgo] = ContentAddressMethod::parseWithAlgo(camStr); FramedSource source(conn.from); FileSerialisationMethod dumpMethod; From 528e4904181072f9abc1c5657ba40fa181a27e48 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 22 Aug 2024 13:47:33 +0200 Subject: [PATCH 112/718] Disable the static build in CI GHA builds are now frequently timing out, so let's not do this. If wanted, it could be done in a separate job. --- flake.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index cded6c3a9..d7a6eead9 100644 --- a/flake.nix +++ b/flake.nix @@ -195,7 +195,8 @@ } // lib.optionalAttrs (! nixpkgsFor.${system}.native.stdenv.hostPlatform.isDarwin) { # TODO: enable static builds for darwin, blocked on: # https://github.com/NixOS/nixpkgs/issues/320448 - "static-" = nixpkgsFor.${system}.static; + # TODO: disabled to speed up GHA CI. + #"static-" = nixpkgsFor.${system}.static; }) (nixpkgsPrefix: nixpkgs: flatMapAttrs nixpkgs.nixComponents From 3af73bae5c3d21d74718d5da08c93eb1f7fe8636 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 22 Aug 2024 13:48:46 +0200 Subject: [PATCH 113/718] Remove checks for nixComponents We are currently building Nix twice in the main GHA CI job, which is frequently timing out. Obviously, we want this to be fast, so only do the main build for now. --- flake.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/flake.nix b/flake.nix index d7a6eead9..f5893d8f6 100644 --- a/flake.nix +++ b/flake.nix @@ -189,6 +189,7 @@ # system, we should reenable this. #perlBindings = self.hydraJobs.perlBindings.${system}; } + /* # Add "passthru" tests // flatMapAttrs ({ "" = nixpkgsFor.${system}.native; @@ -210,6 +211,7 @@ "${nixpkgsPrefix}nix-functional-tests" = nixpkgs.nixComponents.nix-functional-tests; } ) + */ // devFlake.checks.${system} or {} ); From 21a164aa0399b16f8484f9f2d70036cf7e6a28f9 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 22 Aug 2024 15:26:34 +0200 Subject: [PATCH 114/718] Fix hang Signed-off-by: Eelco Dolstra --- src/libutil/file-system.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libutil/file-system.cc b/src/libutil/file-system.cc index ded7335f9..aa5f3670c 100644 --- a/src/libutil/file-system.cc +++ b/src/libutil/file-system.cc @@ -339,7 +339,7 @@ void recursiveSync(const Path & path) while (!dirsToEnumerate.empty()) { auto currentDir = dirsToEnumerate.back(); dirsToEnumerate.pop_back(); - for (auto & entry : std::filesystem::directory_iterator(path)) { + for (auto & entry : std::filesystem::directory_iterator(currentDir)) { auto st = entry.symlink_status(); if (fs::is_directory(st)) { dirsToEnumerate.emplace_back(entry.path()); From 9ff0b55d4ef8c810455035e5735488349912999f Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 22 Aug 2024 15:34:19 +0200 Subject: [PATCH 115/718] Add a VM test for fsync-store-paths Based on https://github.com/squalus/nix-durability-tests/blob/master/flake.nix. --- tests/nixos/default.nix | 2 ++ tests/nixos/fsync.nix | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 tests/nixos/fsync.nix diff --git a/tests/nixos/default.nix b/tests/nixos/default.nix index 3fa341ef1..40d29b371 100644 --- a/tests/nixos/default.nix +++ b/tests/nixos/default.nix @@ -155,4 +155,6 @@ in user-sandboxing = runNixOSTestFor "x86_64-linux" ./user-sandboxing; s3-binary-cache-store = runNixOSTestFor "x86_64-linux" ./s3-binary-cache-store.nix; + + fsync = runNixOSTestFor "x86_64-linux" ./fsync.nix; } diff --git a/tests/nixos/fsync.nix b/tests/nixos/fsync.nix new file mode 100644 index 000000000..99ac2b25d --- /dev/null +++ b/tests/nixos/fsync.nix @@ -0,0 +1,39 @@ +{ lib, config, nixpkgs, pkgs, ... }: + +let + pkg1 = pkgs.go; +in + +{ + name = "fsync"; + + nodes.machine = + { config, lib, pkgs, ... }: + { virtualisation.emptyDiskImages = [ 1024 ]; + environment.systemPackages = [ pkg1 ]; + nix.settings.experimental-features = [ "nix-command" ]; + nix.settings.fsync-store-paths = true; + nix.settings.require-sigs = false; + boot.supportedFilesystems = [ "ext4" "btrfs" "xfs" ]; + }; + + testScript = { nodes }: '' + # fmt: off + for fs in ("ext4", "btrfs", "xfs"): + machine.succeed("mkfs.{} {} /dev/vdb".format(fs, "-F" if fs == "ext4" else "-f")) + machine.succeed("mkdir -p /mnt") + machine.succeed("mount /dev/vdb /mnt") + machine.succeed("sync") + machine.succeed("nix copy --offline ${pkg1} --to /mnt") + machine.crash() + + machine.start() + machine.wait_for_unit("multi-user.target") + machine.succeed("mkdir -p /mnt") + machine.succeed("mount /dev/vdb /mnt") + machine.succeed("nix path-info --offline --store /mnt ${pkg1}") + machine.succeed("nix store verify --all --store /mnt --no-trust") + + machine.succeed("umount /dev/vdb") + ''; +} From 71e7188e07b807497c5d93fa20d34c6bf731f9c1 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 22 Aug 2024 15:48:36 +0200 Subject: [PATCH 116/718] Add release note --- doc/manual/rl-next/fsync-store-paths.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 doc/manual/rl-next/fsync-store-paths.md diff --git a/doc/manual/rl-next/fsync-store-paths.md b/doc/manual/rl-next/fsync-store-paths.md new file mode 100644 index 000000000..0e9e7f7f2 --- /dev/null +++ b/doc/manual/rl-next/fsync-store-paths.md @@ -0,0 +1,9 @@ +--- +synopsis: Add setting `fsync-store-paths` +issues: [1218] +prs: [7126] +--- + +Nix now has a setting `fsync-store-paths` that ensures that new store paths are durably written to disk before they are registered as "valid" in Nix's database. This can prevent Nix store corruption if the system crashes or there is a power loss. This setting defaults to `false`. + +Author: [**@squalus**](https://github.com/squalus) From 168bf9c3cdcf458060b17b4b8df06a28e28d5c69 Mon Sep 17 00:00:00 2001 From: aleksana Date: Thu, 22 Aug 2024 23:06:43 +0800 Subject: [PATCH 117/718] README: update CI badge The `Test` workflow was renamed to `CI` in https://github.com/NixOS/nix/commit/9aa486c4be2801a25847b9c75012054d04e792d0. It still seems to be showing the status it was last running on the master branch. This information is misleading and should be corrected. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ab647e53b..54a6fcc39 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Nix [![Open Collective supporters](https://opencollective.com/nixos/tiers/supporter/badge.svg?label=Supporters&color=brightgreen)](https://opencollective.com/nixos) -[![Test](https://github.com/NixOS/nix/workflows/Test/badge.svg)](https://github.com/NixOS/nix/actions) +[![CI](https://github.com/NixOS/nix/workflows/CI/badge.svg)](https://github.com/NixOS/nix/actions/workflows/ci.yml) Nix is a powerful package manager for Linux and other Unix systems that makes package management reliable and reproducible. Please refer to the [Nix manual](https://nix.dev/reference/nix-manual) From 5d28a0032282970788f723910f40a67e402d2e09 Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Mon, 19 Aug 2024 16:33:23 +0300 Subject: [PATCH 118/718] Add nix_store_copy_closure to libstore-c --- src/libstore-c/nix_api_store.cc | 12 ++++++++++++ src/libstore-c/nix_api_store.h | 10 ++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/libstore-c/nix_api_store.cc b/src/libstore-c/nix_api_store.cc index 79841ca49..fb7391276 100644 --- a/src/libstore-c/nix_api_store.cc +++ b/src/libstore-c/nix_api_store.cc @@ -144,3 +144,15 @@ StorePath * nix_store_path_clone(const StorePath * p) { return new StorePath{p->path}; } + +nix_err nix_store_copy_closure(nix_c_context * context, Store * srcStore, Store * dstStore, StorePath * path) +{ + if (context) + context->last_err_code = NIX_OK; + try { + nix::RealisedPath::Set paths; + paths.insert(path->path); + nix::copyClosure(*srcStore->ptr, *dstStore->ptr, paths); + } + NIXC_CATCH_ERRS +} diff --git a/src/libstore-c/nix_api_store.h b/src/libstore-c/nix_api_store.h index 4b2134457..93208cb7c 100644 --- a/src/libstore-c/nix_api_store.h +++ b/src/libstore-c/nix_api_store.h @@ -161,6 +161,16 @@ nix_err nix_store_realise( nix_err nix_store_get_version(nix_c_context * context, Store * store, nix_get_string_callback callback, void * user_data); +/** + * @brief Copy the closure of `path` from `srcStore` to `dstStore`. + * + * @param[out] context Optional, stores error information + * @param[in] srcStore nix source store reference + * @param[in] srcStore nix destination store reference + * @param[in] path Path to copy + */ +nix_err nix_store_copy_closure(nix_c_context * context, Store * srcStore, Store * dstStore, StorePath * path); + // cffi end #ifdef __cplusplus } From 2a14a20bb3c8db049e48b6c7887909d378e92ef4 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Fri, 23 Aug 2024 20:47:22 +0200 Subject: [PATCH 119/718] packaging: Expose libs This exposes the libraries in a way that is easily replicated in Nixpkgs, without having to create a package set within a package set. --- packaging/everything.nix | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/packaging/everything.nix b/packaging/everything.nix index 8c8ce6611..6dae7f1c2 100644 --- a/packaging/everything.nix +++ b/packaging/everything.nix @@ -76,7 +76,7 @@ ] ++ lib.optionals (stdenv.buildPlatform.canExecute stdenv.hostPlatform) [ nix-perl-bindings ]; -}).overrideAttrs (_: { +}).overrideAttrs (finalAttrs: prevAttrs: { doCheck = true; doInstallCheck = true; @@ -90,4 +90,37 @@ installCheckInputs = [ nix-functional-tests ]; + passthru = prevAttrs.passthru // { + /** + These are the libraries that are part of the Nix project. They are used + by the Nix CLI and other tools. + + If you need to use these libraries in your project, we recommend to use + the `-c` C API libraries exclusively, if possible. + + We also recommend that you build the complete package to ensure that the unit tests pass. + You could do this in CI, or by passing it in an unused environment variable. e.g in a `mkDerivation` call: + + ```nix + buildInputs = [ nix.libs.nix-util-c nix.libs.nix-store-c ]; + # Make sure the nix libs we use are ok + unusedInputsForTests = [ nix ]; + disallowedReferences = nix.all; + ``` + */ + libs = { + inherit + nix-util + nix-util-c + nix-store + nix-store-c + nix-fetchers + nix-expr + nix-expr-c + nix-flake + nix-main + nix-main-c + ; + }; + }; }) From c9f45677b585dabb3a83570e21426257d92746bd Mon Sep 17 00:00:00 2001 From: Bryan Honof Date: Wed, 21 Aug 2024 16:57:06 +0200 Subject: [PATCH 120/718] fix: Error on malformed URI query parameter Signed-off-by: Bryan Honof --- src/libutil/url.cc | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/libutil/url.cc b/src/libutil/url.cc index bcbe9ea4e..78c832440 100644 --- a/src/libutil/url.cc +++ b/src/libutil/url.cc @@ -79,10 +79,15 @@ std::map decodeQuery(const std::string & query) for (auto s : tokenizeString(query, "&")) { auto e = s.find('='); - if (e != std::string::npos) - result.emplace( - s.substr(0, e), - percentDecode(std::string_view(s).substr(e + 1))); + + if (e == std::string::npos) { + warn("invalid URI query '%s', did you forget an equals sign `=`?", s); + continue; + } + + result.emplace( + s.substr(0, e), + percentDecode(std::string_view(s).substr(e + 1))); } return result; From 096bec8eb27a534b54c4cd810a5a9d8250703a0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sun, 25 Aug 2024 09:04:47 +0200 Subject: [PATCH 121/718] Revert "Merge pull request #11300 from noamraph/homeless-shelter-to-proc" This reverts commit 43e82c944671ad7ce5da1b75991a4c1f48b545c4, reversing changes made to d79b9bdec0557315b0897707394339082cec004c. Since /proc/homeless-shelter returns a different errno than /homeless-shelter (ENOENT vs EACCES), we need to revert this change. Software depends on this error code i.e. cargo and therefore breaks. --- doc/manual/src/language/derivations.md | 3 +-- src/libstore/unix/build/local-derivation-goal.cc | 7 ------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/doc/manual/src/language/derivations.md b/doc/manual/src/language/derivations.md index b57f6bb6a..8e3f0f791 100644 --- a/doc/manual/src/language/derivations.md +++ b/doc/manual/src/language/derivations.md @@ -264,8 +264,7 @@ The [`builder`](#attr-builder) is executed as follows: - `PATH` is set to `/path-not-set` to prevent shells from initialising it to their built-in default value. - - `HOME` is set to `/proc/homeless-shelter` on Linux and `/homeless-shelter` - on OSX, to prevent programs from + - `HOME` is set to `/homeless-shelter` to prevent programs from using `/etc/passwd` or the like to find the user's home directory, which could cause impurity. Usually, when `HOME` is set, it is used as the location of the home directory, even if diff --git a/src/libstore/unix/build/local-derivation-goal.cc b/src/libstore/unix/build/local-derivation-goal.cc index e1035fbdd..d3482df17 100644 --- a/src/libstore/unix/build/local-derivation-goal.cc +++ b/src/libstore/unix/build/local-derivation-goal.cc @@ -102,14 +102,7 @@ void handleDiffHook( } } -// We want $HOME to be un-creatable in the sandbox. On Linux, -// you can't create anything inside /proc since it's a virtual filesystem. -// On Darwin it seems that `/homeless-shelter` is good enough. -#if __linux__ -const Path LocalDerivationGoal::homeDir = "/proc/homeless-shelter"; -#else const Path LocalDerivationGoal::homeDir = "/homeless-shelter"; -#endif LocalDerivationGoal::~LocalDerivationGoal() From 90560eeccc990315fa44bf18e78ed69aa7d552a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sun, 25 Aug 2024 09:03:59 +0200 Subject: [PATCH 122/718] Revert "Merge pull request #11350 from noamraph/homeless-shelter-to-proc-changelog" This reverts commit fa49d2e356d44d416ac86d2286189e8f5f6878ba, reversing changes made to af26fe39344faff70e009d980820b8667c319cb2. --- doc/manual/rl-next/homeless-shelter-to-proc.md | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 doc/manual/rl-next/homeless-shelter-to-proc.md diff --git a/doc/manual/rl-next/homeless-shelter-to-proc.md b/doc/manual/rl-next/homeless-shelter-to-proc.md deleted file mode 100644 index 73213c0df..000000000 --- a/doc/manual/rl-next/homeless-shelter-to-proc.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -synopsis: On linux, set $HOME=/proc/homeless-shelter instead of /homeless-shelter -issues: [8313, 11295] -prs: [11300] ---- - -When building, $HOME is set to a non-existing directory. Previously it was always set to `/homeless-shelter`. Before a build, Nix verifies that it doesn't exist. In some scenarios (specifically when using the Linux sandbox with a single-user installation), it is possible to create the `/homeless-shelter` directory, and some tools will create it, resulting in a build error. - -Now, on Linux, $HOME is set to `/proc/homeless-shelter`. This directory can never be created, since `/proc` is a virtual filesystem. This resolves the issue. From 93a8b06070306df388a168a2285a3476070c7399 Mon Sep 17 00:00:00 2001 From: Emily Date: Mon, 26 Aug 2024 05:26:49 +0100 Subject: [PATCH 123/718] sequoia-nixbld-user-migration: increment base UID by 1 --- scripts/sequoia-nixbld-user-migration.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/sequoia-nixbld-user-migration.sh b/scripts/sequoia-nixbld-user-migration.sh index 9208a3605..644249192 100755 --- a/scripts/sequoia-nixbld-user-migration.sh +++ b/scripts/sequoia-nixbld-user-migration.sh @@ -2,7 +2,7 @@ set -x -((NEW_NIX_FIRST_BUILD_UID=350)) +((NEW_NIX_FIRST_BUILD_UID=351)) ((TEMP_NIX_FIRST_BUILD_UID=31000)) nix_user_n() { From 77ddcbe12e169051f9bad1ab5e7581b148a94883 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 26 Aug 2024 16:15:13 +0200 Subject: [PATCH 124/718] getDoc: Explain why we partially apply __functor --- src/libexpr/eval.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index b87d96be0..ca41a9944 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -621,6 +621,11 @@ std::optional EvalState::getDoc(Value & v) Value & functor = *v.attrs()->find(sFunctor)->value; Value * vp = &v; Value partiallyApplied; + // The first paramater is not user-provided, and may be + // handled by code that is opaque to the user, like lib.const = x: y: y; + // So preferably we show docs that are relevant to the + // "partially applied" function returned by e.g. `const`. + // We apply the first argument: callFunction(functor, 1, &vp, partiallyApplied, noPos); auto _level = addCallDepth(noPos); return getDoc(partiallyApplied); From 11cf29b15c8ea144035eb6a9d9f31bb05eee2048 Mon Sep 17 00:00:00 2001 From: Emily Date: Mon, 26 Aug 2024 17:59:58 +0100 Subject: [PATCH 125/718] install-darwin: increment base UID by 1 (#15) --- scripts/bigsur-nixbld-user-migration.sh | 2 +- scripts/install-darwin-multi-user.sh | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/bigsur-nixbld-user-migration.sh b/scripts/bigsur-nixbld-user-migration.sh index bc42e02e6..57f65da72 100755 --- a/scripts/bigsur-nixbld-user-migration.sh +++ b/scripts/bigsur-nixbld-user-migration.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -((NEW_NIX_FIRST_BUILD_UID=350)) +((NEW_NIX_FIRST_BUILD_UID=351)) id_available(){ dscl . list /Users UniqueID | grep -E '\b'"$1"'\b' >/dev/null diff --git a/scripts/install-darwin-multi-user.sh b/scripts/install-darwin-multi-user.sh index bd1a54ad8..89c66b8f4 100644 --- a/scripts/install-darwin-multi-user.sh +++ b/scripts/install-darwin-multi-user.sh @@ -9,11 +9,11 @@ set -o pipefail # - we changed UID to 301 because Big Sur updates failed into recovery mode # we're targeting the 200-400 UID range for role users mentioned in the # usage note for sysadminctl -# - we changed UID to 350 because Sequoia now uses UIDs 300-304 for its own +# - we changed UID to 351 because Sequoia now uses UIDs 300-304 for its own # daemon users # - we changed GID to 350 alongside above just because it hides the nixbld # group from the Users & Groups settings panel :) -export NIX_FIRST_BUILD_UID="${NIX_FIRST_BUILD_UID:-350}" +export NIX_FIRST_BUILD_UID="${NIX_FIRST_BUILD_UID:-351}" export NIX_BUILD_GROUP_ID="${NIX_BUILD_GROUP_ID:-350}" export NIX_BUILD_USER_NAME_TEMPLATE="_nixbld%d" From dbabfc92d4e1864f793f167a438e532673afdc14 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 26 Aug 2024 15:42:09 -0400 Subject: [PATCH 126/718] Make sure we have an `execvpe` on Windows too Necessary to fix a build (that was already broken in other ways) after PR #11021. --- src/libutil/{unix => }/exec.hh | 7 ++++++- src/libutil/meson.build | 1 + src/libutil/unix/meson.build | 1 - src/libutil/unix/processes.cc | 8 +++++--- src/libutil/windows/processes.cc | 8 ++++++++ 5 files changed, 20 insertions(+), 5 deletions(-) rename src/libutil/{unix => }/exec.hh (53%) diff --git a/src/libutil/unix/exec.hh b/src/libutil/exec.hh similarity index 53% rename from src/libutil/unix/exec.hh rename to src/libutil/exec.hh index e6b80889a..405e19268 100644 --- a/src/libutil/unix/exec.hh +++ b/src/libutil/exec.hh @@ -1,5 +1,7 @@ #pragma once +#include "os-string.hh" + namespace nix { /** @@ -8,6 +10,9 @@ namespace nix { * * We use our own implementation unconditionally for consistency. */ -int execvpe(const char * file0, char * const argv[], char * const envp[]); +int execvpe( + const OsString::value_type * file0, + const OsString::value_type * const argv[], + const OsString::value_type * const envp[]); } diff --git a/src/libutil/meson.build b/src/libutil/meson.build index 200eeb4e9..72ff461ca 100644 --- a/src/libutil/meson.build +++ b/src/libutil/meson.build @@ -129,6 +129,7 @@ sources = files( 'english.cc', 'environment-variables.cc', 'error.cc', + 'exec.hh', 'executable-path.cc', 'exit.cc', 'experimental-features.cc', diff --git a/src/libutil/unix/meson.build b/src/libutil/unix/meson.build index d36152db9..1c5bf27fb 100644 --- a/src/libutil/unix/meson.build +++ b/src/libutil/unix/meson.build @@ -13,7 +13,6 @@ sources += files( include_dirs += include_directories('.') headers += files( - 'exec.hh', 'monitor-fd.hh', 'signals-impl.hh', ) diff --git a/src/libutil/unix/processes.cc b/src/libutil/unix/processes.cc index 09acba35a..43d9179d9 100644 --- a/src/libutil/unix/processes.cc +++ b/src/libutil/unix/processes.cc @@ -420,10 +420,12 @@ bool statusOk(int status) return WIFEXITED(status) && WEXITSTATUS(status) == 0; } -int execvpe(const char * file0, char * const argv[], char * const envp[]) +int execvpe(const char * file0, const char * const argv[], const char * const envp[]) { - auto file = ExecutablePath::load().findPath(file0).string(); - return execve(file.c_str(), argv, envp); + auto file = ExecutablePath::load().findPath(file0); + // `const_cast` is safe. See the note in + // https://pubs.opengroup.org/onlinepubs/9799919799/functions/exec.html + return execve(file.c_str(), const_cast(argv), const_cast(envp)); } } diff --git a/src/libutil/windows/processes.cc b/src/libutil/windows/processes.cc index 9cd714f84..7f34c5632 100644 --- a/src/libutil/windows/processes.cc +++ b/src/libutil/windows/processes.cc @@ -1,6 +1,7 @@ #include "current-process.hh" #include "environment-variables.hh" #include "error.hh" +#include "executable-path.hh" #include "file-descriptor.hh" #include "file-path.hh" #include "signals.hh" @@ -377,4 +378,11 @@ bool statusOk(int status) { return status == 0; } + +int execvpe(const wchar_t * file0, const wchar_t * const argv[], const wchar_t * const envp[]) +{ + auto file = ExecutablePath::load().findPath(file0); + return _wexecve(file.c_str(), argv, envp); +} + } From a97a08411c4e34323b48e95ed593bb53d67bde23 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 26 Aug 2024 12:24:37 -0400 Subject: [PATCH 127/718] More support for `std::filepath` in libnixutil We're not replacing `Path` in exposed definitions in many cases, but just adding alternatives. This will allow us to "top down" change `Path` to `std::fileysystem::path`, and then we can remove the `Path`-using utilities which will become unused. Also add some test files which we forgot to include in the libutil unit tests `meson.build`. Co-Authored-By: siddhantCodes --- src/libcmd/common-eval-args.cc | 6 +- src/libcmd/installables.cc | 4 +- src/libcmd/repl.cc | 4 +- src/libexpr/parser.y | 2 +- src/libstore/gc.cc | 2 +- src/libstore/local-overlay-store.cc | 2 +- src/libutil/args.hh | 22 ++++++ src/libutil/exec.hh | 5 +- src/libutil/executable-path.cc | 6 +- src/libutil/executable-path.hh | 6 +- src/libutil/file-system.cc | 32 ++++++--- src/libutil/file-system.hh | 69 ++++++++++++++++++- src/libutil/linux/namespaces.cc | 2 +- src/libutil/os-string.hh | 17 +++-- src/libutil/posix-source-accessor.cc | 2 +- src/libutil/serialise.cc | 6 +- src/libutil/strings.cc | 4 +- src/libutil/unix/users.cc | 2 + src/nix/bundle.cc | 4 +- src/nix/config-check.cc | 4 +- src/nix/develop.cc | 6 +- src/nix/flake.cc | 10 +-- src/nix/run.cc | 18 ++--- src/nix/self-exe.cc | 4 +- tests/unit/libfetchers/public-key.cc | 6 +- .../libstore-support/tests/nix_api_store.hh | 2 +- tests/unit/libstore-support/tests/protocol.hh | 6 +- .../libstore/derivation-advanced-attrs.cc | 6 +- tests/unit/libstore/derivation.cc | 6 +- tests/unit/libstore/machines.cc | 20 +++--- tests/unit/libstore/nar-info.cc | 6 +- tests/unit/libstore/path-info.cc | 6 +- tests/unit/libstore/store-reference.cc | 6 +- .../libutil-support/tests/characterization.hh | 10 +-- tests/unit/libutil/file-system.cc | 56 ++++++++------- tests/unit/libutil/git.cc | 6 +- tests/unit/libutil/meson.build | 3 + 37 files changed, 258 insertions(+), 120 deletions(-) diff --git a/src/libcmd/common-eval-args.cc b/src/libcmd/common-eval-args.cc index ae9994a05..ccbf957d9 100644 --- a/src/libcmd/common-eval-args.cc +++ b/src/libcmd/common-eval-args.cc @@ -18,6 +18,8 @@ namespace nix { +namespace fs { using namespace std::filesystem; } + fetchers::Settings fetchSettings; static GlobalConfig::Register rFetchSettings(&fetchSettings); @@ -119,8 +121,8 @@ MixEvalArgs::MixEvalArgs() .category = category, .labels = {"original-ref", "resolved-ref"}, .handler = {[&](std::string _from, std::string _to) { - auto from = parseFlakeRef(fetchSettings, _from, absPath(".")); - auto to = parseFlakeRef(fetchSettings, _to, absPath(".")); + auto from = parseFlakeRef(fetchSettings, _from, fs::current_path().string()); + auto to = parseFlakeRef(fetchSettings, _to, fs::current_path().string()); fetchers::Attrs extraAttrs; if (to.subdir != "") extraAttrs["dir"] = to.subdir; fetchers::overrideRegistry(from.input, to.input, extraAttrs); diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc index 0fe956ec0..22e7eb546 100644 --- a/src/libcmd/installables.cc +++ b/src/libcmd/installables.cc @@ -31,6 +31,8 @@ namespace nix { +namespace fs { using namespace std::filesystem; } + void completeFlakeInputPath( AddCompletions & completions, ref evalState, @@ -341,7 +343,7 @@ void completeFlakeRefWithFragment( auto flakeRefS = std::string(prefix.substr(0, hash)); // TODO: ideally this would use the command base directory instead of assuming ".". - auto flakeRef = parseFlakeRef(fetchSettings, expandTilde(flakeRefS), absPath(".")); + auto flakeRef = parseFlakeRef(fetchSettings, expandTilde(flakeRefS), fs::current_path().string()); auto evalCache = openEvalCache(*evalState, std::make_shared(lockFlake( diff --git a/src/libcmd/repl.cc b/src/libcmd/repl.cc index e7c43367c..63f6c1bdd 100644 --- a/src/libcmd/repl.cc +++ b/src/libcmd/repl.cc @@ -622,7 +622,7 @@ ProcessLineResult NixRepl::processLine(std::string line) // When missing, trigger the normal exception // e.g. :doc builtins.foo // behaves like - // nix-repl> builtins.foo + // nix-repl> builtins.foo // error: attribute 'foo' missing evalString(arg, v); assert(false); @@ -720,7 +720,7 @@ void NixRepl::loadFlake(const std::string & flakeRefS) if (flakeRefS.empty()) throw Error("cannot use ':load-flake' without a path specified. (Use '.' for the current working directory.)"); - auto flakeRef = parseFlakeRef(fetchSettings, flakeRefS, absPath("."), true); + auto flakeRef = parseFlakeRef(fetchSettings, flakeRefS, std::filesystem::current_path().string(), true); if (evalSettings.pureEval && !flakeRef.input.isLocked()) throw Error("cannot use ':load-flake' on locked flake reference '%s' (use --impure to override)", flakeRefS); diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index f2ccca7fc..a79abbf16 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -350,7 +350,7 @@ string_parts_interpolated path_start : PATH { - Path path(absPath({$1.p, $1.l}, state->basePath.path.abs())); + Path path(absPath(std::string_view{$1.p, $1.l}, state->basePath.path.abs())); /* add back in the trailing '/' to the first segment */ if ($1.p[$1.l-1] == '/' && $1.l > 1) path += "/"; diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index 1494712da..91cf76366 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -333,7 +333,7 @@ static std::string quoteRegexChars(const std::string & raw) } #if __linux__ -static void readFileRoots(const char * path, UncheckedRoots & roots) +static void readFileRoots(const std::filesystem::path & path, UncheckedRoots & roots) { try { roots[readFile(path)].emplace(path); diff --git a/src/libstore/local-overlay-store.cc b/src/libstore/local-overlay-store.cc index ec2c5f4e9..b86beba2c 100644 --- a/src/libstore/local-overlay-store.cc +++ b/src/libstore/local-overlay-store.cc @@ -31,7 +31,7 @@ LocalOverlayStore::LocalOverlayStore(std::string_view scheme, PathView path, con if (checkMount.get()) { std::smatch match; std::string mountInfo; - auto mounts = readFile("/proc/self/mounts"); + auto mounts = readFile(std::filesystem::path{"/proc/self/mounts"}); auto regex = std::regex(R"((^|\n)overlay )" + realStoreDir.get() + R"( .*(\n|$))"); // Mount points can be stacked, so there might be multiple matching entries. diff --git a/src/libutil/args.hh b/src/libutil/args.hh index c0236ee3d..513b8d811 100644 --- a/src/libutil/args.hh +++ b/src/libutil/args.hh @@ -113,6 +113,16 @@ protected: , arity(1) { } + Handler(std::filesystem::path * dest) + : fun([dest](std::vector ss) { *dest = ss[0]; }) + , arity(1) + { } + + Handler(std::optional * dest) + : fun([dest](std::vector ss) { *dest = ss[0]; }) + , arity(1) + { } + template Handler(T * dest, const T & val) : fun([dest, val](std::vector ss) { *dest = val; }) @@ -283,6 +293,18 @@ public: }); } + /** + * Expect a path argument. + */ + void expectArg(const std::string & label, std::filesystem::path * dest, bool optional = false) + { + expectArgs({ + .label = label, + .optional = optional, + .handler = {dest} + }); + } + /** * Expect 0 or more arguments. */ diff --git a/src/libutil/exec.hh b/src/libutil/exec.hh index 405e19268..cbbe80c4e 100644 --- a/src/libutil/exec.hh +++ b/src/libutil/exec.hh @@ -10,9 +10,6 @@ namespace nix { * * We use our own implementation unconditionally for consistency. */ -int execvpe( - const OsString::value_type * file0, - const OsString::value_type * const argv[], - const OsString::value_type * const envp[]); +int execvpe(const OsChar * file0, const OsChar * const argv[], const OsChar * const envp[]); } diff --git a/src/libutil/executable-path.cc b/src/libutil/executable-path.cc index da71088e7..9fb5214b2 100644 --- a/src/libutil/executable-path.cc +++ b/src/libutil/executable-path.cc @@ -6,7 +6,9 @@ namespace nix { -namespace fs = std::filesystem; +namespace fs { +using namespace std::filesystem; +} constexpr static const OsStringView path_var_separator{ &ExecutablePath::separator, @@ -24,7 +26,7 @@ ExecutablePath ExecutablePath::load() ExecutablePath ExecutablePath::parse(const OsString & path) { auto strings = path.empty() ? (std::list{}) - : basicSplitString, OsString::value_type>(path, path_var_separator); + : basicSplitString, OsChar>(path, path_var_separator); std::vector ret; ret.reserve(strings.size()); diff --git a/src/libutil/executable-path.hh b/src/libutil/executable-path.hh index f46d5e212..c5cfa1c39 100644 --- a/src/libutil/executable-path.hh +++ b/src/libutil/executable-path.hh @@ -7,11 +7,15 @@ namespace nix { MakeError(ExecutableLookupError, Error); +/** + * @todo rename, it is not just good for execuatable paths, but also + * other lists of paths. + */ struct ExecutablePath { std::vector directories; - constexpr static const OsString::value_type separator = + constexpr static const OsChar separator = #ifdef WIN32 L';' #else diff --git a/src/libutil/file-system.cc b/src/libutil/file-system.cc index aa5f3670c..edcacb50a 100644 --- a/src/libutil/file-system.cc +++ b/src/libutil/file-system.cc @@ -26,10 +26,10 @@ #include "strings-inline.hh" -namespace fs = std::filesystem; - namespace nix { +namespace fs { using namespace std::filesystem; } + /** * Treat the string as possibly an absolute path, by inspecting the * start of it. Return whether it was probably intended to be @@ -73,6 +73,10 @@ Path absPath(PathView path, std::optional dir, bool resolveSymlinks) return canonPath(path, resolveSymlinks); } +std::filesystem::path absPath(const std::filesystem::path & path, bool resolveSymlinks) +{ + return absPath(path.string(), std::nullopt, resolveSymlinks); +} Path canonPath(PathView path, bool resolveSymlinks) { @@ -206,10 +210,10 @@ bool pathExists(const Path & path) return maybeLstat(path).has_value(); } -bool pathAccessible(const Path & path) +bool pathAccessible(const std::filesystem::path & path) { try { - return pathExists(path); + return pathExists(path.string()); } catch (SysError & e) { // swallow EPERM if (e.errNo == EPERM) return false; @@ -238,6 +242,11 @@ std::string readFile(const Path & path) return readFile(fd.get()); } +std::string readFile(const std::filesystem::path & path) +{ + return readFile(os_string_to_string(PathViewNG { path })); +} + void readFile(const Path & path, Sink & sink) { @@ -324,7 +333,7 @@ void recursiveSync(const Path & path) /* If it's a file, just fsync and return. */ auto st = lstat(path); if (S_ISREG(st.st_mode)) { - AutoCloseFD fd = open(path.c_str(), O_RDONLY, 0); + AutoCloseFD fd = toDescriptor(open(path.c_str(), O_RDONLY, 0)); if (!fd) throw SysError("opening file '%1%'", path); fd.fsync(); @@ -344,7 +353,7 @@ void recursiveSync(const Path & path) if (fs::is_directory(st)) { dirsToEnumerate.emplace_back(entry.path()); } else if (fs::is_regular_file(st)) { - AutoCloseFD fd = open(entry.path().c_str(), O_RDONLY, 0); + AutoCloseFD fd = toDescriptor(open(entry.path().string().c_str(), O_RDONLY, 0)); if (!fd) throw SysError("opening file '%1%'", entry.path()); fd.fsync(); @@ -355,7 +364,7 @@ void recursiveSync(const Path & path) /* Fsync all the directories. */ for (auto dir = dirsToFsync.rbegin(); dir != dirsToFsync.rend(); ++dir) { - AutoCloseFD fd = open(dir->c_str(), O_RDONLY, 0); + AutoCloseFD fd = toDescriptor(open(dir->string().c_str(), O_RDONLY, 0)); if (!fd) throw SysError("opening directory '%1%'", *dir); fd.fsync(); @@ -595,19 +604,20 @@ void createSymlink(const Path & target, const Path & link) fs::create_symlink(target, link); } -void replaceSymlink(const Path & target, const Path & link) +void replaceSymlink(const fs::path & target, const fs::path & link) { for (unsigned int n = 0; true; n++) { - Path tmp = canonPath(fmt("%s/.%d_%s", dirOf(link), n, baseNameOf(link))); + auto tmp = link.parent_path() / fs::path{fmt(".%d_%s", n, link.filename().string())}; + tmp = tmp.lexically_normal(); try { - createSymlink(target, tmp); + fs::create_symlink(target, tmp); } catch (fs::filesystem_error & e) { if (e.code() == std::errc::file_exists) continue; throw; } - std::filesystem::rename(tmp, link); + fs::rename(tmp, link); break; } diff --git a/src/libutil/file-system.hh b/src/libutil/file-system.hh index 0f406a2de..eb3e4ec66 100644 --- a/src/libutil/file-system.hh +++ b/src/libutil/file-system.hh @@ -46,16 +46,33 @@ struct Source; * @return An absolutized path, resolving paths relative to the * specified directory, or the current directory otherwise. The path * is also canonicalised. + * + * In the process of being deprecated for `std::filesystem::absolute`. */ Path absPath(PathView path, std::optional dir = {}, bool resolveSymlinks = false); +inline Path absPath(const Path & path, + std::optional dir = {}, + bool resolveSymlinks = false) +{ + return absPath(PathView{path}, dir, resolveSymlinks); +} + +std::filesystem::path absPath(const std::filesystem::path & path, + bool resolveSymlinks = false); + /** * Canonicalise a path by removing all `.` or `..` components and * double or trailing slashes. Optionally resolves all symlink * components such that each component of the resulting path is *not* * a symbolic link. + * + * In the process of being deprecated for + * `std::filesystem::path::lexically_normal` (for the `resolveSymlinks = + * false` case), and `std::filesystem::weakly_canonical` (for the + * `resolveSymlinks = true` case). */ Path canonPath(PathView path, bool resolveSymlinks = false); @@ -64,12 +81,18 @@ Path canonPath(PathView path, bool resolveSymlinks = false); * everything before the final `/`. If the path is the root or an * immediate child thereof (e.g., `/foo`), this means `/` * is returned. + * + * In the process of being deprecated for + * `std::filesystem::path::parent_path`. */ Path dirOf(const PathView path); /** * @return the base name of the given canonical path, i.e., everything * following the final `/` (trailing slashes are removed). + * + * In the process of being deprecated for + * `std::filesystem::path::filename`. */ std::string_view baseNameOf(std::string_view path); @@ -98,20 +121,42 @@ std::optional maybeLstat(const Path & path); /** * @return true iff the given path exists. + * + * In the process of being deprecated for `fs::symlink_exists`. */ bool pathExists(const Path & path); +namespace fs { + +/** + * ``` + * symlink_exists(p) = std::filesystem::exists(std::filesystem::symlink_status(p)) + * ``` + * Missing convenience analogous to + * ``` + * std::filesystem::exists(p) = std::filesystem::exists(std::filesystem::status(p)) + * ``` + */ +inline bool symlink_exists(const std::filesystem::path & path) { + return std::filesystem::exists(std::filesystem::symlink_status(path)); +} + +} // namespace fs + /** * A version of pathExists that returns false on a permission error. * Useful for inferring default paths across directories that might not * be readable. * @return true iff the given path can be accessed and exists */ -bool pathAccessible(const Path & path); +bool pathAccessible(const std::filesystem::path & path); /** * Read the contents (target) of a symbolic link. The result is not * in any way canonicalised. + * + * In the process of being deprecated for + * `std::filesystem::read_symlink`. */ Path readLink(const Path & path); @@ -124,14 +169,23 @@ Descriptor openDirectory(const std::filesystem::path & path); * Read the contents of a file into a string. */ std::string readFile(const Path & path); +std::string readFile(const std::filesystem::path & path); void readFile(const Path & path, Sink & sink); /** * Write a string to a file. */ void writeFile(const Path & path, std::string_view s, mode_t mode = 0666, bool sync = false); +static inline void writeFile(const std::filesystem::path & path, std::string_view s, mode_t mode = 0666, bool sync = false) +{ + return writeFile(path.string(), s, mode, sync); +} void writeFile(const Path & path, Source & source, mode_t mode = 0666, bool sync = false); +static inline void writeFile(const std::filesystem::path & path, Source & source, mode_t mode = 0666, bool sync = false) +{ + return writeFile(path.string(), source, mode, sync); +} /** * Flush a path's parent directory to disk. @@ -154,6 +208,9 @@ void deletePath(const std::filesystem::path & path, uint64_t & bytesFreed); /** * Create a directory and all its parents, if necessary. + * + * In the process of being deprecated for + * `std::filesystem::create_directories`. */ void createDirs(const Path & path); inline void createDirs(PathView path) @@ -192,13 +249,21 @@ void setWriteTime(const std::filesystem::path & path, const struct stat & st); /** * Create a symlink. + * + * In the process of being deprecated for + * `std::filesystem::create_symlink`. */ void createSymlink(const Path & target, const Path & link); /** * Atomically create or replace a symlink. */ -void replaceSymlink(const Path & target, const Path & link); +void replaceSymlink(const std::filesystem::path & target, const std::filesystem::path & link); + +inline void replaceSymlink(const Path & target, const Path & link) +{ + return replaceSymlink(std::filesystem::path{target}, std::filesystem::path{link}); +} /** * Similar to 'renameFile', but fallback to a copy+remove if `src` and `dst` diff --git a/src/libutil/linux/namespaces.cc b/src/libutil/linux/namespaces.cc index d4766cbba..c5e21dffc 100644 --- a/src/libutil/linux/namespaces.cc +++ b/src/libutil/linux/namespaces.cc @@ -118,7 +118,7 @@ void saveMountNamespace() void restoreMountNamespace() { try { - auto savedCwd = absPath("."); + auto savedCwd = std::filesystem::current_path(); if (fdSavedMountNamespace && setns(fdSavedMountNamespace.get(), CLONE_NEWNS) == -1) throw SysError("restoring parent mount namespace"); diff --git a/src/libutil/os-string.hh b/src/libutil/os-string.hh index 0d75173e5..3e24763fb 100644 --- a/src/libutil/os-string.hh +++ b/src/libutil/os-string.hh @@ -11,21 +11,30 @@ namespace nix { * Named because it is similar to the Rust type, except it is in the * native encoding not WTF-8. * - * Same as `std::filesystem::path::string_type`, but manually defined to + * Same as `std::filesystem::path::value_type`, but manually defined to * avoid including a much more complex header. */ -using OsString = std::basic_string< +using OsChar = #if defined(_WIN32) && !defined(__CYGWIN__) wchar_t #else char #endif - >; + ; + +/** + * Named because it is similar to the Rust type, except it is in the + * native encoding not WTF-8. + * + * Same as `std::filesystem::path::string_type`, but manually defined + * for the same reason as `OsChar`. + */ +using OsString = std::basic_string; /** * `std::string_view` counterpart for `OsString`. */ -using OsStringView = std::basic_string_view; +using OsStringView = std::basic_string_view; std::string os_string_to_string(OsStringView path); diff --git a/src/libutil/posix-source-accessor.cc b/src/libutil/posix-source-accessor.cc index 2b1a485d5..8cec3388d 100644 --- a/src/libutil/posix-source-accessor.cc +++ b/src/libutil/posix-source-accessor.cc @@ -20,7 +20,7 @@ PosixSourceAccessor::PosixSourceAccessor() SourcePath PosixSourceAccessor::createAtRoot(const std::filesystem::path & path) { - std::filesystem::path path2 = absPath(path.string()); + std::filesystem::path path2 = absPath(path); return { make_ref(path2.root_path()), CanonPath { path2.relative_path().string() }, diff --git a/src/libutil/serialise.cc b/src/libutil/serialise.cc index 8a57858f5..4aa5ae385 100644 --- a/src/libutil/serialise.cc +++ b/src/libutil/serialise.cc @@ -9,6 +9,7 @@ #ifdef _WIN32 # include +# include # include "windows-error.hh" #else # include @@ -167,13 +168,14 @@ bool FdSource::hasData() while (true) { fd_set fds; FD_ZERO(&fds); - FD_SET(fd, &fds); + int fd_ = fromDescriptorReadOnly(fd); + FD_SET(fd_, &fds); struct timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = 0; - auto n = select(fd + 1, &fds, nullptr, nullptr, &timeout); + auto n = select(fd_ + 1, &fds, nullptr, nullptr, &timeout); if (n < 0) { if (errno == EINTR) continue; throw SysError("polling file descriptor"); diff --git a/src/libutil/strings.cc b/src/libutil/strings.cc index 60297228e..5cad95758 100644 --- a/src/libutil/strings.cc +++ b/src/libutil/strings.cc @@ -14,8 +14,8 @@ template std::list splitString(std::string_view s, std::string_view template std::set splitString(std::string_view s, std::string_view separators); template std::vector splitString(std::string_view s, std::string_view separators); -template std::list basicSplitString( - std::basic_string_view s, std::basic_string_view separators); +template std::list +basicSplitString(std::basic_string_view s, std::basic_string_view separators); template std::string concatStringsSep(std::string_view, const std::list &); template std::string concatStringsSep(std::string_view, const std::set &); diff --git a/src/libutil/unix/users.cc b/src/libutil/unix/users.cc index 58063a953..107a6e04f 100644 --- a/src/libutil/unix/users.cc +++ b/src/libutil/unix/users.cc @@ -9,6 +9,8 @@ namespace nix { +namespace fs { using namespace std::filesystem; } + std::string getUserName() { auto pw = getpwuid(geteuid()); diff --git a/src/nix/bundle.cc b/src/nix/bundle.cc index e152c26f2..5b7862c4e 100644 --- a/src/nix/bundle.cc +++ b/src/nix/bundle.cc @@ -6,6 +6,8 @@ #include "local-fs-store.hh" #include "eval-inline.hh" +namespace nix::fs { using namespace std::filesystem; } + using namespace nix; struct CmdBundle : InstallableValueCommand @@ -78,7 +80,7 @@ struct CmdBundle : InstallableValueCommand auto [bundlerFlakeRef, bundlerName, extendedOutputsSpec] = parseFlakeRefWithFragmentAndExtendedOutputsSpec( - fetchSettings, bundler, absPath(".")); + fetchSettings, bundler, fs::current_path().string()); const flake::LockFlags lockFlags{ .writeLockFile = false }; InstallableFlake bundler{this, evalState, std::move(bundlerFlakeRef), bundlerName, std::move(extendedOutputsSpec), diff --git a/src/nix/config-check.cc b/src/nix/config-check.cc index 1a6574de2..6cf73785e 100644 --- a/src/nix/config-check.cc +++ b/src/nix/config-check.cc @@ -10,6 +10,8 @@ #include "worker-protocol.hh" #include "executable-path.hh" +namespace nix::fs { using namespace std::filesystem; } + using namespace nix; namespace { @@ -40,8 +42,6 @@ void checkInfo(const std::string & msg) { } -namespace fs = std::filesystem; - struct CmdConfigCheck : StoreCommand { bool success = true; diff --git a/src/nix/develop.cc b/src/nix/develop.cc index effc86a0a..04672e2ad 100644 --- a/src/nix/develop.cc +++ b/src/nix/develop.cc @@ -21,6 +21,8 @@ #include "strings.hh" +namespace nix::fs { using namespace std::filesystem; } + using namespace nix; struct DevelopSettings : Config @@ -341,7 +343,7 @@ struct Common : InstallableCommand, MixProfile ref store, const BuildEnvironment & buildEnvironment, const std::filesystem::path & tmpDir, - const std::filesystem::path & outputsDir = std::filesystem::path { absPath(".") } / "outputs") + const std::filesystem::path & outputsDir = fs::path { fs::current_path() } / "outputs") { // A list of colon-separated environment variables that should be // prepended to, rather than overwritten, in order to keep the shell usable. @@ -450,7 +452,7 @@ struct Common : InstallableCommand, MixProfile auto targetFilePath = tmpDir / OS_STR(".attrs."); targetFilePath += ext; - writeFile(targetFilePath.string(), content); + writeFile(targetFilePath, content); auto fileInBuilderEnv = buildEnvironment.vars.find(envVar); assert(fileInBuilderEnv != buildEnvironment.vars.end()); diff --git a/src/nix/flake.cc b/src/nix/flake.cc index b7bbb767b..2db1e039e 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -25,7 +25,7 @@ #include "strings-inline.hh" -namespace fs = std::filesystem; +namespace nix::fs { using namespace std::filesystem; } using namespace nix; using namespace nix::flake; @@ -53,7 +53,7 @@ public: FlakeRef getFlakeRef() { - return parseFlakeRef(fetchSettings, flakeUrl, absPath(".")); //FIXME + return parseFlakeRef(fetchSettings, flakeUrl, fs::current_path().string()); //FIXME } LockedFlake lockFlake() @@ -65,7 +65,7 @@ public: { return { // Like getFlakeRef but with expandTilde calld first - parseFlakeRef(fetchSettings, expandTilde(flakeUrl), absPath(".")) + parseFlakeRef(fetchSettings, expandTilde(flakeUrl), fs::current_path().string()) }; } }; @@ -880,7 +880,7 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand auto evalState = getEvalState(); auto [templateFlakeRef, templateName] = parseFlakeRefWithFragment( - fetchSettings, templateUrl, absPath(".")); + fetchSettings, templateUrl, fs::current_path().string()); auto installable = InstallableFlake(nullptr, evalState, std::move(templateFlakeRef), templateName, ExtendedOutputsSpec::Default(), @@ -927,7 +927,7 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand } continue; } else - writeFile(to2.string(), contents); + writeFile(to2, contents); } else if (fs::is_symlink(st)) { auto target = fs::read_symlink(from2); diff --git a/src/nix/run.cc b/src/nix/run.cc index dfe7f374f..63ae8a195 100644 --- a/src/nix/run.cc +++ b/src/nix/run.cc @@ -20,6 +20,8 @@ #include +namespace nix::fs { using namespace std::filesystem; } + using namespace nix; std::string chrootHelperName = "__run_in_chroot"; @@ -170,25 +172,25 @@ void chrootHelper(int argc, char * * argv) if (!pathExists(storeDir)) { // FIXME: Use overlayfs? - std::filesystem::path tmpDir = createTempDir(); + fs::path tmpDir = createTempDir(); createDirs(tmpDir + storeDir); if (mount(realStoreDir.c_str(), (tmpDir + storeDir).c_str(), "", MS_BIND, 0) == -1) throw SysError("mounting '%s' on '%s'", realStoreDir, storeDir); - for (auto entry : std::filesystem::directory_iterator{"/"}) { + for (auto entry : fs::directory_iterator{"/"}) { checkInterrupt(); auto src = entry.path(); - Path dst = tmpDir / entry.path().filename(); + fs::path dst = tmpDir / entry.path().filename(); if (pathExists(dst)) continue; auto st = entry.symlink_status(); - if (std::filesystem::is_directory(st)) { + if (fs::is_directory(st)) { if (mkdir(dst.c_str(), 0700) == -1) throw SysError("creating directory '%s'", dst); if (mount(src.c_str(), dst.c_str(), "", MS_BIND | MS_REC, 0) == -1) throw SysError("mounting '%s' on '%s'", src, dst); - } else if (std::filesystem::is_symlink(st)) + } else if (fs::is_symlink(st)) createSymlink(readLink(src), dst); } @@ -205,9 +207,9 @@ void chrootHelper(int argc, char * * argv) if (mount(realStoreDir.c_str(), storeDir.c_str(), "", MS_BIND, 0) == -1) throw SysError("mounting '%s' on '%s'", realStoreDir, storeDir); - writeFile("/proc/self/setgroups", "deny"); - writeFile("/proc/self/uid_map", fmt("%d %d %d", uid, uid, 1)); - writeFile("/proc/self/gid_map", fmt("%d %d %d", gid, gid, 1)); + writeFile(fs::path{"/proc/self/setgroups"}, "deny"); + writeFile(fs::path{"/proc/self/uid_map"}, fmt("%d %d %d", uid, uid, 1)); + writeFile(fs::path{"/proc/self/gid_map"}, fmt("%d %d %d", gid, gid, 1)); #if __linux__ if (system != "") diff --git a/src/nix/self-exe.cc b/src/nix/self-exe.cc index a260bafd5..81a117e60 100644 --- a/src/nix/self-exe.cc +++ b/src/nix/self-exe.cc @@ -5,7 +5,9 @@ namespace nix { -namespace fs = std::filesystem; +namespace fs { +using namespace std::filesystem; +} fs::path getNixBin(std::optional binaryNameOpt) { diff --git a/tests/unit/libfetchers/public-key.cc b/tests/unit/libfetchers/public-key.cc index 8a639da9f..80796bd0f 100644 --- a/tests/unit/libfetchers/public-key.cc +++ b/tests/unit/libfetchers/public-key.cc @@ -10,11 +10,11 @@ using nlohmann::json; class PublicKeyTest : public CharacterizationTest { - Path unitTestData = getUnitTestData() + "/public-key"; + std::filesystem::path unitTestData = getUnitTestData() / "public-key"; public: - Path goldenMaster(std::string_view testStem) const override { - return unitTestData + "/" + testStem; + std::filesystem::path goldenMaster(std::string_view testStem) const override { + return unitTestData / testStem; } }; diff --git a/tests/unit/libstore-support/tests/nix_api_store.hh b/tests/unit/libstore-support/tests/nix_api_store.hh index a2d35d083..193b44970 100644 --- a/tests/unit/libstore-support/tests/nix_api_store.hh +++ b/tests/unit/libstore-support/tests/nix_api_store.hh @@ -10,7 +10,7 @@ #include #include -namespace fs = std::filesystem; +namespace fs { using namespace std::filesystem; } namespace nixC { class nix_api_store_test : public nix_api_util_context diff --git a/tests/unit/libstore-support/tests/protocol.hh b/tests/unit/libstore-support/tests/protocol.hh index 3c9e52c11..3f6799d1c 100644 --- a/tests/unit/libstore-support/tests/protocol.hh +++ b/tests/unit/libstore-support/tests/protocol.hh @@ -12,10 +12,10 @@ namespace nix { template class ProtoTest : public CharacterizationTest, public LibStoreTest { - Path unitTestData = getUnitTestData() + "/" + protocolDir; + std::filesystem::path unitTestData = getUnitTestData() / protocolDir; - Path goldenMaster(std::string_view testStem) const override { - return unitTestData + "/" + testStem + ".bin"; + std::filesystem::path goldenMaster(std::string_view testStem) const override { + return unitTestData / (std::string { testStem + ".bin" }); } }; diff --git a/tests/unit/libstore/derivation-advanced-attrs.cc b/tests/unit/libstore/derivation-advanced-attrs.cc index 26cf947a8..4d839ddab 100644 --- a/tests/unit/libstore/derivation-advanced-attrs.cc +++ b/tests/unit/libstore/derivation-advanced-attrs.cc @@ -16,12 +16,12 @@ using nlohmann::json; class DerivationAdvancedAttrsTest : public CharacterizationTest, public LibStoreTest { - Path unitTestData = getUnitTestData() + "/derivation"; + std::filesystem::path unitTestData = getUnitTestData() / "derivation"; public: - Path goldenMaster(std::string_view testStem) const override + std::filesystem::path goldenMaster(std::string_view testStem) const override { - return unitTestData + "/" + testStem; + return unitTestData / testStem; } }; diff --git a/tests/unit/libstore/derivation.cc b/tests/unit/libstore/derivation.cc index 71979f885..14652921a 100644 --- a/tests/unit/libstore/derivation.cc +++ b/tests/unit/libstore/derivation.cc @@ -13,11 +13,11 @@ using nlohmann::json; class DerivationTest : public CharacterizationTest, public LibStoreTest { - Path unitTestData = getUnitTestData() + "/derivation"; + std::filesystem::path unitTestData = getUnitTestData() / "derivation"; public: - Path goldenMaster(std::string_view testStem) const override { - return unitTestData + "/" + testStem; + std::filesystem::path goldenMaster(std::string_view testStem) const override { + return unitTestData / testStem; } /** diff --git a/tests/unit/libstore/machines.cc b/tests/unit/libstore/machines.cc index 2307f4d62..2d66e9534 100644 --- a/tests/unit/libstore/machines.cc +++ b/tests/unit/libstore/machines.cc @@ -13,6 +13,8 @@ using testing::Eq; using testing::Field; using testing::SizeIs; +namespace nix::fs { using namespace std::filesystem; } + using namespace nix; TEST(machines, getMachinesWithEmptyBuilders) { @@ -135,10 +137,10 @@ TEST(machines, getMachinesWithIncorrectFormat) { } TEST(machines, getMachinesWithCorrectFileReference) { - auto path = absPath(getUnitTestData() + "/machines/valid"); - ASSERT_TRUE(pathExists(path)); + auto path = fs::weakly_canonical(getUnitTestData() / "machines/valid"); + ASSERT_TRUE(fs::exists(path)); - auto actual = Machine::parseConfig({}, "@" + path); + auto actual = Machine::parseConfig({}, "@" + path.string()); ASSERT_THAT(actual, SizeIs(3)); EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, AuthorityMatches("nix@scratchy.labs.cs.uu.nl")))); EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, AuthorityMatches("nix@itchy.labs.cs.uu.nl")))); @@ -146,20 +148,22 @@ TEST(machines, getMachinesWithCorrectFileReference) { } TEST(machines, getMachinesWithCorrectFileReferenceToEmptyFile) { - auto path = "/dev/null"; - ASSERT_TRUE(pathExists(path)); + fs::path path = "/dev/null"; + ASSERT_TRUE(fs::exists(path)); - auto actual = Machine::parseConfig({}, std::string{"@"} + path); + auto actual = Machine::parseConfig({}, "@" + path.string()); ASSERT_THAT(actual, SizeIs(0)); } TEST(machines, getMachinesWithIncorrectFileReference) { - auto actual = Machine::parseConfig({}, "@" + absPath("/not/a/file")); + auto path = fs::weakly_canonical("/not/a/file"); + ASSERT_TRUE(!fs::exists(path)); + auto actual = Machine::parseConfig({}, "@" + path.string()); ASSERT_THAT(actual, SizeIs(0)); } TEST(machines, getMachinesWithCorrectFileReferenceToIncorrectFile) { EXPECT_THROW( - Machine::parseConfig({}, "@" + absPath(getUnitTestData() + "/machines/bad_format")), + Machine::parseConfig({}, "@" + fs::weakly_canonical(getUnitTestData() / "machines" / "bad_format").string()), FormatError); } diff --git a/tests/unit/libstore/nar-info.cc b/tests/unit/libstore/nar-info.cc index a6cb62de4..0d155743d 100644 --- a/tests/unit/libstore/nar-info.cc +++ b/tests/unit/libstore/nar-info.cc @@ -13,10 +13,10 @@ using nlohmann::json; class NarInfoTest : public CharacterizationTest, public LibStoreTest { - Path unitTestData = getUnitTestData() + "/nar-info"; + std::filesystem::path unitTestData = getUnitTestData() / "nar-info"; - Path goldenMaster(PathView testStem) const override { - return unitTestData + "/" + testStem + ".json"; + std::filesystem::path goldenMaster(PathView testStem) const override { + return unitTestData / (testStem + ".json"); } }; diff --git a/tests/unit/libstore/path-info.cc b/tests/unit/libstore/path-info.cc index 9e9c6303d..d6c4c2a7f 100644 --- a/tests/unit/libstore/path-info.cc +++ b/tests/unit/libstore/path-info.cc @@ -12,10 +12,10 @@ using nlohmann::json; class PathInfoTest : public CharacterizationTest, public LibStoreTest { - Path unitTestData = getUnitTestData() + "/path-info"; + std::filesystem::path unitTestData = getUnitTestData() / "path-info"; - Path goldenMaster(PathView testStem) const override { - return unitTestData + "/" + testStem + ".json"; + std::filesystem::path goldenMaster(PathView testStem) const override { + return unitTestData / (testStem + ".json"); } }; diff --git a/tests/unit/libstore/store-reference.cc b/tests/unit/libstore/store-reference.cc index 052cd7bed..d4c42f0fd 100644 --- a/tests/unit/libstore/store-reference.cc +++ b/tests/unit/libstore/store-reference.cc @@ -13,11 +13,11 @@ using nlohmann::json; class StoreReferenceTest : public CharacterizationTest, public LibStoreTest { - Path unitTestData = getUnitTestData() + "/store-reference"; + std::filesystem::path unitTestData = getUnitTestData() / "store-reference"; - Path goldenMaster(PathView testStem) const override + std::filesystem::path goldenMaster(PathView testStem) const override { - return unitTestData + "/" + testStem + ".txt"; + return unitTestData / (testStem + ".txt"); } }; diff --git a/tests/unit/libutil-support/tests/characterization.hh b/tests/unit/libutil-support/tests/characterization.hh index 19ba824ac..5e790e75b 100644 --- a/tests/unit/libutil-support/tests/characterization.hh +++ b/tests/unit/libutil-support/tests/characterization.hh @@ -13,7 +13,7 @@ namespace nix { * The path to the unit test data directory. See the contributing guide * in the manual for further details. */ -static inline Path getUnitTestData() { +static inline std::filesystem::path getUnitTestData() { return getEnv("_NIX_TEST_UNIT_DATA").value(); } @@ -36,7 +36,7 @@ protected: * While the "golden master" for this characterization test is * located. It should not be shared with any other test. */ - virtual Path goldenMaster(PathView testStem) const = 0; + virtual std::filesystem::path goldenMaster(PathView testStem) const = 0; public: /** @@ -77,7 +77,7 @@ public: if (testAccept()) { - createDirs(dirOf(file)); + std::filesystem::create_directories(file.parent_path()); writeFile2(file, got); GTEST_SKIP() << "Updating golden master " @@ -97,10 +97,10 @@ public: { writeTest( testStem, test, - [](const Path & f) -> std::string { + [](const std::filesystem::path & f) -> std::string { return readFile(f); }, - [](const Path & f, const std::string & c) { + [](const std::filesystem::path & f, const std::string & c) { return writeFile(f, c); }); } diff --git a/tests/unit/libutil/file-system.cc b/tests/unit/libutil/file-system.cc index cfddaae1c..7ef804f34 100644 --- a/tests/unit/libutil/file-system.cc +++ b/tests/unit/libutil/file-system.cc @@ -12,8 +12,8 @@ #include #ifdef _WIN32 -# define FS_SEP "\\" -# define FS_ROOT "C:" FS_SEP // Need a mounted one, C drive is likely +# define FS_SEP L"\\" +# define FS_ROOT L"C:" FS_SEP // Need a mounted one, C drive is likely #else # define FS_SEP "/" # define FS_ROOT FS_SEP @@ -23,6 +23,12 @@ # define PATH_MAX 4096 #endif +#ifdef _WIN32 +# define GET_CWD _wgetcwd +#else +# define GET_CWD getcwd +#endif + namespace nix { /* ----------- tests for file-system.hh -------------------------------------*/ @@ -33,34 +39,34 @@ namespace nix { TEST(absPath, doesntChangeRoot) { - auto p = absPath(FS_ROOT); + auto p = absPath(std::filesystem::path{FS_ROOT}); ASSERT_EQ(p, FS_ROOT); } TEST(absPath, turnsEmptyPathIntoCWD) { - char cwd[PATH_MAX + 1]; - auto p = absPath(""); + OsChar cwd[PATH_MAX + 1]; + auto p = absPath(std::filesystem::path{""}); - ASSERT_EQ(p, getcwd((char *) &cwd, PATH_MAX)); + ASSERT_EQ(p, GET_CWD((OsChar *) &cwd, PATH_MAX)); } TEST(absPath, usesOptionalBasePathWhenGiven) { - char _cwd[PATH_MAX + 1]; - char * cwd = getcwd((char *) &_cwd, PATH_MAX); + OsChar _cwd[PATH_MAX + 1]; + OsChar * cwd = GET_CWD((OsChar *) &_cwd, PATH_MAX); - auto p = absPath("", cwd); + auto p = absPath(std::filesystem::path{""}.string(), std::filesystem::path{cwd}.string()); - ASSERT_EQ(p, cwd); + ASSERT_EQ(p, std::filesystem::path{cwd}.string()); } TEST(absPath, isIdempotent) { - char _cwd[PATH_MAX + 1]; - char * cwd = getcwd((char *) &_cwd, PATH_MAX); - auto p1 = absPath(cwd); + OsChar _cwd[PATH_MAX + 1]; + OsChar * cwd = GET_CWD((OsChar *) &_cwd, PATH_MAX); + auto p1 = absPath(std::filesystem::path{cwd}); auto p2 = absPath(p1); ASSERT_EQ(p1, p2); @@ -68,8 +74,8 @@ TEST(absPath, isIdempotent) TEST(absPath, pathIsCanonicalised) { - auto path = FS_ROOT "some/path/with/trailing/dot/."; - auto p1 = absPath(path); + auto path = FS_ROOT OS_STR("some/path/with/trailing/dot/."); + auto p1 = absPath(std::filesystem::path{path}); auto p2 = absPath(p1); ASSERT_EQ(p1, FS_ROOT "some" FS_SEP "path" FS_SEP "with" FS_SEP "trailing" FS_SEP "dot"); @@ -82,26 +88,26 @@ TEST(absPath, pathIsCanonicalised) TEST(canonPath, removesTrailingSlashes) { - auto path = FS_ROOT "this/is/a/path//"; - auto p = canonPath(path); + std::filesystem::path path = FS_ROOT "this/is/a/path//"; + auto p = canonPath(path.string()); - ASSERT_EQ(p, FS_ROOT "this" FS_SEP "is" FS_SEP "a" FS_SEP "path"); + ASSERT_EQ(p, std::filesystem::path{FS_ROOT "this" FS_SEP "is" FS_SEP "a" FS_SEP "path"}.string()); } TEST(canonPath, removesDots) { - auto path = FS_ROOT "this/./is/a/path/./"; - auto p = canonPath(path); + std::filesystem::path path = FS_ROOT "this/./is/a/path/./"; + auto p = canonPath(path.string()); - ASSERT_EQ(p, FS_ROOT "this" FS_SEP "is" FS_SEP "a" FS_SEP "path"); + ASSERT_EQ(p, std::filesystem::path{FS_ROOT "this" FS_SEP "is" FS_SEP "a" FS_SEP "path"}.string()); } TEST(canonPath, removesDots2) { - auto path = FS_ROOT "this/a/../is/a////path/foo/.."; - auto p = canonPath(path); + std::filesystem::path path = FS_ROOT "this/a/../is/a////path/foo/.."; + auto p = canonPath(path.string()); - ASSERT_EQ(p, FS_ROOT "this" FS_SEP "is" FS_SEP "a" FS_SEP "path"); + ASSERT_EQ(p, std::filesystem::path{FS_ROOT "this" FS_SEP "is" FS_SEP "a" FS_SEP "path"}.string()); } TEST(canonPath, requiresAbsolutePath) @@ -243,7 +249,7 @@ TEST(isDirOrInDir, DISABLED_shouldWork) TEST(pathExists, rootExists) { - ASSERT_TRUE(pathExists(FS_ROOT)); + ASSERT_TRUE(pathExists(std::filesystem::path{FS_ROOT}.string())); } TEST(pathExists, cwdExists) diff --git a/tests/unit/libutil/git.cc b/tests/unit/libutil/git.cc index 3d01d9806..9232de5b9 100644 --- a/tests/unit/libutil/git.cc +++ b/tests/unit/libutil/git.cc @@ -11,12 +11,12 @@ using namespace git; class GitTest : public CharacterizationTest { - Path unitTestData = getUnitTestData() + "/git"; + std::filesystem::path unitTestData = getUnitTestData() / "git"; public: - Path goldenMaster(std::string_view testStem) const override { - return unitTestData + "/" + testStem; + std::filesystem::path goldenMaster(std::string_view testStem) const override { + return unitTestData / std::string(testStem); } /** diff --git a/tests/unit/libutil/meson.build b/tests/unit/libutil/meson.build index 83cec13ec..c39db8cda 100644 --- a/tests/unit/libutil/meson.build +++ b/tests/unit/libutil/meson.build @@ -48,12 +48,14 @@ subdir('build-utils-meson/diagnostics') sources = files( 'args.cc', 'canon-path.cc', + 'checked-arithmetic.cc', 'chunked-vector.cc', 'closure.cc', 'compression.cc', 'config.cc', 'executable-path.cc', 'file-content-address.cc', + 'file-system.cc', 'git.cc', 'hash.cc', 'hilite.cc', @@ -62,6 +64,7 @@ sources = files( 'lru-cache.cc', 'nix_api_util.cc', 'pool.cc', + 'position.cc', 'processes.cc', 'references.cc', 'spawn.cc', From 8bce63f30a773611f782ea3a53b9ab46180392c7 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 26 Aug 2024 16:44:19 -0400 Subject: [PATCH 128/718] More `std::filesystem` for `nix-collect-garbage` Co-Authored-By: siddhantCodes --- .../nix-collect-garbage.cc | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/nix-collect-garbage/nix-collect-garbage.cc b/src/nix-collect-garbage/nix-collect-garbage.cc index 457e5f3c9..20d5161df 100644 --- a/src/nix-collect-garbage/nix-collect-garbage.cc +++ b/src/nix-collect-garbage/nix-collect-garbage.cc @@ -11,6 +11,8 @@ #include #include +namespace nix::fs { using namespace std::filesystem; } + using namespace nix; std::string deleteOlderThan; @@ -21,23 +23,23 @@ bool dryRun = false; * Of course, this makes rollbacks to before this point in time * impossible. */ -void removeOldGenerations(std::filesystem::path dir) +void removeOldGenerations(fs::path dir) { if (access(dir.string().c_str(), R_OK) != 0) return; bool canWrite = access(dir.string().c_str(), W_OK) == 0; - for (auto & i : std::filesystem::directory_iterator{dir}) { + for (auto & i : fs::directory_iterator{dir}) { checkInterrupt(); auto path = i.path().string(); auto type = i.symlink_status().type(); - if (type == std::filesystem::file_type::symlink && canWrite) { + if (type == fs::file_type::symlink && canWrite) { std::string link; try { link = readLink(path); - } catch (std::filesystem::filesystem_error & e) { + } catch (fs::filesystem_error & e) { if (e.code() == std::errc::no_such_file_or_directory) continue; throw; } @@ -49,7 +51,7 @@ void removeOldGenerations(std::filesystem::path dir) } else deleteOldGenerations(path, dryRun); } - } else if (type == std::filesystem::file_type::directory) { + } else if (type == fs::file_type::directory) { removeOldGenerations(path); } } @@ -81,8 +83,11 @@ static int main_nix_collect_garbage(int argc, char * * argv) }); if (removeOld) { - std::set dirsToClean = { - profilesDir(), settings.nixStateDir + "/profiles", dirOf(getDefaultProfile())}; + std::set dirsToClean = { + profilesDir(), + fs::path{settings.nixStateDir} / "profiles", + fs::path{getDefaultProfile()}.parent_path(), + }; for (auto & dir : dirsToClean) removeOldGenerations(dir); } From c7ec33605e8c2dff0ebe40e4a1beba7a98530432 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Wed, 14 Aug 2024 16:19:35 -0400 Subject: [PATCH 129/718] Meson misc things Meson-ify a few things, scripts, completions, etc. Should make our Meson build complete except for docs. Co-Authored-By: Qyriad Co-Authored-By: eldritch horrors --- build-utils-meson/export/meson.build | 3 +++ flake.nix | 3 ++- meson.build | 4 +++- misc/bash/meson.build | 8 +++++++ misc/fish/meson.build | 8 +++++++ misc/meson.build | 5 +++++ misc/systemd/meson.build | 25 ++++++++++++++++++++++ misc/zsh/meson.build | 10 +++++++++ scripts/meson.build | 29 ++++++++++++++++++++++++++ src/libstore/meson.build | 22 ++++++++++++++----- src/libstore/meson.options | 4 ---- src/libutil/meson.build | 2 +- src/nix/meson.build | 14 ++++++++++++- src/nix/meson.options | 6 ++++++ src/nix/misc | 1 + src/nix/package.nix | 8 ++++++- src/nix/scripts | 1 + subprojects | 1 + tests/unit/libutil-support/meson.build | 1 + 19 files changed, 141 insertions(+), 14 deletions(-) create mode 100644 misc/bash/meson.build create mode 100644 misc/fish/meson.build create mode 100644 misc/meson.build create mode 100644 misc/systemd/meson.build create mode 100644 misc/zsh/meson.build create mode 100644 scripts/meson.build create mode 100644 src/nix/meson.options create mode 120000 src/nix/misc create mode 120000 src/nix/scripts create mode 120000 subprojects diff --git a/build-utils-meson/export/meson.build b/build-utils-meson/export/meson.build index 40f6dcd59..9f5950572 100644 --- a/build-utils-meson/export/meson.build +++ b/build-utils-meson/export/meson.build @@ -10,6 +10,7 @@ foreach dep : deps_public_subproject endforeach requires_public += deps_public +extra_pkg_config_variables = get_variable('extra_pkg_config_variables', {}) import('pkgconfig').generate( this_library, filebase : meson.project_name(), @@ -20,6 +21,7 @@ import('pkgconfig').generate( requires : requires_public, requires_private : requires_private, libraries_private : libraries_private, + variables : extra_pkg_config_variables, ) meson.override_dependency(meson.project_name(), declare_dependency( @@ -27,4 +29,5 @@ meson.override_dependency(meson.project_name(), declare_dependency( link_with : this_library, compile_args : ['-std=c++2a'], dependencies : deps_public_subproject + deps_public, + variables : extra_pkg_config_variables, )) diff --git a/flake.nix b/flake.nix index f5893d8f6..5ca9c1a45 100644 --- a/flake.nix +++ b/flake.nix @@ -295,6 +295,7 @@ devShells = let makeShell = pkgs: stdenv: (pkgs.nix.override { inherit stdenv; forDevShell = true; }).overrideAttrs (attrs: let + buildCanExecuteHost = stdenv.buildPlatform.canExecute stdenv.hostPlatform; modular = devFlake.getSystem stdenv.buildPlatform.system; transformFlag = prefix: flag: assert builtins.isString flag; @@ -352,7 +353,7 @@ ++ pkgs.nixComponents.nix-external-api-docs.nativeBuildInputs ++ pkgs.nixComponents.nix-functional-tests.baseNativeBuildInputs ++ lib.optional - (!stdenv.buildPlatform.canExecute stdenv.hostPlatform + (!buildCanExecuteHost # Hack around https://github.com/nixos/nixpkgs/commit/bf7ad8cfbfa102a90463433e2c5027573b462479 && !(stdenv.hostPlatform.isWindows && stdenv.buildPlatform.isDarwin) && stdenv.hostPlatform.emulatorAvailable pkgs.buildPackages diff --git a/meson.build b/meson.build index 715a3862d..8dd44cc10 100644 --- a/meson.build +++ b/meson.build @@ -3,7 +3,9 @@ project('nix-dev-shell', 'cpp', version : files('.version'), - subproject_dir : 'src', + default_options : [ + 'localstatedir=/nix/var', + ] ) # Internal Libraries diff --git a/misc/bash/meson.build b/misc/bash/meson.build new file mode 100644 index 000000000..8a97a02cb --- /dev/null +++ b/misc/bash/meson.build @@ -0,0 +1,8 @@ +configure_file( + input : 'completion.sh', + output : 'nix', + install : true, + install_dir : get_option('datadir') / 'bash-completion' / 'completions', + install_mode : 'rw-r--r--', + copy : true, +) diff --git a/misc/fish/meson.build b/misc/fish/meson.build new file mode 100644 index 000000000..e7e89b438 --- /dev/null +++ b/misc/fish/meson.build @@ -0,0 +1,8 @@ +configure_file( + input : 'completion.fish', + output : 'nix.fish', + install : true, + install_dir : get_option('datadir') / 'fish' / 'vendor_completions.d', + install_mode : 'rw-r--r--', + copy : true, +) diff --git a/misc/meson.build b/misc/meson.build new file mode 100644 index 000000000..a6d1f944b --- /dev/null +++ b/misc/meson.build @@ -0,0 +1,5 @@ +subdir('bash') +subdir('fish') +subdir('zsh') + +subdir('systemd') diff --git a/misc/systemd/meson.build b/misc/systemd/meson.build new file mode 100644 index 000000000..58b30f30b --- /dev/null +++ b/misc/systemd/meson.build @@ -0,0 +1,25 @@ +foreach config : [ 'nix-daemon.socket', 'nix-daemon.service' ] + configure_file( + input : config + '.in', + output : config, + install : true, + install_dir : get_option('prefix') / 'lib/systemd/system', + install_mode : 'rw-r--r--', + configuration : { + 'storedir' : store_dir, + 'localstatedir' : localstatedir, + 'bindir' : get_option('datadir'), + }, + ) +endforeach + +configure_file( + input : 'nix-daemon.conf.in', + output : 'nix-daemon.conf', + install : true, + install_dir : get_option('prefix') / 'lib/tmpfiles.d', + install_mode : 'rw-r--r--', + configuration : { + 'localstatedir' : localstatedir, + }, +) diff --git a/misc/zsh/meson.build b/misc/zsh/meson.build new file mode 100644 index 000000000..f3d0426e7 --- /dev/null +++ b/misc/zsh/meson.build @@ -0,0 +1,10 @@ +foreach script : [ [ 'completion.zsh', '_nix' ], [ 'run-help-nix' ] ] + configure_file( + input : script[0], + output : script.get(1, script[0]), + install : true, + install_dir : get_option('datadir') / 'zsh/site-functions', + install_mode : 'rw-r--r--', + copy : true, + ) +endforeach diff --git a/scripts/meson.build b/scripts/meson.build new file mode 100644 index 000000000..2671e6a13 --- /dev/null +++ b/scripts/meson.build @@ -0,0 +1,29 @@ +# configures `scripts/nix-profile.sh.in` (and copies the original to the build directory). +# this is only needed for tests, but running it unconditionally does not hurt enough to care. +configure_file( + input : 'nix-profile.sh.in', + output : 'nix-profile.sh', + configuration : { + 'localstatedir': localstatedir, + } +) + +# https://github.com/mesonbuild/meson/issues/860 +configure_file( + input : 'nix-profile.sh.in', + output : 'nix-profile.sh.in', + copy : true, +) + +foreach rc : [ '.sh', '.fish', '-daemon.sh', '-daemon.fish' ] + configure_file( + input : 'nix-profile' + rc + '.in', + output : 'nix' + rc, + install : true, + install_dir : get_option('profile-dir'), + install_mode : 'rw-r--r--', + configuration : { + 'localstatedir': localstatedir, + }, + ) +endforeach diff --git a/src/libstore/meson.build b/src/libstore/meson.build index 8e30845e1..2adc9b3e4 100644 --- a/src/libstore/meson.build +++ b/src/libstore/meson.build @@ -7,6 +7,7 @@ project('nix-store', 'cpp', 'debug=true', 'optimization=2', 'errorlogs=true', # Please print logs for tests that fail + 'localstatedir=/nix/var', ], meson_version : '>= 1.1', license : 'LGPL-2.1-or-later', @@ -324,7 +325,7 @@ fs = import('fs') prefix = get_option('prefix') # For each of these paths, assume that it is relative to the prefix unless -# it is already an absolute path (which is the default for store-dir, state-dir, and log-dir). +# it is already an absolute path (which is the default for store-dir, localstatedir, and log-dir). path_opts = [ # Meson built-ins. 'datadir', @@ -334,13 +335,13 @@ path_opts = [ 'libexecdir', # Homecooked Nix directories. 'store-dir', - 'state-dir', + 'localstatedir', 'log-dir', ] # For your grepping pleasure, this loop sets the following variables that aren't mentioned # literally above: # store_dir -# state_dir +# localstatedir # log_dir # profile_dir foreach optname : path_opts @@ -364,12 +365,12 @@ lsof = find_program('lsof', required : false) # Aside from prefix itself, each of these was made into an absolute path # by joining it with prefix, unless it was already an absolute path -# (which is the default for store-dir, state-dir, and log-dir). +# (which is the default for store-dir, localstatedir, and log-dir). cpp_str_defines = { 'NIX_PREFIX': prefix, 'NIX_STORE_DIR': store_dir, 'NIX_DATA_DIR': datadir, - 'NIX_STATE_DIR': state_dir / 'nix', + 'NIX_STATE_DIR': localstatedir / 'nix', 'NIX_LOG_DIR': log_dir, 'NIX_CONF_DIR': sysconfdir / 'nix', 'NIX_MAN_DIR': mandir, @@ -421,4 +422,15 @@ install_headers(headers, subdir : 'nix', preserve_path : true) libraries_private = [] +extra_pkg_config_variables = { + 'storedir' : get_option('store-dir'), +} + +# Working around https://github.com/mesonbuild/meson/issues/13584 +if host_machine.system() != 'macos' + extra_pkg_config_variables += { + 'localstatedir' : get_option('localstatedir'), + } +endif + subdir('build-utils-meson/export') diff --git a/src/libstore/meson.options b/src/libstore/meson.options index 723a8e020..ebad24dc4 100644 --- a/src/libstore/meson.options +++ b/src/libstore/meson.options @@ -16,10 +16,6 @@ option('store-dir', type : 'string', value : '/nix/store', description : 'path of the Nix store', ) -option('state-dir', type : 'string', value : '/nix/var', - description : 'path to store state in for Nix', -) - option('log-dir', type : 'string', value : '/nix/var/log/nix', description : 'path to store logs in for Nix', ) diff --git a/src/libutil/meson.build b/src/libutil/meson.build index 72ff461ca..797dcae6d 100644 --- a/src/libutil/meson.build +++ b/src/libutil/meson.build @@ -129,7 +129,6 @@ sources = files( 'english.cc', 'environment-variables.cc', 'error.cc', - 'exec.hh', 'executable-path.cc', 'exit.cc', 'experimental-features.cc', @@ -186,6 +185,7 @@ headers = [config_h] + files( 'english.hh', 'environment-variables.hh', 'error.hh', + 'exec.hh', 'executable-path.hh', 'exit.hh', 'experimental-features.hh', diff --git a/src/nix/meson.build b/src/nix/meson.build index 798c98e33..6edb768e3 100644 --- a/src/nix/meson.build +++ b/src/nix/meson.build @@ -7,6 +7,7 @@ project('nix', 'cpp', 'debug=true', 'optimization=2', 'errorlogs=true', # Please print logs for tests that fail + 'localstatedir=/nix/var', ], meson_version : '>= 1.1', license : 'LGPL-2.1-or-later', @@ -16,9 +17,11 @@ cxx = meson.get_compiler('cpp') subdir('build-utils-meson/deps-lists') +nix_store = dependency('nix-store') + deps_private_maybe_subproject = [ dependency('nix-util'), - dependency('nix-store'), + nix_store, dependency('nix-expr'), dependency('nix-flake'), dependency('nix-fetchers'), @@ -244,3 +247,12 @@ custom_target( ) # TODO(Ericson3214): Dosen't yet work #meson.override_find_program(linkname, t) + +localstatedir = nix_store.get_variable( + 'localstatedir', + default_value : get_option('localstatedir'), +) +assert(localstatedir == get_option('localstatedir')) +store_dir = nix_store.get_variable('storedir') +subdir('scripts') +subdir('misc') diff --git a/src/nix/meson.options b/src/nix/meson.options new file mode 100644 index 000000000..8430dd669 --- /dev/null +++ b/src/nix/meson.options @@ -0,0 +1,6 @@ +# vim: filetype=meson + +# A relative path means it gets appended to prefix. +option('profile-dir', type : 'string', value : 'etc/profile.d', + description : 'the path to install shell profile files', +) diff --git a/src/nix/misc b/src/nix/misc new file mode 120000 index 000000000..2825552c9 --- /dev/null +++ b/src/nix/misc @@ -0,0 +1 @@ +../../misc \ No newline at end of file diff --git a/src/nix/package.nix b/src/nix/package.nix index ef7265458..3e19c6dca 100644 --- a/src/nix/package.nix +++ b/src/nix/package.nix @@ -36,9 +36,10 @@ mkMesonDerivation (finalAttrs: { ../../.version ./.version ./meson.build - # ./meson.options + ./meson.options # Symbolic links to other dirs + ## exes ./build-remote ./doc ./nix-build @@ -48,6 +49,11 @@ mkMesonDerivation (finalAttrs: { ./nix-env ./nix-instantiate ./nix-store + ## dirs + ./scripts + ../../scripts + ./misc + ../../misc # Doc nix files for --help ../../doc/manual/generate-manpage.nix diff --git a/src/nix/scripts b/src/nix/scripts new file mode 120000 index 000000000..c5efc95eb --- /dev/null +++ b/src/nix/scripts @@ -0,0 +1 @@ +../../scripts \ No newline at end of file diff --git a/subprojects b/subprojects new file mode 120000 index 000000000..e8310385c --- /dev/null +++ b/subprojects @@ -0,0 +1 @@ +src \ No newline at end of file diff --git a/tests/unit/libutil-support/meson.build b/tests/unit/libutil-support/meson.build index 6be4972c6..42b49a6a0 100644 --- a/tests/unit/libutil-support/meson.build +++ b/tests/unit/libutil-support/meson.build @@ -46,6 +46,7 @@ include_dirs = [include_directories('.')] headers = files( 'tests/characterization.hh', + 'tests/gtest-with-params.hh', 'tests/hash.hh', 'tests/nix_api_util.hh', 'tests/string_callback.hh', From 8e63dc4455b80c096c74a97f07cfc15a1264502d Mon Sep 17 00:00:00 2001 From: Seggy Umboh Date: Tue, 27 Aug 2024 17:23:27 -0700 Subject: [PATCH 130/718] Fix diskutil deleteVolume command in Uninstall guide (#11371) Co-authored-by: Valentin Gagarin --- doc/manual/src/installation/uninstall.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/manual/src/installation/uninstall.md b/doc/manual/src/installation/uninstall.md index 590327fea..91fb90bc0 100644 --- a/doc/manual/src/installation/uninstall.md +++ b/doc/manual/src/installation/uninstall.md @@ -133,7 +133,9 @@ which you may remove. diskutil list ``` - If you _do_ find a "Nix Store" volume, delete it by running `diskutil deleteVolume` with the store volume's `diskXsY` identifier. + If you _do_ find a "Nix Store" volume, delete it by running `diskutil apfs deleteVolume` with the store volume's `diskXsY` identifier. + + If you get an error that the volume is in use by the kernel, reboot and immediately delete the volume before starting any other process. > **Note** > From cb4b9be4587efcee0c642eeb0aafab006b314d95 Mon Sep 17 00:00:00 2001 From: Jan Hrcek <2716069+jhrcek@users.noreply.github.com> Date: Wed, 28 Aug 2024 09:01:56 +0200 Subject: [PATCH 131/718] Fix few duplicate word occurrences (#11381) --- doc/manual/src/development/json-guideline.md | 2 +- doc/manual/src/protocols/store-path.md | 2 +- doc/manual/src/release-notes/rl-2.23.md | 2 +- package.nix | 2 +- src/libstore/local-overlay-store.md | 4 ++-- src/nix/flake.md | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/manual/src/development/json-guideline.md b/doc/manual/src/development/json-guideline.md index b4bc92af9..309b4b3a0 100644 --- a/doc/manual/src/development/json-guideline.md +++ b/doc/manual/src/development/json-guideline.md @@ -90,7 +90,7 @@ This representation is extensible and preserves the ordering: ## Self-describing values -As described in the previous section, it's crucial that schemas can be extended with with new fields without breaking compatibility. +As described in the previous section, it's crucial that schemas can be extended with new fields without breaking compatibility. However, that should *not* mean we use the presence/absence of fields to indicate optional information *within* a version of the schema. Instead, always include the field, and use `null` to indicate the "nothing" case. diff --git a/doc/manual/src/protocols/store-path.md b/doc/manual/src/protocols/store-path.md index 52352d358..8ec6f8201 100644 --- a/doc/manual/src/protocols/store-path.md +++ b/doc/manual/src/protocols/store-path.md @@ -82,7 +82,7 @@ where - if `type` = `"source:" ...`: - the the hash of the [Nix Archive (NAR)] serialization of the [file system object](@docroot@/store/file-system-object.md) of the store object. + the hash of the [Nix Archive (NAR)] serialization of the [file system object](@docroot@/store/file-system-object.md) of the store object. - if `type` = `"output:" id`: diff --git a/doc/manual/src/release-notes/rl-2.23.md b/doc/manual/src/release-notes/rl-2.23.md index ac842fdc0..76e9534a8 100644 --- a/doc/manual/src/release-notes/rl-2.23.md +++ b/doc/manual/src/release-notes/rl-2.23.md @@ -85,7 +85,7 @@ - Store object info JSON format now uses `null` rather than omitting fields [#9995](https://github.com/NixOS/nix/pull/9995) The [store object info JSON format](@docroot@/protocols/json/store-object-info.md), used for e.g. `nix path-info`, no longer omits fields to indicate absent information, but instead includes the fields with a `null` value. - For example, `"ca": null` is used to to indicate a store object that isn't content-addressed rather than omitting the `ca` field entirely. + For example, `"ca": null` is used to indicate a store object that isn't content-addressed rather than omitting the `ca` field entirely. This makes records of this sort more self-describing, and easier to consume programmatically. We will follow this design principle going forward; diff --git a/package.nix b/package.nix index d41748b7c..5c8d9f9b6 100644 --- a/package.nix +++ b/package.nix @@ -60,7 +60,7 @@ # Run the functional tests as part of the build. , doInstallCheck ? test-client != null || __forDefaults.canRunInstalled -# Check test coverage of Nix. Probably want to use with with at least +# Check test coverage of Nix. Probably want to use with at least # one of `doCHeck` or `doInstallCheck` enabled. , withCoverageChecks ? false diff --git a/src/libstore/local-overlay-store.md b/src/libstore/local-overlay-store.md index 1e1a3d26c..baa395895 100644 --- a/src/libstore/local-overlay-store.md +++ b/src/libstore/local-overlay-store.md @@ -77,13 +77,13 @@ The parts of a local overlay store are as follows: The lower store directory and upper layer directory are combined via OverlayFS to create this directory. Nix doesn't do this itself, because it typically wouldn't have the permissions to do so, so it is the responsibility of the user to set this up first. - Nix can, however, optionally check that that the OverlayFS mount settings appear as expected, matching Nix's own settings. + Nix can, however, optionally check that the OverlayFS mount settings appear as expected, matching Nix's own settings. - **Upper SQLite database**: > Not directly specified. > The location of the database instead depends on the [`state`](#store-experimental-local-overlay-store-state) setting. - > It is is always `${state}/db`. + > It is always `${state}/db`. This contains the metadata of all of the upper layer [store objects][store object] (everything beyond their file system objects), and also duplicate copies of some lower layer store object's metadta. The duplication is so the metadata for the [closure](@docroot@/glossary.md#gloss-closure) of upper layer [store objects][store object] can be found entirely within the upper layer. diff --git a/src/nix/flake.md b/src/nix/flake.md index 46d5a3867..d8ee4ac71 100644 --- a/src/nix/flake.md +++ b/src/nix/flake.md @@ -120,7 +120,7 @@ Contrary to URL-like references, path-like flake references can contain arbitrar ### Examples -* `.`: The flake to which the current directory belongs to. +* `.`: The flake to which the current directory belongs. * `/home/alice/src/patchelf`: A flake in some other directory. * `./../sub directory/with Ûñî©ôδ€`: A flake in another relative directory that has Unicode characters in its name. From 5dd6c4f062ec392b965a5fcfc18fd3f75e2a79cb Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 19 Aug 2024 13:21:44 +0200 Subject: [PATCH 132/718] libgit2, GitRepo: Write thin packfiles libgit2 didn't write thin ones, hence the patch. This should improve performance on systems with weak I/O in ~/.cache, especially in terms of operations per second, or where system calls are slower. (macOS, VMs?) --- packaging/dependencies.nix | 2 + .../libgit2-mempack-thin-packfile.patch | 282 ++++++++++++++++++ src/libfetchers/git-utils.cc | 57 ++++ src/libfetchers/git-utils.hh | 2 + 4 files changed, 343 insertions(+) create mode 100644 packaging/patches/libgit2-mempack-thin-packfile.patch diff --git a/packaging/dependencies.nix b/packaging/dependencies.nix index 21c48e5cc..74b5cbc05 100644 --- a/packaging/dependencies.nix +++ b/packaging/dependencies.nix @@ -115,6 +115,8 @@ scope: { version = inputs.libgit2.lastModifiedDate; cmakeFlags = attrs.cmakeFlags or [] ++ [ "-DUSE_SSH=exec" ]; + patches = attrs.patches or [] + ++ [ ./patches/libgit2-mempack-thin-packfile.patch ]; }); busybox-sandbox-shell = pkgs.busybox-sandbox-shell or (pkgs.busybox.override { diff --git a/packaging/patches/libgit2-mempack-thin-packfile.patch b/packaging/patches/libgit2-mempack-thin-packfile.patch new file mode 100644 index 000000000..fb74b1683 --- /dev/null +++ b/packaging/patches/libgit2-mempack-thin-packfile.patch @@ -0,0 +1,282 @@ +commit 9bacade4a3ef4b6b26e2c02f549eef0e9eb9eaa2 +Author: Robert Hensing +Date: Sun Aug 18 20:20:36 2024 +0200 + + Add unoptimized git_mempack_write_thin_pack + +diff --git a/include/git2/sys/mempack.h b/include/git2/sys/mempack.h +index 17da590a3..3688bdd50 100644 +--- a/include/git2/sys/mempack.h ++++ b/include/git2/sys/mempack.h +@@ -44,6 +44,29 @@ GIT_BEGIN_DECL + */ + GIT_EXTERN(int) git_mempack_new(git_odb_backend **out); + ++/** ++ * Write a thin packfile with the objects in the memory store. ++ * ++ * A thin packfile is a packfile that does not contain its transitive closure of ++ * references. This is useful for efficiently distributing additions to a ++ * repository over the network, but also finds use in the efficient bulk ++ * addition of objects to a repository, locally. ++ * ++ * This operation performs the (shallow) insert operations into the ++ * `git_packbuilder`, but does not write the packfile to disk; ++ * see `git_packbuilder_write_buf`. ++ * ++ * It also does not reset the memory store; see `git_mempack_reset`. ++ * ++ * @note This function may or may not write trees and blobs that are not ++ * referenced by commits. Currently everything is written, but this ++ * behavior may change in the future as the packer is optimized. ++ * ++ * @param backend The mempack backend ++ * @param pb The packbuilder to use to write the packfile ++ */ ++GIT_EXTERN(int) git_mempack_write_thin_pack(git_odb_backend *backend, git_packbuilder *pb); ++ + /** + * Dump all the queued in-memory writes to a packfile. + * +diff --git a/src/libgit2/odb_mempack.c b/src/libgit2/odb_mempack.c +index 6f27f45f8..0b61e2b66 100644 +--- a/src/libgit2/odb_mempack.c ++++ b/src/libgit2/odb_mempack.c +@@ -132,6 +132,35 @@ cleanup: + return err; + } + ++int git_mempack_write_thin_pack(git_odb_backend *backend, git_packbuilder *pb) ++{ ++ struct memory_packer_db *db = (struct memory_packer_db *)backend; ++ const git_oid *oid; ++ size_t iter = 0; ++ int err = -1; ++ ++ /* TODO: Implement the recency heuristics. ++ For this it probably makes sense to only write what's referenced ++ through commits, an option I've carved out for you in the docs. ++ wrt heuristics: ask your favorite LLM to translate https://git-scm.com/docs/pack-heuristics/en ++ to actual normal reference documentation. */ ++ while (true) { ++ err = git_oidmap_iterate(NULL, db->objects, &iter, &oid); ++ if (err == GIT_ITEROVER) { ++ err = 0; ++ break; ++ } ++ if (err != 0) ++ return err; ++ ++ err = git_packbuilder_insert(pb, oid, NULL); ++ if (err != 0) ++ return err; ++ } ++ ++ return 0; ++} ++ + int git_mempack_dump( + git_buf *pack, + git_repository *repo, +diff --git a/tests/libgit2/mempack/thinpack.c b/tests/libgit2/mempack/thinpack.c +new file mode 100644 +index 000000000..604a4dda2 +--- /dev/null ++++ b/tests/libgit2/mempack/thinpack.c +@@ -0,0 +1,196 @@ ++#include "clar_libgit2.h" ++#include "git2/indexer.h" ++#include "git2/odb_backend.h" ++#include "git2/tree.h" ++#include "git2/types.h" ++#include "git2/sys/mempack.h" ++#include "git2/sys/odb_backend.h" ++#include "util.h" ++ ++static git_repository *_repo; ++static git_odb_backend * _mempack_backend; ++ ++void test_mempack_thinpack__initialize(void) ++{ ++ git_odb *odb; ++ ++ _repo = cl_git_sandbox_init_new("mempack_thinpack_repo"); ++ ++ cl_git_pass(git_mempack_new(&_mempack_backend)); ++ cl_git_pass(git_repository_odb(&odb, _repo)); ++ cl_git_pass(git_odb_add_backend(odb, _mempack_backend, 999)); ++ git_odb_free(odb); ++} ++ ++void _mempack_thinpack__cleanup(void) ++{ ++ cl_git_sandbox_cleanup(); ++} ++ ++/* ++ Generating a packfile for an unchanged repo works and produces an empty packfile. ++ Even if we allow this scenario to be detected, it shouldn't misbehave if the ++ application is unaware of it. ++*/ ++void test_mempack_thinpack__empty(void) ++{ ++ git_packbuilder *pb; ++ int version; ++ int n; ++ git_buf buf = GIT_BUF_INIT; ++ ++ git_packbuilder_new(&pb, _repo); ++ ++ cl_git_pass(git_mempack_write_thin_pack(_mempack_backend, pb)); ++ cl_git_pass(git_packbuilder_write_buf(&buf, pb)); ++ cl_assert_in_range(12, buf.size, 1024 /* empty packfile is >0 bytes, but certainly not that big */); ++ cl_assert(buf.ptr[0] == 'P'); ++ cl_assert(buf.ptr[1] == 'A'); ++ cl_assert(buf.ptr[2] == 'C'); ++ cl_assert(buf.ptr[3] == 'K'); ++ version = (buf.ptr[4] << 24) | (buf.ptr[5] << 16) | (buf.ptr[6] << 8) | buf.ptr[7]; ++ /* Subject to change. https://git-scm.com/docs/pack-format: Git currently accepts version number 2 or 3 but generates version 2 only.*/ ++ cl_assert_equal_i(2, version); ++ n = (buf.ptr[8] << 24) | (buf.ptr[9] << 16) | (buf.ptr[10] << 8) | buf.ptr[11]; ++ cl_assert_equal_i(0, n); ++ git_buf_dispose(&buf); ++ ++ git_packbuilder_free(pb); ++} ++ ++#define LIT_LEN(x) x, sizeof(x) - 1 ++ ++/* ++ Check that git_mempack_write_thin_pack produces a thin packfile. ++*/ ++void test_mempack_thinpack__thin(void) ++{ ++ /* Outline: ++ - Create tree 1 ++ - Flush to packfile A ++ - Create tree 2 ++ - Flush to packfile B ++ ++ Tree 2 has a new blob and a reference to a blob from tree 1. ++ ++ Expectation: ++ - Packfile B is thin and does not contain the objects from packfile A ++ */ ++ ++ ++ git_oid oid_blob_1; ++ git_oid oid_blob_2; ++ git_oid oid_blob_3; ++ git_oid oid_tree_1; ++ git_oid oid_tree_2; ++ git_treebuilder *tb; ++ ++ git_packbuilder *pb; ++ git_buf buf = GIT_BUF_INIT; ++ git_indexer *indexer; ++ git_indexer_progress stats; ++ char pack_dir_path[1024]; ++ ++ char sbuf[1024]; ++ const char * repo_path; ++ const char * pack_name_1; ++ const char * pack_name_2; ++ git_str pack_path_1 = GIT_STR_INIT; ++ git_str pack_path_2 = GIT_STR_INIT; ++ git_odb_backend * pack_odb_backend_1; ++ git_odb_backend * pack_odb_backend_2; ++ ++ ++ cl_assert_in_range(0, snprintf(pack_dir_path, sizeof(pack_dir_path), "%s/objects/pack", git_repository_path(_repo)), sizeof(pack_dir_path)); ++ ++ /* Create tree 1 */ ++ ++ cl_git_pass(git_blob_create_from_buffer(&oid_blob_1, _repo, LIT_LEN("thinpack blob 1"))); ++ cl_git_pass(git_blob_create_from_buffer(&oid_blob_2, _repo, LIT_LEN("thinpack blob 2"))); ++ ++ ++ cl_git_pass(git_treebuilder_new(&tb, _repo, NULL)); ++ cl_git_pass(git_treebuilder_insert(NULL, tb, "blob1", &oid_blob_1, GIT_FILEMODE_BLOB)); ++ cl_git_pass(git_treebuilder_insert(NULL, tb, "blob2", &oid_blob_2, GIT_FILEMODE_BLOB)); ++ cl_git_pass(git_treebuilder_write(&oid_tree_1, tb)); ++ ++ /* Flush */ ++ ++ cl_git_pass(git_packbuilder_new(&pb, _repo)); ++ cl_git_pass(git_mempack_write_thin_pack(_mempack_backend, pb)); ++ cl_git_pass(git_packbuilder_write_buf(&buf, pb)); ++ cl_git_pass(git_indexer_new(&indexer, pack_dir_path, 0, NULL, NULL)); ++ cl_git_pass(git_indexer_append(indexer, buf.ptr, buf.size, &stats)); ++ cl_git_pass(git_indexer_commit(indexer, &stats)); ++ pack_name_1 = strdup(git_indexer_name(indexer)); ++ cl_assert(pack_name_1); ++ git_buf_dispose(&buf); ++ git_mempack_reset(_mempack_backend); ++ git_indexer_free(indexer); ++ git_packbuilder_free(pb); ++ ++ /* Create tree 2 */ ++ ++ cl_git_pass(git_treebuilder_clear(tb)); ++ /* blob 1 won't be used, but we add it anyway to test that just "declaring" an object doesn't ++ necessarily cause its inclusion in the next thin packfile. It must only be included if new. */ ++ cl_git_pass(git_blob_create_from_buffer(&oid_blob_1, _repo, LIT_LEN("thinpack blob 1"))); ++ cl_git_pass(git_blob_create_from_buffer(&oid_blob_3, _repo, LIT_LEN("thinpack blob 3"))); ++ cl_git_pass(git_treebuilder_insert(NULL, tb, "blob1", &oid_blob_1, GIT_FILEMODE_BLOB)); ++ cl_git_pass(git_treebuilder_insert(NULL, tb, "blob3", &oid_blob_3, GIT_FILEMODE_BLOB)); ++ cl_git_pass(git_treebuilder_write(&oid_tree_2, tb)); ++ ++ /* Flush */ ++ ++ cl_git_pass(git_packbuilder_new(&pb, _repo)); ++ cl_git_pass(git_mempack_write_thin_pack(_mempack_backend, pb)); ++ cl_git_pass(git_packbuilder_write_buf(&buf, pb)); ++ cl_git_pass(git_indexer_new(&indexer, pack_dir_path, 0, NULL, NULL)); ++ cl_git_pass(git_indexer_append(indexer, buf.ptr, buf.size, &stats)); ++ cl_git_pass(git_indexer_commit(indexer, &stats)); ++ pack_name_2 = strdup(git_indexer_name(indexer)); ++ cl_assert(pack_name_2); ++ git_buf_dispose(&buf); ++ git_mempack_reset(_mempack_backend); ++ git_indexer_free(indexer); ++ git_packbuilder_free(pb); ++ git_treebuilder_free(tb); ++ ++ /* Assertions */ ++ ++ assert(pack_name_1); ++ assert(pack_name_2); ++ ++ repo_path = git_repository_path(_repo); ++ ++ snprintf(sbuf, sizeof(sbuf), "objects/pack/pack-%s.pack", pack_name_1); ++ git_str_joinpath(&pack_path_1, repo_path, sbuf); ++ snprintf(sbuf, sizeof(sbuf), "objects/pack/pack-%s.pack", pack_name_2); ++ git_str_joinpath(&pack_path_2, repo_path, sbuf); ++ ++ /* If they're the same, something definitely went wrong. */ ++ cl_assert(strcmp(pack_name_1, pack_name_2) != 0); ++ ++ cl_git_pass(git_odb_backend_one_pack(&pack_odb_backend_1, pack_path_1.ptr)); ++ cl_assert(pack_odb_backend_1->exists(pack_odb_backend_1, &oid_blob_1)); ++ cl_assert(pack_odb_backend_1->exists(pack_odb_backend_1, &oid_blob_2)); ++ cl_assert(!pack_odb_backend_1->exists(pack_odb_backend_1, &oid_blob_3)); ++ cl_assert(pack_odb_backend_1->exists(pack_odb_backend_1, &oid_tree_1)); ++ cl_assert(!pack_odb_backend_1->exists(pack_odb_backend_1, &oid_tree_2)); ++ ++ cl_git_pass(git_odb_backend_one_pack(&pack_odb_backend_2, pack_path_2.ptr)); ++ /* blob 1 is already in the packfile 1, so packfile 2 must not include it, in order to be _thin_. */ ++ cl_assert(!pack_odb_backend_2->exists(pack_odb_backend_2, &oid_blob_1)); ++ cl_assert(!pack_odb_backend_2->exists(pack_odb_backend_2, &oid_blob_2)); ++ cl_assert(pack_odb_backend_2->exists(pack_odb_backend_2, &oid_blob_3)); ++ cl_assert(!pack_odb_backend_2->exists(pack_odb_backend_2, &oid_tree_1)); ++ cl_assert(pack_odb_backend_2->exists(pack_odb_backend_2, &oid_tree_2)); ++ ++ pack_odb_backend_1->free(pack_odb_backend_1); ++ pack_odb_backend_2->free(pack_odb_backend_2); ++ free((void *)pack_name_1); ++ free((void *)pack_name_2); ++ git_str_dispose(&pack_path_1); ++ git_str_dispose(&pack_path_2); ++ ++} diff --git a/src/libfetchers/git-utils.cc b/src/libfetchers/git-utils.cc index 114aa4ec0..5306d8780 100644 --- a/src/libfetchers/git-utils.cc +++ b/src/libfetchers/git-utils.cc @@ -13,13 +13,17 @@ #include #include #include +#include #include +#include #include #include #include #include #include #include +#include +#include #include #include @@ -76,6 +80,9 @@ typedef std::unique_ptr> StatusLi typedef std::unique_ptr> Remote; typedef std::unique_ptr> GitConfig; typedef std::unique_ptr> ConfigIterator; +typedef std::unique_ptr> ObjectDb; +typedef std::unique_ptr> PackBuilder; +typedef std::unique_ptr> Indexer; // A helper to ensure that we don't leak objects returned by libgit2. template @@ -164,6 +171,11 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this /** Location of the repository on disk. */ std::filesystem::path path; Repository repo; + /** + * In-memory object store for efficient batched writing to packfiles. + * Owned by `repo`. + */ + git_odb_backend * mempack_backend; GitRepoImpl(std::filesystem::path _path, bool create, bool bare) : path(std::move(_path)) @@ -177,6 +189,16 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this if (git_repository_init(Setter(repo), path.string().c_str(), bare)) throw Error("creating Git repository '%s': %s", path, git_error_last()->message); } + git_odb * odb; + if (git_repository_odb(&odb, repo.get())) + throw Error("getting Git object database: %s", git_error_last()->message); + + // TODO: release mempack_backend? + if (git_mempack_new(&mempack_backend)) + throw Error("creating mempack backend: %s", git_error_last()->message); + + if (git_odb_add_backend(odb, mempack_backend, 999)) + throw Error("adding mempack backend to Git object database: %s", git_error_last()->message); } operator git_repository * () @@ -184,6 +206,39 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this return repo.get(); } + void flush() override { + git_buf buf = GIT_BUF_INIT; + try { + PackBuilder packBuilder; + git_packbuilder_new(Setter(packBuilder), *this); + git_mempack_write_thin_pack(mempack_backend, packBuilder.get()); + git_packbuilder_write_buf(&buf, packBuilder.get()); + + std::string repo_path = std::string(git_repository_path(repo.get())); + while (!repo_path.empty() && repo_path.back() == '/') + repo_path.pop_back(); + std::string pack_dir_path = repo_path + "/objects/pack"; + + // TODO: could the indexing be done in a separate thread? + Indexer indexer; + git_indexer_progress stats; + if (git_indexer_new(Setter(indexer), pack_dir_path.c_str(), 0, nullptr, nullptr)) + throw Error("creating git packfile indexer: %s", git_error_last()->message); + if (git_indexer_append(indexer.get(), buf.ptr, buf.size, &stats)) + throw Error("appending to git packfile index: %s", git_error_last()->message); + if (git_indexer_commit(indexer.get(), &stats)) + throw Error("committing git packfile index: %s", git_error_last()->message); + + if (git_mempack_reset(mempack_backend)) + throw Error("resetting git mempack backend: %s", git_error_last()->message); + + git_buf_dispose(&buf); + } catch (...) { + git_buf_dispose(&buf); + throw; + } + } + uint64_t getRevCount(const Hash & rev) override { std::unordered_set done; @@ -1008,6 +1063,8 @@ struct GitFileSystemObjectSinkImpl : GitFileSystemObjectSink auto [oid, _name] = popBuilder(); + repo->flush(); + return toHash(oid); } }; diff --git a/src/libfetchers/git-utils.hh b/src/libfetchers/git-utils.hh index 915252868..65a598ce5 100644 --- a/src/libfetchers/git-utils.hh +++ b/src/libfetchers/git-utils.hh @@ -80,6 +80,8 @@ struct GitRepo virtual ref getFileSystemObjectSink() = 0; + virtual void flush() = 0; + virtual void fetch( const std::string & url, const std::string & refspec, From d0f8a9236392ab41414dddbe7400da98fad9f62d Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 26 Aug 2024 11:38:40 +0200 Subject: [PATCH 133/718] Make tarball cache more interruptible --- src/libfetchers/git-utils.cc | 7 +++++++ src/libutil/unix/signals-impl.hh | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/src/libfetchers/git-utils.cc b/src/libfetchers/git-utils.cc index 5306d8780..fb5341599 100644 --- a/src/libfetchers/git-utils.cc +++ b/src/libfetchers/git-utils.cc @@ -211,8 +211,12 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this try { PackBuilder packBuilder; git_packbuilder_new(Setter(packBuilder), *this); + checkInterrupt(); git_mempack_write_thin_pack(mempack_backend, packBuilder.get()); + checkInterrupt(); + // TODO make git_packbuilder_write_buf() interruptible git_packbuilder_write_buf(&buf, packBuilder.get()); + checkInterrupt(); std::string repo_path = std::string(git_repository_path(repo.get())); while (!repo_path.empty() && repo_path.back() == '/') @@ -224,8 +228,10 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this git_indexer_progress stats; if (git_indexer_new(Setter(indexer), pack_dir_path.c_str(), 0, nullptr, nullptr)) throw Error("creating git packfile indexer: %s", git_error_last()->message); + // TODO: feed buf in (fairly large) chunk to make this interruptible if (git_indexer_append(indexer.get(), buf.ptr, buf.size, &stats)) throw Error("appending to git packfile index: %s", git_error_last()->message); + checkInterrupt(); if (git_indexer_commit(indexer.get(), &stats)) throw Error("committing git packfile index: %s", git_error_last()->message); @@ -237,6 +243,7 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this git_buf_dispose(&buf); throw; } + checkInterrupt(); } uint64_t getRevCount(const Hash & rev) override diff --git a/src/libutil/unix/signals-impl.hh b/src/libutil/unix/signals-impl.hh index 7ac8c914d..2193922be 100644 --- a/src/libutil/unix/signals-impl.hh +++ b/src/libutil/unix/signals-impl.hh @@ -84,6 +84,12 @@ static inline bool getInterrupted() return unix::_isInterrupted; } +/** + * Throw `Interrupted` exception if the process has been interrupted. + * + * Call this in long-running loops and between slow operations to terminate + * them as needed. + */ void inline checkInterrupt() { using namespace unix; From 97ff2ed4555ce0761368046270fc4466550bfb0c Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 26 Aug 2024 11:39:14 +0200 Subject: [PATCH 134/718] Sync tarball cache within tarball cache Activity --- src/libfetchers/github.cc | 3 ++- src/libfetchers/tarball.cc | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libfetchers/github.cc b/src/libfetchers/github.cc index 2e914164a..ecfd035fc 100644 --- a/src/libfetchers/github.cc +++ b/src/libfetchers/github.cc @@ -261,11 +261,12 @@ struct GitArchiveInputScheme : InputScheme auto tarballCache = getTarballCache(); auto parseSink = tarballCache->getFileSystemObjectSink(); auto lastModified = unpackTarfileToSink(archive, *parseSink); + auto tree = parseSink->sync(); act.reset(); TarballInfo tarballInfo { - .treeHash = tarballCache->dereferenceSingletonDirectory(parseSink->sync()), + .treeHash = tarballCache->dereferenceSingletonDirectory(tree), .lastModified = lastModified }; diff --git a/src/libfetchers/tarball.cc b/src/libfetchers/tarball.cc index dd4f3b780..a082b0078 100644 --- a/src/libfetchers/tarball.cc +++ b/src/libfetchers/tarball.cc @@ -170,6 +170,7 @@ static DownloadTarballResult downloadTarball_( auto tarballCache = getTarballCache(); auto parseSink = tarballCache->getFileSystemObjectSink(); auto lastModified = unpackTarfileToSink(archive, *parseSink); + auto tree = parseSink->sync(); act.reset(); @@ -184,7 +185,7 @@ static DownloadTarballResult downloadTarball_( } else { infoAttrs.insert_or_assign("etag", res->etag); infoAttrs.insert_or_assign("treeHash", - tarballCache->dereferenceSingletonDirectory(parseSink->sync()).gitRev()); + tarballCache->dereferenceSingletonDirectory(tree).gitRev()); infoAttrs.insert_or_assign("lastModified", uint64_t(lastModified)); if (res->immutableUrl) infoAttrs.insert_or_assign("immutableUrl", *res->immutableUrl); From fb8d3ed1506d2c0e3065abaad9587e16dccfd1b9 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 26 Aug 2024 15:04:47 +0200 Subject: [PATCH 135/718] fixup: sync -> flush The latter is not used for memory synchronization things. --- src/libfetchers/git-utils.cc | 7 ++++++- src/libfetchers/git-utils.hh | 6 +++++- src/libfetchers/github.cc | 2 +- src/libfetchers/tarball.cc | 2 +- tests/unit/libfetchers/git-utils.cc | 2 +- 5 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/libfetchers/git-utils.cc b/src/libfetchers/git-utils.cc index fb5341599..59b4d424a 100644 --- a/src/libfetchers/git-utils.cc +++ b/src/libfetchers/git-utils.cc @@ -170,6 +170,11 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this { /** Location of the repository on disk. */ std::filesystem::path path; + /** + * libgit2 repository. Note that new objects are not written to disk, + * because we are using a mempack backend. For writing to disk, see + * `flush()`, which is also called by `GitFileSystemObjectSink::sync()`. + */ Repository repo; /** * In-memory object store for efficient batched writing to packfiles. @@ -1064,7 +1069,7 @@ struct GitFileSystemObjectSinkImpl : GitFileSystemObjectSink git_tree_entry_filemode(entry)); } - Hash sync() override + Hash flush() override { updateBuilders({}); diff --git a/src/libfetchers/git-utils.hh b/src/libfetchers/git-utils.hh index 65a598ce5..f45b5a504 100644 --- a/src/libfetchers/git-utils.hh +++ b/src/libfetchers/git-utils.hh @@ -7,12 +7,16 @@ namespace nix { namespace fetchers { struct PublicKey; } +/** + * A sink that writes into a Git repository. Note that nothing may be written + * until `flush()` is called. + */ struct GitFileSystemObjectSink : ExtendedFileSystemObjectSink { /** * Flush builder and return a final Git hash. */ - virtual Hash sync() = 0; + virtual Hash flush() = 0; }; struct GitRepo diff --git a/src/libfetchers/github.cc b/src/libfetchers/github.cc index ecfd035fc..308cff33a 100644 --- a/src/libfetchers/github.cc +++ b/src/libfetchers/github.cc @@ -261,7 +261,7 @@ struct GitArchiveInputScheme : InputScheme auto tarballCache = getTarballCache(); auto parseSink = tarballCache->getFileSystemObjectSink(); auto lastModified = unpackTarfileToSink(archive, *parseSink); - auto tree = parseSink->sync(); + auto tree = parseSink->flush(); act.reset(); diff --git a/src/libfetchers/tarball.cc b/src/libfetchers/tarball.cc index a082b0078..aa5d61bc5 100644 --- a/src/libfetchers/tarball.cc +++ b/src/libfetchers/tarball.cc @@ -170,7 +170,7 @@ static DownloadTarballResult downloadTarball_( auto tarballCache = getTarballCache(); auto parseSink = tarballCache->getFileSystemObjectSink(); auto lastModified = unpackTarfileToSink(archive, *parseSink); - auto tree = parseSink->sync(); + auto tree = parseSink->flush(); act.reset(); diff --git a/tests/unit/libfetchers/git-utils.cc b/tests/unit/libfetchers/git-utils.cc index de5110cc3..0bf3076dc 100644 --- a/tests/unit/libfetchers/git-utils.cc +++ b/tests/unit/libfetchers/git-utils.cc @@ -77,7 +77,7 @@ TEST_F(GitUtilsTest, sink_basic) // sink->createHardlink("foo-1.1/links/foo-2", CanonPath("foo-1.1/hello")); - auto result = repo->dereferenceSingletonDirectory(sink->sync()); + auto result = repo->dereferenceSingletonDirectory(sink->flush()); auto accessor = repo->getAccessor(result, false); auto entries = accessor->readDirectory(CanonPath::root); ASSERT_EQ(entries.size(), 5); From 57c48304bba7d1f92fb9acc8abc9e8db4450fc0c Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 26 Aug 2024 15:34:35 +0200 Subject: [PATCH 136/718] fixup: Release odb --- src/libfetchers/git-utils.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/libfetchers/git-utils.cc b/src/libfetchers/git-utils.cc index 59b4d424a..70391a287 100644 --- a/src/libfetchers/git-utils.cc +++ b/src/libfetchers/git-utils.cc @@ -194,15 +194,16 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this if (git_repository_init(Setter(repo), path.string().c_str(), bare)) throw Error("creating Git repository '%s': %s", path, git_error_last()->message); } - git_odb * odb; - if (git_repository_odb(&odb, repo.get())) + + ObjectDb odb; + if (git_repository_odb(Setter(odb), repo.get())) throw Error("getting Git object database: %s", git_error_last()->message); - // TODO: release mempack_backend? + // mempack_backend will be owned by the repository, so we are not expected to free it ourselves. if (git_mempack_new(&mempack_backend)) throw Error("creating mempack backend: %s", git_error_last()->message); - if (git_odb_add_backend(odb, mempack_backend, 999)) + if (git_odb_add_backend(odb.get(), mempack_backend, 999)) throw Error("adding mempack backend to Git object database: %s", git_error_last()->message); } From c1fe3546ed67babeecfb376315063f0642ce4bbd Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 28 Aug 2024 01:48:25 +0200 Subject: [PATCH 137/718] libgit2: Add libgit2-packbuilder-callback-interruptible.patch --- packaging/dependencies.nix | 18 +- ...2-packbuilder-callback-interruptible.patch | 930 ++++++++++++++++++ 2 files changed, 947 insertions(+), 1 deletion(-) create mode 100644 packaging/patches/libgit2-packbuilder-callback-interruptible.patch diff --git a/packaging/dependencies.nix b/packaging/dependencies.nix index 74b5cbc05..0182f29c0 100644 --- a/packaging/dependencies.nix +++ b/packaging/dependencies.nix @@ -115,8 +115,24 @@ scope: { version = inputs.libgit2.lastModifiedDate; cmakeFlags = attrs.cmakeFlags or [] ++ [ "-DUSE_SSH=exec" ]; + nativeBuildInputs = attrs.nativeBuildInputs or [] + ++ [ + # Needed for `git apply`; see `prePatch` + pkgs.buildPackages.gitMinimal + ]; + # Only `git apply` can handle git binary patches + prePatch = '' + patch() { + git apply + } + ''; patches = attrs.patches or [] - ++ [ ./patches/libgit2-mempack-thin-packfile.patch ]; + ++ [ + ./patches/libgit2-mempack-thin-packfile.patch + + # binary patch; see `prePatch` + ./patches/libgit2-packbuilder-callback-interruptible.patch + ]; }); busybox-sandbox-shell = pkgs.busybox-sandbox-shell or (pkgs.busybox.override { diff --git a/packaging/patches/libgit2-packbuilder-callback-interruptible.patch b/packaging/patches/libgit2-packbuilder-callback-interruptible.patch new file mode 100644 index 000000000..c67822ff7 --- /dev/null +++ b/packaging/patches/libgit2-packbuilder-callback-interruptible.patch @@ -0,0 +1,930 @@ +commit e9823c5da4fa977c46bcb97167fbdd0d70adb5ff +Author: Robert Hensing +Date: Mon Aug 26 20:07:04 2024 +0200 + + Make packbuilder interruptible using progress callback + + Forward errors from packbuilder->progress_cb + + This allows the callback to terminate long-running operations when + the application is interrupted. + +diff --git a/include/git2/pack.h b/include/git2/pack.h +index 0f6bd2ab9..bee72a6c0 100644 +--- a/include/git2/pack.h ++++ b/include/git2/pack.h +@@ -247,6 +247,9 @@ typedef int GIT_CALLBACK(git_packbuilder_progress)( + * @param progress_cb Function to call with progress information during + * pack building. Be aware that this is called inline with pack building + * operations, so performance may be affected. ++ * When progress_cb returns an error, the pack building process will be ++ * aborted and the error will be returned from the invoked function. ++ * `pb` must then be freed. + * @param progress_cb_payload Payload for progress callback. + * @return 0 or an error code + */ +diff --git a/src/libgit2/pack-objects.c b/src/libgit2/pack-objects.c +index b2d80cba9..7c331c2d5 100644 +--- a/src/libgit2/pack-objects.c ++++ b/src/libgit2/pack-objects.c +@@ -932,6 +932,9 @@ static int report_delta_progress( + { + int ret; + ++ if (pb->failure) ++ return pb->failure; ++ + if (pb->progress_cb) { + uint64_t current_time = git_time_monotonic(); + uint64_t elapsed = current_time - pb->last_progress_report_time; +@@ -943,8 +946,10 @@ static int report_delta_progress( + GIT_PACKBUILDER_DELTAFICATION, + count, pb->nr_objects, pb->progress_cb_payload); + +- if (ret) ++ if (ret) { ++ pb->failure = ret; + return git_error_set_after_callback(ret); ++ } + } + } + +@@ -976,7 +981,10 @@ static int find_deltas(git_packbuilder *pb, git_pobject **list, + } + + pb->nr_deltified += 1; +- report_delta_progress(pb, pb->nr_deltified, false); ++ if ((error = report_delta_progress(pb, pb->nr_deltified, false)) < 0) { ++ GIT_ASSERT(git_packbuilder__progress_unlock(pb) == 0); ++ goto on_error; ++ } + + po = *list++; + (*list_size)--; +@@ -1124,6 +1132,10 @@ struct thread_params { + size_t depth; + size_t working; + size_t data_ready; ++ ++ /* A pb->progress_cb can stop the packing process by returning an error. ++ When that happens, all threads observe the error and stop voluntarily. */ ++ bool stopped; + }; + + static void *threaded_find_deltas(void *arg) +@@ -1133,7 +1145,12 @@ static void *threaded_find_deltas(void *arg) + while (me->remaining) { + if (find_deltas(me->pb, me->list, &me->remaining, + me->window, me->depth) < 0) { +- ; /* TODO */ ++ me->stopped = true; ++ GIT_ASSERT_WITH_RETVAL(git_packbuilder__progress_lock(me->pb) == 0, NULL); ++ me->working = false; ++ git_cond_signal(&me->pb->progress_cond); ++ GIT_ASSERT_WITH_RETVAL(git_packbuilder__progress_unlock(me->pb) == 0, NULL); ++ return NULL; + } + + GIT_ASSERT_WITH_RETVAL(git_packbuilder__progress_lock(me->pb) == 0, NULL); +@@ -1175,8 +1192,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list, + pb->nr_threads = git__online_cpus(); + + if (pb->nr_threads <= 1) { +- find_deltas(pb, list, &list_size, window, depth); +- return 0; ++ return find_deltas(pb, list, &list_size, window, depth); + } + + p = git__mallocarray(pb->nr_threads, sizeof(*p)); +@@ -1195,6 +1211,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list, + p[i].depth = depth; + p[i].working = 1; + p[i].data_ready = 0; ++ p[i].stopped = 0; + + /* try to split chunks on "path" boundaries */ + while (sub_size && sub_size < list_size && +@@ -1262,7 +1279,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list, + (!victim || victim->remaining < p[i].remaining)) + victim = &p[i]; + +- if (victim) { ++ if (victim && !target->stopped) { + sub_size = victim->remaining / 2; + list = victim->list + victim->list_size - sub_size; + while (sub_size && list[0]->hash && +@@ -1286,7 +1303,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list, + } + target->list_size = sub_size; + target->remaining = sub_size; +- target->working = 1; ++ target->working = 1; /* even when target->stopped, so that we don't process this thread again */ + GIT_ASSERT(git_packbuilder__progress_unlock(pb) == 0); + + if (git_mutex_lock(&target->mutex)) { +@@ -1299,7 +1316,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list, + git_cond_signal(&target->cond); + git_mutex_unlock(&target->mutex); + +- if (!sub_size) { ++ if (target->stopped || !sub_size) { + git_thread_join(&target->thread, NULL); + git_cond_free(&target->cond); + git_mutex_free(&target->mutex); +@@ -1308,7 +1325,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list, + } + + git__free(p); +- return 0; ++ return pb->failure; + } + + #else +@@ -1319,6 +1336,7 @@ int git_packbuilder__prepare(git_packbuilder *pb) + { + git_pobject **delta_list; + size_t i, n = 0; ++ int error; + + if (pb->nr_objects == 0 || pb->done) + return 0; /* nothing to do */ +@@ -1327,8 +1345,10 @@ int git_packbuilder__prepare(git_packbuilder *pb) + * Although we do not report progress during deltafication, we + * at least report that we are in the deltafication stage + */ +- if (pb->progress_cb) +- pb->progress_cb(GIT_PACKBUILDER_DELTAFICATION, 0, pb->nr_objects, pb->progress_cb_payload); ++ if (pb->progress_cb) { ++ if ((error = pb->progress_cb(GIT_PACKBUILDER_DELTAFICATION, 0, pb->nr_objects, pb->progress_cb_payload)) < 0) ++ return git_error_set_after_callback(error); ++ } + + delta_list = git__mallocarray(pb->nr_objects, sizeof(*delta_list)); + GIT_ERROR_CHECK_ALLOC(delta_list); +@@ -1345,31 +1365,33 @@ int git_packbuilder__prepare(git_packbuilder *pb) + + if (n > 1) { + git__tsort((void **)delta_list, n, type_size_sort); +- if (ll_find_deltas(pb, delta_list, n, ++ if ((error = ll_find_deltas(pb, delta_list, n, + GIT_PACK_WINDOW + 1, +- GIT_PACK_DEPTH) < 0) { ++ GIT_PACK_DEPTH)) < 0) { + git__free(delta_list); +- return -1; ++ return error; + } + } + +- report_delta_progress(pb, pb->nr_objects, true); ++ error = report_delta_progress(pb, pb->nr_objects, true); + + pb->done = true; + git__free(delta_list); +- return 0; ++ return error; + } + +-#define PREPARE_PACK if (git_packbuilder__prepare(pb) < 0) { return -1; } ++#define PREPARE_PACK error = git_packbuilder__prepare(pb); if (error < 0) { return error; } + + int git_packbuilder_foreach(git_packbuilder *pb, int (*cb)(void *buf, size_t size, void *payload), void *payload) + { ++ int error; + PREPARE_PACK; + return write_pack(pb, cb, payload); + } + + int git_packbuilder__write_buf(git_str *buf, git_packbuilder *pb) + { ++ int error; + PREPARE_PACK; + + return write_pack(pb, &write_pack_buf, buf); +diff --git a/src/libgit2/pack-objects.h b/src/libgit2/pack-objects.h +index bbc8b9430..380a28ebe 100644 +--- a/src/libgit2/pack-objects.h ++++ b/src/libgit2/pack-objects.h +@@ -100,6 +100,10 @@ struct git_packbuilder { + uint64_t last_progress_report_time; + + bool done; ++ ++ /* A non-zero error code in failure causes all threads to shut themselves ++ down. Some functions will return this error code. */ ++ volatile int failure; + }; + + int git_packbuilder__write_buf(git_str *buf, git_packbuilder *pb); +diff --git a/tests/libgit2/pack/cancel.c b/tests/libgit2/pack/cancel.c +new file mode 100644 +index 000000000..a0aa9716a +--- /dev/null ++++ b/tests/libgit2/pack/cancel.c +@@ -0,0 +1,240 @@ ++#include "clar_libgit2.h" ++#include "futils.h" ++#include "pack.h" ++#include "hash.h" ++#include "iterator.h" ++#include "vector.h" ++#include "posix.h" ++#include "hash.h" ++#include "pack-objects.h" ++ ++static git_repository *_repo; ++static git_revwalk *_revwalker; ++static git_packbuilder *_packbuilder; ++static git_indexer *_indexer; ++static git_vector _commits; ++static int _commits_is_initialized; ++static git_indexer_progress _stats; ++ ++extern bool git_disable_pack_keep_file_checks; ++ ++static void pack_packbuilder_init(const char *sandbox) { ++ _repo = cl_git_sandbox_init(sandbox); ++ /* cl_git_pass(p_chdir(sandbox)); */ ++ cl_git_pass(git_revwalk_new(&_revwalker, _repo)); ++ cl_git_pass(git_packbuilder_new(&_packbuilder, _repo)); ++ cl_git_pass(git_vector_init(&_commits, 0, NULL)); ++ _commits_is_initialized = 1; ++ memset(&_stats, 0, sizeof(_stats)); ++ p_fsync__cnt = 0; ++} ++ ++void test_pack_cancel__initialize(void) ++{ ++ pack_packbuilder_init("small.git"); ++} ++ ++void test_pack_cancel__cleanup(void) ++{ ++ git_oid *o; ++ unsigned int i; ++ ++ cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_FSYNC_GITDIR, 0)); ++ cl_git_pass(git_libgit2_opts(GIT_OPT_DISABLE_PACK_KEEP_FILE_CHECKS, false)); ++ ++ if (_commits_is_initialized) { ++ _commits_is_initialized = 0; ++ git_vector_foreach(&_commits, i, o) { ++ git__free(o); ++ } ++ git_vector_free(&_commits); ++ } ++ ++ git_packbuilder_free(_packbuilder); ++ _packbuilder = NULL; ++ ++ git_revwalk_free(_revwalker); ++ _revwalker = NULL; ++ ++ git_indexer_free(_indexer); ++ _indexer = NULL; ++ ++ /* cl_git_pass(p_chdir("..")); */ ++ cl_git_sandbox_cleanup(); ++ _repo = NULL; ++} ++ ++static int seed_packbuilder(void) ++{ ++ int error; ++ git_oid oid, *o; ++ unsigned int i; ++ ++ git_revwalk_sorting(_revwalker, GIT_SORT_TIME); ++ cl_git_pass(git_revwalk_push_ref(_revwalker, "HEAD")); ++ ++ while (git_revwalk_next(&oid, _revwalker) == 0) { ++ o = git__malloc(sizeof(git_oid)); ++ cl_assert(o != NULL); ++ git_oid_cpy(o, &oid); ++ cl_git_pass(git_vector_insert(&_commits, o)); ++ } ++ ++ git_vector_foreach(&_commits, i, o) { ++ if((error = git_packbuilder_insert(_packbuilder, o, NULL)) < 0) ++ return error; ++ } ++ ++ git_vector_foreach(&_commits, i, o) { ++ git_object *obj; ++ cl_git_pass(git_object_lookup(&obj, _repo, o, GIT_OBJECT_COMMIT)); ++ error = git_packbuilder_insert_tree(_packbuilder, ++ git_commit_tree_id((git_commit *)obj)); ++ git_object_free(obj); ++ if (error < 0) ++ return error; ++ } ++ ++ return 0; ++} ++ ++static int fail_stage; ++ ++static int packbuilder_cancel_after_n_calls_cb(int stage, uint32_t current, uint32_t total, void *payload) ++{ ++ ++ /* Force the callback to run again on the next opportunity regardless ++ of how fast we're running. */ ++ _packbuilder->last_progress_report_time = 0; ++ ++ if (stage == fail_stage) { ++ int *calls = (int *)payload; ++ int n = *calls; ++ /* Always decrement, including past zero. This way the error is only ++ triggered once, making sure it is picked up immediately. */ ++ --*calls; ++ if (n == 0) ++ return GIT_EUSER; ++ } ++ ++ return 0; ++} ++ ++static void test_cancel(int n) ++{ ++ ++ int calls_remaining = n; ++ int err; ++ git_buf buf = GIT_BUF_INIT; ++ ++ /* Switch to a small repository, so that `packbuilder_cancel_after_n_calls_cb` ++ can hack the time to call the callback on every opportunity. */ ++ ++ cl_git_pass(git_packbuilder_set_callbacks(_packbuilder, &packbuilder_cancel_after_n_calls_cb, &calls_remaining)); ++ err = seed_packbuilder(); ++ if (!err) ++ err = git_packbuilder_write_buf(&buf, _packbuilder); ++ ++ cl_assert_equal_i(GIT_EUSER, err); ++} ++void test_pack_cancel__cancel_after_add_0(void) ++{ ++ fail_stage = GIT_PACKBUILDER_ADDING_OBJECTS; ++ test_cancel(0); ++} ++ ++void test_pack_cancel__cancel_after_add_1(void) ++{ ++ cl_skip(); ++ fail_stage = GIT_PACKBUILDER_ADDING_OBJECTS; ++ test_cancel(1); ++} ++ ++void test_pack_cancel__cancel_after_delta_0(void) ++{ ++ fail_stage = GIT_PACKBUILDER_DELTAFICATION; ++ test_cancel(0); ++} ++ ++void test_pack_cancel__cancel_after_delta_1(void) ++{ ++ fail_stage = GIT_PACKBUILDER_DELTAFICATION; ++ test_cancel(1); ++} ++ ++void test_pack_cancel__cancel_after_delta_0_threaded(void) ++{ ++#ifdef GIT_THREADS ++ git_packbuilder_set_threads(_packbuilder, 8); ++ fail_stage = GIT_PACKBUILDER_DELTAFICATION; ++ test_cancel(0); ++#else ++ cl_skip(); ++#endif ++} ++ ++void test_pack_cancel__cancel_after_delta_1_threaded(void) ++{ ++#ifdef GIT_THREADS ++ git_packbuilder_set_threads(_packbuilder, 8); ++ fail_stage = GIT_PACKBUILDER_DELTAFICATION; ++ test_cancel(1); ++#else ++ cl_skip(); ++#endif ++} ++ ++static int foreach_cb(void *buf, size_t len, void *payload) ++{ ++ git_indexer *idx = (git_indexer *) payload; ++ cl_git_pass(git_indexer_append(idx, buf, len, &_stats)); ++ return 0; ++} ++ ++void test_pack_cancel__foreach(void) ++{ ++ git_indexer *idx; ++ ++ seed_packbuilder(); ++ ++#ifdef GIT_EXPERIMENTAL_SHA256 ++ cl_git_pass(git_indexer_new(&idx, ".", GIT_OID_SHA1, NULL)); ++#else ++ cl_git_pass(git_indexer_new(&idx, ".", 0, NULL, NULL)); ++#endif ++ ++ cl_git_pass(git_packbuilder_foreach(_packbuilder, foreach_cb, idx)); ++ cl_git_pass(git_indexer_commit(idx, &_stats)); ++ git_indexer_free(idx); ++} ++ ++static int foreach_cancel_cb(void *buf, size_t len, void *payload) ++{ ++ git_indexer *idx = (git_indexer *)payload; ++ cl_git_pass(git_indexer_append(idx, buf, len, &_stats)); ++ return (_stats.total_objects > 2) ? -1111 : 0; ++} ++ ++void test_pack_cancel__foreach_with_cancel(void) ++{ ++ git_indexer *idx; ++ ++ seed_packbuilder(); ++ ++#ifdef GIT_EXPERIMENTAL_SHA256 ++ cl_git_pass(git_indexer_new(&idx, ".", GIT_OID_SHA1, NULL)); ++#else ++ cl_git_pass(git_indexer_new(&idx, ".", 0, NULL, NULL)); ++#endif ++ ++ cl_git_fail_with( ++ git_packbuilder_foreach(_packbuilder, foreach_cancel_cb, idx), -1111); ++ git_indexer_free(idx); ++} ++ ++void test_pack_cancel__keep_file_check(void) ++{ ++ assert(!git_disable_pack_keep_file_checks); ++ cl_git_pass(git_libgit2_opts(GIT_OPT_DISABLE_PACK_KEEP_FILE_CHECKS, true)); ++ assert(git_disable_pack_keep_file_checks); ++} +diff --git a/tests/resources/small.git/HEAD b/tests/resources/small.git/HEAD +new file mode 100644 +index 0000000000000000000000000000000000000000..cb089cd89a7d7686d284d8761201649346b5aa1c +GIT binary patch +literal 23 +ecmXR)O|w!cN=+-)&qz&7Db~+TEG|hc;sO9;xClW2 + +literal 0 +HcmV?d00001 + +diff --git a/tests/resources/small.git/config b/tests/resources/small.git/config +new file mode 100644 +index 0000000000000000000000000000000000000000..07d359d07cf1ed0c0074fdad71ffff5942f0adfa +GIT binary patch +literal 66 +zcmaz}&M!)h<>D+#Eyypk5{uv*03B5png9R* + +literal 0 +HcmV?d00001 + +diff --git a/tests/resources/small.git/description b/tests/resources/small.git/description +new file mode 100644 +index 0000000000000000000000000000000000000000..498b267a8c7812490d6479839c5577eaaec79d62 +GIT binary patch +literal 73 +zcmWH|%S+5nO;IRHEyyp$t+PQ$;d2LNXyJgRZve!Elw`VEGWs$&r??@ +Q$yWgB0LrH#Y0~2Y0PnOK(EtDd + +literal 0 +HcmV?d00001 + +diff --git a/tests/resources/small.git/hooks/applypatch-msg.sample b/tests/resources/small.git/hooks/applypatch-msg.sample +new file mode 100755 +index 0000000000000000000000000000000000000000..dcbf8167fa503f96ff6a39c68409007eadc9b1f3 +GIT binary patch +literal 535 +zcmY+AX;Q;542A#a6e8^~FyI8r&I~hf2QJ{GO6(?HuvEG*+#R{4EI%zhfA8r{j%sh$ +zHE~E-UtQd8{bq4@*S%jq3@bmxwQDXGv#o!N`o3AHMw3xD)hy0#>&E&zzl%vRffomqo=v6>_2NRa#TwDdYvTVQyueO*15Nlo%=#DXgC0bhF3vTa`LQGaO9;jeD$OP?~ +za$G4Q{z+Q_{5V?5h;a-noM$P{<>Q~j4o7u%#P6^o^16{y*jU=-K8GYD_dUtdj4FSx +zSC0C!DvAnv%S!4dgk +XB^)11aoGMJPCqWs%IS0YSv(eBT&%T6 + +literal 0 +HcmV?d00001 + +diff --git a/tests/resources/small.git/hooks/commit-msg.sample b/tests/resources/small.git/hooks/commit-msg.sample +new file mode 100755 +index 0000000000000000000000000000000000000000..f3780f92349638ebe32f6baf24c7c3027675d7c9 +GIT binary patch +literal 953 +zcmaJy@-{3h^^Cx;#d0zEA@DDc$nY4ez&|=%jTg@_HU*ub=!!y$xW09TSjlj +z(`I@QCsM`!9&80$I98wsQ8yK#)Orb<8re8FjkKh630D$QUDwi~(gkX=RunYm$rDjk +zlp%RUSnzA#6yjdG5?T?2DcYKp+v_lts0ljn&bh3J0bD5@N@1UKZ190O6ZeWr-BuZ^ +zWRebCX%(%=Xoj#(xYk1Cjtr!=tyBesf@m6}8zY6Ijbz9i9ziI_jG9MvR +zDH*e>^ga9IR?2wrSrAVm;eButj4Y>7(E2?b~jsu>& +zRKCJ7bp#19sqYh627wD%D9R$8=Ml$TNlumDypl~$jBu*G>5fIR^FB0h0Ex&TGZNr> +zL5hs1_K>taRb!|ThN9ns7^@4MXKP+6aGI_UK)T-M#rcP$;kN(Vcf#P)+5GzWa{l@J +z>-E{`$1iiNVYxq27}j;uo%;)r3kJI2xCFF~Ux;$Q%) +wjbk6JlDCM`jU&P+UVOvg`|iYl<7~9k>HHB4I;pdlQ=I-^$DrHaN$@lH1?P!0U;qFB + +literal 0 +HcmV?d00001 + +diff --git a/tests/resources/small.git/hooks/fsmonitor-watchman.sample b/tests/resources/small.git/hooks/fsmonitor-watchman.sample +new file mode 100755 +index 0000000000000000000000000000000000000000..41184ebc318c159f51cd1ebe2290559805df89d8 +GIT binary patch +literal 4777 +zcmbtYYi}F368$Xwipg4lq(BeHMvzvH-4;n7DGJBPqq#tw3aed8+IU5-m)yvL>;Cqh +z8FFRGj$`9CA8aoJ?j^$%==FV``-=rhLcPW`McSytRm~mEO7_&_cAVZrf1fFy*ha@8oe%*-aBYE +zcjzZg>LOkgxuUr-XJnHyD;zmPnRaSc#!k_P*d_BttRdc+J6G7za5#+^Y1nkc2Oowk`ya47uUR3Feu?B(w;S{(VYzxh}q-=#zP@uxSx{wbyPUMFU;K(06)$o{07&3yI?q{GqMcQ1c_^M<0< +zF4acAV)Il-V(rCTC1(;bsZ*}bl8dmejAk~yb`B}!^0;g^(o9kGUfZfDOvyp@x4OQt +zSgWh6T|3eq;9MFs8-#z+FDM1h(IjRUP|``PxupgJ7CUHOH90gbgl^2~97`?_X{P)) +zB*$r1cDlF-%azKND}?Gv`2K8-9v5e`gQoft=j?T<&a13c^!wY_$D`5z-X1g?ty&6- +zQN50{8?bUk9AI->^W@~~nkOghHIC2YN+AXkLQG_2-{Pq3%{`3KUMeG$iIn%%^6*NYb +zn|_BdV#C)n4565VccX;uT8&z3vSi!HXGbUj2B!R +zdz~&#fk#L-&k$fLwo$4?>12g@AXOKFekuo#6EHB%gmpD?1eyh%N8s{2wGoTu +z*@6cEZ^ZW!FAF_|JL`NkV7k}0ow|-2jHwbgH0;c@Dq*o?@&c*HnGdyx6^su8Qk%2{ +z*ye(dxO*6-&>qn1+zw}tc6;=sOX{4WB=VqjTS^))y1jlX2Q;=e!qMmFA5lC$#;BxC +z=Y%tRpWxb+_uQAvAw7Q{HGV#R$xb&udLCzZ+HN?kTyB};1EJ8UlQ5!>5eGW@)RX0n +zkjj>EF!3=0Gl^8dzv$B^NMGRxJoqN4A`xq-@wCbrx*u2NmIJ1xZ%H +zh;{|4T3(!E9sY#Ni(wUJYs1MmIc9bl)(4Nl3_wD_BWB>i<1S(LX7m*{Q7PU$muMS* +zM!%0EZx-Vw=Zey;erC?SNxF;pY@^A%-krqzfLV2meBp1vWdyArFYn`DD19T)Hw(?n +z)}{NP(Lk(o*?gl#B@pP7^*r|=;PIDT4|F#{2Hzh-AL0Rv$6uT;n|WzE4=slK?on@(fZeGhRgQCu56qB +z{+n81Az96qnQjMY*-*r-KV*7;Z#4QuJRJJV$M^KdldiMhj?ImK6~FvwJ*L5a){QoM=L5TYHkGO1$UrO3`a>{?Opw|b +zG(#59NQ#jFL9v~vgOVkM@^^(^A}onOE))yWEwhIlk&{ZyseZ^O0b=w8&O=BK{k<5B +k^Q-B@eG}LeHrquz%(SVEp_N)VhYZikCW__82JXfD17`J9Qvd(} + +literal 0 +HcmV?d00001 + +diff --git a/tests/resources/small.git/hooks/pre-applypatch.sample b/tests/resources/small.git/hooks/pre-applypatch.sample +new file mode 100755 +index 0000000000000000000000000000000000000000..625837e25f91421b8809a097f4a3103dd387ef31 +GIT binary patch +literal 481 +zcmY+ATTa6;5Jms9iouO45IBJXEg&Jm9@v1LPHMM_ZR|;#6tQh$71hSXq*MxP;V& +zj0cY7SCL=x4`a46sF)C>94Gk%=3q$W2s;j6iHtB2$R0%gix4oK@&T~=ALd_o*CKxt +I-`Pv{1Bpzc>;M1& + +literal 0 +HcmV?d00001 + +diff --git a/tests/resources/small.git/hooks/pre-commit.sample b/tests/resources/small.git/hooks/pre-commit.sample +new file mode 100755 +index 0000000000000000000000000000000000000000..10b39b2e26981b8f87ea424e735ef87359066dbb +GIT binary patch +literal 1706 +zcmZuxU2ohr5PY_N#pZ0-F<{-v&v-X^RA+u>k}E$4d&uD7=g_fA8+pNNV=4s0|iD3p<=DTXClTS +zXV23tJ;ECmN@M0j@zUAKEYW@3bv!SeYZ8ZH`YQNTApFVNc;F|9r5p4TqGs=>8E?6y +zi|gY{iM#PG1nL?UE9YCnWTk72kgZPG*Usqw!~Qd3c?~@w2?%eg@~)+VlSs6N5Yf2^ +zz;owF#K#r^&KMq1A`oqVGFpD&-!Pv|Rc +zO3KSqA@h9nSc%bm`0)Amk6*J}@14J*1-219l%%7D!Pl}UK>|lVi0Dfgu2jN3WC!uL +z0ej??b2iSehVgdnWHmZV4kUo*QL#aiIp}U=9x)IXk}JJ7VQ;CI9Rtn5e0VcjbYcVt+`x5D+svCGD;Z5hm*E$jSEQZ%SQ(}oLgslTvrKK@9Qf#b!hajVFnp9@oIix;NcI9Wk +xjnh0ya!AWet{I7YpD;y6HXyzI*lfSvH=o6*7mJZPkuaYpm>vzZ`wyGEBtOQPo|pgt + +literal 0 +HcmV?d00001 + +diff --git a/tests/resources/small.git/hooks/pre-push.sample b/tests/resources/small.git/hooks/pre-push.sample +new file mode 100755 +index 0000000000000000000000000000000000000000..02cbd80c287f959fe33975bb66c56293e3f5b396 +GIT binary patch +literal 1431 +zcmaJ>U60!~5PUX&#a1@z9B{IIZkjLT0t5kq9#8~D(I5{+8&J~9;#ndUk~-ZT`r|uG +z$#K$$J{TsKs*LP1}9!GoZ@4I4myMMG_di|of +z%?llx{O8TS-#^;(OioEmPy%kwWQBA1OMzV{hsQ8XFzS1k!~YQoLa5 +zhtP1fA$q6VmMbbAC_9)4I628k*O5J$NR19uHe4QYDK<==I~SQk)Nu%xQ~KH +z53w=!ke(FGb_PpnZfd*+hnXDTn;2*`u^~;?+5C~cn?bRka7NR%06%e6O91{MAgN6J +zmlO8{Biw4&wr&&(z4p3eln`E}XR9m9bNYZ7Ibrg(4yZIXrfgD7N*AFD7L3YSM#j}% +zo__rOS5fr;@8UM<6cl+cv_$YB$PQ&9dv($eM*))g!_cu!QcSh-mqE9i#QDZT)=o#` +z?8!RtE?w6p?GkGZ-6yt_p~5~4ecu|Sf^)6096%h*q-eNiEA1;Xwg)p~Q&iGSG7-IQ +z9aII&`ps$WOojFA`*bjGkFk|E@sHHuD}W^d`7YJ3YE^zrQnqR +zGoq?;YGKe)93o|_=^f%3U1KYZGPOXRRxK7w`UUbMMa3<86OmVH!EKP$8RCrn9mWX+ +zC?9yF!fRVLmud3hF<}x;;sR}f(*r}6Gap3fR6zLHR~kbMgD{98N`L+r&?3p~*0+FX +zcAL%j=(SO}xTJUTvA`&Lf`2mv4koPG9&|;2+68$XxiXKL@ma;l5d2^5Ba_rPh_DHI-u1#&_upttZXp;no03$20|NFiM +zK#D#xQ>!Z3JkX8T-LDVm!B5j7y_{;JDmmTTef+K1oIiPzeEr+Ai*<2PUgnG4^ZB>p +z_fkAvoR1emuf~ri^K$-px=4#D-vY9w& +z`bCv#2zVn=YnJyeNey(Y +zRh`9vtLw~A+5zsjp|W0Nsa|29Rm!B>OoG5a+vi;ari8O>KkU!KAWg_fa3btK2x*_@ +z0bEc7J;Ubghm}n9bOi(Sv_B66nQ7U)J7f0fO}8Wuf*uorcIgEG +zOHc|-V6+HlRhOP}?Cn?@5iwSl43abmBA^2lyL$+cpabCGVES+v^j^FO_}?FIp%En%Ll?Z*7*}TwrZyg5OSZ9rY-`aU~Mc-jjv{Ll)FLMgtB4ujktfQ`Xhqrka +zT=P!A;9w^;Z?PqpLwOLu=cj3L>TdUKw2;DMu)`oVkj}#bcDx4tYg=j%D`+i{W~fVM +zVmZ>W9VMyin9c-0KzI_;iZ-g|OyzuG`Yq%(%dvl;ifnVr0;jWE&S`z|rQu=!yHBBO +zx`OJ;oOQ(KKM<$(bC38o>pD0%|HA(E0TRw7qj$fJ_pRN+7Nm>dSC(gLg{(`t+5Z=?o+}wXU4tHy+&%F&aRhFebeEhR2R5|$#Ycbp^w@t +zTl%=f1t=w+WpJzF<|CE@?SCNAz)%9?w33lQ8vrHJqPfH9@}qs*QXOG71W=ylx;wOB +zcx!Bj^)Yy6WX$a^vBkBJ5CobqlaDx_B0c<3b+8)f84LCrt;e;qxc+7>VbwVK{skNv!wvBiTa^9Iu +zkwP;VK)jH$WJ{`MRwAA9fal!y0dtV;FWg8PTkWU>CwnqD>1ZX2B@;$DlX%C5MI+}{ +z9xQVnffR*~v2KAUj*hCdgul~`bk#mk`o>zk9)<2Uc8?hUZAEvd!`9em)~$Z)zev>w^8 +zyAgCP_$&Y)7HSQ84`xG}OeTavaEswwF|8Xpi5iZzZa@hCiv(J-%bfFC&)HLlO+Rhw +zG6g?9eL5&A!SuJnQ6}LxG%tU+@vZ`i+!+Rz6iYvsTdhnPo7lW{m-}{hya@viX4)XZ +zngaw+j;gloB#|UwI@8sOmQpc`h+bicQJnQIB5eifIMQNgD2+oai33m!34~xU|0Azj +zhu$8z+T5^;Pxx@d{N)pzOJLSa^e;aDf$W%N5XcOf!mGC9l9j$Ev2h6N+6ZQC+CJzl +zaM7?S!SrFLS2DASjj(h6y1WN3N?|bmqmyzm!&nLoE|`rKBOc_yDF$a#FsUn!IQf(t +zdC&Us(kQz*7mvH^j*^MC@>wTDb}g%~sx*ng#>{@lR=XG-Z5_ +z#<9*Oh0joMzt;nS)ObAp)347`D=}r-;nV!TbIq&xrGRGsF6fZg+!VkfUei@_&l-M& +zPqQ+Dw)RV}+)I8RuqAxa`Pv8e&!_gXS=e2-un>=Ktn}-;%lLZxaVn?Q>yZCb2R3Wk +z77zr%;Rq&h|2ncqyKYmFI0148JVY7Q$V5p=dWj+Qqpu%i|xp2C=WaOb2Wudn^h0EcD%$p9YVU1fnoRV9`(cy(vv6K>FXS!2jY>1GnU--7)4usH&K +zao*&P^@9~YmUe|ZdLW@C>H;!*Vt3>Nw4M*;=?j(TBD#O@XCv0|MEhA;z}kTFRv@`tPHhp=&Yh +zg%Zhg4i7o_k{a5i&f5;tZ==%}^Sn4aD_6%qs_XAuJt&EumdH4Yu`UjT<-+XHTuHss+b +YOmM2;hq8Egm*4=7_P9T{21QBYH*F=mfB*mh + +literal 0 +HcmV?d00001 + +diff --git a/tests/resources/small.git/hooks/prepare-commit-msg.sample b/tests/resources/small.git/hooks/prepare-commit-msg.sample +new file mode 100755 +index 0000000000000000000000000000000000000000..b1970da1b6d3f42f00069fd17c325de72cda812e +GIT binary patch +literal 1702 +zcmb_cTW{Mo6n>t6#i?x6xmZ$SFLf{QfG*3r0L?Pg?px55l8$UTGO3bO;spKi{V3XX +z))weX0X>M9bNMcZ-6yG%>(n}JI2|25dr}WZBP@ih?JX^+@ +zu#5O48P>yRX(mfDIhYP)doc1&TADZa@ZGpusJ$6G+e$ZMcmC +zoOosDQPS}l{H?YPsq(4;0SGkATa9eeqAaDcjq8n2wALbFwU@2i@FAaRV!=uw-nwx1gKn2SvY +z>Ff>;2sg!+Hxfkwv1lsiii=p6WenF=5)6LZcQaZ=aS_}+-4Y&?!@HWh|<^gJ21!|T@+%On#w6azxPHV}XsRbe*w +zR_TZ2XEsQa1lPK~biYqg@0-RW@5J1@=<87cFzEUABdCoFH2CZo?}l(Z*!OFqUxo>K +z_d`l#4d9|H6;VPT{X?^{VJ>oL|D7K{BJwwqB>`YcPoGk+9hbvHnoQ{EM|kPgD_`wk +zKm4#2xu;-y`RAm!=L_BnLvJ8$AZm8@?)v<%vwvsw8AF2x6!mTT;c72A_~U9nIq0ST +zv)N0!I!^1p=g8-RQfx5)E_Mb_4I2vtQpI30XZ&t-9h5!Hn + +literal 0 +HcmV?d00001 + +diff --git a/tests/resources/small.git/hooks/push-to-checkout.sample b/tests/resources/small.git/hooks/push-to-checkout.sample +new file mode 100755 +index 0000000000000000000000000000000000000000..a80611e18896f212c390d845e49a3f6d5693b41d +GIT binary patch +literal 2840 +zcmai0U31$u5PXh)#YOS7cE^-rw@uolNhe9&aUS|HtvhX>G$45tVUYj>fRdF?|9kfU +zNR~aG=E)WbEbeyq7JTw}ZuHIE2kUtL<AoeCNptd-NM1aZLhESzC;I`+Ns +zfmNNjdAp^W8#Q*}l>CT7RB9F5(BbI8ly2l~+E};JW|>&d1)=epZ-8vm8ppkbEVn#R +zt30a5A-c(YQR8eM5%;|UAnO>rt!&@x@G@yp+92%w-}%(5P_+P&Wf_zb$f-Qrl5(7z +z2ah(bkE;!DK(&aAMuQ%1TS>ai?wSXCOCSj=_}8x4IbCx^$}9q)whwv)SBt| +zg#MX4;;Oau`m=MI9(^&zPbueY@~>3*ixX%mvR5m_1&nAg@ZKvY1E$O}&EtLiG;mhV +z1xhMIm~fGjmf_#{62f`y;09?I7M1W2tWQvz<}i9lR>OpQyUJi45_&*pQus&EkwY<> +zI|ZAx=*3i9a-)g)hXkvO7>UJ5MNgL(Z+-wpXVcgbSgpmFmbf1~DPA(OVGI&FNLeIE +zNH!_aiH$vsif$_j7=T2{cS(!DOI`~bn@)vSd-0d7xL=DF;UNP|tW}4ih>DvHtu9tY_pbJ6x(6E*hxgC +zzNDao%qlr-IE%YGbS4hF!n!on7#W3$bX-_hbZAaws^nHu#)Dx=WzdbJ>AKzAy@T$x +zSWE^x9+|TEHVEPyaPYa0DOChp?AeHSBBDbZNokQpAY{lE!7geZI=jV)G^2@l)&91Zb1+`T+oq9wWF +zRV~kGTGce0O~p^6mj{kT5kL(pv>r;Lvd7VDX*P>A^Th`$3cWO0L81p4Ysdo3ZP1(SrR-peEdTo;-@bkB((G +zPHYQXUL!@Q$e(OQ;R9r%@Afz+50I7>*^^c&&|E*r-jN)LH=pM4AqMwWxSv|nqjddE +Z4{_hwv8!W(T +zYw`X3V>TCdnSD1ru8&`j=2DIPbCT@SnIgUw>$+lEYP}+x8(BMYnr=iT3*ndq)xzaV +z>I+qjv}vC#8_9M+b1p#uNS0M0)q

8!3p_LRQ0MA3M`!2foxzRUjbFY@}O~(ki=S +zqscnq8cU*dY)D$$cqE}n)V0yIk>CNKHCrndOtSP*HbOb;nbwAHSb;R+gs^?^Dve%) +zoW}t(*D}$>O3ab0TS^-;J|u&sb-PkZzo#kn*#xYt(;FGuwzSb^g&RDiGcOz9TB;Hu`nJh)$W=C=XCSm2AY=$w3G3P-V#Oo+N*;#2 +z4ijJ-pBZ=;T(RTgp_HYrD!uW-dTMfkuqY5jwOy)~gM;#=P^i{!l7`pXTS^s(&^{RU +zydaw}OpS#^D1cXM8?FW+fh`t7D(g;yr6|}fdaNtZBx3hlK~IpkTu3!Qq%R+zAo#t}Bs8^3$vHD+-TGT@`F>H1Cc#WAVW;&$S6%fE2d6@kLS0g&ihIM{}0z +z8#XhD>b>3{(BH|Px7}&lJ4%y1v(CihZJx@8MPoGdl*BJGD;usf*iS7%;{Joe; +zNFuBa>*~o&qETDPo~u&~$FxE1xb^x&(CbE`Y3GfsibL2rl+L;>P6j&Y3U>K$mkp*6 +zd`Q{<^+^&;GskGjwD-%!boR&i-TCA9UOR|@=GYb5x#+dhd7fkaVIR^pol`Mv+rUbmZ43dVL6^S7g3{NsPiG$iy$5EDB% +z6KIgnb$H(n&t3e4E6d4V7w^B?JS}JkG)PM6+X3Co`SQs($O*AA+MG~{S7RJ=cy-l& +z>~%3y`tjfx2>uOutB_^s +ziwG=e=ch|FQ0IkN91US7rhdQkXhwwt$gU0WEVDjo=IPb+?6PC=s8}J*ua(Ms))`UL +fi$|vMHn?H_tSE3ettp-hLlsZCxaLX8(nU;bVRB;Ce6@s#eu2|WvLz>- +zvy(&>Gyfp@+BtKnpqWkKi^+v{4jn_pNw_zeuxETifiGO|)w}OANj2n2D^K=o3j6P6uOL70#cbA{uzWXDlk1wr9GV1X(2W{RuTvjXV +zCmd8u +zH%V`94=q3)Dk)PHNrnFC(T1)Om6f{Usj;u1R->&XoCYVK2V3ZlgZuF?N}1+33OER*x +z*9Z=L=zI8CN>A_^jYjt0F$psO$sL=38q5q|SG)qCN6{^>RFh5E&l5GZ$pEahnF&d+ +z5c>64t}uJPkf~_!VUj#&N%nC-gUMj%=@B=!V>&}xtj2%@-mOm#rQUSJ3(ccmc+fza +znZ#uxF>N?QN5UrIEd!5RgHEfW#;(nKYF+D<*rdshJ$X-z2OZ2X;)nn@KSVdVhaA?}@3;6gZxb4v +zozoWSr{{+!h}zGpumG3H`=AvWpm^9kW;J$Jp^Xl*?8ckr`fqN%c|Z;VC0|cM4vSrk +zH_O8Yvh85nvJp^;``wo8=z0f`FWg?`>gO#y1hjX1{}rTlg9rwIKia8eyGexA3GnuR +z`Rg~XZoW;0pA)vI8=p5!+6sIn#C^FCvR>ffv39h6SCNi9v);%WD;WZ`of_MgwyRWy +z-yY%n*Y>X89W-v4`Ff%bx$Vkn}$!Ay}rnY6F$m-Kg*KD_+;Lx#g4|^&N +I02NaX#p`nv=Kufz + +literal 0 +HcmV?d00001 + +diff --git a/tests/resources/small.git/objects/af/5626b4a114abcb82d63db7c8082c3c4756e51b b/tests/resources/small.git/objects/af/5626b4a114abcb82d63db7c8082c3c4756e51b +new file mode 100644 +index 0000000000000000000000000000000000000000..822bc151862ec3763cf2d3fa2372b93bbd3a4b65 +GIT binary patch +literal 30 +mcmb>0i}&W3IZ_@1U=^!a~EV1casc=c+{&un1qQN*i9hD|0|m(2n|iwp*q%W +z%N;b$hu%cM`$TMo*~EnC1BFP&Pfj~;jZVKXQ96s_PhV<-XAROi+@-v8dBLUa`!;GB +k^iXlEv8$>R)1G>9th&t3j;s7J{?^9n|7U^`%mXoWC24Q^m!3%@{ + +literal 0 +HcmV?d00001 + From 9b1cefe27e542d890aa346996a03dfecd9793dfe Mon Sep 17 00:00:00 2001 From: Bryan Honof Date: Wed, 28 Aug 2024 18:48:18 +0200 Subject: [PATCH 138/718] Update src/libutil/url.cc Co-authored-by: Robert Hensing --- src/libutil/url.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libutil/url.cc b/src/libutil/url.cc index 78c832440..8ef1857bb 100644 --- a/src/libutil/url.cc +++ b/src/libutil/url.cc @@ -81,7 +81,7 @@ std::map decodeQuery(const std::string & query) auto e = s.find('='); if (e == std::string::npos) { - warn("invalid URI query '%s', did you forget an equals sign `=`?", s); + warn("dubious URI query '%s' is missing equal sign '%s'", s, "="); continue; } From 9cc550d65252d3ad822cc12496ef71482c47ff7e Mon Sep 17 00:00:00 2001 From: Alyssa Ross Date: Sat, 31 Aug 2024 15:59:18 +0200 Subject: [PATCH 139/718] Don't refer to public keys as secret keys in error This constructor is used for public keys as well. --- src/libutil/signature/local-keys.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libutil/signature/local-keys.cc b/src/libutil/signature/local-keys.cc index 858b036f5..00c4543f2 100644 --- a/src/libutil/signature/local-keys.cc +++ b/src/libutil/signature/local-keys.cc @@ -22,7 +22,7 @@ Key::Key(std::string_view s) key = ss.payload; if (name == "" || key == "") - throw Error("secret key is corrupt"); + throw Error("key is corrupt"); key = base64Decode(key); } From a33cb8af5693af56dd69073dc5dddb4c6900ad7a Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 2 Sep 2024 17:28:11 +0200 Subject: [PATCH 140/718] Respect max-substitution-jobs again This broke in #11005. Any number of PathSubstitutionGoals would be woken up by a single build slot becoming available. If there are a lot of substitution goals active, this could lead to us running out of file descriptors (especially on macOS where the default limit is 256). --- src/libstore/build/substitution-goal.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstore/build/substitution-goal.cc b/src/libstore/build/substitution-goal.cc index 0152f1808..a26eea820 100644 --- a/src/libstore/build/substitution-goal.cc +++ b/src/libstore/build/substitution-goal.cc @@ -183,7 +183,7 @@ Goal::Co PathSubstitutionGoal::tryToRun(StorePath subPath, nix::ref sub, /* Make sure that we are allowed to start a substitution. Note that even if maxSubstitutionJobs == 0, we still allow a substituter to run. This prevents infinite waiting. */ - if (worker.getNrSubstitutions() >= std::max(1U, (unsigned int) settings.maxSubstitutionJobs)) { + while (worker.getNrSubstitutions() >= std::max(1U, (unsigned int) settings.maxSubstitutionJobs)) { worker.waitForBuildSlot(shared_from_this()); co_await Suspend{}; } From b7acd1c4145c7316085f2a12bfa26ef742ac6146 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 2 Sep 2024 17:28:55 +0200 Subject: [PATCH 141/718] "unsigned" -> size_t Slight cleanup. --- src/libstore/build/worker.cc | 4 ++-- src/libstore/build/worker.hh | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libstore/build/worker.cc b/src/libstore/build/worker.cc index ab0ba67b5..dbe86f43f 100644 --- a/src/libstore/build/worker.cc +++ b/src/libstore/build/worker.cc @@ -184,13 +184,13 @@ void Worker::wakeUp(GoalPtr goal) } -unsigned Worker::getNrLocalBuilds() +size_t Worker::getNrLocalBuilds() { return nrLocalBuilds; } -unsigned Worker::getNrSubstitutions() +size_t Worker::getNrSubstitutions() { return nrSubstitutions; } diff --git a/src/libstore/build/worker.hh b/src/libstore/build/worker.hh index 33a7bf015..e083dbea6 100644 --- a/src/libstore/build/worker.hh +++ b/src/libstore/build/worker.hh @@ -92,12 +92,12 @@ private: * Number of build slots occupied. This includes local builds but does not * include substitutions or remote builds via the build hook. */ - unsigned int nrLocalBuilds; + size_t nrLocalBuilds; /** * Number of substitution slots occupied. */ - unsigned int nrSubstitutions; + size_t nrSubstitutions; /** * Maps used to prevent multiple instantiations of a goal for the @@ -235,12 +235,12 @@ public: * Return the number of local build processes currently running (but not * remote builds via the build hook). */ - unsigned int getNrLocalBuilds(); + size_t getNrLocalBuilds(); /** * Return the number of substitution processes currently running. */ - unsigned int getNrSubstitutions(); + size_t getNrSubstitutions(); /** * Registers a running child process. `inBuildSlot` means that From 13100eaa4f5b8e1934e312ac9300bd0e84d450c2 Mon Sep 17 00:00:00 2001 From: Sandro Date: Mon, 2 Sep 2024 23:25:44 +0200 Subject: [PATCH 142/718] Fix link anchor --- src/libstore/globals.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh index e5e7024cb..be922c9f7 100644 --- a/src/libstore/globals.hh +++ b/src/libstore/globals.hh @@ -1204,7 +1204,7 @@ public: If the user is trusted (see `trusted-users` option), when building a fixed-output derivation, environment variables set in this option - will be passed to the builder if they are listed in [`impureEnvVars`](@docroot@/language/advanced-attributes.md##adv-attr-impureEnvVars). + will be passed to the builder if they are listed in [`impureEnvVars`](@docroot@/language/advanced-attributes.md#adv-attr-impureEnvVars). This option is useful for, e.g., setting `https_proxy` for fixed-output derivations and in a multi-user Nix installation, or From 4decd6f8b3bf11636f6710a3d8db396ba30fefe2 Mon Sep 17 00:00:00 2001 From: Jeremy Kerfs Date: Tue, 3 Sep 2024 03:36:00 -0500 Subject: [PATCH 143/718] add removal of ~root/.cache/nix to uninstall instructions (#11407) --- doc/manual/src/installation/uninstall.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/manual/src/installation/uninstall.md b/doc/manual/src/installation/uninstall.md index 91fb90bc0..bb21af24e 100644 --- a/doc/manual/src/installation/uninstall.md +++ b/doc/manual/src/installation/uninstall.md @@ -19,7 +19,7 @@ If you are on Linux with systemd: Remove files created by Nix: ```console -sudo rm -rf /etc/nix /etc/profile.d/nix.sh /etc/tmpfiles.d/nix-daemon.conf /nix ~root/.nix-channels ~root/.nix-defexpr ~root/.nix-profile +sudo rm -rf /etc/nix /etc/profile.d/nix.sh /etc/tmpfiles.d/nix-daemon.conf /nix ~root/.nix-channels ~root/.nix-defexpr ~root/.nix-profile ~root/.cache/nix ``` Remove build users and their group: From 02bb633a582b05991e77b65e866a06ef21b2482a Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 3 Sep 2024 16:49:57 +0200 Subject: [PATCH 144/718] maintainers/upload-release.pl: Delete temporary directories when we're done --- maintainers/upload-release.pl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/maintainers/upload-release.pl b/maintainers/upload-release.pl index 731988568..8a470c7cc 100755 --- a/maintainers/upload-release.pl +++ b/maintainers/upload-release.pl @@ -112,7 +112,7 @@ sub copyManual { system("xz -d < '$manualNar' | nix-store --restore $tmpDir/manual.tmp") == 0 or die "unable to unpack $manualNar\n"; rename("$tmpDir/manual.tmp/share/doc/nix/manual", "$tmpDir/manual") or die; - system("rm -rf '$tmpDir/manual.tmp'") == 0 or die; + File::Path::remove_tree("$tmpDir/manual.tmp", {safe => 1}); } system("aws s3 sync '$tmpDir/manual' s3://$releasesBucketName/$releaseDir/manual") == 0 @@ -281,3 +281,6 @@ system("git remote update origin") == 0 or die; system("git tag --force --sign $version $nixRev -m 'Tagging release $version'") == 0 or die; system("git push --tags") == 0 or die; system("git push --force-with-lease origin $nixRev:refs/heads/latest-release") == 0 or die if $isLatest; + +File::Path::remove_tree($narCache, {safe => 1}); +File::Path::remove_tree($tmpDir, {safe => 1}); From 46b31880458f0cbea2a45a42734d1ac76c9ea88f Mon Sep 17 00:00:00 2001 From: Parker Hoyes Date: Mon, 26 Aug 2024 13:50:22 +0000 Subject: [PATCH 145/718] Move daemon process into sub-cgroup The daemon process is now moved into a new sub-cgroup called nix-daemon when the daemon starts. This is necessary to abide by the no-processes-in-inner-nodes rule, because the service cgroup becomes an inner node when the child cgroups for the build are created (see LocalDerivationGoal::startBuilder()). See #9675 --- .../unix/build/local-derivation-goal.cc | 21 ++++++------ src/libutil/linux/cgroup.cc | 32 +++++++++++++++++++ src/libutil/linux/cgroup.hh | 9 ++++++ src/nix/unix/daemon.cc | 25 +++++++++++++++ 4 files changed, 75 insertions(+), 12 deletions(-) diff --git a/src/libstore/unix/build/local-derivation-goal.cc b/src/libstore/unix/build/local-derivation-goal.cc index 01a133766..d55278a52 100644 --- a/src/libstore/unix/build/local-derivation-goal.cc +++ b/src/libstore/unix/build/local-derivation-goal.cc @@ -444,25 +444,22 @@ void LocalDerivationGoal::startBuilder() #if __linux__ experimentalFeatureSettings.require(Xp::Cgroups); + /* If we're running from the daemon, then this will return the + root cgroup of the service. Otherwise, it will return the + current cgroup. */ + auto rootCgroup = getRootCgroup(); auto cgroupFS = getCgroupFS(); if (!cgroupFS) throw Error("cannot determine the cgroups file system"); - - auto ourCgroups = getCgroups("/proc/self/cgroup"); - auto ourCgroup = ourCgroups[""]; - if (ourCgroup == "") - throw Error("cannot determine cgroup name from /proc/self/cgroup"); - - auto ourCgroupPath = canonPath(*cgroupFS + "/" + ourCgroup); - - if (!pathExists(ourCgroupPath)) - throw Error("expected cgroup directory '%s'", ourCgroupPath); + auto rootCgroupPath = canonPath(*cgroupFS + "/" + rootCgroup); + if (!pathExists(rootCgroupPath)) + throw Error("expected cgroup directory '%s'", rootCgroupPath); static std::atomic counter{0}; cgroup = buildUser - ? fmt("%s/nix-build-uid-%d", ourCgroupPath, buildUser->getUID()) - : fmt("%s/nix-build-pid-%d-%d", ourCgroupPath, getpid(), counter++); + ? fmt("%s/nix-build-uid-%d", rootCgroupPath, buildUser->getUID()) + : fmt("%s/nix-build-pid-%d-%d", rootCgroupPath, getpid(), counter++); debug("using cgroup '%s'", *cgroup); diff --git a/src/libutil/linux/cgroup.cc b/src/libutil/linux/cgroup.cc index 140ff4566..706f0f159 100644 --- a/src/libutil/linux/cgroup.cc +++ b/src/libutil/linux/cgroup.cc @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -144,4 +145,35 @@ CgroupStats destroyCgroup(const Path & cgroup) return destroyCgroup(cgroup, true); } +std::string getCurrentCgroup() +{ + auto cgroupFS = getCgroupFS(); + if (!cgroupFS) + throw Error("cannot determine the cgroups file system"); + + auto ourCgroups = getCgroups("/proc/self/cgroup"); + auto ourCgroup = ourCgroups[""]; + if (ourCgroup == "") + throw Error("cannot determine cgroup name from /proc/self/cgroup"); + return ourCgroup; +} + +static std::optional rootCgroup; +static std::mutex rootCgroupMutex; + +std::string getRootCgroup() +{ + { + std::lock_guard guard(rootCgroupMutex); + if (rootCgroup) + return *rootCgroup; + } + auto current = getCurrentCgroup(); + std::lock_guard guard(rootCgroupMutex); + if (rootCgroup) + return *rootCgroup; + rootCgroup = current; + return current; +} + } diff --git a/src/libutil/linux/cgroup.hh b/src/libutil/linux/cgroup.hh index 783a0ab87..87d135ba6 100644 --- a/src/libutil/linux/cgroup.hh +++ b/src/libutil/linux/cgroup.hh @@ -25,4 +25,13 @@ struct CgroupStats */ CgroupStats destroyCgroup(const Path & cgroup); +std::string getCurrentCgroup(); + +/** + * Get the cgroup that should be used as the parent when creating new + * sub-cgroups. The first time this is called, the current cgroup will be + * returned, and then all subsequent calls will return the original cgroup. + */ +std::string getRootCgroup(); + } diff --git a/src/nix/unix/daemon.cc b/src/nix/unix/daemon.cc index 66d8dbcf0..746963a01 100644 --- a/src/nix/unix/daemon.cc +++ b/src/nix/unix/daemon.cc @@ -33,6 +33,10 @@ #include #include +#if __linux__ +#include "cgroup.hh" +#endif + #if __APPLE__ || __FreeBSD__ #include #endif @@ -312,6 +316,27 @@ static void daemonLoop(std::optional forceTrustClientOpt) // Get rid of children automatically; don't let them become zombies. setSigChldAction(true); + #if __linux__ + if (settings.useCgroups) { + experimentalFeatureSettings.require(Xp::Cgroups); + + // This also sets the root cgroup to the current one. + auto rootCgroup = getRootCgroup(); + auto cgroupFS = getCgroupFS(); + if (!cgroupFS) + throw Error("cannot determine the cgroups file system"); + auto rootCgroupPath = canonPath(*cgroupFS + "/" + rootCgroup); + if (!pathExists(rootCgroupPath)) + throw Error("expected cgroup directory '%s'", rootCgroupPath); + auto daemonCgroupPath = rootCgroupPath + "/nix-daemon"; + // Create new sub-cgroup for the daemon. + if (mkdir(daemonCgroupPath.c_str(), 0755) != 0 && errno != EEXIST) + throw SysError("creating cgroup '%s'", daemonCgroupPath); + // Move daemon into the new cgroup. + writeFile(daemonCgroupPath + "/cgroup.procs", fmt("%d", getpid())); + } + #endif + // Loop accepting connections. while (1) { From 4c88deef38678154f3043ca2e0f4bd84a3c6cbc5 Mon Sep 17 00:00:00 2001 From: Parker Hoyes Date: Tue, 3 Sep 2024 17:27:56 +0000 Subject: [PATCH 146/718] Add tests for daemon with cgroups --- tests/nixos/cgroups/default.nix | 40 +++++++++++++++++++++++++++++++++ tests/nixos/cgroups/hang.nix | 10 +++++++++ tests/nixos/default.nix | 2 ++ 3 files changed, 52 insertions(+) create mode 100644 tests/nixos/cgroups/default.nix create mode 100644 tests/nixos/cgroups/hang.nix diff --git a/tests/nixos/cgroups/default.nix b/tests/nixos/cgroups/default.nix new file mode 100644 index 000000000..b8febbf4b --- /dev/null +++ b/tests/nixos/cgroups/default.nix @@ -0,0 +1,40 @@ +{ nixpkgs, ... }: + +{ + name = "cgroups"; + + nodes = + { + host = + { config, pkgs, ... }: + { virtualisation.additionalPaths = [ pkgs.stdenvNoCC ]; + nix.extraOptions = + '' + extra-experimental-features = nix-command auto-allocate-uids cgroups + extra-system-features = uid-range + ''; + nix.settings.use-cgroups = true; + nix.nixPath = [ "nixpkgs=${nixpkgs}" ]; + }; + }; + + testScript = { nodes }: '' + start_all() + + host.wait_for_unit("multi-user.target") + + # Start build in background + host.execute("NIX_REMOTE=daemon nix build --auto-allocate-uids --file ${./hang.nix} >&2 &") + service = "/sys/fs/cgroup/system.slice/nix-daemon.service" + + # Wait for cgroups to be created + host.succeed(f"until [ -e {service}/nix-daemon ]; do sleep 1; done", timeout=30) + host.succeed(f"until [ -e {service}/nix-build-uid-* ]; do sleep 1; done", timeout=30) + + # Check that there aren't processes where there shouldn't be, and that there are where there should be + host.succeed(f'[ -z "$(cat {service}/cgroup.procs)" ]') + host.succeed(f'[ -n "$(cat {service}/nix-daemon/cgroup.procs)" ]') + host.succeed(f'[ -n "$(cat {service}/nix-build-uid-*/cgroup.procs)" ]') + ''; + +} diff --git a/tests/nixos/cgroups/hang.nix b/tests/nixos/cgroups/hang.nix new file mode 100644 index 000000000..cefe2d031 --- /dev/null +++ b/tests/nixos/cgroups/hang.nix @@ -0,0 +1,10 @@ +{ }: + +with import {}; + +runCommand "hang" + { requiredSystemFeatures = "uid-range"; + } + '' + sleep infinity + '' diff --git a/tests/nixos/default.nix b/tests/nixos/default.nix index 40d29b371..62fc6b10f 100644 --- a/tests/nixos/default.nix +++ b/tests/nixos/default.nix @@ -157,4 +157,6 @@ in s3-binary-cache-store = runNixOSTestFor "x86_64-linux" ./s3-binary-cache-store.nix; fsync = runNixOSTestFor "x86_64-linux" ./fsync.nix; + + cgroups = runNixOSTestFor "x86_64-linux" ./cgroups; } From 62a99049c40be4971220f4115f00943f5e299b07 Mon Sep 17 00:00:00 2001 From: Parker Hoyes Date: Tue, 3 Sep 2024 19:07:18 +0000 Subject: [PATCH 147/718] Enable cgroups delegation for systemd --- misc/systemd/nix-daemon.service.in | 1 + 1 file changed, 1 insertion(+) diff --git a/misc/systemd/nix-daemon.service.in b/misc/systemd/nix-daemon.service.in index 45fbea02c..b3055cfe2 100644 --- a/misc/systemd/nix-daemon.service.in +++ b/misc/systemd/nix-daemon.service.in @@ -11,6 +11,7 @@ ExecStart=@@bindir@/nix-daemon nix-daemon --daemon KillMode=process LimitNOFILE=1048576 TasksMax=1048576 +Delegate=yes [Install] WantedBy=multi-user.target From 9e79061bac9d60cc2704964dc6fcc736c91173b2 Mon Sep 17 00:00:00 2001 From: Cole Helbling Date: Tue, 3 Sep 2024 13:27:11 -0700 Subject: [PATCH 148/718] fixup: use the real bindir for systemd unit's bindir Prior to this commit, the unit contained this line: ExecStart=@share/nix-daemon nix-daemon --daemon which caused systemd to complain: Failed to restart nix-daemon.service: Unit nix-daemon.service has a bad unit file setting. See system logs and 'systemctl status nix-daemon.service' for details. and had this in the unit output: Sep 03 13:34:59 scadrial systemd[1]: /etc/systemd/system/nix-daemon.service:10: Neither a valid executable name nor an absolute path: share/nix-daemon Sep 03 13:34:59 scadrial systemd[1]: nix-daemon.service: Unit configuration has fatal error, unit will not be started. (Notice how it's trying to execute `share/nix-daemon`, which is unlikely to exist.) Now with this commit, the path to the daemon binary is properly set: ExecStart=@/nix/store/lcbx6d8gzznf3z3c8lsv9jy3j6c67x6r-nix-2.25.0pre20240903_dirty/bin/nix-daemon nix-daemon --daemon --- misc/systemd/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc/systemd/meson.build b/misc/systemd/meson.build index 58b30f30b..6ccb6a873 100644 --- a/misc/systemd/meson.build +++ b/misc/systemd/meson.build @@ -8,7 +8,7 @@ foreach config : [ 'nix-daemon.socket', 'nix-daemon.service' ] configuration : { 'storedir' : store_dir, 'localstatedir' : localstatedir, - 'bindir' : get_option('datadir'), + 'bindir' : bindir, }, ) endforeach From 9d24080090539c717015add8f2d8ce02d1d84a2d Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 4 Sep 2024 14:43:43 +0200 Subject: [PATCH 149/718] Git fetcher: Ignore .gitmodules entries that are not submodules Fixes #10739. --- src/libfetchers/git-utils.cc | 18 ++++++++++++------ tests/functional/fetchGitSubmodules.sh | 21 +++++++++++++++++++++ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/libfetchers/git-utils.cc b/src/libfetchers/git-utils.cc index 114aa4ec0..0bc930ab2 100644 --- a/src/libfetchers/git-utils.cc +++ b/src/libfetchers/git-utils.cc @@ -601,12 +601,16 @@ struct GitSourceAccessor : SourceAccessor return readBlob(path, true); } - Hash getSubmoduleRev(const CanonPath & path) + /** + * If `path` exists and is a submodule, return its + * revision. Otherwise return nothing. + */ + std::optional getSubmoduleRev(const CanonPath & path) { - auto entry = need(path); + auto entry = lookup(path); - if (git_tree_entry_type(entry) != GIT_OBJECT_COMMIT) - throw Error("'%s' is not a submodule", showPath(path)); + if (!entry || git_tree_entry_type(entry) != GIT_OBJECT_COMMIT) + return std::nullopt; return toHash(*git_tree_entry_id(entry)); } @@ -1074,8 +1078,10 @@ std::vector> GitRepoImpl::getSubmodules auto rawAccessor = getRawAccessor(rev); for (auto & submodule : parseSubmodules(pathTemp)) { - auto rev = rawAccessor->getSubmoduleRev(submodule.path); - result.push_back({std::move(submodule), rev}); + /* Filter out .gitmodules entries that don't exist or are not + submodules. */ + if (auto rev = rawAccessor->getSubmoduleRev(submodule.path)) + result.push_back({std::move(submodule), *rev}); } return result; diff --git a/tests/functional/fetchGitSubmodules.sh b/tests/functional/fetchGitSubmodules.sh index 4a3e4c347..cd3b51674 100755 --- a/tests/functional/fetchGitSubmodules.sh +++ b/tests/functional/fetchGitSubmodules.sh @@ -104,6 +104,27 @@ noSubmoduleRepo=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$subR [[ $noSubmoduleRepoBaseline == $noSubmoduleRepo ]] +# Test .gitmodules with entries that refer to non-existent objects or objects that are not submodules. +cat >> $rootRepo/.gitmodules < $rootRepo/file +git -C $rootRepo add file +git -C $rootRepo commit -a -m "Add bad submodules" + +rev=$(git -C $rootRepo rev-parse HEAD) + +r=$(nix eval --raw --expr "builtins.fetchGit { url = file://$rootRepo; rev = \"$rev\"; submodules = true; }") + +[[ -f $r/file ]] +[[ ! -e $r/missing ]] + # Test relative submodule URLs. rm $TEST_HOME/.cache/nix/fetcher-cache* rm -rf $rootRepo/.git $rootRepo/.gitmodules $rootRepo/sub From 46f65058655550bff87cf547954f7ca5622d1b2d Mon Sep 17 00:00:00 2001 From: Jeremy Kolb Date: Wed, 4 Sep 2024 10:14:51 -0400 Subject: [PATCH 150/718] Pull fut.get() out of the lock This is https://gerrit.lix.systems/c/lix/+/1462 by @jade_ see: https://git.lix.systems/lix-project/lix/issues/366 see: https://gerrit.lix.systems/c/lix/+/1462 --- src/libstore/store-api.cc | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index 8eef340cc..fc03133f8 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -822,14 +822,25 @@ StorePathSet Store::queryValidPaths(const StorePathSet & paths, SubstituteFlag m auto doQuery = [&](const StorePath & path) { checkInterrupt(); queryPathInfo(path, {[path, &state_, &wakeup](std::future> fut) { - auto state(state_.lock()); + bool exists = false; + std::exception_ptr newExc{}; + try { auto info = fut.get(); - state->valid.insert(path); + exists = true; } catch (InvalidPath &) { } catch (...) { - state->exc = std::current_exception(); + newExc = std::current_exception(); } + + auto state(state_.lock()); + + if (exists) + state->valid.insert(path); + + if (newExc != nullptr) + state->exc = newExc; + assert(state->left); if (!--state->left) wakeup.notify_one(); From 8152c5c828e845bf39334318c65297cf3dfbf518 Mon Sep 17 00:00:00 2001 From: Jeremy Kolb Date: Wed, 4 Sep 2024 12:55:32 -0400 Subject: [PATCH 151/718] Remote nullptr Co-authored-by: Eelco Dolstra --- src/libstore/store-api.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index fc03133f8..fc8d51c39 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -838,7 +838,7 @@ StorePathSet Store::queryValidPaths(const StorePathSet & paths, SubstituteFlag m if (exists) state->valid.insert(path); - if (newExc != nullptr) + if (newExc) state->exc = newExc; assert(state->left); From 03484641a1c712b6d10f636e7dbb5280c1668c4b Mon Sep 17 00:00:00 2001 From: Parker Hoyes Date: Wed, 4 Sep 2024 18:11:16 +0000 Subject: [PATCH 152/718] Simplify getRootCgroup() Static local initializers are atomic in C++. --- src/libutil/linux/cgroup.cc | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/src/libutil/linux/cgroup.cc b/src/libutil/linux/cgroup.cc index 706f0f159..ad3e8a017 100644 --- a/src/libutil/linux/cgroup.cc +++ b/src/libutil/linux/cgroup.cc @@ -6,7 +6,6 @@ #include #include -#include #include #include #include @@ -158,22 +157,10 @@ std::string getCurrentCgroup() return ourCgroup; } -static std::optional rootCgroup; -static std::mutex rootCgroupMutex; - std::string getRootCgroup() { - { - std::lock_guard guard(rootCgroupMutex); - if (rootCgroup) - return *rootCgroup; - } - auto current = getCurrentCgroup(); - std::lock_guard guard(rootCgroupMutex); - if (rootCgroup) - return *rootCgroup; - rootCgroup = current; - return current; + static std::string rootCgroup = getCurrentCgroup(); + return rootCgroup; } } From bd6ae2f3b929e8bf280692f3cae36bce7f688b4f Mon Sep 17 00:00:00 2001 From: Parker Hoyes Date: Wed, 4 Sep 2024 19:10:31 +0000 Subject: [PATCH 153/718] Use getCurrentCgroup() in getMaxCPU() --- src/libutil/current-process.cc | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/libutil/current-process.cc b/src/libutil/current-process.cc index 0bc46d746..ed1c1ca6c 100644 --- a/src/libutil/current-process.cc +++ b/src/libutil/current-process.cc @@ -32,11 +32,7 @@ unsigned int getMaxCPU() auto cgroupFS = getCgroupFS(); if (!cgroupFS) return 0; - auto cgroups = getCgroups("/proc/self/cgroup"); - auto cgroup = cgroups[""]; - if (cgroup == "") return 0; - - auto cpuFile = *cgroupFS + "/" + cgroup + "/cpu.max"; + auto cpuFile = *cgroupFS + "/" + getCurrentCgroup() + "/cpu.max"; auto cpuMax = readFile(cpuFile); auto cpuMaxParts = tokenizeString>(cpuMax, " \n"); From 495d32e1b8e5d5143f048d1be755a96bea822b19 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 4 Sep 2024 21:43:59 +0200 Subject: [PATCH 154/718] NAR parser: Fix check for duplicate / incorrectly sorted entries "prevName" was always empty because it was declared in the wrong scope. --- src/libutil/archive.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libutil/archive.cc b/src/libutil/archive.cc index 9ed65be6a..e4a6a3181 100644 --- a/src/libutil/archive.cc +++ b/src/libutil/archive.cc @@ -214,11 +214,13 @@ static void parse(FileSystemObjectSink & sink, Source & source, const CanonPath else if (t == "directory") { sink.createDirectory(path); + std::string prevName; + while (1) { s = getString(); if (s == "entry") { - std::string name, prevName; + std::string name; s = getString(); if (s != "(") throw badArchive("expected open tag"); From ef3d3c568248ce5f2b2b7ff1bebb837d22b7df65 Mon Sep 17 00:00:00 2001 From: "Travis A. Everett" Date: Wed, 4 Sep 2024 20:19:39 -0500 Subject: [PATCH 155/718] use existing GID in sequoia migration script I hardcoded the wrong GID (30001 instead of 30000), but it's better to just pick up the GID from the existing group. --- scripts/sequoia-nixbld-user-migration.sh | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/scripts/sequoia-nixbld-user-migration.sh b/scripts/sequoia-nixbld-user-migration.sh index 644249192..ecf19fc87 100755 --- a/scripts/sequoia-nixbld-user-migration.sh +++ b/scripts/sequoia-nixbld-user-migration.sh @@ -17,18 +17,23 @@ any_nixbld(){ dscl . list /Users UniqueID | grep -E '\b_nixbld' >/dev/null } +dsclattr() { + dscl . -read "$1" | awk "/$2/ { print \$2 }" +} + re_create_nixbld_user(){ local name uid name="$1" uid="$2" + gid="$3" sudo /usr/bin/dscl . -create "/Users/$name" "UniqueID" "$uid" sudo /usr/bin/dscl . -create "/Users/$name" "IsHidden" "1" sudo /usr/bin/dscl . -create "/Users/$name" "NFSHomeDirectory" "/var/empty" sudo /usr/bin/dscl . -create "/Users/$name" "RealName" "Nix build user $name" sudo /usr/bin/dscl . -create "/Users/$name" "UserShell" "/sbin/nologin" - sudo /usr/bin/dscl . -create "/Users/$name" "PrimaryGroupID" "30001" + sudo /usr/bin/dscl . -create "/Users/$name" "PrimaryGroupID" "$gid" } hit_id_cap(){ @@ -68,11 +73,12 @@ temporarily_move_existing_nixbld_uids(){ } change_nixbld_uids(){ - local name next_id user_n + local existing_gid name next_id user_n ((next_id=NEW_NIX_FIRST_BUILD_UID)) ((user_n=1)) name="$(nix_user_n "$user_n")" + existing_gid="$(dsclattr "/Groups/nixbld" "PrimaryGroupID")" # we know that we have *some* nixbld users, but macOS may have # already clobbered the first few users if this system has been @@ -91,7 +97,7 @@ change_nixbld_uids(){ fi done - re_create_nixbld_user "$name" "$next_id" + re_create_nixbld_user "$name" "$next_id" "$existing_gid" echo " $name was missing; created with uid: $next_id" ((user_n++)) From 38d9d536a884db28edb4f31a415921029c93faae Mon Sep 17 00:00:00 2001 From: Valentin Gagarin Date: Thu, 5 Sep 2024 03:28:06 +0200 Subject: [PATCH 156/718] docs: small fixups on the default expression - highlighted example - linked definitions to the glossary (this is a shorter read) - fixed some artefact --- .../files/default-nix-expression.md | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/doc/manual/src/command-ref/files/default-nix-expression.md b/doc/manual/src/command-ref/files/default-nix-expression.md index 620f7035c..2bd45ff5d 100644 --- a/doc/manual/src/command-ref/files/default-nix-expression.md +++ b/doc/manual/src/command-ref/files/default-nix-expression.md @@ -1,6 +1,6 @@ ## Default Nix expression -The source for the default [Nix expressions](@docroot@/language/index.md) used by [`nix-env`]: +The source for the [Nix expressions](@docroot@/glossary.md#gloss-nix-expression) used by [`nix-env`] by default: - `~/.nix-defexpr` - `$XDG_STATE_HOME/nix/defexpr` if [`use-xdg-base-directories`] is set to `true`. @@ -18,24 +18,25 @@ Then, the resulting expression is interpreted like this: - If the expression is an attribute set, it is used as the default Nix expression. - If the expression is a function, an empty set is passed as argument and the return value is used as the default Nix expression. - -For example, if the default expression contains two files, `foo.nix` and `bar.nix`, then the default Nix expression will be equivalent to - -```nix -{ - foo = import ~/.nix-defexpr/foo.nix; - bar = import ~/.nix-defexpr/bar.nix; -} -``` +> **Example** +> +> If the default expression contains two files, `foo.nix` and `bar.nix`, then the default Nix expression will be equivalent to +> +> ```nix +> { +> foo = import ~/.nix-defexpr/foo.nix; +> bar = import ~/.nix-defexpr/bar.nix; +> } +> ``` The file [`manifest.nix`](@docroot@/command-ref/files/manifest.nix.md) is always ignored. -The command [`nix-channel`] places a symlink to the user's current [channels profile](@docroot@/command-ref/files/channels.md) in this directory. +The command [`nix-channel`] places a symlink to the current user's [channels] in this directory, the [user channel link](#user-channel-link). This makes all subscribed channels available as attributes in the default expression. ## User channel link -A symlink that ensures that [`nix-env`] can find your channels: +A symlink that ensures that [`nix-env`] can find the current user's [channels]: - `~/.nix-defexpr/channels` - `$XDG_STATE_HOME/defexpr/channels` if [`use-xdg-base-directories`] is set to `true`. @@ -45,8 +46,9 @@ This symlink points to: - `$XDG_STATE_HOME/profiles/channels` for regular users - `$NIX_STATE_DIR/profiles/per-user/root/channels` for `root` -In a multi-user installation, you may also have `~/.nix-defexpr/channels_root`, which links to the channels of the root user.[`nix-env`]: ../nix-env.md +In a multi-user installation, you may also have `~/.nix-defexpr/channels_root`, which links to the channels of the root user. -[`nix-env`]: @docroot@/command-ref/nix-env.md [`nix-channel`]: @docroot@/command-ref/nix-channel.md +[`nix-env`]: @docroot@/command-ref/nix-env.md [`use-xdg-base-directories`]: @docroot@/command-ref/conf-file.md#conf-use-xdg-base-directories +[channels]: @docroot@/command-ref/files/channels.md From 48249e001a7c1bc9fac7a94a997566164944b17c Mon Sep 17 00:00:00 2001 From: Valentin Gagarin Date: Thu, 5 Sep 2024 04:13:43 +0200 Subject: [PATCH 157/718] docs: reword glossary entry on Nix expression this makes it less cumbersome to read and puts the statements in meaningful order. --- doc/manual/src/glossary.md | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/doc/manual/src/glossary.md b/doc/manual/src/glossary.md index 877c4668b..808ef477c 100644 --- a/doc/manual/src/glossary.md +++ b/doc/manual/src/glossary.md @@ -182,13 +182,18 @@ - [Nix expression]{#gloss-nix-expression} - 1. Commonly, a high-level description of software packages and compositions - thereof. Deploying software using Nix entails writing Nix - expressions for your packages. Nix expressions specify [derivations][derivation], - which are [instantiated][instantiate] into the Nix store as [store derivations][store derivation]. - These derivations can then be [realised][realise] to produce [outputs][output]. + A syntactically valid use of the [Nix language]. - 2. A syntactically valid use of the [Nix language]. For example, the contents of a `.nix` file form an expression. + > **Example** + > + > The contents of a `.nix` file form a Nix expression. + + Nix expressions specify [derivations][derivation], which are [instantiated][instantiate] into the Nix store as [store derivations][store derivation]. + These derivations can then be [realised][realise] to produce [outputs][output]. + + > **Example** + > + > Building and deploying software using Nix entails writing Nix expressions as a high-level description of packages and compositions thereof. - [reference]{#gloss-reference} From 17655ecfefc1f804caf935902469ebb1f621deac Mon Sep 17 00:00:00 2001 From: Valentin Gagarin Date: Thu, 5 Sep 2024 04:18:02 +0200 Subject: [PATCH 158/718] docs: explain provenance of default `nix-path` values this should make it more obvious how things are related to each other, and also hopefully expose the historical context without having to say on every corner that these details are accounting for legacy decisions. --- src/libexpr/eval-settings.hh | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/libexpr/eval-settings.hh b/src/libexpr/eval-settings.hh index 3d412bbbf..115e3ee50 100644 --- a/src/libexpr/eval-settings.hh +++ b/src/libexpr/eval-settings.hh @@ -87,10 +87,19 @@ struct EvalSettings : Config If the respective paths are accessible, the default values are: - `$HOME/.nix-defexpr/channels` + + The [user channel link](@docroot@/command-ref/files/default-nix-expression.md#user-channel-link), pointing to the current state of [channels](@docroot@/command-ref/files/channels.md) for the current user. + - `nixpkgs=$NIX_STATE_DIR/profiles/per-user/root/channels/nixpkgs` + + The current state of the `nixpkgs` channel for the `root` user. + - `$NIX_STATE_DIR/profiles/per-user/root/channels` - See [`NIX_STATE_DIR`](@docroot@/command-ref/env-common.md#env-NIX_STATE_DIR) for details. + The current state of all channels for the `root` user. + + These files are set up by the [Nix installer](@docroot@/installation/installing-binary.md). + See [`NIX_STATE_DIR`](@docroot@/command-ref/env-common.md#env-NIX_STATE_DIR) for details on the environment variable. > **Note** > From a1cc362d9d249b95e4c9ad403f1e6e26ca302413 Mon Sep 17 00:00:00 2001 From: Valentin Gagarin Date: Thu, 5 Sep 2024 10:34:07 +0200 Subject: [PATCH 159/718] fix broken link (#11435) --- doc/manual/src/glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/manual/src/glossary.md b/doc/manual/src/glossary.md index 877c4668b..aacee2680 100644 --- a/doc/manual/src/glossary.md +++ b/doc/manual/src/glossary.md @@ -119,7 +119,7 @@ A store object consists of a [file system object], [references][reference] to other store objects, and other metadata. It can be referred to by a [store path]. - See [Store Object](@docroot@/store/index.md#store-object) for details. + See [Store Object](@docroot@/store/store-object.md) for details. [store object]: #gloss-store-object From 22ba4dc78d956020e06e0618f020e11700749823 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Mon, 26 Aug 2024 21:14:20 +0200 Subject: [PATCH 160/718] builtins.readDir: fix nix error trace on filesystem errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before: nix-env % ./src/nix/nix eval --impure --expr 'let f = builtins.readDir "/nix/store/hs3yxdq9knimwdm51gvbs4dvncz46f9d-hello-2.12.1/foo"; in f' --show-trace error: filesystem error: directory iterator cannot open directory: No such file or directory [/nix/store/hs3yxdq9knimwdm51gvbs4dvncz46f9d-hello-2.12.1/foo] After: error: … while calling the 'readDir' builtin at «string»:1:9: 1| let f = builtins.readDir "/nix/store/hs3yxdq9knimwdm51gvbs4dvncz46f9d-hello-2.12.1/foo"; in f | ^ error: reading directory '/nix/store/hs3yxdq9knimwdm51gvbs4dvncz46f9d-hello-2.12.1/foo': No such file or directory --- src/libutil/posix-source-accessor.cc | 40 +++++++++++++++------------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/src/libutil/posix-source-accessor.cc b/src/libutil/posix-source-accessor.cc index 8cec3388d..f26f74d58 100644 --- a/src/libutil/posix-source-accessor.cc +++ b/src/libutil/posix-source-accessor.cc @@ -132,23 +132,24 @@ SourceAccessor::DirEntries PosixSourceAccessor::readDirectory(const CanonPath & { assertNoSymlinks(path); DirEntries res; - for (auto & entry : std::filesystem::directory_iterator{makeAbsPath(path)}) { - checkInterrupt(); - auto type = [&]() -> std::optional { - std::filesystem::file_type nativeType; - try { - nativeType = entry.symlink_status().type(); - } catch (std::filesystem::filesystem_error & e) { - // We cannot always stat the child. (Ideally there is no - // stat because the native directory entry has the type - // already, but this isn't always the case.) - if (e.code() == std::errc::permission_denied || e.code() == std::errc::operation_not_permitted) - return std::nullopt; - else throw; - } + try { + for (auto & entry : std::filesystem::directory_iterator{makeAbsPath(path)}) { + checkInterrupt(); + auto type = [&]() -> std::optional { + std::filesystem::file_type nativeType; + try { + nativeType = entry.symlink_status().type(); + } catch (std::filesystem::filesystem_error & e) { + // We cannot always stat the child. (Ideally there is no + // stat because the native directory entry has the type + // already, but this isn't always the case.) + if (e.code() == std::errc::permission_denied || e.code() == std::errc::operation_not_permitted) + return std::nullopt; + else throw; + } - // cannot exhaustively enumerate because implementation-specific - // additional file types are allowed. + // cannot exhaustively enumerate because implementation-specific + // additional file types are allowed. #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wswitch-enum" switch (nativeType) { @@ -158,8 +159,11 @@ SourceAccessor::DirEntries PosixSourceAccessor::readDirectory(const CanonPath & default: return tMisc; } #pragma GCC diagnostic pop - }(); - res.emplace(entry.path().filename().string(), type); + }(); + res.emplace(entry.path().filename().string(), type); + } + } catch (std::filesystem::filesystem_error & e) { + throw SysError("reading directory %1%", showPath(path)); } return res; } From 05a1ffe23649950269999fd97fa351e78bd43dd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Thu, 5 Sep 2024 10:59:43 +0200 Subject: [PATCH 161/718] repl: wrap std::filesystem error into SysError /tmp/ecstatic-euler-mAFGV7 % /home/joerg/git/nix/build/subprojects/nix/nix repl Nix 2.25.0 Type :? for help. after doing rm /tmp/ecstatic-euler-mAFGV7 this will result in: nix-repl> :lf . error: cannot determine current working directory: No such file or directory Before it would make the repl crash /tmp/clever-hermann-MCm7A9 % /home/joerg/git/nix/build/subprojects/nix/nix repl Nix 2.25.0 Type :? for help. nix-repl> :lf . error: filesystem error: cannot get current path: No such file or directory --- src/libcmd/repl.cc | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/libcmd/repl.cc b/src/libcmd/repl.cc index 63f6c1bdd..319dae361 100644 --- a/src/libcmd/repl.cc +++ b/src/libcmd/repl.cc @@ -2,6 +2,7 @@ #include #include +#include "error.hh" #include "repl-interacter.hh" #include "repl.hh" @@ -720,7 +721,14 @@ void NixRepl::loadFlake(const std::string & flakeRefS) if (flakeRefS.empty()) throw Error("cannot use ':load-flake' without a path specified. (Use '.' for the current working directory.)"); - auto flakeRef = parseFlakeRef(fetchSettings, flakeRefS, std::filesystem::current_path().string(), true); + std::filesystem::path cwd; + try { + cwd = std::filesystem::current_path(); + } catch (std::filesystem::filesystem_error & e) { + throw SysError("cannot determine current working directory"); + } + + auto flakeRef = parseFlakeRef(fetchSettings, flakeRefS, cwd.string(), true); if (evalSettings.pureEval && !flakeRef.input.isLocked()) throw Error("cannot use ':load-flake' on locked flake reference '%s' (use --impure to override)", flakeRefS); From 70c52d72f4ee93b68b57b12cd7892bba03446067 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Thu, 5 Sep 2024 12:59:54 +0200 Subject: [PATCH 162/718] builtins.unpackChannel: wrap filesystem errors and sanitize channelName Otherwise these errors are not caught correctly --- src/libstore/builtins/unpack-channel.cc | 28 +++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/libstore/builtins/unpack-channel.cc b/src/libstore/builtins/unpack-channel.cc index a5f2b8e3a..7f9a520ee 100644 --- a/src/libstore/builtins/unpack-channel.cc +++ b/src/libstore/builtins/unpack-channel.cc @@ -13,21 +13,37 @@ void builtinUnpackChannel( return i->second; }; - auto out = outputs.at("out"); - auto channelName = getAttr("channelName"); + std::filesystem::path out(outputs.at("out")); + std::filesystem::path channelName(getAttr("channelName")); auto src = getAttr("src"); + if (channelName.filename() != channelName) { + throw Error("channelName is not allowed to contain filesystem seperators, got %1%", channelName); + } + createDirs(out); unpackTarfile(src, out); - auto entries = std::filesystem::directory_iterator{out}; - auto fileName = entries->path().string(); - auto fileCount = std::distance(std::filesystem::begin(entries), std::filesystem::end(entries)); + size_t fileCount; + std::string fileName; + try { + auto entries = std::filesystem::directory_iterator{out}; + fileName = entries->path().string(); + fileCount = std::distance(std::filesystem::begin(entries), std::filesystem::end(entries)); + } catch (std::filesystem::filesystem_error &e) { + throw SysError("failed to read directory %1%", out); + } + if (fileCount != 1) throw Error("channel tarball '%s' contains more than one file", src); - std::filesystem::rename(fileName, (out + "/" + channelName)); + std::filesystem::path target(out / channelName); + try { + std::filesystem::rename(fileName, target); + } catch (std::filesystem::filesystem_error &e) { + throw SysError("failed to rename %1% to %2%", fileName, target); + } } } From a81083d080152eb06200c250a4879ece451165d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Thu, 5 Sep 2024 15:16:51 +0200 Subject: [PATCH 163/718] Revert "Update src/libutil/url.cc" This reverts commit 9b1cefe27e542d890aa346996a03dfecd9793dfe. --- src/libutil/url.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libutil/url.cc b/src/libutil/url.cc index 8ef1857bb..78c832440 100644 --- a/src/libutil/url.cc +++ b/src/libutil/url.cc @@ -81,7 +81,7 @@ std::map decodeQuery(const std::string & query) auto e = s.find('='); if (e == std::string::npos) { - warn("dubious URI query '%s' is missing equal sign '%s'", s, "="); + warn("invalid URI query '%s', did you forget an equals sign `=`?", s); continue; } From 5a5a010120928262341a11b88b58373a55f013b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Thu, 5 Sep 2024 15:16:53 +0200 Subject: [PATCH 164/718] Revert "fix: Error on malformed URI query parameter" This reverts commit c9f45677b585dabb3a83570e21426257d92746bd. This now triggers on simple cases like `nix build .#nix`. Reverting for now. --- src/libutil/url.cc | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/libutil/url.cc b/src/libutil/url.cc index 78c832440..bcbe9ea4e 100644 --- a/src/libutil/url.cc +++ b/src/libutil/url.cc @@ -79,15 +79,10 @@ std::map decodeQuery(const std::string & query) for (auto s : tokenizeString(query, "&")) { auto e = s.find('='); - - if (e == std::string::npos) { - warn("invalid URI query '%s', did you forget an equals sign `=`?", s); - continue; - } - - result.emplace( - s.substr(0, e), - percentDecode(std::string_view(s).substr(e + 1))); + if (e != std::string::npos) + result.emplace( + s.substr(0, e), + percentDecode(std::string_view(s).substr(e + 1))); } return result; From 83d5b32803e5b828967a27b1ea93c5728d3a4d0a Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 5 Sep 2024 16:41:15 +0200 Subject: [PATCH 165/718] Add test case for NARs with duplicate directory entries This test was made by @puckipedia. --- tests/functional/duplicate.nar | Bin 0 -> 1400 bytes tests/functional/local.mk | 2 +- tests/functional/{case-hack.sh => nars.sh} | 9 +++++---- 3 files changed, 6 insertions(+), 5 deletions(-) create mode 100644 tests/functional/duplicate.nar rename tests/functional/{case-hack.sh => nars.sh} (79%) diff --git a/tests/functional/duplicate.nar b/tests/functional/duplicate.nar new file mode 100644 index 0000000000000000000000000000000000000000..1d0993ed4cab41a6d45907ac0c17026afd5471a2 GIT binary patch literal 1400 zcmdT@+it=z49zZ#4T*h25D#ojRW~kz9 z$BsP}-LYn0DAbktf#N+v9qTBW&+onV;7jX2S0C@V9t<{lr}pt&I-XgF4v29E z3g3EyMu?&G+_E0O>ztu< "$TEST_ROOT/case.nar" cmp case.nar "$TEST_ROOT/case.nar" From da1ad28912334bb57f923afb4745273fd68f695c Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 5 Sep 2024 16:48:43 +0200 Subject: [PATCH 166/718] Test that nix-store --restore fails if the output already exists This restores the behaviour from before the std::filesystem refactorings. --- src/libutil/fs-sink.cc | 3 ++- tests/functional/nars.sh | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libutil/fs-sink.cc b/src/libutil/fs-sink.cc index 154346cee..b1e342c77 100644 --- a/src/libutil/fs-sink.cc +++ b/src/libutil/fs-sink.cc @@ -71,7 +71,8 @@ static GlobalConfig::Register r1(&restoreSinkSettings); void RestoreSink::createDirectory(const CanonPath & path) { - std::filesystem::create_directory(dstPath / path.rel()); + if (!std::filesystem::create_directory(dstPath / path.rel())) + throw Error("path '%s' already exists", (dstPath / path.rel()).string()); }; struct RestoreRegularFile : CreateRegularFileSink { diff --git a/tests/functional/nars.sh b/tests/functional/nars.sh index c58d12cd5..106bd10fc 100755 --- a/tests/functional/nars.sh +++ b/tests/functional/nars.sh @@ -10,6 +10,9 @@ clearStore rm -rf "$TEST_ROOT/out" expectStderr 1 nix-store --restore "$TEST_ROOT/out" < duplicate.nar | grepQuiet "NAR directory is not sorted" +# Check that nix-store --restore fails if the output already exists. +expectStderr 1 nix-store --restore "$TEST_ROOT/out" < duplicate.nar | grepQuiet "path '.*/out/' already exists" + # Check whether restoring and dumping a NAR that contains case # collisions is round-tripping, even on a case-insensitive system. rm -rf "$TEST_ROOT/case" From 77c090cdbd56220895a2447efae79f68ed7861c5 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 5 Sep 2024 16:54:12 +0200 Subject: [PATCH 167/718] More tests --- tests/functional/nars.sh | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/functional/nars.sh b/tests/functional/nars.sh index 106bd10fc..b2b6b2b1a 100755 --- a/tests/functional/nars.sh +++ b/tests/functional/nars.sh @@ -13,6 +13,17 @@ expectStderr 1 nix-store --restore "$TEST_ROOT/out" < duplicate.nar | grepQuiet # Check that nix-store --restore fails if the output already exists. expectStderr 1 nix-store --restore "$TEST_ROOT/out" < duplicate.nar | grepQuiet "path '.*/out/' already exists" +rm -rf "$TEST_ROOT/out" +echo foo > "$TEST_ROOT/out" +expectStderr 1 nix-store --restore "$TEST_ROOT/out" < duplicate.nar | grepQuiet "cannot create directory.*File exists" + +rm -rf "$TEST_ROOT/out" +ln -s "$TEST_ROOT/out2" "$TEST_ROOT/out" +expectStderr 1 nix-store --restore "$TEST_ROOT/out" < duplicate.nar | grepQuiet "cannot create directory.*File exists" + +mkdir -p "$TEST_ROOT/out2" +expectStderr 1 nix-store --restore "$TEST_ROOT/out" < duplicate.nar | grepQuiet "path '.*/out/' already exists" + # Check whether restoring and dumping a NAR that contains case # collisions is round-tripping, even on a case-insensitive system. rm -rf "$TEST_ROOT/case" From 35575873813f60fff26f27a65e09038986f17cb5 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 5 Sep 2024 19:26:10 +0200 Subject: [PATCH 168/718] Detect NAR directory entries that collide with another path after case-hacking The test was made by @puckipedia. --- src/libutil/archive.cc | 3 +++ tests/functional/case-collision.nar | Bin 0 -> 1928 bytes tests/functional/nars.sh | 6 ++++++ 3 files changed, 9 insertions(+) create mode 100644 tests/functional/case-collision.nar diff --git a/src/libutil/archive.cc b/src/libutil/archive.cc index e4a6a3181..0d72f910d 100644 --- a/src/libutil/archive.cc +++ b/src/libutil/archive.cc @@ -243,6 +243,9 @@ static void parse(FileSystemObjectSink & sink, Source & source, const CanonPath debug("case collision between '%1%' and '%2%'", i->first, name); name += caseHackSuffix; name += std::to_string(++i->second); + auto j = names.find(name); + if (j != names.end()) + throw Error("NAR contains file name '%s' that collides with case-hacked file name '%s'", prevName, j->first); } else names[name] = 0; } diff --git a/tests/functional/case-collision.nar b/tests/functional/case-collision.nar new file mode 100644 index 0000000000000000000000000000000000000000..2eff86901c617be2a830d23074923cb5b3b69aa3 GIT binary patch literal 1928 zcmd^9%}&EG3@&2)Y!WvfAc(_YXsQr5o`XF=mU?TnHklH4TQ7Zf(qMC#G>KJ{av&Gy za}?+EXU7lO&ocTjmrj*>2lMyfx+4Dz*%4W6x6p6LgbVFJp>-|c8?s<9`cB0$vW{^$ z?iYCMuQE2ai07y7GmkrZ&%wH>q|5FJD{C-t@C1MJc_jzOWqdC0M~c()?t*xok{-HJ zs!i9+H#iU9)|ED!?3UuAbZZF8FyEZ~jG6y2J~toM9S7FoQvGmE`2|Vij(PpHA1=*f z7ka8+sd=Qc8V} DaOkrB literal 0 HcmV?d00001 diff --git a/tests/functional/nars.sh b/tests/functional/nars.sh index b2b6b2b1a..f2339af88 100755 --- a/tests/functional/nars.sh +++ b/tests/functional/nars.sh @@ -37,3 +37,9 @@ cmp case.nar "$TEST_ROOT/case.nar" # removal of the suffix). touch "$TEST_ROOT/case/xt_CONNMARK.h~nix~case~hack~3" (! nix-store "${opts[@]}" --dump "$TEST_ROOT/case" > /dev/null) + +# Detect NARs that have a directory entry that after case-hacking +# collides with another entry (e.g. a directory containing 'Test', +# 'Test~nix~case~hack~1' and 'test'). +rm -rf "$TEST_ROOT/case" +expectStderr 1 nix-store "${opts[@]}" --restore "$TEST_ROOT/case" < case-collision.nar | grepQuiet "NAR contains file name 'test' that collides with case-hacked file name 'Test~nix~case~hack~1'" From 7a765a6aafa27267659eb7339cf7039990f30caa Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 5 Sep 2024 20:37:26 +0200 Subject: [PATCH 169/718] Test that deserializing NARs with names with equal Unicode normal forms fails on macOS The test is based on the one by @puckipedia but with the file names swapped to make them sorted. --- tests/functional/nars.sh | 11 +++++++++++ tests/functional/unnormalized.nar | Bin 0 -> 1728 bytes 2 files changed, 11 insertions(+) create mode 100644 tests/functional/unnormalized.nar diff --git a/tests/functional/nars.sh b/tests/functional/nars.sh index f2339af88..b16650e7e 100755 --- a/tests/functional/nars.sh +++ b/tests/functional/nars.sh @@ -43,3 +43,14 @@ touch "$TEST_ROOT/case/xt_CONNMARK.h~nix~case~hack~3" # 'Test~nix~case~hack~1' and 'test'). rm -rf "$TEST_ROOT/case" expectStderr 1 nix-store "${opts[@]}" --restore "$TEST_ROOT/case" < case-collision.nar | grepQuiet "NAR contains file name 'test' that collides with case-hacked file name 'Test~nix~case~hack~1'" + +# Deserializing a NAR that contains file names that Unicode-normalize +# to the same name should fail on macOS but succeed on Linux. +rm -rf "$TEST_ROOT/out" +if [[ $(uname) = Darwin ]]; then + expectStderr 1 nix-store --restore "$TEST_ROOT/out" < unnormalized.nar | grepQuiet "cannot create directory.*File exists" +else + nix-store --restore "$TEST_ROOT/out" < unnormalized.nar + [[ -e $TEST_ROOT/out/â ]] + [[ -e $TEST_ROOT/out/â ]] +fi diff --git a/tests/functional/unnormalized.nar b/tests/functional/unnormalized.nar new file mode 100644 index 0000000000000000000000000000000000000000..4b7edb17e0b4a9b75cf2958e9f12cceca22d267c GIT binary patch literal 1728 zcmd^9&2GXl4DNo}ka&koJMc51YTAwW-~mEvXhfQz#07fgQFxVI_fQML(N5J=2`NbQ zV*7LLe6bx5vh%0qe#)&Vu$+Qc|z8XR?vo72w}Ja>8T2af{uR|2^gTKAx4X{4ZTc z-^V~CHIFT~SHUB7Jzi)&Hr6bq0+*^U@tqW~ Date: Thu, 5 Sep 2024 20:55:24 +0200 Subject: [PATCH 170/718] Fix test on macOS --- tests/functional/nars.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/functional/nars.sh b/tests/functional/nars.sh index b16650e7e..bd2c49fce 100755 --- a/tests/functional/nars.sh +++ b/tests/functional/nars.sh @@ -48,7 +48,7 @@ expectStderr 1 nix-store "${opts[@]}" --restore "$TEST_ROOT/case" < case-collisi # to the same name should fail on macOS but succeed on Linux. rm -rf "$TEST_ROOT/out" if [[ $(uname) = Darwin ]]; then - expectStderr 1 nix-store --restore "$TEST_ROOT/out" < unnormalized.nar | grepQuiet "cannot create directory.*File exists" + expectStderr 1 nix-store --restore "$TEST_ROOT/out" < unnormalized.nar | grepQuiet "path '.*/out/â' already exists" else nix-store --restore "$TEST_ROOT/out" < unnormalized.nar [[ -e $TEST_ROOT/out/â ]] From 9fcb588dd8a7b3f0d7d103cea449abcf9f736ad6 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 5 Sep 2024 22:21:53 +0200 Subject: [PATCH 171/718] RestoreSink::createDirectory(): Use append() On macOS, `mkdir("x/')` behaves differently than `mkdir("x")` if `x` is a dangling symlink (the formed succeed while the latter fails). So make sure we always strip the trailing slash. --- src/libutil/fs-sink.cc | 20 ++++++++++---------- tests/functional/nars.sh | 8 ++++---- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/libutil/fs-sink.cc b/src/libutil/fs-sink.cc index b1e342c77..72e5c731f 100644 --- a/src/libutil/fs-sink.cc +++ b/src/libutil/fs-sink.cc @@ -68,11 +68,19 @@ static RestoreSinkSettings restoreSinkSettings; static GlobalConfig::Register r1(&restoreSinkSettings); +static std::filesystem::path append(const std::filesystem::path & src, const CanonPath & path) +{ + auto dst = src; + if (!path.rel().empty()) + dst /= path.rel(); + return dst; +} void RestoreSink::createDirectory(const CanonPath & path) { - if (!std::filesystem::create_directory(dstPath / path.rel())) - throw Error("path '%s' already exists", (dstPath / path.rel()).string()); + auto p = append(dstPath, path); + if (!std::filesystem::create_directory(p)) + throw Error("path '%s' already exists", p.string()); }; struct RestoreRegularFile : CreateRegularFileSink { @@ -94,14 +102,6 @@ struct RestoreRegularFile : CreateRegularFileSink { void preallocateContents(uint64_t size) override; }; -static std::filesystem::path append(const std::filesystem::path & src, const CanonPath & path) -{ - auto dst = src; - if (!path.rel().empty()) - dst /= path.rel(); - return dst; -} - void RestoreSink::createRegularFile(const CanonPath & path, std::function func) { auto p = append(dstPath, path); diff --git a/tests/functional/nars.sh b/tests/functional/nars.sh index bd2c49fce..4f2470ea7 100755 --- a/tests/functional/nars.sh +++ b/tests/functional/nars.sh @@ -11,18 +11,18 @@ rm -rf "$TEST_ROOT/out" expectStderr 1 nix-store --restore "$TEST_ROOT/out" < duplicate.nar | grepQuiet "NAR directory is not sorted" # Check that nix-store --restore fails if the output already exists. -expectStderr 1 nix-store --restore "$TEST_ROOT/out" < duplicate.nar | grepQuiet "path '.*/out/' already exists" +expectStderr 1 nix-store --restore "$TEST_ROOT/out" < duplicate.nar | grepQuiet "path '.*/out' already exists" rm -rf "$TEST_ROOT/out" echo foo > "$TEST_ROOT/out" -expectStderr 1 nix-store --restore "$TEST_ROOT/out" < duplicate.nar | grepQuiet "cannot create directory.*File exists" +expectStderr 1 nix-store --restore "$TEST_ROOT/out" < duplicate.nar | grepQuiet "File exists" rm -rf "$TEST_ROOT/out" ln -s "$TEST_ROOT/out2" "$TEST_ROOT/out" -expectStderr 1 nix-store --restore "$TEST_ROOT/out" < duplicate.nar | grepQuiet "cannot create directory.*File exists" +expectStderr 1 nix-store --restore "$TEST_ROOT/out" < duplicate.nar | grepQuiet "File exists" mkdir -p "$TEST_ROOT/out2" -expectStderr 1 nix-store --restore "$TEST_ROOT/out" < duplicate.nar | grepQuiet "path '.*/out/' already exists" +expectStderr 1 nix-store --restore "$TEST_ROOT/out" < duplicate.nar | grepQuiet "path '.*/out' already exists" # Check whether restoring and dumping a NAR that contains case # collisions is round-tripping, even on a case-insensitive system. From 92be107c8eb324460a040e104be1f790cf0b57fd Mon Sep 17 00:00:00 2001 From: Valentin Gagarin Date: Fri, 6 Sep 2024 10:33:12 +0200 Subject: [PATCH 172/718] update instructions to build the manual --- doc/manual/src/development/documentation.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/manual/src/development/documentation.md b/doc/manual/src/development/documentation.md index 63f574ab7..d5a95e0c1 100644 --- a/doc/manual/src/development/documentation.md +++ b/doc/manual/src/development/documentation.md @@ -13,13 +13,13 @@ Incremental refactorings of the documentation build setup to make it faster or e Build the manual from scratch: ```console -nix-build $(nix-instantiate)'!doc' +nix-build -E '(import ./.).packages.${builtins.currentSystem}.nix.doc' ``` or ```console -nix build .#^doc +nix build .#nix^doc ``` and open `./result-doc/share/doc/nix/manual/index.html`. From 52ba3cc5eac0418218a90c0cddb06688d4c7b5d3 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 6 Sep 2024 16:28:09 +0200 Subject: [PATCH 173/718] Test that deserializing regular files / symlinks is exclusive --- tests/functional/nars.sh | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/tests/functional/nars.sh b/tests/functional/nars.sh index 4f2470ea7..ed19637a1 100755 --- a/tests/functional/nars.sh +++ b/tests/functional/nars.sh @@ -24,6 +24,44 @@ expectStderr 1 nix-store --restore "$TEST_ROOT/out" < duplicate.nar | grepQuiet mkdir -p "$TEST_ROOT/out2" expectStderr 1 nix-store --restore "$TEST_ROOT/out" < duplicate.nar | grepQuiet "path '.*/out' already exists" +# The same, but for a regular file. +nix-store --dump ./nars.sh > "$TEST_ROOT/tmp.nar" + +rm -rf "$TEST_ROOT/out" +nix-store --restore "$TEST_ROOT/out" < "$TEST_ROOT/tmp.nar" +expectStderr 1 nix-store --restore "$TEST_ROOT/out" < "$TEST_ROOT/tmp.nar" | grepQuiet "File exists" + +rm -rf "$TEST_ROOT/out" +mkdir -p "$TEST_ROOT/out" +expectStderr 1 nix-store --restore "$TEST_ROOT/out" < "$TEST_ROOT/tmp.nar" | grepQuiet "File exists" + +rm -rf "$TEST_ROOT/out" +ln -s "$TEST_ROOT/out2" "$TEST_ROOT/out" +expectStderr 1 nix-store --restore "$TEST_ROOT/out" < "$TEST_ROOT/tmp.nar" | grepQuiet "File exists" + +mkdir -p "$TEST_ROOT/out2" +expectStderr 1 nix-store --restore "$TEST_ROOT/out" < "$TEST_ROOT/tmp.nar" | grepQuiet "File exists" + +# The same, but for a symlink +ln -sfn foo "$TEST_ROOT/symlink" +nix-store --dump "$TEST_ROOT/symlink" > "$TEST_ROOT/tmp.nar" + +rm -rf "$TEST_ROOT/out" +nix-store --restore "$TEST_ROOT/out" < "$TEST_ROOT/tmp.nar" +[[ -L "$TEST_ROOT/out" ]] +expectStderr 1 nix-store --restore "$TEST_ROOT/out" < "$TEST_ROOT/tmp.nar" | grepQuiet "File exists" + +rm -rf "$TEST_ROOT/out" +mkdir -p "$TEST_ROOT/out" +expectStderr 1 nix-store --restore "$TEST_ROOT/out" < "$TEST_ROOT/tmp.nar" | grepQuiet "File exists" + +rm -rf "$TEST_ROOT/out" +ln -s "$TEST_ROOT/out2" "$TEST_ROOT/out" +expectStderr 1 nix-store --restore "$TEST_ROOT/out" < "$TEST_ROOT/tmp.nar" | grepQuiet "File exists" + +mkdir -p "$TEST_ROOT/out2" +expectStderr 1 nix-store --restore "$TEST_ROOT/out" < "$TEST_ROOT/tmp.nar" | grepQuiet "File exists" + # Check whether restoring and dumping a NAR that contains case # collisions is round-tripping, even on a case-insensitive system. rm -rf "$TEST_ROOT/case" From 9df5236c468839ead6627131886f3d1153035bf3 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Tue, 27 Aug 2024 13:43:50 +0200 Subject: [PATCH 174/718] progress-bar: Only write when truly updated --- src/libmain/progress-bar.cc | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/libmain/progress-bar.cc b/src/libmain/progress-bar.cc index bb4c52ef7..d864d9473 100644 --- a/src/libmain/progress-bar.cc +++ b/src/libmain/progress-bar.cc @@ -75,6 +75,9 @@ private: bool active = true; bool paused = false; bool haveUpdate = true; + + /** Helps avoid unnecessary redraws, see `draw()` */ + std::string lastOutput; }; Sync state_; @@ -360,6 +363,31 @@ public: } std::chrono::milliseconds draw(State & state) + { + // Call draw() and render if the output has changed. + + // Excessive redrawing is noticable on slow terminals, and it interferes + // with text selection in some terminals, including libvte-based terminal + // emulators. + + std::optional newOutput; + auto nextWakeup = draw(state, newOutput); + { + auto state(state_.lock()); + if (newOutput && *newOutput != state->lastOutput) { + writeToStderr(*newOutput); + state->lastOutput = std::move(*newOutput); + } + } + return nextWakeup; + } + + /** + * @param output[out] `nullopt` if nothing is to be drawn. Otherwise, a + * string of ANSI terminal output that can be used to + * render the progress bar. + */ + std::chrono::milliseconds draw(State & state, std::optional & output) { auto nextWakeup = std::chrono::milliseconds::max(); @@ -412,7 +440,7 @@ public: auto width = getWindowSize().second; if (width <= 0) width = std::numeric_limits::max(); - writeToStderr("\r" + filterANSIEscapes(line, false, width) + ANSI_NORMAL + "\e[K"); + output = "\r" + filterANSIEscapes(line, false, width) + ANSI_NORMAL + "\e[K"; return nextWakeup; } From 047d9643b54aa857dfff81ba8aed7881a97938a4 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Sun, 8 Sep 2024 01:09:51 +0200 Subject: [PATCH 175/718] refact: Extract ProgressBar::redraw(newOutput) --- src/libmain/progress-bar.cc | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/src/libmain/progress-bar.cc b/src/libmain/progress-bar.cc index d864d9473..2ea743034 100644 --- a/src/libmain/progress-bar.cc +++ b/src/libmain/progress-bar.cc @@ -362,23 +362,28 @@ public: updateCV.notify_one(); } + /** + * Redraw, if the output has changed. + * + * Excessive redrawing is noticable on slow terminals, and it interferes + * with text selection in some terminals, including libvte-based terminal + * emulators. + */ + void redraw(std::string newOutput) + { + auto state(state_.lock()); + if (newOutput != state->lastOutput) { + writeToStderr(newOutput); + state->lastOutput = std::move(newOutput); + } + } + std::chrono::milliseconds draw(State & state) { - // Call draw() and render if the output has changed. - - // Excessive redrawing is noticable on slow terminals, and it interferes - // with text selection in some terminals, including libvte-based terminal - // emulators. - std::optional newOutput; auto nextWakeup = draw(state, newOutput); - { - auto state(state_.lock()); - if (newOutput && *newOutput != state->lastOutput) { - writeToStderr(*newOutput); - state->lastOutput = std::move(*newOutput); - } - } + if (newOutput) + redraw(*newOutput); return nextWakeup; } From e10ea78f9313d8df381301ac2fc3023de3993689 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Sun, 8 Sep 2024 01:21:40 +0200 Subject: [PATCH 176/718] refact: Inline ProgressBar::draw(state, newOutput), inline local output --- src/libmain/progress-bar.cc | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/libmain/progress-bar.cc b/src/libmain/progress-bar.cc index 2ea743034..ce513d204 100644 --- a/src/libmain/progress-bar.cc +++ b/src/libmain/progress-bar.cc @@ -379,20 +379,6 @@ public: } std::chrono::milliseconds draw(State & state) - { - std::optional newOutput; - auto nextWakeup = draw(state, newOutput); - if (newOutput) - redraw(*newOutput); - return nextWakeup; - } - - /** - * @param output[out] `nullopt` if nothing is to be drawn. Otherwise, a - * string of ANSI terminal output that can be used to - * render the progress bar. - */ - std::chrono::milliseconds draw(State & state, std::optional & output) { auto nextWakeup = std::chrono::milliseconds::max(); @@ -445,7 +431,7 @@ public: auto width = getWindowSize().second; if (width <= 0) width = std::numeric_limits::max(); - output = "\r" + filterANSIEscapes(line, false, width) + ANSI_NORMAL + "\e[K"; + redraw("\r" + filterANSIEscapes(line, false, width) + ANSI_NORMAL + "\e[K"); return nextWakeup; } From c955563b6440ffe7abb22f15744ceea8b4ce2d9c Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Sun, 8 Sep 2024 11:44:24 +0200 Subject: [PATCH 177/718] fix: Avoid deadlock in ProgressBar::redraw() --- src/libmain/progress-bar.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libmain/progress-bar.cc b/src/libmain/progress-bar.cc index ce513d204..e63d4f13f 100644 --- a/src/libmain/progress-bar.cc +++ b/src/libmain/progress-bar.cc @@ -75,11 +75,11 @@ private: bool active = true; bool paused = false; bool haveUpdate = true; - - /** Helps avoid unnecessary redraws, see `draw()` */ - std::string lastOutput; }; + /** Helps avoid unnecessary redraws, see `redraw()` */ + Sync lastOutput_; + Sync state_; std::thread updateThread; @@ -371,10 +371,10 @@ public: */ void redraw(std::string newOutput) { - auto state(state_.lock()); - if (newOutput != state->lastOutput) { + auto lastOutput(lastOutput_.lock()); + if (newOutput != *lastOutput) { writeToStderr(newOutput); - state->lastOutput = std::move(newOutput); + *lastOutput = std::move(newOutput); } } From 4cfa59fdb32aa4fcc58b735d8843ce308692a652 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 9 Sep 2024 14:11:35 +0200 Subject: [PATCH 178/718] Typo --- tests/functional/nars.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/functional/nars.sh b/tests/functional/nars.sh index ed19637a1..9f5f43dc6 100755 --- a/tests/functional/nars.sh +++ b/tests/functional/nars.sh @@ -42,7 +42,7 @@ expectStderr 1 nix-store --restore "$TEST_ROOT/out" < "$TEST_ROOT/tmp.nar" | gre mkdir -p "$TEST_ROOT/out2" expectStderr 1 nix-store --restore "$TEST_ROOT/out" < "$TEST_ROOT/tmp.nar" | grepQuiet "File exists" -# The same, but for a symlink +# The same, but for a symlink. ln -sfn foo "$TEST_ROOT/symlink" nix-store --dump "$TEST_ROOT/symlink" > "$TEST_ROOT/tmp.nar" From 5ca2f58798e6f514b5194c16c0fea0d8ec128171 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 9 Sep 2024 14:29:05 +0200 Subject: [PATCH 179/718] Improve use-case-hack description slightly --- src/libutil/archive.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libutil/archive.cc b/src/libutil/archive.cc index 0d72f910d..e26b7eb93 100644 --- a/src/libutil/archive.cc +++ b/src/libutil/archive.cc @@ -23,7 +23,7 @@ struct ArchiveSettings : Config false, #endif "use-case-hack", - "Whether to enable a Darwin-specific hack for dealing with file name collisions."}; + "Whether to enable a macOS-specific hack for dealing with file name case collisions."}; }; static ArchiveSettings archiveSettings; From c5a4dfa6602796ebb3c62493a2fd33f2b58ec91c Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 9 Sep 2024 15:41:38 +0200 Subject: [PATCH 180/718] nix flake {metadata,archive}: Fix chroot stores Fixes $ nix flake metadata --store /tmp/nix nixpkgs error: path '/tmp/nix/nix/store/65xpqkz92d9j7k5ric4z8lzhiigxsfbg-source/flake.nix' is not in the Nix store This has been broken since 598deb2b23bc59df61c92ea25745d675686f3991. --- src/libflake/flake/flake.cc | 27 ++++++++++++++++----------- src/libflake/flake/flake.hh | 10 ++++++++++ src/nix/flake.cc | 4 ++-- tests/functional/flakes/flakes.sh | 3 +++ 4 files changed, 31 insertions(+), 13 deletions(-) diff --git a/src/libflake/flake/flake.cc b/src/libflake/flake/flake.cc index fd1183514..35db13f7e 100644 --- a/src/libflake/flake/flake.cc +++ b/src/libflake/flake/flake.cc @@ -751,6 +751,21 @@ LockedFlake lockFlake( } } +std::pair sourcePathToStorePath( + ref store, + const SourcePath & _path) +{ + auto path = _path.path.abs(); + + if (auto store2 = store.dynamic_pointer_cast()) { + auto realStoreDir = store2->getRealStoreDir(); + if (isInDir(path, realStoreDir)) + path = store2->storeDir + path.substr(realStoreDir.size()); + } + + return store->toStorePath(path); +} + void callFlake(EvalState & state, const LockedFlake & lockedFlake, Value & vRes) @@ -768,17 +783,7 @@ void callFlake(EvalState & state, auto lockedNode = node.dynamic_pointer_cast(); - // FIXME: This is a hack to support chroot stores. Remove this - // once we can pass a sourcePath rather than a storePath to - // call-flake.nix. - auto path = sourcePath.path.abs(); - if (auto store = state.store.dynamic_pointer_cast()) { - auto realStoreDir = store->getRealStoreDir(); - if (isInDir(path, realStoreDir)) - path = store->storeDir + path.substr(realStoreDir.size()); - } - - auto [storePath, subdir] = state.store->toStorePath(path); + auto [storePath, subdir] = sourcePathToStorePath(state.store, sourcePath); emitTreeAttrs( state, diff --git a/src/libflake/flake/flake.hh b/src/libflake/flake/flake.hh index cce17009c..496e18673 100644 --- a/src/libflake/flake/flake.hh +++ b/src/libflake/flake/flake.hh @@ -214,6 +214,16 @@ void callFlake( const LockedFlake & lockedFlake, Value & v); +/** + * Map a `SourcePath` to the corresponding store path. This is a + * temporary hack to support chroot stores while we don't have full + * lazy trees. FIXME: Remove this once we can pass a sourcePath rather + * than a storePath to call-flake.nix. + */ +std::pair sourcePathToStorePath( + ref store, + const SourcePath & path); + } void emitTreeAttrs( diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 2db1e039e..8e109b327 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -214,7 +214,7 @@ struct CmdFlakeMetadata : FlakeCommand, MixJSON auto & flake = lockedFlake.flake; // Currently, all flakes are in the Nix store via the rootFS accessor. - auto storePath = store->printStorePath(store->toStorePath(flake.path.path.abs()).first); + auto storePath = store->printStorePath(sourcePathToStorePath(store, flake.path).first); if (json) { nlohmann::json j; @@ -1079,7 +1079,7 @@ struct CmdFlakeArchive : FlakeCommand, MixJSON, MixDryRun StorePathSet sources; - auto storePath = store->toStorePath(flake.flake.path.path.abs()).first; + auto storePath = sourcePathToStorePath(store, flake.flake.path).first; sources.insert(storePath); diff --git a/tests/functional/flakes/flakes.sh b/tests/functional/flakes/flakes.sh index 26b91eda7..aa4cb1e18 100755 --- a/tests/functional/flakes/flakes.sh +++ b/tests/functional/flakes/flakes.sh @@ -184,6 +184,9 @@ nix registry list | grepInverse '^user' # nothing in user registry nix flake metadata flake1 nix flake metadata flake1 | grepQuiet 'Locked URL:.*flake1.*' +# Test 'nix flake metadata' on a chroot store. +nix flake metadata --store $TEST_ROOT/chroot-store flake1 + # Test 'nix flake metadata' on a local flake. (cd "$flake1Dir" && nix flake metadata) | grepQuiet 'URL:.*flake1.*' (cd "$flake1Dir" && nix flake metadata .) | grepQuiet 'URL:.*flake1.*' From b80b091bac1eeb6fa64db1ae078de5c6a2e4b1b8 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 9 Sep 2024 19:52:21 +0200 Subject: [PATCH 181/718] Git fetcher: Don't update mtime of ref file if fetching by rev This fixes the warning $ nix eval --store /tmp/nix --expr 'builtins.fetchTree { type = "git"; url = "https://github.com/DeterminateSystems/attic"; ref = "fixups-for-magic-nix-cache"; rev = "635753a2069d4b8228e846dc5c09ad361c75cd1a"; }' warning: could not update mtime for file '/home/eelco/.cache/nix/gitv3/09788h9zgba5lbfkaa6ija2dvi004jwsqjf5ln21i2njs07cz766/refs/heads/fixups-for-magic-nix-cache': error: changing modification time of '"/home/eelco/.cache/nix/gitv3/09788h9zgba5lbfkaa6ija2dvi004jwsqjf5ln21i2njs07cz766/refs/heads/fixups-for-magic-nix-cache"': No such file or directory When we're fetching by rev, that file doesn't necessarily exist, and we don't care about it anyway. --- src/libfetchers/git.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libfetchers/git.cc b/src/libfetchers/git.cc index 076c757c5..6c5bda470 100644 --- a/src/libfetchers/git.cc +++ b/src/libfetchers/git.cc @@ -584,9 +584,10 @@ struct GitInputScheme : InputScheme } try { - setWriteTime(localRefFile, now, now); + if (!input.getRev()) + setWriteTime(localRefFile, now, now); } catch (Error & e) { - warn("could not update mtime for file '%s': %s", localRefFile, e.msg()); + warn("could not update mtime for file '%s': %s", localRefFile, e.info().msg); } if (!originalRef && !storeCachedHead(repoInfo.url, ref)) warn("could not update cached head '%s' for '%s'", ref, repoInfo.url); From c55b285cf91139c4936ea439e7a43811f554dcdf Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Mon, 9 Sep 2024 22:15:45 -0400 Subject: [PATCH 182/718] tests: test was re-named --- tests/functional/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/functional/meson.build b/tests/functional/meson.build index ebecdd9e8..5167fa814 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -159,7 +159,7 @@ suites = [ 'derivation-advanced-attributes.sh', 'import-derivation.sh', 'nix_path.sh', - 'case-hack.sh', + 'nars.sh', 'placeholders.sh', 'ssh-relay.sh', 'build.sh', From be480971c20fdd859a13053bd6ebefa0b3a04042 Mon Sep 17 00:00:00 2001 From: zimbatm Date: Tue, 10 Sep 2024 15:26:35 +0200 Subject: [PATCH 183/718] doc: add HACKING.md symlink As a hacker, I should be able to checkout the repo, and find relevant information on how to develop in the project somewhere in the top-level. Either in the README.md, or CONTRIBUTING.md or HACKING.md files. This PR symlinks the HACKING.md into the right place in the manual. --- HACKING.md | 1 + 1 file changed, 1 insertion(+) create mode 120000 HACKING.md diff --git a/HACKING.md b/HACKING.md new file mode 120000 index 000000000..d3576d60d --- /dev/null +++ b/HACKING.md @@ -0,0 +1 @@ +doc/manual/src/development/building.md \ No newline at end of file From 1ca1439b1f7bdaad9115e60b9d221c006cff1395 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Tue, 10 Sep 2024 16:40:08 +0200 Subject: [PATCH 184/718] add missing filesystem include (x86_64-darwin fix) --- src/libutil/args.hh | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libutil/args.hh b/src/libutil/args.hh index 513b8d811..127a0809e 100644 --- a/src/libutil/args.hh +++ b/src/libutil/args.hh @@ -2,6 +2,7 @@ ///@file #include +#include #include #include #include From c4766d7b8b659ce3f6fb1c339aeeec9ca3c7eeba Mon Sep 17 00:00:00 2001 From: zimbatm Date: Thu, 5 Sep 2024 10:29:48 +0200 Subject: [PATCH 185/718] fix(nix fmt): remove the default "." argument When `nix fmt` is called without an argument, Nix appends the "." argument before calling the formatter. The comment in the code is: > Format the current flake out of the box This also happens when formatting sub-folders. This means that the formatter is now unable to distinguish, as an interface, whether the "." argument is coming from the flake or the user's intent to format the current folder. This decision should be up to the formatter. Treefmt, for example, will automatically look up the project's root and format all the files. This is the desired behaviour. But because the "." argument is passed, it cannot function as expected. --- doc/manual/rl-next/nix-fmt-default-argument.md | 17 +++++++++++++++++ src/nix/fmt.cc | 10 ++-------- tests/functional/fmt.sh | 11 +++++++---- tests/functional/fmt.simple.sh | 3 ++- 4 files changed, 28 insertions(+), 13 deletions(-) create mode 100644 doc/manual/rl-next/nix-fmt-default-argument.md diff --git a/doc/manual/rl-next/nix-fmt-default-argument.md b/doc/manual/rl-next/nix-fmt-default-argument.md new file mode 100644 index 000000000..54161ab30 --- /dev/null +++ b/doc/manual/rl-next/nix-fmt-default-argument.md @@ -0,0 +1,17 @@ +--- +synopsis: Removing the default argument passed to the `nix fmt` formatter +issues: [] +prs: [11438] +--- + +The underlying formatter no longer receives the ". " default argument when `nix fmt` is called with no arguments. + +This change was necessary as the formatter wasn't able to distinguish between +a user wanting to format the current folder with `nix fmt .` or the generic +`nix fmt`. + +The default behaviour is now the responsibility of the formatter itself, and +allows tools such as treefmt to format the whole tree instead of only the +current directory and below. + +Author: [**@zimbatm**](https://github.com/zimbatm) diff --git a/src/nix/fmt.cc b/src/nix/fmt.cc index d65834495..f444d6add 100644 --- a/src/nix/fmt.cc +++ b/src/nix/fmt.cc @@ -40,14 +40,8 @@ struct CmdFmt : SourceExprCommand { Strings programArgs{app.program}; // Propagate arguments from the CLI - if (args.empty()) { - // Format the current flake out of the box - programArgs.push_back("."); - } else { - // User wants more power, let them decide which paths to include/exclude - for (auto &i : args) { - programArgs.push_back(i); - } + for (auto &i : args) { + programArgs.push_back(i); } // Release our references to eval caches to ensure they are persisted to disk, because diff --git a/tests/functional/fmt.sh b/tests/functional/fmt.sh index b29fe64d6..9a79260e6 100755 --- a/tests/functional/fmt.sh +++ b/tests/functional/fmt.sh @@ -5,11 +5,11 @@ source common.sh TODO_NixOS # Provide a `shell` variable. Try not to `export` it, perhaps. clearStoreIfPossible -rm -rf $TEST_HOME/.cache $TEST_HOME/.config $TEST_HOME/.local +rm -rf "$TEST_HOME"/.cache "$TEST_HOME"/.config "$TEST_HOME"/.local -cp ./simple.nix ./simple.builder.sh ./fmt.simple.sh ./config.nix $TEST_HOME +cp ./simple.nix ./simple.builder.sh ./fmt.simple.sh ./config.nix "$TEST_HOME" -cd $TEST_HOME +cd "$TEST_HOME" nix fmt --help | grep "Format" @@ -30,6 +30,9 @@ cat << EOF > flake.nix }; } EOF -nix fmt ./file ./folder | grep 'Formatting: ./file ./folder' +# No arguments check +[[ "$(nix fmt)" = "Formatting(0):" ]] +# Argument forwarding check +nix fmt ./file ./folder | grep 'Formatting(2): ./file ./folder' nix flake check nix flake show | grep -P "package 'formatter'" diff --git a/tests/functional/fmt.simple.sh b/tests/functional/fmt.simple.sh index 4c8c67ebb..e53f6c9be 100755 --- a/tests/functional/fmt.simple.sh +++ b/tests/functional/fmt.simple.sh @@ -1 +1,2 @@ -echo Formatting: "${@}" +#!/usr/bin/env bash +echo "Formatting(${#}):" "${@}" From ebebe626ff4ec6da98c0a043c64b35efe1c05bc3 Mon Sep 17 00:00:00 2001 From: Artturin Date: Wed, 11 Sep 2024 00:17:03 +0300 Subject: [PATCH 186/718] Fix making the build directory kept by `keep-failed` readable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Caused by 1d3696f0fb88d610abc234a60e0d6d424feafdf1 Without this fix the kept build directory is readable only by root ``` $ sudo ls -ld /comp-temp/nix-build-openssh-static-x86_64-unknown-linux-musl-9.8p1.drv-5 drwx------ root root 60 B Wed Sep 11 00:09:48 2024  /comp-temp/nix-build-openssh-static-x86_64-unknown-linux-musl-9.8p1.drv-5/ $ sudo ls -ld /comp-temp/nix-build-openssh-static-x86_64-unknown-linux-musl-9.8p1.drv-5/build drwxr-xr-x nixbld1 nixbld 80 B Wed Sep 11 00:09:58 2024  /comp-temp/nix-build-openssh-static-x86_64-unknown-linux-musl-9.8p1.drv-5/build/ ``` --- src/libstore/unix/build/local-derivation-goal.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libstore/unix/build/local-derivation-goal.cc b/src/libstore/unix/build/local-derivation-goal.cc index d55278a52..08b973cd1 100644 --- a/src/libstore/unix/build/local-derivation-goal.cc +++ b/src/libstore/unix/build/local-derivation-goal.cc @@ -2997,6 +2997,7 @@ void LocalDerivationGoal::deleteTmpDir(bool force) might have privileged stuff (like a copy of netrc). */ if (settings.keepFailed && !force && !drv->isBuiltin()) { printError("note: keeping build directory '%s'", tmpDir); + chmod(topTmpDir.c_str(), 0755); chmod(tmpDir.c_str(), 0755); } else From f2e7e996dafe069a8671f8c5a6796174c415da44 Mon Sep 17 00:00:00 2001 From: "Travis A. Everett" Date: Tue, 10 Sep 2024 20:54:09 -0500 Subject: [PATCH 187/718] sequoia-nixbld-user-migration: disable trace mode Was hoping to leave this enabled for a little while as core community members test this script out, but Apple's aggressive release timeline for macOS 15 Sequoia has caught us off-guard here. It's probably not ideal for a general audience if the script spews all of this output--and people can still force bash to run in trace mode if we really need to debug a problem. --- scripts/sequoia-nixbld-user-migration.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/scripts/sequoia-nixbld-user-migration.sh b/scripts/sequoia-nixbld-user-migration.sh index ecf19fc87..12c736d8e 100755 --- a/scripts/sequoia-nixbld-user-migration.sh +++ b/scripts/sequoia-nixbld-user-migration.sh @@ -1,7 +1,5 @@ #!/usr/bin/env bash -set -x - ((NEW_NIX_FIRST_BUILD_UID=351)) ((TEMP_NIX_FIRST_BUILD_UID=31000)) From 04ce0e648aeac282b114cf426cea8a078c97e0a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Thu, 5 Sep 2024 14:08:20 +0200 Subject: [PATCH 188/718] add release notes for filesystem fixes Update doc/manual/rl-next/filesystem-errors.md Co-authored-by: John Ericson --- doc/manual/rl-next/filesystem-errors.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 doc/manual/rl-next/filesystem-errors.md diff --git a/doc/manual/rl-next/filesystem-errors.md b/doc/manual/rl-next/filesystem-errors.md new file mode 100644 index 000000000..2d5b26228 --- /dev/null +++ b/doc/manual/rl-next/filesystem-errors.md @@ -0,0 +1,14 @@ +--- +synopsis: wrap filesystem exceptions more correctly +issues: [] +prs: [11378] +--- + + +With the switch to `std::filesystem` in different places, Nix started to throw `std::filesystem::filesystem_error` in many places instead of its own exceptions. + +This lead to no longer generating error traces, for example when listing a non-existing directory, and can also lead to crashes inside the Nix REPL. + +This version catches these types of exception correctly and wrap them into Nix's own exeception type. + +Author: [**@Mic92**](https://github.com/Mic92) From 38bfbb297c380f8b07d8a20ffdeb72da71c1567c Mon Sep 17 00:00:00 2001 From: Noam Yorav-Raphael Date: Wed, 11 Sep 2024 13:36:46 +0300 Subject: [PATCH 189/718] Use envvars NIX_CACHE_HOME, NIX_CONFIG_HOME, NIX_DATA_HOME, NIX_STATE_HOME if defined (#11351) --- doc/manual/rl-next/add-nix-state-home.md | 14 ++++++ doc/manual/src/command-ref/env-common.md | 15 ++++++- scripts/nix-profile.sh.in | 46 ++++++++++--------- src/libcmd/repl.cc | 2 +- src/libexpr/eval-cache.cc | 2 +- src/libexpr/eval-settings.cc | 2 +- src/libfetchers/cache.cc | 2 +- src/libfetchers/git-utils.cc | 2 +- src/libfetchers/git.cc | 2 +- src/libfetchers/mercurial.cc | 2 +- src/libfetchers/registry.cc | 4 +- src/libflake/flake/config.cc | 2 +- src/libstore/globals.cc | 2 +- src/libstore/nar-info-disk-cache.cc | 2 +- src/libstore/store-api.cc | 2 +- src/libutil/users.cc | 57 ++++++++++++++++++++---- src/libutil/users.hh | 8 ++-- 17 files changed, 118 insertions(+), 48 deletions(-) create mode 100644 doc/manual/rl-next/add-nix-state-home.md diff --git a/doc/manual/rl-next/add-nix-state-home.md b/doc/manual/rl-next/add-nix-state-home.md new file mode 100644 index 000000000..bbfdd5d38 --- /dev/null +++ b/doc/manual/rl-next/add-nix-state-home.md @@ -0,0 +1,14 @@ +--- +synopsis: Use envvars NIX_CACHE_HOME, NIX_CONFIG_HOME, NIX_DATA_HOME, NIX_STATE_HOME if defined +prs: [11351] +--- + +Added new environment variables: + +- `NIX_CACHE_HOME` +- `NIX_CONFIG_HOME` +- `NIX_DATA_HOME` +- `NIX_STATE_HOME` + +Each, if defined, takes precedence over the corresponding [XDG environment variable](@docroot@/command-ref/env-common.md#xdg-base-directories). +This provides more fine-grained control over where Nix looks for files, and allows to have a stand-alone Nix environment, which only uses files in a specific directory, and doesn't interfere with the user environment. diff --git a/doc/manual/src/command-ref/env-common.md b/doc/manual/src/command-ref/env-common.md index 0b5017882..ee3995111 100644 --- a/doc/manual/src/command-ref/env-common.md +++ b/doc/manual/src/command-ref/env-common.md @@ -138,6 +138,19 @@ The following environment variables are used to determine locations of various s - [`XDG_STATE_HOME`]{#env-XDG_STATE_HOME} (default `~/.local/state`) - [`XDG_CACHE_HOME`]{#env-XDG_CACHE_HOME} (default `~/.cache`) - [XDG Base Directory Specification]: https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html [`use-xdg-base-directories`]: @docroot@/command-ref/conf-file.md#conf-use-xdg-base-directories + +In addition, setting the following environment variables overrides the XDG base directories: + +- [`NIX_CONFIG_HOME`]{#env-NIX_CONFIG_HOME} (default `$XDG_CONFIG_HOME/nix`) +- [`NIX_STATE_HOME`]{#env-NIX_STATE_HOME} (default `$XDG_STATE_HOME/nix`) +- [`NIX_CACHE_HOME`]{#env-NIX_CACHE_HOME} (default `$XDG_CACHE_HOME/nix`) + +When [`use-xdg-base-directories`] is enabled, the configuration directory is: + +1. `$NIX_CONFIG_HOME`, if it is defined +2. Otherwise, `$XDG_CONFIG_HOME/nix`, if `XDG_CONFIG_HOME` is defined +3. Otherwise, `~/.config/nix`. + +Likewise for the state and cache directories. diff --git a/scripts/nix-profile.sh.in b/scripts/nix-profile.sh.in index e868399b1..3d0e498f4 100644 --- a/scripts/nix-profile.sh.in +++ b/scripts/nix-profile.sh.in @@ -3,29 +3,33 @@ if [ -n "$HOME" ] && [ -n "$USER" ]; then # Set up the per-user profile. - NIX_LINK="$HOME/.nix-profile" - if [ -n "${XDG_STATE_HOME-}" ]; then - NIX_LINK_NEW="$XDG_STATE_HOME/nix/profile" + if [ -n "$NIX_STATE_HOME" ]; then + NIX_LINK="$NIX_STATE_HOME/profile" else - NIX_LINK_NEW="$HOME/.local/state/nix/profile" - fi - if [ -e "$NIX_LINK_NEW" ]; then - if [ -t 2 ] && [ -e "$NIX_LINK" ]; then - warning="\033[1;35mwarning:\033[0m" - printf "$warning Both %s and legacy %s exist; using the former.\n" "$NIX_LINK_NEW" "$NIX_LINK" 1>&2 - if [ "$(realpath "$NIX_LINK")" = "$(realpath "$NIX_LINK_NEW")" ]; then - printf " Since the profiles match, you can safely delete either of them.\n" 1>&2 - else - # This should be an exceptionally rare occasion: the only way to get it would be to - # 1. Update to newer Nix; - # 2. Remove .nix-profile; - # 3. Set the $NIX_LINK_NEW to something other than the default user profile; - # 4. Roll back to older Nix. - # If someone did all that, they can probably figure out how to migrate the profile. - printf "$warning Profiles do not match. You should manually migrate from %s to %s.\n" "$NIX_LINK" "$NIX_LINK_NEW" 1>&2 - fi + NIX_LINK="$HOME/.nix-profile" + if [ -n "${XDG_STATE_HOME-}" ]; then + NIX_LINK_NEW="$XDG_STATE_HOME/nix/profile" + else + NIX_LINK_NEW="$HOME/.local/state/nix/profile" + fi + if [ -e "$NIX_LINK_NEW" ]; then + if [ -t 2 ] && [ -e "$NIX_LINK" ]; then + warning="\033[1;35mwarning:\033[0m" + printf "$warning Both %s and legacy %s exist; using the former.\n" "$NIX_LINK_NEW" "$NIX_LINK" 1>&2 + if [ "$(realpath "$NIX_LINK")" = "$(realpath "$NIX_LINK_NEW")" ]; then + printf " Since the profiles match, you can safely delete either of them.\n" 1>&2 + else + # This should be an exceptionally rare occasion: the only way to get it would be to + # 1. Update to newer Nix; + # 2. Remove .nix-profile; + # 3. Set the $NIX_LINK_NEW to something other than the default user profile; + # 4. Roll back to older Nix. + # If someone did all that, they can probably figure out how to migrate the profile. + printf "$warning Profiles do not match. You should manually migrate from %s to %s.\n" "$NIX_LINK" "$NIX_LINK_NEW" 1>&2 + fi + fi + NIX_LINK="$NIX_LINK_NEW" fi - NIX_LINK="$NIX_LINK_NEW" fi # Set up environment. diff --git a/src/libcmd/repl.cc b/src/libcmd/repl.cc index 63f6c1bdd..b09ae3d09 100644 --- a/src/libcmd/repl.cc +++ b/src/libcmd/repl.cc @@ -134,7 +134,7 @@ NixRepl::NixRepl(const LookupPath & lookupPath, nix::ref store, refstaticBaseEnv.get())) , runNixPtr{runNix} - , interacter(make_unique(getDataDir() + "/nix/repl-history")) + , interacter(make_unique(getDataDir() + "/repl-history")) { } diff --git a/src/libexpr/eval-cache.cc b/src/libexpr/eval-cache.cc index 9019edc1f..c407cc89a 100644 --- a/src/libexpr/eval-cache.cc +++ b/src/libexpr/eval-cache.cc @@ -69,7 +69,7 @@ struct AttrDb { auto state(_state->lock()); - Path cacheDir = getCacheDir() + "/nix/eval-cache-v5"; + Path cacheDir = getCacheDir() + "/eval-cache-v5"; createDirs(cacheDir); Path dbPath = cacheDir + "/" + fingerprint.to_string(HashFormat::Base16, false) + ".sqlite"; diff --git a/src/libexpr/eval-settings.cc b/src/libexpr/eval-settings.cc index 2846eccbc..4cbcb39b9 100644 --- a/src/libexpr/eval-settings.cc +++ b/src/libexpr/eval-settings.cc @@ -99,7 +99,7 @@ const std::string & EvalSettings::getCurrentSystem() const Path getNixDefExpr() { return settings.useXDGBaseDirectories - ? getStateDir() + "/nix/defexpr" + ? getStateDir() + "/defexpr" : getHome() + "/.nix-defexpr"; } diff --git a/src/libfetchers/cache.cc b/src/libfetchers/cache.cc index 7019b0325..b0b6cb887 100644 --- a/src/libfetchers/cache.cc +++ b/src/libfetchers/cache.cc @@ -36,7 +36,7 @@ struct CacheImpl : Cache { auto state(_state.lock()); - auto dbPath = getCacheDir() + "/nix/fetcher-cache-v2.sqlite"; + auto dbPath = getCacheDir() + "/fetcher-cache-v2.sqlite"; createDirs(dirOf(dbPath)); state->db = SQLite(dbPath); diff --git a/src/libfetchers/git-utils.cc b/src/libfetchers/git-utils.cc index 114aa4ec0..31c42008f 100644 --- a/src/libfetchers/git-utils.cc +++ b/src/libfetchers/git-utils.cc @@ -1083,7 +1083,7 @@ std::vector> GitRepoImpl::getSubmodules ref getTarballCache() { - static auto repoDir = std::filesystem::path(getCacheDir()) / "nix" / "tarball-cache"; + static auto repoDir = std::filesystem::path(getCacheDir()) / "tarball-cache"; return GitRepo::openRepo(repoDir, true, true); } diff --git a/src/libfetchers/git.cc b/src/libfetchers/git.cc index 076c757c5..13682231d 100644 --- a/src/libfetchers/git.cc +++ b/src/libfetchers/git.cc @@ -44,7 +44,7 @@ bool isCacheFileWithinTtl(time_t now, const struct stat & st) Path getCachePath(std::string_view key, bool shallow) { return getCacheDir() - + "/nix/gitv3/" + + "/gitv3/" + hashString(HashAlgorithm::SHA256, key).to_string(HashFormat::Nix32, false) + (shallow ? "-shallow" : ""); } diff --git a/src/libfetchers/mercurial.cc b/src/libfetchers/mercurial.cc index 3feb3cb19..2c987f79d 100644 --- a/src/libfetchers/mercurial.cc +++ b/src/libfetchers/mercurial.cc @@ -263,7 +263,7 @@ struct MercurialInputScheme : InputScheme return makeResult(res->value, res->storePath); } - Path cacheDir = fmt("%s/nix/hg/%s", getCacheDir(), hashString(HashAlgorithm::SHA256, actualUrl).to_string(HashFormat::Nix32, false)); + Path cacheDir = fmt("%s/hg/%s", getCacheDir(), hashString(HashAlgorithm::SHA256, actualUrl).to_string(HashFormat::Nix32, false)); /* If this is a commit hash that we already have, we don't have to pull again. */ diff --git a/src/libfetchers/registry.cc b/src/libfetchers/registry.cc index 3c893c8ea..7f7a09053 100644 --- a/src/libfetchers/registry.cc +++ b/src/libfetchers/registry.cc @@ -116,7 +116,7 @@ static std::shared_ptr getSystemRegistry(const Settings & settings) Path getUserRegistryPath() { - return getConfigDir() + "/nix/registry.json"; + return getConfigDir() + "/registry.json"; } std::shared_ptr getUserRegistry(const Settings & settings) @@ -159,7 +159,7 @@ static std::shared_ptr getGlobalRegistry(const Settings & settings, re if (!hasPrefix(path, "/")) { auto storePath = downloadFile(store, path, "flake-registry.json").storePath; if (auto store2 = store.dynamic_pointer_cast()) - store2->addPermRoot(storePath, getCacheDir() + "/nix/flake-registry.json"); + store2->addPermRoot(storePath, getCacheDir() + "/flake-registry.json"); path = store->toRealPath(storePath); } diff --git a/src/libflake/flake/config.cc b/src/libflake/flake/config.cc index e526cdddf..4879de463 100644 --- a/src/libflake/flake/config.cc +++ b/src/libflake/flake/config.cc @@ -12,7 +12,7 @@ typedef std::map> TrustedList; Path trustedListPath() { - return getDataDir() + "/nix/trusted-settings.json"; + return getDataDir() + "/trusted-settings.json"; } static TrustedList readTrustedList() diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc index 52ab35b4c..8958e6997 100644 --- a/src/libstore/globals.cc +++ b/src/libstore/globals.cc @@ -135,7 +135,7 @@ std::vector getUserConfigFiles() std::vector files; auto dirs = getConfigDirs(); for (auto & dir : dirs) { - files.insert(files.end(), dir + "/nix/nix.conf"); + files.insert(files.end(), dir + "/nix.conf"); } return files; } diff --git a/src/libstore/nar-info-disk-cache.cc b/src/libstore/nar-info-disk-cache.cc index 83e63794e..80e8d3414 100644 --- a/src/libstore/nar-info-disk-cache.cc +++ b/src/libstore/nar-info-disk-cache.cc @@ -87,7 +87,7 @@ public: Sync _state; - NarInfoDiskCacheImpl(Path dbPath = getCacheDir() + "/nix/binary-cache-v6.sqlite") + NarInfoDiskCacheImpl(Path dbPath = getCacheDir() + "/binary-cache-v6.sqlite") { auto state(_state.lock()); diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index fc8d51c39..426a69ae2 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -1315,7 +1315,7 @@ ref openStore(StoreReference && storeURI) /* If /nix doesn't exist, there is no daemon socket, and we're not root, then automatically set up a chroot store in ~/.local/share/nix/root. */ - auto chrootStore = getDataDir() + "/nix/root"; + auto chrootStore = getDataDir() + "/root"; if (!pathExists(chrootStore)) { try { createDirs(chrootStore); diff --git a/src/libutil/users.cc b/src/libutil/users.cc index d546e364f..b4bc67cbc 100644 --- a/src/libutil/users.cc +++ b/src/libutil/users.cc @@ -7,15 +7,33 @@ namespace nix { Path getCacheDir() { - auto cacheDir = getEnv("XDG_CACHE_HOME"); - return cacheDir ? *cacheDir : getHome() + "/.cache"; + auto dir = getEnv("NIX_CACHE_HOME"); + if (dir) { + return *dir; + } else { + auto xdgDir = getEnv("XDG_CACHE_HOME"); + if (xdgDir) { + return *xdgDir + "/nix"; + } else { + return getHome() + "/.cache/nix"; + } + } } Path getConfigDir() { - auto configDir = getEnv("XDG_CONFIG_HOME"); - return configDir ? *configDir : getHome() + "/.config"; + auto dir = getEnv("NIX_CONFIG_HOME"); + if (dir) { + return *dir; + } else { + auto xdgDir = getEnv("XDG_CONFIG_HOME"); + if (xdgDir) { + return *xdgDir + "/nix"; + } else { + return getHome() + "/.config/nix"; + } + } } std::vector getConfigDirs() @@ -23,6 +41,9 @@ std::vector getConfigDirs() Path configHome = getConfigDir(); auto configDirs = getEnv("XDG_CONFIG_DIRS").value_or("/etc/xdg"); std::vector result = tokenizeString>(configDirs, ":"); + for (auto& p : result) { + p += "/nix"; + } result.insert(result.begin(), configHome); return result; } @@ -30,19 +51,37 @@ std::vector getConfigDirs() Path getDataDir() { - auto dataDir = getEnv("XDG_DATA_HOME"); - return dataDir ? *dataDir : getHome() + "/.local/share"; + auto dir = getEnv("NIX_DATA_HOME"); + if (dir) { + return *dir; + } else { + auto xdgDir = getEnv("XDG_DATA_HOME"); + if (xdgDir) { + return *xdgDir + "/nix"; + } else { + return getHome() + "/.local/share/nix"; + } + } } Path getStateDir() { - auto stateDir = getEnv("XDG_STATE_HOME"); - return stateDir ? *stateDir : getHome() + "/.local/state"; + auto dir = getEnv("NIX_STATE_HOME"); + if (dir) { + return *dir; + } else { + auto xdgDir = getEnv("XDG_STATE_HOME"); + if (xdgDir) { + return *xdgDir + "/nix"; + } else { + return getHome() + "/.local/state/nix"; + } + } } Path createNixStateDir() { - Path dir = getStateDir() + "/nix"; + Path dir = getStateDir(); createDirs(dir); return dir; } diff --git a/src/libutil/users.hh b/src/libutil/users.hh index 153cc73fd..d22c3311d 100644 --- a/src/libutil/users.hh +++ b/src/libutil/users.hh @@ -24,12 +24,12 @@ Path getHomeOf(uid_t userId); Path getHome(); /** - * @return $XDG_CACHE_HOME or $HOME/.cache. + * @return $NIX_CACHE_HOME or $XDG_CACHE_HOME/nix or $HOME/.cache/nix. */ Path getCacheDir(); /** - * @return $XDG_CONFIG_HOME or $HOME/.config. + * @return $NIX_CONFIG_HOME or $XDG_CONFIG_HOME/nix or $HOME/.config/nix. */ Path getConfigDir(); @@ -39,12 +39,12 @@ Path getConfigDir(); std::vector getConfigDirs(); /** - * @return $XDG_DATA_HOME or $HOME/.local/share. + * @return $NIX_DATA_HOME or $XDG_DATA_HOME/nix or $HOME/.local/share/nix. */ Path getDataDir(); /** - * @return $XDG_STATE_HOME or $HOME/.local/state. + * @return $NIX_STATE_HOME or $XDG_STATE_HOME/nix or $HOME/.local/state/nix. */ Path getStateDir(); From 51a01aa6c5524c6aad571d324a0f9baa2bbb9f51 Mon Sep 17 00:00:00 2001 From: "Travis A. Everett" Date: Wed, 11 Sep 2024 08:55:57 -0500 Subject: [PATCH 190/718] sequoia-nixbld-user-migration: halt on error Addressing user feedback about a case where actions the script takes may fail without a specific permission if run over SSH. --- scripts/sequoia-nixbld-user-migration.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/sequoia-nixbld-user-migration.sh b/scripts/sequoia-nixbld-user-migration.sh index 12c736d8e..88e801706 100755 --- a/scripts/sequoia-nixbld-user-migration.sh +++ b/scripts/sequoia-nixbld-user-migration.sh @@ -1,5 +1,7 @@ #!/usr/bin/env bash +set -eo pipefail + ((NEW_NIX_FIRST_BUILD_UID=351)) ((TEMP_NIX_FIRST_BUILD_UID=31000)) From 3fbd71701a39dea79dea576ba90fe42925d85459 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 11 Sep 2024 17:27:39 +0200 Subject: [PATCH 191/718] Add test --- tests/nixos/github-flakes.nix | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/nixos/github-flakes.nix b/tests/nixos/github-flakes.nix index 221045009..8e646f6dd 100644 --- a/tests/nixos/github-flakes.nix +++ b/tests/nixos/github-flakes.nix @@ -181,8 +181,14 @@ in print(out) info = json.loads(out) assert info["revision"] == "${private-flake-rev}", f"revision mismatch: {info['revision']} != ${private-flake-rev}" + assert info["fingerprint"] cat_log() + # Fetching with the resolved URL should produce the same result. + info2 = json.loads(client.succeed(f"nix flake metadata {info['url']} --json --access-tokens github.com=ghp_000000000000000000000000000000000000 --tarball-ttl 0")) + print(info["fingerprint"], info2["fingerprint"]) + assert info["fingerprint"] == info2["fingerprint"], "fingerprint mismatch" + client.succeed("nix registry pin nixpkgs") client.succeed("nix flake metadata nixpkgs --tarball-ttl 0 >&2") From e557096cefad10ccef86dc674fc5e053c13716e6 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 11 Sep 2024 17:31:53 +0200 Subject: [PATCH 192/718] Add release note --- doc/manual/rl-next/no-flake-substitution.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 doc/manual/rl-next/no-flake-substitution.md diff --git a/doc/manual/rl-next/no-flake-substitution.md b/doc/manual/rl-next/no-flake-substitution.md new file mode 100644 index 000000000..67ec58750 --- /dev/null +++ b/doc/manual/rl-next/no-flake-substitution.md @@ -0,0 +1,8 @@ +--- +synopsis: Flakes are no longer substituted +prs: [10612] +--- + +Nix will no longer attempt to substitute the source code of flakes from a binary cache. This functionality was broken because it could lead to different evaluation results depending on whether the flake was available in the binary cache, or even depending on whether the flake was already in the local store. + +Author: [**@edolstra**](https://github.com/edolstra) From 193dc490971b0435c7de7565b86110a59d515ff2 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Wed, 11 Sep 2024 11:59:11 -0400 Subject: [PATCH 193/718] tweak unpack channel built-in, std::filesystem::path for tarball --- src/libstore/builtins/unpack-channel.cc | 36 ++++++++++++++----------- src/libutil/tarfile.cc | 22 ++++++++------- src/libutil/tarfile.hh | 6 ++--- 3 files changed, 37 insertions(+), 27 deletions(-) diff --git a/src/libstore/builtins/unpack-channel.cc b/src/libstore/builtins/unpack-channel.cc index 7f9a520ee..d30626a30 100644 --- a/src/libstore/builtins/unpack-channel.cc +++ b/src/libstore/builtins/unpack-channel.cc @@ -3,46 +3,52 @@ namespace nix { +namespace fs { using namespace std::filesystem; } + void builtinUnpackChannel( const BasicDerivation & drv, const std::map & outputs) { - auto getAttr = [&](const std::string & name) { + auto getAttr = [&](const std::string & name) -> const std::string & { auto i = drv.env.find(name); if (i == drv.env.end()) throw Error("attribute '%s' missing", name); return i->second; }; - std::filesystem::path out(outputs.at("out")); - std::filesystem::path channelName(getAttr("channelName")); - auto src = getAttr("src"); + fs::path out{outputs.at("out")}; + auto & channelName = getAttr("channelName"); + auto & src = getAttr("src"); - if (channelName.filename() != channelName) { + if (fs::path{channelName}.filename().string() != channelName) { throw Error("channelName is not allowed to contain filesystem seperators, got %1%", channelName); } - createDirs(out); + try { + fs::create_directories(out); + } catch (fs::filesystem_error &) { + throw SysError("creating directory '%1%'", out.string()); + } unpackTarfile(src, out); size_t fileCount; std::string fileName; try { - auto entries = std::filesystem::directory_iterator{out}; + auto entries = fs::directory_iterator{out}; fileName = entries->path().string(); - fileCount = std::distance(std::filesystem::begin(entries), std::filesystem::end(entries)); - } catch (std::filesystem::filesystem_error &e) { - throw SysError("failed to read directory %1%", out); + fileCount = std::distance(fs::begin(entries), fs::end(entries)); + } catch (fs::filesystem_error &) { + throw SysError("failed to read directory %1%", out.string()); } - if (fileCount != 1) throw Error("channel tarball '%s' contains more than one file", src); - std::filesystem::path target(out / channelName); + + auto target = out / channelName; try { - std::filesystem::rename(fileName, target); - } catch (std::filesystem::filesystem_error &e) { - throw SysError("failed to rename %1% to %2%", fileName, target); + fs::rename(fileName, target); + } catch (fs::filesystem_error &) { + throw SysError("failed to rename %1% to %2%", fileName, target.string()); } } diff --git a/src/libutil/tarfile.cc b/src/libutil/tarfile.cc index 2e3236295..a8a22d283 100644 --- a/src/libutil/tarfile.cc +++ b/src/libutil/tarfile.cc @@ -8,6 +8,10 @@ namespace nix { +namespace fs { +using namespace std::filesystem; +} + namespace { int callback_open(struct archive *, void * self) @@ -102,14 +106,14 @@ TarArchive::TarArchive(Source & source, bool raw, std::optional com "Failed to open archive (%s)"); } -TarArchive::TarArchive(const Path & path) +TarArchive::TarArchive(const fs::path & path) : archive{archive_read_new()} , buffer(defaultBufferSize) { archive_read_support_filter_all(archive); enableSupportedFormats(archive); archive_read_set_option(archive, NULL, "mac-ext", NULL); - check(archive_read_open_filename(archive, path.c_str(), 16384), "failed to open archive: %s"); + check(archive_read_open_filename(archive, path.string().c_str(), 16384), "failed to open archive: %s"); } void TarArchive::close() @@ -123,7 +127,7 @@ TarArchive::~TarArchive() archive_read_free(this->archive); } -static void extract_archive(TarArchive & archive, const Path & destDir) +static void extract_archive(TarArchive & archive, const fs::path & destDir) { int flags = ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_SECURE_SYMLINKS | ARCHIVE_EXTRACT_SECURE_NODOTDOT; @@ -140,7 +144,7 @@ static void extract_archive(TarArchive & archive, const Path & destDir) else archive.check(r); - archive_entry_copy_pathname(entry, (destDir + "/" + name).c_str()); + archive_entry_copy_pathname(entry, (destDir / name).string().c_str()); // sources can and do contain dirs with no rx bits if (archive_entry_filetype(entry) == AE_IFDIR && (archive_entry_mode(entry) & 0500) != 0500) @@ -149,7 +153,7 @@ static void extract_archive(TarArchive & archive, const Path & destDir) // Patch hardlink path const char * original_hardlink = archive_entry_hardlink(entry); if (original_hardlink) { - archive_entry_copy_hardlink(entry, (destDir + "/" + original_hardlink).c_str()); + archive_entry_copy_hardlink(entry, (destDir / original_hardlink).string().c_str()); } archive.check(archive_read_extract(archive.archive, entry, flags)); @@ -158,19 +162,19 @@ static void extract_archive(TarArchive & archive, const Path & destDir) archive.close(); } -void unpackTarfile(Source & source, const Path & destDir) +void unpackTarfile(Source & source, const fs::path & destDir) { auto archive = TarArchive(source); - createDirs(destDir); + fs::create_directories(destDir); extract_archive(archive, destDir); } -void unpackTarfile(const Path & tarFile, const Path & destDir) +void unpackTarfile(const fs::path & tarFile, const fs::path & destDir) { auto archive = TarArchive(tarFile); - createDirs(destDir); + fs::create_directories(destDir); extract_archive(archive, destDir); } diff --git a/src/libutil/tarfile.hh b/src/libutil/tarfile.hh index 0517177db..5e29c6bba 100644 --- a/src/libutil/tarfile.hh +++ b/src/libutil/tarfile.hh @@ -15,7 +15,7 @@ struct TarArchive void check(int err, const std::string & reason = "failed to extract archive (%s)"); - explicit TarArchive(const Path & path); + explicit TarArchive(const std::filesystem::path & path); /// @brief Create a generic archive from source. /// @param source - Input byte stream. @@ -37,9 +37,9 @@ struct TarArchive int getArchiveFilterCodeByName(const std::string & method); -void unpackTarfile(Source & source, const Path & destDir); +void unpackTarfile(Source & source, const std::filesystem::path & destDir); -void unpackTarfile(const Path & tarFile, const Path & destDir); +void unpackTarfile(const std::filesystem::path & tarFile, const std::filesystem::path & destDir); time_t unpackTarfileToSink(TarArchive & archive, ExtendedFileSystemObjectSink & parseSink); From 48477d4a3e7130c89b2ded4496c00ef74601091f Mon Sep 17 00:00:00 2001 From: "Travis A. Everett" Date: Wed, 11 Sep 2024 12:50:47 -0500 Subject: [PATCH 194/718] doc: add admonitions for macOS 15 Sequoia update (#11487) The impending release of macOS 15 Sequoia will break many existing nix installs on macOS, which may lead to an increased number of people who are looking to try to reinstall Nix without noticing the open/pinned issue (#10892) that explains the problem and outlines how to migrate existing installs. These admonitions are a short-term measure until we are over the hump and support volumes dwindle. --- doc/manual/src/installation/index.md | 8 ++++++++ doc/manual/src/installation/installing-binary.md | 8 ++++++++ doc/manual/src/installation/uninstall.md | 8 ++++++++ 3 files changed, 24 insertions(+) diff --git a/doc/manual/src/installation/index.md b/doc/manual/src/installation/index.md index dafdeb667..16a7f485a 100644 --- a/doc/manual/src/installation/index.md +++ b/doc/manual/src/installation/index.md @@ -14,6 +14,14 @@ This option requires either: * Linux running systemd, with SELinux disabled * MacOS +> **Updating to macOS 15 Sequoia** +> +> If you recently updated to macOS 15 Sequoia and are getting +> ```console +> error: the user '_nixbld1' in the group 'nixbld' does not exist +> ``` +> when running Nix commands, refer to GitHub issue [NixOS/nix#10892](https://github.com/NixOS/nix/issues/10892) for instructions to fix your installation without reinstalling. + ```console $ bash <(curl -L https://nixos.org/nix/install) --daemon ``` diff --git a/doc/manual/src/installation/installing-binary.md b/doc/manual/src/installation/installing-binary.md index 6a168ff3d..6a1a5ddca 100644 --- a/doc/manual/src/installation/installing-binary.md +++ b/doc/manual/src/installation/installing-binary.md @@ -1,5 +1,13 @@ # Installing a Binary Distribution +> **Updating to macOS 15 Sequoia** +> +> If you recently updated to macOS 15 Sequoia and are getting +> ```console +> error: the user '_nixbld1' in the group 'nixbld' does not exist +> ``` +> when running Nix commands, refer to GitHub issue [NixOS/nix#10892](https://github.com/NixOS/nix/issues/10892) for instructions to fix your installation without reinstalling. + To install the latest version Nix, run the following command: ```console diff --git a/doc/manual/src/installation/uninstall.md b/doc/manual/src/installation/uninstall.md index bb21af24e..429fcae46 100644 --- a/doc/manual/src/installation/uninstall.md +++ b/doc/manual/src/installation/uninstall.md @@ -43,6 +43,14 @@ which you may remove. ### macOS +> **Updating to macOS 15 Sequoia** +> +> If you recently updated to macOS 15 Sequoia and are getting +> ```console +> error: the user '_nixbld1' in the group 'nixbld' does not exist +> ``` +> when running Nix commands, refer to GitHub issue [NixOS/nix#10892](https://github.com/NixOS/nix/issues/10892) for instructions to fix your installation without reinstalling. + 1. If system-wide shell initialisation files haven't been altered since installing Nix, use the backups made by the installer: ```console From 30aa45a37313f54006ad88b9f42f11d8c175b1db Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 11 Sep 2024 20:35:04 +0200 Subject: [PATCH 195/718] Formatting --- src/libflake/flake/lockfile.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libflake/flake/lockfile.cc b/src/libflake/flake/lockfile.cc index 80f14ff6f..70b60716f 100644 --- a/src/libflake/flake/lockfile.cc +++ b/src/libflake/flake/lockfile.cc @@ -54,12 +54,13 @@ StorePath LockedNode::computeStorePath(Store & store) const } -static std::shared_ptr doFind(const ref& root, const InputPath & path, std::vector& visited) { +static std::shared_ptr doFind(const ref & root, const InputPath & path, std::vector & visited) +{ auto pos = root; auto found = std::find(visited.cbegin(), visited.cend(), path); - if(found != visited.end()) { + if (found != visited.end()) { std::vector cycle; std::transform(found, visited.cend(), std::back_inserter(cycle), printInputPath); cycle.push_back(printInputPath(path)); From 12fd65d1799f6b1fe0c7e07d5a8022afc6b6dc40 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 11 Sep 2024 21:58:32 +0200 Subject: [PATCH 196/718] Disable subflakes test Relative path flakes ("subflakes") are basically fundamentally broken, since they produce lock file entries like "locked": { "lastModified": 1, "narHash": "sha256-/2tW9SKjQbRLzfcJs5SHijli6l3+iPr1235zylGynK8=", "path": "./flakeC", "type": "path" }, that don't specify what "./flakeC" is relative to. They *sometimes* worked by accident because the `narHash` field allowed `fetchToStore()` to get the store path of the subflake *if* it happened to exist in the local store or in a substituter. Subflakes are properly fixed in #10089 (which adds a "parent" field to the lock file). Rather than come up with some crazy hack to make them work in the interim, let's just disable the only test that depends on the broken behaviour for now. --- tests/functional/flakes/follow-paths.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/functional/flakes/follow-paths.sh b/tests/functional/flakes/follow-paths.sh index ea56b9503..d908a03c4 100755 --- a/tests/functional/flakes/follow-paths.sh +++ b/tests/functional/flakes/follow-paths.sh @@ -2,6 +2,9 @@ source ./common.sh +# FIXME: this test is disabled because relative path flakes are broken. Re-enable this in #10089. +exit 0 + requireGit flakeFollowsA=$TEST_ROOT/follows/flakeA From 421aa1add1cbae1fd51b8d9efa4ed47dce7a06ac Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 12 Sep 2024 14:58:33 +0200 Subject: [PATCH 197/718] Add tests for invalid file names in NARs Note: in general, we rely on the OS to tell us if a name is invalid or if two names normalize in the same way. But for security, we do want to make sure that we catch '.', '..', slashes and NUL characters. (NUL characters aren't really a security issue, but since they would be truncated when we pass them to the OS, it would be canonicity problem.) --- tests/functional/dot.nar | Bin 0 -> 288 bytes tests/functional/dotdot.nar | Bin 0 -> 288 bytes tests/functional/empty.nar | Bin 0 -> 280 bytes tests/functional/nars.sh | 20 ++++++++++++++++++++ tests/functional/nul.nar | Bin 0 -> 288 bytes tests/functional/slash.nar | Bin 0 -> 288 bytes 6 files changed, 20 insertions(+) create mode 100644 tests/functional/dot.nar create mode 100644 tests/functional/dotdot.nar create mode 100644 tests/functional/empty.nar create mode 100644 tests/functional/nul.nar create mode 100644 tests/functional/slash.nar diff --git a/tests/functional/dot.nar b/tests/functional/dot.nar new file mode 100644 index 0000000000000000000000000000000000000000..3a9452f67fd7dc8b8c9328c767337c5c51b006c4 GIT binary patch literal 288 zcmd;OfPlQr3f;t_5|HVR1lLB%1_BGN=+`wFRFy{S)p`l zUI|zXmpOTfxnOf(@_JBxFnjXyQ&8k_xq}_5uP8OWG$*l$fdk4<&d)0Wx}lg2%Fjs6 R$;szJ_)8Ni4znK@9{^kc8+8Bx literal 0 HcmV?d00001 diff --git a/tests/functional/dotdot.nar b/tests/functional/dotdot.nar new file mode 100644 index 0000000000000000000000000000000000000000..f8d019c3926a8285fd3258798a8f88efc65df48d GIT binary patch literal 288 zcmd;OfPlQr3f;t_5|HVR1lLB%1_BGN=+`wFRFy{S)p`l zUI|zXmpOTfxnOgcpz8JXAPks2dHE?|d0hHo?qG-NFG@`>%}Fd`;DGXz^Yco8ZYXAh V@-tF%a`L$l{?des!_3FU2LN}%8>9dL literal 0 HcmV?d00001 diff --git a/tests/functional/empty.nar b/tests/functional/empty.nar new file mode 100644 index 0000000000000000000000000000000000000000..43434f2b4404161a74e8a90c0b5c8e3a11194fdf GIT binary patch literal 280 zcmd;OfPlQr3f;t_5|HVR1lLB%1_BGN=+`wFRFy{S)p`l zUI|zXmpOTfxnOgk${Aqh=jEq>#c}C_+0PEuSd^Mxnv+<>zyaka=jW9G?Jj16@-tF% Ra`L$l{?UYr!_3FU2LQ_<8%6*C literal 0 HcmV?d00001 diff --git a/tests/functional/nars.sh b/tests/functional/nars.sh index 9f5f43dc6..68b9b45d9 100755 --- a/tests/functional/nars.sh +++ b/tests/functional/nars.sh @@ -92,3 +92,23 @@ else [[ -e $TEST_ROOT/out/â ]] [[ -e $TEST_ROOT/out/â ]] fi + +# Unpacking a NAR with a NUL character in a file name should fail. +rm -rf "$TEST_ROOT/out" +expectStderr 1 nix-store --restore "$TEST_ROOT/out" < nul.nar | grepQuiet "NAR contains invalid file name 'f" + +# Likewise for a '.' filename. +rm -rf "$TEST_ROOT/out" +expectStderr 1 nix-store --restore "$TEST_ROOT/out" < dot.nar | grepQuiet "NAR contains invalid file name '.'" + +# Likewise for a '..' filename. +rm -rf "$TEST_ROOT/out" +expectStderr 1 nix-store --restore "$TEST_ROOT/out" < dotdot.nar | grepQuiet "NAR contains invalid file name '..'" + +# Likewise for a filename containing a slash. +rm -rf "$TEST_ROOT/out" +expectStderr 1 nix-store --restore "$TEST_ROOT/out" < slash.nar | grepQuiet "NAR contains invalid file name 'x/y'" + +# Likewise for an empty filename. +rm -rf "$TEST_ROOT/out" +expectStderr 1 nix-store --restore "$TEST_ROOT/out" < empty.nar | grepQuiet "NAR contains invalid file name ''" diff --git a/tests/functional/nul.nar b/tests/functional/nul.nar new file mode 100644 index 0000000000000000000000000000000000000000..9ae48baf6fa658433e37afdb6cae18b2d056a06c GIT binary patch literal 288 zcmd;OfPlQr3f;t_5|HVR1lLB%1_BGN=+`wFRFy{S)p`l zUI|zXmpOTfxnOgcq3Y8Z^1&>aJ$d;lV0m2nVeVju>Mu%7FU?6TV&H)Clk@XRfNm&e WgYq*{b8_;z5dPAHio?vu#RmYtiX0vQ literal 0 HcmV?d00001 diff --git a/tests/functional/slash.nar b/tests/functional/slash.nar new file mode 100644 index 0000000000000000000000000000000000000000..118a60216cc12d33df202aec4c5dd8fbfbcfce75 GIT binary patch literal 288 zcmd;OfPlQr3f;t_5|HVR1lLB%1_BGN=+`wFRFy{S)p`l zUI|zXmpOTfxnOgcq3SF2Atu1=$;(dx%j41ya|b(Ae^F|BX-;Ah0|%6!oS#<$bVD&4 Vl%J8BlatSd@Ruf39A-W)J^<^_9BBXm literal 0 HcmV?d00001 From 4de9587e50644b59ca7fcf0e1ad940d0dddcb89c Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 12 Sep 2024 15:27:55 +0200 Subject: [PATCH 198/718] Improve badArchive() --- src/libutil/archive.cc | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/libutil/archive.cc b/src/libutil/archive.cc index e26b7eb93..d9a3afd41 100644 --- a/src/libutil/archive.cc +++ b/src/libutil/archive.cc @@ -128,9 +128,10 @@ void dumpString(std::string_view s, Sink & sink) } -static SerialisationError badArchive(const std::string & s) +template +static SerialisationError badArchive(std::string_view s, const Args & ... args) { - return SerialisationError("bad archive: " + s); + return SerialisationError("bad archive: " + s, args...); } @@ -223,7 +224,7 @@ static void parse(FileSystemObjectSink & sink, Source & source, const CanonPath std::string name; s = getString(); - if (s != "(") throw badArchive("expected open tag"); + if (s != "(") throw badArchive("expected open tag '%s'", s); while (1) { s = getString(); @@ -233,9 +234,9 @@ static void parse(FileSystemObjectSink & sink, Source & source, const CanonPath } else if (s == "name") { name = getString(); if (name.empty() || name == "." || name == ".." || name.find('/') != std::string::npos || name.find((char) 0) != std::string::npos) - throw Error("NAR contains invalid file name '%1%'", name); + throw badArchive("NAR contains invalid file name '%1%'", name); if (name <= prevName) - throw Error("NAR directory is not sorted"); + throw badArchive("NAR directory is not sorted"); prevName = name; if (archiveSettings.useCaseHack) { auto i = names.find(name); @@ -245,7 +246,7 @@ static void parse(FileSystemObjectSink & sink, Source & source, const CanonPath name += std::to_string(++i->second); auto j = names.find(name); if (j != names.end()) - throw Error("NAR contains file name '%s' that collides with case-hacked file name '%s'", prevName, j->first); + throw badArchive("NAR contains file name '%s' that collides with case-hacked file name '%s'", prevName, j->first); } else names[name] = 0; } @@ -253,7 +254,7 @@ static void parse(FileSystemObjectSink & sink, Source & source, const CanonPath if (name.empty()) throw badArchive("entry name missing"); parse(sink, source, path / name); } else - throw badArchive("unknown field " + s); + throw badArchive("unknown field '%s'", s); } } @@ -265,7 +266,7 @@ static void parse(FileSystemObjectSink & sink, Source & source, const CanonPath s = getString(); if (s != "target") - throw badArchive("expected 'target' got " + s); + throw badArchive("expected 'target', got '%s'", s); std::string target = getString(); sink.createSymlink(path, target); @@ -274,12 +275,12 @@ static void parse(FileSystemObjectSink & sink, Source & source, const CanonPath s = getString(); } - else throw badArchive("unknown file type " + t); + else throw badArchive("unknown file type '%s'", t); } else - throw badArchive("unknown field " + s); + throw badArchive("unknown field '%s'", s); } } From 69bf9947c78ea80b761dae81053ad50ad7ad8532 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 12 Sep 2024 15:29:54 +0200 Subject: [PATCH 199/718] Put 'names' in the right scope --- src/libutil/archive.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libutil/archive.cc b/src/libutil/archive.cc index d9a3afd41..9ddec44cd 100644 --- a/src/libutil/archive.cc +++ b/src/libutil/archive.cc @@ -173,8 +173,6 @@ static void parse(FileSystemObjectSink & sink, Source & source, const CanonPath s = readString(source); if (s != "(") throw badArchive("expected open tag"); - std::map names; - auto getString = [&]() { checkInterrupt(); return readString(source); @@ -215,6 +213,8 @@ static void parse(FileSystemObjectSink & sink, Source & source, const CanonPath else if (t == "directory") { sink.createDirectory(path); + std::map names; + std::string prevName; while (1) { From 27ec0def740208f6884a1aad862f4e2e181ca0a9 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 12 Sep 2024 15:33:55 +0200 Subject: [PATCH 200/718] Typo --- src/libutil/archive.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libutil/archive.cc b/src/libutil/archive.cc index 9ddec44cd..c9362d6cb 100644 --- a/src/libutil/archive.cc +++ b/src/libutil/archive.cc @@ -82,7 +82,7 @@ void SourceAccessor::dumpPath( name.erase(pos); } if (!unhacked.emplace(name, i.first).second) - throw Error("file name collision in between '%s' and '%s'", + throw Error("file name collision between '%s' and '%s'", (path / unhacked[name]), (path / i.first)); } else From 7aa3e7e3a5281acf350eff0fe039656cd4986e2c Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 12 Sep 2024 15:57:46 +0200 Subject: [PATCH 201/718] Make the NAR parser much stricter wrt field order We really want to enforce a canonical representation since NAR hashing/signing/deduplication depends on that. --- src/libutil/archive.cc | 177 ++++++++---------- .../functional/executable-after-contents.nar | Bin 0 -> 320 bytes tests/functional/name-after-node.nar | Bin 0 -> 288 bytes tests/functional/nars.sh | 8 + 4 files changed, 85 insertions(+), 100 deletions(-) create mode 100644 tests/functional/executable-after-contents.nar create mode 100644 tests/functional/name-after-node.nar diff --git a/src/libutil/archive.cc b/src/libutil/archive.cc index c9362d6cb..20d8a1e09 100644 --- a/src/libutil/archive.cc +++ b/src/libutil/archive.cc @@ -168,120 +168,97 @@ struct CaseInsensitiveCompare static void parse(FileSystemObjectSink & sink, Source & source, const CanonPath & path) { - std::string s; - - s = readString(source); - if (s != "(") throw badArchive("expected open tag"); - auto getString = [&]() { checkInterrupt(); return readString(source); }; - // For first iteration - s = getString(); + auto expectTag = [&](std::string_view expected) { + auto tag = getString(); + if (tag != expected) + throw badArchive("expected tag '%s', got '%s'", expected, tag); + }; - while (1) { + expectTag("("); - if (s == ")") { - break; - } + expectTag("type"); - else if (s == "type") { - std::string t = getString(); + auto type = getString(); - if (t == "regular") { - sink.createRegularFile(path, [&](auto & crf) { - while (1) { - s = getString(); + if (type == "regular") { + sink.createRegularFile(path, [&](auto & crf) { + auto tag = getString(); - if (s == "contents") { - parseContents(crf, source); - } - - else if (s == "executable") { - auto s2 = getString(); - if (s2 != "") throw badArchive("executable marker has non-empty value"); - crf.isExecutable(); - } - - else break; - } - }); + if (tag == "executable") { + auto s2 = getString(); + if (s2 != "") throw badArchive("executable marker has non-empty value"); + crf.isExecutable(); + tag = getString(); } - else if (t == "directory") { - sink.createDirectory(path); + if (tag == "contents") + parseContents(crf, source); - std::map names; - - std::string prevName; - - while (1) { - s = getString(); - - if (s == "entry") { - std::string name; - - s = getString(); - if (s != "(") throw badArchive("expected open tag '%s'", s); - - while (1) { - s = getString(); - - if (s == ")") { - break; - } else if (s == "name") { - name = getString(); - if (name.empty() || name == "." || name == ".." || name.find('/') != std::string::npos || name.find((char) 0) != std::string::npos) - throw badArchive("NAR contains invalid file name '%1%'", name); - if (name <= prevName) - throw badArchive("NAR directory is not sorted"); - prevName = name; - if (archiveSettings.useCaseHack) { - auto i = names.find(name); - if (i != names.end()) { - debug("case collision between '%1%' and '%2%'", i->first, name); - name += caseHackSuffix; - name += std::to_string(++i->second); - auto j = names.find(name); - if (j != names.end()) - throw badArchive("NAR contains file name '%s' that collides with case-hacked file name '%s'", prevName, j->first); - } else - names[name] = 0; - } - } else if (s == "node") { - if (name.empty()) throw badArchive("entry name missing"); - parse(sink, source, path / name); - } else - throw badArchive("unknown field '%s'", s); - } - } - - else break; - } - } - - else if (t == "symlink") { - s = getString(); - - if (s != "target") - throw badArchive("expected 'target', got '%s'", s); - - std::string target = getString(); - sink.createSymlink(path, target); - - // for the next iteration - s = getString(); - } - - else throw badArchive("unknown file type '%s'", t); - - } - - else - throw badArchive("unknown field '%s'", s); + expectTag(")"); + }); } + + else if (type == "directory") { + sink.createDirectory(path); + + std::map names; + + std::string prevName; + + while (1) { + auto tag = getString(); + + if (tag == ")") break; + + if (tag != "entry") + throw badArchive("expected tag 'entry' or ')', got '%s'", tag); + + expectTag("("); + + expectTag("name"); + + auto name = getString(); + if (name.empty() || name == "." || name == ".." || name.find('/') != std::string::npos || name.find((char) 0) != std::string::npos) + throw badArchive("NAR contains invalid file name '%1%'", name); + if (name <= prevName) + throw badArchive("NAR directory is not sorted"); + prevName = name; + if (archiveSettings.useCaseHack) { + auto i = names.find(name); + if (i != names.end()) { + debug("case collision between '%1%' and '%2%'", i->first, name); + name += caseHackSuffix; + name += std::to_string(++i->second); + auto j = names.find(name); + if (j != names.end()) + throw badArchive("NAR contains file name '%s' that collides with case-hacked file name '%s'", prevName, j->first); + } else + names[name] = 0; + } + + expectTag("node"); + + parse(sink, source, path / name); + + expectTag(")"); + } + } + + else if (type == "symlink") { + expectTag("target"); + + auto target = getString(); + sink.createSymlink(path, target); + + expectTag(")"); + } + + else throw badArchive("unknown file type '%s'", type); } diff --git a/tests/functional/executable-after-contents.nar b/tests/functional/executable-after-contents.nar new file mode 100644 index 0000000000000000000000000000000000000000..f8c003480d786957a141aca605ae3e78819f61d9 GIT binary patch literal 320 zcmah@Ne;p=3=Co|690fh4?HQPhDHiD3NC7YPiiK|3d_=X#>@ERe!+2UeGYy6P5|HVR1lLB%1_BGN=+`wFRFy{S)p`l zUI|zXmpOU)DPVJO$;0enhniQEnqHcdSj4~qqH1W`puGQgd?hxe)Hwgo?x5 YotKykwvQPqo|c~vX2I--sYmAn07Q};jQ{`u literal 0 HcmV?d00001 diff --git a/tests/functional/nars.sh b/tests/functional/nars.sh index 68b9b45d9..87fd7beec 100755 --- a/tests/functional/nars.sh +++ b/tests/functional/nars.sh @@ -112,3 +112,11 @@ expectStderr 1 nix-store --restore "$TEST_ROOT/out" < slash.nar | grepQuiet "NAR # Likewise for an empty filename. rm -rf "$TEST_ROOT/out" expectStderr 1 nix-store --restore "$TEST_ROOT/out" < empty.nar | grepQuiet "NAR contains invalid file name ''" + +# Test that the 'executable' field cannot come before the 'contents' field. +rm -rf "$TEST_ROOT/out" +expectStderr 1 nix-store --restore "$TEST_ROOT/out" < executable-after-contents.nar | grepQuiet "expected tag ')', got 'executable'" + +# Test that the 'name' field cannot come before the 'node' field in a directory entry. +rm -rf "$TEST_ROOT/out" +expectStderr 1 nix-store --restore "$TEST_ROOT/out" < name-after-node.nar | grepQuiet "expected tag 'name'" From 5737d31d4ea7afceaebde0a44fbf188bfe39783b Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 12 Sep 2024 17:25:25 +0200 Subject: [PATCH 202/718] Test the case hack a bit more --- tests/functional/nars.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/functional/nars.sh b/tests/functional/nars.sh index 87fd7beec..28876e497 100755 --- a/tests/functional/nars.sh +++ b/tests/functional/nars.sh @@ -67,6 +67,12 @@ expectStderr 1 nix-store --restore "$TEST_ROOT/out" < "$TEST_ROOT/tmp.nar" | gre rm -rf "$TEST_ROOT/case" opts=("--option" "use-case-hack" "true") nix-store "${opts[@]}" --restore "$TEST_ROOT/case" < case.nar +[[ -e "$TEST_ROOT/case/xt_CONNMARK.h" ]] +[[ -e "$TEST_ROOT/case/xt_CONNmark.h~nix~case~hack~1" ]] +[[ -e "$TEST_ROOT/case/xt_connmark.h~nix~case~hack~2" ]] +[[ -e "$TEST_ROOT/case/x/FOO" ]] +[[ -d "$TEST_ROOT/case/x/Foo~nix~case~hack~1" ]] +[[ -e "$TEST_ROOT/case/x/foo~nix~case~hack~2/a~nix~case~hack~1/foo" ]] nix-store "${opts[@]}" --dump "$TEST_ROOT/case" > "$TEST_ROOT/case.nar" cmp case.nar "$TEST_ROOT/case.nar" [ "$(nix-hash "${opts[@]}" --type sha256 "$TEST_ROOT/case")" = "$(nix-hash --flat --type sha256 case.nar)" ] From 2226f9864ed1b529bb300bf444a57bdd6c3d22fa Mon Sep 17 00:00:00 2001 From: Bryan Honof Date: Thu, 12 Sep 2024 03:05:41 +0200 Subject: [PATCH 203/718] feat(run): inherit from MixEnvironment --- src/nix/run.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/nix/run.cc b/src/nix/run.cc index 63ae8a195..956563591 100644 --- a/src/nix/run.cc +++ b/src/nix/run.cc @@ -75,7 +75,7 @@ void execProgramInStore(ref store, } -struct CmdRun : InstallableValueCommand +struct CmdRun : InstallableValueCommand, MixEnvironment { using InstallableCommand::run; @@ -135,6 +135,8 @@ struct CmdRun : InstallableValueCommand // we are about to exec out of this process without running C++ destructors. state->evalCaches.clear(); + setEnviron(); + execProgramInStore(store, UseLookupPath::DontUse, app.program, allArgs); } }; From 976f539f7dd2ee6345b605def105883d16b32c60 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 28 Aug 2024 02:35:46 +0200 Subject: [PATCH 204/718] Make Repo::flush interruptible --- src/libfetchers/git-utils.cc | 115 ++++++++++++++++++++++++++--------- 1 file changed, 85 insertions(+), 30 deletions(-) diff --git a/src/libfetchers/git-utils.cc b/src/libfetchers/git-utils.cc index 70391a287..265eb35d2 100644 --- a/src/libfetchers/git-utils.cc +++ b/src/libfetchers/git-utils.cc @@ -166,6 +166,45 @@ static Object peelToTreeOrBlob(git_object * obj) return peelObject(obj, GIT_OBJECT_TREE); } +struct PackBuilderContext { + std::exception_ptr exception; + + void handleException(const char * activity, int errCode) + { + switch (errCode) { + case GIT_OK: + break; + case GIT_EUSER: + if (!exception) + panic("PackBuilderContext::handleException: user error, but exception was not set"); + + std::rethrow_exception(exception); + default: + throw Error("%s: %i, %s", Uncolored(activity), errCode, git_error_last()->message); + } + } +}; + +extern "C" { + +/** + * A `git_packbuilder_progress` implementation that aborts the pack building if needed. + */ +static int packBuilderProgressCheckInterrupt(int stage, uint32_t current, uint32_t total, void *payload) +{ + PackBuilderContext & args = * (PackBuilderContext *) payload; + try { + checkInterrupt(); + return GIT_OK; + } catch (const std::exception & e) { + args.exception = std::current_exception(); + return GIT_EUSER; + } +}; +static git_packbuilder_progress PACKBUILDER_PROGRESS_CHECK_INTERRUPT = &packBuilderProgressCheckInterrupt; + +} // extern "C" + struct GitRepoImpl : GitRepo, std::enable_shared_from_this { /** Location of the repository on disk. */ @@ -213,42 +252,58 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this } void flush() override { + checkInterrupt(); + git_buf buf = GIT_BUF_INIT; - try { - PackBuilder packBuilder; - git_packbuilder_new(Setter(packBuilder), *this); - checkInterrupt(); - git_mempack_write_thin_pack(mempack_backend, packBuilder.get()); - checkInterrupt(); - // TODO make git_packbuilder_write_buf() interruptible - git_packbuilder_write_buf(&buf, packBuilder.get()); - checkInterrupt(); + Finally _disposeBuf { [&] { git_buf_dispose(&buf); } }; + PackBuilder packBuilder; + PackBuilderContext packBuilderContext; + git_packbuilder_new(Setter(packBuilder), *this); + git_packbuilder_set_callbacks(packBuilder.get(), PACKBUILDER_PROGRESS_CHECK_INTERRUPT, &packBuilderContext); + git_packbuilder_set_threads(packBuilder.get(), 0 /* autodetect */); - std::string repo_path = std::string(git_repository_path(repo.get())); - while (!repo_path.empty() && repo_path.back() == '/') - repo_path.pop_back(); - std::string pack_dir_path = repo_path + "/objects/pack"; + packBuilderContext.handleException( + "preparing packfile", + git_mempack_write_thin_pack(mempack_backend, packBuilder.get()) + ); + checkInterrupt(); + packBuilderContext.handleException( + "writing packfile", + git_packbuilder_write_buf(&buf, packBuilder.get()) + ); + checkInterrupt(); - // TODO: could the indexing be done in a separate thread? - Indexer indexer; - git_indexer_progress stats; - if (git_indexer_new(Setter(indexer), pack_dir_path.c_str(), 0, nullptr, nullptr)) - throw Error("creating git packfile indexer: %s", git_error_last()->message); - // TODO: feed buf in (fairly large) chunk to make this interruptible - if (git_indexer_append(indexer.get(), buf.ptr, buf.size, &stats)) + std::string repo_path = std::string(git_repository_path(repo.get())); + while (!repo_path.empty() && repo_path.back() == '/') + repo_path.pop_back(); + std::string pack_dir_path = repo_path + "/objects/pack"; + + // TODO (performance): could the indexing be done in a separate thread? + // we'd need a more streaming variation of + // git_packbuilder_write_buf, or incur the cost of + // copying parts of the buffer to a separate thread. + // (synchronously on the git_packbuilder_write_buf thread) + Indexer indexer; + git_indexer_progress stats; + if (git_indexer_new(Setter(indexer), pack_dir_path.c_str(), 0, nullptr, nullptr)) + throw Error("creating git packfile indexer: %s", git_error_last()->message); + + // TODO: provide index callback for checkInterrupt() termination + // though this is about an order of magnitude faster than the packbuilder + // expect up to 1 sec latency due to uninterruptible git_indexer_append. + constexpr size_t chunkSize = 128 * 1024; + for (size_t offset = 0; offset < buf.size; offset += chunkSize) { + if (git_indexer_append(indexer.get(), buf.ptr + offset, std::min(chunkSize, buf.size - offset), &stats)) throw Error("appending to git packfile index: %s", git_error_last()->message); checkInterrupt(); - if (git_indexer_commit(indexer.get(), &stats)) - throw Error("committing git packfile index: %s", git_error_last()->message); - - if (git_mempack_reset(mempack_backend)) - throw Error("resetting git mempack backend: %s", git_error_last()->message); - - git_buf_dispose(&buf); - } catch (...) { - git_buf_dispose(&buf); - throw; } + + if (git_indexer_commit(indexer.get(), &stats)) + throw Error("committing git packfile index: %s", git_error_last()->message); + + if (git_mempack_reset(mempack_backend)) + throw Error("resetting git mempack backend: %s", git_error_last()->message); + checkInterrupt(); } From 459d02672c5ea9c6b909c0ace6b11141af79421e Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 28 Aug 2024 11:13:03 +0200 Subject: [PATCH 205/718] fix Windows build --- packaging/dependencies.nix | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/packaging/dependencies.nix b/packaging/dependencies.nix index 0182f29c0..e5f4c0f91 100644 --- a/packaging/dependencies.nix +++ b/packaging/dependencies.nix @@ -116,20 +116,25 @@ scope: { cmakeFlags = attrs.cmakeFlags or [] ++ [ "-DUSE_SSH=exec" ]; nativeBuildInputs = attrs.nativeBuildInputs or [] - ++ [ + # gitMinimal does not build on Windows. See packbuilder patch. + ++ lib.optionals (!stdenv.hostPlatform.isWindows) [ # Needed for `git apply`; see `prePatch` pkgs.buildPackages.gitMinimal ]; # Only `git apply` can handle git binary patches - prePatch = '' - patch() { - git apply - } - ''; + prePatch = attrs.prePatch or "" + + lib.optionalString (!stdenv.hostPlatform.isWindows) '' + patch() { + git apply + } + ''; patches = attrs.patches or [] ++ [ ./patches/libgit2-mempack-thin-packfile.patch - + ] + # gitMinimal does not build on Windows, but fortunately this patch only + # impacts interruptibility + ++ lib.optionals (!stdenv.hostPlatform.isWindows) [ # binary patch; see `prePatch` ./patches/libgit2-packbuilder-callback-interruptible.patch ]; From 09d71974ef158defe3bae12889c9751b198fdac6 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 16 Sep 2024 14:11:08 +0200 Subject: [PATCH 206/718] shellcheck --- tests/functional/flakes/relative-paths.sh | 54 ++++++++++++----------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/tests/functional/flakes/relative-paths.sh b/tests/functional/flakes/relative-paths.sh index 3e4c97cc4..e72339b7f 100644 --- a/tests/functional/flakes/relative-paths.sh +++ b/tests/functional/flakes/relative-paths.sh @@ -1,16 +1,18 @@ +#!/usr/bin/env bash + source ./common.sh requireGit -rootFlake=$TEST_ROOT/flake1 -subflake0=$rootFlake/sub0 -subflake1=$rootFlake/sub1 -subflake2=$rootFlake/sub2 +rootFlake="$TEST_ROOT/flake1" +subflake0="$rootFlake/sub0" +subflake1="$rootFlake/sub1" +subflake2="$rootFlake/sub2" -rm -rf $rootFlake -mkdir -p $rootFlake $subflake0 $subflake1 $subflake2 +rm -rf "$rootFlake" +mkdir -p "$rootFlake" "$subflake0" "$subflake1" "$subflake2" -cat > $rootFlake/flake.nix < "$rootFlake/flake.nix" < $rootFlake/flake.nix < $subflake0/flake.nix < "$subflake0/flake.nix" < $subflake0/flake.nix < $subflake1/flake.nix < "$subflake1/flake.nix" < $subflake1/flake.nix < $subflake2/flake.nix < "$subflake2/flake.nix" < $subflake2/flake.nix < $rootFlake/flake.nix < "$rootFlake/flake.nix" < $rootFlake/flake.nix < Date: Mon, 16 Sep 2024 14:52:23 +0200 Subject: [PATCH 207/718] parentPath -> parentInputPath --- src/libflake/flake/flake.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libflake/flake/flake.cc b/src/libflake/flake/flake.cc index 632968f50..461ac0a90 100644 --- a/src/libflake/flake/flake.cc +++ b/src/libflake/flake/flake.cc @@ -404,7 +404,7 @@ LockedFlake lockFlake( { FlakeInput input; SourcePath sourcePath; - std::optional parentPath; // FIXME: rename to inputPathPrefix? + std::optional parentInputPath; // FIXME: rename to inputPathPrefix? }; std::map overrides; @@ -469,7 +469,7 @@ LockedFlake lockFlake( Override { .input = inputOverride, .sourcePath = sourcePath, - .parentPath = inputPathPrefix // FIXME: should this be inputPath? + .parentInputPath = inputPathPrefix // FIXME: should this be inputPath? }); } } @@ -531,7 +531,7 @@ LockedFlake lockFlake( auto overridenParentPath = input.ref->input.isRelative() - ? std::optional(hasOverride ? i->second.parentPath : inputPathPrefix) + ? std::optional(hasOverride ? i->second.parentInputPath : inputPathPrefix) : std::nullopt; auto resolveRelativePath = [&]() -> std::optional From afa6cc72714161042f05cacf9b21d328a49ccd78 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 22:59:12 +0000 Subject: [PATCH 208/718] Bump cachix/install-nix-action from V27 to 28 Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from V27 to 28. This release includes the previously tagged commit. - [Release notes](https://github.com/cachix/install-nix-action/releases) - [Commits](https://github.com/cachix/install-nix-action/compare/V27...V28) --- updated-dependencies: - dependency-name: cachix/install-nix-action dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 84e5ab998..30272ecf1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 - - uses: cachix/install-nix-action@V27 + - uses: cachix/install-nix-action@V28 with: # The sandbox would otherwise be disabled by default on Darwin extra_nix_config: "sandbox = true" @@ -89,7 +89,7 @@ jobs: with: fetch-depth: 0 - run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV - - uses: cachix/install-nix-action@V27 + - uses: cachix/install-nix-action@V28 with: install_url: https://releases.nixos.org/nix/nix-2.20.3/install - uses: cachix/cachix-action@v15 @@ -112,7 +112,7 @@ jobs: steps: - uses: actions/checkout@v4 - run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV - - uses: cachix/install-nix-action@V27 + - uses: cachix/install-nix-action@V28 with: install_url: '${{needs.installer.outputs.installerURL}}' install_options: "--tarball-url-prefix https://${{ env.CACHIX_NAME }}.cachix.org/serve" @@ -142,7 +142,7 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 - - uses: cachix/install-nix-action@V27 + - uses: cachix/install-nix-action@V28 with: install_url: https://releases.nixos.org/nix/nix-2.20.3/install - run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV From 65f138f6693eca7edfa0aeacc780597520868201 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 17 Sep 2024 12:37:33 +0200 Subject: [PATCH 209/718] nix derivation add: Remove reference to "installable" It doesn't operate on an installable, so don't mention it. --- src/nix/derivation-add.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nix/derivation-add.md b/src/nix/derivation-add.md index 331cbdd88..35507d9ad 100644 --- a/src/nix/derivation-add.md +++ b/src/nix/derivation-add.md @@ -3,7 +3,7 @@ R""( # Description This command reads from standard input a JSON representation of a -[store derivation] to which an [*installable*](./nix.md#installables) evaluates. +[store derivation]. Store derivations are used internally by Nix. They are store paths with extension `.drv` that represent the build-time dependency graph to which From c7c3a7f667d9ed85ef8255205c54c15b6b99bcd9 Mon Sep 17 00:00:00 2001 From: Yuriy Taraday Date: Tue, 17 Sep 2024 16:15:39 +0200 Subject: [PATCH 210/718] Fix meson build on macOS in sandbox Workaround at src/libstore/meson.build#L429-L434 by @Ericson2314 from https://github.com/NixOS/nix/pull/11302 erroneously used `macos` instead of `darwin` to distinguish macOS, while meson docs list only `darwin`: https://mesonbuild.com/Reference-tables.html#operating-system-names. Original thread: https://github.com/NixOS/nix/issues/2503#issuecomment-2353184049 --- src/libstore/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstore/meson.build b/src/libstore/meson.build index 2adc9b3e4..6a6aabf97 100644 --- a/src/libstore/meson.build +++ b/src/libstore/meson.build @@ -427,7 +427,7 @@ extra_pkg_config_variables = { } # Working around https://github.com/mesonbuild/meson/issues/13584 -if host_machine.system() != 'macos' +if host_machine.system() != 'darwin' extra_pkg_config_variables += { 'localstatedir' : get_option('localstatedir'), } From ee3f0b7a8b40becb2c03d944a0f02169bb205cda Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 17 Sep 2024 16:55:44 +0200 Subject: [PATCH 211/718] Rename import-derivation -> import-from-derivation --- maintainers/flake-module.nix | 2 +- .../ca/{import-derivation.sh => import-from-derivation.sh} | 2 +- tests/functional/ca/local.mk | 2 +- tests/functional/ca/meson.build | 2 +- .../{import-derivation.nix => import-from-derivation.nix} | 0 .../{import-derivation.sh => import-from-derivation.sh} | 4 ++-- tests/functional/local.mk | 2 +- tests/functional/meson.build | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) rename tests/functional/ca/{import-derivation.sh => import-from-derivation.sh} (55%) rename tests/functional/{import-derivation.nix => import-from-derivation.nix} (100%) rename tests/functional/{import-derivation.sh => import-from-derivation.sh} (58%) diff --git a/maintainers/flake-module.nix b/maintainers/flake-module.nix index 0b83e5696..fb286208d 100644 --- a/maintainers/flake-module.nix +++ b/maintainers/flake-module.nix @@ -508,7 +508,7 @@ ''^tests/functional/ca/concurrent-builds\.sh$'' ''^tests/functional/ca/eval-store\.sh$'' ''^tests/functional/ca/gc\.sh$'' - ''^tests/functional/ca/import-derivation\.sh$'' + ''^tests/functional/ca/import-from-derivation\.sh$'' ''^tests/functional/ca/new-build-cmd\.sh$'' ''^tests/functional/ca/nix-shell\.sh$'' ''^tests/functional/ca/post-hook\.sh$'' diff --git a/tests/functional/ca/import-derivation.sh b/tests/functional/ca/import-from-derivation.sh similarity index 55% rename from tests/functional/ca/import-derivation.sh rename to tests/functional/ca/import-from-derivation.sh index e98e0fbd0..0713619a6 100644 --- a/tests/functional/ca/import-derivation.sh +++ b/tests/functional/ca/import-from-derivation.sh @@ -2,5 +2,5 @@ source common.sh export NIX_TESTS_CA_BY_DEFAULT=1 -cd .. && source import-derivation.sh +cd .. && source import-from-derivation.sh diff --git a/tests/functional/ca/local.mk b/tests/functional/ca/local.mk index 4f86b268f..7c2fcc451 100644 --- a/tests/functional/ca/local.mk +++ b/tests/functional/ca/local.mk @@ -7,7 +7,7 @@ ca-tests := \ $(d)/duplicate-realisation-in-closure.sh \ $(d)/eval-store.sh \ $(d)/gc.sh \ - $(d)/import-derivation.sh \ + $(d)/import-from-derivation.sh \ $(d)/new-build-cmd.sh \ $(d)/nix-copy.sh \ $(d)/nix-run.sh \ diff --git a/tests/functional/ca/meson.build b/tests/functional/ca/meson.build index f682ab28f..00cf8b35f 100644 --- a/tests/functional/ca/meson.build +++ b/tests/functional/ca/meson.build @@ -16,7 +16,7 @@ suites += { 'duplicate-realisation-in-closure.sh', 'eval-store.sh', 'gc.sh', - 'import-derivation.sh', + 'import-from-derivation.sh', 'new-build-cmd.sh', 'nix-copy.sh', 'nix-run.sh', diff --git a/tests/functional/import-derivation.nix b/tests/functional/import-from-derivation.nix similarity index 100% rename from tests/functional/import-derivation.nix rename to tests/functional/import-from-derivation.nix diff --git a/tests/functional/import-derivation.sh b/tests/functional/import-from-derivation.sh similarity index 58% rename from tests/functional/import-derivation.sh rename to tests/functional/import-from-derivation.sh index 68ddcfa4a..dc6e80ed2 100755 --- a/tests/functional/import-derivation.sh +++ b/tests/functional/import-from-derivation.sh @@ -4,11 +4,11 @@ source common.sh clearStoreIfPossible -if nix-instantiate --readonly-mode ./import-derivation.nix; then +if nix-instantiate --readonly-mode ./import-from-derivation.nix; then echo "read-only evaluation of an imported derivation unexpectedly failed" exit 1 fi -outPath=$(nix-build ./import-derivation.nix --no-out-link) +outPath=$(nix-build ./import-from-derivation.nix --no-out-link) [ "$(cat "$outPath")" = FOO579 ] diff --git a/tests/functional/local.mk b/tests/functional/local.mk index f61823765..3f796291a 100644 --- a/tests/functional/local.mk +++ b/tests/functional/local.mk @@ -88,7 +88,7 @@ nix_tests = \ why-depends.sh \ derivation-json.sh \ derivation-advanced-attributes.sh \ - import-derivation.sh \ + import-from-derivation.sh \ nix_path.sh \ nars.sh \ placeholders.sh \ diff --git a/tests/functional/meson.build b/tests/functional/meson.build index 5167fa814..69b6d3194 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -157,7 +157,7 @@ suites = [ 'why-depends.sh', 'derivation-json.sh', 'derivation-advanced-attributes.sh', - 'import-derivation.sh', + 'import-from-derivation.sh', 'nix_path.sh', 'nars.sh', 'placeholders.sh', From 98db531df2527c7740abf38ee08ce8733e625519 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Tue, 17 Sep 2024 18:46:50 +0200 Subject: [PATCH 212/718] libstore-support: check that we can create the store --- tests/unit/libstore-support/tests/nix_api_store.hh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/unit/libstore-support/tests/nix_api_store.hh b/tests/unit/libstore-support/tests/nix_api_store.hh index 193b44970..8b034146b 100644 --- a/tests/unit/libstore-support/tests/nix_api_store.hh +++ b/tests/unit/libstore-support/tests/nix_api_store.hh @@ -61,6 +61,10 @@ protected: const char ** params[] = {p1, p2, p3, nullptr}; store = nix_store_open(ctx, "local", params); + if (!store) { + std::string errMsg = nix_err_msg(nullptr, ctx, nullptr); + ASSERT_NE(store, nullptr) << "Could not open store: " << errMsg; + }; } }; } From a20659f4fa5df9020c40086aa05d394e8119c30d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Tue, 17 Sep 2024 19:13:29 +0200 Subject: [PATCH 213/718] unitests: fix tmpdir when running with meson on macOS --- tests/unit/libstore-support/tests/nix_api_store.hh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/unit/libstore-support/tests/nix_api_store.hh b/tests/unit/libstore-support/tests/nix_api_store.hh index 8b034146b..b7d5c2c33 100644 --- a/tests/unit/libstore-support/tests/nix_api_store.hh +++ b/tests/unit/libstore-support/tests/nix_api_store.hh @@ -3,6 +3,7 @@ #include "tests/nix_api_util.hh" #include "file-system.hh" +#include #include "nix_api_store.h" #include "nix_api_store_internal.h" @@ -47,7 +48,9 @@ protected: if (fs::create_directory(nixDir)) break; } #else - auto tmpl = nix::defaultTempDir() + "/tests_nix-store.XXXXXX"; + // resolve any symlinks in i.e. on macOS /tmp -> /private/tmp + // because this is not allowed for a nix store. + auto tmpl = nix::absPath(std::filesystem::path(nix::defaultTempDir()) / "tests_nix-store.XXXXXX", true); nixDir = mkdtemp((char *) tmpl.c_str()); #endif From 9e335ee3b9aa2897962be368e2325fbf4c529c88 Mon Sep 17 00:00:00 2001 From: quatquatt <78693624+quatquatt@users.noreply.github.com> Date: Tue, 17 Sep 2024 22:19:56 -0400 Subject: [PATCH 214/718] docs: Provide an example of updating multiple inputs with `nix flake update` docs: Provide an example of updating multiple inputs with `nix flake update` --- src/nix/flake-update.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/nix/flake-update.md b/src/nix/flake-update.md index 63df3b12a..8b0159ff7 100644 --- a/src/nix/flake-update.md +++ b/src/nix/flake-update.md @@ -25,6 +25,19 @@ R""( → 'github:NixOS/nixpkgs/a3a3dda3bacf61e8a39258a0ed9c924eeca8e293' (2023-07-05) ``` +* Update multiple inputs: + + ```console + # nix flake update nixpkgs nixpkgs-unstable + warning: updating lock file '/home/myself/repos/testflake/flake.lock': + • Updated input 'nixpkgs': + 'github:nixos/nixpkgs/8f7492cce28977fbf8bd12c72af08b1f6c7c3e49' (2024-09-14) + → 'github:nixos/nixpkgs/086b448a5d54fd117f4dc2dee55c9f0ff461bdc1' (2024-09-16) + • Updated input 'nixpkgs-unstable': + 'github:nixos/nixpkgs/345c263f2f53a3710abe117f28a5cb86d0ba4059' (2024-09-13) + → 'github:nixos/nixpkgs/99dc8785f6a0adac95f5e2ab05cc2e1bf666d172' (2024-09-16) + ``` + * Update only a single input of a flake in a different directory: ```console From 0624cf0f59dc7363c57d472c6d2b4db07f1dcbec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Wed, 18 Sep 2024 08:45:54 +0200 Subject: [PATCH 215/718] mergify: enable merge-queue for backports --- .mergify.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mergify.yml b/.mergify.yml index 663c45d92..c297d3d5e 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -14,7 +14,7 @@ queue_rules: pull_request_rules: - name: merge using the merge queue conditions: - - base=master + - base~=master|.+-maintenance - label~=merge-queue|dependencies actions: queue: {} From 8690b6f1381a17bbe8e838d874aa23c541b1cf52 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 18 Sep 2024 12:42:20 +0200 Subject: [PATCH 216/718] Test IFD/filterSource in a chroot Relevant to #11503. --- tests/functional/import-from-derivation.nix | 25 ++++++++++------ tests/functional/import-from-derivation.sh | 33 +++++++++++++++++++-- 2 files changed, 47 insertions(+), 11 deletions(-) diff --git a/tests/functional/import-from-derivation.nix b/tests/functional/import-from-derivation.nix index 44fa9a45d..cc53451cf 100644 --- a/tests/functional/import-from-derivation.nix +++ b/tests/functional/import-from-derivation.nix @@ -1,7 +1,6 @@ with import ./config.nix; -let - +rec { bar = mkDerivation { name = "bar"; builder = builtins.toFile "builder.sh" @@ -15,12 +14,20 @@ let assert builtins.pathExists bar; import bar; -in + result = mkDerivation { + name = "foo"; + builder = builtins.toFile "builder.sh" + '' + echo -n FOO${toString value} > $out + ''; + }; -mkDerivation { - name = "foo"; - builder = builtins.toFile "builder.sh" - '' - echo -n FOO${toString value} > $out - ''; + addPath = mkDerivation { + name = "add-path"; + src = builtins.filterSource (path: type: true) result; + builder = builtins.toFile "builder.sh" + '' + echo -n BLA$(cat $src) > $out + ''; + }; } diff --git a/tests/functional/import-from-derivation.sh b/tests/functional/import-from-derivation.sh index dc6e80ed2..de94bdd00 100755 --- a/tests/functional/import-from-derivation.sh +++ b/tests/functional/import-from-derivation.sh @@ -4,11 +4,40 @@ source common.sh clearStoreIfPossible -if nix-instantiate --readonly-mode ./import-from-derivation.nix; then +if nix-instantiate --readonly-mode ./import-from-derivation.nix -A result; then echo "read-only evaluation of an imported derivation unexpectedly failed" exit 1 fi -outPath=$(nix-build ./import-from-derivation.nix --no-out-link) +outPath=$(nix-build ./import-from-derivation.nix -A result --no-out-link) [ "$(cat "$outPath")" = FOO579 ] + +# Test filterSource on the result of a derivation. +outPath2=$(nix-build ./import-from-derivation.nix -A addPath --no-out-link) +[[ "$(cat "$outPath2")" = BLAFOO579 ]] + +# Test that IFD works with a chroot store. +if canUseSandbox; then + + store2="$TEST_ROOT/store2" + store2_url="$store2?store=$NIX_STORE_DIR" + + # Copy the derivation outputs to the chroot store to avoid having + # to actually build anything, as that would fail due to the lack + # of a shell in the sandbox. We only care about testing the IFD + # semantics. + for i in bar result addPath; do + nix copy --to "$store2_url" --no-check-sigs "$(nix-build ./import-from-derivation.nix -A $i --no-out-link)" + done + + clearStore + + outPath_check=$(nix-build ./import-from-derivation.nix -A result --no-out-link --store "$store2_url") + [[ "$outPath" = "$outPath_check" ]] + [[ ! -e "$outPath" ]] + [[ -e "$store2/nix/store/$(basename $outPath)" ]] + + outPath2_check=$(nix-build ./import-from-derivation.nix -A addPath --no-out-link --store "$store2_url") + [[ "$outPath2" = "$outPath2_check" ]] +fi From 8105307f0f3caeae1c1d0bca51bee3a417e4304a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikodem=20Rabuli=C5=84ski?= Date: Mon, 6 May 2024 18:16:50 +0200 Subject: [PATCH 217/718] Always initialize curl in parent process on darwin Because of an objc quirk[1], calling curl_global_init for the first time after fork() will always result in a crash. Up until now the solution has been to set OBJC_DISABLE_INITIALIZE_FORK_SAFETY for every nix process to ignore that error. This is less than ideal because we were setting it in package.nix, which meant that running nix tests locally would fail because that variable was not set. Instead of working around that error we address it at the core - by calling curl_global_init inside initLibStore, which should mean curl will already have been initialized by the time we try to do so in a forked process. [1] https://github.com/apple-oss-distributions/objc4/blob/01edf1705fbc3ff78a423cd21e03dfc21eb4d780/runtime/objc-initialize.mm#L614-L636 (cherry-picked and adapted from https://git.lix.systems/lix-project/lix/commit/c7d97802e4f59b8621e67cf62275d6a7fde8fe62) --- misc/launchd/org.nixos.nix-daemon.plist.in | 5 ----- package.nix | 5 ----- src/libstore/globals.cc | 14 +++++++++++++- tests/functional/package.nix | 7 ------- 4 files changed, 13 insertions(+), 18 deletions(-) diff --git a/misc/launchd/org.nixos.nix-daemon.plist.in b/misc/launchd/org.nixos.nix-daemon.plist.in index e1470cf99..664608305 100644 --- a/misc/launchd/org.nixos.nix-daemon.plist.in +++ b/misc/launchd/org.nixos.nix-daemon.plist.in @@ -2,11 +2,6 @@ - EnvironmentVariables - - OBJC_DISABLE_INITIALIZE_FORK_SAFETY - YES - Label org.nixos.nix-daemon KeepAlive diff --git a/package.nix b/package.nix index 5c8d9f9b6..8ab184667 100644 --- a/package.nix +++ b/package.nix @@ -325,11 +325,6 @@ in { preInstallCheck = lib.optionalString (! doBuild) '' mkdir -p src/nix-channel - '' - # See https://github.com/NixOS/nix/issues/2523 - # Occurs often in tests since https://github.com/NixOS/nix/pull/9900 - + lib.optionalString stdenv.hostPlatform.isDarwin '' - export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES ''; separateDebugInfo = !stdenv.hostPlatform.isStatic; diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc index 8958e6997..b64e73c26 100644 --- a/src/libstore/globals.cc +++ b/src/libstore/globals.cc @@ -12,6 +12,7 @@ #include #include +#include #include #ifndef _WIN32 @@ -363,10 +364,21 @@ void initLibStore(bool loadConfig) { preloadNSS(); + /* Because of an objc quirk[1], calling curl_global_init for the first time + after fork() will always result in a crash. + Up until now the solution has been to set OBJC_DISABLE_INITIALIZE_FORK_SAFETY + for every nix process to ignore that error. + Instead of working around that error we address it at the core - + by calling curl_global_init here, which should mean curl will already + have been initialized by the time we try to do so in a forked process. + + [1] https://github.com/apple-oss-distributions/objc4/blob/01edf1705fbc3ff78a423cd21e03dfc21eb4d780/runtime/objc-initialize.mm#L614-L636 + */ + curl_global_init(CURL_GLOBAL_ALL); +#if __APPLE__ /* On macOS, don't use the per-session TMPDIR (as set e.g. by sshd). This breaks build users because they don't have access to the TMPDIR, in particular in ‘nix-store --serve’. */ -#if __APPLE__ if (hasPrefix(defaultTempDir(), "/var/folders/")) unsetenv("TMPDIR"); #endif diff --git a/tests/functional/package.nix b/tests/functional/package.nix index 277711123..675cefa64 100644 --- a/tests/functional/package.nix +++ b/tests/functional/package.nix @@ -95,13 +95,6 @@ mkMesonDerivation (finalAttrs: { "--print-errorlogs" ]; - preCheck = - # See https://github.com/NixOS/nix/issues/2523 - # Occurs often in tests since https://github.com/NixOS/nix/pull/9900 - lib.optionalString stdenv.hostPlatform.isDarwin '' - export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES - ''; - doCheck = true; installPhase = '' From 2b7642632e5d60c6c191a70a5c8cf68903c66140 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Wed, 18 Sep 2024 08:39:31 +0200 Subject: [PATCH 218/718] devShell: increase priority of clang-tools Before we would get the unwrapped version of clang-tools from clang itself, which doesn't quite work. --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 5ca9c1a45..cbcf10021 100644 --- a/flake.nix +++ b/flake.nix @@ -370,7 +370,7 @@ # TODO: Remove the darwin check once # https://github.com/NixOS/nixpkgs/pull/291814 is available ++ lib.optional (stdenv.cc.isClang && !stdenv.buildPlatform.isDarwin) pkgs.buildPackages.bear - ++ lib.optional (stdenv.cc.isClang && stdenv.hostPlatform == stdenv.buildPlatform) pkgs.buildPackages.clang-tools; + ++ lib.optional (stdenv.cc.isClang && stdenv.hostPlatform == stdenv.buildPlatform) (lib.hiPrio pkgs.buildPackages.clang-tools); buildInputs = attrs.buildInputs or [] ++ [ From f0a4f1908744fc9ad3e2ba3ff6c60cb2d65a56d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Wed, 18 Sep 2024 15:39:08 +0200 Subject: [PATCH 219/718] add description + example for nix flake archive Update src/nix/flake-archive.md Update src/nix/flake-archive.md --- src/nix/flake-archive.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/nix/flake-archive.md b/src/nix/flake-archive.md index 85bbeeb16..18c735b11 100644 --- a/src/nix/flake-archive.md +++ b/src/nix/flake-archive.md @@ -22,8 +22,20 @@ R""( # nix flake archive --json --dry-run nixops ``` +* Upload all flake inputs to a different machine for remote evaluation + + ``` + # nix flake archive --to ssh://some-machine + ``` + + On the remote machine the flake can then be accessed via its store path. That's computed like this: + + ``` + # nix flake metadata --json | jq -r '.path' + ``` + # Description -FIXME +Copy a flake and all its inputs to a store. This is useful i.e. to evaluate flakes on a different host. )"" From d772a8b3dc41f689c052662778f488bef44ded49 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 18 Sep 2024 18:05:08 +0200 Subject: [PATCH 220/718] shellcheck --- tests/functional/import-from-derivation.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/functional/import-from-derivation.sh b/tests/functional/import-from-derivation.sh index de94bdd00..c5ed88a1d 100755 --- a/tests/functional/import-from-derivation.sh +++ b/tests/functional/import-from-derivation.sh @@ -28,7 +28,7 @@ if canUseSandbox; then # of a shell in the sandbox. We only care about testing the IFD # semantics. for i in bar result addPath; do - nix copy --to "$store2_url" --no-check-sigs "$(nix-build ./import-from-derivation.nix -A $i --no-out-link)" + nix copy --to "$store2_url" --no-check-sigs "$(nix-build ./import-from-derivation.nix -A "$i" --no-out-link)" done clearStore @@ -36,7 +36,7 @@ if canUseSandbox; then outPath_check=$(nix-build ./import-from-derivation.nix -A result --no-out-link --store "$store2_url") [[ "$outPath" = "$outPath_check" ]] [[ ! -e "$outPath" ]] - [[ -e "$store2/nix/store/$(basename $outPath)" ]] + [[ -e "$store2/nix/store/$(basename "$outPath")" ]] outPath2_check=$(nix-build ./import-from-derivation.nix -A addPath --no-out-link --store "$store2_url") [[ "$outPath2" = "$outPath2_check" ]] From a673084733885c2a4e3126b0eef2a2c1c19e5237 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 18 Sep 2024 19:06:48 +0200 Subject: [PATCH 221/718] Fix tests --- tests/functional/import-from-derivation.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/functional/import-from-derivation.sh b/tests/functional/import-from-derivation.sh index c5ed88a1d..83ef92a6f 100755 --- a/tests/functional/import-from-derivation.sh +++ b/tests/functional/import-from-derivation.sh @@ -2,6 +2,8 @@ source common.sh +TODO_NixOS + clearStoreIfPossible if nix-instantiate --readonly-mode ./import-from-derivation.nix -A result; then @@ -13,6 +15,11 @@ outPath=$(nix-build ./import-from-derivation.nix -A result --no-out-link) [ "$(cat "$outPath")" = FOO579 ] +# FIXME: the next tests are broken on CA. +if [[ -n "${NIX_TESTS_CA_BY_DEFAULT:-}" ]]; then + exit 0 +fi + # Test filterSource on the result of a derivation. outPath2=$(nix-build ./import-from-derivation.nix -A addPath --no-out-link) [[ "$(cat "$outPath2")" = BLAFOO579 ]] From 04a47e93f611f08df9f0cadad761a8f5268fff1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Wed, 18 Sep 2024 20:32:49 +0200 Subject: [PATCH 222/718] tests/functional/shell: fix test in macOS devshell --- tests/functional/shell.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/functional/shell.sh b/tests/functional/shell.sh index c2ac3b24d..04a03eef5 100755 --- a/tests/functional/shell.sh +++ b/tests/functional/shell.sh @@ -31,11 +31,13 @@ env > $TEST_ROOT/expected-env nix shell -f shell-hello.nix hello -c env > $TEST_ROOT/actual-env # Remove/reset variables we expect to be different. # - PATH is modified by nix shell +# - we unset TMPDIR on macOS if it contains /var/folders # - _ is set by bash and is expectedf to differ because it contains the original command # - __CF_USER_TEXT_ENCODING is set by macOS and is beyond our control sed -i \ -e 's/PATH=.*/PATH=.../' \ -e 's/_=.*/_=.../' \ + -e '/^TMPDIR=\/var\/folders\/.*/d' \ -e '/^__CF_USER_TEXT_ENCODING=.*$/d' \ $TEST_ROOT/expected-env $TEST_ROOT/actual-env sort $TEST_ROOT/expected-env > $TEST_ROOT/expected-env.sorted From 5c87c40a5eb11833193d9364f84e25464e4d1044 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 18 Sep 2024 22:42:44 +0200 Subject: [PATCH 223/718] Use close_range when available This fixes the FreeBSD build of nix-util --- configure.ac | 2 +- src/libutil/meson.build | 1 + src/libutil/unix/file-descriptor.cc | 5 ++++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 5c22ed176..198198dea 100644 --- a/configure.ac +++ b/configure.ac @@ -86,7 +86,7 @@ static char buf[1024];]], AC_LANG_POP(C++) -AC_CHECK_FUNCS([statvfs pipe2]) +AC_CHECK_FUNCS([statvfs pipe2 close_range]) # Check for lutimes, optionally used for changing the mtime of diff --git a/src/libutil/meson.build b/src/libutil/meson.build index 797dcae6d..7a058b29c 100644 --- a/src/libutil/meson.build +++ b/src/libutil/meson.build @@ -28,6 +28,7 @@ subdir('build-utils-meson/subprojects') # HAVE_LUTIMES 1`. The `#define` is unconditional, 0 for not found and 1 # for found. One therefore uses it with `#if` not `#ifdef`. check_funcs = [ + 'close_range', # Optionally used for changing the mtime of symlinks. 'lutimes', # Optionally used for creating pipes on Unix diff --git a/src/libutil/unix/file-descriptor.cc b/src/libutil/unix/file-descriptor.cc index f867199c0..2c1126e09 100644 --- a/src/libutil/unix/file-descriptor.cc +++ b/src/libutil/unix/file-descriptor.cc @@ -121,10 +121,13 @@ void Pipe::create() ////////////////////////////////////////////////////////////////////// #if __linux__ || __FreeBSD__ -// In future we can use a syscall wrapper, but at the moment musl and older glibc version don't support it. static int unix_close_range(unsigned int first, unsigned int last, int flags) { +#if !HAVE_CLOSE_RANGE return syscall(SYS_close_range, first, last, (unsigned int)flags); +#else + return close_range(first, last, flags); +#endif } #endif From c75907e47bf653158aa5773112455949cc3e3163 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 18 Sep 2024 23:05:13 +0200 Subject: [PATCH 224/718] Revert "tests.installer: Load profile with -o unset" I must have made a mistake while testing this, because nounset does not work on any of the distributions. This reverts commit 2f0db04da08e67f29577c27fae3c0eb758fc0879. --- tests/installer/default.nix | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/installer/default.nix b/tests/installer/default.nix index 7c82045ad..4aed6eae4 100644 --- a/tests/installer/default.nix +++ b/tests/installer/default.nix @@ -217,16 +217,10 @@ let $ssh < Date: Thu, 19 Sep 2024 00:00:17 +0200 Subject: [PATCH 225/718] nix-util / meson: Add -latomic on arm I couldn't get the test program to work correctly after many attempts, so let's just unblock this without making it perfect. --- src/libutil/meson.build | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/libutil/meson.build b/src/libutil/meson.build index 797dcae6d..482997096 100644 --- a/src/libutil/meson.build +++ b/src/libutil/meson.build @@ -50,6 +50,14 @@ endforeach subdir('build-utils-meson/threads') +# Check if -latomic is needed +# This is needed for std::atomic on some platforms +# We did not manage to test this reliably on all platforms, so we hardcode +# it for now. +if host_machine.cpu_family() == 'arm' + deps_other += cxx.find_library('atomic') +endif + if host_machine.system() == 'windows' socket = cxx.find_library('ws2_32') deps_other += socket From 97fffd8765d61571577b621d14b8a03740367458 Mon Sep 17 00:00:00 2001 From: Noam Yorav-Raphael Date: Thu, 19 Sep 2024 07:20:04 +0300 Subject: [PATCH 226/718] nix-profile.sh.in: fix envvar condition --- scripts/nix-profile.sh.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/nix-profile.sh.in b/scripts/nix-profile.sh.in index 3d0e498f4..2d6bf6e95 100644 --- a/scripts/nix-profile.sh.in +++ b/scripts/nix-profile.sh.in @@ -1,9 +1,9 @@ # This file is tested by tests/installer/default.nix. -if [ -n "$HOME" ] && [ -n "$USER" ]; then +if [ -n "${HOME-}" ] && [ -n "${USER-}" ]; then # Set up the per-user profile. - if [ -n "$NIX_STATE_HOME" ]; then + if [ -n "${NIX_STATE_HOME-}" ]; then NIX_LINK="$NIX_STATE_HOME/profile" else NIX_LINK="$HOME/.nix-profile" From 0c2fdd2f3c0f04bef4b5c74fbb02a5f8227c07df Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 19 Sep 2024 19:16:31 +0200 Subject: [PATCH 227/718] Fix missing GC root in zipAttrsWith My SNAFU was that I assumed that all the `Value *`s we put in `attrsSeen` are already reachable (which they are), but I forgot about the `elems` pointer in `ListBuilder`. Fixes #11547. --- src/libexpr/primops.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 9de8ff599..ed1597e5d 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -3136,7 +3136,7 @@ static void prim_zipAttrsWith(EvalState & state, const PosIdx pos, Value * * arg std::optional list; }; - std::map attrsSeen; + std::map, traceable_allocator>> attrsSeen; state.forceFunction(*args[0], pos, "while evaluating the first argument passed to builtins.zipAttrsWith"); state.forceList(*args[1], pos, "while evaluating the second argument passed to builtins.zipAttrsWith"); From 4449b0da744c32cb9cbb06b661a5f5df4444497a Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 19 Sep 2024 19:52:47 +0200 Subject: [PATCH 228/718] Use HAVE_BOEHMGC Co-authored-by: Robert Hensing --- src/libexpr/primops.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index ed1597e5d..8d53a1dfd 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -3136,7 +3136,11 @@ static void prim_zipAttrsWith(EvalState & state, const PosIdx pos, Value * * arg std::optional list; }; +#if HAVE_BOEHMGC std::map, traceable_allocator>> attrsSeen; +#else + std::map attrsSeen; +#endif state.forceFunction(*args[0], pos, "while evaluating the first argument passed to builtins.zipAttrsWith"); state.forceList(*args[1], pos, "while evaluating the second argument passed to builtins.zipAttrsWith"); From b9f78abb7ff5e9e01ced5b94805ccaa563f46bc6 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 19 Sep 2024 20:07:04 +0200 Subject: [PATCH 229/718] Alias traceable_allocator to std::allocator when building without GC This allows us to get rid of a bunch of #ifdefs. --- src/libcmd/command.cc | 7 +------ src/libexpr/eval.cc | 4 ---- src/libexpr/eval.hh | 14 +------------- src/libexpr/gc-small-vector.hh | 17 ++--------------- src/libexpr/get-drvs.hh | 4 ---- src/libexpr/primops.cc | 4 ---- src/libexpr/value.hh | 10 ++++------ 7 files changed, 8 insertions(+), 52 deletions(-) diff --git a/src/libcmd/command.cc b/src/libcmd/command.cc index 67fef1909..6d8bfc19b 100644 --- a/src/libcmd/command.cc +++ b/src/libcmd/command.cc @@ -127,14 +127,9 @@ ref EvalCommand::getEvalState() { if (!evalState) { evalState = - #if HAVE_BOEHMGC std::allocate_shared( traceable_allocator(), - #else - std::make_shared( - #endif - lookupPath, getEvalStore(), fetchSettings, evalSettings, getStore()) - ; + lookupPath, getEvalStore(), fetchSettings, evalSettings, getStore()); evalState->repair = repair; diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 2420f15c1..be3bbda22 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -99,11 +99,7 @@ static const char * makeImmutableString(std::string_view s) RootValue allocRootValue(Value * v) { -#if HAVE_BOEHMGC return std::allocate_shared(traceable_allocator(), v); -#else - return std::make_shared(v); -#endif } // Pretty print types for assertion errors diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index da9dd2087..f7ed6be83 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -139,11 +139,7 @@ struct Constant bool impureOnly = false; }; -#if HAVE_BOEHMGC - typedef std::map, traceable_allocator > > ValMap; -#else - typedef std::map ValMap; -#endif +typedef std::map, traceable_allocator > > ValMap; typedef std::unordered_map DocCommentMap; @@ -329,21 +325,13 @@ private: /** * A cache from path names to parse trees. */ -#if HAVE_BOEHMGC typedef std::unordered_map, std::equal_to, traceable_allocator>> FileParseCache; -#else - typedef std::unordered_map FileParseCache; -#endif FileParseCache fileParseCache; /** * A cache from path names to values. */ -#if HAVE_BOEHMGC typedef std::unordered_map, std::equal_to, traceable_allocator>> FileEvalCache; -#else - typedef std::unordered_map FileEvalCache; -#endif FileEvalCache fileEvalCache; /** diff --git a/src/libexpr/gc-small-vector.hh b/src/libexpr/gc-small-vector.hh index 7f4f08fc7..8330dd2dc 100644 --- a/src/libexpr/gc-small-vector.hh +++ b/src/libexpr/gc-small-vector.hh @@ -2,28 +2,15 @@ #include -#if HAVE_BOEHMGC - -#include -#include -#include - -#endif +#include "value.hh" namespace nix { -struct Value; - /** * A GC compatible vector that may used a reserved portion of `nItems` on the stack instead of allocating on the heap. */ -#if HAVE_BOEHMGC template using SmallVector = boost::container::small_vector>; -#else -template -using SmallVector = boost::container::small_vector; -#endif /** * A vector of value pointers. See `SmallVector`. @@ -39,4 +26,4 @@ using SmallValueVector = SmallVector; template using SmallTemporaryValueVector = SmallVector; -} \ No newline at end of file +} diff --git a/src/libexpr/get-drvs.hh b/src/libexpr/get-drvs.hh index db3eedb05..e4e277af8 100644 --- a/src/libexpr/get-drvs.hh +++ b/src/libexpr/get-drvs.hh @@ -83,11 +83,7 @@ public: }; -#if HAVE_BOEHMGC typedef std::list> PackageInfos; -#else -typedef std::list PackageInfos; -#endif /** diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 8d53a1dfd..ed1597e5d 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -3136,11 +3136,7 @@ static void prim_zipAttrsWith(EvalState & state, const PosIdx pos, Value * * arg std::optional list; }; -#if HAVE_BOEHMGC std::map, traceable_allocator>> attrsSeen; -#else - std::map attrsSeen; -#endif state.forceFunction(*args[0], pos, "while evaluating the first argument passed to builtins.zipAttrsWith"); state.forceList(*args[1], pos, "while evaluating the second argument passed to builtins.zipAttrsWith"); diff --git a/src/libexpr/value.hh b/src/libexpr/value.hh index f68befe0e..087406965 100644 --- a/src/libexpr/value.hh +++ b/src/libexpr/value.hh @@ -12,7 +12,11 @@ #if HAVE_BOEHMGC #include +#else +template +using traceable_allocator = std::allocator; #endif + #include namespace nix { @@ -498,15 +502,9 @@ void Value::mkBlackhole() } -#if HAVE_BOEHMGC typedef std::vector> ValueVector; typedef std::unordered_map, std::equal_to, traceable_allocator>> ValueMap; typedef std::map, traceable_allocator>> ValueVectorMap; -#else -typedef std::vector ValueVector; -typedef std::unordered_map ValueMap; -typedef std::map ValueVectorMap; -#endif /** From 31d408c351e5a98b8016e1fb6ca8348814145d54 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 19 Sep 2024 20:45:13 +0200 Subject: [PATCH 230/718] Alias gc_allocator --- src/libexpr/primops.cc | 4 ---- src/libexpr/value.hh | 3 +++ 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index ed1597e5d..7b6f222a8 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -631,11 +631,7 @@ struct CompareValues }; -#if HAVE_BOEHMGC typedef std::list> ValueList; -#else -typedef std::list ValueList; -#endif static Bindings::const_iterator getAttr( diff --git a/src/libexpr/value.hh b/src/libexpr/value.hh index 087406965..a837ac133 100644 --- a/src/libexpr/value.hh +++ b/src/libexpr/value.hh @@ -15,6 +15,9 @@ #else template using traceable_allocator = std::allocator; + +template +using gc_allocator = std::allocator; #endif #include From 589d8f1f2be4c036f459288e4a90be30371bbf41 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 19 Sep 2024 20:54:30 +0200 Subject: [PATCH 231/718] Move GC-related definitions to eval-gc.hh --- src/libcmd/repl.cc | 5 ----- src/libexpr-c/nix_api_external.cc | 6 ------ src/libexpr-c/nix_api_value.cc | 6 ------ src/libexpr/eval-gc.hh | 18 ++++++++++++++++++ src/libexpr/eval.cc | 11 ----------- src/libexpr/value.hh | 11 +---------- src/nix/main.cc | 1 - 7 files changed, 19 insertions(+), 39 deletions(-) diff --git a/src/libcmd/repl.cc b/src/libcmd/repl.cc index 46b6fbadc..531038321 100644 --- a/src/libcmd/repl.cc +++ b/src/libcmd/repl.cc @@ -29,11 +29,6 @@ #include "ref.hh" #include "value.hh" -#if HAVE_BOEHMGC -#define GC_INCLUDE_NEW -#include -#endif - #include "strings.hh" namespace nix { diff --git a/src/libexpr-c/nix_api_external.cc b/src/libexpr-c/nix_api_external.cc index fa78eb5df..d673bcb0b 100644 --- a/src/libexpr-c/nix_api_external.cc +++ b/src/libexpr-c/nix_api_external.cc @@ -14,12 +14,6 @@ #include -#if HAVE_BOEHMGC -# include "gc/gc.h" -# define GC_INCLUDE_NEW 1 -# include "gc_cpp.h" -#endif - void nix_set_string_return(nix_string_return * str, const char * c) { str->str = c; diff --git a/src/libexpr-c/nix_api_value.cc b/src/libexpr-c/nix_api_value.cc index fa2a9cbe2..bae078d31 100644 --- a/src/libexpr-c/nix_api_value.cc +++ b/src/libexpr-c/nix_api_value.cc @@ -14,12 +14,6 @@ #include "nix_api_value.h" #include "value/context.hh" -#if HAVE_BOEHMGC -# include "gc/gc.h" -# define GC_INCLUDE_NEW 1 -# include "gc_cpp.h" -#endif - // Internal helper functions to check [in] and [out] `Value *` parameters static const nix::Value & check_value_not_null(const nix_value * value) { diff --git a/src/libexpr/eval-gc.hh b/src/libexpr/eval-gc.hh index 005175eb7..584365844 100644 --- a/src/libexpr/eval-gc.hh +++ b/src/libexpr/eval-gc.hh @@ -3,6 +3,24 @@ #include +#if HAVE_BOEHMGC + +# define GC_INCLUDE_NEW + +# include +# include +# include + +#else + +template +using traceable_allocator = std::allocator; + +template +using gc_allocator = std::allocator; + +#endif + namespace nix { /** diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index be3bbda22..5952ebe41 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -1,5 +1,4 @@ #include "eval.hh" -#include "eval-gc.hh" #include "eval-settings.hh" #include "primops.hh" #include "print-options.hh" @@ -39,16 +38,6 @@ # include #endif -#if HAVE_BOEHMGC - -# define GC_INCLUDE_NEW - -# include -# include -# include - -#endif - #include "strings-inline.hh" using json = nlohmann::json; diff --git a/src/libexpr/value.hh b/src/libexpr/value.hh index a837ac133..0ffe74dab 100644 --- a/src/libexpr/value.hh +++ b/src/libexpr/value.hh @@ -4,22 +4,13 @@ #include #include +#include "eval-gc.hh" #include "symbol-table.hh" #include "value/context.hh" #include "source-path.hh" #include "print-options.hh" #include "checked-arithmetic.hh" -#if HAVE_BOEHMGC -#include -#else -template -using traceable_allocator = std::allocator; - -template -using gc_allocator = std::allocator; -#endif - #include namespace nix { diff --git a/src/nix/main.cc b/src/nix/main.cc index 34de79ac8..7a9516d5e 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -2,7 +2,6 @@ #include "current-process.hh" #include "command.hh" #include "common-args.hh" -#include "eval-gc.hh" #include "eval.hh" #include "eval-settings.hh" #include "globals.hh" From 2f4a7a830135e52827b112e4f46a0f46a78dac64 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 19 Sep 2024 21:03:59 +0200 Subject: [PATCH 232/718] Add a few more aliases --- src/libcmd/repl.cc | 2 -- src/libexpr/eval-gc.hh | 7 +++++++ src/libexpr/eval.cc | 8 -------- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/libcmd/repl.cc b/src/libcmd/repl.cc index 531038321..940b16dfd 100644 --- a/src/libcmd/repl.cc +++ b/src/libcmd/repl.cc @@ -57,9 +57,7 @@ enum class ProcessLineResult { struct NixRepl : AbstractNixRepl , detail::ReplCompleterMixin - #if HAVE_BOEHMGC , gc - #endif { size_t debugTraceIndex; diff --git a/src/libexpr/eval-gc.hh b/src/libexpr/eval-gc.hh index 584365844..8f492c56d 100644 --- a/src/libexpr/eval-gc.hh +++ b/src/libexpr/eval-gc.hh @@ -13,12 +13,19 @@ #else +/* Some dummy aliases for Boehm GC definitions to reduce the number of + #ifdefs. */ + template using traceable_allocator = std::allocator; template using gc_allocator = std::allocator; +#define GC_MALLOC_ATOMIC std::malloc +#define GC_STRDUP std::strdup +struct gc { }; + #endif namespace nix { diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 5952ebe41..379839ce3 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -47,11 +47,7 @@ namespace nix { static char * allocString(size_t size) { char * t; -#if HAVE_BOEHMGC t = (char *) GC_MALLOC_ATOMIC(size); -#else - t = (char *) malloc(size); -#endif if (!t) throw std::bad_alloc(); return t; } @@ -60,11 +56,7 @@ static char * allocString(size_t size) static char * dupString(const char * s) { char * t; -#if HAVE_BOEHMGC t = GC_STRDUP(s); -#else - t = strdup(s); -#endif if (!t) throw std::bad_alloc(); return t; } From b2bb92ef09e380c3a706efe01ef68d7c7803f1aa Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 19 Sep 2024 22:09:49 +0200 Subject: [PATCH 233/718] Formatting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jörg Thalheim --- src/libexpr/eval-gc.hh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/libexpr/eval-gc.hh b/src/libexpr/eval-gc.hh index 8f492c56d..1be9ff65b 100644 --- a/src/libexpr/eval-gc.hh +++ b/src/libexpr/eval-gc.hh @@ -22,9 +22,10 @@ using traceable_allocator = std::allocator; template using gc_allocator = std::allocator; -#define GC_MALLOC_ATOMIC std::malloc -#define GC_STRDUP std::strdup -struct gc { }; +# define GC_MALLOC_ATOMIC std::malloc +# define GC_STRDUP std::strdup +struct gc +{}; #endif From 088569463b9de59ce7928ca5a9b4a2413533444a Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 20 Sep 2024 15:01:32 +0200 Subject: [PATCH 234/718] Fix build without GC --- src/libexpr/eval-gc.hh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libexpr/eval-gc.hh b/src/libexpr/eval-gc.hh index 1be9ff65b..3b420e418 100644 --- a/src/libexpr/eval-gc.hh +++ b/src/libexpr/eval-gc.hh @@ -23,7 +23,8 @@ template using gc_allocator = std::allocator; # define GC_MALLOC_ATOMIC std::malloc -# define GC_STRDUP std::strdup +# define GC_STRDUP strdup + struct gc {}; From ec47133be343bfdf2aad93dc75b5943f5667f1b0 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 20 Sep 2024 15:08:45 +0200 Subject: [PATCH 235/718] Fix warning --- src/libexpr-c/nix_api_expr.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/libexpr-c/nix_api_expr.cc b/src/libexpr-c/nix_api_expr.cc index 8f21d7022..333e99460 100644 --- a/src/libexpr-c/nix_api_expr.cc +++ b/src/libexpr-c/nix_api_expr.cc @@ -16,8 +16,6 @@ #if HAVE_BOEHMGC # include -# define GC_INCLUDE_NEW 1 -# include "gc_cpp.h" #endif nix_err nix_libexpr_init(nix_c_context * context) From d0c351bf4392e76d81b282aaaafdf2c2e0a64c69 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Fri, 20 Sep 2024 10:41:45 -0400 Subject: [PATCH 236/718] Revert "base64Decode: clearer error message when an invalid character is detected" We have a safer way of doing this. This reverts commit dc3ccf02bfd4d359228b54f5c24ae2b6caf6428e. --- src/libutil/util.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 6f7a4299d..db3ed1ddf 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -243,9 +243,8 @@ std::string base64Decode(std::string_view s) if (c == '\n') continue; char digit = base64DecodeChars[(unsigned char) c]; - if (digit == npos) { - throw Error("invalid character in Base64 string: '%c' in '%s'", c, s.data()); - } + if (digit == npos) + throw Error("invalid character in Base64 string: '%c'", c); bits += 6; d = d << 6 | digit; From da332d678e7ad5b544eb6283d3c8c8da9e38ba4b Mon Sep 17 00:00:00 2001 From: Ryan Hendrickson Date: Fri, 20 Sep 2024 15:57:36 -0400 Subject: [PATCH 237/718] libexpr: deprecate the bogus "or"-as-variable As a prelude to making "or" work like a normal variable, emit a warning any time the "fn or" production is used in a context that will change how it is parsed when that production is refactored. In detail: in the future, OR_KW will be moved to expr_simple, and the cursed ExprCall production that is currently part of the expr_select nonterminal will be generated "normally" in expr_app instead. Any productions that accept an expr_select will be affected, except for the expr_app nonterminal itself (because, while expr_app has a production accepting a bare expr_select, its other production will continue to accept "fn or" expressions). So all we need to do is emit an appropriate warning when an expr_simple representing a cursed ExprCall is accepted in one of those productions without first going through expr_app. As the warning message describes, users can suppress the warning by wrapping their problematic "fn or" expressions in parentheses. For example, "f g or" can be made future-proof by rewriting it as "f (g or)"; similarly "[ x y or ]" can be rewritten as "[ x (y or) ]", etc. The parentheses preserve the current grouping behavior, as in the future "f g or" will be parsed as "(f g) or", just like "f g anything-else" is grouped. (Mechanically, this suppresses the warning because the problem ExprCalls go through the "expr_app : expr_select" production, which resets the cursed status on the ExprCall.) --- src/libexpr/nixexpr.cc | 28 +++++++++++++++++++ src/libexpr/nixexpr.hh | 12 +++++++- src/libexpr/parser.y | 23 ++++++++++----- .../eval-okay-deprecate-cursed-or.err.exp | 12 ++++++++ .../lang/eval-okay-deprecate-cursed-or.exp | 1 + .../lang/eval-okay-deprecate-cursed-or.nix | 11 ++++++++ 6 files changed, 79 insertions(+), 8 deletions(-) create mode 100644 tests/functional/lang/eval-okay-deprecate-cursed-or.err.exp create mode 100644 tests/functional/lang/eval-okay-deprecate-cursed-or.exp create mode 100644 tests/functional/lang/eval-okay-deprecate-cursed-or.nix diff --git a/src/libexpr/nixexpr.cc b/src/libexpr/nixexpr.cc index dbc74faf9..063ff0753 100644 --- a/src/libexpr/nixexpr.cc +++ b/src/libexpr/nixexpr.cc @@ -663,4 +663,32 @@ std::string DocComment::getInnerText(const PosTable & positions) const { return docStr; } + + +/* ‘Cursed or’ handling. + * + * In parser.y, every use of expr_select in a production must call one of the + * two below functions. + * + * To be removed by https://github.com/NixOS/nix/pull/11121 + */ + +void ExprCall::resetCursedOr() +{ + cursedOrEndPos.reset(); +} + +void ExprCall::warnIfCursedOr(const SymbolTable & symbols, const PosTable & positions) +{ + if (cursedOrEndPos.has_value()) { + std::ostringstream out; + out << "at " << positions[pos] << ": " + "This expression uses `or` as an identifier in a way that will change in a future Nix release.\n" + "Wrap this entire expression in parentheses to preserve its current meaning:\n" + " (" << positions[pos].getSnippetUpTo(positions[*cursedOrEndPos]).value_or("could not read expression") << ")\n" + "Give feedback at https://github.com/NixOS/nix/pull/11121"; + warn(out.str()); + } +} + } diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh index 7868834f1..bdf4e214a 100644 --- a/src/libexpr/nixexpr.hh +++ b/src/libexpr/nixexpr.hh @@ -96,6 +96,10 @@ struct Expr virtual void setName(Symbol name); virtual void setDocComment(DocComment docComment) { }; virtual PosIdx getPos() const { return noPos; } + + // These are temporary methods to be used only in parser.y + virtual void resetCursedOr() { }; + virtual void warnIfCursedOr(const SymbolTable & symbols, const PosTable & positions) { }; }; #define COMMON_METHODS \ @@ -354,10 +358,16 @@ struct ExprCall : Expr Expr * fun; std::vector args; PosIdx pos; + std::optional cursedOrEndPos; // used during parsing to warn about https://github.com/NixOS/nix/issues/11118 ExprCall(const PosIdx & pos, Expr * fun, std::vector && args) - : fun(fun), args(args), pos(pos) + : fun(fun), args(args), pos(pos), cursedOrEndPos({}) + { } + ExprCall(const PosIdx & pos, Expr * fun, std::vector && args, PosIdx && cursedOrEndPos) + : fun(fun), args(args), pos(pos), cursedOrEndPos(cursedOrEndPos) { } PosIdx getPos() const override { return pos; } + virtual void resetCursedOr() override; + virtual void warnIfCursedOr(const SymbolTable & symbols, const PosTable & positions) override; COMMON_METHODS }; diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index a79abbf16..944c7b1af 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -264,19 +264,28 @@ expr_op ; expr_app - : expr_app expr_select { $$ = makeCall(CUR_POS, $1, $2); } - | expr_select + : expr_app expr_select { $$ = makeCall(CUR_POS, $1, $2); $2->warnIfCursedOr(state->symbols, state->positions); } + | /* Once a ‘cursed or’ reaches this nonterminal, it is no longer cursed, + because the uncursed parse would also produce an expr_app. But we need + to remove the cursed status in order to prevent valid things like + `f (g or)` from triggering the warning. */ + expr_select { $$ = $1; $$->resetCursedOr(); } ; expr_select : expr_simple '.' attrpath { $$ = new ExprSelect(CUR_POS, $1, std::move(*$3), nullptr); delete $3; } | expr_simple '.' attrpath OR_KW expr_select - { $$ = new ExprSelect(CUR_POS, $1, std::move(*$3), $5); delete $3; } - | /* Backwards compatibility: because Nixpkgs has a rarely used - function named ‘or’, allow stuff like ‘map or [...]’. */ + { $$ = new ExprSelect(CUR_POS, $1, std::move(*$3), $5); delete $3; $5->warnIfCursedOr(state->symbols, state->positions); } + | /* Backwards compatibility: because Nixpkgs has a function named ‘or’, + allow stuff like ‘map or [...]’. This production is problematic (see + https://github.com/NixOS/nix/issues/11118) and will be refactored in the + future by treating `or` as a regular identifier. The refactor will (in + very rare cases, we think) change the meaning of expressions, so we mark + the ExprCall with data (establishing that it is a ‘cursed or’) that can + be used to emit a warning when an affected expression is parsed. */ expr_simple OR_KW - { $$ = new ExprCall(CUR_POS, $1, {new ExprVar(CUR_POS, state->s.or_)}); } + { $$ = new ExprCall(CUR_POS, $1, {new ExprVar(CUR_POS, state->s.or_)}, state->positions.add(state->origin, @$.endOffset)); } | expr_simple ; @@ -472,7 +481,7 @@ string_attr ; expr_list - : expr_list expr_select { $$ = $1; $1->elems.push_back($2); /* !!! dangerous */ } + : expr_list expr_select { $$ = $1; $1->elems.push_back($2); /* !!! dangerous */; $2->warnIfCursedOr(state->symbols, state->positions); } | { $$ = new ExprList; } ; diff --git a/tests/functional/lang/eval-okay-deprecate-cursed-or.err.exp b/tests/functional/lang/eval-okay-deprecate-cursed-or.err.exp new file mode 100644 index 000000000..4a656827a --- /dev/null +++ b/tests/functional/lang/eval-okay-deprecate-cursed-or.err.exp @@ -0,0 +1,12 @@ +warning: at /pwd/lang/eval-okay-deprecate-cursed-or.nix:3:47: This expression uses `or` as an identifier in a way that will change in a future Nix release. +Wrap this entire expression in parentheses to preserve its current meaning: + ((x: x) or) +Give feedback at https://github.com/NixOS/nix/pull/11121 +warning: at /pwd/lang/eval-okay-deprecate-cursed-or.nix:4:39: This expression uses `or` as an identifier in a way that will change in a future Nix release. +Wrap this entire expression in parentheses to preserve its current meaning: + ((x: x + 1) or) +Give feedback at https://github.com/NixOS/nix/pull/11121 +warning: at /pwd/lang/eval-okay-deprecate-cursed-or.nix:5:44: This expression uses `or` as an identifier in a way that will change in a future Nix release. +Wrap this entire expression in parentheses to preserve its current meaning: + ((x: x) or) +Give feedback at https://github.com/NixOS/nix/pull/11121 diff --git a/tests/functional/lang/eval-okay-deprecate-cursed-or.exp b/tests/functional/lang/eval-okay-deprecate-cursed-or.exp new file mode 100644 index 000000000..573541ac9 --- /dev/null +++ b/tests/functional/lang/eval-okay-deprecate-cursed-or.exp @@ -0,0 +1 @@ +0 diff --git a/tests/functional/lang/eval-okay-deprecate-cursed-or.nix b/tests/functional/lang/eval-okay-deprecate-cursed-or.nix new file mode 100644 index 000000000..a4f9e747f --- /dev/null +++ b/tests/functional/lang/eval-okay-deprecate-cursed-or.nix @@ -0,0 +1,11 @@ +let + # These are cursed and should warn + cursed0 = builtins.length (let or = 1; in [ (x: x) or ]); + cursed1 = let or = 1; in (x: x * 2) (x: x + 1) or; + cursed2 = let or = 1; in { a = 2; }.a or (x: x) or; + + # These are uses of `or` as an identifier that are not cursed + allowed0 = let or = (x: x); in map or []; + allowed1 = let f = (x: x); or = f; in f (f or); +in +0 From c04bc17a5a0fdcb725a11ef6541f94730112e7b6 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 23 Sep 2024 15:09:44 +0200 Subject: [PATCH 238/718] builtin:fetchurl: Enable TLS verification This is better for privacy and to avoid leaking netrc credentials in a MITM attack, but also the assumption that we check the hash no longer holds in some cases (in particular for impure derivations). Partially reverts https://github.com/NixOS/nix/commit/5db358d4d78aea7204a8f22c5bf2a309267ee038. --- src/libstore/builtins/fetchurl.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/libstore/builtins/fetchurl.cc b/src/libstore/builtins/fetchurl.cc index b9dfeba2f..f33060c33 100644 --- a/src/libstore/builtins/fetchurl.cc +++ b/src/libstore/builtins/fetchurl.cc @@ -38,10 +38,7 @@ void builtinFetchurl( auto source = sinkToSource([&](Sink & sink) { - /* No need to do TLS verification, because we check the hash of - the result anyway. */ FileTransferRequest request(url); - request.verifyTLS = false; request.decompress = false; auto decompressor = makeDecompressionSink( From 2b6b03d8df8811ef85605461c030466af84a8761 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Tue, 17 Sep 2024 15:25:30 -0400 Subject: [PATCH 239/718] Ensure error messages don't leak private key Since #8766, invalid base64 is rendered in errors, but we don't actually want to show this in the case of an invalid private keys. Co-Authored-By: Eelco Dolstra --- src/libfetchers/git-utils.cc | 8 +++++++- src/libstore/machines.cc | 5 +++-- src/libstore/ssh.cc | 14 ++++++++++++-- src/libstore/ssh.hh | 3 +++ src/libutil/hash.cc | 7 ++++++- src/libutil/signature/local-keys.cc | 27 ++++++++++++++++++++------- src/libutil/signature/local-keys.hh | 16 ++++++++++------ src/libutil/util.cc | 2 +- src/libutil/util.hh | 6 +++++- tests/unit/libexpr/nix_api_expr.cc | 2 +- 10 files changed, 68 insertions(+), 22 deletions(-) diff --git a/src/libfetchers/git-utils.cc b/src/libfetchers/git-utils.cc index d5acd3190..a52e2db76 100644 --- a/src/libfetchers/git-utils.cc +++ b/src/libfetchers/git-utils.cc @@ -583,7 +583,13 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this std::string re = R"(Good "git" signature for \* with .* key SHA256:[)"; for (const fetchers::PublicKey & k : publicKeys){ // Calculate sha256 fingerprint from public key and escape the regex symbol '+' to match the key literally - auto fingerprint = trim(hashString(HashAlgorithm::SHA256, base64Decode(k.key)).to_string(nix::HashFormat::Base64, false), "="); + std::string keyDecoded; + try { + keyDecoded = base64Decode(k.key); + } catch (Error & e) { + e.addTrace({}, "while decoding public key '%s' used for git signature", k.key); + } + auto fingerprint = trim(hashString(HashAlgorithm::SHA256, keyDecoded).to_string(nix::HashFormat::Base64, false), "="); auto escaped_fingerprint = std::regex_replace(fingerprint, std::regex("\\+"), "\\+" ); re += "(" + escaped_fingerprint + ")"; } diff --git a/src/libstore/machines.cc b/src/libstore/machines.cc index 256cf9188..5e038fb28 100644 --- a/src/libstore/machines.cc +++ b/src/libstore/machines.cc @@ -159,8 +159,9 @@ static Machine parseBuilderLine(const std::set & defaultSystems, co const auto & str = tokens[fieldIndex]; try { base64Decode(str); - } catch (const Error & e) { - throw FormatError("bad machine specification: a column #%lu in a row: '%s' is not valid base64 string: %s", fieldIndex, line, e.what()); + } catch (FormatError & e) { + e.addTrace({}, "while parsing machine specification at a column #%lu in a row: '%s'", fieldIndex, line); + throw; } return str; }; diff --git a/src/libstore/ssh.cc b/src/libstore/ssh.cc index b8c5f4d97..dec733fd5 100644 --- a/src/libstore/ssh.cc +++ b/src/libstore/ssh.cc @@ -7,6 +7,16 @@ namespace nix { +static std::string parsePublicHostKey(std::string_view host, std::string_view sshPublicHostKey) +{ + try { + return base64Decode(sshPublicHostKey); + } catch (Error & e) { + e.addTrace({}, "while decoding ssh public host key for host '%s'", host); + throw; + } +} + SSHMaster::SSHMaster( std::string_view host, std::string_view keyFile, @@ -15,7 +25,7 @@ SSHMaster::SSHMaster( : host(host) , fakeSSH(host == "localhost") , keyFile(keyFile) - , sshPublicHostKey(sshPublicHostKey) + , sshPublicHostKey(parsePublicHostKey(host, sshPublicHostKey)) , useMaster(useMaster && !fakeSSH) , compress(compress) , logFD(logFD) @@ -39,7 +49,7 @@ void SSHMaster::addCommonSSHOpts(Strings & args) std::filesystem::path fileName = state->tmpDir->path() / "host-key"; auto p = host.rfind("@"); std::string thost = p != std::string::npos ? std::string(host, p + 1) : host; - writeFile(fileName.string(), thost + " " + base64Decode(sshPublicHostKey) + "\n"); + writeFile(fileName.string(), thost + " " + sshPublicHostKey + "\n"); args.insert(args.end(), {"-oUserKnownHostsFile=" + fileName.string()}); } if (compress) diff --git a/src/libstore/ssh.hh b/src/libstore/ssh.hh index 19b30e883..4097134d0 100644 --- a/src/libstore/ssh.hh +++ b/src/libstore/ssh.hh @@ -14,6 +14,9 @@ private: const std::string host; bool fakeSSH; const std::string keyFile; + /** + * Raw bytes, not Base64 encoding. + */ const std::string sshPublicHostKey; const bool useMaster; const bool compress; diff --git a/src/libutil/hash.cc b/src/libutil/hash.cc index ab2a8695d..748176d33 100644 --- a/src/libutil/hash.cc +++ b/src/libutil/hash.cc @@ -245,7 +245,12 @@ Hash::Hash(std::string_view rest, HashAlgorithm algo, bool isSRI) } else if (isSRI || rest.size() == base64Len()) { - auto d = base64Decode(rest); + std::string d; + try { + d = base64Decode(rest); + } catch (Error & e) { + e.addTrace({}, "While decoding hash '%s'", rest); + } if (d.size() != hashSize) throw BadHash("invalid %s hash '%s'", isSRI ? "SRI" : "base-64", rest); assert(hashSize); diff --git a/src/libutil/signature/local-keys.cc b/src/libutil/signature/local-keys.cc index 00c4543f2..70bcb5f33 100644 --- a/src/libutil/signature/local-keys.cc +++ b/src/libutil/signature/local-keys.cc @@ -14,17 +14,25 @@ BorrowedCryptoValue BorrowedCryptoValue::parse(std::string_view s) return {s.substr(0, colon), s.substr(colon + 1)}; } -Key::Key(std::string_view s) +Key::Key(std::string_view s, bool sensitiveValue) { auto ss = BorrowedCryptoValue::parse(s); name = ss.name; key = ss.payload; - if (name == "" || key == "") - throw Error("key is corrupt"); + try { + if (name == "" || key == "") + throw FormatError("key is corrupt"); - key = base64Decode(key); + key = base64Decode(key); + } catch (Error & e) { + std::string extra; + if (!sensitiveValue) + extra = fmt(" with raw value '%s'", key); + e.addTrace({}, "while decoding key named '%s'%s", name, extra); + throw; + } } std::string Key::to_string() const @@ -33,7 +41,7 @@ std::string Key::to_string() const } SecretKey::SecretKey(std::string_view s) - : Key(s) + : Key{s, true} { if (key.size() != crypto_sign_SECRETKEYBYTES) throw Error("secret key is not valid"); @@ -66,7 +74,7 @@ SecretKey SecretKey::generate(std::string_view name) } PublicKey::PublicKey(std::string_view s) - : Key(s) + : Key{s, false} { if (key.size() != crypto_sign_PUBLICKEYBYTES) throw Error("public key is not valid"); @@ -83,7 +91,12 @@ bool PublicKey::verifyDetached(std::string_view data, std::string_view sig) cons bool PublicKey::verifyDetachedAnon(std::string_view data, std::string_view sig) const { - auto sig2 = base64Decode(sig); + std::string sig2; + try { + sig2 = base64Decode(sig); + } catch (Error & e) { + e.addTrace({}, "while decoding signature '%s'", sig); + } if (sig2.size() != crypto_sign_BYTES) throw Error("signature is not valid"); diff --git a/src/libutil/signature/local-keys.hh b/src/libutil/signature/local-keys.hh index 4aafc1239..9977f0dac 100644 --- a/src/libutil/signature/local-keys.hh +++ b/src/libutil/signature/local-keys.hh @@ -31,15 +31,19 @@ struct Key std::string name; std::string key; - /** - * Construct Key from a string in the format - * ‘:’. - */ - Key(std::string_view s); - std::string to_string() const; protected: + + /** + * Construct Key from a string in the format + * ‘:’. + * + * @param sensitiveValue Avoid displaying the raw Base64 in error + * messages to avoid leaking private keys. + */ + Key(std::string_view s, bool sensitiveValue); + Key(std::string_view name, std::string && key) : name(name), key(std::move(key)) { } }; diff --git a/src/libutil/util.cc b/src/libutil/util.cc index db3ed1ddf..0d728e2d5 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -244,7 +244,7 @@ std::string base64Decode(std::string_view s) char digit = base64DecodeChars[(unsigned char) c]; if (digit == npos) - throw Error("invalid character in Base64 string: '%c'", c); + throw FormatError("invalid character in Base64 string: '%c'", c); bits += 6; d = d << 6 | digit; diff --git a/src/libutil/util.hh b/src/libutil/util.hh index 25128a900..75a4af76e 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -172,9 +172,13 @@ constexpr char treeNull[] = " "; /** - * Base64 encoding/decoding. + * Encode arbitrary bytes as Base64. */ std::string base64Encode(std::string_view s); + +/** + * Decode arbitrary bytes to Base64. + */ std::string base64Decode(std::string_view s); diff --git a/tests/unit/libexpr/nix_api_expr.cc b/tests/unit/libexpr/nix_api_expr.cc index 8b97d6923..b37ac44b3 100644 --- a/tests/unit/libexpr/nix_api_expr.cc +++ b/tests/unit/libexpr/nix_api_expr.cc @@ -8,7 +8,7 @@ #include "tests/nix_api_expr.hh" #include "tests/string_callback.hh" -#include "gmock/gmock.h" +#include #include namespace nixC { From f2f47fa725fc87bfb536de171a2ea81f2789c9fb Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 24 Sep 2024 16:13:28 +0200 Subject: [PATCH 240/718] Add a test for builtin:fetchurl cert verification --- tests/nixos/default.nix | 2 ++ tests/nixos/fetchurl.nix | 78 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 tests/nixos/fetchurl.nix diff --git a/tests/nixos/default.nix b/tests/nixos/default.nix index 62fc6b10f..c61a2888f 100644 --- a/tests/nixos/default.nix +++ b/tests/nixos/default.nix @@ -159,4 +159,6 @@ in fsync = runNixOSTestFor "x86_64-linux" ./fsync.nix; cgroups = runNixOSTestFor "x86_64-linux" ./cgroups; + + fetchurl = runNixOSTestFor "x86_64-linux" ./fetchurl.nix; } diff --git a/tests/nixos/fetchurl.nix b/tests/nixos/fetchurl.nix new file mode 100644 index 000000000..476f779bc --- /dev/null +++ b/tests/nixos/fetchurl.nix @@ -0,0 +1,78 @@ +# Test whether builtin:fetchurl properly performs TLS certificate +# checks on HTTPS servers. + +{ lib, config, pkgs, ... }: + +let + + makeTlsCert = name: pkgs.runCommand name { + nativeBuildInputs = with pkgs; [ openssl ]; + } '' + mkdir -p $out + openssl req -x509 \ + -subj '/CN=${name}/' -days 49710 \ + -addext 'subjectAltName = DNS:${name}' \ + -keyout "$out/key.pem" -newkey ed25519 \ + -out "$out/cert.pem" -noenc + ''; + + goodCert = makeTlsCert "good"; + badCert = makeTlsCert "bad"; + +in + +{ + name = "nss-preload"; + + nodes = { + machine = { lib, pkgs, ... }: { + services.nginx = { + enable = true; + + virtualHosts."good" = { + addSSL = true; + sslCertificate = "${goodCert}/cert.pem"; + sslCertificateKey = "${goodCert}/key.pem"; + root = pkgs.runCommand "nginx-root" {} '' + mkdir "$out" + echo 'hello world' > "$out/index.html" + ''; + }; + + virtualHosts."bad" = { + addSSL = true; + sslCertificate = "${badCert}/cert.pem"; + sslCertificateKey = "${badCert}/key.pem"; + root = pkgs.runCommand "nginx-root" {} '' + mkdir "$out" + echo 'foobar' > "$out/index.html" + ''; + }; + }; + + security.pki.certificateFiles = [ "${goodCert}/cert.pem" ]; + + networking.hosts."127.0.0.1" = [ "good" "bad" ]; + + virtualisation.writableStore = true; + + nix.settings.experimental-features = "nix-command"; + }; + }; + + testScript = { nodes, ... }: '' + machine.wait_for_unit("nginx") + machine.wait_for_open_port(443) + + out = machine.succeed("curl https://good/index.html") + assert out == "hello world\n" + + # Fetching from a server with a trusted cert should work. + machine.succeed("nix build --no-substitute --expr 'import { url = \"https://good/index.html\"; hash = \"sha256-qUiQTy8PR5uPgZdpSzAYSw0u0cHNKh7A+4XSmaGSpEc=\"; }'") + + # Fetching from a server with an untrusted cert should fail. + err = machine.fail("nix build --no-substitute --expr 'import { url = \"https://bad/index.html\"; hash = \"sha256-rsBwZF/lPuOzdjBZN2E08FjMM3JHyXit0Xi2zN+wAZ8=\"; }' 2>&1") + print(err) + assert "SSL certificate problem: self-signed certificate" in err + ''; +} From eb3a368a33ce6d29f30a34472958dd96e50a829d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Wed, 25 Sep 2024 08:32:44 +0200 Subject: [PATCH 241/718] docs/testing: add --verbose flag for running single tests Most of the time people run single tests for debugging reason, so it's a sane default to have them see all the console output. This commit still retains the section about running tests directly with meson, because in some debugging cases it's just nice to have less abstractions i.e. when using strace. --- doc/manual/src/development/testing.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/doc/manual/src/development/testing.md b/doc/manual/src/development/testing.md index 8b8bc568d..0df72cc38 100644 --- a/doc/manual/src/development/testing.md +++ b/doc/manual/src/development/testing.md @@ -162,7 +162,7 @@ ninja: no work to do. Individual tests can be run with `meson`: ```shell-session -$ meson test ${testName} +$ meson test --verbose ${testName} ninja: Entering directory `/home/jcericson/src/nix/master/build' ninja: no work to do. 1/1 nix-functional-tests:main / ${testName} OK 0.41s @@ -177,7 +177,11 @@ Timeout: 0 Full log written to /home/jcericson/src/nix/master/build/meson-logs/testlog.txt ``` -or without `meson`, showing the output: +The `--verbose` flag will make Meson also show the console output of each test for easier debugging. +The test script will then be traced with `set -x` and the output displayed as it happens, +regardless of whether the test succeeds or fails. + +Tests can be also run directly without `meson`: ```shell-session $ TEST_NAME=${testName} NIX_REMOTE='' PS4='+(${BASH_SOURCE[0]-$0}:$LINENO) tests/functional/${testName}.sh @@ -188,8 +192,6 @@ output from bar ... ``` -The test script will then be traced with `set -x` and the output displayed as it happens, regardless of whether the test succeeds or fails. - ### Debugging failing functional tests When a functional test fails, it usually does so somewhere in the middle of the script. From f2063255a40d534035b706235752a5c0a09c6d15 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 25 Sep 2024 16:29:43 +0200 Subject: [PATCH 242/718] tests/functional/flakes/relative-paths.sh: Fix build failure in hydraJobs.tests.functional_user --- tests/functional/flakes/relative-paths.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/functional/flakes/relative-paths.sh b/tests/functional/flakes/relative-paths.sh index e72339b7f..9b93da9c1 100644 --- a/tests/functional/flakes/relative-paths.sh +++ b/tests/functional/flakes/relative-paths.sh @@ -71,7 +71,9 @@ git -C "$rootFlake" add sub2/flake.lock # Make sure there are no content locks for relative path flakes. (! grep "$TEST_ROOT" "$subflake2/flake.lock") -(! grep "$NIX_STORE_DIR" "$subflake2/flake.lock") +if ! isTestOnNixOS; then + (! grep "$NIX_STORE_DIR" "$subflake2/flake.lock") +fi (! grep narHash "$subflake2/flake.lock") # Test circular relative path flakes. FIXME: doesn't work at the moment. From 7b39cd631e0d3c3d238015c6f450c59bbc9cbc5b Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 25 Sep 2024 22:33:50 +0200 Subject: [PATCH 243/718] Add release note --- doc/manual/rl-next/verify-tls.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 doc/manual/rl-next/verify-tls.md diff --git a/doc/manual/rl-next/verify-tls.md b/doc/manual/rl-next/verify-tls.md new file mode 100644 index 000000000..489941d5b --- /dev/null +++ b/doc/manual/rl-next/verify-tls.md @@ -0,0 +1,8 @@ +--- +synopsis: "`` uses TLS verification" +prs: [11585] +--- + +Previously `` did not do TLS verification. This was because the Nix sandbox in the past did not have access to TLS certificates, and Nix checks the hash of the fetched file anyway. However, this can expose authentication data from `netrc` and URLs to man-in-the-middle attackers. In addition, Nix now in some cases (such as when using impure derivations) does *not* check the hash. Therefore we have now enabled TLS verification. This means that downloads by `` will now fail if you're fetching from a HTTPS server that does not have a valid certificate. + +`` is also known as the builtin derivation builder `builtin:fetchurl`. It's not to be confused with the evaluation-time function `builtins.fetchurl`, which was not affected by this issues. From ef8987955be337976ae229c44870cf6adc43bba5 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 26 Sep 2024 00:15:04 +0200 Subject: [PATCH 244/718] Typo --- doc/manual/rl-next/verify-tls.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/manual/rl-next/verify-tls.md b/doc/manual/rl-next/verify-tls.md index 489941d5b..afc689f46 100644 --- a/doc/manual/rl-next/verify-tls.md +++ b/doc/manual/rl-next/verify-tls.md @@ -5,4 +5,4 @@ prs: [11585] Previously `` did not do TLS verification. This was because the Nix sandbox in the past did not have access to TLS certificates, and Nix checks the hash of the fetched file anyway. However, this can expose authentication data from `netrc` and URLs to man-in-the-middle attackers. In addition, Nix now in some cases (such as when using impure derivations) does *not* check the hash. Therefore we have now enabled TLS verification. This means that downloads by `` will now fail if you're fetching from a HTTPS server that does not have a valid certificate. -`` is also known as the builtin derivation builder `builtin:fetchurl`. It's not to be confused with the evaluation-time function `builtins.fetchurl`, which was not affected by this issues. +`` is also known as the builtin derivation builder `builtin:fetchurl`. It's not to be confused with the evaluation-time function `builtins.fetchurl`, which was not affected by this issue. From a5959aa12170fc75cafc9e2416fae9aa67f91e6b Mon Sep 17 00:00:00 2001 From: Jason Yundt Date: Wed, 25 Sep 2024 20:21:33 -0400 Subject: [PATCH 245/718] docs: specify that flake.lock files are JSON (#11594) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs: specify that flake.lock files are JSON Recently, I decided that I was going to write some code that would parse flake.lock files. I went to the Nix Reference Manual in order to look up information on the format of flake.lock files, and I realized that a key detail was missing from the Nix Reference Manual: it never says that flake.lock files are JSON files. This commit fixes that issue. This commit makes sure to specify that flake.lock files are encoded in UTF-8. Confusingly, there’s multiple different JSON standards. Neither ECMA-404, 2nd Edition [1] nor ISO/IEC 21778:2017 [2] mention UTF-8. RFC 8259 requires UTF-8, but only sometimes [3]. I chose to explicitly specify that flake.lock files are UTF-8 in order to avoid any possible ambiguities from the JSON standards. [1]: [2]: [3]: --- src/nix/flake.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/nix/flake.md b/src/nix/flake.md index d8ee4ac71..2b999431c 100644 --- a/src/nix/flake.md +++ b/src/nix/flake.md @@ -565,8 +565,9 @@ or NixOS modules, which are composed into the top-level flake's Inputs specified in `flake.nix` are typically "unlocked" in the sense that they don't specify an exact revision. To ensure reproducibility, Nix will automatically generate and use a *lock file* called -`flake.lock` in the flake's directory. The lock file contains a graph -structure isomorphic to the graph of dependencies of the root +`flake.lock` in the flake's directory. +The lock file is a UTF-8 JSON file. +It contains a graph structure isomorphic to the graph of dependencies of the root flake. Each node in the graph (except the root node) maps the (usually) unlocked input specifications in `flake.nix` to locked input specifications. Each node also contains some metadata, such as the From 12d5b2cfa1e77816abc9c7c6989afaead9723bbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Tue, 24 Sep 2024 08:02:57 +0200 Subject: [PATCH 246/718] create git caches atomically When working on speeding up the CI, I triggered a race condition in the creation of the tarball cache. This code now instead will ensure that half-initialized repositories are no longer visible to any other nix process. This is the error message that I got before: error: opening Git repository '"/Users/runner/.cache/nix/tarball-cache"': could not find repository at '/Users/runner/.cache/nix/tarball-cache' --- src/libfetchers/git-utils.cc | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/libfetchers/git-utils.cc b/src/libfetchers/git-utils.cc index a52e2db76..582686412 100644 --- a/src/libfetchers/git-utils.cc +++ b/src/libfetchers/git-utils.cc @@ -205,6 +205,27 @@ static git_packbuilder_progress PACKBUILDER_PROGRESS_CHECK_INTERRUPT = &packBuil } // extern "C" +static void initRepoAtomically(std::filesystem::path &path, bool bare) { + if (pathExists(path.string())) return; + + Path tmpDir = createTempDir(std::filesystem::path(path).parent_path()); + AutoDelete delTmpDir(tmpDir, true); + Repository tmpRepo; + + if (git_repository_init(Setter(tmpRepo), tmpDir.c_str(), bare)) + throw Error("creating Git repository %s: %s", path, git_error_last()->message); + try { + std::filesystem::rename(tmpDir, path); + } catch (std::filesystem::filesystem_error & e) { + if (e.code() == std::errc::file_exists) // Someone might race us to create the repository. + return; + else + throw SysError("moving temporary git repository from %s to %s", tmpDir, path); + } + // we successfully moved the repository, so the temporary directory no longer exists. + delTmpDir.cancel(); +} + struct GitRepoImpl : GitRepo, std::enable_shared_from_this { /** Location of the repository on disk. */ @@ -226,13 +247,9 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this { initLibGit2(); - if (pathExists(path.string())) { - if (git_repository_open(Setter(repo), path.string().c_str())) - throw Error("opening Git repository '%s': %s", path, git_error_last()->message); - } else { - if (git_repository_init(Setter(repo), path.string().c_str(), bare)) - throw Error("creating Git repository '%s': %s", path, git_error_last()->message); - } + initRepoAtomically(path, bare); + if (git_repository_open(Setter(repo), path.string().c_str())) + throw Error("opening Git repository %s: %s", path, git_error_last()->message); ObjectDb odb; if (git_repository_odb(Setter(odb), repo.get())) From 1271a95b7940316dc45ebd70bb86d36a0e1e68b8 Mon Sep 17 00:00:00 2001 From: Josh Heinrichs Date: Thu, 26 Sep 2024 12:30:41 -0600 Subject: [PATCH 247/718] Fix reference to HTTP Binary Cache Store in docs --- src/libstore/s3-binary-cache-store.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstore/s3-binary-cache-store.md b/src/libstore/s3-binary-cache-store.md index 675470261..2cbf56e22 100644 --- a/src/libstore/s3-binary-cache-store.md +++ b/src/libstore/s3-binary-cache-store.md @@ -3,7 +3,7 @@ R"( **Store URL format**: `s3://`*bucket-name* This store allows reading and writing a binary cache stored in an AWS S3 (or S3-compatible service) bucket. -This store shares many idioms with the [HTTP Binary Cache Store](#http-binary-cache-store). +This store shares many idioms with the [HTTP Binary Cache Store](./http-binary-cache-store.md). For AWS S3, the binary cache URL for a bucket named `example-nix-cache` will be exactly . For S3 compatible binary caches, consult that cache's documentation. From 4566854981423ec36c1c7987ea2bcaba619b5d4e Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 27 Sep 2024 00:16:52 +0200 Subject: [PATCH 248/718] HttpBinaryCacheStore::getFile(): Fix uncaught exception This method is marked as `noexcept`, but `enqueueFileTransfer()` can throw `Interrupted` if the user has hit Ctrl-C or if the `ThreadPool` that the thread is a part of is shutting down. --- src/libstore/http-binary-cache-store.cc | 37 +++++++++++++------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/src/libstore/http-binary-cache-store.cc b/src/libstore/http-binary-cache-store.cc index b15ef4e4c..fc7ac2dea 100644 --- a/src/libstore/http-binary-cache-store.cc +++ b/src/libstore/http-binary-cache-store.cc @@ -169,28 +169,29 @@ protected: { try { checkEnabled(); + + auto request(makeRequest(path)); + + auto callbackPtr = std::make_shared(std::move(callback)); + + getFileTransfer()->enqueueFileTransfer(request, + {[callbackPtr, this](std::future result) { + try { + (*callbackPtr)(std::move(result.get().data)); + } catch (FileTransferError & e) { + if (e.error == FileTransfer::NotFound || e.error == FileTransfer::Forbidden) + return (*callbackPtr)({}); + maybeDisable(); + callbackPtr->rethrow(); + } catch (...) { + callbackPtr->rethrow(); + } + }}); + } catch (...) { callback.rethrow(); return; } - - auto request(makeRequest(path)); - - auto callbackPtr = std::make_shared(std::move(callback)); - - getFileTransfer()->enqueueFileTransfer(request, - {[callbackPtr, this](std::future result) { - try { - (*callbackPtr)(std::move(result.get().data)); - } catch (FileTransferError & e) { - if (e.error == FileTransfer::NotFound || e.error == FileTransfer::Forbidden) - return (*callbackPtr)({}); - maybeDisable(); - callbackPtr->rethrow(); - } catch (...) { - callbackPtr->rethrow(); - } - }}); } /** From aee34e477657b18b002f43205ffddb7b9bd1b331 Mon Sep 17 00:00:00 2001 From: Valentin Gagarin Date: Fri, 27 Sep 2024 11:07:04 +0200 Subject: [PATCH 249/718] fix location --- src/libstore/s3-binary-cache-store.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstore/s3-binary-cache-store.md b/src/libstore/s3-binary-cache-store.md index 2cbf56e22..daa41defd 100644 --- a/src/libstore/s3-binary-cache-store.md +++ b/src/libstore/s3-binary-cache-store.md @@ -3,7 +3,7 @@ R"( **Store URL format**: `s3://`*bucket-name* This store allows reading and writing a binary cache stored in an AWS S3 (or S3-compatible service) bucket. -This store shares many idioms with the [HTTP Binary Cache Store](./http-binary-cache-store.md). +This store shares many idioms with the [HTTP Binary Cache Store](@docroot@/store/types/http-binary-cache-store.md). For AWS S3, the binary cache URL for a bucket named `example-nix-cache` will be exactly . For S3 compatible binary caches, consult that cache's documentation. From 3b0c5ab835039b00c0d8fee62a0db16fd59693d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Fri, 27 Sep 2024 11:07:50 +0200 Subject: [PATCH 250/718] tests/functional/flakes/run: fix tests in macOS devshell same fix as in 04a47e93f611f08df9f0cadad761a8f5268fff1f --- tests/functional/flakes/run.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/functional/flakes/run.sh b/tests/functional/flakes/run.sh index 61af6049a..9c31dc134 100755 --- a/tests/functional/flakes/run.sh +++ b/tests/functional/flakes/run.sh @@ -37,11 +37,13 @@ env > $TEST_ROOT/expected-env nix run -f shell-hello.nix env > $TEST_ROOT/actual-env # Remove/reset variables we expect to be different. # - PATH is modified by nix shell +# - we unset TMPDIR on macOS if it contains /var/folders # - _ is set by bash and is expected to differ because it contains the original command # - __CF_USER_TEXT_ENCODING is set by macOS and is beyond our control sed -i \ -e 's/PATH=.*/PATH=.../' \ -e 's/_=.*/_=.../' \ + -e '/^TMPDIR=\/var\/folders\/.*/d' \ -e '/^__CF_USER_TEXT_ENCODING=.*$/d' \ $TEST_ROOT/expected-env $TEST_ROOT/actual-env sort $TEST_ROOT/expected-env | uniq > $TEST_ROOT/expected-env.sorted From c1ecf0bee973e620c9282bd71ddf1a5710968249 Mon Sep 17 00:00:00 2001 From: Puck Meerburg Date: Sat, 28 Sep 2024 16:54:39 +0200 Subject: [PATCH 251/718] fix passing CA files into builtins:fetchurl sandbox MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch has been manually adapted from https://github.com/lix-project/lix/commit/14dc84ed03f1b7e5a41bb6fdce00916faab32b60 Tested with: $ NIX_SSL_CERT_FILE=$(nix-build '' -A cacert)/etc/ssl/certs/ca-bundle.crt nix-build --store $(mktemp -d) -E 'import { url = https://google.com; }' Finished at 16:57:50 after 1s warning: found empty hash, assuming 'sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=' this derivation will be built: nix-output-monitor error: DerivationReadError /nix/store/4qljhy0jj2b0abjzpsbyarpia1bqylwc-google.com.drv: openFile: does not exist (No such file or directory) /nix/store/4qljhy0jj2b0abjzpsbyarpia1bqylwc-google.com.drv nix-output-monitor error: DerivationReadError /nix/store/4qljhy0jj2b0abjzpsbyarpia1bqylwc-google.com.drv: openFile: does not exist (No such file or directory) nix-output-monitor error: DerivationReadError /nix/store/4qljhy0jj2b0abjzpsbyarpia1bqylwc-google.com.drv: openFile: does not exist (No such file or directory) nix-output-monitor error: DerivationReadError /nix/store/4qljhy0jj2b0abjzpsbyarpia1bqylwc-google.com.drv: openFile: does not exist (No such file or directory) google.com> building '/nix/store/4qljhy0jj2b0abjzpsbyarpia1bqylwc-google.com.drv' nix-output-monitor error: DerivationReadError /nix/store/4qljhy0jj2b0abjzpsbyarpia1bqylwc-google.com.drv: openFile: does not exist (No such file or directory) google.com> error: nix-output-monitor error: DerivationReadError /nix/store/4qljhy0jj2b0abjzpsbyarpia1bqylwc-google.com.drv: openFile: does not exist (No such file or directory) google.com> … writing file '/nix/store/0zynn4n8yx59bczy1mgh1lq2rnprvvrc-google.com' nix-output-monitor error: DerivationReadError /nix/store/4qljhy0jj2b0abjzpsbyarpia1bqylwc-google.com.drv: openFile: does not exist (No such file or directory) google.com> nix-output-monitor error: DerivationReadError /nix/store/4qljhy0jj2b0abjzpsbyarpia1bqylwc-google.com.drv: openFile: does not exist (No such file or directory) google.com> error: unable to download 'https://google.com': Problem with the SSL CA cert (path? access rights?) (77) error setting certificate file: /nix/store/nlgbippbbgn38hynjkp1ghiybcq1dqhx-nss-cacert-3.101.1/etc/ssl/certs/ca-bundle.crt nix-output-monitor error: DerivationReadError /nix/store/4qljhy0jj2b0abjzpsbyarpia1bqylwc-google.com.drv: openFile: does not exist (No such file or directory) nix-output-monitor error: DerivationReadError /nix/store/4qljhy0jj2b0abjzpsbyarpia1bqylwc-google.com.drv: openFile: does not exist (No such file or directory) error: builder for '/nix/store/4qljhy0jj2b0abjzpsbyarpia1bqylwc-google.com.drv' failed with exit code 1 Now returns: nix-env % NIX_SSL_CERT_FILE=$(nix-build '' -A cacert)/etc/ssl/certs/ca-bundle.crt nix-build --store $(mktemp -d) -E 'import { url = https://google.com; }' Finished at 17:05:48 after 0s warning: found empty hash, assuming 'sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=' this derivation will be built: nix-output-monitor error: DerivationReadError /nix/store/4qljhy0jj2b0abjzpsbyarpia1bqylwc-google.com.drv: openFile: does not exist (No such file or directory) /nix/store/4qljhy0jj2b0abjzpsbyarpia1bqylwc-google.com.drv nix-output-monitor error: DerivationReadError /nix/store/4qljhy0jj2b0abjzpsbyarpia1bqylwc-google.com.drv: openFile: does not exist (No such file or directory) nix-output-monitor error: DerivationReadError /nix/store/4qljhy0jj2b0abjzpsbyarpia1bqylwc-google.com.drv: openFile: does not exist (No such file or directory) nix-output-monitor error: DerivationReadError /nix/store/4qljhy0jj2b0abjzpsbyarpia1bqylwc-google.com.drv: openFile: does not exist (No such file or directory) google.com> building '/nix/store/4qljhy0jj2b0abjzpsbyarpia1bqylwc-google.com.drv' nix-output-monitor error: DerivationReadError /nix/store/4qljhy0jj2b0abjzpsbyarpia1bqylwc-google.com.drv: openFile: does not exist (No such file or directory) nix-output-monitor error: DerivationReadError /nix/store/4qljhy0jj2b0abjzpsbyarpia1bqylwc-google.com.drv: openFile: does not exist (No such file or directory) error: hash mismatch in fixed-output derivation '/nix/store/4qljhy0jj2b0abjzpsbyarpia1bqylwc-google.com.drv': specified: sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= --- src/libstore/builtins.hh | 3 ++- src/libstore/builtins/fetchurl.cc | 6 +++++- .../unix/build/local-derivation-goal.cc | 21 ++++++++++++------- tests/nixos/fetchurl.nix | 6 ++++++ 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/libstore/builtins.hh b/src/libstore/builtins.hh index 93558b49e..091946e01 100644 --- a/src/libstore/builtins.hh +++ b/src/libstore/builtins.hh @@ -9,7 +9,8 @@ namespace nix { void builtinFetchurl( const BasicDerivation & drv, const std::map & outputs, - const std::string & netrcData); + const std::string & netrcData, + const std::string & caFileData); void builtinUnpackChannel( const BasicDerivation & drv, diff --git a/src/libstore/builtins/fetchurl.cc b/src/libstore/builtins/fetchurl.cc index f33060c33..90e58dfdb 100644 --- a/src/libstore/builtins/fetchurl.cc +++ b/src/libstore/builtins/fetchurl.cc @@ -9,7 +9,8 @@ namespace nix { void builtinFetchurl( const BasicDerivation & drv, const std::map & outputs, - const std::string & netrcData) + const std::string & netrcData, + const std::string & caFileData) { /* Make the host's netrc data available. Too bad curl requires this to be stored in a file. It would be nice if we could just @@ -19,6 +20,9 @@ void builtinFetchurl( writeFile(settings.netrcFile, netrcData, 0600); } + settings.caFile = "ca-certificates.crt"; + writeFile(settings.caFile, caFileData, 0600); + auto out = get(drv.outputs, "out"); if (!out) throw Error("'builtin:fetchurl' requires an 'out' output"); diff --git a/src/libstore/unix/build/local-derivation-goal.cc b/src/libstore/unix/build/local-derivation-goal.cc index 08b973cd1..5ccaa3787 100644 --- a/src/libstore/unix/build/local-derivation-goal.cc +++ b/src/libstore/unix/build/local-derivation-goal.cc @@ -1743,13 +1743,20 @@ void LocalDerivationGoal::runChild() bool setUser = true; - /* Make the contents of netrc available to builtin:fetchurl - (which may run under a different uid and/or in a sandbox). */ + /* Make the contents of netrc and the CA certificate bundle + available to builtin:fetchurl (which may run under a + different uid and/or in a sandbox). */ std::string netrcData; - try { - if (drv->isBuiltin() && drv->builder == "builtin:fetchurl") - netrcData = readFile(settings.netrcFile); - } catch (SystemError &) { } + std::string caFileData; + if (drv->isBuiltin() && drv->builder == "builtin:fetchurl") { + try { + netrcData = readFile(settings.netrcFile); + } catch (SystemError &) { } + + try { + caFileData = readFile(settings.caFile); + } catch (SystemError &) { } + } #if __linux__ if (useChroot) { @@ -2188,7 +2195,7 @@ void LocalDerivationGoal::runChild() worker.store.printStorePath(scratchOutputs.at(e.first))); if (drv->builder == "builtin:fetchurl") - builtinFetchurl(*drv, outputs, netrcData); + builtinFetchurl(*drv, outputs, netrcData, caFileData); else if (drv->builder == "builtin:buildenv") builtinBuildenv(*drv, outputs); else if (drv->builder == "builtin:unpack-channel") diff --git a/tests/nixos/fetchurl.nix b/tests/nixos/fetchurl.nix index 476f779bc..f873bf4b5 100644 --- a/tests/nixos/fetchurl.nix +++ b/tests/nixos/fetchurl.nix @@ -67,6 +67,9 @@ in out = machine.succeed("curl https://good/index.html") assert out == "hello world\n" + out = machine.succeed("cat ${badCert}/cert.pem > /tmp/cafile.pem; curl --cacert /tmp/cafile.pem https://bad/index.html") + assert out == "foobar\n" + # Fetching from a server with a trusted cert should work. machine.succeed("nix build --no-substitute --expr 'import { url = \"https://good/index.html\"; hash = \"sha256-qUiQTy8PR5uPgZdpSzAYSw0u0cHNKh7A+4XSmaGSpEc=\"; }'") @@ -74,5 +77,8 @@ in err = machine.fail("nix build --no-substitute --expr 'import { url = \"https://bad/index.html\"; hash = \"sha256-rsBwZF/lPuOzdjBZN2E08FjMM3JHyXit0Xi2zN+wAZ8=\"; }' 2>&1") print(err) assert "SSL certificate problem: self-signed certificate" in err + + # Fetching from a server with a trusted cert should work via environment variable override. + machine.succeed("NIX_SSL_CERT_FILE=/tmp/cafile.pem nix build --no-substitute --expr 'import { url = \"https://bad/index.html\"; hash = \"sha256-rsBwZF/lPuOzdjBZN2E08FjMM3JHyXit0Xi2zN+wAZ8=\"; }'") ''; } From 410853ddcf91910bd4db7421b3df756e25a4fbbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sat, 28 Sep 2024 17:06:10 +0200 Subject: [PATCH 252/718] tests/nixos/fetchurl: drop unused variables --- tests/nixos/fetchurl.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/nixos/fetchurl.nix b/tests/nixos/fetchurl.nix index f873bf4b5..243c0cacc 100644 --- a/tests/nixos/fetchurl.nix +++ b/tests/nixos/fetchurl.nix @@ -1,7 +1,7 @@ # Test whether builtin:fetchurl properly performs TLS certificate # checks on HTTPS servers. -{ lib, config, pkgs, ... }: +{ pkgs, ... }: let @@ -25,7 +25,7 @@ in name = "nss-preload"; nodes = { - machine = { lib, pkgs, ... }: { + machine = { pkgs, ... }: { services.nginx = { enable = true; @@ -60,7 +60,7 @@ in }; }; - testScript = { nodes, ... }: '' + testScript = '' machine.wait_for_unit("nginx") machine.wait_for_open_port(443) From 3b6cf350e798c6cc55e6c4af1fd45162c80efa74 Mon Sep 17 00:00:00 2001 From: Jordan Justen Date: Sat, 28 Sep 2024 15:23:36 -0700 Subject: [PATCH 253/718] doc, src: Fix various spelling typos Signed-off-by: Jordan Justen --- doc/manual/src/command-ref/nix-store/query.md | 3 +-- src/libexpr/primops/context.cc | 2 +- src/libexpr/primops/fetchTree.cc | 2 +- src/libstore/builtins/unpack-channel.cc | 2 +- src/libstore/local-overlay-store.md | 2 +- src/libstore/local.mk | 2 +- src/nix/nix.md | 2 +- 7 files changed, 7 insertions(+), 8 deletions(-) diff --git a/doc/manual/src/command-ref/nix-store/query.md b/doc/manual/src/command-ref/nix-store/query.md index b4efa734e..601f46af6 100644 --- a/doc/manual/src/command-ref/nix-store/query.md +++ b/doc/manual/src/command-ref/nix-store/query.md @@ -104,7 +104,7 @@ symlink. Prints a set of derivation files (`.drv`) which are supposed produce said paths when realized. Might print nothing, for example for source paths - or paths subsituted from a binary cache. + or paths substituted from a binary cache. - `--graph` @@ -241,4 +241,3 @@ $ nix-store --query --roots $(which svn) /nix/var/nix/profiles/default-82-link /home/eelco/.local/state/nix/profiles/profile-97-link ``` - diff --git a/src/libexpr/primops/context.cc b/src/libexpr/primops/context.cc index 8c3f1b4e8..02683b173 100644 --- a/src/libexpr/primops/context.cc +++ b/src/libexpr/primops/context.cc @@ -86,7 +86,7 @@ static RegisterPrimOp primop_unsafeDiscardOutputDependency({ This is the opposite of [`builtins.addDrvOutputDependencies`](#builtins-addDrvOutputDependencies). - This is unsafe because it allows us to "forget" store objects we would have otherwise refered to with the string context, + This is unsafe because it allows us to "forget" store objects we would have otherwise referred to with the string context, whereas Nix normally tracks all dependencies consistently. Safe operations "grow" but never "shrink" string contexts. [`builtins.addDrvOutputDependencies`] in contrast is safe because "derivation deep" string context element always refers to the underlying derivation (among many more things). diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc index 5d074e623..1004d79ee 100644 --- a/src/libexpr/primops/fetchTree.cc +++ b/src/libexpr/primops/fetchTree.cc @@ -246,7 +246,7 @@ static RegisterPrimOp primop_fetchTree({ The following source types and associated input attributes are supported. - `"file"` diff --git a/src/libstore/builtins/unpack-channel.cc b/src/libstore/builtins/unpack-channel.cc index d30626a30..a6369ee1c 100644 --- a/src/libstore/builtins/unpack-channel.cc +++ b/src/libstore/builtins/unpack-channel.cc @@ -20,7 +20,7 @@ void builtinUnpackChannel( auto & src = getAttr("src"); if (fs::path{channelName}.filename().string() != channelName) { - throw Error("channelName is not allowed to contain filesystem seperators, got %1%", channelName); + throw Error("channelName is not allowed to contain filesystem separators, got %1%", channelName); } try { diff --git a/src/libstore/local-overlay-store.md b/src/libstore/local-overlay-store.md index baa395895..9434ebfb9 100644 --- a/src/libstore/local-overlay-store.md +++ b/src/libstore/local-overlay-store.md @@ -4,7 +4,7 @@ R"( This store type is a variation of the [local store] designed to leverage Linux's [Overlay Filesystem](https://docs.kernel.org/filesystems/overlayfs.html) (OverlayFS for short). Just as OverlayFS combines a lower and upper filesystem by treating the upper one as a patch against the lower, the local overlay store combines a lower store with an upper almost-[local store]. -("almost" because while the upper fileystems for OverlayFS is valid on its own, the upper almost-store is not a valid local store on its own because some references will dangle.) +("almost" because while the upper filesystems for OverlayFS is valid on its own, the upper almost-store is not a valid local store on its own because some references will dangle.) To use this store, you will first need to configure an OverlayFS mountpoint [appropriately](#example-filesystem-layout) as Nix will not do this for you (though it will verify the mountpoint is configured correctly). ### Conceptual parts of a local overlay store diff --git a/src/libstore/local.mk b/src/libstore/local.mk index 88be6a366..43d8993ba 100644 --- a/src/libstore/local.mk +++ b/src/libstore/local.mk @@ -59,7 +59,7 @@ NIX_ROOT = endif # Prefix all but `NIX_STORE_DIR`, since we aren't doing a local store -# yet so a "logical" store dir that is the same as unix is prefered. +# yet so a "logical" store dir that is the same as unix is preferred. # # Also, it keeps the unit tests working. diff --git a/src/nix/nix.md b/src/nix/nix.md index 443757a05..b88bd9a94 100644 --- a/src/nix/nix.md +++ b/src/nix/nix.md @@ -302,7 +302,7 @@ or with an **expression**: terraform "$@" ``` -or with cascading interpreters. Note that the `#! nix` lines don't need to follow after the first line, to accomodate other interpreters. +or with cascading interpreters. Note that the `#! nix` lines don't need to follow after the first line, to accommodate other interpreters. ``` #!/usr/bin/env nix From 8c4842de8cc1a8329f9b42ada13ab1a074cfa9dd Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Sun, 29 Sep 2024 18:42:38 +0200 Subject: [PATCH 254/718] doc/nix fmt: Do not document behavior we do not control This leads to confusion about what the command does. E.g. https://github.com/NixOS/nix/issues/9359 - Move the description up - Remove details about the individual formatters --- src/nix/fmt.md | 24 +++++++++--------------- tests/functional/fmt.sh | 2 +- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/src/nix/fmt.md b/src/nix/fmt.md index 1c78bb36f..a2afde61c 100644 --- a/src/nix/fmt.md +++ b/src/nix/fmt.md @@ -1,5 +1,14 @@ R""( +# Description + +`nix fmt` calls the formatter specified in the flake. + +Flags can be forwarded to the formatter by using `--` followed by the flags. + +Any arguments will be forwarded to the formatter. Typically these are the files to format. + + # Examples With [nixpkgs-fmt](https://github.com/nix-community/nixpkgs-fmt): @@ -13,10 +22,6 @@ With [nixpkgs-fmt](https://github.com/nix-community/nixpkgs-fmt): } ``` -- Format the current flake: `$ nix fmt` - -- Format a specific folder or file: `$ nix fmt ./folder ./file.nix` - With [nixfmt](https://github.com/serokell/nixfmt): ```nix @@ -28,8 +33,6 @@ With [nixfmt](https://github.com/serokell/nixfmt): } ``` -- Format specific files: `$ nix fmt ./file1.nix ./file2.nix` - With [Alejandra](https://github.com/kamadorueda/alejandra): ```nix @@ -41,13 +44,4 @@ With [Alejandra](https://github.com/kamadorueda/alejandra): } ``` -- Format the current flake: `$ nix fmt` - -- Format a specific folder or file: `$ nix fmt ./folder ./file.nix` - -# Description - -`nix fmt` will rewrite all Nix files (\*.nix) to a canonical format -using the formatter specified in your flake. - )"" diff --git a/tests/functional/fmt.sh b/tests/functional/fmt.sh index 9a79260e6..4e0fd57a5 100755 --- a/tests/functional/fmt.sh +++ b/tests/functional/fmt.sh @@ -11,7 +11,7 @@ cp ./simple.nix ./simple.builder.sh ./fmt.simple.sh ./config.nix "$TEST_HOME" cd "$TEST_HOME" -nix fmt --help | grep "Format" +nix fmt --help | grep "forward" cat << EOF > flake.nix { From a614fbb2a2f049feee6855b8ef89a14cfb48529d Mon Sep 17 00:00:00 2001 From: Gerg-L Date: Sun, 29 Sep 2024 15:03:08 -0400 Subject: [PATCH 255/718] nix-ng: add meta.mainProgram --- packaging/everything.nix | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packaging/everything.nix b/packaging/everything.nix index 6dae7f1c2..d26c81572 100644 --- a/packaging/everything.nix +++ b/packaging/everything.nix @@ -39,7 +39,7 @@ nix-perl-bindings, }: -(buildEnv rec { +(buildEnv { name = "nix-${nix-cli.version}"; paths = [ nix-util @@ -76,6 +76,8 @@ ] ++ lib.optionals (stdenv.buildPlatform.canExecute stdenv.hostPlatform) [ nix-perl-bindings ]; + + meta.mainProgram = "nix"; }).overrideAttrs (finalAttrs: prevAttrs: { doCheck = true; doInstallCheck = true; From 3df619339c012eac62379191ebe0891fdc93a916 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 30 Sep 2024 11:49:53 +0200 Subject: [PATCH 256/718] Split ignoreException for destructors or interrupt-safe --- src/libexpr/eval-cache.cc | 6 +- src/libmain/shared.cc | 2 +- src/libstore/build/derivation-goal.cc | 4 +- src/libstore/build/substitution-goal.cc | 2 +- src/libstore/filetransfer.cc | 2 +- src/libstore/gc.cc | 4 +- src/libstore/local-store.cc | 174 +++++++++--------- src/libstore/optimise-store.cc | 2 +- src/libstore/pathlocks.cc | 2 +- src/libstore/remote-fs-accessor.cc | 4 +- src/libstore/sqlite.cc | 6 +- src/libstore/store-api.cc | 2 +- src/libstore/unix/build/hook-instance.cc | 2 +- .../unix/build/local-derivation-goal.cc | 8 +- src/libstore/worker-protocol-connection.cc | 2 +- src/libutil/current-process.cc | 2 +- src/libutil/file-descriptor.cc | 3 +- src/libutil/file-system.cc | 3 +- src/libutil/logging.cc | 2 +- src/libutil/serialise.cc | 3 +- src/libutil/serialise.hh | 4 +- src/libutil/thread-pool.cc | 5 +- src/libutil/unix/signals.cc | 2 +- src/libutil/util.cc | 14 +- src/libutil/util.hh | 23 ++- src/nix/develop.cc | 2 +- src/nix/flake.cc | 4 +- 27 files changed, 164 insertions(+), 125 deletions(-) diff --git a/src/libexpr/eval-cache.cc b/src/libexpr/eval-cache.cc index c407cc89a..ea3319f99 100644 --- a/src/libexpr/eval-cache.cc +++ b/src/libexpr/eval-cache.cc @@ -101,7 +101,7 @@ struct AttrDb state->txn->commit(); state->txn.reset(); } catch (...) { - ignoreException(); + ignoreExceptionInDestructor(); } } @@ -112,7 +112,7 @@ struct AttrDb try { return fun(); } catch (SQLiteError &) { - ignoreException(); + ignoreExceptionExceptInterrupt(); failed = true; return 0; } @@ -351,7 +351,7 @@ static std::shared_ptr makeAttrDb( try { return std::make_shared(cfg, fingerprint, symbols); } catch (SQLiteError &) { - ignoreException(); + ignoreExceptionExceptInterrupt(); return nullptr; } } diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc index a224f8d92..50f90bfb3 100644 --- a/src/libmain/shared.cc +++ b/src/libmain/shared.cc @@ -416,7 +416,7 @@ RunPager::~RunPager() } #endif } catch (...) { - ignoreException(); + ignoreExceptionInDestructor(); } } diff --git a/src/libstore/build/derivation-goal.cc b/src/libstore/build/derivation-goal.cc index b809e3ffe..34ed16a38 100644 --- a/src/libstore/build/derivation-goal.cc +++ b/src/libstore/build/derivation-goal.cc @@ -90,7 +90,7 @@ DerivationGoal::~DerivationGoal() { /* Careful: we should never ever throw an exception from a destructor. */ - try { closeLogFile(); } catch (...) { ignoreException(); } + try { closeLogFile(); } catch (...) { ignoreExceptionInDestructor(); } } @@ -814,7 +814,7 @@ void replaceValidPath(const Path & storePath, const Path & tmpPath) // attempt to recover movePath(oldPath, storePath); } catch (...) { - ignoreException(); + ignoreExceptionExceptInterrupt(); } throw; } diff --git a/src/libstore/build/substitution-goal.cc b/src/libstore/build/substitution-goal.cc index a26eea820..315500719 100644 --- a/src/libstore/build/substitution-goal.cc +++ b/src/libstore/build/substitution-goal.cc @@ -294,7 +294,7 @@ void PathSubstitutionGoal::cleanup() outPipe.close(); } catch (...) { - ignoreException(); + ignoreExceptionInDestructor(); } } diff --git a/src/libstore/filetransfer.cc b/src/libstore/filetransfer.cc index 58c52acc0..154ec6007 100644 --- a/src/libstore/filetransfer.cc +++ b/src/libstore/filetransfer.cc @@ -139,7 +139,7 @@ struct curlFileTransfer : public FileTransfer if (!done) fail(FileTransferError(Interrupted, {}, "download of '%s' was interrupted", request.uri)); } catch (...) { - ignoreException(); + ignoreExceptionInDestructor(); } } diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index 91cf76366..73195794a 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -958,8 +958,8 @@ void LocalStore::autoGC(bool sync) } catch (...) { // FIXME: we could propagate the exception to the - // future, but we don't really care. - ignoreException(); + // future, but we don't really care. (what??) + ignoreExceptionInDestructor(); } }).detach(); diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index a8c27b92f..394ee2cc1 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -522,7 +522,7 @@ LocalStore::~LocalStore() unlink(fnTempRoots.c_str()); } } catch (...) { - ignoreException(); + ignoreExceptionInDestructor(); } } @@ -1096,108 +1096,114 @@ void LocalStore::addToStore(const ValidPathInfo & info, Source & source, if (checkSigs && pathInfoIsUntrusted(info)) throw Error("cannot add path '%s' because it lacks a signature by a trusted key", printStorePath(info.path)); - /* In case we are not interested in reading the NAR: discard it. */ - bool narRead = false; - Finally cleanup = [&]() { - if (!narRead) { - NullFileSystemObjectSink sink; - try { - parseDump(sink, source); - } catch (...) { - ignoreException(); + { + /* In case we are not interested in reading the NAR: discard it. */ + bool narRead = false; + Finally cleanup = [&]() { + if (!narRead) { + NullFileSystemObjectSink sink; + try { + parseDump(sink, source); + } catch (...) { + // TODO: should Interrupted be handled here? + ignoreExceptionInDestructor(); + } } - } - }; + }; - addTempRoot(info.path); - - if (repair || !isValidPath(info.path)) { - - PathLocks outputLock; - - auto realPath = Store::toRealPath(info.path); - - /* Lock the output path. But don't lock if we're being called - from a build hook (whose parent process already acquired a - lock on this path). */ - if (!locksHeld.count(printStorePath(info.path))) - outputLock.lockPaths({realPath}); + addTempRoot(info.path); if (repair || !isValidPath(info.path)) { - deletePath(realPath); + PathLocks outputLock; - /* While restoring the path from the NAR, compute the hash - of the NAR. */ - HashSink hashSink(HashAlgorithm::SHA256); + auto realPath = Store::toRealPath(info.path); - TeeSource wrapperSource { source, hashSink }; + /* Lock the output path. But don't lock if we're being called + from a build hook (whose parent process already acquired a + lock on this path). */ + if (!locksHeld.count(printStorePath(info.path))) + outputLock.lockPaths({realPath}); - narRead = true; - restorePath(realPath, wrapperSource, settings.fsyncStorePaths); + if (repair || !isValidPath(info.path)) { - auto hashResult = hashSink.finish(); + deletePath(realPath); - if (hashResult.first != info.narHash) - throw Error("hash mismatch importing path '%s';\n specified: %s\n got: %s", - printStorePath(info.path), info.narHash.to_string(HashFormat::Nix32, true), hashResult.first.to_string(HashFormat::Nix32, true)); + /* While restoring the path from the NAR, compute the hash + of the NAR. */ + HashSink hashSink(HashAlgorithm::SHA256); - if (hashResult.second != info.narSize) - throw Error("size mismatch importing path '%s';\n specified: %s\n got: %s", - printStorePath(info.path), info.narSize, hashResult.second); + TeeSource wrapperSource { source, hashSink }; - if (info.ca) { - auto & specified = *info.ca; - auto actualHash = ({ - auto accessor = getFSAccessor(false); - CanonPath path { printStorePath(info.path) }; - Hash h { HashAlgorithm::SHA256 }; // throwaway def to appease C++ - auto fim = specified.method.getFileIngestionMethod(); - switch (fim) { - case FileIngestionMethod::Flat: - case FileIngestionMethod::NixArchive: - { - HashModuloSink caSink { - specified.hash.algo, - std::string { info.path.hashPart() }, + narRead = true; + restorePath(realPath, wrapperSource, settings.fsyncStorePaths); + + auto hashResult = hashSink.finish(); + + if (hashResult.first != info.narHash) + throw Error("hash mismatch importing path '%s';\n specified: %s\n got: %s", + printStorePath(info.path), info.narHash.to_string(HashFormat::Nix32, true), hashResult.first.to_string(HashFormat::Nix32, true)); + + if (hashResult.second != info.narSize) + throw Error("size mismatch importing path '%s';\n specified: %s\n got: %s", + printStorePath(info.path), info.narSize, hashResult.second); + + if (info.ca) { + auto & specified = *info.ca; + auto actualHash = ({ + auto accessor = getFSAccessor(false); + CanonPath path { printStorePath(info.path) }; + Hash h { HashAlgorithm::SHA256 }; // throwaway def to appease C++ + auto fim = specified.method.getFileIngestionMethod(); + switch (fim) { + case FileIngestionMethod::Flat: + case FileIngestionMethod::NixArchive: + { + HashModuloSink caSink { + specified.hash.algo, + std::string { info.path.hashPart() }, + }; + dumpPath({accessor, path}, caSink, (FileSerialisationMethod) fim); + h = caSink.finish().first; + break; + } + case FileIngestionMethod::Git: + h = git::dumpHash(specified.hash.algo, {accessor, path}).hash; + break; + } + ContentAddress { + .method = specified.method, + .hash = std::move(h), }; - dumpPath({accessor, path}, caSink, (FileSerialisationMethod) fim); - h = caSink.finish().first; - break; + }); + if (specified.hash != actualHash.hash) { + throw Error("ca hash mismatch importing path '%s';\n specified: %s\n got: %s", + printStorePath(info.path), + specified.hash.to_string(HashFormat::Nix32, true), + actualHash.hash.to_string(HashFormat::Nix32, true)); } - case FileIngestionMethod::Git: - h = git::dumpHash(specified.hash.algo, {accessor, path}).hash; - break; - } - ContentAddress { - .method = specified.method, - .hash = std::move(h), - }; - }); - if (specified.hash != actualHash.hash) { - throw Error("ca hash mismatch importing path '%s';\n specified: %s\n got: %s", - printStorePath(info.path), - specified.hash.to_string(HashFormat::Nix32, true), - actualHash.hash.to_string(HashFormat::Nix32, true)); } + + autoGC(); + + canonicalisePathMetaData(realPath); + + optimisePath(realPath, repair); // FIXME: combine with hashPath() + + if (settings.fsyncStorePaths) { + recursiveSync(realPath); + syncParent(realPath); + } + + registerValidPath(info); } - autoGC(); - - canonicalisePathMetaData(realPath); - - optimisePath(realPath, repair); // FIXME: combine with hashPath() - - if (settings.fsyncStorePaths) { - recursiveSync(realPath); - syncParent(realPath); - } - - registerValidPath(info); + outputLock.setDeletion(true); } - - outputLock.setDeletion(true); } + + // In case `cleanup` ignored an `Interrupted` exception + checkInterrupt(); } diff --git a/src/libstore/optimise-store.cc b/src/libstore/optimise-store.cc index 9d903f218..aeff24c64 100644 --- a/src/libstore/optimise-store.cc +++ b/src/libstore/optimise-store.cc @@ -35,7 +35,7 @@ struct MakeReadOnly /* This will make the path read-only. */ if (path != "") canonicaliseTimestampAndPermissions(path); } catch (...) { - ignoreException(); + ignoreExceptionInDestructor(); } } }; diff --git a/src/libstore/pathlocks.cc b/src/libstore/pathlocks.cc index 37793db5b..c855e797f 100644 --- a/src/libstore/pathlocks.cc +++ b/src/libstore/pathlocks.cc @@ -27,7 +27,7 @@ PathLocks::~PathLocks() try { unlock(); } catch (...) { - ignoreException(); + ignoreExceptionInDestructor(); } } diff --git a/src/libstore/remote-fs-accessor.cc b/src/libstore/remote-fs-accessor.cc index 20f1d826c..7e360b5fe 100644 --- a/src/libstore/remote-fs-accessor.cc +++ b/src/libstore/remote-fs-accessor.cc @@ -30,7 +30,7 @@ ref RemoteFSAccessor::addToCache(std::string_view hashPart, std: /* FIXME: do this asynchronously. */ writeFile(makeCacheFile(hashPart, "nar"), nar); } catch (...) { - ignoreException(); + ignoreExceptionExceptInterrupt(); } } @@ -42,7 +42,7 @@ ref RemoteFSAccessor::addToCache(std::string_view hashPart, std: nlohmann::json j = listNar(narAccessor, CanonPath::root, true); writeFile(makeCacheFile(hashPart, "ls"), j.dump()); } catch (...) { - ignoreException(); + ignoreExceptionExceptInterrupt(); } } diff --git a/src/libstore/sqlite.cc b/src/libstore/sqlite.cc index 3175c1978..f02e472fd 100644 --- a/src/libstore/sqlite.cc +++ b/src/libstore/sqlite.cc @@ -86,7 +86,7 @@ SQLite::~SQLite() if (db && sqlite3_close(db) != SQLITE_OK) SQLiteError::throw_(db, "closing database"); } catch (...) { - ignoreException(); + ignoreExceptionInDestructor(); } } @@ -125,7 +125,7 @@ SQLiteStmt::~SQLiteStmt() if (stmt && sqlite3_finalize(stmt) != SQLITE_OK) SQLiteError::throw_(db, "finalizing statement '%s'", sql); } catch (...) { - ignoreException(); + ignoreExceptionInDestructor(); } } @@ -240,7 +240,7 @@ SQLiteTxn::~SQLiteTxn() if (active && sqlite3_exec(db, "rollback;", 0, 0, 0) != SQLITE_OK) SQLiteError::throw_(db, "aborting transaction"); } catch (...) { - ignoreException(); + ignoreExceptionInDestructor(); } } diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index 426a69ae2..8109ea322 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -1055,7 +1055,7 @@ std::map copyPaths( // not be within our control to change that, and we might still want // to at least copy the output paths. if (e.missingFeature == Xp::CaDerivations) - ignoreException(); + ignoreExceptionExceptInterrupt(); else throw; } diff --git a/src/libstore/unix/build/hook-instance.cc b/src/libstore/unix/build/hook-instance.cc index 4f8492fe9..79eb25a91 100644 --- a/src/libstore/unix/build/hook-instance.cc +++ b/src/libstore/unix/build/hook-instance.cc @@ -91,7 +91,7 @@ HookInstance::~HookInstance() toHook.writeSide = -1; if (pid != -1) pid.kill(); } catch (...) { - ignoreException(); + ignoreExceptionInDestructor(); } } diff --git a/src/libstore/unix/build/local-derivation-goal.cc b/src/libstore/unix/build/local-derivation-goal.cc index 08b973cd1..732988df3 100644 --- a/src/libstore/unix/build/local-derivation-goal.cc +++ b/src/libstore/unix/build/local-derivation-goal.cc @@ -109,9 +109,9 @@ LocalDerivationGoal::~LocalDerivationGoal() { /* Careful: we should never ever throw an exception from a destructor. */ - try { deleteTmpDir(false); } catch (...) { ignoreException(); } - try { killChild(); } catch (...) { ignoreException(); } - try { stopDaemon(); } catch (...) { ignoreException(); } + try { deleteTmpDir(false); } catch (...) { ignoreExceptionInDestructor(); } + try { killChild(); } catch (...) { ignoreExceptionInDestructor(); } + try { stopDaemon(); } catch (...) { ignoreExceptionInDestructor(); } } @@ -1531,7 +1531,7 @@ void LocalDerivationGoal::startDaemon() NotTrusted, daemon::Recursive); debug("terminated daemon connection"); } catch (SystemError &) { - ignoreException(); + ignoreExceptionExceptInterrupt(); } }); diff --git a/src/libstore/worker-protocol-connection.cc b/src/libstore/worker-protocol-connection.cc index ae434c7f0..6585df4be 100644 --- a/src/libstore/worker-protocol-connection.cc +++ b/src/libstore/worker-protocol-connection.cc @@ -12,7 +12,7 @@ WorkerProto::BasicClientConnection::~BasicClientConnection() try { to.flush(); } catch (...) { - ignoreException(); + ignoreExceptionInDestructor(); } } diff --git a/src/libutil/current-process.cc b/src/libutil/current-process.cc index ed1c1ca6c..ac01f441e 100644 --- a/src/libutil/current-process.cc +++ b/src/libutil/current-process.cc @@ -45,7 +45,7 @@ unsigned int getMaxCPU() auto period = cpuMaxParts[1]; if (quota != "max") return std::ceil(std::stoi(quota) / std::stof(period)); - } catch (Error &) { ignoreException(lvlDebug); } + } catch (Error &) { ignoreExceptionInDestructor(lvlDebug); } #endif return 0; diff --git a/src/libutil/file-descriptor.cc b/src/libutil/file-descriptor.cc index 4c5daf398..3d8d70fdb 100644 --- a/src/libutil/file-descriptor.cc +++ b/src/libutil/file-descriptor.cc @@ -2,6 +2,7 @@ #include "signals.hh" #include "finally.hh" #include "serialise.hh" +#include "util.hh" #include #include @@ -65,7 +66,7 @@ AutoCloseFD::~AutoCloseFD() try { close(); } catch (...) { - ignoreException(); + ignoreExceptionInDestructor(); } } diff --git a/src/libutil/file-system.cc b/src/libutil/file-system.cc index edcacb50a..224b78b23 100644 --- a/src/libutil/file-system.cc +++ b/src/libutil/file-system.cc @@ -5,6 +5,7 @@ #include "signals.hh" #include "finally.hh" #include "serialise.hh" +#include "util.hh" #include #include @@ -517,7 +518,7 @@ AutoDelete::~AutoDelete() } } } catch (...) { - ignoreException(); + ignoreExceptionInDestructor(); } } diff --git a/src/libutil/logging.cc b/src/libutil/logging.cc index 29427f2f6..3ef71a716 100644 --- a/src/libutil/logging.cc +++ b/src/libutil/logging.cc @@ -346,7 +346,7 @@ Activity::~Activity() try { logger.stopActivity(id); } catch (...) { - ignoreException(); + ignoreExceptionInDestructor(); } } diff --git a/src/libutil/serialise.cc b/src/libutil/serialise.cc index 4aa5ae385..168d2ed32 100644 --- a/src/libutil/serialise.cc +++ b/src/libutil/serialise.cc @@ -1,5 +1,6 @@ #include "serialise.hh" #include "signals.hh" +#include "util.hh" #include #include @@ -52,7 +53,7 @@ void BufferedSink::flush() FdSink::~FdSink() { - try { flush(); } catch (...) { ignoreException(); } + try { flush(); } catch (...) { ignoreExceptionInDestructor(); } } diff --git a/src/libutil/serialise.hh b/src/libutil/serialise.hh index 4bb1a3e4b..d9e34e1e0 100644 --- a/src/libutil/serialise.hh +++ b/src/libutil/serialise.hh @@ -503,7 +503,7 @@ struct FramedSource : Source } } } catch (...) { - ignoreException(); + ignoreExceptionInDestructor(); } } @@ -550,7 +550,7 @@ struct FramedSink : nix::BufferedSink to << 0; to.flush(); } catch (...) { - ignoreException(); + ignoreExceptionInDestructor(); } } diff --git a/src/libutil/thread-pool.cc b/src/libutil/thread-pool.cc index 0f6349642..0355e1f07 100644 --- a/src/libutil/thread-pool.cc +++ b/src/libutil/thread-pool.cc @@ -111,9 +111,8 @@ void ThreadPool::doWork(bool mainThread) try { std::rethrow_exception(exc); } catch (std::exception & e) { - if (!dynamic_cast(&e) && - !dynamic_cast(&e)) - ignoreException(); + if (!dynamic_cast(&e)) + ignoreExceptionExceptInterrupt(); } catch (...) { } } diff --git a/src/libutil/unix/signals.cc b/src/libutil/unix/signals.cc index 7e30687d8..d0608dace 100644 --- a/src/libutil/unix/signals.cc +++ b/src/libutil/unix/signals.cc @@ -91,7 +91,7 @@ void unix::triggerInterrupt() try { callback(); } catch (...) { - ignoreException(); + ignoreExceptionInDestructor(); } } } diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 0d728e2d5..ed5c7e4f1 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -1,6 +1,7 @@ #include "util.hh" #include "fmt.hh" #include "file-path.hh" +#include "signals.hh" #include #include @@ -182,7 +183,7 @@ std::string shellEscape(const std::string_view s) } -void ignoreException(Verbosity lvl) +void ignoreExceptionInDestructor(Verbosity lvl) { /* Make sure no exceptions leave this function. printError() also throws when remote is closed. */ @@ -195,6 +196,17 @@ void ignoreException(Verbosity lvl) } catch (...) { } } +void ignoreExceptionExceptInterrupt(Verbosity lvl) +{ + try { + throw; + } catch (const Interrupted & e) { + throw; + } catch (std::exception & e) { + printMsg(lvl, "error (ignored): %1%", e.what()); + } +} + constexpr char base64Chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; diff --git a/src/libutil/util.hh b/src/libutil/util.hh index 75a4af76e..0fb6ff837 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -156,9 +156,26 @@ std::string toLower(std::string s); std::string shellEscape(const std::string_view s); -/* Exception handling in destructors: print an error message, then - ignore the exception. */ -void ignoreException(Verbosity lvl = lvlError); +/** + * Exception handling in destructors: print an error message, then + * ignore the exception. + * + * If you're not in a destructor, you usually want to use `ignoreExceptionExceptInterrupt()`. + * + * This function might also be used in callbacks whose caller may not handle exceptions, + * but ideally we propagate the exception using an exception_ptr in such cases. + * See e.g. `PackBuilderContext` + */ +void ignoreExceptionInDestructor(Verbosity lvl = lvlError); + +/** + * Not destructor-safe. + * Print an error message, then ignore the exception. + * If the exception is an `Interrupted` exception, rethrow it. + * + * This may be used in a few places where Interrupt can't happen, but that's ok. + */ +void ignoreExceptionExceptInterrupt(Verbosity lvl = lvlError); diff --git a/src/nix/develop.cc b/src/nix/develop.cc index 04672e2ad..c7a733025 100644 --- a/src/nix/develop.cc +++ b/src/nix/develop.cc @@ -672,7 +672,7 @@ struct CmdDevelop : Common, MixEnvironment throw Error("package 'nixpkgs#bashInteractive' does not provide a 'bin/bash'"); } catch (Error &) { - ignoreException(); + ignoreExceptionExceptInterrupt(); } // Override SHELL with the one chosen for this environment. diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 8e109b327..640a80aed 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -372,9 +372,11 @@ struct CmdFlakeCheck : FlakeCommand auto reportError = [&](const Error & e) { try { throw e; + } catch (Interrupted & e) { + throw; } catch (Error & e) { if (settings.keepGoing) { - ignoreException(); + ignoreExceptionExceptInterrupt(); hasErrors = true; } else From 4e313606379f3020cee15f248b9b9c5853aa5ca9 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 30 Sep 2024 13:02:51 +0200 Subject: [PATCH 257/718] Reference issue in tests/functional/flakes/run.sh --- tests/functional/flakes/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/functional/flakes/run.sh b/tests/functional/flakes/run.sh index 9c31dc134..6efdd673b 100755 --- a/tests/functional/flakes/run.sh +++ b/tests/functional/flakes/run.sh @@ -37,7 +37,7 @@ env > $TEST_ROOT/expected-env nix run -f shell-hello.nix env > $TEST_ROOT/actual-env # Remove/reset variables we expect to be different. # - PATH is modified by nix shell -# - we unset TMPDIR on macOS if it contains /var/folders +# - we unset TMPDIR on macOS if it contains /var/folders. bad. https://github.com/NixOS/nix/issues/7731 # - _ is set by bash and is expected to differ because it contains the original command # - __CF_USER_TEXT_ENCODING is set by macOS and is beyond our control sed -i \ From 1f024ecfcdc248214c5b4ad8f7b1c8a959fd522c Mon Sep 17 00:00:00 2001 From: Bryan Honof Date: Mon, 30 Sep 2024 14:42:47 +0200 Subject: [PATCH 258/718] fix: warn on malformed URI query parameter --- src/libflake/flake/flakeref.cc | 2 +- src/libutil/url.cc | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/libflake/flake/flakeref.cc b/src/libflake/flake/flakeref.cc index a57fce9f3..01fe747f9 100644 --- a/src/libflake/flake/flakeref.cc +++ b/src/libflake/flake/flakeref.cc @@ -88,7 +88,7 @@ std::pair parsePathFlakeRefWithFragment( if (fragmentStart != std::string::npos) { fragment = percentDecode(url.substr(fragmentStart+1)); } - if (pathEnd != std::string::npos && fragmentStart != std::string::npos) { + if (pathEnd != std::string::npos && fragmentStart != std::string::npos && url[pathEnd] == '?') { query = decodeQuery(url.substr(pathEnd+1, fragmentStart-pathEnd-1)); } diff --git a/src/libutil/url.cc b/src/libutil/url.cc index bcbe9ea4e..9ed49dcbe 100644 --- a/src/libutil/url.cc +++ b/src/libutil/url.cc @@ -79,10 +79,14 @@ std::map decodeQuery(const std::string & query) for (auto s : tokenizeString(query, "&")) { auto e = s.find('='); - if (e != std::string::npos) - result.emplace( - s.substr(0, e), - percentDecode(std::string_view(s).substr(e + 1))); + if (e == std::string::npos) { + warn("dubious URI query '%s' is missing equal sign '%s', ignoring", s, "="); + continue; + } + + result.emplace( + s.substr(0, e), + percentDecode(std::string_view(s).substr(e + 1))); } return result; From 5150a962f53cfd702315ed96fb5ce395af6e94a4 Mon Sep 17 00:00:00 2001 From: Bryan Honof Date: Mon, 30 Sep 2024 14:43:15 +0200 Subject: [PATCH 259/718] test(functional/flakes): add dubious-query MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jörg Thalheim --- tests/functional/flakes/dubious-query.sh | 31 ++++++++++++++++++++++++ tests/functional/flakes/local.mk | 3 ++- tests/functional/flakes/meson.build | 1 + 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 tests/functional/flakes/dubious-query.sh diff --git a/tests/functional/flakes/dubious-query.sh b/tests/functional/flakes/dubious-query.sh new file mode 100644 index 000000000..b481b5f81 --- /dev/null +++ b/tests/functional/flakes/dubious-query.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +source ./common.sh + +requireGit + +repoDir="$TEST_ROOT/repo" +createGitRepo "$repoDir" +createSimpleGitFlake "$repoDir" + +# Check that a flakeref without a query is accepted correctly. +expectStderr 0 nix --offline build --dry-run "git+file://$repoDir#foo" + +# Check that a flakeref with a good query is accepted correctly. +expectStderr 0 nix --offline build --dry-run "git+file://$repoDir?foo=bar#foo" + +# Check that we get the dubious query warning, when passing in a query without an equal sign. +expectStderr 0 nix --offline build --dry-run "git+file://$repoDir?bar#foo" \ + | grepQuiet "warning: dubious URI query 'bar' is missing equal sign '=', ignoring" + +# Check that the anchor (#) is taken as a whole, not split, and throws an error. +expectStderr 1 nix --offline build --dry-run "git+file://$repoDir#foo?bar" \ + | grepQuiet "error: flake 'git+file://$repoDir' does not provide attribute 'packages.$system.foo?bar', 'legacyPackages.$system.foo?bar' or 'foo?bar'" + +# Check that a literal `?` in the query doesn't print dubious query warning. +expectStderr 0 nix --offline build --dry-run "git+file://$repoDir?#foo" \ + | grepInverse "warning: dubious URI query " + +# Check that a literal `?=` in the query doesn't print dubious query warning. +expectStderr 0 nix --offline build --dry-run "git+file://$repoDir?=#foo" \ + | grepInverse "warning: dubious URI query " diff --git a/tests/functional/flakes/local.mk b/tests/functional/flakes/local.mk index 71e50ad07..a37840240 100644 --- a/tests/functional/flakes/local.mk +++ b/tests/functional/flakes/local.mk @@ -19,6 +19,7 @@ flake-tests := \ $(d)/eval-cache.sh \ $(d)/search-root.sh \ $(d)/config.sh \ - $(d)/show.sh + $(d)/show.sh \ + $(d)/dubious-query.sh install-tests-groups += flake diff --git a/tests/functional/flakes/meson.build b/tests/functional/flakes/meson.build index 8c1afd6ff..4f455fcce 100644 --- a/tests/functional/flakes/meson.build +++ b/tests/functional/flakes/meson.build @@ -23,6 +23,7 @@ suites += { 'search-root.sh', 'config.sh', 'show.sh', + 'dubious-query.sh', ], 'workdir': meson.current_build_dir(), } From f8268cbe1618c723a4332a7de9e23f027b871779 Mon Sep 17 00:00:00 2001 From: Yann Hamdaoui Date: Thu, 26 Sep 2024 18:17:31 +0200 Subject: [PATCH 260/718] Fix NAR tests on Linux+ZFS+normalize A test added recently checks that when trying to deserialize a NAR with two files that Unicode-normalize to the same result either succeeds on Linux, or fails with an "already exists" error on Darwin. However, failing with an "already exists" error can in fact also happen on Linux, when using ZFS with the proper utf8 and Unicode normalization options set. This commit fixes the issue by not assuming the behavior from the current system, but just by blindly checking that either one of the two aforementioned possibilities happen, whether on Darwin or on Linux. Additionally, we check that the Unicode normalization behaviour of nix-store is the same as the host file system. --- tests/functional/nars.sh | 44 ++++++++++++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/tests/functional/nars.sh b/tests/functional/nars.sh index 28876e497..cf2823116 100755 --- a/tests/functional/nars.sh +++ b/tests/functional/nars.sh @@ -88,17 +88,49 @@ touch "$TEST_ROOT/case/xt_CONNMARK.h~nix~case~hack~3" rm -rf "$TEST_ROOT/case" expectStderr 1 nix-store "${opts[@]}" --restore "$TEST_ROOT/case" < case-collision.nar | grepQuiet "NAR contains file name 'test' that collides with case-hacked file name 'Test~nix~case~hack~1'" -# Deserializing a NAR that contains file names that Unicode-normalize -# to the same name should fail on macOS but succeed on Linux. +# Deserializing a NAR that contains file names that Unicode-normalize to the +# same name should fail on macOS and specific Linux setups (typically ZFS with +# `utf8only` enabled and `normalization` set to anything else than `none`). The +# deserialization should succeed on most Linux, where file names aren't +# unicode-normalized. +# +# We test that: +# +# 1. It either succeeds or fails with "already exists" error. +# 2. Nix has the same behavior with respect to unicode normalization than +# $TEST_ROOT's filesystem (when using basic Unix commands) rm -rf "$TEST_ROOT/out" -if [[ $(uname) = Darwin ]]; then - expectStderr 1 nix-store --restore "$TEST_ROOT/out" < unnormalized.nar | grepQuiet "path '.*/out/â' already exists" -else - nix-store --restore "$TEST_ROOT/out" < unnormalized.nar +set +e +unicodeTestOut=$(nix-store --restore "$TEST_ROOT/out" < unnormalized.nar 2>&1) +unicodeTestCode=$? +touch "$TEST_ROOT/unicode-â" +touch "$TEST_ROOT/unicode-â" +set -e + +touchFilesCount=$(find "$TEST_ROOT" -maxdepth 1 -name "unicode-*" -type f | wc -l) + +if (( unicodeTestCode == 1 )); then + # If the command failed (MacOS or ZFS + normalization), checks that it failed + # with the expected "already exists" error, and that this is the same + # behavior as `touch` + echo "$unicodeTestOut" | grepQuiet "path '.*/out/â' already exists" + + (( touchFilesCount == 1 )) +elif (( unicodeTestCode == 0 )); then + # If the command succeeded, check that both files are present, and that this + # is the same behavior as `touch` [[ -e $TEST_ROOT/out/â ]] [[ -e $TEST_ROOT/out/â ]] + + (( touchFilesCount == 2 )) +else + # if the return code is neither 0 or 1, fail the test. + echo "NAR deserialization of files with the same Unicode normalization failed with unexpected return code $unicodeTestCode" >&2 + exit 1 fi +rm -f "$TEST_ROOT/unicode-*" + # Unpacking a NAR with a NUL character in a file name should fail. rm -rf "$TEST_ROOT/out" expectStderr 1 nix-store --restore "$TEST_ROOT/out" < nul.nar | grepQuiet "NAR contains invalid file name 'f" From c7db10000c8e7d3c79ab958ff545ba8b3c748a60 Mon Sep 17 00:00:00 2001 From: Philipp Otterbein Date: Mon, 30 Sep 2024 21:27:06 +0200 Subject: [PATCH 261/718] fix: include missing header when GC is disabled --- src/libexpr/eval-gc.hh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libexpr/eval-gc.hh b/src/libexpr/eval-gc.hh index 3b420e418..af248f589 100644 --- a/src/libexpr/eval-gc.hh +++ b/src/libexpr/eval-gc.hh @@ -13,6 +13,8 @@ #else +# include + /* Some dummy aliases for Boehm GC definitions to reduce the number of #ifdefs. */ From 5cf6b2cb75f6d0facecaa457fd31cb525436e157 Mon Sep 17 00:00:00 2001 From: Philipp Otterbein Date: Mon, 30 Sep 2024 22:15:04 +0200 Subject: [PATCH 262/718] eval: remove superfluous strdup --- src/libexpr/eval-gc.hh | 1 - src/libexpr/eval.cc | 16 ++++------------ 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/src/libexpr/eval-gc.hh b/src/libexpr/eval-gc.hh index 3b420e418..8f0b32c1c 100644 --- a/src/libexpr/eval-gc.hh +++ b/src/libexpr/eval-gc.hh @@ -23,7 +23,6 @@ template using gc_allocator = std::allocator; # define GC_MALLOC_ATOMIC std::malloc -# define GC_STRDUP strdup struct gc {}; diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 379839ce3..9eae6078b 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -53,15 +53,6 @@ static char * allocString(size_t size) } -static char * dupString(const char * s) -{ - char * t; - t = GC_STRDUP(s); - if (!t) throw std::bad_alloc(); - return t; -} - - // When there's no need to write to the string, we can optimize away empty // string allocations. // This function handles makeImmutableString(std::string_view()) by returning @@ -832,9 +823,10 @@ static const char * * encodeContext(const NixStringContext & context) size_t n = 0; auto ctx = (const char * *) allocBytes((context.size() + 1) * sizeof(char *)); - for (auto & i : context) - ctx[n++] = dupString(i.to_string().c_str()); - ctx[n] = 0; + for (auto & i : context) { + ctx[n++] = makeImmutableString({i.to_string()}); + } + ctx[n] = nullptr; return ctx; } else return nullptr; From d2f627dda9bcbf887c5b6c68e637c1e18bb043e0 Mon Sep 17 00:00:00 2001 From: Kevin Cox Date: Mon, 30 Sep 2024 17:27:49 -0400 Subject: [PATCH 263/718] Improve documentation of `nix flake lock` The previous documentation was inaccurate, stating that it would not update existing inputs. However these inputs will be updated if they are outdated (for example the version of an existing input has been changed). The new text properly reflects this behaviour. --- src/nix/flake-lock.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/nix/flake-lock.md b/src/nix/flake-lock.md index 6d10258e3..d13666a4c 100644 --- a/src/nix/flake-lock.md +++ b/src/nix/flake-lock.md @@ -30,9 +30,9 @@ R""( # Description -This command adds inputs to the lock file of a flake (`flake.lock`) -so that it contains a lock for every flake input specified in -`flake.nix`. Existing lock file entries are not updated. +This command updates the lock file of a flake (`flake.lock`) +so that it contains an up-to-date lock for every flake input specified in +`flake.nix`. Lock file entries are aready up-to-date are not modified. If you want to update existing lock entries, use [`nix flake update`](@docroot@/command-ref/new-cli/nix3-flake-update.md) From 348cca088c420cbbbae409bd9d6b6ec4b44c47e7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Sep 2024 22:28:36 +0000 Subject: [PATCH 264/718] Bump cachix/install-nix-action from V28 to 29 Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from V28 to 29. This release includes the previously tagged commit. - [Release notes](https://github.com/cachix/install-nix-action/releases) - [Commits](https://github.com/cachix/install-nix-action/compare/V28...v29) --- updated-dependencies: - dependency-name: cachix/install-nix-action dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 30272ecf1..99e50d198 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 - - uses: cachix/install-nix-action@V28 + - uses: cachix/install-nix-action@v29 with: # The sandbox would otherwise be disabled by default on Darwin extra_nix_config: "sandbox = true" @@ -89,7 +89,7 @@ jobs: with: fetch-depth: 0 - run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV - - uses: cachix/install-nix-action@V28 + - uses: cachix/install-nix-action@v29 with: install_url: https://releases.nixos.org/nix/nix-2.20.3/install - uses: cachix/cachix-action@v15 @@ -112,7 +112,7 @@ jobs: steps: - uses: actions/checkout@v4 - run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV - - uses: cachix/install-nix-action@V28 + - uses: cachix/install-nix-action@v29 with: install_url: '${{needs.installer.outputs.installerURL}}' install_options: "--tarball-url-prefix https://${{ env.CACHIX_NAME }}.cachix.org/serve" @@ -142,7 +142,7 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 - - uses: cachix/install-nix-action@V28 + - uses: cachix/install-nix-action@v29 with: install_url: https://releases.nixos.org/nix/nix-2.20.3/install - run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV From b6656160ba95a623f276c9bd92e4a0f820f1b96b Mon Sep 17 00:00:00 2001 From: Valentin Gagarin Date: Tue, 1 Oct 2024 17:28:43 +0200 Subject: [PATCH 265/718] doc: don't use bash substitution in install command --- doc/manual/src/installation/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/manual/src/installation/index.md b/doc/manual/src/installation/index.md index 16a7f485a..48725c1ba 100644 --- a/doc/manual/src/installation/index.md +++ b/doc/manual/src/installation/index.md @@ -23,7 +23,7 @@ This option requires either: > when running Nix commands, refer to GitHub issue [NixOS/nix#10892](https://github.com/NixOS/nix/issues/10892) for instructions to fix your installation without reinstalling. ```console -$ bash <(curl -L https://nixos.org/nix/install) --daemon +$ curl -L https://nixos.org/nix/install | sh -s -- --daemon ``` ## Single-user @@ -36,7 +36,7 @@ cannot offer equivalent sharing, isolation, or security. This option is suitable for systems without systemd. ```console -$ bash <(curl -L https://nixos.org/nix/install) --no-daemon +$ curl -L https://nixos.org/nix/install | sh -s -- --no-daemon ``` ## Distributions From 071ddbed57482db8fcbf303fe6754b2cca789e61 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Thu, 3 Oct 2024 01:17:33 +0200 Subject: [PATCH 266/718] doc/manual: Fix some broken fragments --- doc/manual/src/command-ref/nix-env.md | 2 +- doc/manual/src/language/derivations.md | 4 ++-- doc/manual/src/language/operators.md | 4 ++-- doc/manual/src/release-notes/rl-2.23.md | 2 +- src/libcmd/installables.cc | 2 +- src/nix/shell.md | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/manual/src/command-ref/nix-env.md b/doc/manual/src/command-ref/nix-env.md index c6f627365..bda02149e 100644 --- a/doc/manual/src/command-ref/nix-env.md +++ b/doc/manual/src/command-ref/nix-env.md @@ -62,7 +62,7 @@ These pages can be viewed offline: Several operations, such as [`nix-env --query`](./nix-env/query.md) and [`nix-env --install`](./nix-env/install.md), take a list of *arguments* that specify the packages on which to operate. -Packages are identified based on a `name` part and a `version` part of a [symbolic derivation name](@docroot@/language/derivations.md#attr-names): +Packages are identified based on a `name` part and a `version` part of a [symbolic derivation name](@docroot@/language/derivations.md#attr-name): - `name`: Everything up to but not including the first dash (`-`) that is *not* followed by a letter. - `version`: The rest, excluding the separating dash. diff --git a/doc/manual/src/language/derivations.md b/doc/manual/src/language/derivations.md index 8e3f0f791..771b2bd91 100644 --- a/doc/manual/src/language/derivations.md +++ b/doc/manual/src/language/derivations.md @@ -113,7 +113,7 @@ It outputs an attribute set, and produces a [store derivation] as a side effect ### Optional -- [`args`]{#attr-args} ([List](@docroot@/language/types.md#list) of [String](@docroot@/language/types.md#type-string)) +- [`args`]{#attr-args} ([List](@docroot@/language/types.md#type-list) of [String](@docroot@/language/types.md#type-string)) Default: `[ ]` @@ -132,7 +132,7 @@ It outputs an attribute set, and produces a [store derivation] as a side effect > }; > ``` -- [`outputs`]{#attr-outputs} ([List](@docroot@/language/types.md#list) of [String](@docroot@/language/types.md#type-string)) +- [`outputs`]{#attr-outputs} ([List](@docroot@/language/types.md#type-list) of [String](@docroot@/language/types.md#type-string)) Default: `[ "out" ]` diff --git a/doc/manual/src/language/operators.md b/doc/manual/src/language/operators.md index 27444258a..e2ed3fbed 100644 --- a/doc/manual/src/language/operators.md +++ b/doc/manual/src/language/operators.md @@ -33,7 +33,7 @@ [path]: ./types.md#type-path [number]: ./types.md#type-float [list]: ./types.md#type-list -[attribute set]: ./types.md#attribute-set +[attribute set]: ./types.md#type-attrs @@ -75,7 +75,7 @@ The result is a [Boolean] value. See also: [`builtins.hasAttr`](@docroot@/language/builtins.md#builtins-hasAttr) -[Boolean]: ./types.md#type-boolean +[Boolean]: ./types.md#type-bool [Has attribute]: #has-attribute diff --git a/doc/manual/src/release-notes/rl-2.23.md b/doc/manual/src/release-notes/rl-2.23.md index 76e9534a8..249c183e6 100644 --- a/doc/manual/src/release-notes/rl-2.23.md +++ b/doc/manual/src/release-notes/rl-2.23.md @@ -96,7 +96,7 @@ Nix can now warn when evaluation of a Nix expression causes a large path to be copied to the Nix store. The threshold for this warning can be configured using [the `warn-large-path-threshold` - setting](@docroot@/command-ref/conf-file.md#warn-large-path-threshold), + setting](@docroot@/command-ref/conf-file.md#conf-warn-large-path-threshold), e.g. `--warn-large-path-threshold 100M` will warn about paths larger than 100 MiB. diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc index 22e7eb546..f9d6d8ce8 100644 --- a/src/libcmd/installables.cc +++ b/src/libcmd/installables.cc @@ -88,7 +88,7 @@ MixFlakeOptions::MixFlakeOptions() > **DEPRECATED** > - > Use [`--no-use-registries`](#opt-no-use-registries) instead. + > Use [`--no-use-registries`](@docroot@/command-ref/conf-file.md#conf-use-registries) instead. )", .category = category, .handler = {[&]() { diff --git a/src/nix/shell.md b/src/nix/shell.md index 7c315fb3f..677151a85 100644 --- a/src/nix/shell.md +++ b/src/nix/shell.md @@ -48,7 +48,7 @@ R""( # Description `nix shell` runs a command in an environment in which the `$PATH` variable -provides the specified [*installables*](./nix.md#installable). If no command is specified, it starts the +provides the specified [*installables*](./nix.md#installables). If no command is specified, it starts the default shell of your user account specified by `$SHELL`. # Use as a `#!`-interpreter From 94f649fad55432e75e5f22815738b90f9cd81c57 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 3 Oct 2024 15:56:30 +0200 Subject: [PATCH 267/718] Cleanup: Remove migrations for ancient CA schemas These versions are more than 3 years old and were very early in the existence of CA derivations support (which was and is experimental), so they're unlikely to still exist in the real world. So let's get rid of support for them. --- src/libstore/local-store.cc | 59 ++----------------------------------- 1 file changed, 3 insertions(+), 56 deletions(-) diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 394ee2cc1..7d6c82b03 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -93,7 +93,7 @@ struct LocalStore::State::Stmts { SQLiteStmt AddRealisationReference; }; -int getSchema(Path schemaPath) +static int getSchema(Path schemaPath) { int curSchema = 0; if (pathExists(schemaPath)) { @@ -130,61 +130,8 @@ void migrateCASchema(SQLite& db, Path schemaPath, AutoCloseFD& lockFd) curCASchema = nixCASchemaVersion; } - if (curCASchema < 2) { - SQLiteTxn txn(db); - // Ugly little sql dance to add a new `id` column and make it the primary key - db.exec(R"( - create table Realisations2 ( - id integer primary key autoincrement not null, - drvPath text not null, - outputName text not null, -- symbolic output id, usually "out" - outputPath integer not null, - signatures text, -- space-separated list - foreign key (outputPath) references ValidPaths(id) on delete cascade - ); - insert into Realisations2 (drvPath, outputName, outputPath, signatures) - select drvPath, outputName, outputPath, signatures from Realisations; - drop table Realisations; - alter table Realisations2 rename to Realisations; - )"); - db.exec(R"( - create index if not exists IndexRealisations on Realisations(drvPath, outputName); - - create table if not exists RealisationsRefs ( - referrer integer not null, - realisationReference integer, - foreign key (referrer) references Realisations(id) on delete cascade, - foreign key (realisationReference) references Realisations(id) on delete restrict - ); - )"); - txn.commit(); - } - - if (curCASchema < 3) { - SQLiteTxn txn(db); - // Apply new indices added in this schema update. - db.exec(R"( - -- used by QueryRealisationReferences - create index if not exists IndexRealisationsRefs on RealisationsRefs(referrer); - -- used by cascade deletion when ValidPaths is deleted - create index if not exists IndexRealisationsRefsOnOutputPath on Realisations(outputPath); - )"); - txn.commit(); - } - if (curCASchema < 4) { - SQLiteTxn txn(db); - db.exec(R"( - create trigger if not exists DeleteSelfRefsViaRealisations before delete on ValidPaths - begin - delete from RealisationsRefs where realisationReference in ( - select id from Realisations where outputPath = old.id - ); - end; - -- used by deletion trigger - create index if not exists IndexRealisationsRefsRealisationReference on RealisationsRefs(realisationReference); - )"); - txn.commit(); - } + if (curCASchema < 4) + throw Error("experimental CA schema version %d is no longer supported", curCASchema); writeFile(schemaPath, fmt("%d", nixCASchemaVersion), 0666, true); lockFile(lockFd.get(), ltRead, true); From 15e5684884b282ac116ad7007e63e0862929c505 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 4 Oct 2024 14:56:43 +0200 Subject: [PATCH 268/718] experimental-features.hh: Don't include json-utils.hh This caused nlohmann/json.hpp to leak into a lot of compilation units, which is slow (when not using precompiled headers). Cuts build time from 46m24s to 42m5s (real time with -j24: 2m42s to 2m24s). --- src/libexpr/primops/fetchTree.cc | 2 ++ src/libfetchers/git.cc | 2 +- src/libflake/flake/flake.cc | 2 ++ src/libstore/derivations.cc | 5 +++-- src/libstore/local-store.cc | 2 ++ src/libstore/nar-info.cc | 1 + src/libutil/config-global.cc | 2 ++ src/libutil/experimental-features.hh | 9 ++------- src/libutil/json-utils.hh | 9 ++++++++- src/nix/main.cc | 1 + tests/unit/libstore/derivation-advanced-attrs.cc | 2 +- 11 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc index 1004d79ee..d2266e2bc 100644 --- a/src/libexpr/primops/fetchTree.cc +++ b/src/libexpr/primops/fetchTree.cc @@ -11,6 +11,8 @@ #include "value-to-json.hh" #include "fetch-to-store.hh" +#include + #include #include #include diff --git a/src/libfetchers/git.cc b/src/libfetchers/git.cc index 5c6b3d3cc..99d91919e 100644 --- a/src/libfetchers/git.cc +++ b/src/libfetchers/git.cc @@ -13,8 +13,8 @@ #include "git-utils.hh" #include "logging.hh" #include "finally.hh" - #include "fetch-settings.hh" +#include "json-utils.hh" #include #include diff --git a/src/libflake/flake/flake.cc b/src/libflake/flake/flake.cc index 35db13f7e..d18e01464 100644 --- a/src/libflake/flake/flake.cc +++ b/src/libflake/flake/flake.cc @@ -13,6 +13,8 @@ #include "value-to-json.hh" #include "local-fs-store.hh" +#include + namespace nix { using namespace flake; diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc index 8f9c71851..9b6f67852 100644 --- a/src/libstore/derivations.cc +++ b/src/libstore/derivations.cc @@ -7,11 +7,12 @@ #include "split.hh" #include "common-protocol.hh" #include "common-protocol-impl.hh" +#include "strings-inline.hh" +#include "json-utils.hh" + #include #include -#include "strings-inline.hh" - namespace nix { std::optional DerivationOutput::path(const StoreDirConfig & store, std::string_view drvName, OutputNameView outputName) const diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 7d6c82b03..eafdac0cd 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -50,6 +50,8 @@ #include +#include + #include "strings.hh" diff --git a/src/libstore/nar-info.cc b/src/libstore/nar-info.cc index 2442a7b09..8b2557060 100644 --- a/src/libstore/nar-info.cc +++ b/src/libstore/nar-info.cc @@ -2,6 +2,7 @@ #include "nar-info.hh" #include "store-api.hh" #include "strings.hh" +#include "json-utils.hh" namespace nix { diff --git a/src/libutil/config-global.cc b/src/libutil/config-global.cc index 4c08898a4..3ed1dd1d3 100644 --- a/src/libutil/config-global.cc +++ b/src/libutil/config-global.cc @@ -1,5 +1,7 @@ #include "config-global.hh" +#include + namespace nix { bool GlobalConfig::set(const std::string & name, const std::string & value) diff --git a/src/libutil/experimental-features.hh b/src/libutil/experimental-features.hh index e65e51280..412bf0886 100644 --- a/src/libutil/experimental-features.hh +++ b/src/libutil/experimental-features.hh @@ -2,9 +2,10 @@ ///@file #include "error.hh" -#include "json-utils.hh" #include "types.hh" +#include + namespace nix { /** @@ -98,10 +99,4 @@ public: void to_json(nlohmann::json &, const ExperimentalFeature &); void from_json(const nlohmann::json &, ExperimentalFeature &); -/** - * It is always rendered as a string - */ -template<> -struct json_avoids_null : std::true_type {}; - } diff --git a/src/libutil/json-utils.hh b/src/libutil/json-utils.hh index fe7a406cf..a61c9cada 100644 --- a/src/libutil/json-utils.hh +++ b/src/libutil/json-utils.hh @@ -3,12 +3,13 @@ #include #include -#include #include "types.hh" namespace nix { +enum struct ExperimentalFeature; + const nlohmann::json * get(const nlohmann::json & map, const std::string & key); nlohmann::json * get(nlohmann::json & map, const std::string & key); @@ -71,6 +72,12 @@ struct json_avoids_null> : std::true_type {}; template struct json_avoids_null> : std::true_type {}; +/** + * `ExperimentalFeature` is always rendered as a string. + */ +template<> +struct json_avoids_null : std::true_type {}; + } namespace nlohmann { diff --git a/src/nix/main.cc b/src/nix/main.cc index 7a9516d5e..eff2d60a4 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -19,6 +19,7 @@ #include "eval-cache.hh" #include "flake/flake.hh" #include "self-exe.hh" +#include "json-utils.hh" #include #include diff --git a/tests/unit/libstore/derivation-advanced-attrs.cc b/tests/unit/libstore/derivation-advanced-attrs.cc index 4d839ddab..9d2c64ef3 100644 --- a/tests/unit/libstore/derivation-advanced-attrs.cc +++ b/tests/unit/libstore/derivation-advanced-attrs.cc @@ -1,4 +1,3 @@ -#include #include #include @@ -9,6 +8,7 @@ #include "tests/characterization.hh" #include "parsed-derivations.hh" #include "types.hh" +#include "json-utils.hh" namespace nix { From 4c0c8e5428b9fe47544897877a67f1e839b6223d Mon Sep 17 00:00:00 2001 From: Philipp Otterbein Date: Fri, 4 Oct 2024 01:24:39 +0200 Subject: [PATCH 269/718] cleanup: remove superfluous std::string copies --- src/libcmd/repl.cc | 2 +- src/libexpr/eval.cc | 13 ++++--------- src/libexpr/get-drvs.cc | 9 +++++---- src/libexpr/primops.cc | 4 ++-- src/libexpr/primops/fromTOML.cc | 2 +- src/libexpr/print.cc | 2 +- src/nix-build/nix-build.cc | 4 ++-- src/nix/config-check.cc | 12 ++++++------ 8 files changed, 22 insertions(+), 26 deletions(-) diff --git a/src/libcmd/repl.cc b/src/libcmd/repl.cc index 940b16dfd..1ae126e1e 100644 --- a/src/libcmd/repl.cc +++ b/src/libcmd/repl.cc @@ -654,7 +654,7 @@ ProcessLineResult NixRepl::processLine(std::string line) ss << "No documentation found.\n\n"; } - auto markdown = ss.str(); + auto markdown = ss.view(); logger->cout(trim(renderMarkdownToTerminal(markdown))); } else diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 9eae6078b..64516fd98 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -572,16 +572,13 @@ std::optional EvalState::getDoc(Value & v) s << docStr; s << '\0'; // for making a c string below - std::string ss = s.str(); return Doc { .pos = pos, .name = name, .arity = 0, // FIXME: figure out how deep by syntax only? It's not semantically useful though... .args = {}, - .doc = - // FIXME: this leaks; make the field std::string? - strdup(ss.data()), + .doc = makeImmutableString(s.view()), // NOTE: memory leak when compiled without GC }; } if (isFunctor(v)) { @@ -1805,11 +1802,9 @@ void ExprIf::eval(EvalState & state, Env & env, Value & v) void ExprAssert::eval(EvalState & state, Env & env, Value & v) { if (!state.evalBool(env, cond, pos, "in the condition of the assert statement")) { - auto exprStr = ({ - std::ostringstream out; - cond->show(state.symbols, out); - out.str(); - }); + std::ostringstream out; + cond->show(state.symbols, out); + auto exprStr = out.view(); if (auto eq = dynamic_cast(cond)) { try { diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc index 20963ec91..1ac13fcd2 100644 --- a/src/libexpr/get-drvs.cc +++ b/src/libexpr/get-drvs.cc @@ -374,11 +374,12 @@ static void getDerivations(EvalState & state, Value & vIn, bound to the attribute with the "lower" name should take precedence). */ for (auto & i : v.attrs()->lexicographicOrder(state.symbols)) { + std::string_view symbol{state.symbols[i->name]}; try { - debug("evaluating attribute '%1%'", state.symbols[i->name]); - if (!std::regex_match(std::string(state.symbols[i->name]), attrRegex)) + debug("evaluating attribute '%1%'", symbol); + if (!std::regex_match(symbol.begin(), symbol.end(), attrRegex)) continue; - std::string pathPrefix2 = addToPath(pathPrefix, state.symbols[i->name]); + std::string pathPrefix2 = addToPath(pathPrefix, symbol); if (combineChannels) getDerivations(state, *i->value, pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures); else if (getDerivation(state, *i->value, pathPrefix2, drvs, done, ignoreAssertionFailures)) { @@ -392,7 +393,7 @@ static void getDerivations(EvalState & state, Value & vIn, } } } catch (Error & e) { - e.addTrace(state.positions[i->pos], "while evaluating the attribute '%s'", state.symbols[i->name]); + e.addTrace(state.positions[i->pos], "while evaluating the attribute '%s'", symbol); throw; } } diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 7b6f222a8..4cc0de960 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -2129,7 +2129,7 @@ static void prim_toXML(EvalState & state, const PosIdx pos, Value * * args, Valu std::ostringstream out; NixStringContext context; printValueAsXML(state, true, false, *args[0], out, context, pos); - v.mkString(out.str(), context); + v.mkString(out.view(), context); } static RegisterPrimOp primop_toXML({ @@ -2237,7 +2237,7 @@ static void prim_toJSON(EvalState & state, const PosIdx pos, Value * * args, Val std::ostringstream out; NixStringContext context; printValueAsJSON(state, true, *args[0], pos, out, context); - v.mkString(out.str(), context); + v.mkString(out.view(), context); } static RegisterPrimOp primop_toJSON({ diff --git a/src/libexpr/primops/fromTOML.cc b/src/libexpr/primops/fromTOML.cc index b4f1df7a8..15568e529 100644 --- a/src/libexpr/primops/fromTOML.cc +++ b/src/libexpr/primops/fromTOML.cc @@ -66,7 +66,7 @@ static void prim_fromTOML(EvalState & state, const PosIdx pos, Value * * args, V attrs.alloc("_type").mkString("timestamp"); std::ostringstream s; s << t; - attrs.alloc("value").mkString(s.str()); + attrs.alloc("value").mkString(s.view()); v.mkAttrs(attrs); } else { throw std::runtime_error("Dates and times are not supported"); diff --git a/src/libexpr/print.cc b/src/libexpr/print.cc index 4d1a6868c..11a6c9161 100644 --- a/src/libexpr/print.cc +++ b/src/libexpr/print.cc @@ -460,7 +460,7 @@ private: std::ostringstream s; s << state.positions[v.payload.lambda.fun->pos]; - output << " @ " << filterANSIEscapes(s.str()); + output << " @ " << filterANSIEscapes(s.view()); } } else if (v.isPrimOp()) { if (v.primOp()) diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc index a5b9e1e54..f894d1034 100644 --- a/src/nix-build/nix-build.cc +++ b/src/nix-build/nix-build.cc @@ -260,9 +260,9 @@ static void main_nix_build(int argc, char * * argv) // read the shebang to understand which packages to read from. Since // this is handled via nix-shell -p, we wrap our ruby script execution // in ruby -e 'load' which ignores the shebangs. - envCommand = fmt("exec %1% %2% -e 'load(ARGV.shift)' -- %3% %4%", execArgs, interpreter, shellEscape(script), joined.str()); + envCommand = fmt("exec %1% %2% -e 'load(ARGV.shift)' -- %3% %4%", execArgs, interpreter, shellEscape(script), joined.view()); } else { - envCommand = fmt("exec %1% %2% %3% %4%", execArgs, interpreter, shellEscape(script), joined.str()); + envCommand = fmt("exec %1% %2% %3% %4%", execArgs, interpreter, shellEscape(script), joined.view()); } } diff --git a/src/nix/config-check.cc b/src/nix/config-check.cc index 6cf73785e..be252c3f1 100644 --- a/src/nix/config-check.cc +++ b/src/nix/config-check.cc @@ -26,17 +26,17 @@ std::string formatProtocol(unsigned int proto) return "unknown"; } -bool checkPass(const std::string & msg) { +bool checkPass(std::string_view msg) { notice(ANSI_GREEN "[PASS] " ANSI_NORMAL + msg); return true; } -bool checkFail(const std::string & msg) { +bool checkFail(std::string_view msg) { notice(ANSI_RED "[FAIL] " ANSI_NORMAL + msg); return false; } -void checkInfo(const std::string & msg) { +void checkInfo(std::string_view msg) { notice(ANSI_BLUE "[INFO] " ANSI_NORMAL + msg); } @@ -91,7 +91,7 @@ struct CmdConfigCheck : StoreCommand ss << "Multiple versions of nix found in PATH:\n"; for (auto & dir : dirs) ss << " " << dir << "\n"; - return checkFail(ss.str()); + return checkFail(ss.view()); } return checkPass("PATH contains only one nix version."); @@ -132,7 +132,7 @@ struct CmdConfigCheck : StoreCommand for (auto & dir : dirs) ss << " " << dir << "\n"; ss << "\n"; - return checkFail(ss.str()); + return checkFail(ss.view()); } return checkPass("All profiles are gcroots."); @@ -151,7 +151,7 @@ struct CmdConfigCheck : StoreCommand << "sync with the daemon.\n\n" << "Client protocol: " << formatProtocol(clientProto) << "\n" << "Store protocol: " << formatProtocol(storeProto) << "\n\n"; - return checkFail(ss.str()); + return checkFail(ss.view()); } return checkPass("Client protocol matches store protocol."); From c88e90109623c785d9f4a84d18b56240f064ae74 Mon Sep 17 00:00:00 2001 From: Vinayak Kaushik <112626461+VinayakKaushikDH@users.noreply.github.com> Date: Sun, 6 Oct 2024 19:26:42 +0200 Subject: [PATCH 270/718] Fix typo in uninstall.md --- doc/manual/src/installation/uninstall.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/manual/src/installation/uninstall.md b/doc/manual/src/installation/uninstall.md index 429fcae46..47689a16e 100644 --- a/doc/manual/src/installation/uninstall.md +++ b/doc/manual/src/installation/uninstall.md @@ -100,7 +100,7 @@ which you may remove. LABEL=Nix\040Store /nix apfs rw,nobrowse ``` - by setting the cursor on the respective line using the error keys, and pressing `dd`, and then `:wq` to save the file. + by setting the cursor on the respective line using the arrow keys, and pressing `dd`, and then `:wq` to save the file. This will prevent automatic mounting of the Nix Store volume. From caf3b5589160bea3de26958b71df78ca73979398 Mon Sep 17 00:00:00 2001 From: Philipp Otterbein Date: Mon, 7 Oct 2024 01:05:17 +0200 Subject: [PATCH 271/718] cont. cleanup: remove superfluous std::string copies --- src/libexpr/primops.cc | 15 +++++++++++---- src/libstore/daemon.cc | 4 ++-- src/libstore/outputs-spec.cc | 7 +++---- src/libutil/args.cc | 2 +- src/nix-build/nix-build.cc | 6 +++--- src/nix-env/user-env.cc | 4 +--- 6 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 4cc0de960..29121bb81 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -40,6 +40,13 @@ namespace nix { * Miscellaneous *************************************************************/ +static inline Value * mkString(EvalState & state, const std::csub_match & match) +{ + Value * v = state.allocValue(); + v->mkString({match.first, match.second}); + return v; +} + StringMap EvalState::realiseContext(const NixStringContext & context, StorePathSet * maybePathsOut, bool isIFD) { std::vector drvs; @@ -4268,7 +4275,7 @@ void prim_match(EvalState & state, const PosIdx pos, Value * * args, Value & v) if (!match[i + 1].matched) v2 = &state.vNull; else - (v2 = state.allocValue())->mkString(match[i + 1].str()); + v2 = mkString(state, match[i + 1]); v.mkList(list); } catch (std::regex_error & e) { @@ -4352,7 +4359,7 @@ void prim_split(EvalState & state, const PosIdx pos, Value * * args, Value & v) auto match = *i; // Add a string for non-matched characters. - (list[idx++] = state.allocValue())->mkString(match.prefix().str()); + list[idx++] = mkString(state, match.prefix()); // Add a list for matched substrings. const size_t slen = match.size() - 1; @@ -4363,14 +4370,14 @@ void prim_split(EvalState & state, const PosIdx pos, Value * * args, Value & v) if (!match[si + 1].matched) v2 = &state.vNull; else - (v2 = state.allocValue())->mkString(match[si + 1].str()); + v2 = mkString(state, match[si + 1]); } (list[idx++] = state.allocValue())->mkList(list2); // Add a string for non-matched suffix characters. if (idx == 2 * len) - (list[idx++] = state.allocValue())->mkString(match.suffix().str()); + list[idx++] = mkString(state, match.suffix()); } assert(idx == 2 * len + 1); diff --git a/src/libstore/daemon.cc b/src/libstore/daemon.cc index 6079eae7b..f0c3c866e 100644 --- a/src/libstore/daemon.cc +++ b/src/libstore/daemon.cc @@ -90,11 +90,11 @@ struct TunnelLogger : public Logger { if (ei.level > verbosity) return; - std::stringstream oss; + std::ostringstream oss; showErrorInfo(oss, ei, false); StringSink buf; - buf << STDERR_NEXT << oss.str(); + buf << STDERR_NEXT << oss.view(); enqueueMsg(buf.s); } diff --git a/src/libstore/outputs-spec.cc b/src/libstore/outputs-spec.cc index 86788a87e..f5ecbd74b 100644 --- a/src/libstore/outputs-spec.cc +++ b/src/libstore/outputs-spec.cc @@ -30,16 +30,15 @@ std::optional OutputsSpec::parseOpt(std::string_view s) { static std::regex regex(std::string { outputSpecRegexStr }); - std::smatch match; - std::string s2 { s }; // until some improves std::regex - if (!std::regex_match(s2, match, regex)) + std::cmatch match; + if (!std::regex_match(s.cbegin(), s.cend(), match, regex)) return std::nullopt; if (match[1].matched) return { OutputsSpec::All {} }; if (match[2].matched) - return OutputsSpec::Names { tokenizeString(match[2].str(), ",") }; + return OutputsSpec::Names { tokenizeString({match[2].first, match[2].second}, ",") }; assert(false); } diff --git a/src/libutil/args.cc b/src/libutil/args.cc index d58f4b4ae..4e87389d6 100644 --- a/src/libutil/args.cc +++ b/src/libutil/args.cc @@ -293,7 +293,7 @@ void RootArgs::parseCmdline(const Strings & _cmdline, bool allowShebang) // We match one space after `nix` so that we preserve indentation. // No space is necessary for an empty line. An empty line has basically no effect. if (std::regex_match(line, match, std::regex("^#!\\s*nix(:? |$)(.*)$"))) - shebangContent += match[2].str() + "\n"; + shebangContent += std::string_view{match[2].first, match[2].second} + "\n"; } for (const auto & word : parseShebangContent(shebangContent)) { cmdline.push_back(word); diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc index f894d1034..8c52979f6 100644 --- a/src/nix-build/nix-build.cc +++ b/src/nix-build/nix-build.cc @@ -36,7 +36,7 @@ extern char * * environ __attribute__((weak)); /* Recreate the effect of the perl shellwords function, breaking up a * string into arguments like a shell word, including escapes */ -static std::vector shellwords(const std::string & s) +static std::vector shellwords(std::string_view s) { std::regex whitespace("^\\s+"); auto begin = s.cbegin(); @@ -51,7 +51,7 @@ static std::vector shellwords(const std::string & s) auto it = begin; for (; it != s.cend(); ++it) { if (st == sBegin) { - std::smatch match; + std::cmatch match; if (regex_search(it, s.cend(), match, whitespace)) { cur.append(begin, it); res.push_back(cur); @@ -173,7 +173,7 @@ static void main_nix_build(int argc, char * * argv) line = chomp(line); std::smatch match; if (std::regex_match(line, match, std::regex("^#!\\s*nix-shell\\s+(.*)$"))) - for (const auto & word : shellwords(match[1].str())) + for (const auto & word : shellwords({match[1].first, match[1].second})) args.push_back(word); } } diff --git a/src/nix-env/user-env.cc b/src/nix-env/user-env.cc index a24dd11d6..ebd8ef42b 100644 --- a/src/nix-env/user-env.cc +++ b/src/nix-env/user-env.cc @@ -111,9 +111,7 @@ bool createUserEnv(EvalState & state, PackageInfos & elems, auto manifestFile = ({ std::ostringstream str; printAmbiguous(manifest, state.symbols, str, nullptr, std::numeric_limits::max()); - // TODO with C++20 we can use str.view() instead and avoid copy. - std::string str2 = str.str(); - StringSource source { str2 }; + StringSource source { str.view() }; state.store->addToStoreFromDump( source, "env-manifest.nix", FileSerialisationMethod::Flat, ContentAddressMethod::Raw::Text, HashAlgorithm::SHA256, references); }); From e21c7895ebec83db0ae39231fba9b35b080b6b1e Mon Sep 17 00:00:00 2001 From: Philipp Otterbein Date: Mon, 7 Oct 2024 02:05:53 +0200 Subject: [PATCH 272/718] MacOS built: add workaround for missing view() member of std::ostringstream --- src/libcmd/repl.cc | 4 ++-- src/libexpr/eval.cc | 6 +++--- src/libexpr/primops.cc | 4 ++-- src/libexpr/primops/fromTOML.cc | 2 +- src/libexpr/print.cc | 2 +- src/libstore/daemon.cc | 2 +- src/libutil/strings.cc | 15 +++++++++++++++ src/libutil/strings.hh | 5 +++++ src/nix-build/nix-build.cc | 4 ++-- src/nix-env/user-env.cc | 2 +- src/nix/config-check.cc | 12 ++++++------ 11 files changed, 39 insertions(+), 19 deletions(-) diff --git a/src/libcmd/repl.cc b/src/libcmd/repl.cc index 1ae126e1e..018171889 100644 --- a/src/libcmd/repl.cc +++ b/src/libcmd/repl.cc @@ -645,7 +645,7 @@ ProcessLineResult NixRepl::processLine(std::string line) logger->cout(trim(renderMarkdownToTerminal(markdown))); } else if (fallbackPos) { - std::stringstream ss; + std::ostringstream ss; ss << "Attribute `" << fallbackName << "`\n\n"; ss << " … defined at " << state->positions[fallbackPos] << "\n\n"; if (fallbackDoc) { @@ -654,7 +654,7 @@ ProcessLineResult NixRepl::processLine(std::string line) ss << "No documentation found.\n\n"; } - auto markdown = ss.view(); + auto markdown = toView(ss); logger->cout(trim(renderMarkdownToTerminal(markdown))); } else diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 64516fd98..8fbba7c14 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -539,7 +539,7 @@ std::optional EvalState::getDoc(Value & v) if (v.isLambda()) { auto exprLambda = v.payload.lambda.fun; - std::stringstream s(std::ios_base::out); + std::ostringstream s(std::ios_base::out); std::string name; auto pos = positions[exprLambda->getPos()]; std::string docStr; @@ -578,7 +578,7 @@ std::optional EvalState::getDoc(Value & v) .name = name, .arity = 0, // FIXME: figure out how deep by syntax only? It's not semantically useful though... .args = {}, - .doc = makeImmutableString(s.view()), // NOTE: memory leak when compiled without GC + .doc = makeImmutableString(toView(s)), // NOTE: memory leak when compiled without GC }; } if (isFunctor(v)) { @@ -1804,7 +1804,7 @@ void ExprAssert::eval(EvalState & state, Env & env, Value & v) if (!state.evalBool(env, cond, pos, "in the condition of the assert statement")) { std::ostringstream out; cond->show(state.symbols, out); - auto exprStr = out.view(); + auto exprStr = toView(out); if (auto eq = dynamic_cast(cond)) { try { diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 29121bb81..a3c8a0c9c 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -2136,7 +2136,7 @@ static void prim_toXML(EvalState & state, const PosIdx pos, Value * * args, Valu std::ostringstream out; NixStringContext context; printValueAsXML(state, true, false, *args[0], out, context, pos); - v.mkString(out.view(), context); + v.mkString(toView(out), context); } static RegisterPrimOp primop_toXML({ @@ -2244,7 +2244,7 @@ static void prim_toJSON(EvalState & state, const PosIdx pos, Value * * args, Val std::ostringstream out; NixStringContext context; printValueAsJSON(state, true, *args[0], pos, out, context); - v.mkString(out.view(), context); + v.mkString(toView(out), context); } static RegisterPrimOp primop_toJSON({ diff --git a/src/libexpr/primops/fromTOML.cc b/src/libexpr/primops/fromTOML.cc index 15568e529..264046711 100644 --- a/src/libexpr/primops/fromTOML.cc +++ b/src/libexpr/primops/fromTOML.cc @@ -66,7 +66,7 @@ static void prim_fromTOML(EvalState & state, const PosIdx pos, Value * * args, V attrs.alloc("_type").mkString("timestamp"); std::ostringstream s; s << t; - attrs.alloc("value").mkString(s.view()); + attrs.alloc("value").mkString(toView(s)); v.mkAttrs(attrs); } else { throw std::runtime_error("Dates and times are not supported"); diff --git a/src/libexpr/print.cc b/src/libexpr/print.cc index 11a6c9161..d62aaf25f 100644 --- a/src/libexpr/print.cc +++ b/src/libexpr/print.cc @@ -460,7 +460,7 @@ private: std::ostringstream s; s << state.positions[v.payload.lambda.fun->pos]; - output << " @ " << filterANSIEscapes(s.view()); + output << " @ " << filterANSIEscapes(toView(s)); } } else if (v.isPrimOp()) { if (v.primOp()) diff --git a/src/libstore/daemon.cc b/src/libstore/daemon.cc index f0c3c866e..b921dbe2d 100644 --- a/src/libstore/daemon.cc +++ b/src/libstore/daemon.cc @@ -94,7 +94,7 @@ struct TunnelLogger : public Logger showErrorInfo(oss, ei, false); StringSink buf; - buf << STDERR_NEXT << oss.view(); + buf << STDERR_NEXT << toView(oss); enqueueMsg(buf.s); } diff --git a/src/libutil/strings.cc b/src/libutil/strings.cc index 5cad95758..d1c9f700c 100644 --- a/src/libutil/strings.cc +++ b/src/libutil/strings.cc @@ -6,6 +6,21 @@ namespace nix { +struct view_stringbuf : public std::stringbuf +{ + inline std::string_view toView() + { + auto begin = pbase(); + return {begin, begin + pubseekoff(0, std::ios_base::cur, std::ios_base::out)}; + } +}; + +std::string_view toView(const std::ostringstream & os) +{ + auto buf = static_cast(os.rdbuf()); + return buf->toView(); +} + template std::list tokenizeString(std::string_view s, std::string_view separators); template std::set tokenizeString(std::string_view s, std::string_view separators); template std::vector tokenizeString(std::string_view s, std::string_view separators); diff --git a/src/libutil/strings.hh b/src/libutil/strings.hh index 88b48d770..533126be1 100644 --- a/src/libutil/strings.hh +++ b/src/libutil/strings.hh @@ -8,6 +8,11 @@ namespace nix { +/* + * workaround for unavailable view() method (C++20) of std::ostringstream under MacOS with clang-16 + */ +std::string_view toView(const std::ostringstream & os); + /** * String tokenizer. * diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc index 8c52979f6..7d32a6f97 100644 --- a/src/nix-build/nix-build.cc +++ b/src/nix-build/nix-build.cc @@ -260,9 +260,9 @@ static void main_nix_build(int argc, char * * argv) // read the shebang to understand which packages to read from. Since // this is handled via nix-shell -p, we wrap our ruby script execution // in ruby -e 'load' which ignores the shebangs. - envCommand = fmt("exec %1% %2% -e 'load(ARGV.shift)' -- %3% %4%", execArgs, interpreter, shellEscape(script), joined.view()); + envCommand = fmt("exec %1% %2% -e 'load(ARGV.shift)' -- %3% %4%", execArgs, interpreter, shellEscape(script), toView(joined)); } else { - envCommand = fmt("exec %1% %2% %3% %4%", execArgs, interpreter, shellEscape(script), joined.view()); + envCommand = fmt("exec %1% %2% %3% %4%", execArgs, interpreter, shellEscape(script), toView(joined)); } } diff --git a/src/nix-env/user-env.cc b/src/nix-env/user-env.cc index ebd8ef42b..ee62077c0 100644 --- a/src/nix-env/user-env.cc +++ b/src/nix-env/user-env.cc @@ -111,7 +111,7 @@ bool createUserEnv(EvalState & state, PackageInfos & elems, auto manifestFile = ({ std::ostringstream str; printAmbiguous(manifest, state.symbols, str, nullptr, std::numeric_limits::max()); - StringSource source { str.view() }; + StringSource source { toView(str) }; state.store->addToStoreFromDump( source, "env-manifest.nix", FileSerialisationMethod::Flat, ContentAddressMethod::Raw::Text, HashAlgorithm::SHA256, references); }); diff --git a/src/nix/config-check.cc b/src/nix/config-check.cc index be252c3f1..a72b06542 100644 --- a/src/nix/config-check.cc +++ b/src/nix/config-check.cc @@ -87,11 +87,11 @@ struct CmdConfigCheck : StoreCommand } if (dirs.size() != 1) { - std::stringstream ss; + std::ostringstream ss; ss << "Multiple versions of nix found in PATH:\n"; for (auto & dir : dirs) ss << " " << dir << "\n"; - return checkFail(ss.view()); + return checkFail(toView(ss)); } return checkPass("PATH contains only one nix version."); @@ -125,14 +125,14 @@ struct CmdConfigCheck : StoreCommand } if (!dirs.empty()) { - std::stringstream ss; + std::ostringstream 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) ss << " " << dir << "\n"; ss << "\n"; - return checkFail(ss.view()); + return checkFail(toView(ss)); } return checkPass("All profiles are gcroots."); @@ -145,13 +145,13 @@ struct CmdConfigCheck : StoreCommand : PROTOCOL_VERSION; if (clientProto != storeProto) { - std::stringstream ss; + std::ostringstream 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.view()); + return checkFail(toView(ss)); } return checkPass("Client protocol matches store protocol."); From 011fa9e0859bf898b756f63733af5a1f6bce8d35 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 7 Oct 2024 14:54:35 +0200 Subject: [PATCH 273/718] tests/functional/nars.sh: Fail test if touch fails, comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jörg Thalheim --- tests/functional/nars.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/functional/nars.sh b/tests/functional/nars.sh index cf2823116..39d9389db 100755 --- a/tests/functional/nars.sh +++ b/tests/functional/nars.sh @@ -103,10 +103,11 @@ rm -rf "$TEST_ROOT/out" set +e unicodeTestOut=$(nix-store --restore "$TEST_ROOT/out" < unnormalized.nar 2>&1) unicodeTestCode=$? -touch "$TEST_ROOT/unicode-â" -touch "$TEST_ROOT/unicode-â" set -e +touch "$TEST_ROOT/unicode-â" # non-canonical version +touch "$TEST_ROOT/unicode-â" + touchFilesCount=$(find "$TEST_ROOT" -maxdepth 1 -name "unicode-*" -type f | wc -l) if (( unicodeTestCode == 1 )); then From b5c88650c57ac39a1631fda29e25c7a457e2a503 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 7 Oct 2024 10:47:57 -0400 Subject: [PATCH 274/718] Slightly more `std::filesystem` for `nix eval` Progress on #9205 --- src/nix/eval.cc | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/nix/eval.cc b/src/nix/eval.cc index 512e68711..04b18ff41 100644 --- a/src/nix/eval.cc +++ b/src/nix/eval.cc @@ -11,11 +11,13 @@ using namespace nix; +namespace nix::fs { using namespace std::filesystem; } + struct CmdEval : MixJSON, InstallableValueCommand, MixReadOnlyOption { bool raw = false; std::optional apply; - std::optional writeTo; + std::optional writeTo; CmdEval() : InstallableValueCommand() { @@ -75,20 +77,20 @@ struct CmdEval : MixJSON, InstallableValueCommand, MixReadOnlyOption if (writeTo) { stopProgressBar(); - if (pathExists(*writeTo)) - throw Error("path '%s' already exists", *writeTo); + if (fs::symlink_exists(*writeTo)) + throw Error("path '%s' already exists", writeTo->string()); - std::function recurse; + std::function recurse; - recurse = [&](Value & v, const PosIdx pos, const std::filesystem::path & path) + recurse = [&](Value & v, const PosIdx pos, const fs::path & path) { state->forceValue(v, pos); if (v.type() == nString) // FIXME: disallow strings with contexts? writeFile(path.string(), v.string_view()); else if (v.type() == nAttrs) { - // TODO abstract mkdir perms for Windows - createDir(path.string(), 0777); + // Directory should not already exist + assert(fs::create_directory(path.string())); for (auto & attr : *v.attrs()) { std::string_view name = state->symbols[attr.name]; try { From 06255654a7bd8c97edee65b800a7bbae0f46b2ea Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2024 22:41:39 +0000 Subject: [PATCH 275/718] build(deps): bump cachix/install-nix-action from 29 to 30 Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 29 to 30. - [Release notes](https://github.com/cachix/install-nix-action/releases) - [Commits](https://github.com/cachix/install-nix-action/compare/v29...v30) --- updated-dependencies: - dependency-name: cachix/install-nix-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 99e50d198..0e2e07da2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 - - uses: cachix/install-nix-action@v29 + - uses: cachix/install-nix-action@v30 with: # The sandbox would otherwise be disabled by default on Darwin extra_nix_config: "sandbox = true" @@ -89,7 +89,7 @@ jobs: with: fetch-depth: 0 - run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV - - uses: cachix/install-nix-action@v29 + - uses: cachix/install-nix-action@v30 with: install_url: https://releases.nixos.org/nix/nix-2.20.3/install - uses: cachix/cachix-action@v15 @@ -112,7 +112,7 @@ jobs: steps: - uses: actions/checkout@v4 - run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV - - uses: cachix/install-nix-action@v29 + - uses: cachix/install-nix-action@v30 with: install_url: '${{needs.installer.outputs.installerURL}}' install_options: "--tarball-url-prefix https://${{ env.CACHIX_NAME }}.cachix.org/serve" @@ -142,7 +142,7 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 - - uses: cachix/install-nix-action@v29 + - uses: cachix/install-nix-action@v30 with: install_url: https://releases.nixos.org/nix/nix-2.20.3/install - run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV From de96f632f8c68abfb80d7d45ba3ad0bc3f451bcd Mon Sep 17 00:00:00 2001 From: Philipp Otterbein Date: Tue, 8 Oct 2024 02:25:14 +0200 Subject: [PATCH 276/718] std::string_view shall not be null terminated --- src/libexpr/eval.cc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 8fbba7c14..f17753415 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -539,7 +539,7 @@ std::optional EvalState::getDoc(Value & v) if (v.isLambda()) { auto exprLambda = v.payload.lambda.fun; - std::ostringstream s(std::ios_base::out); + std::ostringstream s; std::string name; auto pos = positions[exprLambda->getPos()]; std::string docStr; @@ -571,8 +571,6 @@ std::optional EvalState::getDoc(Value & v) s << docStr; - s << '\0'; // for making a c string below - return Doc { .pos = pos, .name = name, From a353a99269a88bdf1f96a2512c2102b965b5f531 Mon Sep 17 00:00:00 2001 From: Philipp Otterbein Date: Tue, 8 Oct 2024 02:25:52 +0200 Subject: [PATCH 277/718] cont. cleanup: remove superfluous std::string copies --- src/libmain/progress-bar.cc | 4 ++-- src/libutil/logging.cc | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libmain/progress-bar.cc b/src/libmain/progress-bar.cc index e63d4f13f..22f890f7d 100644 --- a/src/libmain/progress-bar.cc +++ b/src/libmain/progress-bar.cc @@ -158,10 +158,10 @@ public: { auto state(state_.lock()); - std::stringstream oss; + std::ostringstream oss; showErrorInfo(oss, ei, loggerSettings.showTrace.get()); - log(*state, ei.level, oss.str()); + log(*state, ei.level, toView(oss)); } void log(State & state, Verbosity lvl, std::string_view s) diff --git a/src/libutil/logging.cc b/src/libutil/logging.cc index 3ef71a716..3d7371457 100644 --- a/src/libutil/logging.cc +++ b/src/libutil/logging.cc @@ -85,10 +85,10 @@ public: void logEI(const ErrorInfo & ei) override { - std::stringstream oss; + std::ostringstream oss; showErrorInfo(oss, ei, loggerSettings.showTrace.get()); - log(ei.level, oss.str()); + log(ei.level, toView(oss)); } void startActivity(ActivityId act, Verbosity lvl, ActivityType type, From 76f75e76915329c4f3502abcbea1df8e3ee658c9 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 8 Oct 2024 15:28:49 +0200 Subject: [PATCH 278/718] nix copy: Add --profile flag This allows `nix copy` to atomically copy a store path and point a profile to it, without the risk that the store path might be GC'ed in between. This is useful for instance when deploying a new NixOS system profile from a remote store. --- src/libcmd/command.cc | 35 ++++++++++++++++++++++------------- src/libcmd/command.hh | 12 ++++++++---- src/nix/build.cc | 2 +- src/nix/copy.cc | 8 +++++--- src/nix/copy.md | 9 +++++++++ src/nix/develop.cc | 2 +- src/nix/profile.cc | 6 +++--- src/nix/realisation.cc | 2 +- tests/functional/zstd.sh | 4 +++- 9 files changed, 53 insertions(+), 27 deletions(-) diff --git a/src/libcmd/command.cc b/src/libcmd/command.cc index 6d8bfc19b..e38f982d8 100644 --- a/src/libcmd/command.cc +++ b/src/libcmd/command.cc @@ -179,30 +179,34 @@ BuiltPathsCommand::BuiltPathsCommand(bool recursive) void BuiltPathsCommand::run(ref store, Installables && installables) { - BuiltPaths paths; + BuiltPaths rootPaths, allPaths; + if (all) { if (installables.size()) throw UsageError("'--all' does not expect arguments"); // XXX: Only uses opaque paths, ignores all the realisations for (auto & p : store->queryAllValidPaths()) - paths.emplace_back(BuiltPath::Opaque{p}); + rootPaths.emplace_back(BuiltPath::Opaque{p}); + allPaths = rootPaths; } else { - paths = Installable::toBuiltPaths(getEvalStore(), store, realiseMode, operateOn, installables); + rootPaths = Installable::toBuiltPaths(getEvalStore(), store, realiseMode, operateOn, installables); + allPaths = rootPaths; + if (recursive) { // XXX: This only computes the store path closure, ignoring // intermediate realisations StorePathSet pathsRoots, pathsClosure; - for (auto & root : paths) { + for (auto & root : rootPaths) { auto rootFromThis = root.outPaths(); pathsRoots.insert(rootFromThis.begin(), rootFromThis.end()); } store->computeFSClosure(pathsRoots, pathsClosure); for (auto & path : pathsClosure) - paths.emplace_back(BuiltPath::Opaque{path}); + allPaths.emplace_back(BuiltPath::Opaque{path}); } } - run(store, std::move(paths)); + run(store, std::move(allPaths), std::move(rootPaths)); } StorePathsCommand::StorePathsCommand(bool recursive) @@ -210,10 +214,10 @@ StorePathsCommand::StorePathsCommand(bool recursive) { } -void StorePathsCommand::run(ref store, BuiltPaths && paths) +void StorePathsCommand::run(ref store, BuiltPaths && allPaths, BuiltPaths && rootPaths) { StorePathSet storePaths; - for (auto & builtPath : paths) + for (auto & builtPath : allPaths) for (auto & p : builtPath.outPaths()) storePaths.insert(p); @@ -242,17 +246,21 @@ MixProfile::MixProfile() }); } -void MixProfile::updateProfile(const StorePath & storePath) +void MixProfile::updateProfile( + const StorePath & storePath, + ref store_) { if (!profile) return; - auto store = getStore().dynamic_pointer_cast(); + auto store = store_.dynamic_pointer_cast(); if (!store) throw Error("'--profile' is not supported for this Nix store"); auto profile2 = absPath(*profile); switchLink(profile2, createGeneration(*store, profile2, storePath)); } -void MixProfile::updateProfile(const BuiltPaths & buildables) +void MixProfile::updateProfile( + const BuiltPaths & buildables, + ref store) { if (!profile) return; @@ -274,7 +282,7 @@ void MixProfile::updateProfile(const BuiltPaths & buildables) if (result.size() != 1) throw UsageError("'--profile' requires that the arguments produce a single store path, but there are %d", result.size()); - updateProfile(result[0]); + updateProfile(result[0], store); } MixDefaultProfile::MixDefaultProfile() @@ -308,7 +316,8 @@ MixEnvironment::MixEnvironment() : ignoreEnvironment(false) }); } -void MixEnvironment::setEnviron() { +void MixEnvironment::setEnviron() +{ if (ignoreEnvironment) { if (!unset.empty()) throw UsageError("--unset does not make sense with --ignore-environment"); diff --git a/src/libcmd/command.hh b/src/libcmd/command.hh index 4a72627ed..8ada78782 100644 --- a/src/libcmd/command.hh +++ b/src/libcmd/command.hh @@ -238,7 +238,7 @@ public: BuiltPathsCommand(bool recursive = false); - virtual void run(ref store, BuiltPaths && paths) = 0; + virtual void run(ref store, BuiltPaths && allPaths, BuiltPaths && rootPaths) = 0; void run(ref store, Installables && installables) override; @@ -251,7 +251,7 @@ struct StorePathsCommand : public BuiltPathsCommand virtual void run(ref store, StorePaths && storePaths) = 0; - void run(ref store, BuiltPaths && paths) override; + void run(ref store, BuiltPaths && allPaths, BuiltPaths && rootPaths) override; }; /** @@ -301,11 +301,15 @@ struct MixProfile : virtual StoreCommand MixProfile(); /* If 'profile' is set, make it point at 'storePath'. */ - void updateProfile(const StorePath & storePath); + void updateProfile( + const StorePath & storePath, + ref store); /* If 'profile' is set, make it point at the store path produced by 'buildables'. */ - void updateProfile(const BuiltPaths & buildables); + void updateProfile( + const BuiltPaths & buildables, + ref store); }; struct MixDefaultProfile : MixProfile diff --git a/src/nix/build.cc b/src/nix/build.cc index da9132d02..cffbeccb6 100644 --- a/src/nix/build.cc +++ b/src/nix/build.cc @@ -161,7 +161,7 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile BuiltPaths buildables2; for (auto & b : buildables) buildables2.push_back(b.path); - updateProfile(buildables2); + updateProfile(buildables2, store); } }; diff --git a/src/nix/copy.cc b/src/nix/copy.cc index 151d28277..c058a7446 100644 --- a/src/nix/copy.cc +++ b/src/nix/copy.cc @@ -4,7 +4,7 @@ using namespace nix; -struct CmdCopy : virtual CopyCommand, virtual BuiltPathsCommand +struct CmdCopy : virtual CopyCommand, virtual BuiltPathsCommand, MixProfile { CheckSigsFlag checkSigs = CheckSigs; @@ -43,19 +43,21 @@ struct CmdCopy : virtual CopyCommand, virtual BuiltPathsCommand Category category() override { return catSecondary; } - void run(ref srcStore, BuiltPaths && paths) override + void run(ref srcStore, BuiltPaths && allPaths, BuiltPaths && rootPaths) override { auto dstStore = getDstStore(); RealisedPath::Set stuffToCopy; - for (auto & builtPath : paths) { + for (auto & builtPath : allPaths) { auto theseRealisations = builtPath.toRealisedPaths(*srcStore); stuffToCopy.insert(theseRealisations.begin(), theseRealisations.end()); } copyPaths( *srcStore, *dstStore, stuffToCopy, NoRepair, checkSigs, substitute); + + updateProfile(rootPaths, dstStore); } }; diff --git a/src/nix/copy.md b/src/nix/copy.md index 6ab7cdee3..813050fcb 100644 --- a/src/nix/copy.md +++ b/src/nix/copy.md @@ -55,6 +55,15 @@ R""( # nix copy --to /tmp/nix nixpkgs#hello --no-check-sigs ``` +* Update the NixOS system profile to point to a closure copied from a + remote machine: + + ```console + # nix copy --from ssh://server \ + --profile /nix/var/nix/profiles/system \ + /nix/store/r14v3km89zm3prwsa521fab5kgzvfbw4-nixos-system-foobar-24.05.20240925.759537f + ``` + # Description `nix copy` copies store path closures between two Nix stores. The diff --git a/src/nix/develop.cc b/src/nix/develop.cc index c7a733025..ca9f6a4af 100644 --- a/src/nix/develop.cc +++ b/src/nix/develop.cc @@ -502,7 +502,7 @@ struct Common : InstallableCommand, MixProfile auto strPath = store->printStorePath(shellOutPath); - updateProfile(shellOutPath); + updateProfile(shellOutPath, store); debug("reading environment file '%s'", strPath); diff --git a/src/nix/profile.cc b/src/nix/profile.cc index 324fd6330..ae1f3e6e9 100644 --- a/src/nix/profile.cc +++ b/src/nix/profile.cc @@ -424,7 +424,7 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile } try { - updateProfile(manifest.build(store)); + updateProfile(manifest.build(store), store); } catch (BuildEnvFileConflictError & conflictError) { // FIXME use C++20 std::ranges once macOS has it // See https://github.com/NixOS/nix/compare/3efa476c5439f8f6c1968a6ba20a31d1239c2f04..1fe5d172ece51a619e879c4b86f603d9495cc102 @@ -669,7 +669,7 @@ struct CmdProfileRemove : virtual EvalCommand, MixDefaultProfile, MixProfileElem removedCount, newManifest.elements.size()); - updateProfile(newManifest.build(store)); + updateProfile(newManifest.build(store), store); } }; @@ -779,7 +779,7 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf builtPaths.find(&*installable)->second.first); } - updateProfile(manifest.build(store)); + updateProfile(manifest.build(store), store); } }; diff --git a/src/nix/realisation.cc b/src/nix/realisation.cc index e1f231222..a386d98ea 100644 --- a/src/nix/realisation.cc +++ b/src/nix/realisation.cc @@ -36,7 +36,7 @@ struct CmdRealisationInfo : BuiltPathsCommand, MixJSON Category category() override { return catSecondary; } - void run(ref store, BuiltPaths && paths) override + void run(ref store, BuiltPaths && paths, BuiltPaths && rootPaths) override { experimentalFeatureSettings.require(Xp::CaDerivations); RealisedPath::Set realisations; diff --git a/tests/functional/zstd.sh b/tests/functional/zstd.sh index 90fe58539..cdc30c66e 100755 --- a/tests/functional/zstd.sh +++ b/tests/functional/zstd.sh @@ -18,7 +18,9 @@ HASH=$(nix hash path $outPath) clearStore clearCacheCache -nix copy --from $cacheURI $outPath --no-check-sigs +nix copy --from $cacheURI $outPath --no-check-sigs --profile $TEST_ROOT/profile + +[[ -e $TEST_ROOT/profile ]] if ls $cacheDir/nar/*.zst &> /dev/null; then echo "files do exist" From 43ad8c5eb2bdf4995467595f83efd6d9a747b440 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 8 Oct 2024 15:36:21 +0200 Subject: [PATCH 279/718] Make getDstStore() a virtual method in StoreCommand --- src/libcmd/command.cc | 12 ++++-------- src/libcmd/command.hh | 23 ++++++++++++++++------- src/nix/build.cc | 2 +- src/nix/copy.cc | 2 +- src/nix/develop.cc | 2 +- src/nix/profile.cc | 6 +++--- 6 files changed, 26 insertions(+), 21 deletions(-) diff --git a/src/libcmd/command.cc b/src/libcmd/command.cc index e38f982d8..0fb4f5680 100644 --- a/src/libcmd/command.cc +++ b/src/libcmd/command.cc @@ -246,21 +246,17 @@ MixProfile::MixProfile() }); } -void MixProfile::updateProfile( - const StorePath & storePath, - ref store_) +void MixProfile::updateProfile(const StorePath & storePath) { if (!profile) return; - auto store = store_.dynamic_pointer_cast(); + auto store = getDstStore().dynamic_pointer_cast(); if (!store) throw Error("'--profile' is not supported for this Nix store"); auto profile2 = absPath(*profile); switchLink(profile2, createGeneration(*store, profile2, storePath)); } -void MixProfile::updateProfile( - const BuiltPaths & buildables, - ref store) +void MixProfile::updateProfile(const BuiltPaths & buildables) { if (!profile) return; @@ -282,7 +278,7 @@ void MixProfile::updateProfile( if (result.size() != 1) throw UsageError("'--profile' requires that the arguments produce a single store path, but there are %d", result.size()); - updateProfile(result[0], store); + updateProfile(result[0]); } MixDefaultProfile::MixDefaultProfile() diff --git a/src/libcmd/command.hh b/src/libcmd/command.hh index 8ada78782..73aaab741 100644 --- a/src/libcmd/command.hh +++ b/src/libcmd/command.hh @@ -45,7 +45,20 @@ struct StoreCommand : virtual Command { StoreCommand(); void run() override; + + /** + * Return the default Nix store. + */ ref getStore(); + + /** + * Return the destination Nix store. + */ + virtual ref getDstStore() + { + return getStore(); + } + virtual ref createStore(); /** * Main entry point, with a `Store` provided @@ -68,7 +81,7 @@ struct CopyCommand : virtual StoreCommand ref createStore() override; - ref getDstStore(); + ref getDstStore() override; }; /** @@ -301,15 +314,11 @@ struct MixProfile : virtual StoreCommand MixProfile(); /* If 'profile' is set, make it point at 'storePath'. */ - void updateProfile( - const StorePath & storePath, - ref store); + void updateProfile(const StorePath & storePath); /* If 'profile' is set, make it point at the store path produced by 'buildables'. */ - void updateProfile( - const BuiltPaths & buildables, - ref store); + void updateProfile(const BuiltPaths & buildables); }; struct MixDefaultProfile : MixProfile diff --git a/src/nix/build.cc b/src/nix/build.cc index cffbeccb6..da9132d02 100644 --- a/src/nix/build.cc +++ b/src/nix/build.cc @@ -161,7 +161,7 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile BuiltPaths buildables2; for (auto & b : buildables) buildables2.push_back(b.path); - updateProfile(buildables2, store); + updateProfile(buildables2); } }; diff --git a/src/nix/copy.cc b/src/nix/copy.cc index c058a7446..60a64723c 100644 --- a/src/nix/copy.cc +++ b/src/nix/copy.cc @@ -57,7 +57,7 @@ struct CmdCopy : virtual CopyCommand, virtual BuiltPathsCommand, MixProfile copyPaths( *srcStore, *dstStore, stuffToCopy, NoRepair, checkSigs, substitute); - updateProfile(rootPaths, dstStore); + updateProfile(rootPaths); } }; diff --git a/src/nix/develop.cc b/src/nix/develop.cc index ca9f6a4af..c7a733025 100644 --- a/src/nix/develop.cc +++ b/src/nix/develop.cc @@ -502,7 +502,7 @@ struct Common : InstallableCommand, MixProfile auto strPath = store->printStorePath(shellOutPath); - updateProfile(shellOutPath, store); + updateProfile(shellOutPath); debug("reading environment file '%s'", strPath); diff --git a/src/nix/profile.cc b/src/nix/profile.cc index ae1f3e6e9..324fd6330 100644 --- a/src/nix/profile.cc +++ b/src/nix/profile.cc @@ -424,7 +424,7 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile } try { - updateProfile(manifest.build(store), store); + updateProfile(manifest.build(store)); } catch (BuildEnvFileConflictError & conflictError) { // FIXME use C++20 std::ranges once macOS has it // See https://github.com/NixOS/nix/compare/3efa476c5439f8f6c1968a6ba20a31d1239c2f04..1fe5d172ece51a619e879c4b86f603d9495cc102 @@ -669,7 +669,7 @@ struct CmdProfileRemove : virtual EvalCommand, MixDefaultProfile, MixProfileElem removedCount, newManifest.elements.size()); - updateProfile(newManifest.build(store), store); + updateProfile(newManifest.build(store)); } }; @@ -779,7 +779,7 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf builtPaths.find(&*installable)->second.first); } - updateProfile(manifest.build(store), store); + updateProfile(manifest.build(store)); } }; From 7f6d006bebfb56b2967165c7f2e8c940abafac24 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 8 Oct 2024 16:35:53 +0200 Subject: [PATCH 280/718] nix copy: Add --out-link --- src/libcmd/command.cc | 25 +++++++++++++++++++++++++ src/libcmd/command.hh | 10 ++++++++++ src/libcmd/installables.cc | 8 ++++++++ src/libcmd/installables.hh | 2 ++ src/nix/build.cc | 25 +------------------------ src/nix/copy.cc | 18 ++++++++++++++++++ tests/functional/zstd.sh | 3 ++- 7 files changed, 66 insertions(+), 25 deletions(-) diff --git a/src/libcmd/command.cc b/src/libcmd/command.cc index 0fb4f5680..8053e1da6 100644 --- a/src/libcmd/command.cc +++ b/src/libcmd/command.cc @@ -334,4 +334,29 @@ void MixEnvironment::setEnviron() } } +void createOutLinks( + const std::filesystem::path & outLink, + const BuiltPaths & buildables, + LocalFSStore & store) +{ + for (const auto & [_i, buildable] : enumerate(buildables)) { + auto i = _i; + std::visit(overloaded { + [&](const BuiltPath::Opaque & bo) { + auto symlink = outLink; + if (i) symlink += fmt("-%d", i); + store.addPermRoot(bo.path, absPath(symlink.string())); + }, + [&](const BuiltPath::Built & bfd) { + for (auto & output : bfd.outputs) { + auto symlink = outLink; + if (i) symlink += fmt("-%d", i); + if (output.first != "out") symlink += fmt("-%s", output.first); + store.addPermRoot(output.second, absPath(symlink.string())); + } + }, + }, buildable.raw()); + } +} + } diff --git a/src/libcmd/command.hh b/src/libcmd/command.hh index 73aaab741..e9fcf3df9 100644 --- a/src/libcmd/command.hh +++ b/src/libcmd/command.hh @@ -18,6 +18,7 @@ extern char * * savedArgv; class EvalState; struct Pos; class Store; +class LocalFSStore; static constexpr Command::Category catHelp = -1; static constexpr Command::Category catSecondary = 100; @@ -367,4 +368,13 @@ void printClosureDiff( const StorePath & afterPath, std::string_view indent); +/** + * Create symlinks prefixed by `outLink` to the store paths in + * `buildables`. + */ +void createOutLinks( + const std::filesystem::path & outLink, + const BuiltPaths & buildables, + LocalFSStore & store); + } diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc index f9d6d8ce8..86d26f6c4 100644 --- a/src/libcmd/installables.cc +++ b/src/libcmd/installables.cc @@ -917,4 +917,12 @@ void BuiltPathsCommand::applyDefaultInstallables(std::vector & rawI rawInstallables.push_back("."); } +BuiltPaths toBuiltPaths(const std::vector & builtPathsWithResult) +{ + BuiltPaths res; + for (auto & i : builtPathsWithResult) + res.push_back(i.path); + return res; +} + } diff --git a/src/libcmd/installables.hh b/src/libcmd/installables.hh index bf5759230..c995c3019 100644 --- a/src/libcmd/installables.hh +++ b/src/libcmd/installables.hh @@ -86,6 +86,8 @@ struct BuiltPathWithResult std::optional result; }; +BuiltPaths toBuiltPaths(const std::vector & builtPathsWithResult); + /** * Shorthand, for less typing and helping us keep the choice of * collection in sync. diff --git a/src/nix/build.cc b/src/nix/build.cc index da9132d02..3569b0cde 100644 --- a/src/nix/build.cc +++ b/src/nix/build.cc @@ -42,29 +42,6 @@ static nlohmann::json builtPathsWithResultToJSON(const std::vector& buildables, LocalFSStore& store2) -{ - for (const auto & [_i, buildable] : enumerate(buildables)) { - auto i = _i; - std::visit(overloaded { - [&](const BuiltPath::Opaque & bo) { - auto symlink = outLink; - if (i) symlink += fmt("-%d", i); - store2.addPermRoot(bo.path, absPath(symlink.string())); - }, - [&](const BuiltPath::Built & bfd) { - for (auto & output : bfd.outputs) { - auto symlink = outLink; - if (i) symlink += fmt("-%d", i); - if (output.first != "out") symlink += fmt("-%s", output.first); - store2.addPermRoot(output.second, absPath(symlink.string())); - } - }, - }, buildable.path.raw()); - } -} - struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile { Path outLink = "result"; @@ -140,7 +117,7 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile if (outLink != "") if (auto store2 = store.dynamic_pointer_cast()) - createOutLinks(outLink, buildables, *store2); + createOutLinks(outLink, toBuiltPaths(buildables), *store2); if (printOutputPaths) { stopProgressBar(); diff --git a/src/nix/copy.cc b/src/nix/copy.cc index 60a64723c..399a6c0fd 100644 --- a/src/nix/copy.cc +++ b/src/nix/copy.cc @@ -1,11 +1,13 @@ #include "command.hh" #include "shared.hh" #include "store-api.hh" +#include "local-fs-store.hh" using namespace nix; struct CmdCopy : virtual CopyCommand, virtual BuiltPathsCommand, MixProfile { + std::optional outLink; CheckSigsFlag checkSigs = CheckSigs; SubstituteFlag substitute = NoSubstitute; @@ -13,6 +15,15 @@ struct CmdCopy : virtual CopyCommand, virtual BuiltPathsCommand, MixProfile CmdCopy() : BuiltPathsCommand(true) { + addFlag({ + .longName = "out-link", + .shortName = 'o', + .description = "Create symlinks prefixed with *path* to the top-level store paths fetched from the source store.", + .labels = {"path"}, + .handler = {&outLink}, + .completer = completePath + }); + addFlag({ .longName = "no-check-sigs", .description = "Do not require that paths are signed by trusted keys.", @@ -58,6 +69,13 @@ struct CmdCopy : virtual CopyCommand, virtual BuiltPathsCommand, MixProfile *srcStore, *dstStore, stuffToCopy, NoRepair, checkSigs, substitute); updateProfile(rootPaths); + + if (outLink) { + if (auto store2 = dstStore.dynamic_pointer_cast()) + createOutLinks(*outLink, rootPaths, *store2); + else + throw Error("'--out-link' is not supported for this Nix store"); + } } }; diff --git a/tests/functional/zstd.sh b/tests/functional/zstd.sh index cdc30c66e..1eb1b5343 100755 --- a/tests/functional/zstd.sh +++ b/tests/functional/zstd.sh @@ -18,9 +18,10 @@ HASH=$(nix hash path $outPath) clearStore clearCacheCache -nix copy --from $cacheURI $outPath --no-check-sigs --profile $TEST_ROOT/profile +nix copy --from $cacheURI $outPath --no-check-sigs --profile $TEST_ROOT/profile --out-link $TEST_ROOT/result [[ -e $TEST_ROOT/profile ]] +[[ -e $TEST_ROOT/result ]] if ls $cacheDir/nar/*.zst &> /dev/null; then echo "files do exist" From e9b5704d1c3bdead2d9d259b3c443a391306b6d7 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 8 Oct 2024 16:49:35 +0200 Subject: [PATCH 281/718] Add release note --- doc/manual/rl-next/nix-copy-flags.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 doc/manual/rl-next/nix-copy-flags.md diff --git a/doc/manual/rl-next/nix-copy-flags.md b/doc/manual/rl-next/nix-copy-flags.md new file mode 100644 index 000000000..f5b2b9716 --- /dev/null +++ b/doc/manual/rl-next/nix-copy-flags.md @@ -0,0 +1,18 @@ +--- +synopsis: "`nix copy` supports `--profile` and `--out-link`" +prs: [11657] +--- + +The `nix copy` command now has flags `--profile` and `--out-link`, similar to `nix build`. `--profile` makes a profile point to the +top-level store path, while `--out-link` create symlinks to the top-level store paths. + +For example, when updating the local NixOS system profile from a NixOS system closure on a remote machine, instead of +``` +# nix copy --from ssh://server $path +# nix build --profile /nix/var/nix/profiles/system $path +``` +you can now do +``` +# nix copy --from ssh://server --profile /nix/var/nix/profiles/system $path +``` +The advantage is that this avoids a time window where *path* is not a garbage collector root, and so could be deleted by a concurrent `nix store gc` process. From 57a478572d994d7aa4cca3b145fb1c38744145cd Mon Sep 17 00:00:00 2001 From: John Ericson Date: Wed, 9 Oct 2024 10:39:18 -0400 Subject: [PATCH 282/718] Rename `baseNativeBuildInputs` as requested Co-Authored-By: Robert Hensing --- flake.nix | 2 +- tests/functional/package.nix | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.nix b/flake.nix index cbcf10021..64b587760 100644 --- a/flake.nix +++ b/flake.nix @@ -351,7 +351,7 @@ ++ lib.optionals havePerl pkgs.nixComponents.nix-perl-bindings.nativeBuildInputs ++ pkgs.nixComponents.nix-internal-api-docs.nativeBuildInputs ++ pkgs.nixComponents.nix-external-api-docs.nativeBuildInputs - ++ pkgs.nixComponents.nix-functional-tests.baseNativeBuildInputs + ++ pkgs.nixComponents.nix-functional-tests.externalNativeBuildInputs ++ lib.optional (!buildCanExecuteHost # Hack around https://github.com/nixos/nixpkgs/commit/bf7ad8cfbfa102a90463433e2c5027573b462479 diff --git a/tests/functional/package.nix b/tests/functional/package.nix index 675cefa64..a0c1f249f 100644 --- a/tests/functional/package.nix +++ b/tests/functional/package.nix @@ -48,7 +48,7 @@ mkMesonDerivation (finalAttrs: { ]; # Hack for sake of the dev shell - passthru.baseNativeBuildInputs = [ + passthru.externalNativeBuildInputs = [ meson ninja pkg-config @@ -66,7 +66,7 @@ mkMesonDerivation (finalAttrs: { util-linux ]; - nativeBuildInputs = finalAttrs.passthru.baseNativeBuildInputs ++ [ + nativeBuildInputs = finalAttrs.passthru.externalNativeBuildInputs ++ [ nix-cli ]; From f7db612e8b123d58173d3dad728afb8d45366657 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Wed, 9 Oct 2024 10:41:48 -0400 Subject: [PATCH 283/718] Reword next release release note a bit This is unrelated to this PR, but requested in https://github.com/NixOS/nix/pull/11224#discussion_r1715031841 Co-Authored-By: Robert Hensing --- doc/manual/rl-next/build-hook-default.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/manual/rl-next/build-hook-default.md b/doc/manual/rl-next/build-hook-default.md index 0d5a130c0..f13537983 100644 --- a/doc/manual/rl-next/build-hook-default.md +++ b/doc/manual/rl-next/build-hook-default.md @@ -16,7 +16,7 @@ This has a small adverse affect on remote building --- the `build-remote` execut This means that other applications linking `libnixstore` that wish to use remote building must arrange for the `nix` command to be on the PATH (or manually overriding `build-hook`) in order for that to work. Long term we don't envision this being a downside, because we plan to [get rid of `build-remote` and the build hook setting entirely](https://github.com/NixOS/nix/issues/1221). -There is simply no need to add a second layer of remote-procedure-calling when we want to connect to a remote builder. +There should simply be no need to have an extra, intermediate layer of remote-procedure-calling when we want to connect to a remote builder. The build hook protocol did in principle support custom ways of remote building, but that can also be accomplished with a custom service for the ssh or daemon/ssh-ng protocols, or with a custom [store type](@docroot@/store/types/index.md) i.e. `Store` subclass. -The Perl bindings no longer expose `getBinDir` either, since they libraries those bindings wrap no longer know the location of installed binaries as described above. +The Perl bindings no longer expose `getBinDir` either, since the underlying C++ libraries those bindings wrap no longer know the location of installed binaries as described above. From 0db8ff820b5263cc1473364601dcc9f3ad844521 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Wed, 9 Oct 2024 10:58:44 -0400 Subject: [PATCH 284/718] More comment rewording as requested Co-Authored-By: Robert Hensing --- src/nix/self-exe.cc | 5 +++-- src/nix/self-exe.hh | 6 +++--- tests/functional/meson.build | 5 +++-- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/nix/self-exe.cc b/src/nix/self-exe.cc index 81a117e60..77d20a835 100644 --- a/src/nix/self-exe.cc +++ b/src/nix/self-exe.cc @@ -13,11 +13,12 @@ fs::path getNixBin(std::optional binaryNameOpt) { auto getBinaryName = [&] { return binaryNameOpt ? *binaryNameOpt : "nix"; }; - // If the environment variable is set, use it unconditionally + // If the environment variable is set, use it unconditionally. if (auto envOpt = getEnvNonEmpty("NIX_BIN_DIR")) return fs::path{*envOpt} / std::string{getBinaryName()}; - // Use some-times avaiable OS tricks to get to the path of this Nix, and try that + // Try OS tricks, if available, to get to the path of this Nix, and + // see if we can find the right executable next to that. if (auto selfOpt = getSelfExe()) { fs::path path{*selfOpt}; if (binaryNameOpt) diff --git a/src/nix/self-exe.hh b/src/nix/self-exe.hh index 0772afa67..3161553ec 100644 --- a/src/nix/self-exe.hh +++ b/src/nix/self-exe.hh @@ -17,9 +17,9 @@ namespace nix { * Instead, we'll query the OS for the path to the current executable, * using `getSelfExe()`. * - * As a last resort, we resort to `PATH`. Hopefully we find a `nix` - * there that's compatible. If you're porting Nix to a new platform, - * that might be good enough for a while, but you'll want to improve + * As a last resort, we rely on `PATH`. Hopefully we find a `nix` there + * that's compatible. If you're porting Nix to a new platform, that + * might be good enough for a while, but you'll want to improve * `getSelfExe()` to work on your platform. * * @param binary_name the exact binary name we're looking up. Might be diff --git a/tests/functional/meson.build b/tests/functional/meson.build index 69b6d3194..54f3e7a01 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -253,8 +253,9 @@ foreach suite : suites 'NIX_REMOTE': '', 'PS4': '+(${BASH_SOURCE[0]-$0}:$LINENO) ', }, - # some tests take 15+ seconds even on an otherwise idle machine, on a loaded machine - # this can easily drive them to failure. give them more time than default of 30sec + # Some tests take 15+ seconds even on an otherwise idle machine; + # on a loaded machine this can easily drive them to failure. Give + # them more time than the default of 30 seconds. timeout : 300, # Used for target dependency/ordering tracking, not adding compiler flags or anything. depends : suite['deps'], From 6594573f3dab704a237c520caafe36e38346c8e1 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Wed, 9 Oct 2024 10:53:45 -0400 Subject: [PATCH 285/718] Remove dead code in the Meson build system Identified in https://github.com/NixOS/nix/pull/11224#discussion_r1715056429 Co-Authored-By: Robert Hensing --- scripts/meson.build | 9 --------- 1 file changed, 9 deletions(-) diff --git a/scripts/meson.build b/scripts/meson.build index 2671e6a13..777da42b1 100644 --- a/scripts/meson.build +++ b/scripts/meson.build @@ -1,5 +1,3 @@ -# configures `scripts/nix-profile.sh.in` (and copies the original to the build directory). -# this is only needed for tests, but running it unconditionally does not hurt enough to care. configure_file( input : 'nix-profile.sh.in', output : 'nix-profile.sh', @@ -8,13 +6,6 @@ configure_file( } ) -# https://github.com/mesonbuild/meson/issues/860 -configure_file( - input : 'nix-profile.sh.in', - output : 'nix-profile.sh.in', - copy : true, -) - foreach rc : [ '.sh', '.fish', '-daemon.sh', '-daemon.fish' ] configure_file( input : 'nix-profile' + rc + '.in', From 67a66212c3c134605f5e59a8e8ce3afb94ccb605 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Wed, 9 Oct 2024 11:08:31 -0400 Subject: [PATCH 286/718] Extend Nix repl missing executable error message Co-Authored-By: Robert Hensing Date: Tue, 30 Jul 2024 15:05:22 -0400 Subject: [PATCH 287/718] Build the manual with Meson MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Qyriad Co-Authored-By: Robert Hensing Co-Authored-By: eldritch horrors Co-authored-by: Jörg Thalheim Co-authored-by: Tom Bereknyei --- doc/manual/.version | 1 + doc/manual/book.toml | 14 +- doc/manual/generate-deps.py | 22 ++ doc/manual/local.mk | 9 +- doc/manual/meson.build | 353 +++++++++++++++++++++++ doc/manual/package.nix | 71 +++++ doc/manual/remove_before_wrapper.py | 33 +++ doc/manual/render-manpage.sh | 25 ++ doc/manual/src/command-ref/meson.build | 63 ++++ doc/manual/src/development/meson.build | 12 + doc/manual/src/language/constructs.md | 1 + doc/manual/src/language/meson.build | 20 ++ doc/manual/src/language/values.md | 1 + doc/manual/src/meson.build | 17 ++ doc/manual/src/protocols/json/index.md | 1 + doc/manual/src/release-notes/meson.build | 24 ++ doc/manual/src/store/meson.build | 18 ++ doc/manual/substitute.py | 111 +++++++ flake.nix | 2 + meson.build | 3 + packaging/components.nix | 1 + packaging/everything.nix | 2 + packaging/hydra.nix | 3 + src/nix-manual | 1 + 24 files changed, 805 insertions(+), 3 deletions(-) create mode 120000 doc/manual/.version create mode 100755 doc/manual/generate-deps.py create mode 100644 doc/manual/meson.build create mode 100644 doc/manual/package.nix create mode 100644 doc/manual/remove_before_wrapper.py create mode 100755 doc/manual/render-manpage.sh create mode 100644 doc/manual/src/command-ref/meson.build create mode 100644 doc/manual/src/development/meson.build create mode 100644 doc/manual/src/language/constructs.md create mode 100644 doc/manual/src/language/meson.build create mode 100644 doc/manual/src/language/values.md create mode 100644 doc/manual/src/meson.build create mode 100644 doc/manual/src/protocols/json/index.md create mode 100644 doc/manual/src/release-notes/meson.build create mode 100644 doc/manual/src/store/meson.build create mode 100644 doc/manual/substitute.py create mode 120000 src/nix-manual diff --git a/doc/manual/.version b/doc/manual/.version new file mode 120000 index 000000000..b7badcd0c --- /dev/null +++ b/doc/manual/.version @@ -0,0 +1 @@ +../../.version \ No newline at end of file diff --git a/doc/manual/book.toml b/doc/manual/book.toml index 73fb7e75e..acae7aec7 100644 --- a/doc/manual/book.toml +++ b/doc/manual/book.toml @@ -7,9 +7,21 @@ additional-js = ["redirects.js"] edit-url-template = "https://github.com/NixOS/nix/tree/master/doc/manual/{path}" git-repository-url = "https://github.com/NixOS/nix" +# Handles replacing @docroot@ with a path to ./src relative to that markdown file, +# {{#include handlebars}}, and the @generated@ syntax used within these. it mostly +# but not entirely replaces the links preprocessor (which we cannot simply use due +# to @generated@ files living in a different directory to make meson happy). we do +# not want to disable the links preprocessor entirely though because that requires +# disabling *all* built-in preprocessors and selectively reenabling those we want. +[preprocessor.substitute] +command = "python3 ./substitute.py" +before = ["anchors", "links"] + [preprocessor.anchors] renderers = ["html"] -command = "jq --from-file doc/manual/anchors.jq" +command = "jq --from-file ./anchors.jq" + +[output.markdown] [output.linkcheck] # no Internet during the build (in the sandbox) diff --git a/doc/manual/generate-deps.py b/doc/manual/generate-deps.py new file mode 100755 index 000000000..297bd3939 --- /dev/null +++ b/doc/manual/generate-deps.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 + +import glob +import sys + +# meson expects makefile-style dependency declarations, i.e. +# +# target: dependency... +# +# meson seems to pass depfiles straight on to ninja even though +# it also parses the file itself (or at least has code to do so +# in its tree), so we must live by ninja's rules: only slashes, +# spaces and octothorpes can be escaped, anything else is taken +# literally. since the rules for these aren't even the same for +# all three we will just fail when we encounter any of them (if +# asserts are off for some reason the depfile will likely point +# to nonexistant paths, making everything phony and thus fine.) +for path in glob.glob(sys.argv[1] + '/**', recursive=True): + assert '\\' not in path + assert ' ' not in path + assert '#' not in path + print("ignored:", path) diff --git a/doc/manual/local.mk b/doc/manual/local.mk index fcc50f460..3c777efc3 100644 --- a/doc/manual/local.mk +++ b/doc/manual/local.mk @@ -223,8 +223,13 @@ $(docdir)/manual/index.html: $(MANUAL_SRCS) $(d)/book.toml $(d)/anchors.jq $(d)/ sed -i "s,@docroot@,$$docroot,g" "$$file"; \ done; \ set -euo pipefail; \ - RUST_LOG=warn mdbook build "$$tmp/manual" -d $(DESTDIR)$(docdir)/manual.tmp 2>&1 \ - | { grep -Fv "because fragment resolution isn't implemented" || :; }; \ + ( \ + cd "$$tmp/manual"; \ + RUST_LOG=warn \ + MDBOOK_SUBSTITUTE_SEARCH=$(d)/src \ + mdbook build -d $(DESTDIR)$(docdir)/manual.tmp 2>&1 \ + | { grep -Fv "because fragment resolution isn't implemented" || :; } \ + ); \ rm -rf "$$tmp/manual" @rm -rf $(DESTDIR)$(docdir)/manual @mv $(DESTDIR)$(docdir)/manual.tmp/html $(DESTDIR)$(docdir)/manual diff --git a/doc/manual/meson.build b/doc/manual/meson.build new file mode 100644 index 000000000..31d1814d7 --- /dev/null +++ b/doc/manual/meson.build @@ -0,0 +1,353 @@ +project('nix-manual', + version : files('.version'), + meson_version : '>= 1.1', + license : 'LGPL-2.1-or-later', +) + +nix = find_program('nix', native : true) + +mdbook = find_program('mdbook', native : true) +bash = find_program('bash', native : true) + +pymod = import('python') +python = pymod.find_installation('python3') + +nix_env_for_docs = { + 'HOME': '/dummy', + 'NIX_CONF_DIR': '/dummy', + 'NIX_SSL_CERT_FILE': '/dummy/no-ca-bundle.crt', + 'NIX_STATE_DIR': '/dummy', + 'NIX_CONFIG': 'cores = 0', +} + +nix_for_docs = [nix, '--experimental-features', 'nix-command'] +nix_eval_for_docs_common = nix_for_docs + [ + 'eval', + '-I', 'nix=' + meson.current_source_dir(), + '--store', 'dummy://', + '--impure', +] +nix_eval_for_docs = nix_eval_for_docs_common + '--raw' + +conf_file_json = custom_target( + command : nix_for_docs + ['config', 'show', '--json'], + capture : true, + output : 'conf-file.json', + env : nix_env_for_docs, +) + +language_json = custom_target( + command: [nix, '__dump-language'], + output : 'language.json', + capture : true, + env : nix_env_for_docs, +) + +nix3_cli_json = custom_target( + command : [nix, '__dump-cli'], + capture : true, + output : 'nix.json', + env : nix_env_for_docs, +) + +generate_manual_deps = files( + 'generate-deps.py', +) + +# Generates types +subdir('src/store') +# Generates builtins.md and builtin-constants.md. +subdir('src/language') +# Generates new-cli pages, experimental-features-shortlist.md, and conf-file.md. +subdir('src/command-ref') +# Generates experimental-feature-descriptions.md. +subdir('src/development') +# Generates rl-next-generated.md. +subdir('src/release-notes') +subdir('src') + +# Hacky way to figure out if `nix` is an `ExternalProgram` or +# `Exectuable`. Only the latter can occur in custom target input lists. +if nix.full_path().startswith(meson.build_root()) + nix_input = nix +else + nix_input = [] +endif + +manual = custom_target( + 'manual', + command : [ + bash, + '-euo', 'pipefail', + '-c', + ''' + @0@ @INPUT0@ @CURRENT_SOURCE_DIR@ > @DEPFILE@ + @0@ @INPUT1@ summary @2@ < @CURRENT_SOURCE_DIR@/src/SUMMARY.md.in > @2@/src/SUMMARY.md + rsync -r --include='*.md' @CURRENT_SOURCE_DIR@/ @2@/ + (cd @2@; RUST_LOG=warn @1@ build -d @2@ 3>&2 2>&1 1>&3) | { grep -Fv "because fragment resolution isn't implemented" || :; } 3>&2 2>&1 1>&3 + rm -rf @2@/manual + mv @2@/html @2@/manual + find @2@/manual -iname meson.build -delete + '''.format( + python.full_path(), + mdbook.full_path(), + meson.current_build_dir(), + ), + ], + input : [ + generate_manual_deps, + 'substitute.py', + 'book.toml', + 'anchors.jq', + 'custom.css', + nix3_cli_files, + experimental_features_shortlist_md, + experimental_feature_descriptions_md, + types_dir, + conf_file_md, + builtins_md, + rl_next_generated, + summary_rl_next, + nix_input, + ], + output : [ + 'manual', + 'markdown', + ], + depfile : 'manual.d', + env : { + 'RUST_LOG': 'info', + 'MDBOOK_SUBSTITUTE_SEARCH': meson.current_build_dir() / 'src', + }, +) +manual_html = manual[0] +manual_md = manual[1] + +install_subdir( + manual_html.full_path(), + install_dir : get_option('datadir') / 'doc/nix', +) + +nix_nested_manpages = [ + [ 'nix-env', + [ + 'delete-generations', + 'install', + 'list-generations', + 'query', + 'rollback', + 'set-flag', + 'set', + 'switch-generation', + 'switch-profile', + 'uninstall', + 'upgrade', + ], + ], + [ 'nix-store', + [ + 'add-fixed', + 'add', + 'delete', + 'dump-db', + 'dump', + 'export', + 'gc', + 'generate-binary-cache-key', + 'import', + 'load-db', + 'optimise', + 'print-env', + 'query', + 'read-log', + 'realise', + 'repair-path', + 'restore', + 'serve', + 'verify', + 'verify-path', + ], + ], +] + +foreach command : nix_nested_manpages + foreach page : command[1] + title = command[0] + ' --' + page + section = '1' + custom_target( + command : [ + bash, + files('./render-manpage.sh'), + '--out-no-smarty', + title, + section, + '@INPUT0@/command-ref' / command[0] / (page + '.md'), + '@OUTPUT0@', + ], + input : [ + manual_md, + nix_input, + ], + output : command[0] + '-' + page + '.1', + install : true, + install_dir : get_option('mandir') / 'man1', + ) + endforeach +endforeach + +nix3_manpages = [ + 'nix3-build', + 'nix3-bundle', + 'nix3-config', + 'nix3-config-show', + 'nix3-copy', + 'nix3-daemon', + 'nix3-derivation-add', + 'nix3-derivation', + 'nix3-derivation-show', + 'nix3-develop', + #'nix3-doctor', + 'nix3-edit', + 'nix3-eval', + 'nix3-flake-archive', + 'nix3-flake-check', + 'nix3-flake-clone', + 'nix3-flake-info', + 'nix3-flake-init', + 'nix3-flake-lock', + 'nix3-flake', + 'nix3-flake-metadata', + 'nix3-flake-new', + 'nix3-flake-prefetch', + 'nix3-flake-show', + 'nix3-flake-update', + 'nix3-fmt', + 'nix3-hash-file', + 'nix3-hash', + 'nix3-hash-path', + 'nix3-hash-to-base16', + 'nix3-hash-to-base32', + 'nix3-hash-to-base64', + 'nix3-hash-to-sri', + 'nix3-help', + 'nix3-help-stores', + 'nix3-key-convert-secret-to-public', + 'nix3-key-generate-secret', + 'nix3-key', + 'nix3-log', + 'nix3-nar-cat', + 'nix3-nar-dump-path', + 'nix3-nar-ls', + 'nix3-nar', + 'nix3-path-info', + 'nix3-print-dev-env', + 'nix3-profile-diff-closures', + 'nix3-profile-history', + 'nix3-profile-install', + 'nix3-profile-list', + 'nix3-profile', + 'nix3-profile-remove', + 'nix3-profile-rollback', + 'nix3-profile-upgrade', + 'nix3-profile-wipe-history', + 'nix3-realisation-info', + 'nix3-realisation', + 'nix3-registry-add', + 'nix3-registry-list', + 'nix3-registry', + 'nix3-registry-pin', + 'nix3-registry-remove', + 'nix3-repl', + 'nix3-run', + 'nix3-search', + #'nix3-shell', + 'nix3-store-add-file', + 'nix3-store-add-path', + 'nix3-store-cat', + 'nix3-store-copy-log', + 'nix3-store-copy-sigs', + 'nix3-store-delete', + 'nix3-store-diff-closures', + 'nix3-store-dump-path', + 'nix3-store-gc', + 'nix3-store-ls', + 'nix3-store-make-content-addressed', + 'nix3-store', + 'nix3-store-optimise', + 'nix3-store-path-from-hash-part', + 'nix3-store-ping', + 'nix3-store-prefetch-file', + 'nix3-store-repair', + 'nix3-store-sign', + 'nix3-store-verify', + 'nix3-upgrade-nix', + 'nix3-why-depends', + 'nix', +] + +foreach page : nix3_manpages + section = '1' + custom_target( + command : [ + bash, + '@INPUT0@', + page, + section, + '@INPUT1@/command-ref/new-cli/@0@.md'.format(page), + '@OUTPUT@', + ], + input : [ + files('./render-manpage.sh'), + manual_md, + nix_input, + ], + output : page + '.1', + install : true, + install_dir : get_option('mandir') / 'man1', + ) +endforeach + +nix_manpages = [ + [ 'nix-env', 1 ], + [ 'nix-store', 1 ], + [ 'nix-build', 1 ], + [ 'nix-shell', 1 ], + [ 'nix-instantiate', 1 ], + [ 'nix-collect-garbage', 1 ], + [ 'nix-prefetch-url', 1 ], + [ 'nix-channel', 1 ], + [ 'nix-hash', 1 ], + [ 'nix-copy-closure', 1 ], + [ 'nix.conf', 5, conf_file_md.full_path() ], + [ 'nix-daemon', 8 ], + [ 'nix-profiles', 5, 'files/profiles.md' ], +] + +foreach entry : nix_manpages + title = entry[0] + # nix.conf.5 and nix-profiles.5 are based off of conf-file.md and files/profiles.md, + # rather than a stem identical to its mdbook source. + # Therefore we use an optional third element of this array to override the name pattern + md_file = entry.get(2, title + '.md') + section = entry[1].to_string() + md_file_resolved = join_paths('@INPUT1@/command-ref/', md_file) + custom_target( + command : [ + bash, + '@INPUT0@', + title, + section, + md_file_resolved, + '@OUTPUT@', + ], + input : [ + files('./render-manpage.sh'), + manual_md, + entry.get(3, []), + nix_input, + ], + output : '@0@.@1@'.format(entry[0], entry[1]), + install : true, + install_dir : get_option('mandir') / 'man@0@'.format(entry[1]), + ) +endforeach diff --git a/doc/manual/package.nix b/doc/manual/package.nix new file mode 100644 index 000000000..2e6fcede3 --- /dev/null +++ b/doc/manual/package.nix @@ -0,0 +1,71 @@ +{ lib +, mkMesonDerivation + +, meson +, ninja +, lowdown +, mdbook +, mdbook-linkcheck +, jq +, python3 +, rsync +, nix-cli + +# Configuration Options + +, version +}: + +let + inherit (lib) fileset; +in + +mkMesonDerivation (finalAttrs: { + pname = "nix-manual"; + inherit version; + + workDir = ./.; + fileset = fileset.difference + (fileset.unions [ + ../../.version + # Too many different types of files to filter for now + ../../doc/manual + ./. + ]) + # Do a blacklist instead + ../../doc/manual/package.nix; + + # TODO the man pages should probably be separate + outputs = [ "out" "man" ]; + + # Hack for sake of the dev shell + passthru.externalNativeBuildInputs = [ + meson + ninja + (lib.getBin lowdown) + mdbook + mdbook-linkcheck + jq + python3 + rsync + ]; + + nativeBuildInputs = finalAttrs.passthru.externalNativeBuildInputs ++ [ + nix-cli + ]; + + preConfigure = + '' + chmod u+w ./.version + echo ${finalAttrs.version} > ./.version + ''; + + postInstall = '' + mkdir -p ''$out/nix-support + echo "doc manual ''$out/share/doc/nix/manual" >> ''$out/nix-support/hydra-build-products + ''; + + meta = { + platforms = lib.platforms.all; + }; +}) diff --git a/doc/manual/remove_before_wrapper.py b/doc/manual/remove_before_wrapper.py new file mode 100644 index 000000000..6da4c19b0 --- /dev/null +++ b/doc/manual/remove_before_wrapper.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 + +import os +import subprocess +import sys +import shutil +import typing as t + +def main(): + if len(sys.argv) < 4 or '--' not in sys.argv: + print("Usage: remove-before-wrapper -- ") + sys.exit(1) + + # Extract the parts + output: str = sys.argv[1] + nix_command_idx: int = sys.argv.index('--') + 1 + nix_command: t.List[str] = sys.argv[nix_command_idx:] + + output_temp: str = output + '.tmp' + + # Remove the output and temp output in case they exist + shutil.rmtree(output, ignore_errors=True) + shutil.rmtree(output_temp, ignore_errors=True) + + # Execute nix command with `--write-to` tempary output + nix_command_write_to = nix_command + ['--write-to', output_temp] + subprocess.run(nix_command_write_to, check=True) + + # Move the temporary output to the intended location + os.rename(output_temp, output) + +if __name__ == "__main__": + main() diff --git a/doc/manual/render-manpage.sh b/doc/manual/render-manpage.sh new file mode 100755 index 000000000..65a9c124e --- /dev/null +++ b/doc/manual/render-manpage.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +set -euo pipefail + +lowdown_args= + +if [ "$1" = --out-no-smarty ]; then + lowdown_args=--out-no-smarty + shift +fi + +[ "$#" = 4 ] || { + echo "wrong number of args passed" >&2 + exit 1 +} + +title="$1" +section="$2" +infile="$3" +outfile="$4" + +( + printf "Title: %s\n\n" "$title" + cat "$infile" +) | lowdown -sT man --nroff-nolinks $lowdown_args -M section="$section" -o "$outfile" diff --git a/doc/manual/src/command-ref/meson.build b/doc/manual/src/command-ref/meson.build new file mode 100644 index 000000000..2976f69ff --- /dev/null +++ b/doc/manual/src/command-ref/meson.build @@ -0,0 +1,63 @@ +xp_features_json = custom_target( + command : [nix, '__dump-xp-features'], + capture : true, + output : 'xp-features.json', +) + +experimental_features_shortlist_md = custom_target( + command : nix_eval_for_docs + [ + '--expr', + 'import @INPUT0@ (builtins.fromJSON (builtins.readFile ./@INPUT1@))', + ], + input : [ + '../../generate-xp-features-shortlist.nix', + xp_features_json, + ], + output : 'experimental-features-shortlist.md', + capture : true, + env : nix_env_for_docs, +) + +nix3_cli_files = custom_target( + command : [ + python.full_path(), + '@INPUT0@', + '@OUTPUT@', + '--' + ] + nix_eval_for_docs + [ + '--expr', + 'import @INPUT1@ true (builtins.readFile ./@INPUT2@)', + ], + input : [ + '../../remove_before_wrapper.py', + '../../generate-manpage.nix', + nix3_cli_json, + ], + output : 'new-cli', + env : nix_env_for_docs, +) + +conf_file_md_body = custom_target( + command : [ + nix_eval_for_docs, + '--expr', + 'import @INPUT0@ { prefix = "conf"; } (builtins.fromJSON (builtins.readFile ./@INPUT1@))', + ], + capture : true, + input : [ + '../../generate-settings.nix', + conf_file_json, + ], + output : 'conf-file.body.md', + env : nix_env_for_docs, +) + +conf_file_md = custom_target( + command : [ 'cat', '@INPUT0@', '@INPUT1@' ], + capture : true, + input : [ + 'conf-file-prefix.md', + conf_file_md_body, + ], + output : 'conf-file.md', +) diff --git a/doc/manual/src/development/meson.build b/doc/manual/src/development/meson.build new file mode 100644 index 000000000..5ffbfe394 --- /dev/null +++ b/doc/manual/src/development/meson.build @@ -0,0 +1,12 @@ +experimental_feature_descriptions_md = custom_target( + command : nix_eval_for_docs + [ + '--expr', + 'import @INPUT0@ (builtins.fromJSON (builtins.readFile @INPUT1@))', + ], + input : [ + '../../generate-xp-features.nix', + xp_features_json, + ], + capture : true, + output : 'experimental-feature-descriptions.md', +) diff --git a/doc/manual/src/language/constructs.md b/doc/manual/src/language/constructs.md new file mode 100644 index 000000000..41a180246 --- /dev/null +++ b/doc/manual/src/language/constructs.md @@ -0,0 +1 @@ +# Language Constructs diff --git a/doc/manual/src/language/meson.build b/doc/manual/src/language/meson.build new file mode 100644 index 000000000..97469e2f3 --- /dev/null +++ b/doc/manual/src/language/meson.build @@ -0,0 +1,20 @@ +builtins_md = custom_target( + command : [ + python.full_path(), + '@INPUT0@', + '@OUTPUT@', + '--' + ] + nix_eval_for_docs + [ + '--expr', + '(builtins.readFile @INPUT3@) + import @INPUT1@ (builtins.fromJSON (builtins.readFile ./@INPUT2@)) + (builtins.readFile @INPUT4@)', + ], + input : [ + '../../remove_before_wrapper.py', + '../../generate-builtins.nix', + language_json, + 'builtins-prefix.md', + 'builtins-suffix.md' + ], + output : 'builtins.md', + env : nix_env_for_docs, +) diff --git a/doc/manual/src/language/values.md b/doc/manual/src/language/values.md new file mode 100644 index 000000000..e05f56025 --- /dev/null +++ b/doc/manual/src/language/values.md @@ -0,0 +1 @@ +# Data Types diff --git a/doc/manual/src/meson.build b/doc/manual/src/meson.build new file mode 100644 index 000000000..098a29897 --- /dev/null +++ b/doc/manual/src/meson.build @@ -0,0 +1,17 @@ +summary_rl_next = custom_target( + command : [ + bash, + '-euo', 'pipefail', + '-c', + ''' + if [ -e "@INPUT@" ]; then + echo ' - [Upcoming release](release-notes/rl-next.md)' + fi + ''', + ], + input : [ + rl_next_generated, + ], + capture: true, + output : 'SUMMARY-rl-next.md', +) diff --git a/doc/manual/src/protocols/json/index.md b/doc/manual/src/protocols/json/index.md new file mode 100644 index 000000000..1fcd1e62d --- /dev/null +++ b/doc/manual/src/protocols/json/index.md @@ -0,0 +1 @@ +# JSON Formats diff --git a/doc/manual/src/release-notes/meson.build b/doc/manual/src/release-notes/meson.build new file mode 100644 index 000000000..d8bf154e1 --- /dev/null +++ b/doc/manual/src/release-notes/meson.build @@ -0,0 +1,24 @@ +rl_next_generated = custom_target( + command : [ + 'bash', + '-euo', + 'pipefail', + '-c', + ''' + if type -p build-release-notes > /dev/null; then + build-release-notes --change-authors @CURRENT_SOURCE_DIR@/../../change-authors.yml @CURRENT_SOURCE_DIR@/../../rl-next + elif type -p changelog-d > /dev/null; then + changelog-d @CURRENT_SOURCE_DIR@/../../rl-next + fi + @0@ @INPUT0@ @CURRENT_SOURCE_DIR@/../../rl-next > @DEPFILE@ + '''.format( + python.full_path(), + ), + ], + input : [ + generate_manual_deps, + ], + output : 'rl-next.md', + capture : true, + depfile : 'rl-next.d', +) diff --git a/doc/manual/src/store/meson.build b/doc/manual/src/store/meson.build new file mode 100644 index 000000000..e3006020d --- /dev/null +++ b/doc/manual/src/store/meson.build @@ -0,0 +1,18 @@ +types_dir = custom_target( + command : [ + python.full_path(), + '@INPUT0@', + '@OUTPUT@', + '--' + ] + nix_eval_for_docs + [ + '--expr', + 'import @INPUT1@ (builtins.fromJSON (builtins.readFile ./@INPUT2@)).stores', + ], + input : [ + '../../remove_before_wrapper.py', + '../../generate-store-types.nix', + nix3_cli_json, + ], + output : 'types', + env : nix_env_for_docs, +) diff --git a/doc/manual/substitute.py b/doc/manual/substitute.py new file mode 100644 index 000000000..52cef4fa0 --- /dev/null +++ b/doc/manual/substitute.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python3 + +from pathlib import Path +import json +import os, os.path +import sys +import typing as t + +name = 'substitute.py' + +def log(*args: t.Any, **kwargs: t.Any) -> None: + kwargs['file'] = sys.stderr + print(f'{name}:', *args, **kwargs) + +def do_include(content: str, relative_md_path: Path, source_root: Path, search_path: Path) -> str: + assert not relative_md_path.is_absolute(), f'{relative_md_path=} from mdbook should be relative' + + md_path_abs = source_root / relative_md_path + var_abs = md_path_abs.parent + assert var_abs.is_dir(), f'supposed directory {var_abs} is not a directory (cwd={os.getcwd()})' + + lines = [] + for l in content.splitlines(keepends=True): + if l.strip().startswith("{{#include "): + requested = l.strip()[11:][:-2] + if requested.startswith("@generated@/"): + included = search_path / Path(requested[12:]) + requested = included.relative_to(search_path) + else: + included = source_root / relative_md_path.parent / requested + requested = included.resolve().relative_to(source_root) + assert included.exists(), f"{requested} not found at {included}" + lines.append(do_include(included.read_text(), requested, source_root, search_path) + "\n") + else: + lines.append(l) + return "".join(lines) + +def recursive_replace(data: dict[str, t.Any], book_root: Path, search_path: Path) -> dict[str, t.Any]: + match data: + case {'sections': sections}: + return data | dict( + sections = [recursive_replace(section, book_root, search_path) for section in sections], + ) + case {'Chapter': chapter}: + path_to_chapter = Path(chapter['path']) + chapter_content = chapter['content'] + + return data | dict( + Chapter = chapter | dict( + # first process includes. this must happen before docroot processing since + # mdbook does not see these included files, only the final agglomeration. + content = do_include( + chapter_content, + path_to_chapter, + book_root, + search_path + ).replace( + '@docroot@', + ("../" * len(path_to_chapter.parent.parts) or "./")[:-1] + ), + sub_items = [ + recursive_replace(sub_item, book_root, search_path) + for sub_item in chapter['sub_items'] + ], + ), + ) + + case rest: + assert False, f'should have been called on a dict, not {type(rest)=}\n\t{rest=}' + +def main() -> None: + + + if len(sys.argv) > 1 and sys.argv[1] == 'supports': + return 0 + + # includes pointing into @generated@ will look here + search_path = Path(os.environ['MDBOOK_SUBSTITUTE_SEARCH']) + + if len(sys.argv) > 1 and sys.argv[1] == 'summary': + print(do_include( + sys.stdin.read(), + Path('src/SUMMARY.md'), + Path(sys.argv[2]).resolve(), + search_path)) + return + + # mdbook communicates with us over stdin and stdout. + # It splorks us a JSON array, the first element describing the context, + # the second element describing the book itself, + # and then expects us to send it the modified book JSON over stdout. + + context, book = json.load(sys.stdin) + + # book_root is the directory where book contents leave (ie, src/) + book_root = Path(context['root']) / context['config']['book']['src'] + + # Find @var@ in all parts of our recursive book structure. + replaced_content = recursive_replace(book, book_root, search_path) + + replaced_content_str = json.dumps(replaced_content) + + # Give mdbook our changes. + print(replaced_content_str) + +try: + sys.exit(main()) +except AssertionError as e: + print(f'{name}: INTERNAL ERROR in mdbook preprocessor: {e}', file=sys.stderr) + print(f'this is a bug in {name}', file=sys.stderr) + raise diff --git a/flake.nix b/flake.nix index 64b587760..303779c2b 100644 --- a/flake.nix +++ b/flake.nix @@ -221,6 +221,7 @@ inherit (nixpkgsFor.${system}.native) changelog-d; default = self.packages.${system}.nix-ng; + nix-manual = nixpkgsFor.${system}.native.nixComponents.nix-manual; nix-internal-api-docs = nixpkgsFor.${system}.native.nixComponents.nix-internal-api-docs; nix-external-api-docs = nixpkgsFor.${system}.native.nixComponents.nix-external-api-docs; } @@ -349,6 +350,7 @@ ++ pkgs.nixComponents.nix-store.nativeBuildInputs ++ pkgs.nixComponents.nix-fetchers.nativeBuildInputs ++ lib.optionals havePerl pkgs.nixComponents.nix-perl-bindings.nativeBuildInputs + ++ lib.optionals buildCanExecuteHost pkgs.nixComponents.nix-manual.externalNativeBuildInputs ++ pkgs.nixComponents.nix-internal-api-docs.nativeBuildInputs ++ pkgs.nixComponents.nix-external-api-docs.nativeBuildInputs ++ pkgs.nixComponents.nix-functional-tests.externalNativeBuildInputs diff --git a/meson.build b/meson.build index 8dd44cc10..636d38b08 100644 --- a/meson.build +++ b/meson.build @@ -23,6 +23,9 @@ subproject('nix') # Docs subproject('internal-api-docs') subproject('external-api-docs') +if not meson.is_cross_build() + subproject('nix-manual') +endif # External C wrapper libraries subproject('libutil-c') diff --git a/packaging/components.nix b/packaging/components.nix index 5fc3236cf..4c18dc6a3 100644 --- a/packaging/components.nix +++ b/packaging/components.nix @@ -60,6 +60,7 @@ in nix-functional-tests = callPackage ../src/nix-functional-tests/package.nix { version = fineVersion; }; + nix-manual = callPackage ../doc/manual/package.nix { version = fineVersion; }; nix-internal-api-docs = callPackage ../src/internal-api-docs/package.nix { version = fineVersion; }; nix-external-api-docs = callPackage ../src/external-api-docs/package.nix { version = fineVersion; }; diff --git a/packaging/everything.nix b/packaging/everything.nix index d26c81572..ae2f93da0 100644 --- a/packaging/everything.nix +++ b/packaging/everything.nix @@ -33,6 +33,7 @@ nix-functional-tests, + nix-manual, nix-internal-api-docs, nix-external-api-docs, @@ -70,6 +71,7 @@ nix-cli + nix-manual nix-internal-api-docs nix-external-api-docs diff --git a/packaging/hydra.nix b/packaging/hydra.nix index 65978835c..cba1b2583 100644 --- a/packaging/hydra.nix +++ b/packaging/hydra.nix @@ -146,6 +146,9 @@ in withCoverageChecks = true; }; + # Nix's manual + manual = nixpkgsFor.x86_64-linux.native.nixComponents.nix-manual; + # API docs for Nix's unstable internal C++ interfaces. internal-api-docs = nixpkgsFor.x86_64-linux.native.nixComponents.nix-internal-api-docs; diff --git a/src/nix-manual b/src/nix-manual new file mode 120000 index 000000000..492c97408 --- /dev/null +++ b/src/nix-manual @@ -0,0 +1 @@ +../doc/manual/ \ No newline at end of file From 0be70469dccbf58f478113fa515609bcfbc92e64 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 9 Oct 2024 20:53:43 +0200 Subject: [PATCH 288/718] Propagate errors from early sandbox initialization to the parent This should help with issues like https://github.com/DeterminateSystems/nix-installer/issues/1227, which currently just print "unable to start build process". --- .../unix/build/local-derivation-goal.cc | 103 +++++++++++++----- .../unix/build/local-derivation-goal.hh | 5 + tests/functional/supplementary-groups.sh | 8 +- 3 files changed, 81 insertions(+), 35 deletions(-) diff --git a/src/libstore/unix/build/local-derivation-goal.cc b/src/libstore/unix/build/local-derivation-goal.cc index 904b48f7b..0eda8455f 100644 --- a/src/libstore/unix/build/local-derivation-goal.cc +++ b/src/libstore/unix/build/local-derivation-goal.cc @@ -433,6 +433,41 @@ static void doBind(const Path & source, const Path & target, bool optional = fal }; #endif +/** + * Rethrow the current exception as a subclass of `Error`. + */ +static void rethrowExceptionAsError() +{ + try { + throw; + } catch (Error &) { + throw; + } catch (std::exception & e) { + throw Error(e.what()); + } catch (...) { + throw Error("unknown exception"); + } +} + +/** + * Send the current exception to the parent in the format expected by + * `LocalDerivationGoal::processSandboxSetupMessages()`. + */ +static void handleChildException(bool sendException) +{ + try { + rethrowExceptionAsError(); + } catch (Error & e) { + if (sendException) { + writeFull(STDERR_FILENO, "\1\n"); + FdSink sink(STDERR_FILENO); + sink << e; + sink.flush(); + } else + std::cerr << e.msg(); + } +} + void LocalDerivationGoal::startBuilder() { if ((buildUser && buildUser->getUIDCount() != 1) @@ -949,32 +984,40 @@ void LocalDerivationGoal::startBuilder() root. */ openSlave(); - /* Drop additional groups here because we can't do it - after we've created the new user namespace. */ - if (setgroups(0, 0) == -1) { - if (errno != EPERM) - throw SysError("setgroups failed"); - if (settings.requireDropSupplementaryGroups) - throw Error("setgroups failed. Set the require-drop-supplementary-groups option to false to skip this step."); + try { + /* Drop additional groups here because we can't do it + after we've created the new user namespace. */ + if (setgroups(0, 0) == -1) { + if (errno != EPERM) + throw SysError("setgroups failed"); + if (settings.requireDropSupplementaryGroups) + throw Error("setgroups failed. Set the require-drop-supplementary-groups option to false to skip this step."); + } + + ProcessOptions options; + options.cloneFlags = CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWIPC | CLONE_NEWUTS | CLONE_PARENT | SIGCHLD; + if (privateNetwork) + options.cloneFlags |= CLONE_NEWNET; + if (usingUserNamespace) + options.cloneFlags |= CLONE_NEWUSER; + + pid_t child = startProcess([&]() { runChild(); }, options); + + writeFull(sendPid.writeSide.get(), fmt("%d\n", child)); + _exit(0); + } catch (...) { + handleChildException(true); + _exit(1); } - - ProcessOptions options; - options.cloneFlags = CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWIPC | CLONE_NEWUTS | CLONE_PARENT | SIGCHLD; - if (privateNetwork) - options.cloneFlags |= CLONE_NEWNET; - if (usingUserNamespace) - options.cloneFlags |= CLONE_NEWUSER; - - pid_t child = startProcess([&]() { runChild(); }, options); - - writeFull(sendPid.writeSide.get(), fmt("%d\n", child)); - _exit(0); }); sendPid.writeSide.close(); - if (helper.wait() != 0) + if (helper.wait() != 0) { + processSandboxSetupMessages(); + // Only reached if the child process didn't send an exception. throw Error("unable to start build process"); + } userNamespaceSync.readSide = -1; @@ -1050,7 +1093,12 @@ void LocalDerivationGoal::startBuilder() pid.setSeparatePG(true); worker.childStarted(shared_from_this(), {builderOut.get()}, true, true); - /* Check if setting up the build environment failed. */ + processSandboxSetupMessages(); +} + + +void LocalDerivationGoal::processSandboxSetupMessages() +{ std::vector msgs; while (true) { std::string msg = [&]() { @@ -1078,7 +1126,8 @@ void LocalDerivationGoal::startBuilder() } -void LocalDerivationGoal::initTmpDir() { +void LocalDerivationGoal::initTmpDir() +{ /* In a sandbox, for determinism, always use the same temporary directory. */ #if __linux__ @@ -2237,14 +2286,8 @@ void LocalDerivationGoal::runChild() throw SysError("executing '%1%'", drv->builder); - } catch (Error & e) { - if (sendException) { - writeFull(STDERR_FILENO, "\1\n"); - FdSink sink(STDERR_FILENO); - sink << e; - sink.flush(); - } else - std::cerr << e.msg(); + } catch (...) { + handleChildException(sendException); _exit(1); } } diff --git a/src/libstore/unix/build/local-derivation-goal.hh b/src/libstore/unix/build/local-derivation-goal.hh index bf25cf2a6..231393308 100644 --- a/src/libstore/unix/build/local-derivation-goal.hh +++ b/src/libstore/unix/build/local-derivation-goal.hh @@ -210,6 +210,11 @@ struct LocalDerivationGoal : public DerivationGoal */ void initEnv(); + /** + * Process messages send by the sandbox initialization. + */ + void processSandboxSetupMessages(); + /** * Setup tmp dir location. */ diff --git a/tests/functional/supplementary-groups.sh b/tests/functional/supplementary-groups.sh index 5d329efc9..50259a3e1 100755 --- a/tests/functional/supplementary-groups.sh +++ b/tests/functional/supplementary-groups.sh @@ -9,7 +9,7 @@ needLocalStore "The test uses --store always so we would just be bypassing the d TODO_NixOS -unshare --mount --map-root-user bash < Date: Thu, 10 Oct 2024 11:00:01 +0200 Subject: [PATCH 289/718] Document common options in stable nix binaries (#11663) --- doc/manual/src/command-ref/opt-common.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/doc/manual/src/command-ref/opt-common.md b/doc/manual/src/command-ref/opt-common.md index 69a700207..70ae03959 100644 --- a/doc/manual/src/command-ref/opt-common.md +++ b/doc/manual/src/command-ref/opt-common.md @@ -1,3 +1,7 @@ + + # Common Options Most Nix commands accept the following command-line options: @@ -161,6 +165,14 @@ Most Nix commands accept the following command-line options: You can override this using `--arg`, e.g., `nix-env --install --attr pkgname --arg system \"i686-freebsd\"`. (Note that since the argument is a Nix string literal, you have to escape the quotes.) +- [`--arg-from-file`](#opt-arg-from-file) *name* *path* + + Pass the contents of file *path* as the argument *name* to Nix functions. + +- [`--arg-from-stdin`](#opt-arg-from-stdin) *name* + + Pass the contents of stdin as the argument *name* to Nix functions. + - [`--argstr`](#opt-argstr) *name* *value* This option is like `--arg`, only the value is not a Nix expression but a string. @@ -179,6 +191,10 @@ Most Nix commands accept the following command-line options: attribute of the fourth element of the array in the `foo` attribute of the top-level expression. +- [`--eval-store`](#opt-eval-store) *store-url* + + The [URL to the Nix store](@docroot@/store/types/index.md#store-url-format) to use for evaluation, i.e. where to store derivations (`.drv` files) and inputs referenced by them. + - [`--expr`](#opt-expr) / `-E` Interpret the command line arguments as a list of Nix expressions to be parsed and evaluated, rather than as a list of file names of Nix expressions. @@ -194,6 +210,10 @@ Most Nix commands accept the following command-line options: Paths added through `-I` take precedence over the [`nix-path` configuration setting](@docroot@/command-ref/conf-file.md#conf-nix-path) and the [`NIX_PATH` environment variable](@docroot@/command-ref/env-common.md#env-NIX_PATH). +- [`--impure`](#opt-impure) + + Allow access to mutable paths and repositories. + - [`--option`](#opt-option) *name* *value* Set the Nix configuration option *name* to *value*. From e6db2dafe6e33ceaa9fd7798caca5e75f7133ac3 Mon Sep 17 00:00:00 2001 From: Onni Hakala Date: Thu, 10 Oct 2024 20:35:55 +0300 Subject: [PATCH 290/718] Update distributed-builds.md Fixes deprecation warning from nix build: warning: 'nix store ping' is a deprecated alias for 'nix store info' --- doc/manual/src/advanced-topics/distributed-builds.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/manual/src/advanced-topics/distributed-builds.md b/doc/manual/src/advanced-topics/distributed-builds.md index ddabaeb4d..52acd039c 100644 --- a/doc/manual/src/advanced-topics/distributed-builds.md +++ b/doc/manual/src/advanced-topics/distributed-builds.md @@ -12,14 +12,14 @@ machine is accessible via SSH and that it has Nix installed. You can test whether connecting to the remote Nix instance works, e.g. ```console -$ nix store ping --store ssh://mac +$ nix store info --store ssh://mac ``` will try to connect to the machine named `mac`. It is possible to specify an SSH identity file as part of the remote store URI, e.g. ```console -$ nix store ping --store ssh://mac?ssh-key=/home/alice/my-key +$ nix store info --store ssh://mac?ssh-key=/home/alice/my-key ``` Since builds should be non-interactive, the key should not have a From 0500fba56a02c3c8458d257b6ea24af1c81c8b9e Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 11 Oct 2024 14:31:15 +0200 Subject: [PATCH 291/718] builtins.fetchurl: Fix segfault on s3:// URLs Also, add an activity to show that we're downloading an s3:// file. Fixes #11674. --- src/libstore/filetransfer.cc | 5 +++++ tests/nixos/s3-binary-cache-store.nix | 3 +++ 2 files changed, 8 insertions(+) diff --git a/src/libstore/filetransfer.cc b/src/libstore/filetransfer.cc index 154ec6007..e9e4b2c44 100644 --- a/src/libstore/filetransfer.cc +++ b/src/libstore/filetransfer.cc @@ -759,12 +759,17 @@ struct curlFileTransfer : public FileTransfer S3Helper s3Helper(profile, region, scheme, endpoint); + Activity act(*logger, lvlTalkative, actFileTransfer, + fmt("downloading '%s'", request.uri), + {request.uri}, request.parentAct); + // FIXME: implement ETag auto s3Res = s3Helper.getObject(bucketName, key); FileTransferResult res; if (!s3Res.data) throw FileTransferError(NotFound, "S3 object '%s' does not exist", request.uri); res.data = std::move(*s3Res.data); + res.urls.push_back(request.uri); callback(std::move(res)); #else throw nix::Error("cannot download '%s' because Nix is not built with S3 support", request.uri); diff --git a/tests/nixos/s3-binary-cache-store.nix b/tests/nixos/s3-binary-cache-store.nix index 015457968..6ae2e3572 100644 --- a/tests/nixos/s3-binary-cache-store.nix +++ b/tests/nixos/s3-binary-cache-store.nix @@ -51,6 +51,9 @@ in { server.succeed("${env} nix copy --to '${storeUrl}' ${pkgA}") + # Test fetchurl on s3:// URLs while we're at it. + client.succeed("${env} nix eval --impure --expr 'builtins.fetchurl { name = \"foo\"; url = \"s3://my-cache/nix-cache-info?endpoint=http://server:9000®ion=eu-west-1\"; }'") + # Copy a package from the binary cache. client.fail("nix path-info ${pkgA}") From d38f62f64d389cb4e9a582d89aa3f8a50fb3c074 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 11 Oct 2024 14:55:22 +0200 Subject: [PATCH 292/718] Make S3 downloads slightly more interruptable --- src/libstore/s3-binary-cache-store.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libstore/s3-binary-cache-store.cc b/src/libstore/s3-binary-cache-store.cc index 21175b1eb..bcbf0b55e 100644 --- a/src/libstore/s3-binary-cache-store.cc +++ b/src/libstore/s3-binary-cache-store.cc @@ -9,6 +9,7 @@ #include "globals.hh" #include "compression.hh" #include "filetransfer.hh" +#include "signals.hh" #include #include @@ -117,6 +118,7 @@ class RetryStrategy : public Aws::Client::DefaultRetryStrategy { bool ShouldRetry(const Aws::Client::AWSError& error, long attemptedRetries) const override { + checkInterrupt(); auto retry = Aws::Client::DefaultRetryStrategy::ShouldRetry(error, attemptedRetries); if (retry) printError("AWS error '%s' (%s), will retry in %d ms", From 30655dd146fb2d3bf3604632a6b65ce78f9709dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Fri, 11 Oct 2024 21:04:42 +0200 Subject: [PATCH 293/718] git-utils: fix x86_64-w64-mingw32 build --- src/libfetchers/git-utils.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libfetchers/git-utils.cc b/src/libfetchers/git-utils.cc index 582686412..d13daf887 100644 --- a/src/libfetchers/git-utils.cc +++ b/src/libfetchers/git-utils.cc @@ -208,7 +208,7 @@ static git_packbuilder_progress PACKBUILDER_PROGRESS_CHECK_INTERRUPT = &packBuil static void initRepoAtomically(std::filesystem::path &path, bool bare) { if (pathExists(path.string())) return; - Path tmpDir = createTempDir(std::filesystem::path(path).parent_path()); + Path tmpDir = createTempDir(os_string_to_string(PathViewNG { std::filesystem::path(path).parent_path() })); AutoDelete delTmpDir(tmpDir, true); Repository tmpRepo; From bd1961b7cce25f802436205d35d41f71d9bfba48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Fri, 11 Oct 2024 21:50:50 +0200 Subject: [PATCH 294/718] meson: fix executable extensions for windows build --- src/nix/meson.build | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/nix/meson.build b/src/nix/meson.build index 6edb768e3..275a35c24 100644 --- a/src/nix/meson.build +++ b/src/nix/meson.build @@ -212,18 +212,23 @@ nix_symlinks = [ 'nix-store', ] +name_suffix = '' +if host_machine.system() == 'windows' + name_suffix = '.exe' +endif + foreach linkname : nix_symlinks install_symlink( - linkname, + linkname + name_suffix, # TODO(Qyriad): should these continue to be relative symlinks? - pointing_to : 'nix', + pointing_to : fs.name(this_exe), install_dir : get_option('bindir'), # The 'runtime' tag is what executables default to, which we want to emulate here. install_tag : 'runtime' ) t = custom_target( command: ['ln', '-sf', fs.name(this_exe), '@OUTPUT@'], - output: linkname, + output: linkname + name_suffix, # TODO(Ericson2314): Don't do this once we have the `meson.override_find_program` working) build_by_default: true ) @@ -233,15 +238,15 @@ endforeach install_symlink( 'build-remote', - pointing_to : '..' / '..'/ get_option('bindir') / 'nix', - install_dir : get_option('libexecdir') / 'nix', + pointing_to : '..' / '..'/ get_option('bindir') / fs.name(this_exe), + install_dir : get_option('libexecdir') / fs.name(this_exe), # The 'runtime' tag is what executables default to, which we want to emulate here. install_tag : 'runtime' ) custom_target( command: ['ln', '-sf', fs.name(this_exe), '@OUTPUT@'], - output: 'build-remote', + output: 'build-remote' + name_suffix, # TODO(Ericson2314): Don't do this once we have the `meson.override_find_program` working) build_by_default: true ) From 5a794d93669a5abb4d151f4594264c38033650b1 Mon Sep 17 00:00:00 2001 From: Geoffrey Thomas Date: Sat, 12 Oct 2024 19:55:58 -0400 Subject: [PATCH 295/718] libstore: Make our sandbox pivot_root directory accessible to ourself If you have the Nix store mounted from a nonlocal filesystem whose exporter is not running as root, making the directory mode 000 makes it inaccessible to that remote unprivileged user and therefore breaks the build. (Specifically, I am running into this with a virtiofs mount using Apple Virtualization.framework as a non-root user, but I expect the same thing would happen with virtiofs in qemu on Linux as a non-root user or with various userspace network file servers.) Make the directory mode 500 (dr-x------) to make the sandbox work in this use case, which explicitly conveys our intention to read and search the directory. The code only works because root can already bypass directory checks, so this does not actually grant more permissions to the directory owner / does not make the sandbox less secure. --- src/libstore/unix/build/local-derivation-goal.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstore/unix/build/local-derivation-goal.cc b/src/libstore/unix/build/local-derivation-goal.cc index 0eda8455f..e3e3a4c9b 100644 --- a/src/libstore/unix/build/local-derivation-goal.cc +++ b/src/libstore/unix/build/local-derivation-goal.cc @@ -2008,7 +2008,7 @@ void LocalDerivationGoal::runChild() if (chdir(chrootRootDir.c_str()) == -1) throw SysError("cannot change directory to '%1%'", chrootRootDir); - if (mkdir("real-root", 0) == -1) + if (mkdir("real-root", 0500) == -1) throw SysError("cannot create real-root directory"); if (pivot_root(".", "real-root") == -1) From 3c59df412ad417e950505f319036af1659cc4aa9 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Sun, 13 Oct 2024 12:29:48 +0200 Subject: [PATCH 296/718] nix/meson.build: Rename name_suffix -> executable_suffix --- src/nix/meson.build | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/nix/meson.build b/src/nix/meson.build index 275a35c24..55089d821 100644 --- a/src/nix/meson.build +++ b/src/nix/meson.build @@ -212,14 +212,14 @@ nix_symlinks = [ 'nix-store', ] -name_suffix = '' +executable_suffix = '' if host_machine.system() == 'windows' - name_suffix = '.exe' + executable_suffix = '.exe' endif foreach linkname : nix_symlinks install_symlink( - linkname + name_suffix, + linkname + executable_suffix, # TODO(Qyriad): should these continue to be relative symlinks? pointing_to : fs.name(this_exe), install_dir : get_option('bindir'), @@ -228,7 +228,7 @@ foreach linkname : nix_symlinks ) t = custom_target( command: ['ln', '-sf', fs.name(this_exe), '@OUTPUT@'], - output: linkname + name_suffix, + output: linkname + executable_suffix, # TODO(Ericson2314): Don't do this once we have the `meson.override_find_program` working) build_by_default: true ) @@ -246,7 +246,7 @@ install_symlink( custom_target( command: ['ln', '-sf', fs.name(this_exe), '@OUTPUT@'], - output: 'build-remote' + name_suffix, + output: 'build-remote' + executable_suffix, # TODO(Ericson2314): Don't do this once we have the `meson.override_find_program` working) build_by_default: true ) From de0a34a36232c1cc36dcb2b1d29ba2c7ec944501 Mon Sep 17 00:00:00 2001 From: Valentin Gagarin Date: Sun, 13 Oct 2024 12:31:01 +0200 Subject: [PATCH 297/718] doc: note that `nix eval` is eager (#11670) doc: note that `nix eval` is eager --------- Co-authored-by: Robert Hensing --- src/nix/eval.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/nix/eval.md b/src/nix/eval.md index 48d5aa597..bd5b035e1 100644 --- a/src/nix/eval.md +++ b/src/nix/eval.md @@ -50,8 +50,9 @@ R""( # Description -This command evaluates the given Nix expression and prints the -result on standard output. +This command evaluates the given Nix expression, and prints the result on standard output. + +It also evaluates any nested attribute values and list items. # Output format From 0a49d1e0d2e722b8a532b2526c5b44214ec8946a Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Sun, 13 Oct 2024 22:03:52 +0200 Subject: [PATCH 298/718] refactor: lib.composeManyExtensions --- packaging/dependencies.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/dependencies.nix b/packaging/dependencies.nix index e5f4c0f91..d202ed44f 100644 --- a/packaging/dependencies.nix +++ b/packaging/dependencies.nix @@ -180,6 +180,6 @@ scope: { ]; in stdenv.mkDerivation (lib.extends - (lib.foldr lib.composeExtensions (_: _: {}) exts) + (lib.composeManyExtensions exts) f); } From d21026b6f12240d709d9149815af1e905224a133 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Sun, 13 Oct 2024 22:18:57 +0200 Subject: [PATCH 299/718] packaging: Remove package.nix from libexpr src --- src/libexpr/package.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libexpr/package.nix b/src/libexpr/package.nix index 4d10079ff..b69ee9814 100644 --- a/src/libexpr/package.nix +++ b/src/libexpr/package.nix @@ -55,7 +55,10 @@ mkMesonDerivation (finalAttrs: { (fileset.fileFilter (file: file.hasExt "hh") ./.) ./lexer.l ./parser.y - (fileset.fileFilter (file: file.hasExt "nix") ./.) + (fileset.difference + (fileset.fileFilter (file: file.hasExt "nix") ./.) + ./package.nix + ) ]; outputs = [ "out" "dev" ]; From 0aef34b790d7552109bf8d7b83e1f3e1792d16f9 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Sun, 13 Oct 2024 22:25:25 +0200 Subject: [PATCH 300/718] packaging: Add mesonLayer ... and remove a few unused arguments. This adds pkg-config to a two or three packages that don't use it, but we shouldn't let that bother us. It's like our personal stdenv. --- packaging/dependencies.nix | 11 +++++++++++ src/external-api-docs/package.nix | 4 ---- src/internal-api-docs/package.nix | 4 ---- src/libcmd/package.nix | 11 ----------- src/libexpr-c/package.nix | 10 ---------- src/libexpr/package.nix | 7 ------- src/libfetchers/package.nix | 12 ------------ src/libflake/package.nix | 13 ------------- src/libmain-c/package.nix | 11 ----------- src/libmain/package.nix | 11 ----------- src/libstore-c/package.nix | 11 ----------- src/libstore/package.nix | 11 ++--------- src/libutil-c/package.nix | 11 ----------- src/libutil/package.nix | 11 ----------- src/nix/package.nix | 15 --------------- src/perl/package.nix | 7 ------- tests/unit/libexpr-support/package.nix | 11 ----------- tests/unit/libexpr/package.nix | 11 ----------- tests/unit/libfetchers/package.nix | 11 ----------- tests/unit/libflake/package.nix | 11 ----------- tests/unit/libstore-support/package.nix | 11 ----------- tests/unit/libstore/package.nix | 11 ----------- tests/unit/libutil-support/package.nix | 11 ----------- tests/unit/libutil/package.nix | 11 ----------- 24 files changed, 13 insertions(+), 235 deletions(-) diff --git a/packaging/dependencies.nix b/packaging/dependencies.nix index d202ed44f..49a65ce9e 100644 --- a/packaging/dependencies.nix +++ b/packaging/dependencies.nix @@ -60,6 +60,16 @@ let workDir = null; }; + mesonLayer = finalAttrs: prevAttrs: + { + mesonFlags = prevAttrs.mesonFlags or []; + nativeBuildInputs = [ + pkgs.buildPackages.meson + pkgs.buildPackages.ninja + pkgs.buildPackages.pkg-config + ] ++ prevAttrs.nativeBuildInputs or []; + }; + # Work around weird `--as-needed` linker behavior with BSD, see # https://github.com/mesonbuild/meson/issues/3593 bsdNoLinkAsNeeded = finalAttrs: prevAttrs: @@ -177,6 +187,7 @@ scope: { miscGoodPractice bsdNoLinkAsNeeded localSourceLayer + mesonLayer ]; in stdenv.mkDerivation (lib.extends diff --git a/src/external-api-docs/package.nix b/src/external-api-docs/package.nix index 743b3e9b7..0c592955a 100644 --- a/src/external-api-docs/package.nix +++ b/src/external-api-docs/package.nix @@ -1,8 +1,6 @@ { lib , mkMesonDerivation -, meson -, ninja , doxygen # Configuration Options @@ -37,8 +35,6 @@ mkMesonDerivation (finalAttrs: { ]; nativeBuildInputs = [ - meson - ninja doxygen ]; diff --git a/src/internal-api-docs/package.nix b/src/internal-api-docs/package.nix index 07ca6d4d9..993a257a6 100644 --- a/src/internal-api-docs/package.nix +++ b/src/internal-api-docs/package.nix @@ -1,8 +1,6 @@ { lib , mkMesonDerivation -, meson -, ninja , doxygen # Configuration Options @@ -32,8 +30,6 @@ mkMesonDerivation (finalAttrs: { ]; nativeBuildInputs = [ - meson - ninja doxygen ]; diff --git a/src/libcmd/package.nix b/src/libcmd/package.nix index cde494901..9ac28bb88 100644 --- a/src/libcmd/package.nix +++ b/src/libcmd/package.nix @@ -1,11 +1,6 @@ { lib , stdenv , mkMesonDerivation -, releaseTools - -, meson -, ninja -, pkg-config , nix-util , nix-store @@ -56,12 +51,6 @@ mkMesonDerivation (finalAttrs: { outputs = [ "out" "dev" ]; - nativeBuildInputs = [ - meson - ninja - pkg-config - ]; - buildInputs = [ ({ inherit editline readline; }.${readlineFlavor}) ] ++ lib.optional enableMarkdown lowdown; diff --git a/src/libexpr-c/package.nix b/src/libexpr-c/package.nix index eb42195a4..24ead19bc 100644 --- a/src/libexpr-c/package.nix +++ b/src/libexpr-c/package.nix @@ -2,10 +2,6 @@ , stdenv , mkMesonDerivation -, meson -, ninja -, pkg-config - , nix-store-c , nix-expr @@ -37,12 +33,6 @@ mkMesonDerivation (finalAttrs: { outputs = [ "out" "dev" ]; - nativeBuildInputs = [ - meson - ninja - pkg-config - ]; - propagatedBuildInputs = [ nix-store-c nix-expr diff --git a/src/libexpr/package.nix b/src/libexpr/package.nix index b69ee9814..4d4e14be2 100644 --- a/src/libexpr/package.nix +++ b/src/libexpr/package.nix @@ -1,11 +1,7 @@ { lib , stdenv , mkMesonDerivation -, releaseTools -, meson -, ninja -, pkg-config , bison , flex , cmake # for resolving toml11 dep @@ -64,9 +60,6 @@ mkMesonDerivation (finalAttrs: { outputs = [ "out" "dev" ]; nativeBuildInputs = [ - meson - ninja - pkg-config bison flex cmake diff --git a/src/libfetchers/package.nix b/src/libfetchers/package.nix index 9b5d8bff7..988ad3d1e 100644 --- a/src/libfetchers/package.nix +++ b/src/libfetchers/package.nix @@ -1,17 +1,11 @@ { lib , stdenv , mkMesonDerivation -, releaseTools - -, meson -, ninja -, pkg-config , nix-util , nix-store , nlohmann_json , libgit2 -, man # Configuration Options @@ -39,12 +33,6 @@ mkMesonDerivation (finalAttrs: { outputs = [ "out" "dev" ]; - nativeBuildInputs = [ - meson - ninja - pkg-config - ]; - buildInputs = [ libgit2 ]; diff --git a/src/libflake/package.nix b/src/libflake/package.nix index 851adf07e..50566a23a 100644 --- a/src/libflake/package.nix +++ b/src/libflake/package.nix @@ -1,19 +1,12 @@ { lib , stdenv , mkMesonDerivation -, releaseTools - -, meson -, ninja -, pkg-config , nix-util , nix-store , nix-fetchers , nix-expr , nlohmann_json -, libgit2 -, man # Configuration Options @@ -41,12 +34,6 @@ mkMesonDerivation (finalAttrs: { outputs = [ "out" "dev" ]; - nativeBuildInputs = [ - meson - ninja - pkg-config - ]; - propagatedBuildInputs = [ nix-store nix-util diff --git a/src/libmain-c/package.nix b/src/libmain-c/package.nix index ce6f67300..15d27bdfb 100644 --- a/src/libmain-c/package.nix +++ b/src/libmain-c/package.nix @@ -1,11 +1,6 @@ { lib , stdenv , mkMesonDerivation -, releaseTools - -, meson -, ninja -, pkg-config , nix-util-c , nix-store @@ -40,12 +35,6 @@ mkMesonDerivation (finalAttrs: { outputs = [ "out" "dev" ]; - nativeBuildInputs = [ - meson - ninja - pkg-config - ]; - propagatedBuildInputs = [ nix-util-c nix-store diff --git a/src/libmain/package.nix b/src/libmain/package.nix index 47513dbdc..dfed47110 100644 --- a/src/libmain/package.nix +++ b/src/libmain/package.nix @@ -1,11 +1,6 @@ { lib , stdenv , mkMesonDerivation -, releaseTools - -, meson -, ninja -, pkg-config , openssl @@ -38,12 +33,6 @@ mkMesonDerivation (finalAttrs: { outputs = [ "out" "dev" ]; - nativeBuildInputs = [ - meson - ninja - pkg-config - ]; - propagatedBuildInputs = [ nix-util nix-store diff --git a/src/libstore-c/package.nix b/src/libstore-c/package.nix index e4f372236..6f1ec4ad0 100644 --- a/src/libstore-c/package.nix +++ b/src/libstore-c/package.nix @@ -1,11 +1,6 @@ { lib , stdenv , mkMesonDerivation -, releaseTools - -, meson -, ninja -, pkg-config , nix-util-c , nix-store @@ -38,12 +33,6 @@ mkMesonDerivation (finalAttrs: { outputs = [ "out" "dev" ]; - nativeBuildInputs = [ - meson - ninja - pkg-config - ]; - propagatedBuildInputs = [ nix-util-c nix-store diff --git a/src/libstore/package.nix b/src/libstore/package.nix index 4582ba0d2..c52968ac3 100644 --- a/src/libstore/package.nix +++ b/src/libstore/package.nix @@ -1,11 +1,7 @@ { lib , stdenv , mkMesonDerivation -, releaseTools -, meson -, ninja -, pkg-config , unixtools , nix-util @@ -53,11 +49,8 @@ mkMesonDerivation (finalAttrs: { outputs = [ "out" "dev" ]; - nativeBuildInputs = [ - meson - ninja - pkg-config - ] ++ lib.optional embeddedSandboxShell unixtools.hexdump; + nativeBuildInputs = + lib.optional embeddedSandboxShell unixtools.hexdump; buildInputs = [ boost diff --git a/src/libutil-c/package.nix b/src/libutil-c/package.nix index ccfafd4d3..f2d28fb51 100644 --- a/src/libutil-c/package.nix +++ b/src/libutil-c/package.nix @@ -1,11 +1,6 @@ { lib , stdenv , mkMesonDerivation -, releaseTools - -, meson -, ninja -, pkg-config , nix-util @@ -37,12 +32,6 @@ mkMesonDerivation (finalAttrs: { outputs = [ "out" "dev" ]; - nativeBuildInputs = [ - meson - ninja - pkg-config - ]; - propagatedBuildInputs = [ nix-util ]; diff --git a/src/libutil/package.nix b/src/libutil/package.nix index 4ce1a75b0..9ae9a3ee7 100644 --- a/src/libutil/package.nix +++ b/src/libutil/package.nix @@ -1,11 +1,6 @@ { lib , stdenv , mkMesonDerivation -, releaseTools - -, meson -, ninja -, pkg-config , boost , brotli @@ -45,12 +40,6 @@ mkMesonDerivation (finalAttrs: { outputs = [ "out" "dev" ]; - nativeBuildInputs = [ - meson - ninja - pkg-config - ]; - buildInputs = [ brotli libsodium diff --git a/src/nix/package.nix b/src/nix/package.nix index 3e19c6dca..de7abe6b3 100644 --- a/src/nix/package.nix +++ b/src/nix/package.nix @@ -1,21 +1,12 @@ { lib , stdenv , mkMesonDerivation -, releaseTools - -, meson -, ninja -, pkg-config , nix-store , nix-expr , nix-main , nix-cmd -, rapidcheck -, gtest -, runCommand - # Configuration Options , version @@ -90,12 +81,6 @@ mkMesonDerivation (finalAttrs: { ] ); - nativeBuildInputs = [ - meson - ninja - pkg-config - ]; - buildInputs = [ nix-store nix-expr diff --git a/src/perl/package.nix b/src/perl/package.nix index 0b9343fba..681ece32a 100644 --- a/src/perl/package.nix +++ b/src/perl/package.nix @@ -3,11 +3,7 @@ , mkMesonDerivation , perl , perlPackages -, meson -, ninja -, pkg-config , nix-store -, darwin , version , curl , bzip2 @@ -36,9 +32,6 @@ perl.pkgs.toPerlModule (mkMesonDerivation (finalAttrs: { ]); nativeBuildInputs = [ - meson - ninja - pkg-config perl curl ]; diff --git a/tests/unit/libexpr-support/package.nix b/tests/unit/libexpr-support/package.nix index f53aa842f..e0f9c334a 100644 --- a/tests/unit/libexpr-support/package.nix +++ b/tests/unit/libexpr-support/package.nix @@ -1,11 +1,6 @@ { lib , stdenv , mkMesonDerivation -, releaseTools - -, meson -, ninja -, pkg-config , nix-store-test-support , nix-expr @@ -39,12 +34,6 @@ mkMesonDerivation (finalAttrs: { outputs = [ "out" "dev" ]; - nativeBuildInputs = [ - meson - ninja - pkg-config - ]; - propagatedBuildInputs = [ nix-store-test-support nix-expr diff --git a/tests/unit/libexpr/package.nix b/tests/unit/libexpr/package.nix index e70ed7836..5eb8169d8 100644 --- a/tests/unit/libexpr/package.nix +++ b/tests/unit/libexpr/package.nix @@ -2,11 +2,6 @@ , buildPackages , stdenv , mkMesonDerivation -, releaseTools - -, meson -, ninja -, pkg-config , nix-expr , nix-expr-c @@ -42,12 +37,6 @@ mkMesonDerivation (finalAttrs: { (fileset.fileFilter (file: file.hasExt "hh") ./.) ]; - nativeBuildInputs = [ - meson - ninja - pkg-config - ]; - buildInputs = [ nix-expr nix-expr-c diff --git a/tests/unit/libfetchers/package.nix b/tests/unit/libfetchers/package.nix index ad512f562..571496307 100644 --- a/tests/unit/libfetchers/package.nix +++ b/tests/unit/libfetchers/package.nix @@ -2,11 +2,6 @@ , buildPackages , stdenv , mkMesonDerivation -, releaseTools - -, meson -, ninja -, pkg-config , nix-fetchers , nix-store-test-support @@ -41,12 +36,6 @@ mkMesonDerivation (finalAttrs: { (fileset.fileFilter (file: file.hasExt "hh") ./.) ]; - nativeBuildInputs = [ - meson - ninja - pkg-config - ]; - buildInputs = [ nix-fetchers nix-store-test-support diff --git a/tests/unit/libflake/package.nix b/tests/unit/libflake/package.nix index 0d63d2ff7..285d641d7 100644 --- a/tests/unit/libflake/package.nix +++ b/tests/unit/libflake/package.nix @@ -2,11 +2,6 @@ , buildPackages , stdenv , mkMesonDerivation -, releaseTools - -, meson -, ninja -, pkg-config , nix-flake , nix-expr-test-support @@ -41,12 +36,6 @@ mkMesonDerivation (finalAttrs: { (fileset.fileFilter (file: file.hasExt "hh") ./.) ]; - nativeBuildInputs = [ - meson - ninja - pkg-config - ]; - buildInputs = [ nix-flake nix-expr-test-support diff --git a/tests/unit/libstore-support/package.nix b/tests/unit/libstore-support/package.nix index f512db3ee..3c6fdb9fa 100644 --- a/tests/unit/libstore-support/package.nix +++ b/tests/unit/libstore-support/package.nix @@ -1,11 +1,6 @@ { lib , stdenv , mkMesonDerivation -, releaseTools - -, meson -, ninja -, pkg-config , nix-util-test-support , nix-store @@ -39,12 +34,6 @@ mkMesonDerivation (finalAttrs: { outputs = [ "out" "dev" ]; - nativeBuildInputs = [ - meson - ninja - pkg-config - ]; - propagatedBuildInputs = [ nix-util-test-support nix-store diff --git a/tests/unit/libstore/package.nix b/tests/unit/libstore/package.nix index 7560a5b79..8446e4d7a 100644 --- a/tests/unit/libstore/package.nix +++ b/tests/unit/libstore/package.nix @@ -2,11 +2,6 @@ , buildPackages , stdenv , mkMesonDerivation -, releaseTools - -, meson -, ninja -, pkg-config , nix-store , nix-store-c @@ -43,12 +38,6 @@ mkMesonDerivation (finalAttrs: { (fileset.fileFilter (file: file.hasExt "hh") ./.) ]; - nativeBuildInputs = [ - meson - ninja - pkg-config - ]; - buildInputs = [ nix-store nix-store-c diff --git a/tests/unit/libutil-support/package.nix b/tests/unit/libutil-support/package.nix index 1665804cb..add6d8fa8 100644 --- a/tests/unit/libutil-support/package.nix +++ b/tests/unit/libutil-support/package.nix @@ -1,11 +1,6 @@ { lib , stdenv , mkMesonDerivation -, releaseTools - -, meson -, ninja -, pkg-config , nix-util @@ -38,12 +33,6 @@ mkMesonDerivation (finalAttrs: { outputs = [ "out" "dev" ]; - nativeBuildInputs = [ - meson - ninja - pkg-config - ]; - propagatedBuildInputs = [ nix-util rapidcheck diff --git a/tests/unit/libutil/package.nix b/tests/unit/libutil/package.nix index 2fce5bfa8..fe8c9500e 100644 --- a/tests/unit/libutil/package.nix +++ b/tests/unit/libutil/package.nix @@ -2,11 +2,6 @@ , buildPackages , stdenv , mkMesonDerivation -, releaseTools - -, meson -, ninja -, pkg-config , nix-util , nix-util-c @@ -41,12 +36,6 @@ mkMesonDerivation (finalAttrs: { (fileset.fileFilter (file: file.hasExt "hh") ./.) ]; - nativeBuildInputs = [ - meson - ninja - pkg-config - ]; - buildInputs = [ nix-util nix-util-c From e10ff893e568adddec1c7f8cc95bcd768ba48b38 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Sun, 13 Oct 2024 22:40:09 +0200 Subject: [PATCH 301/718] packaging: Factor out mkPackageBuilder --- packaging/dependencies.nix | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/packaging/dependencies.nix b/packaging/dependencies.nix index 49a65ce9e..3e58a05d1 100644 --- a/packaging/dependencies.nix +++ b/packaging/dependencies.nix @@ -38,6 +38,10 @@ let # Indirection for Nixpkgs to override when package.nix files are vendored filesetToSource = lib.fileset.toSource; + /** Given a set of layers, create a mkDerivation-like function */ + mkPackageBuilder = exts: userFn: + stdenv.mkDerivation (lib.extends (lib.composeManyExtensions exts) userFn); + localSourceLayer = finalAttrs: prevAttrs: let workDirPath = @@ -62,7 +66,6 @@ let mesonLayer = finalAttrs: prevAttrs: { - mesonFlags = prevAttrs.mesonFlags or []; nativeBuildInputs = [ pkgs.buildPackages.meson pkgs.buildPackages.ninja @@ -182,15 +185,11 @@ scope: { inherit resolvePath filesetToSource; - mkMesonDerivation = f: let - exts = [ + mkMesonDerivation = + mkPackageBuilder [ miscGoodPractice bsdNoLinkAsNeeded localSourceLayer mesonLayer ]; - in stdenv.mkDerivation - (lib.extends - (lib.composeManyExtensions exts) - f); } From 15e3e1543b4e9edf3d0bd99558a8c30ee12d5343 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Sun, 13 Oct 2024 23:17:54 +0200 Subject: [PATCH 302/718] packaging: Add mkMeson{Library,Executable} and: - move pkg-config out of mkMesonDerivation, for components that don't produce any executable code --- packaging/dependencies.nix | 33 +++++++++++++++++++++++-- src/libcmd/package.nix | 10 ++------ src/libexpr-c/package.nix | 10 ++------ src/libexpr/package.nix | 10 ++------ src/libfetchers/package.nix | 10 ++------ src/libflake/package.nix | 10 ++------ src/libmain-c/package.nix | 10 ++------ src/libmain/package.nix | 10 ++------ src/libstore-c/package.nix | 10 ++------ src/libstore/package.nix | 10 ++------ src/libutil-c/package.nix | 10 ++------ src/libutil/package.nix | 10 ++------ src/nix/package.nix | 8 ++---- src/perl/package.nix | 2 ++ tests/functional/package.nix | 1 - tests/unit/libexpr-support/package.nix | 10 ++------ tests/unit/libexpr/package.nix | 8 ++---- tests/unit/libfetchers/package.nix | 8 ++---- tests/unit/libflake/package.nix | 8 ++---- tests/unit/libstore-support/package.nix | 10 ++------ tests/unit/libstore/package.nix | 8 ++---- tests/unit/libutil-support/package.nix | 10 ++------ tests/unit/libutil/package.nix | 8 ++---- 23 files changed, 73 insertions(+), 151 deletions(-) diff --git a/packaging/dependencies.nix b/packaging/dependencies.nix index 3e58a05d1..13766f2c0 100644 --- a/packaging/dependencies.nix +++ b/packaging/dependencies.nix @@ -69,10 +69,23 @@ let nativeBuildInputs = [ pkgs.buildPackages.meson pkgs.buildPackages.ninja - pkgs.buildPackages.pkg-config ] ++ prevAttrs.nativeBuildInputs or []; }; + mesonBuildLayer = finalAttrs: prevAttrs: + { + nativeBuildInputs = prevAttrs.nativeBuildInputs or [] ++ [ + pkgs.buildPackages.pkg-config + ]; + separateDebugInfo = !stdenv.hostPlatform.isStatic; + hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie"; + }; + + mesonLibraryLayer = finalAttrs: prevAttrs: + { + outputs = prevAttrs.outputs or [ "out" ] ++ [ "dev" ]; + }; + # Work around weird `--as-needed` linker behavior with BSD, see # https://github.com/mesonbuild/meson/issues/3593 bsdNoLinkAsNeeded = finalAttrs: prevAttrs: @@ -188,8 +201,24 @@ scope: { mkMesonDerivation = mkPackageBuilder [ miscGoodPractice - bsdNoLinkAsNeeded localSourceLayer mesonLayer ]; + mkMesonExecutable = + mkPackageBuilder [ + miscGoodPractice + bsdNoLinkAsNeeded + localSourceLayer + mesonLayer + mesonBuildLayer + ]; + mkMesonLibrary = + mkPackageBuilder [ + miscGoodPractice + bsdNoLinkAsNeeded + localSourceLayer + mesonLayer + mesonBuildLayer + mesonLibraryLayer + ]; } diff --git a/src/libcmd/package.nix b/src/libcmd/package.nix index 9ac28bb88..244179ee4 100644 --- a/src/libcmd/package.nix +++ b/src/libcmd/package.nix @@ -1,6 +1,6 @@ { lib , stdenv -, mkMesonDerivation +, mkMesonLibrary , nix-util , nix-store @@ -33,7 +33,7 @@ let inherit (lib) fileset; in -mkMesonDerivation (finalAttrs: { +mkMesonLibrary (finalAttrs: { pname = "nix-cmd"; inherit version; @@ -49,8 +49,6 @@ mkMesonDerivation (finalAttrs: { (fileset.fileFilter (file: file.hasExt "hh") ./.) ]; - outputs = [ "out" "dev" ]; - buildInputs = [ ({ inherit editline readline; }.${readlineFlavor}) ] ++ lib.optional enableMarkdown lowdown; @@ -82,10 +80,6 @@ mkMesonDerivation (finalAttrs: { LDFLAGS = "-fuse-ld=gold"; }; - separateDebugInfo = !stdenv.hostPlatform.isStatic; - - hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie"; - meta = { platforms = lib.platforms.unix ++ lib.platforms.windows; }; diff --git a/src/libexpr-c/package.nix b/src/libexpr-c/package.nix index 24ead19bc..df49a8bdc 100644 --- a/src/libexpr-c/package.nix +++ b/src/libexpr-c/package.nix @@ -1,6 +1,6 @@ { lib , stdenv -, mkMesonDerivation +, mkMesonLibrary , nix-store-c , nix-expr @@ -14,7 +14,7 @@ let inherit (lib) fileset; in -mkMesonDerivation (finalAttrs: { +mkMesonLibrary (finalAttrs: { pname = "nix-expr-c"; inherit version; @@ -31,8 +31,6 @@ mkMesonDerivation (finalAttrs: { (fileset.fileFilter (file: file.hasExt "h") ./.) ]; - outputs = [ "out" "dev" ]; - propagatedBuildInputs = [ nix-store-c nix-expr @@ -53,10 +51,6 @@ mkMesonDerivation (finalAttrs: { LDFLAGS = "-fuse-ld=gold"; }; - separateDebugInfo = !stdenv.hostPlatform.isStatic; - - hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie"; - meta = { platforms = lib.platforms.unix ++ lib.platforms.windows; }; diff --git a/src/libexpr/package.nix b/src/libexpr/package.nix index 4d4e14be2..ca1f8bf21 100644 --- a/src/libexpr/package.nix +++ b/src/libexpr/package.nix @@ -1,6 +1,6 @@ { lib , stdenv -, mkMesonDerivation +, mkMesonLibrary , bison , flex @@ -34,7 +34,7 @@ let inherit (lib) fileset; in -mkMesonDerivation (finalAttrs: { +mkMesonLibrary (finalAttrs: { pname = "nix-expr"; inherit version; @@ -57,8 +57,6 @@ mkMesonDerivation (finalAttrs: { ) ]; - outputs = [ "out" "dev" ]; - nativeBuildInputs = [ bison flex @@ -98,10 +96,6 @@ mkMesonDerivation (finalAttrs: { LDFLAGS = "-fuse-ld=gold"; }; - separateDebugInfo = !stdenv.hostPlatform.isStatic; - - hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie"; - meta = { platforms = lib.platforms.unix ++ lib.platforms.windows; }; diff --git a/src/libfetchers/package.nix b/src/libfetchers/package.nix index 988ad3d1e..70973bdb2 100644 --- a/src/libfetchers/package.nix +++ b/src/libfetchers/package.nix @@ -1,6 +1,6 @@ { lib , stdenv -, mkMesonDerivation +, mkMesonLibrary , nix-util , nix-store @@ -16,7 +16,7 @@ let inherit (lib) fileset; in -mkMesonDerivation (finalAttrs: { +mkMesonLibrary (finalAttrs: { pname = "nix-fetchers"; inherit version; @@ -31,8 +31,6 @@ mkMesonDerivation (finalAttrs: { (fileset.fileFilter (file: file.hasExt "hh") ./.) ]; - outputs = [ "out" "dev" ]; - buildInputs = [ libgit2 ]; @@ -55,10 +53,6 @@ mkMesonDerivation (finalAttrs: { LDFLAGS = "-fuse-ld=gold"; }; - separateDebugInfo = !stdenv.hostPlatform.isStatic; - - hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie"; - meta = { platforms = lib.platforms.unix ++ lib.platforms.windows; }; diff --git a/src/libflake/package.nix b/src/libflake/package.nix index 50566a23a..fff481720 100644 --- a/src/libflake/package.nix +++ b/src/libflake/package.nix @@ -1,6 +1,6 @@ { lib , stdenv -, mkMesonDerivation +, mkMesonLibrary , nix-util , nix-store @@ -17,7 +17,7 @@ let inherit (lib) fileset; in -mkMesonDerivation (finalAttrs: { +mkMesonLibrary (finalAttrs: { pname = "nix-flake"; inherit version; @@ -32,8 +32,6 @@ mkMesonDerivation (finalAttrs: { (fileset.fileFilter (file: file.hasExt "hh") ./.) ]; - outputs = [ "out" "dev" ]; - propagatedBuildInputs = [ nix-store nix-util @@ -54,10 +52,6 @@ mkMesonDerivation (finalAttrs: { LDFLAGS = "-fuse-ld=gold"; }; - separateDebugInfo = !stdenv.hostPlatform.isStatic; - - hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie"; - meta = { platforms = lib.platforms.unix ++ lib.platforms.windows; }; diff --git a/src/libmain-c/package.nix b/src/libmain-c/package.nix index 15d27bdfb..5522037f3 100644 --- a/src/libmain-c/package.nix +++ b/src/libmain-c/package.nix @@ -1,6 +1,6 @@ { lib , stdenv -, mkMesonDerivation +, mkMesonLibrary , nix-util-c , nix-store @@ -16,7 +16,7 @@ let inherit (lib) fileset; in -mkMesonDerivation (finalAttrs: { +mkMesonLibrary (finalAttrs: { pname = "nix-main-c"; inherit version; @@ -33,8 +33,6 @@ mkMesonDerivation (finalAttrs: { (fileset.fileFilter (file: file.hasExt "h") ./.) ]; - outputs = [ "out" "dev" ]; - propagatedBuildInputs = [ nix-util-c nix-store @@ -57,10 +55,6 @@ mkMesonDerivation (finalAttrs: { LDFLAGS = "-fuse-ld=gold"; }; - separateDebugInfo = !stdenv.hostPlatform.isStatic; - - hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie"; - meta = { platforms = lib.platforms.unix ++ lib.platforms.windows; }; diff --git a/src/libmain/package.nix b/src/libmain/package.nix index dfed47110..7e7b80472 100644 --- a/src/libmain/package.nix +++ b/src/libmain/package.nix @@ -1,6 +1,6 @@ { lib , stdenv -, mkMesonDerivation +, mkMesonLibrary , openssl @@ -16,7 +16,7 @@ let inherit (lib) fileset; in -mkMesonDerivation (finalAttrs: { +mkMesonLibrary (finalAttrs: { pname = "nix-main"; inherit version; @@ -31,8 +31,6 @@ mkMesonDerivation (finalAttrs: { (fileset.fileFilter (file: file.hasExt "hh") ./.) ]; - outputs = [ "out" "dev" ]; - propagatedBuildInputs = [ nix-util nix-store @@ -51,10 +49,6 @@ mkMesonDerivation (finalAttrs: { LDFLAGS = "-fuse-ld=gold"; }; - separateDebugInfo = !stdenv.hostPlatform.isStatic; - - hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie"; - meta = { platforms = lib.platforms.unix ++ lib.platforms.windows; }; diff --git a/src/libstore-c/package.nix b/src/libstore-c/package.nix index 6f1ec4ad0..896a1a39f 100644 --- a/src/libstore-c/package.nix +++ b/src/libstore-c/package.nix @@ -1,6 +1,6 @@ { lib , stdenv -, mkMesonDerivation +, mkMesonLibrary , nix-util-c , nix-store @@ -14,7 +14,7 @@ let inherit (lib) fileset; in -mkMesonDerivation (finalAttrs: { +mkMesonLibrary (finalAttrs: { pname = "nix-store-c"; inherit version; @@ -31,8 +31,6 @@ mkMesonDerivation (finalAttrs: { (fileset.fileFilter (file: file.hasExt "h") ./.) ]; - outputs = [ "out" "dev" ]; - propagatedBuildInputs = [ nix-util-c nix-store @@ -53,10 +51,6 @@ mkMesonDerivation (finalAttrs: { LDFLAGS = "-fuse-ld=gold"; }; - separateDebugInfo = !stdenv.hostPlatform.isStatic; - - hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie"; - meta = { platforms = lib.platforms.unix ++ lib.platforms.windows; }; diff --git a/src/libstore/package.nix b/src/libstore/package.nix index c52968ac3..9568462b5 100644 --- a/src/libstore/package.nix +++ b/src/libstore/package.nix @@ -1,6 +1,6 @@ { lib , stdenv -, mkMesonDerivation +, mkMesonLibrary , unixtools @@ -25,7 +25,7 @@ let inherit (lib) fileset; in -mkMesonDerivation (finalAttrs: { +mkMesonLibrary (finalAttrs: { pname = "nix-store"; inherit version; @@ -47,8 +47,6 @@ mkMesonDerivation (finalAttrs: { (fileset.fileFilter (file: file.hasExt "sql") ./.) ]; - outputs = [ "out" "dev" ]; - nativeBuildInputs = lib.optional embeddedSandboxShell unixtools.hexdump; @@ -91,10 +89,6 @@ mkMesonDerivation (finalAttrs: { LDFLAGS = "-fuse-ld=gold"; }; - separateDebugInfo = !stdenv.hostPlatform.isStatic; - - hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie"; - meta = { platforms = lib.platforms.unix ++ lib.platforms.windows; }; diff --git a/src/libutil-c/package.nix b/src/libutil-c/package.nix index f2d28fb51..35533f981 100644 --- a/src/libutil-c/package.nix +++ b/src/libutil-c/package.nix @@ -1,6 +1,6 @@ { lib , stdenv -, mkMesonDerivation +, mkMesonLibrary , nix-util @@ -13,7 +13,7 @@ let inherit (lib) fileset; in -mkMesonDerivation (finalAttrs: { +mkMesonLibrary (finalAttrs: { pname = "nix-util-c"; inherit version; @@ -30,8 +30,6 @@ mkMesonDerivation (finalAttrs: { (fileset.fileFilter (file: file.hasExt "h") ./.) ]; - outputs = [ "out" "dev" ]; - propagatedBuildInputs = [ nix-util ]; @@ -51,10 +49,6 @@ mkMesonDerivation (finalAttrs: { LDFLAGS = "-fuse-ld=gold"; }; - separateDebugInfo = !stdenv.hostPlatform.isStatic; - - hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie"; - meta = { platforms = lib.platforms.unix ++ lib.platforms.windows; }; diff --git a/src/libutil/package.nix b/src/libutil/package.nix index 9ae9a3ee7..17a156740 100644 --- a/src/libutil/package.nix +++ b/src/libutil/package.nix @@ -1,6 +1,6 @@ { lib , stdenv -, mkMesonDerivation +, mkMesonLibrary , boost , brotli @@ -19,7 +19,7 @@ let inherit (lib) fileset; in -mkMesonDerivation (finalAttrs: { +mkMesonLibrary (finalAttrs: { pname = "nix-util"; inherit version; @@ -38,8 +38,6 @@ mkMesonDerivation (finalAttrs: { (fileset.fileFilter (file: file.hasExt "hh") ./.) ]; - outputs = [ "out" "dev" ]; - buildInputs = [ brotli libsodium @@ -77,10 +75,6 @@ mkMesonDerivation (finalAttrs: { LDFLAGS = "-fuse-ld=gold"; }; - separateDebugInfo = !stdenv.hostPlatform.isStatic; - - hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie"; - meta = { platforms = lib.platforms.unix ++ lib.platforms.windows; }; diff --git a/src/nix/package.nix b/src/nix/package.nix index de7abe6b3..0a9c676d8 100644 --- a/src/nix/package.nix +++ b/src/nix/package.nix @@ -1,6 +1,6 @@ { lib , stdenv -, mkMesonDerivation +, mkMesonExecutable , nix-store , nix-expr @@ -16,7 +16,7 @@ let inherit (lib) fileset; in -mkMesonDerivation (finalAttrs: { +mkMesonExecutable (finalAttrs: { pname = "nix"; inherit version; @@ -103,10 +103,6 @@ mkMesonDerivation (finalAttrs: { LDFLAGS = "-fuse-ld=gold"; }; - separateDebugInfo = !stdenv.hostPlatform.isStatic; - - hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie"; - meta = { platforms = lib.platforms.unix ++ lib.platforms.windows; }; diff --git a/src/perl/package.nix b/src/perl/package.nix index 681ece32a..fe617fd47 100644 --- a/src/perl/package.nix +++ b/src/perl/package.nix @@ -1,6 +1,7 @@ { lib , stdenv , mkMesonDerivation +, pkg-config , perl , perlPackages , nix-store @@ -32,6 +33,7 @@ perl.pkgs.toPerlModule (mkMesonDerivation (finalAttrs: { ]); nativeBuildInputs = [ + pkg-config perl curl ]; diff --git a/tests/functional/package.nix b/tests/functional/package.nix index a0c1f249f..21be38c54 100644 --- a/tests/functional/package.nix +++ b/tests/functional/package.nix @@ -75,7 +75,6 @@ mkMesonDerivation (finalAttrs: { nix-expr ]; - preConfigure = # "Inline" .version so it's not a symlink, and includes the suffix. # Do the meson utils, without modification. diff --git a/tests/unit/libexpr-support/package.nix b/tests/unit/libexpr-support/package.nix index e0f9c334a..234d83730 100644 --- a/tests/unit/libexpr-support/package.nix +++ b/tests/unit/libexpr-support/package.nix @@ -1,6 +1,6 @@ { lib , stdenv -, mkMesonDerivation +, mkMesonLibrary , nix-store-test-support , nix-expr @@ -16,7 +16,7 @@ let inherit (lib) fileset; in -mkMesonDerivation (finalAttrs: { +mkMesonLibrary (finalAttrs: { pname = "nix-util-test-support"; inherit version; @@ -32,8 +32,6 @@ mkMesonDerivation (finalAttrs: { (fileset.fileFilter (file: file.hasExt "hh") ./.) ]; - outputs = [ "out" "dev" ]; - propagatedBuildInputs = [ nix-store-test-support nix-expr @@ -55,10 +53,6 @@ mkMesonDerivation (finalAttrs: { LDFLAGS = "-fuse-ld=gold"; }; - separateDebugInfo = !stdenv.hostPlatform.isStatic; - - hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie"; - meta = { platforms = lib.platforms.unix ++ lib.platforms.windows; }; diff --git a/tests/unit/libexpr/package.nix b/tests/unit/libexpr/package.nix index 5eb8169d8..1d99b581c 100644 --- a/tests/unit/libexpr/package.nix +++ b/tests/unit/libexpr/package.nix @@ -1,7 +1,7 @@ { lib , buildPackages , stdenv -, mkMesonDerivation +, mkMesonExecutable , nix-expr , nix-expr-c @@ -21,7 +21,7 @@ let inherit (lib) fileset; in -mkMesonDerivation (finalAttrs: { +mkMesonExecutable (finalAttrs: { pname = "nix-expr-tests"; inherit version; @@ -60,10 +60,6 @@ mkMesonDerivation (finalAttrs: { LDFLAGS = "-fuse-ld=gold"; }; - separateDebugInfo = !stdenv.hostPlatform.isStatic; - - hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie"; - passthru = { tests = { run = runCommand "${finalAttrs.pname}-run" { diff --git a/tests/unit/libfetchers/package.nix b/tests/unit/libfetchers/package.nix index 571496307..ed27b4021 100644 --- a/tests/unit/libfetchers/package.nix +++ b/tests/unit/libfetchers/package.nix @@ -1,7 +1,7 @@ { lib , buildPackages , stdenv -, mkMesonDerivation +, mkMesonExecutable , nix-fetchers , nix-store-test-support @@ -20,7 +20,7 @@ let inherit (lib) fileset; in -mkMesonDerivation (finalAttrs: { +mkMesonExecutable (finalAttrs: { pname = "nix-fetchers-tests"; inherit version; @@ -58,10 +58,6 @@ mkMesonDerivation (finalAttrs: { LDFLAGS = "-fuse-ld=gold"; }; - separateDebugInfo = !stdenv.hostPlatform.isStatic; - - hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie"; - passthru = { tests = { run = runCommand "${finalAttrs.pname}-run" { diff --git a/tests/unit/libflake/package.nix b/tests/unit/libflake/package.nix index 285d641d7..eaf946202 100644 --- a/tests/unit/libflake/package.nix +++ b/tests/unit/libflake/package.nix @@ -1,7 +1,7 @@ { lib , buildPackages , stdenv -, mkMesonDerivation +, mkMesonExecutable , nix-flake , nix-expr-test-support @@ -20,7 +20,7 @@ let inherit (lib) fileset; in -mkMesonDerivation (finalAttrs: { +mkMesonExecutable (finalAttrs: { pname = "nix-flake-tests"; inherit version; @@ -58,10 +58,6 @@ mkMesonDerivation (finalAttrs: { LDFLAGS = "-fuse-ld=gold"; }; - separateDebugInfo = !stdenv.hostPlatform.isStatic; - - hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie"; - passthru = { tests = { run = runCommand "${finalAttrs.pname}-run" { diff --git a/tests/unit/libstore-support/package.nix b/tests/unit/libstore-support/package.nix index 3c6fdb9fa..b6106b727 100644 --- a/tests/unit/libstore-support/package.nix +++ b/tests/unit/libstore-support/package.nix @@ -1,6 +1,6 @@ { lib , stdenv -, mkMesonDerivation +, mkMesonLibrary , nix-util-test-support , nix-store @@ -16,7 +16,7 @@ let inherit (lib) fileset; in -mkMesonDerivation (finalAttrs: { +mkMesonLibrary (finalAttrs: { pname = "nix-store-test-support"; inherit version; @@ -32,8 +32,6 @@ mkMesonDerivation (finalAttrs: { (fileset.fileFilter (file: file.hasExt "hh") ./.) ]; - outputs = [ "out" "dev" ]; - propagatedBuildInputs = [ nix-util-test-support nix-store @@ -55,10 +53,6 @@ mkMesonDerivation (finalAttrs: { LDFLAGS = "-fuse-ld=gold"; }; - separateDebugInfo = !stdenv.hostPlatform.isStatic; - - hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie"; - meta = { platforms = lib.platforms.unix ++ lib.platforms.windows; }; diff --git a/tests/unit/libstore/package.nix b/tests/unit/libstore/package.nix index 8446e4d7a..5fbb34a76 100644 --- a/tests/unit/libstore/package.nix +++ b/tests/unit/libstore/package.nix @@ -1,7 +1,7 @@ { lib , buildPackages , stdenv -, mkMesonDerivation +, mkMesonExecutable , nix-store , nix-store-c @@ -22,7 +22,7 @@ let inherit (lib) fileset; in -mkMesonDerivation (finalAttrs: { +mkMesonExecutable (finalAttrs: { pname = "nix-store-tests"; inherit version; @@ -62,10 +62,6 @@ mkMesonDerivation (finalAttrs: { LDFLAGS = "-fuse-ld=gold"; }; - separateDebugInfo = !stdenv.hostPlatform.isStatic; - - hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie"; - passthru = { tests = { run = let diff --git a/tests/unit/libutil-support/package.nix b/tests/unit/libutil-support/package.nix index add6d8fa8..16319cf2d 100644 --- a/tests/unit/libutil-support/package.nix +++ b/tests/unit/libutil-support/package.nix @@ -1,6 +1,6 @@ { lib , stdenv -, mkMesonDerivation +, mkMesonLibrary , nix-util @@ -15,7 +15,7 @@ let inherit (lib) fileset; in -mkMesonDerivation (finalAttrs: { +mkMesonLibrary (finalAttrs: { pname = "nix-util-test-support"; inherit version; @@ -31,8 +31,6 @@ mkMesonDerivation (finalAttrs: { (fileset.fileFilter (file: file.hasExt "hh") ./.) ]; - outputs = [ "out" "dev" ]; - propagatedBuildInputs = [ nix-util rapidcheck @@ -53,10 +51,6 @@ mkMesonDerivation (finalAttrs: { LDFLAGS = "-fuse-ld=gold"; }; - separateDebugInfo = !stdenv.hostPlatform.isStatic; - - hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie"; - meta = { platforms = lib.platforms.unix ++ lib.platforms.windows; }; diff --git a/tests/unit/libutil/package.nix b/tests/unit/libutil/package.nix index fe8c9500e..37a80e639 100644 --- a/tests/unit/libutil/package.nix +++ b/tests/unit/libutil/package.nix @@ -1,7 +1,7 @@ { lib , buildPackages , stdenv -, mkMesonDerivation +, mkMesonExecutable , nix-util , nix-util-c @@ -20,7 +20,7 @@ let inherit (lib) fileset; in -mkMesonDerivation (finalAttrs: { +mkMesonExecutable (finalAttrs: { pname = "nix-util-tests"; inherit version; @@ -59,10 +59,6 @@ mkMesonDerivation (finalAttrs: { LDFLAGS = "-fuse-ld=gold"; }; - separateDebugInfo = !stdenv.hostPlatform.isStatic; - - hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie"; - passthru = { tests = { run = runCommand "${finalAttrs.pname}-run" { From d2f4d076195f048146fa64916283a524f6820380 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 14 Oct 2024 13:15:55 +0200 Subject: [PATCH 303/718] Add assert --- src/libfetchers/tarball.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libfetchers/tarball.cc b/src/libfetchers/tarball.cc index aa5d61bc5..28574e7b1 100644 --- a/src/libfetchers/tarball.cc +++ b/src/libfetchers/tarball.cc @@ -90,6 +90,7 @@ DownloadFileResult downloadFile( /* Cache metadata for all URLs in the redirect chain. */ for (auto & url : res.urls) { key.second.insert_or_assign("url", url); + assert(!res.urls.empty()); infoAttrs.insert_or_assign("url", *res.urls.rbegin()); getCache()->upsert(key, *store, infoAttrs, *storePath); } From 4012954b596b725dd61d49668691a69d491120c3 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 14 Oct 2024 13:53:54 +0200 Subject: [PATCH 304/718] Handle tarballs where directory entries are not contiguous I.e. when not all entries underneath a directory X follow eachother, but there is some entry Y that isn't a child of X in between. Fixes #11656. --- src/libfetchers/git-utils.cc | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/libfetchers/git-utils.cc b/src/libfetchers/git-utils.cc index d13daf887..95ee33089 100644 --- a/src/libfetchers/git-utils.cc +++ b/src/libfetchers/git-utils.cc @@ -977,8 +977,24 @@ struct GitFileSystemObjectSinkImpl : GitFileSystemObjectSink void pushBuilder(std::string name) { + const git_tree_entry * entry; + Tree prevTree = nullptr; + + if (!pendingDirs.empty() && + (entry = git_treebuilder_get(pendingDirs.back().builder.get(), name.c_str()))) + { + /* Clone a tree that we've already finished. This happens + if a tarball has directory entries that are not + contiguous. */ + if (git_tree_entry_type(entry) != GIT_OBJECT_TREE) + throw Error("parent of '%s' is not a directory", name); + + if (git_tree_entry_to_object((git_object * *) (git_tree * *) Setter(prevTree), *repo, entry)) + throw Error("looking up parent of '%s': %s", name, git_error_last()->message); + } + git_treebuilder * b; - if (git_treebuilder_new(&b, *repo, nullptr)) + if (git_treebuilder_new(&b, *repo, prevTree.get())) throw Error("creating a tree builder: %s", git_error_last()->message); pendingDirs.push_back({ .name = std::move(name), .builder = TreeBuilder(b) }); }; From a7b9877da9d1bdafcc9b2f4681ecb3a1b83de7fc Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 14 Oct 2024 14:10:36 +0200 Subject: [PATCH 305/718] Add a test --- tests/functional/tarball.sh | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/functional/tarball.sh b/tests/functional/tarball.sh index 0202037aa..0682869b2 100755 --- a/tests/functional/tarball.sh +++ b/tests/functional/tarball.sh @@ -97,3 +97,17 @@ chmod +x "$TEST_ROOT/tar_root/foo" tar cvf "$TEST_ROOT/tar.tar" -C "$TEST_ROOT/tar_root" . path="$(nix flake prefetch --refresh --json "tarball+file://$TEST_ROOT/tar.tar" | jq -r .storePath)" [[ $(cat "$path/foo") = bar ]] + +# Test a tarball with non-contiguous directory entries. +rm -rf "$TEST_ROOT/tar_root" +mkdir -p "$TEST_ROOT/tar_root/a/b" +echo foo > "$TEST_ROOT/tar_root/a/b/foo" +echo bla > "$TEST_ROOT/tar_root/bla" +tar cvf "$TEST_ROOT/tar.tar" -C "$TEST_ROOT/tar_root" . +echo abc > "$TEST_ROOT/tar_root/bla" +echo xyzzy > "$TEST_ROOT/tar_root/a/b/xyzzy" +tar rvf "$TEST_ROOT/tar.tar" -C "$TEST_ROOT/tar_root" ./a/b/xyzzy ./bla +path="$(nix flake prefetch --refresh --json "tarball+file://$TEST_ROOT/tar.tar" | jq -r .storePath)" +[[ $(cat "$path/a/b/xyzzy") = xyzzy ]] +[[ $(cat "$path/a/b/foo") = foo ]] +[[ $(cat "$path/bla") = abc ]] From 5d35424445a4fbdd2f46f57614e8a6de98177653 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 14 Oct 2024 16:17:18 +0200 Subject: [PATCH 306/718] path fetcher: Allow the lastModified attribute to be overriden again Fixes #11660. --- src/libfetchers/path.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libfetchers/path.cc b/src/libfetchers/path.cc index fca0df84b..fe1534aba 100644 --- a/src/libfetchers/path.cc +++ b/src/libfetchers/path.cc @@ -157,7 +157,11 @@ struct PathInputScheme : InputScheme }); storePath = store->addToStoreFromDump(*src, "source"); } - input.attrs.insert_or_assign("lastModified", uint64_t(mtime)); + + /* Trust the lastModified value supplied by the user, if + any. It's not a "secure" attribute so we don't care. */ + if (!input.getLastModified()) + input.attrs.insert_or_assign("lastModified", uint64_t(mtime)); return {makeStorePathAccessor(store, *storePath), std::move(input)}; } From eb7d7780b18bce679639336cfd8ba6af1fe6139d Mon Sep 17 00:00:00 2001 From: John Ericson Date: Thu, 10 Oct 2024 12:04:33 -0400 Subject: [PATCH 307/718] Rename `doc/manual{src -> source}` This is needed to avoid this https://github.com/mesonbuild/meson/issues/13774 when we go back to making our subproject directory `src`. --- .../ISSUE_TEMPLATE/missing_documentation.md | 2 +- .github/labeler.yml | 2 +- .gitignore | 22 +++---- CONTRIBUTING.md | 4 +- HACKING.md | 2 +- doc/manual/book.toml | 3 +- doc/manual/generate-store-types.nix | 2 +- doc/manual/local.mk | 56 +++++++++--------- doc/manual/meson.build | 16 ++--- doc/manual/redirects.js | 2 +- doc/manual/{src => source}/SUMMARY.md.in | 0 doc/manual/{src => source}/_redirects | 0 .../advanced-topics/cores-vs-jobs.md | 0 .../advanced-topics/diff-hook.md | 0 .../advanced-topics/distributed-builds.md | 0 .../{src => source}/advanced-topics/index.md | 0 .../advanced-topics/post-build-hook.md | 0 .../architecture/architecture.md | 0 doc/manual/{src => source}/c-api.md | 0 .../command-ref/conf-file-prefix.md | 0 .../{src => source}/command-ref/env-common.md | 0 .../command-ref/experimental-commands.md | 0 .../{src => source}/command-ref/files.md | 0 .../command-ref/files/channels.md | 0 .../files/default-nix-expression.md | 0 .../command-ref/files/manifest.json.md | 0 .../command-ref/files/manifest.nix.md | 0 .../command-ref/files/profiles.md | 0 .../{src => source}/command-ref/index.md | 0 .../command-ref/main-commands.md | 0 .../{src => source}/command-ref/meson.build | 0 .../{src => source}/command-ref/nix-build.md | 0 .../command-ref/nix-channel.md | 0 .../command-ref/nix-collect-garbage.md | 0 .../command-ref/nix-copy-closure.md | 0 .../{src => source}/command-ref/nix-daemon.md | 0 .../{src => source}/command-ref/nix-env.md | 0 .../command-ref/nix-env/delete-generations.md | 0 .../command-ref/nix-env/env-common.md | 0 .../command-ref/nix-env/install.md | 0 .../command-ref/nix-env/list-generations.md | 0 .../command-ref/nix-env/opt-common.md | 0 .../command-ref/nix-env/query.md | 0 .../command-ref/nix-env/rollback.md | 0 .../command-ref/nix-env/set-flag.md | 0 .../command-ref/nix-env/set.md | 0 .../command-ref/nix-env/switch-generation.md | 0 .../command-ref/nix-env/switch-profile.md | 0 .../command-ref/nix-env/uninstall.md | 0 .../command-ref/nix-env/upgrade.md | 0 .../{src => source}/command-ref/nix-hash.md | 0 .../command-ref/nix-instantiate.md | 0 .../command-ref/nix-prefetch-url.md | 0 .../{src => source}/command-ref/nix-shell.md | 0 .../{src => source}/command-ref/nix-store.md | 0 .../command-ref/nix-store/add-fixed.md | 0 .../command-ref/nix-store/add.md | 0 .../command-ref/nix-store/delete.md | 0 .../command-ref/nix-store/dump-db.md | 0 .../command-ref/nix-store/dump.md | 0 .../command-ref/nix-store/export.md | 0 .../command-ref/nix-store/gc.md | 0 .../nix-store/generate-binary-cache-key.md | 0 .../command-ref/nix-store/import.md | 0 .../command-ref/nix-store/load-db.md | 0 .../command-ref/nix-store/opt-common.md | 0 .../command-ref/nix-store/optimise.md | 0 .../command-ref/nix-store/print-env.md | 0 .../command-ref/nix-store/query.md | 0 .../command-ref/nix-store/read-log.md | 0 .../command-ref/nix-store/realise.md | 0 .../command-ref/nix-store/repair-path.md | 0 .../command-ref/nix-store/restore.md | 0 .../command-ref/nix-store/serve.md | 0 .../command-ref/nix-store/verify-path.md | 0 .../command-ref/nix-store/verify.md | 0 .../{src => source}/command-ref/opt-common.md | 0 .../command-ref/status-build-failure.md | 0 .../{src => source}/command-ref/utilities.md | 0 .../{src => source}/development/building.md | 0 .../development/cli-guideline.md | 0 .../development/contributing.md | 0 doc/manual/{src => source}/development/cxx.md | 0 .../development/documentation.md | 4 +- .../development/experimental-features.md | 0 .../{src => source}/development/index.md | 0 .../development/json-guideline.md | 0 .../{src => source}/development/meson.build | 0 .../{src => source}/development/testing.md | 0 doc/manual/{src => source}/favicon.png | Bin doc/manual/{src => source}/favicon.svg | 0 .../figures/user-environments.png | Bin .../figures/user-environments.sxd | Bin doc/manual/{src => source}/glossary.md | 0 .../installation/building-source.md | 0 .../installation/env-variables.md | 0 .../{src => source}/installation/index.md | 0 .../installation/installing-binary.md | 0 .../installation/installing-docker.md | 0 .../installation/installing-source.md | 0 .../installation/multi-user.md | 0 .../installation/nix-security.md | 0 .../installation/obtaining-source.md | 0 .../installation/prerequisites-source.md | 0 .../installation/single-user.md | 0 .../installation/supported-platforms.md | 0 .../{src => source}/installation/uninstall.md | 0 .../{src => source}/installation/upgrading.md | 0 doc/manual/{src => source}/introduction.md | 0 .../language/advanced-attributes.md | 0 .../language/builtins-prefix.md | 0 .../language/builtins-suffix.md | 0 .../{src => source}/language/constructs.md | 0 .../language/constructs/lookup-path.md | 0 .../{src => source}/language/derivations.md | 0 .../{src => source}/language/identifiers.md | 0 .../language/import-from-derivation.md | 0 doc/manual/{src => source}/language/index.md | 0 .../{src => source}/language/meson.build | 0 .../{src => source}/language/operators.md | 0 doc/manual/{src => source}/language/scope.md | 0 .../language/string-context.md | 0 .../language/string-interpolation.md | 0 .../language/string-literals.md | 0 doc/manual/{src => source}/language/syntax.md | 0 doc/manual/{src => source}/language/types.md | 0 doc/manual/{src => source}/language/values.md | 0 .../{src => source}/language/variables.md | 0 doc/manual/{src => source}/meson.build | 0 .../binary-cache-substituter.md | 0 .../package-management/garbage-collection.md | 0 .../garbage-collector-roots.md | 0 .../package-management/index.md | 0 .../package-management/profiles.md | 0 .../package-management/sharing-packages.md | 0 .../package-management/ssh-substituter.md | 0 .../protocols/derivation-aterm.md | 0 doc/manual/{src => source}/protocols/index.md | 0 .../protocols/json/derivation.md | 0 .../{src => source}/protocols/json/index.md | 0 .../protocols/json/store-object-info.md | 0 .../{src => source}/protocols/nix-archive.md | 0 .../{src => source}/protocols/store-path.md | 0 .../protocols/tarball-fetcher.md | 0 doc/manual/{src => source}/quick-start.md | 0 .../{src => source}/release-notes/index.md | 0 .../{src => source}/release-notes/meson.build | 0 .../release-notes/rl-0.10.1.md | 0 .../{src => source}/release-notes/rl-0.10.md | 0 .../{src => source}/release-notes/rl-0.11.md | 0 .../{src => source}/release-notes/rl-0.12.md | 0 .../{src => source}/release-notes/rl-0.13.md | 0 .../{src => source}/release-notes/rl-0.14.md | 0 .../{src => source}/release-notes/rl-0.15.md | 0 .../{src => source}/release-notes/rl-0.16.md | 0 .../{src => source}/release-notes/rl-0.5.md | 0 .../{src => source}/release-notes/rl-0.6.md | 0 .../{src => source}/release-notes/rl-0.7.md | 0 .../{src => source}/release-notes/rl-0.8.1.md | 0 .../{src => source}/release-notes/rl-0.8.md | 0 .../{src => source}/release-notes/rl-0.9.1.md | 0 .../{src => source}/release-notes/rl-0.9.2.md | 0 .../{src => source}/release-notes/rl-0.9.md | 0 .../{src => source}/release-notes/rl-1.0.md | 0 .../{src => source}/release-notes/rl-1.1.md | 0 .../{src => source}/release-notes/rl-1.10.md | 0 .../release-notes/rl-1.11.10.md | 0 .../{src => source}/release-notes/rl-1.11.md | 0 .../{src => source}/release-notes/rl-1.2.md | 0 .../{src => source}/release-notes/rl-1.3.md | 0 .../{src => source}/release-notes/rl-1.4.md | 0 .../{src => source}/release-notes/rl-1.5.1.md | 0 .../{src => source}/release-notes/rl-1.5.2.md | 0 .../{src => source}/release-notes/rl-1.5.md | 0 .../{src => source}/release-notes/rl-1.6.1.md | 0 .../{src => source}/release-notes/rl-1.6.md | 0 .../{src => source}/release-notes/rl-1.7.md | 0 .../{src => source}/release-notes/rl-1.8.md | 0 .../{src => source}/release-notes/rl-1.9.md | 0 .../{src => source}/release-notes/rl-2.0.md | 0 .../{src => source}/release-notes/rl-2.1.md | 0 .../{src => source}/release-notes/rl-2.10.md | 0 .../{src => source}/release-notes/rl-2.11.md | 0 .../{src => source}/release-notes/rl-2.12.md | 0 .../{src => source}/release-notes/rl-2.13.md | 0 .../{src => source}/release-notes/rl-2.14.md | 0 .../{src => source}/release-notes/rl-2.15.md | 0 .../{src => source}/release-notes/rl-2.16.md | 0 .../{src => source}/release-notes/rl-2.17.md | 0 .../{src => source}/release-notes/rl-2.18.md | 0 .../{src => source}/release-notes/rl-2.19.md | 0 .../{src => source}/release-notes/rl-2.2.md | 0 .../{src => source}/release-notes/rl-2.20.md | 0 .../{src => source}/release-notes/rl-2.21.md | 0 .../{src => source}/release-notes/rl-2.22.md | 0 .../{src => source}/release-notes/rl-2.23.md | 0 .../{src => source}/release-notes/rl-2.24.md | 0 .../{src => source}/release-notes/rl-2.3.md | 0 .../{src => source}/release-notes/rl-2.4.md | 0 .../{src => source}/release-notes/rl-2.5.md | 0 .../{src => source}/release-notes/rl-2.6.md | 0 .../{src => source}/release-notes/rl-2.7.md | 0 .../{src => source}/release-notes/rl-2.8.md | 0 .../{src => source}/release-notes/rl-2.9.md | 0 .../store/file-system-object.md | 0 .../file-system-object/content-address.md | 0 doc/manual/{src => source}/store/index.md | 0 doc/manual/{src => source}/store/meson.build | 0 .../{src => source}/store/store-object.md | 0 .../store/store-object/content-address.md | 0 .../{src => source}/store/store-path.md | 0 .../{src => source}/store/types/index.md.in | 0 doc/manual/substitute.py | 4 +- maintainers/release-notes | 8 +-- .../unix/build/local-derivation-goal.cc | 4 +- src/nix/help-stores.md | 2 +- src/nix/package.nix | 4 +- src/nix/profiles.md | 2 +- tests/functional/check.sh | 2 +- tests/functional/common/functions.sh | 2 +- tests/functional/linux-sandbox.sh | 6 +- 221 files changed, 75 insertions(+), 74 deletions(-) rename doc/manual/{src => source}/SUMMARY.md.in (100%) rename doc/manual/{src => source}/_redirects (100%) rename doc/manual/{src => source}/advanced-topics/cores-vs-jobs.md (100%) rename doc/manual/{src => source}/advanced-topics/diff-hook.md (100%) rename doc/manual/{src => source}/advanced-topics/distributed-builds.md (100%) rename doc/manual/{src => source}/advanced-topics/index.md (100%) rename doc/manual/{src => source}/advanced-topics/post-build-hook.md (100%) rename doc/manual/{src => source}/architecture/architecture.md (100%) rename doc/manual/{src => source}/c-api.md (100%) rename doc/manual/{src => source}/command-ref/conf-file-prefix.md (100%) rename doc/manual/{src => source}/command-ref/env-common.md (100%) rename doc/manual/{src => source}/command-ref/experimental-commands.md (100%) rename doc/manual/{src => source}/command-ref/files.md (100%) rename doc/manual/{src => source}/command-ref/files/channels.md (100%) rename doc/manual/{src => source}/command-ref/files/default-nix-expression.md (100%) rename doc/manual/{src => source}/command-ref/files/manifest.json.md (100%) rename doc/manual/{src => source}/command-ref/files/manifest.nix.md (100%) rename doc/manual/{src => source}/command-ref/files/profiles.md (100%) rename doc/manual/{src => source}/command-ref/index.md (100%) rename doc/manual/{src => source}/command-ref/main-commands.md (100%) rename doc/manual/{src => source}/command-ref/meson.build (100%) rename doc/manual/{src => source}/command-ref/nix-build.md (100%) rename doc/manual/{src => source}/command-ref/nix-channel.md (100%) rename doc/manual/{src => source}/command-ref/nix-collect-garbage.md (100%) rename doc/manual/{src => source}/command-ref/nix-copy-closure.md (100%) rename doc/manual/{src => source}/command-ref/nix-daemon.md (100%) rename doc/manual/{src => source}/command-ref/nix-env.md (100%) rename doc/manual/{src => source}/command-ref/nix-env/delete-generations.md (100%) rename doc/manual/{src => source}/command-ref/nix-env/env-common.md (100%) rename doc/manual/{src => source}/command-ref/nix-env/install.md (100%) rename doc/manual/{src => source}/command-ref/nix-env/list-generations.md (100%) rename doc/manual/{src => source}/command-ref/nix-env/opt-common.md (100%) rename doc/manual/{src => source}/command-ref/nix-env/query.md (100%) rename doc/manual/{src => source}/command-ref/nix-env/rollback.md (100%) rename doc/manual/{src => source}/command-ref/nix-env/set-flag.md (100%) rename doc/manual/{src => source}/command-ref/nix-env/set.md (100%) rename doc/manual/{src => source}/command-ref/nix-env/switch-generation.md (100%) rename doc/manual/{src => source}/command-ref/nix-env/switch-profile.md (100%) rename doc/manual/{src => source}/command-ref/nix-env/uninstall.md (100%) rename doc/manual/{src => source}/command-ref/nix-env/upgrade.md (100%) rename doc/manual/{src => source}/command-ref/nix-hash.md (100%) rename doc/manual/{src => source}/command-ref/nix-instantiate.md (100%) rename doc/manual/{src => source}/command-ref/nix-prefetch-url.md (100%) rename doc/manual/{src => source}/command-ref/nix-shell.md (100%) rename doc/manual/{src => source}/command-ref/nix-store.md (100%) rename doc/manual/{src => source}/command-ref/nix-store/add-fixed.md (100%) rename doc/manual/{src => source}/command-ref/nix-store/add.md (100%) rename doc/manual/{src => source}/command-ref/nix-store/delete.md (100%) rename doc/manual/{src => source}/command-ref/nix-store/dump-db.md (100%) rename doc/manual/{src => source}/command-ref/nix-store/dump.md (100%) rename doc/manual/{src => source}/command-ref/nix-store/export.md (100%) rename doc/manual/{src => source}/command-ref/nix-store/gc.md (100%) rename doc/manual/{src => source}/command-ref/nix-store/generate-binary-cache-key.md (100%) rename doc/manual/{src => source}/command-ref/nix-store/import.md (100%) rename doc/manual/{src => source}/command-ref/nix-store/load-db.md (100%) rename doc/manual/{src => source}/command-ref/nix-store/opt-common.md (100%) rename doc/manual/{src => source}/command-ref/nix-store/optimise.md (100%) rename doc/manual/{src => source}/command-ref/nix-store/print-env.md (100%) rename doc/manual/{src => source}/command-ref/nix-store/query.md (100%) rename doc/manual/{src => source}/command-ref/nix-store/read-log.md (100%) rename doc/manual/{src => source}/command-ref/nix-store/realise.md (100%) rename doc/manual/{src => source}/command-ref/nix-store/repair-path.md (100%) rename doc/manual/{src => source}/command-ref/nix-store/restore.md (100%) rename doc/manual/{src => source}/command-ref/nix-store/serve.md (100%) rename doc/manual/{src => source}/command-ref/nix-store/verify-path.md (100%) rename doc/manual/{src => source}/command-ref/nix-store/verify.md (100%) rename doc/manual/{src => source}/command-ref/opt-common.md (100%) rename doc/manual/{src => source}/command-ref/status-build-failure.md (100%) rename doc/manual/{src => source}/command-ref/utilities.md (100%) rename doc/manual/{src => source}/development/building.md (100%) rename doc/manual/{src => source}/development/cli-guideline.md (100%) rename doc/manual/{src => source}/development/contributing.md (100%) rename doc/manual/{src => source}/development/cxx.md (100%) rename doc/manual/{src => source}/development/documentation.md (98%) rename doc/manual/{src => source}/development/experimental-features.md (100%) rename doc/manual/{src => source}/development/index.md (100%) rename doc/manual/{src => source}/development/json-guideline.md (100%) rename doc/manual/{src => source}/development/meson.build (100%) rename doc/manual/{src => source}/development/testing.md (100%) rename doc/manual/{src => source}/favicon.png (100%) rename doc/manual/{src => source}/favicon.svg (100%) rename doc/manual/{src => source}/figures/user-environments.png (100%) rename doc/manual/{src => source}/figures/user-environments.sxd (100%) rename doc/manual/{src => source}/glossary.md (100%) rename doc/manual/{src => source}/installation/building-source.md (100%) rename doc/manual/{src => source}/installation/env-variables.md (100%) rename doc/manual/{src => source}/installation/index.md (100%) rename doc/manual/{src => source}/installation/installing-binary.md (100%) rename doc/manual/{src => source}/installation/installing-docker.md (100%) rename doc/manual/{src => source}/installation/installing-source.md (100%) rename doc/manual/{src => source}/installation/multi-user.md (100%) rename doc/manual/{src => source}/installation/nix-security.md (100%) rename doc/manual/{src => source}/installation/obtaining-source.md (100%) rename doc/manual/{src => source}/installation/prerequisites-source.md (100%) rename doc/manual/{src => source}/installation/single-user.md (100%) rename doc/manual/{src => source}/installation/supported-platforms.md (100%) rename doc/manual/{src => source}/installation/uninstall.md (100%) rename doc/manual/{src => source}/installation/upgrading.md (100%) rename doc/manual/{src => source}/introduction.md (100%) rename doc/manual/{src => source}/language/advanced-attributes.md (100%) rename doc/manual/{src => source}/language/builtins-prefix.md (100%) rename doc/manual/{src => source}/language/builtins-suffix.md (100%) rename doc/manual/{src => source}/language/constructs.md (100%) rename doc/manual/{src => source}/language/constructs/lookup-path.md (100%) rename doc/manual/{src => source}/language/derivations.md (100%) rename doc/manual/{src => source}/language/identifiers.md (100%) rename doc/manual/{src => source}/language/import-from-derivation.md (100%) rename doc/manual/{src => source}/language/index.md (100%) rename doc/manual/{src => source}/language/meson.build (100%) rename doc/manual/{src => source}/language/operators.md (100%) rename doc/manual/{src => source}/language/scope.md (100%) rename doc/manual/{src => source}/language/string-context.md (100%) rename doc/manual/{src => source}/language/string-interpolation.md (100%) rename doc/manual/{src => source}/language/string-literals.md (100%) rename doc/manual/{src => source}/language/syntax.md (100%) rename doc/manual/{src => source}/language/types.md (100%) rename doc/manual/{src => source}/language/values.md (100%) rename doc/manual/{src => source}/language/variables.md (100%) rename doc/manual/{src => source}/meson.build (100%) rename doc/manual/{src => source}/package-management/binary-cache-substituter.md (100%) rename doc/manual/{src => source}/package-management/garbage-collection.md (100%) rename doc/manual/{src => source}/package-management/garbage-collector-roots.md (100%) rename doc/manual/{src => source}/package-management/index.md (100%) rename doc/manual/{src => source}/package-management/profiles.md (100%) rename doc/manual/{src => source}/package-management/sharing-packages.md (100%) rename doc/manual/{src => source}/package-management/ssh-substituter.md (100%) rename doc/manual/{src => source}/protocols/derivation-aterm.md (100%) rename doc/manual/{src => source}/protocols/index.md (100%) rename doc/manual/{src => source}/protocols/json/derivation.md (100%) rename doc/manual/{src => source}/protocols/json/index.md (100%) rename doc/manual/{src => source}/protocols/json/store-object-info.md (100%) rename doc/manual/{src => source}/protocols/nix-archive.md (100%) rename doc/manual/{src => source}/protocols/store-path.md (100%) rename doc/manual/{src => source}/protocols/tarball-fetcher.md (100%) rename doc/manual/{src => source}/quick-start.md (100%) rename doc/manual/{src => source}/release-notes/index.md (100%) rename doc/manual/{src => source}/release-notes/meson.build (100%) rename doc/manual/{src => source}/release-notes/rl-0.10.1.md (100%) rename doc/manual/{src => source}/release-notes/rl-0.10.md (100%) rename doc/manual/{src => source}/release-notes/rl-0.11.md (100%) rename doc/manual/{src => source}/release-notes/rl-0.12.md (100%) rename doc/manual/{src => source}/release-notes/rl-0.13.md (100%) rename doc/manual/{src => source}/release-notes/rl-0.14.md (100%) rename doc/manual/{src => source}/release-notes/rl-0.15.md (100%) rename doc/manual/{src => source}/release-notes/rl-0.16.md (100%) rename doc/manual/{src => source}/release-notes/rl-0.5.md (100%) rename doc/manual/{src => source}/release-notes/rl-0.6.md (100%) rename doc/manual/{src => source}/release-notes/rl-0.7.md (100%) rename doc/manual/{src => source}/release-notes/rl-0.8.1.md (100%) rename doc/manual/{src => source}/release-notes/rl-0.8.md (100%) rename doc/manual/{src => source}/release-notes/rl-0.9.1.md (100%) rename doc/manual/{src => source}/release-notes/rl-0.9.2.md (100%) rename doc/manual/{src => source}/release-notes/rl-0.9.md (100%) rename doc/manual/{src => source}/release-notes/rl-1.0.md (100%) rename doc/manual/{src => source}/release-notes/rl-1.1.md (100%) rename doc/manual/{src => source}/release-notes/rl-1.10.md (100%) rename doc/manual/{src => source}/release-notes/rl-1.11.10.md (100%) rename doc/manual/{src => source}/release-notes/rl-1.11.md (100%) rename doc/manual/{src => source}/release-notes/rl-1.2.md (100%) rename doc/manual/{src => source}/release-notes/rl-1.3.md (100%) rename doc/manual/{src => source}/release-notes/rl-1.4.md (100%) rename doc/manual/{src => source}/release-notes/rl-1.5.1.md (100%) rename doc/manual/{src => source}/release-notes/rl-1.5.2.md (100%) rename doc/manual/{src => source}/release-notes/rl-1.5.md (100%) rename doc/manual/{src => source}/release-notes/rl-1.6.1.md (100%) rename doc/manual/{src => source}/release-notes/rl-1.6.md (100%) rename doc/manual/{src => source}/release-notes/rl-1.7.md (100%) rename doc/manual/{src => source}/release-notes/rl-1.8.md (100%) rename doc/manual/{src => source}/release-notes/rl-1.9.md (100%) rename doc/manual/{src => source}/release-notes/rl-2.0.md (100%) rename doc/manual/{src => source}/release-notes/rl-2.1.md (100%) rename doc/manual/{src => source}/release-notes/rl-2.10.md (100%) rename doc/manual/{src => source}/release-notes/rl-2.11.md (100%) rename doc/manual/{src => source}/release-notes/rl-2.12.md (100%) rename doc/manual/{src => source}/release-notes/rl-2.13.md (100%) rename doc/manual/{src => source}/release-notes/rl-2.14.md (100%) rename doc/manual/{src => source}/release-notes/rl-2.15.md (100%) rename doc/manual/{src => source}/release-notes/rl-2.16.md (100%) rename doc/manual/{src => source}/release-notes/rl-2.17.md (100%) rename doc/manual/{src => source}/release-notes/rl-2.18.md (100%) rename doc/manual/{src => source}/release-notes/rl-2.19.md (100%) rename doc/manual/{src => source}/release-notes/rl-2.2.md (100%) rename doc/manual/{src => source}/release-notes/rl-2.20.md (100%) rename doc/manual/{src => source}/release-notes/rl-2.21.md (100%) rename doc/manual/{src => source}/release-notes/rl-2.22.md (100%) rename doc/manual/{src => source}/release-notes/rl-2.23.md (100%) rename doc/manual/{src => source}/release-notes/rl-2.24.md (100%) rename doc/manual/{src => source}/release-notes/rl-2.3.md (100%) rename doc/manual/{src => source}/release-notes/rl-2.4.md (100%) rename doc/manual/{src => source}/release-notes/rl-2.5.md (100%) rename doc/manual/{src => source}/release-notes/rl-2.6.md (100%) rename doc/manual/{src => source}/release-notes/rl-2.7.md (100%) rename doc/manual/{src => source}/release-notes/rl-2.8.md (100%) rename doc/manual/{src => source}/release-notes/rl-2.9.md (100%) rename doc/manual/{src => source}/store/file-system-object.md (100%) rename doc/manual/{src => source}/store/file-system-object/content-address.md (100%) rename doc/manual/{src => source}/store/index.md (100%) rename doc/manual/{src => source}/store/meson.build (100%) rename doc/manual/{src => source}/store/store-object.md (100%) rename doc/manual/{src => source}/store/store-object/content-address.md (100%) rename doc/manual/{src => source}/store/store-path.md (100%) rename doc/manual/{src => source}/store/types/index.md.in (100%) diff --git a/.github/ISSUE_TEMPLATE/missing_documentation.md b/.github/ISSUE_TEMPLATE/missing_documentation.md index be3f6af97..cf663e28d 100644 --- a/.github/ISSUE_TEMPLATE/missing_documentation.md +++ b/.github/ISSUE_TEMPLATE/missing_documentation.md @@ -23,7 +23,7 @@ assignees: '' - [ ] checked [open documentation issues and pull requests] for possible duplicates [latest Nix manual]: https://nixos.org/manual/nix/unstable/ -[source]: https://github.com/NixOS/nix/tree/master/doc/manual/src +[source]: https://github.com/NixOS/nix/tree/master/doc/manual/source [open documentation issues and pull requests]: https://github.com/NixOS/nix/labels/documentation ## Priorities diff --git a/.github/labeler.yml b/.github/labeler.yml index 0e6fd3e26..9f7cb76c5 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -9,7 +9,7 @@ - any-glob-to-any-file: "CONTRIBUTING.md" - any-glob-to-any-file: ".github/ISSUE_TEMPLATE/*" - any-glob-to-any-file: ".github/PULL_REQUEST_TEMPLATE.md" - - any-glob-to-any-file: "doc/manual/src/contributing/**" + - any-glob-to-any-file: "doc/manual/source/contributing/**" "documentation": - changed-files: diff --git a/.gitignore b/.gitignore index a17b627f4..8d6693984 100644 --- a/.gitignore +++ b/.gitignore @@ -23,17 +23,17 @@ perl/Makefile.config /doc/manual/conf-file.json /doc/manual/language.json /doc/manual/xp-features.json -/doc/manual/src/SUMMARY.md -/doc/manual/src/SUMMARY-rl-next.md -/doc/manual/src/store/types/* -!/doc/manual/src/store/types/index.md.in -/doc/manual/src/command-ref/new-cli -/doc/manual/src/command-ref/conf-file.md -/doc/manual/src/command-ref/experimental-features-shortlist.md -/doc/manual/src/contributing/experimental-feature-descriptions.md -/doc/manual/src/language/builtins.md -/doc/manual/src/language/builtin-constants.md -/doc/manual/src/release-notes/rl-next.md +/doc/manual/source/SUMMARY.md +/doc/manual/source/SUMMARY-rl-next.md +/doc/manual/source/store/types/* +!/doc/manual/source/store/types/index.md.in +/doc/manual/source/command-ref/new-cli +/doc/manual/source/command-ref/conf-file.md +/doc/manual/source/command-ref/experimental-features-shortlist.md +/doc/manual/source/contributing/experimental-feature-descriptions.md +/doc/manual/source/language/builtins.md +/doc/manual/source/language/builtin-constants.md +/doc/manual/source/release-notes/rl-next.md # /scripts/ /scripts/nix-profile.sh diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 56508df34..ad8678962 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -79,7 +79,7 @@ Check out the [security policy](https://github.com/NixOS/nix/security/policy). - Functional tests – [`tests/functional/**.sh`](./tests/functional) - Unit tests – [`src/*/tests`](./src/) - Integration tests – [`tests/nixos/*`](./tests/nixos) - - [ ] User documentation in the [manual](./doc/manual/src) + - [ ] User documentation in the [manual](./doc/manual/source) - [ ] API documentation in header files - [ ] Code and comments are self-explanatory - [ ] Commit message explains **why** the change was made @@ -90,7 +90,7 @@ Check out the [security policy](https://github.com/NixOS/nix/security/policy). ## Making changes to the Nix manual The Nix reference manual is hosted on https://nixos.org/manual/nix. -The underlying source files are located in [`doc/manual/src`](./doc/manual/src). +The underlying source files are located in [`doc/manual/source`](./doc/manual/source). For small changes you can [use GitHub to edit these files](https://docs.github.com/en/repositories/working-with-files/managing-files/editing-files) For larger changes see the [Nix reference manual](https://nix.dev/manual/nix/development/development/contributing.html). diff --git a/HACKING.md b/HACKING.md index d3576d60d..02971da3e 120000 --- a/HACKING.md +++ b/HACKING.md @@ -1 +1 @@ -doc/manual/src/development/building.md \ No newline at end of file +doc/manual/source/development/building.md \ No newline at end of file diff --git a/doc/manual/book.toml b/doc/manual/book.toml index acae7aec7..213739174 100644 --- a/doc/manual/book.toml +++ b/doc/manual/book.toml @@ -1,5 +1,6 @@ [book] title = "Nix Reference Manual" +src = "source" [output.html] additional-css = ["custom.css"] @@ -7,7 +8,7 @@ additional-js = ["redirects.js"] edit-url-template = "https://github.com/NixOS/nix/tree/master/doc/manual/{path}" git-repository-url = "https://github.com/NixOS/nix" -# Handles replacing @docroot@ with a path to ./src relative to that markdown file, +# Handles replacing @docroot@ with a path to ./source relative to that markdown file, # {{#include handlebars}}, and the @generated@ syntax used within these. it mostly # but not entirely replaces the links preprocessor (which we cannot simply use due # to @generated@ files living in a different directory to make meson happy). we do diff --git a/doc/manual/generate-store-types.nix b/doc/manual/generate-store-types.nix index 3b78a0e1b..46179abc5 100644 --- a/doc/manual/generate-store-types.nix +++ b/doc/manual/generate-store-types.nix @@ -21,7 +21,7 @@ let "index.md" = replaceStrings [ "@store-types@" ] [ index ] - (readFile ./src/store/types/index.md.in); + (readFile ./source/store/types/index.md.in); tableOfContents = let diff --git a/doc/manual/local.mk b/doc/manual/local.mk index 3c777efc3..36cccc506 100644 --- a/doc/manual/local.mk +++ b/doc/manual/local.mk @@ -4,8 +4,8 @@ doc_nix = $(nix_PATH) MANUAL_SRCS := \ - $(call rwildcard, $(d)/src, *.md) \ - $(call rwildcard, $(d)/src, */*.md) + $(call rwildcard, $(d)/source, *.md) \ + $(call rwildcard, $(d)/source, */*.md) man-pages := $(foreach n, \ nix-env.1 nix-store.1 \ @@ -18,11 +18,11 @@ man-pages := $(foreach n, \ , $(d)/$(n)) # man pages for subcommands -# convert from `$(d)/src/command-ref/nix-{1}/{2}.md` to `$(d)/nix-{1}-{2}.1` +# convert from `$(d)/source/command-ref/nix-{1}/{2}.md` to `$(d)/nix-{1}-{2}.1` # FIXME: unify with how nix3-cli man pages are generated man-pages += $(foreach subcommand, \ - $(filter-out %opt-common.md %env-common.md, $(wildcard $(d)/src/command-ref/nix-*/*.md)), \ - $(d)/$(subst /,-,$(subst $(d)/src/command-ref/,,$(subst .md,.1,$(subcommand))))) + $(filter-out %opt-common.md %env-common.md, $(wildcard $(d)/source/command-ref/nix-*/*.md)), \ + $(d)/$(subst /,-,$(subst $(d)/source/command-ref/,,$(subst .md,.1,$(subcommand))))) clean-files += $(d)/*.1 $(d)/*.5 $(d)/*.8 @@ -49,11 +49,11 @@ define process-includes done < <(grep '{{#include' $(1)) endef -$(d)/nix-env-%.1: $(d)/src/command-ref/nix-env/%.md +$(d)/nix-env-%.1: $(d)/source/command-ref/nix-env/%.md @printf "Title: %s\n\n" "$(subst nix-env-,nix-env --,$$(basename "$@" .1))" > $^.tmp $(render-subcommand) -$(d)/nix-store-%.1: $(d)/src/command-ref/nix-store/%.md +$(d)/nix-store-%.1: $(d)/source/command-ref/nix-store/%.md @printf -- 'Title: %s\n\n' "$(subst nix-store-,nix-store --,$$(basename "$@" .1))" > $^.tmp $(render-subcommand) @@ -69,50 +69,50 @@ define render-subcommand endef -$(d)/%.1: $(d)/src/command-ref/%.md +$(d)/%.1: $(d)/source/command-ref/%.md @printf "Title: %s\n\n" "$$(basename $@ .1)" > $^.tmp @cat $^ >> $^.tmp @$(call process-includes,$^,$^.tmp) $(trace-gen) lowdown -sT man --nroff-nolinks -M section=1 $^.tmp -o $@ @rm $^.tmp -$(d)/%.8: $(d)/src/command-ref/%.md +$(d)/%.8: $(d)/source/command-ref/%.md @printf "Title: %s\n\n" "$$(basename $@ .8)" > $^.tmp @cat $^ >> $^.tmp $(trace-gen) lowdown -sT man --nroff-nolinks -M section=8 $^.tmp -o $@ @rm $^.tmp -$(d)/nix.conf.5: $(d)/src/command-ref/conf-file.md +$(d)/nix.conf.5: $(d)/source/command-ref/conf-file.md @printf "Title: %s\n\n" "$$(basename $@ .5)" > $^.tmp @cat $^ >> $^.tmp @$(call process-includes,$^,$^.tmp) $(trace-gen) lowdown -sT man --nroff-nolinks -M section=5 $^.tmp -o $@ @rm $^.tmp -$(d)/nix-profiles.5: $(d)/src/command-ref/files/profiles.md +$(d)/nix-profiles.5: $(d)/source/command-ref/files/profiles.md @printf "Title: %s\n\n" "$$(basename $@ .5)" > $^.tmp @cat $^ >> $^.tmp $(trace-gen) lowdown -sT man --nroff-nolinks -M section=5 $^.tmp -o $@ @rm $^.tmp -$(d)/src/SUMMARY.md: $(d)/src/SUMMARY.md.in $(d)/src/SUMMARY-rl-next.md $(d)/src/store/types $(d)/src/command-ref/new-cli $(d)/src/development/experimental-feature-descriptions.md +$(d)/source/SUMMARY.md: $(d)/source/SUMMARY.md.in $(d)/source/SUMMARY-rl-next.md $(d)/source/store/types $(d)/source/command-ref/new-cli $(d)/source/development/experimental-feature-descriptions.md @cp $< $@ @$(call process-includes,$@,$@) -$(d)/src/store/types: $(d)/nix.json $(d)/utils.nix $(d)/generate-store-info.nix $(d)/generate-store-types.nix $(d)/src/store/types/index.md.in $(doc_nix) +$(d)/source/store/types: $(d)/nix.json $(d)/utils.nix $(d)/generate-store-info.nix $(d)/generate-store-types.nix $(d)/source/store/types/index.md.in $(doc_nix) @# FIXME: build out of tree! @rm -rf $@.tmp $(trace-gen) $(nix-eval) --write-to $@.tmp --expr 'import doc/manual/generate-store-types.nix (builtins.fromJSON (builtins.readFile $<)).stores' @# do not destroy existing contents @mv $@.tmp/* $@/ -$(d)/src/command-ref/new-cli: $(d)/nix.json $(d)/utils.nix $(d)/generate-manpage.nix $(d)/generate-settings.nix $(d)/generate-store-info.nix $(doc_nix) +$(d)/source/command-ref/new-cli: $(d)/nix.json $(d)/utils.nix $(d)/generate-manpage.nix $(d)/generate-settings.nix $(d)/generate-store-info.nix $(doc_nix) @rm -rf $@ $@.tmp $(trace-gen) $(nix-eval) --write-to $@.tmp --expr 'import doc/manual/generate-manpage.nix true (builtins.readFile $<)' @mv $@.tmp $@ -$(d)/src/command-ref/conf-file.md: $(d)/conf-file.json $(d)/utils.nix $(d)/generate-settings.nix $(d)/src/command-ref/conf-file-prefix.md $(d)/src/command-ref/experimental-features-shortlist.md $(doc_nix) - @cat doc/manual/src/command-ref/conf-file-prefix.md > $@.tmp +$(d)/source/command-ref/conf-file.md: $(d)/conf-file.json $(d)/utils.nix $(d)/generate-settings.nix $(d)/source/command-ref/conf-file-prefix.md $(d)/source/command-ref/experimental-features-shortlist.md $(doc_nix) + @cat doc/manual/source/command-ref/conf-file-prefix.md > $@.tmp $(trace-gen) $(nix-eval) --expr 'import doc/manual/generate-settings.nix { prefix = "conf"; } (builtins.fromJSON (builtins.readFile $<))' >> $@.tmp; @mv $@.tmp $@ @@ -124,12 +124,12 @@ $(d)/conf-file.json: $(doc_nix) $(trace-gen) $(dummy-env) $(doc_nix) config show --json --experimental-features nix-command > $@.tmp @mv $@.tmp $@ -$(d)/src/development/experimental-feature-descriptions.md: $(d)/xp-features.json $(d)/utils.nix $(d)/generate-xp-features.nix $(doc_nix) +$(d)/source/development/experimental-feature-descriptions.md: $(d)/xp-features.json $(d)/utils.nix $(d)/generate-xp-features.nix $(doc_nix) @rm -rf $@ $@.tmp $(trace-gen) $(nix-eval) --write-to $@.tmp --expr 'import doc/manual/generate-xp-features.nix (builtins.fromJSON (builtins.readFile $<))' @mv $@.tmp $@ -$(d)/src/command-ref/experimental-features-shortlist.md: $(d)/xp-features.json $(d)/utils.nix $(d)/generate-xp-features-shortlist.nix $(doc_nix) +$(d)/source/command-ref/experimental-features-shortlist.md: $(d)/xp-features.json $(d)/utils.nix $(d)/generate-xp-features-shortlist.nix $(doc_nix) @rm -rf $@ $@.tmp $(trace-gen) $(nix-eval) --write-to $@.tmp --expr 'import doc/manual/generate-xp-features-shortlist.nix (builtins.fromJSON (builtins.readFile $<))' @mv $@.tmp $@ @@ -138,10 +138,10 @@ $(d)/xp-features.json: $(doc_nix) $(trace-gen) $(dummy-env) $(doc_nix) __dump-xp-features > $@.tmp @mv $@.tmp $@ -$(d)/src/language/builtins.md: $(d)/language.json $(d)/generate-builtins.nix $(d)/src/language/builtins-prefix.md $(doc_nix) - @cat doc/manual/src/language/builtins-prefix.md > $@.tmp +$(d)/source/language/builtins.md: $(d)/language.json $(d)/generate-builtins.nix $(d)/source/language/builtins-prefix.md $(doc_nix) + @cat doc/manual/source/language/builtins-prefix.md > $@.tmp $(trace-gen) $(nix-eval) --expr 'import doc/manual/generate-builtins.nix (builtins.fromJSON (builtins.readFile $<))' >> $@.tmp; - @cat doc/manual/src/language/builtins-suffix.md >> $@.tmp + @cat doc/manual/source/language/builtins-suffix.md >> $@.tmp @mv $@.tmp $@ $(d)/language.json: $(doc_nix) @@ -149,7 +149,7 @@ $(d)/language.json: $(doc_nix) @mv $@.tmp $@ # Generate "Upcoming release" notes (or clear it and remove from menu) -$(d)/src/release-notes/rl-next.md: $(d)/rl-next $(d)/rl-next/* +$(d)/source/release-notes/rl-next.md: $(d)/rl-next $(d)/rl-next/* @if type -p changelog-d > /dev/null; then \ echo " GEN " $@; \ changelog-d doc/manual/rl-next > $@; \ @@ -158,7 +158,7 @@ $(d)/src/release-notes/rl-next.md: $(d)/rl-next $(d)/rl-next/* true > $@; \ fi -$(d)/src/SUMMARY-rl-next.md: $(d)/src/release-notes/rl-next.md +$(d)/source/SUMMARY-rl-next.md: $(d)/source/release-notes/rl-next.md $(trace-gen) true @if [ -s $< ]; then \ echo ' - [Upcoming release](release-notes/rl-next.md)' > $@; \ @@ -194,9 +194,9 @@ $(mandir)/man1/nix3-manpages: doc/manual/generated/man1/nix3-manpages @mkdir -p $(DESTDIR)$$(dirname $@) $(trace-install) install -m 0644 $$(dirname $<)/* $(DESTDIR)$$(dirname $@) -doc/manual/generated/man1/nix3-manpages: $(d)/src/command-ref/new-cli +doc/manual/generated/man1/nix3-manpages: $(d)/source/command-ref/new-cli @mkdir -p $(DESTDIR)$$(dirname $@) - $(trace-gen) for i in doc/manual/src/command-ref/new-cli/*.md; do \ + $(trace-gen) for i in doc/manual/source/command-ref/new-cli/*.md; do \ name=$$(basename $$i .md); \ tmpFile=$$(mktemp); \ if [[ $$name = SUMMARY ]]; then continue; fi; \ @@ -211,7 +211,7 @@ doc/manual/generated/man1/nix3-manpages: $(d)/src/command-ref/new-cli # `@docroot@` is to be preserved for documenting the mechanism # FIXME: maybe contributing guides should live right next to the code # instead of in the manual -$(docdir)/manual/index.html: $(MANUAL_SRCS) $(d)/book.toml $(d)/anchors.jq $(d)/custom.css $(d)/src/SUMMARY.md $(d)/src/store/types $(d)/src/command-ref/new-cli $(d)/src/development/experimental-feature-descriptions.md $(d)/src/command-ref/conf-file.md $(d)/src/language/builtins.md $(d)/src/release-notes/rl-next.md $(d)/src/figures $(d)/src/favicon.png $(d)/src/favicon.svg +$(docdir)/manual/index.html: $(MANUAL_SRCS) $(d)/book.toml $(d)/anchors.jq $(d)/custom.css $(d)/source/SUMMARY.md $(d)/source/store/types $(d)/source/command-ref/new-cli $(d)/source/development/experimental-feature-descriptions.md $(d)/source/command-ref/conf-file.md $(d)/source/language/builtins.md $(d)/source/release-notes/rl-next.md $(d)/source/figures $(d)/source/favicon.png $(d)/source/favicon.svg $(trace-gen) \ tmp="$$(mktemp -d)"; \ cp -r doc/manual "$$tmp"; \ @@ -219,14 +219,14 @@ $(docdir)/manual/index.html: $(MANUAL_SRCS) $(d)/book.toml $(d)/anchors.jq $(d)/ $(call process-includes,$$file,$$file); \ done; \ find "$$tmp" -name '*.md' ! -name 'documentation.md' | while read -r file; do \ - docroot="$$(realpath --relative-to="$$(dirname "$$file")" $$tmp/manual/src)"; \ + docroot="$$(realpath --relative-to="$$(dirname "$$file")" $$tmp/manual/source)"; \ sed -i "s,@docroot@,$$docroot,g" "$$file"; \ done; \ set -euo pipefail; \ ( \ cd "$$tmp/manual"; \ RUST_LOG=warn \ - MDBOOK_SUBSTITUTE_SEARCH=$(d)/src \ + MDBOOK_SUBSTITUTE_SEARCH=$(d)/source \ mdbook build -d $(DESTDIR)$(docdir)/manual.tmp 2>&1 \ | { grep -Fv "because fragment resolution isn't implemented" || :; } \ ); \ diff --git a/doc/manual/meson.build b/doc/manual/meson.build index 31d1814d7..3630e2dc8 100644 --- a/doc/manual/meson.build +++ b/doc/manual/meson.build @@ -55,16 +55,16 @@ generate_manual_deps = files( ) # Generates types -subdir('src/store') +subdir('source/store') # Generates builtins.md and builtin-constants.md. -subdir('src/language') +subdir('source/language') # Generates new-cli pages, experimental-features-shortlist.md, and conf-file.md. -subdir('src/command-ref') +subdir('source/command-ref') # Generates experimental-feature-descriptions.md. -subdir('src/development') +subdir('source/development') # Generates rl-next-generated.md. -subdir('src/release-notes') -subdir('src') +subdir('source/release-notes') +subdir('source') # Hacky way to figure out if `nix` is an `ExternalProgram` or # `Exectuable`. Only the latter can occur in custom target input lists. @@ -82,7 +82,7 @@ manual = custom_target( '-c', ''' @0@ @INPUT0@ @CURRENT_SOURCE_DIR@ > @DEPFILE@ - @0@ @INPUT1@ summary @2@ < @CURRENT_SOURCE_DIR@/src/SUMMARY.md.in > @2@/src/SUMMARY.md + @0@ @INPUT1@ summary @2@ < @CURRENT_SOURCE_DIR@/source/SUMMARY.md.in > @2@/source/SUMMARY.md rsync -r --include='*.md' @CURRENT_SOURCE_DIR@/ @2@/ (cd @2@; RUST_LOG=warn @1@ build -d @2@ 3>&2 2>&1 1>&3) | { grep -Fv "because fragment resolution isn't implemented" || :; } 3>&2 2>&1 1>&3 rm -rf @2@/manual @@ -117,7 +117,7 @@ manual = custom_target( depfile : 'manual.d', env : { 'RUST_LOG': 'info', - 'MDBOOK_SUBSTITUTE_SEARCH': meson.current_build_dir() / 'src', + 'MDBOOK_SUBSTITUTE_SEARCH': meson.current_build_dir() / 'source', }, ) manual_html = manual[0] diff --git a/doc/manual/redirects.js b/doc/manual/redirects.js index cb8cd18fa..dea141391 100644 --- a/doc/manual/redirects.js +++ b/doc/manual/redirects.js @@ -1,7 +1,7 @@ // redirect rules for URL fragments (client-side) to prevent link rot. // this must be done on the client side, as web servers do not see the fragment part of the URL. // it will only work with JavaScript enabled in the browser, but this is the best we can do here. -// see src/_redirects for path redirects (server-side) +// see source/_redirects for path redirects (server-side) // redirects are declared as follows: // each entry has as its key a path matching the requested URL path, relative to the mdBook document root. diff --git a/doc/manual/src/SUMMARY.md.in b/doc/manual/source/SUMMARY.md.in similarity index 100% rename from doc/manual/src/SUMMARY.md.in rename to doc/manual/source/SUMMARY.md.in diff --git a/doc/manual/src/_redirects b/doc/manual/source/_redirects similarity index 100% rename from doc/manual/src/_redirects rename to doc/manual/source/_redirects diff --git a/doc/manual/src/advanced-topics/cores-vs-jobs.md b/doc/manual/source/advanced-topics/cores-vs-jobs.md similarity index 100% rename from doc/manual/src/advanced-topics/cores-vs-jobs.md rename to doc/manual/source/advanced-topics/cores-vs-jobs.md diff --git a/doc/manual/src/advanced-topics/diff-hook.md b/doc/manual/source/advanced-topics/diff-hook.md similarity index 100% rename from doc/manual/src/advanced-topics/diff-hook.md rename to doc/manual/source/advanced-topics/diff-hook.md diff --git a/doc/manual/src/advanced-topics/distributed-builds.md b/doc/manual/source/advanced-topics/distributed-builds.md similarity index 100% rename from doc/manual/src/advanced-topics/distributed-builds.md rename to doc/manual/source/advanced-topics/distributed-builds.md diff --git a/doc/manual/src/advanced-topics/index.md b/doc/manual/source/advanced-topics/index.md similarity index 100% rename from doc/manual/src/advanced-topics/index.md rename to doc/manual/source/advanced-topics/index.md diff --git a/doc/manual/src/advanced-topics/post-build-hook.md b/doc/manual/source/advanced-topics/post-build-hook.md similarity index 100% rename from doc/manual/src/advanced-topics/post-build-hook.md rename to doc/manual/source/advanced-topics/post-build-hook.md diff --git a/doc/manual/src/architecture/architecture.md b/doc/manual/source/architecture/architecture.md similarity index 100% rename from doc/manual/src/architecture/architecture.md rename to doc/manual/source/architecture/architecture.md diff --git a/doc/manual/src/c-api.md b/doc/manual/source/c-api.md similarity index 100% rename from doc/manual/src/c-api.md rename to doc/manual/source/c-api.md diff --git a/doc/manual/src/command-ref/conf-file-prefix.md b/doc/manual/source/command-ref/conf-file-prefix.md similarity index 100% rename from doc/manual/src/command-ref/conf-file-prefix.md rename to doc/manual/source/command-ref/conf-file-prefix.md diff --git a/doc/manual/src/command-ref/env-common.md b/doc/manual/source/command-ref/env-common.md similarity index 100% rename from doc/manual/src/command-ref/env-common.md rename to doc/manual/source/command-ref/env-common.md diff --git a/doc/manual/src/command-ref/experimental-commands.md b/doc/manual/source/command-ref/experimental-commands.md similarity index 100% rename from doc/manual/src/command-ref/experimental-commands.md rename to doc/manual/source/command-ref/experimental-commands.md diff --git a/doc/manual/src/command-ref/files.md b/doc/manual/source/command-ref/files.md similarity index 100% rename from doc/manual/src/command-ref/files.md rename to doc/manual/source/command-ref/files.md diff --git a/doc/manual/src/command-ref/files/channels.md b/doc/manual/source/command-ref/files/channels.md similarity index 100% rename from doc/manual/src/command-ref/files/channels.md rename to doc/manual/source/command-ref/files/channels.md diff --git a/doc/manual/src/command-ref/files/default-nix-expression.md b/doc/manual/source/command-ref/files/default-nix-expression.md similarity index 100% rename from doc/manual/src/command-ref/files/default-nix-expression.md rename to doc/manual/source/command-ref/files/default-nix-expression.md diff --git a/doc/manual/src/command-ref/files/manifest.json.md b/doc/manual/source/command-ref/files/manifest.json.md similarity index 100% rename from doc/manual/src/command-ref/files/manifest.json.md rename to doc/manual/source/command-ref/files/manifest.json.md diff --git a/doc/manual/src/command-ref/files/manifest.nix.md b/doc/manual/source/command-ref/files/manifest.nix.md similarity index 100% rename from doc/manual/src/command-ref/files/manifest.nix.md rename to doc/manual/source/command-ref/files/manifest.nix.md diff --git a/doc/manual/src/command-ref/files/profiles.md b/doc/manual/source/command-ref/files/profiles.md similarity index 100% rename from doc/manual/src/command-ref/files/profiles.md rename to doc/manual/source/command-ref/files/profiles.md diff --git a/doc/manual/src/command-ref/index.md b/doc/manual/source/command-ref/index.md similarity index 100% rename from doc/manual/src/command-ref/index.md rename to doc/manual/source/command-ref/index.md diff --git a/doc/manual/src/command-ref/main-commands.md b/doc/manual/source/command-ref/main-commands.md similarity index 100% rename from doc/manual/src/command-ref/main-commands.md rename to doc/manual/source/command-ref/main-commands.md diff --git a/doc/manual/src/command-ref/meson.build b/doc/manual/source/command-ref/meson.build similarity index 100% rename from doc/manual/src/command-ref/meson.build rename to doc/manual/source/command-ref/meson.build diff --git a/doc/manual/src/command-ref/nix-build.md b/doc/manual/source/command-ref/nix-build.md similarity index 100% rename from doc/manual/src/command-ref/nix-build.md rename to doc/manual/source/command-ref/nix-build.md diff --git a/doc/manual/src/command-ref/nix-channel.md b/doc/manual/source/command-ref/nix-channel.md similarity index 100% rename from doc/manual/src/command-ref/nix-channel.md rename to doc/manual/source/command-ref/nix-channel.md diff --git a/doc/manual/src/command-ref/nix-collect-garbage.md b/doc/manual/source/command-ref/nix-collect-garbage.md similarity index 100% rename from doc/manual/src/command-ref/nix-collect-garbage.md rename to doc/manual/source/command-ref/nix-collect-garbage.md diff --git a/doc/manual/src/command-ref/nix-copy-closure.md b/doc/manual/source/command-ref/nix-copy-closure.md similarity index 100% rename from doc/manual/src/command-ref/nix-copy-closure.md rename to doc/manual/source/command-ref/nix-copy-closure.md diff --git a/doc/manual/src/command-ref/nix-daemon.md b/doc/manual/source/command-ref/nix-daemon.md similarity index 100% rename from doc/manual/src/command-ref/nix-daemon.md rename to doc/manual/source/command-ref/nix-daemon.md diff --git a/doc/manual/src/command-ref/nix-env.md b/doc/manual/source/command-ref/nix-env.md similarity index 100% rename from doc/manual/src/command-ref/nix-env.md rename to doc/manual/source/command-ref/nix-env.md diff --git a/doc/manual/src/command-ref/nix-env/delete-generations.md b/doc/manual/source/command-ref/nix-env/delete-generations.md similarity index 100% rename from doc/manual/src/command-ref/nix-env/delete-generations.md rename to doc/manual/source/command-ref/nix-env/delete-generations.md diff --git a/doc/manual/src/command-ref/nix-env/env-common.md b/doc/manual/source/command-ref/nix-env/env-common.md similarity index 100% rename from doc/manual/src/command-ref/nix-env/env-common.md rename to doc/manual/source/command-ref/nix-env/env-common.md diff --git a/doc/manual/src/command-ref/nix-env/install.md b/doc/manual/source/command-ref/nix-env/install.md similarity index 100% rename from doc/manual/src/command-ref/nix-env/install.md rename to doc/manual/source/command-ref/nix-env/install.md diff --git a/doc/manual/src/command-ref/nix-env/list-generations.md b/doc/manual/source/command-ref/nix-env/list-generations.md similarity index 100% rename from doc/manual/src/command-ref/nix-env/list-generations.md rename to doc/manual/source/command-ref/nix-env/list-generations.md diff --git a/doc/manual/src/command-ref/nix-env/opt-common.md b/doc/manual/source/command-ref/nix-env/opt-common.md similarity index 100% rename from doc/manual/src/command-ref/nix-env/opt-common.md rename to doc/manual/source/command-ref/nix-env/opt-common.md diff --git a/doc/manual/src/command-ref/nix-env/query.md b/doc/manual/source/command-ref/nix-env/query.md similarity index 100% rename from doc/manual/src/command-ref/nix-env/query.md rename to doc/manual/source/command-ref/nix-env/query.md diff --git a/doc/manual/src/command-ref/nix-env/rollback.md b/doc/manual/source/command-ref/nix-env/rollback.md similarity index 100% rename from doc/manual/src/command-ref/nix-env/rollback.md rename to doc/manual/source/command-ref/nix-env/rollback.md diff --git a/doc/manual/src/command-ref/nix-env/set-flag.md b/doc/manual/source/command-ref/nix-env/set-flag.md similarity index 100% rename from doc/manual/src/command-ref/nix-env/set-flag.md rename to doc/manual/source/command-ref/nix-env/set-flag.md diff --git a/doc/manual/src/command-ref/nix-env/set.md b/doc/manual/source/command-ref/nix-env/set.md similarity index 100% rename from doc/manual/src/command-ref/nix-env/set.md rename to doc/manual/source/command-ref/nix-env/set.md diff --git a/doc/manual/src/command-ref/nix-env/switch-generation.md b/doc/manual/source/command-ref/nix-env/switch-generation.md similarity index 100% rename from doc/manual/src/command-ref/nix-env/switch-generation.md rename to doc/manual/source/command-ref/nix-env/switch-generation.md diff --git a/doc/manual/src/command-ref/nix-env/switch-profile.md b/doc/manual/source/command-ref/nix-env/switch-profile.md similarity index 100% rename from doc/manual/src/command-ref/nix-env/switch-profile.md rename to doc/manual/source/command-ref/nix-env/switch-profile.md diff --git a/doc/manual/src/command-ref/nix-env/uninstall.md b/doc/manual/source/command-ref/nix-env/uninstall.md similarity index 100% rename from doc/manual/src/command-ref/nix-env/uninstall.md rename to doc/manual/source/command-ref/nix-env/uninstall.md diff --git a/doc/manual/src/command-ref/nix-env/upgrade.md b/doc/manual/source/command-ref/nix-env/upgrade.md similarity index 100% rename from doc/manual/src/command-ref/nix-env/upgrade.md rename to doc/manual/source/command-ref/nix-env/upgrade.md diff --git a/doc/manual/src/command-ref/nix-hash.md b/doc/manual/source/command-ref/nix-hash.md similarity index 100% rename from doc/manual/src/command-ref/nix-hash.md rename to doc/manual/source/command-ref/nix-hash.md diff --git a/doc/manual/src/command-ref/nix-instantiate.md b/doc/manual/source/command-ref/nix-instantiate.md similarity index 100% rename from doc/manual/src/command-ref/nix-instantiate.md rename to doc/manual/source/command-ref/nix-instantiate.md diff --git a/doc/manual/src/command-ref/nix-prefetch-url.md b/doc/manual/source/command-ref/nix-prefetch-url.md similarity index 100% rename from doc/manual/src/command-ref/nix-prefetch-url.md rename to doc/manual/source/command-ref/nix-prefetch-url.md diff --git a/doc/manual/src/command-ref/nix-shell.md b/doc/manual/source/command-ref/nix-shell.md similarity index 100% rename from doc/manual/src/command-ref/nix-shell.md rename to doc/manual/source/command-ref/nix-shell.md diff --git a/doc/manual/src/command-ref/nix-store.md b/doc/manual/source/command-ref/nix-store.md similarity index 100% rename from doc/manual/src/command-ref/nix-store.md rename to doc/manual/source/command-ref/nix-store.md diff --git a/doc/manual/src/command-ref/nix-store/add-fixed.md b/doc/manual/source/command-ref/nix-store/add-fixed.md similarity index 100% rename from doc/manual/src/command-ref/nix-store/add-fixed.md rename to doc/manual/source/command-ref/nix-store/add-fixed.md diff --git a/doc/manual/src/command-ref/nix-store/add.md b/doc/manual/source/command-ref/nix-store/add.md similarity index 100% rename from doc/manual/src/command-ref/nix-store/add.md rename to doc/manual/source/command-ref/nix-store/add.md diff --git a/doc/manual/src/command-ref/nix-store/delete.md b/doc/manual/source/command-ref/nix-store/delete.md similarity index 100% rename from doc/manual/src/command-ref/nix-store/delete.md rename to doc/manual/source/command-ref/nix-store/delete.md diff --git a/doc/manual/src/command-ref/nix-store/dump-db.md b/doc/manual/source/command-ref/nix-store/dump-db.md similarity index 100% rename from doc/manual/src/command-ref/nix-store/dump-db.md rename to doc/manual/source/command-ref/nix-store/dump-db.md diff --git a/doc/manual/src/command-ref/nix-store/dump.md b/doc/manual/source/command-ref/nix-store/dump.md similarity index 100% rename from doc/manual/src/command-ref/nix-store/dump.md rename to doc/manual/source/command-ref/nix-store/dump.md diff --git a/doc/manual/src/command-ref/nix-store/export.md b/doc/manual/source/command-ref/nix-store/export.md similarity index 100% rename from doc/manual/src/command-ref/nix-store/export.md rename to doc/manual/source/command-ref/nix-store/export.md diff --git a/doc/manual/src/command-ref/nix-store/gc.md b/doc/manual/source/command-ref/nix-store/gc.md similarity index 100% rename from doc/manual/src/command-ref/nix-store/gc.md rename to doc/manual/source/command-ref/nix-store/gc.md diff --git a/doc/manual/src/command-ref/nix-store/generate-binary-cache-key.md b/doc/manual/source/command-ref/nix-store/generate-binary-cache-key.md similarity index 100% rename from doc/manual/src/command-ref/nix-store/generate-binary-cache-key.md rename to doc/manual/source/command-ref/nix-store/generate-binary-cache-key.md diff --git a/doc/manual/src/command-ref/nix-store/import.md b/doc/manual/source/command-ref/nix-store/import.md similarity index 100% rename from doc/manual/src/command-ref/nix-store/import.md rename to doc/manual/source/command-ref/nix-store/import.md diff --git a/doc/manual/src/command-ref/nix-store/load-db.md b/doc/manual/source/command-ref/nix-store/load-db.md similarity index 100% rename from doc/manual/src/command-ref/nix-store/load-db.md rename to doc/manual/source/command-ref/nix-store/load-db.md diff --git a/doc/manual/src/command-ref/nix-store/opt-common.md b/doc/manual/source/command-ref/nix-store/opt-common.md similarity index 100% rename from doc/manual/src/command-ref/nix-store/opt-common.md rename to doc/manual/source/command-ref/nix-store/opt-common.md diff --git a/doc/manual/src/command-ref/nix-store/optimise.md b/doc/manual/source/command-ref/nix-store/optimise.md similarity index 100% rename from doc/manual/src/command-ref/nix-store/optimise.md rename to doc/manual/source/command-ref/nix-store/optimise.md diff --git a/doc/manual/src/command-ref/nix-store/print-env.md b/doc/manual/source/command-ref/nix-store/print-env.md similarity index 100% rename from doc/manual/src/command-ref/nix-store/print-env.md rename to doc/manual/source/command-ref/nix-store/print-env.md diff --git a/doc/manual/src/command-ref/nix-store/query.md b/doc/manual/source/command-ref/nix-store/query.md similarity index 100% rename from doc/manual/src/command-ref/nix-store/query.md rename to doc/manual/source/command-ref/nix-store/query.md diff --git a/doc/manual/src/command-ref/nix-store/read-log.md b/doc/manual/source/command-ref/nix-store/read-log.md similarity index 100% rename from doc/manual/src/command-ref/nix-store/read-log.md rename to doc/manual/source/command-ref/nix-store/read-log.md diff --git a/doc/manual/src/command-ref/nix-store/realise.md b/doc/manual/source/command-ref/nix-store/realise.md similarity index 100% rename from doc/manual/src/command-ref/nix-store/realise.md rename to doc/manual/source/command-ref/nix-store/realise.md diff --git a/doc/manual/src/command-ref/nix-store/repair-path.md b/doc/manual/source/command-ref/nix-store/repair-path.md similarity index 100% rename from doc/manual/src/command-ref/nix-store/repair-path.md rename to doc/manual/source/command-ref/nix-store/repair-path.md diff --git a/doc/manual/src/command-ref/nix-store/restore.md b/doc/manual/source/command-ref/nix-store/restore.md similarity index 100% rename from doc/manual/src/command-ref/nix-store/restore.md rename to doc/manual/source/command-ref/nix-store/restore.md diff --git a/doc/manual/src/command-ref/nix-store/serve.md b/doc/manual/source/command-ref/nix-store/serve.md similarity index 100% rename from doc/manual/src/command-ref/nix-store/serve.md rename to doc/manual/source/command-ref/nix-store/serve.md diff --git a/doc/manual/src/command-ref/nix-store/verify-path.md b/doc/manual/source/command-ref/nix-store/verify-path.md similarity index 100% rename from doc/manual/src/command-ref/nix-store/verify-path.md rename to doc/manual/source/command-ref/nix-store/verify-path.md diff --git a/doc/manual/src/command-ref/nix-store/verify.md b/doc/manual/source/command-ref/nix-store/verify.md similarity index 100% rename from doc/manual/src/command-ref/nix-store/verify.md rename to doc/manual/source/command-ref/nix-store/verify.md diff --git a/doc/manual/src/command-ref/opt-common.md b/doc/manual/source/command-ref/opt-common.md similarity index 100% rename from doc/manual/src/command-ref/opt-common.md rename to doc/manual/source/command-ref/opt-common.md diff --git a/doc/manual/src/command-ref/status-build-failure.md b/doc/manual/source/command-ref/status-build-failure.md similarity index 100% rename from doc/manual/src/command-ref/status-build-failure.md rename to doc/manual/source/command-ref/status-build-failure.md diff --git a/doc/manual/src/command-ref/utilities.md b/doc/manual/source/command-ref/utilities.md similarity index 100% rename from doc/manual/src/command-ref/utilities.md rename to doc/manual/source/command-ref/utilities.md diff --git a/doc/manual/src/development/building.md b/doc/manual/source/development/building.md similarity index 100% rename from doc/manual/src/development/building.md rename to doc/manual/source/development/building.md diff --git a/doc/manual/src/development/cli-guideline.md b/doc/manual/source/development/cli-guideline.md similarity index 100% rename from doc/manual/src/development/cli-guideline.md rename to doc/manual/source/development/cli-guideline.md diff --git a/doc/manual/src/development/contributing.md b/doc/manual/source/development/contributing.md similarity index 100% rename from doc/manual/src/development/contributing.md rename to doc/manual/source/development/contributing.md diff --git a/doc/manual/src/development/cxx.md b/doc/manual/source/development/cxx.md similarity index 100% rename from doc/manual/src/development/cxx.md rename to doc/manual/source/development/cxx.md diff --git a/doc/manual/src/development/documentation.md b/doc/manual/source/development/documentation.md similarity index 98% rename from doc/manual/src/development/documentation.md rename to doc/manual/source/development/documentation.md index d5a95e0c1..d51373e7b 100644 --- a/doc/manual/src/development/documentation.md +++ b/doc/manual/source/development/documentation.md @@ -35,7 +35,7 @@ In order to reflect changes to the [Makefile for the manual], clear all generate [Makefile for the manual]: https://github.com/NixOS/nix/blob/master/doc/manual/local.mk ```console -rm $(git ls-files doc/manual/ -o | grep -F '.md') && rmdir doc/manual/src/command-ref/new-cli && make manual-html -j $NIX_BUILD_CORES +rm $(git ls-files doc/manual/ -o | grep -F '.md') && rmdir doc/manual/source/command-ref/new-cli && make manual-html -j $NIX_BUILD_CORES ``` ## Style guide @@ -182,7 +182,7 @@ Please observe these guidelines to ease reviews: `@docroot@` provides a base path for links that occur in reusable snippets or other documentation that doesn't have a base path of its own. -If a broken link occurs in a snippet that was inserted into multiple generated files in different directories, use `@docroot@` to reference the `doc/manual/src` directory. +If a broken link occurs in a snippet that was inserted into multiple generated files in different directories, use `@docroot@` to reference the `doc/manual/source` directory. If the `@docroot@` literal appears in an error message from the [`mdbook-linkcheck`] tool, the `@docroot@` replacement needs to be applied to the generated source file that mentions it. See existing `@docroot@` logic in the [Makefile for the manual]. diff --git a/doc/manual/src/development/experimental-features.md b/doc/manual/source/development/experimental-features.md similarity index 100% rename from doc/manual/src/development/experimental-features.md rename to doc/manual/source/development/experimental-features.md diff --git a/doc/manual/src/development/index.md b/doc/manual/source/development/index.md similarity index 100% rename from doc/manual/src/development/index.md rename to doc/manual/source/development/index.md diff --git a/doc/manual/src/development/json-guideline.md b/doc/manual/source/development/json-guideline.md similarity index 100% rename from doc/manual/src/development/json-guideline.md rename to doc/manual/source/development/json-guideline.md diff --git a/doc/manual/src/development/meson.build b/doc/manual/source/development/meson.build similarity index 100% rename from doc/manual/src/development/meson.build rename to doc/manual/source/development/meson.build diff --git a/doc/manual/src/development/testing.md b/doc/manual/source/development/testing.md similarity index 100% rename from doc/manual/src/development/testing.md rename to doc/manual/source/development/testing.md diff --git a/doc/manual/src/favicon.png b/doc/manual/source/favicon.png similarity index 100% rename from doc/manual/src/favicon.png rename to doc/manual/source/favicon.png diff --git a/doc/manual/src/favicon.svg b/doc/manual/source/favicon.svg similarity index 100% rename from doc/manual/src/favicon.svg rename to doc/manual/source/favicon.svg diff --git a/doc/manual/src/figures/user-environments.png b/doc/manual/source/figures/user-environments.png similarity index 100% rename from doc/manual/src/figures/user-environments.png rename to doc/manual/source/figures/user-environments.png diff --git a/doc/manual/src/figures/user-environments.sxd b/doc/manual/source/figures/user-environments.sxd similarity index 100% rename from doc/manual/src/figures/user-environments.sxd rename to doc/manual/source/figures/user-environments.sxd diff --git a/doc/manual/src/glossary.md b/doc/manual/source/glossary.md similarity index 100% rename from doc/manual/src/glossary.md rename to doc/manual/source/glossary.md diff --git a/doc/manual/src/installation/building-source.md b/doc/manual/source/installation/building-source.md similarity index 100% rename from doc/manual/src/installation/building-source.md rename to doc/manual/source/installation/building-source.md diff --git a/doc/manual/src/installation/env-variables.md b/doc/manual/source/installation/env-variables.md similarity index 100% rename from doc/manual/src/installation/env-variables.md rename to doc/manual/source/installation/env-variables.md diff --git a/doc/manual/src/installation/index.md b/doc/manual/source/installation/index.md similarity index 100% rename from doc/manual/src/installation/index.md rename to doc/manual/source/installation/index.md diff --git a/doc/manual/src/installation/installing-binary.md b/doc/manual/source/installation/installing-binary.md similarity index 100% rename from doc/manual/src/installation/installing-binary.md rename to doc/manual/source/installation/installing-binary.md diff --git a/doc/manual/src/installation/installing-docker.md b/doc/manual/source/installation/installing-docker.md similarity index 100% rename from doc/manual/src/installation/installing-docker.md rename to doc/manual/source/installation/installing-docker.md diff --git a/doc/manual/src/installation/installing-source.md b/doc/manual/source/installation/installing-source.md similarity index 100% rename from doc/manual/src/installation/installing-source.md rename to doc/manual/source/installation/installing-source.md diff --git a/doc/manual/src/installation/multi-user.md b/doc/manual/source/installation/multi-user.md similarity index 100% rename from doc/manual/src/installation/multi-user.md rename to doc/manual/source/installation/multi-user.md diff --git a/doc/manual/src/installation/nix-security.md b/doc/manual/source/installation/nix-security.md similarity index 100% rename from doc/manual/src/installation/nix-security.md rename to doc/manual/source/installation/nix-security.md diff --git a/doc/manual/src/installation/obtaining-source.md b/doc/manual/source/installation/obtaining-source.md similarity index 100% rename from doc/manual/src/installation/obtaining-source.md rename to doc/manual/source/installation/obtaining-source.md diff --git a/doc/manual/src/installation/prerequisites-source.md b/doc/manual/source/installation/prerequisites-source.md similarity index 100% rename from doc/manual/src/installation/prerequisites-source.md rename to doc/manual/source/installation/prerequisites-source.md diff --git a/doc/manual/src/installation/single-user.md b/doc/manual/source/installation/single-user.md similarity index 100% rename from doc/manual/src/installation/single-user.md rename to doc/manual/source/installation/single-user.md diff --git a/doc/manual/src/installation/supported-platforms.md b/doc/manual/source/installation/supported-platforms.md similarity index 100% rename from doc/manual/src/installation/supported-platforms.md rename to doc/manual/source/installation/supported-platforms.md diff --git a/doc/manual/src/installation/uninstall.md b/doc/manual/source/installation/uninstall.md similarity index 100% rename from doc/manual/src/installation/uninstall.md rename to doc/manual/source/installation/uninstall.md diff --git a/doc/manual/src/installation/upgrading.md b/doc/manual/source/installation/upgrading.md similarity index 100% rename from doc/manual/src/installation/upgrading.md rename to doc/manual/source/installation/upgrading.md diff --git a/doc/manual/src/introduction.md b/doc/manual/source/introduction.md similarity index 100% rename from doc/manual/src/introduction.md rename to doc/manual/source/introduction.md diff --git a/doc/manual/src/language/advanced-attributes.md b/doc/manual/source/language/advanced-attributes.md similarity index 100% rename from doc/manual/src/language/advanced-attributes.md rename to doc/manual/source/language/advanced-attributes.md diff --git a/doc/manual/src/language/builtins-prefix.md b/doc/manual/source/language/builtins-prefix.md similarity index 100% rename from doc/manual/src/language/builtins-prefix.md rename to doc/manual/source/language/builtins-prefix.md diff --git a/doc/manual/src/language/builtins-suffix.md b/doc/manual/source/language/builtins-suffix.md similarity index 100% rename from doc/manual/src/language/builtins-suffix.md rename to doc/manual/source/language/builtins-suffix.md diff --git a/doc/manual/src/language/constructs.md b/doc/manual/source/language/constructs.md similarity index 100% rename from doc/manual/src/language/constructs.md rename to doc/manual/source/language/constructs.md diff --git a/doc/manual/src/language/constructs/lookup-path.md b/doc/manual/source/language/constructs/lookup-path.md similarity index 100% rename from doc/manual/src/language/constructs/lookup-path.md rename to doc/manual/source/language/constructs/lookup-path.md diff --git a/doc/manual/src/language/derivations.md b/doc/manual/source/language/derivations.md similarity index 100% rename from doc/manual/src/language/derivations.md rename to doc/manual/source/language/derivations.md diff --git a/doc/manual/src/language/identifiers.md b/doc/manual/source/language/identifiers.md similarity index 100% rename from doc/manual/src/language/identifiers.md rename to doc/manual/source/language/identifiers.md diff --git a/doc/manual/src/language/import-from-derivation.md b/doc/manual/source/language/import-from-derivation.md similarity index 100% rename from doc/manual/src/language/import-from-derivation.md rename to doc/manual/source/language/import-from-derivation.md diff --git a/doc/manual/src/language/index.md b/doc/manual/source/language/index.md similarity index 100% rename from doc/manual/src/language/index.md rename to doc/manual/source/language/index.md diff --git a/doc/manual/src/language/meson.build b/doc/manual/source/language/meson.build similarity index 100% rename from doc/manual/src/language/meson.build rename to doc/manual/source/language/meson.build diff --git a/doc/manual/src/language/operators.md b/doc/manual/source/language/operators.md similarity index 100% rename from doc/manual/src/language/operators.md rename to doc/manual/source/language/operators.md diff --git a/doc/manual/src/language/scope.md b/doc/manual/source/language/scope.md similarity index 100% rename from doc/manual/src/language/scope.md rename to doc/manual/source/language/scope.md diff --git a/doc/manual/src/language/string-context.md b/doc/manual/source/language/string-context.md similarity index 100% rename from doc/manual/src/language/string-context.md rename to doc/manual/source/language/string-context.md diff --git a/doc/manual/src/language/string-interpolation.md b/doc/manual/source/language/string-interpolation.md similarity index 100% rename from doc/manual/src/language/string-interpolation.md rename to doc/manual/source/language/string-interpolation.md diff --git a/doc/manual/src/language/string-literals.md b/doc/manual/source/language/string-literals.md similarity index 100% rename from doc/manual/src/language/string-literals.md rename to doc/manual/source/language/string-literals.md diff --git a/doc/manual/src/language/syntax.md b/doc/manual/source/language/syntax.md similarity index 100% rename from doc/manual/src/language/syntax.md rename to doc/manual/source/language/syntax.md diff --git a/doc/manual/src/language/types.md b/doc/manual/source/language/types.md similarity index 100% rename from doc/manual/src/language/types.md rename to doc/manual/source/language/types.md diff --git a/doc/manual/src/language/values.md b/doc/manual/source/language/values.md similarity index 100% rename from doc/manual/src/language/values.md rename to doc/manual/source/language/values.md diff --git a/doc/manual/src/language/variables.md b/doc/manual/source/language/variables.md similarity index 100% rename from doc/manual/src/language/variables.md rename to doc/manual/source/language/variables.md diff --git a/doc/manual/src/meson.build b/doc/manual/source/meson.build similarity index 100% rename from doc/manual/src/meson.build rename to doc/manual/source/meson.build diff --git a/doc/manual/src/package-management/binary-cache-substituter.md b/doc/manual/source/package-management/binary-cache-substituter.md similarity index 100% rename from doc/manual/src/package-management/binary-cache-substituter.md rename to doc/manual/source/package-management/binary-cache-substituter.md diff --git a/doc/manual/src/package-management/garbage-collection.md b/doc/manual/source/package-management/garbage-collection.md similarity index 100% rename from doc/manual/src/package-management/garbage-collection.md rename to doc/manual/source/package-management/garbage-collection.md diff --git a/doc/manual/src/package-management/garbage-collector-roots.md b/doc/manual/source/package-management/garbage-collector-roots.md similarity index 100% rename from doc/manual/src/package-management/garbage-collector-roots.md rename to doc/manual/source/package-management/garbage-collector-roots.md diff --git a/doc/manual/src/package-management/index.md b/doc/manual/source/package-management/index.md similarity index 100% rename from doc/manual/src/package-management/index.md rename to doc/manual/source/package-management/index.md diff --git a/doc/manual/src/package-management/profiles.md b/doc/manual/source/package-management/profiles.md similarity index 100% rename from doc/manual/src/package-management/profiles.md rename to doc/manual/source/package-management/profiles.md diff --git a/doc/manual/src/package-management/sharing-packages.md b/doc/manual/source/package-management/sharing-packages.md similarity index 100% rename from doc/manual/src/package-management/sharing-packages.md rename to doc/manual/source/package-management/sharing-packages.md diff --git a/doc/manual/src/package-management/ssh-substituter.md b/doc/manual/source/package-management/ssh-substituter.md similarity index 100% rename from doc/manual/src/package-management/ssh-substituter.md rename to doc/manual/source/package-management/ssh-substituter.md diff --git a/doc/manual/src/protocols/derivation-aterm.md b/doc/manual/source/protocols/derivation-aterm.md similarity index 100% rename from doc/manual/src/protocols/derivation-aterm.md rename to doc/manual/source/protocols/derivation-aterm.md diff --git a/doc/manual/src/protocols/index.md b/doc/manual/source/protocols/index.md similarity index 100% rename from doc/manual/src/protocols/index.md rename to doc/manual/source/protocols/index.md diff --git a/doc/manual/src/protocols/json/derivation.md b/doc/manual/source/protocols/json/derivation.md similarity index 100% rename from doc/manual/src/protocols/json/derivation.md rename to doc/manual/source/protocols/json/derivation.md diff --git a/doc/manual/src/protocols/json/index.md b/doc/manual/source/protocols/json/index.md similarity index 100% rename from doc/manual/src/protocols/json/index.md rename to doc/manual/source/protocols/json/index.md diff --git a/doc/manual/src/protocols/json/store-object-info.md b/doc/manual/source/protocols/json/store-object-info.md similarity index 100% rename from doc/manual/src/protocols/json/store-object-info.md rename to doc/manual/source/protocols/json/store-object-info.md diff --git a/doc/manual/src/protocols/nix-archive.md b/doc/manual/source/protocols/nix-archive.md similarity index 100% rename from doc/manual/src/protocols/nix-archive.md rename to doc/manual/source/protocols/nix-archive.md diff --git a/doc/manual/src/protocols/store-path.md b/doc/manual/source/protocols/store-path.md similarity index 100% rename from doc/manual/src/protocols/store-path.md rename to doc/manual/source/protocols/store-path.md diff --git a/doc/manual/src/protocols/tarball-fetcher.md b/doc/manual/source/protocols/tarball-fetcher.md similarity index 100% rename from doc/manual/src/protocols/tarball-fetcher.md rename to doc/manual/source/protocols/tarball-fetcher.md diff --git a/doc/manual/src/quick-start.md b/doc/manual/source/quick-start.md similarity index 100% rename from doc/manual/src/quick-start.md rename to doc/manual/source/quick-start.md diff --git a/doc/manual/src/release-notes/index.md b/doc/manual/source/release-notes/index.md similarity index 100% rename from doc/manual/src/release-notes/index.md rename to doc/manual/source/release-notes/index.md diff --git a/doc/manual/src/release-notes/meson.build b/doc/manual/source/release-notes/meson.build similarity index 100% rename from doc/manual/src/release-notes/meson.build rename to doc/manual/source/release-notes/meson.build diff --git a/doc/manual/src/release-notes/rl-0.10.1.md b/doc/manual/source/release-notes/rl-0.10.1.md similarity index 100% rename from doc/manual/src/release-notes/rl-0.10.1.md rename to doc/manual/source/release-notes/rl-0.10.1.md diff --git a/doc/manual/src/release-notes/rl-0.10.md b/doc/manual/source/release-notes/rl-0.10.md similarity index 100% rename from doc/manual/src/release-notes/rl-0.10.md rename to doc/manual/source/release-notes/rl-0.10.md diff --git a/doc/manual/src/release-notes/rl-0.11.md b/doc/manual/source/release-notes/rl-0.11.md similarity index 100% rename from doc/manual/src/release-notes/rl-0.11.md rename to doc/manual/source/release-notes/rl-0.11.md diff --git a/doc/manual/src/release-notes/rl-0.12.md b/doc/manual/source/release-notes/rl-0.12.md similarity index 100% rename from doc/manual/src/release-notes/rl-0.12.md rename to doc/manual/source/release-notes/rl-0.12.md diff --git a/doc/manual/src/release-notes/rl-0.13.md b/doc/manual/source/release-notes/rl-0.13.md similarity index 100% rename from doc/manual/src/release-notes/rl-0.13.md rename to doc/manual/source/release-notes/rl-0.13.md diff --git a/doc/manual/src/release-notes/rl-0.14.md b/doc/manual/source/release-notes/rl-0.14.md similarity index 100% rename from doc/manual/src/release-notes/rl-0.14.md rename to doc/manual/source/release-notes/rl-0.14.md diff --git a/doc/manual/src/release-notes/rl-0.15.md b/doc/manual/source/release-notes/rl-0.15.md similarity index 100% rename from doc/manual/src/release-notes/rl-0.15.md rename to doc/manual/source/release-notes/rl-0.15.md diff --git a/doc/manual/src/release-notes/rl-0.16.md b/doc/manual/source/release-notes/rl-0.16.md similarity index 100% rename from doc/manual/src/release-notes/rl-0.16.md rename to doc/manual/source/release-notes/rl-0.16.md diff --git a/doc/manual/src/release-notes/rl-0.5.md b/doc/manual/source/release-notes/rl-0.5.md similarity index 100% rename from doc/manual/src/release-notes/rl-0.5.md rename to doc/manual/source/release-notes/rl-0.5.md diff --git a/doc/manual/src/release-notes/rl-0.6.md b/doc/manual/source/release-notes/rl-0.6.md similarity index 100% rename from doc/manual/src/release-notes/rl-0.6.md rename to doc/manual/source/release-notes/rl-0.6.md diff --git a/doc/manual/src/release-notes/rl-0.7.md b/doc/manual/source/release-notes/rl-0.7.md similarity index 100% rename from doc/manual/src/release-notes/rl-0.7.md rename to doc/manual/source/release-notes/rl-0.7.md diff --git a/doc/manual/src/release-notes/rl-0.8.1.md b/doc/manual/source/release-notes/rl-0.8.1.md similarity index 100% rename from doc/manual/src/release-notes/rl-0.8.1.md rename to doc/manual/source/release-notes/rl-0.8.1.md diff --git a/doc/manual/src/release-notes/rl-0.8.md b/doc/manual/source/release-notes/rl-0.8.md similarity index 100% rename from doc/manual/src/release-notes/rl-0.8.md rename to doc/manual/source/release-notes/rl-0.8.md diff --git a/doc/manual/src/release-notes/rl-0.9.1.md b/doc/manual/source/release-notes/rl-0.9.1.md similarity index 100% rename from doc/manual/src/release-notes/rl-0.9.1.md rename to doc/manual/source/release-notes/rl-0.9.1.md diff --git a/doc/manual/src/release-notes/rl-0.9.2.md b/doc/manual/source/release-notes/rl-0.9.2.md similarity index 100% rename from doc/manual/src/release-notes/rl-0.9.2.md rename to doc/manual/source/release-notes/rl-0.9.2.md diff --git a/doc/manual/src/release-notes/rl-0.9.md b/doc/manual/source/release-notes/rl-0.9.md similarity index 100% rename from doc/manual/src/release-notes/rl-0.9.md rename to doc/manual/source/release-notes/rl-0.9.md diff --git a/doc/manual/src/release-notes/rl-1.0.md b/doc/manual/source/release-notes/rl-1.0.md similarity index 100% rename from doc/manual/src/release-notes/rl-1.0.md rename to doc/manual/source/release-notes/rl-1.0.md diff --git a/doc/manual/src/release-notes/rl-1.1.md b/doc/manual/source/release-notes/rl-1.1.md similarity index 100% rename from doc/manual/src/release-notes/rl-1.1.md rename to doc/manual/source/release-notes/rl-1.1.md diff --git a/doc/manual/src/release-notes/rl-1.10.md b/doc/manual/source/release-notes/rl-1.10.md similarity index 100% rename from doc/manual/src/release-notes/rl-1.10.md rename to doc/manual/source/release-notes/rl-1.10.md diff --git a/doc/manual/src/release-notes/rl-1.11.10.md b/doc/manual/source/release-notes/rl-1.11.10.md similarity index 100% rename from doc/manual/src/release-notes/rl-1.11.10.md rename to doc/manual/source/release-notes/rl-1.11.10.md diff --git a/doc/manual/src/release-notes/rl-1.11.md b/doc/manual/source/release-notes/rl-1.11.md similarity index 100% rename from doc/manual/src/release-notes/rl-1.11.md rename to doc/manual/source/release-notes/rl-1.11.md diff --git a/doc/manual/src/release-notes/rl-1.2.md b/doc/manual/source/release-notes/rl-1.2.md similarity index 100% rename from doc/manual/src/release-notes/rl-1.2.md rename to doc/manual/source/release-notes/rl-1.2.md diff --git a/doc/manual/src/release-notes/rl-1.3.md b/doc/manual/source/release-notes/rl-1.3.md similarity index 100% rename from doc/manual/src/release-notes/rl-1.3.md rename to doc/manual/source/release-notes/rl-1.3.md diff --git a/doc/manual/src/release-notes/rl-1.4.md b/doc/manual/source/release-notes/rl-1.4.md similarity index 100% rename from doc/manual/src/release-notes/rl-1.4.md rename to doc/manual/source/release-notes/rl-1.4.md diff --git a/doc/manual/src/release-notes/rl-1.5.1.md b/doc/manual/source/release-notes/rl-1.5.1.md similarity index 100% rename from doc/manual/src/release-notes/rl-1.5.1.md rename to doc/manual/source/release-notes/rl-1.5.1.md diff --git a/doc/manual/src/release-notes/rl-1.5.2.md b/doc/manual/source/release-notes/rl-1.5.2.md similarity index 100% rename from doc/manual/src/release-notes/rl-1.5.2.md rename to doc/manual/source/release-notes/rl-1.5.2.md diff --git a/doc/manual/src/release-notes/rl-1.5.md b/doc/manual/source/release-notes/rl-1.5.md similarity index 100% rename from doc/manual/src/release-notes/rl-1.5.md rename to doc/manual/source/release-notes/rl-1.5.md diff --git a/doc/manual/src/release-notes/rl-1.6.1.md b/doc/manual/source/release-notes/rl-1.6.1.md similarity index 100% rename from doc/manual/src/release-notes/rl-1.6.1.md rename to doc/manual/source/release-notes/rl-1.6.1.md diff --git a/doc/manual/src/release-notes/rl-1.6.md b/doc/manual/source/release-notes/rl-1.6.md similarity index 100% rename from doc/manual/src/release-notes/rl-1.6.md rename to doc/manual/source/release-notes/rl-1.6.md diff --git a/doc/manual/src/release-notes/rl-1.7.md b/doc/manual/source/release-notes/rl-1.7.md similarity index 100% rename from doc/manual/src/release-notes/rl-1.7.md rename to doc/manual/source/release-notes/rl-1.7.md diff --git a/doc/manual/src/release-notes/rl-1.8.md b/doc/manual/source/release-notes/rl-1.8.md similarity index 100% rename from doc/manual/src/release-notes/rl-1.8.md rename to doc/manual/source/release-notes/rl-1.8.md diff --git a/doc/manual/src/release-notes/rl-1.9.md b/doc/manual/source/release-notes/rl-1.9.md similarity index 100% rename from doc/manual/src/release-notes/rl-1.9.md rename to doc/manual/source/release-notes/rl-1.9.md diff --git a/doc/manual/src/release-notes/rl-2.0.md b/doc/manual/source/release-notes/rl-2.0.md similarity index 100% rename from doc/manual/src/release-notes/rl-2.0.md rename to doc/manual/source/release-notes/rl-2.0.md diff --git a/doc/manual/src/release-notes/rl-2.1.md b/doc/manual/source/release-notes/rl-2.1.md similarity index 100% rename from doc/manual/src/release-notes/rl-2.1.md rename to doc/manual/source/release-notes/rl-2.1.md diff --git a/doc/manual/src/release-notes/rl-2.10.md b/doc/manual/source/release-notes/rl-2.10.md similarity index 100% rename from doc/manual/src/release-notes/rl-2.10.md rename to doc/manual/source/release-notes/rl-2.10.md diff --git a/doc/manual/src/release-notes/rl-2.11.md b/doc/manual/source/release-notes/rl-2.11.md similarity index 100% rename from doc/manual/src/release-notes/rl-2.11.md rename to doc/manual/source/release-notes/rl-2.11.md diff --git a/doc/manual/src/release-notes/rl-2.12.md b/doc/manual/source/release-notes/rl-2.12.md similarity index 100% rename from doc/manual/src/release-notes/rl-2.12.md rename to doc/manual/source/release-notes/rl-2.12.md diff --git a/doc/manual/src/release-notes/rl-2.13.md b/doc/manual/source/release-notes/rl-2.13.md similarity index 100% rename from doc/manual/src/release-notes/rl-2.13.md rename to doc/manual/source/release-notes/rl-2.13.md diff --git a/doc/manual/src/release-notes/rl-2.14.md b/doc/manual/source/release-notes/rl-2.14.md similarity index 100% rename from doc/manual/src/release-notes/rl-2.14.md rename to doc/manual/source/release-notes/rl-2.14.md diff --git a/doc/manual/src/release-notes/rl-2.15.md b/doc/manual/source/release-notes/rl-2.15.md similarity index 100% rename from doc/manual/src/release-notes/rl-2.15.md rename to doc/manual/source/release-notes/rl-2.15.md diff --git a/doc/manual/src/release-notes/rl-2.16.md b/doc/manual/source/release-notes/rl-2.16.md similarity index 100% rename from doc/manual/src/release-notes/rl-2.16.md rename to doc/manual/source/release-notes/rl-2.16.md diff --git a/doc/manual/src/release-notes/rl-2.17.md b/doc/manual/source/release-notes/rl-2.17.md similarity index 100% rename from doc/manual/src/release-notes/rl-2.17.md rename to doc/manual/source/release-notes/rl-2.17.md diff --git a/doc/manual/src/release-notes/rl-2.18.md b/doc/manual/source/release-notes/rl-2.18.md similarity index 100% rename from doc/manual/src/release-notes/rl-2.18.md rename to doc/manual/source/release-notes/rl-2.18.md diff --git a/doc/manual/src/release-notes/rl-2.19.md b/doc/manual/source/release-notes/rl-2.19.md similarity index 100% rename from doc/manual/src/release-notes/rl-2.19.md rename to doc/manual/source/release-notes/rl-2.19.md diff --git a/doc/manual/src/release-notes/rl-2.2.md b/doc/manual/source/release-notes/rl-2.2.md similarity index 100% rename from doc/manual/src/release-notes/rl-2.2.md rename to doc/manual/source/release-notes/rl-2.2.md diff --git a/doc/manual/src/release-notes/rl-2.20.md b/doc/manual/source/release-notes/rl-2.20.md similarity index 100% rename from doc/manual/src/release-notes/rl-2.20.md rename to doc/manual/source/release-notes/rl-2.20.md diff --git a/doc/manual/src/release-notes/rl-2.21.md b/doc/manual/source/release-notes/rl-2.21.md similarity index 100% rename from doc/manual/src/release-notes/rl-2.21.md rename to doc/manual/source/release-notes/rl-2.21.md diff --git a/doc/manual/src/release-notes/rl-2.22.md b/doc/manual/source/release-notes/rl-2.22.md similarity index 100% rename from doc/manual/src/release-notes/rl-2.22.md rename to doc/manual/source/release-notes/rl-2.22.md diff --git a/doc/manual/src/release-notes/rl-2.23.md b/doc/manual/source/release-notes/rl-2.23.md similarity index 100% rename from doc/manual/src/release-notes/rl-2.23.md rename to doc/manual/source/release-notes/rl-2.23.md diff --git a/doc/manual/src/release-notes/rl-2.24.md b/doc/manual/source/release-notes/rl-2.24.md similarity index 100% rename from doc/manual/src/release-notes/rl-2.24.md rename to doc/manual/source/release-notes/rl-2.24.md diff --git a/doc/manual/src/release-notes/rl-2.3.md b/doc/manual/source/release-notes/rl-2.3.md similarity index 100% rename from doc/manual/src/release-notes/rl-2.3.md rename to doc/manual/source/release-notes/rl-2.3.md diff --git a/doc/manual/src/release-notes/rl-2.4.md b/doc/manual/source/release-notes/rl-2.4.md similarity index 100% rename from doc/manual/src/release-notes/rl-2.4.md rename to doc/manual/source/release-notes/rl-2.4.md diff --git a/doc/manual/src/release-notes/rl-2.5.md b/doc/manual/source/release-notes/rl-2.5.md similarity index 100% rename from doc/manual/src/release-notes/rl-2.5.md rename to doc/manual/source/release-notes/rl-2.5.md diff --git a/doc/manual/src/release-notes/rl-2.6.md b/doc/manual/source/release-notes/rl-2.6.md similarity index 100% rename from doc/manual/src/release-notes/rl-2.6.md rename to doc/manual/source/release-notes/rl-2.6.md diff --git a/doc/manual/src/release-notes/rl-2.7.md b/doc/manual/source/release-notes/rl-2.7.md similarity index 100% rename from doc/manual/src/release-notes/rl-2.7.md rename to doc/manual/source/release-notes/rl-2.7.md diff --git a/doc/manual/src/release-notes/rl-2.8.md b/doc/manual/source/release-notes/rl-2.8.md similarity index 100% rename from doc/manual/src/release-notes/rl-2.8.md rename to doc/manual/source/release-notes/rl-2.8.md diff --git a/doc/manual/src/release-notes/rl-2.9.md b/doc/manual/source/release-notes/rl-2.9.md similarity index 100% rename from doc/manual/src/release-notes/rl-2.9.md rename to doc/manual/source/release-notes/rl-2.9.md diff --git a/doc/manual/src/store/file-system-object.md b/doc/manual/source/store/file-system-object.md similarity index 100% rename from doc/manual/src/store/file-system-object.md rename to doc/manual/source/store/file-system-object.md diff --git a/doc/manual/src/store/file-system-object/content-address.md b/doc/manual/source/store/file-system-object/content-address.md similarity index 100% rename from doc/manual/src/store/file-system-object/content-address.md rename to doc/manual/source/store/file-system-object/content-address.md diff --git a/doc/manual/src/store/index.md b/doc/manual/source/store/index.md similarity index 100% rename from doc/manual/src/store/index.md rename to doc/manual/source/store/index.md diff --git a/doc/manual/src/store/meson.build b/doc/manual/source/store/meson.build similarity index 100% rename from doc/manual/src/store/meson.build rename to doc/manual/source/store/meson.build diff --git a/doc/manual/src/store/store-object.md b/doc/manual/source/store/store-object.md similarity index 100% rename from doc/manual/src/store/store-object.md rename to doc/manual/source/store/store-object.md diff --git a/doc/manual/src/store/store-object/content-address.md b/doc/manual/source/store/store-object/content-address.md similarity index 100% rename from doc/manual/src/store/store-object/content-address.md rename to doc/manual/source/store/store-object/content-address.md diff --git a/doc/manual/src/store/store-path.md b/doc/manual/source/store/store-path.md similarity index 100% rename from doc/manual/src/store/store-path.md rename to doc/manual/source/store/store-path.md diff --git a/doc/manual/src/store/types/index.md.in b/doc/manual/source/store/types/index.md.in similarity index 100% rename from doc/manual/src/store/types/index.md.in rename to doc/manual/source/store/types/index.md.in diff --git a/doc/manual/substitute.py b/doc/manual/substitute.py index 52cef4fa0..a8b11d932 100644 --- a/doc/manual/substitute.py +++ b/doc/manual/substitute.py @@ -80,7 +80,7 @@ def main() -> None: if len(sys.argv) > 1 and sys.argv[1] == 'summary': print(do_include( sys.stdin.read(), - Path('src/SUMMARY.md'), + Path('source/SUMMARY.md'), Path(sys.argv[2]).resolve(), search_path)) return @@ -92,7 +92,7 @@ def main() -> None: context, book = json.load(sys.stdin) - # book_root is the directory where book contents leave (ie, src/) + # book_root is the directory where book contents leave (ie, source/) book_root = Path(context['root']) / context['config']['book']['src'] # Find @var@ in all parts of our recursive book structure. diff --git a/maintainers/release-notes b/maintainers/release-notes index c0c4ee734..0cdcd517b 100755 --- a/maintainers/release-notes +++ b/maintainers/release-notes @@ -78,7 +78,7 @@ if ! git diff --quiet --cached; then die "repo has staged changes, please commit or stash them" fi -if ! grep "$SUMMARY_MARKER_LINE" doc/manual/src/SUMMARY.md.in >/dev/null; then +if ! grep "$SUMMARY_MARKER_LINE" doc/manual/source/SUMMARY.md.in >/dev/null; then # would have been nice to catch this early, but won't be worth the extra infra die "SUMMARY.md.in is missing the marker line '$SUMMARY_MARKER_LINE', which would be used for inserting a new release notes page. Please fix the script." fi @@ -117,7 +117,7 @@ log "version_full=$version_full" log "IS_PATCH=$IS_PATCH" basename=rl-${version_major_minor}.md -file=doc/manual/src/release-notes/$basename +file=doc/manual/source/release-notes/$basename if ! $IS_PATCH; then if [[ -e $file ]]; then @@ -169,7 +169,7 @@ if ! $IS_PATCH; then # find the marker line, insert new link after it escaped_marker="$(echo "$SUMMARY_MARKER_LINE" | sed -e 's/\//\\\//g' -e 's/ /\\ /g')" escaped_line="$(echo "$NEW_SUMMARY_LINE" | sed -e 's/\//\\\//g' -e 's/ /\\ /g')" - logcmd sed -i -e "/$escaped_marker/a $escaped_line" doc/manual/src/SUMMARY.md.in + logcmd sed -i -e "/$escaped_marker/a $escaped_line" doc/manual/source/SUMMARY.md.in fi for f in doc/manual/rl-next/*.md; do @@ -178,7 +178,7 @@ for f in doc/manual/rl-next/*.md; do fi done -logcmd git add $file doc/manual/src/SUMMARY.md.in +logcmd git add $file doc/manual/source/SUMMARY.md.in logcmd git status logcmd git commit -m "release notes: $version_full" diff --git a/src/libstore/unix/build/local-derivation-goal.cc b/src/libstore/unix/build/local-derivation-goal.cc index e3e3a4c9b..ec7a771a2 100644 --- a/src/libstore/unix/build/local-derivation-goal.cc +++ b/src/libstore/unix/build/local-derivation-goal.cc @@ -3068,7 +3068,7 @@ bool LocalDerivationGoal::isReadDesc(int fd) StorePath LocalDerivationGoal::makeFallbackPath(OutputNameView outputName) { // This is a bogus path type, constructed this way to ensure that it doesn't collide with any other store path - // See doc/manual/src/protocols/store-path.md for details + // See doc/manual/source/protocols/store-path.md for details // TODO: We may want to separate the responsibilities of constructing the path fingerprint and of actually doing the hashing auto pathType = "rewrite:" + std::string(drvPath.to_string()) + ":name:" + std::string(outputName); return worker.store.makeStorePath( @@ -3081,7 +3081,7 @@ StorePath LocalDerivationGoal::makeFallbackPath(OutputNameView outputName) StorePath LocalDerivationGoal::makeFallbackPath(const StorePath & path) { // This is a bogus path type, constructed this way to ensure that it doesn't collide with any other store path - // See doc/manual/src/protocols/store-path.md for details + // See doc/manual/source/protocols/store-path.md for details auto pathType = "rewrite:" + std::string(drvPath.to_string()) + ":" + std::string(path.to_string()); return worker.store.makeStorePath( pathType, diff --git a/src/nix/help-stores.md b/src/nix/help-stores.md index 5c5624f5e..ff9d39c50 120000 --- a/src/nix/help-stores.md +++ b/src/nix/help-stores.md @@ -1 +1 @@ -../../doc/manual/src/store/types/index.md.in \ No newline at end of file +../../doc/manual/source/store/types/index.md.in \ No newline at end of file diff --git a/src/nix/package.nix b/src/nix/package.nix index 3e19c6dca..ee640ab54 100644 --- a/src/nix/package.nix +++ b/src/nix/package.nix @@ -66,9 +66,9 @@ mkMesonDerivation (finalAttrs: { ../nix-env/buildenv.nix ./get-env.sh ./help-stores.md - ../../doc/manual/src/store/types/index.md.in + ../../doc/manual/source/store/types/index.md.in ./profiles.md - ../../doc/manual/src/command-ref/files/profiles.md + ../../doc/manual/source/command-ref/files/profiles.md # Files ] ++ lib.concatMap diff --git a/src/nix/profiles.md b/src/nix/profiles.md index c67a86194..f65e71065 120000 --- a/src/nix/profiles.md +++ b/src/nix/profiles.md @@ -1 +1 @@ -../../doc/manual/src/command-ref/files/profiles.md \ No newline at end of file +../../doc/manual/source/command-ref/files/profiles.md \ No newline at end of file diff --git a/tests/functional/check.sh b/tests/functional/check.sh index 9b15dccb6..23e3d2ff0 100755 --- a/tests/functional/check.sh +++ b/tests/functional/check.sh @@ -23,7 +23,7 @@ nix-build dependencies.nix --no-out-link nix-build dependencies.nix --no-out-link --check # Build failure exit codes (100, 104, etc.) are from -# doc/manual/src/command-ref/status-build-failure.md +# doc/manual/source/command-ref/status-build-failure.md # check for dangling temporary build directories # only retain if build fails and --keep-failed is specified, or... diff --git a/tests/functional/common/functions.sh b/tests/functional/common/functions.sh index d05fac4e7..7195149cb 100644 --- a/tests/functional/common/functions.sh +++ b/tests/functional/common/functions.sh @@ -28,7 +28,7 @@ clearProfiles() { # Clear the store, but do not fail if we're in an environment where we can't. # This allows the test to run in a NixOS test environment, where we use the system store. -# See doc/manual/src/contributing/testing.md / Running functional tests on NixOS. +# See doc/manual/source/contributing/testing.md / Running functional tests on NixOS. clearStoreIfPossible() { if isTestOnNixOS; then echo "clearStoreIfPossible: Not clearing store, because we're on NixOS. Moving on." diff --git a/tests/functional/linux-sandbox.sh b/tests/functional/linux-sandbox.sh index 653a3873f..1fc89f8ae 100755 --- a/tests/functional/linux-sandbox.sh +++ b/tests/functional/linux-sandbox.sh @@ -40,13 +40,13 @@ nix-sandbox-build dependencies.nix --check # Test that sandboxed builds with --check and -K can move .check directory to store nix-sandbox-build check.nix -A nondeterministic -# `100 + 4` means non-determinstic, see doc/manual/src/command-ref/status-build-failure.md +# `100 + 4` means non-determinstic, see doc/manual/source/command-ref/status-build-failure.md expectStderr 104 nix-sandbox-build check.nix -A nondeterministic --check -K > $TEST_ROOT/log grepQuietInverse 'error: renaming' $TEST_ROOT/log grepQuiet 'may not be deterministic' $TEST_ROOT/log # Test that sandboxed builds cannot write to /etc easily -# `100` means build failure without extra info, see doc/manual/src/command-ref/status-build-failure.md +# `100` means build failure without extra info, see doc/manual/source/command-ref/status-build-failure.md expectStderr 100 nix-sandbox-build -E 'with import ./config.nix; mkDerivation { name = "etc-write"; buildCommand = "echo > /etc/test"; }' | grepQuiet "/etc/test: Permission denied" @@ -56,7 +56,7 @@ testCert () { expectation=$1 # "missing" | "present" mode=$2 # "normal" | "fixed-output" certFile=$3 # a string that can be the path to a cert file - # `100` means build failure without extra info, see doc/manual/src/command-ref/status-build-failure.md + # `100` means build failure without extra info, see doc/manual/source/command-ref/status-build-failure.md [ "$mode" == fixed-output ] && ret=1 || ret=100 expectStderr $ret nix-sandbox-build linux-sandbox-cert-test.nix --argstr mode "$mode" --option ssl-cert-file "$certFile" | grepQuiet "CERT_${expectation}_IN_SANDBOX" From 379ada42bc00e3b6d0f18e1ca57d31d4fd4ee67c Mon Sep 17 00:00:00 2001 From: John Ericson Date: Thu, 10 Oct 2024 12:05:26 -0400 Subject: [PATCH 308/718] Make the subproject dir `src` again We got rid of this in c7ec33605e8c2dff0ebe40e4a1beba7a98530432 because of bug https://github.com/mesonbuild/meson/issues/13774, but in the previous commit we renamed the manual source directory, which avoids it. Now we can change it back. --- meson.build | 1 + subprojects | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 120000 subprojects diff --git a/meson.build b/meson.build index 636d38b08..97704d170 100644 --- a/meson.build +++ b/meson.build @@ -3,6 +3,7 @@ project('nix-dev-shell', 'cpp', version : files('.version'), + subproject_dir : 'src', default_options : [ 'localstatedir=/nix/var', ] diff --git a/subprojects b/subprojects deleted file mode 120000 index e8310385c..000000000 --- a/subprojects +++ /dev/null @@ -1 +0,0 @@ -src \ No newline at end of file From 188d97e1f1a6ce41f1eaed813adf878cfa6acdeb Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 15 Oct 2024 20:55:05 +0200 Subject: [PATCH 309/718] Restore input substitution The ability to substitute inputs was removed in #10612 because it was broken: with user-specified inputs containing a `narHash` attribute, substitution resulted in an input that lacked the attributes returned by the real fetcher (such as `lastModified`). To fix this, we introduce a new input attribute `final`. If `final = true`, fetching the input cannot add or change any attributes. We only attempt to substitute inputs that have `final = true`. This is implied by lock file entries; we only write a lock file if all its entries are "final". The user can specified `final = true` in `fetchTree`, in which case it is their responsibility to ensure that all attributes returned by the fetcher are included in the `fetchTree` call. For example, nix eval --impure --expr 'builtins.fetchTree { type = "github"; owner = "NixOS"; repo = "patchelf"; final = true; narHash = "sha256-FSoxTcRZMGHNJh8dNtKOkcUtjhmhU6yQXcZZfUPLhQM="; }' succeeds in a store path with the specified NAR hash exists or is substitutable, but fails with error: fetching final input '{"final":true,"narHash":"sha256-FSoxTcRZMGHNJh8dNtKOkcUtjhmhU6yQXcZZfUPLhQM=","owner":"NixOS","repo":"patchelf","type":"github"}' resulted in different input '{"final":true,"lastModified":1718457448,"narHash":"sha256-FSoxTcRZMGHNJh8dNtKOkcUtjhmhU6yQXcZZfUPLhQM=","owner":"NixOS","repo":"patchelf","rev":"a0f54334df36770b335c051e540ba40afcbf8378","type":"github"}' --- src/libexpr/call-flake.nix | 3 ++- src/libfetchers/fetchers.cc | 46 +++++++++++++++++++++++++++++++++- src/libfetchers/fetchers.hh | 33 +++++++++++++----------- src/libfetchers/path.cc | 1 + src/libflake/flake/flake.cc | 1 - src/libflake/flake/lockfile.cc | 12 +++++++-- src/libflake/flake/lockfile.hh | 4 +-- 7 files changed, 79 insertions(+), 21 deletions(-) diff --git a/src/libexpr/call-flake.nix b/src/libexpr/call-flake.nix index a411564df..c44d64885 100644 --- a/src/libexpr/call-flake.nix +++ b/src/libexpr/call-flake.nix @@ -44,7 +44,8 @@ let overrides.${key}.sourceInfo else # FIXME: remove obsolete node.info. - fetchTree (node.info or {} // removeAttrs node.locked ["dir"]); + # Note: lock file entries are always final. + fetchTree (node.info or {} // removeAttrs node.locked ["dir"] // { final = true; }); subdir = overrides.${key}.dir or node.locked.dir or ""; diff --git a/src/libfetchers/fetchers.cc b/src/libfetchers/fetchers.cc index b07e8cb6e..ff4c7567f 100644 --- a/src/libfetchers/fetchers.cc +++ b/src/libfetchers/fetchers.cc @@ -3,6 +3,7 @@ #include "source-path.hh" #include "fetch-to-store.hh" #include "json-utils.hh" +#include "store-path-accessor.hh" #include @@ -100,7 +101,7 @@ Input Input::fromAttrs(const Settings & settings, Attrs && attrs) auto allowedAttrs = inputScheme->allowedAttrs(); for (auto & [name, _] : attrs) - if (name != "type" && allowedAttrs.count(name) == 0) + if (name != "type" && name != "final" && allowedAttrs.count(name) == 0) throw Error("input attribute '%s' not supported by scheme '%s'", name, schemeName); auto res = inputScheme->inputFromAttrs(settings, attrs); @@ -145,6 +146,11 @@ bool Input::isLocked() const return scheme && scheme->isLocked(*this); } +bool Input::isFinal() const +{ + return maybeGetBoolAttr(attrs, "final").value_or(false); +} + Attrs Input::toAttrs() const { return attrs; @@ -221,6 +227,12 @@ void InputScheme::checkLocks(const Input & specified, const Input & final) const throw Error("'revCount' attribute mismatch in input '%s', expected %d", final.to_string(), *prevRevCount); } + + assert(final.isFinal()); + + if (specified.isFinal() && specified.attrs != final.attrs) + throw Error("fetching final input '%s' resulted in different input '%s'", + attrsToJSON(specified.attrs), attrsToJSON(final.attrs)); } std::pair, Input> Input::getAccessor(ref store) const @@ -244,11 +256,43 @@ std::pair, Input> Input::getAccessorUnchecked(ref sto if (!scheme) throw Error("cannot fetch unsupported input '%s'", attrsToJSON(toAttrs())); + /* The tree may already be in the Nix store, or it could be + substituted (which is often faster than fetching from the + original source). So check that. We only do this for final + inputs, otherwise there is a risk that we don't return the + same attributes (like `lastModified`) that the "real" fetcher + would return. + + FIXME: add a setting to disable this. + FIXME: substituting may be slower than fetching normally, + e.g. for fetchers like that Git that are incremental! + */ + if (isFinal() && getNarHash()) { + try { + auto storePath = computeStorePath(*store); + + store->ensurePath(storePath); + + debug("using substituted/cached input '%s' in '%s'", + to_string(), store->printStorePath(storePath)); + + auto accessor = makeStorePathAccessor(store, storePath); + + accessor->fingerprint = scheme->getFingerprint(store, *this); + + return {accessor, *this}; + } catch (Error & e) { + debug("substitution of input '%s' failed: %s", to_string(), e.what()); + } + } + auto [accessor, final] = scheme->getAccessor(store, *this); assert(!accessor->fingerprint); accessor->fingerprint = scheme->getFingerprint(store, final); + final.attrs.insert_or_assign("final", Explicit(true)); + return {accessor, std::move(final)}; } diff --git a/src/libfetchers/fetchers.hh b/src/libfetchers/fetchers.hh index a5f9bdcc6..e74625f7f 100644 --- a/src/libfetchers/fetchers.hh +++ b/src/libfetchers/fetchers.hh @@ -84,11 +84,21 @@ public: bool isDirect() const; /** - * Check whether this is a "locked" input, that is, - * one that contains a commit hash or content hash. + * Check whether this is a "locked" input, that is, it has + * attributes like a Git revision or NAR hash that uniquely + * identify its contents. */ bool isLocked() const; + /** + * Check whether this is a "final" input, meaning that fetching it + * will not add or change any attributes. For instance, a Git + * input with a `rev` attribute but without a `lastModified` + * attribute is considered locked but not final. Only "final" + * inputs can be substituted from a binary cache. + */ + bool isFinal() const; + bool operator ==(const Input & other) const noexcept; bool contains(const Input & other) const; @@ -144,6 +154,10 @@ public: /** * For locked inputs, return a string that uniquely specifies the * content of the input (typically a commit hash or content hash). + * + * Only known-equivalent inputs should return the same fingerprint. + * + * This is not a stable identifier between Nix versions, but not guaranteed to change either. */ std::optional getFingerprint(ref store) const; }; @@ -212,24 +226,15 @@ struct InputScheme */ virtual std::optional experimentalFeature() const; + /// See `Input::isDirect()`. virtual bool isDirect(const Input & input) const { return true; } - /** - * A sufficiently unique string that can be used as a cache key to identify the `input`. - * - * Only known-equivalent inputs should return the same fingerprint. - * - * This is not a stable identifier between Nix versions, but not guaranteed to change either. - */ + /// See `Input::getFingerprint()`. virtual std::optional getFingerprint(ref store, const Input & input) const { return std::nullopt; } - /** - * Return `true` if this input is considered "locked", i.e. it has - * attributes like a Git revision or NAR hash that uniquely - * identify its contents. - */ + /// See `Input::isLocked()`. virtual bool isLocked(const Input & input) const { return false; } diff --git a/src/libfetchers/path.cc b/src/libfetchers/path.cc index fca0df84b..564ad6e71 100644 --- a/src/libfetchers/path.cc +++ b/src/libfetchers/path.cc @@ -72,6 +72,7 @@ struct PathInputScheme : InputScheme auto query = attrsToQuery(input.attrs); query.erase("path"); query.erase("type"); + query.erase("final"); return ParsedURL { .scheme = "path", .path = getStrAttr(input.attrs, "path"), diff --git a/src/libflake/flake/flake.cc b/src/libflake/flake/flake.cc index d18e01464..f6f29f241 100644 --- a/src/libflake/flake/flake.cc +++ b/src/libflake/flake/flake.cc @@ -85,7 +85,6 @@ static void forceTrivialValue(EvalState & state, Value & value, const PosIdx pos state.forceValue(value, pos); } - static void expectType(EvalState & state, ValueType type, Value & value, const PosIdx pos) { diff --git a/src/libflake/flake/lockfile.cc b/src/libflake/flake/lockfile.cc index 70b60716f..f80c27acd 100644 --- a/src/libflake/flake/lockfile.cc +++ b/src/libflake/flake/lockfile.cc @@ -46,6 +46,10 @@ LockedNode::LockedNode( if (!lockedRef.input.isLocked()) throw Error("lock file contains unlocked input '%s'", fetchers::attrsToJSON(lockedRef.input.toAttrs())); + + // For backward compatibility, lock file entries are implicitly final. + assert(!lockedRef.input.attrs.contains("final")); + lockedRef.input.attrs.insert_or_assign("final", Explicit(true)); } StorePath LockedNode::computeStorePath(Store & store) const @@ -53,7 +57,6 @@ StorePath LockedNode::computeStorePath(Store & store) const return lockedRef.input.computeStorePath(store); } - static std::shared_ptr doFind(const ref & root, const InputPath & path, std::vector & visited) { auto pos = root; @@ -191,6 +194,11 @@ std::pair LockFile::toJSON() const if (auto lockedNode = node.dynamic_pointer_cast()) { n["original"] = fetchers::attrsToJSON(lockedNode->originalRef.toAttrs()); n["locked"] = fetchers::attrsToJSON(lockedNode->lockedRef.toAttrs()); + /* For backward compatibility, omit the "final" + attribute. We never allow non-final inputs in lock files + anyway. */ + assert(lockedNode->lockedRef.input.isFinal()); + n["locked"].erase("final"); if (!lockedNode->isFlake) n["flake"] = false; } @@ -239,7 +247,7 @@ std::optional LockFile::isUnlocked() const for (auto & i : nodes) { if (i == ref(root)) continue; auto node = i.dynamic_pointer_cast(); - if (node && !node->lockedRef.input.isLocked()) + if (node && (!node->lockedRef.input.isLocked() || !node->lockedRef.input.isFinal())) return node->lockedRef; } diff --git a/src/libflake/flake/lockfile.hh b/src/libflake/flake/lockfile.hh index 841931c11..a2711a516 100644 --- a/src/libflake/flake/lockfile.hh +++ b/src/libflake/flake/lockfile.hh @@ -68,8 +68,8 @@ struct LockFile std::pair to_string() const; /** - * Check whether this lock file has any unlocked inputs. If so, - * return one. + * Check whether this lock file has any unlocked or non-final + * inputs. If so, return one. */ std::optional isUnlocked() const; From e33d6f24e3267ae72dfbaa9fa45051460541afc0 Mon Sep 17 00:00:00 2001 From: Ivan Tkachev Date: Wed, 16 Oct 2024 15:24:33 +0300 Subject: [PATCH 310/718] #11704 --- src/nix/run.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/nix/run.cc b/src/nix/run.cc index 956563591..c9857e13e 100644 --- a/src/nix/run.cc +++ b/src/nix/run.cc @@ -167,10 +167,9 @@ void chrootHelper(int argc, char * * argv) /* Bind-mount realStoreDir on /nix/store. If the latter mount point doesn't already exists, we have to create a chroot environment containing the mount point and bind mounts for the - children of /. Would be nice if we could use overlayfs here, - but that doesn't work in a user namespace yet (Ubuntu has a - patch for this: - https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1478578). */ + children of /. + Overlayfs for user namespaces is fixed in Linux since ac519625ed + (v5.11, 14 February 2021) */ if (!pathExists(storeDir)) { // FIXME: Use overlayfs? @@ -206,8 +205,9 @@ void chrootHelper(int argc, char * * argv) if (chdir(cwd) == -1) throw SysError("chdir to '%s' in chroot", cwd); } else - if (mount(realStoreDir.c_str(), storeDir.c_str(), "", MS_BIND, 0) == -1) - throw SysError("mounting '%s' on '%s'", realStoreDir, storeDir); + if (mount("overlay", storeDir.c_str(), "overlay", MS_MGC_VAL, fmt("lowerdir=%s:%s", storeDir, realStoreDir).c_str()) == -1) + if (mount(realStoreDir.c_str(), storeDir.c_str(), "", MS_BIND, 0) == -1) + throw SysError("mounting '%s' on '%s'", realStoreDir, storeDir); writeFile(fs::path{"/proc/self/setgroups"}, "deny"); writeFile(fs::path{"/proc/self/uid_map"}, fmt("%d %d %d", uid, uid, 1)); From fc09815eda00e3ba9211932ab14d2bdf4feab7db Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 16 Oct 2024 15:17:38 +0200 Subject: [PATCH 311/718] Typo Co-authored-by: Cole Helbling --- src/libfetchers/fetchers.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libfetchers/fetchers.cc b/src/libfetchers/fetchers.cc index ff4c7567f..f25781a12 100644 --- a/src/libfetchers/fetchers.cc +++ b/src/libfetchers/fetchers.cc @@ -265,7 +265,7 @@ std::pair, Input> Input::getAccessorUnchecked(ref sto FIXME: add a setting to disable this. FIXME: substituting may be slower than fetching normally, - e.g. for fetchers like that Git that are incremental! + e.g. for fetchers like Git that are incremental! */ if (isFinal() && getNarHash()) { try { From ed1f9dd13f23450aad86f7687dd1b596d06ceed4 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 16 Oct 2024 15:18:23 +0200 Subject: [PATCH 312/718] Don't mark inputs as final in getAccessorUnchecked() We haven't added the narHash attribute yet at that point. And if the caller uses getAccesor() instead of fetchToStore() (e.g. in `nix registry pin`), the narHash attribute will never be added. This could lead to a mismatch. --- src/libfetchers/fetchers.cc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/libfetchers/fetchers.cc b/src/libfetchers/fetchers.cc index f25781a12..26229134d 100644 --- a/src/libfetchers/fetchers.cc +++ b/src/libfetchers/fetchers.cc @@ -185,6 +185,14 @@ std::pair Input::fetchToStore(ref store) const auto narHash = store->queryPathInfo(storePath)->narHash; final.attrs.insert_or_assign("narHash", narHash.to_string(HashFormat::SRI, true)); + // FIXME: we would like to mark inputs as final in + // getAccessorUnchecked(), but then we can't add + // narHash. Or maybe narHash should be excluded from the + // concept of "final" inputs? + final.attrs.insert_or_assign("final", Explicit(true)); + + assert(final.isFinal()); + scheme->checkLocks(*this, final); return {storePath, final}; @@ -228,8 +236,6 @@ void InputScheme::checkLocks(const Input & specified, const Input & final) const final.to_string(), *prevRevCount); } - assert(final.isFinal()); - if (specified.isFinal() && specified.attrs != final.attrs) throw Error("fetching final input '%s' resulted in different input '%s'", attrsToJSON(specified.attrs), attrsToJSON(final.attrs)); @@ -291,8 +297,6 @@ std::pair, Input> Input::getAccessorUnchecked(ref sto assert(!accessor->fingerprint); accessor->fingerprint = scheme->getFingerprint(store, final); - final.attrs.insert_or_assign("final", Explicit(true)); - return {accessor, std::move(final)}; } From 781ff7672e344c97d946b45db1bebaf85e2e92f7 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 16 Oct 2024 17:18:07 +0200 Subject: [PATCH 313/718] Add test --- tests/functional/fetchPath.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/functional/fetchPath.sh b/tests/functional/fetchPath.sh index 560a270c1..1df895b61 100755 --- a/tests/functional/fetchPath.sh +++ b/tests/functional/fetchPath.sh @@ -6,3 +6,6 @@ touch "$TEST_ROOT/foo" -t 202211111111 # We only check whether 2022-11-1* **:**:** is the last modified date since # `lastModified` is transformed into UTC in `builtins.fetchTarball`. [[ "$(nix eval --impure --raw --expr "(builtins.fetchTree \"path://$TEST_ROOT/foo\").lastModifiedDate")" =~ 2022111.* ]] + +# Check that we can override lastModified for "path:" inputs. +[[ "$(nix eval --impure --expr "(builtins.fetchTree { type = \"path\"; path = \"$TEST_ROOT/foo\"; lastModified = 123; }).lastModified")" = 123 ]] From 0e5a5303ad29b62c2acb405cd18097cae0d93ce8 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Thu, 10 Oct 2024 12:31:34 +0200 Subject: [PATCH 314/718] fix: Ignore Interrupted in recursive-nix daemon worker Otherwise, if checkInterrupt() in any of the supported store operations would catch onto a user interrupt, the exception would bubble to the thread start and be handled by std::terminate(): a crash. --- src/libstore/unix/build/local-derivation-goal.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libstore/unix/build/local-derivation-goal.cc b/src/libstore/unix/build/local-derivation-goal.cc index 0eda8455f..394eab875 100644 --- a/src/libstore/unix/build/local-derivation-goal.cc +++ b/src/libstore/unix/build/local-derivation-goal.cc @@ -65,6 +65,7 @@ #include #include "strings.hh" +#include "signals.hh" namespace nix { @@ -1579,6 +1580,8 @@ void LocalDerivationGoal::startDaemon() FdSink(remote.get()), NotTrusted, daemon::Recursive); debug("terminated daemon connection"); + } catch (const Interrupted &) { + debug("interrupted daemon connection"); } catch (SystemError &) { ignoreExceptionExceptInterrupt(); } From de41e4617523f9355fb896edcf77cc777d45b564 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Thu, 10 Oct 2024 12:38:26 +0200 Subject: [PATCH 315/718] Document recursive-nix startDaemon/stopDaemon --- src/libstore/unix/build/local-derivation-goal.hh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/libstore/unix/build/local-derivation-goal.hh b/src/libstore/unix/build/local-derivation-goal.hh index 231393308..1ea247661 100644 --- a/src/libstore/unix/build/local-derivation-goal.hh +++ b/src/libstore/unix/build/local-derivation-goal.hh @@ -225,8 +225,15 @@ struct LocalDerivationGoal : public DerivationGoal */ void writeStructuredAttrs(); + /** + * Start an in-process nix daemon thread for recursive-nix. + */ void startDaemon(); + /** + * Stop the in-process nix daemon thread. + * @see startDaemon + */ void stopDaemon(); /** From 3f9ff10786b879a02750780936b50271e675ea57 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Thu, 10 Oct 2024 12:46:36 +0200 Subject: [PATCH 316/718] ThreadPool: catch Interrupted --- src/libutil/thread-pool.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libutil/thread-pool.cc b/src/libutil/thread-pool.cc index 0355e1f07..57172da7e 100644 --- a/src/libutil/thread-pool.cc +++ b/src/libutil/thread-pool.cc @@ -110,6 +110,11 @@ void ThreadPool::doWork(bool mainThread) propagate it. */ try { std::rethrow_exception(exc); + } catch (const Interrupted &) { + // The interrupted state may be picked up multiple + // workers, which is expected, so we should ignore + // it silently and let the first one bubble up, + // rethrown via the original state->exception. } catch (std::exception & e) { if (!dynamic_cast(&e)) ignoreExceptionExceptInterrupt(); From 16320f6d24222c1cf9cb718f24628e4f1f5bf889 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Thu, 10 Oct 2024 13:08:26 +0200 Subject: [PATCH 317/718] Handle ThreadPoolShutdown with normal catch --- src/libutil/thread-pool.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libutil/thread-pool.cc b/src/libutil/thread-pool.cc index 57172da7e..cc76b1d37 100644 --- a/src/libutil/thread-pool.cc +++ b/src/libutil/thread-pool.cc @@ -115,9 +115,10 @@ void ThreadPool::doWork(bool mainThread) // workers, which is expected, so we should ignore // it silently and let the first one bubble up, // rethrown via the original state->exception. + } catch (const ThreadPoolShutDown &) { + // Similarly expected. } catch (std::exception & e) { - if (!dynamic_cast(&e)) - ignoreExceptionExceptInterrupt(); + ignoreExceptionExceptInterrupt(); } catch (...) { } } From fd8a4a86d9b6672584cb4b3d7d8d9d94790c55a3 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Thu, 10 Oct 2024 13:09:12 +0200 Subject: [PATCH 318/718] ThreadPool: don't silently ignore non-std exceptions Introduced in 8f6b347abd without explanation. Throwing anything that's not that is a programming mistake that we don't want to ignore silently. A crash would be ok, because that means we/they can fix the offending throw. --- src/libutil/thread-pool.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libutil/thread-pool.cc b/src/libutil/thread-pool.cc index cc76b1d37..75424cd0e 100644 --- a/src/libutil/thread-pool.cc +++ b/src/libutil/thread-pool.cc @@ -119,7 +119,6 @@ void ThreadPool::doWork(bool mainThread) // Similarly expected. } catch (std::exception & e) { ignoreExceptionExceptInterrupt(); - } catch (...) { } } } From ed184f0b612401c7a70a9a736ad67fa13a79a45f Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 16 Oct 2024 19:40:45 +0200 Subject: [PATCH 319/718] Typo Co-authored-by: Cole Helbling --- src/libutil/thread-pool.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libutil/thread-pool.cc b/src/libutil/thread-pool.cc index 75424cd0e..0725c1926 100644 --- a/src/libutil/thread-pool.cc +++ b/src/libutil/thread-pool.cc @@ -111,7 +111,7 @@ void ThreadPool::doWork(bool mainThread) try { std::rethrow_exception(exc); } catch (const Interrupted &) { - // The interrupted state may be picked up multiple + // The interrupted state may be picked up by multiple // workers, which is expected, so we should ignore // it silently and let the first one bubble up, // rethrown via the original state->exception. From 7bd0c70b37d624ec32dc39cc52fcbcd78bb0dab9 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 16 Oct 2024 22:03:44 +0200 Subject: [PATCH 320/718] maintainers/README.md: Remove the list of team members Let's have one canonical location for the team membership. --- maintainers/README.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/maintainers/README.md b/maintainers/README.md index b92833497..1a275d998 100644 --- a/maintainers/README.md +++ b/maintainers/README.md @@ -29,11 +29,7 @@ We aim to achieve this by improving the contributor experience and attracting mo ## Members -- Eelco Dolstra (@edolstra) – Team lead -- Valentin Gagarin (@fricklerhandwerk) -- Thomas Bereknyei (@tomberek) -- Robert Hensing (@roberth) -- John Ericson (@Ericson2314) +See https://nixos.org/community/teams/nix/ for the current team membership. The team is on Github as [@NixOS/nix-team](https://github.com/orgs/NixOS/teams/nix-team). From c196011d230fbc449afa0098196c8bed1d7478f2 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 16 Oct 2024 22:06:28 +0200 Subject: [PATCH 321/718] maintainers/onboarding: Start documenting --- maintainers/onboarding.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 maintainers/onboarding.md diff --git a/maintainers/onboarding.md b/maintainers/onboarding.md new file mode 100644 index 000000000..e750bd8a7 --- /dev/null +++ b/maintainers/onboarding.md @@ -0,0 +1,6 @@ + +# Onboarding a new team member + +- https://github.com/NixOS/nixos-homepage/ +- https://github.com/orgs/NixOS/teams/nix-team +- Matrix room From 78b5b4c105f1adb33c416889f4378cede154cf68 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 17 Oct 2024 14:12:39 +0200 Subject: [PATCH 322/718] Tarball fetcher: Fix compat with old lock files that didn't include lastModified Fixes flake-regressions/tests/DeterminateSystems/fh/0.1.10: error: fetching final input '{"final":true,"narHash":"sha256-0dZpggYjjmWEk+rGixiBHOHuQfLzEzNfrtjSig04s6Q=","rev":"9ccae1754eec0341b640d5705302ac0923d22875","revCount":1618,"type":"tarball","url":"https://api.flakehub.com/f/pinned/nix-community/fenix/0.1.1618%2Brev-9ccae1754eec0341b640d5705302ac0923d22875/018aea4c-03c9-7734-95d5-b84cc8881e3d/source.tar.gz"}' resulted in different input '{"final":true,"lastModified":1696141234,"narHash":"sha256-0dZpggYjjmWEk+rGixiBHOHuQfLzEzNfrtjSig04s6Q=","rev":"9ccae1754eec0341b640d5705302ac0923d22875","revCount":1618,"type":"tarball","url":"https://api.flakehub.com/f/pinned/nix-community/fenix/0.1.1618%2Brev-9ccae1754eec0341b640d5705302ac0923d22875/018aea4c-03c9-7734-95d5-b84cc8881e3d/source.tar.gz"}' --- src/libfetchers/tarball.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libfetchers/tarball.cc b/src/libfetchers/tarball.cc index 28574e7b1..27ad89b6e 100644 --- a/src/libfetchers/tarball.cc +++ b/src/libfetchers/tarball.cc @@ -384,7 +384,11 @@ struct TarballInputScheme : CurlInputScheme input = immutableInput; } - if (result.lastModified && !input.attrs.contains("lastModified")) + /* If we got a lastModified and the input is not final and + doesn't have one, then return it. Note that we don't do + this if the input is final for compatibility with old lock + files that didn't include lastModified. */ + if (result.lastModified && !_input.isFinal() && !input.attrs.contains("lastModified")) input.attrs.insert_or_assign("lastModified", uint64_t(result.lastModified)); input.attrs.insert_or_assign("narHash", From 7d1f7f8d59fe1a9bbed3adc09a76de07ba84e8e8 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 17 Oct 2024 16:20:08 +0200 Subject: [PATCH 323/718] Tarball fetcher: Handle lock files that *do* contain lastModified Fixes flake-regressions/tests/DeterminateSystems/eva/0.1.0: error: 'lastModified' attribute mismatch in input 'https://api.flakehub.com/f/pinned/ipetkov/crane/0.14.1/018ac45c-ff5e-7076-b956-d478a0336516/source.tar.gz?narHash=sha256-mnE14re43v3/Jc50Jv0BKPMtEk7FEtDSligP6B5HwlI%3D', expected 1695511445 --- src/libfetchers/fetchers.cc | 4 ++-- src/libfetchers/tarball.cc | 12 +++++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/libfetchers/fetchers.cc b/src/libfetchers/fetchers.cc index 26229134d..9717533d6 100644 --- a/src/libfetchers/fetchers.cc +++ b/src/libfetchers/fetchers.cc @@ -220,8 +220,8 @@ void InputScheme::checkLocks(const Input & specified, const Input & final) const if (auto prevLastModified = specified.getLastModified()) { if (final.getLastModified() != prevLastModified) - throw Error("'lastModified' attribute mismatch in input '%s', expected %d", - final.to_string(), *prevLastModified); + throw Error("'lastModified' attribute mismatch in input '%s', expected %d, got %d", + final.to_string(), *prevLastModified, final.getLastModified().value_or(-1)); } if (auto prevRev = specified.getRev()) { diff --git a/src/libfetchers/tarball.cc b/src/libfetchers/tarball.cc index 27ad89b6e..e723d3061 100644 --- a/src/libfetchers/tarball.cc +++ b/src/libfetchers/tarball.cc @@ -384,11 +384,13 @@ struct TarballInputScheme : CurlInputScheme input = immutableInput; } - /* If we got a lastModified and the input is not final and - doesn't have one, then return it. Note that we don't do - this if the input is final for compatibility with old lock - files that didn't include lastModified. */ - if (result.lastModified && !_input.isFinal() && !input.attrs.contains("lastModified")) + /* If we got a lastModified, then return it. But for + compatibility with old lock files that didn't include + lastModified, don't do this if the original input was final + and didn't contain a lastModified. */ + if (result.lastModified + && !input.attrs.contains("lastModified") + && (!_input.isFinal() || _input.attrs.contains("lastModified"))) input.attrs.insert_or_assign("lastModified", uint64_t(result.lastModified)); input.attrs.insert_or_assign("narHash", From e65510da56246d0ef52bd83893bb55ae7cb3348d Mon Sep 17 00:00:00 2001 From: John Ericson Date: Thu, 10 Oct 2024 14:56:26 -0400 Subject: [PATCH 324/718] Move unit tests to the location Meson expects them to be Everything that is a separate subproject should live in the subprojects directory. Progress on #2503 This reverts commit 451f8a8c19e2ab95999553f5bf3a1fb056877933. --- .github/labeler.yml | 2 +- .gitignore | 10 +- Makefile | 16 +-- doc/manual/source/development/testing.md | 4 +- maintainers/flake-module.nix | 120 +++++++++--------- meson.build | 16 +-- package.nix | 2 - packaging/components.nix | 16 +-- src/internal-api-docs/doxygen.cfg.in | 16 +-- src/libexpr-test-support/.version | 1 + src/libexpr-test-support/build-utils-meson | 1 + .../libexpr-test-support}/local.mk | 0 .../libexpr-test-support}/meson.build | 0 .../libexpr-test-support}/package.nix | 6 +- .../libexpr-test-support}/tests/libexpr.hh | 0 .../tests/nix_api_expr.hh | 0 .../tests/value/context.cc | 0 .../tests/value/context.hh | 0 src/libexpr-tests/.version | 1 + src/libexpr-tests/build-utils-meson | 1 + .../libexpr-tests}/data/.gitkeep | 0 .../libexpr-tests}/derived-path.cc | 0 .../libexpr-tests}/error_traces.cc | 0 .../libexpr => src/libexpr-tests}/eval.cc | 0 .../libexpr => src/libexpr-tests}/json.cc | 0 .../libexpr => src/libexpr-tests}/local.mk | 6 +- .../libexpr => src/libexpr-tests}/main.cc | 0 .../libexpr => src/libexpr-tests}/meson.build | 0 .../libexpr-tests}/nix_api_expr.cc | 0 .../libexpr-tests}/nix_api_external.cc | 0 .../libexpr-tests}/nix_api_value.cc | 0 .../libexpr => src/libexpr-tests}/package.nix | 6 +- .../libexpr => src/libexpr-tests}/primops.cc | 0 .../libexpr-tests}/search-path.cc | 0 .../libexpr => src/libexpr-tests}/trivial.cc | 0 .../libexpr-tests}/value/context.cc | 0 .../libexpr-tests}/value/print.cc | 0 .../libexpr-tests}/value/value.cc | 0 src/libfetchers-tests/.version | 1 + src/libfetchers-tests/build-utils-meson | 1 + .../data/public-key/defaultType.json | 0 .../data/public-key/noRoundTrip.json | 0 .../data/public-key/simple.json | 0 .../libfetchers-tests}/git-utils.cc | 0 .../libfetchers-tests}/local.mk | 4 +- .../libfetchers-tests}/meson.build | 0 .../libfetchers-tests}/package.nix | 6 +- .../libfetchers-tests}/public-key.cc | 0 src/libflake-tests/.version | 1 + src/libflake-tests/build-utils-meson | 1 + .../libflake-tests}/data/.gitkeep | 0 .../libflake-tests}/flakeref.cc | 0 .../libflake => src/libflake-tests}/local.mk | 6 +- .../libflake-tests}/meson.build | 0 .../libflake-tests}/package.nix | 6 +- .../libflake-tests}/url-name.cc | 0 src/libstore-test-support/.version | 1 + src/libstore-test-support/build-utils-meson | 1 + .../libstore-test-support}/local.mk | 0 .../libstore-test-support}/meson.build | 0 .../libstore-test-support}/package.nix | 6 +- .../tests/derived-path.cc | 0 .../tests/derived-path.hh | 0 .../libstore-test-support}/tests/libstore.hh | 0 .../tests/nix_api_store.hh | 0 .../tests/outputs-spec.cc | 0 .../tests/outputs-spec.hh | 0 .../libstore-test-support}/tests/path.cc | 0 .../libstore-test-support}/tests/path.hh | 0 .../libstore-test-support}/tests/protocol.hh | 0 src/libstore-tests/.version | 1 + src/libstore-tests/build-utils-meson | 1 + .../libstore-tests}/common-protocol.cc | 0 .../libstore-tests}/content-address.cc | 0 .../data/common-protocol/content-address.bin | Bin .../data/common-protocol/drv-output.bin | Bin .../optional-content-address.bin | Bin .../common-protocol/optional-store-path.bin | Bin .../data/common-protocol/realisation.bin | Bin .../data/common-protocol/set.bin | Bin .../data/common-protocol/store-path.bin | Bin .../data/common-protocol/string.bin | Bin .../data/common-protocol/vector.bin | Bin .../advanced-attributes-defaults.drv | 1 + .../advanced-attributes-defaults.json | 0 ...d-attributes-structured-attrs-defaults.drv | 1 + ...-attributes-structured-attrs-defaults.json | 0 .../advanced-attributes-structured-attrs.drv | 1 + .../advanced-attributes-structured-attrs.json | 0 .../data/derivation/advanced-attributes.drv | 1 + .../derivation/bad-old-version-dyn-deps.drv | 0 .../data/derivation/bad-version.drv | 0 .../data/derivation/dynDerivationDeps.drv | 0 .../data/derivation/dynDerivationDeps.json | 0 .../data/derivation/output-caFixedFlat.json | 0 .../data/derivation/output-caFixedNAR.json | 0 .../data/derivation/output-caFixedText.json | 0 .../data/derivation/output-caFloating.json | 0 .../data/derivation/output-deferred.json | 0 .../data/derivation/output-impure.json | 0 .../derivation/output-inputAddressed.json | 0 .../data/derivation/simple.drv | 0 .../data/derivation/simple.json | 0 .../libstore-tests}/data/machines/bad_format | 0 .../libstore-tests}/data/machines/valid | 0 .../libstore-tests}/data/nar-info/impure.json | 0 .../libstore-tests}/data/nar-info/pure.json | 0 .../data/path-info/empty_impure.json | 0 .../data/path-info/empty_pure.json | 0 .../data/path-info/impure.json | 0 .../libstore-tests}/data/path-info/pure.json | 0 .../data/serve-protocol/build-options-2.1.bin | Bin .../data/serve-protocol/build-options-2.2.bin | Bin .../data/serve-protocol/build-options-2.3.bin | Bin .../data/serve-protocol/build-options-2.7.bin | Bin .../data/serve-protocol/build-result-2.2.bin | Bin .../data/serve-protocol/build-result-2.3.bin | Bin .../data/serve-protocol/build-result-2.6.bin | Bin .../data/serve-protocol/content-address.bin | Bin .../data/serve-protocol/drv-output.bin | Bin .../serve-protocol/handshake-to-client.bin | Bin .../optional-content-address.bin | Bin .../serve-protocol/optional-store-path.bin | Bin .../data/serve-protocol/realisation.bin | Bin .../data/serve-protocol/set.bin | Bin .../data/serve-protocol/store-path.bin | Bin .../data/serve-protocol/string.bin | Bin .../unkeyed-valid-path-info-2.3.bin | Bin .../unkeyed-valid-path-info-2.4.bin | Bin .../data/serve-protocol/vector.bin | Bin .../data/store-reference/auto.txt | 0 .../data/store-reference/auto_param.txt | 0 .../data/store-reference/local_1.txt | 0 .../data/store-reference/local_2.txt | 0 .../store-reference/local_shorthand_1.txt | 0 .../store-reference/local_shorthand_2.txt | 0 .../data/store-reference/ssh.txt | 0 .../data/store-reference/unix.txt | 0 .../data/store-reference/unix_shorthand.txt | 0 .../data/worker-protocol/build-mode.bin | Bin .../worker-protocol/build-result-1.27.bin | Bin .../worker-protocol/build-result-1.28.bin | Bin .../worker-protocol/build-result-1.29.bin | Bin .../worker-protocol/build-result-1.37.bin | Bin .../client-handshake-info_1_30.bin | 0 .../client-handshake-info_1_33.bin | Bin .../client-handshake-info_1_35.bin | Bin .../data/worker-protocol/content-address.bin | Bin .../worker-protocol/derived-path-1.29.bin | Bin .../worker-protocol/derived-path-1.30.bin | Bin .../data/worker-protocol/drv-output.bin | Bin .../worker-protocol/handshake-to-client.bin | Bin .../keyed-build-result-1.29.bin | Bin .../optional-content-address.bin | Bin .../worker-protocol/optional-store-path.bin | Bin .../worker-protocol/optional-trusted-flag.bin | Bin .../data/worker-protocol/realisation.bin | Bin .../data/worker-protocol/set.bin | Bin .../data/worker-protocol/store-path.bin | Bin .../data/worker-protocol/string.bin | Bin .../unkeyed-valid-path-info-1.15.bin | Bin .../worker-protocol/valid-path-info-1.15.bin | Bin .../worker-protocol/valid-path-info-1.16.bin | Bin .../data/worker-protocol/vector.bin | Bin .../derivation-advanced-attrs.cc | 0 .../libstore-tests}/derivation.cc | 0 .../libstore-tests}/derived-path.cc | 0 .../libstore-tests}/downstream-placeholder.cc | 0 .../http-binary-cache-store.cc | 0 .../libstore-tests}/legacy-ssh-store.cc | 0 .../local-binary-cache-store.cc | 0 .../libstore-tests}/local-overlay-store.cc | 0 .../libstore-tests}/local-store.cc | 0 .../libstore => src/libstore-tests}/local.mk | 4 +- .../libstore-tests}/machines.cc | 0 .../libstore-tests}/meson.build | 0 .../libstore-tests}/nar-info-disk-cache.cc | 0 .../libstore-tests}/nar-info.cc | 0 .../libstore-tests}/nix_api_store.cc | 0 .../libstore-tests}/outputs-spec.cc | 0 .../libstore-tests}/package.nix | 10 +- .../libstore-tests}/path-info.cc | 0 .../libstore => src/libstore-tests}/path.cc | 0 .../libstore-tests}/references.cc | 0 .../libstore-tests}/s3-binary-cache-store.cc | 0 .../libstore-tests}/serve-protocol.cc | 0 .../libstore-tests}/ssh-store.cc | 0 .../libstore-tests}/store-reference.cc | 0 .../libstore-tests}/uds-remote-store.cc | 0 .../libstore-tests}/worker-protocol.cc | 0 src/libutil-test-support/.version | 1 + src/libutil-test-support/build-utils-meson | 1 + .../libutil-test-support}/local.mk | 0 .../libutil-test-support}/meson.build | 0 .../libutil-test-support}/package.nix | 6 +- .../tests/characterization.hh | 0 .../tests/gtest-with-params.hh | 0 .../libutil-test-support}/tests/hash.cc | 0 .../libutil-test-support}/tests/hash.hh | 0 .../tests/nix_api_util.hh | 0 .../tests/string_callback.cc | 0 .../tests/string_callback.hh | 0 .../tests/tracing-file-system-object-sink.cc | 0 .../tests/tracing-file-system-object-sink.hh | 0 src/libutil-tests/.version | 1 + .../libutil => src/libutil-tests}/args.cc | 0 src/libutil-tests/build-utils-meson | 1 + .../libutil-tests}/canon-path.cc | 0 .../libutil-tests}/checked-arithmetic.cc | 0 .../libutil-tests}/chunked-vector.cc | 0 .../libutil => src/libutil-tests}/closure.cc | 0 .../libutil-tests}/compression.cc | 0 .../libutil => src/libutil-tests}/config.cc | 0 .../libutil-tests}/data/git/check-data.sh | 0 .../data/git/hello-world-blob.bin | Bin .../libutil-tests}/data/git/hello-world.bin | Bin .../libutil-tests}/data/git/tree.bin | Bin .../libutil-tests}/data/git/tree.txt | 0 .../libutil-tests}/executable-path.cc | 0 .../libutil-tests}/file-content-address.cc | 0 .../libutil-tests}/file-system.cc | 0 .../unit/libutil => src/libutil-tests}/git.cc | 2 +- .../libutil => src/libutil-tests}/hash.cc | 0 .../libutil => src/libutil-tests}/hilite.cc | 0 .../libutil-tests}/json-utils.cc | 0 .../libutil => src/libutil-tests}/local.mk | 2 +- .../libutil => src/libutil-tests}/logging.cc | 0 .../libutil-tests}/lru-cache.cc | 0 .../libutil => src/libutil-tests}/meson.build | 0 .../libutil-tests}/nix_api_util.cc | 0 .../libutil => src/libutil-tests}/package.nix | 6 +- .../libutil => src/libutil-tests}/pool.cc | 0 .../libutil => src/libutil-tests}/position.cc | 0 .../libutil-tests}/processes.cc | 0 .../libutil-tests}/references.cc | 0 .../libutil => src/libutil-tests}/spawn.cc | 0 .../libutil => src/libutil-tests}/strings.cc | 0 .../libutil-tests}/suggestions.cc | 0 .../libutil => src/libutil-tests}/terminal.cc | 0 .../unit/libutil => src/libutil-tests}/url.cc | 0 .../libutil => src/libutil-tests}/util.cc | 0 .../libutil-tests}/xml-writer.cc | 0 src/nix-expr-test-support | 1 - src/nix-expr-tests | 1 - src/nix-fetchers-tests | 1 - src/nix-flake-tests | 1 - src/nix-store-test-support | 1 - src/nix-store-tests | 1 - src/nix-util-test-support | 1 - src/nix-util-tests | 1 - tests/unit/libexpr-support/.version | 1 - tests/unit/libexpr-support/build-utils-meson | 1 - tests/unit/libexpr/.version | 1 - tests/unit/libexpr/build-utils-meson | 1 - tests/unit/libfetchers/.version | 1 - tests/unit/libfetchers/build-utils-meson | 1 - tests/unit/libflake/.version | 1 - tests/unit/libflake/build-utils-meson | 1 - tests/unit/libstore-support/.version | 1 - tests/unit/libstore-support/build-utils-meson | 1 - tests/unit/libstore/.version | 1 - tests/unit/libstore/build-utils-meson | 1 - .../advanced-attributes-defaults.drv | 1 - ...d-attributes-structured-attrs-defaults.drv | 1 - .../advanced-attributes-structured-attrs.drv | 1 - .../data/derivation/advanced-attributes.drv | 1 - tests/unit/libutil-support/.version | 1 - tests/unit/libutil-support/build-utils-meson | 1 - tests/unit/libutil/.version | 1 - tests/unit/libutil/build-utils-meson | 1 - 270 files changed, 158 insertions(+), 168 deletions(-) create mode 120000 src/libexpr-test-support/.version create mode 120000 src/libexpr-test-support/build-utils-meson rename {tests/unit/libexpr-support => src/libexpr-test-support}/local.mk (100%) rename {tests/unit/libexpr-support => src/libexpr-test-support}/meson.build (100%) rename {tests/unit/libexpr-support => src/libexpr-test-support}/package.nix (91%) rename {tests/unit/libexpr-support => src/libexpr-test-support}/tests/libexpr.hh (100%) rename {tests/unit/libexpr-support => src/libexpr-test-support}/tests/nix_api_expr.hh (100%) rename {tests/unit/libexpr-support => src/libexpr-test-support}/tests/value/context.cc (100%) rename {tests/unit/libexpr-support => src/libexpr-test-support}/tests/value/context.hh (100%) create mode 120000 src/libexpr-tests/.version create mode 120000 src/libexpr-tests/build-utils-meson rename {tests/unit/libexpr => src/libexpr-tests}/data/.gitkeep (100%) rename {tests/unit/libexpr => src/libexpr-tests}/derived-path.cc (100%) rename {tests/unit/libexpr => src/libexpr-tests}/error_traces.cc (100%) rename {tests/unit/libexpr => src/libexpr-tests}/eval.cc (100%) rename {tests/unit/libexpr => src/libexpr-tests}/json.cc (100%) rename {tests/unit/libexpr => src/libexpr-tests}/local.mk (91%) rename {tests/unit/libexpr => src/libexpr-tests}/main.cc (100%) rename {tests/unit/libexpr => src/libexpr-tests}/meson.build (100%) rename {tests/unit/libexpr => src/libexpr-tests}/nix_api_expr.cc (100%) rename {tests/unit/libexpr => src/libexpr-tests}/nix_api_external.cc (100%) rename {tests/unit/libexpr => src/libexpr-tests}/nix_api_value.cc (100%) rename {tests/unit/libexpr => src/libexpr-tests}/package.nix (94%) rename {tests/unit/libexpr => src/libexpr-tests}/primops.cc (100%) rename {tests/unit/libexpr => src/libexpr-tests}/search-path.cc (100%) rename {tests/unit/libexpr => src/libexpr-tests}/trivial.cc (100%) rename {tests/unit/libexpr => src/libexpr-tests}/value/context.cc (100%) rename {tests/unit/libexpr => src/libexpr-tests}/value/print.cc (100%) rename {tests/unit/libexpr => src/libexpr-tests}/value/value.cc (100%) create mode 120000 src/libfetchers-tests/.version create mode 120000 src/libfetchers-tests/build-utils-meson rename {tests/unit/libfetchers => src/libfetchers-tests}/data/public-key/defaultType.json (100%) rename {tests/unit/libfetchers => src/libfetchers-tests}/data/public-key/noRoundTrip.json (100%) rename {tests/unit/libfetchers => src/libfetchers-tests}/data/public-key/simple.json (100%) rename {tests/unit/libfetchers => src/libfetchers-tests}/git-utils.cc (100%) rename {tests/unit/libfetchers => src/libfetchers-tests}/local.mk (93%) rename {tests/unit/libfetchers => src/libfetchers-tests}/meson.build (100%) rename {tests/unit/libfetchers => src/libfetchers-tests}/package.nix (94%) rename {tests/unit/libfetchers => src/libfetchers-tests}/public-key.cc (100%) create mode 120000 src/libflake-tests/.version create mode 120000 src/libflake-tests/build-utils-meson rename {tests/unit/libflake => src/libflake-tests}/data/.gitkeep (100%) rename {tests/unit/libflake => src/libflake-tests}/flakeref.cc (100%) rename {tests/unit/libflake => src/libflake-tests}/local.mk (90%) rename {tests/unit/libflake => src/libflake-tests}/meson.build (100%) rename {tests/unit/libflake => src/libflake-tests}/package.nix (94%) rename {tests/unit/libflake => src/libflake-tests}/url-name.cc (100%) create mode 120000 src/libstore-test-support/.version create mode 120000 src/libstore-test-support/build-utils-meson rename {tests/unit/libstore-support => src/libstore-test-support}/local.mk (100%) rename {tests/unit/libstore-support => src/libstore-test-support}/meson.build (100%) rename {tests/unit/libstore-support => src/libstore-test-support}/package.nix (91%) rename {tests/unit/libstore-support => src/libstore-test-support}/tests/derived-path.cc (100%) rename {tests/unit/libstore-support => src/libstore-test-support}/tests/derived-path.hh (100%) rename {tests/unit/libstore-support => src/libstore-test-support}/tests/libstore.hh (100%) rename {tests/unit/libstore-support => src/libstore-test-support}/tests/nix_api_store.hh (100%) rename {tests/unit/libstore-support => src/libstore-test-support}/tests/outputs-spec.cc (100%) rename {tests/unit/libstore-support => src/libstore-test-support}/tests/outputs-spec.hh (100%) rename {tests/unit/libstore-support => src/libstore-test-support}/tests/path.cc (100%) rename {tests/unit/libstore-support => src/libstore-test-support}/tests/path.hh (100%) rename {tests/unit/libstore-support => src/libstore-test-support}/tests/protocol.hh (100%) create mode 120000 src/libstore-tests/.version create mode 120000 src/libstore-tests/build-utils-meson rename {tests/unit/libstore => src/libstore-tests}/common-protocol.cc (100%) rename {tests/unit/libstore => src/libstore-tests}/content-address.cc (100%) rename {tests/unit/libstore => src/libstore-tests}/data/common-protocol/content-address.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/common-protocol/drv-output.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/common-protocol/optional-content-address.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/common-protocol/optional-store-path.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/common-protocol/realisation.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/common-protocol/set.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/common-protocol/store-path.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/common-protocol/string.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/common-protocol/vector.bin (100%) create mode 120000 src/libstore-tests/data/derivation/advanced-attributes-defaults.drv rename {tests/unit/libstore => src/libstore-tests}/data/derivation/advanced-attributes-defaults.json (100%) create mode 120000 src/libstore-tests/data/derivation/advanced-attributes-structured-attrs-defaults.drv rename {tests/unit/libstore => src/libstore-tests}/data/derivation/advanced-attributes-structured-attrs-defaults.json (100%) create mode 120000 src/libstore-tests/data/derivation/advanced-attributes-structured-attrs.drv rename {tests/unit/libstore => src/libstore-tests}/data/derivation/advanced-attributes-structured-attrs.json (100%) create mode 120000 src/libstore-tests/data/derivation/advanced-attributes.drv rename {tests/unit/libstore => src/libstore-tests}/data/derivation/bad-old-version-dyn-deps.drv (100%) rename {tests/unit/libstore => src/libstore-tests}/data/derivation/bad-version.drv (100%) rename {tests/unit/libstore => src/libstore-tests}/data/derivation/dynDerivationDeps.drv (100%) rename {tests/unit/libstore => src/libstore-tests}/data/derivation/dynDerivationDeps.json (100%) rename {tests/unit/libstore => src/libstore-tests}/data/derivation/output-caFixedFlat.json (100%) rename {tests/unit/libstore => src/libstore-tests}/data/derivation/output-caFixedNAR.json (100%) rename {tests/unit/libstore => src/libstore-tests}/data/derivation/output-caFixedText.json (100%) rename {tests/unit/libstore => src/libstore-tests}/data/derivation/output-caFloating.json (100%) rename {tests/unit/libstore => src/libstore-tests}/data/derivation/output-deferred.json (100%) rename {tests/unit/libstore => src/libstore-tests}/data/derivation/output-impure.json (100%) rename {tests/unit/libstore => src/libstore-tests}/data/derivation/output-inputAddressed.json (100%) rename {tests/unit/libstore => src/libstore-tests}/data/derivation/simple.drv (100%) rename {tests/unit/libstore => src/libstore-tests}/data/derivation/simple.json (100%) rename {tests/unit/libstore => src/libstore-tests}/data/machines/bad_format (100%) rename {tests/unit/libstore => src/libstore-tests}/data/machines/valid (100%) rename {tests/unit/libstore => src/libstore-tests}/data/nar-info/impure.json (100%) rename {tests/unit/libstore => src/libstore-tests}/data/nar-info/pure.json (100%) rename {tests/unit/libstore => src/libstore-tests}/data/path-info/empty_impure.json (100%) rename {tests/unit/libstore => src/libstore-tests}/data/path-info/empty_pure.json (100%) rename {tests/unit/libstore => src/libstore-tests}/data/path-info/impure.json (100%) rename {tests/unit/libstore => src/libstore-tests}/data/path-info/pure.json (100%) rename {tests/unit/libstore => src/libstore-tests}/data/serve-protocol/build-options-2.1.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/serve-protocol/build-options-2.2.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/serve-protocol/build-options-2.3.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/serve-protocol/build-options-2.7.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/serve-protocol/build-result-2.2.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/serve-protocol/build-result-2.3.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/serve-protocol/build-result-2.6.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/serve-protocol/content-address.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/serve-protocol/drv-output.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/serve-protocol/handshake-to-client.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/serve-protocol/optional-content-address.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/serve-protocol/optional-store-path.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/serve-protocol/realisation.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/serve-protocol/set.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/serve-protocol/store-path.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/serve-protocol/string.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/serve-protocol/unkeyed-valid-path-info-2.3.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/serve-protocol/unkeyed-valid-path-info-2.4.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/serve-protocol/vector.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/store-reference/auto.txt (100%) rename {tests/unit/libstore => src/libstore-tests}/data/store-reference/auto_param.txt (100%) rename {tests/unit/libstore => src/libstore-tests}/data/store-reference/local_1.txt (100%) rename {tests/unit/libstore => src/libstore-tests}/data/store-reference/local_2.txt (100%) rename {tests/unit/libstore => src/libstore-tests}/data/store-reference/local_shorthand_1.txt (100%) rename {tests/unit/libstore => src/libstore-tests}/data/store-reference/local_shorthand_2.txt (100%) rename {tests/unit/libstore => src/libstore-tests}/data/store-reference/ssh.txt (100%) rename {tests/unit/libstore => src/libstore-tests}/data/store-reference/unix.txt (100%) rename {tests/unit/libstore => src/libstore-tests}/data/store-reference/unix_shorthand.txt (100%) rename {tests/unit/libstore => src/libstore-tests}/data/worker-protocol/build-mode.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/worker-protocol/build-result-1.27.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/worker-protocol/build-result-1.28.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/worker-protocol/build-result-1.29.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/worker-protocol/build-result-1.37.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/worker-protocol/client-handshake-info_1_30.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/worker-protocol/client-handshake-info_1_33.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/worker-protocol/client-handshake-info_1_35.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/worker-protocol/content-address.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/worker-protocol/derived-path-1.29.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/worker-protocol/derived-path-1.30.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/worker-protocol/drv-output.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/worker-protocol/handshake-to-client.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/worker-protocol/keyed-build-result-1.29.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/worker-protocol/optional-content-address.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/worker-protocol/optional-store-path.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/worker-protocol/optional-trusted-flag.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/worker-protocol/realisation.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/worker-protocol/set.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/worker-protocol/store-path.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/worker-protocol/string.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/worker-protocol/unkeyed-valid-path-info-1.15.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/worker-protocol/valid-path-info-1.15.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/worker-protocol/valid-path-info-1.16.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/data/worker-protocol/vector.bin (100%) rename {tests/unit/libstore => src/libstore-tests}/derivation-advanced-attrs.cc (100%) rename {tests/unit/libstore => src/libstore-tests}/derivation.cc (100%) rename {tests/unit/libstore => src/libstore-tests}/derived-path.cc (100%) rename {tests/unit/libstore => src/libstore-tests}/downstream-placeholder.cc (100%) rename {tests/unit/libstore => src/libstore-tests}/http-binary-cache-store.cc (100%) rename {tests/unit/libstore => src/libstore-tests}/legacy-ssh-store.cc (100%) rename {tests/unit/libstore => src/libstore-tests}/local-binary-cache-store.cc (100%) rename {tests/unit/libstore => src/libstore-tests}/local-overlay-store.cc (100%) rename {tests/unit/libstore => src/libstore-tests}/local-store.cc (100%) rename {tests/unit/libstore => src/libstore-tests}/local.mk (92%) rename {tests/unit/libstore => src/libstore-tests}/machines.cc (100%) rename {tests/unit/libstore => src/libstore-tests}/meson.build (100%) rename {tests/unit/libstore => src/libstore-tests}/nar-info-disk-cache.cc (100%) rename {tests/unit/libstore => src/libstore-tests}/nar-info.cc (100%) rename {tests/unit/libstore => src/libstore-tests}/nix_api_store.cc (100%) rename {tests/unit/libstore => src/libstore-tests}/outputs-spec.cc (100%) rename {tests/unit/libstore => src/libstore-tests}/package.nix (90%) rename {tests/unit/libstore => src/libstore-tests}/path-info.cc (100%) rename {tests/unit/libstore => src/libstore-tests}/path.cc (100%) rename {tests/unit/libstore => src/libstore-tests}/references.cc (100%) rename {tests/unit/libstore => src/libstore-tests}/s3-binary-cache-store.cc (100%) rename {tests/unit/libstore => src/libstore-tests}/serve-protocol.cc (100%) rename {tests/unit/libstore => src/libstore-tests}/ssh-store.cc (100%) rename {tests/unit/libstore => src/libstore-tests}/store-reference.cc (100%) rename {tests/unit/libstore => src/libstore-tests}/uds-remote-store.cc (100%) rename {tests/unit/libstore => src/libstore-tests}/worker-protocol.cc (100%) create mode 120000 src/libutil-test-support/.version create mode 120000 src/libutil-test-support/build-utils-meson rename {tests/unit/libutil-support => src/libutil-test-support}/local.mk (100%) rename {tests/unit/libutil-support => src/libutil-test-support}/meson.build (100%) rename {tests/unit/libutil-support => src/libutil-test-support}/package.nix (90%) rename {tests/unit/libutil-support => src/libutil-test-support}/tests/characterization.hh (100%) rename {tests/unit/libutil-support => src/libutil-test-support}/tests/gtest-with-params.hh (100%) rename {tests/unit/libutil-support => src/libutil-test-support}/tests/hash.cc (100%) rename {tests/unit/libutil-support => src/libutil-test-support}/tests/hash.hh (100%) rename {tests/unit/libutil-support => src/libutil-test-support}/tests/nix_api_util.hh (100%) rename {tests/unit/libutil-support => src/libutil-test-support}/tests/string_callback.cc (100%) rename {tests/unit/libutil-support => src/libutil-test-support}/tests/string_callback.hh (100%) rename {tests/unit/libutil-support => src/libutil-test-support}/tests/tracing-file-system-object-sink.cc (100%) rename {tests/unit/libutil-support => src/libutil-test-support}/tests/tracing-file-system-object-sink.hh (100%) create mode 120000 src/libutil-tests/.version rename {tests/unit/libutil => src/libutil-tests}/args.cc (100%) create mode 120000 src/libutil-tests/build-utils-meson rename {tests/unit/libutil => src/libutil-tests}/canon-path.cc (100%) rename {tests/unit/libutil => src/libutil-tests}/checked-arithmetic.cc (100%) rename {tests/unit/libutil => src/libutil-tests}/chunked-vector.cc (100%) rename {tests/unit/libutil => src/libutil-tests}/closure.cc (100%) rename {tests/unit/libutil => src/libutil-tests}/compression.cc (100%) rename {tests/unit/libutil => src/libutil-tests}/config.cc (100%) rename {tests/unit/libutil => src/libutil-tests}/data/git/check-data.sh (100%) rename {tests/unit/libutil => src/libutil-tests}/data/git/hello-world-blob.bin (100%) rename {tests/unit/libutil => src/libutil-tests}/data/git/hello-world.bin (100%) rename {tests/unit/libutil => src/libutil-tests}/data/git/tree.bin (100%) rename {tests/unit/libutil => src/libutil-tests}/data/git/tree.txt (100%) rename {tests/unit/libutil => src/libutil-tests}/executable-path.cc (100%) rename {tests/unit/libutil => src/libutil-tests}/file-content-address.cc (100%) rename {tests/unit/libutil => src/libutil-tests}/file-system.cc (100%) rename {tests/unit/libutil => src/libutil-tests}/git.cc (99%) rename {tests/unit/libutil => src/libutil-tests}/hash.cc (100%) rename {tests/unit/libutil => src/libutil-tests}/hilite.cc (100%) rename {tests/unit/libutil => src/libutil-tests}/json-utils.cc (100%) rename {tests/unit/libutil => src/libutil-tests}/local.mk (96%) rename {tests/unit/libutil => src/libutil-tests}/logging.cc (100%) rename {tests/unit/libutil => src/libutil-tests}/lru-cache.cc (100%) rename {tests/unit/libutil => src/libutil-tests}/meson.build (100%) rename {tests/unit/libutil => src/libutil-tests}/nix_api_util.cc (100%) rename {tests/unit/libutil => src/libutil-tests}/package.nix (94%) rename {tests/unit/libutil => src/libutil-tests}/pool.cc (100%) rename {tests/unit/libutil => src/libutil-tests}/position.cc (100%) rename {tests/unit/libutil => src/libutil-tests}/processes.cc (100%) rename {tests/unit/libutil => src/libutil-tests}/references.cc (100%) rename {tests/unit/libutil => src/libutil-tests}/spawn.cc (100%) rename {tests/unit/libutil => src/libutil-tests}/strings.cc (100%) rename {tests/unit/libutil => src/libutil-tests}/suggestions.cc (100%) rename {tests/unit/libutil => src/libutil-tests}/terminal.cc (100%) rename {tests/unit/libutil => src/libutil-tests}/url.cc (100%) rename {tests/unit/libutil => src/libutil-tests}/util.cc (100%) rename {tests/unit/libutil => src/libutil-tests}/xml-writer.cc (100%) delete mode 120000 src/nix-expr-test-support delete mode 120000 src/nix-expr-tests delete mode 120000 src/nix-fetchers-tests delete mode 120000 src/nix-flake-tests delete mode 120000 src/nix-store-test-support delete mode 120000 src/nix-store-tests delete mode 120000 src/nix-util-test-support delete mode 120000 src/nix-util-tests delete mode 120000 tests/unit/libexpr-support/.version delete mode 120000 tests/unit/libexpr-support/build-utils-meson delete mode 120000 tests/unit/libexpr/.version delete mode 120000 tests/unit/libexpr/build-utils-meson delete mode 120000 tests/unit/libfetchers/.version delete mode 120000 tests/unit/libfetchers/build-utils-meson delete mode 120000 tests/unit/libflake/.version delete mode 120000 tests/unit/libflake/build-utils-meson delete mode 120000 tests/unit/libstore-support/.version delete mode 120000 tests/unit/libstore-support/build-utils-meson delete mode 120000 tests/unit/libstore/.version delete mode 120000 tests/unit/libstore/build-utils-meson delete mode 120000 tests/unit/libstore/data/derivation/advanced-attributes-defaults.drv delete mode 120000 tests/unit/libstore/data/derivation/advanced-attributes-structured-attrs-defaults.drv delete mode 120000 tests/unit/libstore/data/derivation/advanced-attributes-structured-attrs.drv delete mode 120000 tests/unit/libstore/data/derivation/advanced-attributes.drv delete mode 120000 tests/unit/libutil-support/.version delete mode 120000 tests/unit/libutil-support/build-utils-meson delete mode 120000 tests/unit/libutil/.version delete mode 120000 tests/unit/libutil/build-utils-meson diff --git a/.github/labeler.yml b/.github/labeler.yml index 9f7cb76c5..97ca9284d 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -1,7 +1,7 @@ "c api": - changed-files: - any-glob-to-any-file: "src/lib*-c/**/*" - - any-glob-to-any-file: "test/unit/**/nix_api_*" + - any-glob-to-any-file: "src/*test*/**/nix_api_*" - any-glob-to-any-file: "doc/external-api/**/*" "contributor-experience": diff --git a/.gitignore b/.gitignore index 8d6693984..11a80ab5b 100644 --- a/.gitignore +++ b/.gitignore @@ -49,22 +49,22 @@ perl/Makefile.config /src/libexpr/parser-tab.output /src/libexpr/nix.tbl /src/libexpr/tests -/tests/unit/libexpr/libnixexpr-tests +/src/libexpr-tests/libnixexpr-tests # /src/libfetchers -/tests/unit/libfetchers/libnixfetchers-tests +/src/libfetchers-tests/libnixfetchers-tests # /src/libflake -/tests/unit/libflake/libnixflake-tests +/src/libflake-tests/libnixflake-tests # /src/libstore/ *.gen.* /src/libstore/tests -/tests/unit/libstore/libnixstore-tests +/src/libstore-tests/libnixstore-tests # /src/libutil/ /src/libutil/tests -/tests/unit/libutil/libnixutil-tests +/src/libutil-tests/libnixutil-tests /src/nix/nix diff --git a/Makefile b/Makefile index dbf510a3e..4d70be0e8 100644 --- a/Makefile +++ b/Makefile @@ -40,14 +40,14 @@ endif ifeq ($(ENABLE_UNIT_TESTS), yes) makefiles += \ - tests/unit/libutil/local.mk \ - tests/unit/libutil-support/local.mk \ - tests/unit/libstore/local.mk \ - tests/unit/libstore-support/local.mk \ - tests/unit/libfetchers/local.mk \ - tests/unit/libexpr/local.mk \ - tests/unit/libexpr-support/local.mk \ - tests/unit/libflake/local.mk + src/libutil-tests/local.mk \ + src/libutil-test-support/local.mk \ + src/libstore-tests/local.mk \ + src/libstore-test-support/local.mk \ + src/libfetchers-tests/local.mk \ + src/libexpr-tests/local.mk \ + src/libexpr-test-support/local.mk \ + src/libflake-tests/local.mk endif ifeq ($(ENABLE_FUNCTIONAL_TESTS), yes) diff --git a/doc/manual/source/development/testing.md b/doc/manual/source/development/testing.md index 0df72cc38..9d228fd16 100644 --- a/doc/manual/source/development/testing.md +++ b/doc/manual/source/development/testing.md @@ -60,10 +60,10 @@ The unit tests are defined using the [googletest] and [rapidcheck] frameworks. > ``` The tests for each Nix library (`libnixexpr`, `libnixstore`, etc..) live inside a directory `src/${library_name_without-nix}-test`. -Given an interface (header) and implementation pair in the original library, say, `src/libexpr/value/context.{hh,cc}`, we write tests for it in `src/nix-expr-tests/value/context.cc`, and (possibly) declare/define additional interfaces for testing purposes in `src/nix-expr-test-support/tests/value/context.{hh,cc}`. +Given an interface (header) and implementation pair in the original library, say, `src/libexpr/value/context.{hh,cc}`, we write tests for it in `src/libexpr-tests/value/context.cc`, and (possibly) declare/define additional interfaces for testing purposes in `src/libexpr-test-support/tests/value/context.{hh,cc}`. Data for unit tests is stored in a `data` subdir of the directory for each unit test executable. -For example, `libnixstore` code is in `src/libstore`, and its test data is in `src/nix-store-tests/data`. +For example, `libnixstore` code is in `src/libstore`, and its test data is in `src/libstore-tests/data`. The path to the `src/${library_name_without-nix}-test/data` directory is passed to the unit test executable with the environment variable `_NIX_TEST_UNIT_DATA`. Note that each executable only gets the data for its tests. diff --git a/maintainers/flake-module.nix b/maintainers/flake-module.nix index fb286208d..78c36d6b6 100644 --- a/maintainers/flake-module.nix +++ b/maintainers/flake-module.nix @@ -15,7 +15,7 @@ excludes = [ # We don't want to format test data # ''tests/(?!nixos/).*\.nix'' - ''^tests/unit/[^/]*/data/.*$'' + ''^src/[^/]*-tests/data/.*$'' # Don't format vendored code ''^doc/manual/redirects\.js$'' @@ -427,64 +427,64 @@ ''^tests/nixos/ca-fd-leak/sender\.c'' ''^tests/nixos/ca-fd-leak/smuggler\.c'' ''^tests/nixos/user-sandboxing/attacker\.c'' - ''^tests/unit/libexpr-support/tests/libexpr\.hh'' - ''^tests/unit/libexpr-support/tests/value/context\.cc'' - ''^tests/unit/libexpr-support/tests/value/context\.hh'' - ''^tests/unit/libexpr/derived-path\.cc'' - ''^tests/unit/libexpr/error_traces\.cc'' - ''^tests/unit/libexpr/eval\.cc'' - ''^tests/unit/libexpr/json\.cc'' - ''^tests/unit/libexpr/main\.cc'' - ''^tests/unit/libexpr/primops\.cc'' - ''^tests/unit/libexpr/search-path\.cc'' - ''^tests/unit/libexpr/trivial\.cc'' - ''^tests/unit/libexpr/value/context\.cc'' - ''^tests/unit/libexpr/value/print\.cc'' - ''^tests/unit/libfetchers/public-key\.cc'' - ''^tests/unit/libflake/flakeref\.cc'' - ''^tests/unit/libflake/url-name\.cc'' - ''^tests/unit/libstore-support/tests/derived-path\.cc'' - ''^tests/unit/libstore-support/tests/derived-path\.hh'' - ''^tests/unit/libstore-support/tests/nix_api_store\.hh'' - ''^tests/unit/libstore-support/tests/outputs-spec\.cc'' - ''^tests/unit/libstore-support/tests/outputs-spec\.hh'' - ''^tests/unit/libstore-support/tests/path\.cc'' - ''^tests/unit/libstore-support/tests/path\.hh'' - ''^tests/unit/libstore-support/tests/protocol\.hh'' - ''^tests/unit/libstore/common-protocol\.cc'' - ''^tests/unit/libstore/content-address\.cc'' - ''^tests/unit/libstore/derivation\.cc'' - ''^tests/unit/libstore/derived-path\.cc'' - ''^tests/unit/libstore/downstream-placeholder\.cc'' - ''^tests/unit/libstore/machines\.cc'' - ''^tests/unit/libstore/nar-info-disk-cache\.cc'' - ''^tests/unit/libstore/nar-info\.cc'' - ''^tests/unit/libstore/outputs-spec\.cc'' - ''^tests/unit/libstore/path-info\.cc'' - ''^tests/unit/libstore/path\.cc'' - ''^tests/unit/libstore/serve-protocol\.cc'' - ''^tests/unit/libstore/worker-protocol\.cc'' - ''^tests/unit/libutil-support/tests/characterization\.hh'' - ''^tests/unit/libutil-support/tests/hash\.cc'' - ''^tests/unit/libutil-support/tests/hash\.hh'' - ''^tests/unit/libutil/args\.cc'' - ''^tests/unit/libutil/canon-path\.cc'' - ''^tests/unit/libutil/chunked-vector\.cc'' - ''^tests/unit/libutil/closure\.cc'' - ''^tests/unit/libutil/compression\.cc'' - ''^tests/unit/libutil/config\.cc'' - ''^tests/unit/libutil/file-content-address\.cc'' - ''^tests/unit/libutil/git\.cc'' - ''^tests/unit/libutil/hash\.cc'' - ''^tests/unit/libutil/hilite\.cc'' - ''^tests/unit/libutil/json-utils\.cc'' - ''^tests/unit/libutil/logging\.cc'' - ''^tests/unit/libutil/lru-cache\.cc'' - ''^tests/unit/libutil/pool\.cc'' - ''^tests/unit/libutil/references\.cc'' - ''^tests/unit/libutil/suggestions\.cc'' - ''^tests/unit/libutil/url\.cc'' - ''^tests/unit/libutil/xml-writer\.cc'' + ''^src/libexpr-test-support/tests/libexpr\.hh'' + ''^src/libexpr-test-support/tests/value/context\.cc'' + ''^src/libexpr-test-support/tests/value/context\.hh'' + ''^src/libexpr-tests/derived-path\.cc'' + ''^src/libexpr-tests/error_traces\.cc'' + ''^src/libexpr-tests/eval\.cc'' + ''^src/libexpr-tests/json\.cc'' + ''^src/libexpr-tests/main\.cc'' + ''^src/libexpr-tests/primops\.cc'' + ''^src/libexpr-tests/search-path\.cc'' + ''^src/libexpr-tests/trivial\.cc'' + ''^src/libexpr-tests/value/context\.cc'' + ''^src/libexpr-tests/value/print\.cc'' + ''^src/libfetchers-tests/public-key\.cc'' + ''^src/libflake-tests/flakeref\.cc'' + ''^src/libflake-tests/url-name\.cc'' + ''^src/libstore-test-support/tests/derived-path\.cc'' + ''^src/libstore-test-support/tests/derived-path\.hh'' + ''^src/libstore-test-support/tests/nix_api_store\.hh'' + ''^src/libstore-test-support/tests/outputs-spec\.cc'' + ''^src/libstore-test-support/tests/outputs-spec\.hh'' + ''^src/libstore-test-support/tests/path\.cc'' + ''^src/libstore-test-support/tests/path\.hh'' + ''^src/libstore-test-support/tests/protocol\.hh'' + ''^src/libstore-tests/common-protocol\.cc'' + ''^src/libstore-tests/content-address\.cc'' + ''^src/libstore-tests/derivation\.cc'' + ''^src/libstore-tests/derived-path\.cc'' + ''^src/libstore-tests/downstream-placeholder\.cc'' + ''^src/libstore-tests/machines\.cc'' + ''^src/libstore-tests/nar-info-disk-cache\.cc'' + ''^src/libstore-tests/nar-info\.cc'' + ''^src/libstore-tests/outputs-spec\.cc'' + ''^src/libstore-tests/path-info\.cc'' + ''^src/libstore-tests/path\.cc'' + ''^src/libstore-tests/serve-protocol\.cc'' + ''^src/libstore-tests/worker-protocol\.cc'' + ''^src/libutil-test-support/tests/characterization\.hh'' + ''^src/libutil-test-support/tests/hash\.cc'' + ''^src/libutil-test-support/tests/hash\.hh'' + ''^src/libutil-tests/args\.cc'' + ''^src/libutil-tests/canon-path\.cc'' + ''^src/libutil-tests/chunked-vector\.cc'' + ''^src/libutil-tests/closure\.cc'' + ''^src/libutil-tests/compression\.cc'' + ''^src/libutil-tests/config\.cc'' + ''^src/libutil-tests/file-content-address\.cc'' + ''^src/libutil-tests/git\.cc'' + ''^src/libutil-tests/hash\.cc'' + ''^src/libutil-tests/hilite\.cc'' + ''^src/libutil-tests/json-utils\.cc'' + ''^src/libutil-tests/logging\.cc'' + ''^src/libutil-tests/lru-cache\.cc'' + ''^src/libutil-tests/pool\.cc'' + ''^src/libutil-tests/references\.cc'' + ''^src/libutil-tests/suggestions\.cc'' + ''^src/libutil-tests/url\.cc'' + ''^src/libutil-tests/xml-writer\.cc'' ]; }; shellcheck = { @@ -650,7 +650,7 @@ ''^tests/functional/user-envs\.sh$'' ''^tests/functional/why-depends\.sh$'' ''^tests/functional/zstd\.sh$'' - ''^tests/unit/libutil/data/git/check-data\.sh$'' + ''^src/libutil-tests/data/git/check-data\.sh$'' ]; }; # TODO: nixfmt, https://github.com/NixOS/nixfmt/issues/153 diff --git a/meson.build b/meson.build index 97704d170..d68db0a0d 100644 --- a/meson.build +++ b/meson.build @@ -40,12 +40,12 @@ if not meson.is_cross_build() endif # Testing -subproject('nix-util-test-support') -subproject('nix-util-tests') -subproject('nix-store-test-support') -subproject('nix-store-tests') -subproject('nix-fetchers-tests') -subproject('nix-expr-test-support') -subproject('nix-expr-tests') -subproject('nix-flake-tests') +subproject('libutil-test-support') +subproject('libutil-tests') +subproject('libstore-test-support') +subproject('libstore-tests') +subproject('libfetchers-tests') +subproject('libexpr-test-support') +subproject('libexpr-tests') +subproject('libflake-tests') subproject('nix-functional-tests') diff --git a/package.nix b/package.nix index 8ab184667..00621d475 100644 --- a/package.nix +++ b/package.nix @@ -176,8 +176,6 @@ in { ./scripts/local.mk ] ++ lib.optionals enableManual [ ./doc/manual - ] ++ lib.optionals buildUnitTests [ - ./tests/unit ] ++ lib.optionals doInstallCheck [ ./tests/functional ])); diff --git a/packaging/components.nix b/packaging/components.nix index 4c18dc6a3..5cc0be784 100644 --- a/packaging/components.nix +++ b/packaging/components.nix @@ -32,24 +32,24 @@ in nix-util = callPackage ../src/libutil/package.nix { }; nix-util-c = callPackage ../src/libutil-c/package.nix { }; - nix-util-test-support = callPackage ../tests/unit/libutil-support/package.nix { }; - nix-util-tests = callPackage ../tests/unit/libutil/package.nix { }; + nix-util-test-support = callPackage ../src/libutil-test-support/package.nix { }; + nix-util-tests = callPackage ../src/libutil-tests/package.nix { }; nix-store = callPackage ../src/libstore/package.nix { }; nix-store-c = callPackage ../src/libstore-c/package.nix { }; - nix-store-test-support = callPackage ../tests/unit/libstore-support/package.nix { }; - nix-store-tests = callPackage ../tests/unit/libstore/package.nix { }; + nix-store-test-support = callPackage ../src/libstore-test-support/package.nix { }; + nix-store-tests = callPackage ../src/libstore-tests/package.nix { }; nix-fetchers = callPackage ../src/libfetchers/package.nix { }; - nix-fetchers-tests = callPackage ../tests/unit/libfetchers/package.nix { }; + nix-fetchers-tests = callPackage ../src/libfetchers-tests/package.nix { }; nix-expr = callPackage ../src/libexpr/package.nix { }; nix-expr-c = callPackage ../src/libexpr-c/package.nix { }; - nix-expr-test-support = callPackage ../tests/unit/libexpr-support/package.nix { }; - nix-expr-tests = callPackage ../tests/unit/libexpr/package.nix { }; + nix-expr-test-support = callPackage ../src/libexpr-test-support/package.nix { }; + nix-expr-tests = callPackage ../src/libexpr-tests/package.nix { }; nix-flake = callPackage ../src/libflake/package.nix { }; - nix-flake-tests = callPackage ../tests/unit/libflake/package.nix { }; + nix-flake-tests = callPackage ../src/libflake-tests/package.nix { }; nix-main = callPackage ../src/libmain/package.nix { }; nix-main-c = callPackage ../src/libmain-c/package.nix { }; diff --git a/src/internal-api-docs/doxygen.cfg.in b/src/internal-api-docs/doxygen.cfg.in index f1ef75b38..86c64a396 100644 --- a/src/internal-api-docs/doxygen.cfg.in +++ b/src/internal-api-docs/doxygen.cfg.in @@ -41,21 +41,21 @@ INPUT = \ @src@/libcmd \ @src@/libexpr \ @src@/libexpr/flake \ - @src@/nix-expr-tests \ - @src@/nix-expr-tests/value \ - @src@/nix-expr-test-support/test \ - @src@/nix-expr-test-support/test/value \ + @src@/libexpr-tests \ + @src@/libexpr-tests/value \ + @src@/libexpr-test-support/test \ + @src@/libexpr-test-support/test/value \ @src@/libexpr/value \ @src@/libfetchers \ @src@/libmain \ @src@/libstore \ @src@/libstore/build \ @src@/libstore/builtins \ - @src@/nix-store-tests \ - @src@/nix-store-test-support/test \ + @src@/libstore-tests \ + @src@/libstore-test-support/test \ @src@/libutil \ - @src@/nix-util-tests \ - @src@/nix-util-test-support/test \ + @src@/libutil-tests \ + @src@/libutil-test-support/test \ @src@/nix \ @src@/nix-env \ @src@/nix-store diff --git a/src/libexpr-test-support/.version b/src/libexpr-test-support/.version new file mode 120000 index 000000000..b7badcd0c --- /dev/null +++ b/src/libexpr-test-support/.version @@ -0,0 +1 @@ +../../.version \ No newline at end of file diff --git a/src/libexpr-test-support/build-utils-meson b/src/libexpr-test-support/build-utils-meson new file mode 120000 index 000000000..5fff21bab --- /dev/null +++ b/src/libexpr-test-support/build-utils-meson @@ -0,0 +1 @@ +../../build-utils-meson \ No newline at end of file diff --git a/tests/unit/libexpr-support/local.mk b/src/libexpr-test-support/local.mk similarity index 100% rename from tests/unit/libexpr-support/local.mk rename to src/libexpr-test-support/local.mk diff --git a/tests/unit/libexpr-support/meson.build b/src/libexpr-test-support/meson.build similarity index 100% rename from tests/unit/libexpr-support/meson.build rename to src/libexpr-test-support/meson.build diff --git a/tests/unit/libexpr-support/package.nix b/src/libexpr-test-support/package.nix similarity index 91% rename from tests/unit/libexpr-support/package.nix rename to src/libexpr-test-support/package.nix index 234d83730..bcf6118e0 100644 --- a/tests/unit/libexpr-support/package.nix +++ b/src/libexpr-test-support/package.nix @@ -22,9 +22,9 @@ mkMesonLibrary (finalAttrs: { workDir = ./.; fileset = fileset.unions [ - ../../../build-utils-meson + ../../build-utils-meson ./build-utils-meson - ../../../.version + ../../.version ./.version ./meson.build # ./meson.options @@ -43,7 +43,7 @@ mkMesonLibrary (finalAttrs: { # Do the meson utils, without modification. '' chmod u+w ./.version - echo ${version} > ../../../.version + echo ${version} > ../../.version ''; mesonFlags = [ diff --git a/tests/unit/libexpr-support/tests/libexpr.hh b/src/libexpr-test-support/tests/libexpr.hh similarity index 100% rename from tests/unit/libexpr-support/tests/libexpr.hh rename to src/libexpr-test-support/tests/libexpr.hh diff --git a/tests/unit/libexpr-support/tests/nix_api_expr.hh b/src/libexpr-test-support/tests/nix_api_expr.hh similarity index 100% rename from tests/unit/libexpr-support/tests/nix_api_expr.hh rename to src/libexpr-test-support/tests/nix_api_expr.hh diff --git a/tests/unit/libexpr-support/tests/value/context.cc b/src/libexpr-test-support/tests/value/context.cc similarity index 100% rename from tests/unit/libexpr-support/tests/value/context.cc rename to src/libexpr-test-support/tests/value/context.cc diff --git a/tests/unit/libexpr-support/tests/value/context.hh b/src/libexpr-test-support/tests/value/context.hh similarity index 100% rename from tests/unit/libexpr-support/tests/value/context.hh rename to src/libexpr-test-support/tests/value/context.hh diff --git a/src/libexpr-tests/.version b/src/libexpr-tests/.version new file mode 120000 index 000000000..b7badcd0c --- /dev/null +++ b/src/libexpr-tests/.version @@ -0,0 +1 @@ +../../.version \ No newline at end of file diff --git a/src/libexpr-tests/build-utils-meson b/src/libexpr-tests/build-utils-meson new file mode 120000 index 000000000..5fff21bab --- /dev/null +++ b/src/libexpr-tests/build-utils-meson @@ -0,0 +1 @@ +../../build-utils-meson \ No newline at end of file diff --git a/tests/unit/libexpr/data/.gitkeep b/src/libexpr-tests/data/.gitkeep similarity index 100% rename from tests/unit/libexpr/data/.gitkeep rename to src/libexpr-tests/data/.gitkeep diff --git a/tests/unit/libexpr/derived-path.cc b/src/libexpr-tests/derived-path.cc similarity index 100% rename from tests/unit/libexpr/derived-path.cc rename to src/libexpr-tests/derived-path.cc diff --git a/tests/unit/libexpr/error_traces.cc b/src/libexpr-tests/error_traces.cc similarity index 100% rename from tests/unit/libexpr/error_traces.cc rename to src/libexpr-tests/error_traces.cc diff --git a/tests/unit/libexpr/eval.cc b/src/libexpr-tests/eval.cc similarity index 100% rename from tests/unit/libexpr/eval.cc rename to src/libexpr-tests/eval.cc diff --git a/tests/unit/libexpr/json.cc b/src/libexpr-tests/json.cc similarity index 100% rename from tests/unit/libexpr/json.cc rename to src/libexpr-tests/json.cc diff --git a/tests/unit/libexpr/local.mk b/src/libexpr-tests/local.mk similarity index 91% rename from tests/unit/libexpr/local.mk rename to src/libexpr-tests/local.mk index 1617e2823..79583a9ee 100644 --- a/tests/unit/libexpr/local.mk +++ b/src/libexpr-tests/local.mk @@ -20,9 +20,9 @@ libexpr-tests_SOURCES := \ $(wildcard $(d)/flake/*.cc) libexpr-tests_EXTRA_INCLUDES = \ - -I tests/unit/libexpr-support \ - -I tests/unit/libstore-support \ - -I tests/unit/libutil-support \ + -I src/libexpr-test-support \ + -I src/libstore-test-support \ + -I src/libutil-test-support \ $(INCLUDE_libexpr) \ $(INCLUDE_libexprc) \ $(INCLUDE_libfetchers) \ diff --git a/tests/unit/libexpr/main.cc b/src/libexpr-tests/main.cc similarity index 100% rename from tests/unit/libexpr/main.cc rename to src/libexpr-tests/main.cc diff --git a/tests/unit/libexpr/meson.build b/src/libexpr-tests/meson.build similarity index 100% rename from tests/unit/libexpr/meson.build rename to src/libexpr-tests/meson.build diff --git a/tests/unit/libexpr/nix_api_expr.cc b/src/libexpr-tests/nix_api_expr.cc similarity index 100% rename from tests/unit/libexpr/nix_api_expr.cc rename to src/libexpr-tests/nix_api_expr.cc diff --git a/tests/unit/libexpr/nix_api_external.cc b/src/libexpr-tests/nix_api_external.cc similarity index 100% rename from tests/unit/libexpr/nix_api_external.cc rename to src/libexpr-tests/nix_api_external.cc diff --git a/tests/unit/libexpr/nix_api_value.cc b/src/libexpr-tests/nix_api_value.cc similarity index 100% rename from tests/unit/libexpr/nix_api_value.cc rename to src/libexpr-tests/nix_api_value.cc diff --git a/tests/unit/libexpr/package.nix b/src/libexpr-tests/package.nix similarity index 94% rename from tests/unit/libexpr/package.nix rename to src/libexpr-tests/package.nix index 1d99b581c..959d6b84e 100644 --- a/tests/unit/libexpr/package.nix +++ b/src/libexpr-tests/package.nix @@ -27,9 +27,9 @@ mkMesonExecutable (finalAttrs: { workDir = ./.; fileset = fileset.unions [ - ../../../build-utils-meson + ../../build-utils-meson ./build-utils-meson - ../../../.version + ../../.version ./.version ./meson.build # ./meson.options @@ -50,7 +50,7 @@ mkMesonExecutable (finalAttrs: { # Do the meson utils, without modification. '' chmod u+w ./.version - echo ${version} > ../../../.version + echo ${version} > ../../.version ''; mesonFlags = [ diff --git a/tests/unit/libexpr/primops.cc b/src/libexpr-tests/primops.cc similarity index 100% rename from tests/unit/libexpr/primops.cc rename to src/libexpr-tests/primops.cc diff --git a/tests/unit/libexpr/search-path.cc b/src/libexpr-tests/search-path.cc similarity index 100% rename from tests/unit/libexpr/search-path.cc rename to src/libexpr-tests/search-path.cc diff --git a/tests/unit/libexpr/trivial.cc b/src/libexpr-tests/trivial.cc similarity index 100% rename from tests/unit/libexpr/trivial.cc rename to src/libexpr-tests/trivial.cc diff --git a/tests/unit/libexpr/value/context.cc b/src/libexpr-tests/value/context.cc similarity index 100% rename from tests/unit/libexpr/value/context.cc rename to src/libexpr-tests/value/context.cc diff --git a/tests/unit/libexpr/value/print.cc b/src/libexpr-tests/value/print.cc similarity index 100% rename from tests/unit/libexpr/value/print.cc rename to src/libexpr-tests/value/print.cc diff --git a/tests/unit/libexpr/value/value.cc b/src/libexpr-tests/value/value.cc similarity index 100% rename from tests/unit/libexpr/value/value.cc rename to src/libexpr-tests/value/value.cc diff --git a/src/libfetchers-tests/.version b/src/libfetchers-tests/.version new file mode 120000 index 000000000..b7badcd0c --- /dev/null +++ b/src/libfetchers-tests/.version @@ -0,0 +1 @@ +../../.version \ No newline at end of file diff --git a/src/libfetchers-tests/build-utils-meson b/src/libfetchers-tests/build-utils-meson new file mode 120000 index 000000000..5fff21bab --- /dev/null +++ b/src/libfetchers-tests/build-utils-meson @@ -0,0 +1 @@ +../../build-utils-meson \ No newline at end of file diff --git a/tests/unit/libfetchers/data/public-key/defaultType.json b/src/libfetchers-tests/data/public-key/defaultType.json similarity index 100% rename from tests/unit/libfetchers/data/public-key/defaultType.json rename to src/libfetchers-tests/data/public-key/defaultType.json diff --git a/tests/unit/libfetchers/data/public-key/noRoundTrip.json b/src/libfetchers-tests/data/public-key/noRoundTrip.json similarity index 100% rename from tests/unit/libfetchers/data/public-key/noRoundTrip.json rename to src/libfetchers-tests/data/public-key/noRoundTrip.json diff --git a/tests/unit/libfetchers/data/public-key/simple.json b/src/libfetchers-tests/data/public-key/simple.json similarity index 100% rename from tests/unit/libfetchers/data/public-key/simple.json rename to src/libfetchers-tests/data/public-key/simple.json diff --git a/tests/unit/libfetchers/git-utils.cc b/src/libfetchers-tests/git-utils.cc similarity index 100% rename from tests/unit/libfetchers/git-utils.cc rename to src/libfetchers-tests/git-utils.cc diff --git a/tests/unit/libfetchers/local.mk b/src/libfetchers-tests/local.mk similarity index 93% rename from tests/unit/libfetchers/local.mk rename to src/libfetchers-tests/local.mk index 30aa142a5..5c90f1fc7 100644 --- a/tests/unit/libfetchers/local.mk +++ b/src/libfetchers-tests/local.mk @@ -17,8 +17,8 @@ endif libfetchers-tests_SOURCES := $(wildcard $(d)/*.cc) libfetchers-tests_EXTRA_INCLUDES = \ - -I tests/unit/libstore-support \ - -I tests/unit/libutil-support \ + -I src/libstore-test-support \ + -I src/libutil-test-support \ $(INCLUDE_libfetchers) \ $(INCLUDE_libstore) \ $(INCLUDE_libutil) diff --git a/tests/unit/libfetchers/meson.build b/src/libfetchers-tests/meson.build similarity index 100% rename from tests/unit/libfetchers/meson.build rename to src/libfetchers-tests/meson.build diff --git a/tests/unit/libfetchers/package.nix b/src/libfetchers-tests/package.nix similarity index 94% rename from tests/unit/libfetchers/package.nix rename to src/libfetchers-tests/package.nix index ed27b4021..7b2ba8f2c 100644 --- a/tests/unit/libfetchers/package.nix +++ b/src/libfetchers-tests/package.nix @@ -26,9 +26,9 @@ mkMesonExecutable (finalAttrs: { workDir = ./.; fileset = fileset.unions [ - ../../../build-utils-meson + ../../build-utils-meson ./build-utils-meson - ../../../.version + ../../.version ./.version ./meson.build # ./meson.options @@ -48,7 +48,7 @@ mkMesonExecutable (finalAttrs: { # Do the meson utils, without modification. '' chmod u+w ./.version - echo ${version} > ../../../.version + echo ${version} > ../../.version ''; mesonFlags = [ diff --git a/tests/unit/libfetchers/public-key.cc b/src/libfetchers-tests/public-key.cc similarity index 100% rename from tests/unit/libfetchers/public-key.cc rename to src/libfetchers-tests/public-key.cc diff --git a/src/libflake-tests/.version b/src/libflake-tests/.version new file mode 120000 index 000000000..b7badcd0c --- /dev/null +++ b/src/libflake-tests/.version @@ -0,0 +1 @@ +../../.version \ No newline at end of file diff --git a/src/libflake-tests/build-utils-meson b/src/libflake-tests/build-utils-meson new file mode 120000 index 000000000..5fff21bab --- /dev/null +++ b/src/libflake-tests/build-utils-meson @@ -0,0 +1 @@ +../../build-utils-meson \ No newline at end of file diff --git a/tests/unit/libflake/data/.gitkeep b/src/libflake-tests/data/.gitkeep similarity index 100% rename from tests/unit/libflake/data/.gitkeep rename to src/libflake-tests/data/.gitkeep diff --git a/tests/unit/libflake/flakeref.cc b/src/libflake-tests/flakeref.cc similarity index 100% rename from tests/unit/libflake/flakeref.cc rename to src/libflake-tests/flakeref.cc diff --git a/tests/unit/libflake/local.mk b/src/libflake-tests/local.mk similarity index 90% rename from tests/unit/libflake/local.mk rename to src/libflake-tests/local.mk index 590bcf7c0..8599b43f6 100644 --- a/tests/unit/libflake/local.mk +++ b/src/libflake-tests/local.mk @@ -20,9 +20,9 @@ libflake-tests_SOURCES := \ $(wildcard $(d)/flake/*.cc) libflake-tests_EXTRA_INCLUDES = \ - -I tests/unit/libflake-support \ - -I tests/unit/libstore-support \ - -I tests/unit/libutil-support \ + -I src/libflake-test-support \ + -I src/libstore-test-support \ + -I src/libutil-test-support \ $(INCLUDE_libflake) \ $(INCLUDE_libexpr) \ $(INCLUDE_libfetchers) \ diff --git a/tests/unit/libflake/meson.build b/src/libflake-tests/meson.build similarity index 100% rename from tests/unit/libflake/meson.build rename to src/libflake-tests/meson.build diff --git a/tests/unit/libflake/package.nix b/src/libflake-tests/package.nix similarity index 94% rename from tests/unit/libflake/package.nix rename to src/libflake-tests/package.nix index eaf946202..67e716979 100644 --- a/tests/unit/libflake/package.nix +++ b/src/libflake-tests/package.nix @@ -26,9 +26,9 @@ mkMesonExecutable (finalAttrs: { workDir = ./.; fileset = fileset.unions [ - ../../../build-utils-meson + ../../build-utils-meson ./build-utils-meson - ../../../.version + ../../.version ./.version ./meson.build # ./meson.options @@ -48,7 +48,7 @@ mkMesonExecutable (finalAttrs: { # Do the meson utils, without modification. '' chmod u+w ./.version - echo ${version} > ../../../.version + echo ${version} > ../../.version ''; mesonFlags = [ diff --git a/tests/unit/libflake/url-name.cc b/src/libflake-tests/url-name.cc similarity index 100% rename from tests/unit/libflake/url-name.cc rename to src/libflake-tests/url-name.cc diff --git a/src/libstore-test-support/.version b/src/libstore-test-support/.version new file mode 120000 index 000000000..b7badcd0c --- /dev/null +++ b/src/libstore-test-support/.version @@ -0,0 +1 @@ +../../.version \ No newline at end of file diff --git a/src/libstore-test-support/build-utils-meson b/src/libstore-test-support/build-utils-meson new file mode 120000 index 000000000..5fff21bab --- /dev/null +++ b/src/libstore-test-support/build-utils-meson @@ -0,0 +1 @@ +../../build-utils-meson \ No newline at end of file diff --git a/tests/unit/libstore-support/local.mk b/src/libstore-test-support/local.mk similarity index 100% rename from tests/unit/libstore-support/local.mk rename to src/libstore-test-support/local.mk diff --git a/tests/unit/libstore-support/meson.build b/src/libstore-test-support/meson.build similarity index 100% rename from tests/unit/libstore-support/meson.build rename to src/libstore-test-support/meson.build diff --git a/tests/unit/libstore-support/package.nix b/src/libstore-test-support/package.nix similarity index 91% rename from tests/unit/libstore-support/package.nix rename to src/libstore-test-support/package.nix index b6106b727..48f8b5e6b 100644 --- a/tests/unit/libstore-support/package.nix +++ b/src/libstore-test-support/package.nix @@ -22,9 +22,9 @@ mkMesonLibrary (finalAttrs: { workDir = ./.; fileset = fileset.unions [ - ../../../build-utils-meson + ../../build-utils-meson ./build-utils-meson - ../../../.version + ../../.version ./.version ./meson.build # ./meson.options @@ -43,7 +43,7 @@ mkMesonLibrary (finalAttrs: { # Do the meson utils, without modification. '' chmod u+w ./.version - echo ${version} > ../../../.version + echo ${version} > ../../.version ''; mesonFlags = [ diff --git a/tests/unit/libstore-support/tests/derived-path.cc b/src/libstore-test-support/tests/derived-path.cc similarity index 100% rename from tests/unit/libstore-support/tests/derived-path.cc rename to src/libstore-test-support/tests/derived-path.cc diff --git a/tests/unit/libstore-support/tests/derived-path.hh b/src/libstore-test-support/tests/derived-path.hh similarity index 100% rename from tests/unit/libstore-support/tests/derived-path.hh rename to src/libstore-test-support/tests/derived-path.hh diff --git a/tests/unit/libstore-support/tests/libstore.hh b/src/libstore-test-support/tests/libstore.hh similarity index 100% rename from tests/unit/libstore-support/tests/libstore.hh rename to src/libstore-test-support/tests/libstore.hh diff --git a/tests/unit/libstore-support/tests/nix_api_store.hh b/src/libstore-test-support/tests/nix_api_store.hh similarity index 100% rename from tests/unit/libstore-support/tests/nix_api_store.hh rename to src/libstore-test-support/tests/nix_api_store.hh diff --git a/tests/unit/libstore-support/tests/outputs-spec.cc b/src/libstore-test-support/tests/outputs-spec.cc similarity index 100% rename from tests/unit/libstore-support/tests/outputs-spec.cc rename to src/libstore-test-support/tests/outputs-spec.cc diff --git a/tests/unit/libstore-support/tests/outputs-spec.hh b/src/libstore-test-support/tests/outputs-spec.hh similarity index 100% rename from tests/unit/libstore-support/tests/outputs-spec.hh rename to src/libstore-test-support/tests/outputs-spec.hh diff --git a/tests/unit/libstore-support/tests/path.cc b/src/libstore-test-support/tests/path.cc similarity index 100% rename from tests/unit/libstore-support/tests/path.cc rename to src/libstore-test-support/tests/path.cc diff --git a/tests/unit/libstore-support/tests/path.hh b/src/libstore-test-support/tests/path.hh similarity index 100% rename from tests/unit/libstore-support/tests/path.hh rename to src/libstore-test-support/tests/path.hh diff --git a/tests/unit/libstore-support/tests/protocol.hh b/src/libstore-test-support/tests/protocol.hh similarity index 100% rename from tests/unit/libstore-support/tests/protocol.hh rename to src/libstore-test-support/tests/protocol.hh diff --git a/src/libstore-tests/.version b/src/libstore-tests/.version new file mode 120000 index 000000000..b7badcd0c --- /dev/null +++ b/src/libstore-tests/.version @@ -0,0 +1 @@ +../../.version \ No newline at end of file diff --git a/src/libstore-tests/build-utils-meson b/src/libstore-tests/build-utils-meson new file mode 120000 index 000000000..5fff21bab --- /dev/null +++ b/src/libstore-tests/build-utils-meson @@ -0,0 +1 @@ +../../build-utils-meson \ No newline at end of file diff --git a/tests/unit/libstore/common-protocol.cc b/src/libstore-tests/common-protocol.cc similarity index 100% rename from tests/unit/libstore/common-protocol.cc rename to src/libstore-tests/common-protocol.cc diff --git a/tests/unit/libstore/content-address.cc b/src/libstore-tests/content-address.cc similarity index 100% rename from tests/unit/libstore/content-address.cc rename to src/libstore-tests/content-address.cc diff --git a/tests/unit/libstore/data/common-protocol/content-address.bin b/src/libstore-tests/data/common-protocol/content-address.bin similarity index 100% rename from tests/unit/libstore/data/common-protocol/content-address.bin rename to src/libstore-tests/data/common-protocol/content-address.bin diff --git a/tests/unit/libstore/data/common-protocol/drv-output.bin b/src/libstore-tests/data/common-protocol/drv-output.bin similarity index 100% rename from tests/unit/libstore/data/common-protocol/drv-output.bin rename to src/libstore-tests/data/common-protocol/drv-output.bin diff --git a/tests/unit/libstore/data/common-protocol/optional-content-address.bin b/src/libstore-tests/data/common-protocol/optional-content-address.bin similarity index 100% rename from tests/unit/libstore/data/common-protocol/optional-content-address.bin rename to src/libstore-tests/data/common-protocol/optional-content-address.bin diff --git a/tests/unit/libstore/data/common-protocol/optional-store-path.bin b/src/libstore-tests/data/common-protocol/optional-store-path.bin similarity index 100% rename from tests/unit/libstore/data/common-protocol/optional-store-path.bin rename to src/libstore-tests/data/common-protocol/optional-store-path.bin diff --git a/tests/unit/libstore/data/common-protocol/realisation.bin b/src/libstore-tests/data/common-protocol/realisation.bin similarity index 100% rename from tests/unit/libstore/data/common-protocol/realisation.bin rename to src/libstore-tests/data/common-protocol/realisation.bin diff --git a/tests/unit/libstore/data/common-protocol/set.bin b/src/libstore-tests/data/common-protocol/set.bin similarity index 100% rename from tests/unit/libstore/data/common-protocol/set.bin rename to src/libstore-tests/data/common-protocol/set.bin diff --git a/tests/unit/libstore/data/common-protocol/store-path.bin b/src/libstore-tests/data/common-protocol/store-path.bin similarity index 100% rename from tests/unit/libstore/data/common-protocol/store-path.bin rename to src/libstore-tests/data/common-protocol/store-path.bin diff --git a/tests/unit/libstore/data/common-protocol/string.bin b/src/libstore-tests/data/common-protocol/string.bin similarity index 100% rename from tests/unit/libstore/data/common-protocol/string.bin rename to src/libstore-tests/data/common-protocol/string.bin diff --git a/tests/unit/libstore/data/common-protocol/vector.bin b/src/libstore-tests/data/common-protocol/vector.bin similarity index 100% rename from tests/unit/libstore/data/common-protocol/vector.bin rename to src/libstore-tests/data/common-protocol/vector.bin diff --git a/src/libstore-tests/data/derivation/advanced-attributes-defaults.drv b/src/libstore-tests/data/derivation/advanced-attributes-defaults.drv new file mode 120000 index 000000000..f8f30ac32 --- /dev/null +++ b/src/libstore-tests/data/derivation/advanced-attributes-defaults.drv @@ -0,0 +1 @@ +../../../../tests/functional/derivation/advanced-attributes-defaults.drv \ No newline at end of file diff --git a/tests/unit/libstore/data/derivation/advanced-attributes-defaults.json b/src/libstore-tests/data/derivation/advanced-attributes-defaults.json similarity index 100% rename from tests/unit/libstore/data/derivation/advanced-attributes-defaults.json rename to src/libstore-tests/data/derivation/advanced-attributes-defaults.json diff --git a/src/libstore-tests/data/derivation/advanced-attributes-structured-attrs-defaults.drv b/src/libstore-tests/data/derivation/advanced-attributes-structured-attrs-defaults.drv new file mode 120000 index 000000000..837e9a0e4 --- /dev/null +++ b/src/libstore-tests/data/derivation/advanced-attributes-structured-attrs-defaults.drv @@ -0,0 +1 @@ +../../../../tests/functional/derivation/advanced-attributes-structured-attrs-defaults.drv \ No newline at end of file diff --git a/tests/unit/libstore/data/derivation/advanced-attributes-structured-attrs-defaults.json b/src/libstore-tests/data/derivation/advanced-attributes-structured-attrs-defaults.json similarity index 100% rename from tests/unit/libstore/data/derivation/advanced-attributes-structured-attrs-defaults.json rename to src/libstore-tests/data/derivation/advanced-attributes-structured-attrs-defaults.json diff --git a/src/libstore-tests/data/derivation/advanced-attributes-structured-attrs.drv b/src/libstore-tests/data/derivation/advanced-attributes-structured-attrs.drv new file mode 120000 index 000000000..e08bb5737 --- /dev/null +++ b/src/libstore-tests/data/derivation/advanced-attributes-structured-attrs.drv @@ -0,0 +1 @@ +../../../../tests/functional/derivation/advanced-attributes-structured-attrs.drv \ No newline at end of file diff --git a/tests/unit/libstore/data/derivation/advanced-attributes-structured-attrs.json b/src/libstore-tests/data/derivation/advanced-attributes-structured-attrs.json similarity index 100% rename from tests/unit/libstore/data/derivation/advanced-attributes-structured-attrs.json rename to src/libstore-tests/data/derivation/advanced-attributes-structured-attrs.json diff --git a/src/libstore-tests/data/derivation/advanced-attributes.drv b/src/libstore-tests/data/derivation/advanced-attributes.drv new file mode 120000 index 000000000..1dc394a0a --- /dev/null +++ b/src/libstore-tests/data/derivation/advanced-attributes.drv @@ -0,0 +1 @@ +../../../../tests/functional/derivation/advanced-attributes.drv \ No newline at end of file diff --git a/tests/unit/libstore/data/derivation/bad-old-version-dyn-deps.drv b/src/libstore-tests/data/derivation/bad-old-version-dyn-deps.drv similarity index 100% rename from tests/unit/libstore/data/derivation/bad-old-version-dyn-deps.drv rename to src/libstore-tests/data/derivation/bad-old-version-dyn-deps.drv diff --git a/tests/unit/libstore/data/derivation/bad-version.drv b/src/libstore-tests/data/derivation/bad-version.drv similarity index 100% rename from tests/unit/libstore/data/derivation/bad-version.drv rename to src/libstore-tests/data/derivation/bad-version.drv diff --git a/tests/unit/libstore/data/derivation/dynDerivationDeps.drv b/src/libstore-tests/data/derivation/dynDerivationDeps.drv similarity index 100% rename from tests/unit/libstore/data/derivation/dynDerivationDeps.drv rename to src/libstore-tests/data/derivation/dynDerivationDeps.drv diff --git a/tests/unit/libstore/data/derivation/dynDerivationDeps.json b/src/libstore-tests/data/derivation/dynDerivationDeps.json similarity index 100% rename from tests/unit/libstore/data/derivation/dynDerivationDeps.json rename to src/libstore-tests/data/derivation/dynDerivationDeps.json diff --git a/tests/unit/libstore/data/derivation/output-caFixedFlat.json b/src/libstore-tests/data/derivation/output-caFixedFlat.json similarity index 100% rename from tests/unit/libstore/data/derivation/output-caFixedFlat.json rename to src/libstore-tests/data/derivation/output-caFixedFlat.json diff --git a/tests/unit/libstore/data/derivation/output-caFixedNAR.json b/src/libstore-tests/data/derivation/output-caFixedNAR.json similarity index 100% rename from tests/unit/libstore/data/derivation/output-caFixedNAR.json rename to src/libstore-tests/data/derivation/output-caFixedNAR.json diff --git a/tests/unit/libstore/data/derivation/output-caFixedText.json b/src/libstore-tests/data/derivation/output-caFixedText.json similarity index 100% rename from tests/unit/libstore/data/derivation/output-caFixedText.json rename to src/libstore-tests/data/derivation/output-caFixedText.json diff --git a/tests/unit/libstore/data/derivation/output-caFloating.json b/src/libstore-tests/data/derivation/output-caFloating.json similarity index 100% rename from tests/unit/libstore/data/derivation/output-caFloating.json rename to src/libstore-tests/data/derivation/output-caFloating.json diff --git a/tests/unit/libstore/data/derivation/output-deferred.json b/src/libstore-tests/data/derivation/output-deferred.json similarity index 100% rename from tests/unit/libstore/data/derivation/output-deferred.json rename to src/libstore-tests/data/derivation/output-deferred.json diff --git a/tests/unit/libstore/data/derivation/output-impure.json b/src/libstore-tests/data/derivation/output-impure.json similarity index 100% rename from tests/unit/libstore/data/derivation/output-impure.json rename to src/libstore-tests/data/derivation/output-impure.json diff --git a/tests/unit/libstore/data/derivation/output-inputAddressed.json b/src/libstore-tests/data/derivation/output-inputAddressed.json similarity index 100% rename from tests/unit/libstore/data/derivation/output-inputAddressed.json rename to src/libstore-tests/data/derivation/output-inputAddressed.json diff --git a/tests/unit/libstore/data/derivation/simple.drv b/src/libstore-tests/data/derivation/simple.drv similarity index 100% rename from tests/unit/libstore/data/derivation/simple.drv rename to src/libstore-tests/data/derivation/simple.drv diff --git a/tests/unit/libstore/data/derivation/simple.json b/src/libstore-tests/data/derivation/simple.json similarity index 100% rename from tests/unit/libstore/data/derivation/simple.json rename to src/libstore-tests/data/derivation/simple.json diff --git a/tests/unit/libstore/data/machines/bad_format b/src/libstore-tests/data/machines/bad_format similarity index 100% rename from tests/unit/libstore/data/machines/bad_format rename to src/libstore-tests/data/machines/bad_format diff --git a/tests/unit/libstore/data/machines/valid b/src/libstore-tests/data/machines/valid similarity index 100% rename from tests/unit/libstore/data/machines/valid rename to src/libstore-tests/data/machines/valid diff --git a/tests/unit/libstore/data/nar-info/impure.json b/src/libstore-tests/data/nar-info/impure.json similarity index 100% rename from tests/unit/libstore/data/nar-info/impure.json rename to src/libstore-tests/data/nar-info/impure.json diff --git a/tests/unit/libstore/data/nar-info/pure.json b/src/libstore-tests/data/nar-info/pure.json similarity index 100% rename from tests/unit/libstore/data/nar-info/pure.json rename to src/libstore-tests/data/nar-info/pure.json diff --git a/tests/unit/libstore/data/path-info/empty_impure.json b/src/libstore-tests/data/path-info/empty_impure.json similarity index 100% rename from tests/unit/libstore/data/path-info/empty_impure.json rename to src/libstore-tests/data/path-info/empty_impure.json diff --git a/tests/unit/libstore/data/path-info/empty_pure.json b/src/libstore-tests/data/path-info/empty_pure.json similarity index 100% rename from tests/unit/libstore/data/path-info/empty_pure.json rename to src/libstore-tests/data/path-info/empty_pure.json diff --git a/tests/unit/libstore/data/path-info/impure.json b/src/libstore-tests/data/path-info/impure.json similarity index 100% rename from tests/unit/libstore/data/path-info/impure.json rename to src/libstore-tests/data/path-info/impure.json diff --git a/tests/unit/libstore/data/path-info/pure.json b/src/libstore-tests/data/path-info/pure.json similarity index 100% rename from tests/unit/libstore/data/path-info/pure.json rename to src/libstore-tests/data/path-info/pure.json diff --git a/tests/unit/libstore/data/serve-protocol/build-options-2.1.bin b/src/libstore-tests/data/serve-protocol/build-options-2.1.bin similarity index 100% rename from tests/unit/libstore/data/serve-protocol/build-options-2.1.bin rename to src/libstore-tests/data/serve-protocol/build-options-2.1.bin diff --git a/tests/unit/libstore/data/serve-protocol/build-options-2.2.bin b/src/libstore-tests/data/serve-protocol/build-options-2.2.bin similarity index 100% rename from tests/unit/libstore/data/serve-protocol/build-options-2.2.bin rename to src/libstore-tests/data/serve-protocol/build-options-2.2.bin diff --git a/tests/unit/libstore/data/serve-protocol/build-options-2.3.bin b/src/libstore-tests/data/serve-protocol/build-options-2.3.bin similarity index 100% rename from tests/unit/libstore/data/serve-protocol/build-options-2.3.bin rename to src/libstore-tests/data/serve-protocol/build-options-2.3.bin diff --git a/tests/unit/libstore/data/serve-protocol/build-options-2.7.bin b/src/libstore-tests/data/serve-protocol/build-options-2.7.bin similarity index 100% rename from tests/unit/libstore/data/serve-protocol/build-options-2.7.bin rename to src/libstore-tests/data/serve-protocol/build-options-2.7.bin diff --git a/tests/unit/libstore/data/serve-protocol/build-result-2.2.bin b/src/libstore-tests/data/serve-protocol/build-result-2.2.bin similarity index 100% rename from tests/unit/libstore/data/serve-protocol/build-result-2.2.bin rename to src/libstore-tests/data/serve-protocol/build-result-2.2.bin diff --git a/tests/unit/libstore/data/serve-protocol/build-result-2.3.bin b/src/libstore-tests/data/serve-protocol/build-result-2.3.bin similarity index 100% rename from tests/unit/libstore/data/serve-protocol/build-result-2.3.bin rename to src/libstore-tests/data/serve-protocol/build-result-2.3.bin diff --git a/tests/unit/libstore/data/serve-protocol/build-result-2.6.bin b/src/libstore-tests/data/serve-protocol/build-result-2.6.bin similarity index 100% rename from tests/unit/libstore/data/serve-protocol/build-result-2.6.bin rename to src/libstore-tests/data/serve-protocol/build-result-2.6.bin diff --git a/tests/unit/libstore/data/serve-protocol/content-address.bin b/src/libstore-tests/data/serve-protocol/content-address.bin similarity index 100% rename from tests/unit/libstore/data/serve-protocol/content-address.bin rename to src/libstore-tests/data/serve-protocol/content-address.bin diff --git a/tests/unit/libstore/data/serve-protocol/drv-output.bin b/src/libstore-tests/data/serve-protocol/drv-output.bin similarity index 100% rename from tests/unit/libstore/data/serve-protocol/drv-output.bin rename to src/libstore-tests/data/serve-protocol/drv-output.bin diff --git a/tests/unit/libstore/data/serve-protocol/handshake-to-client.bin b/src/libstore-tests/data/serve-protocol/handshake-to-client.bin similarity index 100% rename from tests/unit/libstore/data/serve-protocol/handshake-to-client.bin rename to src/libstore-tests/data/serve-protocol/handshake-to-client.bin diff --git a/tests/unit/libstore/data/serve-protocol/optional-content-address.bin b/src/libstore-tests/data/serve-protocol/optional-content-address.bin similarity index 100% rename from tests/unit/libstore/data/serve-protocol/optional-content-address.bin rename to src/libstore-tests/data/serve-protocol/optional-content-address.bin diff --git a/tests/unit/libstore/data/serve-protocol/optional-store-path.bin b/src/libstore-tests/data/serve-protocol/optional-store-path.bin similarity index 100% rename from tests/unit/libstore/data/serve-protocol/optional-store-path.bin rename to src/libstore-tests/data/serve-protocol/optional-store-path.bin diff --git a/tests/unit/libstore/data/serve-protocol/realisation.bin b/src/libstore-tests/data/serve-protocol/realisation.bin similarity index 100% rename from tests/unit/libstore/data/serve-protocol/realisation.bin rename to src/libstore-tests/data/serve-protocol/realisation.bin diff --git a/tests/unit/libstore/data/serve-protocol/set.bin b/src/libstore-tests/data/serve-protocol/set.bin similarity index 100% rename from tests/unit/libstore/data/serve-protocol/set.bin rename to src/libstore-tests/data/serve-protocol/set.bin diff --git a/tests/unit/libstore/data/serve-protocol/store-path.bin b/src/libstore-tests/data/serve-protocol/store-path.bin similarity index 100% rename from tests/unit/libstore/data/serve-protocol/store-path.bin rename to src/libstore-tests/data/serve-protocol/store-path.bin diff --git a/tests/unit/libstore/data/serve-protocol/string.bin b/src/libstore-tests/data/serve-protocol/string.bin similarity index 100% rename from tests/unit/libstore/data/serve-protocol/string.bin rename to src/libstore-tests/data/serve-protocol/string.bin diff --git a/tests/unit/libstore/data/serve-protocol/unkeyed-valid-path-info-2.3.bin b/src/libstore-tests/data/serve-protocol/unkeyed-valid-path-info-2.3.bin similarity index 100% rename from tests/unit/libstore/data/serve-protocol/unkeyed-valid-path-info-2.3.bin rename to src/libstore-tests/data/serve-protocol/unkeyed-valid-path-info-2.3.bin diff --git a/tests/unit/libstore/data/serve-protocol/unkeyed-valid-path-info-2.4.bin b/src/libstore-tests/data/serve-protocol/unkeyed-valid-path-info-2.4.bin similarity index 100% rename from tests/unit/libstore/data/serve-protocol/unkeyed-valid-path-info-2.4.bin rename to src/libstore-tests/data/serve-protocol/unkeyed-valid-path-info-2.4.bin diff --git a/tests/unit/libstore/data/serve-protocol/vector.bin b/src/libstore-tests/data/serve-protocol/vector.bin similarity index 100% rename from tests/unit/libstore/data/serve-protocol/vector.bin rename to src/libstore-tests/data/serve-protocol/vector.bin diff --git a/tests/unit/libstore/data/store-reference/auto.txt b/src/libstore-tests/data/store-reference/auto.txt similarity index 100% rename from tests/unit/libstore/data/store-reference/auto.txt rename to src/libstore-tests/data/store-reference/auto.txt diff --git a/tests/unit/libstore/data/store-reference/auto_param.txt b/src/libstore-tests/data/store-reference/auto_param.txt similarity index 100% rename from tests/unit/libstore/data/store-reference/auto_param.txt rename to src/libstore-tests/data/store-reference/auto_param.txt diff --git a/tests/unit/libstore/data/store-reference/local_1.txt b/src/libstore-tests/data/store-reference/local_1.txt similarity index 100% rename from tests/unit/libstore/data/store-reference/local_1.txt rename to src/libstore-tests/data/store-reference/local_1.txt diff --git a/tests/unit/libstore/data/store-reference/local_2.txt b/src/libstore-tests/data/store-reference/local_2.txt similarity index 100% rename from tests/unit/libstore/data/store-reference/local_2.txt rename to src/libstore-tests/data/store-reference/local_2.txt diff --git a/tests/unit/libstore/data/store-reference/local_shorthand_1.txt b/src/libstore-tests/data/store-reference/local_shorthand_1.txt similarity index 100% rename from tests/unit/libstore/data/store-reference/local_shorthand_1.txt rename to src/libstore-tests/data/store-reference/local_shorthand_1.txt diff --git a/tests/unit/libstore/data/store-reference/local_shorthand_2.txt b/src/libstore-tests/data/store-reference/local_shorthand_2.txt similarity index 100% rename from tests/unit/libstore/data/store-reference/local_shorthand_2.txt rename to src/libstore-tests/data/store-reference/local_shorthand_2.txt diff --git a/tests/unit/libstore/data/store-reference/ssh.txt b/src/libstore-tests/data/store-reference/ssh.txt similarity index 100% rename from tests/unit/libstore/data/store-reference/ssh.txt rename to src/libstore-tests/data/store-reference/ssh.txt diff --git a/tests/unit/libstore/data/store-reference/unix.txt b/src/libstore-tests/data/store-reference/unix.txt similarity index 100% rename from tests/unit/libstore/data/store-reference/unix.txt rename to src/libstore-tests/data/store-reference/unix.txt diff --git a/tests/unit/libstore/data/store-reference/unix_shorthand.txt b/src/libstore-tests/data/store-reference/unix_shorthand.txt similarity index 100% rename from tests/unit/libstore/data/store-reference/unix_shorthand.txt rename to src/libstore-tests/data/store-reference/unix_shorthand.txt diff --git a/tests/unit/libstore/data/worker-protocol/build-mode.bin b/src/libstore-tests/data/worker-protocol/build-mode.bin similarity index 100% rename from tests/unit/libstore/data/worker-protocol/build-mode.bin rename to src/libstore-tests/data/worker-protocol/build-mode.bin diff --git a/tests/unit/libstore/data/worker-protocol/build-result-1.27.bin b/src/libstore-tests/data/worker-protocol/build-result-1.27.bin similarity index 100% rename from tests/unit/libstore/data/worker-protocol/build-result-1.27.bin rename to src/libstore-tests/data/worker-protocol/build-result-1.27.bin diff --git a/tests/unit/libstore/data/worker-protocol/build-result-1.28.bin b/src/libstore-tests/data/worker-protocol/build-result-1.28.bin similarity index 100% rename from tests/unit/libstore/data/worker-protocol/build-result-1.28.bin rename to src/libstore-tests/data/worker-protocol/build-result-1.28.bin diff --git a/tests/unit/libstore/data/worker-protocol/build-result-1.29.bin b/src/libstore-tests/data/worker-protocol/build-result-1.29.bin similarity index 100% rename from tests/unit/libstore/data/worker-protocol/build-result-1.29.bin rename to src/libstore-tests/data/worker-protocol/build-result-1.29.bin diff --git a/tests/unit/libstore/data/worker-protocol/build-result-1.37.bin b/src/libstore-tests/data/worker-protocol/build-result-1.37.bin similarity index 100% rename from tests/unit/libstore/data/worker-protocol/build-result-1.37.bin rename to src/libstore-tests/data/worker-protocol/build-result-1.37.bin diff --git a/tests/unit/libstore/data/worker-protocol/client-handshake-info_1_30.bin b/src/libstore-tests/data/worker-protocol/client-handshake-info_1_30.bin similarity index 100% rename from tests/unit/libstore/data/worker-protocol/client-handshake-info_1_30.bin rename to src/libstore-tests/data/worker-protocol/client-handshake-info_1_30.bin diff --git a/tests/unit/libstore/data/worker-protocol/client-handshake-info_1_33.bin b/src/libstore-tests/data/worker-protocol/client-handshake-info_1_33.bin similarity index 100% rename from tests/unit/libstore/data/worker-protocol/client-handshake-info_1_33.bin rename to src/libstore-tests/data/worker-protocol/client-handshake-info_1_33.bin diff --git a/tests/unit/libstore/data/worker-protocol/client-handshake-info_1_35.bin b/src/libstore-tests/data/worker-protocol/client-handshake-info_1_35.bin similarity index 100% rename from tests/unit/libstore/data/worker-protocol/client-handshake-info_1_35.bin rename to src/libstore-tests/data/worker-protocol/client-handshake-info_1_35.bin diff --git a/tests/unit/libstore/data/worker-protocol/content-address.bin b/src/libstore-tests/data/worker-protocol/content-address.bin similarity index 100% rename from tests/unit/libstore/data/worker-protocol/content-address.bin rename to src/libstore-tests/data/worker-protocol/content-address.bin diff --git a/tests/unit/libstore/data/worker-protocol/derived-path-1.29.bin b/src/libstore-tests/data/worker-protocol/derived-path-1.29.bin similarity index 100% rename from tests/unit/libstore/data/worker-protocol/derived-path-1.29.bin rename to src/libstore-tests/data/worker-protocol/derived-path-1.29.bin diff --git a/tests/unit/libstore/data/worker-protocol/derived-path-1.30.bin b/src/libstore-tests/data/worker-protocol/derived-path-1.30.bin similarity index 100% rename from tests/unit/libstore/data/worker-protocol/derived-path-1.30.bin rename to src/libstore-tests/data/worker-protocol/derived-path-1.30.bin diff --git a/tests/unit/libstore/data/worker-protocol/drv-output.bin b/src/libstore-tests/data/worker-protocol/drv-output.bin similarity index 100% rename from tests/unit/libstore/data/worker-protocol/drv-output.bin rename to src/libstore-tests/data/worker-protocol/drv-output.bin diff --git a/tests/unit/libstore/data/worker-protocol/handshake-to-client.bin b/src/libstore-tests/data/worker-protocol/handshake-to-client.bin similarity index 100% rename from tests/unit/libstore/data/worker-protocol/handshake-to-client.bin rename to src/libstore-tests/data/worker-protocol/handshake-to-client.bin diff --git a/tests/unit/libstore/data/worker-protocol/keyed-build-result-1.29.bin b/src/libstore-tests/data/worker-protocol/keyed-build-result-1.29.bin similarity index 100% rename from tests/unit/libstore/data/worker-protocol/keyed-build-result-1.29.bin rename to src/libstore-tests/data/worker-protocol/keyed-build-result-1.29.bin diff --git a/tests/unit/libstore/data/worker-protocol/optional-content-address.bin b/src/libstore-tests/data/worker-protocol/optional-content-address.bin similarity index 100% rename from tests/unit/libstore/data/worker-protocol/optional-content-address.bin rename to src/libstore-tests/data/worker-protocol/optional-content-address.bin diff --git a/tests/unit/libstore/data/worker-protocol/optional-store-path.bin b/src/libstore-tests/data/worker-protocol/optional-store-path.bin similarity index 100% rename from tests/unit/libstore/data/worker-protocol/optional-store-path.bin rename to src/libstore-tests/data/worker-protocol/optional-store-path.bin diff --git a/tests/unit/libstore/data/worker-protocol/optional-trusted-flag.bin b/src/libstore-tests/data/worker-protocol/optional-trusted-flag.bin similarity index 100% rename from tests/unit/libstore/data/worker-protocol/optional-trusted-flag.bin rename to src/libstore-tests/data/worker-protocol/optional-trusted-flag.bin diff --git a/tests/unit/libstore/data/worker-protocol/realisation.bin b/src/libstore-tests/data/worker-protocol/realisation.bin similarity index 100% rename from tests/unit/libstore/data/worker-protocol/realisation.bin rename to src/libstore-tests/data/worker-protocol/realisation.bin diff --git a/tests/unit/libstore/data/worker-protocol/set.bin b/src/libstore-tests/data/worker-protocol/set.bin similarity index 100% rename from tests/unit/libstore/data/worker-protocol/set.bin rename to src/libstore-tests/data/worker-protocol/set.bin diff --git a/tests/unit/libstore/data/worker-protocol/store-path.bin b/src/libstore-tests/data/worker-protocol/store-path.bin similarity index 100% rename from tests/unit/libstore/data/worker-protocol/store-path.bin rename to src/libstore-tests/data/worker-protocol/store-path.bin diff --git a/tests/unit/libstore/data/worker-protocol/string.bin b/src/libstore-tests/data/worker-protocol/string.bin similarity index 100% rename from tests/unit/libstore/data/worker-protocol/string.bin rename to src/libstore-tests/data/worker-protocol/string.bin diff --git a/tests/unit/libstore/data/worker-protocol/unkeyed-valid-path-info-1.15.bin b/src/libstore-tests/data/worker-protocol/unkeyed-valid-path-info-1.15.bin similarity index 100% rename from tests/unit/libstore/data/worker-protocol/unkeyed-valid-path-info-1.15.bin rename to src/libstore-tests/data/worker-protocol/unkeyed-valid-path-info-1.15.bin diff --git a/tests/unit/libstore/data/worker-protocol/valid-path-info-1.15.bin b/src/libstore-tests/data/worker-protocol/valid-path-info-1.15.bin similarity index 100% rename from tests/unit/libstore/data/worker-protocol/valid-path-info-1.15.bin rename to src/libstore-tests/data/worker-protocol/valid-path-info-1.15.bin diff --git a/tests/unit/libstore/data/worker-protocol/valid-path-info-1.16.bin b/src/libstore-tests/data/worker-protocol/valid-path-info-1.16.bin similarity index 100% rename from tests/unit/libstore/data/worker-protocol/valid-path-info-1.16.bin rename to src/libstore-tests/data/worker-protocol/valid-path-info-1.16.bin diff --git a/tests/unit/libstore/data/worker-protocol/vector.bin b/src/libstore-tests/data/worker-protocol/vector.bin similarity index 100% rename from tests/unit/libstore/data/worker-protocol/vector.bin rename to src/libstore-tests/data/worker-protocol/vector.bin diff --git a/tests/unit/libstore/derivation-advanced-attrs.cc b/src/libstore-tests/derivation-advanced-attrs.cc similarity index 100% rename from tests/unit/libstore/derivation-advanced-attrs.cc rename to src/libstore-tests/derivation-advanced-attrs.cc diff --git a/tests/unit/libstore/derivation.cc b/src/libstore-tests/derivation.cc similarity index 100% rename from tests/unit/libstore/derivation.cc rename to src/libstore-tests/derivation.cc diff --git a/tests/unit/libstore/derived-path.cc b/src/libstore-tests/derived-path.cc similarity index 100% rename from tests/unit/libstore/derived-path.cc rename to src/libstore-tests/derived-path.cc diff --git a/tests/unit/libstore/downstream-placeholder.cc b/src/libstore-tests/downstream-placeholder.cc similarity index 100% rename from tests/unit/libstore/downstream-placeholder.cc rename to src/libstore-tests/downstream-placeholder.cc diff --git a/tests/unit/libstore/http-binary-cache-store.cc b/src/libstore-tests/http-binary-cache-store.cc similarity index 100% rename from tests/unit/libstore/http-binary-cache-store.cc rename to src/libstore-tests/http-binary-cache-store.cc diff --git a/tests/unit/libstore/legacy-ssh-store.cc b/src/libstore-tests/legacy-ssh-store.cc similarity index 100% rename from tests/unit/libstore/legacy-ssh-store.cc rename to src/libstore-tests/legacy-ssh-store.cc diff --git a/tests/unit/libstore/local-binary-cache-store.cc b/src/libstore-tests/local-binary-cache-store.cc similarity index 100% rename from tests/unit/libstore/local-binary-cache-store.cc rename to src/libstore-tests/local-binary-cache-store.cc diff --git a/tests/unit/libstore/local-overlay-store.cc b/src/libstore-tests/local-overlay-store.cc similarity index 100% rename from tests/unit/libstore/local-overlay-store.cc rename to src/libstore-tests/local-overlay-store.cc diff --git a/tests/unit/libstore/local-store.cc b/src/libstore-tests/local-store.cc similarity index 100% rename from tests/unit/libstore/local-store.cc rename to src/libstore-tests/local-store.cc diff --git a/tests/unit/libstore/local.mk b/src/libstore-tests/local.mk similarity index 92% rename from tests/unit/libstore/local.mk rename to src/libstore-tests/local.mk index 8d3d6b0af..b565ff0be 100644 --- a/tests/unit/libstore/local.mk +++ b/src/libstore-tests/local.mk @@ -17,8 +17,8 @@ endif libstore-tests_SOURCES := $(wildcard $(d)/*.cc) libstore-tests_EXTRA_INCLUDES = \ - -I tests/unit/libstore-support \ - -I tests/unit/libutil-support \ + -I src/libstore-test-support \ + -I src/libutil-test-support \ $(INCLUDE_libstore) \ $(INCLUDE_libstorec) \ $(INCLUDE_libutil) \ diff --git a/tests/unit/libstore/machines.cc b/src/libstore-tests/machines.cc similarity index 100% rename from tests/unit/libstore/machines.cc rename to src/libstore-tests/machines.cc diff --git a/tests/unit/libstore/meson.build b/src/libstore-tests/meson.build similarity index 100% rename from tests/unit/libstore/meson.build rename to src/libstore-tests/meson.build diff --git a/tests/unit/libstore/nar-info-disk-cache.cc b/src/libstore-tests/nar-info-disk-cache.cc similarity index 100% rename from tests/unit/libstore/nar-info-disk-cache.cc rename to src/libstore-tests/nar-info-disk-cache.cc diff --git a/tests/unit/libstore/nar-info.cc b/src/libstore-tests/nar-info.cc similarity index 100% rename from tests/unit/libstore/nar-info.cc rename to src/libstore-tests/nar-info.cc diff --git a/tests/unit/libstore/nix_api_store.cc b/src/libstore-tests/nix_api_store.cc similarity index 100% rename from tests/unit/libstore/nix_api_store.cc rename to src/libstore-tests/nix_api_store.cc diff --git a/tests/unit/libstore/outputs-spec.cc b/src/libstore-tests/outputs-spec.cc similarity index 100% rename from tests/unit/libstore/outputs-spec.cc rename to src/libstore-tests/outputs-spec.cc diff --git a/tests/unit/libstore/package.nix b/src/libstore-tests/package.nix similarity index 90% rename from tests/unit/libstore/package.nix rename to src/libstore-tests/package.nix index 5fbb34a76..5b2fd108b 100644 --- a/tests/unit/libstore/package.nix +++ b/src/libstore-tests/package.nix @@ -28,9 +28,9 @@ mkMesonExecutable (finalAttrs: { workDir = ./.; fileset = fileset.unions [ - ../../../build-utils-meson + ../../build-utils-meson ./build-utils-meson - ../../../.version + ../../.version ./.version ./meson.build # ./meson.options @@ -52,7 +52,7 @@ mkMesonExecutable (finalAttrs: { # Do the meson utils, without modification. '' chmod u+w ./.version - echo ${version} > ../../../.version + echo ${version} > ../../.version ''; mesonFlags = [ @@ -71,7 +71,7 @@ mkMesonExecutable (finalAttrs: { root = ../..; fileset = lib.fileset.unions [ ./data - ../../functional/derivation + ../../tests/functional/derivation ]; }; in runCommand "${finalAttrs.pname}-run" { @@ -80,7 +80,7 @@ mkMesonExecutable (finalAttrs: { export HOME="$PWD/home-dir" mkdir -p "$HOME" '' + '' - export _NIX_TEST_UNIT_DATA=${data + "/unit/libstore/data"} + export _NIX_TEST_UNIT_DATA=${data + "/src/libstore-tests/data"} ${stdenv.hostPlatform.emulator buildPackages} ${lib.getExe finalAttrs.finalPackage} touch $out ''); diff --git a/tests/unit/libstore/path-info.cc b/src/libstore-tests/path-info.cc similarity index 100% rename from tests/unit/libstore/path-info.cc rename to src/libstore-tests/path-info.cc diff --git a/tests/unit/libstore/path.cc b/src/libstore-tests/path.cc similarity index 100% rename from tests/unit/libstore/path.cc rename to src/libstore-tests/path.cc diff --git a/tests/unit/libstore/references.cc b/src/libstore-tests/references.cc similarity index 100% rename from tests/unit/libstore/references.cc rename to src/libstore-tests/references.cc diff --git a/tests/unit/libstore/s3-binary-cache-store.cc b/src/libstore-tests/s3-binary-cache-store.cc similarity index 100% rename from tests/unit/libstore/s3-binary-cache-store.cc rename to src/libstore-tests/s3-binary-cache-store.cc diff --git a/tests/unit/libstore/serve-protocol.cc b/src/libstore-tests/serve-protocol.cc similarity index 100% rename from tests/unit/libstore/serve-protocol.cc rename to src/libstore-tests/serve-protocol.cc diff --git a/tests/unit/libstore/ssh-store.cc b/src/libstore-tests/ssh-store.cc similarity index 100% rename from tests/unit/libstore/ssh-store.cc rename to src/libstore-tests/ssh-store.cc diff --git a/tests/unit/libstore/store-reference.cc b/src/libstore-tests/store-reference.cc similarity index 100% rename from tests/unit/libstore/store-reference.cc rename to src/libstore-tests/store-reference.cc diff --git a/tests/unit/libstore/uds-remote-store.cc b/src/libstore-tests/uds-remote-store.cc similarity index 100% rename from tests/unit/libstore/uds-remote-store.cc rename to src/libstore-tests/uds-remote-store.cc diff --git a/tests/unit/libstore/worker-protocol.cc b/src/libstore-tests/worker-protocol.cc similarity index 100% rename from tests/unit/libstore/worker-protocol.cc rename to src/libstore-tests/worker-protocol.cc diff --git a/src/libutil-test-support/.version b/src/libutil-test-support/.version new file mode 120000 index 000000000..b7badcd0c --- /dev/null +++ b/src/libutil-test-support/.version @@ -0,0 +1 @@ +../../.version \ No newline at end of file diff --git a/src/libutil-test-support/build-utils-meson b/src/libutil-test-support/build-utils-meson new file mode 120000 index 000000000..5fff21bab --- /dev/null +++ b/src/libutil-test-support/build-utils-meson @@ -0,0 +1 @@ +../../build-utils-meson \ No newline at end of file diff --git a/tests/unit/libutil-support/local.mk b/src/libutil-test-support/local.mk similarity index 100% rename from tests/unit/libutil-support/local.mk rename to src/libutil-test-support/local.mk diff --git a/tests/unit/libutil-support/meson.build b/src/libutil-test-support/meson.build similarity index 100% rename from tests/unit/libutil-support/meson.build rename to src/libutil-test-support/meson.build diff --git a/tests/unit/libutil-support/package.nix b/src/libutil-test-support/package.nix similarity index 90% rename from tests/unit/libutil-support/package.nix rename to src/libutil-test-support/package.nix index 16319cf2d..2525e1602 100644 --- a/tests/unit/libutil-support/package.nix +++ b/src/libutil-test-support/package.nix @@ -21,9 +21,9 @@ mkMesonLibrary (finalAttrs: { workDir = ./.; fileset = fileset.unions [ - ../../../build-utils-meson + ../../build-utils-meson ./build-utils-meson - ../../../.version + ../../.version ./.version ./meson.build # ./meson.options @@ -41,7 +41,7 @@ mkMesonLibrary (finalAttrs: { # Do the meson utils, without modification. '' chmod u+w ./.version - echo ${version} > ../../../.version + echo ${version} > ../../.version ''; mesonFlags = [ diff --git a/tests/unit/libutil-support/tests/characterization.hh b/src/libutil-test-support/tests/characterization.hh similarity index 100% rename from tests/unit/libutil-support/tests/characterization.hh rename to src/libutil-test-support/tests/characterization.hh diff --git a/tests/unit/libutil-support/tests/gtest-with-params.hh b/src/libutil-test-support/tests/gtest-with-params.hh similarity index 100% rename from tests/unit/libutil-support/tests/gtest-with-params.hh rename to src/libutil-test-support/tests/gtest-with-params.hh diff --git a/tests/unit/libutil-support/tests/hash.cc b/src/libutil-test-support/tests/hash.cc similarity index 100% rename from tests/unit/libutil-support/tests/hash.cc rename to src/libutil-test-support/tests/hash.cc diff --git a/tests/unit/libutil-support/tests/hash.hh b/src/libutil-test-support/tests/hash.hh similarity index 100% rename from tests/unit/libutil-support/tests/hash.hh rename to src/libutil-test-support/tests/hash.hh diff --git a/tests/unit/libutil-support/tests/nix_api_util.hh b/src/libutil-test-support/tests/nix_api_util.hh similarity index 100% rename from tests/unit/libutil-support/tests/nix_api_util.hh rename to src/libutil-test-support/tests/nix_api_util.hh diff --git a/tests/unit/libutil-support/tests/string_callback.cc b/src/libutil-test-support/tests/string_callback.cc similarity index 100% rename from tests/unit/libutil-support/tests/string_callback.cc rename to src/libutil-test-support/tests/string_callback.cc diff --git a/tests/unit/libutil-support/tests/string_callback.hh b/src/libutil-test-support/tests/string_callback.hh similarity index 100% rename from tests/unit/libutil-support/tests/string_callback.hh rename to src/libutil-test-support/tests/string_callback.hh diff --git a/tests/unit/libutil-support/tests/tracing-file-system-object-sink.cc b/src/libutil-test-support/tests/tracing-file-system-object-sink.cc similarity index 100% rename from tests/unit/libutil-support/tests/tracing-file-system-object-sink.cc rename to src/libutil-test-support/tests/tracing-file-system-object-sink.cc diff --git a/tests/unit/libutil-support/tests/tracing-file-system-object-sink.hh b/src/libutil-test-support/tests/tracing-file-system-object-sink.hh similarity index 100% rename from tests/unit/libutil-support/tests/tracing-file-system-object-sink.hh rename to src/libutil-test-support/tests/tracing-file-system-object-sink.hh diff --git a/src/libutil-tests/.version b/src/libutil-tests/.version new file mode 120000 index 000000000..b7badcd0c --- /dev/null +++ b/src/libutil-tests/.version @@ -0,0 +1 @@ +../../.version \ No newline at end of file diff --git a/tests/unit/libutil/args.cc b/src/libutil-tests/args.cc similarity index 100% rename from tests/unit/libutil/args.cc rename to src/libutil-tests/args.cc diff --git a/src/libutil-tests/build-utils-meson b/src/libutil-tests/build-utils-meson new file mode 120000 index 000000000..5fff21bab --- /dev/null +++ b/src/libutil-tests/build-utils-meson @@ -0,0 +1 @@ +../../build-utils-meson \ No newline at end of file diff --git a/tests/unit/libutil/canon-path.cc b/src/libutil-tests/canon-path.cc similarity index 100% rename from tests/unit/libutil/canon-path.cc rename to src/libutil-tests/canon-path.cc diff --git a/tests/unit/libutil/checked-arithmetic.cc b/src/libutil-tests/checked-arithmetic.cc similarity index 100% rename from tests/unit/libutil/checked-arithmetic.cc rename to src/libutil-tests/checked-arithmetic.cc diff --git a/tests/unit/libutil/chunked-vector.cc b/src/libutil-tests/chunked-vector.cc similarity index 100% rename from tests/unit/libutil/chunked-vector.cc rename to src/libutil-tests/chunked-vector.cc diff --git a/tests/unit/libutil/closure.cc b/src/libutil-tests/closure.cc similarity index 100% rename from tests/unit/libutil/closure.cc rename to src/libutil-tests/closure.cc diff --git a/tests/unit/libutil/compression.cc b/src/libutil-tests/compression.cc similarity index 100% rename from tests/unit/libutil/compression.cc rename to src/libutil-tests/compression.cc diff --git a/tests/unit/libutil/config.cc b/src/libutil-tests/config.cc similarity index 100% rename from tests/unit/libutil/config.cc rename to src/libutil-tests/config.cc diff --git a/tests/unit/libutil/data/git/check-data.sh b/src/libutil-tests/data/git/check-data.sh similarity index 100% rename from tests/unit/libutil/data/git/check-data.sh rename to src/libutil-tests/data/git/check-data.sh diff --git a/tests/unit/libutil/data/git/hello-world-blob.bin b/src/libutil-tests/data/git/hello-world-blob.bin similarity index 100% rename from tests/unit/libutil/data/git/hello-world-blob.bin rename to src/libutil-tests/data/git/hello-world-blob.bin diff --git a/tests/unit/libutil/data/git/hello-world.bin b/src/libutil-tests/data/git/hello-world.bin similarity index 100% rename from tests/unit/libutil/data/git/hello-world.bin rename to src/libutil-tests/data/git/hello-world.bin diff --git a/tests/unit/libutil/data/git/tree.bin b/src/libutil-tests/data/git/tree.bin similarity index 100% rename from tests/unit/libutil/data/git/tree.bin rename to src/libutil-tests/data/git/tree.bin diff --git a/tests/unit/libutil/data/git/tree.txt b/src/libutil-tests/data/git/tree.txt similarity index 100% rename from tests/unit/libutil/data/git/tree.txt rename to src/libutil-tests/data/git/tree.txt diff --git a/tests/unit/libutil/executable-path.cc b/src/libutil-tests/executable-path.cc similarity index 100% rename from tests/unit/libutil/executable-path.cc rename to src/libutil-tests/executable-path.cc diff --git a/tests/unit/libutil/file-content-address.cc b/src/libutil-tests/file-content-address.cc similarity index 100% rename from tests/unit/libutil/file-content-address.cc rename to src/libutil-tests/file-content-address.cc diff --git a/tests/unit/libutil/file-system.cc b/src/libutil-tests/file-system.cc similarity index 100% rename from tests/unit/libutil/file-system.cc rename to src/libutil-tests/file-system.cc diff --git a/tests/unit/libutil/git.cc b/src/libutil-tests/git.cc similarity index 99% rename from tests/unit/libutil/git.cc rename to src/libutil-tests/git.cc index 9232de5b9..048956a58 100644 --- a/tests/unit/libutil/git.cc +++ b/src/libutil-tests/git.cc @@ -88,7 +88,7 @@ TEST_F(GitTest, blob_write) { /** * This data is for "shallow" tree tests. However, we use "real" hashes * so that we can check our test data in a small shell script test test - * (`tests/unit/libutil/data/git/check-data.sh`). + * (`src/libutil-tests/data/git/check-data.sh`). */ const static Tree tree = { { diff --git a/tests/unit/libutil/hash.cc b/src/libutil-tests/hash.cc similarity index 100% rename from tests/unit/libutil/hash.cc rename to src/libutil-tests/hash.cc diff --git a/tests/unit/libutil/hilite.cc b/src/libutil-tests/hilite.cc similarity index 100% rename from tests/unit/libutil/hilite.cc rename to src/libutil-tests/hilite.cc diff --git a/tests/unit/libutil/json-utils.cc b/src/libutil-tests/json-utils.cc similarity index 100% rename from tests/unit/libutil/json-utils.cc rename to src/libutil-tests/json-utils.cc diff --git a/tests/unit/libutil/local.mk b/src/libutil-tests/local.mk similarity index 96% rename from tests/unit/libutil/local.mk rename to src/libutil-tests/local.mk index 404f35cf1..c747863a4 100644 --- a/tests/unit/libutil/local.mk +++ b/src/libutil-tests/local.mk @@ -17,7 +17,7 @@ endif libutil-tests_SOURCES := $(wildcard $(d)/*.cc) libutil-tests_EXTRA_INCLUDES = \ - -I tests/unit/libutil-support \ + -I src/libutil-test-support \ $(INCLUDE_libutil) \ $(INCLUDE_libutilc) diff --git a/tests/unit/libutil/logging.cc b/src/libutil-tests/logging.cc similarity index 100% rename from tests/unit/libutil/logging.cc rename to src/libutil-tests/logging.cc diff --git a/tests/unit/libutil/lru-cache.cc b/src/libutil-tests/lru-cache.cc similarity index 100% rename from tests/unit/libutil/lru-cache.cc rename to src/libutil-tests/lru-cache.cc diff --git a/tests/unit/libutil/meson.build b/src/libutil-tests/meson.build similarity index 100% rename from tests/unit/libutil/meson.build rename to src/libutil-tests/meson.build diff --git a/tests/unit/libutil/nix_api_util.cc b/src/libutil-tests/nix_api_util.cc similarity index 100% rename from tests/unit/libutil/nix_api_util.cc rename to src/libutil-tests/nix_api_util.cc diff --git a/tests/unit/libutil/package.nix b/src/libutil-tests/package.nix similarity index 94% rename from tests/unit/libutil/package.nix rename to src/libutil-tests/package.nix index 37a80e639..b099037ee 100644 --- a/tests/unit/libutil/package.nix +++ b/src/libutil-tests/package.nix @@ -26,9 +26,9 @@ mkMesonExecutable (finalAttrs: { workDir = ./.; fileset = fileset.unions [ - ../../../build-utils-meson + ../../build-utils-meson ./build-utils-meson - ../../../.version + ../../.version ./.version ./meson.build # ./meson.options @@ -49,7 +49,7 @@ mkMesonExecutable (finalAttrs: { # Do the meson utils, without modification. '' chmod u+w ./.version - echo ${version} > ../../../.version + echo ${version} > ../../.version ''; mesonFlags = [ diff --git a/tests/unit/libutil/pool.cc b/src/libutil-tests/pool.cc similarity index 100% rename from tests/unit/libutil/pool.cc rename to src/libutil-tests/pool.cc diff --git a/tests/unit/libutil/position.cc b/src/libutil-tests/position.cc similarity index 100% rename from tests/unit/libutil/position.cc rename to src/libutil-tests/position.cc diff --git a/tests/unit/libutil/processes.cc b/src/libutil-tests/processes.cc similarity index 100% rename from tests/unit/libutil/processes.cc rename to src/libutil-tests/processes.cc diff --git a/tests/unit/libutil/references.cc b/src/libutil-tests/references.cc similarity index 100% rename from tests/unit/libutil/references.cc rename to src/libutil-tests/references.cc diff --git a/tests/unit/libutil/spawn.cc b/src/libutil-tests/spawn.cc similarity index 100% rename from tests/unit/libutil/spawn.cc rename to src/libutil-tests/spawn.cc diff --git a/tests/unit/libutil/strings.cc b/src/libutil-tests/strings.cc similarity index 100% rename from tests/unit/libutil/strings.cc rename to src/libutil-tests/strings.cc diff --git a/tests/unit/libutil/suggestions.cc b/src/libutil-tests/suggestions.cc similarity index 100% rename from tests/unit/libutil/suggestions.cc rename to src/libutil-tests/suggestions.cc diff --git a/tests/unit/libutil/terminal.cc b/src/libutil-tests/terminal.cc similarity index 100% rename from tests/unit/libutil/terminal.cc rename to src/libutil-tests/terminal.cc diff --git a/tests/unit/libutil/url.cc b/src/libutil-tests/url.cc similarity index 100% rename from tests/unit/libutil/url.cc rename to src/libutil-tests/url.cc diff --git a/tests/unit/libutil/util.cc b/src/libutil-tests/util.cc similarity index 100% rename from tests/unit/libutil/util.cc rename to src/libutil-tests/util.cc diff --git a/tests/unit/libutil/xml-writer.cc b/src/libutil-tests/xml-writer.cc similarity index 100% rename from tests/unit/libutil/xml-writer.cc rename to src/libutil-tests/xml-writer.cc diff --git a/src/nix-expr-test-support b/src/nix-expr-test-support deleted file mode 120000 index 427b80dff..000000000 --- a/src/nix-expr-test-support +++ /dev/null @@ -1 +0,0 @@ -../tests/unit/libexpr-support \ No newline at end of file diff --git a/src/nix-expr-tests b/src/nix-expr-tests deleted file mode 120000 index 3af7110d3..000000000 --- a/src/nix-expr-tests +++ /dev/null @@ -1 +0,0 @@ -../tests/unit/libexpr \ No newline at end of file diff --git a/src/nix-fetchers-tests b/src/nix-fetchers-tests deleted file mode 120000 index 80e4b68ae..000000000 --- a/src/nix-fetchers-tests +++ /dev/null @@ -1 +0,0 @@ -../tests/unit/libfetchers \ No newline at end of file diff --git a/src/nix-flake-tests b/src/nix-flake-tests deleted file mode 120000 index bb2d49400..000000000 --- a/src/nix-flake-tests +++ /dev/null @@ -1 +0,0 @@ -../tests/unit/libflake \ No newline at end of file diff --git a/src/nix-store-test-support b/src/nix-store-test-support deleted file mode 120000 index af4befd90..000000000 --- a/src/nix-store-test-support +++ /dev/null @@ -1 +0,0 @@ -../tests/unit/libstore-support \ No newline at end of file diff --git a/src/nix-store-tests b/src/nix-store-tests deleted file mode 120000 index fc9b910af..000000000 --- a/src/nix-store-tests +++ /dev/null @@ -1 +0,0 @@ -../tests/unit/libstore \ No newline at end of file diff --git a/src/nix-util-test-support b/src/nix-util-test-support deleted file mode 120000 index 4b25930eb..000000000 --- a/src/nix-util-test-support +++ /dev/null @@ -1 +0,0 @@ -../tests/unit/libutil-support \ No newline at end of file diff --git a/src/nix-util-tests b/src/nix-util-tests deleted file mode 120000 index e1138411a..000000000 --- a/src/nix-util-tests +++ /dev/null @@ -1 +0,0 @@ -../tests/unit/libutil \ No newline at end of file diff --git a/tests/unit/libexpr-support/.version b/tests/unit/libexpr-support/.version deleted file mode 120000 index 0df9915bf..000000000 --- a/tests/unit/libexpr-support/.version +++ /dev/null @@ -1 +0,0 @@ -../../../.version \ No newline at end of file diff --git a/tests/unit/libexpr-support/build-utils-meson b/tests/unit/libexpr-support/build-utils-meson deleted file mode 120000 index f2d8e8a50..000000000 --- a/tests/unit/libexpr-support/build-utils-meson +++ /dev/null @@ -1 +0,0 @@ -../../../build-utils-meson/ \ No newline at end of file diff --git a/tests/unit/libexpr/.version b/tests/unit/libexpr/.version deleted file mode 120000 index 0df9915bf..000000000 --- a/tests/unit/libexpr/.version +++ /dev/null @@ -1 +0,0 @@ -../../../.version \ No newline at end of file diff --git a/tests/unit/libexpr/build-utils-meson b/tests/unit/libexpr/build-utils-meson deleted file mode 120000 index f2d8e8a50..000000000 --- a/tests/unit/libexpr/build-utils-meson +++ /dev/null @@ -1 +0,0 @@ -../../../build-utils-meson/ \ No newline at end of file diff --git a/tests/unit/libfetchers/.version b/tests/unit/libfetchers/.version deleted file mode 120000 index 0df9915bf..000000000 --- a/tests/unit/libfetchers/.version +++ /dev/null @@ -1 +0,0 @@ -../../../.version \ No newline at end of file diff --git a/tests/unit/libfetchers/build-utils-meson b/tests/unit/libfetchers/build-utils-meson deleted file mode 120000 index f2d8e8a50..000000000 --- a/tests/unit/libfetchers/build-utils-meson +++ /dev/null @@ -1 +0,0 @@ -../../../build-utils-meson/ \ No newline at end of file diff --git a/tests/unit/libflake/.version b/tests/unit/libflake/.version deleted file mode 120000 index 0df9915bf..000000000 --- a/tests/unit/libflake/.version +++ /dev/null @@ -1 +0,0 @@ -../../../.version \ No newline at end of file diff --git a/tests/unit/libflake/build-utils-meson b/tests/unit/libflake/build-utils-meson deleted file mode 120000 index f2d8e8a50..000000000 --- a/tests/unit/libflake/build-utils-meson +++ /dev/null @@ -1 +0,0 @@ -../../../build-utils-meson/ \ No newline at end of file diff --git a/tests/unit/libstore-support/.version b/tests/unit/libstore-support/.version deleted file mode 120000 index 0df9915bf..000000000 --- a/tests/unit/libstore-support/.version +++ /dev/null @@ -1 +0,0 @@ -../../../.version \ No newline at end of file diff --git a/tests/unit/libstore-support/build-utils-meson b/tests/unit/libstore-support/build-utils-meson deleted file mode 120000 index f2d8e8a50..000000000 --- a/tests/unit/libstore-support/build-utils-meson +++ /dev/null @@ -1 +0,0 @@ -../../../build-utils-meson/ \ No newline at end of file diff --git a/tests/unit/libstore/.version b/tests/unit/libstore/.version deleted file mode 120000 index 0df9915bf..000000000 --- a/tests/unit/libstore/.version +++ /dev/null @@ -1 +0,0 @@ -../../../.version \ No newline at end of file diff --git a/tests/unit/libstore/build-utils-meson b/tests/unit/libstore/build-utils-meson deleted file mode 120000 index f2d8e8a50..000000000 --- a/tests/unit/libstore/build-utils-meson +++ /dev/null @@ -1 +0,0 @@ -../../../build-utils-meson/ \ No newline at end of file diff --git a/tests/unit/libstore/data/derivation/advanced-attributes-defaults.drv b/tests/unit/libstore/data/derivation/advanced-attributes-defaults.drv deleted file mode 120000 index 353090ad8..000000000 --- a/tests/unit/libstore/data/derivation/advanced-attributes-defaults.drv +++ /dev/null @@ -1 +0,0 @@ -../../../../functional/derivation/advanced-attributes-defaults.drv \ No newline at end of file diff --git a/tests/unit/libstore/data/derivation/advanced-attributes-structured-attrs-defaults.drv b/tests/unit/libstore/data/derivation/advanced-attributes-structured-attrs-defaults.drv deleted file mode 120000 index 11713da12..000000000 --- a/tests/unit/libstore/data/derivation/advanced-attributes-structured-attrs-defaults.drv +++ /dev/null @@ -1 +0,0 @@ -../../../../functional/derivation/advanced-attributes-structured-attrs-defaults.drv \ No newline at end of file diff --git a/tests/unit/libstore/data/derivation/advanced-attributes-structured-attrs.drv b/tests/unit/libstore/data/derivation/advanced-attributes-structured-attrs.drv deleted file mode 120000 index 962f8ea3f..000000000 --- a/tests/unit/libstore/data/derivation/advanced-attributes-structured-attrs.drv +++ /dev/null @@ -1 +0,0 @@ -../../../../functional/derivation/advanced-attributes-structured-attrs.drv \ No newline at end of file diff --git a/tests/unit/libstore/data/derivation/advanced-attributes.drv b/tests/unit/libstore/data/derivation/advanced-attributes.drv deleted file mode 120000 index 2a53a05ca..000000000 --- a/tests/unit/libstore/data/derivation/advanced-attributes.drv +++ /dev/null @@ -1 +0,0 @@ -../../../../functional/derivation/advanced-attributes.drv \ No newline at end of file diff --git a/tests/unit/libutil-support/.version b/tests/unit/libutil-support/.version deleted file mode 120000 index 0df9915bf..000000000 --- a/tests/unit/libutil-support/.version +++ /dev/null @@ -1 +0,0 @@ -../../../.version \ No newline at end of file diff --git a/tests/unit/libutil-support/build-utils-meson b/tests/unit/libutil-support/build-utils-meson deleted file mode 120000 index f2d8e8a50..000000000 --- a/tests/unit/libutil-support/build-utils-meson +++ /dev/null @@ -1 +0,0 @@ -../../../build-utils-meson/ \ No newline at end of file diff --git a/tests/unit/libutil/.version b/tests/unit/libutil/.version deleted file mode 120000 index 0df9915bf..000000000 --- a/tests/unit/libutil/.version +++ /dev/null @@ -1 +0,0 @@ -../../../.version \ No newline at end of file diff --git a/tests/unit/libutil/build-utils-meson b/tests/unit/libutil/build-utils-meson deleted file mode 120000 index f2d8e8a50..000000000 --- a/tests/unit/libutil/build-utils-meson +++ /dev/null @@ -1 +0,0 @@ -../../../build-utils-meson/ \ No newline at end of file From defff01a51b3e3339ef2571d0321b3ebc6f5ebfc Mon Sep 17 00:00:00 2001 From: Eman Resu <78693624+llakala@users.noreply.github.com> Date: Fri, 18 Oct 2024 13:26:38 -0400 Subject: [PATCH 325/718] docs: clarify syntax for escaping dollar curlies --- doc/manual/source/language/string-literals.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/doc/manual/source/language/string-literals.md b/doc/manual/source/language/string-literals.md index 8f4b75f3e..ca064989a 100644 --- a/doc/manual/source/language/string-literals.md +++ b/doc/manual/source/language/string-literals.md @@ -150,6 +150,21 @@ These special characters are escaped as follows: `''\` escapes any other character. +A "dollar-curly" (`${`) can be written as follows: +> **Example** +> +> ```nix +> '' +> echo ''${PATH} +> '' +> ``` +> +> "echo ${PATH}\n" + +> **Note** +> +> This differs from the syntax for escaping a dollar-curly within double quotes (`"\${"`). Be aware of which one is needed at a given moment. + A "double-dollar-curly" (`$${`) can be written literally. > **Example** From 8277b50b6f6d8bbac7bbe4ba3a1009fe49a45990 Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman <145775305+xokdvium@users.noreply.github.com> Date: Sat, 19 Oct 2024 00:40:14 +0300 Subject: [PATCH 326/718] fix(nix/eval.cc): move call to `fs::create_directory` out of `assert` If the call is inside the assertion, then in non-assert builds the call would be stripped out. This is highly unexpected. --- src/nix/eval.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/nix/eval.cc b/src/nix/eval.cc index 04b18ff41..babf2ca32 100644 --- a/src/nix/eval.cc +++ b/src/nix/eval.cc @@ -89,8 +89,9 @@ struct CmdEval : MixJSON, InstallableValueCommand, MixReadOnlyOption // FIXME: disallow strings with contexts? writeFile(path.string(), v.string_view()); else if (v.type() == nAttrs) { + [[maybe_unused]] bool directoryCreated = fs::create_directory(path); // Directory should not already exist - assert(fs::create_directory(path.string())); + assert(directoryCreated); for (auto & attr : *v.attrs()) { std::string_view name = state->symbols[attr.name]; try { From 90d257b77168b73ebb7b41ae075ee1233bb79332 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Sun, 20 Oct 2024 19:31:16 +0200 Subject: [PATCH 327/718] doc: Explain why tryEval does not return the message --- src/libexpr/primops.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index a3c8a0c9c..203d10932 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -944,6 +944,9 @@ static RegisterPrimOp primop_tryEval({ `let e = { x = throw ""; }; in (builtins.tryEval (builtins.deepSeq e e)).success` will be `false`. + + `tryEval` intentionally does not return the error message, because that risks bringing non-determinism into the evaluation result, and it would become very difficult to improve error reporting without breaking existing expressions. + Instead, use [`builtins.addErrorContext`](@docroot@/language/builtins.md#builtins-addErrorContext) to add context to the error message, and use a Nix unit testing tool for testing. )", .fun = prim_tryEval, }); From 48a7ac23bc55c3465312ad4a2948106bc3271a5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Tue, 22 Oct 2024 09:33:04 +0200 Subject: [PATCH 328/718] make doxygen build more silent The buildoutput of doxygen often hides important build warnings and errors behind a wall of text. --- src/external-api-docs/doxygen.cfg.in | 2 ++ src/internal-api-docs/doxygen.cfg.in | 3 +++ 2 files changed, 5 insertions(+) diff --git a/src/external-api-docs/doxygen.cfg.in b/src/external-api-docs/doxygen.cfg.in index 1be71d895..7ae4c83df 100644 --- a/src/external-api-docs/doxygen.cfg.in +++ b/src/external-api-docs/doxygen.cfg.in @@ -56,3 +56,5 @@ GENERATE_TREEVIEW = YES OPTIMIZE_OUTPUT_FOR_C = YES USE_MDFILE_AS_MAINPAGE = doc/external-api/README.md + +QUIET = YES diff --git a/src/internal-api-docs/doxygen.cfg.in b/src/internal-api-docs/doxygen.cfg.in index 86c64a396..bf4c42d11 100644 --- a/src/internal-api-docs/doxygen.cfg.in +++ b/src/internal-api-docs/doxygen.cfg.in @@ -97,3 +97,6 @@ EXPAND_AS_DEFINED = \ DECLARE_WORKER_SERIALISER \ DECLARE_SERVE_SERIALISER \ LENGTH_PREFIXED_PROTO_HELPER + +WARN_IF_UNDOCUMENTED = NO +QUIET = YES From 2105574702b582578c43b551cfe8905715211f03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Fri, 18 Oct 2024 12:03:33 +0300 Subject: [PATCH 329/718] fix env-vars beeing written to `/tmp` This overall seems like insecure tmp file handling to me. Because other users could replace files in /tmp with a symlink and make the nix-shell override other files. fixes https://github.com/NixOS/nix/issues/11470 --- src/nix-build/nix-build.cc | 17 +++++------------ tests/functional/nix-shell.sh | 9 +++++++++ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc index 7d32a6f97..3222ab96d 100644 --- a/src/nix-build/nix-build.cc +++ b/src/nix-build/nix-build.cc @@ -526,8 +526,6 @@ static void main_nix_build(int argc, char * * argv) // Set the environment. auto env = getEnv(); - auto tmp = getEnvNonEmpty("TMPDIR").value_or("/tmp"); - if (pure) { decltype(env) newEnv; for (auto & i : env) @@ -538,18 +536,16 @@ static void main_nix_build(int argc, char * * argv) env["__ETC_PROFILE_SOURCED"] = "1"; } - env["NIX_BUILD_TOP"] = env["TMPDIR"] = env["TEMPDIR"] = env["TMP"] = env["TEMP"] = tmp; + env["NIX_BUILD_TOP"] = env["TMPDIR"] = env["TEMPDIR"] = env["TMP"] = env["TEMP"] = tmpDir.path(); env["NIX_STORE"] = store->storeDir; env["NIX_BUILD_CORES"] = std::to_string(settings.buildCores); auto passAsFile = tokenizeString(getOr(drv.env, "passAsFile", "")); - bool keepTmp = false; int fileNr = 0; for (auto & var : drv.env) if (passAsFile.count(var.first)) { - keepTmp = true; auto fn = ".attr-" + std::to_string(fileNr++); Path p = (tmpDir.path() / fn).string(); writeFile(p, var.second); @@ -591,7 +587,6 @@ static void main_nix_build(int argc, char * * argv) env["NIX_ATTRS_SH_FILE"] = attrsSH; env["NIX_ATTRS_JSON_FILE"] = attrsJSON; - keepTmp = true; } } @@ -601,12 +596,10 @@ static void main_nix_build(int argc, char * * argv) lose the current $PATH directories. */ auto rcfile = (tmpDir.path() / "rc").string(); std::string rc = fmt( - R"(_nix_shell_clean_tmpdir() { command rm -rf %1%; }; )"s + - (keepTmp ? - "trap _nix_shell_clean_tmpdir EXIT; " - "exitHooks+=(_nix_shell_clean_tmpdir); " - "failureHooks+=(_nix_shell_clean_tmpdir); ": - "_nix_shell_clean_tmpdir; ") + + (R"(_nix_shell_clean_tmpdir() { command rm -rf %1%; };)"s + "trap _nix_shell_clean_tmpdir EXIT; " + "exitHooks+=(_nix_shell_clean_tmpdir); " + "failureHooks+=(_nix_shell_clean_tmpdir); ") + (pure ? "" : "[ -n \"$PS1\" ] && [ -e ~/.bashrc ] && source ~/.bashrc;") + "%2%" // always clear PATH. diff --git a/tests/functional/nix-shell.sh b/tests/functional/nix-shell.sh index b9625eb66..b14e3dc6a 100755 --- a/tests/functional/nix-shell.sh +++ b/tests/functional/nix-shell.sh @@ -31,6 +31,15 @@ output=$(nix-shell --pure --keep SELECTED_IMPURE_VAR "$shellDotNix" -A shellDrv [ "$output" = " - foo - bar - baz" ] +# test NIX_BUILD_TOP +testTmpDir=$(pwd)/nix-shell +mkdir -p "$testTmpDir" +output=$(TMPDIR="$testTmpDir" nix-shell --pure "$shellDotNix" -A shellDrv --run 'echo $NIX_BUILD_TOP') +[[ "$output" =~ ${testTmpDir}.* ]] || { + echo "expected $output =~ ${testTmpDir}.*" >&2 + exit 1 +} + # Test nix-shell on a .drv [[ $(nix-shell --pure $(nix-instantiate "$shellDotNix" -A shellDrv) --run \ 'echo "$IMPURE_VAR - $VAR_FROM_STDENV_SETUP - $VAR_FROM_NIX - $TEST_inNixShell"') = " - foo - bar - false" ]] From 85b0cd320a1d3cdb9bcbfa650f7080839ab2fc55 Mon Sep 17 00:00:00 2001 From: Marian Hammer Date: Fri, 18 Oct 2024 11:06:41 +0200 Subject: [PATCH 330/718] nix/tests: run test help.sh only if nix is built with documentation tests/functional/help.sh calls nix-* commands with option --help if nix is built without documentation the option --help throws an error because the man page it wants to display is missing --- configure.ac | 4 ++++ package.nix | 3 ++- tests/functional/local.mk | 5 ++++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 198198dea..fc59904f3 100644 --- a/configure.ac +++ b/configure.ac @@ -170,6 +170,10 @@ AS_IF( [test "$ENABLE_FUNCTIONAL_TESTS" == "yes" || test "$ENABLE_DOC_GEN" == "yes"], [NEED_PROG(jq, jq)]) +AS_IF( + [test "$ENABLE_DOC_GEN" == "yes"], + [NEED_PROG(man, man)]) + AS_IF([test "$ENABLE_BUILD" == "yes"],[ # Look for boost, a required dependency. diff --git a/package.nix b/package.nix index 00621d475..658f2275f 100644 --- a/package.nix +++ b/package.nix @@ -207,9 +207,10 @@ in { git mercurial openssh - man # for testing `nix-* --help` ] ++ lib.optionals (doInstallCheck || enableManual) [ jq # Also for custom mdBook preprocessor. + ] ++ lib.optionals enableManual [ + man ] ++ lib.optional stdenv.hostPlatform.isStatic unixtools.hexdump ; diff --git a/tests/functional/local.mk b/tests/functional/local.mk index 3f796291a..e50b5eaf1 100644 --- a/tests/functional/local.mk +++ b/tests/functional/local.mk @@ -114,7 +114,6 @@ nix_tests = \ impure-env.sh \ debugger.sh \ extra-sandbox-profile.sh \ - help.sh ifeq ($(HAVE_LIBCPUID), 1) nix_tests += compute-levels.sh @@ -128,6 +127,10 @@ ifeq ($(ENABLE_BUILD), yes) endif endif +ifeq ($(ENABLE_DOC_GEN), yes) + nix_tests += help.sh +endif + $(d)/test-libstoreconsumer.sh.test $(d)/test-libstoreconsumer.sh.test-debug: \ $(buildprefix)$(d)/test-libstoreconsumer/test-libstoreconsumer $(d)/plugins.sh.test $(d)/plugins.sh.test-debug: \ From d2c880b03f58eb4fdd6d19eb3ffa4345a0477419 Mon Sep 17 00:00:00 2001 From: Puck Meerburg Date: Fri, 1 Mar 2024 11:42:24 -0500 Subject: [PATCH 331/718] fix: Run all derivation builders inside the sandbox on macOS --- configure.ac | 6 +- package.nix | 2 + .../unix/build/local-derivation-goal.cc | 237 +++++++++--------- 3 files changed, 123 insertions(+), 122 deletions(-) diff --git a/configure.ac b/configure.ac index 198198dea..c7c9b3f4b 100644 --- a/configure.ac +++ b/configure.ac @@ -62,12 +62,16 @@ AC_CHECK_TOOL([AR], [ar]) AC_SYS_LARGEFILE -# Solaris-specific stuff. +# OS-specific stuff. case "$host_os" in solaris*) # Solaris requires -lsocket -lnsl for network functions LDFLAGS="-lsocket -lnsl $LDFLAGS" ;; + darwin*) + # Need to link to libsandbox. + LDFLAGS="-lsandbox $LDFLAGS" + ;; esac diff --git a/package.nix b/package.nix index 00621d475..77f1de58c 100644 --- a/package.nix +++ b/package.nix @@ -23,6 +23,7 @@ , libseccomp , libsodium , man +, darwin , lowdown , mdbook , mdbook-linkcheck @@ -232,6 +233,7 @@ in { gtest rapidcheck ] ++ lib.optional stdenv.isLinux libseccomp + ++ lib.optional stdenv.hostPlatform.isDarwin darwin.apple_sdk.libs.sandbox ++ lib.optional stdenv.hostPlatform.isx86_64 libcpuid # There have been issues building these dependencies ++ lib.optional (stdenv.hostPlatform == stdenv.buildPlatform && (stdenv.isLinux || stdenv.isDarwin)) diff --git a/src/libstore/unix/build/local-derivation-goal.cc b/src/libstore/unix/build/local-derivation-goal.cc index b4685b3a7..067755c0d 100644 --- a/src/libstore/unix/build/local-derivation-goal.cc +++ b/src/libstore/unix/build/local-derivation-goal.cc @@ -58,6 +58,10 @@ #if __APPLE__ #include #include +#include + +/* This definition is undocumented but depended upon by all major browsers. */ +extern "C" int sandbox_init_with_parameters(const char *profile, uint64_t flags, const char *const parameters[], char **errorbuf); #endif #include @@ -2088,141 +2092,132 @@ void LocalDerivationGoal::runChild() std::string builder = "invalid"; - if (drv->isBuiltin()) { - ; - } #if __APPLE__ - else { - /* This has to appear before import statements. */ - std::string sandboxProfile = "(version 1)\n"; + /* This has to appear before import statements. */ + std::string sandboxProfile = "(version 1)\n"; - if (useChroot) { + if (useChroot) { - /* Lots and lots and lots of file functions freak out if they can't stat their full ancestry */ - PathSet ancestry; + /* Lots and lots and lots of file functions freak out if they can't stat their full ancestry */ + PathSet ancestry; - /* We build the ancestry before adding all inputPaths to the store because we know they'll - all have the same parents (the store), and there might be lots of inputs. This isn't - particularly efficient... I doubt it'll be a bottleneck in practice */ - for (auto & i : pathsInChroot) { - Path cur = i.first; - while (cur.compare("/") != 0) { - cur = dirOf(cur); - ancestry.insert(cur); - } - } - - /* And we want the store in there regardless of how empty pathsInChroot. We include the innermost - path component this time, since it's typically /nix/store and we care about that. */ - Path cur = worker.store.storeDir; + /* We build the ancestry before adding all inputPaths to the store because we know they'll + all have the same parents (the store), and there might be lots of inputs. This isn't + particularly efficient... I doubt it'll be a bottleneck in practice */ + for (auto & i : pathsInChroot) { + Path cur = i.first; while (cur.compare("/") != 0) { - ancestry.insert(cur); cur = dirOf(cur); + ancestry.insert(cur); } + } - /* Add all our input paths to the chroot */ - for (auto & i : inputPaths) { - auto p = worker.store.printStorePath(i); - pathsInChroot[p] = p; - } + /* And we want the store in there regardless of how empty pathsInChroot. We include the innermost + path component this time, since it's typically /nix/store and we care about that. */ + Path cur = worker.store.storeDir; + while (cur.compare("/") != 0) { + ancestry.insert(cur); + cur = dirOf(cur); + } - /* Violations will go to the syslog if you set this. Unfortunately the destination does not appear to be configurable */ - if (settings.darwinLogSandboxViolations) { - sandboxProfile += "(deny default)\n"; - } else { - sandboxProfile += "(deny default (with no-log))\n"; - } + /* Add all our input paths to the chroot */ + for (auto & i : inputPaths) { + auto p = worker.store.printStorePath(i); + pathsInChroot[p] = p; + } - sandboxProfile += - #include "sandbox-defaults.sb" - ; - - if (!derivationType->isSandboxed()) - sandboxProfile += - #include "sandbox-network.sb" - ; - - /* Add the output paths we'll use at build-time to the chroot */ - sandboxProfile += "(allow file-read* file-write* process-exec\n"; - for (auto & [_, path] : scratchOutputs) - sandboxProfile += fmt("\t(subpath \"%s\")\n", worker.store.printStorePath(path)); - - sandboxProfile += ")\n"; - - /* Our inputs (transitive dependencies and any impurities computed above) - - without file-write* allowed, access() incorrectly returns EPERM - */ - sandboxProfile += "(allow file-read* file-write* process-exec\n"; - for (auto & i : pathsInChroot) { - if (i.first != i.second.source) - throw Error( - "can't map '%1%' to '%2%': mismatched impure paths not supported on Darwin", - i.first, i.second.source); - - std::string path = i.first; - auto optSt = maybeLstat(path.c_str()); - if (!optSt) { - if (i.second.optional) - continue; - throw SysError("getting attributes of required path '%s", path); - } - if (S_ISDIR(optSt->st_mode)) - sandboxProfile += fmt("\t(subpath \"%s\")\n", path); - else - sandboxProfile += fmt("\t(literal \"%s\")\n", path); - } - sandboxProfile += ")\n"; - - /* Allow file-read* on full directory hierarchy to self. Allows realpath() */ - sandboxProfile += "(allow file-read*\n"; - for (auto & i : ancestry) { - sandboxProfile += fmt("\t(literal \"%s\")\n", i); - } - sandboxProfile += ")\n"; - - sandboxProfile += additionalSandboxProfile; - } else - sandboxProfile += - #include "sandbox-minimal.sb" - ; - - debug("Generated sandbox profile:"); - debug(sandboxProfile); - - Path sandboxFile = tmpDir + "/.sandbox.sb"; - - writeFile(sandboxFile, sandboxProfile); - - bool allowLocalNetworking = parsedDrv->getBoolAttr("__darwinAllowLocalNetworking"); - - /* The tmpDir in scope points at the temporary build directory for our derivation. Some packages try different mechanisms - to find temporary directories, so we want to open up a broader place for them to put their files, if needed. */ - Path globalTmpDir = canonPath(defaultTempDir(), true); - - /* They don't like trailing slashes on subpath directives */ - while (!globalTmpDir.empty() && globalTmpDir.back() == '/') - globalTmpDir.pop_back(); - - if (getEnv("_NIX_TEST_NO_SANDBOX") != "1") { - builder = "/usr/bin/sandbox-exec"; - args.push_back("sandbox-exec"); - args.push_back("-f"); - args.push_back(sandboxFile); - args.push_back("-D"); - args.push_back("_GLOBAL_TMP_DIR=" + globalTmpDir); - if (allowLocalNetworking) { - args.push_back("-D"); - args.push_back(std::string("_ALLOW_LOCAL_NETWORKING=1")); - } - args.push_back(drv->builder); + /* Violations will go to the syslog if you set this. Unfortunately the destination does not appear to be configurable */ + if (settings.darwinLogSandboxViolations) { + sandboxProfile += "(deny default)\n"; } else { - builder = drv->builder; - args.push_back(std::string(baseNameOf(drv->builder))); + sandboxProfile += "(deny default (with no-log))\n"; + } + + sandboxProfile += + #include "sandbox-defaults.sb" + ; + + if (!derivationType->isSandboxed()) + sandboxProfile += + #include "sandbox-network.sb" + ; + + /* Add the output paths we'll use at build-time to the chroot */ + sandboxProfile += "(allow file-read* file-write* process-exec\n"; + for (auto & [_, path] : scratchOutputs) + sandboxProfile += fmt("\t(subpath \"%s\")\n", worker.store.printStorePath(path)); + + sandboxProfile += ")\n"; + + /* Our inputs (transitive dependencies and any impurities computed above) + + without file-write* allowed, access() incorrectly returns EPERM + */ + sandboxProfile += "(allow file-read* file-write* process-exec\n"; + for (auto & i : pathsInChroot) { + if (i.first != i.second.source) + throw Error( + "can't map '%1%' to '%2%': mismatched impure paths not supported on Darwin", + i.first, i.second.source); + + std::string path = i.first; + auto optSt = maybeLstat(path.c_str()); + if (!optSt) { + if (i.second.optional) + continue; + throw SysError("getting attributes of required path '%s", path); + } + if (S_ISDIR(optSt->st_mode)) + sandboxProfile += fmt("\t(subpath \"%s\")\n", path); + else + sandboxProfile += fmt("\t(literal \"%s\")\n", path); + } + sandboxProfile += ")\n"; + + /* Allow file-read* on full directory hierarchy to self. Allows realpath() */ + sandboxProfile += "(allow file-read*\n"; + for (auto & i : ancestry) { + sandboxProfile += fmt("\t(literal \"%s\")\n", i); + } + sandboxProfile += ")\n"; + + sandboxProfile += additionalSandboxProfile; + } else + sandboxProfile += + #include "sandbox-minimal.sb" + ; + + debug("Generated sandbox profile:"); + debug(sandboxProfile); + + bool allowLocalNetworking = parsedDrv->getBoolAttr("__darwinAllowLocalNetworking"); + + /* The tmpDir in scope points at the temporary build directory for our derivation. Some packages try different mechanisms + to find temporary directories, so we want to open up a broader place for them to put their files, if needed. */ + Path globalTmpDir = canonPath(defaultTempDir(), true); + + /* They don't like trailing slashes on subpath directives */ + while (!globalTmpDir.empty() && globalTmpDir.back() == '/') + globalTmpDir.pop_back(); + + if (getEnv("_NIX_TEST_NO_SANDBOX") != "1") { + Strings sandboxArgs; + sandboxArgs.push_back("_GLOBAL_TMP_DIR"); + sandboxArgs.push_back(globalTmpDir); + if (allowLocalNetworking) { + sandboxArgs.push_back("_ALLOW_LOCAL_NETWORKING"); + sandboxArgs.push_back("1"); + } + if (sandbox_init_with_parameters(sandboxProfile.c_str(), 0, stringsToCharPtrs(sandboxArgs).data(), NULL)) { + writeFull(STDERR_FILENO, "failed to configure sandbox\n"); + _exit(1); } } + + builder = drv->builder; + args.push_back(std::string(baseNameOf(drv->builder))); #else - else { + if (!drv->isBuiltin()) { builder = drv->builder; args.push_back(std::string(baseNameOf(drv->builder))); } From f7335530619f9b18d6cc249a297e4dca369101a5 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Thu, 3 Oct 2024 12:23:17 +0200 Subject: [PATCH 332/718] packaging: Add darwin -lsandbox in meson --- src/libstore/meson.build | 5 +++++ src/libstore/package.nix | 2 ++ 2 files changed, 7 insertions(+) diff --git a/src/libstore/meson.build b/src/libstore/meson.build index 6a6aabf97..c2aa5bff3 100644 --- a/src/libstore/meson.build +++ b/src/libstore/meson.build @@ -69,6 +69,11 @@ has_acl_support = cxx.has_header('sys/xattr.h') \ and cxx.has_function('lremovexattr') configdata.set('HAVE_ACL_SUPPORT', has_acl_support.to_int()) +if host_machine.system() == 'darwin' + sandbox = cxx.find_library('sandbox') + deps_other += [sandbox] +endif + subdir('build-utils-meson/threads') boost = dependency( diff --git a/src/libstore/package.nix b/src/libstore/package.nix index 9568462b5..f04e3b95f 100644 --- a/src/libstore/package.nix +++ b/src/libstore/package.nix @@ -3,6 +3,7 @@ , mkMesonLibrary , unixtools +, darwin , nix-util , boost @@ -56,6 +57,7 @@ mkMesonLibrary (finalAttrs: { sqlite ] ++ lib.optional stdenv.hostPlatform.isLinux libseccomp # There have been issues building these dependencies + ++ lib.optional stdenv.hostPlatform.isDarwin darwin.apple_sdk.libs.sandbox ++ lib.optional (stdenv.hostPlatform == stdenv.buildPlatform && (stdenv.isLinux || stdenv.isDarwin)) aws-sdk-cpp ; From 14d09e0b55898ac22d4cdeade3bf6c4174052ffd Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Thu, 3 Oct 2024 12:44:12 +0200 Subject: [PATCH 333/718] local-derivation-goal: Print sandbox error detail on darwin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Théophane Hufschmitt --- src/libstore/unix/build/local-derivation-goal.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libstore/unix/build/local-derivation-goal.cc b/src/libstore/unix/build/local-derivation-goal.cc index 067755c0d..f34d68403 100644 --- a/src/libstore/unix/build/local-derivation-goal.cc +++ b/src/libstore/unix/build/local-derivation-goal.cc @@ -2208,8 +2208,9 @@ void LocalDerivationGoal::runChild() sandboxArgs.push_back("_ALLOW_LOCAL_NETWORKING"); sandboxArgs.push_back("1"); } - if (sandbox_init_with_parameters(sandboxProfile.c_str(), 0, stringsToCharPtrs(sandboxArgs).data(), NULL)) { - writeFull(STDERR_FILENO, "failed to configure sandbox\n"); + char * sandbox_errbuf = nullptr; + if (sandbox_init_with_parameters(sandboxProfile.c_str(), 0, stringsToCharPtrs(sandboxArgs).data(), &sandbox_errbuf)) { + writeFull(STDERR_FILENO, fmt("failed to configure sandbox: %s\n", sandbox_errbuf ? sandbox_errbuf : "(null)")); _exit(1); } } From 06e27042e176b79561f50decb0fdf836b7bec3f5 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Thu, 3 Oct 2024 12:50:27 +0200 Subject: [PATCH 334/718] local-derivation-goal: Refactor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This works because the `builder` and `args` variables are only used in the non-builtin code path. Co-Authored-By: Théophane Hufschmitt --- src/libstore/unix/build/local-derivation-goal.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/libstore/unix/build/local-derivation-goal.cc b/src/libstore/unix/build/local-derivation-goal.cc index f34d68403..f781a84c6 100644 --- a/src/libstore/unix/build/local-derivation-goal.cc +++ b/src/libstore/unix/build/local-derivation-goal.cc @@ -2214,15 +2214,12 @@ void LocalDerivationGoal::runChild() _exit(1); } } +#endif - builder = drv->builder; - args.push_back(std::string(baseNameOf(drv->builder))); -#else if (!drv->isBuiltin()) { builder = drv->builder; args.push_back(std::string(baseNameOf(drv->builder))); } -#endif for (auto & i : drv->args) args.push_back(rewriteStrings(i, inputRewrites)); From 766263d53ae69d70c5915426e6e8f58abd988226 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Tue, 22 Oct 2024 15:28:04 +0200 Subject: [PATCH 335/718] Fix meson build on darwin std::stringbuf is defined in --- src/libutil/strings.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libutil/strings.cc b/src/libutil/strings.cc index d1c9f700c..c221a43c6 100644 --- a/src/libutil/strings.cc +++ b/src/libutil/strings.cc @@ -1,5 +1,6 @@ #include #include +#include #include "strings-inline.hh" #include "os-string.hh" From d1e0bae55afb3c3ef0bcad5d644b0e04da6279b3 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Thu, 3 Oct 2024 12:57:00 +0200 Subject: [PATCH 336/718] local-derivation-goal: Move builder preparation to non-builtin code path --- .../unix/build/local-derivation-goal.cc | 25 ++++++++----------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/src/libstore/unix/build/local-derivation-goal.cc b/src/libstore/unix/build/local-derivation-goal.cc index f781a84c6..dcfaadeef 100644 --- a/src/libstore/unix/build/local-derivation-goal.cc +++ b/src/libstore/unix/build/local-derivation-goal.cc @@ -2087,11 +2087,6 @@ void LocalDerivationGoal::runChild() throw SysError("setuid failed"); } - /* Fill in the arguments. */ - Strings args; - - std::string builder = "invalid"; - #if __APPLE__ /* This has to appear before import statements. */ std::string sandboxProfile = "(version 1)\n"; @@ -2216,14 +2211,6 @@ void LocalDerivationGoal::runChild() } #endif - if (!drv->isBuiltin()) { - builder = drv->builder; - args.push_back(std::string(baseNameOf(drv->builder))); - } - - for (auto & i : drv->args) - args.push_back(rewriteStrings(i, inputRewrites)); - /* Indicate that we managed to set up the build environment. */ writeFull(STDERR_FILENO, std::string("\2\n")); @@ -2254,6 +2241,14 @@ void LocalDerivationGoal::runChild() } } + // Now builder is not builtin + + Strings args; + args.push_back(std::string(baseNameOf(drv->builder))); + + for (auto & i : drv->args) + args.push_back(rewriteStrings(i, inputRewrites)); + #if __APPLE__ posix_spawnattr_t attrp; @@ -2275,9 +2270,9 @@ void LocalDerivationGoal::runChild() posix_spawnattr_setbinpref_np(&attrp, 1, &cpu, NULL); } - posix_spawn(NULL, builder.c_str(), NULL, &attrp, stringsToCharPtrs(args).data(), stringsToCharPtrs(envStrs).data()); + posix_spawn(NULL, drv->builder.c_str(), NULL, &attrp, stringsToCharPtrs(args).data(), stringsToCharPtrs(envStrs).data()); #else - execve(builder.c_str(), stringsToCharPtrs(args).data(), stringsToCharPtrs(envStrs).data()); + execve(drv->builder.c_str(), stringsToCharPtrs(args).data(), stringsToCharPtrs(envStrs).data()); #endif throw SysError("executing '%1%'", drv->builder); From e1834f4caaa77d3b0dafc4b79e5d10ced0526419 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Mon, 21 Oct 2024 16:32:53 +0200 Subject: [PATCH 337/718] warn-large-path-threshold: define 0 as number to disable warnings the default int64_t max was still overflowing for me, when this was dumped as json (noticed during building the manual). So making 0, the default and define it as "no warnings" fixes the situtation. Also it's much more human-readable in documentation. --- src/libstore/globals.hh | 7 +++---- src/libstore/store-api.cc | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh index be922c9f7..ff3df46ba 100644 --- a/src/libstore/globals.hh +++ b/src/libstore/globals.hh @@ -1227,14 +1227,13 @@ public: Setting warnLargePathThreshold{ this, - // n.b. this is deliberately int64 max rather than uint64 max because - // this goes through the Nix language JSON parser and thus needs to be - // representable in Nix language integers. - std::numeric_limits::max(), + 0, "warn-large-path-threshold", R"( Warn when copying a path larger than this number of bytes to the Nix store (as determined by its NAR serialisation). + Default is 0, which disables the warning. + Set it to 1 to warn on all paths. )" }; }; diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index 8109ea322..10577fa2a 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -171,7 +171,7 @@ std::pair StoreDirConfig::computeStorePath( PathFilter & filter) const { auto [h, size] = hashPath(path, method.getFileIngestionMethod(), hashAlgo, filter); - if (size && *size >= settings.warnLargePathThreshold) + if (settings.warnLargePathThreshold && size && *size >= settings.warnLargePathThreshold) warn("hashed large path '%s' (%s)", path, renderSize(*size)); return { makeFixedOutputPathFromCA( @@ -214,7 +214,7 @@ StorePath Store::addToStore( auto sink = sourceToSink([&](Source & source) { LengthSource lengthSource(source); storePath = addToStoreFromDump(lengthSource, name, fsm, method, hashAlgo, references, repair); - if (lengthSource.total >= settings.warnLargePathThreshold) + if (settings.warnLargePathThreshold && lengthSource.total >= settings.warnLargePathThreshold) warn("copied large path '%s' to the store (%s)", path, renderSize(lengthSource.total)); }); dumpPath(path, *sink, fsm, filter); From e09666d3147b1b1cfca8e4c037c5b53fbb1a3089 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 22 Oct 2024 22:05:48 +0200 Subject: [PATCH 338/718] Fix test name --- tests/nixos/s3-binary-cache-store.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/nixos/s3-binary-cache-store.nix b/tests/nixos/s3-binary-cache-store.nix index 6ae2e3572..6c51fcba5 100644 --- a/tests/nixos/s3-binary-cache-store.nix +++ b/tests/nixos/s3-binary-cache-store.nix @@ -12,7 +12,7 @@ let storeUrl = "s3://my-cache?endpoint=http://server:9000®ion=eu-west-1"; in { - name = "nix-copy-closure"; + name = "s3-binary-cache-store"; nodes = { server = From 75016c26f99cb5df553db39374c719909f29d7ee Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 22 Oct 2024 22:23:16 +0200 Subject: [PATCH 339/718] Add a test for chroot stores --- tests/nixos/chroot-store.nix | 31 +++++++++++++++++++++++++++++++ tests/nixos/default.nix | 2 ++ 2 files changed, 33 insertions(+) create mode 100644 tests/nixos/chroot-store.nix diff --git a/tests/nixos/chroot-store.nix b/tests/nixos/chroot-store.nix new file mode 100644 index 000000000..4b167fc38 --- /dev/null +++ b/tests/nixos/chroot-store.nix @@ -0,0 +1,31 @@ +{ lib, config, nixpkgs, ... }: + +let + pkgs = config.nodes.machine.nixpkgs.pkgs; + pkgA = pkgs.hello; + pkgB = pkgs.cowsay; +in { + name = "chroot-store"; + + nodes = + { machine = + { config, lib, pkgs, ... }: + { virtualisation.writableStore = true; + virtualisation.additionalPaths = [ pkgA ]; + environment.systemPackages = [ pkgB ]; + nix.extraOptions = "experimental-features = nix-command"; + }; + }; + + testScript = { nodes }: '' + # fmt: off + start_all() + + machine.succeed("nix copy --no-check-sigs --to /tmp/nix ${pkgA}") + + machine.succeed("nix shell --store /tmp/nix ${pkgA} --command hello >&2") + + # Test that /nix/store is available via an overlayfs mount. + machine.succeed("nix shell --store /tmp/nix ${pkgA} --command cowsay foo >&2") + ''; +} diff --git a/tests/nixos/default.nix b/tests/nixos/default.nix index c61a2888f..49e2603e1 100644 --- a/tests/nixos/default.nix +++ b/tests/nixos/default.nix @@ -161,4 +161,6 @@ in cgroups = runNixOSTestFor "x86_64-linux" ./cgroups; fetchurl = runNixOSTestFor "x86_64-linux" ./fetchurl.nix; + + chrootStore = runNixOSTestFor "x86_64-linux" ./chroot-store.nix; } From c49bff2434971d693b03525622082a81b5ed75eb Mon Sep 17 00:00:00 2001 From: Artemis Tosini Date: Thu, 24 Oct 2024 21:24:47 +0000 Subject: [PATCH 340/718] Fix OpenBSD build with Makefiles OpenBSD dynamic libraries never link to libc directly. Instead, they have undefined symbols for all libc functions they use that ld.so resolves to the libc referred to in the main executable. Thus, disallowing undefined symbols will always fail --- mk/libraries.mk | 4 +++- mk/platform.mk | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/mk/libraries.mk b/mk/libraries.mk index b99ba2782..a7848ba35 100644 --- a/mk/libraries.mk +++ b/mk/libraries.mk @@ -86,7 +86,9 @@ define build-library else ifndef HOST_DARWIN ifndef HOST_WINDOWS - $(1)_LDFLAGS += -Wl,-z,defs + ifndef HOST_OPENBSD + $(1)_LDFLAGS += -Wl,-z,defs + endif endif endif endif diff --git a/mk/platform.mk b/mk/platform.mk index 22c114a20..3c4fff780 100644 --- a/mk/platform.mk +++ b/mk/platform.mk @@ -21,6 +21,10 @@ ifdef HOST_OS HOST_NETBSD = 1 HOST_UNIX = 1 endif + ifeq ($(patsubst openbsd%,,$(HOST_KERNEL)),) + HOST_OPENBSD = 1 + HOST_UNIX = 1 + endif ifeq ($(HOST_KERNEL), linux) HOST_LINUX = 1 HOST_UNIX = 1 From 27ea43781371cad717077ae723b11a79c0d0fc78 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 10 Oct 2024 16:54:11 +0200 Subject: [PATCH 341/718] Support fine-grained database schema migrations Backward-compatible schema changes (e.g. those that add tables or nullable columns) now no longer need a change to the global schema file (/nix/var/nix/db/schema). Thus, old Nix versions can continue to access the database. This is especially useful for schema changes required by experimental features. In particular, it replaces the ad-hoc handling of the schema changes for CA derivations (i.e. the file /nix/var/nix/db/ca-schema). Schema versions 8 and 10 could have been handled by this mechanism in a backward-compatible way as well. --- src/libstore/local-store.cc | 105 ++++++++++++++++++------------------ src/libstore/local-store.hh | 2 + 2 files changed, 54 insertions(+), 53 deletions(-) diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index eafdac0cd..f708bd1b0 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -95,51 +95,6 @@ struct LocalStore::State::Stmts { SQLiteStmt AddRealisationReference; }; -static int getSchema(Path schemaPath) -{ - int curSchema = 0; - if (pathExists(schemaPath)) { - auto s = readFile(schemaPath); - auto n = string2Int(s); - if (!n) - throw Error("'%1%' is corrupt", schemaPath); - curSchema = *n; - } - return curSchema; -} - -void migrateCASchema(SQLite& db, Path schemaPath, AutoCloseFD& lockFd) -{ - const int nixCASchemaVersion = 4; - int curCASchema = getSchema(schemaPath); - if (curCASchema != nixCASchemaVersion) { - if (curCASchema > nixCASchemaVersion) { - throw Error("current Nix store ca-schema is version %1%, but I only support %2%", - curCASchema, nixCASchemaVersion); - } - - if (!lockFile(lockFd.get(), ltWrite, false)) { - printInfo("waiting for exclusive access to the Nix store for ca drvs..."); - lockFile(lockFd.get(), ltNone, false); // We have acquired a shared lock; release it to prevent deadlocks - lockFile(lockFd.get(), ltWrite, true); - } - - if (curCASchema == 0) { - static const char schema[] = - #include "ca-specific-schema.sql.gen.hh" - ; - db.exec(schema); - curCASchema = nixCASchemaVersion; - } - - if (curCASchema < 4) - throw Error("experimental CA schema version %d is no longer supported", curCASchema); - - writeFile(schemaPath, fmt("%d", nixCASchemaVersion), 0666, true); - lockFile(lockFd.get(), ltRead, true); - } -} - LocalStore::LocalStore( std::string_view scheme, PathView path, @@ -316,6 +271,10 @@ LocalStore::LocalStore( openDB(*state, false); + /* Legacy database schema migrations. Don't bump 'schema' for + new migrations; instead, add a migration to + upgradeDBSchema(). */ + if (curSchema < 8) { SQLiteTxn txn(state->db); state->db.exec("alter table ValidPaths add column ultimate integer"); @@ -342,13 +301,7 @@ LocalStore::LocalStore( else openDB(*state, false); - if (experimentalFeatureSettings.isEnabled(Xp::CaDerivations)) { - if (!readOnly) { - migrateCASchema(state->db, dbDir + "/ca-schema", globalLock); - } else { - throw Error("need to migrate to content-addressed schema, but this cannot be done in read-only mode"); - } - } + upgradeDBSchema(*state); /* Prepare SQL statements. */ state->stmts->RegisterValidPath.create(state->db, @@ -483,7 +436,17 @@ std::string LocalStore::getUri() int LocalStore::getSchema() -{ return nix::getSchema(schemaPath); } +{ + int curSchema = 0; + if (pathExists(schemaPath)) { + auto s = readFile(schemaPath); + auto n = string2Int(s); + if (!n) + throw Error("'%1%' is corrupt", schemaPath); + curSchema = *n; + } + return curSchema; +} void LocalStore::openDB(State & state, bool create) { @@ -566,6 +529,42 @@ void LocalStore::openDB(State & state, bool create) } +void LocalStore::upgradeDBSchema(State & state) +{ + state.db.exec("create table if not exists SchemaMigrations (migration text primary key not null);"); + + std::set schemaMigrations; + + { + SQLiteStmt querySchemaMigrations; + querySchemaMigrations.create(state.db, "select migration from SchemaMigrations;"); + auto useQuerySchemaMigrations(querySchemaMigrations.use()); + while (useQuerySchemaMigrations.next()) + schemaMigrations.insert(useQuerySchemaMigrations.getStr(0)); + } + + auto doUpgrade = [&](const std::string & migrationName, const std::string & stmt) + { + if (schemaMigrations.contains(migrationName)) + return; + + debug("executing Nix database schema migration '%s'...", migrationName); + + SQLiteTxn txn(state.db); + state.db.exec(stmt + fmt(";\ninsert into SchemaMigrations values('%s')", migrationName)); + txn.commit(); + + schemaMigrations.insert(migrationName); + }; + + if (experimentalFeatureSettings.isEnabled(Xp::CaDerivations)) + doUpgrade( + "20220326-ca-derivations", + #include "ca-specific-schema.sql.gen.hh" + ); +} + + /* To improve purity, users may want to make the Nix store a read-only bind mount. So make the Nix store writable for this process. */ void LocalStore::makeStoreWritable() diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh index 21848cc4d..83154d651 100644 --- a/src/libstore/local-store.hh +++ b/src/libstore/local-store.hh @@ -356,6 +356,8 @@ private: void openDB(State & state, bool create); + void upgradeDBSchema(State & state); + void makeStoreWritable(); uint64_t queryValidPathId(State & state, const StorePath & path); From fecc1ca2055ee590d8b957830f70512fcecbfe4b Mon Sep 17 00:00:00 2001 From: Artemis Tosini Date: Sat, 26 Oct 2024 16:46:32 +0000 Subject: [PATCH 342/718] package.nix: Disable GC on OpenBSD Nix fails to build on OpenBSD with a linking error due to a non-found symbol in boehm-gc. Just disable the GC until we can find a proper workaround. --- package.nix | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package.nix b/package.nix index 658f2275f..42fd9b683 100644 --- a/package.nix +++ b/package.nix @@ -76,7 +76,9 @@ # # Temporarily disabled on Windows because the `GC_throw_bad_alloc` # symbol is missing during linking. -, enableGC ? !stdenv.hostPlatform.isWindows +# +# Disabled on OpenBSD because of missing `_data_start` symbol while linking +, enableGC ? !stdenv.hostPlatform.isWindows && !stdenv.hostPlatform.isOpenBSD # Whether to enable Markdown rendering in the Nix binary. , enableMarkdown ? !stdenv.hostPlatform.isWindows From d0232028111ce4f5a066d9a302fec142ebe91037 Mon Sep 17 00:00:00 2001 From: Artemis Tosini Date: Sat, 26 Oct 2024 17:12:06 +0000 Subject: [PATCH 343/718] Add support for `utimensat` as an alternative to `lutimes` OpenBSD doesn't support `lutimes`, but does support `utimensat` which subsumes it. In fact, all the BSDs, Linux, and newer macOS all support it. So lets make this our first choice for the implementation. In addition, let's get rid of the `lutimes` `ENOSYS` special case. The Linux manpage says > ENOSYS > > The kernel does not support this call; Linux 2.6.22 or later is > required. which I think is the origin of this check, but that's a very old version of Linux at this point. The code can be simplified a lot of we drop support for it here (as we've done elsewhere, anyways). Co-Authored-By: John Ericson --- configure.ac | 7 ++-- src/libutil/file-system.cc | 70 +++++++++++++++++++------------------- src/libutil/meson.build | 4 +++ 3 files changed, 43 insertions(+), 38 deletions(-) diff --git a/configure.ac b/configure.ac index fc59904f3..746e953dd 100644 --- a/configure.ac +++ b/configure.ac @@ -89,9 +89,10 @@ AC_LANG_POP(C++) AC_CHECK_FUNCS([statvfs pipe2 close_range]) -# Check for lutimes, optionally used for changing the mtime of -# symlinks. -AC_CHECK_FUNCS([lutimes]) +# Check for lutimes and utimensat, optionally used for changing the +# mtime of symlinks. +AC_CHECK_DECLS([AT_SYMLINK_NOFOLLOW], [], [], [[#include ]]) +AC_CHECK_FUNCS([lutimes utimensat]) # Check whether the store optimiser can optimise symlinks. diff --git a/src/libutil/file-system.cc b/src/libutil/file-system.cc index 224b78b23..fd51d7d3c 100644 --- a/src/libutil/file-system.cc +++ b/src/libutil/file-system.cc @@ -630,7 +630,28 @@ void setWriteTime( time_t modificationTime, std::optional optIsSymlink) { -#ifndef _WIN32 +#ifdef _WIN32 + // FIXME use `fs::last_write_time`. + // + // Would be nice to use std::filesystem unconditionally, but + // doesn't support access time just modification time. + // + // System clock vs File clock issues also make that annoying. + warn("Changing file times is not yet implemented on Windows, path is '%s'", path); +#elif HAVE_UTIMENSAT && HAVE_DECL_AT_SYMLINK_NOFOLLOW + struct timespec times[2] = { + { + .tv_sec = accessedTime, + .tv_nsec = 0, + }, + { + .tv_sec = modificationTime, + .tv_nsec = 0, + }, + }; + if (utimensat(AT_FDCWD, path.c_str(), times, AT_SYMLINK_NOFOLLOW) == -1) + throw SysError("changing modification time of '%s' (using `utimensat`)", path); +#else struct timeval times[2] = { { .tv_sec = accessedTime, @@ -641,42 +662,21 @@ void setWriteTime( .tv_usec = 0, }, }; -#endif - - auto nonSymlink = [&]{ - bool isSymlink = optIsSymlink - ? *optIsSymlink - : fs::is_symlink(path); - - if (!isSymlink) { -#ifdef _WIN32 - // FIXME use `fs::last_write_time`. - // - // Would be nice to use std::filesystem unconditionally, but - // doesn't support access time just modification time. - // - // System clock vs File clock issues also make that annoying. - warn("Changing file times is not yet implemented on Windows, path is '%s'", path); -#else - if (utimes(path.c_str(), times) == -1) { - - throw SysError("changing modification time of '%s' (not a symlink)", path); - } -#endif - } else { - throw Error("Cannot modification time of symlink '%s'", path); - } - }; - #if HAVE_LUTIMES - if (lutimes(path.c_str(), times) == -1) { - if (errno == ENOSYS) - nonSymlink(); - else - throw SysError("changing modification time of '%s'", path); - } + if (lutimes(path.c_str(), times) == -1) + throw SysError("changing modification time of '%s'", path); #else - nonSymlink(); + bool isSymlink = optIsSymlink + ? *optIsSymlink + : fs::is_symlink(path); + + if (!isSymlink) { + if (utimes(path.c_str(), times) == -1) + throw SysError("changing modification time of '%s' (not a symlink)", path); + } else { + throw Error("Cannot modification time of symlink '%s'", path); + } +#endif #endif } diff --git a/src/libutil/meson.build b/src/libutil/meson.build index 57b741a50..08413783d 100644 --- a/src/libutil/meson.build +++ b/src/libutil/meson.build @@ -42,6 +42,8 @@ check_funcs = [ # Optionally used to try to close more file descriptors (e.g. before # forking) on Unix. 'sysconf', + # Optionally used for changing the mtime of files and symlinks. + 'utimensat', ] foreach funcspec : check_funcs define_name = 'HAVE_' + funcspec.underscorify().to_upper() @@ -49,6 +51,8 @@ foreach funcspec : check_funcs configdata.set(define_name, define_value) endforeach +configdata.set('HAVE_DECL_AT_SYMLINK_NOFOLLOW', cxx.has_header_symbol('fcntl.h', 'AT_SYMLINK_NOFOLLOW').to_int()) + subdir('build-utils-meson/threads') # Check if -latomic is needed From 5f691206ba248943f4771f77677c967cf24bb867 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 30 Oct 2024 00:57:35 +0100 Subject: [PATCH 344/718] refact: Extract scopedImport --- src/libexpr/primops.cc | 58 +++++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 23 deletions(-) diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 203d10932..bcf66971f 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -178,6 +178,38 @@ static void mkOutputString( o.second.path(*state.store, Derivation::nameFromPath(drvPath), o.first)); } +/** + * Import a Nix file with an alternate base scope, as `builtins.scopedImport` does. + * + * @param state The evaluation state. + * @param pos The position of the import call. + * @param path The path to the file to import. + * @param vScope The base scope to use for the import. + * @param v Return value + */ +static void scopedImport(EvalState & state, const PosIdx pos, SourcePath & path, Value * vScope, Value & v) { + state.forceAttrs(*vScope, pos, "while evaluating the first argument passed to builtins.scopedImport"); + + Env * env = &state.allocEnv(vScope->attrs()->size()); + env->up = &state.baseEnv; + + auto staticEnv = std::make_shared(nullptr, state.staticBaseEnv.get(), vScope->attrs()->size()); + + unsigned int displ = 0; + for (auto & attr : *vScope->attrs()) { + staticEnv->vars.emplace_back(attr.name, displ); + env->values[displ++] = attr.value; + } + + // No need to call staticEnv.sort(), because + // args[0]->attrs is already sorted. + + printTalkative("evaluating file '%1%'", path); + Expr * e = state.parseExprFromFile(resolveExprPath(path), staticEnv); + + e->eval(state, *env, v); +} + /* Load and evaluate an expression from path specified by the argument. */ static void import(EvalState & state, const PosIdx pos, Value & vPath, Value * vScope, Value & v) @@ -226,30 +258,10 @@ static void import(EvalState & state, const PosIdx pos, Value & vPath, Value * v } else { - if (!vScope) + if (vScope) + scopedImport(state, pos, path, vScope, v); + else state.evalFile(path, v); - else { - state.forceAttrs(*vScope, pos, "while evaluating the first argument passed to builtins.scopedImport"); - - Env * env = &state.allocEnv(vScope->attrs()->size()); - env->up = &state.baseEnv; - - auto staticEnv = std::make_shared(nullptr, state.staticBaseEnv.get(), vScope->attrs()->size()); - - unsigned int displ = 0; - for (auto & attr : *vScope->attrs()) { - staticEnv->vars.emplace_back(attr.name, displ); - env->values[displ++] = attr.value; - } - - // No need to call staticEnv.sort(), because - // args[0]->attrs is already sorted. - - printTalkative("evaluating file '%1%'", path); - Expr * e = state.parseExprFromFile(resolveExprPath(path), staticEnv); - - e->eval(state, *env, v); - } } } From 760be5fe1e7754f7bea63cdc88bbfcccc0e83324 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 30 Oct 2024 01:04:23 +0100 Subject: [PATCH 345/718] refact: Extract derivationToValue --- src/libexpr/primops.cc | 68 +++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 27 deletions(-) diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index bcf66971f..71afd6f1c 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -178,6 +178,46 @@ static void mkOutputString( o.second.path(*state.store, Derivation::nameFromPath(drvPath), o.first)); } +/** + * `import` will parse a derivation when it imports a `.drv` file from the store. + * + * @param state The evaluation state. + * @param pos The position of the `import` call. + * @param path The path to the `.drv` to import. + * @param storePath The path to the `.drv` to import. + * @param v Return value + */ +void derivationToValue(EvalState & state, const PosIdx pos, const SourcePath & path, const StorePath & storePath, Value & v) { + auto path2 = path.path.abs(); + Derivation drv = state.store->readDerivation(storePath); + auto attrs = state.buildBindings(3 + drv.outputs.size()); + attrs.alloc(state.sDrvPath).mkString(path2, { + NixStringContextElem::DrvDeep { .drvPath = storePath }, + }); + attrs.alloc(state.sName).mkString(drv.env["name"]); + + auto list = state.buildList(drv.outputs.size()); + for (const auto & [i, o] : enumerate(drv.outputs)) { + mkOutputString(state, attrs, storePath, o); + (list[i] = state.allocValue())->mkString(o.first); + } + attrs.alloc(state.sOutputs).mkList(list); + + auto w = state.allocValue(); + w->mkAttrs(attrs); + + if (!state.vImportedDrvToDerivation) { + state.vImportedDrvToDerivation = allocRootValue(state.allocValue()); + state.eval(state.parseExprFromString( + #include "imported-drv-to-derivation.nix.gen.hh" + , state.rootPath(CanonPath::root)), **state.vImportedDrvToDerivation); + } + + state.forceFunction(**state.vImportedDrvToDerivation, pos, "while evaluating imported-drv-to-derivation.nix.gen.hh"); + v.mkApp(*state.vImportedDrvToDerivation, w); + state.forceAttrs(v, pos, "while calling imported-drv-to-derivation.nix.gen.hh"); +} + /** * Import a Nix file with an alternate base scope, as `builtins.scopedImport` does. * @@ -228,33 +268,7 @@ static void import(EvalState & state, const PosIdx pos, Value & vPath, Value * v }; if (auto storePath = isValidDerivationInStore()) { - Derivation drv = state.store->readDerivation(*storePath); - auto attrs = state.buildBindings(3 + drv.outputs.size()); - attrs.alloc(state.sDrvPath).mkString(path2, { - NixStringContextElem::DrvDeep { .drvPath = *storePath }, - }); - attrs.alloc(state.sName).mkString(drv.env["name"]); - - auto list = state.buildList(drv.outputs.size()); - for (const auto & [i, o] : enumerate(drv.outputs)) { - mkOutputString(state, attrs, *storePath, o); - (list[i] = state.allocValue())->mkString(o.first); - } - attrs.alloc(state.sOutputs).mkList(list); - - auto w = state.allocValue(); - w->mkAttrs(attrs); - - if (!state.vImportedDrvToDerivation) { - state.vImportedDrvToDerivation = allocRootValue(state.allocValue()); - state.eval(state.parseExprFromString( - #include "imported-drv-to-derivation.nix.gen.hh" - , state.rootPath(CanonPath::root)), **state.vImportedDrvToDerivation); - } - - state.forceFunction(**state.vImportedDrvToDerivation, pos, "while evaluating imported-drv-to-derivation.nix.gen.hh"); - v.mkApp(*state.vImportedDrvToDerivation, w); - state.forceAttrs(v, pos, "while calling imported-drv-to-derivation.nix.gen.hh"); + derivationToValue(state, pos, path, *storePath, v); } else { From 64744503cc45a449155ef95ca1802ceb12c88a8e Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 30 Oct 2024 01:08:01 +0100 Subject: [PATCH 346/718] Tidy --- src/libexpr/primops.cc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 71afd6f1c..84aa6bac9 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -270,12 +270,11 @@ static void import(EvalState & state, const PosIdx pos, Value & vPath, Value * v if (auto storePath = isValidDerivationInStore()) { derivationToValue(state, pos, path, *storePath, v); } - + else if (vScope) { + scopedImport(state, pos, path, vScope, v); + } else { - if (vScope) - scopedImport(state, pos, path, vScope, v); - else - state.evalFile(path, v); + state.evalFile(path, v); } } From 9491abdfec502f888244d6886ee56817a99ae8bc Mon Sep 17 00:00:00 2001 From: Adrian Hesketh Date: Mon, 7 Oct 2024 08:15:02 +0100 Subject: [PATCH 347/718] docs: update distributed-builds.md --- .../advanced-topics/distributed-builds.md | 75 ++++++++++++++----- 1 file changed, 56 insertions(+), 19 deletions(-) diff --git a/doc/manual/source/advanced-topics/distributed-builds.md b/doc/manual/source/advanced-topics/distributed-builds.md index 52acd039c..66e371888 100644 --- a/doc/manual/source/advanced-topics/distributed-builds.md +++ b/doc/manual/source/advanced-topics/distributed-builds.md @@ -1,35 +1,57 @@ # Remote Builds -Nix supports remote builds, where a local Nix installation can forward -Nix builds to other machines. This allows multiple builds to be -performed in parallel and allows Nix to perform multi-platform builds in -a semi-transparent way. For instance, if you perform a build for a -`x86_64-darwin` on an `i686-linux` machine, Nix can automatically -forward the build to a `x86_64-darwin` machine, if available. +A local Nix installation can forward Nix builds to other machines, +this allows multiple builds to be performed in parallel. -To forward a build to a remote machine, it’s required that the remote -machine is accessible via SSH and that it has Nix installed. You can -test whether connecting to the remote Nix instance works, e.g. +Remote builds also allow Nix to perform multi-platform builds in a +semi-transparent way. For example, if you perform a build for a +`x86_64-darwin` on an `i686-linux` machine, Nix can automatically +forward the build to a `x86_64-darwin` machine, if one is available. + +## Requirements + +For a local machine to forward a build to a remote machine, the remote machine must: + +- Have Nix installed +- Be running an SSH server, e.g. `sshd` +- Be accessible via SSH from the local machine over the network +- Have the local machine's public SSH key in `/etc/ssh/authorized_keys.d/` +- Have the username of the SSH user in the `trusted-users` setting in `nix.conf` + +## Testing + +To test connecting to a remote Nix instance (in this case `mac`), run: ```console -$ nix store info --store ssh://mac +nix store info --store ssh://username@mac ``` -will try to connect to the machine named `mac`. It is possible to -specify an SSH identity file as part of the remote store URI, e.g. +To specify an SSH identity file as part of the remote store URI add a +query paramater, e.g. ```console -$ nix store info --store ssh://mac?ssh-key=/home/alice/my-key +nix store info --store ssh://username@mac?ssh-key=/home/alice/my-key ``` Since builds should be non-interactive, the key should not have a passphrase. Alternatively, you can load identities ahead of time into `ssh-agent` or `gpg-agent`. +In a multi-user installation (default), builds are executed by the Nix +Daemon. The Nix Daemon cannot prompt for a passphrase via the terminal +or `ssh-agent`, so the SSH key must not have a passphrase. + +In addition, the Nix Daemon's user (typically root) needs to have SSH +access to the remote builder. + +Access can be verified by running `sudo su`, and then validating SSH +access, e.g. by running `ssh mac`. SSH identity files for root users +are usually stored in `/root/.ssh/` (Linux) or `/var/root/.ssh` (MacOS). + If you get the error ```console -bash: nix-store: command not found +bash: nix: command not found error: cannot connect to 'mac' ``` @@ -40,15 +62,28 @@ The [list of remote build machines](@docroot@/command-ref/conf-file.md#conf-buil For example, the following command allows you to build a derivation for `x86_64-darwin` on a Linux machine: ```console -$ uname +uname +``` + +```console Linux +``` -$ nix build --impure \ - --expr '(with import { system = "x86_64-darwin"; }; runCommand "foo" {} "uname > $out")' \ - --builders 'ssh://mac x86_64-darwin' +```console +nix build --impure \ + --expr '(with import { system = "x86_64-darwin"; }; runCommand "foo" {} "uname > $out")' \ + --builders 'ssh://mac x86_64-darwin' +``` + +```console [1/0/1 built, 0.0 MiB DL] building foo on ssh://mac +``` -$ cat ./result +```console +cat ./result +``` + +```console Darwin ``` @@ -62,6 +97,8 @@ Remote build machines can also be configured in [`nix.conf`](@docroot@/command-r builders = ssh://mac x86_64-darwin ; ssh://beastie x86_64-freebsd +After making changes to `nix.conf`, restart the Nix daemon for changes to take effect. + Finally, remote build machines can be configured in a separate configuration file included in `builders` via the syntax `@/path/to/file`. For example, From a75b082a284c09b63b52952f2d4a360a3cadfb71 Mon Sep 17 00:00:00 2001 From: Tim Van Baak Date: Tue, 29 Oct 2024 21:33:28 -0700 Subject: [PATCH 348/718] Expand shellcheck coverage in functional tests Ref NixOS/nix#10795 --- maintainers/flake-module.nix | 15 +----- tests/functional/build.sh | 9 ++-- tests/functional/check.sh | 80 +++++++++++++++---------------- tests/functional/eval.sh | 12 ++--- tests/functional/fetchurl.sh | 64 ++++++++++++------------- tests/functional/flakes/common.sh | 18 ++++--- tests/functional/gc.sh | 40 ++++++++-------- tests/functional/help.sh | 1 + tests/functional/lang.sh | 3 ++ tests/functional/nar-access.sh | 44 ++++++++--------- tests/functional/shell.sh | 24 +++++----- tests/functional/zstd.sh | 12 ++--- 12 files changed, 159 insertions(+), 163 deletions(-) diff --git a/maintainers/flake-module.nix b/maintainers/flake-module.nix index 78c36d6b6..225b0b300 100644 --- a/maintainers/flake-module.nix +++ b/maintainers/flake-module.nix @@ -7,7 +7,7 @@ perSystem = { config, pkgs, ... }: { - # https://flake.parts/options/pre-commit-hooks-nix.html#options + # https://flake.parts/options/git-hooks-nix#options pre-commit.settings = { hooks = { clang-format = { @@ -501,7 +501,6 @@ ''^scripts/install-nix-from-closure\.sh$'' ''^scripts/install-systemd-multi-user\.sh$'' ''^src/nix/get-env\.sh$'' - ''^tests/functional/build\.sh$'' ''^tests/functional/ca/build-dry\.sh$'' ''^tests/functional/ca/build-with-garbage-path\.sh$'' ''^tests/functional/ca/common\.sh$'' @@ -517,7 +516,6 @@ ''^tests/functional/ca/selfref-gc\.sh$'' ''^tests/functional/ca/why-depends\.sh$'' ''^tests/functional/characterisation-test-infra\.sh$'' - ''^tests/functional/check\.sh$'' ''^tests/functional/common/vars-and-functions\.sh$'' ''^tests/functional/completions\.sh$'' ''^tests/functional/compute-levels\.sh$'' @@ -534,7 +532,6 @@ ''^tests/functional/dyn-drv/old-daemon-error-hack\.sh$'' ''^tests/functional/dyn-drv/recursive-mod-json\.sh$'' ''^tests/functional/eval-store\.sh$'' - ''^tests/functional/eval\.sh$'' ''^tests/functional/export-graph\.sh$'' ''^tests/functional/export\.sh$'' ''^tests/functional/extra-sandbox-profile\.sh$'' @@ -544,13 +541,11 @@ ''^tests/functional/fetchGitSubmodules\.sh$'' ''^tests/functional/fetchGitVerification\.sh$'' ''^tests/functional/fetchMercurial\.sh$'' - ''^tests/functional/fetchurl\.sh$'' ''^tests/functional/fixed\.builder1\.sh$'' ''^tests/functional/fixed\.builder2\.sh$'' ''^tests/functional/fixed\.sh$'' ''^tests/functional/flakes/absolute-paths\.sh$'' ''^tests/functional/flakes/check\.sh$'' - ''^tests/functional/flakes/common\.sh$'' ''^tests/functional/flakes/config\.sh$'' ''^tests/functional/flakes/develop\.sh$'' ''^tests/functional/flakes/flakes\.sh$'' @@ -565,16 +560,12 @@ ''^tests/functional/gc-concurrent\.sh$'' ''^tests/functional/gc-concurrent2\.builder\.sh$'' ''^tests/functional/gc-non-blocking\.sh$'' - ''^tests/functional/gc\.sh$'' ''^tests/functional/git-hashing/common\.sh$'' ''^tests/functional/git-hashing/simple\.sh$'' ''^tests/functional/hash-convert\.sh$'' - ''^tests/functional/help\.sh$'' ''^tests/functional/impure-derivations\.sh$'' - ''^tests/functional/impure-env\.sh$'' ''^tests/functional/impure-eval\.sh$'' ''^tests/functional/install-darwin\.sh$'' - ''^tests/functional/lang\.sh$'' ''^tests/functional/legacy-ssh-store\.sh$'' ''^tests/functional/linux-sandbox\.sh$'' ''^tests/functional/local-overlay-store/add-lower-inner\.sh$'' @@ -603,7 +594,6 @@ ''^tests/functional/logging\.sh$'' ''^tests/functional/misc\.sh$'' ''^tests/functional/multiple-outputs\.sh$'' - ''^tests/functional/nar-access\.sh$'' ''^tests/functional/nested-sandboxing\.sh$'' ''^tests/functional/nested-sandboxing/command\.sh$'' ''^tests/functional/nix-build\.sh$'' @@ -624,7 +614,6 @@ ''^tests/functional/path-from-hash-part\.sh$'' ''^tests/functional/path-info\.sh$'' ''^tests/functional/placeholders\.sh$'' - ''^tests/functional/plugins\.sh$'' ''^tests/functional/post-hook\.sh$'' ''^tests/functional/pure-eval\.sh$'' ''^tests/functional/push-to-store-old\.sh$'' @@ -639,7 +628,6 @@ ''^tests/functional/search\.sh$'' ''^tests/functional/secure-drv-outputs\.sh$'' ''^tests/functional/selfref-gc\.sh$'' - ''^tests/functional/shell\.sh$'' ''^tests/functional/shell\.shebang\.sh$'' ''^tests/functional/simple\.builder\.sh$'' ''^tests/functional/supplementary-groups\.sh$'' @@ -649,7 +637,6 @@ ''^tests/functional/user-envs\.builder\.sh$'' ''^tests/functional/user-envs\.sh$'' ''^tests/functional/why-depends\.sh$'' - ''^tests/functional/zstd\.sh$'' ''^src/libutil-tests/data/git/check-data\.sh$'' ]; }; diff --git a/tests/functional/build.sh b/tests/functional/build.sh index 5396a465f..3f65a7c2c 100755 --- a/tests/functional/build.sh +++ b/tests/functional/build.sh @@ -84,6 +84,7 @@ expectStderr 1 nix build --expr '""' --no-link \ | grepQuiet "has 0 entries in its context. It should only have exactly one entry" # Too much string context +# shellcheck disable=SC2016 # The ${} in this is Nix, not shell expectStderr 1 nix build --impure --expr 'with (import ./multiple-outputs.nix).e.a_a; "${drvPath}${outPath}"' --no-link \ | grepQuiet "has 2 entries in its context. It should only have exactly one entry" @@ -160,7 +161,7 @@ printf "%s\n" "$drv^*" | nix build --no-link --stdin --json | jq --exit-status ' out="$(nix build -f fod-failing.nix -L 2>&1)" && status=0 || status=$? test "$status" = 1 # one "hash mismatch" error, one "build of ... failed" -test "$(<<<"$out" grep -E '^error:' | wc -l)" = 2 +test "$(<<<"$out" grep -cE '^error:')" = 2 <<<"$out" grepQuiet -E "hash mismatch in fixed-output derivation '.*-x1\\.drv'" <<<"$out" grepQuiet -vE "hash mismatch in fixed-output derivation '.*-x3\\.drv'" <<<"$out" grepQuiet -vE "hash mismatch in fixed-output derivation '.*-x2\\.drv'" @@ -169,7 +170,7 @@ test "$(<<<"$out" grep -E '^error:' | wc -l)" = 2 out="$(nix build -f fod-failing.nix -L x1 x2 x3 --keep-going 2>&1)" && status=0 || status=$? test "$status" = 1 # three "hash mismatch" errors - for each failing fod, one "build of ... failed" -test "$(<<<"$out" grep -E '^error:' | wc -l)" = 4 +test "$(<<<"$out" grep -cE '^error:')" = 4 <<<"$out" grepQuiet -E "hash mismatch in fixed-output derivation '.*-x1\\.drv'" <<<"$out" grepQuiet -E "hash mismatch in fixed-output derivation '.*-x3\\.drv'" <<<"$out" grepQuiet -E "hash mismatch in fixed-output derivation '.*-x2\\.drv'" @@ -177,13 +178,13 @@ test "$(<<<"$out" grep -E '^error:' | wc -l)" = 4 out="$(nix build -f fod-failing.nix -L x4 2>&1)" && status=0 || status=$? test "$status" = 1 -test "$(<<<"$out" grep -E '^error:' | wc -l)" = 2 +test "$(<<<"$out" grep -cE '^error:')" = 2 <<<"$out" grepQuiet -E "error: 1 dependencies of derivation '.*-x4\\.drv' failed to build" <<<"$out" grepQuiet -E "hash mismatch in fixed-output derivation '.*-x2\\.drv'" out="$(nix build -f fod-failing.nix -L x4 --keep-going 2>&1)" && status=0 || status=$? test "$status" = 1 -test "$(<<<"$out" grep -E '^error:' | wc -l)" = 3 +test "$(<<<"$out" grep -cE '^error:')" = 3 <<<"$out" grepQuiet -E "error: 2 dependencies of derivation '.*-x4\\.drv' failed to build" <<<"$out" grepQuiet -vE "hash mismatch in fixed-output derivation '.*-x3\\.drv'" <<<"$out" grepQuiet -vE "hash mismatch in fixed-output derivation '.*-x2\\.drv'" diff --git a/tests/functional/check.sh b/tests/functional/check.sh index 23e3d2ff0..bff6b2ec8 100755 --- a/tests/functional/check.sh +++ b/tests/functional/check.sh @@ -7,9 +7,9 @@ buggyNeedLocalStore "see #4813" checkBuildTempDirRemoved () { - buildDir=$(sed -n 's/CHECK_TMPDIR=//p' $1 | head -1) + buildDir=$(sed -n 's/CHECK_TMPDIR=//p' "$1" | head -1) checkBuildIdFile=${buildDir}/checkBuildId - [[ ! -f $checkBuildIdFile ]] || ! grep $checkBuildId $checkBuildIdFile + [[ ! -f $checkBuildIdFile ]] || ! grep "$checkBuildId" "$checkBuildIdFile" } # written to build temp directories to verify created by this instance @@ -28,15 +28,15 @@ nix-build dependencies.nix --no-out-link --check # check for dangling temporary build directories # only retain if build fails and --keep-failed is specified, or... # ...build is non-deterministic and --check and --keep-failed are both specified -nix-build check.nix -A failed --argstr checkBuildId $checkBuildId \ - --no-out-link 2> $TEST_ROOT/log || status=$? +nix-build check.nix -A failed --argstr checkBuildId "$checkBuildId" \ + --no-out-link 2> "$TEST_ROOT/log" || status=$? [ "$status" = "100" ] -checkBuildTempDirRemoved $TEST_ROOT/log +checkBuildTempDirRemoved "$TEST_ROOT/log" -nix-build check.nix -A failed --argstr checkBuildId $checkBuildId \ - --no-out-link --keep-failed 2> $TEST_ROOT/log || status=$? +nix-build check.nix -A failed --argstr checkBuildId "$checkBuildId" \ + --no-out-link --keep-failed 2> "$TEST_ROOT/log" || status=$? [ "$status" = "100" ] -if checkBuildTempDirRemoved $TEST_ROOT/log; then false; fi +if checkBuildTempDirRemoved "$TEST_ROOT/log"; then false; fi test_custom_build_dir() { local customBuildDir="$TEST_ROOT/custom-build-dir" @@ -44,42 +44,42 @@ test_custom_build_dir() { # Nix does not create the parent directories, and perhaps it shouldn't try to # decide the permissions of build-dir. mkdir "$customBuildDir" - nix-build check.nix -A failed --argstr checkBuildId $checkBuildId \ - --no-out-link --keep-failed --option build-dir "$TEST_ROOT/custom-build-dir" 2> $TEST_ROOT/log || status=$? + nix-build check.nix -A failed --argstr checkBuildId "$checkBuildId" \ + --no-out-link --keep-failed --option build-dir "$TEST_ROOT/custom-build-dir" 2> "$TEST_ROOT/log" || status=$? [ "$status" = "100" ] [[ 1 == "$(count "$customBuildDir/nix-build-"*)" ]] - local buildDir="$customBuildDir/nix-build-"*"" - if [[ -e $buildDir/build ]]; then - buildDir=$buildDir/build + local buildDir=("$customBuildDir/nix-build-"*) + if [[ -e ${buildDir[*]}/build ]]; then + buildDir[0]="${buildDir[*]}/build" fi - grep $checkBuildId $buildDir/checkBuildId + grep "$checkBuildId" "${buildDir[*]}/checkBuildId" } test_custom_build_dir -nix-build check.nix -A deterministic --argstr checkBuildId $checkBuildId \ - --no-out-link 2> $TEST_ROOT/log -checkBuildTempDirRemoved $TEST_ROOT/log +nix-build check.nix -A deterministic --argstr checkBuildId "$checkBuildId" \ + --no-out-link 2> "$TEST_ROOT/log" +checkBuildTempDirRemoved "$TEST_ROOT/log" -nix-build check.nix -A deterministic --argstr checkBuildId $checkBuildId \ - --no-out-link --check --keep-failed 2> $TEST_ROOT/log -if grepQuiet 'may not be deterministic' $TEST_ROOT/log; then false; fi -checkBuildTempDirRemoved $TEST_ROOT/log +nix-build check.nix -A deterministic --argstr checkBuildId "$checkBuildId" \ + --no-out-link --check --keep-failed 2> "$TEST_ROOT/log" +if grepQuiet 'may not be deterministic' "$TEST_ROOT/log"; then false; fi +checkBuildTempDirRemoved "$TEST_ROOT/log" -nix-build check.nix -A nondeterministic --argstr checkBuildId $checkBuildId \ - --no-out-link 2> $TEST_ROOT/log -checkBuildTempDirRemoved $TEST_ROOT/log +nix-build check.nix -A nondeterministic --argstr checkBuildId "$checkBuildId" \ + --no-out-link 2> "$TEST_ROOT/log" +checkBuildTempDirRemoved "$TEST_ROOT/log" -nix-build check.nix -A nondeterministic --argstr checkBuildId $checkBuildId \ - --no-out-link --check 2> $TEST_ROOT/log || status=$? -grep 'may not be deterministic' $TEST_ROOT/log +nix-build check.nix -A nondeterministic --argstr checkBuildId "$checkBuildId" \ + --no-out-link --check 2> "$TEST_ROOT/log" || status=$? +grep 'may not be deterministic' "$TEST_ROOT/log" [ "$status" = "104" ] -checkBuildTempDirRemoved $TEST_ROOT/log +checkBuildTempDirRemoved "$TEST_ROOT/log" -nix-build check.nix -A nondeterministic --argstr checkBuildId $checkBuildId \ - --no-out-link --check --keep-failed 2> $TEST_ROOT/log || status=$? -grep 'may not be deterministic' $TEST_ROOT/log +nix-build check.nix -A nondeterministic --argstr checkBuildId "$checkBuildId" \ + --no-out-link --check --keep-failed 2> "$TEST_ROOT/log" || status=$? +grep 'may not be deterministic' "$TEST_ROOT/log" [ "$status" = "104" ] -if checkBuildTempDirRemoved $TEST_ROOT/log; then false; fi +if checkBuildTempDirRemoved "$TEST_ROOT/log"; then false; fi TODO_NixOS @@ -87,24 +87,24 @@ clearStore path=$(nix-build check.nix -A fetchurl --no-out-link) -chmod +w $path -echo foo > $path -chmod -w $path +chmod +w "$path" +echo foo > "$path" +chmod -w "$path" nix-build check.nix -A fetchurl --no-out-link --check # Note: "check" doesn't repair anything, it just compares to the hash stored in the database. -[[ $(cat $path) = foo ]] +[[ $(cat "$path") = foo ]] nix-build check.nix -A fetchurl --no-out-link --repair -[[ $(cat $path) != foo ]] +[[ $(cat "$path") != foo ]] -echo 'Hello World' > $TEST_ROOT/dummy +echo 'Hello World' > "$TEST_ROOT/dummy" nix-build check.nix -A hashmismatch --no-out-link || status=$? [ "$status" = "102" ] -echo -n > $TEST_ROOT/dummy +echo -n > "$TEST_ROOT/dummy" nix-build check.nix -A hashmismatch --no-out-link -echo 'Hello World' > $TEST_ROOT/dummy +echo 'Hello World' > "$TEST_ROOT/dummy" nix-build check.nix -A hashmismatch --no-out-link --check || status=$? [ "$status" = "102" ] diff --git a/tests/functional/eval.sh b/tests/functional/eval.sh index 22d2d02a2..e2ced41c2 100755 --- a/tests/functional/eval.sh +++ b/tests/functional/eval.sh @@ -35,13 +35,13 @@ nix-instantiate --eval -E 'assert 1 + 2 == 3; true' [[ "$(nix-instantiate --eval -E '{"assert"=1;bar=2;}')" == '{ "assert" = 1; bar = 2; }' ]] # Check that symlink cycles don't cause a hang. -ln -sfn cycle.nix $TEST_ROOT/cycle.nix -(! nix eval --file $TEST_ROOT/cycle.nix) +ln -sfn cycle.nix "$TEST_ROOT/cycle.nix" +(! nix eval --file "$TEST_ROOT/cycle.nix") # Check that relative symlinks are resolved correctly. -mkdir -p $TEST_ROOT/xyzzy $TEST_ROOT/foo -ln -sfn ../xyzzy $TEST_ROOT/foo/bar -printf 123 > $TEST_ROOT/xyzzy/default.nix +mkdir -p "$TEST_ROOT/xyzzy" "$TEST_ROOT/foo" +ln -sfn ../xyzzy "$TEST_ROOT/foo/bar" +printf 123 > "$TEST_ROOT/xyzzy/default.nix" [[ $(nix eval --impure --expr "import $TEST_ROOT/foo/bar") = 123 ]] # Test --arg-from-file. @@ -57,7 +57,7 @@ fi # Test that unknown settings are warned about out="$(expectStderr 0 nix eval --option foobar baz --expr '""' --raw)" -[[ "$(echo "$out" | grep foobar | wc -l)" = 1 ]] +[[ "$(echo "$out" | grep -c foobar)" = 1 ]] # Test flag alias out="$(nix eval --expr '{}' --build-cores 1)" diff --git a/tests/functional/fetchurl.sh b/tests/functional/fetchurl.sh index 5af44fcf2..c25ac3216 100755 --- a/tests/functional/fetchurl.sh +++ b/tests/functional/fetchurl.sh @@ -9,12 +9,12 @@ clearStore # Test fetching a flat file. hash=$(nix-hash --flat --type sha256 ./fetchurl.sh) -outPath=$(nix-build -vvvvv --expr 'import ' --argstr url file://$(pwd)/fetchurl.sh --argstr sha256 $hash --no-out-link) +outPath=$(nix-build -vvvvv --expr 'import ' --argstr url "file://$(pwd)/fetchurl.sh" --argstr sha256 "$hash" --no-out-link) -cmp $outPath fetchurl.sh +cmp "$outPath" fetchurl.sh # Do not re-fetch paths already present. -outPath2=$(nix-build -vvvvv --expr 'import ' --argstr url file:///does-not-exist/must-remain-unused/fetchurl.sh --argstr sha256 $hash --no-out-link) +outPath2=$(nix-build -vvvvv --expr 'import ' --argstr url file:///does-not-exist/must-remain-unused/fetchurl.sh --argstr sha256 "$hash" --no-out-link) test "$outPath" == "$outPath2" # Now using a base-64 hash. @@ -22,9 +22,9 @@ clearStore hash=$(nix hash file --type sha512 --base64 ./fetchurl.sh) -outPath=$(nix-build -vvvvv --expr 'import ' --argstr url file://$(pwd)/fetchurl.sh --argstr sha512 $hash --no-out-link) +outPath=$(nix-build -vvvvv --expr 'import ' --argstr url "file://$(pwd)/fetchurl.sh" --argstr sha512 "$hash" --no-out-link) -cmp $outPath fetchurl.sh +cmp "$outPath" fetchurl.sh # Now using an SRI hash. clearStore @@ -33,58 +33,58 @@ hash=$(nix hash file ./fetchurl.sh) [[ $hash =~ ^sha256- ]] -outPath=$(nix-build -vvvvv --expr 'import ' --argstr url file://$(pwd)/fetchurl.sh --argstr hash $hash --no-out-link) +outPath=$(nix-build -vvvvv --expr 'import ' --argstr url "file://$(pwd)/fetchurl.sh" --argstr hash "$hash" --no-out-link) -cmp $outPath fetchurl.sh +cmp "$outPath" fetchurl.sh # Test that we can substitute from a different store dir. clearStore -other_store=file://$TEST_ROOT/other_store?store=/fnord/store +other_store="file://$TEST_ROOT/other_store?store=/fnord/store" hash=$(nix hash file --type sha256 --base16 ./fetchurl.sh) -storePath=$(nix --store $other_store store add-file ./fetchurl.sh) +nix --store "$other_store" store add-file ./fetchurl.sh -outPath=$(nix-build -vvvvv --expr 'import ' --argstr url file:///no-such-dir/fetchurl.sh --argstr sha256 $hash --no-out-link --substituters $other_store) +outPath=$(nix-build -vvvvv --expr 'import ' --argstr url file:///no-such-dir/fetchurl.sh --argstr sha256 "$hash" --no-out-link --substituters "$other_store") # Test hashed mirrors with an SRI hash. -nix-build -vvvvv --expr 'import ' --argstr url file:///no-such-dir/fetchurl.sh --argstr hash $(nix hash to-sri --type sha256 $hash) \ - --no-out-link --substituters $other_store +nix-build -vvvvv --expr 'import ' --argstr url file:///no-such-dir/fetchurl.sh --argstr hash "$(nix hash to-sri --type sha256 "$hash")" \ + --no-out-link --substituters "$other_store" # Test unpacking a NAR. -rm -rf $TEST_ROOT/archive -mkdir -p $TEST_ROOT/archive -cp ./fetchurl.sh $TEST_ROOT/archive -chmod +x $TEST_ROOT/archive/fetchurl.sh -ln -s foo $TEST_ROOT/archive/symlink -nar=$TEST_ROOT/archive.nar -nix-store --dump $TEST_ROOT/archive > $nar +rm -rf "$TEST_ROOT/archive" +mkdir -p "$TEST_ROOT/archive" +cp ./fetchurl.sh "$TEST_ROOT/archive" +chmod +x "$TEST_ROOT/archive/fetchurl.sh" +ln -s foo "$TEST_ROOT/archive/symlink" +nar="$TEST_ROOT/archive.nar" +nix-store --dump "$TEST_ROOT/archive" > "$nar" -hash=$(nix-hash --flat --type sha256 $nar) +hash=$(nix-hash --flat --type sha256 "$nar") -outPath=$(nix-build -vvvvv --expr 'import ' --argstr url file://$nar --argstr sha256 $hash \ +outPath=$(nix-build -vvvvv --expr 'import ' --argstr url "file://$nar" --argstr sha256 "$hash" \ --arg unpack true --argstr name xyzzy --no-out-link) -echo $outPath | grepQuiet 'xyzzy' +echo "$outPath" | grepQuiet 'xyzzy' -test -x $outPath/fetchurl.sh -test -L $outPath/symlink +test -x "$outPath/fetchurl.sh" +test -L "$outPath/symlink" -nix-store --delete $outPath +nix-store --delete "$outPath" # Test unpacking a compressed NAR. -narxz=$TEST_ROOT/archive.nar.xz -rm -f $narxz -xz --keep $nar -outPath=$(nix-build -vvvvv --expr 'import ' --argstr url file://$narxz --argstr sha256 $hash \ +narxz="$TEST_ROOT/archive.nar.xz" +rm -f "$narxz" +xz --keep "$nar" +outPath=$(nix-build -vvvvv --expr 'import ' --argstr url "file://$narxz" --argstr sha256 "$hash" \ --arg unpack true --argstr name xyzzy --no-out-link) -test -x $outPath/fetchurl.sh -test -L $outPath/symlink +test -x "$outPath/fetchurl.sh" +test -L "$outPath/symlink" # Make sure that *not* passing a outputHash fails. requireDaemonNewerThan "2.20" expected=100 if [[ -v NIX_DAEMON_PACKAGE ]]; then expected=1; fi # work around the daemon not returning a 100 status correctly -expectStderr $expected nix-build --expr '{ url }: builtins.derivation { name = "nix-cache-info"; system = "x86_64-linux"; builder = "builtin:fetchurl"; inherit url; outputHashMode = "flat"; }' --argstr url file://$narxz 2>&1 | grep 'must be a fixed-output or impure derivation' +expectStderr $expected nix-build --expr '{ url }: builtins.derivation { name = "nix-cache-info"; system = "x86_64-linux"; builder = "builtin:fetchurl"; inherit url; outputHashMode = "flat"; }' --argstr url "file://$narxz" 2>&1 | grep 'must be a fixed-output or impure derivation' diff --git a/tests/functional/flakes/common.sh b/tests/functional/flakes/common.sh index f83a02aba..8ec70d703 100644 --- a/tests/functional/flakes/common.sh +++ b/tests/functional/flakes/common.sh @@ -1,10 +1,13 @@ +#!/usr/bin/env bash + source ../common.sh +# shellcheck disable=SC2034 # this variable is used by tests that source this file registry=$TEST_ROOT/registry.json writeSimpleFlake() { local flakeDir="$1" - cat > $flakeDir/flake.nix < "$flakeDir/flake.nix" < $flakeDir/flake.nix < "$flakeDir/flake.nix" < $flakeDir/flake.nix < "$flakeDir/flake.nix" <&1 | grepQuiet -F 'trace: { repeating = «repeated»; tracing = «potential infinite recursion»; }' nix-instantiate --eval -E 'builtins.warn "Hello" 123' 2>&1 | grepQuiet 'warning: Hello' +# shellcheck disable=SC2016 # The ${} in this is Nix, not shell nix-instantiate --eval -E 'builtins.addErrorContext "while doing ${"something"} interesting" (builtins.warn "Hello" 123)' 2>/dev/null | grepQuiet 123 # warn does not accept non-strings for now expectStderr 1 nix-instantiate --eval -E 'let x = builtins.warn { x = x; } true; in x' \ | grepQuiet "expected a string but found a set" expectStderr 1 nix-instantiate --eval --abort-on-warn -E 'builtins.warn "Hello" 123' | grepQuiet Hello +# shellcheck disable=SC2016 # The ${} in this is Nix, not shell NIX_ABORT_ON_WARN=1 expectStderr 1 nix-instantiate --eval -E 'builtins.addErrorContext "while doing ${"something"} interesting" (builtins.warn "Hello" 123)' | grepQuiet "while doing something interesting" set +x @@ -106,6 +108,7 @@ for i in lang/eval-fail-*.nix; do fi )" if + # shellcheck disable=SC2086 # word splitting of flags is intended expectStderr 1 nix-instantiate $flags "lang/$i.nix" \ | sed "s!$(pwd)!/pwd!g" > "lang/$i.err" then diff --git a/tests/functional/nar-access.sh b/tests/functional/nar-access.sh index b254081cf..2b0a6a329 100755 --- a/tests/functional/nar-access.sh +++ b/tests/functional/nar-access.sh @@ -9,57 +9,57 @@ cd "$TEST_ROOT" # Dump path to nar. narFile="$TEST_ROOT/path.nar" -nix-store --dump $storePath > $narFile +nix-store --dump "$storePath" > "$narFile" # Check that find and nar ls match. -( cd $storePath; find . | sort ) > files.find -nix nar ls -R -d $narFile "" | sort > files.ls-nar +( cd "$storePath"; find . | sort ) > files.find +nix nar ls -R -d "$narFile" "" | sort > files.ls-nar diff -u files.find files.ls-nar # Check that file contents of data match. -nix nar cat $narFile /foo/data > data.cat-nar -diff -u data.cat-nar $storePath/foo/data +nix nar cat "$narFile" /foo/data > data.cat-nar +diff -u data.cat-nar "$storePath/foo/data" # Check that file contents of baz match. -nix nar cat $narFile /foo/baz > baz.cat-nar -diff -u baz.cat-nar $storePath/foo/baz +nix nar cat "$narFile" /foo/baz > baz.cat-nar +diff -u baz.cat-nar "$storePath/foo/baz" -nix store cat $storePath/foo/baz > baz.cat-nar -diff -u baz.cat-nar $storePath/foo/baz +nix store cat "$storePath/foo/baz" > baz.cat-nar +diff -u baz.cat-nar "$storePath/foo/baz" TODO_NixOS # Check that 'nix store cat' fails on invalid store paths. -invalidPath="$(dirname $storePath)/99999999999999999999999999999999-foo" -cp -r $storePath $invalidPath -expect 1 nix store cat $invalidPath/foo/baz +invalidPath="$(dirname "$storePath")/99999999999999999999999999999999-foo" +cp -r "$storePath" "$invalidPath" +expect 1 nix store cat "$invalidPath/foo/baz" # Test --json. diff -u \ - <(nix nar ls --json $narFile / | jq -S) \ + <(nix nar ls --json "$narFile" / | jq -S) \ <(echo '{"type":"directory","entries":{"foo":{},"foo-x":{},"qux":{},"zyx":{}}}' | jq -S) diff -u \ - <(nix nar ls --json -R $narFile /foo | jq -S) \ + <(nix nar ls --json -R "$narFile" /foo | jq -S) \ <(echo '{"type":"directory","entries":{"bar":{"type":"regular","size":0,"narOffset":368},"baz":{"type":"regular","size":0,"narOffset":552},"data":{"type":"regular","size":58,"narOffset":736}}}' | jq -S) diff -u \ - <(nix nar ls --json -R $narFile /foo/bar | jq -S) \ + <(nix nar ls --json -R "$narFile" /foo/bar | jq -S) \ <(echo '{"type":"regular","size":0,"narOffset":368}' | jq -S) diff -u \ - <(nix store ls --json $storePath | jq -S) \ + <(nix store ls --json "$storePath" | jq -S) \ <(echo '{"type":"directory","entries":{"foo":{},"foo-x":{},"qux":{},"zyx":{}}}' | jq -S) diff -u \ - <(nix store ls --json -R $storePath/foo | jq -S) \ + <(nix store ls --json -R "$storePath/foo" | jq -S) \ <(echo '{"type":"directory","entries":{"bar":{"type":"regular","size":0},"baz":{"type":"regular","size":0},"data":{"type":"regular","size":58}}}' | jq -S) diff -u \ - <(nix store ls --json -R $storePath/foo/bar| jq -S) \ + <(nix store ls --json -R "$storePath/foo/bar"| jq -S) \ <(echo '{"type":"regular","size":0}' | jq -S) # Test missing files. -expect 1 nix store ls --json -R $storePath/xyzzy 2>&1 | grep 'does not exist' -expect 1 nix store ls $storePath/xyzzy 2>&1 | grep 'does not exist' +expect 1 nix store ls --json -R "$storePath/xyzzy" 2>&1 | grep 'does not exist' +expect 1 nix store ls "$storePath/xyzzy" 2>&1 | grep 'does not exist' # Test failure to dump. -if nix-store --dump $storePath >/dev/full ; then +if nix-store --dump "$storePath" >/dev/full ; then echo "dumping to /dev/full should fail" - exit -1 + exit 1 fi diff --git a/tests/functional/shell.sh b/tests/functional/shell.sh index 04a03eef5..cfc8e4102 100755 --- a/tests/functional/shell.sh +++ b/tests/functional/shell.sh @@ -27,8 +27,8 @@ expect 1 nix shell -f shell-hello.nix forbidden-symlink -c hello 2>&1 | grepQuie # For instance, we might set an environment variable temporarily to affect some # initialization or whatnot, but this must not leak into the environment of the # command being run. -env > $TEST_ROOT/expected-env -nix shell -f shell-hello.nix hello -c env > $TEST_ROOT/actual-env +env > "$TEST_ROOT/expected-env" +nix shell -f shell-hello.nix hello -c env > "$TEST_ROOT/actual-env" # Remove/reset variables we expect to be different. # - PATH is modified by nix shell # - we unset TMPDIR on macOS if it contains /var/folders @@ -39,10 +39,10 @@ sed -i \ -e 's/_=.*/_=.../' \ -e '/^TMPDIR=\/var\/folders\/.*/d' \ -e '/^__CF_USER_TEXT_ENCODING=.*$/d' \ - $TEST_ROOT/expected-env $TEST_ROOT/actual-env -sort $TEST_ROOT/expected-env > $TEST_ROOT/expected-env.sorted -sort $TEST_ROOT/actual-env > $TEST_ROOT/actual-env.sorted -diff $TEST_ROOT/expected-env.sorted $TEST_ROOT/actual-env.sorted + "$TEST_ROOT/expected-env" "$TEST_ROOT/actual-env" +sort "$TEST_ROOT/expected-env" > "$TEST_ROOT/expected-env.sorted" +sort "$TEST_ROOT/actual-env" > "$TEST_ROOT/actual-env.sorted" +diff "$TEST_ROOT/expected-env.sorted" "$TEST_ROOT/actual-env.sorted" if isDaemonNewer "2.20.0pre20231220"; then # Test that command line attribute ordering is reflected in the PATH @@ -53,8 +53,8 @@ fi requireSandboxSupport -chmod -R u+w $TEST_ROOT/store0 || true -rm -rf $TEST_ROOT/store0 +chmod -R u+w "$TEST_ROOT/store0" || true +rm -rf "$TEST_ROOT/store0" clearStore @@ -64,10 +64,10 @@ path=$(nix eval --raw -f shell-hello.nix hello) # visible in the sandbox. nix shell --sandbox-build-dir /build-tmp \ --sandbox-paths '/nix? /bin? /lib? /lib64? /usr?' \ - --store $TEST_ROOT/store0 -f shell-hello.nix hello -c hello | grep 'Hello World' + --store "$TEST_ROOT/store0" -f shell-hello.nix hello -c hello | grep 'Hello World' -path2=$(nix shell --sandbox-paths '/nix? /bin? /lib? /lib64? /usr?' --store $TEST_ROOT/store0 -f shell-hello.nix hello -c $SHELL -c 'type -p hello') +path2=$(nix shell --sandbox-paths '/nix? /bin? /lib? /lib64? /usr?' --store "$TEST_ROOT/store0" -f shell-hello.nix hello -c "$SHELL" -c 'type -p hello') -[[ $path/bin/hello = $path2 ]] +[[ "$path/bin/hello" = "$path2" ]] -[[ -e $TEST_ROOT/store0/nix/store/$(basename $path)/bin/hello ]] +[[ -e $TEST_ROOT/store0/nix/store/$(basename "$path")/bin/hello ]] diff --git a/tests/functional/zstd.sh b/tests/functional/zstd.sh index 90fe58539..450fb7d35 100755 --- a/tests/functional/zstd.sh +++ b/tests/functional/zstd.sh @@ -11,22 +11,22 @@ cacheURI="file://$cacheDir?compression=zstd" outPath=$(nix-build dependencies.nix --no-out-link) -nix copy --to $cacheURI $outPath +nix copy --to "$cacheURI" "$outPath" -HASH=$(nix hash path $outPath) +HASH=$(nix hash path "$outPath") clearStore clearCacheCache -nix copy --from $cacheURI $outPath --no-check-sigs +nix copy --from "$cacheURI" "$outPath" --no-check-sigs -if ls $cacheDir/nar/*.zst &> /dev/null; then +if ls "$cacheDir/nar/"*.zst &> /dev/null; then echo "files do exist" else echo "nars do not exist" exit 1 fi -HASH2=$(nix hash path $outPath) +HASH2=$(nix hash path "$outPath") -[[ $HASH = $HASH2 ]] +[[ "$HASH" = "$HASH2" ]] From a7a0767df7e97d6a4c1abbebda1f412e44fa9149 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 30 Oct 2024 20:53:41 +0100 Subject: [PATCH 349/718] Rename final -> __final --- src/libexpr/call-flake.nix | 2 +- src/libfetchers/fetchers.cc | 6 +++--- src/libfetchers/fetchers.hh | 13 +++++++------ src/libfetchers/path.cc | 2 +- src/libflake/flake/lockfile.cc | 8 ++++---- 5 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/libexpr/call-flake.nix b/src/libexpr/call-flake.nix index c44d64885..79b3e804e 100644 --- a/src/libexpr/call-flake.nix +++ b/src/libexpr/call-flake.nix @@ -45,7 +45,7 @@ let else # FIXME: remove obsolete node.info. # Note: lock file entries are always final. - fetchTree (node.info or {} // removeAttrs node.locked ["dir"] // { final = true; }); + fetchTree (node.info or {} // removeAttrs node.locked ["dir"] // { __final = true; }); subdir = overrides.${key}.dir or node.locked.dir or ""; diff --git a/src/libfetchers/fetchers.cc b/src/libfetchers/fetchers.cc index 9717533d6..cea6e43ae 100644 --- a/src/libfetchers/fetchers.cc +++ b/src/libfetchers/fetchers.cc @@ -101,7 +101,7 @@ Input Input::fromAttrs(const Settings & settings, Attrs && attrs) auto allowedAttrs = inputScheme->allowedAttrs(); for (auto & [name, _] : attrs) - if (name != "type" && name != "final" && allowedAttrs.count(name) == 0) + if (name != "type" && name != "__final" && allowedAttrs.count(name) == 0) throw Error("input attribute '%s' not supported by scheme '%s'", name, schemeName); auto res = inputScheme->inputFromAttrs(settings, attrs); @@ -148,7 +148,7 @@ bool Input::isLocked() const bool Input::isFinal() const { - return maybeGetBoolAttr(attrs, "final").value_or(false); + return maybeGetBoolAttr(attrs, "__final").value_or(false); } Attrs Input::toAttrs() const @@ -189,7 +189,7 @@ std::pair Input::fetchToStore(ref store) const // getAccessorUnchecked(), but then we can't add // narHash. Or maybe narHash should be excluded from the // concept of "final" inputs? - final.attrs.insert_or_assign("final", Explicit(true)); + final.attrs.insert_or_assign("__final", Explicit(true)); assert(final.isFinal()); diff --git a/src/libfetchers/fetchers.hh b/src/libfetchers/fetchers.hh index e74625f7f..ce535e6fe 100644 --- a/src/libfetchers/fetchers.hh +++ b/src/libfetchers/fetchers.hh @@ -78,24 +78,28 @@ public: Attrs toAttrs() const; /** - * Check whether this is a "direct" input, that is, not + * Return whether this is a "direct" input, that is, not * one that goes through a registry. */ bool isDirect() const; /** - * Check whether this is a "locked" input, that is, it has + * Return whether this is a "locked" input, that is, it has * attributes like a Git revision or NAR hash that uniquely * identify its contents. */ bool isLocked() const; /** - * Check whether this is a "final" input, meaning that fetching it + * Return whether this is a "final" input, meaning that fetching it * will not add or change any attributes. For instance, a Git * input with a `rev` attribute but without a `lastModified` * attribute is considered locked but not final. Only "final" * inputs can be substituted from a binary cache. + * + * The "final" state is denoted by the presence of an attribute + * `__final = true`. This attribute is currently undocumented and + * for internal use only. */ bool isFinal() const; @@ -226,15 +230,12 @@ struct InputScheme */ virtual std::optional experimentalFeature() const; - /// See `Input::isDirect()`. virtual bool isDirect(const Input & input) const { return true; } - /// See `Input::getFingerprint()`. virtual std::optional getFingerprint(ref store, const Input & input) const { return std::nullopt; } - /// See `Input::isLocked()`. virtual bool isLocked(const Input & input) const { return false; } diff --git a/src/libfetchers/path.cc b/src/libfetchers/path.cc index 564ad6e71..f12c969af 100644 --- a/src/libfetchers/path.cc +++ b/src/libfetchers/path.cc @@ -72,7 +72,7 @@ struct PathInputScheme : InputScheme auto query = attrsToQuery(input.attrs); query.erase("path"); query.erase("type"); - query.erase("final"); + query.erase("__final"); return ParsedURL { .scheme = "path", .path = getStrAttr(input.attrs, "path"), diff --git a/src/libflake/flake/lockfile.cc b/src/libflake/flake/lockfile.cc index f80c27acd..668ed165f 100644 --- a/src/libflake/flake/lockfile.cc +++ b/src/libflake/flake/lockfile.cc @@ -48,8 +48,8 @@ LockedNode::LockedNode( fetchers::attrsToJSON(lockedRef.input.toAttrs())); // For backward compatibility, lock file entries are implicitly final. - assert(!lockedRef.input.attrs.contains("final")); - lockedRef.input.attrs.insert_or_assign("final", Explicit(true)); + assert(!lockedRef.input.attrs.contains("__final")); + lockedRef.input.attrs.insert_or_assign("__final", Explicit(true)); } StorePath LockedNode::computeStorePath(Store & store) const @@ -194,11 +194,11 @@ std::pair LockFile::toJSON() const if (auto lockedNode = node.dynamic_pointer_cast()) { n["original"] = fetchers::attrsToJSON(lockedNode->originalRef.toAttrs()); n["locked"] = fetchers::attrsToJSON(lockedNode->lockedRef.toAttrs()); - /* For backward compatibility, omit the "final" + /* For backward compatibility, omit the "__final" attribute. We never allow non-final inputs in lock files anyway. */ assert(lockedNode->lockedRef.input.isFinal()); - n["locked"].erase("final"); + n["locked"].erase("__final"); if (!lockedNode->isFlake) n["flake"] = false; } From 78aedda6bd42d81b4e608bcb8ace641b5a2ef3ec Mon Sep 17 00:00:00 2001 From: Emil Petersen Date: Thu, 31 Oct 2024 00:31:03 +0100 Subject: [PATCH 350/718] Update content-address.md (#11771) Correct a few typos. Make explicit that FSO acronym refers to File System Object. --- .../source/store/file-system-object/content-address.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/manual/source/store/file-system-object/content-address.md b/doc/manual/source/store/file-system-object/content-address.md index 410d7fb7c..72b087fe9 100644 --- a/doc/manual/source/store/file-system-object/content-address.md +++ b/doc/manual/source/store/file-system-object/content-address.md @@ -1,13 +1,13 @@ # Content-Addressing File System Objects -For many operations, Nix needs to calculate [a content addresses](@docroot@/glossary.md#gloss-content-address) of [a file system object][file system object]. +For many operations, Nix needs to calculate [a content addresses](@docroot@/glossary.md#gloss-content-address) of [a file system object][file system object] (FSO). Usually this is needed as part of [content addressing store objects](../store-object/content-address.md), since store objects always have a root file system object. But some command-line utilities also just work on "raw" file system objects, not part of any store object. Every content addressing scheme Nix uses ultimately involves feeding data into a [hash function](https://en.wikipedia.org/wiki/Hash_function), and getting back an opaque fixed-size digest which is deemed a content address. -The various *methods* of content addressing thus differ in how abstract data (in this case, a file system object and its descendents) are fed into the hash function. +The various *methods* of content addressing thus differ in how abstract data (in this case, a file system object and its descendants) are fed into the hash function. ## Serialising File System Objects { #serial } @@ -25,7 +25,7 @@ For example, Unix commands like `sha256sum` or `sha1sum` will produce hashes for ### Nix Archive (NAR) { #serial-nix-archive } -For the other cases of [file system objects][file system object], especially directories with arbitrary descendents, we need a more complex serialisation format. +For the other cases of [file system objects][file system object], especially directories with arbitrary descendants, we need a more complex serialisation format. Examples of such serialisations are the ZIP and TAR file formats. However, for our purposes these formats have two problems: From a530939fe40f788d070e5593c884381758cf4192 Mon Sep 17 00:00:00 2001 From: Tim Van Baak Date: Thu, 31 Oct 2024 06:46:33 -0700 Subject: [PATCH 351/718] Add check for one nix-build-* directory --- tests/functional/check.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/functional/check.sh b/tests/functional/check.sh index bff6b2ec8..b21349288 100755 --- a/tests/functional/check.sh +++ b/tests/functional/check.sh @@ -49,6 +49,10 @@ test_custom_build_dir() { [ "$status" = "100" ] [[ 1 == "$(count "$customBuildDir/nix-build-"*)" ]] local buildDir=("$customBuildDir/nix-build-"*) + if [[ "${#buildDir[@]}" -ne 1 ]]; then + echo "expected one nix-build-* directory, got: ${buildDir[*]}" >&2 + exit 1 + fi if [[ -e ${buildDir[*]}/build ]]; then buildDir[0]="${buildDir[*]}/build" fi From 39fe52a126a7cba609016f0035e1a85001001acf Mon Sep 17 00:00:00 2001 From: Tim Van Baak Date: Thu, 31 Oct 2024 06:46:58 -0700 Subject: [PATCH 352/718] Replace shebang with shellcheck directive --- tests/functional/flakes/common.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/functional/flakes/common.sh b/tests/functional/flakes/common.sh index 8ec70d703..e43e180e3 100644 --- a/tests/functional/flakes/common.sh +++ b/tests/functional/flakes/common.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +# shellcheck shell=bash source ../common.sh From 5f71ebb956227fb5aa88b532522c7d63e5752f5a Mon Sep 17 00:00:00 2001 From: Pol Dellaiera Date: Sun, 27 Oct 2024 23:39:26 +0100 Subject: [PATCH 353/718] fix: make sure directory exists before using `ln` --- scripts/install-systemd-multi-user.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/install-systemd-multi-user.sh b/scripts/install-systemd-multi-user.sh index a79a69990..dc373f4db 100755 --- a/scripts/install-systemd-multi-user.sh +++ b/scripts/install-systemd-multi-user.sh @@ -96,6 +96,9 @@ poly_configure_nix_daemon_service() { if [ -e /run/systemd/system ]; then task "Setting up the nix-daemon systemd service" + _sudo "to create parent of the nix-daemon tmpfiles config" \ + mkdir -p "$(dirname "$TMPFILES_DEST")" + _sudo "to create the nix-daemon tmpfiles config" \ ln -sfn "/nix/var/nix/profiles/default$TMPFILES_SRC" "$TMPFILES_DEST" From 9bb153acb2b79e0d7236ebd6b25346e32f172049 Mon Sep 17 00:00:00 2001 From: Valentin Gagarin Date: Mon, 2 Sep 2024 15:02:55 +0200 Subject: [PATCH 354/718] maintainers: add checklist for security releases Co-Authored-By: Robert Hensing --- maintainers/README.md | 3 ++ maintainers/release-process.md | 54 +++++++++++++++++++++++++++++++-- maintainers/security-reports.md | 31 +++++++++++++++++++ 3 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 maintainers/security-reports.md diff --git a/maintainers/README.md b/maintainers/README.md index 1a275d998..fd9bbed8e 100644 --- a/maintainers/README.md +++ b/maintainers/README.md @@ -59,6 +59,9 @@ Team meetings are generally open to anyone interested. We can make exceptions to discuss sensitive issues, such as security incidents or people matters. Contact any team member to get a calendar invite for reminders and updates. +> [!IMPORTANT] +> [Handling security reports](./security-reports.md) always takes priority. + ## Project board protocol The team uses a [GitHub project board](https://github.com/orgs/NixOS/projects/19/views/1) for tracking its work. diff --git a/maintainers/release-process.md b/maintainers/release-process.md index 7a2b3c0a7..bf3c308cf 100644 --- a/maintainers/release-process.md +++ b/maintainers/release-process.md @@ -15,7 +15,7 @@ release: * (Optionally) Updated `fallback-paths.nix` in Nixpkgs -* An updated manual on https://nixos.org/manual/nix/stable/ +* An updated manual on https://nix.dev/manual/nix/latest/ ## Creating a new release from the `master` branch @@ -194,8 +194,58 @@ release: * Bump the version number of the release branch as above (e.g. to `2.12.2`). - + ## Recovering from mistakes `upload-release.pl` should be idempotent. For instance a wrong `IS_LATEST` value can be fixed that way, by running the script on the actual latest release. +## Security releases + +> See also the instructions for [handling security reports](./security-reports.md). + +Once a security fix is ready for merging: + +1. Summarize *all* past communication in the report. + +1. Request a CVE in the [GitHub security advisory](https://github.com/NixOS/nix/security/advisories) for the security fix. + +1. Notify all collaborators on the advisory with a timeline for the release. + +1. Merge the fix. Publish the advisory. + +1. [Make point releases](#creating-point-releases) for all affected versions. + +1. Update the affected Nix releases in Nixpkgs to the patched version. + + For each Nix release, change the `version = ` strings and run + + ```shell-session + nix-build -A nixVersions.nix__ + ``` + + to get the correct hash for the `hash =` field. + +1. Once the release is built by Hydra, update fallback paths. + + For the Nix release `${version}` shipped with Nixpkgs, run: + + ```shell-session + curl https://releases.nixos.org/nix/nix-${version}/fallback-paths.nix > nixos/modules/installer/tools/nix-fallback-paths.nix + ``` + + Starting with Nixpkgs 24.11, there is an automatic check that fallback paths with Nix binaries match the Nix release shipped with Nixpkgs. + +1. Backport the updates to the two most recent stable releases of Nixpkgs. + + Add `backport release-` labels, which will trigger GitHub Actions to attempt automatic backports. + +1. Once the pull request against `master` lands on `nixpkgs-unstable`, post a Discourse announcement with + + - Links to the CVE and GitHub security advisory + - A description of the vulnerability and its fix + - Credits to the reporters of the vulnerability and contributors of the fix + - A list of affected and patched Nix releases + - Instructions for updating + - A link to the [pull request tracker](https://nixpk.gs/pr-tracker.html) to follow when the patched Nix versions will appear on the various release channels + + Check [past announcements](https://discourse.nixos.org/search?expanded=true&q=Security%20fix%20in%3Atitle%20order%3Alatest_topic) for reference. diff --git a/maintainers/security-reports.md b/maintainers/security-reports.md new file mode 100644 index 000000000..700590cf7 --- /dev/null +++ b/maintainers/security-reports.md @@ -0,0 +1,31 @@ +# Handling security reports + +Reports can be expected to be submitted following the [security policy](https://github.com/NixOS/nix/security/policy), but may reach maintainers on various other channels. + +In case a vulnerability is reported: + +1. [Create a GitHub security advisory](https://github.com/NixOS/nix/security/advisories/new) + + > [!IMPORTANT] + > Add the reporter as a collaborator so they get notified of all activities. + + In addition to the details in the advisory template, the initial report should: + + - Include sufficient details of the vulnerability to allow it to be understood and reproduced. + - Redact any personal data. + - Set a deadline (if applicable). + - Provide proof of concept code (if available). + - Reference any further reading material that may be appropriate. + +1. Establish a private communication channel (e.g. a Matrix room) with the reporter and all Nix maintainers. + +1. Communicate with the reporter which team members are assigned and when they are available. + +1. Consider which immediate preliminary measures should be taken before working on a fix. + +1. Prioritize fixing the security issue over ongoing work. + +1. Keep everyone involved up to date on progress and the estimated timeline for releasing the fix. + +> See also the instructions for [security releases](./release-process.md#security-releases). + From 020dbac0e01fdf6c5ed6e33b9c4bd4796db507bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Forsman?= Date: Fri, 1 Nov 2024 11:55:33 +0100 Subject: [PATCH 355/718] doc/rl-2.19: add entry for always-allow-substitutes option (#11775) * doc/rl-2.19: add entry for always-allow-substitutes option Fixes https://github.com/NixOS/nix/issues/9427. --- doc/manual/source/release-notes/rl-2.19.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/manual/source/release-notes/rl-2.19.md b/doc/manual/source/release-notes/rl-2.19.md index e2e2f85cc..e6a93c7ea 100644 --- a/doc/manual/source/release-notes/rl-2.19.md +++ b/doc/manual/source/release-notes/rl-2.19.md @@ -75,3 +75,7 @@ (experimental) can be found by any program that follows the [XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html). - A new command `nix store add` has been added. It replaces `nix store add-file` and `nix store add-path` which are now deprecated. + +- A new option [`always-allow-substitutes`](@docroot@/command-ref/conf-file.md#conf-always-allow-substitutes) has been added. + + When set to `true`, Nix will always try to substitute a derivation, even if it has the [`allowSubstitutes`]{#adv-attr-allowSubstitutes} attribute set to `false`. From 5c49d0b5d235e1cbec31b3225c338781f6c7c506 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 1 Nov 2024 15:34:48 +0100 Subject: [PATCH 356/718] Handle final handling for old lock files with improper narHash fields This fixes the error '{"__final":true,"lastModified":1686592866,"narHash":"sha256-riGg89eWhXJcPNrQGcSwTEEm7CGxWC06oSX44hajeMw","owner":"nixos","repo":"nixpkgs","rev":"0eeebd64de89e4163f4d3cf34ffe925a5cf67a05","type":"github"}' resulted in different input '{"__final":true,"lastModified":1686592866,"narHash":"sha256-riGg89eWhXJcPNrQGcSwTEEm7CGxWC06oSX44hajeMw=","owner":"nixos","repo":"nixpkgs","rev":"0eeebd64de89e4163f4d3cf34ffe925a5cf67a05","type":"github"}' in flake-regressions/tests/nix-community/patsh/0.2.1 (note the lack of a trailing '=' in the NAR hash in the lock file). --- src/libfetchers/fetchers.cc | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/libfetchers/fetchers.cc b/src/libfetchers/fetchers.cc index cea6e43ae..cce1971ff 100644 --- a/src/libfetchers/fetchers.cc +++ b/src/libfetchers/fetchers.cc @@ -236,9 +236,22 @@ void InputScheme::checkLocks(const Input & specified, const Input & final) const final.to_string(), *prevRevCount); } - if (specified.isFinal() && specified.attrs != final.attrs) - throw Error("fetching final input '%s' resulted in different input '%s'", - attrsToJSON(specified.attrs), attrsToJSON(final.attrs)); + /* If the original input is final, then the result must be the + same (i.e. cannot remove, add or change fields. */ + if (specified.isFinal()) { + + /* Backwards compatibility hack: we had some lock files in the + past that 'narHash' fields with incorrect base-64 + formatting (lacking the trailing '=', e.g. 'sha256-ri...Mw' + instead of ''sha256-ri...Mw='). So fix */ + auto specified2 = specified; + if (auto prevNarHash = specified2.getNarHash()) + specified2.attrs.insert_or_assign("narHash", prevNarHash->to_string(HashFormat::SRI, true)); + + if (specified2.attrs != final.attrs) + throw Error("fetching final input '%s' resulted in different input '%s'", + attrsToJSON(specified2.attrs), attrsToJSON(final.attrs)); + } } std::pair, Input> Input::getAccessor(ref store) const From f314e35b3726e7295eb39e70fd2d67e473c12ef8 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 1 Nov 2024 16:33:51 +0100 Subject: [PATCH 357/718] Simplify "final" inputs We now just check that the fetcher doesn't change any attributes in the input, and return all the original attributes (i.e. discarding any new attributes and keeping any attributes that the fetcher didn't keep). --- src/libfetchers/fetchers.cc | 50 ++++++++++++++++++++++--------------- src/libfetchers/fetchers.hh | 27 ++++++++++++-------- src/libfetchers/tarball.cc | 12 ++++----- 3 files changed, 51 insertions(+), 38 deletions(-) diff --git a/src/libfetchers/fetchers.cc b/src/libfetchers/fetchers.cc index cce1971ff..2aedb8a2e 100644 --- a/src/libfetchers/fetchers.cc +++ b/src/libfetchers/fetchers.cc @@ -193,7 +193,7 @@ std::pair Input::fetchToStore(ref store) const assert(final.isFinal()); - scheme->checkLocks(*this, final); + checkLocks(*this, final); return {storePath, final}; } catch (Error & e) { @@ -205,8 +205,35 @@ std::pair Input::fetchToStore(ref store) const return {std::move(storePath), input}; } -void InputScheme::checkLocks(const Input & specified, const Input & final) const +void Input::checkLocks(Input specified, Input & final) { + /* If the original input is final, then we just return the + original attributes, dropping any new fields returned by the + fetcher. However, any fields that are in both the original and + final input must be identical. */ + if (specified.isFinal()) { + + /* Backwards compatibility hack: we had some lock files in the + past that 'narHash' fields with incorrect base-64 + formatting (lacking the trailing '=', e.g. 'sha256-ri...Mw' + instead of ''sha256-ri...Mw='). So fix that. */ + if (auto prevNarHash = specified.getNarHash()) + specified.attrs.insert_or_assign("narHash", prevNarHash->to_string(HashFormat::SRI, true)); + + for (auto & field : specified.attrs) { + auto field2 = final.attrs.find(field.first); + if (field2 != final.attrs.end() && field.second != field2->second) + throw Error("mismatch in field '%s' of final input '%s', got '%s'", + field.first, + attrsToJSON(specified.attrs), + attrsToJSON(final.attrs)); + } + + final.attrs = specified.attrs; + + return; + } + if (auto prevNarHash = specified.getNarHash()) { if (final.getNarHash() != prevNarHash) { if (final.getNarHash()) @@ -235,23 +262,6 @@ void InputScheme::checkLocks(const Input & specified, const Input & final) const throw Error("'revCount' attribute mismatch in input '%s', expected %d", final.to_string(), *prevRevCount); } - - /* If the original input is final, then the result must be the - same (i.e. cannot remove, add or change fields. */ - if (specified.isFinal()) { - - /* Backwards compatibility hack: we had some lock files in the - past that 'narHash' fields with incorrect base-64 - formatting (lacking the trailing '=', e.g. 'sha256-ri...Mw' - instead of ''sha256-ri...Mw='). So fix */ - auto specified2 = specified; - if (auto prevNarHash = specified2.getNarHash()) - specified2.attrs.insert_or_assign("narHash", prevNarHash->to_string(HashFormat::SRI, true)); - - if (specified2.attrs != final.attrs) - throw Error("fetching final input '%s' resulted in different input '%s'", - attrsToJSON(specified2.attrs), attrsToJSON(final.attrs)); - } } std::pair, Input> Input::getAccessor(ref store) const @@ -259,7 +269,7 @@ std::pair, Input> Input::getAccessor(ref store) const try { auto [accessor, final] = getAccessorUnchecked(store); - scheme->checkLocks(*this, final); + checkLocks(*this, final); return {accessor, std::move(final)}; } catch (Error & e) { diff --git a/src/libfetchers/fetchers.hh b/src/libfetchers/fetchers.hh index ce535e6fe..430d6e943 100644 --- a/src/libfetchers/fetchers.hh +++ b/src/libfetchers/fetchers.hh @@ -91,9 +91,9 @@ public: bool isLocked() const; /** - * Return whether this is a "final" input, meaning that fetching it - * will not add or change any attributes. For instance, a Git - * input with a `rev` attribute but without a `lastModified` + * Return whether this is a "final" input, meaning that fetching + * it will not add, remove or change any attributes. For instance, + * a Git input with a `rev` attribute but without a `lastModified` * attribute is considered locked but not final. Only "final" * inputs can be substituted from a binary cache. * @@ -113,6 +113,19 @@ public: */ std::pair fetchToStore(ref store) const; + /** + * Check the locking attributes in `final` against + * `specified`. E.g. if `specified` has a `rev` attribute, then + * `final` must have the same `rev` attribute. Throw an exception + * if there is a mismatch. + * + * If `specified` is marked final (i.e. has the `__final` + * attribute), then the intersection of attributes in `specified` + * and `final` must be equal, and `final.attrs` is set to + * `specified.attrs` (i.e. we discard any new attributes). + */ + static void checkLocks(Input specified, Input & final); + /** * Return a `SourceAccessor` that allows access to files in the * input without copying it to the store. Also return a possibly @@ -238,14 +251,6 @@ struct InputScheme virtual bool isLocked(const Input & input) const { return false; } - - /** - * Check the locking attributes in `final` against - * `specified`. E.g. if `specified` has a `rev` attribute, then - * `final` must have the same `rev` attribute. Throw an exception - * if there is a mismatch. - */ - virtual void checkLocks(const Input & specified, const Input & final) const; }; void registerInputScheme(std::shared_ptr && fetcher); diff --git a/src/libfetchers/tarball.cc b/src/libfetchers/tarball.cc index e723d3061..27ad89b6e 100644 --- a/src/libfetchers/tarball.cc +++ b/src/libfetchers/tarball.cc @@ -384,13 +384,11 @@ struct TarballInputScheme : CurlInputScheme input = immutableInput; } - /* If we got a lastModified, then return it. But for - compatibility with old lock files that didn't include - lastModified, don't do this if the original input was final - and didn't contain a lastModified. */ - if (result.lastModified - && !input.attrs.contains("lastModified") - && (!_input.isFinal() || _input.attrs.contains("lastModified"))) + /* If we got a lastModified and the input is not final and + doesn't have one, then return it. Note that we don't do + this if the input is final for compatibility with old lock + files that didn't include lastModified. */ + if (result.lastModified && !_input.isFinal() && !input.attrs.contains("lastModified")) input.attrs.insert_or_assign("lastModified", uint64_t(result.lastModified)); input.attrs.insert_or_assign("narHash", From 55fe4ee4f35d7d587bd1c5f5b4adca6ce05a0027 Mon Sep 17 00:00:00 2001 From: Michael <50352631+michaelvanstraten@users.noreply.github.com> Date: Fri, 1 Nov 2024 20:42:34 +0100 Subject: [PATCH 358/718] doc/manual: Add 'Debugging Nix' section (#11637) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * doc/manual: Add 'Debugging Nix' section This commit adds a new 'Debugging Nix' section to the Nix manual. It provides instructions on how to build Nix with debug symbols and how to debug the Nix binary using debuggers like `lldb`. Co-authored-by: Jörg Thalheim Co-authored-by: Valentin Gagarin --- doc/manual/source/SUMMARY.md.in | 1 + doc/manual/source/development/debugging.md | 62 ++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 doc/manual/source/development/debugging.md diff --git a/doc/manual/source/SUMMARY.md.in b/doc/manual/source/SUMMARY.md.in index eef7d189c..d7c312ae7 100644 --- a/doc/manual/source/SUMMARY.md.in +++ b/doc/manual/source/SUMMARY.md.in @@ -121,6 +121,7 @@ - [Development](development/index.md) - [Building](development/building.md) - [Testing](development/testing.md) + - [Debugging](development/debugging.md) - [Documentation](development/documentation.md) - [CLI guideline](development/cli-guideline.md) - [JSON guideline](development/json-guideline.md) diff --git a/doc/manual/source/development/debugging.md b/doc/manual/source/development/debugging.md new file mode 100644 index 000000000..ce623110b --- /dev/null +++ b/doc/manual/source/development/debugging.md @@ -0,0 +1,62 @@ +# Debugging Nix + +This section shows how to build and debug Nix with debug symbols enabled. + +## Building Nix with Debug Symbols + +In the development shell, set the `mesonBuildType` environment variable to `debug` before configuring the build: + +```console +[nix-shell]$ export mesonBuildType=debugoptimized +``` + +Then, proceed to build Nix as described in [Building Nix](./building.md). +This will build Nix with debug symbols, which are essential for effective debugging. + +## Debugging the Nix Binary + +Obtain your preferred debugger within the development shell: + +```console +[nix-shell]$ nix-shell -p gdb +``` + +On macOS, use `lldb`: + +```console +[nix-shell]$ nix-shell -p lldb +``` + +### Launching the Debugger + +To debug the Nix binary, run: + +```console +[nix-shell]$ gdb --args ../outputs/out/bin/nix +``` + +On macOS, use `lldb`: + +```console +[nix-shell]$ lldb -- ../outputs/out/bin/nix +``` + +### Using the Debugger + +Inside the debugger, you can set breakpoints, run the program, and inspect variables. + +```gdb +(gdb) break main +(gdb) run +``` + +Refer to the [GDB Documentation](https://www.gnu.org/software/gdb/documentation/) for comprehensive usage instructions. + +On macOS, use `lldb`: + +```lldb +(lldb) breakpoint set --name main +(lldb) process launch -- +``` + +Refer to the [LLDB Tutorial](https://lldb.llvm.org/use/tutorial.html) for comprehensive usage instructions. From 190d0d661e3c00b932b4dba0359fedb218d70c3c Mon Sep 17 00:00:00 2001 From: Brian McKenna Date: Sun, 3 Nov 2024 17:02:43 +1100 Subject: [PATCH 359/718] Rename nul.nar because nul is a special name in Windows For example, we can't even clone the repository on Windows! error: invalid path 'tests/functional/nul.nar' fatal: unable to checkout working tree --- tests/functional/nars.sh | 2 +- tests/functional/{nul.nar => nul-character.nar} | Bin 2 files changed, 1 insertion(+), 1 deletion(-) rename tests/functional/{nul.nar => nul-character.nar} (100%) diff --git a/tests/functional/nars.sh b/tests/functional/nars.sh index 39d9389db..dd90345a6 100755 --- a/tests/functional/nars.sh +++ b/tests/functional/nars.sh @@ -134,7 +134,7 @@ rm -f "$TEST_ROOT/unicode-*" # Unpacking a NAR with a NUL character in a file name should fail. rm -rf "$TEST_ROOT/out" -expectStderr 1 nix-store --restore "$TEST_ROOT/out" < nul.nar | grepQuiet "NAR contains invalid file name 'f" +expectStderr 1 nix-store --restore "$TEST_ROOT/out" < nul-character.nar | grepQuiet "NAR contains invalid file name 'f" # Likewise for a '.' filename. rm -rf "$TEST_ROOT/out" diff --git a/tests/functional/nul.nar b/tests/functional/nul-character.nar similarity index 100% rename from tests/functional/nul.nar rename to tests/functional/nul-character.nar From 14c8b08c865be6e4790e77ae53e67c4c853b1b32 Mon Sep 17 00:00:00 2001 From: Valentin Gagarin Date: Sun, 3 Nov 2024 12:42:31 +0100 Subject: [PATCH 360/718] docs: add links to string context documentation operators are an everyday thing in the Nix language, and this page will hopefully be consulted by many users. string contexts are quite exotic, and not linking to the detailed explanation will require readers to figure out manually what this is about, or worse, skim over and run into problems later. --- doc/manual/source/language/operators.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/manual/source/language/operators.md b/doc/manual/source/language/operators.md index e2ed3fbed..dbf2441cb 100644 --- a/doc/manual/source/language/operators.md +++ b/doc/manual/source/language/operators.md @@ -102,7 +102,7 @@ The `+` operator is overloaded to also work on strings and paths. > > *string* `+` *string* -Concatenate two [strings][string] and merge their string contexts. +Concatenate two [strings][string] and merge their [string contexts](./string-context.md). [String concatenation]: #string-concatenation @@ -128,7 +128,7 @@ The result is a path. > **Note** > -> The string must not have a string context that refers to a [store path]. +> The string must not have a [string context](./string-context.md) that refers to a [store path]. [Path and string concatenation]: #path-and-string-concatenation From 9d2ed0a7d384a7759d5981425fba41ecf1b4b9e1 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Fri, 1 Nov 2024 09:56:50 -0400 Subject: [PATCH 361/718] No longer copy functional tests to the build dir This should make `_NIX_TEST_ACCEPT=1` work again, fixing #11369. Progress on #2503 --- mk/common-test.sh | 8 ++++ tests/functional/binary-cache.sh | 6 +-- tests/functional/build-hook-ca-fixed.nix | 2 +- tests/functional/build-hook.nix | 2 +- tests/functional/ca/content-addressed.nix | 2 +- tests/functional/ca/derivation-json.sh | 2 +- .../ca/duplicate-realisation-in-closure.sh | 2 +- tests/functional/ca/import-from-derivation.sh | 2 + tests/functional/ca/meson.build | 2 +- tests/functional/ca/new-build-cmd.sh | 2 + tests/functional/ca/nix-run.sh | 9 +++- tests/functional/ca/nix-shell.sh | 1 - tests/functional/ca/nondeterministic.nix | 2 +- tests/functional/ca/racy.nix | 2 +- tests/functional/ca/repl.sh | 2 + tests/functional/ca/why-depends.sh | 2 + tests/functional/check-refs.nix | 2 +- tests/functional/check-reqs.nix | 2 +- tests/functional/check.nix | 2 +- tests/functional/chroot-store.sh | 5 ++- tests/functional/common/functions.sh | 9 ++++ tests/functional/common/paths.sh | 5 +-- tests/functional/common/vars.sh | 10 ++++- tests/functional/dependencies.nix | 2 +- tests/functional/dyn-drv/meson.build | 2 +- .../dyn-drv/old-daemon-error-hack.nix | 2 +- .../functional/dyn-drv/recursive-mod-json.nix | 2 +- .../functional/dyn-drv/text-hashed-output.nix | 2 +- tests/functional/eval.sh | 2 +- tests/functional/export-graph.nix | 2 +- tests/functional/extra-sandbox-profile.nix | 2 +- tests/functional/failing.nix | 2 +- tests/functional/filter-source.nix | 2 +- tests/functional/fixed.nix | 2 +- tests/functional/flakes/build-paths.sh | 2 +- tests/functional/flakes/bundle.sh | 5 ++- tests/functional/flakes/common.sh | 5 ++- tests/functional/flakes/config.sh | 3 +- tests/functional/flakes/develop.sh | 8 +++- tests/functional/flakes/eval-cache.sh | 2 +- tests/functional/flakes/flakes.sh | 2 +- tests/functional/flakes/meson.build | 2 +- tests/functional/flakes/run.sh | 5 ++- tests/functional/fmt.sh | 2 +- tests/functional/fod-failing.nix | 2 +- tests/functional/gc-auto.sh | 4 +- tests/functional/gc-concurrent.nix | 2 +- tests/functional/gc-non-blocking.sh | 2 +- tests/functional/gc-runtime.nix | 2 +- tests/functional/git-hashing/meson.build | 2 +- tests/functional/hermetic.nix | 2 +- tests/functional/ifd.nix | 2 +- tests/functional/import-from-derivation.nix | 2 +- tests/functional/impure-derivations.nix | 2 +- tests/functional/impure-env.nix | 2 +- tests/functional/linux-sandbox-cert-test.nix | 2 +- tests/functional/linux-sandbox.sh | 2 +- .../local-overlay-store/meson.build | 2 +- tests/functional/logging.sh | 2 +- tests/functional/meson.build | 41 +++++-------------- tests/functional/multiple-outputs.nix | 2 +- tests/functional/nar-access.nix | 4 +- tests/functional/nested-sandboxing.sh | 9 ++++ tests/functional/nested-sandboxing/runner.nix | 3 ++ tests/functional/nix-build-examples.nix | 2 +- tests/functional/nix-channel.sh | 2 +- tests/functional/nix-profile.sh | 4 +- tests/functional/nix-shell.sh | 4 +- tests/functional/optimise-store.sh | 6 +-- tests/functional/package.nix | 2 - tests/functional/parallel.nix | 2 +- tests/functional/pass-as-file.sh | 2 +- tests/functional/path.nix | 2 +- tests/functional/placeholders.sh | 2 +- tests/functional/plugins.sh | 2 +- tests/functional/readfile-context.nix | 2 +- tests/functional/recursive.nix | 5 ++- tests/functional/restricted.sh | 33 ++++++++++----- tests/functional/search.nix | 2 +- tests/functional/secure-drv-outputs.nix | 2 +- tests/functional/selfref-gc.sh | 2 +- tests/functional/shell-hello.nix | 2 +- tests/functional/shell.nix | 2 +- tests/functional/simple-failing.nix | 2 +- tests/functional/simple.nix | 2 +- tests/functional/structured-attrs-shell.nix | 2 +- tests/functional/structured-attrs.nix | 2 +- tests/functional/symlink-derivation.nix | 2 +- tests/functional/tarball.sh | 4 +- tests/functional/test-libstoreconsumer.sh | 2 +- tests/functional/timeout.nix | 2 +- tests/functional/user-envs.nix | 2 +- tests/functional/why-depends.sh | 2 +- tests/nixos/functional/common.nix | 4 ++ 94 files changed, 198 insertions(+), 140 deletions(-) diff --git a/mk/common-test.sh b/mk/common-test.sh index 817422c40..dd899e869 100644 --- a/mk/common-test.sh +++ b/mk/common-test.sh @@ -9,13 +9,21 @@ test_name=$(echo -n "${test?must be defined by caller (test runner)}" | sed \ -e "s|\.sh$||" \ ) +# Layer violation, but I am not inclined to care too much, as this code +# is about to be deleted. +src_dir=$(realpath tests/functional) + # shellcheck disable=SC2016 TESTS_ENVIRONMENT=( "TEST_NAME=$test_name" 'NIX_REMOTE=' 'PS4=+(${BASH_SOURCE[0]-$0}:$LINENO) ' + "_NIX_TEST_SOURCE_DIR=${src_dir}" + "_NIX_TEST_BUILD_DIR=${src_dir}" ) +unset src_dir + read -r -a bash <<< "${BASH:-/usr/bin/env bash}" run () { diff --git a/tests/functional/binary-cache.sh b/tests/functional/binary-cache.sh index 6a177b657..ff39ab3b7 100755 --- a/tests/functional/binary-cache.sh +++ b/tests/functional/binary-cache.sh @@ -238,7 +238,7 @@ clearCache # preserve quotes variables in the single-quoted string # shellcheck disable=SC2016 outPath=$(nix-build --no-out-link -E ' - with import ./config.nix; + with import '"${config_nix}"'; mkDerivation { name = "nar-listing"; buildCommand = "mkdir $out; echo foo > $out/bar; ln -s xyzzy $out/link"; @@ -258,7 +258,7 @@ clearCache # preserve quotes variables in the single-quoted string # shellcheck disable=SC2016 outPath=$(nix-build --no-out-link -E ' - with import ./config.nix; + with import '"${config_nix}"'; mkDerivation { name = "debug-info"; buildCommand = "mkdir -p $out/lib/debug/.build-id/02; echo foo > $out/lib/debug/.build-id/02/623eda209c26a59b1a8638ff7752f6b945c26b.debug"; @@ -276,7 +276,7 @@ diff -u \ # preserve quotes variables in the single-quoted string # shellcheck disable=SC2016 expr=' - with import ./config.nix; + with import '"${config_nix}"'; mkDerivation { name = "multi-output"; buildCommand = "mkdir -p $out; echo foo > $doc; echo $doc > $out/docref"; diff --git a/tests/functional/build-hook-ca-fixed.nix b/tests/functional/build-hook-ca-fixed.nix index 0ce6d9b12..427ec2c31 100644 --- a/tests/functional/build-hook-ca-fixed.nix +++ b/tests/functional/build-hook-ca-fixed.nix @@ -1,6 +1,6 @@ { busybox }: -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; let diff --git a/tests/functional/build-hook.nix b/tests/functional/build-hook.nix index 99a13aee4..1f0e17a3b 100644 --- a/tests/functional/build-hook.nix +++ b/tests/functional/build-hook.nix @@ -1,6 +1,6 @@ { busybox, contentAddressed ? false }: -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; let diff --git a/tests/functional/ca/content-addressed.nix b/tests/functional/ca/content-addressed.nix index 2559c562f..411ebb86b 100644 --- a/tests/functional/ca/content-addressed.nix +++ b/tests/functional/ca/content-addressed.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/ca/config.nix"; let mkCADerivation = args: mkDerivation ({ __contentAddressed = true; diff --git a/tests/functional/ca/derivation-json.sh b/tests/functional/ca/derivation-json.sh index 1e2a8fe35..bd6dd7177 100644 --- a/tests/functional/ca/derivation-json.sh +++ b/tests/functional/ca/derivation-json.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# + source common.sh export NIX_TESTS_CA_BY_DEFAULT=1 diff --git a/tests/functional/ca/duplicate-realisation-in-closure.sh b/tests/functional/ca/duplicate-realisation-in-closure.sh index 0baf15cc2..4a5e8c042 100644 --- a/tests/functional/ca/duplicate-realisation-in-closure.sh +++ b/tests/functional/ca/duplicate-realisation-in-closure.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -source ./common.sh +source common.sh requireDaemonNewerThan "2.4pre20210625" diff --git a/tests/functional/ca/import-from-derivation.sh b/tests/functional/ca/import-from-derivation.sh index 0713619a6..708d2fc78 100644 --- a/tests/functional/ca/import-from-derivation.sh +++ b/tests/functional/ca/import-from-derivation.sh @@ -1,3 +1,5 @@ +#!/usr/bin/env bash + source common.sh export NIX_TESTS_CA_BY_DEFAULT=1 diff --git a/tests/functional/ca/meson.build b/tests/functional/ca/meson.build index 00cf8b35f..7a7fcc5cf 100644 --- a/tests/functional/ca/meson.build +++ b/tests/functional/ca/meson.build @@ -29,5 +29,5 @@ suites += { 'substitute.sh', 'why-depends.sh', ], - 'workdir': meson.current_build_dir(), + 'workdir': meson.current_source_dir(), } diff --git a/tests/functional/ca/new-build-cmd.sh b/tests/functional/ca/new-build-cmd.sh index 432d4d132..408bfb0f6 100644 --- a/tests/functional/ca/new-build-cmd.sh +++ b/tests/functional/ca/new-build-cmd.sh @@ -1,3 +1,5 @@ +#!/usr/bin/env bash + source common.sh export NIX_TESTS_CA_BY_DEFAULT=1 diff --git a/tests/functional/ca/nix-run.sh b/tests/functional/ca/nix-run.sh index 920950c11..21c09117e 100755 --- a/tests/functional/ca/nix-run.sh +++ b/tests/functional/ca/nix-run.sh @@ -2,6 +2,11 @@ source common.sh -FLAKE_PATH=path:$PWD +flakeDir="$TEST_HOME/flake" +mkdir -p "${flakeDir}" +cp flake.nix "${_NIX_TEST_BUILD_DIR}/ca/config.nix" content-addressed.nix "${flakeDir}" -nix run --no-write-lock-file "$FLAKE_PATH#runnable" +# `config.nix` cannot be gotten via build dir / env var (runs afoul pure eval). Instead get from flake. +removeBuildDirRef "$flakeDir"/*.nix + +nix run --no-write-lock-file "path:${flakeDir}#runnable" diff --git a/tests/functional/ca/nix-shell.sh b/tests/functional/ca/nix-shell.sh index 1c5a6639f..d1fbe54d1 100755 --- a/tests/functional/ca/nix-shell.sh +++ b/tests/functional/ca/nix-shell.sh @@ -5,4 +5,3 @@ source common.sh CONTENT_ADDRESSED=true cd .. source ./nix-shell.sh - diff --git a/tests/functional/ca/nondeterministic.nix b/tests/functional/ca/nondeterministic.nix index d6d099a3e..740be4bd2 100644 --- a/tests/functional/ca/nondeterministic.nix +++ b/tests/functional/ca/nondeterministic.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/ca/config.nix"; let mkCADerivation = args: mkDerivation ({ __contentAddressed = true; diff --git a/tests/functional/ca/racy.nix b/tests/functional/ca/racy.nix index 555a15484..cadd98675 100644 --- a/tests/functional/ca/racy.nix +++ b/tests/functional/ca/racy.nix @@ -2,7 +2,7 @@ # build it at once. -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/ca/config.nix"; mkDerivation { name = "simple"; diff --git a/tests/functional/ca/repl.sh b/tests/functional/ca/repl.sh index 3808c7cb2..0bbbebd85 100644 --- a/tests/functional/ca/repl.sh +++ b/tests/functional/ca/repl.sh @@ -1,3 +1,5 @@ +#!/usr/bin/env bash + source common.sh export NIX_TESTS_CA_BY_DEFAULT=1 diff --git a/tests/functional/ca/why-depends.sh b/tests/functional/ca/why-depends.sh index 0c079f63b..0af8a5440 100644 --- a/tests/functional/ca/why-depends.sh +++ b/tests/functional/ca/why-depends.sh @@ -1,3 +1,5 @@ +#!/usr/bin/env bash + source common.sh export NIX_TESTS_CA_BY_DEFAULT=1 diff --git a/tests/functional/check-refs.nix b/tests/functional/check-refs.nix index 89690e456..54957f635 100644 --- a/tests/functional/check-refs.nix +++ b/tests/functional/check-refs.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; rec { diff --git a/tests/functional/check-reqs.nix b/tests/functional/check-reqs.nix index 41436cb48..4e059f5a4 100644 --- a/tests/functional/check-reqs.nix +++ b/tests/functional/check-reqs.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; rec { dep1 = mkDerivation { diff --git a/tests/functional/check.nix b/tests/functional/check.nix index ddab8eea9..13638eae8 100644 --- a/tests/functional/check.nix +++ b/tests/functional/check.nix @@ -1,6 +1,6 @@ {checkBuildId ? 0}: -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; { nondeterministic = mkDerivation { diff --git a/tests/functional/chroot-store.sh b/tests/functional/chroot-store.sh index 03803a2b9..8c2a969d3 100755 --- a/tests/functional/chroot-store.sh +++ b/tests/functional/chroot-store.sh @@ -37,7 +37,10 @@ if canUseSandbox; then } EOF - cp simple.nix shell.nix simple.builder.sh config.nix "$flakeDir/" + cp simple.nix shell.nix simple.builder.sh "${config_nix}" "$flakeDir/" + + # `config.nix` cannot be gotten via build dir / env var (runs afoul pure eval). Instead get from flake. + removeBuildDirRef "$flakeDir"/*.nix TODO_NixOS diff --git a/tests/functional/common/functions.sh b/tests/functional/common/functions.sh index 7195149cb..286bb58e8 100644 --- a/tests/functional/common/functions.sh +++ b/tests/functional/common/functions.sh @@ -343,6 +343,15 @@ count() { echo $# } +# Sometimes, e.g. due to pure eval, restricted eval, or sandboxing, we +# cannot look up `config.nix` in the build dir, and have to instead get +# it from the current directory. (In this case, the current directly +# will be somewhere in `$TEST_ROOT`.) +removeBuildDirRef() { + # shellcheck disable=SC2016 # The ${} in this is Nix, not shell + sed -i -e 's,"${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/[^ ]*config.nix",./config.nix,' "$@" +} + trap onError ERR fi # COMMON_FUNCTIONS_SH_SOURCED diff --git a/tests/functional/common/paths.sh b/tests/functional/common/paths.sh index 70bdca796..dec3592af 100644 --- a/tests/functional/common/paths.sh +++ b/tests/functional/common/paths.sh @@ -8,11 +8,10 @@ COMMON_PATHS_SH_SOURCED=1 commonDir="$(readlink -f "$(dirname "${BASH_SOURCE[0]-$0}")")" -# Since these are generated files -# shellcheck disable=SC1091 +# Just for `isTestOnNixOS` source "$commonDir/functions.sh" # shellcheck disable=SC1091 -source "$commonDir/subst-vars.sh" +source "${_NIX_TEST_BUILD_DIR}/common/subst-vars.sh" # Make sure shellcheck knows this will be defined by the above generated snippet : "${bash?}" "${bindir?}" diff --git a/tests/functional/common/vars.sh b/tests/functional/common/vars.sh index c99a6a5c2..4b88e8526 100644 --- a/tests/functional/common/vars.sh +++ b/tests/functional/common/vars.sh @@ -6,11 +6,14 @@ if [[ -z "${COMMON_VARS_SH_SOURCED-}" ]]; then COMMON_VARS_SH_SOURCED=1 +_NIX_TEST_SOURCE_DIR=$(realpath "${_NIX_TEST_SOURCE_DIR}") +_NIX_TEST_BUILD_DIR=$(realpath "${_NIX_TEST_BUILD_DIR}") + commonDir="$(readlink -f "$(dirname "${BASH_SOURCE[0]-$0}")")" # Since this is a generated file # shellcheck disable=SC1091 -source "$commonDir/subst-vars.sh" +source "${_NIX_TEST_BUILD_DIR}/common/subst-vars.sh" # Make sure shellcheck knows all these will be defined by the above generated snippet : "${bindir?} ${coreutils?} ${dot?} ${SHELL?} ${busybox?} ${version?} ${system?}" export coreutils dot busybox version system @@ -69,4 +72,9 @@ if [[ $(uname) == Linux ]] && [[ -L /proc/self/ns/user ]] && unshare --user true _canUseSandbox=1 fi +# Very common, shorthand helps +# Used in other files +# shellcheck disable=SC2034 +config_nix="${_NIX_TEST_BUILD_DIR}/config.nix" + fi # COMMON_VARS_SH_SOURCED diff --git a/tests/functional/dependencies.nix b/tests/functional/dependencies.nix index be1a7ae9a..db06321da 100644 --- a/tests/functional/dependencies.nix +++ b/tests/functional/dependencies.nix @@ -1,5 +1,5 @@ { hashInvalidator ? "" }: -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; let { diff --git a/tests/functional/dyn-drv/meson.build b/tests/functional/dyn-drv/meson.build index 3c671d013..5b60a4698 100644 --- a/tests/functional/dyn-drv/meson.build +++ b/tests/functional/dyn-drv/meson.build @@ -15,5 +15,5 @@ suites += { 'dep-built-drv.sh', 'old-daemon-error-hack.sh', ], - 'workdir': meson.current_build_dir(), + 'workdir': meson.current_source_dir(), } diff --git a/tests/functional/dyn-drv/old-daemon-error-hack.nix b/tests/functional/dyn-drv/old-daemon-error-hack.nix index c9d4a62d4..7d3ccf7e4 100644 --- a/tests/functional/dyn-drv/old-daemon-error-hack.nix +++ b/tests/functional/dyn-drv/old-daemon-error-hack.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/dyn-drv/config.nix"; # A simple content-addressed derivation. # The derivation can be arbitrarily modified by passing a different `seed`, diff --git a/tests/functional/dyn-drv/recursive-mod-json.nix b/tests/functional/dyn-drv/recursive-mod-json.nix index c6a24ca4f..0e778aa7f 100644 --- a/tests/functional/dyn-drv/recursive-mod-json.nix +++ b/tests/functional/dyn-drv/recursive-mod-json.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/dyn-drv/config.nix"; let innerName = "foo"; in diff --git a/tests/functional/dyn-drv/text-hashed-output.nix b/tests/functional/dyn-drv/text-hashed-output.nix index 99203b518..aa46fff61 100644 --- a/tests/functional/dyn-drv/text-hashed-output.nix +++ b/tests/functional/dyn-drv/text-hashed-output.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/dyn-drv/config.nix"; # A simple content-addressed derivation. # The derivation can be arbitrarily modified by passing a different `seed`, diff --git a/tests/functional/eval.sh b/tests/functional/eval.sh index e2ced41c2..7af49d7fd 100755 --- a/tests/functional/eval.sh +++ b/tests/functional/eval.sh @@ -45,7 +45,7 @@ printf 123 > "$TEST_ROOT/xyzzy/default.nix" [[ $(nix eval --impure --expr "import $TEST_ROOT/foo/bar") = 123 ]] # Test --arg-from-file. -[[ "$(nix eval --raw --arg-from-file foo config.nix --expr '{ foo }: { inherit foo; }' foo)" = "$(cat config.nix)" ]] +[[ "$(nix eval --raw --arg-from-file foo "${config_nix}" --expr '{ foo }: { inherit foo; }' foo)" = "$(cat "${config_nix}")" ]] # Check that special(-ish) files are drained. if [[ -e /proc/version ]]; then diff --git a/tests/functional/export-graph.nix b/tests/functional/export-graph.nix index 64fe36bd1..97ffe73a9 100644 --- a/tests/functional/export-graph.nix +++ b/tests/functional/export-graph.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; rec { diff --git a/tests/functional/extra-sandbox-profile.nix b/tests/functional/extra-sandbox-profile.nix index aa680b918..5f0e4753f 100644 --- a/tests/functional/extra-sandbox-profile.nix +++ b/tests/functional/extra-sandbox-profile.nix @@ -1,6 +1,6 @@ { destFile, seed }: -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; mkDerivation { name = "simple"; diff --git a/tests/functional/failing.nix b/tests/functional/failing.nix index d25e2d6b6..8b7990679 100644 --- a/tests/functional/failing.nix +++ b/tests/functional/failing.nix @@ -1,5 +1,5 @@ { busybox }: -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; let mkDerivation = args: diff --git a/tests/functional/filter-source.nix b/tests/functional/filter-source.nix index 907163639..dcef9c4e2 100644 --- a/tests/functional/filter-source.nix +++ b/tests/functional/filter-source.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; mkDerivation { name = "filter"; diff --git a/tests/functional/fixed.nix b/tests/functional/fixed.nix index a920a2167..f70b89091 100644 --- a/tests/functional/fixed.nix +++ b/tests/functional/fixed.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; rec { diff --git a/tests/functional/flakes/build-paths.sh b/tests/functional/flakes/build-paths.sh index f8486528b..cbae6a4e6 100755 --- a/tests/functional/flakes/build-paths.sh +++ b/tests/functional/flakes/build-paths.sh @@ -79,7 +79,7 @@ cat > "$flake1Dir"/flake.nix < "$flake1Dir/foo" diff --git a/tests/functional/flakes/bundle.sh b/tests/functional/flakes/bundle.sh index 5e185cbf6..61aa040e7 100755 --- a/tests/functional/flakes/bundle.sh +++ b/tests/functional/flakes/bundle.sh @@ -2,7 +2,10 @@ source common.sh -cp ../simple.nix ../simple.builder.sh ../config.nix "$TEST_HOME" +cp ../simple.nix ../simple.builder.sh "${config_nix}" "$TEST_HOME" + +# `config.nix` cannot be gotten via build dir / env var (runs afoul pure eval). Instead get from flake. +removeBuildDirRef "$TEST_HOME"/*.nix cd "$TEST_HOME" diff --git a/tests/functional/flakes/common.sh b/tests/functional/flakes/common.sh index e43e180e3..8af72f2ad 100644 --- a/tests/functional/flakes/common.sh +++ b/tests/functional/flakes/common.sh @@ -34,7 +34,10 @@ writeSimpleFlake() { } EOF - cp ../simple.nix ../shell.nix ../simple.builder.sh ../config.nix "$flakeDir/" + cp ../simple.nix ../shell.nix ../simple.builder.sh "${config_nix}" "$flakeDir/" + + # `config.nix` cannot be gotten via build dir / env var (runs afoul pure eval). Instead get from flake. + removeBuildDirRef "$flakeDir"/*.nix } createSimpleGitFlake() { diff --git a/tests/functional/flakes/config.sh b/tests/functional/flakes/config.sh index 4f3906118..256a595bc 100755 --- a/tests/functional/flakes/config.sh +++ b/tests/functional/flakes/config.sh @@ -2,7 +2,8 @@ source common.sh -cp ../simple.nix ../simple.builder.sh ../config.nix $TEST_HOME +cp ../simple.nix ../simple.builder.sh "${config_nix}" $TEST_HOME +removeBuildDirRef "$TEST_HOME/simple.nix" cd $TEST_HOME diff --git a/tests/functional/flakes/develop.sh b/tests/functional/flakes/develop.sh index 60abf3ef2..df24f19f0 100755 --- a/tests/functional/flakes/develop.sh +++ b/tests/functional/flakes/develop.sh @@ -8,7 +8,7 @@ clearStore rm -rf $TEST_HOME/.cache $TEST_HOME/.config $TEST_HOME/.local # Create flake under test. -cp ../shell-hello.nix ../config.nix $TEST_HOME/ +cp ../shell-hello.nix "${config_nix}" $TEST_HOME/ cat <$TEST_HOME/flake.nix { inputs.nixpkgs.url = "$TEST_HOME/nixpkgs"; @@ -25,7 +25,11 @@ EOF # Create fake nixpkgs flake. mkdir -p $TEST_HOME/nixpkgs -cp ../config.nix ../shell.nix $TEST_HOME/nixpkgs +cp "${config_nix}" ../shell.nix $TEST_HOME/nixpkgs + +# `config.nix` cannot be gotten via build dir / env var (runs afoul pure eval). Instead get from flake. +removeBuildDirRef "$TEST_HOME/nixpkgs"/*.nix + cat <$TEST_HOME/nixpkgs/flake.nix { outputs = {self}: { diff --git a/tests/functional/flakes/eval-cache.sh b/tests/functional/flakes/eval-cache.sh index e3fd0bbfe..40a0db618 100755 --- a/tests/functional/flakes/eval-cache.sh +++ b/tests/functional/flakes/eval-cache.sh @@ -7,7 +7,7 @@ requireGit flake1Dir="$TEST_ROOT/eval-cache-flake" createGitRepo "$flake1Dir" "" -cp ../simple.nix ../simple.builder.sh ../config.nix "$flake1Dir/" +cp ../simple.nix ../simple.builder.sh "${config_nix}" "$flake1Dir/" git -C "$flake1Dir" add simple.nix simple.builder.sh config.nix git -C "$flake1Dir" commit -m "config.nix" diff --git a/tests/functional/flakes/flakes.sh b/tests/functional/flakes/flakes.sh index aa4cb1e18..5e901c5d1 100755 --- a/tests/functional/flakes/flakes.sh +++ b/tests/functional/flakes/flakes.sh @@ -390,7 +390,7 @@ cat > "$flake3Dir/flake.nix" < flake.nix diff --git a/tests/functional/fmt.sh b/tests/functional/fmt.sh index 4e0fd57a5..e9bff50d5 100755 --- a/tests/functional/fmt.sh +++ b/tests/functional/fmt.sh @@ -7,7 +7,7 @@ TODO_NixOS # Provide a `shell` variable. Try not to `export` it, perhaps. clearStoreIfPossible rm -rf "$TEST_HOME"/.cache "$TEST_HOME"/.config "$TEST_HOME"/.local -cp ./simple.nix ./simple.builder.sh ./fmt.simple.sh ./config.nix "$TEST_HOME" +cp ./simple.nix ./simple.builder.sh ./fmt.simple.sh "${config_nix}" "$TEST_HOME" cd "$TEST_HOME" diff --git a/tests/functional/fod-failing.nix b/tests/functional/fod-failing.nix index 37c04fe12..7881a3fbf 100644 --- a/tests/functional/fod-failing.nix +++ b/tests/functional/fod-failing.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; rec { x1 = mkDerivation { name = "x1"; diff --git a/tests/functional/gc-auto.sh b/tests/functional/gc-auto.sh index 8f25be3e9..efe3e4b2b 100755 --- a/tests/functional/gc-auto.sh +++ b/tests/functional/gc-auto.sh @@ -23,7 +23,7 @@ fifoLock=$TEST_ROOT/fifoLock mkfifo "$fifoLock" expr=$(cat < $fifo2\"; diff --git a/tests/functional/gc-runtime.nix b/tests/functional/gc-runtime.nix index ee5980bdf..2603fafdf 100644 --- a/tests/functional/gc-runtime.nix +++ b/tests/functional/gc-runtime.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; mkDerivation { name = "gc-runtime"; diff --git a/tests/functional/git-hashing/meson.build b/tests/functional/git-hashing/meson.build index 7486bfb8f..470c53fc5 100644 --- a/tests/functional/git-hashing/meson.build +++ b/tests/functional/git-hashing/meson.build @@ -4,5 +4,5 @@ suites += { 'tests': [ 'simple.sh', ], - 'workdir': meson.current_build_dir(), + 'workdir': meson.current_source_dir(), } diff --git a/tests/functional/hermetic.nix b/tests/functional/hermetic.nix index d1dccdff3..dafe8ad9f 100644 --- a/tests/functional/hermetic.nix +++ b/tests/functional/hermetic.nix @@ -5,7 +5,7 @@ , withFinalRefs ? false }: -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; let contentAddressedByDefault = builtins.getEnv "NIX_TESTS_CA_BY_DEFAULT" == "1"; diff --git a/tests/functional/ifd.nix b/tests/functional/ifd.nix index d0b9b54ad..c84ffbc66 100644 --- a/tests/functional/ifd.nix +++ b/tests/functional/ifd.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; import ( mkDerivation { name = "foo"; diff --git a/tests/functional/import-from-derivation.nix b/tests/functional/import-from-derivation.nix index cc53451cf..8864fb30a 100644 --- a/tests/functional/import-from-derivation.nix +++ b/tests/functional/import-from-derivation.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; rec { bar = mkDerivation { diff --git a/tests/functional/impure-derivations.nix b/tests/functional/impure-derivations.nix index 98547e6c1..04710323f 100644 --- a/tests/functional/impure-derivations.nix +++ b/tests/functional/impure-derivations.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; rec { diff --git a/tests/functional/impure-env.nix b/tests/functional/impure-env.nix index 2b0380ed7..6b9e5a825 100644 --- a/tests/functional/impure-env.nix +++ b/tests/functional/impure-env.nix @@ -1,6 +1,6 @@ { var, value }: -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; mkDerivation { name = "test"; diff --git a/tests/functional/linux-sandbox-cert-test.nix b/tests/functional/linux-sandbox-cert-test.nix index 2fc083ea9..e506b6a0f 100644 --- a/tests/functional/linux-sandbox-cert-test.nix +++ b/tests/functional/linux-sandbox-cert-test.nix @@ -1,6 +1,6 @@ { mode }: -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; mkDerivation ( { diff --git a/tests/functional/linux-sandbox.sh b/tests/functional/linux-sandbox.sh index 1fc89f8ae..81ef36237 100755 --- a/tests/functional/linux-sandbox.sh +++ b/tests/functional/linux-sandbox.sh @@ -47,7 +47,7 @@ grepQuiet 'may not be deterministic' $TEST_ROOT/log # Test that sandboxed builds cannot write to /etc easily # `100` means build failure without extra info, see doc/manual/source/command-ref/status-build-failure.md -expectStderr 100 nix-sandbox-build -E 'with import ./config.nix; mkDerivation { name = "etc-write"; buildCommand = "echo > /etc/test"; }' | +expectStderr 100 nix-sandbox-build -E 'with import '"${config_nix}"'; mkDerivation { name = "etc-write"; buildCommand = "echo > /etc/test"; }' | grepQuiet "/etc/test: Permission denied" diff --git a/tests/functional/local-overlay-store/meson.build b/tests/functional/local-overlay-store/meson.build index 6ff5d3169..b7ba5a323 100644 --- a/tests/functional/local-overlay-store/meson.build +++ b/tests/functional/local-overlay-store/meson.build @@ -14,5 +14,5 @@ suites += { 'optimise.sh', 'stale-file-handle.sh', ], - 'workdir': meson.current_build_dir(), + 'workdir': meson.current_source_dir(), } diff --git a/tests/functional/logging.sh b/tests/functional/logging.sh index bd80a9163..c026ac9c2 100755 --- a/tests/functional/logging.sh +++ b/tests/functional/logging.sh @@ -22,7 +22,7 @@ nix-build dependencies.nix --no-out-link --compress-build-log builder="$(realpath "$(mktemp)")" echo -e "#!/bin/sh\nmkdir \$out" > "$builder" outp="$(nix-build -E \ - 'with import ./config.nix; mkDerivation { name = "fnord"; builder = '"$builder"'; }' \ + 'with import '"${config_nix}"'; mkDerivation { name = "fnord"; builder = '"$builder"'; }' \ --out-link "$(mktemp -d)/result")" test -d "$outp" diff --git a/tests/functional/meson.build b/tests/functional/meson.build index 54f3e7a01..b3ac1560c 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -14,27 +14,6 @@ project('nix-functional-tests', 'cpp', fs = import('fs') -# Need to combine source and build trees -run_command( - 'rsync', - '-a', - '--copy-unsafe-links', - meson.current_source_dir() / '', - meson.current_build_dir() / '', -) -# This current-source-escaping relative is no good because we don't know -# where the build directory will be, therefore we fix it up. Once the -# Make build system is gone, we should think about doing this better. -scripts_dir = fs.relative_to( - meson.current_source_dir() / '..' / '..' / 'scripts', - meson.current_build_dir(), -) -run_command( - 'sed', - '-i', meson.current_build_dir() / 'bash-profile.sh', - '-e', 's^../../scripts^@0@^'.format(scripts_dir), -) - nix = find_program('nix') bash = find_program('bash', native : true) busybox = find_program('busybox', native : true, required : false) @@ -185,7 +164,7 @@ suites = [ 'extra-sandbox-profile.sh', 'help.sh', ], - 'workdir': meson.current_build_dir(), + 'workdir': meson.current_source_dir(), }, ] @@ -200,7 +179,7 @@ if nix_store.found() 'tests': [ 'test-libstoreconsumer.sh', ], - 'workdir': meson.current_build_dir(), + 'workdir': meson.current_source_dir(), } endif @@ -217,7 +196,7 @@ if nix_expr.found() and get_option('default_library') != 'static' 'tests': [ 'plugins.sh', ], - 'workdir': meson.current_build_dir(), + 'workdir': meson.current_source_dir(), } endif @@ -228,14 +207,12 @@ subdir('git-hashing') subdir('local-overlay-store') foreach suite : suites + workdir = suite['workdir'] + suite_name = suite['name'] foreach script : suite['tests'] - workdir = suite['workdir'] - prefix = fs.relative_to(workdir, meson.project_build_root()) - - script = script # Turns, e.g., `tests/functional/flakes/show.sh` into a Meson test target called # `functional-flakes-show`. - name = fs.replace_suffix(prefix / script, '') + name = fs.replace_suffix(script, '') test( name, @@ -247,9 +224,11 @@ foreach suite : suites '-o', 'pipefail', script, ], - suite : suite['name'], + suite : suite_name, env : { - 'TEST_NAME': name, + '_NIX_TEST_SOURCE_DIR': meson.current_source_dir(), + '_NIX_TEST_BUILD_DIR': meson.current_build_dir(), + 'TEST_NAME': suite_name / name, 'NIX_REMOTE': '', 'PS4': '+(${BASH_SOURCE[0]-$0}:$LINENO) ', }, diff --git a/tests/functional/multiple-outputs.nix b/tests/functional/multiple-outputs.nix index 6ba7c523d..19ae2a45d 100644 --- a/tests/functional/multiple-outputs.nix +++ b/tests/functional/multiple-outputs.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; rec { diff --git a/tests/functional/nar-access.nix b/tests/functional/nar-access.nix index 0e2a7f721..78972bd36 100644 --- a/tests/functional/nar-access.nix +++ b/tests/functional/nar-access.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; rec { a = mkDerivation { @@ -20,4 +20,4 @@ asdom 12398 EOF ''; }; -} \ No newline at end of file +} diff --git a/tests/functional/nested-sandboxing.sh b/tests/functional/nested-sandboxing.sh index ae0256de2..7462d2968 100755 --- a/tests/functional/nested-sandboxing.sh +++ b/tests/functional/nested-sandboxing.sh @@ -8,6 +8,15 @@ TODO_NixOS requireSandboxSupport +start="$TEST_ROOT/start" +mkdir -p "$start" +cp -r common common.sh ${config_nix} ./nested-sandboxing "$start" +cp "${_NIX_TEST_BUILD_DIR}/common/subst-vars.sh" "$start/common" +# N.B. redefine +_NIX_TEST_SOURCE_DIR="$start" +_NIX_TEST_BUILD_DIR="$start" +cd "$start" + source ./nested-sandboxing/command.sh expectStderr 100 runNixBuild badStoreUrl 2 | grepQuiet '`sandbox-build-dir` must not contain' diff --git a/tests/functional/nested-sandboxing/runner.nix b/tests/functional/nested-sandboxing/runner.nix index 1e79d5065..48ad512b3 100644 --- a/tests/functional/nested-sandboxing/runner.nix +++ b/tests/functional/nested-sandboxing/runner.nix @@ -19,6 +19,9 @@ mkDerivation { export PATH=${builtins.getEnv "NIX_BIN_DIR"}:$PATH + export _NIX_TEST_SOURCE_DIR=$PWD + export _NIX_TEST_BUILD_DIR=$PWD + source common.sh source ./nested-sandboxing/command.sh diff --git a/tests/functional/nix-build-examples.nix b/tests/functional/nix-build-examples.nix index e54dbbf62..aaea8fc07 100644 --- a/tests/functional/nix-build-examples.nix +++ b/tests/functional/nix-build-examples.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; rec { diff --git a/tests/functional/nix-channel.sh b/tests/functional/nix-channel.sh index a4870e7a8..16d6a1355 100755 --- a/tests/functional/nix-channel.sh +++ b/tests/functional/nix-channel.sh @@ -35,7 +35,7 @@ drvPath=$(nix-instantiate dependencies.nix) nix copy --to file://$TEST_ROOT/foo?compression="bzip2" $(nix-store -r "$drvPath") rm -rf $TEST_ROOT/nixexprs mkdir -p $TEST_ROOT/nixexprs -cp config.nix dependencies.nix dependencies.builder*.sh $TEST_ROOT/nixexprs/ +cp "${config_nix}" dependencies.nix dependencies.builder*.sh $TEST_ROOT/nixexprs/ ln -s dependencies.nix $TEST_ROOT/nixexprs/default.nix (cd $TEST_ROOT && tar cvf - nixexprs) | bzip2 > $TEST_ROOT/foo/nixexprs.tar.bz2 diff --git a/tests/functional/nix-profile.sh b/tests/functional/nix-profile.sh index e2f19b99e..7cf5fcb74 100755 --- a/tests/functional/nix-profile.sh +++ b/tests/functional/nix-profile.sh @@ -47,7 +47,7 @@ printf World > $flake1Dir/who printf 1.0 > $flake1Dir/version printf false > $flake1Dir/ca.nix -cp ./config.nix $flake1Dir/ +cp "${config_nix}" $flake1Dir/ # Test upgrading from nix-env. nix-env -f ./user-envs.nix -i foo-1.0 @@ -140,7 +140,7 @@ nix profile install $(nix-build --no-out-link ./simple.nix) # Test packages with same name from different sources mkdir $TEST_ROOT/simple-too -cp ./simple.nix ./config.nix simple.builder.sh $TEST_ROOT/simple-too +cp ./simple.nix "${config_nix}" simple.builder.sh $TEST_ROOT/simple-too nix profile install --file $TEST_ROOT/simple-too/simple.nix '' nix profile list | grep -A4 'Name:.*simple' | grep 'Name:.*simple-1' nix profile remove simple 2>&1 | grep 'removed 1 packages' diff --git a/tests/functional/nix-shell.sh b/tests/functional/nix-shell.sh index b14e3dc6a..2b78216f4 100755 --- a/tests/functional/nix-shell.sh +++ b/tests/functional/nix-shell.sh @@ -79,7 +79,7 @@ sed -e "s|@ENV_PROG@|$(type -P env)|" shell.shebang.expr > $TEST_ROOT/shell.sheb chmod a+rx $TEST_ROOT/shell.shebang.expr # Should fail due to expressions using relative path ! $TEST_ROOT/shell.shebang.expr bar -cp shell.nix config.nix $TEST_ROOT +cp shell.nix "${config_nix}" $TEST_ROOT # Should succeed echo "cwd: $PWD" output=$($TEST_ROOT/shell.shebang.expr bar) @@ -126,7 +126,7 @@ $TEST_ROOT/shell.shebang.nix mkdir $TEST_ROOT/lookup-test $TEST_ROOT/empty echo "import $shellDotNix" > $TEST_ROOT/lookup-test/shell.nix -cp config.nix $TEST_ROOT/lookup-test/ +cp "${config_nix}" $TEST_ROOT/lookup-test/ echo 'abort "do not load default.nix!"' > $TEST_ROOT/lookup-test/default.nix nix-shell $TEST_ROOT/lookup-test -A shellDrv --run 'echo "it works"' | grepQuiet "it works" diff --git a/tests/functional/optimise-store.sh b/tests/functional/optimise-store.sh index 0bedafc43..05c4c41e4 100755 --- a/tests/functional/optimise-store.sh +++ b/tests/functional/optimise-store.sh @@ -4,8 +4,8 @@ source common.sh clearStoreIfPossible -outPath1=$(echo 'with import ./config.nix; mkDerivation { name = "foo1"; builder = builtins.toFile "builder" "mkdir $out; echo hello > $out/foo"; }' | nix-build - --no-out-link --auto-optimise-store) -outPath2=$(echo 'with import ./config.nix; mkDerivation { name = "foo2"; builder = builtins.toFile "builder" "mkdir $out; echo hello > $out/foo"; }' | nix-build - --no-out-link --auto-optimise-store) +outPath1=$(echo 'with import '"${config_nix}"'; mkDerivation { name = "foo1"; builder = builtins.toFile "builder" "mkdir $out; echo hello > $out/foo"; }' | nix-build - --no-out-link --auto-optimise-store) +outPath2=$(echo 'with import '"${config_nix}"'; mkDerivation { name = "foo2"; builder = builtins.toFile "builder" "mkdir $out; echo hello > $out/foo"; }' | nix-build - --no-out-link --auto-optimise-store) TODO_NixOS # ignoring the client-specified setting 'auto-optimise-store', because it is a restricted setting and you are not a trusted user # TODO: only continue when trusted user or root @@ -23,7 +23,7 @@ if [ "$nlink" != 3 ]; then exit 1 fi -outPath3=$(echo 'with import ./config.nix; mkDerivation { name = "foo3"; builder = builtins.toFile "builder" "mkdir $out; echo hello > $out/foo"; }' | nix-build - --no-out-link) +outPath3=$(echo 'with import '"${config_nix}"'; mkDerivation { name = "foo3"; builder = builtins.toFile "builder" "mkdir $out; echo hello > $out/foo"; }' | nix-build - --no-out-link) inode3="$(stat --format=%i $outPath3/foo)" if [ "$inode1" = "$inode3" ]; then diff --git a/tests/functional/package.nix b/tests/functional/package.nix index 21be38c54..9cf6b62e1 100644 --- a/tests/functional/package.nix +++ b/tests/functional/package.nix @@ -6,7 +6,6 @@ , meson , ninja , pkg-config -, rsync , jq , git @@ -52,7 +51,6 @@ mkMesonDerivation (finalAttrs: { meson ninja pkg-config - rsync jq git diff --git a/tests/functional/parallel.nix b/tests/functional/parallel.nix index 23f142059..1f2411c92 100644 --- a/tests/functional/parallel.nix +++ b/tests/functional/parallel.nix @@ -1,6 +1,6 @@ {sleepTime ? 3}: -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; let diff --git a/tests/functional/pass-as-file.sh b/tests/functional/pass-as-file.sh index 6487bfffd..66a8e588e 100755 --- a/tests/functional/pass-as-file.sh +++ b/tests/functional/pass-as-file.sh @@ -5,7 +5,7 @@ source common.sh clearStoreIfPossible outPath=$(nix-build --no-out-link -E " -with import ./config.nix; +with import ${config_nix}; mkDerivation { name = \"pass-as-file\"; diff --git a/tests/functional/path.nix b/tests/functional/path.nix index 883c3c41b..b23300f90 100644 --- a/tests/functional/path.nix +++ b/tests/functional/path.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; mkDerivation { name = "filter"; diff --git a/tests/functional/placeholders.sh b/tests/functional/placeholders.sh index 33ec0c2b7..374203af8 100755 --- a/tests/functional/placeholders.sh +++ b/tests/functional/placeholders.sh @@ -5,7 +5,7 @@ source common.sh clearStoreIfPossible nix-build --no-out-link -E ' - with import ./config.nix; + with import '"${config_nix}"'; mkDerivation { name = "placeholders"; diff --git a/tests/functional/plugins.sh b/tests/functional/plugins.sh index fc2d1907c..b685a8878 100755 --- a/tests/functional/plugins.sh +++ b/tests/functional/plugins.sh @@ -3,7 +3,7 @@ source common.sh for ext in so dylib; do - plugin="$PWD/plugins/libplugintest.$ext" + plugin="${_NIX_TEST_BUILD_DIR}/plugins/libplugintest.$ext" [[ -f "$plugin" ]] && break done diff --git a/tests/functional/readfile-context.nix b/tests/functional/readfile-context.nix index 54cd1afd9..b8f4a4c27 100644 --- a/tests/functional/readfile-context.nix +++ b/tests/functional/readfile-context.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; let diff --git a/tests/functional/recursive.nix b/tests/functional/recursive.nix index fa8cc04db..fe438f0ba 100644 --- a/tests/functional/recursive.nix +++ b/tests/functional/recursive.nix @@ -1,4 +1,5 @@ -with import ./config.nix; +let config_nix = /. + "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; in +with import config_nix; mkDerivation rec { name = "recursive"; @@ -41,7 +42,7 @@ mkDerivation rec { # Build a derivation. nix $opts build -L --impure --expr ' - with import ${./config.nix}; + with import ${config_nix}; mkDerivation { name = "inner1"; buildCommand = "echo $fnord blaat > $out"; diff --git a/tests/functional/restricted.sh b/tests/functional/restricted.sh index e5fe9c136..63bf56cd7 100755 --- a/tests/functional/restricted.sh +++ b/tests/functional/restricted.sh @@ -7,8 +7,19 @@ clearStoreIfPossible nix-instantiate --restrict-eval --eval -E '1 + 2' (! nix-instantiate --eval --restrict-eval ./restricted.nix) (! nix-instantiate --eval --restrict-eval <(echo '1 + 2')) + +mkdir -p "$TEST_ROOT/nix" +cp ./simple.nix "$TEST_ROOT/nix" +cp ./simple.builder.sh "$TEST_ROOT/nix" +cp "${config_nix}" "$TEST_ROOT/nix" +simple_nix="$TEST_ROOT/nix/simple.nix" +# N.B. redefine +config_nix="$TEST_ROOT/nix/config.nix" +removeBuildDirRef "${simple_nix}" +cd "$TEST_ROOT/nix" + nix-instantiate --restrict-eval ./simple.nix -I src=. -nix-instantiate --restrict-eval ./simple.nix -I src1=simple.nix -I src2=config.nix -I src3=./simple.builder.sh +nix-instantiate --restrict-eval ./simple.nix -I src1=./simple.nix -I src2=./config.nix -I src3=./simple.builder.sh # no default NIX_PATH (unset NIX_PATH; ! nix-instantiate --restrict-eval --find-file .) @@ -19,25 +30,25 @@ nix-instantiate --restrict-eval --eval -E 'builtins.readFile ./simple.nix' -I sr expectStderr 1 nix-instantiate --restrict-eval --eval -E 'let __nixPath = [ { prefix = "foo"; path = ./.; } ]; in builtins.readFile ' | grepQuiet "forbidden in restricted mode" nix-instantiate --restrict-eval --eval -E 'let __nixPath = [ { prefix = "foo"; path = ./.; } ]; in builtins.readFile ' -I src=. -p=$(nix eval --raw --expr "builtins.fetchurl file://$(pwd)/restricted.sh" --impure --restrict-eval --allowed-uris "file://$(pwd)") -cmp $p restricted.sh +p=$(nix eval --raw --expr "builtins.fetchurl file://${_NIX_TEST_SOURCE_DIR}/restricted.sh" --impure --restrict-eval --allowed-uris "file://${_NIX_TEST_SOURCE_DIR}") +cmp "$p" "${_NIX_TEST_SOURCE_DIR}/restricted.sh" -(! nix eval --raw --expr "builtins.fetchurl file://$(pwd)/restricted.sh" --impure --restrict-eval) +(! nix eval --raw --expr "builtins.fetchurl file://${_NIX_TEST_SOURCE_DIR}/restricted.sh" --impure --restrict-eval) -(! nix eval --raw --expr "builtins.fetchurl file://$(pwd)/restricted.sh" --impure --restrict-eval --allowed-uris "file://$(pwd)/restricted.sh/") +(! nix eval --raw --expr "builtins.fetchurl file://${_NIX_TEST_SOURCE_DIR}/restricted.sh" --impure --restrict-eval --allowed-uris "file://${_NIX_TEST_SOURCE_DIR}/restricted.sh/") -nix eval --raw --expr "builtins.fetchurl file://$(pwd)/restricted.sh" --impure --restrict-eval --allowed-uris "file://$(pwd)/restricted.sh" +nix eval --raw --expr "builtins.fetchurl file://${_NIX_TEST_SOURCE_DIR}/restricted.sh" --impure --restrict-eval --allowed-uris "file://${_NIX_TEST_SOURCE_DIR}/restricted.sh" (! nix eval --raw --expr "builtins.fetchurl https://github.com/NixOS/patchelf/archive/master.tar.gz" --impure --restrict-eval) (! nix eval --raw --expr "builtins.fetchTarball https://github.com/NixOS/patchelf/archive/master.tar.gz" --impure --restrict-eval) (! nix eval --raw --expr "fetchGit git://github.com/NixOS/patchelf.git" --impure --restrict-eval) -ln -sfn $(pwd)/restricted.nix $TEST_ROOT/restricted.nix +ln -sfn "${_NIX_TEST_SOURCE_DIR}/restricted.nix" "$TEST_ROOT/restricted.nix" [[ $(nix-instantiate --eval $TEST_ROOT/restricted.nix) == 3 ]] (! nix-instantiate --eval --restrict-eval $TEST_ROOT/restricted.nix) (! nix-instantiate --eval --restrict-eval $TEST_ROOT/restricted.nix -I $TEST_ROOT) (! nix-instantiate --eval --restrict-eval $TEST_ROOT/restricted.nix -I .) -nix-instantiate --eval --restrict-eval $TEST_ROOT/restricted.nix -I $TEST_ROOT -I . +nix-instantiate --eval --restrict-eval "$TEST_ROOT/restricted.nix" -I "$TEST_ROOT" -I "${_NIX_TEST_SOURCE_DIR}" [[ $(nix eval --raw --impure --restrict-eval -I . --expr 'builtins.readFile "${import ./simple.nix}/hello"') == 'Hello World!' ]] @@ -54,12 +65,12 @@ expectStderr 1 nix-instantiate --restrict-eval --eval -E "let __nixPath = [ { pr [[ $(nix-instantiate --restrict-eval --eval -E "let __nixPath = [ { prefix = \"foo\"; path = $TEST_ROOT/tunnel.d; } ]; in builtins.readDir " -I $TEST_ROOT/tunnel.d) == '{ "tunnel.d" = "directory"; }' ]] # Check whether we can leak symlink information through directory traversal. -traverseDir="$(pwd)/restricted-traverse-me" -ln -sfn "$(pwd)/restricted-secret" "$(pwd)/restricted-innocent" +traverseDir="${_NIX_TEST_SOURCE_DIR}/restricted-traverse-me" +ln -sfn "${_NIX_TEST_SOURCE_DIR}/restricted-secret" "${_NIX_TEST_SOURCE_DIR}/restricted-innocent" mkdir -p "$traverseDir" goUp="..$(echo "$traverseDir" | sed -e 's,[^/]\+,..,g')" output="$(nix eval --raw --restrict-eval -I "$traverseDir" \ - --expr "builtins.readFile \"$traverseDir/$goUp$(pwd)/restricted-innocent\"" \ + --expr "builtins.readFile \"$traverseDir/$goUp${_NIX_TEST_SOURCE_DIR}/restricted-innocent\"" \ 2>&1 || :)" echo "$output" | grep "is forbidden" echo "$output" | grepInverse -F restricted-secret diff --git a/tests/functional/search.nix b/tests/functional/search.nix index fea6e7a7a..3c3564bda 100644 --- a/tests/functional/search.nix +++ b/tests/functional/search.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; { hello = mkDerivation rec { diff --git a/tests/functional/secure-drv-outputs.nix b/tests/functional/secure-drv-outputs.nix index b4ac8ff53..cd111c315 100644 --- a/tests/functional/secure-drv-outputs.nix +++ b/tests/functional/secure-drv-outputs.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; { diff --git a/tests/functional/selfref-gc.sh b/tests/functional/selfref-gc.sh index 518aea66b..dc4f14cc1 100755 --- a/tests/functional/selfref-gc.sh +++ b/tests/functional/selfref-gc.sh @@ -7,7 +7,7 @@ requireDaemonNewerThan "2.6.0pre20211215" clearStoreIfPossible nix-build --no-out-link -E ' - with import ./config.nix; + with import '"${config_nix}"'; let d1 = mkDerivation { name = "selfref-gc"; diff --git a/tests/functional/shell-hello.nix b/tests/functional/shell-hello.nix index c920d7cb4..fa02e2bb4 100644 --- a/tests/functional/shell-hello.nix +++ b/tests/functional/shell-hello.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; rec { hello = mkDerivation { diff --git a/tests/functional/shell.nix b/tests/functional/shell.nix index 9cae14b78..f6622a487 100644 --- a/tests/functional/shell.nix +++ b/tests/functional/shell.nix @@ -1,6 +1,6 @@ { inNixShell ? false, contentAddressed ? false, fooContents ? "foo" }: -let cfg = import ./config.nix; in +let cfg = import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; in with cfg; let diff --git a/tests/functional/simple-failing.nix b/tests/functional/simple-failing.nix index d176c9c51..228971734 100644 --- a/tests/functional/simple-failing.nix +++ b/tests/functional/simple-failing.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; mkDerivation { name = "simple-failing"; diff --git a/tests/functional/simple.nix b/tests/functional/simple.nix index 2035ca294..96237695c 100644 --- a/tests/functional/simple.nix +++ b/tests/functional/simple.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; mkDerivation { name = "simple"; diff --git a/tests/functional/structured-attrs-shell.nix b/tests/functional/structured-attrs-shell.nix index 57c1e6bd2..7ed28c03f 100644 --- a/tests/functional/structured-attrs-shell.nix +++ b/tests/functional/structured-attrs-shell.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; let dep = mkDerivation { name = "dep"; diff --git a/tests/functional/structured-attrs.nix b/tests/functional/structured-attrs.nix index e93139a44..ae461c21a 100644 --- a/tests/functional/structured-attrs.nix +++ b/tests/functional/structured-attrs.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; let diff --git a/tests/functional/symlink-derivation.nix b/tests/functional/symlink-derivation.nix index e9a74cdce..96765d355 100644 --- a/tests/functional/symlink-derivation.nix +++ b/tests/functional/symlink-derivation.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; let foo_in_store = builtins.toFile "foo" "foo"; diff --git a/tests/functional/tarball.sh b/tests/functional/tarball.sh index 0682869b2..720b3688f 100755 --- a/tests/functional/tarball.sh +++ b/tests/functional/tarball.sh @@ -10,7 +10,7 @@ tarroot=$TEST_ROOT/tarball rm -rf "$tarroot" mkdir -p "$tarroot" cp dependencies.nix "$tarroot/default.nix" -cp config.nix dependencies.builder*.sh "$tarroot/" +cp "${config_nix}" dependencies.builder*.sh "$tarroot/" touch -d '@1000000000' "$tarroot" "$tarroot"/* hash=$(nix hash path "$tarroot") @@ -45,7 +45,7 @@ test_tarball() { nix-instantiate --eval -E 'with ; 1 + 2' -I fnord=file:///no-such-tarball"$ext" (! nix-instantiate --eval -E ' 1' -I fnord=file:///no-such-tarball"$ext") - nix-instantiate --eval -E '' -I fnord=file:///no-such-tarball"$ext" -I fnord=. + nix-instantiate --eval -E '' -I fnord=file:///no-such-tarball"$ext" -I fnord="${_NIX_TEST_BUILD_DIR}" # Ensure that the `name` attribute isn’t accepted as that would mess # with the content-addressing diff --git a/tests/functional/test-libstoreconsumer.sh b/tests/functional/test-libstoreconsumer.sh index 2adead1c0..5b019a1d0 100755 --- a/tests/functional/test-libstoreconsumer.sh +++ b/tests/functional/test-libstoreconsumer.sh @@ -4,5 +4,5 @@ source common.sh drv="$(nix-instantiate simple.nix)" cat "$drv" -out="$(./test-libstoreconsumer/test-libstoreconsumer "$drv")" +out="$("${_NIX_TEST_BUILD_DIR}/test-libstoreconsumer/test-libstoreconsumer" "$drv")" grep -F "Hello World!" < "$out/hello" diff --git a/tests/functional/timeout.nix b/tests/functional/timeout.nix index d0e949e31..ad71e61e2 100644 --- a/tests/functional/timeout.nix +++ b/tests/functional/timeout.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; { diff --git a/tests/functional/user-envs.nix b/tests/functional/user-envs.nix index 46f8b51dd..c8e846d4b 100644 --- a/tests/functional/user-envs.nix +++ b/tests/functional/user-envs.nix @@ -2,7 +2,7 @@ { foo ? "foo" }: -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; assert foo == "foo"; diff --git a/tests/functional/why-depends.sh b/tests/functional/why-depends.sh index ce53546d8..45d1f2f0b 100755 --- a/tests/functional/why-depends.sh +++ b/tests/functional/why-depends.sh @@ -4,7 +4,7 @@ source common.sh clearStoreIfPossible -cp ./dependencies.nix ./dependencies.builder0.sh ./config.nix $TEST_HOME +cp ./dependencies.nix ./dependencies.builder0.sh "${config_nix}" $TEST_HOME cd $TEST_HOME diff --git a/tests/nixos/functional/common.nix b/tests/nixos/functional/common.nix index 51fd76884..86d55d0b6 100644 --- a/tests/nixos/functional/common.nix +++ b/tests/nixos/functional/common.nix @@ -55,6 +55,10 @@ in -e 's!nix_tests += test-libstoreconsumer\.sh!!' \ ; + _NIX_TEST_SOURCE_DIR="$(realpath tests/functional)" + export _NIX_TEST_SOURCE_DIR + export _NIX_TEST_BUILD_DIR="''${_NIX_TEST_SOURCE_DIR}" + export isTestOnNixOS=1 export version=${config.nix.package.version} export NIX_REMOTE_=daemon From 7b7e8a33075cd16c983ac1f9defc7bdbcd5d45bc Mon Sep 17 00:00:00 2001 From: Brian McKenna Date: Mon, 4 Nov 2024 11:51:26 +1100 Subject: [PATCH 362/718] Fix compilation of nix-build on Windows --- src/nix-build/nix-build.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc index 3222ab96d..c394836da 100644 --- a/src/nix-build/nix-build.cc +++ b/src/nix-build/nix-build.cc @@ -536,7 +536,7 @@ static void main_nix_build(int argc, char * * argv) env["__ETC_PROFILE_SOURCED"] = "1"; } - env["NIX_BUILD_TOP"] = env["TMPDIR"] = env["TEMPDIR"] = env["TMP"] = env["TEMP"] = tmpDir.path(); + env["NIX_BUILD_TOP"] = env["TMPDIR"] = env["TEMPDIR"] = env["TMP"] = env["TEMP"] = tmpDir.path().string(); env["NIX_STORE"] = store->storeDir; env["NIX_BUILD_CORES"] = std::to_string(settings.buildCores); From 8ae5610c114c3f147638b91a6a98dc3ac2b01b1a Mon Sep 17 00:00:00 2001 From: Brian McKenna Date: Mon, 4 Nov 2024 19:19:42 +1100 Subject: [PATCH 363/718] Set minimum Windows API to Windows 8 Anything less won't compile because we're using GetCurrentThreadStackLimits from Windows 8. --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 4d70be0e8..ee1a0de31 100644 --- a/Makefile +++ b/Makefile @@ -91,6 +91,7 @@ ifdef HOST_WINDOWS # # TODO do not do this, and instead do fine-grained export annotations. GLOBAL_LDFLAGS += -Wl,--export-all-symbols + GLOBAL_CXXFLAGS += -D_WIN32_WINNT=0x0602 endif GLOBAL_CXXFLAGS += -g -Wall -Wdeprecated-copy -Wignored-qualifiers -Wimplicit-fallthrough -Werror=unused-result -Werror=suggest-override -include $(buildprefix)config.h -std=c++2a -I src From d711c7e965f9578d7cadd6c2fe96d7c912d1ad95 Mon Sep 17 00:00:00 2001 From: Brian McKenna Date: Mon, 4 Nov 2024 19:30:15 +1100 Subject: [PATCH 364/718] Fix compilation of eval under Windows --- src/libexpr/eval.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index f17753415..e4937735b 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -2834,7 +2834,9 @@ void EvalState::printStatistics() #endif #if HAVE_BOEHMGC {GC_is_incremental_mode() ? "gcNonIncremental" : "gc", gcFullOnlyTime}, +#ifndef _WIN32 // TODO implement {GC_is_incremental_mode() ? "gcNonIncrementalFraction" : "gcFraction", gcFullOnlyTime / cpuTime}, +#endif #endif }; topObj["envs"] = { From 0b790b4849c9298f99846b707012aa3507a64ea1 Mon Sep 17 00:00:00 2001 From: Bryan Honof Date: Thu, 12 Sep 2024 03:04:52 +0200 Subject: [PATCH 365/718] feat: add flag `set-env-var` to `MixEnvironment` --- src/libcmd/command.cc | 88 ++++++++++++++++++++-------- src/libcmd/command.hh | 13 ++-- src/libutil/environment-variables.hh | 2 + tests/functional/flakes/develop.sh | 6 +- 4 files changed, 76 insertions(+), 33 deletions(-) diff --git a/src/libcmd/command.cc b/src/libcmd/command.cc index 6d8bfc19b..295d290c5 100644 --- a/src/libcmd/command.cc +++ b/src/libcmd/command.cc @@ -1,3 +1,4 @@ +#include #include #include "command.hh" @@ -9,8 +10,7 @@ #include "profiles.hh" #include "repl.hh" #include "strings.hh" - -extern char * * environ __attribute__((weak)); +#include "environment-variables.hh" namespace nix { @@ -285,48 +285,88 @@ MixDefaultProfile::MixDefaultProfile() MixEnvironment::MixEnvironment() : ignoreEnvironment(false) { addFlag({ - .longName = "ignore-environment", + .longName = "ignore-env", + .aliases = {"ignore-environment"}, .shortName = 'i', - .description = "Clear the entire environment (except those specified with `--keep`).", + .description = "Clear the entire environment, except for those specified with `--keep-env-var`.", + .category = environmentVariablesCategory, .handler = {&ignoreEnvironment, true}, }); addFlag({ - .longName = "keep", + .longName = "keep-env-var", + .aliases = {"keep"}, .shortName = 'k', - .description = "Keep the environment variable *name*.", + .description = "Keep the environment variable *name*, when using `--ignore-env`.", + .category = environmentVariablesCategory, .labels = {"name"}, - .handler = {[&](std::string s) { keep.insert(s); }}, + .handler = {[&](std::string s) { keepVars.insert(s); }}, }); addFlag({ - .longName = "unset", + .longName = "unset-env-var", + .aliases = {"unset"}, .shortName = 'u', .description = "Unset the environment variable *name*.", + .category = environmentVariablesCategory, .labels = {"name"}, - .handler = {[&](std::string s) { unset.insert(s); }}, + .handler = {[&](std::string name) { + if (setVars.contains(name)) + throw UsageError("Cannot unset environment variable '%s' that is set with '%s'", name, "--set-env-var"); + + unsetVars.insert(name); + }}, + }); + + addFlag({ + .longName = "set-env-var", + .shortName = 's', + .description = "Add/override an environment variable *name* with *value*.\n\n" + "> **Notes**\n" + ">\n" + "> Duplicate definitions will be overwritten, last one wins.\n\n" + "> Cancles out with `--unset-env-var`.\n\n", + .category = environmentVariablesCategory, + .labels = {"name", "value"}, + .handler = {[&](std::string name, std::string value) { + if (unsetVars.contains(name)) + throw UsageError( + "Cannot set environment variable '%s' that is unset with '%s'", name, "--unset-env-var"); + + if (setVars.contains(name)) + throw UsageError( + "Duplicate definition of environment variable '%s' with '%s' is ambiguous", name, "--set-env-var"); + + setVars.insert_or_assign(name, value); + }}, }); } void MixEnvironment::setEnviron() { - if (ignoreEnvironment) { - if (!unset.empty()) - throw UsageError("--unset does not make sense with --ignore-environment"); + if (ignoreEnvironment && !unsetVars.empty()) + throw UsageError("--unset-env-var does not make sense with --ignore-env"); - for (const auto & var : keep) { - auto val = getenv(var.c_str()); - if (val) stringsEnv.emplace_back(fmt("%s=%s", var.c_str(), val)); - } + if (!ignoreEnvironment && !keepVars.empty()) + throw UsageError("--keep-env-var does not make sense without --ignore-env"); - vectorEnv = stringsToCharPtrs(stringsEnv); - environ = vectorEnv.data(); - } else { - if (!keep.empty()) - throw UsageError("--keep does not make sense without --ignore-environment"); + auto env = getEnv(); - for (const auto & var : unset) - unsetenv(var.c_str()); - } + if (ignoreEnvironment) + std::erase_if(env, [&](const auto & var) { + return !keepVars.contains(var.first); + }); + + for (const auto & [name, value] : setVars) + env[name] = value; + + if (!unsetVars.empty()) + std::erase_if(env, [&](const auto & var) { + return unsetVars.contains(var.first); + }); + + replaceEnv(env); + + return; } } diff --git a/src/libcmd/command.hh b/src/libcmd/command.hh index 4a72627ed..b823a1c6b 100644 --- a/src/libcmd/command.hh +++ b/src/libcmd/command.hh @@ -315,17 +315,18 @@ struct MixDefaultProfile : MixProfile struct MixEnvironment : virtual Args { - StringSet keep, unset; - Strings stringsEnv; - std::vector vectorEnv; + StringSet keepVars; + StringSet unsetVars; + std::map setVars; bool ignoreEnvironment; MixEnvironment(); /*** - * Modify global environ based on `ignoreEnvironment`, `keep`, and - * `unset`. It's expected that exec will be called before this class - * goes out of scope, otherwise `environ` will become invalid. + * Modify global environ based on `ignoreEnvironment`, `keep`, + * `unset`, and `added`. It's expected that exec will be called + * before this class goes out of scope, otherwise `environ` will + * become invalid. */ void setEnviron(); }; diff --git a/src/libutil/environment-variables.hh b/src/libutil/environment-variables.hh index 879e1f304..1a95f5c97 100644 --- a/src/libutil/environment-variables.hh +++ b/src/libutil/environment-variables.hh @@ -13,6 +13,8 @@ namespace nix { +static constexpr auto environmentVariablesCategory = "Options that change environment variables"; + /** * @return an environment variable. */ diff --git a/tests/functional/flakes/develop.sh b/tests/functional/flakes/develop.sh index df24f19f0..ba41a5feb 100755 --- a/tests/functional/flakes/develop.sh +++ b/tests/functional/flakes/develop.sh @@ -47,9 +47,9 @@ echo "\$ENVVAR" EOF )" = "a" ]] -# Test whether `nix develop --ignore-environment` does _not_ pass through environment variables. +# Test whether `nix develop --ignore-env` does _not_ pass through environment variables. [[ -z "$( - ENVVAR=a nix develop --ignore-environment --no-write-lock-file .#hello < Date: Thu, 19 Sep 2024 18:43:22 +0200 Subject: [PATCH 366/718] test(functional): add tests for new environment operation flags --- maintainers/flake-module.nix | 1 - src/libcmd/command.cc | 6 +-- tests/functional/flakes/develop.sh | 87 +++++++++++++++++++++++++++--- 3 files changed, 81 insertions(+), 13 deletions(-) diff --git a/maintainers/flake-module.nix b/maintainers/flake-module.nix index 225b0b300..5bf7837f7 100644 --- a/maintainers/flake-module.nix +++ b/maintainers/flake-module.nix @@ -547,7 +547,6 @@ ''^tests/functional/flakes/absolute-paths\.sh$'' ''^tests/functional/flakes/check\.sh$'' ''^tests/functional/flakes/config\.sh$'' - ''^tests/functional/flakes/develop\.sh$'' ''^tests/functional/flakes/flakes\.sh$'' ''^tests/functional/flakes/follow-paths\.sh$'' ''^tests/functional/flakes/prefetch\.sh$'' diff --git a/src/libcmd/command.cc b/src/libcmd/command.cc index 295d290c5..2d9731ca6 100644 --- a/src/libcmd/command.cc +++ b/src/libcmd/command.cc @@ -321,11 +321,7 @@ MixEnvironment::MixEnvironment() : ignoreEnvironment(false) addFlag({ .longName = "set-env-var", .shortName = 's', - .description = "Add/override an environment variable *name* with *value*.\n\n" - "> **Notes**\n" - ">\n" - "> Duplicate definitions will be overwritten, last one wins.\n\n" - "> Cancles out with `--unset-env-var`.\n\n", + .description = "Sets an environment variable *name* with *value*.", .category = environmentVariablesCategory, .labels = {"name", "value"}, .handler = {[&](std::string name, std::string value) { diff --git a/tests/functional/flakes/develop.sh b/tests/functional/flakes/develop.sh index ba41a5feb..2e75081d4 100755 --- a/tests/functional/flakes/develop.sh +++ b/tests/functional/flakes/develop.sh @@ -5,11 +5,11 @@ source ../common.sh TODO_NixOS clearStore -rm -rf $TEST_HOME/.cache $TEST_HOME/.config $TEST_HOME/.local +rm -rf "$TEST_HOME/.cache" "$TEST_HOME/.config" "$TEST_HOME/.local" # Create flake under test. -cp ../shell-hello.nix "${config_nix}" $TEST_HOME/ -cat <$TEST_HOME/flake.nix +cp ../shell-hello.nix "$config_nix" "$TEST_HOME/" +cat <"$TEST_HOME/flake.nix" { inputs.nixpkgs.url = "$TEST_HOME/nixpkgs"; outputs = {self, nixpkgs}: { @@ -24,13 +24,13 @@ cat <$TEST_HOME/flake.nix EOF # Create fake nixpkgs flake. -mkdir -p $TEST_HOME/nixpkgs -cp "${config_nix}" ../shell.nix $TEST_HOME/nixpkgs +mkdir -p "$TEST_HOME/nixpkgs" +cp "${config_nix}" ../shell.nix "$TEST_HOME/nixpkgs" # `config.nix` cannot be gotten via build dir / env var (runs afoul pure eval). Instead get from flake. removeBuildDirRef "$TEST_HOME/nixpkgs"/*.nix -cat <$TEST_HOME/nixpkgs/flake.nix +cat <"$TEST_HOME/nixpkgs/flake.nix" { outputs = {self}: { legacyPackages.$system.bashInteractive = (import ./shell.nix {}).bashInteractive; @@ -38,7 +38,7 @@ cat <$TEST_HOME/nixpkgs/flake.nix } EOF -cd $TEST_HOME +cd "$TEST_HOME" # Test whether `nix develop` passes through environment variables. [[ "$( @@ -54,6 +54,79 @@ echo "\$ENVVAR" EOF )" ]] +# Test wether `--keep-env-var` keeps the environment variable. +( + expect='BAR' + got="$(FOO='BAR' nix develop --ignore-env --keep-env-var FOO --no-write-lock-file .#hello < Date: Thu, 19 Sep 2024 19:15:31 +0200 Subject: [PATCH 367/718] chore: run formatters --- maintainers/flake-module.nix | 2 - src/libcmd/command.cc | 82 ++++++++++++++++++------------------ src/libcmd/command.hh | 33 +++++++-------- 3 files changed, 57 insertions(+), 60 deletions(-) diff --git a/maintainers/flake-module.nix b/maintainers/flake-module.nix index 5bf7837f7..fdb031302 100644 --- a/maintainers/flake-module.nix +++ b/maintainers/flake-module.nix @@ -28,8 +28,6 @@ ''^src/build-remote/build-remote\.cc$'' ''^src/libcmd/built-path\.cc$'' ''^src/libcmd/built-path\.hh$'' - ''^src/libcmd/command\.cc$'' - ''^src/libcmd/command\.hh$'' ''^src/libcmd/common-eval-args\.cc$'' ''^src/libcmd/common-eval-args\.hh$'' ''^src/libcmd/editor-for\.cc$'' diff --git a/src/libcmd/command.cc b/src/libcmd/command.cc index 2d9731ca6..1a4c76ec5 100644 --- a/src/libcmd/command.cc +++ b/src/libcmd/command.cc @@ -23,7 +23,8 @@ nix::Commands RegisterCommand::getCommandsFor(const std::vector & p if (name.size() == prefix.size() + 1) { bool equal = true; for (size_t i = 0; i < prefix.size(); ++i) - if (name[i] != prefix[i]) equal = false; + if (name[i] != prefix[i]) + equal = false; if (equal) res.insert_or_assign(name[prefix.size()], command); } @@ -42,16 +43,16 @@ void NixMultiCommand::run() std::set subCommandTextLines; for (auto & [name, _] : commands) subCommandTextLines.insert(fmt("- `%s`", name)); - std::string markdownError = fmt("`nix %s` requires a sub-command. Available sub-commands:\n\n%s\n", - commandName, concatStringsSep("\n", subCommandTextLines)); + std::string markdownError = + fmt("`nix %s` requires a sub-command. Available sub-commands:\n\n%s\n", + commandName, + concatStringsSep("\n", subCommandTextLines)); throw UsageError(renderMarkdownToTerminal(markdownError)); } command->second->run(); } -StoreCommand::StoreCommand() -{ -} +StoreCommand::StoreCommand() {} ref StoreCommand::getStore() { @@ -126,10 +127,8 @@ ref EvalCommand::getEvalStore() ref EvalCommand::getEvalState() { if (!evalState) { - evalState = - std::allocate_shared( - traceable_allocator(), - lookupPath, getEvalStore(), fetchSettings, evalSettings, getStore()); + evalState = std::allocate_shared( + traceable_allocator(), lookupPath, getEvalStore(), fetchSettings, evalSettings, getStore()); evalState->repair = repair; @@ -144,7 +143,8 @@ MixOperateOnOptions::MixOperateOnOptions() { addFlag({ .longName = "derivation", - .description = "Operate on the [store derivation](@docroot@/glossary.md#gloss-store-derivation) rather than its outputs.", + .description = + "Operate on the [store derivation](@docroot@/glossary.md#gloss-store-derivation) rather than its outputs.", .category = installablesCategory, .handler = {&operateOn, OperateOn::Derivation}, }); @@ -233,46 +233,48 @@ void StorePathCommand::run(ref store, StorePaths && storePaths) MixProfile::MixProfile() { - addFlag({ - .longName = "profile", - .description = "The profile to operate on.", - .labels = {"path"}, - .handler = {&profile}, - .completer = completePath - }); + addFlag( + {.longName = "profile", + .description = "The profile to operate on.", + .labels = {"path"}, + .handler = {&profile}, + .completer = completePath}); } void MixProfile::updateProfile(const StorePath & storePath) { - if (!profile) return; + if (!profile) + return; auto store = getStore().dynamic_pointer_cast(); - if (!store) throw Error("'--profile' is not supported for this Nix store"); + if (!store) + throw Error("'--profile' is not supported for this Nix store"); auto profile2 = absPath(*profile); - switchLink(profile2, - createGeneration(*store, profile2, storePath)); + switchLink(profile2, createGeneration(*store, profile2, storePath)); } void MixProfile::updateProfile(const BuiltPaths & buildables) { - if (!profile) return; + if (!profile) + return; StorePaths result; for (auto & buildable : buildables) { - std::visit(overloaded { - [&](const BuiltPath::Opaque & bo) { - result.push_back(bo.path); + std::visit( + overloaded{ + [&](const BuiltPath::Opaque & bo) { result.push_back(bo.path); }, + [&](const BuiltPath::Built & bfd) { + for (auto & output : bfd.outputs) { + result.push_back(output.second); + } + }, }, - [&](const BuiltPath::Built & bfd) { - for (auto & output : bfd.outputs) { - result.push_back(output.second); - } - }, - }, buildable.raw()); + buildable.raw()); } if (result.size() != 1) - throw UsageError("'--profile' requires that the arguments produce a single store path, but there are %d", result.size()); + throw UsageError( + "'--profile' requires that the arguments produce a single store path, but there are %d", result.size()); updateProfile(result[0]); } @@ -282,7 +284,8 @@ MixDefaultProfile::MixDefaultProfile() profile = getDefaultProfile(); } -MixEnvironment::MixEnvironment() : ignoreEnvironment(false) +MixEnvironment::MixEnvironment() + : ignoreEnvironment(false) { addFlag({ .longName = "ignore-env", @@ -338,7 +341,8 @@ MixEnvironment::MixEnvironment() : ignoreEnvironment(false) }); } -void MixEnvironment::setEnviron() { +void MixEnvironment::setEnviron() +{ if (ignoreEnvironment && !unsetVars.empty()) throw UsageError("--unset-env-var does not make sense with --ignore-env"); @@ -348,17 +352,13 @@ void MixEnvironment::setEnviron() { auto env = getEnv(); if (ignoreEnvironment) - std::erase_if(env, [&](const auto & var) { - return !keepVars.contains(var.first); - }); + std::erase_if(env, [&](const auto & var) { return !keepVars.contains(var.first); }); for (const auto & [name, value] : setVars) env[name] = value; if (!unsetVars.empty()) - std::erase_if(env, [&](const auto & var) { - return unsetVars.contains(var.first); - }); + std::erase_if(env, [&](const auto & var) { return unsetVars.contains(var.first); }); replaceEnv(env); diff --git a/src/libcmd/command.hh b/src/libcmd/command.hh index b823a1c6b..8da4327c2 100644 --- a/src/libcmd/command.hh +++ b/src/libcmd/command.hh @@ -13,7 +13,7 @@ namespace nix { extern std::string programPath; -extern char * * savedArgv; +extern char ** savedArgv; class EvalState; struct Pos; @@ -24,7 +24,8 @@ static constexpr Command::Category catSecondary = 100; static constexpr Command::Category catUtility = 101; static constexpr Command::Category catNixInstallation = 102; -static constexpr auto installablesCategory = "Options that change the interpretation of [installables](@docroot@/command-ref/new-cli/nix.md#installables)"; +static constexpr auto installablesCategory = + "Options that change the interpretation of [installables](@docroot@/command-ref/new-cli/nix.md#installables)"; struct NixMultiCommand : MultiCommand, virtual Command { @@ -112,7 +113,9 @@ struct MixFlakeOptions : virtual Args, EvalCommand * arguments) so that the completions for these flags can use them. */ virtual std::vector getFlakeRefsForCompletion() - { return {}; } + { + return {}; + } }; struct SourceExprCommand : virtual Args, MixFlakeOptions @@ -122,11 +125,9 @@ struct SourceExprCommand : virtual Args, MixFlakeOptions SourceExprCommand(); - Installables parseInstallables( - ref store, std::vector ss); + Installables parseInstallables(ref store, std::vector ss); - ref parseInstallable( - ref store, const std::string & installable); + ref parseInstallable(ref store, const std::string & installable); virtual Strings getDefaultFlakeAttrPaths(); @@ -272,10 +273,10 @@ struct RegisterCommand typedef std::map, std::function()>> Commands; static Commands * commands; - RegisterCommand(std::vector && name, - std::function()> command) + RegisterCommand(std::vector && name, std::function()> command) { - if (!commands) commands = new Commands; + if (!commands) + commands = new Commands; commands->emplace(name, command); } @@ -285,13 +286,13 @@ struct RegisterCommand template static RegisterCommand registerCommand(const std::string & name) { - return RegisterCommand({name}, [](){ return make_ref(); }); + return RegisterCommand({name}, []() { return make_ref(); }); } template static RegisterCommand registerCommand2(std::vector && name) { - return RegisterCommand(std::move(name), [](){ return make_ref(); }); + return RegisterCommand(std::move(name), []() { return make_ref(); }); } struct MixProfile : virtual StoreCommand @@ -313,7 +314,8 @@ struct MixDefaultProfile : MixProfile MixDefaultProfile(); }; -struct MixEnvironment : virtual Args { +struct MixEnvironment : virtual Args +{ StringSet keepVars; StringSet unsetVars; @@ -350,9 +352,6 @@ void completeFlakeRefWithFragment( std::string showVersions(const std::set & versions); void printClosureDiff( - ref store, - const StorePath & beforePath, - const StorePath & afterPath, - std::string_view indent); + ref store, const StorePath & beforePath, const StorePath & afterPath, std::string_view indent); } From f07aee934a31596b9431e529f383606df6b33ec7 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Sun, 3 Nov 2024 17:10:54 -0500 Subject: [PATCH 368/718] Update docs in line of build system changes --- doc/manual/source/development/testing.md | 41 ++++++++++++------------ 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/doc/manual/source/development/testing.md b/doc/manual/source/development/testing.md index 9d228fd16..a9f7c939c 100644 --- a/doc/manual/source/development/testing.md +++ b/doc/manual/source/development/testing.md @@ -29,7 +29,7 @@ The unit tests are defined using the [googletest] and [rapidcheck] frameworks. > ``` > src > ├── libexpr -> │ ├── local.mk +> │ ├── meson.build > │ ├── value/context.hh > │ ├── value/context.cc > │ … @@ -37,25 +37,24 @@ The unit tests are defined using the [googletest] and [rapidcheck] frameworks. > ├── tests > │ │ > │ … -> │ └── unit -> │ ├── libutil -> │ │ ├── local.mk -> │ │ … -> │ │ └── data -> │ │ ├── git/tree.txt -> │ │ … -> │ │ -> │ ├── libexpr-support -> │ │ ├── local.mk -> │ │ └── tests -> │ │ ├── value/context.hh -> │ │ ├── value/context.cc -> │ │ … -> │ │ -> │ ├── libexpr -> │ … ├── local.mk -> │ ├── value/context.cc -> │ … +> │ ├── libutil-tests +> │ │ ├── meson.build +> │ │ … +> │ │ └── data +> │ │ ├── git/tree.txt +> │ │ … +> │ │ +> │ ├── libexpr-test-support +> │ │ ├── meson.build +> │ │ └── tests +> │ │ ├── value/context.hh +> │ │ ├── value/context.cc +> │ │ … +> │ │ +> │ ├── libexpr-tests +> │ … ├── meson.build +> │ ├── value/context.cc +> │ … > … > ``` @@ -128,7 +127,7 @@ On other platforms they wouldn't be run at all. ## Functional tests -The functional tests reside under the `tests/functional` directory and are listed in `tests/functional/local.mk`. +The functional tests reside under the `tests/functional` directory and are listed in `tests/functional/meson.build`. Each test is a bash script. Functional tests are run during `installCheck` in the `nix` package build, as well as separately from the build, in VM tests. From f018a0b0c8d6bf4dd5fac85bbf99ada4677abf66 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Sun, 3 Nov 2024 17:10:34 -0500 Subject: [PATCH 369/718] Make functional tests on NixOS use Meson not Make Co-authored-by: Robert Hensing --- tests/functional/common/init.sh | 2 +- tests/functional/common/subst-vars.sh.in | 2 +- tests/functional/meson.build | 4 +- tests/nixos/default.nix | 10 ++--- tests/nixos/functional/common.nix | 51 +++++++++++------------- 5 files changed, 33 insertions(+), 36 deletions(-) diff --git a/tests/functional/common/init.sh b/tests/functional/common/init.sh index d849c0734..66b44c76f 100755 --- a/tests/functional/common/init.sh +++ b/tests/functional/common/init.sh @@ -19,7 +19,7 @@ EOF # When we're doing everything in the same store, we need to bring # dependencies into context. - sed -i "$(dirname "${BASH_SOURCE[0]}")"/../config.nix \ + sed -i "${_NIX_TEST_BUILD_DIR}/config.nix" \ -e 's^\(shell\) = "/nix/store/\([^/]*\)/\(.*\)";^\1 = builtins.appendContext "/nix/store/\2" { "/nix/store/\2".path = true; } + "/\3";^' \ -e 's^\(path\) = "/nix/store/\([^/]*\)/\(.*\)";^\1 = builtins.appendContext "/nix/store/\2" { "/nix/store/\2".path = true; } + "/\3";^' \ ; diff --git a/tests/functional/common/subst-vars.sh.in b/tests/functional/common/subst-vars.sh.in index 6ad22fa70..df140dec1 100644 --- a/tests/functional/common/subst-vars.sh.in +++ b/tests/functional/common/subst-vars.sh.in @@ -1,4 +1,4 @@ -# NOTE: instances of @variable@ are substituted as defined in /mk/templates.mk +# NOTE: instances of @variable@ are substituted by the build system if [[ -z "${COMMON_SUBST_VARS_SH_SOURCED-}" ]]; then diff --git a/tests/functional/meson.build b/tests/functional/meson.build index b3ac1560c..3f514e856 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -1,4 +1,4 @@ -project('nix-functional-tests', 'cpp', +project('nix-functional-tests', version : files('.version'), default_options : [ 'cpp_std=c++2a', @@ -170,6 +170,7 @@ suites = [ nix_store = dependency('nix-store', required : false) if nix_store.found() + add_languages('cpp') subdir('test-libstoreconsumer') suites += { 'name': 'libstoreconsumer', @@ -187,6 +188,7 @@ endif # Plugin tests require shared libraries support. nix_expr = dependency('nix-expr', required : false) if nix_expr.found() and get_option('default_library') != 'static' + add_languages('cpp') subdir('plugins') suites += { 'name': 'plugins', diff --git a/tests/nixos/default.nix b/tests/nixos/default.nix index 49e2603e1..17bfdea38 100644 --- a/tests/nixos/default.nix +++ b/tests/nixos/default.nix @@ -21,7 +21,8 @@ let defaults = { nixpkgs.pkgs = nixpkgsFor.${system}.native; nix.checkAllErrors = false; - nix.package = noTests nixpkgsFor.${system}.native.nix; + # TODO: decide which packaging stage to use. `nix-cli` is efficient, but not the same as the user-facing `everything.nix` package (`default`). Perhaps a good compromise is `everything.nix` + `noTests` defined above? + nix.package = nixpkgsFor.${system}.native.nixComponents.nix-cli; }; _module.args.nixpkgs = nixpkgs; _module.args.system = system; @@ -33,10 +34,9 @@ let forNix = nixVersion: runNixOSTestFor system { imports = [test]; defaults.nixpkgs.overlays = [(curr: prev: { - # NOTE: noTests pkg might not have been built yet for some older versions of the package - # and in versions before 2.25, the untested build wasn't shared with the tested build yet - # Add noTests here when those versions become irrelevant. - nix = (builtins.getFlake "nix/${nixVersion}").packages.${system}.nix; + nix = let + packages = (builtins.getFlake "nix/${nixVersion}").packages.${system}; + in packages.nix-cli or packages.nix; })]; }; }; diff --git a/tests/nixos/functional/common.nix b/tests/nixos/functional/common.nix index 86d55d0b6..561271ba0 100644 --- a/tests/nixos/functional/common.nix +++ b/tests/nixos/functional/common.nix @@ -24,47 +24,42 @@ in environment.systemPackages = let run-test-suite = pkgs.writeShellApplication { name = "run-test-suite"; - runtimeInputs = [ pkgs.gnumake pkgs.jq pkgs.git ]; + runtimeInputs = [ + pkgs.meson + pkgs.ninja + pkgs.jq + pkgs.git + + # Want to avoid `/run/current-system/sw/bin/bash` because we + # want a store path. Likewise for coreutils. + pkgs.bash + pkgs.coreutils + ]; text = '' set -x + cat /proc/sys/fs/file-max ulimit -Hn ulimit -Sn + cd ~ - cp -r ${pkgs.nix.overrideAttrs (o: { - name = "nix-configured-source"; - outputs = [ "out" ]; - separateDebugInfo = false; - disallowedReferences = [ ]; - buildPhase = ":"; - checkPhase = ":"; - installPhase = '' - cp -r . $out - ''; - installCheckPhase = ":"; - fixupPhase = ":"; - doInstallCheck = true; - })} nix + + cp -r ${pkgs.nixComponents.nix-functional-tests.src} nix chmod -R +w nix - cd nix - # Tests we don't need - echo >tests/functional/plugins/local.mk - sed -i tests/functional/local.mk \ - -e 's!nix_tests += plugins\.sh!!' \ - -e 's!nix_tests += test-libstoreconsumer\.sh!!' \ - ; - - _NIX_TEST_SOURCE_DIR="$(realpath tests/functional)" - export _NIX_TEST_SOURCE_DIR - export _NIX_TEST_BUILD_DIR="''${_NIX_TEST_SOURCE_DIR}" + chmod u+w nix/.version + echo ${pkgs.nixComponents.version} > nix/.version export isTestOnNixOS=1 - export version=${config.nix.package.version} + export NIX_REMOTE_=daemon export NIX_REMOTE=daemon + export NIX_STORE=${builtins.storeDir} - make -j1 installcheck --keep-going + + meson setup nix/tests/functional build + cd build + meson test -j1 --print-errorlogs ''; }; in [ From 142f55457beb07790c9e1e316b8b9d3b21a86228 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 4 Nov 2024 12:15:41 -0500 Subject: [PATCH 370/718] Test against tests using Meson-built Nix --- packaging/hydra.nix | 23 +++++++---------------- tests/functional/package.nix | 4 ++-- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/packaging/hydra.nix b/packaging/hydra.nix index cba1b2583..58efb6716 100644 --- a/packaging/hydra.nix +++ b/packaging/hydra.nix @@ -16,25 +16,16 @@ let inherit tarballs; }; - testNixVersions = pkgs: client: daemon: - pkgs.nixComponents.callPackage ../package.nix { + testNixVersions = pkgs: daemon: + pkgs.nixComponents.nix-functional-tests.override { pname = "nix-tests" + lib.optionalString (lib.versionAtLeast daemon.version "2.4pre20211005" && - lib.versionAtLeast client.version "2.4pre20211005") - "-${client.version}-against-${daemon.version}"; + lib.versionAtLeast pkgs.nix.version "2.4pre20211005") + "-${pkgs.nix.version}-against-${daemon.version}"; - test-client = client; test-daemon = daemon; - - doBuild = false; - - # This could be more accurate, but a shorter version will match the - # fine version with rev. This functionality is already covered in - # the normal test, so it's fine. - version = pkgs.nixComponents.version; - versionSuffix = pkgs.nixComponents.versionSuffix; }; # Technically we could just return `pkgs.nixComponents`, but for Hydra it's @@ -196,15 +187,15 @@ in let pkgs = nixpkgsFor.${system}.native; in pkgs.runCommand "install-tests" { - againstSelf = testNixVersions pkgs pkgs.nix pkgs.pkgs.nix; + againstSelf = testNixVersions pkgs pkgs.pkgs.nix; againstCurrentLatest = # FIXME: temporarily disable this on macOS because of #3605. if system == "x86_64-linux" - then testNixVersions pkgs pkgs.nix pkgs.nixVersions.latest + then testNixVersions pkgs pkgs.nixVersions.latest else null; # Disabled because the latest stable version doesn't handle # `NIX_DAEMON_SOCKET_PATH` which is required for the tests to work - # againstLatestStable = testNixVersions pkgs pkgs.nix pkgs.nixStable; + # againstLatestStable = testNixVersions pkgs pkgs.nixStable; } "touch $out"); installerTests = import ../tests/installer { diff --git a/tests/functional/package.nix b/tests/functional/package.nix index 9cf6b62e1..71029146b 100644 --- a/tests/functional/package.nix +++ b/tests/functional/package.nix @@ -24,6 +24,7 @@ # Configuration Options +, pname ? "nix-functional-tests" , version # For running the functional tests against a different pre-built Nix. @@ -35,8 +36,7 @@ let in mkMesonDerivation (finalAttrs: { - pname = "nix-functional-tests"; - inherit version; + inherit pname version; workDir = ./.; fileset = fileset.unions [ From 62ef9fa03c2171bfb90cb3a95c3efaca0ec95926 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 4 Nov 2024 13:07:26 -0500 Subject: [PATCH 371/718] Remove redundant `pkgs.pkgs` Co-authored-by: Robert Hensing --- packaging/hydra.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/hydra.nix b/packaging/hydra.nix index 58efb6716..c59435487 100644 --- a/packaging/hydra.nix +++ b/packaging/hydra.nix @@ -187,7 +187,7 @@ in let pkgs = nixpkgsFor.${system}.native; in pkgs.runCommand "install-tests" { - againstSelf = testNixVersions pkgs pkgs.pkgs.nix; + againstSelf = testNixVersions pkgs pkgs.nix; againstCurrentLatest = # FIXME: temporarily disable this on macOS because of #3605. if system == "x86_64-linux" From 42b5421d5a6dfb07e3f751a1166785eeeffd056a Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 4 Nov 2024 12:35:34 -0500 Subject: [PATCH 372/718] `hydraJobs.build{NoGc,ReadlineNoMarkdown}` build using Meson Getting ready for the complete switch-over Progress on #2503 --- packaging/hydra.nix | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/packaging/hydra.nix b/packaging/hydra.nix index c59435487..6da502079 100644 --- a/packaging/hydra.nix +++ b/packaging/hydra.nix @@ -73,20 +73,28 @@ in (forAllCrossSystems (crossSystem: lib.genAttrs [ "x86_64-linux" ] (system: nixpkgsFor.${system}.cross.${crossSystem}.nixComponents.${pkgName})))); - buildNoGc = forAllSystems (system: - self.packages.${system}.nix.override { enableGC = false; } - ); + buildNoGc = let + components = forAllSystems (system: + nixpkgsFor.${system}.native.nixComponents.overrideScope (self: super: { + nix-expr = super.nix-expr.override { enableGC = false; }; + }) + ); + in forAllPackages (pkgName: forAllSystems (system: components.${system}.${pkgName})); buildNoTests = forAllSystems (system: nixpkgsFor.${system}.native.nixComponents.nix-cli); # Toggles some settings for better coverage. Windows needs these # library combinations, and Debian build Nix with GNU readline too. - buildReadlineNoMarkdown = forAllSystems (system: - self.packages.${system}.nix.override { - enableMarkdown = false; - readlineFlavor = "readline"; - } - ); + buildReadlineNoMarkdown = let + components = forAllSystems (system: + nixpkgsFor.${system}.native.nixComponents.overrideScope (self: super: { + nix-cmd = super.nix-cmd.override { + enableMarkdown = false; + readlineFlavor = "readline"; + }; + }) + ); + in forAllPackages (pkgName: forAllSystems (system: components.${system}.${pkgName})); # Perl bindings for various platforms. perlBindings = forAllSystems (system: nixpkgsFor.${system}.native.nixComponents.nix-perl-bindings); From 39fd4705ac604c9c211b93ef0e6fbfa6d6d3b0d3 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 4 Nov 2024 14:04:21 -0500 Subject: [PATCH 373/718] Factor out the dev shell It had gotten rather big. Hopefully we'll eventually have some generic infra for a "multi-package dev shell" and not need so much code for this, but until then it's better in a separate file. --- flake.nix | 91 +-------------------------------------- packaging/dev-shell.nix | 94 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+), 89 deletions(-) create mode 100644 packaging/dev-shell.nix diff --git a/flake.nix b/flake.nix index 303779c2b..df274f205 100644 --- a/flake.nix +++ b/flake.nix @@ -294,95 +294,8 @@ }); devShells = let - makeShell = pkgs: stdenv: (pkgs.nix.override { inherit stdenv; forDevShell = true; }).overrideAttrs (attrs: - let - buildCanExecuteHost = stdenv.buildPlatform.canExecute stdenv.hostPlatform; - modular = devFlake.getSystem stdenv.buildPlatform.system; - transformFlag = prefix: flag: - assert builtins.isString flag; - let - rest = builtins.substring 2 (builtins.stringLength flag) flag; - in - "-D${prefix}:${rest}"; - havePerl = stdenv.buildPlatform == stdenv.hostPlatform && stdenv.hostPlatform.isUnix; - ignoreCrossFile = flags: builtins.filter (flag: !(lib.strings.hasInfix "cross-file" flag)) flags; - in { - pname = "shell-for-" + attrs.pname; - - # Remove the version suffix to avoid unnecessary attempts to substitute in nix develop - version = lib.fileContents ./.version; - name = attrs.pname; - - installFlags = "sysconfdir=$(out)/etc"; - shellHook = '' - PATH=$prefix/bin:$PATH - unset PYTHONPATH - export MANPATH=$out/share/man:$MANPATH - - # Make bash completion work. - XDG_DATA_DIRS+=:$out/share - ''; - - # We use this shell with the local checkout, not unpackPhase. - src = null; - - env = { - # Needed for Meson to find Boost. - # https://github.com/NixOS/nixpkgs/issues/86131. - BOOST_INCLUDEDIR = "${lib.getDev pkgs.nixDependencies.boost}/include"; - BOOST_LIBRARYDIR = "${lib.getLib pkgs.nixDependencies.boost}/lib"; - # For `make format`, to work without installing pre-commit - _NIX_PRE_COMMIT_HOOKS_CONFIG = - "${(pkgs.formats.yaml { }).generate "pre-commit-config.yaml" modular.pre-commit.settings.rawConfig}"; - }; - - mesonFlags = - map (transformFlag "libutil") (ignoreCrossFile pkgs.nixComponents.nix-util.mesonFlags) - ++ map (transformFlag "libstore") (ignoreCrossFile pkgs.nixComponents.nix-store.mesonFlags) - ++ map (transformFlag "libfetchers") (ignoreCrossFile pkgs.nixComponents.nix-fetchers.mesonFlags) - ++ lib.optionals havePerl (map (transformFlag "perl") (ignoreCrossFile pkgs.nixComponents.nix-perl-bindings.mesonFlags)) - ++ map (transformFlag "libexpr") (ignoreCrossFile pkgs.nixComponents.nix-expr.mesonFlags) - ++ map (transformFlag "libcmd") (ignoreCrossFile pkgs.nixComponents.nix-cmd.mesonFlags) - ; - - nativeBuildInputs = attrs.nativeBuildInputs or [] - ++ pkgs.nixComponents.nix-util.nativeBuildInputs - ++ pkgs.nixComponents.nix-store.nativeBuildInputs - ++ pkgs.nixComponents.nix-fetchers.nativeBuildInputs - ++ lib.optionals havePerl pkgs.nixComponents.nix-perl-bindings.nativeBuildInputs - ++ lib.optionals buildCanExecuteHost pkgs.nixComponents.nix-manual.externalNativeBuildInputs - ++ pkgs.nixComponents.nix-internal-api-docs.nativeBuildInputs - ++ pkgs.nixComponents.nix-external-api-docs.nativeBuildInputs - ++ pkgs.nixComponents.nix-functional-tests.externalNativeBuildInputs - ++ lib.optional - (!buildCanExecuteHost - # Hack around https://github.com/nixos/nixpkgs/commit/bf7ad8cfbfa102a90463433e2c5027573b462479 - && !(stdenv.hostPlatform.isWindows && stdenv.buildPlatform.isDarwin) - && stdenv.hostPlatform.emulatorAvailable pkgs.buildPackages - && lib.meta.availableOn stdenv.buildPlatform (stdenv.hostPlatform.emulator pkgs.buildPackages)) - pkgs.buildPackages.mesonEmulatorHook - ++ [ - pkgs.buildPackages.cmake - pkgs.buildPackages.shellcheck - pkgs.buildPackages.changelog-d - modular.pre-commit.settings.package - (pkgs.writeScriptBin "pre-commit-hooks-install" - modular.pre-commit.settings.installationScript) - ] - # TODO: Remove the darwin check once - # https://github.com/NixOS/nixpkgs/pull/291814 is available - ++ lib.optional (stdenv.cc.isClang && !stdenv.buildPlatform.isDarwin) pkgs.buildPackages.bear - ++ lib.optional (stdenv.cc.isClang && stdenv.hostPlatform == stdenv.buildPlatform) (lib.hiPrio pkgs.buildPackages.clang-tools); - - buildInputs = attrs.buildInputs or [] - ++ [ - pkgs.gtest - pkgs.rapidcheck - ] - ++ lib.optional havePerl pkgs.perl - ; - }); - in + makeShell = import ./packaging/dev-shell.nix { inherit lib devFlake; }; + in forAllSystems (system: let makeShells = prefix: pkgs: diff --git a/packaging/dev-shell.nix b/packaging/dev-shell.nix new file mode 100644 index 000000000..4d1e49c96 --- /dev/null +++ b/packaging/dev-shell.nix @@ -0,0 +1,94 @@ +{ lib, devFlake }: + +pkgs: stdenv: + +(pkgs.nix.override { forDevShell = true; }).overrideAttrs (attrs: + +let + buildCanExecuteHost = stdenv.buildPlatform.canExecute stdenv.hostPlatform; + modular = devFlake.getSystem stdenv.buildPlatform.system; + transformFlag = prefix: flag: + assert builtins.isString flag; + let + rest = builtins.substring 2 (builtins.stringLength flag) flag; + in + "-D${prefix}:${rest}"; + havePerl = stdenv.buildPlatform == stdenv.hostPlatform && stdenv.hostPlatform.isUnix; + ignoreCrossFile = flags: builtins.filter (flag: !(lib.strings.hasInfix "cross-file" flag)) flags; +in { + pname = "shell-for-" + attrs.pname; + + # Remove the version suffix to avoid unnecessary attempts to substitute in nix develop + version = lib.fileContents ../.version; + name = attrs.pname; + + installFlags = "sysconfdir=$(out)/etc"; + shellHook = '' + PATH=$prefix/bin:$PATH + unset PYTHONPATH + export MANPATH=$out/share/man:$MANPATH + + # Make bash completion work. + XDG_DATA_DIRS+=:$out/share + ''; + + # We use this shell with the local checkout, not unpackPhase. + src = null; + + env = { + # Needed for Meson to find Boost. + # https://github.com/NixOS/nixpkgs/issues/86131. + BOOST_INCLUDEDIR = "${lib.getDev pkgs.nixDependencies.boost}/include"; + BOOST_LIBRARYDIR = "${lib.getLib pkgs.nixDependencies.boost}/lib"; + # For `make format`, to work without installing pre-commit + _NIX_PRE_COMMIT_HOOKS_CONFIG = + "${(pkgs.formats.yaml { }).generate "pre-commit-config.yaml" modular.pre-commit.settings.rawConfig}"; + }; + + mesonFlags = + map (transformFlag "libutil") (ignoreCrossFile pkgs.nixComponents.nix-util.mesonFlags) + ++ map (transformFlag "libstore") (ignoreCrossFile pkgs.nixComponents.nix-store.mesonFlags) + ++ map (transformFlag "libfetchers") (ignoreCrossFile pkgs.nixComponents.nix-fetchers.mesonFlags) + ++ lib.optionals havePerl (map (transformFlag "perl") (ignoreCrossFile pkgs.nixComponents.nix-perl-bindings.mesonFlags)) + ++ map (transformFlag "libexpr") (ignoreCrossFile pkgs.nixComponents.nix-expr.mesonFlags) + ++ map (transformFlag "libcmd") (ignoreCrossFile pkgs.nixComponents.nix-cmd.mesonFlags) + ; + + nativeBuildInputs = attrs.nativeBuildInputs or [] + ++ pkgs.nixComponents.nix-util.nativeBuildInputs + ++ pkgs.nixComponents.nix-store.nativeBuildInputs + ++ pkgs.nixComponents.nix-fetchers.nativeBuildInputs + ++ pkgs.nixComponents.nix-expr.nativeBuildInputs + ++ lib.optionals havePerl pkgs.nixComponents.nix-perl-bindings.nativeBuildInputs + ++ lib.optionals buildCanExecuteHost pkgs.nixComponents.nix-manual.externalNativeBuildInputs + ++ pkgs.nixComponents.nix-internal-api-docs.nativeBuildInputs + ++ pkgs.nixComponents.nix-external-api-docs.nativeBuildInputs + ++ pkgs.nixComponents.nix-functional-tests.externalNativeBuildInputs + ++ lib.optional + (!buildCanExecuteHost + # Hack around https://github.com/nixos/nixpkgs/commit/bf7ad8cfbfa102a90463433e2c5027573b462479 + && !(stdenv.hostPlatform.isWindows && stdenv.buildPlatform.isDarwin) + && stdenv.hostPlatform.emulatorAvailable pkgs.buildPackages + && lib.meta.availableOn stdenv.buildPlatform (stdenv.hostPlatform.emulator pkgs.buildPackages)) + pkgs.buildPackages.mesonEmulatorHook + ++ [ + pkgs.buildPackages.cmake + pkgs.buildPackages.shellcheck + pkgs.buildPackages.changelog-d + modular.pre-commit.settings.package + (pkgs.writeScriptBin "pre-commit-hooks-install" + modular.pre-commit.settings.installationScript) + ] + # TODO: Remove the darwin check once + # https://github.com/NixOS/nixpkgs/pull/291814 is available + ++ lib.optional (stdenv.cc.isClang && !stdenv.buildPlatform.isDarwin) pkgs.buildPackages.bear + ++ lib.optional (stdenv.cc.isClang && stdenv.hostPlatform == stdenv.buildPlatform) (lib.hiPrio pkgs.buildPackages.clang-tools); + + buildInputs = attrs.buildInputs or [] + ++ [ + pkgs.gtest + pkgs.rapidcheck + ] + ++ lib.optional havePerl pkgs.perl + ; +}) From 9e1bc9c224a4a33fac36ce7e425266405f5afff3 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 4 Nov 2024 15:13:10 -0500 Subject: [PATCH 374/718] Make the choice of stdenv for the dev shell properly affect all deps We have per-stdenv package sets, so we should be using them. --- flake.nix | 28 +++++++++++++++------------- packaging/dev-shell.nix | 3 ++- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/flake.nix b/flake.nix index df274f205..cfb9021d5 100644 --- a/flake.nix +++ b/flake.nix @@ -295,21 +295,23 @@ devShells = let makeShell = import ./packaging/dev-shell.nix { inherit lib devFlake; }; + prefixAttrs = prefix: lib.mapAttrs' (k: v: lib.nameValuePair "${prefix}-${k}" v); in forAllSystems (system: - let - makeShells = prefix: pkgs: - lib.mapAttrs' - (k: v: lib.nameValuePair "${prefix}-${k}" v) - (forAllStdenvs (stdenvName: makeShell pkgs pkgs.${stdenvName})); - in - (makeShells "native" nixpkgsFor.${system}.native) // - (lib.optionalAttrs (!nixpkgsFor.${system}.native.stdenv.isDarwin) - (makeShells "static" nixpkgsFor.${system}.static) // - (forAllCrossSystems (crossSystem: let pkgs = nixpkgsFor.${system}.cross.${crossSystem}; in makeShell pkgs pkgs.stdenv))) // - { - default = self.devShells.${system}.native-stdenvPackages; - } + prefixAttrs "native" (forAllStdenvs (stdenvName: makeShell { + pkgs = nixpkgsFor.${system}.stdenvs."${stdenvName}Packages"; + })) // + lib.optionalAttrs (!nixpkgsFor.${system}.native.stdenv.isDarwin) ( + prefixAttrs "static" (forAllStdenvs (stdenvName: makeShell { + pkgs = nixpkgsFor.${system}.stdenvs."${stdenvName}Packages".pkgsStatic; + })) // + prefixAttrs "cross" (forAllCrossSystems (crossSystem: makeShell { + pkgs = nixpkgsFor.${system}.cross.${crossSystem}; + })) + ) // + { + default = self.devShells.${system}.native-stdenvPackages; + } ); }; } diff --git a/packaging/dev-shell.nix b/packaging/dev-shell.nix index 4d1e49c96..2ea880721 100644 --- a/packaging/dev-shell.nix +++ b/packaging/dev-shell.nix @@ -1,10 +1,11 @@ { lib, devFlake }: -pkgs: stdenv: +{ pkgs }: (pkgs.nix.override { forDevShell = true; }).overrideAttrs (attrs: let + stdenv = pkgs.nixDependencies.stdenv; buildCanExecuteHost = stdenv.buildPlatform.canExecute stdenv.hostPlatform; modular = devFlake.getSystem stdenv.buildPlatform.system; transformFlag = prefix: flag: From 26ea9053123dee2b88da0dc401ca4391f145e5eb Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 4 Nov 2024 14:33:09 -0500 Subject: [PATCH 375/718] Include more deps for the dev shell When we get rid of the make build system, we would be missing things. Incuding these packages' deps ensure we don't miss things. --- packaging/dev-shell.nix | 9 +++++---- src/libstore-tests/package.nix | 12 ++++++++---- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/packaging/dev-shell.nix b/packaging/dev-shell.nix index 2ea880721..4b2a87632 100644 --- a/packaging/dev-shell.nix +++ b/packaging/dev-shell.nix @@ -86,10 +86,11 @@ in { ++ lib.optional (stdenv.cc.isClang && stdenv.hostPlatform == stdenv.buildPlatform) (lib.hiPrio pkgs.buildPackages.clang-tools); buildInputs = attrs.buildInputs or [] - ++ [ - pkgs.gtest - pkgs.rapidcheck - ] + ++ pkgs.nixComponents.nix-util.buildInputs + ++ pkgs.nixComponents.nix-store.buildInputs + ++ pkgs.nixComponents.nix-fetchers.buildInputs + ++ pkgs.nixComponents.nix-expr.buildInputs + ++ pkgs.nixComponents.nix-store-tests.externalBuildInputs ++ lib.optional havePerl pkgs.perl ; }) diff --git a/src/libstore-tests/package.nix b/src/libstore-tests/package.nix index 5b2fd108b..3704d8c5c 100644 --- a/src/libstore-tests/package.nix +++ b/src/libstore-tests/package.nix @@ -38,15 +38,19 @@ mkMesonExecutable (finalAttrs: { (fileset.fileFilter (file: file.hasExt "hh") ./.) ]; - buildInputs = [ - nix-store - nix-store-c - nix-store-test-support + # Hack for sake of the dev shell + passthru.externalBuildInputs = [ sqlite rapidcheck gtest ]; + buildInputs = finalAttrs.passthru.externalBuildInputs ++ [ + nix-store + nix-store-c + nix-store-test-support + ]; + preConfigure = # "Inline" .version so it's not a symlink, and includes the suffix. # Do the meson utils, without modification. From 9dca7aeece188725d297340273fc63140d160815 Mon Sep 17 00:00:00 2001 From: Brian McKenna Date: Tue, 5 Nov 2024 23:36:02 +1100 Subject: [PATCH 376/718] Set Windows API version in Meson --- build-utils-meson/windows-version/meson.build | 6 ++++++ src/libexpr-c/meson.build | 1 + src/libexpr-test-support/meson.build | 1 + src/libexpr-tests/meson.build | 1 + src/libfetchers-tests/meson.build | 1 + src/libflake-tests/meson.build | 1 + src/libmain-c/meson.build | 1 + src/libstore-c/meson.build | 1 + src/libstore-test-support/meson.build | 1 + src/libstore-tests/meson.build | 1 + src/libstore/meson.build | 1 + src/libutil-c/meson.build | 1 + src/libutil-test-support/meson.build | 1 + src/libutil-tests/meson.build | 1 + src/libutil/meson.build | 1 + src/nix/meson.build | 1 + 16 files changed, 21 insertions(+) create mode 100644 build-utils-meson/windows-version/meson.build diff --git a/build-utils-meson/windows-version/meson.build b/build-utils-meson/windows-version/meson.build new file mode 100644 index 000000000..3a008e5df --- /dev/null +++ b/build-utils-meson/windows-version/meson.build @@ -0,0 +1,6 @@ +if host_machine.system() == 'windows' + # https://learn.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt?view=msvc-170 + # #define _WIN32_WINNT_WIN8 0x0602 + # We currently don't use any API which requires higher than this. + add_project_arguments([ '-D_WIN32_WINNT=0x0602' ], language: 'cpp') +endif diff --git a/src/libexpr-c/meson.build b/src/libexpr-c/meson.build index 6db5b83b8..4160f0d5a 100644 --- a/src/libexpr-c/meson.build +++ b/src/libexpr-c/meson.build @@ -75,6 +75,7 @@ headers = [config_h] + files( headers += files('nix_api_expr_internal.h') subdir('build-utils-meson/export-all-symbols') +subdir('build-utils-meson/windows-version') this_library = library( 'nixexprc', diff --git a/src/libexpr-test-support/meson.build b/src/libexpr-test-support/meson.build index 4f50478aa..b9e7f390d 100644 --- a/src/libexpr-test-support/meson.build +++ b/src/libexpr-test-support/meson.build @@ -56,6 +56,7 @@ headers = files( ) subdir('build-utils-meson/export-all-symbols') +subdir('build-utils-meson/windows-version') this_library = library( 'nix-expr-test-support', diff --git a/src/libexpr-tests/meson.build b/src/libexpr-tests/meson.build index 21c321334..5a5c9f1d4 100644 --- a/src/libexpr-tests/meson.build +++ b/src/libexpr-tests/meson.build @@ -28,6 +28,7 @@ subdir('build-utils-meson/subprojects') subdir('build-utils-meson/threads') subdir('build-utils-meson/export-all-symbols') +subdir('build-utils-meson/windows-version') rapidcheck = dependency('rapidcheck') deps_private += rapidcheck diff --git a/src/libfetchers-tests/meson.build b/src/libfetchers-tests/meson.build index dc9818e27..d948dbad6 100644 --- a/src/libfetchers-tests/meson.build +++ b/src/libfetchers-tests/meson.build @@ -27,6 +27,7 @@ subdir('build-utils-meson/subprojects') subdir('build-utils-meson/threads') subdir('build-utils-meson/export-all-symbols') +subdir('build-utils-meson/windows-version') rapidcheck = dependency('rapidcheck') deps_private += rapidcheck diff --git a/src/libflake-tests/meson.build b/src/libflake-tests/meson.build index c022d7f41..592a7493b 100644 --- a/src/libflake-tests/meson.build +++ b/src/libflake-tests/meson.build @@ -27,6 +27,7 @@ subdir('build-utils-meson/subprojects') subdir('build-utils-meson/threads') subdir('build-utils-meson/export-all-symbols') +subdir('build-utils-meson/windows-version') rapidcheck = dependency('rapidcheck') deps_private += rapidcheck diff --git a/src/libmain-c/meson.build b/src/libmain-c/meson.build index 345382712..0ec0e3f6d 100644 --- a/src/libmain-c/meson.build +++ b/src/libmain-c/meson.build @@ -68,6 +68,7 @@ headers = [config_h] + files( ) subdir('build-utils-meson/export-all-symbols') +subdir('build-utils-meson/windows-version') this_library = library( 'nixmainc', diff --git a/src/libstore-c/meson.build b/src/libstore-c/meson.build index 4bfd944c6..d4f86eeff 100644 --- a/src/libstore-c/meson.build +++ b/src/libstore-c/meson.build @@ -67,6 +67,7 @@ headers = [config_h] + files( headers += files('nix_api_store_internal.h') subdir('build-utils-meson/export-all-symbols') +subdir('build-utils-meson/windows-version') this_library = library( 'nixstorec', diff --git a/src/libstore-test-support/meson.build b/src/libstore-test-support/meson.build index f09d26a31..98ec9882e 100644 --- a/src/libstore-test-support/meson.build +++ b/src/libstore-test-support/meson.build @@ -58,6 +58,7 @@ headers = files( ) subdir('build-utils-meson/export-all-symbols') +subdir('build-utils-meson/windows-version') this_library = library( 'nix-store-test-support', diff --git a/src/libstore-tests/meson.build b/src/libstore-tests/meson.build index 3b36cd62f..f4f67d73a 100644 --- a/src/libstore-tests/meson.build +++ b/src/libstore-tests/meson.build @@ -28,6 +28,7 @@ subdir('build-utils-meson/subprojects') subdir('build-utils-meson/threads') subdir('build-utils-meson/export-all-symbols') +subdir('build-utils-meson/windows-version') sqlite = dependency('sqlite3', 'sqlite', version : '>=3.6.19') deps_private += sqlite diff --git a/src/libstore/meson.build b/src/libstore/meson.build index c2aa5bff3..6c822b441 100644 --- a/src/libstore/meson.build +++ b/src/libstore/meson.build @@ -410,6 +410,7 @@ foreach name, value : cpp_str_defines endforeach subdir('build-utils-meson/export-all-symbols') +subdir('build-utils-meson/windows-version') this_library = library( 'nixstore', diff --git a/src/libutil-c/meson.build b/src/libutil-c/meson.build index b5ed19631..3d5a0b9c2 100644 --- a/src/libutil-c/meson.build +++ b/src/libutil-c/meson.build @@ -63,6 +63,7 @@ headers = [config_h] + files( headers += files('nix_api_util_internal.h') subdir('build-utils-meson/export-all-symbols') +subdir('build-utils-meson/windows-version') this_library = library( 'nixutilc', diff --git a/src/libutil-test-support/meson.build b/src/libutil-test-support/meson.build index 42b49a6a0..c5e1ba80b 100644 --- a/src/libutil-test-support/meson.build +++ b/src/libutil-test-support/meson.build @@ -53,6 +53,7 @@ headers = files( ) subdir('build-utils-meson/export-all-symbols') +subdir('build-utils-meson/windows-version') this_library = library( 'nix-util-test-support', diff --git a/src/libutil-tests/meson.build b/src/libutil-tests/meson.build index c39db8cda..5c3b5e5a3 100644 --- a/src/libutil-tests/meson.build +++ b/src/libutil-tests/meson.build @@ -28,6 +28,7 @@ subdir('build-utils-meson/subprojects') subdir('build-utils-meson/threads') subdir('build-utils-meson/export-all-symbols') +subdir('build-utils-meson/windows-version') rapidcheck = dependency('rapidcheck') deps_private += rapidcheck diff --git a/src/libutil/meson.build b/src/libutil/meson.build index 08413783d..61806120f 100644 --- a/src/libutil/meson.build +++ b/src/libutil/meson.build @@ -265,6 +265,7 @@ else endif subdir('build-utils-meson/export-all-symbols') +subdir('build-utils-meson/windows-version') this_library = library( 'nixutil', diff --git a/src/nix/meson.build b/src/nix/meson.build index 55089d821..7c7a46a6e 100644 --- a/src/nix/meson.build +++ b/src/nix/meson.build @@ -35,6 +35,7 @@ subdir('build-utils-meson/subprojects') subdir('build-utils-meson/threads') subdir('build-utils-meson/export-all-symbols') +subdir('build-utils-meson/windows-version') configdata = configuration_data() From f1fd277f1e5df976a23f4ad7091536e96851865f Mon Sep 17 00:00:00 2001 From: Brian McKenna Date: Wed, 6 Nov 2024 00:04:41 +1100 Subject: [PATCH 377/718] msys2: make symbolic linking work in Meson --- src/libstore/meson.build | 2 ++ src/nix/meson.build | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/src/libstore/meson.build b/src/libstore/meson.build index c2aa5bff3..b10f3753c 100644 --- a/src/libstore/meson.build +++ b/src/libstore/meson.build @@ -34,6 +34,8 @@ subdir('build-utils-meson/subprojects') run_command('ln', '-s', meson.project_build_root() / '__nothing_link_target', meson.project_build_root() / '__nothing_symlink', + # native doesn't allow dangling symlinks, which the tests require + env : { 'MSYS' : 'winsymlinks:lnk' }, check : true, ) can_link_symlink = run_command('ln', diff --git a/src/nix/meson.build b/src/nix/meson.build index 55089d821..cc18aebbf 100644 --- a/src/nix/meson.build +++ b/src/nix/meson.build @@ -229,6 +229,8 @@ foreach linkname : nix_symlinks t = custom_target( command: ['ln', '-sf', fs.name(this_exe), '@OUTPUT@'], output: linkname + executable_suffix, + # native doesn't allow dangling symlinks, but the target executable often doesn't exist at this time + env : { 'MSYS' : 'winsymlinks:lnk' }, # TODO(Ericson2314): Don't do this once we have the `meson.override_find_program` working) build_by_default: true ) @@ -247,6 +249,8 @@ install_symlink( custom_target( command: ['ln', '-sf', fs.name(this_exe), '@OUTPUT@'], output: 'build-remote' + executable_suffix, + # native doesn't allow dangling symlinks, but the target executable often doesn't exist at this time + env : { 'MSYS' : 'winsymlinks:lnk' }, # TODO(Ericson2314): Don't do this once we have the `meson.override_find_program` working) build_by_default: true ) From c25967384f87fb9549bf64df66ee168a3924400b Mon Sep 17 00:00:00 2001 From: Brian McKenna Date: Wed, 6 Nov 2024 00:05:36 +1100 Subject: [PATCH 378/718] msys2: link in wsock32 in libstore --- src/libstore/meson.build | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libstore/meson.build b/src/libstore/meson.build index b10f3753c..d3b5f3269 100644 --- a/src/libstore/meson.build +++ b/src/libstore/meson.build @@ -76,6 +76,11 @@ if host_machine.system() == 'darwin' deps_other += [sandbox] endif +if host_machine.system() == 'windows' + wsock32 = cxx.find_library('wsock32') + deps_other += [wsock32] +endif + subdir('build-utils-meson/threads') boost = dependency( From a9c417dbab680a78f5d33771505f5f9eca4bd544 Mon Sep 17 00:00:00 2001 From: Brian McKenna Date: Wed, 6 Nov 2024 00:06:33 +1100 Subject: [PATCH 379/718] msys2: use ls.exe instead of coreutils.exe for coreutils directory --- tests/functional/meson.build | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/functional/meson.build b/tests/functional/meson.build index 3f514e856..0d46f9ce2 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -17,7 +17,12 @@ fs = import('fs') nix = find_program('nix') bash = find_program('bash', native : true) busybox = find_program('busybox', native : true, required : false) -coreutils = find_program('coreutils', native : true) +if host_machine.system() == 'windows' + # Because of the state of symlinks on Windows, coreutils.exe doesn't usually exist, but things like ls.exe will + coreutils = find_program('ls', native : true) +else + coreutils = find_program('coreutils', native : true) +endif dot = find_program('dot', native : true, required : false) nix_bin_dir = fs.parent(nix.full_path()) From f7abc297ca296cc673f0f595e3c8bf72aae64e8b Mon Sep 17 00:00:00 2001 From: Brian McKenna Date: Wed, 6 Nov 2024 00:14:45 +1100 Subject: [PATCH 380/718] meson: add options for docs, unit tests and binding --- meson.build | 30 +++++++++++++++++------------- meson.options | 13 +++++++++++++ 2 files changed, 30 insertions(+), 13 deletions(-) create mode 100644 meson.options diff --git a/meson.build b/meson.build index d68db0a0d..8985b631e 100644 --- a/meson.build +++ b/meson.build @@ -22,10 +22,12 @@ subproject('libcmd') subproject('nix') # Docs -subproject('internal-api-docs') -subproject('external-api-docs') -if not meson.is_cross_build() - subproject('nix-manual') +if get_option('doc-gen') + subproject('internal-api-docs') + subproject('external-api-docs') + if not meson.is_cross_build() + subproject('nix-manual') + endif endif # External C wrapper libraries @@ -35,17 +37,19 @@ subproject('libexpr-c') subproject('libmain-c') # Language Bindings -if not meson.is_cross_build() +if get_option('bindings') and not meson.is_cross_build() subproject('perl') endif # Testing -subproject('libutil-test-support') -subproject('libutil-tests') -subproject('libstore-test-support') -subproject('libstore-tests') -subproject('libfetchers-tests') -subproject('libexpr-test-support') -subproject('libexpr-tests') -subproject('libflake-tests') +if get_option('unit-tests') + subproject('libutil-test-support') + subproject('libutil-tests') + subproject('libstore-test-support') + subproject('libstore-tests') + subproject('libfetchers-tests') + subproject('libexpr-test-support') + subproject('libexpr-tests') + subproject('libflake-tests') +endif subproject('nix-functional-tests') diff --git a/meson.options b/meson.options new file mode 100644 index 000000000..b3b3b4043 --- /dev/null +++ b/meson.options @@ -0,0 +1,13 @@ +# vim: filetype=meson + +option('doc-gen', type : 'boolean', value : true, + description : 'Generate documentation', +) + +option('unit-tests', type : 'boolean', value : true, + description : 'Build unit tests', +) + +option('bindings', type : 'boolean', value : true, + description : 'Build language bindings (e.g. Perl)', +) From 5bc8957c7373c25d493473b0f7c86247f3347779 Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman <145775305+xokdvium@users.noreply.github.com> Date: Wed, 6 Nov 2024 02:21:35 +0300 Subject: [PATCH 381/718] fix(libstore-tests): remove use-after-free bug for `StringSource` Unfortunately `StringSource` class is very easy was very easy to misuse because the ctor took a plain `std::string_view` which has a bad habit of being implicitly convertible from an rvalue `std::string`. This lead to unintentional use-after-free bugs. This patch makes `StringSource` much harder to misuse by disabling the ctor from a `std::string &&` (but `const std::string &` is ok). Fix affected tests from libstore-tests. Reformat those tests with clangd's range formatting since the diff is tiny and it seems appropriate. --- src/libstore-tests/serve-protocol.cc | 15 ++++----------- src/libstore-tests/worker-protocol.cc | 15 ++++----------- src/libutil/serialise.hh | 8 ++++++++ 3 files changed, 16 insertions(+), 22 deletions(-) diff --git a/src/libstore-tests/serve-protocol.cc b/src/libstore-tests/serve-protocol.cc index 2505c5a9a..5171fea0f 100644 --- a/src/libstore-tests/serve-protocol.cc +++ b/src/libstore-tests/serve-protocol.cc @@ -459,21 +459,14 @@ TEST_F(ServeProtoTest, handshake_client_truncated_replay_throws) CharacterizationTest::readTest("handshake-to-client", [&](std::string toClientLog) { for (size_t len = 0; len < toClientLog.size(); ++len) { NullBufferedSink nullSink; - StringSource in { - // truncate - toClientLog.substr(0, len) - }; + auto substring = toClientLog.substr(0, len); + StringSource in{substring}; if (len < 8) { EXPECT_THROW( - ServeProto::BasicClientConnection::handshake( - nullSink, in, defaultVersion, "blah"), - EndOfFile); + ServeProto::BasicClientConnection::handshake(nullSink, in, defaultVersion, "blah"), EndOfFile); } else { // Not sure why cannot keep on checking for `EndOfFile`. - EXPECT_THROW( - ServeProto::BasicClientConnection::handshake( - nullSink, in, defaultVersion, "blah"), - Error); + EXPECT_THROW(ServeProto::BasicClientConnection::handshake(nullSink, in, defaultVersion, "blah"), Error); } } }); diff --git a/src/libstore-tests/worker-protocol.cc b/src/libstore-tests/worker-protocol.cc index bbea9ed75..1185c37f4 100644 --- a/src/libstore-tests/worker-protocol.cc +++ b/src/libstore-tests/worker-protocol.cc @@ -725,21 +725,14 @@ TEST_F(WorkerProtoTest, handshake_client_truncated_replay_throws) CharacterizationTest::readTest("handshake-to-client", [&](std::string toClientLog) { for (size_t len = 0; len < toClientLog.size(); ++len) { NullBufferedSink nullSink; - StringSource in { - // truncate - toClientLog.substr(0, len) - }; + auto substring = toClientLog.substr(0, len); + StringSource in{substring}; if (len < 8) { EXPECT_THROW( - WorkerProto::BasicClientConnection::handshake( - nullSink, in, defaultVersion, {}), - EndOfFile); + WorkerProto::BasicClientConnection::handshake(nullSink, in, defaultVersion, {}), EndOfFile); } else { // Not sure why cannot keep on checking for `EndOfFile`. - EXPECT_THROW( - WorkerProto::BasicClientConnection::handshake( - nullSink, in, defaultVersion, {}), - Error); + EXPECT_THROW(WorkerProto::BasicClientConnection::handshake(nullSink, in, defaultVersion, {}), Error); } } }); diff --git a/src/libutil/serialise.hh b/src/libutil/serialise.hh index d9e34e1e0..14721d069 100644 --- a/src/libutil/serialise.hh +++ b/src/libutil/serialise.hh @@ -2,6 +2,7 @@ ///@file #include +#include #include "types.hh" #include "util.hh" @@ -202,7 +203,14 @@ struct StringSource : Source { std::string_view s; size_t pos; + + // NOTE: Prevent unintentional dangling views when an implicit conversion + // from std::string -> std::string_view occurs when the string is passed + // by rvalue. + StringSource(std::string &&) = delete; StringSource(std::string_view s) : s(s), pos(0) { } + StringSource(const std::string& str): StringSource(std::string_view(str)) {} + size_t read(char * data, size_t len) override; }; From c49a0ae8b8502e26649c8632d01202f3f75e3214 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Tue, 5 Nov 2024 23:22:43 -0500 Subject: [PATCH 382/718] Slightly tweak `flake.nix` `lib.concatMapAttrs` instead of `lib.mapAttrs'` and `lib.nameValuePair` Co-authored-by: Robert Hensing --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index cfb9021d5..3ef027dd1 100644 --- a/flake.nix +++ b/flake.nix @@ -295,7 +295,7 @@ devShells = let makeShell = import ./packaging/dev-shell.nix { inherit lib devFlake; }; - prefixAttrs = prefix: lib.mapAttrs' (k: v: lib.nameValuePair "${prefix}-${k}" v); + prefixAttrs = prefix: lib.concatMapAttrs (k: v: { "${prefix}-${k}" = v; }); in forAllSystems (system: prefixAttrs "native" (forAllStdenvs (stdenvName: makeShell { From 2e7466a4e0bce4dde9922fa3445d1947d6098fad Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman <145775305+xokdvium@users.noreply.github.com> Date: Wed, 6 Nov 2024 10:54:38 +0300 Subject: [PATCH 383/718] fix(libutil-tests/nix_api_util): get rid of unnecessary memory leaks --- src/libutil-tests/nix_api_util.cc | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/libutil-tests/nix_api_util.cc b/src/libutil-tests/nix_api_util.cc index 0f1cbe5dd..b36f71042 100644 --- a/src/libutil-tests/nix_api_util.cc +++ b/src/libutil-tests/nix_api_util.cc @@ -7,6 +7,8 @@ #include +#include + namespace nixC { TEST_F(nix_api_util_context, nix_context_error) @@ -57,6 +59,14 @@ struct MySettings : nix::Config MySettings mySettings; static nix::GlobalConfig::Register rs(&mySettings); +static auto createOwnedNixContext() +{ + return std::unique_ptr(nix_c_context_create(), {}); +} + TEST_F(nix_api_util_context, nix_setting_get) { ASSERT_EQ(ctx->last_err_code, NIX_OK); @@ -97,7 +107,8 @@ TEST_F(nix_api_util_context, nix_err_msg) // advanced usage unsigned int sz; - err_msg = nix_err_msg(nix_c_context_create(), ctx, &sz); + auto new_ctx = createOwnedNixContext(); + err_msg = nix_err_msg(new_ctx.get(), ctx, &sz); ASSERT_EQ(sz, err_msg.size()); } @@ -113,7 +124,8 @@ TEST_F(nix_api_util_context, nix_err_info_msg) } catch (...) { nix_context_error(ctx); } - nix_err_info_msg(nix_c_context_create(), ctx, OBSERVE_STRING(err_info)); + auto new_ctx = createOwnedNixContext(); + nix_err_info_msg(new_ctx.get(), ctx, OBSERVE_STRING(err_info)); ASSERT_STREQ("testing error", err_info.c_str()); } @@ -130,7 +142,8 @@ TEST_F(nix_api_util_context, nix_err_name) } catch (...) { nix_context_error(ctx); } - nix_err_name(nix_c_context_create(), ctx, OBSERVE_STRING(err_name)); + auto new_ctx = createOwnedNixContext(); + nix_err_name(new_ctx.get(), ctx, OBSERVE_STRING(err_name)); ASSERT_EQ(std::string(err_name), "nix::Error"); } From a150798ce48d457290dc00b7fe1b6a766ed4cc58 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 6 Nov 2024 13:05:37 +0100 Subject: [PATCH 384/718] Document "final" semantics --- src/nix/flake.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/nix/flake.md b/src/nix/flake.md index 2b999431c..b3321441c 100644 --- a/src/nix/flake.md +++ b/src/nix/flake.md @@ -666,6 +666,11 @@ following fields: other attributes are necessary because they provide information not stored in the store path. + The attributes in `locked` are considered "final", meaning that they are the only ones that are passed via the arguments of the `outputs` function of a flake. + For instance, if `locked` contains a `lastModified` attribute while the fetcher does not return a `lastModified` attribute, then the `lastModified` attribute will be passed to the `outputs` function. + Conversely, if `locked` does *not* contain a `lastModified` attribute while the fetcher *does* return a `lastModified` attribute, then no `lastModified` attribute will be passed. + If `locked` contains a `lastModifed` attribute and the fetcher returns a `lastModified` attribute, then they must have the same value. + * `flake`: A Boolean denoting whether this is a flake or non-flake dependency. Corresponds to the `flake` attribute in the `inputs` attribute in `flake.nix`. From 0401e2710f280db356fb606216287a56900462e5 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 6 Nov 2024 13:12:02 +0100 Subject: [PATCH 385/718] More docs --- src/libfetchers/fetchers.hh | 7 +++---- src/nix/flake.md | 4 +++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/libfetchers/fetchers.hh b/src/libfetchers/fetchers.hh index 430d6e943..1ea75ba84 100644 --- a/src/libfetchers/fetchers.hh +++ b/src/libfetchers/fetchers.hh @@ -92,10 +92,9 @@ public: /** * Return whether this is a "final" input, meaning that fetching - * it will not add, remove or change any attributes. For instance, - * a Git input with a `rev` attribute but without a `lastModified` - * attribute is considered locked but not final. Only "final" - * inputs can be substituted from a binary cache. + * it will not add, remove or change any attributes. (See + * `checkLocks()` for the semantics.) Only "final" inputs can be + * substituted from a binary cache. * * The "final" state is denoted by the presence of an attribute * `__final = true`. This attribute is currently undocumented and diff --git a/src/nix/flake.md b/src/nix/flake.md index b3321441c..e35b936be 100644 --- a/src/nix/flake.md +++ b/src/nix/flake.md @@ -148,7 +148,7 @@ reference types: * `ref`: A Git or Mercurial branch or tag name. -Finally, some attribute are typically not specified by the user, but +Finally, some attributes are typically not specified by the user, but can occur in *locked* flake references and are available to Nix code: * `revCount`: The number of ancestors of the commit `rev`. @@ -159,6 +159,8 @@ can occur in *locked* flake references and are available to Nix code: for tarball flakes, it's the most recent timestamp of any file inside the tarball. +Attributes that start with `__` are internal or experimental and may be removed in future versions. + ## Types Currently the `type` attribute can be one of the following: From b7882d51f2da83d8062bbb0e353b41009bd25fcf Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 6 Nov 2024 13:19:53 +0100 Subject: [PATCH 386/718] Rename argument "final" to "result" to avoid ambiguity --- src/libfetchers/fetchers.cc | 60 ++++++++++++++++++------------------- src/libfetchers/fetchers.hh | 8 ++--- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/libfetchers/fetchers.cc b/src/libfetchers/fetchers.cc index 2aedb8a2e..5c06a6bcb 100644 --- a/src/libfetchers/fetchers.cc +++ b/src/libfetchers/fetchers.cc @@ -178,24 +178,24 @@ std::pair Input::fetchToStore(ref store) const auto [storePath, input] = [&]() -> std::pair { try { - auto [accessor, final] = getAccessorUnchecked(store); + auto [accessor, result] = getAccessorUnchecked(store); - auto storePath = nix::fetchToStore(*store, SourcePath(accessor), FetchMode::Copy, final.getName()); + auto storePath = nix::fetchToStore(*store, SourcePath(accessor), FetchMode::Copy, result.getName()); auto narHash = store->queryPathInfo(storePath)->narHash; - final.attrs.insert_or_assign("narHash", narHash.to_string(HashFormat::SRI, true)); + result.attrs.insert_or_assign("narHash", narHash.to_string(HashFormat::SRI, true)); // FIXME: we would like to mark inputs as final in // getAccessorUnchecked(), but then we can't add // narHash. Or maybe narHash should be excluded from the // concept of "final" inputs? - final.attrs.insert_or_assign("__final", Explicit(true)); + result.attrs.insert_or_assign("__final", Explicit(true)); - assert(final.isFinal()); + assert(result.isFinal()); - checkLocks(*this, final); + checkLocks(*this, result); - return {storePath, final}; + return {storePath, result}; } catch (Error & e) { e.addTrace({}, "while fetching the input '%s'", to_string()); throw; @@ -205,12 +205,12 @@ std::pair Input::fetchToStore(ref store) const return {std::move(storePath), input}; } -void Input::checkLocks(Input specified, Input & final) +void Input::checkLocks(Input specified, Input & result) { /* If the original input is final, then we just return the original attributes, dropping any new fields returned by the - fetcher. However, any fields that are in both the original and - final input must be identical. */ + fetcher. However, any fields that are in both the specified and + result input must be identical. */ if (specified.isFinal()) { /* Backwards compatibility hack: we had some lock files in the @@ -221,24 +221,24 @@ void Input::checkLocks(Input specified, Input & final) specified.attrs.insert_or_assign("narHash", prevNarHash->to_string(HashFormat::SRI, true)); for (auto & field : specified.attrs) { - auto field2 = final.attrs.find(field.first); - if (field2 != final.attrs.end() && field.second != field2->second) - throw Error("mismatch in field '%s' of final input '%s', got '%s'", + auto field2 = result.attrs.find(field.first); + if (field2 != result.attrs.end() && field.second != field2->second) + throw Error("mismatch in field '%s' of input '%s', got '%s'", field.first, attrsToJSON(specified.attrs), - attrsToJSON(final.attrs)); + attrsToJSON(result.attrs)); } - final.attrs = specified.attrs; + result.attrs = specified.attrs; return; } if (auto prevNarHash = specified.getNarHash()) { - if (final.getNarHash() != prevNarHash) { - if (final.getNarHash()) + if (result.getNarHash() != prevNarHash) { + if (result.getNarHash()) throw Error((unsigned int) 102, "NAR hash mismatch in input '%s', expected '%s' but got '%s'", - specified.to_string(), prevNarHash->to_string(HashFormat::SRI, true), final.getNarHash()->to_string(HashFormat::SRI, true)); + specified.to_string(), prevNarHash->to_string(HashFormat::SRI, true), result.getNarHash()->to_string(HashFormat::SRI, true)); else throw Error((unsigned int) 102, "NAR hash mismatch in input '%s', expected '%s' but got none", specified.to_string(), prevNarHash->to_string(HashFormat::SRI, true)); @@ -246,32 +246,32 @@ void Input::checkLocks(Input specified, Input & final) } if (auto prevLastModified = specified.getLastModified()) { - if (final.getLastModified() != prevLastModified) + if (result.getLastModified() != prevLastModified) throw Error("'lastModified' attribute mismatch in input '%s', expected %d, got %d", - final.to_string(), *prevLastModified, final.getLastModified().value_or(-1)); + result.to_string(), *prevLastModified, result.getLastModified().value_or(-1)); } if (auto prevRev = specified.getRev()) { - if (final.getRev() != prevRev) + if (result.getRev() != prevRev) throw Error("'rev' attribute mismatch in input '%s', expected %s", - final.to_string(), prevRev->gitRev()); + result.to_string(), prevRev->gitRev()); } if (auto prevRevCount = specified.getRevCount()) { - if (final.getRevCount() != prevRevCount) + if (result.getRevCount() != prevRevCount) throw Error("'revCount' attribute mismatch in input '%s', expected %d", - final.to_string(), *prevRevCount); + result.to_string(), *prevRevCount); } } std::pair, Input> Input::getAccessor(ref store) const { try { - auto [accessor, final] = getAccessorUnchecked(store); + auto [accessor, result] = getAccessorUnchecked(store); - checkLocks(*this, final); + checkLocks(*this, result); - return {accessor, std::move(final)}; + return {accessor, std::move(result)}; } catch (Error & e) { e.addTrace({}, "while fetching the input '%s'", to_string()); throw; @@ -315,12 +315,12 @@ std::pair, Input> Input::getAccessorUnchecked(ref sto } } - auto [accessor, final] = scheme->getAccessor(store, *this); + auto [accessor, result] = scheme->getAccessor(store, *this); assert(!accessor->fingerprint); - accessor->fingerprint = scheme->getFingerprint(store, final); + accessor->fingerprint = scheme->getFingerprint(store, result); - return {accessor, std::move(final)}; + return {accessor, std::move(result)}; } Input Input::applyOverrides( diff --git a/src/libfetchers/fetchers.hh b/src/libfetchers/fetchers.hh index 1ea75ba84..b28ec4568 100644 --- a/src/libfetchers/fetchers.hh +++ b/src/libfetchers/fetchers.hh @@ -113,17 +113,17 @@ public: std::pair fetchToStore(ref store) const; /** - * Check the locking attributes in `final` against + * Check the locking attributes in `result` against * `specified`. E.g. if `specified` has a `rev` attribute, then - * `final` must have the same `rev` attribute. Throw an exception + * `result` must have the same `rev` attribute. Throw an exception * if there is a mismatch. * * If `specified` is marked final (i.e. has the `__final` * attribute), then the intersection of attributes in `specified` - * and `final` must be equal, and `final.attrs` is set to + * and `result` must be equal, and `final.attrs` is set to * `specified.attrs` (i.e. we discard any new attributes). */ - static void checkLocks(Input specified, Input & final); + static void checkLocks(Input specified, Input & result); /** * Return a `SourceAccessor` that allows access to files in the From f7b1e535a3c68991ac66768f456b28677152b2d7 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 6 Nov 2024 14:20:06 +0100 Subject: [PATCH 387/718] nix::readLine: Add eofOk parameter --- src/libutil/file-descriptor.hh | 7 ++++++- src/libutil/unix/file-descriptor.cc | 10 +++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/libutil/file-descriptor.hh b/src/libutil/file-descriptor.hh index b54bab83c..710efaf1d 100644 --- a/src/libutil/file-descriptor.hh +++ b/src/libutil/file-descriptor.hh @@ -77,8 +77,13 @@ void writeFull(Descriptor fd, std::string_view s, bool allowInterrupts = true); /** * Read a line from a file descriptor. + * + * @param fd The file descriptor to read from + * @param eofOk If true, return an unterminated line if EOF is reached. (e.g. the empty string) + * + * @return A line of text ending in `\n`, or a string without `\n` if `eofOk` is true and EOF is reached. */ -std::string readLine(Descriptor fd); +std::string readLine(Descriptor fd, bool eofOk = false); /** * Write a line to a file descriptor. diff --git a/src/libutil/unix/file-descriptor.cc b/src/libutil/unix/file-descriptor.cc index 2c1126e09..ac7c086af 100644 --- a/src/libutil/unix/file-descriptor.cc +++ b/src/libutil/unix/file-descriptor.cc @@ -47,7 +47,7 @@ void writeFull(int fd, std::string_view s, bool allowInterrupts) } -std::string readLine(int fd) +std::string readLine(int fd, bool eofOk) { std::string s; while (1) { @@ -58,8 +58,12 @@ std::string readLine(int fd) if (rd == -1) { if (errno != EINTR) throw SysError("reading a line"); - } else if (rd == 0) - throw EndOfFile("unexpected EOF reading a line"); + } else if (rd == 0) { + if (eofOk) + return s; + else + throw EndOfFile("unexpected EOF reading a line"); + } else { if (ch == '\n') return s; s += ch; From c29808929fb58b2b8b0e27d777d7ed3091f81ad3 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 6 Nov 2024 15:19:03 +0100 Subject: [PATCH 388/718] Move scripts/flake-regressions.sh into the flake-regressions repo It already contained a script "eval-all.sh" that did almost the same thing. --- .github/workflows/ci.yml | 2 +- scripts/flake-regressions.sh | 27 --------------------------- 2 files changed, 1 insertion(+), 28 deletions(-) delete mode 100755 scripts/flake-regressions.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0e2e07da2..27f60574e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -214,4 +214,4 @@ jobs: path: flake-regressions/tests - uses: DeterminateSystems/nix-installer-action@main - uses: DeterminateSystems/magic-nix-cache-action@main - - run: nix build --out-link ./new-nix && PATH=$(pwd)/new-nix/bin:$PATH scripts/flake-regressions.sh + - run: nix build --out-link ./new-nix && PATH=$(pwd)/new-nix/bin:$PATH MAX_FLAKES=25 flake-regressions/eval-all.sh diff --git a/scripts/flake-regressions.sh b/scripts/flake-regressions.sh deleted file mode 100755 index d76531134..000000000 --- a/scripts/flake-regressions.sh +++ /dev/null @@ -1,27 +0,0 @@ -#! /usr/bin/env bash - -set -e - -echo "Nix version:" -nix --version - -cd flake-regressions - -status=0 - -flakes=$(find tests -mindepth 3 -maxdepth 3 -type d -not -path '*/.*' | sort | head -n25) - -echo "Running flake tests..." - -for flake in $flakes; do - - if ! REGENERATE=0 ./eval-flake.sh "$flake"; then - status=1 - echo "❌ $flake" - else - echo "✅ $flake" - fi - -done - -exit "$status" From 3112e59734de7de7470abb5c156847469fe720d9 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 6 Nov 2024 15:05:32 +0100 Subject: [PATCH 389/718] ProgressBar::ask: Accept EOF as a no This may occur when stderr is a tty but stdin is empty. E.g. $ nix build active) return {}; std::cerr << fmt("\r\e[K%s ", msg); - auto s = trim(readLine(STDIN_FILENO)); + auto s = trim(readLine(STDIN_FILENO, true)); if (s.size() != 1) return {}; draw(*state); return s[0]; diff --git a/tests/functional/flakes/config.sh b/tests/functional/flakes/config.sh index 256a595bc..48f1c7a85 100755 --- a/tests/functional/flakes/config.sh +++ b/tests/functional/flakes/config.sh @@ -27,7 +27,17 @@ cat < flake.nix EOF # Without --accept-flake-config, the post hook should not run. +# To test variations in stderr tty-ness, we run the command in different ways, +# none of which should block on stdin or accept the `nixConfig`s. nix build < /dev/null +nix build < /dev/null 2>&1 | cat +# EOF counts as no, even when interactive (throw EOF error before) +if type -p script >/dev/null && script -q -c true /dev/null; then + echo "script is available and GNU-like, so we can ensure a tty" + script -q -c 'nix build < /dev/null' /dev/null +else + echo "script is not available or not GNU-like, so we skip testing with an added tty" +fi (! [[ -f post-hook-ran ]]) TODO_NixOS clearStore diff --git a/tests/functional/package.nix b/tests/functional/package.nix index 71029146b..2f5bf9bc2 100644 --- a/tests/functional/package.nix +++ b/tests/functional/package.nix @@ -60,6 +60,7 @@ mkMesonDerivation (finalAttrs: { # etc. busybox-sandbox-shell # For Overlay FS tests need `mount`, `umount`, and `unshare`. + # For `script` command (ensuring a TTY) # TODO use `unixtools` to be precise over which executables instead? util-linux ]; From c6c8d2af659fbc87bd8abc6310635da5d7e136f3 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 6 Nov 2024 19:44:50 +0100 Subject: [PATCH 390/718] refact: Remove unused arguments --- tests/functional/package.nix | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/functional/package.nix b/tests/functional/package.nix index 2f5bf9bc2..d1582b05d 100644 --- a/tests/functional/package.nix +++ b/tests/functional/package.nix @@ -1,7 +1,6 @@ { lib , stdenv , mkMesonDerivation -, releaseTools , meson , ninja @@ -16,10 +15,6 @@ , nix-expr , nix-cli -, rapidcheck -, gtest -, runCommand - , busybox-sandbox-shell ? null # Configuration Options From ba34ea9fe797a487339d91ba38344acd806e6398 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Wed, 6 Nov 2024 16:06:59 -0500 Subject: [PATCH 391/718] Add missing deps to the dev shell --- packaging/dev-shell.nix | 5 ++++- src/libexpr/package.nix | 4 ++++ src/perl/package.nix | 4 ++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/packaging/dev-shell.nix b/packaging/dev-shell.nix index 4b2a87632..15ce387a0 100644 --- a/packaging/dev-shell.nix +++ b/packaging/dev-shell.nix @@ -88,9 +88,12 @@ in { buildInputs = attrs.buildInputs or [] ++ pkgs.nixComponents.nix-util.buildInputs ++ pkgs.nixComponents.nix-store.buildInputs + ++ pkgs.nixComponents.nix-store-tests.externalBuildInputs ++ pkgs.nixComponents.nix-fetchers.buildInputs ++ pkgs.nixComponents.nix-expr.buildInputs - ++ pkgs.nixComponents.nix-store-tests.externalBuildInputs + ++ pkgs.nixComponents.nix-expr.externalPropagatedBuildInputs + ++ pkgs.nixComponents.nix-cmd.buildInputs + ++ lib.optionals havePerl pkgs.nixComponents.nix-perl-bindings.externalBuildInputs ++ lib.optional havePerl pkgs.perl ; }) diff --git a/src/libexpr/package.nix b/src/libexpr/package.nix index ca1f8bf21..d97e7f3a8 100644 --- a/src/libexpr/package.nix +++ b/src/libexpr/package.nix @@ -71,6 +71,10 @@ mkMesonLibrary (finalAttrs: { nix-util nix-store nix-fetchers + ] ++ finalAttrs.passthru.externalPropagatedBuildInputs; + + # Hack for sake of the dev shell + passthru.externalPropagatedBuildInputs = [ boost nlohmann_json ] ++ lib.optional enableGC boehmgc; diff --git a/src/perl/package.nix b/src/perl/package.nix index fe617fd47..5ee0df13c 100644 --- a/src/perl/package.nix +++ b/src/perl/package.nix @@ -40,6 +40,10 @@ perl.pkgs.toPerlModule (mkMesonDerivation (finalAttrs: { buildInputs = [ nix-store + ] ++ finalAttrs.passthru.externalBuildInputs; + + # Hack for sake of the dev shell + passthru.externalBuildInputs = [ bzip2 libsodium ]; From 71c2e21f3bdbbf27421d8115c0e120df9713e789 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 4 Nov 2024 12:43:21 -0500 Subject: [PATCH 392/718] Temporarily skip coverage checks --- packaging/hydra.nix | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packaging/hydra.nix b/packaging/hydra.nix index 6da502079..d01cdee68 100644 --- a/packaging/hydra.nix +++ b/packaging/hydra.nix @@ -139,11 +139,11 @@ in # docker image with Nix inside dockerImage = lib.genAttrs linux64BitSystems (system: self.packages.${system}.dockerImage); - # Line coverage analysis. - coverage = nixpkgsFor.x86_64-linux.native.nix.override { - pname = "nix-coverage"; - withCoverageChecks = true; - }; + # # Line coverage analysis. + # coverage = nixpkgsFor.x86_64-linux.native.nix.override { + # pname = "nix-coverage"; + # withCoverageChecks = true; + # }; # Nix's manual manual = nixpkgsFor.x86_64-linux.native.nixComponents.nix-manual; From e70c9bb06a310fb1999f924008b340f49356e073 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Thu, 17 Oct 2024 15:38:05 -0400 Subject: [PATCH 393/718] Remove old build system --- Makefile | 129 --- Makefile.config.in | 54 - config/install-sh | 527 ---------- configure.ac | 456 --------- doc/manual/local.mk | 236 ----- flake.nix | 11 +- local.mk | 15 - m4/ax_cxx_compile_stdcxx.m4 | 951 ------------------ m4/ax_cxx_compile_stdcxx_17.m4 | 35 - maintainers/local.mk | 8 - misc/bash/local.mk | 1 - misc/fish/local.mk | 1 - misc/launchd/local.mk | 5 - misc/systemd/local.mk | 8 - misc/upstart/local.mk | 7 - misc/zsh/local.mk | 2 - mk/build-dir.mk | 10 - mk/clean.mk | 11 - mk/common-test.sh | 31 - mk/compilation-database.mk | 11 - mk/cxx-big-literal.mk | 5 - mk/debug-test.sh | 10 - mk/functions.mk | 14 - mk/install-dirs.mk | 11 - mk/install.mk | 62 -- mk/lib.mk | 159 --- mk/libraries.mk | 173 ---- mk/patterns.mk | 41 - mk/platform.mk | 40 - mk/precompiled-headers.mk | 21 - mk/programs.mk | 98 -- mk/run-test.sh | 38 - mk/templates.mk | 19 - mk/tests.mk | 30 - mk/tracing.mk | 18 - package.nix | 366 ------- packaging/components.nix | 8 +- packaging/dev-shell.nix | 2 +- packaging/hydra.nix | 5 +- scripts/local.mk | 13 - src/libcmd/local.mk | 15 - src/libcmd/nix-cmd.pc.in | 9 - src/libexpr-c/local.mk | 25 - src/libexpr-c/nix-expr-c.pc.in | 10 - src/libexpr-test-support/local.mk | 23 - src/libexpr-tests/local.mk | 45 - src/libexpr/local.mk | 50 - src/libexpr/nix-expr.pc.in | 10 - src/libfetchers-tests/local.mk | 37 - src/libfetchers/local.mk | 17 - src/libflake-tests/local.mk | 43 - src/libflake/flake/nix-flake.pc.in | 10 - src/libflake/local.mk | 22 - src/libmain/local.mk | 22 - src/libmain/nix-main.pc.in | 9 - src/libstore-c/local.mk | 21 - src/libstore-c/nix-store-c.pc.in | 9 - src/libstore-test-support/local.mk | 21 - src/libstore-tests/local.mk | 38 - src/libstore/local.mk | 103 -- src/libstore/nix-store.pc.in | 10 - src/libutil-c/local.mk | 18 - src/libutil-c/nix-util-c.pc.in | 9 - src/libutil-test-support/local.mk | 19 - src/libutil-tests/local.mk | 37 - src/libutil/local.mk | 44 - src/libutil/nix-util.pc.in | 9 - src/nix/local.mk | 59 -- tests/functional/ca/local.mk | 29 - tests/functional/dyn-drv/local.mk | 15 - tests/functional/flakes/local.mk | 25 - tests/functional/git-hashing/local.mk | 7 - tests/functional/local-overlay-store/local.mk | 14 - tests/functional/local.mk | 146 --- tests/functional/plugins/local.mk | 11 - .../functional/test-libstoreconsumer/local.mk | 15 - 76 files changed, 9 insertions(+), 4639 deletions(-) delete mode 100644 Makefile delete mode 100644 Makefile.config.in delete mode 100755 config/install-sh delete mode 100644 configure.ac delete mode 100644 doc/manual/local.mk delete mode 100644 local.mk delete mode 100644 m4/ax_cxx_compile_stdcxx.m4 delete mode 100644 m4/ax_cxx_compile_stdcxx_17.m4 delete mode 100644 maintainers/local.mk delete mode 100644 misc/bash/local.mk delete mode 100644 misc/fish/local.mk delete mode 100644 misc/launchd/local.mk delete mode 100644 misc/systemd/local.mk delete mode 100644 misc/upstart/local.mk delete mode 100644 misc/zsh/local.mk delete mode 100644 mk/build-dir.mk delete mode 100644 mk/clean.mk delete mode 100644 mk/common-test.sh delete mode 100644 mk/compilation-database.mk delete mode 100644 mk/cxx-big-literal.mk delete mode 100755 mk/debug-test.sh delete mode 100644 mk/functions.mk delete mode 100644 mk/install-dirs.mk delete mode 100644 mk/install.mk delete mode 100644 mk/lib.mk delete mode 100644 mk/libraries.mk delete mode 100644 mk/patterns.mk delete mode 100644 mk/platform.mk delete mode 100644 mk/precompiled-headers.mk delete mode 100644 mk/programs.mk delete mode 100755 mk/run-test.sh delete mode 100644 mk/templates.mk delete mode 100644 mk/tests.mk delete mode 100644 mk/tracing.mk delete mode 100644 package.nix delete mode 100644 scripts/local.mk delete mode 100644 src/libcmd/local.mk delete mode 100644 src/libcmd/nix-cmd.pc.in delete mode 100644 src/libexpr-c/local.mk delete mode 100644 src/libexpr-c/nix-expr-c.pc.in delete mode 100644 src/libexpr-test-support/local.mk delete mode 100644 src/libexpr-tests/local.mk delete mode 100644 src/libexpr/local.mk delete mode 100644 src/libexpr/nix-expr.pc.in delete mode 100644 src/libfetchers-tests/local.mk delete mode 100644 src/libfetchers/local.mk delete mode 100644 src/libflake-tests/local.mk delete mode 100644 src/libflake/flake/nix-flake.pc.in delete mode 100644 src/libflake/local.mk delete mode 100644 src/libmain/local.mk delete mode 100644 src/libmain/nix-main.pc.in delete mode 100644 src/libstore-c/local.mk delete mode 100644 src/libstore-c/nix-store-c.pc.in delete mode 100644 src/libstore-test-support/local.mk delete mode 100644 src/libstore-tests/local.mk delete mode 100644 src/libstore/local.mk delete mode 100644 src/libstore/nix-store.pc.in delete mode 100644 src/libutil-c/local.mk delete mode 100644 src/libutil-c/nix-util-c.pc.in delete mode 100644 src/libutil-test-support/local.mk delete mode 100644 src/libutil-tests/local.mk delete mode 100644 src/libutil/local.mk delete mode 100644 src/libutil/nix-util.pc.in delete mode 100644 src/nix/local.mk delete mode 100644 tests/functional/ca/local.mk delete mode 100644 tests/functional/dyn-drv/local.mk delete mode 100644 tests/functional/flakes/local.mk delete mode 100644 tests/functional/git-hashing/local.mk delete mode 100644 tests/functional/local-overlay-store/local.mk delete mode 100644 tests/functional/local.mk delete mode 100644 tests/functional/plugins/local.mk delete mode 100644 tests/functional/test-libstoreconsumer/local.mk diff --git a/Makefile b/Makefile deleted file mode 100644 index ee1a0de31..000000000 --- a/Makefile +++ /dev/null @@ -1,129 +0,0 @@ -# External build directory support - -include mk/build-dir.mk - --include $(buildprefix)Makefile.config -clean-files += $(buildprefix)Makefile.config - -# List makefiles - -include mk/platform.mk - -ifeq ($(ENABLE_BUILD), yes) -makefiles = \ - mk/precompiled-headers.mk \ - local.mk \ - src/libutil/local.mk \ - src/libstore/local.mk \ - src/libfetchers/local.mk \ - src/libmain/local.mk \ - src/libexpr/local.mk \ - src/libflake/local.mk \ - src/libcmd/local.mk \ - src/nix/local.mk \ - src/libutil-c/local.mk \ - src/libstore-c/local.mk \ - src/libexpr-c/local.mk - -ifdef HOST_UNIX -makefiles += \ - scripts/local.mk \ - maintainers/local.mk \ - misc/bash/local.mk \ - misc/fish/local.mk \ - misc/zsh/local.mk \ - misc/systemd/local.mk \ - misc/launchd/local.mk \ - misc/upstart/local.mk -endif -endif - -ifeq ($(ENABLE_UNIT_TESTS), yes) -makefiles += \ - src/libutil-tests/local.mk \ - src/libutil-test-support/local.mk \ - src/libstore-tests/local.mk \ - src/libstore-test-support/local.mk \ - src/libfetchers-tests/local.mk \ - src/libexpr-tests/local.mk \ - src/libexpr-test-support/local.mk \ - src/libflake-tests/local.mk -endif - -ifeq ($(ENABLE_FUNCTIONAL_TESTS), yes) -ifdef HOST_UNIX -makefiles += \ - tests/functional/local.mk \ - tests/functional/flakes/local.mk \ - tests/functional/ca/local.mk \ - tests/functional/git-hashing/local.mk \ - tests/functional/dyn-drv/local.mk \ - tests/functional/local-overlay-store/local.mk \ - tests/functional/test-libstoreconsumer/local.mk \ - tests/functional/plugins/local.mk -endif -endif - -# Some makefiles require access to built programs and must be included late. -makefiles-late = - -ifeq ($(ENABLE_DOC_GEN), yes) -makefiles-late += doc/manual/local.mk -endif - -# Miscellaneous global Flags - -OPTIMIZE = 1 - -ifeq ($(OPTIMIZE), 1) - GLOBAL_CXXFLAGS += -O3 $(CXXLTO) - GLOBAL_LDFLAGS += $(CXXLTO) -else - GLOBAL_CXXFLAGS += -O0 -U_FORTIFY_SOURCE - unexport NIX_HARDENING_ENABLE -endif - -ifdef HOST_WINDOWS - # Windows DLLs are stricter about symbol visibility than Unix shared - # objects --- see https://gcc.gnu.org/wiki/Visibility for details. - # This is a temporary sledgehammer to export everything like on Unix, - # and not detail with this yet. - # - # TODO do not do this, and instead do fine-grained export annotations. - GLOBAL_LDFLAGS += -Wl,--export-all-symbols - GLOBAL_CXXFLAGS += -D_WIN32_WINNT=0x0602 -endif - -GLOBAL_CXXFLAGS += -g -Wall -Wdeprecated-copy -Wignored-qualifiers -Wimplicit-fallthrough -Werror=unused-result -Werror=suggest-override -include $(buildprefix)config.h -std=c++2a -I src - -# Include the main lib, causing rules to be defined - -include mk/lib.mk - -# Fallback stub rules for better UX when things are disabled -# -# These must be defined after `mk/lib.mk`. Otherwise the first rule -# incorrectly becomes the default target. - -ifneq ($(ENABLE_UNIT_TESTS), yes) -.PHONY: check -check: - @echo "Unit tests are disabled. Configure without '--disable-unit-tests', or avoid calling 'make check'." - @exit 1 -endif - -ifneq ($(ENABLE_FUNCTIONAL_TESTS), yes) -.PHONY: installcheck -installcheck: - @echo "Functional tests are disabled. Configure without '--disable-functional-tests', or avoid calling 'make installcheck'." - @exit 1 -endif - -# Documentation fallback stub rules. - -ifneq ($(ENABLE_DOC_GEN), yes) -.PHONY: manual-html manpages -manual-html manpages: - @echo "Generated docs are disabled. Configure without '--disable-doc-gen', or avoid calling 'make manpages' and 'make manual-html'." - @exit 1 -endif diff --git a/Makefile.config.in b/Makefile.config.in deleted file mode 100644 index 3100d2073..000000000 --- a/Makefile.config.in +++ /dev/null @@ -1,54 +0,0 @@ -AR = @AR@ -BDW_GC_LIBS = @BDW_GC_LIBS@ -BOOST_LDFLAGS = @BOOST_LDFLAGS@ -BUILD_SHARED_LIBS = @BUILD_SHARED_LIBS@ -CC = @CC@ -CFLAGS = @CFLAGS@ -CXX = @CXX@ -CXXFLAGS = @CXXFLAGS@ -CXXLTO = @CXXLTO@ -EDITLINE_LIBS = @EDITLINE_LIBS@ -ENABLE_BUILD = @ENABLE_BUILD@ -ENABLE_DOC_GEN = @ENABLE_DOC_GEN@ -ENABLE_FUNCTIONAL_TESTS = @ENABLE_FUNCTIONAL_TESTS@ -ENABLE_S3 = @ENABLE_S3@ -ENABLE_UNIT_TESTS = @ENABLE_UNIT_TESTS@ -GTEST_LIBS = @GTEST_LIBS@ -HAVE_LIBCPUID = @HAVE_LIBCPUID@ -HAVE_SECCOMP = @HAVE_SECCOMP@ -HOST_OS = @host_os@ -INSTALL_UNIT_TESTS = @INSTALL_UNIT_TESTS@ -LDFLAGS = @LDFLAGS@ -LIBARCHIVE_LIBS = @LIBARCHIVE_LIBS@ -LIBBROTLI_LIBS = @LIBBROTLI_LIBS@ -LIBCURL_LIBS = @LIBCURL_LIBS@ -LIBGIT2_LIBS = @LIBGIT2_LIBS@ -LIBSECCOMP_LIBS = @LIBSECCOMP_LIBS@ -LOWDOWN_LIBS = @LOWDOWN_LIBS@ -OPENSSL_LIBS = @OPENSSL_LIBS@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -SHELL = @bash@ -SODIUM_LIBS = @SODIUM_LIBS@ -SQLITE3_LIBS = @SQLITE3_LIBS@ -bash = @bash@ -bindir = @bindir@ -checkbindir = @checkbindir@ -checklibdir = @checklibdir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -embedded_sandbox_shell = @embedded_sandbox_shell@ -exec_prefix = @exec_prefix@ -includedir = @includedir@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localstatedir = @localstatedir@ -lsof = @lsof@ -mandir = @mandir@ -pkglibdir = $(libdir)/$(PACKAGE_NAME) -prefix = @prefix@ -sandbox_shell = @sandbox_shell@ -storedir = @storedir@ -sysconfdir = @sysconfdir@ -system = @system@ diff --git a/config/install-sh b/config/install-sh deleted file mode 100755 index 377bb8687..000000000 --- a/config/install-sh +++ /dev/null @@ -1,527 +0,0 @@ -#!/bin/sh -# install - install a program, script, or datafile - -scriptversion=2011-11-20.07; # UTC - -# This originates from X11R5 (mit/util/scripts/install.sh), which was -# later released in X11R6 (xc/config/util/install.sh) with the -# following copyright and license. -# -# Copyright (C) 1994 X Consortium -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- -# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -# Except as contained in this notice, the name of the X Consortium shall not -# be used in advertising or otherwise to promote the sale, use or other deal- -# ings in this Software without prior written authorization from the X Consor- -# tium. -# -# -# FSF changes to this file are in the public domain. -# -# Calling this script install-sh is preferred over install.sh, to prevent -# 'make' implicit rules from creating a file called install from it -# when there is no Makefile. -# -# This script is compatible with the BSD install script, but was written -# from scratch. - -nl=' -' -IFS=" "" $nl" - -# set DOITPROG to echo to test this script - -# Don't use :- since 4.3BSD and earlier shells don't like it. -doit=${DOITPROG-} -if test -z "$doit"; then - doit_exec=exec -else - doit_exec=$doit -fi - -# Put in absolute file names if you don't have them in your path; -# or use environment vars. - -chgrpprog=${CHGRPPROG-chgrp} -chmodprog=${CHMODPROG-chmod} -chownprog=${CHOWNPROG-chown} -cmpprog=${CMPPROG-cmp} -cpprog=${CPPROG-cp} -mkdirprog=${MKDIRPROG-mkdir} -mvprog=${MVPROG-mv} -rmprog=${RMPROG-rm} -stripprog=${STRIPPROG-strip} - -posix_glob='?' -initialize_posix_glob=' - test "$posix_glob" != "?" || { - if (set -f) 2>/dev/null; then - posix_glob= - else - posix_glob=: - fi - } -' - -posix_mkdir= - -# Desired mode of installed file. -mode=0755 - -chgrpcmd= -chmodcmd=$chmodprog -chowncmd= -mvcmd=$mvprog -rmcmd="$rmprog -f" -stripcmd= - -src= -dst= -dir_arg= -dst_arg= - -copy_on_change=false -no_target_directory= - -usage="\ -Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE - or: $0 [OPTION]... SRCFILES... DIRECTORY - or: $0 [OPTION]... -t DIRECTORY SRCFILES... - or: $0 [OPTION]... -d DIRECTORIES... - -In the 1st form, copy SRCFILE to DSTFILE. -In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. -In the 4th, create DIRECTORIES. - -Options: - --help display this help and exit. - --version display version info and exit. - - -c (ignored) - -C install only if different (preserve the last data modification time) - -d create directories instead of installing files. - -g GROUP $chgrpprog installed files to GROUP. - -m MODE $chmodprog installed files to MODE. - -o USER $chownprog installed files to USER. - -s $stripprog installed files. - -t DIRECTORY install into DIRECTORY. - -T report an error if DSTFILE is a directory. - -Environment variables override the default commands: - CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG - RMPROG STRIPPROG -" - -while test $# -ne 0; do - case $1 in - -c) ;; - - -C) copy_on_change=true;; - - -d) dir_arg=true;; - - -g) chgrpcmd="$chgrpprog $2" - shift;; - - --help) echo "$usage"; exit $?;; - - -m) mode=$2 - case $mode in - *' '* | *' '* | *' -'* | *'*'* | *'?'* | *'['*) - echo "$0: invalid mode: $mode" >&2 - exit 1;; - esac - shift;; - - -o) chowncmd="$chownprog $2" - shift;; - - -s) stripcmd=$stripprog;; - - -t) dst_arg=$2 - # Protect names problematic for 'test' and other utilities. - case $dst_arg in - -* | [=\(\)!]) dst_arg=./$dst_arg;; - esac - shift;; - - -T) no_target_directory=true;; - - --version) echo "$0 $scriptversion"; exit $?;; - - --) shift - break;; - - -*) echo "$0: invalid option: $1" >&2 - exit 1;; - - *) break;; - esac - shift -done - -if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then - # When -d is used, all remaining arguments are directories to create. - # When -t is used, the destination is already specified. - # Otherwise, the last argument is the destination. Remove it from $@. - for arg - do - if test -n "$dst_arg"; then - # $@ is not empty: it contains at least $arg. - set fnord "$@" "$dst_arg" - shift # fnord - fi - shift # arg - dst_arg=$arg - # Protect names problematic for 'test' and other utilities. - case $dst_arg in - -* | [=\(\)!]) dst_arg=./$dst_arg;; - esac - done -fi - -if test $# -eq 0; then - if test -z "$dir_arg"; then - echo "$0: no input file specified." >&2 - exit 1 - fi - # It's OK to call 'install-sh -d' without argument. - # This can happen when creating conditional directories. - exit 0 -fi - -if test -z "$dir_arg"; then - do_exit='(exit $ret); exit $ret' - trap "ret=129; $do_exit" 1 - trap "ret=130; $do_exit" 2 - trap "ret=141; $do_exit" 13 - trap "ret=143; $do_exit" 15 - - # Set umask so as not to create temps with too-generous modes. - # However, 'strip' requires both read and write access to temps. - case $mode in - # Optimize common cases. - *644) cp_umask=133;; - *755) cp_umask=22;; - - *[0-7]) - if test -z "$stripcmd"; then - u_plus_rw= - else - u_plus_rw='% 200' - fi - cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; - *) - if test -z "$stripcmd"; then - u_plus_rw= - else - u_plus_rw=,u+rw - fi - cp_umask=$mode$u_plus_rw;; - esac -fi - -for src -do - # Protect names problematic for 'test' and other utilities. - case $src in - -* | [=\(\)!]) src=./$src;; - esac - - if test -n "$dir_arg"; then - dst=$src - dstdir=$dst - test -d "$dstdir" - dstdir_status=$? - else - - # Waiting for this to be detected by the "$cpprog $src $dsttmp" command - # might cause directories to be created, which would be especially bad - # if $src (and thus $dsttmp) contains '*'. - if test ! -f "$src" && test ! -d "$src"; then - echo "$0: $src does not exist." >&2 - exit 1 - fi - - if test -z "$dst_arg"; then - echo "$0: no destination specified." >&2 - exit 1 - fi - dst=$dst_arg - - # If destination is a directory, append the input filename; won't work - # if double slashes aren't ignored. - if test -d "$dst"; then - if test -n "$no_target_directory"; then - echo "$0: $dst_arg: Is a directory" >&2 - exit 1 - fi - dstdir=$dst - dst=$dstdir/`basename "$src"` - dstdir_status=0 - else - # Prefer dirname, but fall back on a substitute if dirname fails. - dstdir=` - (dirname "$dst") 2>/dev/null || - expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$dst" : 'X\(//\)[^/]' \| \ - X"$dst" : 'X\(//\)$' \| \ - X"$dst" : 'X\(/\)' \| . 2>/dev/null || - echo X"$dst" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q' - ` - - test -d "$dstdir" - dstdir_status=$? - fi - fi - - obsolete_mkdir_used=false - - if test $dstdir_status != 0; then - case $posix_mkdir in - '') - # Create intermediate dirs using mode 755 as modified by the umask. - # This is like FreeBSD 'install' as of 1997-10-28. - umask=`umask` - case $stripcmd.$umask in - # Optimize common cases. - *[2367][2367]) mkdir_umask=$umask;; - .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; - - *[0-7]) - mkdir_umask=`expr $umask + 22 \ - - $umask % 100 % 40 + $umask % 20 \ - - $umask % 10 % 4 + $umask % 2 - `;; - *) mkdir_umask=$umask,go-w;; - esac - - # With -d, create the new directory with the user-specified mode. - # Otherwise, rely on $mkdir_umask. - if test -n "$dir_arg"; then - mkdir_mode=-m$mode - else - mkdir_mode= - fi - - posix_mkdir=false - case $umask in - *[123567][0-7][0-7]) - # POSIX mkdir -p sets u+wx bits regardless of umask, which - # is incompatible with FreeBSD 'install' when (umask & 300) != 0. - ;; - *) - tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ - trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 - - if (umask $mkdir_umask && - exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 - then - if test -z "$dir_arg" || { - # Check for POSIX incompatibilities with -m. - # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or - # other-writable bit of parent directory when it shouldn't. - # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. - ls_ld_tmpdir=`ls -ld "$tmpdir"` - case $ls_ld_tmpdir in - d????-?r-*) different_mode=700;; - d????-?--*) different_mode=755;; - *) false;; - esac && - $mkdirprog -m$different_mode -p -- "$tmpdir" && { - ls_ld_tmpdir_1=`ls -ld "$tmpdir"` - test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" - } - } - then posix_mkdir=: - fi - rmdir "$tmpdir/d" "$tmpdir" - else - # Remove any dirs left behind by ancient mkdir implementations. - rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null - fi - trap '' 0;; - esac;; - esac - - if - $posix_mkdir && ( - umask $mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" - ) - then : - else - - # The umask is ridiculous, or mkdir does not conform to POSIX, - # or it failed possibly due to a race condition. Create the - # directory the slow way, step by step, checking for races as we go. - - case $dstdir in - /*) prefix='/';; - [-=\(\)!]*) prefix='./';; - *) prefix='';; - esac - - eval "$initialize_posix_glob" - - oIFS=$IFS - IFS=/ - $posix_glob set -f - set fnord $dstdir - shift - $posix_glob set +f - IFS=$oIFS - - prefixes= - - for d - do - test X"$d" = X && continue - - prefix=$prefix$d - if test -d "$prefix"; then - prefixes= - else - if $posix_mkdir; then - (umask=$mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break - # Don't fail if two instances are running concurrently. - test -d "$prefix" || exit 1 - else - case $prefix in - *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; - *) qprefix=$prefix;; - esac - prefixes="$prefixes '$qprefix'" - fi - fi - prefix=$prefix/ - done - - if test -n "$prefixes"; then - # Don't fail if two instances are running concurrently. - (umask $mkdir_umask && - eval "\$doit_exec \$mkdirprog $prefixes") || - test -d "$dstdir" || exit 1 - obsolete_mkdir_used=true - fi - fi - fi - - if test -n "$dir_arg"; then - { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && - { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && - { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || - test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 - else - - # Make a couple of temp file names in the proper directory. - dsttmp=$dstdir/_inst.$$_ - rmtmp=$dstdir/_rm.$$_ - - # Trap to clean up those temp files at exit. - trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 - - # Copy the file name to the temp name. - (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && - - # and set any options; do chmod last to preserve setuid bits. - # - # If any of these fail, we abort the whole thing. If we want to - # ignore errors from any of these, just make sure not to ignore - # errors from the above "$doit $cpprog $src $dsttmp" command. - # - { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && - { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && - { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && - { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && - - # If -C, don't bother to copy if it wouldn't change the file. - if $copy_on_change && - old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && - new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && - - eval "$initialize_posix_glob" && - $posix_glob set -f && - set X $old && old=:$2:$4:$5:$6 && - set X $new && new=:$2:$4:$5:$6 && - $posix_glob set +f && - - test "$old" = "$new" && - $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 - then - rm -f "$dsttmp" - else - # Rename the file to the real destination. - $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || - - # The rename failed, perhaps because mv can't rename something else - # to itself, or perhaps because mv is so ancient that it does not - # support -f. - { - # Now remove or move aside any old file at destination location. - # We try this two ways since rm can't unlink itself on some - # systems and the destination file might be busy for other - # reasons. In this case, the final cleanup might fail but the new - # file should still install successfully. - { - test ! -f "$dst" || - $doit $rmcmd -f "$dst" 2>/dev/null || - { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && - { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } - } || - { echo "$0: cannot unlink or rename $dst" >&2 - (exit 1); exit 1 - } - } && - - # Now rename the file to the real destination. - $doit $mvcmd "$dsttmp" "$dst" - } - fi || exit 1 - - trap '' 0 - fi -done - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" -# time-stamp-end: "; # UTC" -# End: diff --git a/configure.ac b/configure.ac deleted file mode 100644 index 4df5c80f0..000000000 --- a/configure.ac +++ /dev/null @@ -1,456 +0,0 @@ -AC_INIT([nix],[m4_esyscmd(bash -c "echo -n $(cat ./.version)$VERSION_SUFFIX")]) -AC_CONFIG_MACRO_DIRS([m4]) -AC_CONFIG_SRCDIR(README.md) -AC_CONFIG_AUX_DIR(config) - -AC_PROG_SED - -# Construct a Nix system name (like "i686-linux"): -# https://www.gnu.org/software/autoconf/manual/html_node/Canonicalizing.html#index-AC_005fCANONICAL_005fHOST-1 -# The inital value is produced by the `config/config.guess` script: -# upstream: https://git.savannah.gnu.org/cgit/config.git/tree/config.guess -# It has the following form, which is not documented anywhere: -# --[][-] -# If `./configure` is passed any of the `--host`, `--build`, `--target` options, the value comes from `config/config.sub` instead: -# upstream: https://git.savannah.gnu.org/cgit/config.git/tree/config.sub -AC_CANONICAL_HOST -AC_MSG_CHECKING([for the canonical Nix system name]) - -AC_ARG_WITH(system, AS_HELP_STRING([--with-system=SYSTEM],[Platform identifier (e.g., `i686-linux').]), - [system=$withval], - [case "$host_cpu" in - i*86) - machine_name="i686";; - amd64) - machine_name="x86_64";; - armv6|armv7) - machine_name="${host_cpu}l";; - *) - machine_name="$host_cpu";; - esac - - case "$host_os" in - linux-gnu*|linux-musl*) - # For backward compatibility, strip the `-gnu' part. - system="$machine_name-linux";; - *) - # Strip the version number from names such as `gnu0.3', - # `darwin10.2.0', etc. - system="$machine_name-`echo $host_os | "$SED" -e's/@<:@0-9.@:>@*$//g'`";; - esac]) - -AC_MSG_RESULT($system) -AC_SUBST(system) -AC_DEFINE_UNQUOTED(SYSTEM, ["$system"], [platform identifier ('cpu-os')]) - - -# State should be stored in /nix/var, unless the user overrides it explicitly. -test "$localstatedir" = '${prefix}/var' && localstatedir=/nix/var - -# Assign a default value to C{,XX}FLAGS as the default configure script sets them -# to -O2 otherwise, which we don't want to have hardcoded -CFLAGS=${CFLAGS-""} -CXXFLAGS=${CXXFLAGS-""} - -AC_PROG_CC -AC_PROG_CXX -AC_PROG_CPP - -AC_CHECK_TOOL([AR], [ar]) - -# Use 64-bit file system calls so that we can support files > 2 GiB. -AC_SYS_LARGEFILE - - -# OS-specific stuff. -case "$host_os" in - solaris*) - # Solaris requires -lsocket -lnsl for network functions - LDFLAGS="-lsocket -lnsl $LDFLAGS" - ;; - darwin*) - # Need to link to libsandbox. - LDFLAGS="-lsandbox $LDFLAGS" - ;; -esac - - -ENSURE_NO_GCC_BUG_80431 - - -# Check for pubsetbuf. -AC_MSG_CHECKING([for pubsetbuf]) -AC_LANG_PUSH(C++) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include -using namespace std; -static char buf[1024];]], - [[cerr.rdbuf()->pubsetbuf(buf, sizeof(buf));]])], - [AC_MSG_RESULT(yes) AC_DEFINE(HAVE_PUBSETBUF, 1, [Whether pubsetbuf is available.])], - AC_MSG_RESULT(no)) -AC_LANG_POP(C++) - - -AC_CHECK_FUNCS([statvfs pipe2 close_range]) - - -# Check for lutimes and utimensat, optionally used for changing the -# mtime of symlinks. -AC_CHECK_DECLS([AT_SYMLINK_NOFOLLOW], [], [], [[#include ]]) -AC_CHECK_FUNCS([lutimes utimensat]) - - -# Check whether the store optimiser can optimise symlinks. -AC_MSG_CHECKING([whether it is possible to create a link to a symlink]) -ln -s bla tmp_link -if ln tmp_link tmp_link2 2> /dev/null; then - AC_MSG_RESULT(yes) - AC_DEFINE(CAN_LINK_SYMLINK, 1, [Whether link() works on symlinks.]) -else - AC_MSG_RESULT(no) -fi -rm -f tmp_link tmp_link2 - - -# Check for . -AC_LANG_PUSH(C++) -AC_CHECK_HEADERS([locale]) -AC_LANG_POP(C++) - - -AC_DEFUN([NEED_PROG], -[ -AC_PATH_PROG($1, $2) -if test -z "$$1"; then - AC_MSG_ERROR([$2 is required]) -fi -]) - -NEED_PROG(bash, bash) -AC_PATH_PROG(flex, flex, false) -AC_PATH_PROG(bison, bison, false) -AC_PATH_PROG(dot, dot) -AC_PATH_PROG(lsof, lsof, lsof) - - -AC_SUBST(coreutils, [$(dirname $(type -p cat))]) - - -AC_ARG_WITH(store-dir, AS_HELP_STRING([--with-store-dir=PATH],[path of the Nix store (defaults to /nix/store)]), - storedir=$withval, storedir='/nix/store') -AC_SUBST(storedir) - - -# Running the functional tests without building Nix is useful for testing -# different pre-built versions of Nix against each other. -AC_ARG_ENABLE(build, AS_HELP_STRING([--disable-build],[Do not build nix]), - ENABLE_BUILD=$enableval, ENABLE_BUILD=yes) -AC_SUBST(ENABLE_BUILD) - -# Building without unit tests is useful for bootstrapping with a smaller footprint -# or running the tests in a separate derivation. Otherwise, we do compile and -# run them. - -AC_ARG_ENABLE(unit-tests, AS_HELP_STRING([--disable-unit-tests],[Do not build the tests]), - ENABLE_UNIT_TESTS=$enableval, ENABLE_UNIT_TESTS=$ENABLE_BUILD) -AC_SUBST(ENABLE_UNIT_TESTS) - -AS_IF( - [test "$ENABLE_BUILD" == "no" && test "$ENABLE_UNIT_TESTS" == "yes"], - [AC_MSG_ERROR([Cannot enable unit tests when building overall is disabled. Please do not pass '--enable-unit-tests' or do not pass '--disable-build'.])]) - -AC_ARG_ENABLE(functional-tests, AS_HELP_STRING([--disable-functional-tests],[Do not build the tests]), - ENABLE_FUNCTIONAL_TESTS=$enableval, ENABLE_FUNCTIONAL_TESTS=yes) -AC_SUBST(ENABLE_FUNCTIONAL_TESTS) - -# documentation generation switch -AC_ARG_ENABLE(doc-gen, AS_HELP_STRING([--disable-doc-gen],[disable documentation generation]), - ENABLE_DOC_GEN=$enableval, ENABLE_DOC_GEN=$ENABLE_BUILD) -AC_SUBST(ENABLE_DOC_GEN) - -AS_IF( - [test "$ENABLE_BUILD" == "no" && test "$ENABLE_DOC_GEN" == "yes"], - [AC_MSG_ERROR([Cannot enable generated docs when building overall is disabled. Please do not pass '--enable-doc-gen' or do not pass '--disable-build'.])]) - -AS_IF( - [test "$ENABLE_FUNCTIONAL_TESTS" == "yes" || test "$ENABLE_DOC_GEN" == "yes"], - [NEED_PROG(jq, jq)]) - -AS_IF( - [test "$ENABLE_DOC_GEN" == "yes"], - [NEED_PROG(man, man)]) - -AS_IF([test "$ENABLE_BUILD" == "yes"],[ - -# Look for boost, a required dependency. -# Note that AX_BOOST_BASE only exports *CPP* BOOST_CPPFLAGS, no CXX flags, -# and CPPFLAGS are not passed to the C++ compiler automatically. -# Thus we append the returned CPPFLAGS to the CXXFLAGS here. -AX_BOOST_BASE([1.66], [CXXFLAGS="$BOOST_CPPFLAGS $CXXFLAGS"], [AC_MSG_ERROR([Nix requires boost.])]) -# For unknown reasons, setting this directly in the ACTION-IF-FOUND above -# ends up with LDFLAGS being empty, so we set it afterwards. -LDFLAGS="$BOOST_LDFLAGS $LDFLAGS" - -# On some platforms, new-style atomics need a helper library -AC_MSG_CHECKING(whether -latomic is needed) -AC_LINK_IFELSE([AC_LANG_SOURCE([[ -#include -uint64_t v; -int main() { - return (int)__atomic_load_n(&v, __ATOMIC_ACQUIRE); -}]])], GCC_ATOMIC_BUILTINS_NEED_LIBATOMIC=no, GCC_ATOMIC_BUILTINS_NEED_LIBATOMIC=yes) -AC_MSG_RESULT($GCC_ATOMIC_BUILTINS_NEED_LIBATOMIC) -if test "x$GCC_ATOMIC_BUILTINS_NEED_LIBATOMIC" = xyes; then - LDFLAGS="-latomic $LDFLAGS" -fi - -AC_ARG_ENABLE(install-unit-tests, AS_HELP_STRING([--enable-install-unit-tests],[Install the unit tests for running later (default no)]), - INSTALL_UNIT_TESTS=$enableval, INSTALL_UNIT_TESTS=no) -AC_SUBST(INSTALL_UNIT_TESTS) - -AC_ARG_WITH(check-bin-dir, AS_HELP_STRING([--with-check-bin-dir=PATH],[path to install unit tests for running later (defaults to $libexecdir/nix)]), - checkbindir=$withval, checkbindir=$libexecdir/nix) -AC_SUBST(checkbindir) - -AC_ARG_WITH(check-lib-dir, AS_HELP_STRING([--with-check-lib-dir=PATH],[path to install unit tests for running later (defaults to $libdir)]), - checklibdir=$withval, checklibdir=$libdir) -AC_SUBST(checklibdir) - -# LTO is currently broken with clang for unknown reasons; ld segfaults in the llvm plugin -AC_ARG_ENABLE(lto, AS_HELP_STRING([--enable-lto],[Enable LTO (only supported with GCC) [default=no]]), - lto=$enableval, lto=no) -if test "$lto" = yes; then - if $CXX --version | grep -q GCC; then - AC_SUBST(CXXLTO, [-flto=jobserver]) - else - echo "error: LTO is only supported with GCC at the moment" >&2 - exit 1 - fi -else - AC_SUBST(CXXLTO, [""]) -fi - -PKG_PROG_PKG_CONFIG - -AC_ARG_ENABLE(shared, AS_HELP_STRING([--enable-shared],[Build shared libraries for Nix [default=yes]]), - shared=$enableval, shared=yes) -if test "$shared" = yes; then - AC_SUBST(BUILD_SHARED_LIBS, 1, [Whether to build shared libraries.]) -else - AC_SUBST(BUILD_SHARED_LIBS, 0, [Whether to build shared libraries.]) - PKG_CONFIG="$PKG_CONFIG --static" -fi - -# Look for OpenSSL, a required dependency. FIXME: this is only (maybe) -# used by S3BinaryCacheStore. -PKG_CHECK_MODULES([OPENSSL], [libcrypto >= 1.1.1], [CXXFLAGS="$OPENSSL_CFLAGS $CXXFLAGS"]) - - -# Look for libarchive. -PKG_CHECK_MODULES([LIBARCHIVE], [libarchive >= 3.1.2], [CXXFLAGS="$LIBARCHIVE_CFLAGS $CXXFLAGS"]) -# Workaround until https://github.com/libarchive/libarchive/issues/1446 is fixed -if test "$shared" != yes; then - LIBARCHIVE_LIBS+=' -lz' -fi - -# Look for SQLite, a required dependency. -PKG_CHECK_MODULES([SQLITE3], [sqlite3 >= 3.6.19], [CXXFLAGS="$SQLITE3_CFLAGS $CXXFLAGS"]) - -# Look for libcurl, a required dependency. -PKG_CHECK_MODULES([LIBCURL], [libcurl], [CXXFLAGS="$LIBCURL_CFLAGS $CXXFLAGS"]) - -# Look for editline or readline, a required dependency. -# The the libeditline.pc file was added only in libeditline >= 1.15.2, -# see https://github.com/troglobit/editline/commit/0a8f2ef4203c3a4a4726b9dd1336869cd0da8607, -# Older versions are no longer supported. -AC_ARG_WITH( - [readline-flavor], - AS_HELP_STRING([--with-readline-flavor],[Which library to use for nice line editting with the Nix language REPL" [default=editline]]), - [readline_flavor=$withval], - [readline_flavor=editline]) -AS_CASE(["$readline_flavor"], - [editline], [ - readline_flavor_pc=libeditline - ], - [readline], [ - readline_flavor_pc=readline - AC_DEFINE([USE_READLINE], [1], [Use readline instead of editline]) - ], - [AC_MSG_ERROR([bad value "$readline_flavor" for --with-readline-flavor, must be one of: editline, readline])]) -PKG_CHECK_MODULES([EDITLINE], [$readline_flavor_pc], [CXXFLAGS="$EDITLINE_CFLAGS $CXXFLAGS"]) - -# Look for libsodium. -PKG_CHECK_MODULES([SODIUM], [libsodium], [CXXFLAGS="$SODIUM_CFLAGS $CXXFLAGS"]) - -# Look for libbrotli{enc,dec}. -PKG_CHECK_MODULES([LIBBROTLI], [libbrotlienc libbrotlidec], [CXXFLAGS="$LIBBROTLI_CFLAGS $CXXFLAGS"]) - -# Look for libcpuid. -have_libcpuid= -if test "$machine_name" = "x86_64"; then - AC_ARG_ENABLE([cpuid], - AS_HELP_STRING([--disable-cpuid], [Do not determine microarchitecture levels with libcpuid (relevant to x86_64 only)])) - if test "x$enable_cpuid" != "xno"; then - PKG_CHECK_MODULES([LIBCPUID], [libcpuid], - [CXXFLAGS="$LIBCPUID_CFLAGS $CXXFLAGS" - have_libcpuid=1 - AC_DEFINE([HAVE_LIBCPUID], [1], [Use libcpuid])] - ) - fi -fi -AC_SUBST(HAVE_LIBCPUID, [$have_libcpuid]) - - -# Look for libseccomp, required for Linux sandboxing. -case "$host_os" in - linux*) - AC_ARG_ENABLE([seccomp-sandboxing], - AS_HELP_STRING([--disable-seccomp-sandboxing],[Don't build support for seccomp sandboxing (only recommended if your arch doesn't support libseccomp yet!) - ])) - if test "x$enable_seccomp_sandboxing" != "xno"; then - PKG_CHECK_MODULES([LIBSECCOMP], [libseccomp], - [CXXFLAGS="$LIBSECCOMP_CFLAGS $CXXFLAGS" CFLAGS="$LIBSECCOMP_CFLAGS $CFLAGS"]) - have_seccomp=1 - AC_DEFINE([HAVE_SECCOMP], [1], [Whether seccomp is available and should be used for sandboxing.]) - AC_COMPILE_IFELSE([ - AC_LANG_SOURCE([[ - #include - #ifndef __SNR_fchmodat2 - # error "Missing support for fchmodat2" - #endif - ]]) - ], [], [ - echo "libseccomp is missing __SNR_fchmodat2. Please provide libseccomp 2.5.5 or later" - exit 1 - ]) - else - have_seccomp= - fi - ;; - *) - have_seccomp= - ;; -esac -AC_SUBST(HAVE_SECCOMP, [$have_seccomp]) - -# Optional dependencies for better normalizing file system data -AC_CHECK_HEADERS([sys/xattr.h]) -AS_IF([test "$ac_cv_header_sys_xattr_h" = "yes"],[ - AC_CHECK_FUNCS([llistxattr lremovexattr]) - AS_IF([test "$ac_cv_func_llistxattr" = "yes" && test "$ac_cv_func_lremovexattr" = "yes"],[ - AC_DEFINE([HAVE_ACL_SUPPORT], [1], [Define if we can manipulate file system Access Control Lists]) - ]) -]) - -# Look for aws-cpp-sdk-s3. -AC_LANG_PUSH(C++) -AC_CHECK_HEADERS([aws/s3/S3Client.h], - [AC_DEFINE([ENABLE_S3], [1], [Whether to enable S3 support via aws-sdk-cpp.]) enable_s3=1], - [AC_DEFINE([ENABLE_S3], [0], [Whether to enable S3 support via aws-sdk-cpp.]) enable_s3=]) -AC_SUBST(ENABLE_S3, [$enable_s3]) -AC_LANG_POP(C++) - - -# Whether to use the Boehm garbage collector. -AC_ARG_ENABLE(gc, AS_HELP_STRING([--enable-gc],[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" - AC_DEFINE(HAVE_BOEHMGC, 1, [Whether to use the Boehm garbage collector.]) - - # See `fixupBoehmStackPointer`, for the integration between Boehm GC - # and Boost coroutines. - old_CFLAGS="$CFLAGS" - # Temporary set `-pthread` just for the next check - CFLAGS="$CFLAGS -pthread" - AC_CHECK_FUNCS([pthread_attr_get_np pthread_getattr_np]) - CFLAGS="$old_CFLAGS" -fi - -AS_IF([test "$ENABLE_UNIT_TESTS" == "yes"],[ - -# Look for gtest. -PKG_CHECK_MODULES([GTEST], [gtest_main gmock_main]) - -# Look for rapidcheck. -PKG_CHECK_MODULES([RAPIDCHECK], [rapidcheck rapidcheck_gtest]) - -]) - -# Look for nlohmann/json. -PKG_CHECK_MODULES([NLOHMANN_JSON], [nlohmann_json >= 3.9]) - - -# Look for lowdown library. -AC_ARG_ENABLE([markdown], AS_HELP_STRING([--enable-markdown], [Enable Markdown rendering in the Nix binary (requires lowdown) [default=auto]]), - enable_markdown=$enableval, enable_markdown=auto) -AS_CASE(["$enable_markdown"], - [yes | auto], [ - PKG_CHECK_MODULES([LOWDOWN], [lowdown >= 0.9.0], [ - CXXFLAGS="$LOWDOWN_CFLAGS $CXXFLAGS" - have_lowdown=1 - AC_DEFINE(HAVE_LOWDOWN, 1, [Whether lowdown is available and should be used for Markdown rendering.]) - ], [ - AS_IF([test "x$enable_markdown" == "xyes"], [AC_MSG_ERROR([--enable-markdown was specified, but lowdown was not found.])]) - ]) - ], - [no], [have_lowdown=], - [AC_MSG_ERROR([bad value "$enable_markdown" for --enable-markdown, must be one of: yes, no, auto])]) - - -# Look for libgit2. -PKG_CHECK_MODULES([LIBGIT2], [libgit2]) - - -# Look for toml11, a required dependency. -AC_LANG_PUSH(C++) -AC_CHECK_HEADER([toml.hpp], [], [AC_MSG_ERROR([toml11 is not found.])]) -AC_LANG_POP(C++) - -# Setuid installations. -AC_CHECK_FUNCS([setresuid setreuid lchown]) - - -# Nice to have, but not essential. -AC_CHECK_FUNCS([strsignal posix_fallocate sysconf]) - - -AC_ARG_WITH(sandbox-shell, AS_HELP_STRING([--with-sandbox-shell=PATH],[path of a statically-linked shell to use as /bin/sh in sandboxes]), - sandbox_shell=$withval) -AC_SUBST(sandbox_shell) -if test ${cross_compiling:-no} = no && ! test -z ${sandbox_shell+x}; then - AC_MSG_CHECKING([whether sandbox-shell has the standalone feature]) - # busybox shell sometimes allows executing other busybox applets, - # even if they are not in the path, breaking our sandbox - if PATH= $sandbox_shell -c "busybox" 2>&1 | grep -qv "not found"; then - AC_MSG_RESULT(enabled) - AC_MSG_ERROR([Please disable busybox FEATURE_SH_STANDALONE]) - else - AC_MSG_RESULT(disabled) - fi -fi - -AC_ARG_ENABLE(embedded-sandbox-shell, AS_HELP_STRING([--enable-embedded-sandbox-shell],[include the sandbox shell in the Nix binary [default=no]]), - embedded_sandbox_shell=$enableval, embedded_sandbox_shell=no) -AC_SUBST(embedded_sandbox_shell) -if test "$embedded_sandbox_shell" = yes; then - AC_DEFINE(HAVE_EMBEDDED_SANDBOX_SHELL, 1, [Include the sandbox shell in the Nix binary.]) -fi - -]) - - -# Expand all variables in config.status. -test "$prefix" = NONE && prefix=$ac_default_prefix -test "$exec_prefix" = NONE && exec_prefix='${prefix}' -for name in $ac_subst_vars; do - declare $name="$(eval echo "${!name}")" - declare $name="$(eval echo "${!name}")" - declare $name="$(eval echo "${!name}")" -done - -rm -f Makefile.config - -AC_CONFIG_HEADERS([config.h]) -AC_CONFIG_FILES([]) -AC_OUTPUT diff --git a/doc/manual/local.mk b/doc/manual/local.mk deleted file mode 100644 index 36cccc506..000000000 --- a/doc/manual/local.mk +++ /dev/null @@ -1,236 +0,0 @@ -# The version of Nix used to generate the doc. Can also be -# `$(nix_INSTALL_PATH)` or just `nix` (to grap ambient from the `PATH`), -# if one prefers. -doc_nix = $(nix_PATH) - -MANUAL_SRCS := \ - $(call rwildcard, $(d)/source, *.md) \ - $(call rwildcard, $(d)/source, */*.md) - -man-pages := $(foreach n, \ - nix-env.1 nix-store.1 \ - nix-build.1 nix-shell.1 nix-instantiate.1 \ - nix-collect-garbage.1 \ - nix-prefetch-url.1 nix-channel.1 \ - nix-hash.1 nix-copy-closure.1 \ - nix.conf.5 nix-daemon.8 \ - nix-profiles.5 \ -, $(d)/$(n)) - -# man pages for subcommands -# convert from `$(d)/source/command-ref/nix-{1}/{2}.md` to `$(d)/nix-{1}-{2}.1` -# FIXME: unify with how nix3-cli man pages are generated -man-pages += $(foreach subcommand, \ - $(filter-out %opt-common.md %env-common.md, $(wildcard $(d)/source/command-ref/nix-*/*.md)), \ - $(d)/$(subst /,-,$(subst $(d)/source/command-ref/,,$(subst .md,.1,$(subcommand))))) - -clean-files += $(d)/*.1 $(d)/*.5 $(d)/*.8 - -# Provide a dummy environment for nix, so that it will not access files outside the macOS sandbox. -# Set cores to 0 because otherwise `nix config show` resolves the cores based on the current machine -dummy-env = env -i \ - HOME=/dummy \ - NIX_CONF_DIR=/dummy \ - NIX_SSL_CERT_FILE=/dummy/no-ca-bundle.crt \ - NIX_STATE_DIR=/dummy \ - NIX_CONFIG='cores = 0' - -nix-eval = $(dummy-env) $(doc_nix) eval --experimental-features nix-command -I nix=doc/manual --store dummy:// --impure --raw - -# re-implement mdBook's include directive to make it usable for terminal output and for proper @docroot@ substitution -define process-includes - while read -r line; do \ - set -euo pipefail; \ - filename="$$(dirname $(1))/$$(sed 's/{{#include \(.*\)}}/\1/'<<< $$line)"; \ - test -f "$$filename" || ( echo "#include-d file '$$filename' does not exist." >&2; exit 1; ); \ - matchline="$$(sed 's|/|\\/|g' <<< $$line)"; \ - sed -i "/$$matchline/r $$filename" $(2); \ - sed -i "s/$$matchline//" $(2); \ - done < <(grep '{{#include' $(1)) -endef - -$(d)/nix-env-%.1: $(d)/source/command-ref/nix-env/%.md - @printf "Title: %s\n\n" "$(subst nix-env-,nix-env --,$$(basename "$@" .1))" > $^.tmp - $(render-subcommand) - -$(d)/nix-store-%.1: $(d)/source/command-ref/nix-store/%.md - @printf -- 'Title: %s\n\n' "$(subst nix-store-,nix-store --,$$(basename "$@" .1))" > $^.tmp - $(render-subcommand) - -# FIXME: there surely is some more deduplication to be achieved here with even darker Make magic -define render-subcommand - @cat $^ >> $^.tmp - @$(call process-includes,$^,$^.tmp) - $(trace-gen) lowdown -sT man --nroff-nolinks -M section=1 $^.tmp -o $@ - @# fix up `lowdown`'s automatic escaping of `--` - @# https://github.com/kristapsdz/lowdown/blob/edca6ce6d5336efb147321a43c47a698de41bb7c/entity.c#L202 - @sed -i 's/\e\[u2013\]/--/' $@ - @rm $^.tmp -endef - - -$(d)/%.1: $(d)/source/command-ref/%.md - @printf "Title: %s\n\n" "$$(basename $@ .1)" > $^.tmp - @cat $^ >> $^.tmp - @$(call process-includes,$^,$^.tmp) - $(trace-gen) lowdown -sT man --nroff-nolinks -M section=1 $^.tmp -o $@ - @rm $^.tmp - -$(d)/%.8: $(d)/source/command-ref/%.md - @printf "Title: %s\n\n" "$$(basename $@ .8)" > $^.tmp - @cat $^ >> $^.tmp - $(trace-gen) lowdown -sT man --nroff-nolinks -M section=8 $^.tmp -o $@ - @rm $^.tmp - -$(d)/nix.conf.5: $(d)/source/command-ref/conf-file.md - @printf "Title: %s\n\n" "$$(basename $@ .5)" > $^.tmp - @cat $^ >> $^.tmp - @$(call process-includes,$^,$^.tmp) - $(trace-gen) lowdown -sT man --nroff-nolinks -M section=5 $^.tmp -o $@ - @rm $^.tmp - -$(d)/nix-profiles.5: $(d)/source/command-ref/files/profiles.md - @printf "Title: %s\n\n" "$$(basename $@ .5)" > $^.tmp - @cat $^ >> $^.tmp - $(trace-gen) lowdown -sT man --nroff-nolinks -M section=5 $^.tmp -o $@ - @rm $^.tmp - -$(d)/source/SUMMARY.md: $(d)/source/SUMMARY.md.in $(d)/source/SUMMARY-rl-next.md $(d)/source/store/types $(d)/source/command-ref/new-cli $(d)/source/development/experimental-feature-descriptions.md - @cp $< $@ - @$(call process-includes,$@,$@) - -$(d)/source/store/types: $(d)/nix.json $(d)/utils.nix $(d)/generate-store-info.nix $(d)/generate-store-types.nix $(d)/source/store/types/index.md.in $(doc_nix) - @# FIXME: build out of tree! - @rm -rf $@.tmp - $(trace-gen) $(nix-eval) --write-to $@.tmp --expr 'import doc/manual/generate-store-types.nix (builtins.fromJSON (builtins.readFile $<)).stores' - @# do not destroy existing contents - @mv $@.tmp/* $@/ - -$(d)/source/command-ref/new-cli: $(d)/nix.json $(d)/utils.nix $(d)/generate-manpage.nix $(d)/generate-settings.nix $(d)/generate-store-info.nix $(doc_nix) - @rm -rf $@ $@.tmp - $(trace-gen) $(nix-eval) --write-to $@.tmp --expr 'import doc/manual/generate-manpage.nix true (builtins.readFile $<)' - @mv $@.tmp $@ - -$(d)/source/command-ref/conf-file.md: $(d)/conf-file.json $(d)/utils.nix $(d)/generate-settings.nix $(d)/source/command-ref/conf-file-prefix.md $(d)/source/command-ref/experimental-features-shortlist.md $(doc_nix) - @cat doc/manual/source/command-ref/conf-file-prefix.md > $@.tmp - $(trace-gen) $(nix-eval) --expr 'import doc/manual/generate-settings.nix { prefix = "conf"; } (builtins.fromJSON (builtins.readFile $<))' >> $@.tmp; - @mv $@.tmp $@ - -$(d)/nix.json: $(doc_nix) - $(trace-gen) $(dummy-env) $(doc_nix) __dump-cli > $@.tmp - @mv $@.tmp $@ - -$(d)/conf-file.json: $(doc_nix) - $(trace-gen) $(dummy-env) $(doc_nix) config show --json --experimental-features nix-command > $@.tmp - @mv $@.tmp $@ - -$(d)/source/development/experimental-feature-descriptions.md: $(d)/xp-features.json $(d)/utils.nix $(d)/generate-xp-features.nix $(doc_nix) - @rm -rf $@ $@.tmp - $(trace-gen) $(nix-eval) --write-to $@.tmp --expr 'import doc/manual/generate-xp-features.nix (builtins.fromJSON (builtins.readFile $<))' - @mv $@.tmp $@ - -$(d)/source/command-ref/experimental-features-shortlist.md: $(d)/xp-features.json $(d)/utils.nix $(d)/generate-xp-features-shortlist.nix $(doc_nix) - @rm -rf $@ $@.tmp - $(trace-gen) $(nix-eval) --write-to $@.tmp --expr 'import doc/manual/generate-xp-features-shortlist.nix (builtins.fromJSON (builtins.readFile $<))' - @mv $@.tmp $@ - -$(d)/xp-features.json: $(doc_nix) - $(trace-gen) $(dummy-env) $(doc_nix) __dump-xp-features > $@.tmp - @mv $@.tmp $@ - -$(d)/source/language/builtins.md: $(d)/language.json $(d)/generate-builtins.nix $(d)/source/language/builtins-prefix.md $(doc_nix) - @cat doc/manual/source/language/builtins-prefix.md > $@.tmp - $(trace-gen) $(nix-eval) --expr 'import doc/manual/generate-builtins.nix (builtins.fromJSON (builtins.readFile $<))' >> $@.tmp; - @cat doc/manual/source/language/builtins-suffix.md >> $@.tmp - @mv $@.tmp $@ - -$(d)/language.json: $(doc_nix) - $(trace-gen) $(dummy-env) $(doc_nix) __dump-language > $@.tmp - @mv $@.tmp $@ - -# Generate "Upcoming release" notes (or clear it and remove from menu) -$(d)/source/release-notes/rl-next.md: $(d)/rl-next $(d)/rl-next/* - @if type -p changelog-d > /dev/null; then \ - echo " GEN " $@; \ - changelog-d doc/manual/rl-next > $@; \ - else \ - echo " NULL " $@; \ - true > $@; \ - fi - -$(d)/source/SUMMARY-rl-next.md: $(d)/source/release-notes/rl-next.md - $(trace-gen) true - @if [ -s $< ]; then \ - echo ' - [Upcoming release](release-notes/rl-next.md)' > $@; \ - else \ - true > $@; \ - fi - -# Generate the HTML manual. -.PHONY: manual-html -manual-html: $(docdir)/manual/index.html - -# Open the built HTML manual in the default browser. -manual-html-open: $(docdir)/manual/index.html - @echo " OPEN " $<; \ - xdg-open $< \ - || open $< \ - || { \ - echo "Could not open the manual in a browser. Please open '$<'" >&2; \ - false; \ - } -install: $(docdir)/manual/index.html - -# Generate 'nix' manpages. -.PHONY: manpages -manpages: $(mandir)/man1/nix3-manpages -install: $(mandir)/man1/nix3-manpages -man: doc/manual/generated/man1/nix3-manpages -all: doc/manual/generated/man1/nix3-manpages - -# FIXME: unify with how the other man pages are generated. -# this one works differently and does not use any of the amenities provided by `/mk/lib.mk`. -$(mandir)/man1/nix3-manpages: doc/manual/generated/man1/nix3-manpages - @mkdir -p $(DESTDIR)$$(dirname $@) - $(trace-install) install -m 0644 $$(dirname $<)/* $(DESTDIR)$$(dirname $@) - -doc/manual/generated/man1/nix3-manpages: $(d)/source/command-ref/new-cli - @mkdir -p $(DESTDIR)$$(dirname $@) - $(trace-gen) for i in doc/manual/source/command-ref/new-cli/*.md; do \ - name=$$(basename $$i .md); \ - tmpFile=$$(mktemp); \ - if [[ $$name = SUMMARY ]]; then continue; fi; \ - printf "Title: %s\n\n" "$$name" > $$tmpFile; \ - cat $$i >> $$tmpFile; \ - lowdown -sT man --nroff-nolinks -M section=1 $$tmpFile -o $(DESTDIR)$$(dirname $@)/$$name.1; \ - rm $$tmpFile; \ - done - @touch $@ - -# the `! -name 'documentation.md'` filter excludes the one place where -# `@docroot@` is to be preserved for documenting the mechanism -# FIXME: maybe contributing guides should live right next to the code -# instead of in the manual -$(docdir)/manual/index.html: $(MANUAL_SRCS) $(d)/book.toml $(d)/anchors.jq $(d)/custom.css $(d)/source/SUMMARY.md $(d)/source/store/types $(d)/source/command-ref/new-cli $(d)/source/development/experimental-feature-descriptions.md $(d)/source/command-ref/conf-file.md $(d)/source/language/builtins.md $(d)/source/release-notes/rl-next.md $(d)/source/figures $(d)/source/favicon.png $(d)/source/favicon.svg - $(trace-gen) \ - tmp="$$(mktemp -d)"; \ - cp -r doc/manual "$$tmp"; \ - find "$$tmp" -name '*.md' | while read -r file; do \ - $(call process-includes,$$file,$$file); \ - done; \ - find "$$tmp" -name '*.md' ! -name 'documentation.md' | while read -r file; do \ - docroot="$$(realpath --relative-to="$$(dirname "$$file")" $$tmp/manual/source)"; \ - sed -i "s,@docroot@,$$docroot,g" "$$file"; \ - done; \ - set -euo pipefail; \ - ( \ - cd "$$tmp/manual"; \ - RUST_LOG=warn \ - MDBOOK_SUBSTITUTE_SEARCH=$(d)/source \ - mdbook build -d $(DESTDIR)$(docdir)/manual.tmp 2>&1 \ - | { grep -Fv "because fragment resolution isn't implemented" || :; } \ - ); \ - rm -rf "$$tmp/manual" - @rm -rf $(DESTDIR)$(docdir)/manual - @mv $(DESTDIR)$(docdir)/manual.tmp/html $(DESTDIR)$(docdir)/manual - @rm -rf $(DESTDIR)$(docdir)/manual.tmp diff --git a/flake.nix b/flake.nix index 3ef027dd1..4d339f6e7 100644 --- a/flake.nix +++ b/flake.nix @@ -137,7 +137,7 @@ pkgs = final; }); - nix = final.nixComponents.nix; + nix = final.nixComponents.nix-cli; # See https://github.com/NixOS/nixpkgs/pull/214409 # Remove when fixed in this flake's nixpkgs @@ -189,7 +189,6 @@ # system, we should reenable this. #perlBindings = self.hydraJobs.perlBindings.${system}; } - /* # Add "passthru" tests // flatMapAttrs ({ "" = nixpkgsFor.${system}.native; @@ -211,7 +210,6 @@ "${nixpkgsPrefix}nix-functional-tests" = nixpkgs.nixComponents.nix-functional-tests; } ) - */ // devFlake.checks.${system} or {} ); @@ -220,7 +218,8 @@ # for which we don't apply the full build matrix such as cross or static. inherit (nixpkgsFor.${system}.native) changelog-d; - default = self.packages.${system}.nix-ng; + # TODO probably should be `nix-cli` + default = self.packages.${system}.nix-everything; nix-manual = nixpkgsFor.${system}.native.nixComponents.nix-manual; nix-internal-api-docs = nixpkgsFor.${system}.native.nixComponents.nix-internal-api-docs; nix-external-api-docs = nixpkgsFor.${system}.native.nixComponents.nix-external-api-docs; @@ -228,7 +227,6 @@ # We need to flatten recursive attribute sets of derivations to pass `flake check`. // flatMapAttrs { # Components we'll iterate over in the upcoming lambda - "nix" = { }; "nix-util" = { }; "nix-util-c" = { }; "nix-util-test-support" = { }; @@ -257,10 +255,11 @@ "nix-cli" = { }; + "nix-everything" = { }; + "nix-functional-tests" = { supportsCross = false; }; "nix-perl-bindings" = { supportsCross = false; }; - "nix-ng" = { }; } (pkgName: { supportsCross ? true }: { # These attributes go right into `packages.`. diff --git a/local.mk b/local.mk deleted file mode 100644 index b27c7031e..000000000 --- a/local.mk +++ /dev/null @@ -1,15 +0,0 @@ -GLOBAL_CXXFLAGS += -Wno-deprecated-declarations -Werror=switch -# Allow switch-enum to be overridden for files that do not support it, usually because of dependency headers. -ERROR_SWITCH_ENUM = -Werror=switch-enum - -$(foreach i, config.h $(wildcard src/lib*/*.hh) $(filter-out %_internal.h, $(wildcard src/lib*c/*.h)), \ - $(eval $(call install-file-in, $(i), $(includedir)/nix, 0644))) - -ifdef HOST_UNIX - $(foreach i, $(wildcard src/lib*/unix/*.hh), \ - $(eval $(call install-file-in, $(i), $(includedir)/nix, 0644))) -endif - -$(GCH): src/libutil/util.hh config.h - -GCH_CXXFLAGS = $(INCLUDE_libutil) diff --git a/m4/ax_cxx_compile_stdcxx.m4 b/m4/ax_cxx_compile_stdcxx.m4 deleted file mode 100644 index 43087b2e6..000000000 --- a/m4/ax_cxx_compile_stdcxx.m4 +++ /dev/null @@ -1,951 +0,0 @@ -# =========================================================================== -# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) -# -# DESCRIPTION -# -# Check for baseline language coverage in the compiler for the specified -# version of the C++ standard. If necessary, add switches to CXX and -# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard) -# or '14' (for the C++14 standard). -# -# The second argument, if specified, indicates whether you insist on an -# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. -# -std=c++11). If neither is specified, you get whatever works, with -# preference for an extended mode. -# -# The third argument, if specified 'mandatory' or if left unspecified, -# indicates that baseline support for the specified C++ standard is -# required and that the macro should error out if no mode with that -# support is found. If specified 'optional', then configuration proceeds -# regardless, after defining HAVE_CXX${VERSION} if and only if a -# supporting mode is found. -# -# LICENSE -# -# Copyright (c) 2008 Benjamin Kosnik -# Copyright (c) 2012 Zack Weinberg -# Copyright (c) 2013 Roy Stogner -# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov -# Copyright (c) 2015 Paul Norman -# Copyright (c) 2015 Moritz Klammler -# Copyright (c) 2016, 2018 Krzesimir Nowak -# Copyright (c) 2019 Enji Cooper -# -# Copying and distribution of this file, with or without modification, are -# permitted in any medium without royalty provided the copyright notice -# and this notice are preserved. This file is offered as-is, without any -# warranty. - -#serial 11 - -dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro -dnl (serial version number 13). - -AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl - m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"], - [$1], [14], [ax_cxx_compile_alternatives="14 1y"], - [$1], [17], [ax_cxx_compile_alternatives="17 1z"], - [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl - m4_if([$2], [], [], - [$2], [ext], [], - [$2], [noext], [], - [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl - m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], - [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], - [$3], [optional], [ax_cxx_compile_cxx$1_required=false], - [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) - AC_LANG_PUSH([C++])dnl - ac_success=no - - m4_if([$2], [noext], [], [dnl - if test x$ac_success = xno; then - for alternative in ${ax_cxx_compile_alternatives}; do - switch="-std=gnu++${alternative}" - cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) - AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, - $cachevar, - [ac_save_CXX="$CXX" - CXX="$CXX $switch" - AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], - [eval $cachevar=yes], - [eval $cachevar=no]) - CXX="$ac_save_CXX"]) - if eval test x\$$cachevar = xyes; then - CXX="$CXX $switch" - if test -n "$CXXCPP" ; then - CXXCPP="$CXXCPP $switch" - fi - ac_success=yes - break - fi - done - fi]) - - m4_if([$2], [ext], [], [dnl - if test x$ac_success = xno; then - dnl HP's aCC needs +std=c++11 according to: - dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf - dnl Cray's crayCC needs "-h std=c++11" - for alternative in ${ax_cxx_compile_alternatives}; do - for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do - cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) - AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, - $cachevar, - [ac_save_CXX="$CXX" - CXX="$CXX $switch" - AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], - [eval $cachevar=yes], - [eval $cachevar=no]) - CXX="$ac_save_CXX"]) - if eval test x\$$cachevar = xyes; then - CXX="$CXX $switch" - if test -n "$CXXCPP" ; then - CXXCPP="$CXXCPP $switch" - fi - ac_success=yes - break - fi - done - if test x$ac_success = xyes; then - break - fi - done - fi]) - AC_LANG_POP([C++]) - if test x$ax_cxx_compile_cxx$1_required = xtrue; then - if test x$ac_success = xno; then - AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) - fi - fi - if test x$ac_success = xno; then - HAVE_CXX$1=0 - AC_MSG_NOTICE([No compiler with C++$1 support was found]) - else - HAVE_CXX$1=1 - AC_DEFINE(HAVE_CXX$1,1, - [define if the compiler supports basic C++$1 syntax]) - fi - AC_SUBST(HAVE_CXX$1) -]) - - -dnl Test body for checking C++11 support - -m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], - _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 -) - - -dnl Test body for checking C++14 support - -m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], - _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 - _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 -) - -m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17], - _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 - _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 - _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 -) - -dnl Tests for new features in C++11 - -m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ - -// If the compiler admits that it is not ready for C++11, why torture it? -// Hopefully, this will speed up the test. - -#ifndef __cplusplus - -#error "This is not a C++ compiler" - -#elif __cplusplus < 201103L - -#error "This is not a C++11 compiler" - -#else - -namespace cxx11 -{ - - namespace test_static_assert - { - - template - struct check - { - static_assert(sizeof(int) <= sizeof(T), "not big enough"); - }; - - } - - namespace test_final_override - { - - struct Base - { - virtual ~Base() {} - virtual void f() {} - }; - - struct Derived : public Base - { - virtual ~Derived() override {} - virtual void f() override {} - }; - - } - - namespace test_double_right_angle_brackets - { - - template < typename T > - struct check {}; - - typedef check single_type; - typedef check> double_type; - typedef check>> triple_type; - typedef check>>> quadruple_type; - - } - - namespace test_decltype - { - - int - f() - { - int a = 1; - decltype(a) b = 2; - return a + b; - } - - } - - namespace test_type_deduction - { - - template < typename T1, typename T2 > - struct is_same - { - static const bool value = false; - }; - - template < typename T > - struct is_same - { - static const bool value = true; - }; - - template < typename T1, typename T2 > - auto - add(T1 a1, T2 a2) -> decltype(a1 + a2) - { - return a1 + a2; - } - - int - test(const int c, volatile int v) - { - static_assert(is_same::value == true, ""); - static_assert(is_same::value == false, ""); - static_assert(is_same::value == false, ""); - auto ac = c; - auto av = v; - auto sumi = ac + av + 'x'; - auto sumf = ac + av + 1.0; - static_assert(is_same::value == true, ""); - static_assert(is_same::value == true, ""); - static_assert(is_same::value == true, ""); - static_assert(is_same::value == false, ""); - static_assert(is_same::value == true, ""); - return (sumf > 0.0) ? sumi : add(c, v); - } - - } - - namespace test_noexcept - { - - int f() { return 0; } - int g() noexcept { return 0; } - - static_assert(noexcept(f()) == false, ""); - static_assert(noexcept(g()) == true, ""); - - } - - namespace test_constexpr - { - - template < typename CharT > - unsigned long constexpr - strlen_c_r(const CharT *const s, const unsigned long acc) noexcept - { - return *s ? strlen_c_r(s + 1, acc + 1) : acc; - } - - template < typename CharT > - unsigned long constexpr - strlen_c(const CharT *const s) noexcept - { - return strlen_c_r(s, 0UL); - } - - static_assert(strlen_c("") == 0UL, ""); - static_assert(strlen_c("1") == 1UL, ""); - static_assert(strlen_c("example") == 7UL, ""); - static_assert(strlen_c("another\0example") == 7UL, ""); - - } - - namespace test_rvalue_references - { - - template < int N > - struct answer - { - static constexpr int value = N; - }; - - answer<1> f(int&) { return answer<1>(); } - answer<2> f(const int&) { return answer<2>(); } - answer<3> f(int&&) { return answer<3>(); } - - void - test() - { - int i = 0; - const int c = 0; - static_assert(decltype(f(i))::value == 1, ""); - static_assert(decltype(f(c))::value == 2, ""); - static_assert(decltype(f(0))::value == 3, ""); - } - - } - - namespace test_uniform_initialization - { - - struct test - { - static const int zero {}; - static const int one {1}; - }; - - static_assert(test::zero == 0, ""); - static_assert(test::one == 1, ""); - - } - - namespace test_lambdas - { - - void - test1() - { - auto lambda1 = [](){}; - auto lambda2 = lambda1; - lambda1(); - lambda2(); - } - - int - test2() - { - auto a = [](int i, int j){ return i + j; }(1, 2); - auto b = []() -> int { return '0'; }(); - auto c = [=](){ return a + b; }(); - auto d = [&](){ return c; }(); - auto e = [a, &b](int x) mutable { - const auto identity = [](int y){ return y; }; - for (auto i = 0; i < a; ++i) - a += b--; - return x + identity(a + b); - }(0); - return a + b + c + d + e; - } - - int - test3() - { - const auto nullary = [](){ return 0; }; - const auto unary = [](int x){ return x; }; - using nullary_t = decltype(nullary); - using unary_t = decltype(unary); - const auto higher1st = [](nullary_t f){ return f(); }; - const auto higher2nd = [unary](nullary_t f1){ - return [unary, f1](unary_t f2){ return f2(unary(f1())); }; - }; - return higher1st(nullary) + higher2nd(nullary)(unary); - } - - } - - namespace test_variadic_templates - { - - template - struct sum; - - template - struct sum - { - static constexpr auto value = N0 + sum::value; - }; - - template <> - struct sum<> - { - static constexpr auto value = 0; - }; - - static_assert(sum<>::value == 0, ""); - static_assert(sum<1>::value == 1, ""); - static_assert(sum<23>::value == 23, ""); - static_assert(sum<1, 2>::value == 3, ""); - static_assert(sum<5, 5, 11>::value == 21, ""); - static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); - - } - - // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae - // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function - // because of this. - namespace test_template_alias_sfinae - { - - struct foo {}; - - template - using member = typename T::member_type; - - template - void func(...) {} - - template - void func(member*) {} - - void test(); - - void test() { func(0); } - - } - -} // namespace cxx11 - -#endif // __cplusplus >= 201103L - -]]) - - -dnl Tests for new features in C++14 - -m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ - -// If the compiler admits that it is not ready for C++14, why torture it? -// Hopefully, this will speed up the test. - -#ifndef __cplusplus - -#error "This is not a C++ compiler" - -#elif __cplusplus < 201402L - -#error "This is not a C++14 compiler" - -#else - -namespace cxx14 -{ - - namespace test_polymorphic_lambdas - { - - int - test() - { - const auto lambda = [](auto&&... args){ - const auto istiny = [](auto x){ - return (sizeof(x) == 1UL) ? 1 : 0; - }; - const int aretiny[] = { istiny(args)... }; - return aretiny[0]; - }; - return lambda(1, 1L, 1.0f, '1'); - } - - } - - namespace test_binary_literals - { - - constexpr auto ivii = 0b0000000000101010; - static_assert(ivii == 42, "wrong value"); - - } - - namespace test_generalized_constexpr - { - - template < typename CharT > - constexpr unsigned long - strlen_c(const CharT *const s) noexcept - { - auto length = 0UL; - for (auto p = s; *p; ++p) - ++length; - return length; - } - - static_assert(strlen_c("") == 0UL, ""); - static_assert(strlen_c("x") == 1UL, ""); - static_assert(strlen_c("test") == 4UL, ""); - static_assert(strlen_c("another\0test") == 7UL, ""); - - } - - namespace test_lambda_init_capture - { - - int - test() - { - auto x = 0; - const auto lambda1 = [a = x](int b){ return a + b; }; - const auto lambda2 = [a = lambda1(x)](){ return a; }; - return lambda2(); - } - - } - - namespace test_digit_separators - { - - constexpr auto ten_million = 100'000'000; - static_assert(ten_million == 100000000, ""); - - } - - namespace test_return_type_deduction - { - - auto f(int& x) { return x; } - decltype(auto) g(int& x) { return x; } - - template < typename T1, typename T2 > - struct is_same - { - static constexpr auto value = false; - }; - - template < typename T > - struct is_same - { - static constexpr auto value = true; - }; - - int - test() - { - auto x = 0; - static_assert(is_same::value, ""); - static_assert(is_same::value, ""); - return x; - } - - } - -} // namespace cxx14 - -#endif // __cplusplus >= 201402L - -]]) - - -dnl Tests for new features in C++17 - -m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[ - -// If the compiler admits that it is not ready for C++17, why torture it? -// Hopefully, this will speed up the test. - -#ifndef __cplusplus - -#error "This is not a C++ compiler" - -#elif __cplusplus < 201703L - -#error "This is not a C++17 compiler" - -#else - -#include -#include -#include - -namespace cxx17 -{ - - namespace test_constexpr_lambdas - { - - constexpr int foo = [](){return 42;}(); - - } - - namespace test::nested_namespace::definitions - { - - } - - namespace test_fold_expression - { - - template - int multiply(Args... args) - { - return (args * ... * 1); - } - - template - bool all(Args... args) - { - return (args && ...); - } - - } - - namespace test_extended_static_assert - { - - static_assert (true); - - } - - namespace test_auto_brace_init_list - { - - auto foo = {5}; - auto bar {5}; - - static_assert(std::is_same, decltype(foo)>::value); - static_assert(std::is_same::value); - } - - namespace test_typename_in_template_template_parameter - { - - template typename X> struct D; - - } - - namespace test_fallthrough_nodiscard_maybe_unused_attributes - { - - int f1() - { - return 42; - } - - [[nodiscard]] int f2() - { - [[maybe_unused]] auto unused = f1(); - - switch (f1()) - { - case 17: - f1(); - [[fallthrough]]; - case 42: - f1(); - } - return f1(); - } - - } - - namespace test_extended_aggregate_initialization - { - - struct base1 - { - int b1, b2 = 42; - }; - - struct base2 - { - base2() { - b3 = 42; - } - int b3; - }; - - struct derived : base1, base2 - { - int d; - }; - - derived d1 {{1, 2}, {}, 4}; // full initialization - derived d2 {{}, {}, 4}; // value-initialized bases - - } - - namespace test_general_range_based_for_loop - { - - struct iter - { - int i; - - int& operator* () - { - return i; - } - - const int& operator* () const - { - return i; - } - - iter& operator++() - { - ++i; - return *this; - } - }; - - struct sentinel - { - int i; - }; - - bool operator== (const iter& i, const sentinel& s) - { - return i.i == s.i; - } - - bool operator!= (const iter& i, const sentinel& s) - { - return !(i == s); - } - - struct range - { - iter begin() const - { - return {0}; - } - - sentinel end() const - { - return {5}; - } - }; - - void f() - { - range r {}; - - for (auto i : r) - { - [[maybe_unused]] auto v = i; - } - } - - } - - namespace test_lambda_capture_asterisk_this_by_value - { - - struct t - { - int i; - int foo() - { - return [*this]() - { - return i; - }(); - } - }; - - } - - namespace test_enum_class_construction - { - - enum class byte : unsigned char - {}; - - byte foo {42}; - - } - - namespace test_constexpr_if - { - - template - int f () - { - if constexpr(cond) - { - return 13; - } - else - { - return 42; - } - } - - } - - namespace test_selection_statement_with_initializer - { - - int f() - { - return 13; - } - - int f2() - { - if (auto i = f(); i > 0) - { - return 3; - } - - switch (auto i = f(); i + 4) - { - case 17: - return 2; - - default: - return 1; - } - } - - } - - namespace test_template_argument_deduction_for_class_templates - { - - template - struct pair - { - pair (T1 p1, T2 p2) - : m1 {p1}, - m2 {p2} - {} - - T1 m1; - T2 m2; - }; - - void f() - { - [[maybe_unused]] auto p = pair{13, 42u}; - } - - } - - namespace test_non_type_auto_template_parameters - { - - template - struct B - {}; - - B<5> b1; - B<'a'> b2; - - } - - namespace test_structured_bindings - { - - int arr[2] = { 1, 2 }; - std::pair pr = { 1, 2 }; - - auto f1() -> int(&)[2] - { - return arr; - } - - auto f2() -> std::pair& - { - return pr; - } - - struct S - { - int x1 : 2; - volatile double y1; - }; - - S f3() - { - return {}; - } - - auto [ x1, y1 ] = f1(); - auto& [ xr1, yr1 ] = f1(); - auto [ x2, y2 ] = f2(); - auto& [ xr2, yr2 ] = f2(); - const auto [ x3, y3 ] = f3(); - - } - - namespace test_exception_spec_type_system - { - - struct Good {}; - struct Bad {}; - - void g1() noexcept; - void g2(); - - template - Bad - f(T*, T*); - - template - Good - f(T1*, T2*); - - static_assert (std::is_same_v); - - } - - namespace test_inline_variables - { - - template void f(T) - {} - - template inline T g(T) - { - return T{}; - } - - template<> inline void f<>(int) - {} - - template<> int g<>(int) - { - return 5; - } - - } - -} // namespace cxx17 - -#endif // __cplusplus < 201703L - -]]) diff --git a/m4/ax_cxx_compile_stdcxx_17.m4 b/m4/ax_cxx_compile_stdcxx_17.m4 deleted file mode 100644 index a68341717..000000000 --- a/m4/ax_cxx_compile_stdcxx_17.m4 +++ /dev/null @@ -1,35 +0,0 @@ -# ============================================================================= -# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_17.html -# ============================================================================= -# -# SYNOPSIS -# -# AX_CXX_COMPILE_STDCXX_17([ext|noext], [mandatory|optional]) -# -# DESCRIPTION -# -# Check for baseline language coverage in the compiler for the C++17 -# standard; if necessary, add switches to CXX and CXXCPP to enable -# support. -# -# This macro is a convenience alias for calling the AX_CXX_COMPILE_STDCXX -# macro with the version set to C++17. The two optional arguments are -# forwarded literally as the second and third argument respectively. -# Please see the documentation for the AX_CXX_COMPILE_STDCXX macro for -# more information. If you want to use this macro, you also need to -# download the ax_cxx_compile_stdcxx.m4 file. -# -# LICENSE -# -# Copyright (c) 2015 Moritz Klammler -# Copyright (c) 2016 Krzesimir Nowak -# -# Copying and distribution of this file, with or without modification, are -# permitted in any medium without royalty provided the copyright notice -# and this notice are preserved. This file is offered as-is, without any -# warranty. - -#serial 2 - -AX_REQUIRE_DEFINED([AX_CXX_COMPILE_STDCXX]) -AC_DEFUN([AX_CXX_COMPILE_STDCXX_17], [AX_CXX_COMPILE_STDCXX([17], [$1], [$2])]) diff --git a/maintainers/local.mk b/maintainers/local.mk deleted file mode 100644 index e81517eda..000000000 --- a/maintainers/local.mk +++ /dev/null @@ -1,8 +0,0 @@ - -.PHONY: format -print-top-help += echo ' format: Format source code' - -# This uses the cached .pre-commit-hooks.yaml file -fmt_script := $(d)/format.sh -format: - @$(fmt_script) diff --git a/misc/bash/local.mk b/misc/bash/local.mk deleted file mode 100644 index 66235af05..000000000 --- a/misc/bash/local.mk +++ /dev/null @@ -1 +0,0 @@ -$(eval $(call install-file-as, $(d)/completion.sh, $(datarootdir)/bash-completion/completions/nix, 0644)) diff --git a/misc/fish/local.mk b/misc/fish/local.mk deleted file mode 100644 index ece899fc3..000000000 --- a/misc/fish/local.mk +++ /dev/null @@ -1 +0,0 @@ -$(eval $(call install-file-as, $(d)/completion.fish, $(datarootdir)/fish/vendor_completions.d/nix.fish, 0644)) diff --git a/misc/launchd/local.mk b/misc/launchd/local.mk deleted file mode 100644 index a39188fe6..000000000 --- a/misc/launchd/local.mk +++ /dev/null @@ -1,5 +0,0 @@ -ifdef HOST_DARWIN - - $(eval $(call install-data-in, $(d)/org.nixos.nix-daemon.plist, $(prefix)/Library/LaunchDaemons)) - -endif diff --git a/misc/systemd/local.mk b/misc/systemd/local.mk deleted file mode 100644 index 76121a0f9..000000000 --- a/misc/systemd/local.mk +++ /dev/null @@ -1,8 +0,0 @@ -ifdef HOST_LINUX - - $(foreach n, nix-daemon.socket nix-daemon.service, $(eval $(call install-file-in, $(d)/$(n), $(prefix)/lib/systemd/system, 0644))) - $(foreach n, nix-daemon.conf, $(eval $(call install-file-in, $(d)/$(n), $(prefix)/lib/tmpfiles.d, 0644))) - - clean-files += $(d)/nix-daemon.socket $(d)/nix-daemon.service $(d)/nix-daemon.conf - -endif diff --git a/misc/upstart/local.mk b/misc/upstart/local.mk deleted file mode 100644 index 2fbfb29b9..000000000 --- a/misc/upstart/local.mk +++ /dev/null @@ -1,7 +0,0 @@ -ifdef HOST_LINUX - - $(foreach n, nix-daemon.conf, $(eval $(call install-file-in, $(d)/$(n), $(sysconfdir)/init, 0644))) - - clean-files += $(d)/nix-daemon.conf - -endif diff --git a/misc/zsh/local.mk b/misc/zsh/local.mk deleted file mode 100644 index 0b4e294fb..000000000 --- a/misc/zsh/local.mk +++ /dev/null @@ -1,2 +0,0 @@ -$(eval $(call install-file-as, $(d)/completion.zsh, $(datarootdir)/zsh/site-functions/_nix, 0644)) -$(eval $(call install-file-as, $(d)/run-help-nix, $(datarootdir)/zsh/site-functions/run-help-nix, 0644)) diff --git a/mk/build-dir.mk b/mk/build-dir.mk deleted file mode 100644 index 02f4cae60..000000000 --- a/mk/build-dir.mk +++ /dev/null @@ -1,10 +0,0 @@ -# Initialise support for build directories. -builddir ?= - -ifdef builddir - buildprefix = $(builddir)/ - buildprefixrel = $(builddir) -else - buildprefix = - buildprefixrel = . -endif diff --git a/mk/clean.mk b/mk/clean.mk deleted file mode 100644 index ce9afb3b0..000000000 --- a/mk/clean.mk +++ /dev/null @@ -1,11 +0,0 @@ -clean-files := - -clean: - $(suppress) rm -fv -- $(clean-files) - -dryclean: - @for i in $(clean-files); do if [ -e $$i ]; then echo $$i; fi; done | sort - -print-top-help += \ - echo " clean: Delete generated files"; \ - echo " dryclean: Show what files would be deleted by 'make clean'"; diff --git a/mk/common-test.sh b/mk/common-test.sh deleted file mode 100644 index dd899e869..000000000 --- a/mk/common-test.sh +++ /dev/null @@ -1,31 +0,0 @@ -# shellcheck shell=bash - -# Remove overall test dir (at most one of the two should match) and -# remove file extension. - -test_name=$(echo -n "${test?must be defined by caller (test runner)}" | sed \ - -e "s|^src/[^/]*-test/data/||" \ - -e "s|^tests/functional/||" \ - -e "s|\.sh$||" \ - ) - -# Layer violation, but I am not inclined to care too much, as this code -# is about to be deleted. -src_dir=$(realpath tests/functional) - -# shellcheck disable=SC2016 -TESTS_ENVIRONMENT=( - "TEST_NAME=$test_name" - 'NIX_REMOTE=' - 'PS4=+(${BASH_SOURCE[0]-$0}:$LINENO) ' - "_NIX_TEST_SOURCE_DIR=${src_dir}" - "_NIX_TEST_BUILD_DIR=${src_dir}" -) - -unset src_dir - -read -r -a bash <<< "${BASH:-/usr/bin/env bash}" - -run () { - cd "$(dirname "$1")" && env "${TESTS_ENVIRONMENT[@]}" "${bash[@]}" -x -e -u -o pipefail "$(basename "$1")" -} diff --git a/mk/compilation-database.mk b/mk/compilation-database.mk deleted file mode 100644 index f69dc0de0..000000000 --- a/mk/compilation-database.mk +++ /dev/null @@ -1,11 +0,0 @@ -compile-commands-json-files := - -define write-compile-commands - _srcs := $$(sort $$(foreach src, $$($(1)_SOURCES), $$(src))) - - $(1)_COMPILE_COMMANDS_JSON := $$(addprefix $(buildprefix), $$(addsuffix .compile_commands.json, $$(basename $$(_srcs)))) - - compile-commands-json-files += $$($(1)_COMPILE_COMMANDS_JSON) - - clean-files += $$($(1)_COMPILE_COMMANDS_JSON) -endef diff --git a/mk/cxx-big-literal.mk b/mk/cxx-big-literal.mk deleted file mode 100644 index d64a171c8..000000000 --- a/mk/cxx-big-literal.mk +++ /dev/null @@ -1,5 +0,0 @@ -%.gen.hh: % - @echo 'R"__NIX_STR(' >> $@.tmp - $(trace-gen) cat $< >> $@.tmp - @echo ')__NIX_STR"' >> $@.tmp - @mv $@.tmp $@ diff --git a/mk/debug-test.sh b/mk/debug-test.sh deleted file mode 100755 index 0dd4406c3..000000000 --- a/mk/debug-test.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -set -eu -o pipefail - -test=$1 - -dir="$(dirname "${BASH_SOURCE[0]}")" -source "$dir/common-test.sh" - -run "$test" diff --git a/mk/functions.mk b/mk/functions.mk deleted file mode 100644 index c48775db8..000000000 --- a/mk/functions.mk +++ /dev/null @@ -1,14 +0,0 @@ -# Utility function for recursively finding files, e.g. -# ‘$(call rwildcard, path/to/dir, *.c *.h)’. -rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d)) - -# Given a file name, produce the corresponding dependency file -# (e.g. ‘foo/bar.o’ becomes ‘foo/.bar.o.dep’). -filename-to-dep = $(dir $1).$(notdir $1).dep - -# Return the full path to a program by looking it up in $PATH, or the -# empty string if not found. -find-program = $(shell for i in $$(IFS=: ; echo $$PATH); do p=$$i/$(strip $1); if [ -e $$p ]; then echo $$p; break; fi; done) - -# Ensure that the given string ends in a single slash. -add-trailing-slash = $(patsubst %/,%,$(1))/ diff --git a/mk/install-dirs.mk b/mk/install-dirs.mk deleted file mode 100644 index 732b0d6fc..000000000 --- a/mk/install-dirs.mk +++ /dev/null @@ -1,11 +0,0 @@ -# Default installation paths. -prefix ?= /usr/local -libdir ?= $(prefix)/lib -bindir ?= $(prefix)/bin -libexecdir ?= $(prefix)/libexec -datadir ?= $(prefix)/share -localstatedir ?= $(prefix)/var -sysconfdir ?= $(prefix)/etc -mandir ?= $(prefix)/share/man - -DESTDIR ?= diff --git a/mk/install.mk b/mk/install.mk deleted file mode 100644 index dad0fd853..000000000 --- a/mk/install.mk +++ /dev/null @@ -1,62 +0,0 @@ -# Add a rule for creating $(1) as a directory. This template may be -# called multiple times for the same directory. -define create-dir - _i := $$(call add-trailing-slash, $(DESTDIR)$$(strip $(1))) - ifndef $$(_i)_SEEN - $$(_i)_SEEN = 1 - $$(_i): - $$(trace-mkdir) install -d "$$@" - endif -endef - - -# Add a rule for installing file $(1) as file $(2) with mode $(3). -# The directory containing $(2) will be created automatically. -define install-file-as - - _i := $(DESTDIR)$$(strip $(2)) - - install: $$(_i) - - $$(_i): $(1) | $$(dir $$(_i)) - $$(trace-install) install -m $(3) $(1) "$$@" - - $$(eval $$(call create-dir, $$(dir $(2)))) - -endef - - -# Add a rule for installing file $(1) in directory $(2) with mode -# $(3). The directory will be created automatically. -define install-file-in - $$(eval $$(call install-file-as,$(1),$(2)/$$(notdir $(1)),$(3))) -endef - - -define install-program-in - $$(eval $$(call install-file-in,$(1),$(2),0755)) -endef - - -define install-data-in - $$(eval $$(call install-file-in,$(1),$(2),0644)) -endef - - -# Install a symlink from $(2) to $(1). Note that $(1) need not exist. -define install-symlink - - _i := $(DESTDIR)$$(strip $(2)) - - install: $$(_i) - - $$(_i): | $$(dir $$(_i)) - $$(trace-install) ln -sfn $(1) "$$@" - - $$(eval $$(call create-dir, $$(dir $(2)))) - -endef - - -print-top-help += \ - echo " install: Install into \$$(prefix) (currently set to '$(prefix)')"; diff --git a/mk/lib.mk b/mk/lib.mk deleted file mode 100644 index 1e7af6ad5..000000000 --- a/mk/lib.mk +++ /dev/null @@ -1,159 +0,0 @@ -default: all - - -# Get rid of default suffixes. FIXME: is this a good idea? -.SUFFIXES: - - -# Initialise some variables. -bin-scripts := -noinst-scripts := -man-pages := -install-tests := -install-tests-groups := - -include mk/platform.mk - -# Hack to define a literal space. -space := -space += - - -# Hack to define a literal newline. -define newline - - -endef - - -# Pass -fPIC if we're building dynamic libraries. -BUILD_SHARED_LIBS ?= 1 - -ifeq ($(BUILD_SHARED_LIBS), 1) - ifdef HOST_CYGWIN - GLOBAL_CFLAGS += -U__STRICT_ANSI__ -D_GNU_SOURCE - GLOBAL_CXXFLAGS += -U__STRICT_ANSI__ -D_GNU_SOURCE - else - GLOBAL_CFLAGS += -fPIC - GLOBAL_CXXFLAGS += -fPIC - endif - ifndef HOST_DARWIN - ifndef HOST_SOLARIS - ifndef HOST_FREEBSD - GLOBAL_LDFLAGS += -Wl,--no-copy-dt-needed-entries - endif - endif - endif - SET_RPATH_TO_LIBS ?= 1 -endif - -# Pass -g if we want debug info. -BUILD_DEBUG ?= 1 - -ifeq ($(BUILD_DEBUG), 1) - GLOBAL_CFLAGS += -g - GLOBAL_CXXFLAGS += -g -endif - - -include mk/build-dir.mk -include mk/install-dirs.mk -include mk/functions.mk -include mk/tracing.mk -include mk/clean.mk -include mk/install.mk -include mk/libraries.mk -include mk/programs.mk -include mk/patterns.mk -include mk/templates.mk -include mk/cxx-big-literal.mk -include mk/tests.mk -include mk/compilation-database.mk - - -# Include all sub-Makefiles. -define include-sub-makefile - d := $$(patsubst %/,%,$$(dir $(1))) - include $(1) -endef - -$(foreach mf, $(makefiles), $(eval $(call include-sub-makefile,$(mf)))) - - -# Instantiate stuff. -$(foreach lib, $(libraries), $(eval $(call build-library,$(lib)))) -$(foreach prog, $(programs), $(eval $(call build-program,$(prog)))) -$(foreach script, $(bin-scripts), $(eval $(call install-program-in,$(script),$(bindir)))) -$(foreach script, $(bin-scripts), $(eval programs-list += $(script))) -$(foreach script, $(noinst-scripts), $(eval programs-list += $(script))) -$(foreach template, $(template-files), $(eval $(call instantiate-template,$(template)))) -$(foreach test, $(install-tests), \ - $(eval $(call run-test,$(test))) \ - $(eval installcheck: $(test).test)) -$(foreach test-group, $(install-tests-groups), \ - $(eval $(call run-test-group,$(test-group))) \ - $(eval installcheck: $(test-group).test-group) \ - $(foreach test, $($(test-group)-tests), \ - $(eval $(call run-test,$(test))) \ - $(eval $(test-group).test-group: $(test).test))) - -# Compilation database. -$(foreach lib, $(libraries), $(eval $(call write-compile-commands,$(lib)))) -$(foreach prog, $(programs), $(eval $(call write-compile-commands,$(prog)))) - -compile_commands.json: $(compile-commands-json-files) - @jq --slurp '.' $^ >$@ - -# Include makefiles requiring built programs. -$(foreach mf, $(makefiles-late), $(eval $(call include-sub-makefile,$(mf)))) - - -$(foreach file, $(man-pages), $(eval $(call install-data-in, $(file), $(mandir)/man$(patsubst .%,%,$(suffix $(file)))))) - - -.PHONY: default all man help - -all: $(programs-list) $(libs-list) $(man-pages) - -man: $(man-pages) - - -help: - @echo "The following targets are available:" - @echo "" - @echo " default: Build default targets" -ifdef man-pages - @echo " man: Generate manual pages" -endif - @$(print-top-help) -ifdef programs-list - @echo "" - @echo "The following programs can be built:" - @echo "" - @for i in $(programs-list); do echo " $$i"; done -endif -ifdef libs-list - @echo "" - @echo "The following libraries can be built:" - @echo "" - @for i in $(libs-list); do echo " $$i"; done -endif -ifdef install-tests-groups - @echo "" - @echo "The following groups of functional tests can be run:" - @echo "" - @for i in $(install-tests-groups); do echo " $$i.test-group"; done - @echo "" - @echo "(installcheck includes tests in test groups too.)" -endif - @echo "" - @echo "The following variables control the build:" - @echo "" - @echo " BUILD_SHARED_LIBS ($(BUILD_SHARED_LIBS)): Whether to build shared libraries" - @echo " BUILD_DEBUG ($(BUILD_DEBUG)): Whether to include debug symbols" - @echo " CC ($(CC)): C compiler to be used" - @echo " CFLAGS: Flags for the C compiler" - @echo " CXX ($(CXX)): C++ compiler to be used" - @echo " CXXFLAGS: Flags for the C++ compiler" - @echo " CPPFLAGS: C preprocessor flags, used for both CC and CXX" - @$(print-var-help) diff --git a/mk/libraries.mk b/mk/libraries.mk deleted file mode 100644 index a7848ba35..000000000 --- a/mk/libraries.mk +++ /dev/null @@ -1,173 +0,0 @@ -libs-list := - -ifdef HOST_DARWIN - SO_EXT = dylib -else - ifdef HOST_WINDOWS - SO_EXT = dll - else - SO_EXT = so - endif -endif - -ifdef HOST_UNIX - THREAD_LDFLAGS = -pthread -else - THREAD_LDFLAGS = -endif - -# Build a library with symbolic name $(1). The library is defined by -# various variables prefixed by ‘$(1)_’: -# -# - $(1)_NAME: the name of the library (e.g. ‘libfoo’); defaults to -# $(1). -# -# - $(1)_DIR: the directory where the (non-installed) library will be -# placed. -# -# - $(1)_SOURCES: the source files of the library. -# -# - $(1)_CFLAGS: additional C compiler flags. -# -# - $(1)_CXXFLAGS: additional C++ compiler flags. -# -# - $(1)_ORDER_AFTER: a set of targets on which the object files of -# this libraries will have an order-only dependency. -# -# - $(1)_LIBS: the symbolic names of other libraries on which this -# library depends. -# -# - $(1)_ALLOW_UNDEFINED: if set, the library is allowed to have -# undefined symbols. Has no effect for static libraries. -# -# - $(1)_LDFLAGS: additional linker flags. -# -# - $(1)_LDFLAGS_PROPAGATED: additional linker flags, also propagated -# to the linking of programs/libraries that use this library. -# -# - $(1)_FORCE_INSTALL: if defined, the library will be installed even -# if it's not needed (i.e. dynamically linked) by a program. -# -# - $(1)_INSTALL_DIR: the directory where the library will be -# installed. Defaults to $(libdir). -# -# - $(1)_EXCLUDE_FROM_LIBRARY_LIST: if defined, the library will not -# be automatically marked as a dependency of the top-level all -# target andwill not be listed in the make help output. This is -# useful for libraries built solely for testing, for example. -# -# - BUILD_SHARED_LIBS: if equal to ‘1’, a dynamic library will be -# built, otherwise a static library. -define build-library - $(1)_NAME ?= $(1) - _d := $(buildprefix)$$(strip $$($(1)_DIR)) - _srcs := $$(sort $$(foreach src, $$($(1)_SOURCES), $$(src))) - $(1)_OBJS := $$(addprefix $(buildprefix), $$(addsuffix .o, $$(basename $$(_srcs)))) - _libs := $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_PATH)) - - ifdef HOST_WINDOWS - $(1)_INSTALL_DIR ?= $$(bindir) - else - $(1)_INSTALL_DIR ?= $$(libdir) - endif - - $(1)_LDFLAGS_USE := - $(1)_LDFLAGS_USE_INSTALLED := - $(1)_LIB_CLOSURE := $(1) - - $$(eval $$(call create-dir, $$(_d))) - - ifeq ($(BUILD_SHARED_LIBS), 1) - - ifdef $(1)_ALLOW_UNDEFINED - ifdef HOST_DARWIN - $(1)_LDFLAGS += -undefined suppress -flat_namespace - endif - else - ifndef HOST_DARWIN - ifndef HOST_WINDOWS - ifndef HOST_OPENBSD - $(1)_LDFLAGS += -Wl,-z,defs - endif - endif - endif - endif - - ifndef HOST_DARWIN - $(1)_LDFLAGS += -Wl,-soname=$$($(1)_NAME).$(SO_EXT) - endif - - $(1)_PATH := $$(_d)/$$($(1)_NAME).$(SO_EXT) - - $$($(1)_PATH): $$($(1)_OBJS) $$(_libs) | $$(_d)/ - +$$(trace-ld) $(CXX) -o $$(abspath $$@) -shared $$(LDFLAGS) $$(GLOBAL_LDFLAGS) $$($(1)_OBJS) $$($(1)_LDFLAGS) $$($(1)_LDFLAGS_PROPAGATED) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_LDFLAGS_USE)) $$($(1)_LDFLAGS_UNINSTALLED) - - ifndef HOST_DARWIN - $(1)_LDFLAGS_USE += -Wl,-rpath,$$(abspath $$(_d)) - endif - $(1)_LDFLAGS_USE += -L$$(_d) -l$$(patsubst lib%,%,$$(strip $$($(1)_NAME))) - - $(1)_INSTALL_PATH := $(DESTDIR)$$($(1)_INSTALL_DIR)/$$($(1)_NAME).$(SO_EXT) - - _libs_final := $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_INSTALL_PATH)) - - $$(eval $$(call create-dir, $$($(1)_INSTALL_DIR))) - - $$($(1)_INSTALL_PATH): $$($(1)_OBJS) $$(_libs_final) | $(DESTDIR)$$($(1)_INSTALL_DIR)/ - +$$(trace-ld) $(CXX) -o $$@ -shared $$(LDFLAGS) $$(GLOBAL_LDFLAGS) $$($(1)_OBJS) $$($(1)_LDFLAGS) $$($(1)_LDFLAGS_PROPAGATED) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_LDFLAGS_USE_INSTALLED)) - - $(1)_LDFLAGS_USE_INSTALLED += -L$$(DESTDIR)$$($(1)_INSTALL_DIR) -l$$(patsubst lib%,%,$$(strip $$($(1)_NAME))) - ifndef HOST_DARWIN - ifeq ($(SET_RPATH_TO_LIBS), 1) - $(1)_LDFLAGS_USE_INSTALLED += -Wl,-rpath,$$($(1)_INSTALL_DIR) - else - $(1)_LDFLAGS_USE_INSTALLED += -Wl,-rpath-link,$$($(1)_INSTALL_DIR) - endif - endif - - ifdef $(1)_FORCE_INSTALL - install: $$($(1)_INSTALL_PATH) - endif - - else - - $(1)_PATH := $$(_d)/$$($(1)_NAME).a - - $$($(1)_PATH): $$($(1)_OBJS) | $$(_d)/ - $$(trace-ld) $(LD) $$(ifndef $(HOST_DARWIN),-U) -r -o $$(_d)/$$($(1)_NAME).o $$^ - $$(trace-ar) $(AR) crs $$@ $$(_d)/$$($(1)_NAME).o - - $(1)_LDFLAGS_USE += $$($(1)_PATH) $$($(1)_LDFLAGS) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_LDFLAGS_USE)) - - $(1)_INSTALL_PATH := $$(libdir)/$$($(1)_NAME).a - - $(1)_LIB_CLOSURE += $$($(1)_LIBS) - - endif - - $(1)_LDFLAGS_USE += $$($(1)_LDFLAGS_PROPAGATED) - $(1)_LDFLAGS_USE_INSTALLED += $$($(1)_LDFLAGS_PROPAGATED) - - # Propagate CFLAGS and CXXFLAGS to the individual object files. - $$(foreach obj, $$($(1)_OBJS), $$(eval $$(obj)_CFLAGS=$$($(1)_CFLAGS))) - $$(foreach obj, $$($(1)_OBJS), $$(eval $$(obj)_CXXFLAGS=$$($(1)_CXXFLAGS))) - - # Make each object file depend on the common dependencies. - $$(foreach obj, $$($(1)_OBJS), $$(eval $$(obj): $$($(1)_COMMON_DEPS) $$(GLOBAL_COMMON_DEPS))) - - # Make each object file have order-only dependencies on the common - # order-only dependencies. This includes the order-only dependencies - # of libraries we're depending on. - $(1)_ORDER_AFTER_CLOSED = $$($(1)_ORDER_AFTER) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_ORDER_AFTER_CLOSED)) - - $$(foreach obj, $$($(1)_OBJS), $$(eval $$(obj): | $$($(1)_ORDER_AFTER_CLOSED) $$(GLOBAL_ORDER_AFTER))) - - # Include .dep files, if they exist. - $(1)_DEPS := $$(foreach fn, $$($(1)_OBJS), $$(call filename-to-dep, $$(fn))) - -include $$($(1)_DEPS) - - ifndef $(1)_EXCLUDE_FROM_LIBRARY_LIST - libs-list += $$($(1)_PATH) - endif - clean-files += $$(_d)/*.a $$(_d)/*.$(SO_EXT) $$(_d)/*.o $$(_d)/.*.dep $$($(1)_DEPS) $$($(1)_OBJS) -endef diff --git a/mk/patterns.mk b/mk/patterns.mk deleted file mode 100644 index 4caa2039e..000000000 --- a/mk/patterns.mk +++ /dev/null @@ -1,41 +0,0 @@ - -# These are the complete command lines we use to compile C and C++ files. -# - $< is the source file. -# - $1 is the object file to create. -CC_CMD=$(CC) -o $1 -c $< $(CPPFLAGS) $(GLOBAL_CFLAGS) $(CFLAGS) $($1_CFLAGS) -MMD -MF $(call filename-to-dep,$1) -MP -CXX_CMD=$(CXX) -o $1 -c $< $(CPPFLAGS) $(GLOBAL_CXXFLAGS_PCH) $(GLOBAL_CXXFLAGS) $(CXXFLAGS) $($1_CXXFLAGS) $(ERROR_SWITCH_ENUM) -MMD -MF $(call filename-to-dep,$1) -MP - -# We use COMPILE_COMMANDS_JSON_CMD to turn a compilation command (like CC_CMD -# or CXX_CMD above) into a comple_commands.json file. We rely on bash native -# word splitting to define the positional arguments. -# - $< is the source file being compiled. -COMPILE_COMMANDS_JSON_CMD=jq --null-input '{ directory: $$ENV.PWD, file: "$<", arguments: $$ARGS.positional }' --args -- - - -$(buildprefix)%.o: %.cc - @mkdir -p "$(dir $@)" - $(trace-cxx) $(call CXX_CMD,$@) - -$(buildprefix)%.o: %.cpp - @mkdir -p "$(dir $@)" - $(trace-cxx) $(call CXX_CMD,$@) - -$(buildprefix)%.o: %.c - @mkdir -p "$(dir $@)" - $(trace-cc) $(call CC_CMD,$@) - -# In the following we need to replace the .compile_commands.json extension in $@ with .o -# to make the object file. This is needed because CC_CMD and CXX_CMD do further expansions -# based on the object file name (i.e. *_CXXFLAGS and filename-to-dep). - -$(buildprefix)%.compile_commands.json: %.cc - @mkdir -p "$(dir $@)" - $(trace-jq) $(COMPILE_COMMANDS_JSON_CMD) $(call CXX_CMD,$(@:.compile_commands.json=.o)) > $@ - -$(buildprefix)%.compile_commands.json: %.cpp - @mkdir -p "$(dir $@)" - $(trace-jq) $(COMPILE_COMMANDS_JSON_CMD) $(call CXX_CMD,$(@:.compile_commands.json=.o)) > $@ - -$(buildprefix)%.compile_commands.json: %.c - @mkdir -p "$(dir $@)" - $(trace-jq) $(COMPILE_COMMANDS_JSON_CMD) $(call CC_CMD,$(@:.compile_commands.json=.o)) > $@ diff --git a/mk/platform.mk b/mk/platform.mk deleted file mode 100644 index 3c4fff780..000000000 --- a/mk/platform.mk +++ /dev/null @@ -1,40 +0,0 @@ -ifdef HOST_OS - HOST_KERNEL = $(firstword $(subst -, ,$(HOST_OS))) - ifeq ($(patsubst mingw%,,$(HOST_KERNEL)),) - HOST_MINGW = 1 - HOST_WINDOWS = 1 - endif - ifeq ($(HOST_KERNEL), cygwin) - HOST_CYGWIN = 1 - HOST_WINDOWS = 1 - HOST_UNIX = 1 - endif - ifeq ($(patsubst darwin%,,$(HOST_KERNEL)),) - HOST_DARWIN = 1 - HOST_UNIX = 1 - endif - ifeq ($(patsubst freebsd%,,$(HOST_KERNEL)),) - HOST_FREEBSD = 1 - HOST_UNIX = 1 - endif - ifeq ($(patsubst netbsd%,,$(HOST_KERNEL)),) - HOST_NETBSD = 1 - HOST_UNIX = 1 - endif - ifeq ($(patsubst openbsd%,,$(HOST_KERNEL)),) - HOST_OPENBSD = 1 - HOST_UNIX = 1 - endif - ifeq ($(HOST_KERNEL), linux) - HOST_LINUX = 1 - HOST_UNIX = 1 - endif - ifeq ($(patsubst solaris%,,$(HOST_KERNEL)),) - HOST_SOLARIS = 1 - HOST_UNIX = 1 - endif - ifeq ($(HOST_KERNEL), gnu) - HOST_HURD = 1 - HOST_UNIX = 1 - endif -endif diff --git a/mk/precompiled-headers.mk b/mk/precompiled-headers.mk deleted file mode 100644 index f2803eb79..000000000 --- a/mk/precompiled-headers.mk +++ /dev/null @@ -1,21 +0,0 @@ -PRECOMPILE_HEADERS ?= 0 - -print-var-help += \ - echo " PRECOMPILE_HEADERS ($(PRECOMPILE_HEADERS)): Whether to use precompiled headers to speed up the build"; - -GCH = $(buildprefix)precompiled-headers.h.gch - -$(GCH): precompiled-headers.h - @rm -f $@ - @mkdir -p "$(dir $@)" - $(trace-gen) $(CXX) -c -x c++-header -o $@ $< $(GLOBAL_CXXFLAGS) $(GCH_CXXFLAGS) - -clean-files += $(GCH) - -ifeq ($(PRECOMPILE_HEADERS), 1) - - GLOBAL_CXXFLAGS_PCH += -include $(buildprefix)precompiled-headers.h -Winvalid-pch - - GLOBAL_ORDER_AFTER += $(GCH) - -endif diff --git a/mk/programs.mk b/mk/programs.mk deleted file mode 100644 index 623caaf55..000000000 --- a/mk/programs.mk +++ /dev/null @@ -1,98 +0,0 @@ -programs-list := - -ifdef HOST_WINDOWS - EXE_EXT = .exe -else - EXE_EXT = -endif - -# Build a program with symbolic name $(1). The program is defined by -# various variables prefixed by ‘$(1)_’: -# -# - $(1)_NAME: the name of the program (e.g. ‘foo’); defaults to -# $(1). -# -# - $(1)_DIR: the directory where the (non-installed) program will be -# placed. -# -# - $(1)_SOURCES: the source files of the program. -# -# - $(1)_CFLAGS: additional C compiler flags. -# -# - $(1)_CXXFLAGS: additional C++ compiler flags. -# -# - $(1)_ORDER_AFTER: a set of targets on which the object files of -# this program will have an order-only dependency. -# -# - $(1)_LIBS: the symbolic names of libraries on which this program -# depends. -# -# - $(1)_LDFLAGS: additional linker flags. -# -# - $(1)_INSTALL_DIR: the directory where the program will be -# installed; defaults to $(bindir). -define build-program - $(1)_NAME ?= $(1) - _d := $(buildprefix)$$($(1)_DIR) - _srcs := $$(sort $$(foreach src, $$($(1)_SOURCES), $$(src))) - $(1)_OBJS := $$(addprefix $(buildprefix), $$(addsuffix .o, $$(basename $$(_srcs)))) - _libs := $$(foreach lib, $$($(1)_LIBS), $$(foreach lib2, $$($$(lib)_LIB_CLOSURE), $$($$(lib2)_PATH))) - $(1)_PATH := $$(_d)/$$($(1)_NAME)$(EXE_EXT) - - $$(eval $$(call create-dir, $$(_d))) - - $$($(1)_PATH): $$($(1)_OBJS) $$(_libs) | $$(_d)/ - +$$(trace-ld) $(CXX) -o $$@ $$(LDFLAGS) $$(GLOBAL_LDFLAGS) $$($(1)_OBJS) $$($(1)_LDFLAGS) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_LDFLAGS_USE)) - - $(1)_INSTALL_DIR ?= $$(bindir) - - ifdef $(1)_INSTALL_DIR - - $(1)_INSTALL_PATH := $$($(1)_INSTALL_DIR)/$$($(1)_NAME)$(EXE_EXT) - - $$(eval $$(call create-dir, $$($(1)_INSTALL_DIR))) - - install: $(DESTDIR)$$($(1)_INSTALL_PATH) - - ifeq ($(BUILD_SHARED_LIBS), 1) - - _libs_final := $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_INSTALL_PATH)) - - $(DESTDIR)$$($(1)_INSTALL_PATH): $$($(1)_OBJS) $$(_libs_final) | $(DESTDIR)$$($(1)_INSTALL_DIR)/ - +$$(trace-ld) $(CXX) -o $$@ $$(LDFLAGS) $$(GLOBAL_LDFLAGS) $$($(1)_OBJS) $$($(1)_LDFLAGS) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_LDFLAGS_USE_INSTALLED)) - - else - - $(DESTDIR)$$($(1)_INSTALL_PATH): $$($(1)_PATH) | $(DESTDIR)$$($(1)_INSTALL_DIR)/ - +$$(trace-install) install -t $(DESTDIR)$$($(1)_INSTALL_DIR) $$< - - endif - endif - - # Propagate CFLAGS and CXXFLAGS to the individual object files. - $$(foreach obj, $$($(1)_OBJS), $$(eval $$(obj)_CFLAGS=$$($(1)_CFLAGS))) - $$(foreach obj, $$($(1)_OBJS), $$(eval $$(obj)_CXXFLAGS=$$($(1)_CXXFLAGS))) - - # Make each object file depend on the common dependencies. - $$(foreach obj, $$($(1)_OBJS), $$(eval $$(obj): $$($(1)_COMMON_DEPS) $$(GLOBAL_COMMON_DEPS))) - - # Make each object file have order-only dependencies on the common - # order-only dependencies. This includes the order-only dependencies - # of libraries we're depending on. - $(1)_ORDER_AFTER_CLOSED = $$($(1)_ORDER_AFTER) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_ORDER_AFTER_CLOSED)) - - $$(foreach obj, $$($(1)_OBJS), $$(eval $$(obj): | $$($(1)_ORDER_AFTER_CLOSED) $$(GLOBAL_ORDER_AFTER))) - - # Include .dep files, if they exist. - $(1)_DEPS := $$(foreach fn, $$($(1)_OBJS), $$(call filename-to-dep, $$(fn))) - -include $$($(1)_DEPS) - - programs-list += $$($(1)_PATH) - clean-files += $$($(1)_PATH) $$(_d)/*.o $$(_d)/.*.dep $$($(1)_DEPS) $$($(1)_OBJS) - - # Phony target to run this program (typically as a dependency of 'check'). - .PHONY: $(1)_RUN - $(1)_RUN: $$($(1)_PATH) - $(trace-test) $$($(1)_ENV) $$($(1)_PATH) - -endef diff --git a/mk/run-test.sh b/mk/run-test.sh deleted file mode 100755 index 7f9f1d5f8..000000000 --- a/mk/run-test.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env bash - -set -eu -o pipefail - -red="" -green="" -yellow="" -normal="" - -test=$1 - -dir="$(dirname "${BASH_SOURCE[0]}")" -source "$dir/common-test.sh" - -post_run_msg="ran test $test..." -if [ -t 1 ]; then - red="" - green="" - yellow="" - normal="" -fi - -run_test () { - log="$(run "$test" 2>&1)" && status=0 || status=$? -} - -run_test - -if [[ "$status" = 0 ]]; then - echo "$post_run_msg [${green}PASS$normal]" -elif [[ "$status" = 77 ]]; then - echo "$post_run_msg [${yellow}SKIP$normal]" -else - echo "$post_run_msg [${red}FAIL$normal]" - # shellcheck disable=SC2001 - echo "$log" | sed 's/^/ /' - exit "$status" -fi diff --git a/mk/templates.mk b/mk/templates.mk deleted file mode 100644 index d5dae61c7..000000000 --- a/mk/templates.mk +++ /dev/null @@ -1,19 +0,0 @@ -template-files := - -# Create the file $(1) from $(1).in by running config.status (which -# substitutes all ‘@var@’ variables set by the configure script). -define instantiate-template - - clean-files += $(1) - -endef - -ifneq ($(MAKECMDGOALS), clean) - -$(buildprefix)%.h: %.h.in $(buildprefix)config.status - $(trace-gen) rm -f $@ && cd $(buildprefixrel) && ./config.status --quiet --header=$(@:$(buildprefix)%=%) - -$(buildprefix)%: %.in $(buildprefix)config.status - $(trace-gen) rm -f $@ && cd $(buildprefixrel) && ./config.status --quiet --file=$(@:$(buildprefix)%=%) - -endif diff --git a/mk/tests.mk b/mk/tests.mk deleted file mode 100644 index 0a10f6d3b..000000000 --- a/mk/tests.mk +++ /dev/null @@ -1,30 +0,0 @@ -# Run program $1 as part of ‘make installcheck’. - -test-deps = - -define run-bash - - .PHONY: $1 - $1: $2 - @env BASH=$(bash) $(bash) $3 < /dev/null - -endef - -define run-test - - $(eval $(call run-bash,$1.test,$1 $(test-deps),mk/run-test.sh $1)) - $(eval $(call run-bash,$1.test-debug,$1 $(test-deps),mk/debug-test.sh $1)) - -endef - -define run-test-group - - .PHONY: $1.test-group - -endef - -.PHONY: check installcheck - -print-top-help += \ - echo " check: Run unit tests"; \ - echo " installcheck: Run functional tests"; diff --git a/mk/tracing.mk b/mk/tracing.mk deleted file mode 100644 index 09db1e617..000000000 --- a/mk/tracing.mk +++ /dev/null @@ -1,18 +0,0 @@ -V ?= 0 - -ifeq ($(V), 0) - - trace-gen = @echo " GEN " $@; - trace-cc = @echo " CC " $@; - trace-cxx = @echo " CXX " $@; - trace-ld = @echo " LD " $@; - trace-ar = @echo " AR " $@; - trace-install = @echo " INST " $@; - trace-mkdir = @echo " MKDIR " $@; - trace-test = @echo " TEST " $@; - trace-sh = @echo " SH " $@; - trace-jq = @echo " JQ " $@; - - suppress = @ - -endif diff --git a/package.nix b/package.nix deleted file mode 100644 index 8cbe325e9..000000000 --- a/package.nix +++ /dev/null @@ -1,366 +0,0 @@ -{ lib -, stdenv -, releaseTools -, autoconf-archive -, autoreconfHook -, aws-sdk-cpp -, boehmgc -, nlohmann_json -, bison -, boost -, brotli -, bzip2 -, curl -, editline -, readline -, flex -, git -, gtest -, jq -, libarchive -, libcpuid -, libgit2 -, libseccomp -, libsodium -, man -, darwin -, lowdown -, mdbook -, mdbook-linkcheck -, mercurial -, openssh -, openssl -, pkg-config -, rapidcheck -, sqlite -, toml11 -, unixtools -, xz - -, busybox-sandbox-shell ? null - -# Configuration Options -#: -# This probably seems like too many degrees of freedom, but it -# faithfully reflects how the underlying configure + make build system -# work. The top-level flake.nix will choose useful combinations of these -# options to CI. - -, pname ? "nix" - -, version -, versionSuffix - -# Whether to build Nix. Useful to skip for tasks like testing existing pre-built versions of Nix -, doBuild ? true - -# Run the unit tests as part of the build. See `installUnitTests` for an -# alternative to this. -, doCheck ? __forDefaults.canRunInstalled - -# Run the functional tests as part of the build. -, doInstallCheck ? test-client != null || __forDefaults.canRunInstalled - -# Check test coverage of Nix. Probably want to use with at least -# one of `doCHeck` or `doInstallCheck` enabled. -, withCoverageChecks ? false - -# Whether to build the regular manual -, enableManual ? __forDefaults.canRunInstalled - -# Whether to use garbage collection for the Nix language evaluator. -# -# If it is disabled, we just leak memory, but this is not as bad as it -# sounds so long as evaluation just takes places within short-lived -# processes. (When the process exits, the memory is reclaimed; it is -# only leaked *within* the process.) -# -# Temporarily disabled on Windows because the `GC_throw_bad_alloc` -# symbol is missing during linking. -# -# Disabled on OpenBSD because of missing `_data_start` symbol while linking -, enableGC ? !stdenv.hostPlatform.isWindows && !stdenv.hostPlatform.isOpenBSD - -# Whether to enable Markdown rendering in the Nix binary. -, enableMarkdown ? !stdenv.hostPlatform.isWindows - -# Which interactive line editor library to use for Nix's repl. -# -# Currently supported choices are: -# -# - editline (default) -# - readline -, readlineFlavor ? if stdenv.hostPlatform.isWindows then "readline" else "editline" - -# Whether to install unit tests. This is useful when cross compiling -# since we cannot run them natively during the build, but can do so -# later. -, installUnitTests ? doBuild && !__forDefaults.canExecuteHost - -# For running the functional tests against a pre-built Nix. Probably -# want to use in conjunction with `doBuild = false;`. -, test-daemon ? null -, test-client ? null - -# Avoid setting things that would interfere with a functioning devShell -, forDevShell ? false - -# Not a real argument, just the only way to approximate let-binding some -# stuff for argument defaults. -, __forDefaults ? { - canExecuteHost = stdenv.buildPlatform.canExecute stdenv.hostPlatform; - canRunInstalled = doBuild && __forDefaults.canExecuteHost; - } -}: - -let - inherit (lib) fileset; - - # selected attributes with defaults, will be used to define some - # things which should instead be gotten via `finalAttrs` in order to - # work with overriding. - attrs = { - inherit doBuild doCheck doInstallCheck; - }; - - mkDerivation = - if withCoverageChecks - then - # TODO support `finalAttrs` args function in - # `releaseTools.coverageAnalysis`. - argsFun: - releaseTools.coverageAnalysis (let args = argsFun args; in args) - else stdenv.mkDerivation; -in - -mkDerivation (finalAttrs: let - - inherit (finalAttrs) - doCheck - doInstallCheck - ; - - doBuild = !finalAttrs.dontBuild; - - # Either running the unit tests during the build, or installing them - # to be run later, requiresthe unit tests to be built. - buildUnitTests = doCheck || installUnitTests; - -in { - inherit pname version; - - src = - let - baseFiles = fileset.fileFilter (f: f.name != ".gitignore") ./.; - in - fileset.toSource { - root = ./.; - fileset = fileset.intersection baseFiles (fileset.unions ([ - # For configure - ./.version - ./configure.ac - ./m4 - # TODO: do we really need README.md? It doesn't seem used in the build. - ./README.md - # This could be put behind a conditional - ./maintainers/local.mk - # For make, regardless of what we are building - ./local.mk - ./Makefile - ./Makefile.config.in - ./mk - (fileset.fileFilter (f: lib.strings.hasPrefix "nix-profile" f.name) ./scripts) - ] ++ lib.optionals doBuild [ - ./doc - ./misc - ./precompiled-headers.h - (fileset.difference ./src ./src/perl) - ./COPYING - ./scripts/local.mk - ] ++ lib.optionals enableManual [ - ./doc/manual - ] ++ lib.optionals doInstallCheck [ - ./tests/functional - ])); - }; - - VERSION_SUFFIX = versionSuffix; - - outputs = [ "out" ] - ++ lib.optional doBuild "dev" - # If we are doing just build or just docs, the one thing will use - # "out". We only need additional outputs if we are doing both. - ++ lib.optional (doBuild && enableManual) "doc" - ++ lib.optional installUnitTests "check" - ++ lib.optional doCheck "testresults" - ; - - nativeBuildInputs = [ - autoconf-archive - autoreconfHook - pkg-config - ] ++ lib.optionals doBuild [ - bison - flex - ] ++ lib.optionals enableManual [ - (lib.getBin lowdown) - mdbook - mdbook-linkcheck - ] ++ lib.optionals doInstallCheck [ - git - mercurial - openssh - ] ++ lib.optionals (doInstallCheck || enableManual) [ - jq # Also for custom mdBook preprocessor. - ] ++ lib.optionals enableManual [ - man - ] ++ lib.optional stdenv.hostPlatform.isStatic unixtools.hexdump - ; - - buildInputs = lib.optionals doBuild ( - [ - brotli - bzip2 - curl - libarchive - libgit2 - libsodium - openssl - sqlite - toml11 - xz - ({ inherit readline editline; }.${readlineFlavor}) - ] ++ lib.optionals enableMarkdown [ - lowdown - ] ++ lib.optionals buildUnitTests [ - gtest - rapidcheck - ] ++ lib.optional stdenv.isLinux libseccomp - ++ lib.optional stdenv.hostPlatform.isDarwin darwin.apple_sdk.libs.sandbox - ++ lib.optional stdenv.hostPlatform.isx86_64 libcpuid - # There have been issues building these dependencies - ++ lib.optional (stdenv.hostPlatform == stdenv.buildPlatform && (stdenv.isLinux || stdenv.isDarwin)) - aws-sdk-cpp - ); - - propagatedBuildInputs = lib.optionals doBuild ([ - boost - nlohmann_json - ] ++ lib.optional enableGC boehmgc - ); - - dontBuild = !attrs.doBuild; - doCheck = attrs.doCheck; - - configureFlags = [ - (lib.enableFeature doBuild "build") - (lib.enableFeature buildUnitTests "unit-tests") - (lib.enableFeature doInstallCheck "functional-tests") - (lib.enableFeature enableManual "doc-gen") - (lib.enableFeature enableGC "gc") - (lib.enableFeature enableMarkdown "markdown") - (lib.enableFeature installUnitTests "install-unit-tests") - (lib.withFeatureAs true "readline-flavor" readlineFlavor) - ] ++ lib.optionals (!forDevShell) [ - "--sysconfdir=/etc" - ] ++ lib.optionals installUnitTests [ - "--with-check-bin-dir=${builtins.placeholder "check"}/bin" - "--with-check-lib-dir=${builtins.placeholder "check"}/lib" - ] ++ lib.optionals (doBuild) [ - "--with-boost=${boost}/lib" - ] ++ lib.optionals (doBuild && stdenv.isLinux) [ - "--with-sandbox-shell=${busybox-sandbox-shell}/bin/busybox" - ] ++ lib.optional (doBuild && stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) - "LDFLAGS=-fuse-ld=gold" - ++ lib.optional (doBuild && stdenv.hostPlatform.isStatic) "--enable-embedded-sandbox-shell" - ; - - enableParallelBuilding = true; - - makeFlags = "profiledir=$(out)/etc/profile.d PRECOMPILE_HEADERS=1"; - - preCheck = '' - mkdir $testresults - ''; - - installTargets = lib.optional doBuild "install"; - - installFlags = "sysconfdir=$(out)/etc"; - - # In this case we are probably just running tests, and so there isn't - # anything to install, we just make an empty directory to signify tests - # succeeded. - installPhase = if finalAttrs.installTargets != [] then null else '' - mkdir -p $out - ''; - - postInstall = lib.optionalString doBuild ( - lib.optionalString stdenv.hostPlatform.isStatic '' - mkdir -p $out/nix-support - echo "file binary-dist $out/bin/nix" >> $out/nix-support/hydra-build-products - '' - ) + lib.optionalString enableManual '' - mkdir -p ''${!outputDoc}/nix-support - echo "doc manual ''${!outputDoc}/share/doc/nix/manual" >> ''${!outputDoc}/nix-support/hydra-build-products - ''; - - # So the check output gets links for DLLs in the out output. - preFixup = lib.optionalString (stdenv.hostPlatform.isWindows && builtins.elem "check" finalAttrs.outputs) '' - ln -s "$check/lib/"*.dll "$check/bin" - ln -s "$out/bin/"*.dll "$check/bin" - ''; - - doInstallCheck = attrs.doInstallCheck; - - installCheckFlags = "sysconfdir=$(out)/etc"; - # Work around buggy detection in stdenv. - installCheckTarget = "installcheck"; - - # Work around weird bug where it doesn't think there is a Makefile. - installCheckPhase = if (!doBuild && doInstallCheck) then '' - runHook preInstallCheck - mkdir -p src/nix-channel - make installcheck -j$NIX_BUILD_CORES -l$NIX_BUILD_CORES - '' else null; - - # Needed for tests if we are not doing a build, but testing existing - # built Nix. - preInstallCheck = - lib.optionalString (! doBuild) '' - mkdir -p src/nix-channel - ''; - - separateDebugInfo = !stdenv.hostPlatform.isStatic; - - # TODO Always true after https://github.com/NixOS/nixpkgs/issues/318564 - strictDeps = !withCoverageChecks; - - hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie"; - - meta = { - platforms = lib.platforms.unix ++ lib.platforms.windows; - mainProgram = "nix"; - broken = !(lib.all (a: a) [ - # We cannot run or install unit tests if we don't build them or - # Nix proper (which they depend on). - (installUnitTests -> doBuild) - (doCheck -> doBuild) - # The build process for the manual currently requires extracting - # data from the Nix executable we are trying to document. - (enableManual -> doBuild) - ]); - }; - -} // lib.optionalAttrs withCoverageChecks { - lcovFilter = [ "*/boost/*" "*-tab.*" ]; - - hardeningDisable = ["fortify"]; - - NIX_CFLAGS_COMPILE = "-DCOVERAGE=1"; - - dontInstall = false; -} // lib.optionalAttrs (test-daemon != null) { - NIX_DAEMON_PACKAGE = test-daemon; -} // lib.optionalAttrs (test-client != null) { - NIX_CLIENT_PACKAGE = test-client; -}) diff --git a/packaging/components.nix b/packaging/components.nix index 5cc0be784..c29e04ae9 100644 --- a/packaging/components.nix +++ b/packaging/components.nix @@ -25,11 +25,6 @@ in version = baseVersion + versionSuffix; inherit versionSuffix; - nix = callPackage ../package.nix { - version = fineVersion; - versionSuffix = fineVersionSuffix; - }; - nix-util = callPackage ../src/libutil/package.nix { }; nix-util-c = callPackage ../src/libutil-c/package.nix { }; nix-util-test-support = callPackage ../src/libutil-test-support/package.nix { }; @@ -66,6 +61,5 @@ in nix-perl-bindings = callPackage ../src/perl/package.nix { }; - # Will replace `nix` once the old build system is gone. - nix-ng = callPackage ../packaging/everything.nix { }; + nix-everything = callPackage ../packaging/everything.nix { }; } diff --git a/packaging/dev-shell.nix b/packaging/dev-shell.nix index 15ce387a0..8ac17f61a 100644 --- a/packaging/dev-shell.nix +++ b/packaging/dev-shell.nix @@ -2,7 +2,7 @@ { pkgs }: -(pkgs.nix.override { forDevShell = true; }).overrideAttrs (attrs: +pkgs.nixComponents.nix-util.overrideAttrs (attrs: let stdenv = pkgs.nixDependencies.stdenv; diff --git a/packaging/hydra.nix b/packaging/hydra.nix index d01cdee68..3e5d4bbb2 100644 --- a/packaging/hydra.nix +++ b/packaging/hydra.nix @@ -32,7 +32,7 @@ let # convention to transpose it, and to transpose it efficiently, we need to # enumerate them manually, so that we don't evaluate unnecessary package sets. forAllPackages = lib.genAttrs [ - "nix" + "nix-everything" "nix-util" "nix-util-c" "nix-util-test-support" @@ -54,7 +54,6 @@ let "nix-cmd" "nix-cli" "nix-functional-tests" - "nix-ng" ]; in { @@ -180,7 +179,7 @@ in import (nixpkgs + "/lib/tests/test-with-nix.nix") { lib = nixpkgsFor.${system}.native.lib; - nix = self.packages.${system}.nix; + nix = self.packages.${system}.nix-cli; pkgs = nixpkgsFor.${system}.native; } ); diff --git a/scripts/local.mk b/scripts/local.mk deleted file mode 100644 index 46255e432..000000000 --- a/scripts/local.mk +++ /dev/null @@ -1,13 +0,0 @@ -nix_noinst_scripts := \ - $(d)/nix-profile.sh - -noinst-scripts += $(nix_noinst_scripts) - -profiledir = $(sysconfdir)/profile.d - -$(eval $(call install-file-as, $(d)/nix-profile.sh, $(profiledir)/nix.sh, 0644)) -$(eval $(call install-file-as, $(d)/nix-profile.fish, $(profiledir)/nix.fish, 0644)) -$(eval $(call install-file-as, $(d)/nix-profile-daemon.sh, $(profiledir)/nix-daemon.sh, 0644)) -$(eval $(call install-file-as, $(d)/nix-profile-daemon.fish, $(profiledir)/nix-daemon.fish, 0644)) - -clean-files += $(nix_noinst_scripts) diff --git a/src/libcmd/local.mk b/src/libcmd/local.mk deleted file mode 100644 index a270333f4..000000000 --- a/src/libcmd/local.mk +++ /dev/null @@ -1,15 +0,0 @@ -libraries += libcmd - -libcmd_NAME = libnixcmd - -libcmd_DIR := $(d) - -libcmd_SOURCES := $(wildcard $(d)/*.cc) - -libcmd_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libstore) $(INCLUDE_libfetchers) $(INCLUDE_libexpr) $(INCLUDE_libflake) $(INCLUDE_libmain) - -libcmd_LDFLAGS = $(EDITLINE_LIBS) $(LOWDOWN_LIBS) $(THREAD_LDFLAGS) - -libcmd_LIBS = libutil libstore libfetchers libflake libexpr libmain - -$(eval $(call install-file-in, $(buildprefix)$(d)/nix-cmd.pc, $(libdir)/pkgconfig, 0644)) diff --git a/src/libcmd/nix-cmd.pc.in b/src/libcmd/nix-cmd.pc.in deleted file mode 100644 index 39575f222..000000000 --- a/src/libcmd/nix-cmd.pc.in +++ /dev/null @@ -1,9 +0,0 @@ -prefix=@prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: Nix -Description: Nix Package Manager -Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lnixcmd -Cflags: -I${includedir}/nix -std=c++2a diff --git a/src/libexpr-c/local.mk b/src/libexpr-c/local.mk deleted file mode 100644 index 227a4095b..000000000 --- a/src/libexpr-c/local.mk +++ /dev/null @@ -1,25 +0,0 @@ -libraries += libexprc - -libexprc_NAME = libnixexprc - -libexprc_DIR := $(d) - -libexprc_SOURCES := \ - $(wildcard $(d)/*.cc) \ - -# Not just for this library itself, but also for downstream libraries using this library - -INCLUDE_libexprc := -I $(d) -libexprc_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libutilc) \ - $(INCLUDE_libfetchers) \ - $(INCLUDE_libstore) $(INCLUDE_libstorec) \ - $(INCLUDE_libexpr) $(INCLUDE_libexprc) - -libexprc_LIBS = libutil libutilc libstore libstorec libfetchers libexpr - -libexprc_LDFLAGS += $(THREAD_LDFLAGS) - -$(eval $(call install-file-in, $(d)/nix-expr-c.pc, $(libdir)/pkgconfig, 0644)) - -libexprc_FORCE_INSTALL := 1 - diff --git a/src/libexpr-c/nix-expr-c.pc.in b/src/libexpr-c/nix-expr-c.pc.in deleted file mode 100644 index 06897064d..000000000 --- a/src/libexpr-c/nix-expr-c.pc.in +++ /dev/null @@ -1,10 +0,0 @@ -prefix=@prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: Nix -Description: Nix Language Evaluator - C API -Version: @PACKAGE_VERSION@ -Requires: nix-store-c -Libs: -L${libdir} -lnixexprc -Cflags: -I${includedir}/nix diff --git a/src/libexpr-test-support/local.mk b/src/libexpr-test-support/local.mk deleted file mode 100644 index 0501de33c..000000000 --- a/src/libexpr-test-support/local.mk +++ /dev/null @@ -1,23 +0,0 @@ -libraries += libexpr-test-support - -libexpr-test-support_NAME = libnixexpr-test-support - -libexpr-test-support_DIR := $(d) - -ifeq ($(INSTALL_UNIT_TESTS), yes) - libexpr-test-support_INSTALL_DIR := $(checklibdir) -else - libexpr-test-support_INSTALL_DIR := -endif - -libexpr-test-support_SOURCES := \ - $(wildcard $(d)/tests/*.cc) \ - $(wildcard $(d)/tests/value/*.cc) - -libexpr-test-support_CXXFLAGS += $(libexpr-tests_EXTRA_INCLUDES) - -libexpr-test-support_LIBS = \ - libstore-test-support libutil-test-support \ - libexpr libstore libutil - -libexpr-test-support_LDFLAGS := $(THREAD_LDFLAGS) -lrapidcheck diff --git a/src/libexpr-tests/local.mk b/src/libexpr-tests/local.mk deleted file mode 100644 index 79583a9ee..000000000 --- a/src/libexpr-tests/local.mk +++ /dev/null @@ -1,45 +0,0 @@ -check: libexpr-tests_RUN - -programs += libexpr-tests - -libexpr-tests_NAME := libnixexpr-tests - -libexpr-tests_ENV := _NIX_TEST_UNIT_DATA=$(d)/data GTEST_OUTPUT=xml:$$testresults/libexpr-tests.xml - -libexpr-tests_DIR := $(d) - -ifeq ($(INSTALL_UNIT_TESTS), yes) - libexpr-tests_INSTALL_DIR := $(checkbindir) -else - libexpr-tests_INSTALL_DIR := -endif - -libexpr-tests_SOURCES := \ - $(wildcard $(d)/*.cc) \ - $(wildcard $(d)/value/*.cc) \ - $(wildcard $(d)/flake/*.cc) - -libexpr-tests_EXTRA_INCLUDES = \ - -I src/libexpr-test-support \ - -I src/libstore-test-support \ - -I src/libutil-test-support \ - $(INCLUDE_libexpr) \ - $(INCLUDE_libexprc) \ - $(INCLUDE_libfetchers) \ - $(INCLUDE_libstore) \ - $(INCLUDE_libstorec) \ - $(INCLUDE_libutil) \ - $(INCLUDE_libutilc) - -libexpr-tests_CXXFLAGS += $(libexpr-tests_EXTRA_INCLUDES) - -libexpr-tests_LIBS = \ - libexpr-test-support libstore-test-support libutil-test-support \ - libexpr libexprc libfetchers libstore libstorec libutil libutilc - -libexpr-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) -lgmock - -ifdef HOST_WINDOWS - # Increase the default reserved stack size to 65 MB so Nix doesn't run out of space - libexpr-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024))) -endif diff --git a/src/libexpr/local.mk b/src/libexpr/local.mk deleted file mode 100644 index 68518e184..000000000 --- a/src/libexpr/local.mk +++ /dev/null @@ -1,50 +0,0 @@ -libraries += libexpr - -libexpr_NAME = libnixexpr - -libexpr_DIR := $(d) - -libexpr_SOURCES := \ - $(wildcard $(d)/*.cc) \ - $(wildcard $(d)/value/*.cc) \ - $(wildcard $(d)/primops/*.cc) \ - $(d)/lexer-tab.cc \ - $(d)/parser-tab.cc -# Not just for this library itself, but also for downstream libraries using this library - -INCLUDE_libexpr := -I $(d) - -libexpr_CXXFLAGS += \ - $(INCLUDE_libutil) $(INCLUDE_libstore) $(INCLUDE_libfetchers) $(INCLUDE_libexpr) \ - -DGC_THREADS - -libexpr_LIBS = libutil libstore libfetchers - -libexpr_LDFLAGS += -lboost_context $(THREAD_LDFLAGS) -ifdef HOST_LINUX - libexpr_LDFLAGS += -ldl -endif - -# The dependency on libgc must be propagated (i.e. meaning that -# programs/libraries that use libexpr must explicitly pass -lgc), -# because inline functions in libexpr's header files call libgc. -libexpr_LDFLAGS_PROPAGATED = $(BDW_GC_LIBS) - -libexpr_ORDER_AFTER := $(d)/parser-tab.cc $(d)/parser-tab.hh $(d)/lexer-tab.cc $(d)/lexer-tab.hh - -$(d)/parser-tab.cc $(d)/parser-tab.hh: $(d)/parser.y - $(trace-gen) bison -v -o $(libexpr_DIR)/parser-tab.cc $< -d - -$(d)/lexer-tab.cc $(d)/lexer-tab.hh: $(d)/lexer.l - $(trace-gen) flex --outfile $(libexpr_DIR)/lexer-tab.cc --header-file=$(libexpr_DIR)/lexer-tab.hh $< - -clean-files += $(d)/parser-tab.cc $(d)/parser-tab.hh $(d)/lexer-tab.cc $(d)/lexer-tab.hh - -$(eval $(call install-file-in, $(buildprefix)$(d)/nix-expr.pc, $(libdir)/pkgconfig, 0644)) - -$(foreach i, $(wildcard src/libexpr/value/*.hh), \ - $(eval $(call install-file-in, $(i), $(includedir)/nix/value, 0644))) - -$(d)/primops.cc: $(d)/imported-drv-to-derivation.nix.gen.hh - -$(d)/eval.cc: $(d)/primops/derivation.nix.gen.hh $(d)/fetchurl.nix.gen.hh $(d)/call-flake.nix.gen.hh diff --git a/src/libexpr/nix-expr.pc.in b/src/libexpr/nix-expr.pc.in deleted file mode 100644 index 60ffb5dba..000000000 --- a/src/libexpr/nix-expr.pc.in +++ /dev/null @@ -1,10 +0,0 @@ -prefix=@prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: Nix -Description: Nix Package Manager -Version: @PACKAGE_VERSION@ -Requires: nix-store bdw-gc -Libs: -L${libdir} -lnixexpr -Cflags: -I${includedir}/nix -std=c++2a diff --git a/src/libfetchers-tests/local.mk b/src/libfetchers-tests/local.mk deleted file mode 100644 index 5c90f1fc7..000000000 --- a/src/libfetchers-tests/local.mk +++ /dev/null @@ -1,37 +0,0 @@ -check: libfetchers-tests_RUN - -programs += libfetchers-tests - -libfetchers-tests_NAME = libnixfetchers-tests - -libfetchers-tests_ENV := _NIX_TEST_UNIT_DATA=$(d)/data GTEST_OUTPUT=xml:$$testresults/libfetchers-tests.xml - -libfetchers-tests_DIR := $(d) - -ifeq ($(INSTALL_UNIT_TESTS), yes) - libfetchers-tests_INSTALL_DIR := $(checkbindir) -else - libfetchers-tests_INSTALL_DIR := -endif - -libfetchers-tests_SOURCES := $(wildcard $(d)/*.cc) - -libfetchers-tests_EXTRA_INCLUDES = \ - -I src/libstore-test-support \ - -I src/libutil-test-support \ - $(INCLUDE_libfetchers) \ - $(INCLUDE_libstore) \ - $(INCLUDE_libutil) - -libfetchers-tests_CXXFLAGS += $(libfetchers-tests_EXTRA_INCLUDES) - -libfetchers-tests_LIBS = \ - libstore-test-support libutil-test-support \ - libfetchers libstore libutil - -libfetchers-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) $(LIBGIT2_LIBS) - -ifdef HOST_WINDOWS - # Increase the default reserved stack size to 65 MB so Nix doesn't run out of space - libfetchers-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024))) -endif diff --git a/src/libfetchers/local.mk b/src/libfetchers/local.mk deleted file mode 100644 index e229a0993..000000000 --- a/src/libfetchers/local.mk +++ /dev/null @@ -1,17 +0,0 @@ -libraries += libfetchers - -libfetchers_NAME = libnixfetchers - -libfetchers_DIR := $(d) - -libfetchers_SOURCES := $(wildcard $(d)/*.cc) - -# Not just for this library itself, but also for downstream libraries using this library - -INCLUDE_libfetchers := -I $(d) - -libfetchers_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libstore) $(INCLUDE_libfetchers) - -libfetchers_LDFLAGS += $(THREAD_LDFLAGS) $(LIBGIT2_LIBS) -larchive - -libfetchers_LIBS = libutil libstore diff --git a/src/libflake-tests/local.mk b/src/libflake-tests/local.mk deleted file mode 100644 index 8599b43f6..000000000 --- a/src/libflake-tests/local.mk +++ /dev/null @@ -1,43 +0,0 @@ -check: libflake-tests_RUN - -programs += libflake-tests - -libflake-tests_NAME := libnixflake-tests - -libflake-tests_ENV := _NIX_TEST_UNIT_DATA=$(d)/data GTEST_OUTPUT=xml:$$testresults/libflake-tests.xml - -libflake-tests_DIR := $(d) - -ifeq ($(INSTALL_UNIT_TESTS), yes) - libflake-tests_INSTALL_DIR := $(checkbindir) -else - libflake-tests_INSTALL_DIR := -endif - -libflake-tests_SOURCES := \ - $(wildcard $(d)/*.cc) \ - $(wildcard $(d)/value/*.cc) \ - $(wildcard $(d)/flake/*.cc) - -libflake-tests_EXTRA_INCLUDES = \ - -I src/libflake-test-support \ - -I src/libstore-test-support \ - -I src/libutil-test-support \ - $(INCLUDE_libflake) \ - $(INCLUDE_libexpr) \ - $(INCLUDE_libfetchers) \ - $(INCLUDE_libstore) \ - $(INCLUDE_libutil) \ - -libflake-tests_CXXFLAGS += $(libflake-tests_EXTRA_INCLUDES) - -libflake-tests_LIBS = \ - libexpr-test-support libstore-test-support libutil-test-support \ - libflake libexpr libfetchers libstore libutil - -libflake-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) -lgmock - -ifdef HOST_WINDOWS - # Increase the default reserved stack size to 65 MB so Nix doesn't run out of space - libflake-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024))) -endif diff --git a/src/libflake/flake/nix-flake.pc.in b/src/libflake/flake/nix-flake.pc.in deleted file mode 100644 index 10c52f5e9..000000000 --- a/src/libflake/flake/nix-flake.pc.in +++ /dev/null @@ -1,10 +0,0 @@ -prefix=@prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: Nix -Description: Nix Package Manager -Version: @PACKAGE_VERSION@ -Requires: nix-util nix-store nix-expr -Libs: -L${libdir} -lnixflake -Cflags: -I${includedir}/nix -std=c++2a diff --git a/src/libflake/local.mk b/src/libflake/local.mk deleted file mode 100644 index 5e604ef3a..000000000 --- a/src/libflake/local.mk +++ /dev/null @@ -1,22 +0,0 @@ -libraries += libflake - -libflake_NAME = libnixflake - -libflake_DIR := $(d) - -libflake_SOURCES := $(wildcard $(d)/*.cc $(d)/flake/*.cc) - -# Not just for this library itself, but also for downstream libraries using this library - -INCLUDE_libflake := -I $(d) - -libflake_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libstore) $(INCLUDE_libfetchers) $(INCLUDE_libexpr) $(INCLUDE_libflake) - -libflake_LDFLAGS += $(THREAD_LDFLAGS) - -libflake_LIBS = libutil libstore libfetchers libexpr - -$(eval $(call install-file-in, $(buildprefix)$(d)/flake/nix-flake.pc, $(libdir)/pkgconfig, 0644)) - -$(foreach i, $(wildcard src/libflake/flake/*.hh), \ - $(eval $(call install-file-in, $(i), $(includedir)/nix/flake, 0644))) diff --git a/src/libmain/local.mk b/src/libmain/local.mk deleted file mode 100644 index d41c49dd7..000000000 --- a/src/libmain/local.mk +++ /dev/null @@ -1,22 +0,0 @@ -libraries += libmain - -libmain_NAME = libnixmain - -libmain_DIR := $(d) - -libmain_SOURCES := $(wildcard $(d)/*.cc) -ifdef HOST_UNIX - libmain_SOURCES += $(wildcard $(d)/unix/*.cc) -endif - -INCLUDE_libmain := -I $(d) - -libmain_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libstore) $(INCLUDE_libmain) - -libmain_LDFLAGS += $(OPENSSL_LIBS) - -libmain_LIBS = libstore libutil - -libmain_ALLOW_UNDEFINED = 1 - -$(eval $(call install-file-in, $(buildprefix)$(d)/nix-main.pc, $(libdir)/pkgconfig, 0644)) diff --git a/src/libmain/nix-main.pc.in b/src/libmain/nix-main.pc.in deleted file mode 100644 index fb3ead6fa..000000000 --- a/src/libmain/nix-main.pc.in +++ /dev/null @@ -1,9 +0,0 @@ -prefix=@prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: Nix -Description: Nix Package Manager -Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lnixmain -Cflags: -I${includedir}/nix -std=c++2a diff --git a/src/libstore-c/local.mk b/src/libstore-c/local.mk deleted file mode 100644 index 5e3eff06a..000000000 --- a/src/libstore-c/local.mk +++ /dev/null @@ -1,21 +0,0 @@ -libraries += libstorec - -libstorec_NAME = libnixstorec - -libstorec_DIR := $(d) - -libstorec_SOURCES := $(wildcard $(d)/*.cc) - -libstorec_LIBS = libutil libstore libutilc - -libstorec_LDFLAGS += $(THREAD_LDFLAGS) - -# Not just for this library itself, but also for downstream libraries using this library - -INCLUDE_libstorec := -I $(d) -libstorec_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libutilc) \ - $(INCLUDE_libstore) $(INCLUDE_libstorec) - -$(eval $(call install-file-in, $(d)/nix-store-c.pc, $(libdir)/pkgconfig, 0644)) - -libstorec_FORCE_INSTALL := 1 diff --git a/src/libstore-c/nix-store-c.pc.in b/src/libstore-c/nix-store-c.pc.in deleted file mode 100644 index de3c7b4c6..000000000 --- a/src/libstore-c/nix-store-c.pc.in +++ /dev/null @@ -1,9 +0,0 @@ -prefix=@prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: Nix -Description: Nix Store - C API -Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lnixstorec -lnixutilc -Cflags: -I${includedir}/nix diff --git a/src/libstore-test-support/local.mk b/src/libstore-test-support/local.mk deleted file mode 100644 index 56dedd825..000000000 --- a/src/libstore-test-support/local.mk +++ /dev/null @@ -1,21 +0,0 @@ -libraries += libstore-test-support - -libstore-test-support_NAME = libnixstore-test-support - -libstore-test-support_DIR := $(d) - -ifeq ($(INSTALL_UNIT_TESTS), yes) - libstore-test-support_INSTALL_DIR := $(checklibdir) -else - libstore-test-support_INSTALL_DIR := -endif - -libstore-test-support_SOURCES := $(wildcard $(d)/tests/*.cc) - -libstore-test-support_CXXFLAGS += $(libstore-tests_EXTRA_INCLUDES) - -libstore-test-support_LIBS = \ - libutil-test-support \ - libstore libutil - -libstore-test-support_LDFLAGS := $(THREAD_LDFLAGS) -lrapidcheck diff --git a/src/libstore-tests/local.mk b/src/libstore-tests/local.mk deleted file mode 100644 index b565ff0be..000000000 --- a/src/libstore-tests/local.mk +++ /dev/null @@ -1,38 +0,0 @@ -check: libstore-tests_RUN - -programs += libstore-tests - -libstore-tests_NAME = libnixstore-tests - -libstore-tests_ENV := _NIX_TEST_UNIT_DATA=$(d)/data GTEST_OUTPUT=xml:$$testresults/libstore-tests.xml - -libstore-tests_DIR := $(d) - -ifeq ($(INSTALL_UNIT_TESTS), yes) - libstore-tests_INSTALL_DIR := $(checkbindir) -else - libstore-tests_INSTALL_DIR := -endif - -libstore-tests_SOURCES := $(wildcard $(d)/*.cc) - -libstore-tests_EXTRA_INCLUDES = \ - -I src/libstore-test-support \ - -I src/libutil-test-support \ - $(INCLUDE_libstore) \ - $(INCLUDE_libstorec) \ - $(INCLUDE_libutil) \ - $(INCLUDE_libutilc) - -libstore-tests_CXXFLAGS += $(libstore-tests_EXTRA_INCLUDES) - -libstore-tests_LIBS = \ - libstore-test-support libutil-test-support \ - libstore libstorec libutil libutilc - -libstore-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) - -ifdef HOST_WINDOWS - # Increase the default reserved stack size to 65 MB so Nix doesn't run out of space - libstore-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024))) -endif diff --git a/src/libstore/local.mk b/src/libstore/local.mk deleted file mode 100644 index 43d8993ba..000000000 --- a/src/libstore/local.mk +++ /dev/null @@ -1,103 +0,0 @@ -libraries += libstore - -libstore_NAME = libnixstore - -libstore_DIR := $(d) - -libstore_SOURCES := $(wildcard $(d)/*.cc $(d)/builtins/*.cc $(d)/build/*.cc) -ifdef HOST_UNIX - libstore_SOURCES += $(wildcard $(d)/unix/*.cc $(d)/unix/build/*.cc) -endif -ifdef HOST_LINUX - libstore_SOURCES += $(wildcard $(d)/linux/*.cc) -endif -ifdef HOST_WINDOWS - libstore_SOURCES += $(wildcard $(d)/windows/*.cc) -endif - -libstore_LIBS = libutil - -libstore_LDFLAGS += $(SQLITE3_LIBS) $(LIBCURL_LIBS) $(THREAD_LDFLAGS) -ifdef HOST_LINUX - libstore_LDFLAGS += -ldl -endif -ifdef HOST_WINDOWS - libstore_LDFLAGS += -lws2_32 -endif - -$(foreach file,$(libstore_FILES),$(eval $(call install-data-in,$(d)/$(file),$(datadir)/nix/sandbox))) - -ifeq ($(ENABLE_S3), 1) - libstore_LDFLAGS += -laws-cpp-sdk-transfer -laws-cpp-sdk-s3 -laws-cpp-sdk-core -laws-crt-cpp -endif - -ifdef HOST_SOLARIS - libstore_LDFLAGS += -lsocket -endif - -ifeq ($(HAVE_SECCOMP), 1) - libstore_LDFLAGS += $(LIBSECCOMP_LIBS) -endif - -# Not just for this library itself, but also for downstream libraries using this library - -INCLUDE_libstore := -I $(d) -I $(d)/build -ifdef HOST_UNIX - INCLUDE_libstore += -I $(d)/unix -I $(d)/unix/build -endif -ifdef HOST_LINUX - INCLUDE_libstore += -I $(d)/linux -endif -ifdef HOST_WINDOWS - INCLUDE_libstore += -I $(d)/windows -endif - -ifdef HOST_WINDOWS -NIX_ROOT = N:\\\\ -else -NIX_ROOT = -endif - -# Prefix all but `NIX_STORE_DIR`, since we aren't doing a local store -# yet so a "logical" store dir that is the same as unix is preferred. -# -# Also, it keeps the unit tests working. - -libstore_CXXFLAGS += \ - $(INCLUDE_libutil) $(INCLUDE_libstore) $(INCLUDE_libstore) \ - -DNIX_PREFIX=\"$(NIX_ROOT)$(prefix)\" \ - -DNIX_STORE_DIR=\"$(storedir)\" \ - -DNIX_DATA_DIR=\"$(NIX_ROOT)$(datadir)\" \ - -DNIX_STATE_DIR=\"$(NIX_ROOT)$(localstatedir)/nix\" \ - -DNIX_LOG_DIR=\"$(NIX_ROOT)$(localstatedir)/log/nix\" \ - -DNIX_CONF_DIR=\"$(NIX_ROOT)$(sysconfdir)/nix\" \ - -DNIX_MAN_DIR=\"$(NIX_ROOT)$(mandir)\" \ - -DLSOF=\"$(NIX_ROOT)$(lsof)\" - -ifeq ($(embedded_sandbox_shell),yes) -libstore_CXXFLAGS += -DSANDBOX_SHELL=\"__embedded_sandbox_shell__\" - -$(d)/unix/build/local-derivation-goal.cc: $(d)/unix/embedded-sandbox-shell.gen.hh - -$(d)/unix/embedded-sandbox-shell.gen.hh: $(sandbox_shell) - $(trace-gen) hexdump -v -e '1/1 "0x%x," "\n"' < $< > $@.tmp - @mv $@.tmp $@ -else - ifneq ($(sandbox_shell),) - libstore_CXXFLAGS += -DSANDBOX_SHELL="\"$(sandbox_shell)\"" - endif -endif - -$(d)/local-store.cc: $(d)/schema.sql.gen.hh $(d)/ca-specific-schema.sql.gen.hh - -$(d)/unix/build.cc: - -clean-files += $(d)/schema.sql.gen.hh $(d)/ca-specific-schema.sql.gen.hh - -$(eval $(call install-file-in, $(buildprefix)$(d)/nix-store.pc, $(libdir)/pkgconfig, 0644)) - -$(foreach i, $(wildcard src/libstore/builtins/*.hh), \ - $(eval $(call install-file-in, $(i), $(includedir)/nix/builtins, 0644))) - -$(foreach i, $(wildcard src/libstore/build/*.hh), \ - $(eval $(call install-file-in, $(i), $(includedir)/nix/build, 0644))) diff --git a/src/libstore/nix-store.pc.in b/src/libstore/nix-store.pc.in deleted file mode 100644 index cd3f2b8da..000000000 --- a/src/libstore/nix-store.pc.in +++ /dev/null @@ -1,10 +0,0 @@ -prefix=@prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: Nix -Description: Nix Package Manager -Version: @PACKAGE_VERSION@ -Requires: nix-util -Libs: -L${libdir} -lnixstore -Cflags: -I${includedir}/nix -std=c++2a diff --git a/src/libutil-c/local.mk b/src/libutil-c/local.mk deleted file mode 100644 index f2df1ef43..000000000 --- a/src/libutil-c/local.mk +++ /dev/null @@ -1,18 +0,0 @@ -libraries += libutilc - -libutilc_NAME = libnixutilc - -libutilc_DIR := $(d) - -libutilc_SOURCES := $(wildcard $(d)/*.cc) - -# Not just for this library itself, but also for downstream libraries using this library - -INCLUDE_libutilc := -I $(d) -libutilc_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libutilc) - -libutilc_LIBS = libutil - -libutilc_LDFLAGS += $(THREAD_LDFLAGS) - -libutilc_FORCE_INSTALL := 1 diff --git a/src/libutil-c/nix-util-c.pc.in b/src/libutil-c/nix-util-c.pc.in deleted file mode 100644 index 0ccae3f8a..000000000 --- a/src/libutil-c/nix-util-c.pc.in +++ /dev/null @@ -1,9 +0,0 @@ -prefix=@prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: Nix libutil C API -Description: Common functions for the Nix C API, such as error handling -Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lnixutil -Cflags: -I${includedir}/nix -std=c++2a diff --git a/src/libutil-test-support/local.mk b/src/libutil-test-support/local.mk deleted file mode 100644 index 5f7835c9f..000000000 --- a/src/libutil-test-support/local.mk +++ /dev/null @@ -1,19 +0,0 @@ -libraries += libutil-test-support - -libutil-test-support_NAME = libnixutil-test-support - -libutil-test-support_DIR := $(d) - -ifeq ($(INSTALL_UNIT_TESTS), yes) - libutil-test-support_INSTALL_DIR := $(checklibdir) -else - libutil-test-support_INSTALL_DIR := -endif - -libutil-test-support_SOURCES := $(wildcard $(d)/tests/*.cc) - -libutil-test-support_CXXFLAGS += $(libutil-tests_EXTRA_INCLUDES) - -libutil-test-support_LIBS = libutil - -libutil-test-support_LDFLAGS := $(THREAD_LDFLAGS) -lrapidcheck diff --git a/src/libutil-tests/local.mk b/src/libutil-tests/local.mk deleted file mode 100644 index c747863a4..000000000 --- a/src/libutil-tests/local.mk +++ /dev/null @@ -1,37 +0,0 @@ -check: libutil-tests_RUN - -programs += libutil-tests - -libutil-tests_NAME = libnixutil-tests - -libutil-tests_ENV := _NIX_TEST_UNIT_DATA=$(d)/data GTEST_OUTPUT=xml:$$testresults/libutil-tests.xml - -libutil-tests_DIR := $(d) - -ifeq ($(INSTALL_UNIT_TESTS), yes) - libutil-tests_INSTALL_DIR := $(checkbindir) -else - libutil-tests_INSTALL_DIR := -endif - -libutil-tests_SOURCES := $(wildcard $(d)/*.cc) - -libutil-tests_EXTRA_INCLUDES = \ - -I src/libutil-test-support \ - $(INCLUDE_libutil) \ - $(INCLUDE_libutilc) - -libutil-tests_CXXFLAGS += $(libutil-tests_EXTRA_INCLUDES) - -libutil-tests_LIBS = libutil-test-support libutil libutilc - -libutil-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) - -ifdef HOST_WINDOWS - # Increase the default reserved stack size to 65 MB so Nix doesn't run out of space - libutil-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024))) -endif - -check: $(d)/data/git/check-data.sh.test - -$(eval $(call run-test,$(d)/data/git/check-data.sh)) diff --git a/src/libutil/local.mk b/src/libutil/local.mk deleted file mode 100644 index e9b498e65..000000000 --- a/src/libutil/local.mk +++ /dev/null @@ -1,44 +0,0 @@ -libraries += libutil - -libutil_NAME = libnixutil - -libutil_DIR := $(d) - -libutil_SOURCES := $(wildcard $(d)/*.cc $(d)/signature/*.cc) -ifdef HOST_UNIX - libutil_SOURCES += $(wildcard $(d)/unix/*.cc) -endif -ifdef HOST_LINUX - libutil_SOURCES += $(wildcard $(d)/linux/*.cc) -endif -ifdef HOST_WINDOWS - libutil_SOURCES += $(wildcard $(d)/windows/*.cc) -endif - -# Not just for this library itself, but also for downstream libraries using this library - -INCLUDE_libutil := -I $(d) -ifdef HOST_UNIX - INCLUDE_libutil += -I $(d)/unix -endif -ifdef HOST_LINUX - INCLUDE_libutil += -I $(d)/linux -endif -ifdef HOST_WINDOWS - INCLUDE_libutil += -I $(d)/windows -endif -libutil_CXXFLAGS += $(INCLUDE_libutil) - -libutil_LDFLAGS += $(THREAD_LDFLAGS) $(LIBCURL_LIBS) $(SODIUM_LIBS) $(OPENSSL_LIBS) $(LIBBROTLI_LIBS) $(LIBARCHIVE_LIBS) $(BOOST_LDFLAGS) -lboost_context - -$(foreach i, $(wildcard $(d)/args/*.hh), \ - $(eval $(call install-file-in, $(i), $(includedir)/nix/args, 0644))) -$(foreach i, $(wildcard $(d)/signature/*.hh), \ - $(eval $(call install-file-in, $(i), $(includedir)/nix/signature, 0644))) - - -ifeq ($(HAVE_LIBCPUID), 1) - libutil_LDFLAGS += -lcpuid -endif - -$(eval $(call install-file-in, $(buildprefix)$(d)/nix-util.pc, $(libdir)/pkgconfig, 0644)) diff --git a/src/libutil/nix-util.pc.in b/src/libutil/nix-util.pc.in deleted file mode 100644 index 85bb1e70e..000000000 --- a/src/libutil/nix-util.pc.in +++ /dev/null @@ -1,9 +0,0 @@ -prefix=@prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: Nix -Description: Nix Package Manager -Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lnixutil -Cflags: -I${includedir}/nix -std=c++2a diff --git a/src/nix/local.mk b/src/nix/local.mk deleted file mode 100644 index b57f6b3e2..000000000 --- a/src/nix/local.mk +++ /dev/null @@ -1,59 +0,0 @@ -programs += nix - -nix_DIR := $(d) - -nix_SOURCES := \ - $(wildcard $(d)/*.cc) \ - $(wildcard src/nix-build/*.cc) \ - $(wildcard src/nix-env/*.cc) \ - $(wildcard src/nix-instantiate/*.cc) \ - $(wildcard src/nix-store/*.cc) - -ifdef HOST_UNIX -nix_SOURCES += \ - $(wildcard $(d)/unix/*.cc) \ - $(wildcard src/build-remote/*.cc) \ - $(wildcard src/nix-channel/*.cc) \ - $(wildcard src/nix-collect-garbage/*.cc) \ - $(wildcard src/nix-copy-closure/*.cc) \ - $(wildcard src/nix-daemon/*.cc) -endif - -INCLUDE_nix := -I $(d) -ifdef HOST_UNIX - INCLUDE_nix += -I $(d)/unix -endif - -nix_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libstore) $(INCLUDE_libfetchers) $(INCLUDE_libexpr) $(INCLUDE_libflake) $(INCLUDE_libmain) -I src/libcmd -I doc/manual $(INCLUDE_nix) - -nix_CXXFLAGS += -DNIX_BIN_DIR=\"$(NIX_ROOT)$(bindir)\" - -nix_LIBS = libexpr libmain libfetchers libflake libstore libutil libcmd - -nix_LDFLAGS = $(THREAD_LDFLAGS) $(SODIUM_LIBS) $(EDITLINE_LIBS) $(BOOST_LDFLAGS) $(LOWDOWN_LIBS) - -ifdef HOST_WINDOWS - # Increase the default reserved stack size to 65 MB so Nix doesn't run out of space - nix_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024))) -endif - -$(foreach name, \ - nix-build nix-channel nix-collect-garbage nix-copy-closure nix-daemon nix-env nix-hash nix-instantiate nix-prefetch-url nix-shell nix-store, \ - $(eval $(call install-symlink, nix, $(bindir)/$(name)))) -$(eval $(call install-symlink, $(bindir)/nix, $(libexecdir)/nix/build-remote)) - -src/nix-env/user-env.cc: src/nix-env/buildenv.nix.gen.hh - -$(d)/develop.cc: $(d)/get-env.sh.gen.hh - -src/nix-channel/nix-channel.cc: src/nix-channel/unpack-channel.nix.gen.hh - -$(d)/main.cc: \ - doc/manual/generate-manpage.nix.gen.hh \ - doc/manual/utils.nix.gen.hh doc/manual/generate-settings.nix.gen.hh \ - doc/manual/generate-store-info.nix.gen.hh \ - $(d)/help-stores.md.gen.hh - -$(d)/profile.cc: $(d)/profile.md - -$(d)/profile.md: $(d)/profiles.md.gen.hh diff --git a/tests/functional/ca/local.mk b/tests/functional/ca/local.mk deleted file mode 100644 index 7c2fcc451..000000000 --- a/tests/functional/ca/local.mk +++ /dev/null @@ -1,29 +0,0 @@ -ca-tests := \ - $(d)/build-with-garbage-path.sh \ - $(d)/build.sh \ - $(d)/build-cache.sh \ - $(d)/concurrent-builds.sh \ - $(d)/derivation-json.sh \ - $(d)/duplicate-realisation-in-closure.sh \ - $(d)/eval-store.sh \ - $(d)/gc.sh \ - $(d)/import-from-derivation.sh \ - $(d)/new-build-cmd.sh \ - $(d)/nix-copy.sh \ - $(d)/nix-run.sh \ - $(d)/nix-shell.sh \ - $(d)/post-hook.sh \ - $(d)/recursive.sh \ - $(d)/repl.sh \ - $(d)/selfref-gc.sh \ - $(d)/signatures.sh \ - $(d)/substitute.sh \ - $(d)/why-depends.sh - -install-tests-groups += ca - -clean-files += \ - $(d)/config.nix - -test-deps += \ - tests/functional/ca/config.nix diff --git a/tests/functional/dyn-drv/local.mk b/tests/functional/dyn-drv/local.mk deleted file mode 100644 index c87534944..000000000 --- a/tests/functional/dyn-drv/local.mk +++ /dev/null @@ -1,15 +0,0 @@ -dyn-drv-tests := \ - $(d)/text-hashed-output.sh \ - $(d)/recursive-mod-json.sh \ - $(d)/build-built-drv.sh \ - $(d)/eval-outputOf.sh \ - $(d)/dep-built-drv.sh \ - $(d)/old-daemon-error-hack.sh - -install-tests-groups += dyn-drv - -clean-files += \ - $(d)/config.nix - -test-deps += \ - tests/functional/dyn-drv/config.nix diff --git a/tests/functional/flakes/local.mk b/tests/functional/flakes/local.mk deleted file mode 100644 index a37840240..000000000 --- a/tests/functional/flakes/local.mk +++ /dev/null @@ -1,25 +0,0 @@ -flake-tests := \ - $(d)/flakes.sh \ - $(d)/develop.sh \ - $(d)/edit.sh \ - $(d)/run.sh \ - $(d)/mercurial.sh \ - $(d)/circular.sh \ - $(d)/init.sh \ - $(d)/inputs.sh \ - $(d)/follow-paths.sh \ - $(d)/bundle.sh \ - $(d)/check.sh \ - $(d)/unlocked-override.sh \ - $(d)/absolute-paths.sh \ - $(d)/absolute-attr-paths.sh \ - $(d)/build-paths.sh \ - $(d)/flake-in-submodule.sh \ - $(d)/prefetch.sh \ - $(d)/eval-cache.sh \ - $(d)/search-root.sh \ - $(d)/config.sh \ - $(d)/show.sh \ - $(d)/dubious-query.sh - -install-tests-groups += flake diff --git a/tests/functional/git-hashing/local.mk b/tests/functional/git-hashing/local.mk deleted file mode 100644 index ebec01940..000000000 --- a/tests/functional/git-hashing/local.mk +++ /dev/null @@ -1,7 +0,0 @@ -git-hashing-tests := \ - $(d)/simple.sh - -install-tests-groups += git-hashing - -clean-files += \ - $(d)/config.nix diff --git a/tests/functional/local-overlay-store/local.mk b/tests/functional/local-overlay-store/local.mk deleted file mode 100644 index 6348a4423..000000000 --- a/tests/functional/local-overlay-store/local.mk +++ /dev/null @@ -1,14 +0,0 @@ -local-overlay-store-tests := \ - $(d)/check-post-init.sh \ - $(d)/redundant-add.sh \ - $(d)/build.sh \ - $(d)/bad-uris.sh \ - $(d)/add-lower.sh \ - $(d)/delete-refs.sh \ - $(d)/delete-duplicate.sh \ - $(d)/gc.sh \ - $(d)/verify.sh \ - $(d)/optimise.sh \ - $(d)/stale-file-handle.sh - -install-tests-groups += local-overlay-store diff --git a/tests/functional/local.mk b/tests/functional/local.mk deleted file mode 100644 index e50b5eaf1..000000000 --- a/tests/functional/local.mk +++ /dev/null @@ -1,146 +0,0 @@ -nix_tests = \ - test-infra.sh \ - gc.sh \ - nix-collect-garbage-d.sh \ - remote-store.sh \ - legacy-ssh-store.sh \ - lang.sh \ - lang-gc.sh \ - characterisation-test-infra.sh \ - experimental-features.sh \ - fetchMercurial.sh \ - gc-auto.sh \ - user-envs.sh \ - user-envs-migration.sh \ - binary-cache.sh \ - multiple-outputs.sh \ - nix-build.sh \ - gc-concurrent.sh \ - repair.sh \ - fixed.sh \ - export-graph.sh \ - timeout.sh \ - fetchGitRefs.sh \ - gc-runtime.sh \ - tarball.sh \ - fetchGit.sh \ - fetchurl.sh \ - fetchPath.sh \ - fetchTree-file.sh \ - simple.sh \ - referrers.sh \ - optimise-store.sh \ - substitute-with-invalid-ca.sh \ - signing.sh \ - hash-convert.sh \ - hash-path.sh \ - gc-non-blocking.sh \ - check.sh \ - nix-shell.sh \ - check-refs.sh \ - build-remote-input-addressed.sh \ - secure-drv-outputs.sh \ - restricted.sh \ - fetchGitSubmodules.sh \ - fetchGitVerification.sh \ - readfile-context.sh \ - nix-channel.sh \ - recursive.sh \ - dependencies.sh \ - check-reqs.sh \ - build-remote-content-addressed-fixed.sh \ - build-remote-content-addressed-floating.sh \ - build-remote-trustless-should-pass-0.sh \ - build-remote-trustless-should-pass-1.sh \ - build-remote-trustless-should-pass-2.sh \ - build-remote-trustless-should-pass-3.sh \ - build-remote-trustless-should-fail-0.sh \ - build-remote-with-mounted-ssh-ng.sh \ - nar-access.sh \ - impure-eval.sh \ - pure-eval.sh \ - eval.sh \ - repl.sh \ - binary-cache-build-remote.sh \ - search.sh \ - logging.sh \ - export.sh \ - config.sh \ - add.sh \ - chroot-store.sh \ - filter-source.sh \ - misc.sh \ - dump-db.sh \ - linux-sandbox.sh \ - supplementary-groups.sh \ - build-dry.sh \ - structured-attrs.sh \ - shell.sh \ - brotli.sh \ - zstd.sh \ - compression-levels.sh \ - nix-copy-ssh.sh \ - nix-copy-ssh-ng.sh \ - post-hook.sh \ - function-trace.sh \ - fmt.sh \ - eval-store.sh \ - why-depends.sh \ - derivation-json.sh \ - derivation-advanced-attributes.sh \ - import-from-derivation.sh \ - nix_path.sh \ - nars.sh \ - placeholders.sh \ - ssh-relay.sh \ - build.sh \ - build-delete.sh \ - output-normalization.sh \ - selfref-gc.sh \ - db-migration.sh \ - bash-profile.sh \ - pass-as-file.sh \ - nix-profile.sh \ - suggestions.sh \ - store-info.sh \ - fetchClosure.sh \ - completions.sh \ - impure-derivations.sh \ - path-from-hash-part.sh \ - path-info.sh \ - toString-path.sh \ - read-only-store.sh \ - nested-sandboxing.sh \ - impure-env.sh \ - debugger.sh \ - extra-sandbox-profile.sh \ - -ifeq ($(HAVE_LIBCPUID), 1) - nix_tests += compute-levels.sh -endif - -ifeq ($(ENABLE_BUILD), yes) - nix_tests += test-libstoreconsumer.sh - - ifeq ($(BUILD_SHARED_LIBS), 1) - nix_tests += plugins.sh - endif -endif - -ifeq ($(ENABLE_DOC_GEN), yes) - nix_tests += help.sh -endif - -$(d)/test-libstoreconsumer.sh.test $(d)/test-libstoreconsumer.sh.test-debug: \ - $(buildprefix)$(d)/test-libstoreconsumer/test-libstoreconsumer -$(d)/plugins.sh.test $(d)/plugins.sh.test-debug: \ - $(buildprefix)$(d)/plugins/libplugintest.$(SO_EXT) - -install-tests += $(foreach x, $(nix_tests), $(d)/$(x)) - -test-clean-files := \ - $(d)/common/subst-vars.sh \ - $(d)/config.nix - -clean-files += $(test-clean-files) -test-deps += $(test-clean-files) diff --git a/tests/functional/plugins/local.mk b/tests/functional/plugins/local.mk deleted file mode 100644 index 2314e1341..000000000 --- a/tests/functional/plugins/local.mk +++ /dev/null @@ -1,11 +0,0 @@ -libraries += libplugintest - -libplugintest_DIR := $(d) - -libplugintest_SOURCES := $(d)/plugintest.cc - -libplugintest_ALLOW_UNDEFINED := 1 - -libplugintest_EXCLUDE_FROM_LIBRARY_LIST := 1 - -libplugintest_CXXFLAGS := $(INCLUDE_libutil) $(INCLUDE_libstore) $(INCLUDE_libexpr) $(INCLUDE_libfetchers) diff --git a/tests/functional/test-libstoreconsumer/local.mk b/tests/functional/test-libstoreconsumer/local.mk deleted file mode 100644 index 3e8581c57..000000000 --- a/tests/functional/test-libstoreconsumer/local.mk +++ /dev/null @@ -1,15 +0,0 @@ -programs += test-libstoreconsumer - -test-libstoreconsumer_DIR := $(d) - -# do not install -test-libstoreconsumer_INSTALL_DIR := - -test-libstoreconsumer_SOURCES := \ - $(wildcard $(d)/*.cc) \ - -test-libstoreconsumer_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libstore) - -test-libstoreconsumer_LIBS = libstore libutil - -test-libstoreconsumer_LDFLAGS = $(THREAD_LDFLAGS) $(SODIUM_LIBS) $(EDITLINE_LIBS) $(BOOST_LDFLAGS) $(LOWDOWN_LIBS) From f7591bc6edbedc511e5df3d9b77eb2ddc8fabab0 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Sun, 3 Nov 2024 17:22:12 -0500 Subject: [PATCH 394/718] Make `config.nix` shims As requested in https://github.com/NixOS/nix/pull/11792#discussion_r1827034428 --- .gitignore | 3 --- tests/functional/build-hook-ca-fixed.nix | 2 +- tests/functional/build-hook.nix | 2 +- tests/functional/ca/config.nix | 2 ++ tests/functional/ca/content-addressed.nix | 2 +- tests/functional/ca/nix-run.sh | 3 --- tests/functional/ca/nondeterministic.nix | 2 +- tests/functional/ca/racy.nix | 2 +- tests/functional/check-refs.nix | 2 +- tests/functional/check-reqs.nix | 2 +- tests/functional/check.nix | 2 +- tests/functional/chroot-store.sh | 3 --- tests/functional/common/functions.sh | 9 --------- tests/functional/config.nix | 2 ++ tests/functional/dependencies.nix | 2 +- tests/functional/dyn-drv/config.nix | 2 ++ tests/functional/dyn-drv/old-daemon-error-hack.nix | 2 +- tests/functional/dyn-drv/recursive-mod-json.nix | 2 +- tests/functional/dyn-drv/text-hashed-output.nix | 2 +- tests/functional/export-graph.nix | 2 +- tests/functional/extra-sandbox-profile.nix | 2 +- tests/functional/failing.nix | 2 +- tests/functional/filter-source.nix | 2 +- tests/functional/fixed.nix | 2 +- tests/functional/flakes/bundle.sh | 3 --- tests/functional/flakes/common.sh | 3 --- tests/functional/flakes/config.sh | 1 - tests/functional/flakes/develop.sh | 3 --- tests/functional/flakes/run.sh | 2 -- tests/functional/fod-failing.nix | 2 +- tests/functional/gc-concurrent.nix | 2 +- tests/functional/gc-runtime.nix | 2 +- tests/functional/hermetic.nix | 2 +- tests/functional/ifd.nix | 2 +- tests/functional/import-from-derivation.nix | 2 +- tests/functional/impure-derivations.nix | 2 +- tests/functional/impure-env.nix | 2 +- tests/functional/linux-sandbox-cert-test.nix | 2 +- tests/functional/multiple-outputs.nix | 2 +- tests/functional/nar-access.nix | 2 +- tests/functional/nix-build-examples.nix | 2 +- tests/functional/parallel.nix | 2 +- tests/functional/path.nix | 2 +- tests/functional/readfile-context.nix | 2 +- tests/functional/restricted.sh | 4 ---- tests/functional/search.nix | 2 +- tests/functional/secure-drv-outputs.nix | 2 +- tests/functional/shell-hello.nix | 2 +- tests/functional/shell.nix | 2 +- tests/functional/simple-failing.nix | 2 +- tests/functional/simple.nix | 2 +- tests/functional/structured-attrs-shell.nix | 2 +- tests/functional/structured-attrs.nix | 2 +- tests/functional/symlink-derivation.nix | 2 +- tests/functional/timeout.nix | 2 +- tests/functional/user-envs.nix | 2 +- 56 files changed, 49 insertions(+), 77 deletions(-) create mode 100644 tests/functional/ca/config.nix create mode 100644 tests/functional/config.nix create mode 100644 tests/functional/dyn-drv/config.nix diff --git a/.gitignore b/.gitignore index 11a80ab5b..de1183977 100644 --- a/.gitignore +++ b/.gitignore @@ -102,9 +102,6 @@ perl/Makefile.config /tests/functional/restricted-innocent /tests/functional/shell /tests/functional/shell.drv -/tests/functional/config.nix -/tests/functional/ca/config.nix -/tests/functional/dyn-drv/config.nix /tests/functional/repl-result-out /tests/functional/debugger-test-out /tests/functional/test-libstoreconsumer/test-libstoreconsumer diff --git a/tests/functional/build-hook-ca-fixed.nix b/tests/functional/build-hook-ca-fixed.nix index 427ec2c31..0ce6d9b12 100644 --- a/tests/functional/build-hook-ca-fixed.nix +++ b/tests/functional/build-hook-ca-fixed.nix @@ -1,6 +1,6 @@ { busybox }: -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; let diff --git a/tests/functional/build-hook.nix b/tests/functional/build-hook.nix index 1f0e17a3b..99a13aee4 100644 --- a/tests/functional/build-hook.nix +++ b/tests/functional/build-hook.nix @@ -1,6 +1,6 @@ { busybox, contentAddressed ? false }: -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; let diff --git a/tests/functional/ca/config.nix b/tests/functional/ca/config.nix new file mode 100644 index 000000000..451fbae4f --- /dev/null +++ b/tests/functional/ca/config.nix @@ -0,0 +1,2 @@ +# Shim to get generated file +import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/ca/config.nix" diff --git a/tests/functional/ca/content-addressed.nix b/tests/functional/ca/content-addressed.nix index 411ebb86b..2559c562f 100644 --- a/tests/functional/ca/content-addressed.nix +++ b/tests/functional/ca/content-addressed.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/ca/config.nix"; +with import ./config.nix; let mkCADerivation = args: mkDerivation ({ __contentAddressed = true; diff --git a/tests/functional/ca/nix-run.sh b/tests/functional/ca/nix-run.sh index 21c09117e..e6638cc91 100755 --- a/tests/functional/ca/nix-run.sh +++ b/tests/functional/ca/nix-run.sh @@ -6,7 +6,4 @@ flakeDir="$TEST_HOME/flake" mkdir -p "${flakeDir}" cp flake.nix "${_NIX_TEST_BUILD_DIR}/ca/config.nix" content-addressed.nix "${flakeDir}" -# `config.nix` cannot be gotten via build dir / env var (runs afoul pure eval). Instead get from flake. -removeBuildDirRef "$flakeDir"/*.nix - nix run --no-write-lock-file "path:${flakeDir}#runnable" diff --git a/tests/functional/ca/nondeterministic.nix b/tests/functional/ca/nondeterministic.nix index 740be4bd2..d6d099a3e 100644 --- a/tests/functional/ca/nondeterministic.nix +++ b/tests/functional/ca/nondeterministic.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/ca/config.nix"; +with import ./config.nix; let mkCADerivation = args: mkDerivation ({ __contentAddressed = true; diff --git a/tests/functional/ca/racy.nix b/tests/functional/ca/racy.nix index cadd98675..555a15484 100644 --- a/tests/functional/ca/racy.nix +++ b/tests/functional/ca/racy.nix @@ -2,7 +2,7 @@ # build it at once. -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/ca/config.nix"; +with import ./config.nix; mkDerivation { name = "simple"; diff --git a/tests/functional/check-refs.nix b/tests/functional/check-refs.nix index 54957f635..89690e456 100644 --- a/tests/functional/check-refs.nix +++ b/tests/functional/check-refs.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; rec { diff --git a/tests/functional/check-reqs.nix b/tests/functional/check-reqs.nix index 4e059f5a4..41436cb48 100644 --- a/tests/functional/check-reqs.nix +++ b/tests/functional/check-reqs.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; rec { dep1 = mkDerivation { diff --git a/tests/functional/check.nix b/tests/functional/check.nix index 13638eae8..ddab8eea9 100644 --- a/tests/functional/check.nix +++ b/tests/functional/check.nix @@ -1,6 +1,6 @@ {checkBuildId ? 0}: -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; { nondeterministic = mkDerivation { diff --git a/tests/functional/chroot-store.sh b/tests/functional/chroot-store.sh index 8c2a969d3..46e91f0aa 100755 --- a/tests/functional/chroot-store.sh +++ b/tests/functional/chroot-store.sh @@ -39,9 +39,6 @@ EOF cp simple.nix shell.nix simple.builder.sh "${config_nix}" "$flakeDir/" - # `config.nix` cannot be gotten via build dir / env var (runs afoul pure eval). Instead get from flake. - removeBuildDirRef "$flakeDir"/*.nix - TODO_NixOS outPath=$(nix build --print-out-paths --no-link --sandbox-paths '/nix? /bin? /lib? /lib64? /usr?' --store "$TEST_ROOT/x" path:"$flakeDir") diff --git a/tests/functional/common/functions.sh b/tests/functional/common/functions.sh index 286bb58e8..7195149cb 100644 --- a/tests/functional/common/functions.sh +++ b/tests/functional/common/functions.sh @@ -343,15 +343,6 @@ count() { echo $# } -# Sometimes, e.g. due to pure eval, restricted eval, or sandboxing, we -# cannot look up `config.nix` in the build dir, and have to instead get -# it from the current directory. (In this case, the current directly -# will be somewhere in `$TEST_ROOT`.) -removeBuildDirRef() { - # shellcheck disable=SC2016 # The ${} in this is Nix, not shell - sed -i -e 's,"${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/[^ ]*config.nix",./config.nix,' "$@" -} - trap onError ERR fi # COMMON_FUNCTIONS_SH_SOURCED diff --git a/tests/functional/config.nix b/tests/functional/config.nix new file mode 100644 index 000000000..5d1cb74ec --- /dev/null +++ b/tests/functional/config.nix @@ -0,0 +1,2 @@ +# Shim to get generated file +import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix" diff --git a/tests/functional/dependencies.nix b/tests/functional/dependencies.nix index db06321da..be1a7ae9a 100644 --- a/tests/functional/dependencies.nix +++ b/tests/functional/dependencies.nix @@ -1,5 +1,5 @@ { hashInvalidator ? "" }: -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; let { diff --git a/tests/functional/dyn-drv/config.nix b/tests/functional/dyn-drv/config.nix new file mode 100644 index 000000000..8ec2c67ea --- /dev/null +++ b/tests/functional/dyn-drv/config.nix @@ -0,0 +1,2 @@ +# Shim to get generated file +import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/dyn-drv/config.nix" diff --git a/tests/functional/dyn-drv/old-daemon-error-hack.nix b/tests/functional/dyn-drv/old-daemon-error-hack.nix index 7d3ccf7e4..c9d4a62d4 100644 --- a/tests/functional/dyn-drv/old-daemon-error-hack.nix +++ b/tests/functional/dyn-drv/old-daemon-error-hack.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/dyn-drv/config.nix"; +with import ./config.nix; # A simple content-addressed derivation. # The derivation can be arbitrarily modified by passing a different `seed`, diff --git a/tests/functional/dyn-drv/recursive-mod-json.nix b/tests/functional/dyn-drv/recursive-mod-json.nix index 0e778aa7f..c6a24ca4f 100644 --- a/tests/functional/dyn-drv/recursive-mod-json.nix +++ b/tests/functional/dyn-drv/recursive-mod-json.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/dyn-drv/config.nix"; +with import ./config.nix; let innerName = "foo"; in diff --git a/tests/functional/dyn-drv/text-hashed-output.nix b/tests/functional/dyn-drv/text-hashed-output.nix index aa46fff61..99203b518 100644 --- a/tests/functional/dyn-drv/text-hashed-output.nix +++ b/tests/functional/dyn-drv/text-hashed-output.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/dyn-drv/config.nix"; +with import ./config.nix; # A simple content-addressed derivation. # The derivation can be arbitrarily modified by passing a different `seed`, diff --git a/tests/functional/export-graph.nix b/tests/functional/export-graph.nix index 97ffe73a9..64fe36bd1 100644 --- a/tests/functional/export-graph.nix +++ b/tests/functional/export-graph.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; rec { diff --git a/tests/functional/extra-sandbox-profile.nix b/tests/functional/extra-sandbox-profile.nix index 5f0e4753f..aa680b918 100644 --- a/tests/functional/extra-sandbox-profile.nix +++ b/tests/functional/extra-sandbox-profile.nix @@ -1,6 +1,6 @@ { destFile, seed }: -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; mkDerivation { name = "simple"; diff --git a/tests/functional/failing.nix b/tests/functional/failing.nix index 8b7990679..d25e2d6b6 100644 --- a/tests/functional/failing.nix +++ b/tests/functional/failing.nix @@ -1,5 +1,5 @@ { busybox }: -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; let mkDerivation = args: diff --git a/tests/functional/filter-source.nix b/tests/functional/filter-source.nix index dcef9c4e2..907163639 100644 --- a/tests/functional/filter-source.nix +++ b/tests/functional/filter-source.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; mkDerivation { name = "filter"; diff --git a/tests/functional/fixed.nix b/tests/functional/fixed.nix index f70b89091..a920a2167 100644 --- a/tests/functional/fixed.nix +++ b/tests/functional/fixed.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; rec { diff --git a/tests/functional/flakes/bundle.sh b/tests/functional/flakes/bundle.sh index 61aa040e7..2946aea35 100755 --- a/tests/functional/flakes/bundle.sh +++ b/tests/functional/flakes/bundle.sh @@ -4,9 +4,6 @@ source common.sh cp ../simple.nix ../simple.builder.sh "${config_nix}" "$TEST_HOME" -# `config.nix` cannot be gotten via build dir / env var (runs afoul pure eval). Instead get from flake. -removeBuildDirRef "$TEST_HOME"/*.nix - cd "$TEST_HOME" cat < flake.nix diff --git a/tests/functional/flakes/common.sh b/tests/functional/flakes/common.sh index 8af72f2ad..cc9b2e466 100644 --- a/tests/functional/flakes/common.sh +++ b/tests/functional/flakes/common.sh @@ -35,9 +35,6 @@ writeSimpleFlake() { EOF cp ../simple.nix ../shell.nix ../simple.builder.sh "${config_nix}" "$flakeDir/" - - # `config.nix` cannot be gotten via build dir / env var (runs afoul pure eval). Instead get from flake. - removeBuildDirRef "$flakeDir"/*.nix } createSimpleGitFlake() { diff --git a/tests/functional/flakes/config.sh b/tests/functional/flakes/config.sh index 48f1c7a85..ab2d9f47c 100755 --- a/tests/functional/flakes/config.sh +++ b/tests/functional/flakes/config.sh @@ -3,7 +3,6 @@ source common.sh cp ../simple.nix ../simple.builder.sh "${config_nix}" $TEST_HOME -removeBuildDirRef "$TEST_HOME/simple.nix" cd $TEST_HOME diff --git a/tests/functional/flakes/develop.sh b/tests/functional/flakes/develop.sh index 2e75081d4..b3e438e99 100755 --- a/tests/functional/flakes/develop.sh +++ b/tests/functional/flakes/develop.sh @@ -27,9 +27,6 @@ EOF mkdir -p "$TEST_HOME/nixpkgs" cp "${config_nix}" ../shell.nix "$TEST_HOME/nixpkgs" -# `config.nix` cannot be gotten via build dir / env var (runs afoul pure eval). Instead get from flake. -removeBuildDirRef "$TEST_HOME/nixpkgs"/*.nix - cat <"$TEST_HOME/nixpkgs/flake.nix" { outputs = {self}: { diff --git a/tests/functional/flakes/run.sh b/tests/functional/flakes/run.sh index 2077c965b..c92ddca2b 100755 --- a/tests/functional/flakes/run.sh +++ b/tests/functional/flakes/run.sh @@ -8,8 +8,6 @@ clearStore rm -rf $TEST_HOME/.cache $TEST_HOME/.config $TEST_HOME/.local cp ../shell-hello.nix "${config_nix}" $TEST_HOME -# `config.nix` cannot be gotten via build dir / env var (runs afoul pure eval). Instead get from flake. -removeBuildDirRef "$TEST_HOME"/*.nix cd $TEST_HOME cat < flake.nix diff --git a/tests/functional/fod-failing.nix b/tests/functional/fod-failing.nix index 7881a3fbf..37c04fe12 100644 --- a/tests/functional/fod-failing.nix +++ b/tests/functional/fod-failing.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; rec { x1 = mkDerivation { name = "x1"; diff --git a/tests/functional/gc-concurrent.nix b/tests/functional/gc-concurrent.nix index a5c3c97c3..0aba1f983 100644 --- a/tests/functional/gc-concurrent.nix +++ b/tests/functional/gc-concurrent.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; { lockFifo ? null }: diff --git a/tests/functional/gc-runtime.nix b/tests/functional/gc-runtime.nix index 2603fafdf..ee5980bdf 100644 --- a/tests/functional/gc-runtime.nix +++ b/tests/functional/gc-runtime.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; mkDerivation { name = "gc-runtime"; diff --git a/tests/functional/hermetic.nix b/tests/functional/hermetic.nix index dafe8ad9f..d1dccdff3 100644 --- a/tests/functional/hermetic.nix +++ b/tests/functional/hermetic.nix @@ -5,7 +5,7 @@ , withFinalRefs ? false }: -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; let contentAddressedByDefault = builtins.getEnv "NIX_TESTS_CA_BY_DEFAULT" == "1"; diff --git a/tests/functional/ifd.nix b/tests/functional/ifd.nix index c84ffbc66..d0b9b54ad 100644 --- a/tests/functional/ifd.nix +++ b/tests/functional/ifd.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; import ( mkDerivation { name = "foo"; diff --git a/tests/functional/import-from-derivation.nix b/tests/functional/import-from-derivation.nix index 8864fb30a..cc53451cf 100644 --- a/tests/functional/import-from-derivation.nix +++ b/tests/functional/import-from-derivation.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; rec { bar = mkDerivation { diff --git a/tests/functional/impure-derivations.nix b/tests/functional/impure-derivations.nix index 04710323f..98547e6c1 100644 --- a/tests/functional/impure-derivations.nix +++ b/tests/functional/impure-derivations.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; rec { diff --git a/tests/functional/impure-env.nix b/tests/functional/impure-env.nix index 6b9e5a825..2b0380ed7 100644 --- a/tests/functional/impure-env.nix +++ b/tests/functional/impure-env.nix @@ -1,6 +1,6 @@ { var, value }: -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; mkDerivation { name = "test"; diff --git a/tests/functional/linux-sandbox-cert-test.nix b/tests/functional/linux-sandbox-cert-test.nix index e506b6a0f..2fc083ea9 100644 --- a/tests/functional/linux-sandbox-cert-test.nix +++ b/tests/functional/linux-sandbox-cert-test.nix @@ -1,6 +1,6 @@ { mode }: -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; mkDerivation ( { diff --git a/tests/functional/multiple-outputs.nix b/tests/functional/multiple-outputs.nix index 19ae2a45d..6ba7c523d 100644 --- a/tests/functional/multiple-outputs.nix +++ b/tests/functional/multiple-outputs.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; rec { diff --git a/tests/functional/nar-access.nix b/tests/functional/nar-access.nix index 78972bd36..9948abe59 100644 --- a/tests/functional/nar-access.nix +++ b/tests/functional/nar-access.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; rec { a = mkDerivation { diff --git a/tests/functional/nix-build-examples.nix b/tests/functional/nix-build-examples.nix index aaea8fc07..e54dbbf62 100644 --- a/tests/functional/nix-build-examples.nix +++ b/tests/functional/nix-build-examples.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; rec { diff --git a/tests/functional/parallel.nix b/tests/functional/parallel.nix index 1f2411c92..23f142059 100644 --- a/tests/functional/parallel.nix +++ b/tests/functional/parallel.nix @@ -1,6 +1,6 @@ {sleepTime ? 3}: -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; let diff --git a/tests/functional/path.nix b/tests/functional/path.nix index b23300f90..883c3c41b 100644 --- a/tests/functional/path.nix +++ b/tests/functional/path.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; mkDerivation { name = "filter"; diff --git a/tests/functional/readfile-context.nix b/tests/functional/readfile-context.nix index b8f4a4c27..54cd1afd9 100644 --- a/tests/functional/readfile-context.nix +++ b/tests/functional/readfile-context.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; let diff --git a/tests/functional/restricted.sh b/tests/functional/restricted.sh index 63bf56cd7..00ee4ddc8 100755 --- a/tests/functional/restricted.sh +++ b/tests/functional/restricted.sh @@ -12,10 +12,6 @@ mkdir -p "$TEST_ROOT/nix" cp ./simple.nix "$TEST_ROOT/nix" cp ./simple.builder.sh "$TEST_ROOT/nix" cp "${config_nix}" "$TEST_ROOT/nix" -simple_nix="$TEST_ROOT/nix/simple.nix" -# N.B. redefine -config_nix="$TEST_ROOT/nix/config.nix" -removeBuildDirRef "${simple_nix}" cd "$TEST_ROOT/nix" nix-instantiate --restrict-eval ./simple.nix -I src=. diff --git a/tests/functional/search.nix b/tests/functional/search.nix index 3c3564bda..fea6e7a7a 100644 --- a/tests/functional/search.nix +++ b/tests/functional/search.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; { hello = mkDerivation rec { diff --git a/tests/functional/secure-drv-outputs.nix b/tests/functional/secure-drv-outputs.nix index cd111c315..b4ac8ff53 100644 --- a/tests/functional/secure-drv-outputs.nix +++ b/tests/functional/secure-drv-outputs.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; { diff --git a/tests/functional/shell-hello.nix b/tests/functional/shell-hello.nix index fa02e2bb4..c920d7cb4 100644 --- a/tests/functional/shell-hello.nix +++ b/tests/functional/shell-hello.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; rec { hello = mkDerivation { diff --git a/tests/functional/shell.nix b/tests/functional/shell.nix index f6622a487..9cae14b78 100644 --- a/tests/functional/shell.nix +++ b/tests/functional/shell.nix @@ -1,6 +1,6 @@ { inNixShell ? false, contentAddressed ? false, fooContents ? "foo" }: -let cfg = import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; in +let cfg = import ./config.nix; in with cfg; let diff --git a/tests/functional/simple-failing.nix b/tests/functional/simple-failing.nix index 228971734..d176c9c51 100644 --- a/tests/functional/simple-failing.nix +++ b/tests/functional/simple-failing.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; mkDerivation { name = "simple-failing"; diff --git a/tests/functional/simple.nix b/tests/functional/simple.nix index 96237695c..2035ca294 100644 --- a/tests/functional/simple.nix +++ b/tests/functional/simple.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; mkDerivation { name = "simple"; diff --git a/tests/functional/structured-attrs-shell.nix b/tests/functional/structured-attrs-shell.nix index 7ed28c03f..57c1e6bd2 100644 --- a/tests/functional/structured-attrs-shell.nix +++ b/tests/functional/structured-attrs-shell.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; let dep = mkDerivation { name = "dep"; diff --git a/tests/functional/structured-attrs.nix b/tests/functional/structured-attrs.nix index ae461c21a..e93139a44 100644 --- a/tests/functional/structured-attrs.nix +++ b/tests/functional/structured-attrs.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; let diff --git a/tests/functional/symlink-derivation.nix b/tests/functional/symlink-derivation.nix index 96765d355..e9a74cdce 100644 --- a/tests/functional/symlink-derivation.nix +++ b/tests/functional/symlink-derivation.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; let foo_in_store = builtins.toFile "foo" "foo"; diff --git a/tests/functional/timeout.nix b/tests/functional/timeout.nix index ad71e61e2..d0e949e31 100644 --- a/tests/functional/timeout.nix +++ b/tests/functional/timeout.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; { diff --git a/tests/functional/user-envs.nix b/tests/functional/user-envs.nix index c8e846d4b..46f8b51dd 100644 --- a/tests/functional/user-envs.nix +++ b/tests/functional/user-envs.nix @@ -2,7 +2,7 @@ { foo ? "foo" }: -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; assert foo == "foo"; From 388271e8ec6f5057bc8d39865fcc280e044b2844 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 6 Nov 2024 23:52:48 +0100 Subject: [PATCH 395/718] initRepoAtomically: Catch directory_not_empty --- src/libfetchers/git-utils.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libfetchers/git-utils.cc b/src/libfetchers/git-utils.cc index 95ee33089..74e68fe12 100644 --- a/src/libfetchers/git-utils.cc +++ b/src/libfetchers/git-utils.cc @@ -217,8 +217,12 @@ static void initRepoAtomically(std::filesystem::path &path, bool bare) { try { std::filesystem::rename(tmpDir, path); } catch (std::filesystem::filesystem_error & e) { - if (e.code() == std::errc::file_exists) // Someone might race us to create the repository. + // Someone may race us to create the repository. + if (e.code() == std::errc::file_exists + // `path` may be attempted to be deleted by s::f::rename, in which case the code is: + || e.code() == std::errc::directory_not_empty) { return; + } else throw SysError("moving temporary git repository from %s to %s", tmpDir, path); } From ffc1b30f50654e64405c1d9bc97e28d666c1d492 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 6 Nov 2024 22:47:09 +0100 Subject: [PATCH 396/718] refact: Extract build-utils-meson/libatomic --- build-utils-meson/libatomic/meson.build | 8 ++++++++ src/libutil/meson.build | 9 +-------- 2 files changed, 9 insertions(+), 8 deletions(-) create mode 100644 build-utils-meson/libatomic/meson.build diff --git a/build-utils-meson/libatomic/meson.build b/build-utils-meson/libatomic/meson.build new file mode 100644 index 000000000..d16d23817 --- /dev/null +++ b/build-utils-meson/libatomic/meson.build @@ -0,0 +1,8 @@ + +# Check if -latomic is needed +# This is needed for std::atomic on some platforms +# We did not manage to test this reliably on all platforms, so we hardcode +# it for now. +if host_machine.cpu_family() == 'arm' + deps_other += cxx.find_library('atomic') +endif diff --git a/src/libutil/meson.build b/src/libutil/meson.build index 61806120f..a6dc86394 100644 --- a/src/libutil/meson.build +++ b/src/libutil/meson.build @@ -53,16 +53,9 @@ endforeach configdata.set('HAVE_DECL_AT_SYMLINK_NOFOLLOW', cxx.has_header_symbol('fcntl.h', 'AT_SYMLINK_NOFOLLOW').to_int()) +subdir('build-utils-meson/libatomic') subdir('build-utils-meson/threads') -# Check if -latomic is needed -# This is needed for std::atomic on some platforms -# We did not manage to test this reliably on all platforms, so we hardcode -# it for now. -if host_machine.cpu_family() == 'arm' - deps_other += cxx.find_library('atomic') -endif - if host_machine.system() == 'windows' socket = cxx.find_library('ws2_32') deps_other += socket From f4b05cf8ec1945266a261a6c36dce53e10b5e764 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 6 Nov 2024 22:48:09 +0100 Subject: [PATCH 397/718] fix: Build nix-store on arm with libatomic --- src/libstore/meson.build | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libstore/meson.build b/src/libstore/meson.build index 1d5f949af..101879e90 100644 --- a/src/libstore/meson.build +++ b/src/libstore/meson.build @@ -81,6 +81,7 @@ if host_machine.system() == 'windows' deps_other += [wsock32] endif +subdir('build-utils-meson/libatomic') subdir('build-utils-meson/threads') boost = dependency( From 67d231c0462dd53476342ed68032a930a9acaae5 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 7 Nov 2024 13:46:37 +0100 Subject: [PATCH 398/718] Revert "Merge pull request #11804 from obsidiansystems/remove-old-make" This reverts commit 619eeb658ab8ab6d7ec09d5f0c281f5ad1e10339, reversing changes made to 1af94bf4710f2937a511543e9d14815f3a67814c. --- .gitignore | 3 + Makefile | 129 +++ Makefile.config.in | 54 + config/install-sh | 527 ++++++++++ configure.ac | 456 +++++++++ doc/manual/local.mk | 236 +++++ flake.nix | 11 +- local.mk | 15 + m4/ax_cxx_compile_stdcxx.m4 | 951 ++++++++++++++++++ m4/ax_cxx_compile_stdcxx_17.m4 | 35 + maintainers/local.mk | 8 + misc/bash/local.mk | 1 + misc/fish/local.mk | 1 + misc/launchd/local.mk | 5 + misc/systemd/local.mk | 8 + misc/upstart/local.mk | 7 + misc/zsh/local.mk | 2 + mk/build-dir.mk | 10 + mk/clean.mk | 11 + mk/common-test.sh | 31 + mk/compilation-database.mk | 11 + mk/cxx-big-literal.mk | 5 + mk/debug-test.sh | 10 + mk/functions.mk | 14 + mk/install-dirs.mk | 11 + mk/install.mk | 62 ++ mk/lib.mk | 159 +++ mk/libraries.mk | 173 ++++ mk/patterns.mk | 41 + mk/platform.mk | 40 + mk/precompiled-headers.mk | 21 + mk/programs.mk | 98 ++ mk/run-test.sh | 38 + mk/templates.mk | 19 + mk/tests.mk | 30 + mk/tracing.mk | 18 + package.nix | 366 +++++++ packaging/components.nix | 8 +- packaging/dev-shell.nix | 7 +- packaging/hydra.nix | 15 +- scripts/local.mk | 13 + src/libcmd/local.mk | 15 + src/libcmd/nix-cmd.pc.in | 9 + src/libexpr-c/local.mk | 25 + src/libexpr-c/nix-expr-c.pc.in | 10 + src/libexpr-test-support/local.mk | 23 + src/libexpr-tests/local.mk | 45 + src/libexpr/local.mk | 50 + src/libexpr/nix-expr.pc.in | 10 + src/libexpr/package.nix | 4 - src/libfetchers-tests/local.mk | 37 + src/libfetchers/local.mk | 17 + src/libflake-tests/local.mk | 43 + src/libflake/flake/nix-flake.pc.in | 10 + src/libflake/local.mk | 22 + src/libmain/local.mk | 22 + src/libmain/nix-main.pc.in | 9 + src/libstore-c/local.mk | 21 + src/libstore-c/nix-store-c.pc.in | 9 + src/libstore-test-support/local.mk | 21 + src/libstore-tests/local.mk | 38 + src/libstore/local.mk | 103 ++ src/libstore/nix-store.pc.in | 10 + src/libutil-c/local.mk | 18 + src/libutil-c/nix-util-c.pc.in | 9 + src/libutil-test-support/local.mk | 19 + src/libutil-tests/local.mk | 37 + src/libutil/local.mk | 44 + src/libutil/nix-util.pc.in | 9 + src/nix/local.mk | 59 ++ src/perl/package.nix | 4 - tests/functional/build-hook-ca-fixed.nix | 2 +- tests/functional/build-hook.nix | 2 +- tests/functional/ca/config.nix | 2 - tests/functional/ca/content-addressed.nix | 2 +- tests/functional/ca/local.mk | 29 + tests/functional/ca/nix-run.sh | 3 + tests/functional/ca/nondeterministic.nix | 2 +- tests/functional/ca/racy.nix | 2 +- tests/functional/check-refs.nix | 2 +- tests/functional/check-reqs.nix | 2 +- tests/functional/check.nix | 2 +- tests/functional/chroot-store.sh | 3 + tests/functional/common/functions.sh | 9 + tests/functional/config.nix | 2 - tests/functional/dependencies.nix | 2 +- tests/functional/dyn-drv/config.nix | 2 - tests/functional/dyn-drv/local.mk | 15 + .../dyn-drv/old-daemon-error-hack.nix | 2 +- .../functional/dyn-drv/recursive-mod-json.nix | 2 +- .../functional/dyn-drv/text-hashed-output.nix | 2 +- tests/functional/export-graph.nix | 2 +- tests/functional/extra-sandbox-profile.nix | 2 +- tests/functional/failing.nix | 2 +- tests/functional/filter-source.nix | 2 +- tests/functional/fixed.nix | 2 +- tests/functional/flakes/bundle.sh | 3 + tests/functional/flakes/common.sh | 3 + tests/functional/flakes/config.sh | 1 + tests/functional/flakes/develop.sh | 3 + tests/functional/flakes/local.mk | 25 + tests/functional/flakes/run.sh | 2 + tests/functional/fod-failing.nix | 2 +- tests/functional/gc-concurrent.nix | 2 +- tests/functional/gc-runtime.nix | 2 +- tests/functional/git-hashing/local.mk | 7 + tests/functional/hermetic.nix | 2 +- tests/functional/ifd.nix | 2 +- tests/functional/import-from-derivation.nix | 2 +- tests/functional/impure-derivations.nix | 2 +- tests/functional/impure-env.nix | 2 +- tests/functional/linux-sandbox-cert-test.nix | 2 +- tests/functional/local-overlay-store/local.mk | 14 + tests/functional/local.mk | 146 +++ tests/functional/multiple-outputs.nix | 2 +- tests/functional/nar-access.nix | 2 +- tests/functional/nix-build-examples.nix | 2 +- tests/functional/parallel.nix | 2 +- tests/functional/path.nix | 2 +- tests/functional/plugins/local.mk | 11 + tests/functional/readfile-context.nix | 2 +- tests/functional/restricted.sh | 4 + tests/functional/search.nix | 2 +- tests/functional/secure-drv-outputs.nix | 2 +- tests/functional/shell-hello.nix | 2 +- tests/functional/shell.nix | 2 +- tests/functional/simple-failing.nix | 2 +- tests/functional/simple.nix | 2 +- tests/functional/structured-attrs-shell.nix | 2 +- tests/functional/structured-attrs.nix | 2 +- tests/functional/symlink-derivation.nix | 2 +- .../functional/test-libstoreconsumer/local.mk | 15 + tests/functional/timeout.nix | 2 +- tests/functional/user-envs.nix | 2 +- 134 files changed, 4722 insertions(+), 75 deletions(-) create mode 100644 Makefile create mode 100644 Makefile.config.in create mode 100755 config/install-sh create mode 100644 configure.ac create mode 100644 doc/manual/local.mk create mode 100644 local.mk create mode 100644 m4/ax_cxx_compile_stdcxx.m4 create mode 100644 m4/ax_cxx_compile_stdcxx_17.m4 create mode 100644 maintainers/local.mk create mode 100644 misc/bash/local.mk create mode 100644 misc/fish/local.mk create mode 100644 misc/launchd/local.mk create mode 100644 misc/systemd/local.mk create mode 100644 misc/upstart/local.mk create mode 100644 misc/zsh/local.mk create mode 100644 mk/build-dir.mk create mode 100644 mk/clean.mk create mode 100644 mk/common-test.sh create mode 100644 mk/compilation-database.mk create mode 100644 mk/cxx-big-literal.mk create mode 100755 mk/debug-test.sh create mode 100644 mk/functions.mk create mode 100644 mk/install-dirs.mk create mode 100644 mk/install.mk create mode 100644 mk/lib.mk create mode 100644 mk/libraries.mk create mode 100644 mk/patterns.mk create mode 100644 mk/platform.mk create mode 100644 mk/precompiled-headers.mk create mode 100644 mk/programs.mk create mode 100755 mk/run-test.sh create mode 100644 mk/templates.mk create mode 100644 mk/tests.mk create mode 100644 mk/tracing.mk create mode 100644 package.nix create mode 100644 scripts/local.mk create mode 100644 src/libcmd/local.mk create mode 100644 src/libcmd/nix-cmd.pc.in create mode 100644 src/libexpr-c/local.mk create mode 100644 src/libexpr-c/nix-expr-c.pc.in create mode 100644 src/libexpr-test-support/local.mk create mode 100644 src/libexpr-tests/local.mk create mode 100644 src/libexpr/local.mk create mode 100644 src/libexpr/nix-expr.pc.in create mode 100644 src/libfetchers-tests/local.mk create mode 100644 src/libfetchers/local.mk create mode 100644 src/libflake-tests/local.mk create mode 100644 src/libflake/flake/nix-flake.pc.in create mode 100644 src/libflake/local.mk create mode 100644 src/libmain/local.mk create mode 100644 src/libmain/nix-main.pc.in create mode 100644 src/libstore-c/local.mk create mode 100644 src/libstore-c/nix-store-c.pc.in create mode 100644 src/libstore-test-support/local.mk create mode 100644 src/libstore-tests/local.mk create mode 100644 src/libstore/local.mk create mode 100644 src/libstore/nix-store.pc.in create mode 100644 src/libutil-c/local.mk create mode 100644 src/libutil-c/nix-util-c.pc.in create mode 100644 src/libutil-test-support/local.mk create mode 100644 src/libutil-tests/local.mk create mode 100644 src/libutil/local.mk create mode 100644 src/libutil/nix-util.pc.in create mode 100644 src/nix/local.mk delete mode 100644 tests/functional/ca/config.nix create mode 100644 tests/functional/ca/local.mk delete mode 100644 tests/functional/config.nix delete mode 100644 tests/functional/dyn-drv/config.nix create mode 100644 tests/functional/dyn-drv/local.mk create mode 100644 tests/functional/flakes/local.mk create mode 100644 tests/functional/git-hashing/local.mk create mode 100644 tests/functional/local-overlay-store/local.mk create mode 100644 tests/functional/local.mk create mode 100644 tests/functional/plugins/local.mk create mode 100644 tests/functional/test-libstoreconsumer/local.mk diff --git a/.gitignore b/.gitignore index de1183977..11a80ab5b 100644 --- a/.gitignore +++ b/.gitignore @@ -102,6 +102,9 @@ perl/Makefile.config /tests/functional/restricted-innocent /tests/functional/shell /tests/functional/shell.drv +/tests/functional/config.nix +/tests/functional/ca/config.nix +/tests/functional/dyn-drv/config.nix /tests/functional/repl-result-out /tests/functional/debugger-test-out /tests/functional/test-libstoreconsumer/test-libstoreconsumer diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..ee1a0de31 --- /dev/null +++ b/Makefile @@ -0,0 +1,129 @@ +# External build directory support + +include mk/build-dir.mk + +-include $(buildprefix)Makefile.config +clean-files += $(buildprefix)Makefile.config + +# List makefiles + +include mk/platform.mk + +ifeq ($(ENABLE_BUILD), yes) +makefiles = \ + mk/precompiled-headers.mk \ + local.mk \ + src/libutil/local.mk \ + src/libstore/local.mk \ + src/libfetchers/local.mk \ + src/libmain/local.mk \ + src/libexpr/local.mk \ + src/libflake/local.mk \ + src/libcmd/local.mk \ + src/nix/local.mk \ + src/libutil-c/local.mk \ + src/libstore-c/local.mk \ + src/libexpr-c/local.mk + +ifdef HOST_UNIX +makefiles += \ + scripts/local.mk \ + maintainers/local.mk \ + misc/bash/local.mk \ + misc/fish/local.mk \ + misc/zsh/local.mk \ + misc/systemd/local.mk \ + misc/launchd/local.mk \ + misc/upstart/local.mk +endif +endif + +ifeq ($(ENABLE_UNIT_TESTS), yes) +makefiles += \ + src/libutil-tests/local.mk \ + src/libutil-test-support/local.mk \ + src/libstore-tests/local.mk \ + src/libstore-test-support/local.mk \ + src/libfetchers-tests/local.mk \ + src/libexpr-tests/local.mk \ + src/libexpr-test-support/local.mk \ + src/libflake-tests/local.mk +endif + +ifeq ($(ENABLE_FUNCTIONAL_TESTS), yes) +ifdef HOST_UNIX +makefiles += \ + tests/functional/local.mk \ + tests/functional/flakes/local.mk \ + tests/functional/ca/local.mk \ + tests/functional/git-hashing/local.mk \ + tests/functional/dyn-drv/local.mk \ + tests/functional/local-overlay-store/local.mk \ + tests/functional/test-libstoreconsumer/local.mk \ + tests/functional/plugins/local.mk +endif +endif + +# Some makefiles require access to built programs and must be included late. +makefiles-late = + +ifeq ($(ENABLE_DOC_GEN), yes) +makefiles-late += doc/manual/local.mk +endif + +# Miscellaneous global Flags + +OPTIMIZE = 1 + +ifeq ($(OPTIMIZE), 1) + GLOBAL_CXXFLAGS += -O3 $(CXXLTO) + GLOBAL_LDFLAGS += $(CXXLTO) +else + GLOBAL_CXXFLAGS += -O0 -U_FORTIFY_SOURCE + unexport NIX_HARDENING_ENABLE +endif + +ifdef HOST_WINDOWS + # Windows DLLs are stricter about symbol visibility than Unix shared + # objects --- see https://gcc.gnu.org/wiki/Visibility for details. + # This is a temporary sledgehammer to export everything like on Unix, + # and not detail with this yet. + # + # TODO do not do this, and instead do fine-grained export annotations. + GLOBAL_LDFLAGS += -Wl,--export-all-symbols + GLOBAL_CXXFLAGS += -D_WIN32_WINNT=0x0602 +endif + +GLOBAL_CXXFLAGS += -g -Wall -Wdeprecated-copy -Wignored-qualifiers -Wimplicit-fallthrough -Werror=unused-result -Werror=suggest-override -include $(buildprefix)config.h -std=c++2a -I src + +# Include the main lib, causing rules to be defined + +include mk/lib.mk + +# Fallback stub rules for better UX when things are disabled +# +# These must be defined after `mk/lib.mk`. Otherwise the first rule +# incorrectly becomes the default target. + +ifneq ($(ENABLE_UNIT_TESTS), yes) +.PHONY: check +check: + @echo "Unit tests are disabled. Configure without '--disable-unit-tests', or avoid calling 'make check'." + @exit 1 +endif + +ifneq ($(ENABLE_FUNCTIONAL_TESTS), yes) +.PHONY: installcheck +installcheck: + @echo "Functional tests are disabled. Configure without '--disable-functional-tests', or avoid calling 'make installcheck'." + @exit 1 +endif + +# Documentation fallback stub rules. + +ifneq ($(ENABLE_DOC_GEN), yes) +.PHONY: manual-html manpages +manual-html manpages: + @echo "Generated docs are disabled. Configure without '--disable-doc-gen', or avoid calling 'make manpages' and 'make manual-html'." + @exit 1 +endif diff --git a/Makefile.config.in b/Makefile.config.in new file mode 100644 index 000000000..3100d2073 --- /dev/null +++ b/Makefile.config.in @@ -0,0 +1,54 @@ +AR = @AR@ +BDW_GC_LIBS = @BDW_GC_LIBS@ +BOOST_LDFLAGS = @BOOST_LDFLAGS@ +BUILD_SHARED_LIBS = @BUILD_SHARED_LIBS@ +CC = @CC@ +CFLAGS = @CFLAGS@ +CXX = @CXX@ +CXXFLAGS = @CXXFLAGS@ +CXXLTO = @CXXLTO@ +EDITLINE_LIBS = @EDITLINE_LIBS@ +ENABLE_BUILD = @ENABLE_BUILD@ +ENABLE_DOC_GEN = @ENABLE_DOC_GEN@ +ENABLE_FUNCTIONAL_TESTS = @ENABLE_FUNCTIONAL_TESTS@ +ENABLE_S3 = @ENABLE_S3@ +ENABLE_UNIT_TESTS = @ENABLE_UNIT_TESTS@ +GTEST_LIBS = @GTEST_LIBS@ +HAVE_LIBCPUID = @HAVE_LIBCPUID@ +HAVE_SECCOMP = @HAVE_SECCOMP@ +HOST_OS = @host_os@ +INSTALL_UNIT_TESTS = @INSTALL_UNIT_TESTS@ +LDFLAGS = @LDFLAGS@ +LIBARCHIVE_LIBS = @LIBARCHIVE_LIBS@ +LIBBROTLI_LIBS = @LIBBROTLI_LIBS@ +LIBCURL_LIBS = @LIBCURL_LIBS@ +LIBGIT2_LIBS = @LIBGIT2_LIBS@ +LIBSECCOMP_LIBS = @LIBSECCOMP_LIBS@ +LOWDOWN_LIBS = @LOWDOWN_LIBS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +SHELL = @bash@ +SODIUM_LIBS = @SODIUM_LIBS@ +SQLITE3_LIBS = @SQLITE3_LIBS@ +bash = @bash@ +bindir = @bindir@ +checkbindir = @checkbindir@ +checklibdir = @checklibdir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +embedded_sandbox_shell = @embedded_sandbox_shell@ +exec_prefix = @exec_prefix@ +includedir = @includedir@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +lsof = @lsof@ +mandir = @mandir@ +pkglibdir = $(libdir)/$(PACKAGE_NAME) +prefix = @prefix@ +sandbox_shell = @sandbox_shell@ +storedir = @storedir@ +sysconfdir = @sysconfdir@ +system = @system@ diff --git a/config/install-sh b/config/install-sh new file mode 100755 index 000000000..377bb8687 --- /dev/null +++ b/config/install-sh @@ -0,0 +1,527 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2011-11-20.07; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# 'make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +nl=' +' +IFS=" "" $nl" + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit=${DOITPROG-} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +no_target_directory= + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) no_target_directory=true;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call 'install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names problematic for 'test' and other utilities. + case $src in + -* | [=\(\)!]) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + dst=$dst_arg + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; + esac + + eval "$initialize_posix_glob" + + oIFS=$IFS + IFS=/ + $posix_glob set -f + set fnord $dstdir + shift + $posix_glob set +f + IFS=$oIFS + + prefixes= + + for d + do + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + $posix_glob set +f && + + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/configure.ac b/configure.ac new file mode 100644 index 000000000..4df5c80f0 --- /dev/null +++ b/configure.ac @@ -0,0 +1,456 @@ +AC_INIT([nix],[m4_esyscmd(bash -c "echo -n $(cat ./.version)$VERSION_SUFFIX")]) +AC_CONFIG_MACRO_DIRS([m4]) +AC_CONFIG_SRCDIR(README.md) +AC_CONFIG_AUX_DIR(config) + +AC_PROG_SED + +# Construct a Nix system name (like "i686-linux"): +# https://www.gnu.org/software/autoconf/manual/html_node/Canonicalizing.html#index-AC_005fCANONICAL_005fHOST-1 +# The inital value is produced by the `config/config.guess` script: +# upstream: https://git.savannah.gnu.org/cgit/config.git/tree/config.guess +# It has the following form, which is not documented anywhere: +# --[][-] +# If `./configure` is passed any of the `--host`, `--build`, `--target` options, the value comes from `config/config.sub` instead: +# upstream: https://git.savannah.gnu.org/cgit/config.git/tree/config.sub +AC_CANONICAL_HOST +AC_MSG_CHECKING([for the canonical Nix system name]) + +AC_ARG_WITH(system, AS_HELP_STRING([--with-system=SYSTEM],[Platform identifier (e.g., `i686-linux').]), + [system=$withval], + [case "$host_cpu" in + i*86) + machine_name="i686";; + amd64) + machine_name="x86_64";; + armv6|armv7) + machine_name="${host_cpu}l";; + *) + machine_name="$host_cpu";; + esac + + case "$host_os" in + linux-gnu*|linux-musl*) + # For backward compatibility, strip the `-gnu' part. + system="$machine_name-linux";; + *) + # Strip the version number from names such as `gnu0.3', + # `darwin10.2.0', etc. + system="$machine_name-`echo $host_os | "$SED" -e's/@<:@0-9.@:>@*$//g'`";; + esac]) + +AC_MSG_RESULT($system) +AC_SUBST(system) +AC_DEFINE_UNQUOTED(SYSTEM, ["$system"], [platform identifier ('cpu-os')]) + + +# State should be stored in /nix/var, unless the user overrides it explicitly. +test "$localstatedir" = '${prefix}/var' && localstatedir=/nix/var + +# Assign a default value to C{,XX}FLAGS as the default configure script sets them +# to -O2 otherwise, which we don't want to have hardcoded +CFLAGS=${CFLAGS-""} +CXXFLAGS=${CXXFLAGS-""} + +AC_PROG_CC +AC_PROG_CXX +AC_PROG_CPP + +AC_CHECK_TOOL([AR], [ar]) + +# Use 64-bit file system calls so that we can support files > 2 GiB. +AC_SYS_LARGEFILE + + +# OS-specific stuff. +case "$host_os" in + solaris*) + # Solaris requires -lsocket -lnsl for network functions + LDFLAGS="-lsocket -lnsl $LDFLAGS" + ;; + darwin*) + # Need to link to libsandbox. + LDFLAGS="-lsandbox $LDFLAGS" + ;; +esac + + +ENSURE_NO_GCC_BUG_80431 + + +# Check for pubsetbuf. +AC_MSG_CHECKING([for pubsetbuf]) +AC_LANG_PUSH(C++) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include +using namespace std; +static char buf[1024];]], + [[cerr.rdbuf()->pubsetbuf(buf, sizeof(buf));]])], + [AC_MSG_RESULT(yes) AC_DEFINE(HAVE_PUBSETBUF, 1, [Whether pubsetbuf is available.])], + AC_MSG_RESULT(no)) +AC_LANG_POP(C++) + + +AC_CHECK_FUNCS([statvfs pipe2 close_range]) + + +# Check for lutimes and utimensat, optionally used for changing the +# mtime of symlinks. +AC_CHECK_DECLS([AT_SYMLINK_NOFOLLOW], [], [], [[#include ]]) +AC_CHECK_FUNCS([lutimes utimensat]) + + +# Check whether the store optimiser can optimise symlinks. +AC_MSG_CHECKING([whether it is possible to create a link to a symlink]) +ln -s bla tmp_link +if ln tmp_link tmp_link2 2> /dev/null; then + AC_MSG_RESULT(yes) + AC_DEFINE(CAN_LINK_SYMLINK, 1, [Whether link() works on symlinks.]) +else + AC_MSG_RESULT(no) +fi +rm -f tmp_link tmp_link2 + + +# Check for . +AC_LANG_PUSH(C++) +AC_CHECK_HEADERS([locale]) +AC_LANG_POP(C++) + + +AC_DEFUN([NEED_PROG], +[ +AC_PATH_PROG($1, $2) +if test -z "$$1"; then + AC_MSG_ERROR([$2 is required]) +fi +]) + +NEED_PROG(bash, bash) +AC_PATH_PROG(flex, flex, false) +AC_PATH_PROG(bison, bison, false) +AC_PATH_PROG(dot, dot) +AC_PATH_PROG(lsof, lsof, lsof) + + +AC_SUBST(coreutils, [$(dirname $(type -p cat))]) + + +AC_ARG_WITH(store-dir, AS_HELP_STRING([--with-store-dir=PATH],[path of the Nix store (defaults to /nix/store)]), + storedir=$withval, storedir='/nix/store') +AC_SUBST(storedir) + + +# Running the functional tests without building Nix is useful for testing +# different pre-built versions of Nix against each other. +AC_ARG_ENABLE(build, AS_HELP_STRING([--disable-build],[Do not build nix]), + ENABLE_BUILD=$enableval, ENABLE_BUILD=yes) +AC_SUBST(ENABLE_BUILD) + +# Building without unit tests is useful for bootstrapping with a smaller footprint +# or running the tests in a separate derivation. Otherwise, we do compile and +# run them. + +AC_ARG_ENABLE(unit-tests, AS_HELP_STRING([--disable-unit-tests],[Do not build the tests]), + ENABLE_UNIT_TESTS=$enableval, ENABLE_UNIT_TESTS=$ENABLE_BUILD) +AC_SUBST(ENABLE_UNIT_TESTS) + +AS_IF( + [test "$ENABLE_BUILD" == "no" && test "$ENABLE_UNIT_TESTS" == "yes"], + [AC_MSG_ERROR([Cannot enable unit tests when building overall is disabled. Please do not pass '--enable-unit-tests' or do not pass '--disable-build'.])]) + +AC_ARG_ENABLE(functional-tests, AS_HELP_STRING([--disable-functional-tests],[Do not build the tests]), + ENABLE_FUNCTIONAL_TESTS=$enableval, ENABLE_FUNCTIONAL_TESTS=yes) +AC_SUBST(ENABLE_FUNCTIONAL_TESTS) + +# documentation generation switch +AC_ARG_ENABLE(doc-gen, AS_HELP_STRING([--disable-doc-gen],[disable documentation generation]), + ENABLE_DOC_GEN=$enableval, ENABLE_DOC_GEN=$ENABLE_BUILD) +AC_SUBST(ENABLE_DOC_GEN) + +AS_IF( + [test "$ENABLE_BUILD" == "no" && test "$ENABLE_DOC_GEN" == "yes"], + [AC_MSG_ERROR([Cannot enable generated docs when building overall is disabled. Please do not pass '--enable-doc-gen' or do not pass '--disable-build'.])]) + +AS_IF( + [test "$ENABLE_FUNCTIONAL_TESTS" == "yes" || test "$ENABLE_DOC_GEN" == "yes"], + [NEED_PROG(jq, jq)]) + +AS_IF( + [test "$ENABLE_DOC_GEN" == "yes"], + [NEED_PROG(man, man)]) + +AS_IF([test "$ENABLE_BUILD" == "yes"],[ + +# Look for boost, a required dependency. +# Note that AX_BOOST_BASE only exports *CPP* BOOST_CPPFLAGS, no CXX flags, +# and CPPFLAGS are not passed to the C++ compiler automatically. +# Thus we append the returned CPPFLAGS to the CXXFLAGS here. +AX_BOOST_BASE([1.66], [CXXFLAGS="$BOOST_CPPFLAGS $CXXFLAGS"], [AC_MSG_ERROR([Nix requires boost.])]) +# For unknown reasons, setting this directly in the ACTION-IF-FOUND above +# ends up with LDFLAGS being empty, so we set it afterwards. +LDFLAGS="$BOOST_LDFLAGS $LDFLAGS" + +# On some platforms, new-style atomics need a helper library +AC_MSG_CHECKING(whether -latomic is needed) +AC_LINK_IFELSE([AC_LANG_SOURCE([[ +#include +uint64_t v; +int main() { + return (int)__atomic_load_n(&v, __ATOMIC_ACQUIRE); +}]])], GCC_ATOMIC_BUILTINS_NEED_LIBATOMIC=no, GCC_ATOMIC_BUILTINS_NEED_LIBATOMIC=yes) +AC_MSG_RESULT($GCC_ATOMIC_BUILTINS_NEED_LIBATOMIC) +if test "x$GCC_ATOMIC_BUILTINS_NEED_LIBATOMIC" = xyes; then + LDFLAGS="-latomic $LDFLAGS" +fi + +AC_ARG_ENABLE(install-unit-tests, AS_HELP_STRING([--enable-install-unit-tests],[Install the unit tests for running later (default no)]), + INSTALL_UNIT_TESTS=$enableval, INSTALL_UNIT_TESTS=no) +AC_SUBST(INSTALL_UNIT_TESTS) + +AC_ARG_WITH(check-bin-dir, AS_HELP_STRING([--with-check-bin-dir=PATH],[path to install unit tests for running later (defaults to $libexecdir/nix)]), + checkbindir=$withval, checkbindir=$libexecdir/nix) +AC_SUBST(checkbindir) + +AC_ARG_WITH(check-lib-dir, AS_HELP_STRING([--with-check-lib-dir=PATH],[path to install unit tests for running later (defaults to $libdir)]), + checklibdir=$withval, checklibdir=$libdir) +AC_SUBST(checklibdir) + +# LTO is currently broken with clang for unknown reasons; ld segfaults in the llvm plugin +AC_ARG_ENABLE(lto, AS_HELP_STRING([--enable-lto],[Enable LTO (only supported with GCC) [default=no]]), + lto=$enableval, lto=no) +if test "$lto" = yes; then + if $CXX --version | grep -q GCC; then + AC_SUBST(CXXLTO, [-flto=jobserver]) + else + echo "error: LTO is only supported with GCC at the moment" >&2 + exit 1 + fi +else + AC_SUBST(CXXLTO, [""]) +fi + +PKG_PROG_PKG_CONFIG + +AC_ARG_ENABLE(shared, AS_HELP_STRING([--enable-shared],[Build shared libraries for Nix [default=yes]]), + shared=$enableval, shared=yes) +if test "$shared" = yes; then + AC_SUBST(BUILD_SHARED_LIBS, 1, [Whether to build shared libraries.]) +else + AC_SUBST(BUILD_SHARED_LIBS, 0, [Whether to build shared libraries.]) + PKG_CONFIG="$PKG_CONFIG --static" +fi + +# Look for OpenSSL, a required dependency. FIXME: this is only (maybe) +# used by S3BinaryCacheStore. +PKG_CHECK_MODULES([OPENSSL], [libcrypto >= 1.1.1], [CXXFLAGS="$OPENSSL_CFLAGS $CXXFLAGS"]) + + +# Look for libarchive. +PKG_CHECK_MODULES([LIBARCHIVE], [libarchive >= 3.1.2], [CXXFLAGS="$LIBARCHIVE_CFLAGS $CXXFLAGS"]) +# Workaround until https://github.com/libarchive/libarchive/issues/1446 is fixed +if test "$shared" != yes; then + LIBARCHIVE_LIBS+=' -lz' +fi + +# Look for SQLite, a required dependency. +PKG_CHECK_MODULES([SQLITE3], [sqlite3 >= 3.6.19], [CXXFLAGS="$SQLITE3_CFLAGS $CXXFLAGS"]) + +# Look for libcurl, a required dependency. +PKG_CHECK_MODULES([LIBCURL], [libcurl], [CXXFLAGS="$LIBCURL_CFLAGS $CXXFLAGS"]) + +# Look for editline or readline, a required dependency. +# The the libeditline.pc file was added only in libeditline >= 1.15.2, +# see https://github.com/troglobit/editline/commit/0a8f2ef4203c3a4a4726b9dd1336869cd0da8607, +# Older versions are no longer supported. +AC_ARG_WITH( + [readline-flavor], + AS_HELP_STRING([--with-readline-flavor],[Which library to use for nice line editting with the Nix language REPL" [default=editline]]), + [readline_flavor=$withval], + [readline_flavor=editline]) +AS_CASE(["$readline_flavor"], + [editline], [ + readline_flavor_pc=libeditline + ], + [readline], [ + readline_flavor_pc=readline + AC_DEFINE([USE_READLINE], [1], [Use readline instead of editline]) + ], + [AC_MSG_ERROR([bad value "$readline_flavor" for --with-readline-flavor, must be one of: editline, readline])]) +PKG_CHECK_MODULES([EDITLINE], [$readline_flavor_pc], [CXXFLAGS="$EDITLINE_CFLAGS $CXXFLAGS"]) + +# Look for libsodium. +PKG_CHECK_MODULES([SODIUM], [libsodium], [CXXFLAGS="$SODIUM_CFLAGS $CXXFLAGS"]) + +# Look for libbrotli{enc,dec}. +PKG_CHECK_MODULES([LIBBROTLI], [libbrotlienc libbrotlidec], [CXXFLAGS="$LIBBROTLI_CFLAGS $CXXFLAGS"]) + +# Look for libcpuid. +have_libcpuid= +if test "$machine_name" = "x86_64"; then + AC_ARG_ENABLE([cpuid], + AS_HELP_STRING([--disable-cpuid], [Do not determine microarchitecture levels with libcpuid (relevant to x86_64 only)])) + if test "x$enable_cpuid" != "xno"; then + PKG_CHECK_MODULES([LIBCPUID], [libcpuid], + [CXXFLAGS="$LIBCPUID_CFLAGS $CXXFLAGS" + have_libcpuid=1 + AC_DEFINE([HAVE_LIBCPUID], [1], [Use libcpuid])] + ) + fi +fi +AC_SUBST(HAVE_LIBCPUID, [$have_libcpuid]) + + +# Look for libseccomp, required for Linux sandboxing. +case "$host_os" in + linux*) + AC_ARG_ENABLE([seccomp-sandboxing], + AS_HELP_STRING([--disable-seccomp-sandboxing],[Don't build support for seccomp sandboxing (only recommended if your arch doesn't support libseccomp yet!) + ])) + if test "x$enable_seccomp_sandboxing" != "xno"; then + PKG_CHECK_MODULES([LIBSECCOMP], [libseccomp], + [CXXFLAGS="$LIBSECCOMP_CFLAGS $CXXFLAGS" CFLAGS="$LIBSECCOMP_CFLAGS $CFLAGS"]) + have_seccomp=1 + AC_DEFINE([HAVE_SECCOMP], [1], [Whether seccomp is available and should be used for sandboxing.]) + AC_COMPILE_IFELSE([ + AC_LANG_SOURCE([[ + #include + #ifndef __SNR_fchmodat2 + # error "Missing support for fchmodat2" + #endif + ]]) + ], [], [ + echo "libseccomp is missing __SNR_fchmodat2. Please provide libseccomp 2.5.5 or later" + exit 1 + ]) + else + have_seccomp= + fi + ;; + *) + have_seccomp= + ;; +esac +AC_SUBST(HAVE_SECCOMP, [$have_seccomp]) + +# Optional dependencies for better normalizing file system data +AC_CHECK_HEADERS([sys/xattr.h]) +AS_IF([test "$ac_cv_header_sys_xattr_h" = "yes"],[ + AC_CHECK_FUNCS([llistxattr lremovexattr]) + AS_IF([test "$ac_cv_func_llistxattr" = "yes" && test "$ac_cv_func_lremovexattr" = "yes"],[ + AC_DEFINE([HAVE_ACL_SUPPORT], [1], [Define if we can manipulate file system Access Control Lists]) + ]) +]) + +# Look for aws-cpp-sdk-s3. +AC_LANG_PUSH(C++) +AC_CHECK_HEADERS([aws/s3/S3Client.h], + [AC_DEFINE([ENABLE_S3], [1], [Whether to enable S3 support via aws-sdk-cpp.]) enable_s3=1], + [AC_DEFINE([ENABLE_S3], [0], [Whether to enable S3 support via aws-sdk-cpp.]) enable_s3=]) +AC_SUBST(ENABLE_S3, [$enable_s3]) +AC_LANG_POP(C++) + + +# Whether to use the Boehm garbage collector. +AC_ARG_ENABLE(gc, AS_HELP_STRING([--enable-gc],[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" + AC_DEFINE(HAVE_BOEHMGC, 1, [Whether to use the Boehm garbage collector.]) + + # See `fixupBoehmStackPointer`, for the integration between Boehm GC + # and Boost coroutines. + old_CFLAGS="$CFLAGS" + # Temporary set `-pthread` just for the next check + CFLAGS="$CFLAGS -pthread" + AC_CHECK_FUNCS([pthread_attr_get_np pthread_getattr_np]) + CFLAGS="$old_CFLAGS" +fi + +AS_IF([test "$ENABLE_UNIT_TESTS" == "yes"],[ + +# Look for gtest. +PKG_CHECK_MODULES([GTEST], [gtest_main gmock_main]) + +# Look for rapidcheck. +PKG_CHECK_MODULES([RAPIDCHECK], [rapidcheck rapidcheck_gtest]) + +]) + +# Look for nlohmann/json. +PKG_CHECK_MODULES([NLOHMANN_JSON], [nlohmann_json >= 3.9]) + + +# Look for lowdown library. +AC_ARG_ENABLE([markdown], AS_HELP_STRING([--enable-markdown], [Enable Markdown rendering in the Nix binary (requires lowdown) [default=auto]]), + enable_markdown=$enableval, enable_markdown=auto) +AS_CASE(["$enable_markdown"], + [yes | auto], [ + PKG_CHECK_MODULES([LOWDOWN], [lowdown >= 0.9.0], [ + CXXFLAGS="$LOWDOWN_CFLAGS $CXXFLAGS" + have_lowdown=1 + AC_DEFINE(HAVE_LOWDOWN, 1, [Whether lowdown is available and should be used for Markdown rendering.]) + ], [ + AS_IF([test "x$enable_markdown" == "xyes"], [AC_MSG_ERROR([--enable-markdown was specified, but lowdown was not found.])]) + ]) + ], + [no], [have_lowdown=], + [AC_MSG_ERROR([bad value "$enable_markdown" for --enable-markdown, must be one of: yes, no, auto])]) + + +# Look for libgit2. +PKG_CHECK_MODULES([LIBGIT2], [libgit2]) + + +# Look for toml11, a required dependency. +AC_LANG_PUSH(C++) +AC_CHECK_HEADER([toml.hpp], [], [AC_MSG_ERROR([toml11 is not found.])]) +AC_LANG_POP(C++) + +# Setuid installations. +AC_CHECK_FUNCS([setresuid setreuid lchown]) + + +# Nice to have, but not essential. +AC_CHECK_FUNCS([strsignal posix_fallocate sysconf]) + + +AC_ARG_WITH(sandbox-shell, AS_HELP_STRING([--with-sandbox-shell=PATH],[path of a statically-linked shell to use as /bin/sh in sandboxes]), + sandbox_shell=$withval) +AC_SUBST(sandbox_shell) +if test ${cross_compiling:-no} = no && ! test -z ${sandbox_shell+x}; then + AC_MSG_CHECKING([whether sandbox-shell has the standalone feature]) + # busybox shell sometimes allows executing other busybox applets, + # even if they are not in the path, breaking our sandbox + if PATH= $sandbox_shell -c "busybox" 2>&1 | grep -qv "not found"; then + AC_MSG_RESULT(enabled) + AC_MSG_ERROR([Please disable busybox FEATURE_SH_STANDALONE]) + else + AC_MSG_RESULT(disabled) + fi +fi + +AC_ARG_ENABLE(embedded-sandbox-shell, AS_HELP_STRING([--enable-embedded-sandbox-shell],[include the sandbox shell in the Nix binary [default=no]]), + embedded_sandbox_shell=$enableval, embedded_sandbox_shell=no) +AC_SUBST(embedded_sandbox_shell) +if test "$embedded_sandbox_shell" = yes; then + AC_DEFINE(HAVE_EMBEDDED_SANDBOX_SHELL, 1, [Include the sandbox shell in the Nix binary.]) +fi + +]) + + +# Expand all variables in config.status. +test "$prefix" = NONE && prefix=$ac_default_prefix +test "$exec_prefix" = NONE && exec_prefix='${prefix}' +for name in $ac_subst_vars; do + declare $name="$(eval echo "${!name}")" + declare $name="$(eval echo "${!name}")" + declare $name="$(eval echo "${!name}")" +done + +rm -f Makefile.config + +AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_FILES([]) +AC_OUTPUT diff --git a/doc/manual/local.mk b/doc/manual/local.mk new file mode 100644 index 000000000..36cccc506 --- /dev/null +++ b/doc/manual/local.mk @@ -0,0 +1,236 @@ +# The version of Nix used to generate the doc. Can also be +# `$(nix_INSTALL_PATH)` or just `nix` (to grap ambient from the `PATH`), +# if one prefers. +doc_nix = $(nix_PATH) + +MANUAL_SRCS := \ + $(call rwildcard, $(d)/source, *.md) \ + $(call rwildcard, $(d)/source, */*.md) + +man-pages := $(foreach n, \ + nix-env.1 nix-store.1 \ + nix-build.1 nix-shell.1 nix-instantiate.1 \ + nix-collect-garbage.1 \ + nix-prefetch-url.1 nix-channel.1 \ + nix-hash.1 nix-copy-closure.1 \ + nix.conf.5 nix-daemon.8 \ + nix-profiles.5 \ +, $(d)/$(n)) + +# man pages for subcommands +# convert from `$(d)/source/command-ref/nix-{1}/{2}.md` to `$(d)/nix-{1}-{2}.1` +# FIXME: unify with how nix3-cli man pages are generated +man-pages += $(foreach subcommand, \ + $(filter-out %opt-common.md %env-common.md, $(wildcard $(d)/source/command-ref/nix-*/*.md)), \ + $(d)/$(subst /,-,$(subst $(d)/source/command-ref/,,$(subst .md,.1,$(subcommand))))) + +clean-files += $(d)/*.1 $(d)/*.5 $(d)/*.8 + +# Provide a dummy environment for nix, so that it will not access files outside the macOS sandbox. +# Set cores to 0 because otherwise `nix config show` resolves the cores based on the current machine +dummy-env = env -i \ + HOME=/dummy \ + NIX_CONF_DIR=/dummy \ + NIX_SSL_CERT_FILE=/dummy/no-ca-bundle.crt \ + NIX_STATE_DIR=/dummy \ + NIX_CONFIG='cores = 0' + +nix-eval = $(dummy-env) $(doc_nix) eval --experimental-features nix-command -I nix=doc/manual --store dummy:// --impure --raw + +# re-implement mdBook's include directive to make it usable for terminal output and for proper @docroot@ substitution +define process-includes + while read -r line; do \ + set -euo pipefail; \ + filename="$$(dirname $(1))/$$(sed 's/{{#include \(.*\)}}/\1/'<<< $$line)"; \ + test -f "$$filename" || ( echo "#include-d file '$$filename' does not exist." >&2; exit 1; ); \ + matchline="$$(sed 's|/|\\/|g' <<< $$line)"; \ + sed -i "/$$matchline/r $$filename" $(2); \ + sed -i "s/$$matchline//" $(2); \ + done < <(grep '{{#include' $(1)) +endef + +$(d)/nix-env-%.1: $(d)/source/command-ref/nix-env/%.md + @printf "Title: %s\n\n" "$(subst nix-env-,nix-env --,$$(basename "$@" .1))" > $^.tmp + $(render-subcommand) + +$(d)/nix-store-%.1: $(d)/source/command-ref/nix-store/%.md + @printf -- 'Title: %s\n\n' "$(subst nix-store-,nix-store --,$$(basename "$@" .1))" > $^.tmp + $(render-subcommand) + +# FIXME: there surely is some more deduplication to be achieved here with even darker Make magic +define render-subcommand + @cat $^ >> $^.tmp + @$(call process-includes,$^,$^.tmp) + $(trace-gen) lowdown -sT man --nroff-nolinks -M section=1 $^.tmp -o $@ + @# fix up `lowdown`'s automatic escaping of `--` + @# https://github.com/kristapsdz/lowdown/blob/edca6ce6d5336efb147321a43c47a698de41bb7c/entity.c#L202 + @sed -i 's/\e\[u2013\]/--/' $@ + @rm $^.tmp +endef + + +$(d)/%.1: $(d)/source/command-ref/%.md + @printf "Title: %s\n\n" "$$(basename $@ .1)" > $^.tmp + @cat $^ >> $^.tmp + @$(call process-includes,$^,$^.tmp) + $(trace-gen) lowdown -sT man --nroff-nolinks -M section=1 $^.tmp -o $@ + @rm $^.tmp + +$(d)/%.8: $(d)/source/command-ref/%.md + @printf "Title: %s\n\n" "$$(basename $@ .8)" > $^.tmp + @cat $^ >> $^.tmp + $(trace-gen) lowdown -sT man --nroff-nolinks -M section=8 $^.tmp -o $@ + @rm $^.tmp + +$(d)/nix.conf.5: $(d)/source/command-ref/conf-file.md + @printf "Title: %s\n\n" "$$(basename $@ .5)" > $^.tmp + @cat $^ >> $^.tmp + @$(call process-includes,$^,$^.tmp) + $(trace-gen) lowdown -sT man --nroff-nolinks -M section=5 $^.tmp -o $@ + @rm $^.tmp + +$(d)/nix-profiles.5: $(d)/source/command-ref/files/profiles.md + @printf "Title: %s\n\n" "$$(basename $@ .5)" > $^.tmp + @cat $^ >> $^.tmp + $(trace-gen) lowdown -sT man --nroff-nolinks -M section=5 $^.tmp -o $@ + @rm $^.tmp + +$(d)/source/SUMMARY.md: $(d)/source/SUMMARY.md.in $(d)/source/SUMMARY-rl-next.md $(d)/source/store/types $(d)/source/command-ref/new-cli $(d)/source/development/experimental-feature-descriptions.md + @cp $< $@ + @$(call process-includes,$@,$@) + +$(d)/source/store/types: $(d)/nix.json $(d)/utils.nix $(d)/generate-store-info.nix $(d)/generate-store-types.nix $(d)/source/store/types/index.md.in $(doc_nix) + @# FIXME: build out of tree! + @rm -rf $@.tmp + $(trace-gen) $(nix-eval) --write-to $@.tmp --expr 'import doc/manual/generate-store-types.nix (builtins.fromJSON (builtins.readFile $<)).stores' + @# do not destroy existing contents + @mv $@.tmp/* $@/ + +$(d)/source/command-ref/new-cli: $(d)/nix.json $(d)/utils.nix $(d)/generate-manpage.nix $(d)/generate-settings.nix $(d)/generate-store-info.nix $(doc_nix) + @rm -rf $@ $@.tmp + $(trace-gen) $(nix-eval) --write-to $@.tmp --expr 'import doc/manual/generate-manpage.nix true (builtins.readFile $<)' + @mv $@.tmp $@ + +$(d)/source/command-ref/conf-file.md: $(d)/conf-file.json $(d)/utils.nix $(d)/generate-settings.nix $(d)/source/command-ref/conf-file-prefix.md $(d)/source/command-ref/experimental-features-shortlist.md $(doc_nix) + @cat doc/manual/source/command-ref/conf-file-prefix.md > $@.tmp + $(trace-gen) $(nix-eval) --expr 'import doc/manual/generate-settings.nix { prefix = "conf"; } (builtins.fromJSON (builtins.readFile $<))' >> $@.tmp; + @mv $@.tmp $@ + +$(d)/nix.json: $(doc_nix) + $(trace-gen) $(dummy-env) $(doc_nix) __dump-cli > $@.tmp + @mv $@.tmp $@ + +$(d)/conf-file.json: $(doc_nix) + $(trace-gen) $(dummy-env) $(doc_nix) config show --json --experimental-features nix-command > $@.tmp + @mv $@.tmp $@ + +$(d)/source/development/experimental-feature-descriptions.md: $(d)/xp-features.json $(d)/utils.nix $(d)/generate-xp-features.nix $(doc_nix) + @rm -rf $@ $@.tmp + $(trace-gen) $(nix-eval) --write-to $@.tmp --expr 'import doc/manual/generate-xp-features.nix (builtins.fromJSON (builtins.readFile $<))' + @mv $@.tmp $@ + +$(d)/source/command-ref/experimental-features-shortlist.md: $(d)/xp-features.json $(d)/utils.nix $(d)/generate-xp-features-shortlist.nix $(doc_nix) + @rm -rf $@ $@.tmp + $(trace-gen) $(nix-eval) --write-to $@.tmp --expr 'import doc/manual/generate-xp-features-shortlist.nix (builtins.fromJSON (builtins.readFile $<))' + @mv $@.tmp $@ + +$(d)/xp-features.json: $(doc_nix) + $(trace-gen) $(dummy-env) $(doc_nix) __dump-xp-features > $@.tmp + @mv $@.tmp $@ + +$(d)/source/language/builtins.md: $(d)/language.json $(d)/generate-builtins.nix $(d)/source/language/builtins-prefix.md $(doc_nix) + @cat doc/manual/source/language/builtins-prefix.md > $@.tmp + $(trace-gen) $(nix-eval) --expr 'import doc/manual/generate-builtins.nix (builtins.fromJSON (builtins.readFile $<))' >> $@.tmp; + @cat doc/manual/source/language/builtins-suffix.md >> $@.tmp + @mv $@.tmp $@ + +$(d)/language.json: $(doc_nix) + $(trace-gen) $(dummy-env) $(doc_nix) __dump-language > $@.tmp + @mv $@.tmp $@ + +# Generate "Upcoming release" notes (or clear it and remove from menu) +$(d)/source/release-notes/rl-next.md: $(d)/rl-next $(d)/rl-next/* + @if type -p changelog-d > /dev/null; then \ + echo " GEN " $@; \ + changelog-d doc/manual/rl-next > $@; \ + else \ + echo " NULL " $@; \ + true > $@; \ + fi + +$(d)/source/SUMMARY-rl-next.md: $(d)/source/release-notes/rl-next.md + $(trace-gen) true + @if [ -s $< ]; then \ + echo ' - [Upcoming release](release-notes/rl-next.md)' > $@; \ + else \ + true > $@; \ + fi + +# Generate the HTML manual. +.PHONY: manual-html +manual-html: $(docdir)/manual/index.html + +# Open the built HTML manual in the default browser. +manual-html-open: $(docdir)/manual/index.html + @echo " OPEN " $<; \ + xdg-open $< \ + || open $< \ + || { \ + echo "Could not open the manual in a browser. Please open '$<'" >&2; \ + false; \ + } +install: $(docdir)/manual/index.html + +# Generate 'nix' manpages. +.PHONY: manpages +manpages: $(mandir)/man1/nix3-manpages +install: $(mandir)/man1/nix3-manpages +man: doc/manual/generated/man1/nix3-manpages +all: doc/manual/generated/man1/nix3-manpages + +# FIXME: unify with how the other man pages are generated. +# this one works differently and does not use any of the amenities provided by `/mk/lib.mk`. +$(mandir)/man1/nix3-manpages: doc/manual/generated/man1/nix3-manpages + @mkdir -p $(DESTDIR)$$(dirname $@) + $(trace-install) install -m 0644 $$(dirname $<)/* $(DESTDIR)$$(dirname $@) + +doc/manual/generated/man1/nix3-manpages: $(d)/source/command-ref/new-cli + @mkdir -p $(DESTDIR)$$(dirname $@) + $(trace-gen) for i in doc/manual/source/command-ref/new-cli/*.md; do \ + name=$$(basename $$i .md); \ + tmpFile=$$(mktemp); \ + if [[ $$name = SUMMARY ]]; then continue; fi; \ + printf "Title: %s\n\n" "$$name" > $$tmpFile; \ + cat $$i >> $$tmpFile; \ + lowdown -sT man --nroff-nolinks -M section=1 $$tmpFile -o $(DESTDIR)$$(dirname $@)/$$name.1; \ + rm $$tmpFile; \ + done + @touch $@ + +# the `! -name 'documentation.md'` filter excludes the one place where +# `@docroot@` is to be preserved for documenting the mechanism +# FIXME: maybe contributing guides should live right next to the code +# instead of in the manual +$(docdir)/manual/index.html: $(MANUAL_SRCS) $(d)/book.toml $(d)/anchors.jq $(d)/custom.css $(d)/source/SUMMARY.md $(d)/source/store/types $(d)/source/command-ref/new-cli $(d)/source/development/experimental-feature-descriptions.md $(d)/source/command-ref/conf-file.md $(d)/source/language/builtins.md $(d)/source/release-notes/rl-next.md $(d)/source/figures $(d)/source/favicon.png $(d)/source/favicon.svg + $(trace-gen) \ + tmp="$$(mktemp -d)"; \ + cp -r doc/manual "$$tmp"; \ + find "$$tmp" -name '*.md' | while read -r file; do \ + $(call process-includes,$$file,$$file); \ + done; \ + find "$$tmp" -name '*.md' ! -name 'documentation.md' | while read -r file; do \ + docroot="$$(realpath --relative-to="$$(dirname "$$file")" $$tmp/manual/source)"; \ + sed -i "s,@docroot@,$$docroot,g" "$$file"; \ + done; \ + set -euo pipefail; \ + ( \ + cd "$$tmp/manual"; \ + RUST_LOG=warn \ + MDBOOK_SUBSTITUTE_SEARCH=$(d)/source \ + mdbook build -d $(DESTDIR)$(docdir)/manual.tmp 2>&1 \ + | { grep -Fv "because fragment resolution isn't implemented" || :; } \ + ); \ + rm -rf "$$tmp/manual" + @rm -rf $(DESTDIR)$(docdir)/manual + @mv $(DESTDIR)$(docdir)/manual.tmp/html $(DESTDIR)$(docdir)/manual + @rm -rf $(DESTDIR)$(docdir)/manual.tmp diff --git a/flake.nix b/flake.nix index 4d339f6e7..3ef027dd1 100644 --- a/flake.nix +++ b/flake.nix @@ -137,7 +137,7 @@ pkgs = final; }); - nix = final.nixComponents.nix-cli; + nix = final.nixComponents.nix; # See https://github.com/NixOS/nixpkgs/pull/214409 # Remove when fixed in this flake's nixpkgs @@ -189,6 +189,7 @@ # system, we should reenable this. #perlBindings = self.hydraJobs.perlBindings.${system}; } + /* # Add "passthru" tests // flatMapAttrs ({ "" = nixpkgsFor.${system}.native; @@ -210,6 +211,7 @@ "${nixpkgsPrefix}nix-functional-tests" = nixpkgs.nixComponents.nix-functional-tests; } ) + */ // devFlake.checks.${system} or {} ); @@ -218,8 +220,7 @@ # for which we don't apply the full build matrix such as cross or static. inherit (nixpkgsFor.${system}.native) changelog-d; - # TODO probably should be `nix-cli` - default = self.packages.${system}.nix-everything; + default = self.packages.${system}.nix-ng; nix-manual = nixpkgsFor.${system}.native.nixComponents.nix-manual; nix-internal-api-docs = nixpkgsFor.${system}.native.nixComponents.nix-internal-api-docs; nix-external-api-docs = nixpkgsFor.${system}.native.nixComponents.nix-external-api-docs; @@ -227,6 +228,7 @@ # We need to flatten recursive attribute sets of derivations to pass `flake check`. // flatMapAttrs { # Components we'll iterate over in the upcoming lambda + "nix" = { }; "nix-util" = { }; "nix-util-c" = { }; "nix-util-test-support" = { }; @@ -255,11 +257,10 @@ "nix-cli" = { }; - "nix-everything" = { }; - "nix-functional-tests" = { supportsCross = false; }; "nix-perl-bindings" = { supportsCross = false; }; + "nix-ng" = { }; } (pkgName: { supportsCross ? true }: { # These attributes go right into `packages.`. diff --git a/local.mk b/local.mk new file mode 100644 index 000000000..b27c7031e --- /dev/null +++ b/local.mk @@ -0,0 +1,15 @@ +GLOBAL_CXXFLAGS += -Wno-deprecated-declarations -Werror=switch +# Allow switch-enum to be overridden for files that do not support it, usually because of dependency headers. +ERROR_SWITCH_ENUM = -Werror=switch-enum + +$(foreach i, config.h $(wildcard src/lib*/*.hh) $(filter-out %_internal.h, $(wildcard src/lib*c/*.h)), \ + $(eval $(call install-file-in, $(i), $(includedir)/nix, 0644))) + +ifdef HOST_UNIX + $(foreach i, $(wildcard src/lib*/unix/*.hh), \ + $(eval $(call install-file-in, $(i), $(includedir)/nix, 0644))) +endif + +$(GCH): src/libutil/util.hh config.h + +GCH_CXXFLAGS = $(INCLUDE_libutil) diff --git a/m4/ax_cxx_compile_stdcxx.m4 b/m4/ax_cxx_compile_stdcxx.m4 new file mode 100644 index 000000000..43087b2e6 --- /dev/null +++ b/m4/ax_cxx_compile_stdcxx.m4 @@ -0,0 +1,951 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) +# +# DESCRIPTION +# +# Check for baseline language coverage in the compiler for the specified +# version of the C++ standard. If necessary, add switches to CXX and +# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard) +# or '14' (for the C++14 standard). +# +# The second argument, if specified, indicates whether you insist on an +# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. +# -std=c++11). If neither is specified, you get whatever works, with +# preference for an extended mode. +# +# The third argument, if specified 'mandatory' or if left unspecified, +# indicates that baseline support for the specified C++ standard is +# required and that the macro should error out if no mode with that +# support is found. If specified 'optional', then configuration proceeds +# regardless, after defining HAVE_CXX${VERSION} if and only if a +# supporting mode is found. +# +# LICENSE +# +# Copyright (c) 2008 Benjamin Kosnik +# Copyright (c) 2012 Zack Weinberg +# Copyright (c) 2013 Roy Stogner +# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov +# Copyright (c) 2015 Paul Norman +# Copyright (c) 2015 Moritz Klammler +# Copyright (c) 2016, 2018 Krzesimir Nowak +# Copyright (c) 2019 Enji Cooper +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 11 + +dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro +dnl (serial version number 13). + +AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl + m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"], + [$1], [14], [ax_cxx_compile_alternatives="14 1y"], + [$1], [17], [ax_cxx_compile_alternatives="17 1z"], + [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$2], [], [], + [$2], [ext], [], + [$2], [noext], [], + [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], + [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], + [$3], [optional], [ax_cxx_compile_cxx$1_required=false], + [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) + AC_LANG_PUSH([C++])dnl + ac_success=no + + m4_if([$2], [noext], [], [dnl + if test x$ac_success = xno; then + for alternative in ${ax_cxx_compile_alternatives}; do + switch="-std=gnu++${alternative}" + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, + $cachevar, + [ac_save_CXX="$CXX" + CXX="$CXX $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXX="$ac_save_CXX"]) + if eval test x\$$cachevar = xyes; then + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi + ac_success=yes + break + fi + done + fi]) + + m4_if([$2], [ext], [], [dnl + if test x$ac_success = xno; then + dnl HP's aCC needs +std=c++11 according to: + dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf + dnl Cray's crayCC needs "-h std=c++11" + for alternative in ${ax_cxx_compile_alternatives}; do + for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, + $cachevar, + [ac_save_CXX="$CXX" + CXX="$CXX $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXX="$ac_save_CXX"]) + if eval test x\$$cachevar = xyes; then + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi + ac_success=yes + break + fi + done + if test x$ac_success = xyes; then + break + fi + done + fi]) + AC_LANG_POP([C++]) + if test x$ax_cxx_compile_cxx$1_required = xtrue; then + if test x$ac_success = xno; then + AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) + fi + fi + if test x$ac_success = xno; then + HAVE_CXX$1=0 + AC_MSG_NOTICE([No compiler with C++$1 support was found]) + else + HAVE_CXX$1=1 + AC_DEFINE(HAVE_CXX$1,1, + [define if the compiler supports basic C++$1 syntax]) + fi + AC_SUBST(HAVE_CXX$1) +]) + + +dnl Test body for checking C++11 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 +) + + +dnl Test body for checking C++14 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 +) + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 +) + +dnl Tests for new features in C++11 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ + +// If the compiler admits that it is not ready for C++11, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201103L + +#error "This is not a C++11 compiler" + +#else + +namespace cxx11 +{ + + namespace test_static_assert + { + + template + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + } + + namespace test_final_override + { + + struct Base + { + virtual ~Base() {} + virtual void f() {} + }; + + struct Derived : public Base + { + virtual ~Derived() override {} + virtual void f() override {} + }; + + } + + namespace test_double_right_angle_brackets + { + + template < typename T > + struct check {}; + + typedef check single_type; + typedef check> double_type; + typedef check>> triple_type; + typedef check>>> quadruple_type; + + } + + namespace test_decltype + { + + int + f() + { + int a = 1; + decltype(a) b = 2; + return a + b; + } + + } + + namespace test_type_deduction + { + + template < typename T1, typename T2 > + struct is_same + { + static const bool value = false; + }; + + template < typename T > + struct is_same + { + static const bool value = true; + }; + + template < typename T1, typename T2 > + auto + add(T1 a1, T2 a2) -> decltype(a1 + a2) + { + return a1 + a2; + } + + int + test(const int c, volatile int v) + { + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == false, ""); + auto ac = c; + auto av = v; + auto sumi = ac + av + 'x'; + auto sumf = ac + av + 1.0; + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == true, ""); + return (sumf > 0.0) ? sumi : add(c, v); + } + + } + + namespace test_noexcept + { + + int f() { return 0; } + int g() noexcept { return 0; } + + static_assert(noexcept(f()) == false, ""); + static_assert(noexcept(g()) == true, ""); + + } + + namespace test_constexpr + { + + template < typename CharT > + unsigned long constexpr + strlen_c_r(const CharT *const s, const unsigned long acc) noexcept + { + return *s ? strlen_c_r(s + 1, acc + 1) : acc; + } + + template < typename CharT > + unsigned long constexpr + strlen_c(const CharT *const s) noexcept + { + return strlen_c_r(s, 0UL); + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("1") == 1UL, ""); + static_assert(strlen_c("example") == 7UL, ""); + static_assert(strlen_c("another\0example") == 7UL, ""); + + } + + namespace test_rvalue_references + { + + template < int N > + struct answer + { + static constexpr int value = N; + }; + + answer<1> f(int&) { return answer<1>(); } + answer<2> f(const int&) { return answer<2>(); } + answer<3> f(int&&) { return answer<3>(); } + + void + test() + { + int i = 0; + const int c = 0; + static_assert(decltype(f(i))::value == 1, ""); + static_assert(decltype(f(c))::value == 2, ""); + static_assert(decltype(f(0))::value == 3, ""); + } + + } + + namespace test_uniform_initialization + { + + struct test + { + static const int zero {}; + static const int one {1}; + }; + + static_assert(test::zero == 0, ""); + static_assert(test::one == 1, ""); + + } + + namespace test_lambdas + { + + void + test1() + { + auto lambda1 = [](){}; + auto lambda2 = lambda1; + lambda1(); + lambda2(); + } + + int + test2() + { + auto a = [](int i, int j){ return i + j; }(1, 2); + auto b = []() -> int { return '0'; }(); + auto c = [=](){ return a + b; }(); + auto d = [&](){ return c; }(); + auto e = [a, &b](int x) mutable { + const auto identity = [](int y){ return y; }; + for (auto i = 0; i < a; ++i) + a += b--; + return x + identity(a + b); + }(0); + return a + b + c + d + e; + } + + int + test3() + { + const auto nullary = [](){ return 0; }; + const auto unary = [](int x){ return x; }; + using nullary_t = decltype(nullary); + using unary_t = decltype(unary); + const auto higher1st = [](nullary_t f){ return f(); }; + const auto higher2nd = [unary](nullary_t f1){ + return [unary, f1](unary_t f2){ return f2(unary(f1())); }; + }; + return higher1st(nullary) + higher2nd(nullary)(unary); + } + + } + + namespace test_variadic_templates + { + + template + struct sum; + + template + struct sum + { + static constexpr auto value = N0 + sum::value; + }; + + template <> + struct sum<> + { + static constexpr auto value = 0; + }; + + static_assert(sum<>::value == 0, ""); + static_assert(sum<1>::value == 1, ""); + static_assert(sum<23>::value == 23, ""); + static_assert(sum<1, 2>::value == 3, ""); + static_assert(sum<5, 5, 11>::value == 21, ""); + static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); + + } + + // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae + // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function + // because of this. + namespace test_template_alias_sfinae + { + + struct foo {}; + + template + using member = typename T::member_type; + + template + void func(...) {} + + template + void func(member*) {} + + void test(); + + void test() { func(0); } + + } + +} // namespace cxx11 + +#endif // __cplusplus >= 201103L + +]]) + + +dnl Tests for new features in C++14 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ + +// If the compiler admits that it is not ready for C++14, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201402L + +#error "This is not a C++14 compiler" + +#else + +namespace cxx14 +{ + + namespace test_polymorphic_lambdas + { + + int + test() + { + const auto lambda = [](auto&&... args){ + const auto istiny = [](auto x){ + return (sizeof(x) == 1UL) ? 1 : 0; + }; + const int aretiny[] = { istiny(args)... }; + return aretiny[0]; + }; + return lambda(1, 1L, 1.0f, '1'); + } + + } + + namespace test_binary_literals + { + + constexpr auto ivii = 0b0000000000101010; + static_assert(ivii == 42, "wrong value"); + + } + + namespace test_generalized_constexpr + { + + template < typename CharT > + constexpr unsigned long + strlen_c(const CharT *const s) noexcept + { + auto length = 0UL; + for (auto p = s; *p; ++p) + ++length; + return length; + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("x") == 1UL, ""); + static_assert(strlen_c("test") == 4UL, ""); + static_assert(strlen_c("another\0test") == 7UL, ""); + + } + + namespace test_lambda_init_capture + { + + int + test() + { + auto x = 0; + const auto lambda1 = [a = x](int b){ return a + b; }; + const auto lambda2 = [a = lambda1(x)](){ return a; }; + return lambda2(); + } + + } + + namespace test_digit_separators + { + + constexpr auto ten_million = 100'000'000; + static_assert(ten_million == 100000000, ""); + + } + + namespace test_return_type_deduction + { + + auto f(int& x) { return x; } + decltype(auto) g(int& x) { return x; } + + template < typename T1, typename T2 > + struct is_same + { + static constexpr auto value = false; + }; + + template < typename T > + struct is_same + { + static constexpr auto value = true; + }; + + int + test() + { + auto x = 0; + static_assert(is_same::value, ""); + static_assert(is_same::value, ""); + return x; + } + + } + +} // namespace cxx14 + +#endif // __cplusplus >= 201402L + +]]) + + +dnl Tests for new features in C++17 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[ + +// If the compiler admits that it is not ready for C++17, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201703L + +#error "This is not a C++17 compiler" + +#else + +#include +#include +#include + +namespace cxx17 +{ + + namespace test_constexpr_lambdas + { + + constexpr int foo = [](){return 42;}(); + + } + + namespace test::nested_namespace::definitions + { + + } + + namespace test_fold_expression + { + + template + int multiply(Args... args) + { + return (args * ... * 1); + } + + template + bool all(Args... args) + { + return (args && ...); + } + + } + + namespace test_extended_static_assert + { + + static_assert (true); + + } + + namespace test_auto_brace_init_list + { + + auto foo = {5}; + auto bar {5}; + + static_assert(std::is_same, decltype(foo)>::value); + static_assert(std::is_same::value); + } + + namespace test_typename_in_template_template_parameter + { + + template typename X> struct D; + + } + + namespace test_fallthrough_nodiscard_maybe_unused_attributes + { + + int f1() + { + return 42; + } + + [[nodiscard]] int f2() + { + [[maybe_unused]] auto unused = f1(); + + switch (f1()) + { + case 17: + f1(); + [[fallthrough]]; + case 42: + f1(); + } + return f1(); + } + + } + + namespace test_extended_aggregate_initialization + { + + struct base1 + { + int b1, b2 = 42; + }; + + struct base2 + { + base2() { + b3 = 42; + } + int b3; + }; + + struct derived : base1, base2 + { + int d; + }; + + derived d1 {{1, 2}, {}, 4}; // full initialization + derived d2 {{}, {}, 4}; // value-initialized bases + + } + + namespace test_general_range_based_for_loop + { + + struct iter + { + int i; + + int& operator* () + { + return i; + } + + const int& operator* () const + { + return i; + } + + iter& operator++() + { + ++i; + return *this; + } + }; + + struct sentinel + { + int i; + }; + + bool operator== (const iter& i, const sentinel& s) + { + return i.i == s.i; + } + + bool operator!= (const iter& i, const sentinel& s) + { + return !(i == s); + } + + struct range + { + iter begin() const + { + return {0}; + } + + sentinel end() const + { + return {5}; + } + }; + + void f() + { + range r {}; + + for (auto i : r) + { + [[maybe_unused]] auto v = i; + } + } + + } + + namespace test_lambda_capture_asterisk_this_by_value + { + + struct t + { + int i; + int foo() + { + return [*this]() + { + return i; + }(); + } + }; + + } + + namespace test_enum_class_construction + { + + enum class byte : unsigned char + {}; + + byte foo {42}; + + } + + namespace test_constexpr_if + { + + template + int f () + { + if constexpr(cond) + { + return 13; + } + else + { + return 42; + } + } + + } + + namespace test_selection_statement_with_initializer + { + + int f() + { + return 13; + } + + int f2() + { + if (auto i = f(); i > 0) + { + return 3; + } + + switch (auto i = f(); i + 4) + { + case 17: + return 2; + + default: + return 1; + } + } + + } + + namespace test_template_argument_deduction_for_class_templates + { + + template + struct pair + { + pair (T1 p1, T2 p2) + : m1 {p1}, + m2 {p2} + {} + + T1 m1; + T2 m2; + }; + + void f() + { + [[maybe_unused]] auto p = pair{13, 42u}; + } + + } + + namespace test_non_type_auto_template_parameters + { + + template + struct B + {}; + + B<5> b1; + B<'a'> b2; + + } + + namespace test_structured_bindings + { + + int arr[2] = { 1, 2 }; + std::pair pr = { 1, 2 }; + + auto f1() -> int(&)[2] + { + return arr; + } + + auto f2() -> std::pair& + { + return pr; + } + + struct S + { + int x1 : 2; + volatile double y1; + }; + + S f3() + { + return {}; + } + + auto [ x1, y1 ] = f1(); + auto& [ xr1, yr1 ] = f1(); + auto [ x2, y2 ] = f2(); + auto& [ xr2, yr2 ] = f2(); + const auto [ x3, y3 ] = f3(); + + } + + namespace test_exception_spec_type_system + { + + struct Good {}; + struct Bad {}; + + void g1() noexcept; + void g2(); + + template + Bad + f(T*, T*); + + template + Good + f(T1*, T2*); + + static_assert (std::is_same_v); + + } + + namespace test_inline_variables + { + + template void f(T) + {} + + template inline T g(T) + { + return T{}; + } + + template<> inline void f<>(int) + {} + + template<> int g<>(int) + { + return 5; + } + + } + +} // namespace cxx17 + +#endif // __cplusplus < 201703L + +]]) diff --git a/m4/ax_cxx_compile_stdcxx_17.m4 b/m4/ax_cxx_compile_stdcxx_17.m4 new file mode 100644 index 000000000..a68341717 --- /dev/null +++ b/m4/ax_cxx_compile_stdcxx_17.m4 @@ -0,0 +1,35 @@ +# ============================================================================= +# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_17.html +# ============================================================================= +# +# SYNOPSIS +# +# AX_CXX_COMPILE_STDCXX_17([ext|noext], [mandatory|optional]) +# +# DESCRIPTION +# +# Check for baseline language coverage in the compiler for the C++17 +# standard; if necessary, add switches to CXX and CXXCPP to enable +# support. +# +# This macro is a convenience alias for calling the AX_CXX_COMPILE_STDCXX +# macro with the version set to C++17. The two optional arguments are +# forwarded literally as the second and third argument respectively. +# Please see the documentation for the AX_CXX_COMPILE_STDCXX macro for +# more information. If you want to use this macro, you also need to +# download the ax_cxx_compile_stdcxx.m4 file. +# +# LICENSE +# +# Copyright (c) 2015 Moritz Klammler +# Copyright (c) 2016 Krzesimir Nowak +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 2 + +AX_REQUIRE_DEFINED([AX_CXX_COMPILE_STDCXX]) +AC_DEFUN([AX_CXX_COMPILE_STDCXX_17], [AX_CXX_COMPILE_STDCXX([17], [$1], [$2])]) diff --git a/maintainers/local.mk b/maintainers/local.mk new file mode 100644 index 000000000..e81517eda --- /dev/null +++ b/maintainers/local.mk @@ -0,0 +1,8 @@ + +.PHONY: format +print-top-help += echo ' format: Format source code' + +# This uses the cached .pre-commit-hooks.yaml file +fmt_script := $(d)/format.sh +format: + @$(fmt_script) diff --git a/misc/bash/local.mk b/misc/bash/local.mk new file mode 100644 index 000000000..66235af05 --- /dev/null +++ b/misc/bash/local.mk @@ -0,0 +1 @@ +$(eval $(call install-file-as, $(d)/completion.sh, $(datarootdir)/bash-completion/completions/nix, 0644)) diff --git a/misc/fish/local.mk b/misc/fish/local.mk new file mode 100644 index 000000000..ece899fc3 --- /dev/null +++ b/misc/fish/local.mk @@ -0,0 +1 @@ +$(eval $(call install-file-as, $(d)/completion.fish, $(datarootdir)/fish/vendor_completions.d/nix.fish, 0644)) diff --git a/misc/launchd/local.mk b/misc/launchd/local.mk new file mode 100644 index 000000000..a39188fe6 --- /dev/null +++ b/misc/launchd/local.mk @@ -0,0 +1,5 @@ +ifdef HOST_DARWIN + + $(eval $(call install-data-in, $(d)/org.nixos.nix-daemon.plist, $(prefix)/Library/LaunchDaemons)) + +endif diff --git a/misc/systemd/local.mk b/misc/systemd/local.mk new file mode 100644 index 000000000..76121a0f9 --- /dev/null +++ b/misc/systemd/local.mk @@ -0,0 +1,8 @@ +ifdef HOST_LINUX + + $(foreach n, nix-daemon.socket nix-daemon.service, $(eval $(call install-file-in, $(d)/$(n), $(prefix)/lib/systemd/system, 0644))) + $(foreach n, nix-daemon.conf, $(eval $(call install-file-in, $(d)/$(n), $(prefix)/lib/tmpfiles.d, 0644))) + + clean-files += $(d)/nix-daemon.socket $(d)/nix-daemon.service $(d)/nix-daemon.conf + +endif diff --git a/misc/upstart/local.mk b/misc/upstart/local.mk new file mode 100644 index 000000000..2fbfb29b9 --- /dev/null +++ b/misc/upstart/local.mk @@ -0,0 +1,7 @@ +ifdef HOST_LINUX + + $(foreach n, nix-daemon.conf, $(eval $(call install-file-in, $(d)/$(n), $(sysconfdir)/init, 0644))) + + clean-files += $(d)/nix-daemon.conf + +endif diff --git a/misc/zsh/local.mk b/misc/zsh/local.mk new file mode 100644 index 000000000..0b4e294fb --- /dev/null +++ b/misc/zsh/local.mk @@ -0,0 +1,2 @@ +$(eval $(call install-file-as, $(d)/completion.zsh, $(datarootdir)/zsh/site-functions/_nix, 0644)) +$(eval $(call install-file-as, $(d)/run-help-nix, $(datarootdir)/zsh/site-functions/run-help-nix, 0644)) diff --git a/mk/build-dir.mk b/mk/build-dir.mk new file mode 100644 index 000000000..02f4cae60 --- /dev/null +++ b/mk/build-dir.mk @@ -0,0 +1,10 @@ +# Initialise support for build directories. +builddir ?= + +ifdef builddir + buildprefix = $(builddir)/ + buildprefixrel = $(builddir) +else + buildprefix = + buildprefixrel = . +endif diff --git a/mk/clean.mk b/mk/clean.mk new file mode 100644 index 000000000..ce9afb3b0 --- /dev/null +++ b/mk/clean.mk @@ -0,0 +1,11 @@ +clean-files := + +clean: + $(suppress) rm -fv -- $(clean-files) + +dryclean: + @for i in $(clean-files); do if [ -e $$i ]; then echo $$i; fi; done | sort + +print-top-help += \ + echo " clean: Delete generated files"; \ + echo " dryclean: Show what files would be deleted by 'make clean'"; diff --git a/mk/common-test.sh b/mk/common-test.sh new file mode 100644 index 000000000..dd899e869 --- /dev/null +++ b/mk/common-test.sh @@ -0,0 +1,31 @@ +# shellcheck shell=bash + +# Remove overall test dir (at most one of the two should match) and +# remove file extension. + +test_name=$(echo -n "${test?must be defined by caller (test runner)}" | sed \ + -e "s|^src/[^/]*-test/data/||" \ + -e "s|^tests/functional/||" \ + -e "s|\.sh$||" \ + ) + +# Layer violation, but I am not inclined to care too much, as this code +# is about to be deleted. +src_dir=$(realpath tests/functional) + +# shellcheck disable=SC2016 +TESTS_ENVIRONMENT=( + "TEST_NAME=$test_name" + 'NIX_REMOTE=' + 'PS4=+(${BASH_SOURCE[0]-$0}:$LINENO) ' + "_NIX_TEST_SOURCE_DIR=${src_dir}" + "_NIX_TEST_BUILD_DIR=${src_dir}" +) + +unset src_dir + +read -r -a bash <<< "${BASH:-/usr/bin/env bash}" + +run () { + cd "$(dirname "$1")" && env "${TESTS_ENVIRONMENT[@]}" "${bash[@]}" -x -e -u -o pipefail "$(basename "$1")" +} diff --git a/mk/compilation-database.mk b/mk/compilation-database.mk new file mode 100644 index 000000000..f69dc0de0 --- /dev/null +++ b/mk/compilation-database.mk @@ -0,0 +1,11 @@ +compile-commands-json-files := + +define write-compile-commands + _srcs := $$(sort $$(foreach src, $$($(1)_SOURCES), $$(src))) + + $(1)_COMPILE_COMMANDS_JSON := $$(addprefix $(buildprefix), $$(addsuffix .compile_commands.json, $$(basename $$(_srcs)))) + + compile-commands-json-files += $$($(1)_COMPILE_COMMANDS_JSON) + + clean-files += $$($(1)_COMPILE_COMMANDS_JSON) +endef diff --git a/mk/cxx-big-literal.mk b/mk/cxx-big-literal.mk new file mode 100644 index 000000000..d64a171c8 --- /dev/null +++ b/mk/cxx-big-literal.mk @@ -0,0 +1,5 @@ +%.gen.hh: % + @echo 'R"__NIX_STR(' >> $@.tmp + $(trace-gen) cat $< >> $@.tmp + @echo ')__NIX_STR"' >> $@.tmp + @mv $@.tmp $@ diff --git a/mk/debug-test.sh b/mk/debug-test.sh new file mode 100755 index 000000000..0dd4406c3 --- /dev/null +++ b/mk/debug-test.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +set -eu -o pipefail + +test=$1 + +dir="$(dirname "${BASH_SOURCE[0]}")" +source "$dir/common-test.sh" + +run "$test" diff --git a/mk/functions.mk b/mk/functions.mk new file mode 100644 index 000000000..c48775db8 --- /dev/null +++ b/mk/functions.mk @@ -0,0 +1,14 @@ +# Utility function for recursively finding files, e.g. +# ‘$(call rwildcard, path/to/dir, *.c *.h)’. +rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d)) + +# Given a file name, produce the corresponding dependency file +# (e.g. ‘foo/bar.o’ becomes ‘foo/.bar.o.dep’). +filename-to-dep = $(dir $1).$(notdir $1).dep + +# Return the full path to a program by looking it up in $PATH, or the +# empty string if not found. +find-program = $(shell for i in $$(IFS=: ; echo $$PATH); do p=$$i/$(strip $1); if [ -e $$p ]; then echo $$p; break; fi; done) + +# Ensure that the given string ends in a single slash. +add-trailing-slash = $(patsubst %/,%,$(1))/ diff --git a/mk/install-dirs.mk b/mk/install-dirs.mk new file mode 100644 index 000000000..732b0d6fc --- /dev/null +++ b/mk/install-dirs.mk @@ -0,0 +1,11 @@ +# Default installation paths. +prefix ?= /usr/local +libdir ?= $(prefix)/lib +bindir ?= $(prefix)/bin +libexecdir ?= $(prefix)/libexec +datadir ?= $(prefix)/share +localstatedir ?= $(prefix)/var +sysconfdir ?= $(prefix)/etc +mandir ?= $(prefix)/share/man + +DESTDIR ?= diff --git a/mk/install.mk b/mk/install.mk new file mode 100644 index 000000000..dad0fd853 --- /dev/null +++ b/mk/install.mk @@ -0,0 +1,62 @@ +# Add a rule for creating $(1) as a directory. This template may be +# called multiple times for the same directory. +define create-dir + _i := $$(call add-trailing-slash, $(DESTDIR)$$(strip $(1))) + ifndef $$(_i)_SEEN + $$(_i)_SEEN = 1 + $$(_i): + $$(trace-mkdir) install -d "$$@" + endif +endef + + +# Add a rule for installing file $(1) as file $(2) with mode $(3). +# The directory containing $(2) will be created automatically. +define install-file-as + + _i := $(DESTDIR)$$(strip $(2)) + + install: $$(_i) + + $$(_i): $(1) | $$(dir $$(_i)) + $$(trace-install) install -m $(3) $(1) "$$@" + + $$(eval $$(call create-dir, $$(dir $(2)))) + +endef + + +# Add a rule for installing file $(1) in directory $(2) with mode +# $(3). The directory will be created automatically. +define install-file-in + $$(eval $$(call install-file-as,$(1),$(2)/$$(notdir $(1)),$(3))) +endef + + +define install-program-in + $$(eval $$(call install-file-in,$(1),$(2),0755)) +endef + + +define install-data-in + $$(eval $$(call install-file-in,$(1),$(2),0644)) +endef + + +# Install a symlink from $(2) to $(1). Note that $(1) need not exist. +define install-symlink + + _i := $(DESTDIR)$$(strip $(2)) + + install: $$(_i) + + $$(_i): | $$(dir $$(_i)) + $$(trace-install) ln -sfn $(1) "$$@" + + $$(eval $$(call create-dir, $$(dir $(2)))) + +endef + + +print-top-help += \ + echo " install: Install into \$$(prefix) (currently set to '$(prefix)')"; diff --git a/mk/lib.mk b/mk/lib.mk new file mode 100644 index 000000000..1e7af6ad5 --- /dev/null +++ b/mk/lib.mk @@ -0,0 +1,159 @@ +default: all + + +# Get rid of default suffixes. FIXME: is this a good idea? +.SUFFIXES: + + +# Initialise some variables. +bin-scripts := +noinst-scripts := +man-pages := +install-tests := +install-tests-groups := + +include mk/platform.mk + +# Hack to define a literal space. +space := +space += + + +# Hack to define a literal newline. +define newline + + +endef + + +# Pass -fPIC if we're building dynamic libraries. +BUILD_SHARED_LIBS ?= 1 + +ifeq ($(BUILD_SHARED_LIBS), 1) + ifdef HOST_CYGWIN + GLOBAL_CFLAGS += -U__STRICT_ANSI__ -D_GNU_SOURCE + GLOBAL_CXXFLAGS += -U__STRICT_ANSI__ -D_GNU_SOURCE + else + GLOBAL_CFLAGS += -fPIC + GLOBAL_CXXFLAGS += -fPIC + endif + ifndef HOST_DARWIN + ifndef HOST_SOLARIS + ifndef HOST_FREEBSD + GLOBAL_LDFLAGS += -Wl,--no-copy-dt-needed-entries + endif + endif + endif + SET_RPATH_TO_LIBS ?= 1 +endif + +# Pass -g if we want debug info. +BUILD_DEBUG ?= 1 + +ifeq ($(BUILD_DEBUG), 1) + GLOBAL_CFLAGS += -g + GLOBAL_CXXFLAGS += -g +endif + + +include mk/build-dir.mk +include mk/install-dirs.mk +include mk/functions.mk +include mk/tracing.mk +include mk/clean.mk +include mk/install.mk +include mk/libraries.mk +include mk/programs.mk +include mk/patterns.mk +include mk/templates.mk +include mk/cxx-big-literal.mk +include mk/tests.mk +include mk/compilation-database.mk + + +# Include all sub-Makefiles. +define include-sub-makefile + d := $$(patsubst %/,%,$$(dir $(1))) + include $(1) +endef + +$(foreach mf, $(makefiles), $(eval $(call include-sub-makefile,$(mf)))) + + +# Instantiate stuff. +$(foreach lib, $(libraries), $(eval $(call build-library,$(lib)))) +$(foreach prog, $(programs), $(eval $(call build-program,$(prog)))) +$(foreach script, $(bin-scripts), $(eval $(call install-program-in,$(script),$(bindir)))) +$(foreach script, $(bin-scripts), $(eval programs-list += $(script))) +$(foreach script, $(noinst-scripts), $(eval programs-list += $(script))) +$(foreach template, $(template-files), $(eval $(call instantiate-template,$(template)))) +$(foreach test, $(install-tests), \ + $(eval $(call run-test,$(test))) \ + $(eval installcheck: $(test).test)) +$(foreach test-group, $(install-tests-groups), \ + $(eval $(call run-test-group,$(test-group))) \ + $(eval installcheck: $(test-group).test-group) \ + $(foreach test, $($(test-group)-tests), \ + $(eval $(call run-test,$(test))) \ + $(eval $(test-group).test-group: $(test).test))) + +# Compilation database. +$(foreach lib, $(libraries), $(eval $(call write-compile-commands,$(lib)))) +$(foreach prog, $(programs), $(eval $(call write-compile-commands,$(prog)))) + +compile_commands.json: $(compile-commands-json-files) + @jq --slurp '.' $^ >$@ + +# Include makefiles requiring built programs. +$(foreach mf, $(makefiles-late), $(eval $(call include-sub-makefile,$(mf)))) + + +$(foreach file, $(man-pages), $(eval $(call install-data-in, $(file), $(mandir)/man$(patsubst .%,%,$(suffix $(file)))))) + + +.PHONY: default all man help + +all: $(programs-list) $(libs-list) $(man-pages) + +man: $(man-pages) + + +help: + @echo "The following targets are available:" + @echo "" + @echo " default: Build default targets" +ifdef man-pages + @echo " man: Generate manual pages" +endif + @$(print-top-help) +ifdef programs-list + @echo "" + @echo "The following programs can be built:" + @echo "" + @for i in $(programs-list); do echo " $$i"; done +endif +ifdef libs-list + @echo "" + @echo "The following libraries can be built:" + @echo "" + @for i in $(libs-list); do echo " $$i"; done +endif +ifdef install-tests-groups + @echo "" + @echo "The following groups of functional tests can be run:" + @echo "" + @for i in $(install-tests-groups); do echo " $$i.test-group"; done + @echo "" + @echo "(installcheck includes tests in test groups too.)" +endif + @echo "" + @echo "The following variables control the build:" + @echo "" + @echo " BUILD_SHARED_LIBS ($(BUILD_SHARED_LIBS)): Whether to build shared libraries" + @echo " BUILD_DEBUG ($(BUILD_DEBUG)): Whether to include debug symbols" + @echo " CC ($(CC)): C compiler to be used" + @echo " CFLAGS: Flags for the C compiler" + @echo " CXX ($(CXX)): C++ compiler to be used" + @echo " CXXFLAGS: Flags for the C++ compiler" + @echo " CPPFLAGS: C preprocessor flags, used for both CC and CXX" + @$(print-var-help) diff --git a/mk/libraries.mk b/mk/libraries.mk new file mode 100644 index 000000000..a7848ba35 --- /dev/null +++ b/mk/libraries.mk @@ -0,0 +1,173 @@ +libs-list := + +ifdef HOST_DARWIN + SO_EXT = dylib +else + ifdef HOST_WINDOWS + SO_EXT = dll + else + SO_EXT = so + endif +endif + +ifdef HOST_UNIX + THREAD_LDFLAGS = -pthread +else + THREAD_LDFLAGS = +endif + +# Build a library with symbolic name $(1). The library is defined by +# various variables prefixed by ‘$(1)_’: +# +# - $(1)_NAME: the name of the library (e.g. ‘libfoo’); defaults to +# $(1). +# +# - $(1)_DIR: the directory where the (non-installed) library will be +# placed. +# +# - $(1)_SOURCES: the source files of the library. +# +# - $(1)_CFLAGS: additional C compiler flags. +# +# - $(1)_CXXFLAGS: additional C++ compiler flags. +# +# - $(1)_ORDER_AFTER: a set of targets on which the object files of +# this libraries will have an order-only dependency. +# +# - $(1)_LIBS: the symbolic names of other libraries on which this +# library depends. +# +# - $(1)_ALLOW_UNDEFINED: if set, the library is allowed to have +# undefined symbols. Has no effect for static libraries. +# +# - $(1)_LDFLAGS: additional linker flags. +# +# - $(1)_LDFLAGS_PROPAGATED: additional linker flags, also propagated +# to the linking of programs/libraries that use this library. +# +# - $(1)_FORCE_INSTALL: if defined, the library will be installed even +# if it's not needed (i.e. dynamically linked) by a program. +# +# - $(1)_INSTALL_DIR: the directory where the library will be +# installed. Defaults to $(libdir). +# +# - $(1)_EXCLUDE_FROM_LIBRARY_LIST: if defined, the library will not +# be automatically marked as a dependency of the top-level all +# target andwill not be listed in the make help output. This is +# useful for libraries built solely for testing, for example. +# +# - BUILD_SHARED_LIBS: if equal to ‘1’, a dynamic library will be +# built, otherwise a static library. +define build-library + $(1)_NAME ?= $(1) + _d := $(buildprefix)$$(strip $$($(1)_DIR)) + _srcs := $$(sort $$(foreach src, $$($(1)_SOURCES), $$(src))) + $(1)_OBJS := $$(addprefix $(buildprefix), $$(addsuffix .o, $$(basename $$(_srcs)))) + _libs := $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_PATH)) + + ifdef HOST_WINDOWS + $(1)_INSTALL_DIR ?= $$(bindir) + else + $(1)_INSTALL_DIR ?= $$(libdir) + endif + + $(1)_LDFLAGS_USE := + $(1)_LDFLAGS_USE_INSTALLED := + $(1)_LIB_CLOSURE := $(1) + + $$(eval $$(call create-dir, $$(_d))) + + ifeq ($(BUILD_SHARED_LIBS), 1) + + ifdef $(1)_ALLOW_UNDEFINED + ifdef HOST_DARWIN + $(1)_LDFLAGS += -undefined suppress -flat_namespace + endif + else + ifndef HOST_DARWIN + ifndef HOST_WINDOWS + ifndef HOST_OPENBSD + $(1)_LDFLAGS += -Wl,-z,defs + endif + endif + endif + endif + + ifndef HOST_DARWIN + $(1)_LDFLAGS += -Wl,-soname=$$($(1)_NAME).$(SO_EXT) + endif + + $(1)_PATH := $$(_d)/$$($(1)_NAME).$(SO_EXT) + + $$($(1)_PATH): $$($(1)_OBJS) $$(_libs) | $$(_d)/ + +$$(trace-ld) $(CXX) -o $$(abspath $$@) -shared $$(LDFLAGS) $$(GLOBAL_LDFLAGS) $$($(1)_OBJS) $$($(1)_LDFLAGS) $$($(1)_LDFLAGS_PROPAGATED) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_LDFLAGS_USE)) $$($(1)_LDFLAGS_UNINSTALLED) + + ifndef HOST_DARWIN + $(1)_LDFLAGS_USE += -Wl,-rpath,$$(abspath $$(_d)) + endif + $(1)_LDFLAGS_USE += -L$$(_d) -l$$(patsubst lib%,%,$$(strip $$($(1)_NAME))) + + $(1)_INSTALL_PATH := $(DESTDIR)$$($(1)_INSTALL_DIR)/$$($(1)_NAME).$(SO_EXT) + + _libs_final := $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_INSTALL_PATH)) + + $$(eval $$(call create-dir, $$($(1)_INSTALL_DIR))) + + $$($(1)_INSTALL_PATH): $$($(1)_OBJS) $$(_libs_final) | $(DESTDIR)$$($(1)_INSTALL_DIR)/ + +$$(trace-ld) $(CXX) -o $$@ -shared $$(LDFLAGS) $$(GLOBAL_LDFLAGS) $$($(1)_OBJS) $$($(1)_LDFLAGS) $$($(1)_LDFLAGS_PROPAGATED) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_LDFLAGS_USE_INSTALLED)) + + $(1)_LDFLAGS_USE_INSTALLED += -L$$(DESTDIR)$$($(1)_INSTALL_DIR) -l$$(patsubst lib%,%,$$(strip $$($(1)_NAME))) + ifndef HOST_DARWIN + ifeq ($(SET_RPATH_TO_LIBS), 1) + $(1)_LDFLAGS_USE_INSTALLED += -Wl,-rpath,$$($(1)_INSTALL_DIR) + else + $(1)_LDFLAGS_USE_INSTALLED += -Wl,-rpath-link,$$($(1)_INSTALL_DIR) + endif + endif + + ifdef $(1)_FORCE_INSTALL + install: $$($(1)_INSTALL_PATH) + endif + + else + + $(1)_PATH := $$(_d)/$$($(1)_NAME).a + + $$($(1)_PATH): $$($(1)_OBJS) | $$(_d)/ + $$(trace-ld) $(LD) $$(ifndef $(HOST_DARWIN),-U) -r -o $$(_d)/$$($(1)_NAME).o $$^ + $$(trace-ar) $(AR) crs $$@ $$(_d)/$$($(1)_NAME).o + + $(1)_LDFLAGS_USE += $$($(1)_PATH) $$($(1)_LDFLAGS) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_LDFLAGS_USE)) + + $(1)_INSTALL_PATH := $$(libdir)/$$($(1)_NAME).a + + $(1)_LIB_CLOSURE += $$($(1)_LIBS) + + endif + + $(1)_LDFLAGS_USE += $$($(1)_LDFLAGS_PROPAGATED) + $(1)_LDFLAGS_USE_INSTALLED += $$($(1)_LDFLAGS_PROPAGATED) + + # Propagate CFLAGS and CXXFLAGS to the individual object files. + $$(foreach obj, $$($(1)_OBJS), $$(eval $$(obj)_CFLAGS=$$($(1)_CFLAGS))) + $$(foreach obj, $$($(1)_OBJS), $$(eval $$(obj)_CXXFLAGS=$$($(1)_CXXFLAGS))) + + # Make each object file depend on the common dependencies. + $$(foreach obj, $$($(1)_OBJS), $$(eval $$(obj): $$($(1)_COMMON_DEPS) $$(GLOBAL_COMMON_DEPS))) + + # Make each object file have order-only dependencies on the common + # order-only dependencies. This includes the order-only dependencies + # of libraries we're depending on. + $(1)_ORDER_AFTER_CLOSED = $$($(1)_ORDER_AFTER) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_ORDER_AFTER_CLOSED)) + + $$(foreach obj, $$($(1)_OBJS), $$(eval $$(obj): | $$($(1)_ORDER_AFTER_CLOSED) $$(GLOBAL_ORDER_AFTER))) + + # Include .dep files, if they exist. + $(1)_DEPS := $$(foreach fn, $$($(1)_OBJS), $$(call filename-to-dep, $$(fn))) + -include $$($(1)_DEPS) + + ifndef $(1)_EXCLUDE_FROM_LIBRARY_LIST + libs-list += $$($(1)_PATH) + endif + clean-files += $$(_d)/*.a $$(_d)/*.$(SO_EXT) $$(_d)/*.o $$(_d)/.*.dep $$($(1)_DEPS) $$($(1)_OBJS) +endef diff --git a/mk/patterns.mk b/mk/patterns.mk new file mode 100644 index 000000000..4caa2039e --- /dev/null +++ b/mk/patterns.mk @@ -0,0 +1,41 @@ + +# These are the complete command lines we use to compile C and C++ files. +# - $< is the source file. +# - $1 is the object file to create. +CC_CMD=$(CC) -o $1 -c $< $(CPPFLAGS) $(GLOBAL_CFLAGS) $(CFLAGS) $($1_CFLAGS) -MMD -MF $(call filename-to-dep,$1) -MP +CXX_CMD=$(CXX) -o $1 -c $< $(CPPFLAGS) $(GLOBAL_CXXFLAGS_PCH) $(GLOBAL_CXXFLAGS) $(CXXFLAGS) $($1_CXXFLAGS) $(ERROR_SWITCH_ENUM) -MMD -MF $(call filename-to-dep,$1) -MP + +# We use COMPILE_COMMANDS_JSON_CMD to turn a compilation command (like CC_CMD +# or CXX_CMD above) into a comple_commands.json file. We rely on bash native +# word splitting to define the positional arguments. +# - $< is the source file being compiled. +COMPILE_COMMANDS_JSON_CMD=jq --null-input '{ directory: $$ENV.PWD, file: "$<", arguments: $$ARGS.positional }' --args -- + + +$(buildprefix)%.o: %.cc + @mkdir -p "$(dir $@)" + $(trace-cxx) $(call CXX_CMD,$@) + +$(buildprefix)%.o: %.cpp + @mkdir -p "$(dir $@)" + $(trace-cxx) $(call CXX_CMD,$@) + +$(buildprefix)%.o: %.c + @mkdir -p "$(dir $@)" + $(trace-cc) $(call CC_CMD,$@) + +# In the following we need to replace the .compile_commands.json extension in $@ with .o +# to make the object file. This is needed because CC_CMD and CXX_CMD do further expansions +# based on the object file name (i.e. *_CXXFLAGS and filename-to-dep). + +$(buildprefix)%.compile_commands.json: %.cc + @mkdir -p "$(dir $@)" + $(trace-jq) $(COMPILE_COMMANDS_JSON_CMD) $(call CXX_CMD,$(@:.compile_commands.json=.o)) > $@ + +$(buildprefix)%.compile_commands.json: %.cpp + @mkdir -p "$(dir $@)" + $(trace-jq) $(COMPILE_COMMANDS_JSON_CMD) $(call CXX_CMD,$(@:.compile_commands.json=.o)) > $@ + +$(buildprefix)%.compile_commands.json: %.c + @mkdir -p "$(dir $@)" + $(trace-jq) $(COMPILE_COMMANDS_JSON_CMD) $(call CC_CMD,$(@:.compile_commands.json=.o)) > $@ diff --git a/mk/platform.mk b/mk/platform.mk new file mode 100644 index 000000000..3c4fff780 --- /dev/null +++ b/mk/platform.mk @@ -0,0 +1,40 @@ +ifdef HOST_OS + HOST_KERNEL = $(firstword $(subst -, ,$(HOST_OS))) + ifeq ($(patsubst mingw%,,$(HOST_KERNEL)),) + HOST_MINGW = 1 + HOST_WINDOWS = 1 + endif + ifeq ($(HOST_KERNEL), cygwin) + HOST_CYGWIN = 1 + HOST_WINDOWS = 1 + HOST_UNIX = 1 + endif + ifeq ($(patsubst darwin%,,$(HOST_KERNEL)),) + HOST_DARWIN = 1 + HOST_UNIX = 1 + endif + ifeq ($(patsubst freebsd%,,$(HOST_KERNEL)),) + HOST_FREEBSD = 1 + HOST_UNIX = 1 + endif + ifeq ($(patsubst netbsd%,,$(HOST_KERNEL)),) + HOST_NETBSD = 1 + HOST_UNIX = 1 + endif + ifeq ($(patsubst openbsd%,,$(HOST_KERNEL)),) + HOST_OPENBSD = 1 + HOST_UNIX = 1 + endif + ifeq ($(HOST_KERNEL), linux) + HOST_LINUX = 1 + HOST_UNIX = 1 + endif + ifeq ($(patsubst solaris%,,$(HOST_KERNEL)),) + HOST_SOLARIS = 1 + HOST_UNIX = 1 + endif + ifeq ($(HOST_KERNEL), gnu) + HOST_HURD = 1 + HOST_UNIX = 1 + endif +endif diff --git a/mk/precompiled-headers.mk b/mk/precompiled-headers.mk new file mode 100644 index 000000000..f2803eb79 --- /dev/null +++ b/mk/precompiled-headers.mk @@ -0,0 +1,21 @@ +PRECOMPILE_HEADERS ?= 0 + +print-var-help += \ + echo " PRECOMPILE_HEADERS ($(PRECOMPILE_HEADERS)): Whether to use precompiled headers to speed up the build"; + +GCH = $(buildprefix)precompiled-headers.h.gch + +$(GCH): precompiled-headers.h + @rm -f $@ + @mkdir -p "$(dir $@)" + $(trace-gen) $(CXX) -c -x c++-header -o $@ $< $(GLOBAL_CXXFLAGS) $(GCH_CXXFLAGS) + +clean-files += $(GCH) + +ifeq ($(PRECOMPILE_HEADERS), 1) + + GLOBAL_CXXFLAGS_PCH += -include $(buildprefix)precompiled-headers.h -Winvalid-pch + + GLOBAL_ORDER_AFTER += $(GCH) + +endif diff --git a/mk/programs.mk b/mk/programs.mk new file mode 100644 index 000000000..623caaf55 --- /dev/null +++ b/mk/programs.mk @@ -0,0 +1,98 @@ +programs-list := + +ifdef HOST_WINDOWS + EXE_EXT = .exe +else + EXE_EXT = +endif + +# Build a program with symbolic name $(1). The program is defined by +# various variables prefixed by ‘$(1)_’: +# +# - $(1)_NAME: the name of the program (e.g. ‘foo’); defaults to +# $(1). +# +# - $(1)_DIR: the directory where the (non-installed) program will be +# placed. +# +# - $(1)_SOURCES: the source files of the program. +# +# - $(1)_CFLAGS: additional C compiler flags. +# +# - $(1)_CXXFLAGS: additional C++ compiler flags. +# +# - $(1)_ORDER_AFTER: a set of targets on which the object files of +# this program will have an order-only dependency. +# +# - $(1)_LIBS: the symbolic names of libraries on which this program +# depends. +# +# - $(1)_LDFLAGS: additional linker flags. +# +# - $(1)_INSTALL_DIR: the directory where the program will be +# installed; defaults to $(bindir). +define build-program + $(1)_NAME ?= $(1) + _d := $(buildprefix)$$($(1)_DIR) + _srcs := $$(sort $$(foreach src, $$($(1)_SOURCES), $$(src))) + $(1)_OBJS := $$(addprefix $(buildprefix), $$(addsuffix .o, $$(basename $$(_srcs)))) + _libs := $$(foreach lib, $$($(1)_LIBS), $$(foreach lib2, $$($$(lib)_LIB_CLOSURE), $$($$(lib2)_PATH))) + $(1)_PATH := $$(_d)/$$($(1)_NAME)$(EXE_EXT) + + $$(eval $$(call create-dir, $$(_d))) + + $$($(1)_PATH): $$($(1)_OBJS) $$(_libs) | $$(_d)/ + +$$(trace-ld) $(CXX) -o $$@ $$(LDFLAGS) $$(GLOBAL_LDFLAGS) $$($(1)_OBJS) $$($(1)_LDFLAGS) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_LDFLAGS_USE)) + + $(1)_INSTALL_DIR ?= $$(bindir) + + ifdef $(1)_INSTALL_DIR + + $(1)_INSTALL_PATH := $$($(1)_INSTALL_DIR)/$$($(1)_NAME)$(EXE_EXT) + + $$(eval $$(call create-dir, $$($(1)_INSTALL_DIR))) + + install: $(DESTDIR)$$($(1)_INSTALL_PATH) + + ifeq ($(BUILD_SHARED_LIBS), 1) + + _libs_final := $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_INSTALL_PATH)) + + $(DESTDIR)$$($(1)_INSTALL_PATH): $$($(1)_OBJS) $$(_libs_final) | $(DESTDIR)$$($(1)_INSTALL_DIR)/ + +$$(trace-ld) $(CXX) -o $$@ $$(LDFLAGS) $$(GLOBAL_LDFLAGS) $$($(1)_OBJS) $$($(1)_LDFLAGS) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_LDFLAGS_USE_INSTALLED)) + + else + + $(DESTDIR)$$($(1)_INSTALL_PATH): $$($(1)_PATH) | $(DESTDIR)$$($(1)_INSTALL_DIR)/ + +$$(trace-install) install -t $(DESTDIR)$$($(1)_INSTALL_DIR) $$< + + endif + endif + + # Propagate CFLAGS and CXXFLAGS to the individual object files. + $$(foreach obj, $$($(1)_OBJS), $$(eval $$(obj)_CFLAGS=$$($(1)_CFLAGS))) + $$(foreach obj, $$($(1)_OBJS), $$(eval $$(obj)_CXXFLAGS=$$($(1)_CXXFLAGS))) + + # Make each object file depend on the common dependencies. + $$(foreach obj, $$($(1)_OBJS), $$(eval $$(obj): $$($(1)_COMMON_DEPS) $$(GLOBAL_COMMON_DEPS))) + + # Make each object file have order-only dependencies on the common + # order-only dependencies. This includes the order-only dependencies + # of libraries we're depending on. + $(1)_ORDER_AFTER_CLOSED = $$($(1)_ORDER_AFTER) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_ORDER_AFTER_CLOSED)) + + $$(foreach obj, $$($(1)_OBJS), $$(eval $$(obj): | $$($(1)_ORDER_AFTER_CLOSED) $$(GLOBAL_ORDER_AFTER))) + + # Include .dep files, if they exist. + $(1)_DEPS := $$(foreach fn, $$($(1)_OBJS), $$(call filename-to-dep, $$(fn))) + -include $$($(1)_DEPS) + + programs-list += $$($(1)_PATH) + clean-files += $$($(1)_PATH) $$(_d)/*.o $$(_d)/.*.dep $$($(1)_DEPS) $$($(1)_OBJS) + + # Phony target to run this program (typically as a dependency of 'check'). + .PHONY: $(1)_RUN + $(1)_RUN: $$($(1)_PATH) + $(trace-test) $$($(1)_ENV) $$($(1)_PATH) + +endef diff --git a/mk/run-test.sh b/mk/run-test.sh new file mode 100755 index 000000000..7f9f1d5f8 --- /dev/null +++ b/mk/run-test.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash + +set -eu -o pipefail + +red="" +green="" +yellow="" +normal="" + +test=$1 + +dir="$(dirname "${BASH_SOURCE[0]}")" +source "$dir/common-test.sh" + +post_run_msg="ran test $test..." +if [ -t 1 ]; then + red="" + green="" + yellow="" + normal="" +fi + +run_test () { + log="$(run "$test" 2>&1)" && status=0 || status=$? +} + +run_test + +if [[ "$status" = 0 ]]; then + echo "$post_run_msg [${green}PASS$normal]" +elif [[ "$status" = 77 ]]; then + echo "$post_run_msg [${yellow}SKIP$normal]" +else + echo "$post_run_msg [${red}FAIL$normal]" + # shellcheck disable=SC2001 + echo "$log" | sed 's/^/ /' + exit "$status" +fi diff --git a/mk/templates.mk b/mk/templates.mk new file mode 100644 index 000000000..d5dae61c7 --- /dev/null +++ b/mk/templates.mk @@ -0,0 +1,19 @@ +template-files := + +# Create the file $(1) from $(1).in by running config.status (which +# substitutes all ‘@var@’ variables set by the configure script). +define instantiate-template + + clean-files += $(1) + +endef + +ifneq ($(MAKECMDGOALS), clean) + +$(buildprefix)%.h: %.h.in $(buildprefix)config.status + $(trace-gen) rm -f $@ && cd $(buildprefixrel) && ./config.status --quiet --header=$(@:$(buildprefix)%=%) + +$(buildprefix)%: %.in $(buildprefix)config.status + $(trace-gen) rm -f $@ && cd $(buildprefixrel) && ./config.status --quiet --file=$(@:$(buildprefix)%=%) + +endif diff --git a/mk/tests.mk b/mk/tests.mk new file mode 100644 index 000000000..0a10f6d3b --- /dev/null +++ b/mk/tests.mk @@ -0,0 +1,30 @@ +# Run program $1 as part of ‘make installcheck’. + +test-deps = + +define run-bash + + .PHONY: $1 + $1: $2 + @env BASH=$(bash) $(bash) $3 < /dev/null + +endef + +define run-test + + $(eval $(call run-bash,$1.test,$1 $(test-deps),mk/run-test.sh $1)) + $(eval $(call run-bash,$1.test-debug,$1 $(test-deps),mk/debug-test.sh $1)) + +endef + +define run-test-group + + .PHONY: $1.test-group + +endef + +.PHONY: check installcheck + +print-top-help += \ + echo " check: Run unit tests"; \ + echo " installcheck: Run functional tests"; diff --git a/mk/tracing.mk b/mk/tracing.mk new file mode 100644 index 000000000..09db1e617 --- /dev/null +++ b/mk/tracing.mk @@ -0,0 +1,18 @@ +V ?= 0 + +ifeq ($(V), 0) + + trace-gen = @echo " GEN " $@; + trace-cc = @echo " CC " $@; + trace-cxx = @echo " CXX " $@; + trace-ld = @echo " LD " $@; + trace-ar = @echo " AR " $@; + trace-install = @echo " INST " $@; + trace-mkdir = @echo " MKDIR " $@; + trace-test = @echo " TEST " $@; + trace-sh = @echo " SH " $@; + trace-jq = @echo " JQ " $@; + + suppress = @ + +endif diff --git a/package.nix b/package.nix new file mode 100644 index 000000000..8cbe325e9 --- /dev/null +++ b/package.nix @@ -0,0 +1,366 @@ +{ lib +, stdenv +, releaseTools +, autoconf-archive +, autoreconfHook +, aws-sdk-cpp +, boehmgc +, nlohmann_json +, bison +, boost +, brotli +, bzip2 +, curl +, editline +, readline +, flex +, git +, gtest +, jq +, libarchive +, libcpuid +, libgit2 +, libseccomp +, libsodium +, man +, darwin +, lowdown +, mdbook +, mdbook-linkcheck +, mercurial +, openssh +, openssl +, pkg-config +, rapidcheck +, sqlite +, toml11 +, unixtools +, xz + +, busybox-sandbox-shell ? null + +# Configuration Options +#: +# This probably seems like too many degrees of freedom, but it +# faithfully reflects how the underlying configure + make build system +# work. The top-level flake.nix will choose useful combinations of these +# options to CI. + +, pname ? "nix" + +, version +, versionSuffix + +# Whether to build Nix. Useful to skip for tasks like testing existing pre-built versions of Nix +, doBuild ? true + +# Run the unit tests as part of the build. See `installUnitTests` for an +# alternative to this. +, doCheck ? __forDefaults.canRunInstalled + +# Run the functional tests as part of the build. +, doInstallCheck ? test-client != null || __forDefaults.canRunInstalled + +# Check test coverage of Nix. Probably want to use with at least +# one of `doCHeck` or `doInstallCheck` enabled. +, withCoverageChecks ? false + +# Whether to build the regular manual +, enableManual ? __forDefaults.canRunInstalled + +# Whether to use garbage collection for the Nix language evaluator. +# +# If it is disabled, we just leak memory, but this is not as bad as it +# sounds so long as evaluation just takes places within short-lived +# processes. (When the process exits, the memory is reclaimed; it is +# only leaked *within* the process.) +# +# Temporarily disabled on Windows because the `GC_throw_bad_alloc` +# symbol is missing during linking. +# +# Disabled on OpenBSD because of missing `_data_start` symbol while linking +, enableGC ? !stdenv.hostPlatform.isWindows && !stdenv.hostPlatform.isOpenBSD + +# Whether to enable Markdown rendering in the Nix binary. +, enableMarkdown ? !stdenv.hostPlatform.isWindows + +# Which interactive line editor library to use for Nix's repl. +# +# Currently supported choices are: +# +# - editline (default) +# - readline +, readlineFlavor ? if stdenv.hostPlatform.isWindows then "readline" else "editline" + +# Whether to install unit tests. This is useful when cross compiling +# since we cannot run them natively during the build, but can do so +# later. +, installUnitTests ? doBuild && !__forDefaults.canExecuteHost + +# For running the functional tests against a pre-built Nix. Probably +# want to use in conjunction with `doBuild = false;`. +, test-daemon ? null +, test-client ? null + +# Avoid setting things that would interfere with a functioning devShell +, forDevShell ? false + +# Not a real argument, just the only way to approximate let-binding some +# stuff for argument defaults. +, __forDefaults ? { + canExecuteHost = stdenv.buildPlatform.canExecute stdenv.hostPlatform; + canRunInstalled = doBuild && __forDefaults.canExecuteHost; + } +}: + +let + inherit (lib) fileset; + + # selected attributes with defaults, will be used to define some + # things which should instead be gotten via `finalAttrs` in order to + # work with overriding. + attrs = { + inherit doBuild doCheck doInstallCheck; + }; + + mkDerivation = + if withCoverageChecks + then + # TODO support `finalAttrs` args function in + # `releaseTools.coverageAnalysis`. + argsFun: + releaseTools.coverageAnalysis (let args = argsFun args; in args) + else stdenv.mkDerivation; +in + +mkDerivation (finalAttrs: let + + inherit (finalAttrs) + doCheck + doInstallCheck + ; + + doBuild = !finalAttrs.dontBuild; + + # Either running the unit tests during the build, or installing them + # to be run later, requiresthe unit tests to be built. + buildUnitTests = doCheck || installUnitTests; + +in { + inherit pname version; + + src = + let + baseFiles = fileset.fileFilter (f: f.name != ".gitignore") ./.; + in + fileset.toSource { + root = ./.; + fileset = fileset.intersection baseFiles (fileset.unions ([ + # For configure + ./.version + ./configure.ac + ./m4 + # TODO: do we really need README.md? It doesn't seem used in the build. + ./README.md + # This could be put behind a conditional + ./maintainers/local.mk + # For make, regardless of what we are building + ./local.mk + ./Makefile + ./Makefile.config.in + ./mk + (fileset.fileFilter (f: lib.strings.hasPrefix "nix-profile" f.name) ./scripts) + ] ++ lib.optionals doBuild [ + ./doc + ./misc + ./precompiled-headers.h + (fileset.difference ./src ./src/perl) + ./COPYING + ./scripts/local.mk + ] ++ lib.optionals enableManual [ + ./doc/manual + ] ++ lib.optionals doInstallCheck [ + ./tests/functional + ])); + }; + + VERSION_SUFFIX = versionSuffix; + + outputs = [ "out" ] + ++ lib.optional doBuild "dev" + # If we are doing just build or just docs, the one thing will use + # "out". We only need additional outputs if we are doing both. + ++ lib.optional (doBuild && enableManual) "doc" + ++ lib.optional installUnitTests "check" + ++ lib.optional doCheck "testresults" + ; + + nativeBuildInputs = [ + autoconf-archive + autoreconfHook + pkg-config + ] ++ lib.optionals doBuild [ + bison + flex + ] ++ lib.optionals enableManual [ + (lib.getBin lowdown) + mdbook + mdbook-linkcheck + ] ++ lib.optionals doInstallCheck [ + git + mercurial + openssh + ] ++ lib.optionals (doInstallCheck || enableManual) [ + jq # Also for custom mdBook preprocessor. + ] ++ lib.optionals enableManual [ + man + ] ++ lib.optional stdenv.hostPlatform.isStatic unixtools.hexdump + ; + + buildInputs = lib.optionals doBuild ( + [ + brotli + bzip2 + curl + libarchive + libgit2 + libsodium + openssl + sqlite + toml11 + xz + ({ inherit readline editline; }.${readlineFlavor}) + ] ++ lib.optionals enableMarkdown [ + lowdown + ] ++ lib.optionals buildUnitTests [ + gtest + rapidcheck + ] ++ lib.optional stdenv.isLinux libseccomp + ++ lib.optional stdenv.hostPlatform.isDarwin darwin.apple_sdk.libs.sandbox + ++ lib.optional stdenv.hostPlatform.isx86_64 libcpuid + # There have been issues building these dependencies + ++ lib.optional (stdenv.hostPlatform == stdenv.buildPlatform && (stdenv.isLinux || stdenv.isDarwin)) + aws-sdk-cpp + ); + + propagatedBuildInputs = lib.optionals doBuild ([ + boost + nlohmann_json + ] ++ lib.optional enableGC boehmgc + ); + + dontBuild = !attrs.doBuild; + doCheck = attrs.doCheck; + + configureFlags = [ + (lib.enableFeature doBuild "build") + (lib.enableFeature buildUnitTests "unit-tests") + (lib.enableFeature doInstallCheck "functional-tests") + (lib.enableFeature enableManual "doc-gen") + (lib.enableFeature enableGC "gc") + (lib.enableFeature enableMarkdown "markdown") + (lib.enableFeature installUnitTests "install-unit-tests") + (lib.withFeatureAs true "readline-flavor" readlineFlavor) + ] ++ lib.optionals (!forDevShell) [ + "--sysconfdir=/etc" + ] ++ lib.optionals installUnitTests [ + "--with-check-bin-dir=${builtins.placeholder "check"}/bin" + "--with-check-lib-dir=${builtins.placeholder "check"}/lib" + ] ++ lib.optionals (doBuild) [ + "--with-boost=${boost}/lib" + ] ++ lib.optionals (doBuild && stdenv.isLinux) [ + "--with-sandbox-shell=${busybox-sandbox-shell}/bin/busybox" + ] ++ lib.optional (doBuild && stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) + "LDFLAGS=-fuse-ld=gold" + ++ lib.optional (doBuild && stdenv.hostPlatform.isStatic) "--enable-embedded-sandbox-shell" + ; + + enableParallelBuilding = true; + + makeFlags = "profiledir=$(out)/etc/profile.d PRECOMPILE_HEADERS=1"; + + preCheck = '' + mkdir $testresults + ''; + + installTargets = lib.optional doBuild "install"; + + installFlags = "sysconfdir=$(out)/etc"; + + # In this case we are probably just running tests, and so there isn't + # anything to install, we just make an empty directory to signify tests + # succeeded. + installPhase = if finalAttrs.installTargets != [] then null else '' + mkdir -p $out + ''; + + postInstall = lib.optionalString doBuild ( + lib.optionalString stdenv.hostPlatform.isStatic '' + mkdir -p $out/nix-support + echo "file binary-dist $out/bin/nix" >> $out/nix-support/hydra-build-products + '' + ) + lib.optionalString enableManual '' + mkdir -p ''${!outputDoc}/nix-support + echo "doc manual ''${!outputDoc}/share/doc/nix/manual" >> ''${!outputDoc}/nix-support/hydra-build-products + ''; + + # So the check output gets links for DLLs in the out output. + preFixup = lib.optionalString (stdenv.hostPlatform.isWindows && builtins.elem "check" finalAttrs.outputs) '' + ln -s "$check/lib/"*.dll "$check/bin" + ln -s "$out/bin/"*.dll "$check/bin" + ''; + + doInstallCheck = attrs.doInstallCheck; + + installCheckFlags = "sysconfdir=$(out)/etc"; + # Work around buggy detection in stdenv. + installCheckTarget = "installcheck"; + + # Work around weird bug where it doesn't think there is a Makefile. + installCheckPhase = if (!doBuild && doInstallCheck) then '' + runHook preInstallCheck + mkdir -p src/nix-channel + make installcheck -j$NIX_BUILD_CORES -l$NIX_BUILD_CORES + '' else null; + + # Needed for tests if we are not doing a build, but testing existing + # built Nix. + preInstallCheck = + lib.optionalString (! doBuild) '' + mkdir -p src/nix-channel + ''; + + separateDebugInfo = !stdenv.hostPlatform.isStatic; + + # TODO Always true after https://github.com/NixOS/nixpkgs/issues/318564 + strictDeps = !withCoverageChecks; + + hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie"; + + meta = { + platforms = lib.platforms.unix ++ lib.platforms.windows; + mainProgram = "nix"; + broken = !(lib.all (a: a) [ + # We cannot run or install unit tests if we don't build them or + # Nix proper (which they depend on). + (installUnitTests -> doBuild) + (doCheck -> doBuild) + # The build process for the manual currently requires extracting + # data from the Nix executable we are trying to document. + (enableManual -> doBuild) + ]); + }; + +} // lib.optionalAttrs withCoverageChecks { + lcovFilter = [ "*/boost/*" "*-tab.*" ]; + + hardeningDisable = ["fortify"]; + + NIX_CFLAGS_COMPILE = "-DCOVERAGE=1"; + + dontInstall = false; +} // lib.optionalAttrs (test-daemon != null) { + NIX_DAEMON_PACKAGE = test-daemon; +} // lib.optionalAttrs (test-client != null) { + NIX_CLIENT_PACKAGE = test-client; +}) diff --git a/packaging/components.nix b/packaging/components.nix index c29e04ae9..5cc0be784 100644 --- a/packaging/components.nix +++ b/packaging/components.nix @@ -25,6 +25,11 @@ in version = baseVersion + versionSuffix; inherit versionSuffix; + nix = callPackage ../package.nix { + version = fineVersion; + versionSuffix = fineVersionSuffix; + }; + nix-util = callPackage ../src/libutil/package.nix { }; nix-util-c = callPackage ../src/libutil-c/package.nix { }; nix-util-test-support = callPackage ../src/libutil-test-support/package.nix { }; @@ -61,5 +66,6 @@ in nix-perl-bindings = callPackage ../src/perl/package.nix { }; - nix-everything = callPackage ../packaging/everything.nix { }; + # Will replace `nix` once the old build system is gone. + nix-ng = callPackage ../packaging/everything.nix { }; } diff --git a/packaging/dev-shell.nix b/packaging/dev-shell.nix index 8ac17f61a..4b2a87632 100644 --- a/packaging/dev-shell.nix +++ b/packaging/dev-shell.nix @@ -2,7 +2,7 @@ { pkgs }: -pkgs.nixComponents.nix-util.overrideAttrs (attrs: +(pkgs.nix.override { forDevShell = true; }).overrideAttrs (attrs: let stdenv = pkgs.nixDependencies.stdenv; @@ -88,12 +88,9 @@ in { buildInputs = attrs.buildInputs or [] ++ pkgs.nixComponents.nix-util.buildInputs ++ pkgs.nixComponents.nix-store.buildInputs - ++ pkgs.nixComponents.nix-store-tests.externalBuildInputs ++ pkgs.nixComponents.nix-fetchers.buildInputs ++ pkgs.nixComponents.nix-expr.buildInputs - ++ pkgs.nixComponents.nix-expr.externalPropagatedBuildInputs - ++ pkgs.nixComponents.nix-cmd.buildInputs - ++ lib.optionals havePerl pkgs.nixComponents.nix-perl-bindings.externalBuildInputs + ++ pkgs.nixComponents.nix-store-tests.externalBuildInputs ++ lib.optional havePerl pkgs.perl ; }) diff --git a/packaging/hydra.nix b/packaging/hydra.nix index 3e5d4bbb2..6da502079 100644 --- a/packaging/hydra.nix +++ b/packaging/hydra.nix @@ -32,7 +32,7 @@ let # convention to transpose it, and to transpose it efficiently, we need to # enumerate them manually, so that we don't evaluate unnecessary package sets. forAllPackages = lib.genAttrs [ - "nix-everything" + "nix" "nix-util" "nix-util-c" "nix-util-test-support" @@ -54,6 +54,7 @@ let "nix-cmd" "nix-cli" "nix-functional-tests" + "nix-ng" ]; in { @@ -138,11 +139,11 @@ in # docker image with Nix inside dockerImage = lib.genAttrs linux64BitSystems (system: self.packages.${system}.dockerImage); - # # Line coverage analysis. - # coverage = nixpkgsFor.x86_64-linux.native.nix.override { - # pname = "nix-coverage"; - # withCoverageChecks = true; - # }; + # Line coverage analysis. + coverage = nixpkgsFor.x86_64-linux.native.nix.override { + pname = "nix-coverage"; + withCoverageChecks = true; + }; # Nix's manual manual = nixpkgsFor.x86_64-linux.native.nixComponents.nix-manual; @@ -179,7 +180,7 @@ in import (nixpkgs + "/lib/tests/test-with-nix.nix") { lib = nixpkgsFor.${system}.native.lib; - nix = self.packages.${system}.nix-cli; + nix = self.packages.${system}.nix; pkgs = nixpkgsFor.${system}.native; } ); diff --git a/scripts/local.mk b/scripts/local.mk new file mode 100644 index 000000000..46255e432 --- /dev/null +++ b/scripts/local.mk @@ -0,0 +1,13 @@ +nix_noinst_scripts := \ + $(d)/nix-profile.sh + +noinst-scripts += $(nix_noinst_scripts) + +profiledir = $(sysconfdir)/profile.d + +$(eval $(call install-file-as, $(d)/nix-profile.sh, $(profiledir)/nix.sh, 0644)) +$(eval $(call install-file-as, $(d)/nix-profile.fish, $(profiledir)/nix.fish, 0644)) +$(eval $(call install-file-as, $(d)/nix-profile-daemon.sh, $(profiledir)/nix-daemon.sh, 0644)) +$(eval $(call install-file-as, $(d)/nix-profile-daemon.fish, $(profiledir)/nix-daemon.fish, 0644)) + +clean-files += $(nix_noinst_scripts) diff --git a/src/libcmd/local.mk b/src/libcmd/local.mk new file mode 100644 index 000000000..a270333f4 --- /dev/null +++ b/src/libcmd/local.mk @@ -0,0 +1,15 @@ +libraries += libcmd + +libcmd_NAME = libnixcmd + +libcmd_DIR := $(d) + +libcmd_SOURCES := $(wildcard $(d)/*.cc) + +libcmd_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libstore) $(INCLUDE_libfetchers) $(INCLUDE_libexpr) $(INCLUDE_libflake) $(INCLUDE_libmain) + +libcmd_LDFLAGS = $(EDITLINE_LIBS) $(LOWDOWN_LIBS) $(THREAD_LDFLAGS) + +libcmd_LIBS = libutil libstore libfetchers libflake libexpr libmain + +$(eval $(call install-file-in, $(buildprefix)$(d)/nix-cmd.pc, $(libdir)/pkgconfig, 0644)) diff --git a/src/libcmd/nix-cmd.pc.in b/src/libcmd/nix-cmd.pc.in new file mode 100644 index 000000000..39575f222 --- /dev/null +++ b/src/libcmd/nix-cmd.pc.in @@ -0,0 +1,9 @@ +prefix=@prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: Nix +Description: Nix Package Manager +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -lnixcmd +Cflags: -I${includedir}/nix -std=c++2a diff --git a/src/libexpr-c/local.mk b/src/libexpr-c/local.mk new file mode 100644 index 000000000..227a4095b --- /dev/null +++ b/src/libexpr-c/local.mk @@ -0,0 +1,25 @@ +libraries += libexprc + +libexprc_NAME = libnixexprc + +libexprc_DIR := $(d) + +libexprc_SOURCES := \ + $(wildcard $(d)/*.cc) \ + +# Not just for this library itself, but also for downstream libraries using this library + +INCLUDE_libexprc := -I $(d) +libexprc_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libutilc) \ + $(INCLUDE_libfetchers) \ + $(INCLUDE_libstore) $(INCLUDE_libstorec) \ + $(INCLUDE_libexpr) $(INCLUDE_libexprc) + +libexprc_LIBS = libutil libutilc libstore libstorec libfetchers libexpr + +libexprc_LDFLAGS += $(THREAD_LDFLAGS) + +$(eval $(call install-file-in, $(d)/nix-expr-c.pc, $(libdir)/pkgconfig, 0644)) + +libexprc_FORCE_INSTALL := 1 + diff --git a/src/libexpr-c/nix-expr-c.pc.in b/src/libexpr-c/nix-expr-c.pc.in new file mode 100644 index 000000000..06897064d --- /dev/null +++ b/src/libexpr-c/nix-expr-c.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: Nix +Description: Nix Language Evaluator - C API +Version: @PACKAGE_VERSION@ +Requires: nix-store-c +Libs: -L${libdir} -lnixexprc +Cflags: -I${includedir}/nix diff --git a/src/libexpr-test-support/local.mk b/src/libexpr-test-support/local.mk new file mode 100644 index 000000000..0501de33c --- /dev/null +++ b/src/libexpr-test-support/local.mk @@ -0,0 +1,23 @@ +libraries += libexpr-test-support + +libexpr-test-support_NAME = libnixexpr-test-support + +libexpr-test-support_DIR := $(d) + +ifeq ($(INSTALL_UNIT_TESTS), yes) + libexpr-test-support_INSTALL_DIR := $(checklibdir) +else + libexpr-test-support_INSTALL_DIR := +endif + +libexpr-test-support_SOURCES := \ + $(wildcard $(d)/tests/*.cc) \ + $(wildcard $(d)/tests/value/*.cc) + +libexpr-test-support_CXXFLAGS += $(libexpr-tests_EXTRA_INCLUDES) + +libexpr-test-support_LIBS = \ + libstore-test-support libutil-test-support \ + libexpr libstore libutil + +libexpr-test-support_LDFLAGS := $(THREAD_LDFLAGS) -lrapidcheck diff --git a/src/libexpr-tests/local.mk b/src/libexpr-tests/local.mk new file mode 100644 index 000000000..79583a9ee --- /dev/null +++ b/src/libexpr-tests/local.mk @@ -0,0 +1,45 @@ +check: libexpr-tests_RUN + +programs += libexpr-tests + +libexpr-tests_NAME := libnixexpr-tests + +libexpr-tests_ENV := _NIX_TEST_UNIT_DATA=$(d)/data GTEST_OUTPUT=xml:$$testresults/libexpr-tests.xml + +libexpr-tests_DIR := $(d) + +ifeq ($(INSTALL_UNIT_TESTS), yes) + libexpr-tests_INSTALL_DIR := $(checkbindir) +else + libexpr-tests_INSTALL_DIR := +endif + +libexpr-tests_SOURCES := \ + $(wildcard $(d)/*.cc) \ + $(wildcard $(d)/value/*.cc) \ + $(wildcard $(d)/flake/*.cc) + +libexpr-tests_EXTRA_INCLUDES = \ + -I src/libexpr-test-support \ + -I src/libstore-test-support \ + -I src/libutil-test-support \ + $(INCLUDE_libexpr) \ + $(INCLUDE_libexprc) \ + $(INCLUDE_libfetchers) \ + $(INCLUDE_libstore) \ + $(INCLUDE_libstorec) \ + $(INCLUDE_libutil) \ + $(INCLUDE_libutilc) + +libexpr-tests_CXXFLAGS += $(libexpr-tests_EXTRA_INCLUDES) + +libexpr-tests_LIBS = \ + libexpr-test-support libstore-test-support libutil-test-support \ + libexpr libexprc libfetchers libstore libstorec libutil libutilc + +libexpr-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) -lgmock + +ifdef HOST_WINDOWS + # Increase the default reserved stack size to 65 MB so Nix doesn't run out of space + libexpr-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024))) +endif diff --git a/src/libexpr/local.mk b/src/libexpr/local.mk new file mode 100644 index 000000000..68518e184 --- /dev/null +++ b/src/libexpr/local.mk @@ -0,0 +1,50 @@ +libraries += libexpr + +libexpr_NAME = libnixexpr + +libexpr_DIR := $(d) + +libexpr_SOURCES := \ + $(wildcard $(d)/*.cc) \ + $(wildcard $(d)/value/*.cc) \ + $(wildcard $(d)/primops/*.cc) \ + $(d)/lexer-tab.cc \ + $(d)/parser-tab.cc +# Not just for this library itself, but also for downstream libraries using this library + +INCLUDE_libexpr := -I $(d) + +libexpr_CXXFLAGS += \ + $(INCLUDE_libutil) $(INCLUDE_libstore) $(INCLUDE_libfetchers) $(INCLUDE_libexpr) \ + -DGC_THREADS + +libexpr_LIBS = libutil libstore libfetchers + +libexpr_LDFLAGS += -lboost_context $(THREAD_LDFLAGS) +ifdef HOST_LINUX + libexpr_LDFLAGS += -ldl +endif + +# The dependency on libgc must be propagated (i.e. meaning that +# programs/libraries that use libexpr must explicitly pass -lgc), +# because inline functions in libexpr's header files call libgc. +libexpr_LDFLAGS_PROPAGATED = $(BDW_GC_LIBS) + +libexpr_ORDER_AFTER := $(d)/parser-tab.cc $(d)/parser-tab.hh $(d)/lexer-tab.cc $(d)/lexer-tab.hh + +$(d)/parser-tab.cc $(d)/parser-tab.hh: $(d)/parser.y + $(trace-gen) bison -v -o $(libexpr_DIR)/parser-tab.cc $< -d + +$(d)/lexer-tab.cc $(d)/lexer-tab.hh: $(d)/lexer.l + $(trace-gen) flex --outfile $(libexpr_DIR)/lexer-tab.cc --header-file=$(libexpr_DIR)/lexer-tab.hh $< + +clean-files += $(d)/parser-tab.cc $(d)/parser-tab.hh $(d)/lexer-tab.cc $(d)/lexer-tab.hh + +$(eval $(call install-file-in, $(buildprefix)$(d)/nix-expr.pc, $(libdir)/pkgconfig, 0644)) + +$(foreach i, $(wildcard src/libexpr/value/*.hh), \ + $(eval $(call install-file-in, $(i), $(includedir)/nix/value, 0644))) + +$(d)/primops.cc: $(d)/imported-drv-to-derivation.nix.gen.hh + +$(d)/eval.cc: $(d)/primops/derivation.nix.gen.hh $(d)/fetchurl.nix.gen.hh $(d)/call-flake.nix.gen.hh diff --git a/src/libexpr/nix-expr.pc.in b/src/libexpr/nix-expr.pc.in new file mode 100644 index 000000000..60ffb5dba --- /dev/null +++ b/src/libexpr/nix-expr.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: Nix +Description: Nix Package Manager +Version: @PACKAGE_VERSION@ +Requires: nix-store bdw-gc +Libs: -L${libdir} -lnixexpr +Cflags: -I${includedir}/nix -std=c++2a diff --git a/src/libexpr/package.nix b/src/libexpr/package.nix index d97e7f3a8..ca1f8bf21 100644 --- a/src/libexpr/package.nix +++ b/src/libexpr/package.nix @@ -71,10 +71,6 @@ mkMesonLibrary (finalAttrs: { nix-util nix-store nix-fetchers - ] ++ finalAttrs.passthru.externalPropagatedBuildInputs; - - # Hack for sake of the dev shell - passthru.externalPropagatedBuildInputs = [ boost nlohmann_json ] ++ lib.optional enableGC boehmgc; diff --git a/src/libfetchers-tests/local.mk b/src/libfetchers-tests/local.mk new file mode 100644 index 000000000..5c90f1fc7 --- /dev/null +++ b/src/libfetchers-tests/local.mk @@ -0,0 +1,37 @@ +check: libfetchers-tests_RUN + +programs += libfetchers-tests + +libfetchers-tests_NAME = libnixfetchers-tests + +libfetchers-tests_ENV := _NIX_TEST_UNIT_DATA=$(d)/data GTEST_OUTPUT=xml:$$testresults/libfetchers-tests.xml + +libfetchers-tests_DIR := $(d) + +ifeq ($(INSTALL_UNIT_TESTS), yes) + libfetchers-tests_INSTALL_DIR := $(checkbindir) +else + libfetchers-tests_INSTALL_DIR := +endif + +libfetchers-tests_SOURCES := $(wildcard $(d)/*.cc) + +libfetchers-tests_EXTRA_INCLUDES = \ + -I src/libstore-test-support \ + -I src/libutil-test-support \ + $(INCLUDE_libfetchers) \ + $(INCLUDE_libstore) \ + $(INCLUDE_libutil) + +libfetchers-tests_CXXFLAGS += $(libfetchers-tests_EXTRA_INCLUDES) + +libfetchers-tests_LIBS = \ + libstore-test-support libutil-test-support \ + libfetchers libstore libutil + +libfetchers-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) $(LIBGIT2_LIBS) + +ifdef HOST_WINDOWS + # Increase the default reserved stack size to 65 MB so Nix doesn't run out of space + libfetchers-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024))) +endif diff --git a/src/libfetchers/local.mk b/src/libfetchers/local.mk new file mode 100644 index 000000000..e229a0993 --- /dev/null +++ b/src/libfetchers/local.mk @@ -0,0 +1,17 @@ +libraries += libfetchers + +libfetchers_NAME = libnixfetchers + +libfetchers_DIR := $(d) + +libfetchers_SOURCES := $(wildcard $(d)/*.cc) + +# Not just for this library itself, but also for downstream libraries using this library + +INCLUDE_libfetchers := -I $(d) + +libfetchers_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libstore) $(INCLUDE_libfetchers) + +libfetchers_LDFLAGS += $(THREAD_LDFLAGS) $(LIBGIT2_LIBS) -larchive + +libfetchers_LIBS = libutil libstore diff --git a/src/libflake-tests/local.mk b/src/libflake-tests/local.mk new file mode 100644 index 000000000..8599b43f6 --- /dev/null +++ b/src/libflake-tests/local.mk @@ -0,0 +1,43 @@ +check: libflake-tests_RUN + +programs += libflake-tests + +libflake-tests_NAME := libnixflake-tests + +libflake-tests_ENV := _NIX_TEST_UNIT_DATA=$(d)/data GTEST_OUTPUT=xml:$$testresults/libflake-tests.xml + +libflake-tests_DIR := $(d) + +ifeq ($(INSTALL_UNIT_TESTS), yes) + libflake-tests_INSTALL_DIR := $(checkbindir) +else + libflake-tests_INSTALL_DIR := +endif + +libflake-tests_SOURCES := \ + $(wildcard $(d)/*.cc) \ + $(wildcard $(d)/value/*.cc) \ + $(wildcard $(d)/flake/*.cc) + +libflake-tests_EXTRA_INCLUDES = \ + -I src/libflake-test-support \ + -I src/libstore-test-support \ + -I src/libutil-test-support \ + $(INCLUDE_libflake) \ + $(INCLUDE_libexpr) \ + $(INCLUDE_libfetchers) \ + $(INCLUDE_libstore) \ + $(INCLUDE_libutil) \ + +libflake-tests_CXXFLAGS += $(libflake-tests_EXTRA_INCLUDES) + +libflake-tests_LIBS = \ + libexpr-test-support libstore-test-support libutil-test-support \ + libflake libexpr libfetchers libstore libutil + +libflake-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) -lgmock + +ifdef HOST_WINDOWS + # Increase the default reserved stack size to 65 MB so Nix doesn't run out of space + libflake-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024))) +endif diff --git a/src/libflake/flake/nix-flake.pc.in b/src/libflake/flake/nix-flake.pc.in new file mode 100644 index 000000000..10c52f5e9 --- /dev/null +++ b/src/libflake/flake/nix-flake.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: Nix +Description: Nix Package Manager +Version: @PACKAGE_VERSION@ +Requires: nix-util nix-store nix-expr +Libs: -L${libdir} -lnixflake +Cflags: -I${includedir}/nix -std=c++2a diff --git a/src/libflake/local.mk b/src/libflake/local.mk new file mode 100644 index 000000000..5e604ef3a --- /dev/null +++ b/src/libflake/local.mk @@ -0,0 +1,22 @@ +libraries += libflake + +libflake_NAME = libnixflake + +libflake_DIR := $(d) + +libflake_SOURCES := $(wildcard $(d)/*.cc $(d)/flake/*.cc) + +# Not just for this library itself, but also for downstream libraries using this library + +INCLUDE_libflake := -I $(d) + +libflake_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libstore) $(INCLUDE_libfetchers) $(INCLUDE_libexpr) $(INCLUDE_libflake) + +libflake_LDFLAGS += $(THREAD_LDFLAGS) + +libflake_LIBS = libutil libstore libfetchers libexpr + +$(eval $(call install-file-in, $(buildprefix)$(d)/flake/nix-flake.pc, $(libdir)/pkgconfig, 0644)) + +$(foreach i, $(wildcard src/libflake/flake/*.hh), \ + $(eval $(call install-file-in, $(i), $(includedir)/nix/flake, 0644))) diff --git a/src/libmain/local.mk b/src/libmain/local.mk new file mode 100644 index 000000000..d41c49dd7 --- /dev/null +++ b/src/libmain/local.mk @@ -0,0 +1,22 @@ +libraries += libmain + +libmain_NAME = libnixmain + +libmain_DIR := $(d) + +libmain_SOURCES := $(wildcard $(d)/*.cc) +ifdef HOST_UNIX + libmain_SOURCES += $(wildcard $(d)/unix/*.cc) +endif + +INCLUDE_libmain := -I $(d) + +libmain_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libstore) $(INCLUDE_libmain) + +libmain_LDFLAGS += $(OPENSSL_LIBS) + +libmain_LIBS = libstore libutil + +libmain_ALLOW_UNDEFINED = 1 + +$(eval $(call install-file-in, $(buildprefix)$(d)/nix-main.pc, $(libdir)/pkgconfig, 0644)) diff --git a/src/libmain/nix-main.pc.in b/src/libmain/nix-main.pc.in new file mode 100644 index 000000000..fb3ead6fa --- /dev/null +++ b/src/libmain/nix-main.pc.in @@ -0,0 +1,9 @@ +prefix=@prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: Nix +Description: Nix Package Manager +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -lnixmain +Cflags: -I${includedir}/nix -std=c++2a diff --git a/src/libstore-c/local.mk b/src/libstore-c/local.mk new file mode 100644 index 000000000..5e3eff06a --- /dev/null +++ b/src/libstore-c/local.mk @@ -0,0 +1,21 @@ +libraries += libstorec + +libstorec_NAME = libnixstorec + +libstorec_DIR := $(d) + +libstorec_SOURCES := $(wildcard $(d)/*.cc) + +libstorec_LIBS = libutil libstore libutilc + +libstorec_LDFLAGS += $(THREAD_LDFLAGS) + +# Not just for this library itself, but also for downstream libraries using this library + +INCLUDE_libstorec := -I $(d) +libstorec_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libutilc) \ + $(INCLUDE_libstore) $(INCLUDE_libstorec) + +$(eval $(call install-file-in, $(d)/nix-store-c.pc, $(libdir)/pkgconfig, 0644)) + +libstorec_FORCE_INSTALL := 1 diff --git a/src/libstore-c/nix-store-c.pc.in b/src/libstore-c/nix-store-c.pc.in new file mode 100644 index 000000000..de3c7b4c6 --- /dev/null +++ b/src/libstore-c/nix-store-c.pc.in @@ -0,0 +1,9 @@ +prefix=@prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: Nix +Description: Nix Store - C API +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -lnixstorec -lnixutilc +Cflags: -I${includedir}/nix diff --git a/src/libstore-test-support/local.mk b/src/libstore-test-support/local.mk new file mode 100644 index 000000000..56dedd825 --- /dev/null +++ b/src/libstore-test-support/local.mk @@ -0,0 +1,21 @@ +libraries += libstore-test-support + +libstore-test-support_NAME = libnixstore-test-support + +libstore-test-support_DIR := $(d) + +ifeq ($(INSTALL_UNIT_TESTS), yes) + libstore-test-support_INSTALL_DIR := $(checklibdir) +else + libstore-test-support_INSTALL_DIR := +endif + +libstore-test-support_SOURCES := $(wildcard $(d)/tests/*.cc) + +libstore-test-support_CXXFLAGS += $(libstore-tests_EXTRA_INCLUDES) + +libstore-test-support_LIBS = \ + libutil-test-support \ + libstore libutil + +libstore-test-support_LDFLAGS := $(THREAD_LDFLAGS) -lrapidcheck diff --git a/src/libstore-tests/local.mk b/src/libstore-tests/local.mk new file mode 100644 index 000000000..b565ff0be --- /dev/null +++ b/src/libstore-tests/local.mk @@ -0,0 +1,38 @@ +check: libstore-tests_RUN + +programs += libstore-tests + +libstore-tests_NAME = libnixstore-tests + +libstore-tests_ENV := _NIX_TEST_UNIT_DATA=$(d)/data GTEST_OUTPUT=xml:$$testresults/libstore-tests.xml + +libstore-tests_DIR := $(d) + +ifeq ($(INSTALL_UNIT_TESTS), yes) + libstore-tests_INSTALL_DIR := $(checkbindir) +else + libstore-tests_INSTALL_DIR := +endif + +libstore-tests_SOURCES := $(wildcard $(d)/*.cc) + +libstore-tests_EXTRA_INCLUDES = \ + -I src/libstore-test-support \ + -I src/libutil-test-support \ + $(INCLUDE_libstore) \ + $(INCLUDE_libstorec) \ + $(INCLUDE_libutil) \ + $(INCLUDE_libutilc) + +libstore-tests_CXXFLAGS += $(libstore-tests_EXTRA_INCLUDES) + +libstore-tests_LIBS = \ + libstore-test-support libutil-test-support \ + libstore libstorec libutil libutilc + +libstore-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) + +ifdef HOST_WINDOWS + # Increase the default reserved stack size to 65 MB so Nix doesn't run out of space + libstore-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024))) +endif diff --git a/src/libstore/local.mk b/src/libstore/local.mk new file mode 100644 index 000000000..43d8993ba --- /dev/null +++ b/src/libstore/local.mk @@ -0,0 +1,103 @@ +libraries += libstore + +libstore_NAME = libnixstore + +libstore_DIR := $(d) + +libstore_SOURCES := $(wildcard $(d)/*.cc $(d)/builtins/*.cc $(d)/build/*.cc) +ifdef HOST_UNIX + libstore_SOURCES += $(wildcard $(d)/unix/*.cc $(d)/unix/build/*.cc) +endif +ifdef HOST_LINUX + libstore_SOURCES += $(wildcard $(d)/linux/*.cc) +endif +ifdef HOST_WINDOWS + libstore_SOURCES += $(wildcard $(d)/windows/*.cc) +endif + +libstore_LIBS = libutil + +libstore_LDFLAGS += $(SQLITE3_LIBS) $(LIBCURL_LIBS) $(THREAD_LDFLAGS) +ifdef HOST_LINUX + libstore_LDFLAGS += -ldl +endif +ifdef HOST_WINDOWS + libstore_LDFLAGS += -lws2_32 +endif + +$(foreach file,$(libstore_FILES),$(eval $(call install-data-in,$(d)/$(file),$(datadir)/nix/sandbox))) + +ifeq ($(ENABLE_S3), 1) + libstore_LDFLAGS += -laws-cpp-sdk-transfer -laws-cpp-sdk-s3 -laws-cpp-sdk-core -laws-crt-cpp +endif + +ifdef HOST_SOLARIS + libstore_LDFLAGS += -lsocket +endif + +ifeq ($(HAVE_SECCOMP), 1) + libstore_LDFLAGS += $(LIBSECCOMP_LIBS) +endif + +# Not just for this library itself, but also for downstream libraries using this library + +INCLUDE_libstore := -I $(d) -I $(d)/build +ifdef HOST_UNIX + INCLUDE_libstore += -I $(d)/unix -I $(d)/unix/build +endif +ifdef HOST_LINUX + INCLUDE_libstore += -I $(d)/linux +endif +ifdef HOST_WINDOWS + INCLUDE_libstore += -I $(d)/windows +endif + +ifdef HOST_WINDOWS +NIX_ROOT = N:\\\\ +else +NIX_ROOT = +endif + +# Prefix all but `NIX_STORE_DIR`, since we aren't doing a local store +# yet so a "logical" store dir that is the same as unix is preferred. +# +# Also, it keeps the unit tests working. + +libstore_CXXFLAGS += \ + $(INCLUDE_libutil) $(INCLUDE_libstore) $(INCLUDE_libstore) \ + -DNIX_PREFIX=\"$(NIX_ROOT)$(prefix)\" \ + -DNIX_STORE_DIR=\"$(storedir)\" \ + -DNIX_DATA_DIR=\"$(NIX_ROOT)$(datadir)\" \ + -DNIX_STATE_DIR=\"$(NIX_ROOT)$(localstatedir)/nix\" \ + -DNIX_LOG_DIR=\"$(NIX_ROOT)$(localstatedir)/log/nix\" \ + -DNIX_CONF_DIR=\"$(NIX_ROOT)$(sysconfdir)/nix\" \ + -DNIX_MAN_DIR=\"$(NIX_ROOT)$(mandir)\" \ + -DLSOF=\"$(NIX_ROOT)$(lsof)\" + +ifeq ($(embedded_sandbox_shell),yes) +libstore_CXXFLAGS += -DSANDBOX_SHELL=\"__embedded_sandbox_shell__\" + +$(d)/unix/build/local-derivation-goal.cc: $(d)/unix/embedded-sandbox-shell.gen.hh + +$(d)/unix/embedded-sandbox-shell.gen.hh: $(sandbox_shell) + $(trace-gen) hexdump -v -e '1/1 "0x%x," "\n"' < $< > $@.tmp + @mv $@.tmp $@ +else + ifneq ($(sandbox_shell),) + libstore_CXXFLAGS += -DSANDBOX_SHELL="\"$(sandbox_shell)\"" + endif +endif + +$(d)/local-store.cc: $(d)/schema.sql.gen.hh $(d)/ca-specific-schema.sql.gen.hh + +$(d)/unix/build.cc: + +clean-files += $(d)/schema.sql.gen.hh $(d)/ca-specific-schema.sql.gen.hh + +$(eval $(call install-file-in, $(buildprefix)$(d)/nix-store.pc, $(libdir)/pkgconfig, 0644)) + +$(foreach i, $(wildcard src/libstore/builtins/*.hh), \ + $(eval $(call install-file-in, $(i), $(includedir)/nix/builtins, 0644))) + +$(foreach i, $(wildcard src/libstore/build/*.hh), \ + $(eval $(call install-file-in, $(i), $(includedir)/nix/build, 0644))) diff --git a/src/libstore/nix-store.pc.in b/src/libstore/nix-store.pc.in new file mode 100644 index 000000000..cd3f2b8da --- /dev/null +++ b/src/libstore/nix-store.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: Nix +Description: Nix Package Manager +Version: @PACKAGE_VERSION@ +Requires: nix-util +Libs: -L${libdir} -lnixstore +Cflags: -I${includedir}/nix -std=c++2a diff --git a/src/libutil-c/local.mk b/src/libutil-c/local.mk new file mode 100644 index 000000000..f2df1ef43 --- /dev/null +++ b/src/libutil-c/local.mk @@ -0,0 +1,18 @@ +libraries += libutilc + +libutilc_NAME = libnixutilc + +libutilc_DIR := $(d) + +libutilc_SOURCES := $(wildcard $(d)/*.cc) + +# Not just for this library itself, but also for downstream libraries using this library + +INCLUDE_libutilc := -I $(d) +libutilc_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libutilc) + +libutilc_LIBS = libutil + +libutilc_LDFLAGS += $(THREAD_LDFLAGS) + +libutilc_FORCE_INSTALL := 1 diff --git a/src/libutil-c/nix-util-c.pc.in b/src/libutil-c/nix-util-c.pc.in new file mode 100644 index 000000000..0ccae3f8a --- /dev/null +++ b/src/libutil-c/nix-util-c.pc.in @@ -0,0 +1,9 @@ +prefix=@prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: Nix libutil C API +Description: Common functions for the Nix C API, such as error handling +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -lnixutil +Cflags: -I${includedir}/nix -std=c++2a diff --git a/src/libutil-test-support/local.mk b/src/libutil-test-support/local.mk new file mode 100644 index 000000000..5f7835c9f --- /dev/null +++ b/src/libutil-test-support/local.mk @@ -0,0 +1,19 @@ +libraries += libutil-test-support + +libutil-test-support_NAME = libnixutil-test-support + +libutil-test-support_DIR := $(d) + +ifeq ($(INSTALL_UNIT_TESTS), yes) + libutil-test-support_INSTALL_DIR := $(checklibdir) +else + libutil-test-support_INSTALL_DIR := +endif + +libutil-test-support_SOURCES := $(wildcard $(d)/tests/*.cc) + +libutil-test-support_CXXFLAGS += $(libutil-tests_EXTRA_INCLUDES) + +libutil-test-support_LIBS = libutil + +libutil-test-support_LDFLAGS := $(THREAD_LDFLAGS) -lrapidcheck diff --git a/src/libutil-tests/local.mk b/src/libutil-tests/local.mk new file mode 100644 index 000000000..c747863a4 --- /dev/null +++ b/src/libutil-tests/local.mk @@ -0,0 +1,37 @@ +check: libutil-tests_RUN + +programs += libutil-tests + +libutil-tests_NAME = libnixutil-tests + +libutil-tests_ENV := _NIX_TEST_UNIT_DATA=$(d)/data GTEST_OUTPUT=xml:$$testresults/libutil-tests.xml + +libutil-tests_DIR := $(d) + +ifeq ($(INSTALL_UNIT_TESTS), yes) + libutil-tests_INSTALL_DIR := $(checkbindir) +else + libutil-tests_INSTALL_DIR := +endif + +libutil-tests_SOURCES := $(wildcard $(d)/*.cc) + +libutil-tests_EXTRA_INCLUDES = \ + -I src/libutil-test-support \ + $(INCLUDE_libutil) \ + $(INCLUDE_libutilc) + +libutil-tests_CXXFLAGS += $(libutil-tests_EXTRA_INCLUDES) + +libutil-tests_LIBS = libutil-test-support libutil libutilc + +libutil-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) + +ifdef HOST_WINDOWS + # Increase the default reserved stack size to 65 MB so Nix doesn't run out of space + libutil-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024))) +endif + +check: $(d)/data/git/check-data.sh.test + +$(eval $(call run-test,$(d)/data/git/check-data.sh)) diff --git a/src/libutil/local.mk b/src/libutil/local.mk new file mode 100644 index 000000000..e9b498e65 --- /dev/null +++ b/src/libutil/local.mk @@ -0,0 +1,44 @@ +libraries += libutil + +libutil_NAME = libnixutil + +libutil_DIR := $(d) + +libutil_SOURCES := $(wildcard $(d)/*.cc $(d)/signature/*.cc) +ifdef HOST_UNIX + libutil_SOURCES += $(wildcard $(d)/unix/*.cc) +endif +ifdef HOST_LINUX + libutil_SOURCES += $(wildcard $(d)/linux/*.cc) +endif +ifdef HOST_WINDOWS + libutil_SOURCES += $(wildcard $(d)/windows/*.cc) +endif + +# Not just for this library itself, but also for downstream libraries using this library + +INCLUDE_libutil := -I $(d) +ifdef HOST_UNIX + INCLUDE_libutil += -I $(d)/unix +endif +ifdef HOST_LINUX + INCLUDE_libutil += -I $(d)/linux +endif +ifdef HOST_WINDOWS + INCLUDE_libutil += -I $(d)/windows +endif +libutil_CXXFLAGS += $(INCLUDE_libutil) + +libutil_LDFLAGS += $(THREAD_LDFLAGS) $(LIBCURL_LIBS) $(SODIUM_LIBS) $(OPENSSL_LIBS) $(LIBBROTLI_LIBS) $(LIBARCHIVE_LIBS) $(BOOST_LDFLAGS) -lboost_context + +$(foreach i, $(wildcard $(d)/args/*.hh), \ + $(eval $(call install-file-in, $(i), $(includedir)/nix/args, 0644))) +$(foreach i, $(wildcard $(d)/signature/*.hh), \ + $(eval $(call install-file-in, $(i), $(includedir)/nix/signature, 0644))) + + +ifeq ($(HAVE_LIBCPUID), 1) + libutil_LDFLAGS += -lcpuid +endif + +$(eval $(call install-file-in, $(buildprefix)$(d)/nix-util.pc, $(libdir)/pkgconfig, 0644)) diff --git a/src/libutil/nix-util.pc.in b/src/libutil/nix-util.pc.in new file mode 100644 index 000000000..85bb1e70e --- /dev/null +++ b/src/libutil/nix-util.pc.in @@ -0,0 +1,9 @@ +prefix=@prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: Nix +Description: Nix Package Manager +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -lnixutil +Cflags: -I${includedir}/nix -std=c++2a diff --git a/src/nix/local.mk b/src/nix/local.mk new file mode 100644 index 000000000..b57f6b3e2 --- /dev/null +++ b/src/nix/local.mk @@ -0,0 +1,59 @@ +programs += nix + +nix_DIR := $(d) + +nix_SOURCES := \ + $(wildcard $(d)/*.cc) \ + $(wildcard src/nix-build/*.cc) \ + $(wildcard src/nix-env/*.cc) \ + $(wildcard src/nix-instantiate/*.cc) \ + $(wildcard src/nix-store/*.cc) + +ifdef HOST_UNIX +nix_SOURCES += \ + $(wildcard $(d)/unix/*.cc) \ + $(wildcard src/build-remote/*.cc) \ + $(wildcard src/nix-channel/*.cc) \ + $(wildcard src/nix-collect-garbage/*.cc) \ + $(wildcard src/nix-copy-closure/*.cc) \ + $(wildcard src/nix-daemon/*.cc) +endif + +INCLUDE_nix := -I $(d) +ifdef HOST_UNIX + INCLUDE_nix += -I $(d)/unix +endif + +nix_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libstore) $(INCLUDE_libfetchers) $(INCLUDE_libexpr) $(INCLUDE_libflake) $(INCLUDE_libmain) -I src/libcmd -I doc/manual $(INCLUDE_nix) + +nix_CXXFLAGS += -DNIX_BIN_DIR=\"$(NIX_ROOT)$(bindir)\" + +nix_LIBS = libexpr libmain libfetchers libflake libstore libutil libcmd + +nix_LDFLAGS = $(THREAD_LDFLAGS) $(SODIUM_LIBS) $(EDITLINE_LIBS) $(BOOST_LDFLAGS) $(LOWDOWN_LIBS) + +ifdef HOST_WINDOWS + # Increase the default reserved stack size to 65 MB so Nix doesn't run out of space + nix_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024))) +endif + +$(foreach name, \ + nix-build nix-channel nix-collect-garbage nix-copy-closure nix-daemon nix-env nix-hash nix-instantiate nix-prefetch-url nix-shell nix-store, \ + $(eval $(call install-symlink, nix, $(bindir)/$(name)))) +$(eval $(call install-symlink, $(bindir)/nix, $(libexecdir)/nix/build-remote)) + +src/nix-env/user-env.cc: src/nix-env/buildenv.nix.gen.hh + +$(d)/develop.cc: $(d)/get-env.sh.gen.hh + +src/nix-channel/nix-channel.cc: src/nix-channel/unpack-channel.nix.gen.hh + +$(d)/main.cc: \ + doc/manual/generate-manpage.nix.gen.hh \ + doc/manual/utils.nix.gen.hh doc/manual/generate-settings.nix.gen.hh \ + doc/manual/generate-store-info.nix.gen.hh \ + $(d)/help-stores.md.gen.hh + +$(d)/profile.cc: $(d)/profile.md + +$(d)/profile.md: $(d)/profiles.md.gen.hh diff --git a/src/perl/package.nix b/src/perl/package.nix index 5ee0df13c..fe617fd47 100644 --- a/src/perl/package.nix +++ b/src/perl/package.nix @@ -40,10 +40,6 @@ perl.pkgs.toPerlModule (mkMesonDerivation (finalAttrs: { buildInputs = [ nix-store - ] ++ finalAttrs.passthru.externalBuildInputs; - - # Hack for sake of the dev shell - passthru.externalBuildInputs = [ bzip2 libsodium ]; diff --git a/tests/functional/build-hook-ca-fixed.nix b/tests/functional/build-hook-ca-fixed.nix index 0ce6d9b12..427ec2c31 100644 --- a/tests/functional/build-hook-ca-fixed.nix +++ b/tests/functional/build-hook-ca-fixed.nix @@ -1,6 +1,6 @@ { busybox }: -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; let diff --git a/tests/functional/build-hook.nix b/tests/functional/build-hook.nix index 99a13aee4..1f0e17a3b 100644 --- a/tests/functional/build-hook.nix +++ b/tests/functional/build-hook.nix @@ -1,6 +1,6 @@ { busybox, contentAddressed ? false }: -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; let diff --git a/tests/functional/ca/config.nix b/tests/functional/ca/config.nix deleted file mode 100644 index 451fbae4f..000000000 --- a/tests/functional/ca/config.nix +++ /dev/null @@ -1,2 +0,0 @@ -# Shim to get generated file -import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/ca/config.nix" diff --git a/tests/functional/ca/content-addressed.nix b/tests/functional/ca/content-addressed.nix index 2559c562f..411ebb86b 100644 --- a/tests/functional/ca/content-addressed.nix +++ b/tests/functional/ca/content-addressed.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/ca/config.nix"; let mkCADerivation = args: mkDerivation ({ __contentAddressed = true; diff --git a/tests/functional/ca/local.mk b/tests/functional/ca/local.mk new file mode 100644 index 000000000..7c2fcc451 --- /dev/null +++ b/tests/functional/ca/local.mk @@ -0,0 +1,29 @@ +ca-tests := \ + $(d)/build-with-garbage-path.sh \ + $(d)/build.sh \ + $(d)/build-cache.sh \ + $(d)/concurrent-builds.sh \ + $(d)/derivation-json.sh \ + $(d)/duplicate-realisation-in-closure.sh \ + $(d)/eval-store.sh \ + $(d)/gc.sh \ + $(d)/import-from-derivation.sh \ + $(d)/new-build-cmd.sh \ + $(d)/nix-copy.sh \ + $(d)/nix-run.sh \ + $(d)/nix-shell.sh \ + $(d)/post-hook.sh \ + $(d)/recursive.sh \ + $(d)/repl.sh \ + $(d)/selfref-gc.sh \ + $(d)/signatures.sh \ + $(d)/substitute.sh \ + $(d)/why-depends.sh + +install-tests-groups += ca + +clean-files += \ + $(d)/config.nix + +test-deps += \ + tests/functional/ca/config.nix diff --git a/tests/functional/ca/nix-run.sh b/tests/functional/ca/nix-run.sh index e6638cc91..21c09117e 100755 --- a/tests/functional/ca/nix-run.sh +++ b/tests/functional/ca/nix-run.sh @@ -6,4 +6,7 @@ flakeDir="$TEST_HOME/flake" mkdir -p "${flakeDir}" cp flake.nix "${_NIX_TEST_BUILD_DIR}/ca/config.nix" content-addressed.nix "${flakeDir}" +# `config.nix` cannot be gotten via build dir / env var (runs afoul pure eval). Instead get from flake. +removeBuildDirRef "$flakeDir"/*.nix + nix run --no-write-lock-file "path:${flakeDir}#runnable" diff --git a/tests/functional/ca/nondeterministic.nix b/tests/functional/ca/nondeterministic.nix index d6d099a3e..740be4bd2 100644 --- a/tests/functional/ca/nondeterministic.nix +++ b/tests/functional/ca/nondeterministic.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/ca/config.nix"; let mkCADerivation = args: mkDerivation ({ __contentAddressed = true; diff --git a/tests/functional/ca/racy.nix b/tests/functional/ca/racy.nix index 555a15484..cadd98675 100644 --- a/tests/functional/ca/racy.nix +++ b/tests/functional/ca/racy.nix @@ -2,7 +2,7 @@ # build it at once. -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/ca/config.nix"; mkDerivation { name = "simple"; diff --git a/tests/functional/check-refs.nix b/tests/functional/check-refs.nix index 89690e456..54957f635 100644 --- a/tests/functional/check-refs.nix +++ b/tests/functional/check-refs.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; rec { diff --git a/tests/functional/check-reqs.nix b/tests/functional/check-reqs.nix index 41436cb48..4e059f5a4 100644 --- a/tests/functional/check-reqs.nix +++ b/tests/functional/check-reqs.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; rec { dep1 = mkDerivation { diff --git a/tests/functional/check.nix b/tests/functional/check.nix index ddab8eea9..13638eae8 100644 --- a/tests/functional/check.nix +++ b/tests/functional/check.nix @@ -1,6 +1,6 @@ {checkBuildId ? 0}: -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; { nondeterministic = mkDerivation { diff --git a/tests/functional/chroot-store.sh b/tests/functional/chroot-store.sh index 46e91f0aa..8c2a969d3 100755 --- a/tests/functional/chroot-store.sh +++ b/tests/functional/chroot-store.sh @@ -39,6 +39,9 @@ EOF cp simple.nix shell.nix simple.builder.sh "${config_nix}" "$flakeDir/" + # `config.nix` cannot be gotten via build dir / env var (runs afoul pure eval). Instead get from flake. + removeBuildDirRef "$flakeDir"/*.nix + TODO_NixOS outPath=$(nix build --print-out-paths --no-link --sandbox-paths '/nix? /bin? /lib? /lib64? /usr?' --store "$TEST_ROOT/x" path:"$flakeDir") diff --git a/tests/functional/common/functions.sh b/tests/functional/common/functions.sh index 7195149cb..286bb58e8 100644 --- a/tests/functional/common/functions.sh +++ b/tests/functional/common/functions.sh @@ -343,6 +343,15 @@ count() { echo $# } +# Sometimes, e.g. due to pure eval, restricted eval, or sandboxing, we +# cannot look up `config.nix` in the build dir, and have to instead get +# it from the current directory. (In this case, the current directly +# will be somewhere in `$TEST_ROOT`.) +removeBuildDirRef() { + # shellcheck disable=SC2016 # The ${} in this is Nix, not shell + sed -i -e 's,"${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/[^ ]*config.nix",./config.nix,' "$@" +} + trap onError ERR fi # COMMON_FUNCTIONS_SH_SOURCED diff --git a/tests/functional/config.nix b/tests/functional/config.nix deleted file mode 100644 index 5d1cb74ec..000000000 --- a/tests/functional/config.nix +++ /dev/null @@ -1,2 +0,0 @@ -# Shim to get generated file -import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix" diff --git a/tests/functional/dependencies.nix b/tests/functional/dependencies.nix index be1a7ae9a..db06321da 100644 --- a/tests/functional/dependencies.nix +++ b/tests/functional/dependencies.nix @@ -1,5 +1,5 @@ { hashInvalidator ? "" }: -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; let { diff --git a/tests/functional/dyn-drv/config.nix b/tests/functional/dyn-drv/config.nix deleted file mode 100644 index 8ec2c67ea..000000000 --- a/tests/functional/dyn-drv/config.nix +++ /dev/null @@ -1,2 +0,0 @@ -# Shim to get generated file -import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/dyn-drv/config.nix" diff --git a/tests/functional/dyn-drv/local.mk b/tests/functional/dyn-drv/local.mk new file mode 100644 index 000000000..c87534944 --- /dev/null +++ b/tests/functional/dyn-drv/local.mk @@ -0,0 +1,15 @@ +dyn-drv-tests := \ + $(d)/text-hashed-output.sh \ + $(d)/recursive-mod-json.sh \ + $(d)/build-built-drv.sh \ + $(d)/eval-outputOf.sh \ + $(d)/dep-built-drv.sh \ + $(d)/old-daemon-error-hack.sh + +install-tests-groups += dyn-drv + +clean-files += \ + $(d)/config.nix + +test-deps += \ + tests/functional/dyn-drv/config.nix diff --git a/tests/functional/dyn-drv/old-daemon-error-hack.nix b/tests/functional/dyn-drv/old-daemon-error-hack.nix index c9d4a62d4..7d3ccf7e4 100644 --- a/tests/functional/dyn-drv/old-daemon-error-hack.nix +++ b/tests/functional/dyn-drv/old-daemon-error-hack.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/dyn-drv/config.nix"; # A simple content-addressed derivation. # The derivation can be arbitrarily modified by passing a different `seed`, diff --git a/tests/functional/dyn-drv/recursive-mod-json.nix b/tests/functional/dyn-drv/recursive-mod-json.nix index c6a24ca4f..0e778aa7f 100644 --- a/tests/functional/dyn-drv/recursive-mod-json.nix +++ b/tests/functional/dyn-drv/recursive-mod-json.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/dyn-drv/config.nix"; let innerName = "foo"; in diff --git a/tests/functional/dyn-drv/text-hashed-output.nix b/tests/functional/dyn-drv/text-hashed-output.nix index 99203b518..aa46fff61 100644 --- a/tests/functional/dyn-drv/text-hashed-output.nix +++ b/tests/functional/dyn-drv/text-hashed-output.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/dyn-drv/config.nix"; # A simple content-addressed derivation. # The derivation can be arbitrarily modified by passing a different `seed`, diff --git a/tests/functional/export-graph.nix b/tests/functional/export-graph.nix index 64fe36bd1..97ffe73a9 100644 --- a/tests/functional/export-graph.nix +++ b/tests/functional/export-graph.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; rec { diff --git a/tests/functional/extra-sandbox-profile.nix b/tests/functional/extra-sandbox-profile.nix index aa680b918..5f0e4753f 100644 --- a/tests/functional/extra-sandbox-profile.nix +++ b/tests/functional/extra-sandbox-profile.nix @@ -1,6 +1,6 @@ { destFile, seed }: -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; mkDerivation { name = "simple"; diff --git a/tests/functional/failing.nix b/tests/functional/failing.nix index d25e2d6b6..8b7990679 100644 --- a/tests/functional/failing.nix +++ b/tests/functional/failing.nix @@ -1,5 +1,5 @@ { busybox }: -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; let mkDerivation = args: diff --git a/tests/functional/filter-source.nix b/tests/functional/filter-source.nix index 907163639..dcef9c4e2 100644 --- a/tests/functional/filter-source.nix +++ b/tests/functional/filter-source.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; mkDerivation { name = "filter"; diff --git a/tests/functional/fixed.nix b/tests/functional/fixed.nix index a920a2167..f70b89091 100644 --- a/tests/functional/fixed.nix +++ b/tests/functional/fixed.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; rec { diff --git a/tests/functional/flakes/bundle.sh b/tests/functional/flakes/bundle.sh index 2946aea35..61aa040e7 100755 --- a/tests/functional/flakes/bundle.sh +++ b/tests/functional/flakes/bundle.sh @@ -4,6 +4,9 @@ source common.sh cp ../simple.nix ../simple.builder.sh "${config_nix}" "$TEST_HOME" +# `config.nix` cannot be gotten via build dir / env var (runs afoul pure eval). Instead get from flake. +removeBuildDirRef "$TEST_HOME"/*.nix + cd "$TEST_HOME" cat < flake.nix diff --git a/tests/functional/flakes/common.sh b/tests/functional/flakes/common.sh index cc9b2e466..8af72f2ad 100644 --- a/tests/functional/flakes/common.sh +++ b/tests/functional/flakes/common.sh @@ -35,6 +35,9 @@ writeSimpleFlake() { EOF cp ../simple.nix ../shell.nix ../simple.builder.sh "${config_nix}" "$flakeDir/" + + # `config.nix` cannot be gotten via build dir / env var (runs afoul pure eval). Instead get from flake. + removeBuildDirRef "$flakeDir"/*.nix } createSimpleGitFlake() { diff --git a/tests/functional/flakes/config.sh b/tests/functional/flakes/config.sh index ab2d9f47c..48f1c7a85 100755 --- a/tests/functional/flakes/config.sh +++ b/tests/functional/flakes/config.sh @@ -3,6 +3,7 @@ source common.sh cp ../simple.nix ../simple.builder.sh "${config_nix}" $TEST_HOME +removeBuildDirRef "$TEST_HOME/simple.nix" cd $TEST_HOME diff --git a/tests/functional/flakes/develop.sh b/tests/functional/flakes/develop.sh index b3e438e99..2e75081d4 100755 --- a/tests/functional/flakes/develop.sh +++ b/tests/functional/flakes/develop.sh @@ -27,6 +27,9 @@ EOF mkdir -p "$TEST_HOME/nixpkgs" cp "${config_nix}" ../shell.nix "$TEST_HOME/nixpkgs" +# `config.nix` cannot be gotten via build dir / env var (runs afoul pure eval). Instead get from flake. +removeBuildDirRef "$TEST_HOME/nixpkgs"/*.nix + cat <"$TEST_HOME/nixpkgs/flake.nix" { outputs = {self}: { diff --git a/tests/functional/flakes/local.mk b/tests/functional/flakes/local.mk new file mode 100644 index 000000000..a37840240 --- /dev/null +++ b/tests/functional/flakes/local.mk @@ -0,0 +1,25 @@ +flake-tests := \ + $(d)/flakes.sh \ + $(d)/develop.sh \ + $(d)/edit.sh \ + $(d)/run.sh \ + $(d)/mercurial.sh \ + $(d)/circular.sh \ + $(d)/init.sh \ + $(d)/inputs.sh \ + $(d)/follow-paths.sh \ + $(d)/bundle.sh \ + $(d)/check.sh \ + $(d)/unlocked-override.sh \ + $(d)/absolute-paths.sh \ + $(d)/absolute-attr-paths.sh \ + $(d)/build-paths.sh \ + $(d)/flake-in-submodule.sh \ + $(d)/prefetch.sh \ + $(d)/eval-cache.sh \ + $(d)/search-root.sh \ + $(d)/config.sh \ + $(d)/show.sh \ + $(d)/dubious-query.sh + +install-tests-groups += flake diff --git a/tests/functional/flakes/run.sh b/tests/functional/flakes/run.sh index c92ddca2b..2077c965b 100755 --- a/tests/functional/flakes/run.sh +++ b/tests/functional/flakes/run.sh @@ -8,6 +8,8 @@ clearStore rm -rf $TEST_HOME/.cache $TEST_HOME/.config $TEST_HOME/.local cp ../shell-hello.nix "${config_nix}" $TEST_HOME +# `config.nix` cannot be gotten via build dir / env var (runs afoul pure eval). Instead get from flake. +removeBuildDirRef "$TEST_HOME"/*.nix cd $TEST_HOME cat < flake.nix diff --git a/tests/functional/fod-failing.nix b/tests/functional/fod-failing.nix index 37c04fe12..7881a3fbf 100644 --- a/tests/functional/fod-failing.nix +++ b/tests/functional/fod-failing.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; rec { x1 = mkDerivation { name = "x1"; diff --git a/tests/functional/gc-concurrent.nix b/tests/functional/gc-concurrent.nix index 0aba1f983..a5c3c97c3 100644 --- a/tests/functional/gc-concurrent.nix +++ b/tests/functional/gc-concurrent.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; { lockFifo ? null }: diff --git a/tests/functional/gc-runtime.nix b/tests/functional/gc-runtime.nix index ee5980bdf..2603fafdf 100644 --- a/tests/functional/gc-runtime.nix +++ b/tests/functional/gc-runtime.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; mkDerivation { name = "gc-runtime"; diff --git a/tests/functional/git-hashing/local.mk b/tests/functional/git-hashing/local.mk new file mode 100644 index 000000000..ebec01940 --- /dev/null +++ b/tests/functional/git-hashing/local.mk @@ -0,0 +1,7 @@ +git-hashing-tests := \ + $(d)/simple.sh + +install-tests-groups += git-hashing + +clean-files += \ + $(d)/config.nix diff --git a/tests/functional/hermetic.nix b/tests/functional/hermetic.nix index d1dccdff3..dafe8ad9f 100644 --- a/tests/functional/hermetic.nix +++ b/tests/functional/hermetic.nix @@ -5,7 +5,7 @@ , withFinalRefs ? false }: -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; let contentAddressedByDefault = builtins.getEnv "NIX_TESTS_CA_BY_DEFAULT" == "1"; diff --git a/tests/functional/ifd.nix b/tests/functional/ifd.nix index d0b9b54ad..c84ffbc66 100644 --- a/tests/functional/ifd.nix +++ b/tests/functional/ifd.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; import ( mkDerivation { name = "foo"; diff --git a/tests/functional/import-from-derivation.nix b/tests/functional/import-from-derivation.nix index cc53451cf..8864fb30a 100644 --- a/tests/functional/import-from-derivation.nix +++ b/tests/functional/import-from-derivation.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; rec { bar = mkDerivation { diff --git a/tests/functional/impure-derivations.nix b/tests/functional/impure-derivations.nix index 98547e6c1..04710323f 100644 --- a/tests/functional/impure-derivations.nix +++ b/tests/functional/impure-derivations.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; rec { diff --git a/tests/functional/impure-env.nix b/tests/functional/impure-env.nix index 2b0380ed7..6b9e5a825 100644 --- a/tests/functional/impure-env.nix +++ b/tests/functional/impure-env.nix @@ -1,6 +1,6 @@ { var, value }: -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; mkDerivation { name = "test"; diff --git a/tests/functional/linux-sandbox-cert-test.nix b/tests/functional/linux-sandbox-cert-test.nix index 2fc083ea9..e506b6a0f 100644 --- a/tests/functional/linux-sandbox-cert-test.nix +++ b/tests/functional/linux-sandbox-cert-test.nix @@ -1,6 +1,6 @@ { mode }: -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; mkDerivation ( { diff --git a/tests/functional/local-overlay-store/local.mk b/tests/functional/local-overlay-store/local.mk new file mode 100644 index 000000000..6348a4423 --- /dev/null +++ b/tests/functional/local-overlay-store/local.mk @@ -0,0 +1,14 @@ +local-overlay-store-tests := \ + $(d)/check-post-init.sh \ + $(d)/redundant-add.sh \ + $(d)/build.sh \ + $(d)/bad-uris.sh \ + $(d)/add-lower.sh \ + $(d)/delete-refs.sh \ + $(d)/delete-duplicate.sh \ + $(d)/gc.sh \ + $(d)/verify.sh \ + $(d)/optimise.sh \ + $(d)/stale-file-handle.sh + +install-tests-groups += local-overlay-store diff --git a/tests/functional/local.mk b/tests/functional/local.mk new file mode 100644 index 000000000..e50b5eaf1 --- /dev/null +++ b/tests/functional/local.mk @@ -0,0 +1,146 @@ +nix_tests = \ + test-infra.sh \ + gc.sh \ + nix-collect-garbage-d.sh \ + remote-store.sh \ + legacy-ssh-store.sh \ + lang.sh \ + lang-gc.sh \ + characterisation-test-infra.sh \ + experimental-features.sh \ + fetchMercurial.sh \ + gc-auto.sh \ + user-envs.sh \ + user-envs-migration.sh \ + binary-cache.sh \ + multiple-outputs.sh \ + nix-build.sh \ + gc-concurrent.sh \ + repair.sh \ + fixed.sh \ + export-graph.sh \ + timeout.sh \ + fetchGitRefs.sh \ + gc-runtime.sh \ + tarball.sh \ + fetchGit.sh \ + fetchurl.sh \ + fetchPath.sh \ + fetchTree-file.sh \ + simple.sh \ + referrers.sh \ + optimise-store.sh \ + substitute-with-invalid-ca.sh \ + signing.sh \ + hash-convert.sh \ + hash-path.sh \ + gc-non-blocking.sh \ + check.sh \ + nix-shell.sh \ + check-refs.sh \ + build-remote-input-addressed.sh \ + secure-drv-outputs.sh \ + restricted.sh \ + fetchGitSubmodules.sh \ + fetchGitVerification.sh \ + readfile-context.sh \ + nix-channel.sh \ + recursive.sh \ + dependencies.sh \ + check-reqs.sh \ + build-remote-content-addressed-fixed.sh \ + build-remote-content-addressed-floating.sh \ + build-remote-trustless-should-pass-0.sh \ + build-remote-trustless-should-pass-1.sh \ + build-remote-trustless-should-pass-2.sh \ + build-remote-trustless-should-pass-3.sh \ + build-remote-trustless-should-fail-0.sh \ + build-remote-with-mounted-ssh-ng.sh \ + nar-access.sh \ + impure-eval.sh \ + pure-eval.sh \ + eval.sh \ + repl.sh \ + binary-cache-build-remote.sh \ + search.sh \ + logging.sh \ + export.sh \ + config.sh \ + add.sh \ + chroot-store.sh \ + filter-source.sh \ + misc.sh \ + dump-db.sh \ + linux-sandbox.sh \ + supplementary-groups.sh \ + build-dry.sh \ + structured-attrs.sh \ + shell.sh \ + brotli.sh \ + zstd.sh \ + compression-levels.sh \ + nix-copy-ssh.sh \ + nix-copy-ssh-ng.sh \ + post-hook.sh \ + function-trace.sh \ + fmt.sh \ + eval-store.sh \ + why-depends.sh \ + derivation-json.sh \ + derivation-advanced-attributes.sh \ + import-from-derivation.sh \ + nix_path.sh \ + nars.sh \ + placeholders.sh \ + ssh-relay.sh \ + build.sh \ + build-delete.sh \ + output-normalization.sh \ + selfref-gc.sh \ + db-migration.sh \ + bash-profile.sh \ + pass-as-file.sh \ + nix-profile.sh \ + suggestions.sh \ + store-info.sh \ + fetchClosure.sh \ + completions.sh \ + impure-derivations.sh \ + path-from-hash-part.sh \ + path-info.sh \ + toString-path.sh \ + read-only-store.sh \ + nested-sandboxing.sh \ + impure-env.sh \ + debugger.sh \ + extra-sandbox-profile.sh \ + +ifeq ($(HAVE_LIBCPUID), 1) + nix_tests += compute-levels.sh +endif + +ifeq ($(ENABLE_BUILD), yes) + nix_tests += test-libstoreconsumer.sh + + ifeq ($(BUILD_SHARED_LIBS), 1) + nix_tests += plugins.sh + endif +endif + +ifeq ($(ENABLE_DOC_GEN), yes) + nix_tests += help.sh +endif + +$(d)/test-libstoreconsumer.sh.test $(d)/test-libstoreconsumer.sh.test-debug: \ + $(buildprefix)$(d)/test-libstoreconsumer/test-libstoreconsumer +$(d)/plugins.sh.test $(d)/plugins.sh.test-debug: \ + $(buildprefix)$(d)/plugins/libplugintest.$(SO_EXT) + +install-tests += $(foreach x, $(nix_tests), $(d)/$(x)) + +test-clean-files := \ + $(d)/common/subst-vars.sh \ + $(d)/config.nix + +clean-files += $(test-clean-files) +test-deps += $(test-clean-files) diff --git a/tests/functional/multiple-outputs.nix b/tests/functional/multiple-outputs.nix index 6ba7c523d..19ae2a45d 100644 --- a/tests/functional/multiple-outputs.nix +++ b/tests/functional/multiple-outputs.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; rec { diff --git a/tests/functional/nar-access.nix b/tests/functional/nar-access.nix index 9948abe59..78972bd36 100644 --- a/tests/functional/nar-access.nix +++ b/tests/functional/nar-access.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; rec { a = mkDerivation { diff --git a/tests/functional/nix-build-examples.nix b/tests/functional/nix-build-examples.nix index e54dbbf62..aaea8fc07 100644 --- a/tests/functional/nix-build-examples.nix +++ b/tests/functional/nix-build-examples.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; rec { diff --git a/tests/functional/parallel.nix b/tests/functional/parallel.nix index 23f142059..1f2411c92 100644 --- a/tests/functional/parallel.nix +++ b/tests/functional/parallel.nix @@ -1,6 +1,6 @@ {sleepTime ? 3}: -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; let diff --git a/tests/functional/path.nix b/tests/functional/path.nix index 883c3c41b..b23300f90 100644 --- a/tests/functional/path.nix +++ b/tests/functional/path.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; mkDerivation { name = "filter"; diff --git a/tests/functional/plugins/local.mk b/tests/functional/plugins/local.mk new file mode 100644 index 000000000..2314e1341 --- /dev/null +++ b/tests/functional/plugins/local.mk @@ -0,0 +1,11 @@ +libraries += libplugintest + +libplugintest_DIR := $(d) + +libplugintest_SOURCES := $(d)/plugintest.cc + +libplugintest_ALLOW_UNDEFINED := 1 + +libplugintest_EXCLUDE_FROM_LIBRARY_LIST := 1 + +libplugintest_CXXFLAGS := $(INCLUDE_libutil) $(INCLUDE_libstore) $(INCLUDE_libexpr) $(INCLUDE_libfetchers) diff --git a/tests/functional/readfile-context.nix b/tests/functional/readfile-context.nix index 54cd1afd9..b8f4a4c27 100644 --- a/tests/functional/readfile-context.nix +++ b/tests/functional/readfile-context.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; let diff --git a/tests/functional/restricted.sh b/tests/functional/restricted.sh index 00ee4ddc8..63bf56cd7 100755 --- a/tests/functional/restricted.sh +++ b/tests/functional/restricted.sh @@ -12,6 +12,10 @@ mkdir -p "$TEST_ROOT/nix" cp ./simple.nix "$TEST_ROOT/nix" cp ./simple.builder.sh "$TEST_ROOT/nix" cp "${config_nix}" "$TEST_ROOT/nix" +simple_nix="$TEST_ROOT/nix/simple.nix" +# N.B. redefine +config_nix="$TEST_ROOT/nix/config.nix" +removeBuildDirRef "${simple_nix}" cd "$TEST_ROOT/nix" nix-instantiate --restrict-eval ./simple.nix -I src=. diff --git a/tests/functional/search.nix b/tests/functional/search.nix index fea6e7a7a..3c3564bda 100644 --- a/tests/functional/search.nix +++ b/tests/functional/search.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; { hello = mkDerivation rec { diff --git a/tests/functional/secure-drv-outputs.nix b/tests/functional/secure-drv-outputs.nix index b4ac8ff53..cd111c315 100644 --- a/tests/functional/secure-drv-outputs.nix +++ b/tests/functional/secure-drv-outputs.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; { diff --git a/tests/functional/shell-hello.nix b/tests/functional/shell-hello.nix index c920d7cb4..fa02e2bb4 100644 --- a/tests/functional/shell-hello.nix +++ b/tests/functional/shell-hello.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; rec { hello = mkDerivation { diff --git a/tests/functional/shell.nix b/tests/functional/shell.nix index 9cae14b78..f6622a487 100644 --- a/tests/functional/shell.nix +++ b/tests/functional/shell.nix @@ -1,6 +1,6 @@ { inNixShell ? false, contentAddressed ? false, fooContents ? "foo" }: -let cfg = import ./config.nix; in +let cfg = import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; in with cfg; let diff --git a/tests/functional/simple-failing.nix b/tests/functional/simple-failing.nix index d176c9c51..228971734 100644 --- a/tests/functional/simple-failing.nix +++ b/tests/functional/simple-failing.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; mkDerivation { name = "simple-failing"; diff --git a/tests/functional/simple.nix b/tests/functional/simple.nix index 2035ca294..96237695c 100644 --- a/tests/functional/simple.nix +++ b/tests/functional/simple.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; mkDerivation { name = "simple"; diff --git a/tests/functional/structured-attrs-shell.nix b/tests/functional/structured-attrs-shell.nix index 57c1e6bd2..7ed28c03f 100644 --- a/tests/functional/structured-attrs-shell.nix +++ b/tests/functional/structured-attrs-shell.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; let dep = mkDerivation { name = "dep"; diff --git a/tests/functional/structured-attrs.nix b/tests/functional/structured-attrs.nix index e93139a44..ae461c21a 100644 --- a/tests/functional/structured-attrs.nix +++ b/tests/functional/structured-attrs.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; let diff --git a/tests/functional/symlink-derivation.nix b/tests/functional/symlink-derivation.nix index e9a74cdce..96765d355 100644 --- a/tests/functional/symlink-derivation.nix +++ b/tests/functional/symlink-derivation.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; let foo_in_store = builtins.toFile "foo" "foo"; diff --git a/tests/functional/test-libstoreconsumer/local.mk b/tests/functional/test-libstoreconsumer/local.mk new file mode 100644 index 000000000..3e8581c57 --- /dev/null +++ b/tests/functional/test-libstoreconsumer/local.mk @@ -0,0 +1,15 @@ +programs += test-libstoreconsumer + +test-libstoreconsumer_DIR := $(d) + +# do not install +test-libstoreconsumer_INSTALL_DIR := + +test-libstoreconsumer_SOURCES := \ + $(wildcard $(d)/*.cc) \ + +test-libstoreconsumer_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libstore) + +test-libstoreconsumer_LIBS = libstore libutil + +test-libstoreconsumer_LDFLAGS = $(THREAD_LDFLAGS) $(SODIUM_LIBS) $(EDITLINE_LIBS) $(BOOST_LDFLAGS) $(LOWDOWN_LIBS) diff --git a/tests/functional/timeout.nix b/tests/functional/timeout.nix index d0e949e31..ad71e61e2 100644 --- a/tests/functional/timeout.nix +++ b/tests/functional/timeout.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; { diff --git a/tests/functional/user-envs.nix b/tests/functional/user-envs.nix index 46f8b51dd..c8e846d4b 100644 --- a/tests/functional/user-envs.nix +++ b/tests/functional/user-envs.nix @@ -2,7 +2,7 @@ { foo ? "foo" }: -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; assert foo == "foo"; From cd42f7664e46c4a538ba6d4d3ba2eacebf0bd82a Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 7 Nov 2024 17:53:26 +0100 Subject: [PATCH 399/718] release notes: 2.25.0 --- doc/manual/rl-next/add-nix-state-home.md | 14 --- doc/manual/rl-next/ban-integer-overflow.md | 21 ---- doc/manual/rl-next/build-hook-default.md | 22 ---- doc/manual/rl-next/filesystem-errors.md | 14 --- doc/manual/rl-next/fsync-store-paths.md | 9 -- .../rl-next/nix-flake-show-description.md | 25 ---- .../rl-next/nix-fmt-default-argument.md | 17 --- doc/manual/rl-next/no-flake-substitution.md | 8 -- doc/manual/rl-next/verify-tls.md | 8 -- doc/manual/source/SUMMARY.md.in | 1 + doc/manual/source/release-notes/rl-2.25.md | 118 ++++++++++++++++++ 11 files changed, 119 insertions(+), 138 deletions(-) delete mode 100644 doc/manual/rl-next/add-nix-state-home.md delete mode 100644 doc/manual/rl-next/ban-integer-overflow.md delete mode 100644 doc/manual/rl-next/build-hook-default.md delete mode 100644 doc/manual/rl-next/filesystem-errors.md delete mode 100644 doc/manual/rl-next/fsync-store-paths.md delete mode 100644 doc/manual/rl-next/nix-flake-show-description.md delete mode 100644 doc/manual/rl-next/nix-fmt-default-argument.md delete mode 100644 doc/manual/rl-next/no-flake-substitution.md delete mode 100644 doc/manual/rl-next/verify-tls.md create mode 100644 doc/manual/source/release-notes/rl-2.25.md diff --git a/doc/manual/rl-next/add-nix-state-home.md b/doc/manual/rl-next/add-nix-state-home.md deleted file mode 100644 index bbfdd5d38..000000000 --- a/doc/manual/rl-next/add-nix-state-home.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -synopsis: Use envvars NIX_CACHE_HOME, NIX_CONFIG_HOME, NIX_DATA_HOME, NIX_STATE_HOME if defined -prs: [11351] ---- - -Added new environment variables: - -- `NIX_CACHE_HOME` -- `NIX_CONFIG_HOME` -- `NIX_DATA_HOME` -- `NIX_STATE_HOME` - -Each, if defined, takes precedence over the corresponding [XDG environment variable](@docroot@/command-ref/env-common.md#xdg-base-directories). -This provides more fine-grained control over where Nix looks for files, and allows to have a stand-alone Nix environment, which only uses files in a specific directory, and doesn't interfere with the user environment. diff --git a/doc/manual/rl-next/ban-integer-overflow.md b/doc/manual/rl-next/ban-integer-overflow.md deleted file mode 100644 index 0e553af76..000000000 --- a/doc/manual/rl-next/ban-integer-overflow.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -synopsis: Define integer overflow in the Nix language as an error -issues: [10968] -prs: [11188] ---- - -Previously, integer overflow in the Nix language invoked C++ level signed overflow, which was undefined behaviour, but *usually* manifested as wrapping around on overflow. - -Since prior to the public release of Lix, Lix had C++ signed overflow defined to crash the process and nobody noticed this having accidentally removed overflow from the Nix language for three months until it was caught by fiddling around. -Given the significant body of actual Nix code that has been evaluated by Lix in that time, it does not appear that nixpkgs or much of importance depends on integer overflow, so it appears safe to turn into an error. - -Some other overflows were fixed: -- `builtins.fromJSON` of values greater than the maximum representable value in a signed 64-bit integer will generate an error. -- `nixConfig` in flakes will no longer accept negative values for configuration options. - -Integer overflow now looks like the following: - -``` -$ nix eval --expr '9223372036854775807 + 1' -error: integer overflow in adding 9223372036854775807 + 1 -``` diff --git a/doc/manual/rl-next/build-hook-default.md b/doc/manual/rl-next/build-hook-default.md deleted file mode 100644 index f13537983..000000000 --- a/doc/manual/rl-next/build-hook-default.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -synopsis: |- - The `build-hook` setting's default is less useful when using `libnixstore` as a library -prs: -- 11178 ---- - -*This is an obscure issue that only affects usage of the `libnixstore` library outside of the Nix executable.* - -As part the ongoing [rewrite of the build system](https://github.com/NixOS/nix/issues/2503) to use [Meson](https://mesonbuild.com/), we are also switching to packaging individual Nix components separately (and building them in separate derivations). -This means that when building `libnixstore` we do not know where the Nix binaries will be installed --- `libnixstore` doesn't know about downstream consumers like the Nix binaries at all. - -*This is also unrelated to the _`post`_-`build-hook`*, which is often used for pushing to a cache.* - -This has a small adverse affect on remote building --- the `build-remote` executable that is specified from the [`build-hook`](@docroot@/command-ref/conf-file.md#conf-build-hook) setting will not be gotten from the (presumed) installation location, but instead looked up on the `PATH`. -This means that other applications linking `libnixstore` that wish to use remote building must arrange for the `nix` command to be on the PATH (or manually overriding `build-hook`) in order for that to work. - -Long term we don't envision this being a downside, because we plan to [get rid of `build-remote` and the build hook setting entirely](https://github.com/NixOS/nix/issues/1221). -There should simply be no need to have an extra, intermediate layer of remote-procedure-calling when we want to connect to a remote builder. -The build hook protocol did in principle support custom ways of remote building, but that can also be accomplished with a custom service for the ssh or daemon/ssh-ng protocols, or with a custom [store type](@docroot@/store/types/index.md) i.e. `Store` subclass. - -The Perl bindings no longer expose `getBinDir` either, since the underlying C++ libraries those bindings wrap no longer know the location of installed binaries as described above. diff --git a/doc/manual/rl-next/filesystem-errors.md b/doc/manual/rl-next/filesystem-errors.md deleted file mode 100644 index 2d5b26228..000000000 --- a/doc/manual/rl-next/filesystem-errors.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -synopsis: wrap filesystem exceptions more correctly -issues: [] -prs: [11378] ---- - - -With the switch to `std::filesystem` in different places, Nix started to throw `std::filesystem::filesystem_error` in many places instead of its own exceptions. - -This lead to no longer generating error traces, for example when listing a non-existing directory, and can also lead to crashes inside the Nix REPL. - -This version catches these types of exception correctly and wrap them into Nix's own exeception type. - -Author: [**@Mic92**](https://github.com/Mic92) diff --git a/doc/manual/rl-next/fsync-store-paths.md b/doc/manual/rl-next/fsync-store-paths.md deleted file mode 100644 index 0e9e7f7f2..000000000 --- a/doc/manual/rl-next/fsync-store-paths.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -synopsis: Add setting `fsync-store-paths` -issues: [1218] -prs: [7126] ---- - -Nix now has a setting `fsync-store-paths` that ensures that new store paths are durably written to disk before they are registered as "valid" in Nix's database. This can prevent Nix store corruption if the system crashes or there is a power loss. This setting defaults to `false`. - -Author: [**@squalus**](https://github.com/squalus) diff --git a/doc/manual/rl-next/nix-flake-show-description.md b/doc/manual/rl-next/nix-flake-show-description.md deleted file mode 100644 index 7feb08483..000000000 --- a/doc/manual/rl-next/nix-flake-show-description.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -synopsis: Show package descriptions with `nix flake show` -issues: [10977] -prs: [10980] ---- - -`nix flake show` will now display a package's `meta.description` if it exists. If the description does not fit in the terminal it will be truncated to fit the terminal width. If the size of the terminal width is unknown the description will be capped at 80 characters. - -``` -$ nix flake show -└───packages - └───x86_64-linux - ├───builderImage: package 'docker-image-ara-builder-image.tar.gz' - 'Docker image hosting the nix build environment' - └───runnerImage: package 'docker-image-gitlab-runner.tar.gz' - 'Docker image hosting the gitlab-runner executable' -``` - -In a narrower terminal: - -``` -$ nix flake show -└───packages - └───x86_64-linux - ├───builderImage: package 'docker-image-ara-builder-image.tar.gz' - 'Docker image hosting the nix b... - └───runnerImage: package 'docker-image-gitlab-runner.tar.gz' - 'Docker image hosting the gitlab-run... -``` diff --git a/doc/manual/rl-next/nix-fmt-default-argument.md b/doc/manual/rl-next/nix-fmt-default-argument.md deleted file mode 100644 index 54161ab30..000000000 --- a/doc/manual/rl-next/nix-fmt-default-argument.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -synopsis: Removing the default argument passed to the `nix fmt` formatter -issues: [] -prs: [11438] ---- - -The underlying formatter no longer receives the ". " default argument when `nix fmt` is called with no arguments. - -This change was necessary as the formatter wasn't able to distinguish between -a user wanting to format the current folder with `nix fmt .` or the generic -`nix fmt`. - -The default behaviour is now the responsibility of the formatter itself, and -allows tools such as treefmt to format the whole tree instead of only the -current directory and below. - -Author: [**@zimbatm**](https://github.com/zimbatm) diff --git a/doc/manual/rl-next/no-flake-substitution.md b/doc/manual/rl-next/no-flake-substitution.md deleted file mode 100644 index 67ec58750..000000000 --- a/doc/manual/rl-next/no-flake-substitution.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -synopsis: Flakes are no longer substituted -prs: [10612] ---- - -Nix will no longer attempt to substitute the source code of flakes from a binary cache. This functionality was broken because it could lead to different evaluation results depending on whether the flake was available in the binary cache, or even depending on whether the flake was already in the local store. - -Author: [**@edolstra**](https://github.com/edolstra) diff --git a/doc/manual/rl-next/verify-tls.md b/doc/manual/rl-next/verify-tls.md deleted file mode 100644 index afc689f46..000000000 --- a/doc/manual/rl-next/verify-tls.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -synopsis: "`` uses TLS verification" -prs: [11585] ---- - -Previously `` did not do TLS verification. This was because the Nix sandbox in the past did not have access to TLS certificates, and Nix checks the hash of the fetched file anyway. However, this can expose authentication data from `netrc` and URLs to man-in-the-middle attackers. In addition, Nix now in some cases (such as when using impure derivations) does *not* check the hash. Therefore we have now enabled TLS verification. This means that downloads by `` will now fail if you're fetching from a HTTPS server that does not have a valid certificate. - -`` is also known as the builtin derivation builder `builtin:fetchurl`. It's not to be confused with the evaluation-time function `builtins.fetchurl`, which was not affected by this issue. diff --git a/doc/manual/source/SUMMARY.md.in b/doc/manual/source/SUMMARY.md.in index d7c312ae7..244bf582d 100644 --- a/doc/manual/source/SUMMARY.md.in +++ b/doc/manual/source/SUMMARY.md.in @@ -130,6 +130,7 @@ - [Contributing](development/contributing.md) - [Releases](release-notes/index.md) {{#include ./SUMMARY-rl-next.md}} + - [Release 2.25 (2024-11-07)](release-notes/rl-2.25.md) - [Release 2.24 (2024-07-31)](release-notes/rl-2.24.md) - [Release 2.23 (2024-06-03)](release-notes/rl-2.23.md) - [Release 2.22 (2024-04-23)](release-notes/rl-2.22.md) diff --git a/doc/manual/source/release-notes/rl-2.25.md b/doc/manual/source/release-notes/rl-2.25.md new file mode 100644 index 000000000..7364db980 --- /dev/null +++ b/doc/manual/source/release-notes/rl-2.25.md @@ -0,0 +1,118 @@ +# Release 2.25.0 (2024-11-07) + +- Use envvars NIX_CACHE_HOME, NIX_CONFIG_HOME, NIX_DATA_HOME, NIX_STATE_HOME if defined [#11351](https://github.com/NixOS/nix/pull/11351) + + Added new environment variables: + + - `NIX_CACHE_HOME` + - `NIX_CONFIG_HOME` + - `NIX_DATA_HOME` + - `NIX_STATE_HOME` + + Each, if defined, takes precedence over the corresponding [XDG environment variable](@docroot@/command-ref/env-common.md#xdg-base-directories). + This provides more fine-grained control over where Nix looks for files, and allows to have a stand-alone Nix environment, which only uses files in a specific directory, and doesn't interfere with the user environment. + +- Define integer overflow in the Nix language as an error [#10968](https://github.com/NixOS/nix/issues/10968) [#11188](https://github.com/NixOS/nix/pull/11188) + + Previously, integer overflow in the Nix language invoked C++ level signed overflow, which was undefined behaviour, but *usually* manifested as wrapping around on overflow. + + Since prior to the public release of Lix, Lix had C++ signed overflow defined to crash the process and nobody noticed this having accidentally removed overflow from the Nix language for three months until it was caught by fiddling around. + Given the significant body of actual Nix code that has been evaluated by Lix in that time, it does not appear that nixpkgs or much of importance depends on integer overflow, so it appears safe to turn into an error. + + Some other overflows were fixed: + - `builtins.fromJSON` of values greater than the maximum representable value in a signed 64-bit integer will generate an error. + - `nixConfig` in flakes will no longer accept negative values for configuration options. + + Integer overflow now looks like the following: + + ``` + $ nix eval --expr '9223372036854775807 + 1' + error: integer overflow in adding 9223372036854775807 + 1 + ``` + +- The `build-hook` setting's default is less useful when using `libnixstore` as a library [#11178](https://github.com/NixOS/nix/pull/11178) + + *This is an obscure issue that only affects usage of the `libnixstore` library outside of the Nix executable.* + + As part the ongoing [rewrite of the build system](https://github.com/NixOS/nix/issues/2503) to use [Meson](https://mesonbuild.com/), we are also switching to packaging individual Nix components separately (and building them in separate derivations). + This means that when building `libnixstore` we do not know where the Nix binaries will be installed --- `libnixstore` doesn't know about downstream consumers like the Nix binaries at all. + + *This is also unrelated to the _`post`_-`build-hook`*, which is often used for pushing to a cache.* + + This has a small adverse affect on remote building --- the `build-remote` executable that is specified from the [`build-hook`](@docroot@/command-ref/conf-file.md#conf-build-hook) setting will not be gotten from the (presumed) installation location, but instead looked up on the `PATH`. + This means that other applications linking `libnixstore` that wish to use remote building must arrange for the `nix` command to be on the PATH (or manually overriding `build-hook`) in order for that to work. + + Long term we don't envision this being a downside, because we plan to [get rid of `build-remote` and the build hook setting entirely](https://github.com/NixOS/nix/issues/1221). + There should simply be no need to have an extra, intermediate layer of remote-procedure-calling when we want to connect to a remote builder. + The build hook protocol did in principle support custom ways of remote building, but that can also be accomplished with a custom service for the ssh or daemon/ssh-ng protocols, or with a custom [store type](@docroot@/store/types/index.md) i.e. `Store` subclass. + + The Perl bindings no longer expose `getBinDir` either, since the underlying C++ libraries those bindings wrap no longer know the location of installed binaries as described above. + +- wrap filesystem exceptions more correctly [#11378](https://github.com/NixOS/nix/pull/11378) + + With the switch to `std::filesystem` in different places, Nix started to throw `std::filesystem::filesystem_error` in many places instead of its own exceptions. + + This lead to no longer generating error traces, for example when listing a non-existing directory, and can also lead to crashes inside the Nix REPL. + + This version catches these types of exception correctly and wrap them into Nix's own exeception type. + + Author: [**@Mic92**](https://github.com/Mic92) + +- Add setting `fsync-store-paths` [#1218](https://github.com/NixOS/nix/issues/1218) [#7126](https://github.com/NixOS/nix/pull/7126) + + Nix now has a setting `fsync-store-paths` that ensures that new store paths are durably written to disk before they are registered as "valid" in Nix's database. This can prevent Nix store corruption if the system crashes or there is a power loss. This setting defaults to `false`. + + Author: [**@squalus**](https://github.com/squalus) + +- Show package descriptions with `nix flake show` [#10977](https://github.com/NixOS/nix/issues/10977) [#10980](https://github.com/NixOS/nix/pull/10980) + + `nix flake show` will now display a package's `meta.description` if it exists. If the description does not fit in the terminal it will be truncated to fit the terminal width. If the size of the terminal width is unknown the description will be capped at 80 characters. + + ``` + $ nix flake show + └───packages + └───x86_64-linux + ├───builderImage: package 'docker-image-ara-builder-image.tar.gz' - 'Docker image hosting the nix build environment' + └───runnerImage: package 'docker-image-gitlab-runner.tar.gz' - 'Docker image hosting the gitlab-runner executable' + ``` + + In a narrower terminal: + + ``` + $ nix flake show + └───packages + └───x86_64-linux + ├───builderImage: package 'docker-image-ara-builder-image.tar.gz' - 'Docker image hosting the nix b... + └───runnerImage: package 'docker-image-gitlab-runner.tar.gz' - 'Docker image hosting the gitlab-run... + ``` + +- Removing the default argument passed to the `nix fmt` formatter [#11438](https://github.com/NixOS/nix/pull/11438) + + The underlying formatter no longer receives the ". " default argument when `nix fmt` is called with no arguments. + + This change was necessary as the formatter wasn't able to distinguish between + a user wanting to format the current folder with `nix fmt .` or the generic + `nix fmt`. + + The default behaviour is now the responsibility of the formatter itself, and + allows tools such as treefmt to format the whole tree instead of only the + current directory and below. + + Author: [**@zimbatm**](https://github.com/zimbatm) + +- Flakes are no longer substituted [#10612](https://github.com/NixOS/nix/pull/10612) + + Nix will no longer attempt to substitute the source code of flakes from a binary cache. This functionality was broken because it could lead to different evaluation results depending on whether the flake was available in the binary cache, or even depending on whether the flake was already in the local store. + + Author: [**@edolstra**](https://github.com/edolstra) + +- `` uses TLS verification [#11585](https://github.com/NixOS/nix/pull/11585) + + Previously `` did not do TLS verification. This was because the Nix sandbox in the past did not have access to TLS certificates, and Nix checks the hash of the fetched file anyway. However, this can expose authentication data from `netrc` and URLs to man-in-the-middle attackers. In addition, Nix now in some cases (such as when using impure derivations) does *not* check the hash. Therefore we have now enabled TLS verification. This means that downloads by `` will now fail if you're fetching from a HTTPS server that does not have a valid certificate. + + `` is also known as the builtin derivation builder `builtin:fetchurl`. It's not to be confused with the evaluation-time function `builtins.fetchurl`, which was not affected by this issue. + + +# Contributors + +Querying GitHub API for 2e7466a4e0bce4dde9922fa3445d1947d6098fad, to get handle for 145775305+xokdvium@users.noreply.github.com From 47bffe20e4704495e74747d18273934ead395d5c Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 7 Nov 2024 18:07:48 +0100 Subject: [PATCH 400/718] Revert "Merge pull request #10980 from kjeremy/flake-show-description" This reverts commit 1c5ad159d6ff412cb57f13bf9d2aacbacd258a90, reversing changes made to 67de1932774b834377f704d9d358ef3d4951d0ef. This reverts commit ce4e4a158eb3efdadd0114d19fc06c0fcae8bef4, reversing changes made to 43e82c944671ad7ce5da1b75991a4c1f48b545c4. --- .../rl-next/nix-flake-show-description.md | 25 ----- src/nix/flake.cc | 91 ++----------------- tests/functional/flakes/show.sh | 25 ----- 3 files changed, 9 insertions(+), 132 deletions(-) delete mode 100644 doc/manual/rl-next/nix-flake-show-description.md diff --git a/doc/manual/rl-next/nix-flake-show-description.md b/doc/manual/rl-next/nix-flake-show-description.md deleted file mode 100644 index 7feb08483..000000000 --- a/doc/manual/rl-next/nix-flake-show-description.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -synopsis: Show package descriptions with `nix flake show` -issues: [10977] -prs: [10980] ---- - -`nix flake show` will now display a package's `meta.description` if it exists. If the description does not fit in the terminal it will be truncated to fit the terminal width. If the size of the terminal width is unknown the description will be capped at 80 characters. - -``` -$ nix flake show -└───packages - └───x86_64-linux - ├───builderImage: package 'docker-image-ara-builder-image.tar.gz' - 'Docker image hosting the nix build environment' - └───runnerImage: package 'docker-image-gitlab-runner.tar.gz' - 'Docker image hosting the gitlab-runner executable' -``` - -In a narrower terminal: - -``` -$ nix flake show -└───packages - └───x86_64-linux - ├───builderImage: package 'docker-image-ara-builder-image.tar.gz' - 'Docker image hosting the nix b... - └───runnerImage: package 'docker-image-gitlab-runner.tar.gz' - 'Docker image hosting the gitlab-run... -``` diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 640a80aed..3a54763a1 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -17,7 +17,6 @@ #include "eval-cache.hh" #include "markdown.hh" #include "users.hh" -#include "terminal.hh" #include #include @@ -1275,97 +1274,25 @@ struct CmdFlakeShow : FlakeCommand, MixJSON auto showDerivation = [&]() { auto name = visitor.getAttr(state->sName)->getString(); - std::optional description; - if (auto aMeta = visitor.maybeGetAttr(state->sMeta)) { - if (auto aDescription = aMeta->maybeGetAttr(state->sDescription)) - description = aDescription->getString(); - } if (json) { + std::optional description; + if (auto aMeta = visitor.maybeGetAttr(state->sMeta)) { + if (auto aDescription = aMeta->maybeGetAttr(state->sDescription)) + description = aDescription->getString(); + } j.emplace("type", "derivation"); j.emplace("name", name); j.emplace("description", description ? *description : ""); } else { - auto type = + logger->cout("%s: %s '%s'", + headerPrefix, attrPath.size() == 2 && attrPathS[0] == "devShell" ? "development environment" : attrPath.size() >= 2 && attrPathS[0] == "devShells" ? "development environment" : attrPath.size() == 3 && attrPathS[0] == "checks" ? "derivation" : attrPath.size() >= 1 && attrPathS[0] == "hydraJobs" ? "derivation" : - "package"; - if (description && !description->empty()) { - - // Takes a string and returns the # of characters displayed - auto columnLengthOfString = [](std::string_view s) -> unsigned int { - unsigned int columnCount = 0; - for (auto i = s.begin(); i < s.end();) { - // Test first character to determine if it is one of - // treeConn, treeLast, treeLine - if (*i == -30) { - i += 3; - ++columnCount; - } - // Escape sequences - // https://en.wikipedia.org/wiki/ANSI_escape_code - else if (*i == '\e') { - // Eat '[' - if (*(++i) == '[') { - ++i; - // Eat parameter bytes - while(*i >= 0x30 && *i <= 0x3f) ++i; - - // Eat intermediate bytes - while(*i >= 0x20 && *i <= 0x2f) ++i; - - // Eat final byte - if(*i >= 0x40 && *i <= 0x73) ++i; - } - else { - // Eat Fe Escape sequence - if (*i >= 0x40 && *i <= 0x5f) ++i; - } - } - else { - ++i; - ++columnCount; - } - } - - return columnCount; - }; - - // Maximum length to print - size_t maxLength = getWindowSize().second > 0 ? getWindowSize().second : 80; - - // Trim the description and only use the first line - auto trimmed = trim(*description); - auto newLinePos = trimmed.find('\n'); - auto length = newLinePos != std::string::npos ? newLinePos : trimmed.length(); - - auto beginningOfLine = fmt("%s: %s '%s'", headerPrefix, type, name); - auto line = fmt("%s: %s '%s' - '%s'", headerPrefix, type, name, trimmed.substr(0, length)); - - // If we are already over the maximum length then do not trim - // and don't print the description (preserves existing behavior) - if (columnLengthOfString(beginningOfLine) >= maxLength) { - logger->cout("%s", beginningOfLine); - } - // If the entire line fits then print that - else if (columnLengthOfString(line) < maxLength) { - logger->cout("%s", line); - } - // Otherwise we need to truncate - else { - auto lineLength = columnLengthOfString(line); - auto chopOff = lineLength - maxLength; - line.resize(line.length() - chopOff); - line = line.replace(line.length() - 3, 3, "..."); - - logger->cout("%s", line); - } - } - else { - logger->cout("%s: %s '%s'", headerPrefix, type, name); - } + "package", + name); } }; diff --git a/tests/functional/flakes/show.sh b/tests/functional/flakes/show.sh index 0edc450c3..22e1f4193 100755 --- a/tests/functional/flakes/show.sh +++ b/tests/functional/flakes/show.sh @@ -87,28 +87,3 @@ assert show_output.legacyPackages.${builtins.currentSystem}.AAAAAASomeThingsFail assert show_output.legacyPackages.${builtins.currentSystem}.simple.name == "simple"; true ' - -cat >flake.nix< ./show-output.txt -test "$(awk -F '[:] ' '/aNoDescription/{print $NF}' ./show-output.txt)" = "package 'simple'" -test "$(awk -F '[:] ' '/bOneLineDescription/{print $NF}' ./show-output.txt)" = "package 'simple' - 'one line'" -test "$(awk -F '[:] ' '/cMultiLineDescription/{print $NF}' ./show-output.txt)" = "package 'simple' - 'line one'" -test "$(awk -F '[:] ' '/dLongDescription/{print $NF}' ./show-output.txt)" = "package 'simple' - '012345678901234567890123456..." -test "$(awk -F '[:] ' '/eEmptyDescription/{print $NF}' ./show-output.txt)" = "package 'simple'" \ No newline at end of file From ea6dc8ebf1414305d552d312185f6d4f43c62599 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 7 Nov 2024 20:10:17 +0100 Subject: [PATCH 401/718] Fix 'nix copy' VM test This was broken because the root password wasn't getting set correctly. https://hydra.nixos.org/build/277366631 --- tests/nixos/nix-copy.nix | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/nixos/nix-copy.nix b/tests/nixos/nix-copy.nix index 7db5197aa..8691d0138 100644 --- a/tests/nixos/nix-copy.nix +++ b/tests/nixos/nix-copy.nix @@ -37,7 +37,8 @@ in { { config, pkgs, ... }: { services.openssh.enable = true; services.openssh.settings.PermitRootLogin = "yes"; - users.users.root.password = "foobar"; + users.users.root.hashedPasswordFile = null; + users.users.root.password = "foobar"; virtualisation.writableStore = true; virtualisation.additionalPaths = [ pkgB pkgC ]; }; @@ -64,7 +65,7 @@ in { # Copy the closure of package A from the client to the server using password authentication, # and check that all prompts are visible server.fail("nix-store --check-validity ${pkgA}") - client.send_chars("nix copy --to ssh://server ${pkgA} >&2; echo done\n") + client.send_chars("nix copy --to ssh://server ${pkgA} >&2; echo -n do; echo ne\n") client.wait_for_text("continue connecting") client.send_chars("yes\n") client.wait_for_text("Password:") From 5471d2a454038aabf67d9d21d48cc63a9717f20c Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 7 Nov 2024 20:43:17 +0100 Subject: [PATCH 402/718] Fix tests.remoteBuilds_local_nix_2_18 This was broken since a03bb4455cee010bbfcf7e322b10ec7e35123032 because Nix 2.18 does not support broken $SHELL settings. So don't try a broken $SHELL on old Nix versions. (It's a mystery though why tests.remoteBuilds_local_nix_2_13 and tests.remoteBuilds_local_nix_2_3 didn't fail...) https://hydra.nixos.org/build/277366807 --- tests/nixos/remote-builds.nix | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/nixos/remote-builds.nix b/tests/nixos/remote-builds.nix index ab159eaad..84e5176b7 100644 --- a/tests/nixos/remote-builds.nix +++ b/tests/nixos/remote-builds.nix @@ -34,6 +34,8 @@ let } ''; + supportsBadShell = lib.versionAtLeast config.nodes.client.nix.package.version "2.25pre"; + in { @@ -82,7 +84,7 @@ in nix.settings.substituters = lib.mkForce [ ]; programs.ssh.extraConfig = "ConnectTimeout 30"; environment.systemPackages = [ - # `bad-shell` is used to make sure Nix works an environment with a misbehaving shell. + # `bad-shell` is used to make sure Nix works in an environment with a misbehaving shell. # # More realistically, a bad shell would still run the command ("echo started") # but considering that our solution is to avoid this shell (set via $SHELL), we @@ -125,13 +127,15 @@ in 'echo hello world on $(hostname)' >&2 """) + ${lib.optionalString supportsBadShell '' # Check that SSH uses SHELL for LocalCommand, as expected, and check that # our test setup here is working. The next test will use this bad SHELL. client.succeed(f"SHELL=$(which bad-shell) ssh -oLocalCommand='true' -oPermitLocalCommand=yes {builder1.name} 'echo hello world' | grep -F 'Hello, I am a broken shell'") + ''} # Perform a build and check that it was performed on the builder. out = client.succeed( - "SHELL=$(which bad-shell) nix-build ${expr nodes.client 1} 2> build-output", + "${lib.optionalString supportsBadShell "SHELL=$(which bad-shell)"} nix-build ${expr nodes.client 1} 2> build-output", "grep -q Hello build-output" ) builder1.succeed(f"test -e {out}") From 372353722e379fa6bc1a1478713ec9b79f77f24c Mon Sep 17 00:00:00 2001 From: John Ericson Date: Thu, 7 Nov 2024 13:15:03 -0500 Subject: [PATCH 403/718] Clean up standard stream logic Now we have enough portability stuff --- src/libmain/progress-bar.cc | 2 +- src/libutil/file-descriptor.hh | 32 +++++++++++++++++++++++++++++++- src/libutil/logging.cc | 8 ++------ src/nix-store/nix-store.cc | 6 +++--- src/nix/cat.cc | 2 +- src/nix/dump-path.cc | 4 ++-- src/nix/eval.cc | 2 +- src/nix/log.cc | 2 +- src/nix/sigs.cc | 4 ++-- 9 files changed, 44 insertions(+), 18 deletions(-) diff --git a/src/libmain/progress-bar.cc b/src/libmain/progress-bar.cc index a3b86790b..fa0b73ebe 100644 --- a/src/libmain/progress-bar.cc +++ b/src/libmain/progress-bar.cc @@ -543,7 +543,7 @@ public: auto state(state_.lock()); if (!state->active) return {}; std::cerr << fmt("\r\e[K%s ", msg); - auto s = trim(readLine(STDIN_FILENO, true)); + auto s = trim(readLine(getStandardInput(), true)); if (s.size() != 1) return {}; draw(*state); return s[0]; diff --git a/src/libutil/file-descriptor.hh b/src/libutil/file-descriptor.hh index 710efaf1d..bc8602e5c 100644 --- a/src/libutil/file-descriptor.hh +++ b/src/libutil/file-descriptor.hh @@ -106,8 +106,25 @@ void drainFD( #endif ); +/** + * Get [Standard Input](https://en.wikipedia.org/wiki/Standard_streams#Standard_input_(stdin)) + */ [[gnu::always_inline]] -inline Descriptor getStandardOut() { +inline Descriptor getStandardInput() +{ +#ifndef _WIN32 + return STDIN_FILENO; +#else + return GetStdHandle(STD_INPUT_HANDLE); +#endif +} + +/** + * Get [Standard Output](https://en.wikipedia.org/wiki/Standard_streams#Standard_output_(stdout)) + */ +[[gnu::always_inline]] +inline Descriptor getStandardOutput() +{ #ifndef _WIN32 return STDOUT_FILENO; #else @@ -115,6 +132,19 @@ inline Descriptor getStandardOut() { #endif } +/** + * Get [Standard Error](https://en.wikipedia.org/wiki/Standard_streams#Standard_error_(stderr)) + */ +[[gnu::always_inline]] +inline Descriptor getStandardError() +{ +#ifndef _WIN32 + return STDERR_FILENO; +#else + return GetStdHandle(STD_ERROR_HANDLE); +#endif +} + /** * Automatic cleanup of resources. */ diff --git a/src/libutil/logging.cc b/src/libutil/logging.cc index 3d7371457..80c107ef5 100644 --- a/src/libutil/logging.cc +++ b/src/libutil/logging.cc @@ -38,7 +38,7 @@ void Logger::warn(const std::string & msg) void Logger::writeToStdout(std::string_view s) { - Descriptor standard_out = getStandardOut(); + Descriptor standard_out = getStandardOutput(); writeFull(standard_out, s); writeFull(standard_out, "\n"); } @@ -118,11 +118,7 @@ void writeToStderr(std::string_view s) { try { writeFull( -#ifdef _WIN32 - GetStdHandle(STD_ERROR_HANDLE), -#else - STDERR_FILENO, -#endif + getStandardError(), s, false); } catch (SystemError & e) { /* Ignore failing writes to stderr. We need to ignore write diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc index b4de42ba1..c823c930e 100644 --- a/src/nix-store/nix-store.cc +++ b/src/nix-store/nix-store.cc @@ -694,7 +694,7 @@ static void opDump(Strings opFlags, Strings opArgs) if (!opFlags.empty()) throw UsageError("unknown flag"); if (opArgs.size() != 1) throw UsageError("only one argument allowed"); - FdSink sink(getStandardOut()); + FdSink sink(getStandardOutput()); std::string path = *opArgs.begin(); dumpPath(path, sink); sink.flush(); @@ -722,7 +722,7 @@ static void opExport(Strings opFlags, Strings opArgs) for (auto & i : opArgs) paths.insert(store->followLinksToStorePath(i)); - FdSink sink(getStandardOut()); + FdSink sink(getStandardOutput()); store->exportPaths(paths, sink); sink.flush(); } @@ -835,7 +835,7 @@ static void opServe(Strings opFlags, Strings opArgs) if (!opArgs.empty()) throw UsageError("no arguments expected"); FdSource in(STDIN_FILENO); - FdSink out(getStandardOut()); + FdSink out(getStandardOutput()); /* Exchange the greeting. */ ServeProto::Version clientVersion = diff --git a/src/nix/cat.cc b/src/nix/cat.cc index ee904b0c5..e0179c348 100644 --- a/src/nix/cat.cc +++ b/src/nix/cat.cc @@ -16,7 +16,7 @@ struct MixCat : virtual Args throw Error("path '%1%' is not a regular file", path); stopProgressBar(); - writeFull(getStandardOut(), accessor->readFile(CanonPath(path))); + writeFull(getStandardOutput(), accessor->readFile(CanonPath(path))); } }; diff --git a/src/nix/dump-path.cc b/src/nix/dump-path.cc index 953d77d31..98a059fa1 100644 --- a/src/nix/dump-path.cc +++ b/src/nix/dump-path.cc @@ -20,7 +20,7 @@ struct CmdDumpPath : StorePathCommand void run(ref store, const StorePath & storePath) override { - FdSink sink(getStandardOut()); + FdSink sink(getStandardOutput()); store->narFromPath(storePath, sink); sink.flush(); } @@ -55,7 +55,7 @@ struct CmdDumpPath2 : Command void run() override { - FdSink sink(getStandardOut()); + FdSink sink(getStandardOutput()); dumpPath(path, sink); sink.flush(); } diff --git a/src/nix/eval.cc b/src/nix/eval.cc index babf2ca32..7811b77ed 100644 --- a/src/nix/eval.cc +++ b/src/nix/eval.cc @@ -115,7 +115,7 @@ struct CmdEval : MixJSON, InstallableValueCommand, MixReadOnlyOption else if (raw) { stopProgressBar(); - writeFull(getStandardOut(), *state->coerceToString(noPos, *v, context, "while generating the eval command output")); + writeFull(getStandardOutput(), *state->coerceToString(noPos, *v, context, "while generating the eval command output")); } else if (json) { diff --git a/src/nix/log.cc b/src/nix/log.cc index 7f590c708..1a6f48f5e 100644 --- a/src/nix/log.cc +++ b/src/nix/log.cc @@ -57,7 +57,7 @@ struct CmdLog : InstallableCommand if (!log) continue; stopProgressBar(); printInfo("got build log for '%s' from '%s'", installable->what(), logSub.getUri()); - writeFull(getStandardOut(), *log); + writeFull(getStandardOutput(), *log); return; } diff --git a/src/nix/sigs.cc b/src/nix/sigs.cc index 1e277cbbe..2afe4b267 100644 --- a/src/nix/sigs.cc +++ b/src/nix/sigs.cc @@ -177,7 +177,7 @@ struct CmdKeyGenerateSecret : Command throw UsageError("required argument '--key-name' is missing"); stopProgressBar(); - writeFull(getStandardOut(), SecretKey::generate(*keyName).to_string()); + writeFull(getStandardOutput(), SecretKey::generate(*keyName).to_string()); } }; @@ -199,7 +199,7 @@ struct CmdKeyConvertSecretToPublic : Command { SecretKey secretKey(drainFD(STDIN_FILENO)); stopProgressBar(); - writeFull(getStandardOut(), secretKey.toPublicKey().to_string()); + writeFull(getStandardOutput(), secretKey.toPublicKey().to_string()); } }; From a6149eb89dc48d8f5a279709dfc9b13f85730d5e Mon Sep 17 00:00:00 2001 From: John Ericson Date: Thu, 7 Nov 2024 14:33:46 -0500 Subject: [PATCH 404/718] Add `eofOk` parameter to the Windows `readLine` impl Now the two implementations are back in sync. --- src/libutil/windows/file-descriptor.cc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/libutil/windows/file-descriptor.cc b/src/libutil/windows/file-descriptor.cc index 16773e3ea..7b8a712e8 100644 --- a/src/libutil/windows/file-descriptor.cc +++ b/src/libutil/windows/file-descriptor.cc @@ -61,7 +61,7 @@ void writeFull(HANDLE handle, std::string_view s, bool allowInterrupts) } -std::string readLine(HANDLE handle) +std::string readLine(HANDLE handle, bool eofOk) { std::string s; while (1) { @@ -71,8 +71,12 @@ std::string readLine(HANDLE handle) DWORD rd; if (!ReadFile(handle, &ch, 1, &rd, NULL)) { throw WinError("reading a line"); - } else if (rd == 0) - throw EndOfFile("unexpected EOF reading a line"); + } else if (rd == 0) { + if (eofOk) + return s; + else + throw EndOfFile("unexpected EOF reading a line"); + } else { if (ch == '\n') return s; s += ch; From d5f5717172232802d9c62315d0d348493026c8d1 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 8 Nov 2024 13:14:43 +0100 Subject: [PATCH 405/718] Remove shellInputs.i686-linux It fails to compile (https://hydra.nixos.org/build/277363696) and it's unlikely anybody cares. --- packaging/hydra.nix | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packaging/hydra.nix b/packaging/hydra.nix index 6da502079..f47ed80e3 100644 --- a/packaging/hydra.nix +++ b/packaging/hydra.nix @@ -62,7 +62,9 @@ in build = forAllPackages (pkgName: forAllSystems (system: nixpkgsFor.${system}.native.nixComponents.${pkgName})); - shellInputs = forAllSystems (system: self.devShells.${system}.default.inputDerivation); + shellInputs = removeAttrs + (forAllSystems (system: self.devShells.${system}.default.inputDerivation)) + [ "i686-linux" ]; buildStatic = forAllPackages (pkgName: lib.genAttrs linux64BitSystems (system: nixpkgsFor.${system}.static.nixComponents.${pkgName})); From 3e0129ce3b9eb094d4a3cc8023884f372f1d7ff6 Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman <145775305+xokdvium@users.noreply.github.com> Date: Fri, 8 Nov 2024 15:44:20 +0300 Subject: [PATCH 406/718] fix(libutil/posix-source-accessor.cc): get rid of use-after-move bug Naming class member variables the same as constructor arguments is a very slippery slope because of how member variable names get resolved. Compiler is not very helpful here and we need static analysis to forbid this kind of stuff. The following example illustrates the cause quite well: ```cpp struct B { B(int) {} }; struct A { A(int b): b([&](){ return b; static_assert(std::is_same_v); }()) { static_assert(std::is_same_v); } void member() { static_assert(std::is_same_v); } B b; }; int main() { A(1).member(); } ``` From N4861 6.5.1 Unqualified name lookup: > In all the cases listed in [basic.lookup.unqual], the scopes are searched > for a declaration in the order listed in each of the respective categories; > name lookup ends as soon as a declaration is found for the name. > If no declaration is found, the program is ill-formed. In the affected code there was a use-after-move for all accesses in the constructor body, but this UB wasn't triggered. These types of errors are trivial to catch via clang-tidy's [clang-analyzer-cplusplus.Move]. --- src/libutil/posix-source-accessor.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libutil/posix-source-accessor.cc b/src/libutil/posix-source-accessor.cc index f26f74d58..50b436893 100644 --- a/src/libutil/posix-source-accessor.cc +++ b/src/libutil/posix-source-accessor.cc @@ -7,8 +7,8 @@ namespace nix { -PosixSourceAccessor::PosixSourceAccessor(std::filesystem::path && root) - : root(std::move(root)) +PosixSourceAccessor::PosixSourceAccessor(std::filesystem::path && argRoot) + : root(std::move(argRoot)) { assert(root.empty() || root.is_absolute()); displayPrefix = root.string(); From d228c00614ba70a74ceeaa3233015d91fabcc1b9 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 8 Nov 2024 17:06:49 +0100 Subject: [PATCH 407/718] Trim release notes --- doc/manual/source/release-notes/rl-2.25.md | 60 ++++++---------------- 1 file changed, 15 insertions(+), 45 deletions(-) diff --git a/doc/manual/source/release-notes/rl-2.25.md b/doc/manual/source/release-notes/rl-2.25.md index 7364db980..e2213885b 100644 --- a/doc/manual/source/release-notes/rl-2.25.md +++ b/doc/manual/source/release-notes/rl-2.25.md @@ -1,6 +1,6 @@ # Release 2.25.0 (2024-11-07) -- Use envvars NIX_CACHE_HOME, NIX_CONFIG_HOME, NIX_DATA_HOME, NIX_STATE_HOME if defined [#11351](https://github.com/NixOS/nix/pull/11351) +- New environment variables to override XDG locations [#11351](https://github.com/NixOS/nix/pull/11351) Added new environment variables: @@ -10,35 +10,28 @@ - `NIX_STATE_HOME` Each, if defined, takes precedence over the corresponding [XDG environment variable](@docroot@/command-ref/env-common.md#xdg-base-directories). - This provides more fine-grained control over where Nix looks for files, and allows to have a stand-alone Nix environment, which only uses files in a specific directory, and doesn't interfere with the user environment. + This provides more fine-grained control over where Nix looks for files. It allows having a stand-alone Nix environment that only uses files in a specific directory and that doesn't interfere with the user environment. - Define integer overflow in the Nix language as an error [#10968](https://github.com/NixOS/nix/issues/10968) [#11188](https://github.com/NixOS/nix/pull/11188) - Previously, integer overflow in the Nix language invoked C++ level signed overflow, which was undefined behaviour, but *usually* manifested as wrapping around on overflow. - - Since prior to the public release of Lix, Lix had C++ signed overflow defined to crash the process and nobody noticed this having accidentally removed overflow from the Nix language for three months until it was caught by fiddling around. - Given the significant body of actual Nix code that has been evaluated by Lix in that time, it does not appear that nixpkgs or much of importance depends on integer overflow, so it appears safe to turn into an error. - - Some other overflows were fixed: - - `builtins.fromJSON` of values greater than the maximum representable value in a signed 64-bit integer will generate an error. - - `nixConfig` in flakes will no longer accept negative values for configuration options. - - Integer overflow now looks like the following: + Previously, integer overflow in the Nix language invoked C++ level signed overflow, which manifested as wrapping around on overflow. It now looks like this: ``` $ nix eval --expr '9223372036854775807 + 1' error: integer overflow in adding 9223372036854775807 + 1 ``` -- The `build-hook` setting's default is less useful when using `libnixstore` as a library [#11178](https://github.com/NixOS/nix/pull/11178) + Some other overflows were fixed: + - `builtins.fromJSON` of values greater than the maximum representable value in a signed 64-bit integer will generate an error. + - `nixConfig` in flakes will no longer accept negative values for configuration options. - *This is an obscure issue that only affects usage of the `libnixstore` library outside of the Nix executable.* +- The `build-hook` setting no longer has a useful default when using `libnixstore` as a library [#11178](https://github.com/NixOS/nix/pull/11178) + + *This is an obscure issue that only affects usage of the `libnixstore` library outside of the Nix executable. It is unrelated to the `post-build-hook` settings, which is often used for pushing to a cache.* As part the ongoing [rewrite of the build system](https://github.com/NixOS/nix/issues/2503) to use [Meson](https://mesonbuild.com/), we are also switching to packaging individual Nix components separately (and building them in separate derivations). This means that when building `libnixstore` we do not know where the Nix binaries will be installed --- `libnixstore` doesn't know about downstream consumers like the Nix binaries at all. - *This is also unrelated to the _`post`_-`build-hook`*, which is often used for pushing to a cache.* - This has a small adverse affect on remote building --- the `build-remote` executable that is specified from the [`build-hook`](@docroot@/command-ref/conf-file.md#conf-build-hook) setting will not be gotten from the (presumed) installation location, but instead looked up on the `PATH`. This means that other applications linking `libnixstore` that wish to use remote building must arrange for the `nix` command to be on the PATH (or manually overriding `build-hook`) in order for that to work. @@ -48,13 +41,12 @@ The Perl bindings no longer expose `getBinDir` either, since the underlying C++ libraries those bindings wrap no longer know the location of installed binaries as described above. -- wrap filesystem exceptions more correctly [#11378](https://github.com/NixOS/nix/pull/11378) +- Wrap filesystem exceptions more correctly [#11378](https://github.com/NixOS/nix/pull/11378) With the switch to `std::filesystem` in different places, Nix started to throw `std::filesystem::filesystem_error` in many places instead of its own exceptions. + As a result, Nix no longer generated error traces when (for example) listing a non-existing directory. It could also lead to crashes inside the Nix REPL. - This lead to no longer generating error traces, for example when listing a non-existing directory, and can also lead to crashes inside the Nix REPL. - - This version catches these types of exception correctly and wrap them into Nix's own exeception type. + This version catches these types of exception correctly and wraps them into Nix's own exception type. Author: [**@Mic92**](https://github.com/Mic92) @@ -64,38 +56,16 @@ Author: [**@squalus**](https://github.com/squalus) -- Show package descriptions with `nix flake show` [#10977](https://github.com/NixOS/nix/issues/10977) [#10980](https://github.com/NixOS/nix/pull/10980) - - `nix flake show` will now display a package's `meta.description` if it exists. If the description does not fit in the terminal it will be truncated to fit the terminal width. If the size of the terminal width is unknown the description will be capped at 80 characters. - - ``` - $ nix flake show - └───packages - └───x86_64-linux - ├───builderImage: package 'docker-image-ara-builder-image.tar.gz' - 'Docker image hosting the nix build environment' - └───runnerImage: package 'docker-image-gitlab-runner.tar.gz' - 'Docker image hosting the gitlab-runner executable' - ``` - - In a narrower terminal: - - ``` - $ nix flake show - └───packages - └───x86_64-linux - ├───builderImage: package 'docker-image-ara-builder-image.tar.gz' - 'Docker image hosting the nix b... - └───runnerImage: package 'docker-image-gitlab-runner.tar.gz' - 'Docker image hosting the gitlab-run... - ``` - - Removing the default argument passed to the `nix fmt` formatter [#11438](https://github.com/NixOS/nix/pull/11438) - The underlying formatter no longer receives the ". " default argument when `nix fmt` is called with no arguments. + The underlying formatter no longer receives the "." default argument when `nix fmt` is called with no arguments. This change was necessary as the formatter wasn't able to distinguish between a user wanting to format the current folder with `nix fmt .` or the generic `nix fmt`. - The default behaviour is now the responsibility of the formatter itself, and - allows tools such as treefmt to format the whole tree instead of only the + The default behavior is now the responsibility of the formatter itself, and + allows tools such as `treefmt` to format the whole tree instead of only the current directory and below. Author: [**@zimbatm**](https://github.com/zimbatm) From 397f3c544e976514e949f45b21c7112a7c4912a6 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 8 Nov 2024 17:10:20 +0100 Subject: [PATCH 408/718] Add credits --- doc/manual/source/release-notes/rl-2.25.md | 64 ++++++++++++++++++- .../data/release-credits-email-to-handle.json | 52 ++++++++++++++- .../data/release-credits-handle-to-name.json | 47 +++++++++++++- 3 files changed, 160 insertions(+), 3 deletions(-) diff --git a/doc/manual/source/release-notes/rl-2.25.md b/doc/manual/source/release-notes/rl-2.25.md index e2213885b..2b6706496 100644 --- a/doc/manual/source/release-notes/rl-2.25.md +++ b/doc/manual/source/release-notes/rl-2.25.md @@ -85,4 +85,66 @@ # Contributors -Querying GitHub API for 2e7466a4e0bce4dde9922fa3445d1947d6098fad, to get handle for 145775305+xokdvium@users.noreply.github.com +This release was made possible by the following 58 contributors: + +- 1444 [**(@0x5a4)**](https://github.com/0x5a4) +- Adrian Hesketh [**(@a-h)**](https://github.com/a-h) +- Aleksana [**(@Aleksanaa)**](https://github.com/Aleksanaa) +- Alyssa Ross [**(@alyssais)**](https://github.com/alyssais) +- Andrew Marshall [**(@amarshall)**](https://github.com/amarshall) +- Artemis Tosini [**(@artemist)**](https://github.com/artemist) +- Artturin [**(@Artturin)**](https://github.com/Artturin) +- Bjørn Forsman [**(@bjornfor)**](https://github.com/bjornfor) +- Brian McGee [**(@brianmcgee)**](https://github.com/brianmcgee) +- Brian McKenna [**(@puffnfresh)**](https://github.com/puffnfresh) +- Bryan Honof [**(@bryanhonof)**](https://github.com/bryanhonof) +- Cole Helbling [**(@cole-h)**](https://github.com/cole-h) +- Eelco Dolstra [**(@edolstra)**](https://github.com/edolstra) +- Eman Resu [**(@llakala)**](https://github.com/llakala) +- Emery Hemingway [**(@ehmry)**](https://github.com/ehmry) +- Emil Petersen [**(@leetemil)**](https://github.com/leetemil) +- Emily [**(@emilazy)**](https://github.com/emilazy) +- Geoffrey Thomas [**(@geofft)**](https://github.com/geofft) +- Gerg-L [**(@Gerg-L)**](https://github.com/Gerg-L) +- Ivan Tkachev +- Jacek Galowicz [**(@tfc)**](https://github.com/tfc) +- Jan Hrcek [**(@jhrcek)**](https://github.com/jhrcek) +- Jason Yundt [**(@Jayman2000)**](https://github.com/Jayman2000) +- Jeremy Kerfs [**(@jkerfs)**](https://github.com/jkerfs) +- Jeremy Kolb [**(@kjeremy)**](https://github.com/kjeremy) +- John Ericson [**(@Ericson2314)**](https://github.com/Ericson2314) +- Jonas Chevalier [**(@zimbatm)**](https://github.com/zimbatm) +- Jordan Justen [**(@jljusten)**](https://github.com/jljusten) +- Josh Heinrichs [**(@joshheinrichs-shopify)**](https://github.com/joshheinrichs-shopify) +- Jörg Thalheim [**(@Mic92)**](https://github.com/Mic92) +- Kevin Cox [**(@kevincox)**](https://github.com/kevincox) +- Michael Gallagher [**(@mjgallag)**](https://github.com/mjgallag) +- Michael [**(@michaelvanstraten)**](https://github.com/michaelvanstraten) +- Nikodem Rabuliński [**(@nrabulinski)**](https://github.com/nrabulinski) +- Noam Yorav-Raphael [**(@noamraph)**](https://github.com/noamraph) +- Onni Hakala [**(@onnimonni)**](https://github.com/onnimonni) +- Parker Hoyes [**(@parkerhoyes)**](https://github.com/parkerhoyes) +- Philipp Otterbein +- Pol Dellaiera [**(@drupol)**](https://github.com/drupol) +- Robert Hensing [**(@roberth)**](https://github.com/roberth) +- Ryan Hendrickson [**(@rhendric)**](https://github.com/rhendric) +- Sandro [**(@SuperSandro2000)**](https://github.com/SuperSandro2000) +- Seggy Umboh [**(@secobarbital)**](https://github.com/secobarbital) +- Sergei Zimmerman [**(@xokdvium)**](https://github.com/xokdvium) +- Shivaraj B H [**(@shivaraj-bh)**](https://github.com/shivaraj-bh) +- Siddhant Kumar [**(@siddhantk232)**](https://github.com/siddhantk232) +- Tim [**(@Jaculabilis)**](https://github.com/Jaculabilis) +- Tom Bereknyei +- Travis A. Everett [**(@abathur)**](https://github.com/abathur) +- Valentin Gagarin [**(@fricklerhandwerk)**](https://github.com/fricklerhandwerk) +- Vinayak Kaushik [**(@VinayakKaushikDH)**](https://github.com/VinayakKaushikDH) +- Yann Hamdaoui [**(@yannham)**](https://github.com/yannham) +- Yuriy Taraday [**(@YorikSar)**](https://github.com/YorikSar) +- bryango [**(@bryango)**](https://github.com/bryango) +- emhamm [**(@emhamm)**](https://github.com/emhamm) +- jade [**(@lf-)**](https://github.com/lf-) +- kenji [**(@a-kenji)**](https://github.com/a-kenji) +- pennae [**(@pennae)**](https://github.com/pennae) +- puckipedia [**(@puckipedia)**](https://github.com/puckipedia) +- squalus [**(@squalus)**](https://github.com/squalus) +- tomberek [**(@tomberek)**](https://github.com/tomberek) diff --git a/maintainers/data/release-credits-email-to-handle.json b/maintainers/data/release-credits-email-to-handle.json index cddc1a6e7..d7a238ebd 100644 --- a/maintainers/data/release-credits-email-to-handle.json +++ b/maintainers/data/release-credits-email-to-handle.json @@ -48,5 +48,55 @@ "delroth@gmail.com": "delroth", "enno@nerdworks.de": "elohmeier", "mjbauer95@gmail.com": "matthewbauer", - "MostAwesomeDude@gmail.com": "MostAwesomeDude" + "MostAwesomeDude@gmail.com": "MostAwesomeDude", + "145775305+xokdvium@users.noreply.github.com": "xokdvium", + "bryanhonof@gmail.com": "bryanhonof", + "50352631+michaelvanstraten@users.noreply.github.com": "michaelvanstraten", + "bjorn.forsman@gmail.com": "bjornfor", + "pol.dellaiera@protonmail.com": "drupol", + "tim.vanbaak@gmail.com": "Jaculabilis", + "leetemil@users.noreply.github.com": "leetemil", + "a-h@users.noreply.github.com": "a-h", + "me@artem.ist": "artemist", + "puck@puckipedia.com": "puckipedia", + "marian.hammer@meetwise.com": "emhamm", + "78693624+llakala@users.noreply.github.com": "llakala", + "itkachev@hyperad.tech": null, + "geofft@ldpreload.com": "geofft", + "onni@flaky.build": "onnimonni", + "jacek@galowicz.de": "tfc", + "potterbein@blockstream.com": null, + "49699333+dependabot[bot]@users.noreply.github.com": "dependabot[bot]", + "112626461+VinayakKaushikDH@users.noreply.github.com": "VinayakKaushikDH", + "kevincox@kevincox.ca": "kevincox", + "yann.hamdaoui@tweag.io": "yannham", + "GregLeyda@proton.me": "Gerg-L", + "jljusten@gmail.com": "jljusten", + "josh.heinrichs@shopify.com": "joshheinrichs-shopify", + "jason@jasonyundt.email": "Jayman2000", + "noamraph@gmail.com": "noamraph", + "nikodem@rabulinski.com": "nrabulinski", + "78693624+quatquatt@users.noreply.github.com": "llakala", + "yuriy.taraday@tweag.io": "YorikSar", + "travis.a.everett@gmail.com": "abathur", + "Artturin@artturin.com": "Artturin", + "zimbatm@zimbatm.com": "zimbatm", + "contact@parkerhoyes.com": "parkerhoyes", + "kjeremy@gmail.com": "kjeremy", + "jkerfs@users.noreply.github.com": "jkerfs", + "sandro.jaeckel@gmail.com": "SuperSandro2000", + "hi@alyssa.is": "alyssais", + "2716069+jhrcek@users.noreply.github.com": "jhrcek", + "seggy.umboh@coupa.com": "secobarbital", + "hello@emily.moe": "emilazy", + "ehmry@posteo.net": "ehmry", + "me@aleksana.moe": "Aleksanaa", + "tom@floxdev.com": null, + "sbh69840@gmail.com": "shivaraj-bh", + "mjgallag@gmail.com": "mjgallag", + "bryango@users.noreply.github.com": "bryango", + "aks.kenji@protonmail.com": "a-kenji", + "54070204+0x5a4@users.noreply.github.com": "0x5a4", + "brian@bmcgee.ie": "brianmcgee", + "squalus@squalus.net": "squalus" } \ No newline at end of file diff --git a/maintainers/data/release-credits-handle-to-name.json b/maintainers/data/release-credits-handle-to-name.json index abf9ed05b..765771668 100644 --- a/maintainers/data/release-credits-handle-to-name.json +++ b/maintainers/data/release-credits-handle-to-name.json @@ -41,5 +41,50 @@ "winterqt": "Winter", "GoldsteinE": "Max \u201cGoldstein\u201d Siling", "pennae": null, - "MostAwesomeDude": "Corbin Simpson" + "MostAwesomeDude": "Corbin Simpson", + "VinayakKaushikDH": "Vinayak Kaushik", + "leetemil": "Emil Petersen", + "michaelvanstraten": "Michael", + "parkerhoyes": "Parker Hoyes", + "a-h": "Adrian Hesketh", + "a-kenji": "kenji", + "geofft": "Geoffrey Thomas", + "bryango": null, + "tfc": "Jacek Galowicz", + "brianmcgee": "Brian McGee", + "Gerg-L": null, + "secobarbital": "Seggy Umboh", + "bjornfor": "Bj\u00f8rn Forsman", + "dependabot[bot]": null, + "xokdvium": "Sergei Zimmerman", + "kevincox": "Kevin Cox", + "Jayman2000": "Jason Yundt", + "Artturin": "Artturin", + "0x5a4": "1444", + "llakala": "Eman Resu", + "nrabulinski": "Nikodem Rabuli\u0144ski", + "shivaraj-bh": "Shivaraj B H", + "yannham": "Yann Hamdaoui", + "jkerfs": "Jeremy Kerfs", + "drupol": "Pol Dellaiera", + "onnimonni": "Onni Hakala", + "joshheinrichs-shopify": "Josh Heinrichs", + "puckipedia": null, + "abathur": "Travis A. Everett", + "alyssais": "Alyssa Ross", + "noamraph": "Noam Yorav-Raphael", + "squalus": null, + "emhamm": null, + "mjgallag": "Michael Gallagher", + "jljusten": "Jordan Justen", + "ehmry": "Emery Hemingway", + "jhrcek": "Jan Hrcek", + "Jaculabilis": "Tim", + "bryanhonof": "Bryan Honof", + "zimbatm": "Jonas Chevalier", + "SuperSandro2000": "Sandro", + "Aleksanaa": "Aleksana", + "YorikSar": "Yuriy Taraday", + "kjeremy": "Jeremy Kolb", + "artemist": "Artemis Tosini" } \ No newline at end of file From d90b56d52714426b2d7f946e2f75b1aaebff1221 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 8 Nov 2024 17:31:35 +0100 Subject: [PATCH 409/718] Remove no longer needed hack --- src/libfetchers/tarball.cc | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/libfetchers/tarball.cc b/src/libfetchers/tarball.cc index 27ad89b6e..28574e7b1 100644 --- a/src/libfetchers/tarball.cc +++ b/src/libfetchers/tarball.cc @@ -384,11 +384,7 @@ struct TarballInputScheme : CurlInputScheme input = immutableInput; } - /* If we got a lastModified and the input is not final and - doesn't have one, then return it. Note that we don't do - this if the input is final for compatibility with old lock - files that didn't include lastModified. */ - if (result.lastModified && !_input.isFinal() && !input.attrs.contains("lastModified")) + if (result.lastModified && !input.attrs.contains("lastModified")) input.attrs.insert_or_assign("lastModified", uint64_t(result.lastModified)); input.attrs.insert_or_assign("narHash", From 17b49134fae6450c10fbbd7dfbc613ad08265b83 Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman <145775305+xokdvium@users.noreply.github.com> Date: Fri, 8 Nov 2024 19:15:43 +0300 Subject: [PATCH 410/718] fix(treewide): fix incorrect usage of std::move `auto &&` and `T &&` are forwarding references and can be either lvalue or rvalue references. Moving from universal references is incorrect and should not be done. Moving from integral or floating-point values is pointless and just worsens debug performance. --- src/libstore/filetransfer.cc | 2 +- src/libstore/machines.cc | 2 +- src/libutil/executable-path.cc | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libstore/filetransfer.cc b/src/libstore/filetransfer.cc index e9e4b2c44..42b93cfe0 100644 --- a/src/libstore/filetransfer.cc +++ b/src/libstore/filetransfer.cc @@ -153,7 +153,7 @@ struct curlFileTransfer : public FileTransfer template void fail(T && e) { - failEx(std::make_exception_ptr(std::move(e))); + failEx(std::make_exception_ptr(std::forward(e))); } LambdaSink finalSink; diff --git a/src/libstore/machines.cc b/src/libstore/machines.cc index 5e038fb28..eb729b697 100644 --- a/src/libstore/machines.cc +++ b/src/libstore/machines.cc @@ -33,7 +33,7 @@ Machine::Machine( systemTypes(systemTypes), sshKey(sshKey), maxJobs(maxJobs), - speedFactor(speedFactor == 0.0f ? 1.0f : std::move(speedFactor)), + speedFactor(speedFactor == 0.0f ? 1.0f : speedFactor), supportedFeatures(supportedFeatures), mandatoryFeatures(mandatoryFeatures), sshPublicHostKey(sshPublicHostKey) diff --git a/src/libutil/executable-path.cc b/src/libutil/executable-path.cc index 9fb5214b2..b5e22bab9 100644 --- a/src/libutil/executable-path.cc +++ b/src/libutil/executable-path.cc @@ -35,7 +35,7 @@ ExecutablePath ExecutablePath::parse(const OsString & path) std::make_move_iterator(strings.begin()), std::make_move_iterator(strings.end()), std::back_inserter(ret), - [](auto && str) { + [](OsString && str) { return fs::path{ str.empty() // "A zero-length prefix is a legacy feature that From af63d67ba5cca00cb7e99c41a15447e5a706b1e1 Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman <145775305+xokdvium@users.noreply.github.com> Date: Fri, 8 Nov 2024 19:28:12 +0300 Subject: [PATCH 411/718] fix(libutils): make ref move assignable/constructible --- src/libutil/ref.hh | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/libutil/ref.hh b/src/libutil/ref.hh index 3d0e64ab4..92688bf1e 100644 --- a/src/libutil/ref.hh +++ b/src/libutil/ref.hh @@ -18,11 +18,6 @@ private: std::shared_ptr p; public: - - ref(const ref & r) - : p(r.p) - { } - explicit ref(const std::shared_ptr & p) : p(p) { @@ -75,8 +70,6 @@ public: return ref((std::shared_ptr) p); } - ref & operator=(ref const & rhs) = default; - bool operator == (const ref & other) const { return p == other.p; From 6c3f720e2c7954f9cc3532056f3d215bdfdb3ca6 Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman <145775305+xokdvium@users.noreply.github.com> Date: Fri, 8 Nov 2024 19:29:41 +0300 Subject: [PATCH 412/718] fix(treewide): move arguments where needed Moving from arguments where it should be done. --- src/libcmd/installable-flake.hh | 2 +- src/libcmd/installable-value.hh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcmd/installable-flake.hh b/src/libcmd/installable-flake.hh index 8e0a232ef..212403dd4 100644 --- a/src/libcmd/installable-flake.hh +++ b/src/libcmd/installable-flake.hh @@ -26,7 +26,7 @@ struct ExtraPathInfoFlake : ExtraPathInfoValue Flake flake; ExtraPathInfoFlake(Value && v, Flake && f) - : ExtraPathInfoValue(std::move(v)), flake(f) + : ExtraPathInfoValue(std::move(v)), flake(std::move(f)) { } }; diff --git a/src/libcmd/installable-value.hh b/src/libcmd/installable-value.hh index 60207cd23..4b6dbd306 100644 --- a/src/libcmd/installable-value.hh +++ b/src/libcmd/installable-value.hh @@ -59,7 +59,7 @@ struct ExtraPathInfoValue : ExtraPathInfo Value value; ExtraPathInfoValue(Value && v) - : value(v) + : value(std::move(v)) { } virtual ~ExtraPathInfoValue() = default; From 8dd787fbf6a204b565b031baf0036262177cecc8 Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman <145775305+xokdvium@users.noreply.github.com> Date: Fri, 8 Nov 2024 19:33:57 +0300 Subject: [PATCH 413/718] fix(libutil): remove no-op move from const --- src/libutil/position.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libutil/position.cc b/src/libutil/position.cc index 5a2529262..946f167b6 100644 --- a/src/libutil/position.cc +++ b/src/libutil/position.cc @@ -9,7 +9,7 @@ Pos::Pos(const Pos * other) } line = other->line; column = other->column; - origin = std::move(other->origin); + origin = other->origin; } Pos::operator std::shared_ptr() const From 149802b9f5e1364ddf9905c63d2436e07b911078 Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman <145775305+xokdvium@users.noreply.github.com> Date: Fri, 8 Nov 2024 19:39:26 +0300 Subject: [PATCH 414/718] fix(libstore): make BasicDerivation move-constructible/assignable --- src/libstore/derivations.hh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libstore/derivations.hh b/src/libstore/derivations.hh index 58e5328a5..40740d545 100644 --- a/src/libstore/derivations.hh +++ b/src/libstore/derivations.hh @@ -298,6 +298,10 @@ struct BasicDerivation std::string name; BasicDerivation() = default; + BasicDerivation(BasicDerivation &&) = default; + BasicDerivation(const BasicDerivation &) = default; + BasicDerivation& operator=(BasicDerivation &&) = default; + BasicDerivation& operator=(const BasicDerivation &) = default; virtual ~BasicDerivation() { }; bool isBuiltin() const; From 0347bca15b98f89570d5c55f875931bb81b2eb00 Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman <145775305+xokdvium@users.noreply.github.com> Date: Fri, 8 Nov 2024 20:43:58 +0300 Subject: [PATCH 415/718] fix(libstore/path-info): make ValidPathInfo move constructible/assignable --- src/libstore/path-info.hh | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/libstore/path-info.hh b/src/libstore/path-info.hh index 71f1476a6..9a4c466a8 100644 --- a/src/libstore/path-info.hh +++ b/src/libstore/path-info.hh @@ -176,17 +176,18 @@ struct ValidPathInfo : UnkeyedValidPathInfo { */ Strings shortRefs() const; - ValidPathInfo(const ValidPathInfo & other) = default; - ValidPathInfo(StorePath && path, UnkeyedValidPathInfo info) : UnkeyedValidPathInfo(info), path(std::move(path)) { }; ValidPathInfo(const StorePath & path, UnkeyedValidPathInfo info) : UnkeyedValidPathInfo(info), path(path) { }; ValidPathInfo(const Store & store, std::string_view name, ContentAddressWithReferences && ca, Hash narHash); - - virtual ~ValidPathInfo() { } }; +static_assert(std::is_move_assignable_v); +static_assert(std::is_copy_assignable_v); +static_assert(std::is_copy_constructible_v); +static_assert(std::is_move_constructible_v); + using ValidPathInfos = std::map; } From 4dceca51deaffc7140a2b8a19d75c9cfa2d64c48 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 8 Nov 2024 19:27:54 +0100 Subject: [PATCH 416/718] Don't allow __final in fetchTree It's now only allowed in fetchFinalTree, which is not exposed to users but only to call-flake.nix. --- src/libexpr/call-flake.nix | 5 ++++- src/libexpr/eval.cc | 12 +++++++++--- src/libexpr/eval.hh | 10 ++++++++++ src/libexpr/primops/fetchTree.cc | 20 ++++++++++++++++++++ src/libflake/flake/flake.cc | 8 +++++--- src/libflake/flake/flake.hh | 7 +++++++ src/nix/flake.md | 2 -- 7 files changed, 55 insertions(+), 9 deletions(-) diff --git a/src/libexpr/call-flake.nix b/src/libexpr/call-flake.nix index 79b3e804e..a008346e5 100644 --- a/src/libexpr/call-flake.nix +++ b/src/libexpr/call-flake.nix @@ -10,6 +10,9 @@ lockFileStr: # unlocked trees. overrides: +# This is `prim_fetchFinalTree`. +fetchTreeFinal: + let lockFile = builtins.fromJSON lockFileStr; @@ -45,7 +48,7 @@ let else # FIXME: remove obsolete node.info. # Note: lock file entries are always final. - fetchTree (node.info or {} // removeAttrs node.locked ["dir"] // { __final = true; }); + fetchTreeFinal (node.info or {} // removeAttrs node.locked ["dir"]); subdir = overrides.${key}.dir or node.locked.dir or ""; diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index e4937735b..03d03e076 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -510,9 +510,15 @@ Value * EvalState::addPrimOp(PrimOp && primOp) Value * v = allocValue(); v->mkPrimOp(new PrimOp(primOp)); - staticBaseEnv->vars.emplace_back(envName, baseEnvDispl); - baseEnv.values[baseEnvDispl++] = v; - baseEnv.values[0]->payload.attrs->push_back(Attr(symbols.create(primOp.name), v)); + + if (primOp.internal) + internalPrimOps.emplace(primOp.name, v); + else { + staticBaseEnv->vars.emplace_back(envName, baseEnvDispl); + baseEnv.values[baseEnvDispl++] = v; + baseEnv.values[0]->payload.attrs->push_back(Attr(symbols.create(primOp.name), v)); + } + return v; } diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index f7ed6be83..6b344137f 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -107,6 +107,11 @@ struct PrimOp */ std::optional experimentalFeature; + /** + * If true, this primop is not exposed to the user. + */ + bool internal = false; + /** * Validity check to be performed by functions that introduce primops, * such as RegisterPrimOp() and Value::mkPrimOp(). @@ -591,6 +596,11 @@ public: */ std::shared_ptr staticBaseEnv; // !!! should be private + /** + * Internal primops not exposed to the user. + */ + std::unordered_map, std::equal_to, traceable_allocator>> internalPrimOps; + /** * Name and documentation about every constant. * diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc index d2266e2bc..c207da8ad 100644 --- a/src/libexpr/primops/fetchTree.cc +++ b/src/libexpr/primops/fetchTree.cc @@ -78,6 +78,7 @@ struct FetchTreeParams { bool emptyRevFallback = false; bool allowNameArgument = false; bool isFetchGit = false; + bool isFinal = false; }; static void fetchTree( @@ -195,6 +196,13 @@ static void fetchTree( state.checkURI(input.toURLString()); + if (params.isFinal) { + input.attrs.insert_or_assign("__final", Explicit(true)); + } else { + if (input.isFinal()) + throw Error("input '%s' is not allowed to use the '__final' attribute", input.to_string()); + } + auto [storePath, input2] = input.fetchToStore(state.store); state.allowPath(storePath); @@ -431,6 +439,18 @@ static RegisterPrimOp primop_fetchTree({ .experimentalFeature = Xp::FetchTree, }); +void prim_fetchFinalTree(EvalState & state, const PosIdx pos, Value * * args, Value & v) +{ + fetchTree(state, pos, args, v, {.isFinal = true}); +} + +static RegisterPrimOp primop_fetchFinalTree({ + .name = "fetchFinalTree", + .args = {"input"}, + .fun = prim_fetchFinalTree, + .internal = true, +}); + static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v, const std::string & who, bool unpack, std::string name) { diff --git a/src/libflake/flake/flake.cc b/src/libflake/flake/flake.cc index f6f29f241..edb76f861 100644 --- a/src/libflake/flake/flake.cc +++ b/src/libflake/flake/flake.cc @@ -809,12 +809,14 @@ void callFlake(EvalState & state, auto vCallFlake = state.allocValue(); state.evalFile(state.callFlakeInternal, *vCallFlake); - auto vTmp1 = state.allocValue(); auto vLocks = state.allocValue(); vLocks->mkString(lockFileStr); - state.callFunction(*vCallFlake, *vLocks, *vTmp1, noPos); - state.callFunction(*vTmp1, vOverrides, vRes, noPos); + auto vFetchFinalTree = get(state.internalPrimOps, "fetchFinalTree"); + assert(vFetchFinalTree); + + Value * args[] = {vLocks, &vOverrides, *vFetchFinalTree}; + state.callFunction(*vCallFlake, 3, args, vRes, noPos); } void initLib(const Settings & settings) diff --git a/src/libflake/flake/flake.hh b/src/libflake/flake/flake.hh index 496e18673..cc2bea76e 100644 --- a/src/libflake/flake/flake.hh +++ b/src/libflake/flake/flake.hh @@ -234,4 +234,11 @@ void emitTreeAttrs( bool emptyRevFallback = false, bool forceDirty = false); +/** + * An internal builtin similar to `fetchTree`, except that it + * always treats the input as final (i.e. no attributes can be + * added/removed/changed). + */ +void prim_fetchFinalTree(EvalState & state, const PosIdx pos, Value * * args, Value & v); + } diff --git a/src/nix/flake.md b/src/nix/flake.md index e35b936be..a9b703762 100644 --- a/src/nix/flake.md +++ b/src/nix/flake.md @@ -159,8 +159,6 @@ can occur in *locked* flake references and are available to Nix code: for tarball flakes, it's the most recent timestamp of any file inside the tarball. -Attributes that start with `__` are internal or experimental and may be removed in future versions. - ## Types Currently the `type` attribute can be one of the following: From 59246349d5b227cb3e35fbaef6b5468fbd2d3ec7 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Fri, 8 Nov 2024 20:13:07 +0100 Subject: [PATCH 417/718] Make nix log command easier to copy --- src/libstore/build/derivation-goal.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libstore/build/derivation-goal.cc b/src/libstore/build/derivation-goal.cc index 34ed16a38..3c0445fb6 100644 --- a/src/libstore/build/derivation-goal.cc +++ b/src/libstore/build/derivation-goal.cc @@ -991,7 +991,8 @@ Goal::Co DerivationGoal::buildDone() auto nixLogCommand = experimentalFeatureSettings.isEnabled(Xp::NixCommand) ? "nix log" : "nix-store -l"; - msg += fmt("For full logs, run '" ANSI_BOLD "%s %s" ANSI_NORMAL "'.", + // Don't put quotes around the command. This is copy-pasted a ton, so don't make that error prone. + msg += fmt("For full logs, run " ANSI_BOLD "%s %s" ANSI_NORMAL, nixLogCommand, worker.store.printStorePath(drvPath)); } From 4b44fa0f06d74caf7664a23a771774d093598824 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Fri, 8 Nov 2024 20:17:13 +0100 Subject: [PATCH 418/718] Make nix log command easy to copy on its own line --- src/libstore/build/derivation-goal.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libstore/build/derivation-goal.cc b/src/libstore/build/derivation-goal.cc index 3c0445fb6..794be1568 100644 --- a/src/libstore/build/derivation-goal.cc +++ b/src/libstore/build/derivation-goal.cc @@ -991,8 +991,10 @@ Goal::Co DerivationGoal::buildDone() auto nixLogCommand = experimentalFeatureSettings.isEnabled(Xp::NixCommand) ? "nix log" : "nix-store -l"; - // Don't put quotes around the command. This is copy-pasted a ton, so don't make that error prone. - msg += fmt("For full logs, run " ANSI_BOLD "%s %s" ANSI_NORMAL, + // The command is on a separate line for easy copying, such as with triple click. + // This message will be indented elsewhere, so removing the indentation before the + // command will not put it at the start of the line unfortunately. + msg += fmt("For full logs, run:\n " ANSI_BOLD "%s %s" ANSI_NORMAL, nixLogCommand, worker.store.printStorePath(drvPath)); } From 96eeb6f4ffd4656579c5d3703cee39dbde1c0dbd Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman <145775305+xokdvium@users.noreply.github.com> Date: Sat, 9 Nov 2024 11:58:17 +0300 Subject: [PATCH 419/718] refactor(treewide): make some move ctors noexcept where appropriate This is good practice to avoid pessimisations. Left comments for the reasoning why ctors should be noexcept. There are some tricky cases where we intentionally want throwing move ctors/assignments. But those cases should really be reviewed, since some of those can be replaced with more idiomatic copy/move-and-swap. --- src/libexpr/value.hh | 4 +++- src/libstore/remote-store-connection.hh | 2 +- src/libstore/sqlite.hh | 3 ++- src/libutil/callback.hh | 4 +++- src/libutil/file-descriptor.cc | 5 +++-- src/libutil/file-descriptor.hh | 2 +- src/libutil/finally.hh | 6 +++++- src/libutil/pool.hh | 10 +++++++++- 8 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/libexpr/value.hh b/src/libexpr/value.hh index 0ffe74dab..d98161488 100644 --- a/src/libexpr/value.hh +++ b/src/libexpr/value.hh @@ -141,7 +141,9 @@ public: Value * * elems; ListBuilder(EvalState & state, size_t size); - ListBuilder(ListBuilder && x) + // NOTE: Can be noexcept because we are just copying integral values and + // raw pointers. + ListBuilder(ListBuilder && x) noexcept : size(x.size) , inlineElems{x.inlineElems[0], x.inlineElems[1]} , elems(size <= 2 ? inlineElems : x.elems) diff --git a/src/libstore/remote-store-connection.hh b/src/libstore/remote-store-connection.hh index 513bd6838..f8549d0b2 100644 --- a/src/libstore/remote-store-connection.hh +++ b/src/libstore/remote-store-connection.hh @@ -40,7 +40,7 @@ struct RemoteStore::ConnectionHandle : handle(std::move(handle)) { } - ConnectionHandle(ConnectionHandle && h) + ConnectionHandle(ConnectionHandle && h) noexcept : handle(std::move(h.handle)) { } diff --git a/src/libstore/sqlite.hh b/src/libstore/sqlite.hh index 003e4d101..037380b71 100644 --- a/src/libstore/sqlite.hh +++ b/src/libstore/sqlite.hh @@ -42,7 +42,8 @@ struct SQLite SQLite(const Path & path, SQLiteOpenMode mode = SQLiteOpenMode::Normal); SQLite(const SQLite & from) = delete; SQLite& operator = (const SQLite & from) = delete; - SQLite& operator = (SQLite && from) { db = from.db; from.db = 0; return *this; } + // NOTE: This is noexcept since we are only copying and assigning raw pointers. + SQLite& operator = (SQLite && from) noexcept { db = from.db; from.db = 0; return *this; } ~SQLite(); operator sqlite3 * () { return db; } diff --git a/src/libutil/callback.hh b/src/libutil/callback.hh index 3710d1239..26c386d80 100644 --- a/src/libutil/callback.hh +++ b/src/libutil/callback.hh @@ -21,7 +21,9 @@ public: Callback(std::function)> fun) : fun(fun) { } - Callback(Callback && callback) : fun(std::move(callback.fun)) + // NOTE: std::function is noexcept move-constructible since C++20. + Callback(Callback && callback) noexcept(std::is_nothrow_move_constructible_v) + : fun(std::move(callback.fun)) { auto prev = callback.done.test_and_set(); if (prev) done.test_and_set(); diff --git a/src/libutil/file-descriptor.cc b/src/libutil/file-descriptor.cc index 3d8d70fdb..542c33f3b 100644 --- a/src/libutil/file-descriptor.cc +++ b/src/libutil/file-descriptor.cc @@ -45,8 +45,9 @@ AutoCloseFD::AutoCloseFD() : fd{INVALID_DESCRIPTOR} {} AutoCloseFD::AutoCloseFD(Descriptor fd) : fd{fd} {} - -AutoCloseFD::AutoCloseFD(AutoCloseFD && that) : fd{that.fd} +// NOTE: This can be noexcept since we are just copying a value and resetting +// the file descriptor in the rhs. +AutoCloseFD::AutoCloseFD(AutoCloseFD && that) noexcept : fd{that.fd} { that.fd = INVALID_DESCRIPTOR; } diff --git a/src/libutil/file-descriptor.hh b/src/libutil/file-descriptor.hh index bc8602e5c..fde362999 100644 --- a/src/libutil/file-descriptor.hh +++ b/src/libutil/file-descriptor.hh @@ -155,7 +155,7 @@ public: AutoCloseFD(); AutoCloseFD(Descriptor fd); AutoCloseFD(const AutoCloseFD & fd) = delete; - AutoCloseFD(AutoCloseFD&& fd); + AutoCloseFD(AutoCloseFD&& fd) noexcept; ~AutoCloseFD(); AutoCloseFD& operator =(const AutoCloseFD & fd) = delete; AutoCloseFD& operator =(AutoCloseFD&& fd); diff --git a/src/libutil/finally.hh b/src/libutil/finally.hh index bda4227e6..2b25010a1 100644 --- a/src/libutil/finally.hh +++ b/src/libutil/finally.hh @@ -20,7 +20,11 @@ public: // Copying Finallys is definitely not a good idea and will cause them to be // called twice. Finally(Finally &other) = delete; - Finally(Finally &&other) : fun(std::move(other.fun)) { + // NOTE: Move constructor can be nothrow if the callable type is itself nothrow + // move-constructible. + Finally(Finally && other) noexcept(std::is_nothrow_move_constructible_v) + : fun(std::move(other.fun)) + { other.movedFrom = true; } ~Finally() noexcept(false) diff --git a/src/libutil/pool.hh b/src/libutil/pool.hh index 6247b6125..b2ceb7143 100644 --- a/src/libutil/pool.hh +++ b/src/libutil/pool.hh @@ -109,7 +109,15 @@ public: Handle(Pool & pool, std::shared_ptr r) : pool(pool), r(r) { } public: - Handle(Handle && h) : pool(h.pool), r(h.r) { h.r.reset(); } + // NOTE: Copying std::shared_ptr and calling a .reset() on it is always noexcept. + Handle(Handle && h) noexcept + : pool(h.pool) + , r(h.r) + { + static_assert(noexcept(h.r.reset())); + static_assert(noexcept(std::shared_ptr(h.r))); + h.r.reset(); + } Handle(const Handle & l) = delete; From 0fe3b54ee180975f69b5c2fde658c4b7691384ac Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman <145775305+xokdvium@users.noreply.github.com> Date: Sat, 9 Nov 2024 22:35:18 +0300 Subject: [PATCH 420/718] refactor(treewide): reserve vector capacity when final size is known In these trivial cases the final vector size (or lower bound on the size) is known, so we can avoid some vector reallocations. This is not very important, but is just good practice and general hygiene. --- src/libcmd/installables.cc | 1 + src/libexpr/primops.cc | 1 + src/libstore/build/entry-points.cc | 1 + src/libstore/path-with-outputs.cc | 1 + src/libutil/executable-path.cc | 1 + src/nix/develop.cc | 1 + 6 files changed, 6 insertions(+) diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc index f9d6d8ce8..227bb64ed 100644 --- a/src/libcmd/installables.cc +++ b/src/libcmd/installables.cc @@ -857,6 +857,7 @@ std::vector RawInstallablesCommand::getFlakeRefsForCompletion() { applyDefaultInstallables(rawInstallables); std::vector res; + res.reserve(rawInstallables.size()); for (auto i : rawInstallables) res.push_back(parseFlakeRefWithFragment( fetchSettings, diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 84aa6bac9..45d9f86ac 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -91,6 +91,7 @@ StringMap EvalState::realiseContext(const NixStringContext & context, StorePathS /* Build/substitute the context. */ std::vector buildReqs; + buildReqs.reserve(drvs.size()); for (auto & d : drvs) buildReqs.emplace_back(DerivedPath { d }); buildStore->buildPaths(buildReqs, bmNormal, store); diff --git a/src/libstore/build/entry-points.cc b/src/libstore/build/entry-points.cc index 4c1373bfa..3bf22320e 100644 --- a/src/libstore/build/entry-points.cc +++ b/src/libstore/build/entry-points.cc @@ -66,6 +66,7 @@ std::vector Store::buildPathsWithResults( worker.run(goals); std::vector results; + results.reserve(state.size()); for (auto & [req, goalPtr] : state) results.emplace_back(KeyedBuildResult { diff --git a/src/libstore/path-with-outputs.cc b/src/libstore/path-with-outputs.cc index 161d023d1..e526b1ff6 100644 --- a/src/libstore/path-with-outputs.cc +++ b/src/libstore/path-with-outputs.cc @@ -37,6 +37,7 @@ DerivedPath StorePathWithOutputs::toDerivedPath() const std::vector toDerivedPaths(const std::vector ss) { std::vector reqs; + reqs.reserve(ss.size()); for (auto & s : ss) reqs.push_back(s.toDerivedPath()); return reqs; } diff --git a/src/libutil/executable-path.cc b/src/libutil/executable-path.cc index 9fb5214b2..e75e147b5 100644 --- a/src/libutil/executable-path.cc +++ b/src/libutil/executable-path.cc @@ -56,6 +56,7 @@ ExecutablePath ExecutablePath::parse(const OsString & path) OsString ExecutablePath::render() const { std::vector path2; + path2.reserve(directories.size()); for (auto & p : directories) path2.push_back(p.native()); return basicConcatStringsSep(path_var_separator, path2); diff --git a/src/nix/develop.cc b/src/nix/develop.cc index c7a733025..9a95bc695 100644 --- a/src/nix/develop.cc +++ b/src/nix/develop.cc @@ -610,6 +610,7 @@ struct CmdDevelop : Common, MixEnvironment else if (!command.empty()) { std::vector args; + args.reserve(command.size()); for (auto s : command) args.push_back(shellEscape(s)); script += fmt("exec %s\n", concatStringsSep(" ", args)); From a3613f2a3c33567d30baaed37051fd8f47102e63 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Sun, 10 Nov 2024 20:52:05 +0100 Subject: [PATCH 421/718] autoCallFunction: accept const Bindings & It does not need to mutate the attrs. `const` is shallow. Avoids a const_cast in the hercules-ci-cnix-expr bindings. --- src/libexpr/eval.cc | 2 +- src/libexpr/eval.hh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index e4937735b..876ba32fa 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -1730,7 +1730,7 @@ void EvalState::incrFunctionCall(ExprLambda * fun) } -void EvalState::autoCallFunction(Bindings & args, Value & fun, Value & res) +void EvalState::autoCallFunction(const Bindings & args, Value & fun, Value & res) { auto pos = fun.determinePos(noPos); diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index f7ed6be83..3171bf7fa 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -693,7 +693,7 @@ public: * Automatically call a function for which each argument has a * default value or has a binding in the `args` map. */ - void autoCallFunction(Bindings & args, Value & fun, Value & res); + void autoCallFunction(const Bindings & args, Value & fun, Value & res); /** * Allocation primitives. From e194e27f8574c193b1979cad8beef9ba5d7d584d Mon Sep 17 00:00:00 2001 From: WxNzEMof <143541718+WxNzEMof@users.noreply.github.com> Date: Thu, 25 Jan 2024 21:56:09 +0000 Subject: [PATCH 422/718] docker: Allow building for non-root user Add options uid, gid, uname, and gname to docker.nix. Setting these to e.g. 1000, 1000, "user", "user" will build an image which runs and allows using Nix as that user. --- docker.nix | 50 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/docker.nix b/docker.nix index bd16b71cd..19479e57c 100644 --- a/docker.nix +++ b/docker.nix @@ -9,6 +9,10 @@ , maxLayers ? 100 , nixConf ? {} , flake-registry ? null +, uid ? 0 +, gid ? 0 +, uname ? "root" +, gname ? "root" }: let defaultPkgs = with pkgs; [ @@ -50,6 +54,15 @@ let description = "Unprivileged account (don't use!)"; }; + } // lib.optionalAttrs (uid != 0) { + "${uname}" = { + uid = uid; + shell = "${pkgs.bashInteractive}/bin/bash"; + home = "/home/${uname}"; + gid = gid; + groups = [ "${gname}" ]; + description = "Nix user"; + }; } // lib.listToAttrs ( map ( @@ -70,6 +83,8 @@ let root.gid = 0; nixbld.gid = 30000; nobody.gid = 65534; + } // lib.optionalAttrs (gid != 0) { + "${gname}".gid = gid; }; userToPasswd = ( @@ -150,6 +165,8 @@ let in "${n} = ${vStr}") (defaultNixConf // nixConf))) + "\n"; + userHome = if uid == 0 then "/root" else "/home/${uname}"; + baseSystem = let nixpkgs = pkgs.path; @@ -237,26 +254,26 @@ let mkdir -p $out/etc/nix cat $nixConfContentsPath > $out/etc/nix/nix.conf - mkdir -p $out/root - mkdir -p $out/nix/var/nix/profiles/per-user/root + mkdir -p $out${userHome} + mkdir -p $out/nix/var/nix/profiles/per-user/${uname} ln -s ${profile} $out/nix/var/nix/profiles/default-1-link ln -s $out/nix/var/nix/profiles/default-1-link $out/nix/var/nix/profiles/default - ln -s /nix/var/nix/profiles/default $out/root/.nix-profile + ln -s /nix/var/nix/profiles/default $out${userHome}/.nix-profile - ln -s ${channel} $out/nix/var/nix/profiles/per-user/root/channels-1-link - ln -s $out/nix/var/nix/profiles/per-user/root/channels-1-link $out/nix/var/nix/profiles/per-user/root/channels + ln -s ${channel} $out/nix/var/nix/profiles/per-user/${uname}/channels-1-link + ln -s $out/nix/var/nix/profiles/per-user/${uname}/channels-1-link $out/nix/var/nix/profiles/per-user/${uname}/channels - mkdir -p $out/root/.nix-defexpr - ln -s $out/nix/var/nix/profiles/per-user/root/channels $out/root/.nix-defexpr/channels - echo "${channelURL} ${channelName}" > $out/root/.nix-channels + mkdir -p $out${userHome}/.nix-defexpr + ln -s $out/nix/var/nix/profiles/per-user/${uname}/channels $out${userHome}/.nix-defexpr/channels + echo "${channelURL} ${channelName}" > $out${userHome}/.nix-channels mkdir -p $out/bin $out/usr/bin ln -s ${pkgs.coreutils}/bin/env $out/usr/bin/env ln -s ${pkgs.bashInteractive}/bin/bash $out/bin/sh '' + (lib.optionalString (flake-registry-path != null) '' - nixCacheDir="/root/.cache/nix" + nixCacheDir="${userHome}/.cache/nix" mkdir -p $out$nixCacheDir globalFlakeRegistryPath="$nixCacheDir/flake-registry.json" ln -s ${flake-registry-path} $out$globalFlakeRegistryPath @@ -268,7 +285,7 @@ let in pkgs.dockerTools.buildLayeredImageWithNixDb { - inherit name tag maxLayers; + inherit name tag maxLayers uid gid uname gname; contents = [ baseSystem ]; @@ -279,25 +296,28 @@ pkgs.dockerTools.buildLayeredImageWithNixDb { fakeRootCommands = '' chmod 1777 tmp chmod 1777 var/tmp + chown -R ${toString uid}:${toString gid} .${userHome} + chown -R ${toString uid}:${toString gid} nix ''; config = { - Cmd = [ "/root/.nix-profile/bin/bash" ]; + Cmd = [ "${userHome}/.nix-profile/bin/bash" ]; + User = "${toString uid}:${toString gid}"; Env = [ - "USER=root" + "USER=${uname}" "PATH=${lib.concatStringsSep ":" [ - "/root/.nix-profile/bin" + "${userHome}/.nix-profile/bin" "/nix/var/nix/profiles/default/bin" "/nix/var/nix/profiles/default/sbin" ]}" "MANPATH=${lib.concatStringsSep ":" [ - "/root/.nix-profile/share/man" + "${userHome}/.nix-profile/share/man" "/nix/var/nix/profiles/default/share/man" ]}" "SSL_CERT_FILE=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt" "GIT_SSL_CAINFO=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt" "NIX_SSL_CERT_FILE=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt" - "NIX_PATH=/nix/var/nix/profiles/per-user/root/channels:/root/.nix-defexpr/channels" + "NIX_PATH=/nix/var/nix/profiles/per-user/${uname}/channels:${userHome}/.nix-defexpr/channels" ]; }; From 6f50e6a3faea91b0f05d01e72a89c4fcfbdbf660 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Sun, 10 Nov 2024 23:20:06 +0100 Subject: [PATCH 423/718] maintainers/onboarding: Subscribe to discourse category (#11848) Co-authored-by: Valentin Gagarin --- maintainers/onboarding.md | 1 + 1 file changed, 1 insertion(+) diff --git a/maintainers/onboarding.md b/maintainers/onboarding.md index e750bd8a7..d7491db16 100644 --- a/maintainers/onboarding.md +++ b/maintainers/onboarding.md @@ -4,3 +4,4 @@ - https://github.com/NixOS/nixos-homepage/ - https://github.com/orgs/NixOS/teams/nix-team - Matrix room +- Team member should subscribe to notifications for the [Nix development category on Discourse](https://discourse.nixos.org/c/dev/nix/50) From 036359ac84029ca24cca262b17e35d6b0b834e34 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 11 Nov 2024 13:58:12 +0100 Subject: [PATCH 424/718] Remove release note about flake substitution --- doc/manual/source/release-notes/rl-2.25.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/doc/manual/source/release-notes/rl-2.25.md b/doc/manual/source/release-notes/rl-2.25.md index 2b6706496..29e3e509c 100644 --- a/doc/manual/source/release-notes/rl-2.25.md +++ b/doc/manual/source/release-notes/rl-2.25.md @@ -70,12 +70,6 @@ Author: [**@zimbatm**](https://github.com/zimbatm) -- Flakes are no longer substituted [#10612](https://github.com/NixOS/nix/pull/10612) - - Nix will no longer attempt to substitute the source code of flakes from a binary cache. This functionality was broken because it could lead to different evaluation results depending on whether the flake was available in the binary cache, or even depending on whether the flake was already in the local store. - - Author: [**@edolstra**](https://github.com/edolstra) - - `` uses TLS verification [#11585](https://github.com/NixOS/nix/pull/11585) Previously `` did not do TLS verification. This was because the Nix sandbox in the past did not have access to TLS certificates, and Nix checks the hash of the fetched file anyway. However, this can expose authentication data from `netrc` and URLs to man-in-the-middle attackers. In addition, Nix now in some cases (such as when using impure derivations) does *not* check the hash. Therefore we have now enabled TLS verification. This means that downloads by `` will now fail if you're fetching from a HTTPS server that does not have a valid certificate. From f29e7867a90190469951fea1a1c020dcb33cb27c Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 11 Nov 2024 15:21:34 +0100 Subject: [PATCH 425/718] Revert "Merge pull request #11826 from DeterminateSystems/revert-11804" This reverts commit aeffdeffc89e51790b4686c79e0759a61c246f53, reversing changes made to 723fdeb4f1bd7fad7c3b00603067d23c314b25c5. --- .gitignore | 3 - Makefile | 129 --- Makefile.config.in | 54 - config/install-sh | 527 ---------- configure.ac | 456 --------- doc/manual/local.mk | 236 ----- flake.nix | 11 +- local.mk | 15 - m4/ax_cxx_compile_stdcxx.m4 | 951 ------------------ m4/ax_cxx_compile_stdcxx_17.m4 | 35 - maintainers/local.mk | 8 - misc/bash/local.mk | 1 - misc/fish/local.mk | 1 - misc/launchd/local.mk | 5 - misc/systemd/local.mk | 8 - misc/upstart/local.mk | 7 - misc/zsh/local.mk | 2 - mk/build-dir.mk | 10 - mk/clean.mk | 11 - mk/common-test.sh | 31 - mk/compilation-database.mk | 11 - mk/cxx-big-literal.mk | 5 - mk/debug-test.sh | 10 - mk/functions.mk | 14 - mk/install-dirs.mk | 11 - mk/install.mk | 62 -- mk/lib.mk | 159 --- mk/libraries.mk | 173 ---- mk/patterns.mk | 41 - mk/platform.mk | 40 - mk/precompiled-headers.mk | 21 - mk/programs.mk | 98 -- mk/run-test.sh | 38 - mk/templates.mk | 19 - mk/tests.mk | 30 - mk/tracing.mk | 18 - package.nix | 366 ------- packaging/components.nix | 8 +- packaging/dev-shell.nix | 7 +- packaging/hydra.nix | 15 +- scripts/local.mk | 13 - src/libcmd/local.mk | 15 - src/libcmd/nix-cmd.pc.in | 9 - src/libexpr-c/local.mk | 25 - src/libexpr-c/nix-expr-c.pc.in | 10 - src/libexpr-test-support/local.mk | 23 - src/libexpr-tests/local.mk | 45 - src/libexpr/local.mk | 50 - src/libexpr/nix-expr.pc.in | 10 - src/libexpr/package.nix | 4 + src/libfetchers-tests/local.mk | 37 - src/libfetchers/local.mk | 17 - src/libflake-tests/local.mk | 43 - src/libflake/flake/nix-flake.pc.in | 10 - src/libflake/local.mk | 22 - src/libmain/local.mk | 22 - src/libmain/nix-main.pc.in | 9 - src/libstore-c/local.mk | 21 - src/libstore-c/nix-store-c.pc.in | 9 - src/libstore-test-support/local.mk | 21 - src/libstore-tests/local.mk | 38 - src/libstore/local.mk | 103 -- src/libstore/nix-store.pc.in | 10 - src/libutil-c/local.mk | 18 - src/libutil-c/nix-util-c.pc.in | 9 - src/libutil-test-support/local.mk | 19 - src/libutil-tests/local.mk | 37 - src/libutil/local.mk | 44 - src/libutil/nix-util.pc.in | 9 - src/nix/local.mk | 59 -- src/perl/package.nix | 4 + tests/functional/build-hook-ca-fixed.nix | 2 +- tests/functional/build-hook.nix | 2 +- tests/functional/ca/config.nix | 2 + tests/functional/ca/content-addressed.nix | 2 +- tests/functional/ca/local.mk | 29 - tests/functional/ca/nix-run.sh | 3 - tests/functional/ca/nondeterministic.nix | 2 +- tests/functional/ca/racy.nix | 2 +- tests/functional/check-refs.nix | 2 +- tests/functional/check-reqs.nix | 2 +- tests/functional/check.nix | 2 +- tests/functional/chroot-store.sh | 3 - tests/functional/common/functions.sh | 9 - tests/functional/config.nix | 2 + tests/functional/dependencies.nix | 2 +- tests/functional/dyn-drv/config.nix | 2 + tests/functional/dyn-drv/local.mk | 15 - .../dyn-drv/old-daemon-error-hack.nix | 2 +- .../functional/dyn-drv/recursive-mod-json.nix | 2 +- .../functional/dyn-drv/text-hashed-output.nix | 2 +- tests/functional/export-graph.nix | 2 +- tests/functional/extra-sandbox-profile.nix | 2 +- tests/functional/failing.nix | 2 +- tests/functional/filter-source.nix | 2 +- tests/functional/fixed.nix | 2 +- tests/functional/flakes/bundle.sh | 3 - tests/functional/flakes/common.sh | 3 - tests/functional/flakes/config.sh | 1 - tests/functional/flakes/develop.sh | 3 - tests/functional/flakes/local.mk | 25 - tests/functional/flakes/run.sh | 2 - tests/functional/fod-failing.nix | 2 +- tests/functional/gc-concurrent.nix | 2 +- tests/functional/gc-runtime.nix | 2 +- tests/functional/git-hashing/local.mk | 7 - tests/functional/hermetic.nix | 2 +- tests/functional/ifd.nix | 2 +- tests/functional/import-from-derivation.nix | 2 +- tests/functional/impure-derivations.nix | 2 +- tests/functional/impure-env.nix | 2 +- tests/functional/linux-sandbox-cert-test.nix | 2 +- tests/functional/local-overlay-store/local.mk | 14 - tests/functional/local.mk | 146 --- tests/functional/multiple-outputs.nix | 2 +- tests/functional/nar-access.nix | 2 +- tests/functional/nix-build-examples.nix | 2 +- tests/functional/parallel.nix | 2 +- tests/functional/path.nix | 2 +- tests/functional/plugins/local.mk | 11 - tests/functional/readfile-context.nix | 2 +- tests/functional/restricted.sh | 4 - tests/functional/search.nix | 2 +- tests/functional/secure-drv-outputs.nix | 2 +- tests/functional/shell-hello.nix | 2 +- tests/functional/shell.nix | 2 +- tests/functional/simple-failing.nix | 2 +- tests/functional/simple.nix | 2 +- tests/functional/structured-attrs-shell.nix | 2 +- tests/functional/structured-attrs.nix | 2 +- tests/functional/symlink-derivation.nix | 2 +- .../functional/test-libstoreconsumer/local.mk | 15 - tests/functional/timeout.nix | 2 +- tests/functional/user-envs.nix | 2 +- 134 files changed, 75 insertions(+), 4722 deletions(-) delete mode 100644 Makefile delete mode 100644 Makefile.config.in delete mode 100755 config/install-sh delete mode 100644 configure.ac delete mode 100644 doc/manual/local.mk delete mode 100644 local.mk delete mode 100644 m4/ax_cxx_compile_stdcxx.m4 delete mode 100644 m4/ax_cxx_compile_stdcxx_17.m4 delete mode 100644 maintainers/local.mk delete mode 100644 misc/bash/local.mk delete mode 100644 misc/fish/local.mk delete mode 100644 misc/launchd/local.mk delete mode 100644 misc/systemd/local.mk delete mode 100644 misc/upstart/local.mk delete mode 100644 misc/zsh/local.mk delete mode 100644 mk/build-dir.mk delete mode 100644 mk/clean.mk delete mode 100644 mk/common-test.sh delete mode 100644 mk/compilation-database.mk delete mode 100644 mk/cxx-big-literal.mk delete mode 100755 mk/debug-test.sh delete mode 100644 mk/functions.mk delete mode 100644 mk/install-dirs.mk delete mode 100644 mk/install.mk delete mode 100644 mk/lib.mk delete mode 100644 mk/libraries.mk delete mode 100644 mk/patterns.mk delete mode 100644 mk/platform.mk delete mode 100644 mk/precompiled-headers.mk delete mode 100644 mk/programs.mk delete mode 100755 mk/run-test.sh delete mode 100644 mk/templates.mk delete mode 100644 mk/tests.mk delete mode 100644 mk/tracing.mk delete mode 100644 package.nix delete mode 100644 scripts/local.mk delete mode 100644 src/libcmd/local.mk delete mode 100644 src/libcmd/nix-cmd.pc.in delete mode 100644 src/libexpr-c/local.mk delete mode 100644 src/libexpr-c/nix-expr-c.pc.in delete mode 100644 src/libexpr-test-support/local.mk delete mode 100644 src/libexpr-tests/local.mk delete mode 100644 src/libexpr/local.mk delete mode 100644 src/libexpr/nix-expr.pc.in delete mode 100644 src/libfetchers-tests/local.mk delete mode 100644 src/libfetchers/local.mk delete mode 100644 src/libflake-tests/local.mk delete mode 100644 src/libflake/flake/nix-flake.pc.in delete mode 100644 src/libflake/local.mk delete mode 100644 src/libmain/local.mk delete mode 100644 src/libmain/nix-main.pc.in delete mode 100644 src/libstore-c/local.mk delete mode 100644 src/libstore-c/nix-store-c.pc.in delete mode 100644 src/libstore-test-support/local.mk delete mode 100644 src/libstore-tests/local.mk delete mode 100644 src/libstore/local.mk delete mode 100644 src/libstore/nix-store.pc.in delete mode 100644 src/libutil-c/local.mk delete mode 100644 src/libutil-c/nix-util-c.pc.in delete mode 100644 src/libutil-test-support/local.mk delete mode 100644 src/libutil-tests/local.mk delete mode 100644 src/libutil/local.mk delete mode 100644 src/libutil/nix-util.pc.in delete mode 100644 src/nix/local.mk create mode 100644 tests/functional/ca/config.nix delete mode 100644 tests/functional/ca/local.mk create mode 100644 tests/functional/config.nix create mode 100644 tests/functional/dyn-drv/config.nix delete mode 100644 tests/functional/dyn-drv/local.mk delete mode 100644 tests/functional/flakes/local.mk delete mode 100644 tests/functional/git-hashing/local.mk delete mode 100644 tests/functional/local-overlay-store/local.mk delete mode 100644 tests/functional/local.mk delete mode 100644 tests/functional/plugins/local.mk delete mode 100644 tests/functional/test-libstoreconsumer/local.mk diff --git a/.gitignore b/.gitignore index 11a80ab5b..de1183977 100644 --- a/.gitignore +++ b/.gitignore @@ -102,9 +102,6 @@ perl/Makefile.config /tests/functional/restricted-innocent /tests/functional/shell /tests/functional/shell.drv -/tests/functional/config.nix -/tests/functional/ca/config.nix -/tests/functional/dyn-drv/config.nix /tests/functional/repl-result-out /tests/functional/debugger-test-out /tests/functional/test-libstoreconsumer/test-libstoreconsumer diff --git a/Makefile b/Makefile deleted file mode 100644 index ee1a0de31..000000000 --- a/Makefile +++ /dev/null @@ -1,129 +0,0 @@ -# External build directory support - -include mk/build-dir.mk - --include $(buildprefix)Makefile.config -clean-files += $(buildprefix)Makefile.config - -# List makefiles - -include mk/platform.mk - -ifeq ($(ENABLE_BUILD), yes) -makefiles = \ - mk/precompiled-headers.mk \ - local.mk \ - src/libutil/local.mk \ - src/libstore/local.mk \ - src/libfetchers/local.mk \ - src/libmain/local.mk \ - src/libexpr/local.mk \ - src/libflake/local.mk \ - src/libcmd/local.mk \ - src/nix/local.mk \ - src/libutil-c/local.mk \ - src/libstore-c/local.mk \ - src/libexpr-c/local.mk - -ifdef HOST_UNIX -makefiles += \ - scripts/local.mk \ - maintainers/local.mk \ - misc/bash/local.mk \ - misc/fish/local.mk \ - misc/zsh/local.mk \ - misc/systemd/local.mk \ - misc/launchd/local.mk \ - misc/upstart/local.mk -endif -endif - -ifeq ($(ENABLE_UNIT_TESTS), yes) -makefiles += \ - src/libutil-tests/local.mk \ - src/libutil-test-support/local.mk \ - src/libstore-tests/local.mk \ - src/libstore-test-support/local.mk \ - src/libfetchers-tests/local.mk \ - src/libexpr-tests/local.mk \ - src/libexpr-test-support/local.mk \ - src/libflake-tests/local.mk -endif - -ifeq ($(ENABLE_FUNCTIONAL_TESTS), yes) -ifdef HOST_UNIX -makefiles += \ - tests/functional/local.mk \ - tests/functional/flakes/local.mk \ - tests/functional/ca/local.mk \ - tests/functional/git-hashing/local.mk \ - tests/functional/dyn-drv/local.mk \ - tests/functional/local-overlay-store/local.mk \ - tests/functional/test-libstoreconsumer/local.mk \ - tests/functional/plugins/local.mk -endif -endif - -# Some makefiles require access to built programs and must be included late. -makefiles-late = - -ifeq ($(ENABLE_DOC_GEN), yes) -makefiles-late += doc/manual/local.mk -endif - -# Miscellaneous global Flags - -OPTIMIZE = 1 - -ifeq ($(OPTIMIZE), 1) - GLOBAL_CXXFLAGS += -O3 $(CXXLTO) - GLOBAL_LDFLAGS += $(CXXLTO) -else - GLOBAL_CXXFLAGS += -O0 -U_FORTIFY_SOURCE - unexport NIX_HARDENING_ENABLE -endif - -ifdef HOST_WINDOWS - # Windows DLLs are stricter about symbol visibility than Unix shared - # objects --- see https://gcc.gnu.org/wiki/Visibility for details. - # This is a temporary sledgehammer to export everything like on Unix, - # and not detail with this yet. - # - # TODO do not do this, and instead do fine-grained export annotations. - GLOBAL_LDFLAGS += -Wl,--export-all-symbols - GLOBAL_CXXFLAGS += -D_WIN32_WINNT=0x0602 -endif - -GLOBAL_CXXFLAGS += -g -Wall -Wdeprecated-copy -Wignored-qualifiers -Wimplicit-fallthrough -Werror=unused-result -Werror=suggest-override -include $(buildprefix)config.h -std=c++2a -I src - -# Include the main lib, causing rules to be defined - -include mk/lib.mk - -# Fallback stub rules for better UX when things are disabled -# -# These must be defined after `mk/lib.mk`. Otherwise the first rule -# incorrectly becomes the default target. - -ifneq ($(ENABLE_UNIT_TESTS), yes) -.PHONY: check -check: - @echo "Unit tests are disabled. Configure without '--disable-unit-tests', or avoid calling 'make check'." - @exit 1 -endif - -ifneq ($(ENABLE_FUNCTIONAL_TESTS), yes) -.PHONY: installcheck -installcheck: - @echo "Functional tests are disabled. Configure without '--disable-functional-tests', or avoid calling 'make installcheck'." - @exit 1 -endif - -# Documentation fallback stub rules. - -ifneq ($(ENABLE_DOC_GEN), yes) -.PHONY: manual-html manpages -manual-html manpages: - @echo "Generated docs are disabled. Configure without '--disable-doc-gen', or avoid calling 'make manpages' and 'make manual-html'." - @exit 1 -endif diff --git a/Makefile.config.in b/Makefile.config.in deleted file mode 100644 index 3100d2073..000000000 --- a/Makefile.config.in +++ /dev/null @@ -1,54 +0,0 @@ -AR = @AR@ -BDW_GC_LIBS = @BDW_GC_LIBS@ -BOOST_LDFLAGS = @BOOST_LDFLAGS@ -BUILD_SHARED_LIBS = @BUILD_SHARED_LIBS@ -CC = @CC@ -CFLAGS = @CFLAGS@ -CXX = @CXX@ -CXXFLAGS = @CXXFLAGS@ -CXXLTO = @CXXLTO@ -EDITLINE_LIBS = @EDITLINE_LIBS@ -ENABLE_BUILD = @ENABLE_BUILD@ -ENABLE_DOC_GEN = @ENABLE_DOC_GEN@ -ENABLE_FUNCTIONAL_TESTS = @ENABLE_FUNCTIONAL_TESTS@ -ENABLE_S3 = @ENABLE_S3@ -ENABLE_UNIT_TESTS = @ENABLE_UNIT_TESTS@ -GTEST_LIBS = @GTEST_LIBS@ -HAVE_LIBCPUID = @HAVE_LIBCPUID@ -HAVE_SECCOMP = @HAVE_SECCOMP@ -HOST_OS = @host_os@ -INSTALL_UNIT_TESTS = @INSTALL_UNIT_TESTS@ -LDFLAGS = @LDFLAGS@ -LIBARCHIVE_LIBS = @LIBARCHIVE_LIBS@ -LIBBROTLI_LIBS = @LIBBROTLI_LIBS@ -LIBCURL_LIBS = @LIBCURL_LIBS@ -LIBGIT2_LIBS = @LIBGIT2_LIBS@ -LIBSECCOMP_LIBS = @LIBSECCOMP_LIBS@ -LOWDOWN_LIBS = @LOWDOWN_LIBS@ -OPENSSL_LIBS = @OPENSSL_LIBS@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -SHELL = @bash@ -SODIUM_LIBS = @SODIUM_LIBS@ -SQLITE3_LIBS = @SQLITE3_LIBS@ -bash = @bash@ -bindir = @bindir@ -checkbindir = @checkbindir@ -checklibdir = @checklibdir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -embedded_sandbox_shell = @embedded_sandbox_shell@ -exec_prefix = @exec_prefix@ -includedir = @includedir@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localstatedir = @localstatedir@ -lsof = @lsof@ -mandir = @mandir@ -pkglibdir = $(libdir)/$(PACKAGE_NAME) -prefix = @prefix@ -sandbox_shell = @sandbox_shell@ -storedir = @storedir@ -sysconfdir = @sysconfdir@ -system = @system@ diff --git a/config/install-sh b/config/install-sh deleted file mode 100755 index 377bb8687..000000000 --- a/config/install-sh +++ /dev/null @@ -1,527 +0,0 @@ -#!/bin/sh -# install - install a program, script, or datafile - -scriptversion=2011-11-20.07; # UTC - -# This originates from X11R5 (mit/util/scripts/install.sh), which was -# later released in X11R6 (xc/config/util/install.sh) with the -# following copyright and license. -# -# Copyright (C) 1994 X Consortium -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- -# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -# Except as contained in this notice, the name of the X Consortium shall not -# be used in advertising or otherwise to promote the sale, use or other deal- -# ings in this Software without prior written authorization from the X Consor- -# tium. -# -# -# FSF changes to this file are in the public domain. -# -# Calling this script install-sh is preferred over install.sh, to prevent -# 'make' implicit rules from creating a file called install from it -# when there is no Makefile. -# -# This script is compatible with the BSD install script, but was written -# from scratch. - -nl=' -' -IFS=" "" $nl" - -# set DOITPROG to echo to test this script - -# Don't use :- since 4.3BSD and earlier shells don't like it. -doit=${DOITPROG-} -if test -z "$doit"; then - doit_exec=exec -else - doit_exec=$doit -fi - -# Put in absolute file names if you don't have them in your path; -# or use environment vars. - -chgrpprog=${CHGRPPROG-chgrp} -chmodprog=${CHMODPROG-chmod} -chownprog=${CHOWNPROG-chown} -cmpprog=${CMPPROG-cmp} -cpprog=${CPPROG-cp} -mkdirprog=${MKDIRPROG-mkdir} -mvprog=${MVPROG-mv} -rmprog=${RMPROG-rm} -stripprog=${STRIPPROG-strip} - -posix_glob='?' -initialize_posix_glob=' - test "$posix_glob" != "?" || { - if (set -f) 2>/dev/null; then - posix_glob= - else - posix_glob=: - fi - } -' - -posix_mkdir= - -# Desired mode of installed file. -mode=0755 - -chgrpcmd= -chmodcmd=$chmodprog -chowncmd= -mvcmd=$mvprog -rmcmd="$rmprog -f" -stripcmd= - -src= -dst= -dir_arg= -dst_arg= - -copy_on_change=false -no_target_directory= - -usage="\ -Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE - or: $0 [OPTION]... SRCFILES... DIRECTORY - or: $0 [OPTION]... -t DIRECTORY SRCFILES... - or: $0 [OPTION]... -d DIRECTORIES... - -In the 1st form, copy SRCFILE to DSTFILE. -In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. -In the 4th, create DIRECTORIES. - -Options: - --help display this help and exit. - --version display version info and exit. - - -c (ignored) - -C install only if different (preserve the last data modification time) - -d create directories instead of installing files. - -g GROUP $chgrpprog installed files to GROUP. - -m MODE $chmodprog installed files to MODE. - -o USER $chownprog installed files to USER. - -s $stripprog installed files. - -t DIRECTORY install into DIRECTORY. - -T report an error if DSTFILE is a directory. - -Environment variables override the default commands: - CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG - RMPROG STRIPPROG -" - -while test $# -ne 0; do - case $1 in - -c) ;; - - -C) copy_on_change=true;; - - -d) dir_arg=true;; - - -g) chgrpcmd="$chgrpprog $2" - shift;; - - --help) echo "$usage"; exit $?;; - - -m) mode=$2 - case $mode in - *' '* | *' '* | *' -'* | *'*'* | *'?'* | *'['*) - echo "$0: invalid mode: $mode" >&2 - exit 1;; - esac - shift;; - - -o) chowncmd="$chownprog $2" - shift;; - - -s) stripcmd=$stripprog;; - - -t) dst_arg=$2 - # Protect names problematic for 'test' and other utilities. - case $dst_arg in - -* | [=\(\)!]) dst_arg=./$dst_arg;; - esac - shift;; - - -T) no_target_directory=true;; - - --version) echo "$0 $scriptversion"; exit $?;; - - --) shift - break;; - - -*) echo "$0: invalid option: $1" >&2 - exit 1;; - - *) break;; - esac - shift -done - -if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then - # When -d is used, all remaining arguments are directories to create. - # When -t is used, the destination is already specified. - # Otherwise, the last argument is the destination. Remove it from $@. - for arg - do - if test -n "$dst_arg"; then - # $@ is not empty: it contains at least $arg. - set fnord "$@" "$dst_arg" - shift # fnord - fi - shift # arg - dst_arg=$arg - # Protect names problematic for 'test' and other utilities. - case $dst_arg in - -* | [=\(\)!]) dst_arg=./$dst_arg;; - esac - done -fi - -if test $# -eq 0; then - if test -z "$dir_arg"; then - echo "$0: no input file specified." >&2 - exit 1 - fi - # It's OK to call 'install-sh -d' without argument. - # This can happen when creating conditional directories. - exit 0 -fi - -if test -z "$dir_arg"; then - do_exit='(exit $ret); exit $ret' - trap "ret=129; $do_exit" 1 - trap "ret=130; $do_exit" 2 - trap "ret=141; $do_exit" 13 - trap "ret=143; $do_exit" 15 - - # Set umask so as not to create temps with too-generous modes. - # However, 'strip' requires both read and write access to temps. - case $mode in - # Optimize common cases. - *644) cp_umask=133;; - *755) cp_umask=22;; - - *[0-7]) - if test -z "$stripcmd"; then - u_plus_rw= - else - u_plus_rw='% 200' - fi - cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; - *) - if test -z "$stripcmd"; then - u_plus_rw= - else - u_plus_rw=,u+rw - fi - cp_umask=$mode$u_plus_rw;; - esac -fi - -for src -do - # Protect names problematic for 'test' and other utilities. - case $src in - -* | [=\(\)!]) src=./$src;; - esac - - if test -n "$dir_arg"; then - dst=$src - dstdir=$dst - test -d "$dstdir" - dstdir_status=$? - else - - # Waiting for this to be detected by the "$cpprog $src $dsttmp" command - # might cause directories to be created, which would be especially bad - # if $src (and thus $dsttmp) contains '*'. - if test ! -f "$src" && test ! -d "$src"; then - echo "$0: $src does not exist." >&2 - exit 1 - fi - - if test -z "$dst_arg"; then - echo "$0: no destination specified." >&2 - exit 1 - fi - dst=$dst_arg - - # If destination is a directory, append the input filename; won't work - # if double slashes aren't ignored. - if test -d "$dst"; then - if test -n "$no_target_directory"; then - echo "$0: $dst_arg: Is a directory" >&2 - exit 1 - fi - dstdir=$dst - dst=$dstdir/`basename "$src"` - dstdir_status=0 - else - # Prefer dirname, but fall back on a substitute if dirname fails. - dstdir=` - (dirname "$dst") 2>/dev/null || - expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$dst" : 'X\(//\)[^/]' \| \ - X"$dst" : 'X\(//\)$' \| \ - X"$dst" : 'X\(/\)' \| . 2>/dev/null || - echo X"$dst" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q' - ` - - test -d "$dstdir" - dstdir_status=$? - fi - fi - - obsolete_mkdir_used=false - - if test $dstdir_status != 0; then - case $posix_mkdir in - '') - # Create intermediate dirs using mode 755 as modified by the umask. - # This is like FreeBSD 'install' as of 1997-10-28. - umask=`umask` - case $stripcmd.$umask in - # Optimize common cases. - *[2367][2367]) mkdir_umask=$umask;; - .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; - - *[0-7]) - mkdir_umask=`expr $umask + 22 \ - - $umask % 100 % 40 + $umask % 20 \ - - $umask % 10 % 4 + $umask % 2 - `;; - *) mkdir_umask=$umask,go-w;; - esac - - # With -d, create the new directory with the user-specified mode. - # Otherwise, rely on $mkdir_umask. - if test -n "$dir_arg"; then - mkdir_mode=-m$mode - else - mkdir_mode= - fi - - posix_mkdir=false - case $umask in - *[123567][0-7][0-7]) - # POSIX mkdir -p sets u+wx bits regardless of umask, which - # is incompatible with FreeBSD 'install' when (umask & 300) != 0. - ;; - *) - tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ - trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 - - if (umask $mkdir_umask && - exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 - then - if test -z "$dir_arg" || { - # Check for POSIX incompatibilities with -m. - # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or - # other-writable bit of parent directory when it shouldn't. - # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. - ls_ld_tmpdir=`ls -ld "$tmpdir"` - case $ls_ld_tmpdir in - d????-?r-*) different_mode=700;; - d????-?--*) different_mode=755;; - *) false;; - esac && - $mkdirprog -m$different_mode -p -- "$tmpdir" && { - ls_ld_tmpdir_1=`ls -ld "$tmpdir"` - test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" - } - } - then posix_mkdir=: - fi - rmdir "$tmpdir/d" "$tmpdir" - else - # Remove any dirs left behind by ancient mkdir implementations. - rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null - fi - trap '' 0;; - esac;; - esac - - if - $posix_mkdir && ( - umask $mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" - ) - then : - else - - # The umask is ridiculous, or mkdir does not conform to POSIX, - # or it failed possibly due to a race condition. Create the - # directory the slow way, step by step, checking for races as we go. - - case $dstdir in - /*) prefix='/';; - [-=\(\)!]*) prefix='./';; - *) prefix='';; - esac - - eval "$initialize_posix_glob" - - oIFS=$IFS - IFS=/ - $posix_glob set -f - set fnord $dstdir - shift - $posix_glob set +f - IFS=$oIFS - - prefixes= - - for d - do - test X"$d" = X && continue - - prefix=$prefix$d - if test -d "$prefix"; then - prefixes= - else - if $posix_mkdir; then - (umask=$mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break - # Don't fail if two instances are running concurrently. - test -d "$prefix" || exit 1 - else - case $prefix in - *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; - *) qprefix=$prefix;; - esac - prefixes="$prefixes '$qprefix'" - fi - fi - prefix=$prefix/ - done - - if test -n "$prefixes"; then - # Don't fail if two instances are running concurrently. - (umask $mkdir_umask && - eval "\$doit_exec \$mkdirprog $prefixes") || - test -d "$dstdir" || exit 1 - obsolete_mkdir_used=true - fi - fi - fi - - if test -n "$dir_arg"; then - { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && - { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && - { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || - test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 - else - - # Make a couple of temp file names in the proper directory. - dsttmp=$dstdir/_inst.$$_ - rmtmp=$dstdir/_rm.$$_ - - # Trap to clean up those temp files at exit. - trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 - - # Copy the file name to the temp name. - (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && - - # and set any options; do chmod last to preserve setuid bits. - # - # If any of these fail, we abort the whole thing. If we want to - # ignore errors from any of these, just make sure not to ignore - # errors from the above "$doit $cpprog $src $dsttmp" command. - # - { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && - { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && - { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && - { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && - - # If -C, don't bother to copy if it wouldn't change the file. - if $copy_on_change && - old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && - new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && - - eval "$initialize_posix_glob" && - $posix_glob set -f && - set X $old && old=:$2:$4:$5:$6 && - set X $new && new=:$2:$4:$5:$6 && - $posix_glob set +f && - - test "$old" = "$new" && - $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 - then - rm -f "$dsttmp" - else - # Rename the file to the real destination. - $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || - - # The rename failed, perhaps because mv can't rename something else - # to itself, or perhaps because mv is so ancient that it does not - # support -f. - { - # Now remove or move aside any old file at destination location. - # We try this two ways since rm can't unlink itself on some - # systems and the destination file might be busy for other - # reasons. In this case, the final cleanup might fail but the new - # file should still install successfully. - { - test ! -f "$dst" || - $doit $rmcmd -f "$dst" 2>/dev/null || - { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && - { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } - } || - { echo "$0: cannot unlink or rename $dst" >&2 - (exit 1); exit 1 - } - } && - - # Now rename the file to the real destination. - $doit $mvcmd "$dsttmp" "$dst" - } - fi || exit 1 - - trap '' 0 - fi -done - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" -# time-stamp-end: "; # UTC" -# End: diff --git a/configure.ac b/configure.ac deleted file mode 100644 index 4df5c80f0..000000000 --- a/configure.ac +++ /dev/null @@ -1,456 +0,0 @@ -AC_INIT([nix],[m4_esyscmd(bash -c "echo -n $(cat ./.version)$VERSION_SUFFIX")]) -AC_CONFIG_MACRO_DIRS([m4]) -AC_CONFIG_SRCDIR(README.md) -AC_CONFIG_AUX_DIR(config) - -AC_PROG_SED - -# Construct a Nix system name (like "i686-linux"): -# https://www.gnu.org/software/autoconf/manual/html_node/Canonicalizing.html#index-AC_005fCANONICAL_005fHOST-1 -# The inital value is produced by the `config/config.guess` script: -# upstream: https://git.savannah.gnu.org/cgit/config.git/tree/config.guess -# It has the following form, which is not documented anywhere: -# --[][-] -# If `./configure` is passed any of the `--host`, `--build`, `--target` options, the value comes from `config/config.sub` instead: -# upstream: https://git.savannah.gnu.org/cgit/config.git/tree/config.sub -AC_CANONICAL_HOST -AC_MSG_CHECKING([for the canonical Nix system name]) - -AC_ARG_WITH(system, AS_HELP_STRING([--with-system=SYSTEM],[Platform identifier (e.g., `i686-linux').]), - [system=$withval], - [case "$host_cpu" in - i*86) - machine_name="i686";; - amd64) - machine_name="x86_64";; - armv6|armv7) - machine_name="${host_cpu}l";; - *) - machine_name="$host_cpu";; - esac - - case "$host_os" in - linux-gnu*|linux-musl*) - # For backward compatibility, strip the `-gnu' part. - system="$machine_name-linux";; - *) - # Strip the version number from names such as `gnu0.3', - # `darwin10.2.0', etc. - system="$machine_name-`echo $host_os | "$SED" -e's/@<:@0-9.@:>@*$//g'`";; - esac]) - -AC_MSG_RESULT($system) -AC_SUBST(system) -AC_DEFINE_UNQUOTED(SYSTEM, ["$system"], [platform identifier ('cpu-os')]) - - -# State should be stored in /nix/var, unless the user overrides it explicitly. -test "$localstatedir" = '${prefix}/var' && localstatedir=/nix/var - -# Assign a default value to C{,XX}FLAGS as the default configure script sets them -# to -O2 otherwise, which we don't want to have hardcoded -CFLAGS=${CFLAGS-""} -CXXFLAGS=${CXXFLAGS-""} - -AC_PROG_CC -AC_PROG_CXX -AC_PROG_CPP - -AC_CHECK_TOOL([AR], [ar]) - -# Use 64-bit file system calls so that we can support files > 2 GiB. -AC_SYS_LARGEFILE - - -# OS-specific stuff. -case "$host_os" in - solaris*) - # Solaris requires -lsocket -lnsl for network functions - LDFLAGS="-lsocket -lnsl $LDFLAGS" - ;; - darwin*) - # Need to link to libsandbox. - LDFLAGS="-lsandbox $LDFLAGS" - ;; -esac - - -ENSURE_NO_GCC_BUG_80431 - - -# Check for pubsetbuf. -AC_MSG_CHECKING([for pubsetbuf]) -AC_LANG_PUSH(C++) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include -using namespace std; -static char buf[1024];]], - [[cerr.rdbuf()->pubsetbuf(buf, sizeof(buf));]])], - [AC_MSG_RESULT(yes) AC_DEFINE(HAVE_PUBSETBUF, 1, [Whether pubsetbuf is available.])], - AC_MSG_RESULT(no)) -AC_LANG_POP(C++) - - -AC_CHECK_FUNCS([statvfs pipe2 close_range]) - - -# Check for lutimes and utimensat, optionally used for changing the -# mtime of symlinks. -AC_CHECK_DECLS([AT_SYMLINK_NOFOLLOW], [], [], [[#include ]]) -AC_CHECK_FUNCS([lutimes utimensat]) - - -# Check whether the store optimiser can optimise symlinks. -AC_MSG_CHECKING([whether it is possible to create a link to a symlink]) -ln -s bla tmp_link -if ln tmp_link tmp_link2 2> /dev/null; then - AC_MSG_RESULT(yes) - AC_DEFINE(CAN_LINK_SYMLINK, 1, [Whether link() works on symlinks.]) -else - AC_MSG_RESULT(no) -fi -rm -f tmp_link tmp_link2 - - -# Check for . -AC_LANG_PUSH(C++) -AC_CHECK_HEADERS([locale]) -AC_LANG_POP(C++) - - -AC_DEFUN([NEED_PROG], -[ -AC_PATH_PROG($1, $2) -if test -z "$$1"; then - AC_MSG_ERROR([$2 is required]) -fi -]) - -NEED_PROG(bash, bash) -AC_PATH_PROG(flex, flex, false) -AC_PATH_PROG(bison, bison, false) -AC_PATH_PROG(dot, dot) -AC_PATH_PROG(lsof, lsof, lsof) - - -AC_SUBST(coreutils, [$(dirname $(type -p cat))]) - - -AC_ARG_WITH(store-dir, AS_HELP_STRING([--with-store-dir=PATH],[path of the Nix store (defaults to /nix/store)]), - storedir=$withval, storedir='/nix/store') -AC_SUBST(storedir) - - -# Running the functional tests without building Nix is useful for testing -# different pre-built versions of Nix against each other. -AC_ARG_ENABLE(build, AS_HELP_STRING([--disable-build],[Do not build nix]), - ENABLE_BUILD=$enableval, ENABLE_BUILD=yes) -AC_SUBST(ENABLE_BUILD) - -# Building without unit tests is useful for bootstrapping with a smaller footprint -# or running the tests in a separate derivation. Otherwise, we do compile and -# run them. - -AC_ARG_ENABLE(unit-tests, AS_HELP_STRING([--disable-unit-tests],[Do not build the tests]), - ENABLE_UNIT_TESTS=$enableval, ENABLE_UNIT_TESTS=$ENABLE_BUILD) -AC_SUBST(ENABLE_UNIT_TESTS) - -AS_IF( - [test "$ENABLE_BUILD" == "no" && test "$ENABLE_UNIT_TESTS" == "yes"], - [AC_MSG_ERROR([Cannot enable unit tests when building overall is disabled. Please do not pass '--enable-unit-tests' or do not pass '--disable-build'.])]) - -AC_ARG_ENABLE(functional-tests, AS_HELP_STRING([--disable-functional-tests],[Do not build the tests]), - ENABLE_FUNCTIONAL_TESTS=$enableval, ENABLE_FUNCTIONAL_TESTS=yes) -AC_SUBST(ENABLE_FUNCTIONAL_TESTS) - -# documentation generation switch -AC_ARG_ENABLE(doc-gen, AS_HELP_STRING([--disable-doc-gen],[disable documentation generation]), - ENABLE_DOC_GEN=$enableval, ENABLE_DOC_GEN=$ENABLE_BUILD) -AC_SUBST(ENABLE_DOC_GEN) - -AS_IF( - [test "$ENABLE_BUILD" == "no" && test "$ENABLE_DOC_GEN" == "yes"], - [AC_MSG_ERROR([Cannot enable generated docs when building overall is disabled. Please do not pass '--enable-doc-gen' or do not pass '--disable-build'.])]) - -AS_IF( - [test "$ENABLE_FUNCTIONAL_TESTS" == "yes" || test "$ENABLE_DOC_GEN" == "yes"], - [NEED_PROG(jq, jq)]) - -AS_IF( - [test "$ENABLE_DOC_GEN" == "yes"], - [NEED_PROG(man, man)]) - -AS_IF([test "$ENABLE_BUILD" == "yes"],[ - -# Look for boost, a required dependency. -# Note that AX_BOOST_BASE only exports *CPP* BOOST_CPPFLAGS, no CXX flags, -# and CPPFLAGS are not passed to the C++ compiler automatically. -# Thus we append the returned CPPFLAGS to the CXXFLAGS here. -AX_BOOST_BASE([1.66], [CXXFLAGS="$BOOST_CPPFLAGS $CXXFLAGS"], [AC_MSG_ERROR([Nix requires boost.])]) -# For unknown reasons, setting this directly in the ACTION-IF-FOUND above -# ends up with LDFLAGS being empty, so we set it afterwards. -LDFLAGS="$BOOST_LDFLAGS $LDFLAGS" - -# On some platforms, new-style atomics need a helper library -AC_MSG_CHECKING(whether -latomic is needed) -AC_LINK_IFELSE([AC_LANG_SOURCE([[ -#include -uint64_t v; -int main() { - return (int)__atomic_load_n(&v, __ATOMIC_ACQUIRE); -}]])], GCC_ATOMIC_BUILTINS_NEED_LIBATOMIC=no, GCC_ATOMIC_BUILTINS_NEED_LIBATOMIC=yes) -AC_MSG_RESULT($GCC_ATOMIC_BUILTINS_NEED_LIBATOMIC) -if test "x$GCC_ATOMIC_BUILTINS_NEED_LIBATOMIC" = xyes; then - LDFLAGS="-latomic $LDFLAGS" -fi - -AC_ARG_ENABLE(install-unit-tests, AS_HELP_STRING([--enable-install-unit-tests],[Install the unit tests for running later (default no)]), - INSTALL_UNIT_TESTS=$enableval, INSTALL_UNIT_TESTS=no) -AC_SUBST(INSTALL_UNIT_TESTS) - -AC_ARG_WITH(check-bin-dir, AS_HELP_STRING([--with-check-bin-dir=PATH],[path to install unit tests for running later (defaults to $libexecdir/nix)]), - checkbindir=$withval, checkbindir=$libexecdir/nix) -AC_SUBST(checkbindir) - -AC_ARG_WITH(check-lib-dir, AS_HELP_STRING([--with-check-lib-dir=PATH],[path to install unit tests for running later (defaults to $libdir)]), - checklibdir=$withval, checklibdir=$libdir) -AC_SUBST(checklibdir) - -# LTO is currently broken with clang for unknown reasons; ld segfaults in the llvm plugin -AC_ARG_ENABLE(lto, AS_HELP_STRING([--enable-lto],[Enable LTO (only supported with GCC) [default=no]]), - lto=$enableval, lto=no) -if test "$lto" = yes; then - if $CXX --version | grep -q GCC; then - AC_SUBST(CXXLTO, [-flto=jobserver]) - else - echo "error: LTO is only supported with GCC at the moment" >&2 - exit 1 - fi -else - AC_SUBST(CXXLTO, [""]) -fi - -PKG_PROG_PKG_CONFIG - -AC_ARG_ENABLE(shared, AS_HELP_STRING([--enable-shared],[Build shared libraries for Nix [default=yes]]), - shared=$enableval, shared=yes) -if test "$shared" = yes; then - AC_SUBST(BUILD_SHARED_LIBS, 1, [Whether to build shared libraries.]) -else - AC_SUBST(BUILD_SHARED_LIBS, 0, [Whether to build shared libraries.]) - PKG_CONFIG="$PKG_CONFIG --static" -fi - -# Look for OpenSSL, a required dependency. FIXME: this is only (maybe) -# used by S3BinaryCacheStore. -PKG_CHECK_MODULES([OPENSSL], [libcrypto >= 1.1.1], [CXXFLAGS="$OPENSSL_CFLAGS $CXXFLAGS"]) - - -# Look for libarchive. -PKG_CHECK_MODULES([LIBARCHIVE], [libarchive >= 3.1.2], [CXXFLAGS="$LIBARCHIVE_CFLAGS $CXXFLAGS"]) -# Workaround until https://github.com/libarchive/libarchive/issues/1446 is fixed -if test "$shared" != yes; then - LIBARCHIVE_LIBS+=' -lz' -fi - -# Look for SQLite, a required dependency. -PKG_CHECK_MODULES([SQLITE3], [sqlite3 >= 3.6.19], [CXXFLAGS="$SQLITE3_CFLAGS $CXXFLAGS"]) - -# Look for libcurl, a required dependency. -PKG_CHECK_MODULES([LIBCURL], [libcurl], [CXXFLAGS="$LIBCURL_CFLAGS $CXXFLAGS"]) - -# Look for editline or readline, a required dependency. -# The the libeditline.pc file was added only in libeditline >= 1.15.2, -# see https://github.com/troglobit/editline/commit/0a8f2ef4203c3a4a4726b9dd1336869cd0da8607, -# Older versions are no longer supported. -AC_ARG_WITH( - [readline-flavor], - AS_HELP_STRING([--with-readline-flavor],[Which library to use for nice line editting with the Nix language REPL" [default=editline]]), - [readline_flavor=$withval], - [readline_flavor=editline]) -AS_CASE(["$readline_flavor"], - [editline], [ - readline_flavor_pc=libeditline - ], - [readline], [ - readline_flavor_pc=readline - AC_DEFINE([USE_READLINE], [1], [Use readline instead of editline]) - ], - [AC_MSG_ERROR([bad value "$readline_flavor" for --with-readline-flavor, must be one of: editline, readline])]) -PKG_CHECK_MODULES([EDITLINE], [$readline_flavor_pc], [CXXFLAGS="$EDITLINE_CFLAGS $CXXFLAGS"]) - -# Look for libsodium. -PKG_CHECK_MODULES([SODIUM], [libsodium], [CXXFLAGS="$SODIUM_CFLAGS $CXXFLAGS"]) - -# Look for libbrotli{enc,dec}. -PKG_CHECK_MODULES([LIBBROTLI], [libbrotlienc libbrotlidec], [CXXFLAGS="$LIBBROTLI_CFLAGS $CXXFLAGS"]) - -# Look for libcpuid. -have_libcpuid= -if test "$machine_name" = "x86_64"; then - AC_ARG_ENABLE([cpuid], - AS_HELP_STRING([--disable-cpuid], [Do not determine microarchitecture levels with libcpuid (relevant to x86_64 only)])) - if test "x$enable_cpuid" != "xno"; then - PKG_CHECK_MODULES([LIBCPUID], [libcpuid], - [CXXFLAGS="$LIBCPUID_CFLAGS $CXXFLAGS" - have_libcpuid=1 - AC_DEFINE([HAVE_LIBCPUID], [1], [Use libcpuid])] - ) - fi -fi -AC_SUBST(HAVE_LIBCPUID, [$have_libcpuid]) - - -# Look for libseccomp, required for Linux sandboxing. -case "$host_os" in - linux*) - AC_ARG_ENABLE([seccomp-sandboxing], - AS_HELP_STRING([--disable-seccomp-sandboxing],[Don't build support for seccomp sandboxing (only recommended if your arch doesn't support libseccomp yet!) - ])) - if test "x$enable_seccomp_sandboxing" != "xno"; then - PKG_CHECK_MODULES([LIBSECCOMP], [libseccomp], - [CXXFLAGS="$LIBSECCOMP_CFLAGS $CXXFLAGS" CFLAGS="$LIBSECCOMP_CFLAGS $CFLAGS"]) - have_seccomp=1 - AC_DEFINE([HAVE_SECCOMP], [1], [Whether seccomp is available and should be used for sandboxing.]) - AC_COMPILE_IFELSE([ - AC_LANG_SOURCE([[ - #include - #ifndef __SNR_fchmodat2 - # error "Missing support for fchmodat2" - #endif - ]]) - ], [], [ - echo "libseccomp is missing __SNR_fchmodat2. Please provide libseccomp 2.5.5 or later" - exit 1 - ]) - else - have_seccomp= - fi - ;; - *) - have_seccomp= - ;; -esac -AC_SUBST(HAVE_SECCOMP, [$have_seccomp]) - -# Optional dependencies for better normalizing file system data -AC_CHECK_HEADERS([sys/xattr.h]) -AS_IF([test "$ac_cv_header_sys_xattr_h" = "yes"],[ - AC_CHECK_FUNCS([llistxattr lremovexattr]) - AS_IF([test "$ac_cv_func_llistxattr" = "yes" && test "$ac_cv_func_lremovexattr" = "yes"],[ - AC_DEFINE([HAVE_ACL_SUPPORT], [1], [Define if we can manipulate file system Access Control Lists]) - ]) -]) - -# Look for aws-cpp-sdk-s3. -AC_LANG_PUSH(C++) -AC_CHECK_HEADERS([aws/s3/S3Client.h], - [AC_DEFINE([ENABLE_S3], [1], [Whether to enable S3 support via aws-sdk-cpp.]) enable_s3=1], - [AC_DEFINE([ENABLE_S3], [0], [Whether to enable S3 support via aws-sdk-cpp.]) enable_s3=]) -AC_SUBST(ENABLE_S3, [$enable_s3]) -AC_LANG_POP(C++) - - -# Whether to use the Boehm garbage collector. -AC_ARG_ENABLE(gc, AS_HELP_STRING([--enable-gc],[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" - AC_DEFINE(HAVE_BOEHMGC, 1, [Whether to use the Boehm garbage collector.]) - - # See `fixupBoehmStackPointer`, for the integration between Boehm GC - # and Boost coroutines. - old_CFLAGS="$CFLAGS" - # Temporary set `-pthread` just for the next check - CFLAGS="$CFLAGS -pthread" - AC_CHECK_FUNCS([pthread_attr_get_np pthread_getattr_np]) - CFLAGS="$old_CFLAGS" -fi - -AS_IF([test "$ENABLE_UNIT_TESTS" == "yes"],[ - -# Look for gtest. -PKG_CHECK_MODULES([GTEST], [gtest_main gmock_main]) - -# Look for rapidcheck. -PKG_CHECK_MODULES([RAPIDCHECK], [rapidcheck rapidcheck_gtest]) - -]) - -# Look for nlohmann/json. -PKG_CHECK_MODULES([NLOHMANN_JSON], [nlohmann_json >= 3.9]) - - -# Look for lowdown library. -AC_ARG_ENABLE([markdown], AS_HELP_STRING([--enable-markdown], [Enable Markdown rendering in the Nix binary (requires lowdown) [default=auto]]), - enable_markdown=$enableval, enable_markdown=auto) -AS_CASE(["$enable_markdown"], - [yes | auto], [ - PKG_CHECK_MODULES([LOWDOWN], [lowdown >= 0.9.0], [ - CXXFLAGS="$LOWDOWN_CFLAGS $CXXFLAGS" - have_lowdown=1 - AC_DEFINE(HAVE_LOWDOWN, 1, [Whether lowdown is available and should be used for Markdown rendering.]) - ], [ - AS_IF([test "x$enable_markdown" == "xyes"], [AC_MSG_ERROR([--enable-markdown was specified, but lowdown was not found.])]) - ]) - ], - [no], [have_lowdown=], - [AC_MSG_ERROR([bad value "$enable_markdown" for --enable-markdown, must be one of: yes, no, auto])]) - - -# Look for libgit2. -PKG_CHECK_MODULES([LIBGIT2], [libgit2]) - - -# Look for toml11, a required dependency. -AC_LANG_PUSH(C++) -AC_CHECK_HEADER([toml.hpp], [], [AC_MSG_ERROR([toml11 is not found.])]) -AC_LANG_POP(C++) - -# Setuid installations. -AC_CHECK_FUNCS([setresuid setreuid lchown]) - - -# Nice to have, but not essential. -AC_CHECK_FUNCS([strsignal posix_fallocate sysconf]) - - -AC_ARG_WITH(sandbox-shell, AS_HELP_STRING([--with-sandbox-shell=PATH],[path of a statically-linked shell to use as /bin/sh in sandboxes]), - sandbox_shell=$withval) -AC_SUBST(sandbox_shell) -if test ${cross_compiling:-no} = no && ! test -z ${sandbox_shell+x}; then - AC_MSG_CHECKING([whether sandbox-shell has the standalone feature]) - # busybox shell sometimes allows executing other busybox applets, - # even if they are not in the path, breaking our sandbox - if PATH= $sandbox_shell -c "busybox" 2>&1 | grep -qv "not found"; then - AC_MSG_RESULT(enabled) - AC_MSG_ERROR([Please disable busybox FEATURE_SH_STANDALONE]) - else - AC_MSG_RESULT(disabled) - fi -fi - -AC_ARG_ENABLE(embedded-sandbox-shell, AS_HELP_STRING([--enable-embedded-sandbox-shell],[include the sandbox shell in the Nix binary [default=no]]), - embedded_sandbox_shell=$enableval, embedded_sandbox_shell=no) -AC_SUBST(embedded_sandbox_shell) -if test "$embedded_sandbox_shell" = yes; then - AC_DEFINE(HAVE_EMBEDDED_SANDBOX_SHELL, 1, [Include the sandbox shell in the Nix binary.]) -fi - -]) - - -# Expand all variables in config.status. -test "$prefix" = NONE && prefix=$ac_default_prefix -test "$exec_prefix" = NONE && exec_prefix='${prefix}' -for name in $ac_subst_vars; do - declare $name="$(eval echo "${!name}")" - declare $name="$(eval echo "${!name}")" - declare $name="$(eval echo "${!name}")" -done - -rm -f Makefile.config - -AC_CONFIG_HEADERS([config.h]) -AC_CONFIG_FILES([]) -AC_OUTPUT diff --git a/doc/manual/local.mk b/doc/manual/local.mk deleted file mode 100644 index 36cccc506..000000000 --- a/doc/manual/local.mk +++ /dev/null @@ -1,236 +0,0 @@ -# The version of Nix used to generate the doc. Can also be -# `$(nix_INSTALL_PATH)` or just `nix` (to grap ambient from the `PATH`), -# if one prefers. -doc_nix = $(nix_PATH) - -MANUAL_SRCS := \ - $(call rwildcard, $(d)/source, *.md) \ - $(call rwildcard, $(d)/source, */*.md) - -man-pages := $(foreach n, \ - nix-env.1 nix-store.1 \ - nix-build.1 nix-shell.1 nix-instantiate.1 \ - nix-collect-garbage.1 \ - nix-prefetch-url.1 nix-channel.1 \ - nix-hash.1 nix-copy-closure.1 \ - nix.conf.5 nix-daemon.8 \ - nix-profiles.5 \ -, $(d)/$(n)) - -# man pages for subcommands -# convert from `$(d)/source/command-ref/nix-{1}/{2}.md` to `$(d)/nix-{1}-{2}.1` -# FIXME: unify with how nix3-cli man pages are generated -man-pages += $(foreach subcommand, \ - $(filter-out %opt-common.md %env-common.md, $(wildcard $(d)/source/command-ref/nix-*/*.md)), \ - $(d)/$(subst /,-,$(subst $(d)/source/command-ref/,,$(subst .md,.1,$(subcommand))))) - -clean-files += $(d)/*.1 $(d)/*.5 $(d)/*.8 - -# Provide a dummy environment for nix, so that it will not access files outside the macOS sandbox. -# Set cores to 0 because otherwise `nix config show` resolves the cores based on the current machine -dummy-env = env -i \ - HOME=/dummy \ - NIX_CONF_DIR=/dummy \ - NIX_SSL_CERT_FILE=/dummy/no-ca-bundle.crt \ - NIX_STATE_DIR=/dummy \ - NIX_CONFIG='cores = 0' - -nix-eval = $(dummy-env) $(doc_nix) eval --experimental-features nix-command -I nix=doc/manual --store dummy:// --impure --raw - -# re-implement mdBook's include directive to make it usable for terminal output and for proper @docroot@ substitution -define process-includes - while read -r line; do \ - set -euo pipefail; \ - filename="$$(dirname $(1))/$$(sed 's/{{#include \(.*\)}}/\1/'<<< $$line)"; \ - test -f "$$filename" || ( echo "#include-d file '$$filename' does not exist." >&2; exit 1; ); \ - matchline="$$(sed 's|/|\\/|g' <<< $$line)"; \ - sed -i "/$$matchline/r $$filename" $(2); \ - sed -i "s/$$matchline//" $(2); \ - done < <(grep '{{#include' $(1)) -endef - -$(d)/nix-env-%.1: $(d)/source/command-ref/nix-env/%.md - @printf "Title: %s\n\n" "$(subst nix-env-,nix-env --,$$(basename "$@" .1))" > $^.tmp - $(render-subcommand) - -$(d)/nix-store-%.1: $(d)/source/command-ref/nix-store/%.md - @printf -- 'Title: %s\n\n' "$(subst nix-store-,nix-store --,$$(basename "$@" .1))" > $^.tmp - $(render-subcommand) - -# FIXME: there surely is some more deduplication to be achieved here with even darker Make magic -define render-subcommand - @cat $^ >> $^.tmp - @$(call process-includes,$^,$^.tmp) - $(trace-gen) lowdown -sT man --nroff-nolinks -M section=1 $^.tmp -o $@ - @# fix up `lowdown`'s automatic escaping of `--` - @# https://github.com/kristapsdz/lowdown/blob/edca6ce6d5336efb147321a43c47a698de41bb7c/entity.c#L202 - @sed -i 's/\e\[u2013\]/--/' $@ - @rm $^.tmp -endef - - -$(d)/%.1: $(d)/source/command-ref/%.md - @printf "Title: %s\n\n" "$$(basename $@ .1)" > $^.tmp - @cat $^ >> $^.tmp - @$(call process-includes,$^,$^.tmp) - $(trace-gen) lowdown -sT man --nroff-nolinks -M section=1 $^.tmp -o $@ - @rm $^.tmp - -$(d)/%.8: $(d)/source/command-ref/%.md - @printf "Title: %s\n\n" "$$(basename $@ .8)" > $^.tmp - @cat $^ >> $^.tmp - $(trace-gen) lowdown -sT man --nroff-nolinks -M section=8 $^.tmp -o $@ - @rm $^.tmp - -$(d)/nix.conf.5: $(d)/source/command-ref/conf-file.md - @printf "Title: %s\n\n" "$$(basename $@ .5)" > $^.tmp - @cat $^ >> $^.tmp - @$(call process-includes,$^,$^.tmp) - $(trace-gen) lowdown -sT man --nroff-nolinks -M section=5 $^.tmp -o $@ - @rm $^.tmp - -$(d)/nix-profiles.5: $(d)/source/command-ref/files/profiles.md - @printf "Title: %s\n\n" "$$(basename $@ .5)" > $^.tmp - @cat $^ >> $^.tmp - $(trace-gen) lowdown -sT man --nroff-nolinks -M section=5 $^.tmp -o $@ - @rm $^.tmp - -$(d)/source/SUMMARY.md: $(d)/source/SUMMARY.md.in $(d)/source/SUMMARY-rl-next.md $(d)/source/store/types $(d)/source/command-ref/new-cli $(d)/source/development/experimental-feature-descriptions.md - @cp $< $@ - @$(call process-includes,$@,$@) - -$(d)/source/store/types: $(d)/nix.json $(d)/utils.nix $(d)/generate-store-info.nix $(d)/generate-store-types.nix $(d)/source/store/types/index.md.in $(doc_nix) - @# FIXME: build out of tree! - @rm -rf $@.tmp - $(trace-gen) $(nix-eval) --write-to $@.tmp --expr 'import doc/manual/generate-store-types.nix (builtins.fromJSON (builtins.readFile $<)).stores' - @# do not destroy existing contents - @mv $@.tmp/* $@/ - -$(d)/source/command-ref/new-cli: $(d)/nix.json $(d)/utils.nix $(d)/generate-manpage.nix $(d)/generate-settings.nix $(d)/generate-store-info.nix $(doc_nix) - @rm -rf $@ $@.tmp - $(trace-gen) $(nix-eval) --write-to $@.tmp --expr 'import doc/manual/generate-manpage.nix true (builtins.readFile $<)' - @mv $@.tmp $@ - -$(d)/source/command-ref/conf-file.md: $(d)/conf-file.json $(d)/utils.nix $(d)/generate-settings.nix $(d)/source/command-ref/conf-file-prefix.md $(d)/source/command-ref/experimental-features-shortlist.md $(doc_nix) - @cat doc/manual/source/command-ref/conf-file-prefix.md > $@.tmp - $(trace-gen) $(nix-eval) --expr 'import doc/manual/generate-settings.nix { prefix = "conf"; } (builtins.fromJSON (builtins.readFile $<))' >> $@.tmp; - @mv $@.tmp $@ - -$(d)/nix.json: $(doc_nix) - $(trace-gen) $(dummy-env) $(doc_nix) __dump-cli > $@.tmp - @mv $@.tmp $@ - -$(d)/conf-file.json: $(doc_nix) - $(trace-gen) $(dummy-env) $(doc_nix) config show --json --experimental-features nix-command > $@.tmp - @mv $@.tmp $@ - -$(d)/source/development/experimental-feature-descriptions.md: $(d)/xp-features.json $(d)/utils.nix $(d)/generate-xp-features.nix $(doc_nix) - @rm -rf $@ $@.tmp - $(trace-gen) $(nix-eval) --write-to $@.tmp --expr 'import doc/manual/generate-xp-features.nix (builtins.fromJSON (builtins.readFile $<))' - @mv $@.tmp $@ - -$(d)/source/command-ref/experimental-features-shortlist.md: $(d)/xp-features.json $(d)/utils.nix $(d)/generate-xp-features-shortlist.nix $(doc_nix) - @rm -rf $@ $@.tmp - $(trace-gen) $(nix-eval) --write-to $@.tmp --expr 'import doc/manual/generate-xp-features-shortlist.nix (builtins.fromJSON (builtins.readFile $<))' - @mv $@.tmp $@ - -$(d)/xp-features.json: $(doc_nix) - $(trace-gen) $(dummy-env) $(doc_nix) __dump-xp-features > $@.tmp - @mv $@.tmp $@ - -$(d)/source/language/builtins.md: $(d)/language.json $(d)/generate-builtins.nix $(d)/source/language/builtins-prefix.md $(doc_nix) - @cat doc/manual/source/language/builtins-prefix.md > $@.tmp - $(trace-gen) $(nix-eval) --expr 'import doc/manual/generate-builtins.nix (builtins.fromJSON (builtins.readFile $<))' >> $@.tmp; - @cat doc/manual/source/language/builtins-suffix.md >> $@.tmp - @mv $@.tmp $@ - -$(d)/language.json: $(doc_nix) - $(trace-gen) $(dummy-env) $(doc_nix) __dump-language > $@.tmp - @mv $@.tmp $@ - -# Generate "Upcoming release" notes (or clear it and remove from menu) -$(d)/source/release-notes/rl-next.md: $(d)/rl-next $(d)/rl-next/* - @if type -p changelog-d > /dev/null; then \ - echo " GEN " $@; \ - changelog-d doc/manual/rl-next > $@; \ - else \ - echo " NULL " $@; \ - true > $@; \ - fi - -$(d)/source/SUMMARY-rl-next.md: $(d)/source/release-notes/rl-next.md - $(trace-gen) true - @if [ -s $< ]; then \ - echo ' - [Upcoming release](release-notes/rl-next.md)' > $@; \ - else \ - true > $@; \ - fi - -# Generate the HTML manual. -.PHONY: manual-html -manual-html: $(docdir)/manual/index.html - -# Open the built HTML manual in the default browser. -manual-html-open: $(docdir)/manual/index.html - @echo " OPEN " $<; \ - xdg-open $< \ - || open $< \ - || { \ - echo "Could not open the manual in a browser. Please open '$<'" >&2; \ - false; \ - } -install: $(docdir)/manual/index.html - -# Generate 'nix' manpages. -.PHONY: manpages -manpages: $(mandir)/man1/nix3-manpages -install: $(mandir)/man1/nix3-manpages -man: doc/manual/generated/man1/nix3-manpages -all: doc/manual/generated/man1/nix3-manpages - -# FIXME: unify with how the other man pages are generated. -# this one works differently and does not use any of the amenities provided by `/mk/lib.mk`. -$(mandir)/man1/nix3-manpages: doc/manual/generated/man1/nix3-manpages - @mkdir -p $(DESTDIR)$$(dirname $@) - $(trace-install) install -m 0644 $$(dirname $<)/* $(DESTDIR)$$(dirname $@) - -doc/manual/generated/man1/nix3-manpages: $(d)/source/command-ref/new-cli - @mkdir -p $(DESTDIR)$$(dirname $@) - $(trace-gen) for i in doc/manual/source/command-ref/new-cli/*.md; do \ - name=$$(basename $$i .md); \ - tmpFile=$$(mktemp); \ - if [[ $$name = SUMMARY ]]; then continue; fi; \ - printf "Title: %s\n\n" "$$name" > $$tmpFile; \ - cat $$i >> $$tmpFile; \ - lowdown -sT man --nroff-nolinks -M section=1 $$tmpFile -o $(DESTDIR)$$(dirname $@)/$$name.1; \ - rm $$tmpFile; \ - done - @touch $@ - -# the `! -name 'documentation.md'` filter excludes the one place where -# `@docroot@` is to be preserved for documenting the mechanism -# FIXME: maybe contributing guides should live right next to the code -# instead of in the manual -$(docdir)/manual/index.html: $(MANUAL_SRCS) $(d)/book.toml $(d)/anchors.jq $(d)/custom.css $(d)/source/SUMMARY.md $(d)/source/store/types $(d)/source/command-ref/new-cli $(d)/source/development/experimental-feature-descriptions.md $(d)/source/command-ref/conf-file.md $(d)/source/language/builtins.md $(d)/source/release-notes/rl-next.md $(d)/source/figures $(d)/source/favicon.png $(d)/source/favicon.svg - $(trace-gen) \ - tmp="$$(mktemp -d)"; \ - cp -r doc/manual "$$tmp"; \ - find "$$tmp" -name '*.md' | while read -r file; do \ - $(call process-includes,$$file,$$file); \ - done; \ - find "$$tmp" -name '*.md' ! -name 'documentation.md' | while read -r file; do \ - docroot="$$(realpath --relative-to="$$(dirname "$$file")" $$tmp/manual/source)"; \ - sed -i "s,@docroot@,$$docroot,g" "$$file"; \ - done; \ - set -euo pipefail; \ - ( \ - cd "$$tmp/manual"; \ - RUST_LOG=warn \ - MDBOOK_SUBSTITUTE_SEARCH=$(d)/source \ - mdbook build -d $(DESTDIR)$(docdir)/manual.tmp 2>&1 \ - | { grep -Fv "because fragment resolution isn't implemented" || :; } \ - ); \ - rm -rf "$$tmp/manual" - @rm -rf $(DESTDIR)$(docdir)/manual - @mv $(DESTDIR)$(docdir)/manual.tmp/html $(DESTDIR)$(docdir)/manual - @rm -rf $(DESTDIR)$(docdir)/manual.tmp diff --git a/flake.nix b/flake.nix index 3ef027dd1..4d339f6e7 100644 --- a/flake.nix +++ b/flake.nix @@ -137,7 +137,7 @@ pkgs = final; }); - nix = final.nixComponents.nix; + nix = final.nixComponents.nix-cli; # See https://github.com/NixOS/nixpkgs/pull/214409 # Remove when fixed in this flake's nixpkgs @@ -189,7 +189,6 @@ # system, we should reenable this. #perlBindings = self.hydraJobs.perlBindings.${system}; } - /* # Add "passthru" tests // flatMapAttrs ({ "" = nixpkgsFor.${system}.native; @@ -211,7 +210,6 @@ "${nixpkgsPrefix}nix-functional-tests" = nixpkgs.nixComponents.nix-functional-tests; } ) - */ // devFlake.checks.${system} or {} ); @@ -220,7 +218,8 @@ # for which we don't apply the full build matrix such as cross or static. inherit (nixpkgsFor.${system}.native) changelog-d; - default = self.packages.${system}.nix-ng; + # TODO probably should be `nix-cli` + default = self.packages.${system}.nix-everything; nix-manual = nixpkgsFor.${system}.native.nixComponents.nix-manual; nix-internal-api-docs = nixpkgsFor.${system}.native.nixComponents.nix-internal-api-docs; nix-external-api-docs = nixpkgsFor.${system}.native.nixComponents.nix-external-api-docs; @@ -228,7 +227,6 @@ # We need to flatten recursive attribute sets of derivations to pass `flake check`. // flatMapAttrs { # Components we'll iterate over in the upcoming lambda - "nix" = { }; "nix-util" = { }; "nix-util-c" = { }; "nix-util-test-support" = { }; @@ -257,10 +255,11 @@ "nix-cli" = { }; + "nix-everything" = { }; + "nix-functional-tests" = { supportsCross = false; }; "nix-perl-bindings" = { supportsCross = false; }; - "nix-ng" = { }; } (pkgName: { supportsCross ? true }: { # These attributes go right into `packages.`. diff --git a/local.mk b/local.mk deleted file mode 100644 index b27c7031e..000000000 --- a/local.mk +++ /dev/null @@ -1,15 +0,0 @@ -GLOBAL_CXXFLAGS += -Wno-deprecated-declarations -Werror=switch -# Allow switch-enum to be overridden for files that do not support it, usually because of dependency headers. -ERROR_SWITCH_ENUM = -Werror=switch-enum - -$(foreach i, config.h $(wildcard src/lib*/*.hh) $(filter-out %_internal.h, $(wildcard src/lib*c/*.h)), \ - $(eval $(call install-file-in, $(i), $(includedir)/nix, 0644))) - -ifdef HOST_UNIX - $(foreach i, $(wildcard src/lib*/unix/*.hh), \ - $(eval $(call install-file-in, $(i), $(includedir)/nix, 0644))) -endif - -$(GCH): src/libutil/util.hh config.h - -GCH_CXXFLAGS = $(INCLUDE_libutil) diff --git a/m4/ax_cxx_compile_stdcxx.m4 b/m4/ax_cxx_compile_stdcxx.m4 deleted file mode 100644 index 43087b2e6..000000000 --- a/m4/ax_cxx_compile_stdcxx.m4 +++ /dev/null @@ -1,951 +0,0 @@ -# =========================================================================== -# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) -# -# DESCRIPTION -# -# Check for baseline language coverage in the compiler for the specified -# version of the C++ standard. If necessary, add switches to CXX and -# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard) -# or '14' (for the C++14 standard). -# -# The second argument, if specified, indicates whether you insist on an -# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. -# -std=c++11). If neither is specified, you get whatever works, with -# preference for an extended mode. -# -# The third argument, if specified 'mandatory' or if left unspecified, -# indicates that baseline support for the specified C++ standard is -# required and that the macro should error out if no mode with that -# support is found. If specified 'optional', then configuration proceeds -# regardless, after defining HAVE_CXX${VERSION} if and only if a -# supporting mode is found. -# -# LICENSE -# -# Copyright (c) 2008 Benjamin Kosnik -# Copyright (c) 2012 Zack Weinberg -# Copyright (c) 2013 Roy Stogner -# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov -# Copyright (c) 2015 Paul Norman -# Copyright (c) 2015 Moritz Klammler -# Copyright (c) 2016, 2018 Krzesimir Nowak -# Copyright (c) 2019 Enji Cooper -# -# Copying and distribution of this file, with or without modification, are -# permitted in any medium without royalty provided the copyright notice -# and this notice are preserved. This file is offered as-is, without any -# warranty. - -#serial 11 - -dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro -dnl (serial version number 13). - -AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl - m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"], - [$1], [14], [ax_cxx_compile_alternatives="14 1y"], - [$1], [17], [ax_cxx_compile_alternatives="17 1z"], - [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl - m4_if([$2], [], [], - [$2], [ext], [], - [$2], [noext], [], - [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl - m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], - [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], - [$3], [optional], [ax_cxx_compile_cxx$1_required=false], - [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) - AC_LANG_PUSH([C++])dnl - ac_success=no - - m4_if([$2], [noext], [], [dnl - if test x$ac_success = xno; then - for alternative in ${ax_cxx_compile_alternatives}; do - switch="-std=gnu++${alternative}" - cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) - AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, - $cachevar, - [ac_save_CXX="$CXX" - CXX="$CXX $switch" - AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], - [eval $cachevar=yes], - [eval $cachevar=no]) - CXX="$ac_save_CXX"]) - if eval test x\$$cachevar = xyes; then - CXX="$CXX $switch" - if test -n "$CXXCPP" ; then - CXXCPP="$CXXCPP $switch" - fi - ac_success=yes - break - fi - done - fi]) - - m4_if([$2], [ext], [], [dnl - if test x$ac_success = xno; then - dnl HP's aCC needs +std=c++11 according to: - dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf - dnl Cray's crayCC needs "-h std=c++11" - for alternative in ${ax_cxx_compile_alternatives}; do - for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do - cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) - AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, - $cachevar, - [ac_save_CXX="$CXX" - CXX="$CXX $switch" - AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], - [eval $cachevar=yes], - [eval $cachevar=no]) - CXX="$ac_save_CXX"]) - if eval test x\$$cachevar = xyes; then - CXX="$CXX $switch" - if test -n "$CXXCPP" ; then - CXXCPP="$CXXCPP $switch" - fi - ac_success=yes - break - fi - done - if test x$ac_success = xyes; then - break - fi - done - fi]) - AC_LANG_POP([C++]) - if test x$ax_cxx_compile_cxx$1_required = xtrue; then - if test x$ac_success = xno; then - AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) - fi - fi - if test x$ac_success = xno; then - HAVE_CXX$1=0 - AC_MSG_NOTICE([No compiler with C++$1 support was found]) - else - HAVE_CXX$1=1 - AC_DEFINE(HAVE_CXX$1,1, - [define if the compiler supports basic C++$1 syntax]) - fi - AC_SUBST(HAVE_CXX$1) -]) - - -dnl Test body for checking C++11 support - -m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], - _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 -) - - -dnl Test body for checking C++14 support - -m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], - _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 - _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 -) - -m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17], - _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 - _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 - _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 -) - -dnl Tests for new features in C++11 - -m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ - -// If the compiler admits that it is not ready for C++11, why torture it? -// Hopefully, this will speed up the test. - -#ifndef __cplusplus - -#error "This is not a C++ compiler" - -#elif __cplusplus < 201103L - -#error "This is not a C++11 compiler" - -#else - -namespace cxx11 -{ - - namespace test_static_assert - { - - template - struct check - { - static_assert(sizeof(int) <= sizeof(T), "not big enough"); - }; - - } - - namespace test_final_override - { - - struct Base - { - virtual ~Base() {} - virtual void f() {} - }; - - struct Derived : public Base - { - virtual ~Derived() override {} - virtual void f() override {} - }; - - } - - namespace test_double_right_angle_brackets - { - - template < typename T > - struct check {}; - - typedef check single_type; - typedef check> double_type; - typedef check>> triple_type; - typedef check>>> quadruple_type; - - } - - namespace test_decltype - { - - int - f() - { - int a = 1; - decltype(a) b = 2; - return a + b; - } - - } - - namespace test_type_deduction - { - - template < typename T1, typename T2 > - struct is_same - { - static const bool value = false; - }; - - template < typename T > - struct is_same - { - static const bool value = true; - }; - - template < typename T1, typename T2 > - auto - add(T1 a1, T2 a2) -> decltype(a1 + a2) - { - return a1 + a2; - } - - int - test(const int c, volatile int v) - { - static_assert(is_same::value == true, ""); - static_assert(is_same::value == false, ""); - static_assert(is_same::value == false, ""); - auto ac = c; - auto av = v; - auto sumi = ac + av + 'x'; - auto sumf = ac + av + 1.0; - static_assert(is_same::value == true, ""); - static_assert(is_same::value == true, ""); - static_assert(is_same::value == true, ""); - static_assert(is_same::value == false, ""); - static_assert(is_same::value == true, ""); - return (sumf > 0.0) ? sumi : add(c, v); - } - - } - - namespace test_noexcept - { - - int f() { return 0; } - int g() noexcept { return 0; } - - static_assert(noexcept(f()) == false, ""); - static_assert(noexcept(g()) == true, ""); - - } - - namespace test_constexpr - { - - template < typename CharT > - unsigned long constexpr - strlen_c_r(const CharT *const s, const unsigned long acc) noexcept - { - return *s ? strlen_c_r(s + 1, acc + 1) : acc; - } - - template < typename CharT > - unsigned long constexpr - strlen_c(const CharT *const s) noexcept - { - return strlen_c_r(s, 0UL); - } - - static_assert(strlen_c("") == 0UL, ""); - static_assert(strlen_c("1") == 1UL, ""); - static_assert(strlen_c("example") == 7UL, ""); - static_assert(strlen_c("another\0example") == 7UL, ""); - - } - - namespace test_rvalue_references - { - - template < int N > - struct answer - { - static constexpr int value = N; - }; - - answer<1> f(int&) { return answer<1>(); } - answer<2> f(const int&) { return answer<2>(); } - answer<3> f(int&&) { return answer<3>(); } - - void - test() - { - int i = 0; - const int c = 0; - static_assert(decltype(f(i))::value == 1, ""); - static_assert(decltype(f(c))::value == 2, ""); - static_assert(decltype(f(0))::value == 3, ""); - } - - } - - namespace test_uniform_initialization - { - - struct test - { - static const int zero {}; - static const int one {1}; - }; - - static_assert(test::zero == 0, ""); - static_assert(test::one == 1, ""); - - } - - namespace test_lambdas - { - - void - test1() - { - auto lambda1 = [](){}; - auto lambda2 = lambda1; - lambda1(); - lambda2(); - } - - int - test2() - { - auto a = [](int i, int j){ return i + j; }(1, 2); - auto b = []() -> int { return '0'; }(); - auto c = [=](){ return a + b; }(); - auto d = [&](){ return c; }(); - auto e = [a, &b](int x) mutable { - const auto identity = [](int y){ return y; }; - for (auto i = 0; i < a; ++i) - a += b--; - return x + identity(a + b); - }(0); - return a + b + c + d + e; - } - - int - test3() - { - const auto nullary = [](){ return 0; }; - const auto unary = [](int x){ return x; }; - using nullary_t = decltype(nullary); - using unary_t = decltype(unary); - const auto higher1st = [](nullary_t f){ return f(); }; - const auto higher2nd = [unary](nullary_t f1){ - return [unary, f1](unary_t f2){ return f2(unary(f1())); }; - }; - return higher1st(nullary) + higher2nd(nullary)(unary); - } - - } - - namespace test_variadic_templates - { - - template - struct sum; - - template - struct sum - { - static constexpr auto value = N0 + sum::value; - }; - - template <> - struct sum<> - { - static constexpr auto value = 0; - }; - - static_assert(sum<>::value == 0, ""); - static_assert(sum<1>::value == 1, ""); - static_assert(sum<23>::value == 23, ""); - static_assert(sum<1, 2>::value == 3, ""); - static_assert(sum<5, 5, 11>::value == 21, ""); - static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); - - } - - // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae - // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function - // because of this. - namespace test_template_alias_sfinae - { - - struct foo {}; - - template - using member = typename T::member_type; - - template - void func(...) {} - - template - void func(member*) {} - - void test(); - - void test() { func(0); } - - } - -} // namespace cxx11 - -#endif // __cplusplus >= 201103L - -]]) - - -dnl Tests for new features in C++14 - -m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ - -// If the compiler admits that it is not ready for C++14, why torture it? -// Hopefully, this will speed up the test. - -#ifndef __cplusplus - -#error "This is not a C++ compiler" - -#elif __cplusplus < 201402L - -#error "This is not a C++14 compiler" - -#else - -namespace cxx14 -{ - - namespace test_polymorphic_lambdas - { - - int - test() - { - const auto lambda = [](auto&&... args){ - const auto istiny = [](auto x){ - return (sizeof(x) == 1UL) ? 1 : 0; - }; - const int aretiny[] = { istiny(args)... }; - return aretiny[0]; - }; - return lambda(1, 1L, 1.0f, '1'); - } - - } - - namespace test_binary_literals - { - - constexpr auto ivii = 0b0000000000101010; - static_assert(ivii == 42, "wrong value"); - - } - - namespace test_generalized_constexpr - { - - template < typename CharT > - constexpr unsigned long - strlen_c(const CharT *const s) noexcept - { - auto length = 0UL; - for (auto p = s; *p; ++p) - ++length; - return length; - } - - static_assert(strlen_c("") == 0UL, ""); - static_assert(strlen_c("x") == 1UL, ""); - static_assert(strlen_c("test") == 4UL, ""); - static_assert(strlen_c("another\0test") == 7UL, ""); - - } - - namespace test_lambda_init_capture - { - - int - test() - { - auto x = 0; - const auto lambda1 = [a = x](int b){ return a + b; }; - const auto lambda2 = [a = lambda1(x)](){ return a; }; - return lambda2(); - } - - } - - namespace test_digit_separators - { - - constexpr auto ten_million = 100'000'000; - static_assert(ten_million == 100000000, ""); - - } - - namespace test_return_type_deduction - { - - auto f(int& x) { return x; } - decltype(auto) g(int& x) { return x; } - - template < typename T1, typename T2 > - struct is_same - { - static constexpr auto value = false; - }; - - template < typename T > - struct is_same - { - static constexpr auto value = true; - }; - - int - test() - { - auto x = 0; - static_assert(is_same::value, ""); - static_assert(is_same::value, ""); - return x; - } - - } - -} // namespace cxx14 - -#endif // __cplusplus >= 201402L - -]]) - - -dnl Tests for new features in C++17 - -m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[ - -// If the compiler admits that it is not ready for C++17, why torture it? -// Hopefully, this will speed up the test. - -#ifndef __cplusplus - -#error "This is not a C++ compiler" - -#elif __cplusplus < 201703L - -#error "This is not a C++17 compiler" - -#else - -#include -#include -#include - -namespace cxx17 -{ - - namespace test_constexpr_lambdas - { - - constexpr int foo = [](){return 42;}(); - - } - - namespace test::nested_namespace::definitions - { - - } - - namespace test_fold_expression - { - - template - int multiply(Args... args) - { - return (args * ... * 1); - } - - template - bool all(Args... args) - { - return (args && ...); - } - - } - - namespace test_extended_static_assert - { - - static_assert (true); - - } - - namespace test_auto_brace_init_list - { - - auto foo = {5}; - auto bar {5}; - - static_assert(std::is_same, decltype(foo)>::value); - static_assert(std::is_same::value); - } - - namespace test_typename_in_template_template_parameter - { - - template typename X> struct D; - - } - - namespace test_fallthrough_nodiscard_maybe_unused_attributes - { - - int f1() - { - return 42; - } - - [[nodiscard]] int f2() - { - [[maybe_unused]] auto unused = f1(); - - switch (f1()) - { - case 17: - f1(); - [[fallthrough]]; - case 42: - f1(); - } - return f1(); - } - - } - - namespace test_extended_aggregate_initialization - { - - struct base1 - { - int b1, b2 = 42; - }; - - struct base2 - { - base2() { - b3 = 42; - } - int b3; - }; - - struct derived : base1, base2 - { - int d; - }; - - derived d1 {{1, 2}, {}, 4}; // full initialization - derived d2 {{}, {}, 4}; // value-initialized bases - - } - - namespace test_general_range_based_for_loop - { - - struct iter - { - int i; - - int& operator* () - { - return i; - } - - const int& operator* () const - { - return i; - } - - iter& operator++() - { - ++i; - return *this; - } - }; - - struct sentinel - { - int i; - }; - - bool operator== (const iter& i, const sentinel& s) - { - return i.i == s.i; - } - - bool operator!= (const iter& i, const sentinel& s) - { - return !(i == s); - } - - struct range - { - iter begin() const - { - return {0}; - } - - sentinel end() const - { - return {5}; - } - }; - - void f() - { - range r {}; - - for (auto i : r) - { - [[maybe_unused]] auto v = i; - } - } - - } - - namespace test_lambda_capture_asterisk_this_by_value - { - - struct t - { - int i; - int foo() - { - return [*this]() - { - return i; - }(); - } - }; - - } - - namespace test_enum_class_construction - { - - enum class byte : unsigned char - {}; - - byte foo {42}; - - } - - namespace test_constexpr_if - { - - template - int f () - { - if constexpr(cond) - { - return 13; - } - else - { - return 42; - } - } - - } - - namespace test_selection_statement_with_initializer - { - - int f() - { - return 13; - } - - int f2() - { - if (auto i = f(); i > 0) - { - return 3; - } - - switch (auto i = f(); i + 4) - { - case 17: - return 2; - - default: - return 1; - } - } - - } - - namespace test_template_argument_deduction_for_class_templates - { - - template - struct pair - { - pair (T1 p1, T2 p2) - : m1 {p1}, - m2 {p2} - {} - - T1 m1; - T2 m2; - }; - - void f() - { - [[maybe_unused]] auto p = pair{13, 42u}; - } - - } - - namespace test_non_type_auto_template_parameters - { - - template - struct B - {}; - - B<5> b1; - B<'a'> b2; - - } - - namespace test_structured_bindings - { - - int arr[2] = { 1, 2 }; - std::pair pr = { 1, 2 }; - - auto f1() -> int(&)[2] - { - return arr; - } - - auto f2() -> std::pair& - { - return pr; - } - - struct S - { - int x1 : 2; - volatile double y1; - }; - - S f3() - { - return {}; - } - - auto [ x1, y1 ] = f1(); - auto& [ xr1, yr1 ] = f1(); - auto [ x2, y2 ] = f2(); - auto& [ xr2, yr2 ] = f2(); - const auto [ x3, y3 ] = f3(); - - } - - namespace test_exception_spec_type_system - { - - struct Good {}; - struct Bad {}; - - void g1() noexcept; - void g2(); - - template - Bad - f(T*, T*); - - template - Good - f(T1*, T2*); - - static_assert (std::is_same_v); - - } - - namespace test_inline_variables - { - - template void f(T) - {} - - template inline T g(T) - { - return T{}; - } - - template<> inline void f<>(int) - {} - - template<> int g<>(int) - { - return 5; - } - - } - -} // namespace cxx17 - -#endif // __cplusplus < 201703L - -]]) diff --git a/m4/ax_cxx_compile_stdcxx_17.m4 b/m4/ax_cxx_compile_stdcxx_17.m4 deleted file mode 100644 index a68341717..000000000 --- a/m4/ax_cxx_compile_stdcxx_17.m4 +++ /dev/null @@ -1,35 +0,0 @@ -# ============================================================================= -# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_17.html -# ============================================================================= -# -# SYNOPSIS -# -# AX_CXX_COMPILE_STDCXX_17([ext|noext], [mandatory|optional]) -# -# DESCRIPTION -# -# Check for baseline language coverage in the compiler for the C++17 -# standard; if necessary, add switches to CXX and CXXCPP to enable -# support. -# -# This macro is a convenience alias for calling the AX_CXX_COMPILE_STDCXX -# macro with the version set to C++17. The two optional arguments are -# forwarded literally as the second and third argument respectively. -# Please see the documentation for the AX_CXX_COMPILE_STDCXX macro for -# more information. If you want to use this macro, you also need to -# download the ax_cxx_compile_stdcxx.m4 file. -# -# LICENSE -# -# Copyright (c) 2015 Moritz Klammler -# Copyright (c) 2016 Krzesimir Nowak -# -# Copying and distribution of this file, with or without modification, are -# permitted in any medium without royalty provided the copyright notice -# and this notice are preserved. This file is offered as-is, without any -# warranty. - -#serial 2 - -AX_REQUIRE_DEFINED([AX_CXX_COMPILE_STDCXX]) -AC_DEFUN([AX_CXX_COMPILE_STDCXX_17], [AX_CXX_COMPILE_STDCXX([17], [$1], [$2])]) diff --git a/maintainers/local.mk b/maintainers/local.mk deleted file mode 100644 index e81517eda..000000000 --- a/maintainers/local.mk +++ /dev/null @@ -1,8 +0,0 @@ - -.PHONY: format -print-top-help += echo ' format: Format source code' - -# This uses the cached .pre-commit-hooks.yaml file -fmt_script := $(d)/format.sh -format: - @$(fmt_script) diff --git a/misc/bash/local.mk b/misc/bash/local.mk deleted file mode 100644 index 66235af05..000000000 --- a/misc/bash/local.mk +++ /dev/null @@ -1 +0,0 @@ -$(eval $(call install-file-as, $(d)/completion.sh, $(datarootdir)/bash-completion/completions/nix, 0644)) diff --git a/misc/fish/local.mk b/misc/fish/local.mk deleted file mode 100644 index ece899fc3..000000000 --- a/misc/fish/local.mk +++ /dev/null @@ -1 +0,0 @@ -$(eval $(call install-file-as, $(d)/completion.fish, $(datarootdir)/fish/vendor_completions.d/nix.fish, 0644)) diff --git a/misc/launchd/local.mk b/misc/launchd/local.mk deleted file mode 100644 index a39188fe6..000000000 --- a/misc/launchd/local.mk +++ /dev/null @@ -1,5 +0,0 @@ -ifdef HOST_DARWIN - - $(eval $(call install-data-in, $(d)/org.nixos.nix-daemon.plist, $(prefix)/Library/LaunchDaemons)) - -endif diff --git a/misc/systemd/local.mk b/misc/systemd/local.mk deleted file mode 100644 index 76121a0f9..000000000 --- a/misc/systemd/local.mk +++ /dev/null @@ -1,8 +0,0 @@ -ifdef HOST_LINUX - - $(foreach n, nix-daemon.socket nix-daemon.service, $(eval $(call install-file-in, $(d)/$(n), $(prefix)/lib/systemd/system, 0644))) - $(foreach n, nix-daemon.conf, $(eval $(call install-file-in, $(d)/$(n), $(prefix)/lib/tmpfiles.d, 0644))) - - clean-files += $(d)/nix-daemon.socket $(d)/nix-daemon.service $(d)/nix-daemon.conf - -endif diff --git a/misc/upstart/local.mk b/misc/upstart/local.mk deleted file mode 100644 index 2fbfb29b9..000000000 --- a/misc/upstart/local.mk +++ /dev/null @@ -1,7 +0,0 @@ -ifdef HOST_LINUX - - $(foreach n, nix-daemon.conf, $(eval $(call install-file-in, $(d)/$(n), $(sysconfdir)/init, 0644))) - - clean-files += $(d)/nix-daemon.conf - -endif diff --git a/misc/zsh/local.mk b/misc/zsh/local.mk deleted file mode 100644 index 0b4e294fb..000000000 --- a/misc/zsh/local.mk +++ /dev/null @@ -1,2 +0,0 @@ -$(eval $(call install-file-as, $(d)/completion.zsh, $(datarootdir)/zsh/site-functions/_nix, 0644)) -$(eval $(call install-file-as, $(d)/run-help-nix, $(datarootdir)/zsh/site-functions/run-help-nix, 0644)) diff --git a/mk/build-dir.mk b/mk/build-dir.mk deleted file mode 100644 index 02f4cae60..000000000 --- a/mk/build-dir.mk +++ /dev/null @@ -1,10 +0,0 @@ -# Initialise support for build directories. -builddir ?= - -ifdef builddir - buildprefix = $(builddir)/ - buildprefixrel = $(builddir) -else - buildprefix = - buildprefixrel = . -endif diff --git a/mk/clean.mk b/mk/clean.mk deleted file mode 100644 index ce9afb3b0..000000000 --- a/mk/clean.mk +++ /dev/null @@ -1,11 +0,0 @@ -clean-files := - -clean: - $(suppress) rm -fv -- $(clean-files) - -dryclean: - @for i in $(clean-files); do if [ -e $$i ]; then echo $$i; fi; done | sort - -print-top-help += \ - echo " clean: Delete generated files"; \ - echo " dryclean: Show what files would be deleted by 'make clean'"; diff --git a/mk/common-test.sh b/mk/common-test.sh deleted file mode 100644 index dd899e869..000000000 --- a/mk/common-test.sh +++ /dev/null @@ -1,31 +0,0 @@ -# shellcheck shell=bash - -# Remove overall test dir (at most one of the two should match) and -# remove file extension. - -test_name=$(echo -n "${test?must be defined by caller (test runner)}" | sed \ - -e "s|^src/[^/]*-test/data/||" \ - -e "s|^tests/functional/||" \ - -e "s|\.sh$||" \ - ) - -# Layer violation, but I am not inclined to care too much, as this code -# is about to be deleted. -src_dir=$(realpath tests/functional) - -# shellcheck disable=SC2016 -TESTS_ENVIRONMENT=( - "TEST_NAME=$test_name" - 'NIX_REMOTE=' - 'PS4=+(${BASH_SOURCE[0]-$0}:$LINENO) ' - "_NIX_TEST_SOURCE_DIR=${src_dir}" - "_NIX_TEST_BUILD_DIR=${src_dir}" -) - -unset src_dir - -read -r -a bash <<< "${BASH:-/usr/bin/env bash}" - -run () { - cd "$(dirname "$1")" && env "${TESTS_ENVIRONMENT[@]}" "${bash[@]}" -x -e -u -o pipefail "$(basename "$1")" -} diff --git a/mk/compilation-database.mk b/mk/compilation-database.mk deleted file mode 100644 index f69dc0de0..000000000 --- a/mk/compilation-database.mk +++ /dev/null @@ -1,11 +0,0 @@ -compile-commands-json-files := - -define write-compile-commands - _srcs := $$(sort $$(foreach src, $$($(1)_SOURCES), $$(src))) - - $(1)_COMPILE_COMMANDS_JSON := $$(addprefix $(buildprefix), $$(addsuffix .compile_commands.json, $$(basename $$(_srcs)))) - - compile-commands-json-files += $$($(1)_COMPILE_COMMANDS_JSON) - - clean-files += $$($(1)_COMPILE_COMMANDS_JSON) -endef diff --git a/mk/cxx-big-literal.mk b/mk/cxx-big-literal.mk deleted file mode 100644 index d64a171c8..000000000 --- a/mk/cxx-big-literal.mk +++ /dev/null @@ -1,5 +0,0 @@ -%.gen.hh: % - @echo 'R"__NIX_STR(' >> $@.tmp - $(trace-gen) cat $< >> $@.tmp - @echo ')__NIX_STR"' >> $@.tmp - @mv $@.tmp $@ diff --git a/mk/debug-test.sh b/mk/debug-test.sh deleted file mode 100755 index 0dd4406c3..000000000 --- a/mk/debug-test.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -set -eu -o pipefail - -test=$1 - -dir="$(dirname "${BASH_SOURCE[0]}")" -source "$dir/common-test.sh" - -run "$test" diff --git a/mk/functions.mk b/mk/functions.mk deleted file mode 100644 index c48775db8..000000000 --- a/mk/functions.mk +++ /dev/null @@ -1,14 +0,0 @@ -# Utility function for recursively finding files, e.g. -# ‘$(call rwildcard, path/to/dir, *.c *.h)’. -rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d)) - -# Given a file name, produce the corresponding dependency file -# (e.g. ‘foo/bar.o’ becomes ‘foo/.bar.o.dep’). -filename-to-dep = $(dir $1).$(notdir $1).dep - -# Return the full path to a program by looking it up in $PATH, or the -# empty string if not found. -find-program = $(shell for i in $$(IFS=: ; echo $$PATH); do p=$$i/$(strip $1); if [ -e $$p ]; then echo $$p; break; fi; done) - -# Ensure that the given string ends in a single slash. -add-trailing-slash = $(patsubst %/,%,$(1))/ diff --git a/mk/install-dirs.mk b/mk/install-dirs.mk deleted file mode 100644 index 732b0d6fc..000000000 --- a/mk/install-dirs.mk +++ /dev/null @@ -1,11 +0,0 @@ -# Default installation paths. -prefix ?= /usr/local -libdir ?= $(prefix)/lib -bindir ?= $(prefix)/bin -libexecdir ?= $(prefix)/libexec -datadir ?= $(prefix)/share -localstatedir ?= $(prefix)/var -sysconfdir ?= $(prefix)/etc -mandir ?= $(prefix)/share/man - -DESTDIR ?= diff --git a/mk/install.mk b/mk/install.mk deleted file mode 100644 index dad0fd853..000000000 --- a/mk/install.mk +++ /dev/null @@ -1,62 +0,0 @@ -# Add a rule for creating $(1) as a directory. This template may be -# called multiple times for the same directory. -define create-dir - _i := $$(call add-trailing-slash, $(DESTDIR)$$(strip $(1))) - ifndef $$(_i)_SEEN - $$(_i)_SEEN = 1 - $$(_i): - $$(trace-mkdir) install -d "$$@" - endif -endef - - -# Add a rule for installing file $(1) as file $(2) with mode $(3). -# The directory containing $(2) will be created automatically. -define install-file-as - - _i := $(DESTDIR)$$(strip $(2)) - - install: $$(_i) - - $$(_i): $(1) | $$(dir $$(_i)) - $$(trace-install) install -m $(3) $(1) "$$@" - - $$(eval $$(call create-dir, $$(dir $(2)))) - -endef - - -# Add a rule for installing file $(1) in directory $(2) with mode -# $(3). The directory will be created automatically. -define install-file-in - $$(eval $$(call install-file-as,$(1),$(2)/$$(notdir $(1)),$(3))) -endef - - -define install-program-in - $$(eval $$(call install-file-in,$(1),$(2),0755)) -endef - - -define install-data-in - $$(eval $$(call install-file-in,$(1),$(2),0644)) -endef - - -# Install a symlink from $(2) to $(1). Note that $(1) need not exist. -define install-symlink - - _i := $(DESTDIR)$$(strip $(2)) - - install: $$(_i) - - $$(_i): | $$(dir $$(_i)) - $$(trace-install) ln -sfn $(1) "$$@" - - $$(eval $$(call create-dir, $$(dir $(2)))) - -endef - - -print-top-help += \ - echo " install: Install into \$$(prefix) (currently set to '$(prefix)')"; diff --git a/mk/lib.mk b/mk/lib.mk deleted file mode 100644 index 1e7af6ad5..000000000 --- a/mk/lib.mk +++ /dev/null @@ -1,159 +0,0 @@ -default: all - - -# Get rid of default suffixes. FIXME: is this a good idea? -.SUFFIXES: - - -# Initialise some variables. -bin-scripts := -noinst-scripts := -man-pages := -install-tests := -install-tests-groups := - -include mk/platform.mk - -# Hack to define a literal space. -space := -space += - - -# Hack to define a literal newline. -define newline - - -endef - - -# Pass -fPIC if we're building dynamic libraries. -BUILD_SHARED_LIBS ?= 1 - -ifeq ($(BUILD_SHARED_LIBS), 1) - ifdef HOST_CYGWIN - GLOBAL_CFLAGS += -U__STRICT_ANSI__ -D_GNU_SOURCE - GLOBAL_CXXFLAGS += -U__STRICT_ANSI__ -D_GNU_SOURCE - else - GLOBAL_CFLAGS += -fPIC - GLOBAL_CXXFLAGS += -fPIC - endif - ifndef HOST_DARWIN - ifndef HOST_SOLARIS - ifndef HOST_FREEBSD - GLOBAL_LDFLAGS += -Wl,--no-copy-dt-needed-entries - endif - endif - endif - SET_RPATH_TO_LIBS ?= 1 -endif - -# Pass -g if we want debug info. -BUILD_DEBUG ?= 1 - -ifeq ($(BUILD_DEBUG), 1) - GLOBAL_CFLAGS += -g - GLOBAL_CXXFLAGS += -g -endif - - -include mk/build-dir.mk -include mk/install-dirs.mk -include mk/functions.mk -include mk/tracing.mk -include mk/clean.mk -include mk/install.mk -include mk/libraries.mk -include mk/programs.mk -include mk/patterns.mk -include mk/templates.mk -include mk/cxx-big-literal.mk -include mk/tests.mk -include mk/compilation-database.mk - - -# Include all sub-Makefiles. -define include-sub-makefile - d := $$(patsubst %/,%,$$(dir $(1))) - include $(1) -endef - -$(foreach mf, $(makefiles), $(eval $(call include-sub-makefile,$(mf)))) - - -# Instantiate stuff. -$(foreach lib, $(libraries), $(eval $(call build-library,$(lib)))) -$(foreach prog, $(programs), $(eval $(call build-program,$(prog)))) -$(foreach script, $(bin-scripts), $(eval $(call install-program-in,$(script),$(bindir)))) -$(foreach script, $(bin-scripts), $(eval programs-list += $(script))) -$(foreach script, $(noinst-scripts), $(eval programs-list += $(script))) -$(foreach template, $(template-files), $(eval $(call instantiate-template,$(template)))) -$(foreach test, $(install-tests), \ - $(eval $(call run-test,$(test))) \ - $(eval installcheck: $(test).test)) -$(foreach test-group, $(install-tests-groups), \ - $(eval $(call run-test-group,$(test-group))) \ - $(eval installcheck: $(test-group).test-group) \ - $(foreach test, $($(test-group)-tests), \ - $(eval $(call run-test,$(test))) \ - $(eval $(test-group).test-group: $(test).test))) - -# Compilation database. -$(foreach lib, $(libraries), $(eval $(call write-compile-commands,$(lib)))) -$(foreach prog, $(programs), $(eval $(call write-compile-commands,$(prog)))) - -compile_commands.json: $(compile-commands-json-files) - @jq --slurp '.' $^ >$@ - -# Include makefiles requiring built programs. -$(foreach mf, $(makefiles-late), $(eval $(call include-sub-makefile,$(mf)))) - - -$(foreach file, $(man-pages), $(eval $(call install-data-in, $(file), $(mandir)/man$(patsubst .%,%,$(suffix $(file)))))) - - -.PHONY: default all man help - -all: $(programs-list) $(libs-list) $(man-pages) - -man: $(man-pages) - - -help: - @echo "The following targets are available:" - @echo "" - @echo " default: Build default targets" -ifdef man-pages - @echo " man: Generate manual pages" -endif - @$(print-top-help) -ifdef programs-list - @echo "" - @echo "The following programs can be built:" - @echo "" - @for i in $(programs-list); do echo " $$i"; done -endif -ifdef libs-list - @echo "" - @echo "The following libraries can be built:" - @echo "" - @for i in $(libs-list); do echo " $$i"; done -endif -ifdef install-tests-groups - @echo "" - @echo "The following groups of functional tests can be run:" - @echo "" - @for i in $(install-tests-groups); do echo " $$i.test-group"; done - @echo "" - @echo "(installcheck includes tests in test groups too.)" -endif - @echo "" - @echo "The following variables control the build:" - @echo "" - @echo " BUILD_SHARED_LIBS ($(BUILD_SHARED_LIBS)): Whether to build shared libraries" - @echo " BUILD_DEBUG ($(BUILD_DEBUG)): Whether to include debug symbols" - @echo " CC ($(CC)): C compiler to be used" - @echo " CFLAGS: Flags for the C compiler" - @echo " CXX ($(CXX)): C++ compiler to be used" - @echo " CXXFLAGS: Flags for the C++ compiler" - @echo " CPPFLAGS: C preprocessor flags, used for both CC and CXX" - @$(print-var-help) diff --git a/mk/libraries.mk b/mk/libraries.mk deleted file mode 100644 index a7848ba35..000000000 --- a/mk/libraries.mk +++ /dev/null @@ -1,173 +0,0 @@ -libs-list := - -ifdef HOST_DARWIN - SO_EXT = dylib -else - ifdef HOST_WINDOWS - SO_EXT = dll - else - SO_EXT = so - endif -endif - -ifdef HOST_UNIX - THREAD_LDFLAGS = -pthread -else - THREAD_LDFLAGS = -endif - -# Build a library with symbolic name $(1). The library is defined by -# various variables prefixed by ‘$(1)_’: -# -# - $(1)_NAME: the name of the library (e.g. ‘libfoo’); defaults to -# $(1). -# -# - $(1)_DIR: the directory where the (non-installed) library will be -# placed. -# -# - $(1)_SOURCES: the source files of the library. -# -# - $(1)_CFLAGS: additional C compiler flags. -# -# - $(1)_CXXFLAGS: additional C++ compiler flags. -# -# - $(1)_ORDER_AFTER: a set of targets on which the object files of -# this libraries will have an order-only dependency. -# -# - $(1)_LIBS: the symbolic names of other libraries on which this -# library depends. -# -# - $(1)_ALLOW_UNDEFINED: if set, the library is allowed to have -# undefined symbols. Has no effect for static libraries. -# -# - $(1)_LDFLAGS: additional linker flags. -# -# - $(1)_LDFLAGS_PROPAGATED: additional linker flags, also propagated -# to the linking of programs/libraries that use this library. -# -# - $(1)_FORCE_INSTALL: if defined, the library will be installed even -# if it's not needed (i.e. dynamically linked) by a program. -# -# - $(1)_INSTALL_DIR: the directory where the library will be -# installed. Defaults to $(libdir). -# -# - $(1)_EXCLUDE_FROM_LIBRARY_LIST: if defined, the library will not -# be automatically marked as a dependency of the top-level all -# target andwill not be listed in the make help output. This is -# useful for libraries built solely for testing, for example. -# -# - BUILD_SHARED_LIBS: if equal to ‘1’, a dynamic library will be -# built, otherwise a static library. -define build-library - $(1)_NAME ?= $(1) - _d := $(buildprefix)$$(strip $$($(1)_DIR)) - _srcs := $$(sort $$(foreach src, $$($(1)_SOURCES), $$(src))) - $(1)_OBJS := $$(addprefix $(buildprefix), $$(addsuffix .o, $$(basename $$(_srcs)))) - _libs := $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_PATH)) - - ifdef HOST_WINDOWS - $(1)_INSTALL_DIR ?= $$(bindir) - else - $(1)_INSTALL_DIR ?= $$(libdir) - endif - - $(1)_LDFLAGS_USE := - $(1)_LDFLAGS_USE_INSTALLED := - $(1)_LIB_CLOSURE := $(1) - - $$(eval $$(call create-dir, $$(_d))) - - ifeq ($(BUILD_SHARED_LIBS), 1) - - ifdef $(1)_ALLOW_UNDEFINED - ifdef HOST_DARWIN - $(1)_LDFLAGS += -undefined suppress -flat_namespace - endif - else - ifndef HOST_DARWIN - ifndef HOST_WINDOWS - ifndef HOST_OPENBSD - $(1)_LDFLAGS += -Wl,-z,defs - endif - endif - endif - endif - - ifndef HOST_DARWIN - $(1)_LDFLAGS += -Wl,-soname=$$($(1)_NAME).$(SO_EXT) - endif - - $(1)_PATH := $$(_d)/$$($(1)_NAME).$(SO_EXT) - - $$($(1)_PATH): $$($(1)_OBJS) $$(_libs) | $$(_d)/ - +$$(trace-ld) $(CXX) -o $$(abspath $$@) -shared $$(LDFLAGS) $$(GLOBAL_LDFLAGS) $$($(1)_OBJS) $$($(1)_LDFLAGS) $$($(1)_LDFLAGS_PROPAGATED) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_LDFLAGS_USE)) $$($(1)_LDFLAGS_UNINSTALLED) - - ifndef HOST_DARWIN - $(1)_LDFLAGS_USE += -Wl,-rpath,$$(abspath $$(_d)) - endif - $(1)_LDFLAGS_USE += -L$$(_d) -l$$(patsubst lib%,%,$$(strip $$($(1)_NAME))) - - $(1)_INSTALL_PATH := $(DESTDIR)$$($(1)_INSTALL_DIR)/$$($(1)_NAME).$(SO_EXT) - - _libs_final := $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_INSTALL_PATH)) - - $$(eval $$(call create-dir, $$($(1)_INSTALL_DIR))) - - $$($(1)_INSTALL_PATH): $$($(1)_OBJS) $$(_libs_final) | $(DESTDIR)$$($(1)_INSTALL_DIR)/ - +$$(trace-ld) $(CXX) -o $$@ -shared $$(LDFLAGS) $$(GLOBAL_LDFLAGS) $$($(1)_OBJS) $$($(1)_LDFLAGS) $$($(1)_LDFLAGS_PROPAGATED) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_LDFLAGS_USE_INSTALLED)) - - $(1)_LDFLAGS_USE_INSTALLED += -L$$(DESTDIR)$$($(1)_INSTALL_DIR) -l$$(patsubst lib%,%,$$(strip $$($(1)_NAME))) - ifndef HOST_DARWIN - ifeq ($(SET_RPATH_TO_LIBS), 1) - $(1)_LDFLAGS_USE_INSTALLED += -Wl,-rpath,$$($(1)_INSTALL_DIR) - else - $(1)_LDFLAGS_USE_INSTALLED += -Wl,-rpath-link,$$($(1)_INSTALL_DIR) - endif - endif - - ifdef $(1)_FORCE_INSTALL - install: $$($(1)_INSTALL_PATH) - endif - - else - - $(1)_PATH := $$(_d)/$$($(1)_NAME).a - - $$($(1)_PATH): $$($(1)_OBJS) | $$(_d)/ - $$(trace-ld) $(LD) $$(ifndef $(HOST_DARWIN),-U) -r -o $$(_d)/$$($(1)_NAME).o $$^ - $$(trace-ar) $(AR) crs $$@ $$(_d)/$$($(1)_NAME).o - - $(1)_LDFLAGS_USE += $$($(1)_PATH) $$($(1)_LDFLAGS) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_LDFLAGS_USE)) - - $(1)_INSTALL_PATH := $$(libdir)/$$($(1)_NAME).a - - $(1)_LIB_CLOSURE += $$($(1)_LIBS) - - endif - - $(1)_LDFLAGS_USE += $$($(1)_LDFLAGS_PROPAGATED) - $(1)_LDFLAGS_USE_INSTALLED += $$($(1)_LDFLAGS_PROPAGATED) - - # Propagate CFLAGS and CXXFLAGS to the individual object files. - $$(foreach obj, $$($(1)_OBJS), $$(eval $$(obj)_CFLAGS=$$($(1)_CFLAGS))) - $$(foreach obj, $$($(1)_OBJS), $$(eval $$(obj)_CXXFLAGS=$$($(1)_CXXFLAGS))) - - # Make each object file depend on the common dependencies. - $$(foreach obj, $$($(1)_OBJS), $$(eval $$(obj): $$($(1)_COMMON_DEPS) $$(GLOBAL_COMMON_DEPS))) - - # Make each object file have order-only dependencies on the common - # order-only dependencies. This includes the order-only dependencies - # of libraries we're depending on. - $(1)_ORDER_AFTER_CLOSED = $$($(1)_ORDER_AFTER) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_ORDER_AFTER_CLOSED)) - - $$(foreach obj, $$($(1)_OBJS), $$(eval $$(obj): | $$($(1)_ORDER_AFTER_CLOSED) $$(GLOBAL_ORDER_AFTER))) - - # Include .dep files, if they exist. - $(1)_DEPS := $$(foreach fn, $$($(1)_OBJS), $$(call filename-to-dep, $$(fn))) - -include $$($(1)_DEPS) - - ifndef $(1)_EXCLUDE_FROM_LIBRARY_LIST - libs-list += $$($(1)_PATH) - endif - clean-files += $$(_d)/*.a $$(_d)/*.$(SO_EXT) $$(_d)/*.o $$(_d)/.*.dep $$($(1)_DEPS) $$($(1)_OBJS) -endef diff --git a/mk/patterns.mk b/mk/patterns.mk deleted file mode 100644 index 4caa2039e..000000000 --- a/mk/patterns.mk +++ /dev/null @@ -1,41 +0,0 @@ - -# These are the complete command lines we use to compile C and C++ files. -# - $< is the source file. -# - $1 is the object file to create. -CC_CMD=$(CC) -o $1 -c $< $(CPPFLAGS) $(GLOBAL_CFLAGS) $(CFLAGS) $($1_CFLAGS) -MMD -MF $(call filename-to-dep,$1) -MP -CXX_CMD=$(CXX) -o $1 -c $< $(CPPFLAGS) $(GLOBAL_CXXFLAGS_PCH) $(GLOBAL_CXXFLAGS) $(CXXFLAGS) $($1_CXXFLAGS) $(ERROR_SWITCH_ENUM) -MMD -MF $(call filename-to-dep,$1) -MP - -# We use COMPILE_COMMANDS_JSON_CMD to turn a compilation command (like CC_CMD -# or CXX_CMD above) into a comple_commands.json file. We rely on bash native -# word splitting to define the positional arguments. -# - $< is the source file being compiled. -COMPILE_COMMANDS_JSON_CMD=jq --null-input '{ directory: $$ENV.PWD, file: "$<", arguments: $$ARGS.positional }' --args -- - - -$(buildprefix)%.o: %.cc - @mkdir -p "$(dir $@)" - $(trace-cxx) $(call CXX_CMD,$@) - -$(buildprefix)%.o: %.cpp - @mkdir -p "$(dir $@)" - $(trace-cxx) $(call CXX_CMD,$@) - -$(buildprefix)%.o: %.c - @mkdir -p "$(dir $@)" - $(trace-cc) $(call CC_CMD,$@) - -# In the following we need to replace the .compile_commands.json extension in $@ with .o -# to make the object file. This is needed because CC_CMD and CXX_CMD do further expansions -# based on the object file name (i.e. *_CXXFLAGS and filename-to-dep). - -$(buildprefix)%.compile_commands.json: %.cc - @mkdir -p "$(dir $@)" - $(trace-jq) $(COMPILE_COMMANDS_JSON_CMD) $(call CXX_CMD,$(@:.compile_commands.json=.o)) > $@ - -$(buildprefix)%.compile_commands.json: %.cpp - @mkdir -p "$(dir $@)" - $(trace-jq) $(COMPILE_COMMANDS_JSON_CMD) $(call CXX_CMD,$(@:.compile_commands.json=.o)) > $@ - -$(buildprefix)%.compile_commands.json: %.c - @mkdir -p "$(dir $@)" - $(trace-jq) $(COMPILE_COMMANDS_JSON_CMD) $(call CC_CMD,$(@:.compile_commands.json=.o)) > $@ diff --git a/mk/platform.mk b/mk/platform.mk deleted file mode 100644 index 3c4fff780..000000000 --- a/mk/platform.mk +++ /dev/null @@ -1,40 +0,0 @@ -ifdef HOST_OS - HOST_KERNEL = $(firstword $(subst -, ,$(HOST_OS))) - ifeq ($(patsubst mingw%,,$(HOST_KERNEL)),) - HOST_MINGW = 1 - HOST_WINDOWS = 1 - endif - ifeq ($(HOST_KERNEL), cygwin) - HOST_CYGWIN = 1 - HOST_WINDOWS = 1 - HOST_UNIX = 1 - endif - ifeq ($(patsubst darwin%,,$(HOST_KERNEL)),) - HOST_DARWIN = 1 - HOST_UNIX = 1 - endif - ifeq ($(patsubst freebsd%,,$(HOST_KERNEL)),) - HOST_FREEBSD = 1 - HOST_UNIX = 1 - endif - ifeq ($(patsubst netbsd%,,$(HOST_KERNEL)),) - HOST_NETBSD = 1 - HOST_UNIX = 1 - endif - ifeq ($(patsubst openbsd%,,$(HOST_KERNEL)),) - HOST_OPENBSD = 1 - HOST_UNIX = 1 - endif - ifeq ($(HOST_KERNEL), linux) - HOST_LINUX = 1 - HOST_UNIX = 1 - endif - ifeq ($(patsubst solaris%,,$(HOST_KERNEL)),) - HOST_SOLARIS = 1 - HOST_UNIX = 1 - endif - ifeq ($(HOST_KERNEL), gnu) - HOST_HURD = 1 - HOST_UNIX = 1 - endif -endif diff --git a/mk/precompiled-headers.mk b/mk/precompiled-headers.mk deleted file mode 100644 index f2803eb79..000000000 --- a/mk/precompiled-headers.mk +++ /dev/null @@ -1,21 +0,0 @@ -PRECOMPILE_HEADERS ?= 0 - -print-var-help += \ - echo " PRECOMPILE_HEADERS ($(PRECOMPILE_HEADERS)): Whether to use precompiled headers to speed up the build"; - -GCH = $(buildprefix)precompiled-headers.h.gch - -$(GCH): precompiled-headers.h - @rm -f $@ - @mkdir -p "$(dir $@)" - $(trace-gen) $(CXX) -c -x c++-header -o $@ $< $(GLOBAL_CXXFLAGS) $(GCH_CXXFLAGS) - -clean-files += $(GCH) - -ifeq ($(PRECOMPILE_HEADERS), 1) - - GLOBAL_CXXFLAGS_PCH += -include $(buildprefix)precompiled-headers.h -Winvalid-pch - - GLOBAL_ORDER_AFTER += $(GCH) - -endif diff --git a/mk/programs.mk b/mk/programs.mk deleted file mode 100644 index 623caaf55..000000000 --- a/mk/programs.mk +++ /dev/null @@ -1,98 +0,0 @@ -programs-list := - -ifdef HOST_WINDOWS - EXE_EXT = .exe -else - EXE_EXT = -endif - -# Build a program with symbolic name $(1). The program is defined by -# various variables prefixed by ‘$(1)_’: -# -# - $(1)_NAME: the name of the program (e.g. ‘foo’); defaults to -# $(1). -# -# - $(1)_DIR: the directory where the (non-installed) program will be -# placed. -# -# - $(1)_SOURCES: the source files of the program. -# -# - $(1)_CFLAGS: additional C compiler flags. -# -# - $(1)_CXXFLAGS: additional C++ compiler flags. -# -# - $(1)_ORDER_AFTER: a set of targets on which the object files of -# this program will have an order-only dependency. -# -# - $(1)_LIBS: the symbolic names of libraries on which this program -# depends. -# -# - $(1)_LDFLAGS: additional linker flags. -# -# - $(1)_INSTALL_DIR: the directory where the program will be -# installed; defaults to $(bindir). -define build-program - $(1)_NAME ?= $(1) - _d := $(buildprefix)$$($(1)_DIR) - _srcs := $$(sort $$(foreach src, $$($(1)_SOURCES), $$(src))) - $(1)_OBJS := $$(addprefix $(buildprefix), $$(addsuffix .o, $$(basename $$(_srcs)))) - _libs := $$(foreach lib, $$($(1)_LIBS), $$(foreach lib2, $$($$(lib)_LIB_CLOSURE), $$($$(lib2)_PATH))) - $(1)_PATH := $$(_d)/$$($(1)_NAME)$(EXE_EXT) - - $$(eval $$(call create-dir, $$(_d))) - - $$($(1)_PATH): $$($(1)_OBJS) $$(_libs) | $$(_d)/ - +$$(trace-ld) $(CXX) -o $$@ $$(LDFLAGS) $$(GLOBAL_LDFLAGS) $$($(1)_OBJS) $$($(1)_LDFLAGS) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_LDFLAGS_USE)) - - $(1)_INSTALL_DIR ?= $$(bindir) - - ifdef $(1)_INSTALL_DIR - - $(1)_INSTALL_PATH := $$($(1)_INSTALL_DIR)/$$($(1)_NAME)$(EXE_EXT) - - $$(eval $$(call create-dir, $$($(1)_INSTALL_DIR))) - - install: $(DESTDIR)$$($(1)_INSTALL_PATH) - - ifeq ($(BUILD_SHARED_LIBS), 1) - - _libs_final := $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_INSTALL_PATH)) - - $(DESTDIR)$$($(1)_INSTALL_PATH): $$($(1)_OBJS) $$(_libs_final) | $(DESTDIR)$$($(1)_INSTALL_DIR)/ - +$$(trace-ld) $(CXX) -o $$@ $$(LDFLAGS) $$(GLOBAL_LDFLAGS) $$($(1)_OBJS) $$($(1)_LDFLAGS) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_LDFLAGS_USE_INSTALLED)) - - else - - $(DESTDIR)$$($(1)_INSTALL_PATH): $$($(1)_PATH) | $(DESTDIR)$$($(1)_INSTALL_DIR)/ - +$$(trace-install) install -t $(DESTDIR)$$($(1)_INSTALL_DIR) $$< - - endif - endif - - # Propagate CFLAGS and CXXFLAGS to the individual object files. - $$(foreach obj, $$($(1)_OBJS), $$(eval $$(obj)_CFLAGS=$$($(1)_CFLAGS))) - $$(foreach obj, $$($(1)_OBJS), $$(eval $$(obj)_CXXFLAGS=$$($(1)_CXXFLAGS))) - - # Make each object file depend on the common dependencies. - $$(foreach obj, $$($(1)_OBJS), $$(eval $$(obj): $$($(1)_COMMON_DEPS) $$(GLOBAL_COMMON_DEPS))) - - # Make each object file have order-only dependencies on the common - # order-only dependencies. This includes the order-only dependencies - # of libraries we're depending on. - $(1)_ORDER_AFTER_CLOSED = $$($(1)_ORDER_AFTER) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_ORDER_AFTER_CLOSED)) - - $$(foreach obj, $$($(1)_OBJS), $$(eval $$(obj): | $$($(1)_ORDER_AFTER_CLOSED) $$(GLOBAL_ORDER_AFTER))) - - # Include .dep files, if they exist. - $(1)_DEPS := $$(foreach fn, $$($(1)_OBJS), $$(call filename-to-dep, $$(fn))) - -include $$($(1)_DEPS) - - programs-list += $$($(1)_PATH) - clean-files += $$($(1)_PATH) $$(_d)/*.o $$(_d)/.*.dep $$($(1)_DEPS) $$($(1)_OBJS) - - # Phony target to run this program (typically as a dependency of 'check'). - .PHONY: $(1)_RUN - $(1)_RUN: $$($(1)_PATH) - $(trace-test) $$($(1)_ENV) $$($(1)_PATH) - -endef diff --git a/mk/run-test.sh b/mk/run-test.sh deleted file mode 100755 index 7f9f1d5f8..000000000 --- a/mk/run-test.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env bash - -set -eu -o pipefail - -red="" -green="" -yellow="" -normal="" - -test=$1 - -dir="$(dirname "${BASH_SOURCE[0]}")" -source "$dir/common-test.sh" - -post_run_msg="ran test $test..." -if [ -t 1 ]; then - red="" - green="" - yellow="" - normal="" -fi - -run_test () { - log="$(run "$test" 2>&1)" && status=0 || status=$? -} - -run_test - -if [[ "$status" = 0 ]]; then - echo "$post_run_msg [${green}PASS$normal]" -elif [[ "$status" = 77 ]]; then - echo "$post_run_msg [${yellow}SKIP$normal]" -else - echo "$post_run_msg [${red}FAIL$normal]" - # shellcheck disable=SC2001 - echo "$log" | sed 's/^/ /' - exit "$status" -fi diff --git a/mk/templates.mk b/mk/templates.mk deleted file mode 100644 index d5dae61c7..000000000 --- a/mk/templates.mk +++ /dev/null @@ -1,19 +0,0 @@ -template-files := - -# Create the file $(1) from $(1).in by running config.status (which -# substitutes all ‘@var@’ variables set by the configure script). -define instantiate-template - - clean-files += $(1) - -endef - -ifneq ($(MAKECMDGOALS), clean) - -$(buildprefix)%.h: %.h.in $(buildprefix)config.status - $(trace-gen) rm -f $@ && cd $(buildprefixrel) && ./config.status --quiet --header=$(@:$(buildprefix)%=%) - -$(buildprefix)%: %.in $(buildprefix)config.status - $(trace-gen) rm -f $@ && cd $(buildprefixrel) && ./config.status --quiet --file=$(@:$(buildprefix)%=%) - -endif diff --git a/mk/tests.mk b/mk/tests.mk deleted file mode 100644 index 0a10f6d3b..000000000 --- a/mk/tests.mk +++ /dev/null @@ -1,30 +0,0 @@ -# Run program $1 as part of ‘make installcheck’. - -test-deps = - -define run-bash - - .PHONY: $1 - $1: $2 - @env BASH=$(bash) $(bash) $3 < /dev/null - -endef - -define run-test - - $(eval $(call run-bash,$1.test,$1 $(test-deps),mk/run-test.sh $1)) - $(eval $(call run-bash,$1.test-debug,$1 $(test-deps),mk/debug-test.sh $1)) - -endef - -define run-test-group - - .PHONY: $1.test-group - -endef - -.PHONY: check installcheck - -print-top-help += \ - echo " check: Run unit tests"; \ - echo " installcheck: Run functional tests"; diff --git a/mk/tracing.mk b/mk/tracing.mk deleted file mode 100644 index 09db1e617..000000000 --- a/mk/tracing.mk +++ /dev/null @@ -1,18 +0,0 @@ -V ?= 0 - -ifeq ($(V), 0) - - trace-gen = @echo " GEN " $@; - trace-cc = @echo " CC " $@; - trace-cxx = @echo " CXX " $@; - trace-ld = @echo " LD " $@; - trace-ar = @echo " AR " $@; - trace-install = @echo " INST " $@; - trace-mkdir = @echo " MKDIR " $@; - trace-test = @echo " TEST " $@; - trace-sh = @echo " SH " $@; - trace-jq = @echo " JQ " $@; - - suppress = @ - -endif diff --git a/package.nix b/package.nix deleted file mode 100644 index 8cbe325e9..000000000 --- a/package.nix +++ /dev/null @@ -1,366 +0,0 @@ -{ lib -, stdenv -, releaseTools -, autoconf-archive -, autoreconfHook -, aws-sdk-cpp -, boehmgc -, nlohmann_json -, bison -, boost -, brotli -, bzip2 -, curl -, editline -, readline -, flex -, git -, gtest -, jq -, libarchive -, libcpuid -, libgit2 -, libseccomp -, libsodium -, man -, darwin -, lowdown -, mdbook -, mdbook-linkcheck -, mercurial -, openssh -, openssl -, pkg-config -, rapidcheck -, sqlite -, toml11 -, unixtools -, xz - -, busybox-sandbox-shell ? null - -# Configuration Options -#: -# This probably seems like too many degrees of freedom, but it -# faithfully reflects how the underlying configure + make build system -# work. The top-level flake.nix will choose useful combinations of these -# options to CI. - -, pname ? "nix" - -, version -, versionSuffix - -# Whether to build Nix. Useful to skip for tasks like testing existing pre-built versions of Nix -, doBuild ? true - -# Run the unit tests as part of the build. See `installUnitTests` for an -# alternative to this. -, doCheck ? __forDefaults.canRunInstalled - -# Run the functional tests as part of the build. -, doInstallCheck ? test-client != null || __forDefaults.canRunInstalled - -# Check test coverage of Nix. Probably want to use with at least -# one of `doCHeck` or `doInstallCheck` enabled. -, withCoverageChecks ? false - -# Whether to build the regular manual -, enableManual ? __forDefaults.canRunInstalled - -# Whether to use garbage collection for the Nix language evaluator. -# -# If it is disabled, we just leak memory, but this is not as bad as it -# sounds so long as evaluation just takes places within short-lived -# processes. (When the process exits, the memory is reclaimed; it is -# only leaked *within* the process.) -# -# Temporarily disabled on Windows because the `GC_throw_bad_alloc` -# symbol is missing during linking. -# -# Disabled on OpenBSD because of missing `_data_start` symbol while linking -, enableGC ? !stdenv.hostPlatform.isWindows && !stdenv.hostPlatform.isOpenBSD - -# Whether to enable Markdown rendering in the Nix binary. -, enableMarkdown ? !stdenv.hostPlatform.isWindows - -# Which interactive line editor library to use for Nix's repl. -# -# Currently supported choices are: -# -# - editline (default) -# - readline -, readlineFlavor ? if stdenv.hostPlatform.isWindows then "readline" else "editline" - -# Whether to install unit tests. This is useful when cross compiling -# since we cannot run them natively during the build, but can do so -# later. -, installUnitTests ? doBuild && !__forDefaults.canExecuteHost - -# For running the functional tests against a pre-built Nix. Probably -# want to use in conjunction with `doBuild = false;`. -, test-daemon ? null -, test-client ? null - -# Avoid setting things that would interfere with a functioning devShell -, forDevShell ? false - -# Not a real argument, just the only way to approximate let-binding some -# stuff for argument defaults. -, __forDefaults ? { - canExecuteHost = stdenv.buildPlatform.canExecute stdenv.hostPlatform; - canRunInstalled = doBuild && __forDefaults.canExecuteHost; - } -}: - -let - inherit (lib) fileset; - - # selected attributes with defaults, will be used to define some - # things which should instead be gotten via `finalAttrs` in order to - # work with overriding. - attrs = { - inherit doBuild doCheck doInstallCheck; - }; - - mkDerivation = - if withCoverageChecks - then - # TODO support `finalAttrs` args function in - # `releaseTools.coverageAnalysis`. - argsFun: - releaseTools.coverageAnalysis (let args = argsFun args; in args) - else stdenv.mkDerivation; -in - -mkDerivation (finalAttrs: let - - inherit (finalAttrs) - doCheck - doInstallCheck - ; - - doBuild = !finalAttrs.dontBuild; - - # Either running the unit tests during the build, or installing them - # to be run later, requiresthe unit tests to be built. - buildUnitTests = doCheck || installUnitTests; - -in { - inherit pname version; - - src = - let - baseFiles = fileset.fileFilter (f: f.name != ".gitignore") ./.; - in - fileset.toSource { - root = ./.; - fileset = fileset.intersection baseFiles (fileset.unions ([ - # For configure - ./.version - ./configure.ac - ./m4 - # TODO: do we really need README.md? It doesn't seem used in the build. - ./README.md - # This could be put behind a conditional - ./maintainers/local.mk - # For make, regardless of what we are building - ./local.mk - ./Makefile - ./Makefile.config.in - ./mk - (fileset.fileFilter (f: lib.strings.hasPrefix "nix-profile" f.name) ./scripts) - ] ++ lib.optionals doBuild [ - ./doc - ./misc - ./precompiled-headers.h - (fileset.difference ./src ./src/perl) - ./COPYING - ./scripts/local.mk - ] ++ lib.optionals enableManual [ - ./doc/manual - ] ++ lib.optionals doInstallCheck [ - ./tests/functional - ])); - }; - - VERSION_SUFFIX = versionSuffix; - - outputs = [ "out" ] - ++ lib.optional doBuild "dev" - # If we are doing just build or just docs, the one thing will use - # "out". We only need additional outputs if we are doing both. - ++ lib.optional (doBuild && enableManual) "doc" - ++ lib.optional installUnitTests "check" - ++ lib.optional doCheck "testresults" - ; - - nativeBuildInputs = [ - autoconf-archive - autoreconfHook - pkg-config - ] ++ lib.optionals doBuild [ - bison - flex - ] ++ lib.optionals enableManual [ - (lib.getBin lowdown) - mdbook - mdbook-linkcheck - ] ++ lib.optionals doInstallCheck [ - git - mercurial - openssh - ] ++ lib.optionals (doInstallCheck || enableManual) [ - jq # Also for custom mdBook preprocessor. - ] ++ lib.optionals enableManual [ - man - ] ++ lib.optional stdenv.hostPlatform.isStatic unixtools.hexdump - ; - - buildInputs = lib.optionals doBuild ( - [ - brotli - bzip2 - curl - libarchive - libgit2 - libsodium - openssl - sqlite - toml11 - xz - ({ inherit readline editline; }.${readlineFlavor}) - ] ++ lib.optionals enableMarkdown [ - lowdown - ] ++ lib.optionals buildUnitTests [ - gtest - rapidcheck - ] ++ lib.optional stdenv.isLinux libseccomp - ++ lib.optional stdenv.hostPlatform.isDarwin darwin.apple_sdk.libs.sandbox - ++ lib.optional stdenv.hostPlatform.isx86_64 libcpuid - # There have been issues building these dependencies - ++ lib.optional (stdenv.hostPlatform == stdenv.buildPlatform && (stdenv.isLinux || stdenv.isDarwin)) - aws-sdk-cpp - ); - - propagatedBuildInputs = lib.optionals doBuild ([ - boost - nlohmann_json - ] ++ lib.optional enableGC boehmgc - ); - - dontBuild = !attrs.doBuild; - doCheck = attrs.doCheck; - - configureFlags = [ - (lib.enableFeature doBuild "build") - (lib.enableFeature buildUnitTests "unit-tests") - (lib.enableFeature doInstallCheck "functional-tests") - (lib.enableFeature enableManual "doc-gen") - (lib.enableFeature enableGC "gc") - (lib.enableFeature enableMarkdown "markdown") - (lib.enableFeature installUnitTests "install-unit-tests") - (lib.withFeatureAs true "readline-flavor" readlineFlavor) - ] ++ lib.optionals (!forDevShell) [ - "--sysconfdir=/etc" - ] ++ lib.optionals installUnitTests [ - "--with-check-bin-dir=${builtins.placeholder "check"}/bin" - "--with-check-lib-dir=${builtins.placeholder "check"}/lib" - ] ++ lib.optionals (doBuild) [ - "--with-boost=${boost}/lib" - ] ++ lib.optionals (doBuild && stdenv.isLinux) [ - "--with-sandbox-shell=${busybox-sandbox-shell}/bin/busybox" - ] ++ lib.optional (doBuild && stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) - "LDFLAGS=-fuse-ld=gold" - ++ lib.optional (doBuild && stdenv.hostPlatform.isStatic) "--enable-embedded-sandbox-shell" - ; - - enableParallelBuilding = true; - - makeFlags = "profiledir=$(out)/etc/profile.d PRECOMPILE_HEADERS=1"; - - preCheck = '' - mkdir $testresults - ''; - - installTargets = lib.optional doBuild "install"; - - installFlags = "sysconfdir=$(out)/etc"; - - # In this case we are probably just running tests, and so there isn't - # anything to install, we just make an empty directory to signify tests - # succeeded. - installPhase = if finalAttrs.installTargets != [] then null else '' - mkdir -p $out - ''; - - postInstall = lib.optionalString doBuild ( - lib.optionalString stdenv.hostPlatform.isStatic '' - mkdir -p $out/nix-support - echo "file binary-dist $out/bin/nix" >> $out/nix-support/hydra-build-products - '' - ) + lib.optionalString enableManual '' - mkdir -p ''${!outputDoc}/nix-support - echo "doc manual ''${!outputDoc}/share/doc/nix/manual" >> ''${!outputDoc}/nix-support/hydra-build-products - ''; - - # So the check output gets links for DLLs in the out output. - preFixup = lib.optionalString (stdenv.hostPlatform.isWindows && builtins.elem "check" finalAttrs.outputs) '' - ln -s "$check/lib/"*.dll "$check/bin" - ln -s "$out/bin/"*.dll "$check/bin" - ''; - - doInstallCheck = attrs.doInstallCheck; - - installCheckFlags = "sysconfdir=$(out)/etc"; - # Work around buggy detection in stdenv. - installCheckTarget = "installcheck"; - - # Work around weird bug where it doesn't think there is a Makefile. - installCheckPhase = if (!doBuild && doInstallCheck) then '' - runHook preInstallCheck - mkdir -p src/nix-channel - make installcheck -j$NIX_BUILD_CORES -l$NIX_BUILD_CORES - '' else null; - - # Needed for tests if we are not doing a build, but testing existing - # built Nix. - preInstallCheck = - lib.optionalString (! doBuild) '' - mkdir -p src/nix-channel - ''; - - separateDebugInfo = !stdenv.hostPlatform.isStatic; - - # TODO Always true after https://github.com/NixOS/nixpkgs/issues/318564 - strictDeps = !withCoverageChecks; - - hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie"; - - meta = { - platforms = lib.platforms.unix ++ lib.platforms.windows; - mainProgram = "nix"; - broken = !(lib.all (a: a) [ - # We cannot run or install unit tests if we don't build them or - # Nix proper (which they depend on). - (installUnitTests -> doBuild) - (doCheck -> doBuild) - # The build process for the manual currently requires extracting - # data from the Nix executable we are trying to document. - (enableManual -> doBuild) - ]); - }; - -} // lib.optionalAttrs withCoverageChecks { - lcovFilter = [ "*/boost/*" "*-tab.*" ]; - - hardeningDisable = ["fortify"]; - - NIX_CFLAGS_COMPILE = "-DCOVERAGE=1"; - - dontInstall = false; -} // lib.optionalAttrs (test-daemon != null) { - NIX_DAEMON_PACKAGE = test-daemon; -} // lib.optionalAttrs (test-client != null) { - NIX_CLIENT_PACKAGE = test-client; -}) diff --git a/packaging/components.nix b/packaging/components.nix index 5cc0be784..c29e04ae9 100644 --- a/packaging/components.nix +++ b/packaging/components.nix @@ -25,11 +25,6 @@ in version = baseVersion + versionSuffix; inherit versionSuffix; - nix = callPackage ../package.nix { - version = fineVersion; - versionSuffix = fineVersionSuffix; - }; - nix-util = callPackage ../src/libutil/package.nix { }; nix-util-c = callPackage ../src/libutil-c/package.nix { }; nix-util-test-support = callPackage ../src/libutil-test-support/package.nix { }; @@ -66,6 +61,5 @@ in nix-perl-bindings = callPackage ../src/perl/package.nix { }; - # Will replace `nix` once the old build system is gone. - nix-ng = callPackage ../packaging/everything.nix { }; + nix-everything = callPackage ../packaging/everything.nix { }; } diff --git a/packaging/dev-shell.nix b/packaging/dev-shell.nix index 4b2a87632..8ac17f61a 100644 --- a/packaging/dev-shell.nix +++ b/packaging/dev-shell.nix @@ -2,7 +2,7 @@ { pkgs }: -(pkgs.nix.override { forDevShell = true; }).overrideAttrs (attrs: +pkgs.nixComponents.nix-util.overrideAttrs (attrs: let stdenv = pkgs.nixDependencies.stdenv; @@ -88,9 +88,12 @@ in { buildInputs = attrs.buildInputs or [] ++ pkgs.nixComponents.nix-util.buildInputs ++ pkgs.nixComponents.nix-store.buildInputs + ++ pkgs.nixComponents.nix-store-tests.externalBuildInputs ++ pkgs.nixComponents.nix-fetchers.buildInputs ++ pkgs.nixComponents.nix-expr.buildInputs - ++ pkgs.nixComponents.nix-store-tests.externalBuildInputs + ++ pkgs.nixComponents.nix-expr.externalPropagatedBuildInputs + ++ pkgs.nixComponents.nix-cmd.buildInputs + ++ lib.optionals havePerl pkgs.nixComponents.nix-perl-bindings.externalBuildInputs ++ lib.optional havePerl pkgs.perl ; }) diff --git a/packaging/hydra.nix b/packaging/hydra.nix index f47ed80e3..81406a249 100644 --- a/packaging/hydra.nix +++ b/packaging/hydra.nix @@ -32,7 +32,7 @@ let # convention to transpose it, and to transpose it efficiently, we need to # enumerate them manually, so that we don't evaluate unnecessary package sets. forAllPackages = lib.genAttrs [ - "nix" + "nix-everything" "nix-util" "nix-util-c" "nix-util-test-support" @@ -54,7 +54,6 @@ let "nix-cmd" "nix-cli" "nix-functional-tests" - "nix-ng" ]; in { @@ -141,11 +140,11 @@ in # docker image with Nix inside dockerImage = lib.genAttrs linux64BitSystems (system: self.packages.${system}.dockerImage); - # Line coverage analysis. - coverage = nixpkgsFor.x86_64-linux.native.nix.override { - pname = "nix-coverage"; - withCoverageChecks = true; - }; + # # Line coverage analysis. + # coverage = nixpkgsFor.x86_64-linux.native.nix.override { + # pname = "nix-coverage"; + # withCoverageChecks = true; + # }; # Nix's manual manual = nixpkgsFor.x86_64-linux.native.nixComponents.nix-manual; @@ -182,7 +181,7 @@ in import (nixpkgs + "/lib/tests/test-with-nix.nix") { lib = nixpkgsFor.${system}.native.lib; - nix = self.packages.${system}.nix; + nix = self.packages.${system}.nix-cli; pkgs = nixpkgsFor.${system}.native; } ); diff --git a/scripts/local.mk b/scripts/local.mk deleted file mode 100644 index 46255e432..000000000 --- a/scripts/local.mk +++ /dev/null @@ -1,13 +0,0 @@ -nix_noinst_scripts := \ - $(d)/nix-profile.sh - -noinst-scripts += $(nix_noinst_scripts) - -profiledir = $(sysconfdir)/profile.d - -$(eval $(call install-file-as, $(d)/nix-profile.sh, $(profiledir)/nix.sh, 0644)) -$(eval $(call install-file-as, $(d)/nix-profile.fish, $(profiledir)/nix.fish, 0644)) -$(eval $(call install-file-as, $(d)/nix-profile-daemon.sh, $(profiledir)/nix-daemon.sh, 0644)) -$(eval $(call install-file-as, $(d)/nix-profile-daemon.fish, $(profiledir)/nix-daemon.fish, 0644)) - -clean-files += $(nix_noinst_scripts) diff --git a/src/libcmd/local.mk b/src/libcmd/local.mk deleted file mode 100644 index a270333f4..000000000 --- a/src/libcmd/local.mk +++ /dev/null @@ -1,15 +0,0 @@ -libraries += libcmd - -libcmd_NAME = libnixcmd - -libcmd_DIR := $(d) - -libcmd_SOURCES := $(wildcard $(d)/*.cc) - -libcmd_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libstore) $(INCLUDE_libfetchers) $(INCLUDE_libexpr) $(INCLUDE_libflake) $(INCLUDE_libmain) - -libcmd_LDFLAGS = $(EDITLINE_LIBS) $(LOWDOWN_LIBS) $(THREAD_LDFLAGS) - -libcmd_LIBS = libutil libstore libfetchers libflake libexpr libmain - -$(eval $(call install-file-in, $(buildprefix)$(d)/nix-cmd.pc, $(libdir)/pkgconfig, 0644)) diff --git a/src/libcmd/nix-cmd.pc.in b/src/libcmd/nix-cmd.pc.in deleted file mode 100644 index 39575f222..000000000 --- a/src/libcmd/nix-cmd.pc.in +++ /dev/null @@ -1,9 +0,0 @@ -prefix=@prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: Nix -Description: Nix Package Manager -Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lnixcmd -Cflags: -I${includedir}/nix -std=c++2a diff --git a/src/libexpr-c/local.mk b/src/libexpr-c/local.mk deleted file mode 100644 index 227a4095b..000000000 --- a/src/libexpr-c/local.mk +++ /dev/null @@ -1,25 +0,0 @@ -libraries += libexprc - -libexprc_NAME = libnixexprc - -libexprc_DIR := $(d) - -libexprc_SOURCES := \ - $(wildcard $(d)/*.cc) \ - -# Not just for this library itself, but also for downstream libraries using this library - -INCLUDE_libexprc := -I $(d) -libexprc_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libutilc) \ - $(INCLUDE_libfetchers) \ - $(INCLUDE_libstore) $(INCLUDE_libstorec) \ - $(INCLUDE_libexpr) $(INCLUDE_libexprc) - -libexprc_LIBS = libutil libutilc libstore libstorec libfetchers libexpr - -libexprc_LDFLAGS += $(THREAD_LDFLAGS) - -$(eval $(call install-file-in, $(d)/nix-expr-c.pc, $(libdir)/pkgconfig, 0644)) - -libexprc_FORCE_INSTALL := 1 - diff --git a/src/libexpr-c/nix-expr-c.pc.in b/src/libexpr-c/nix-expr-c.pc.in deleted file mode 100644 index 06897064d..000000000 --- a/src/libexpr-c/nix-expr-c.pc.in +++ /dev/null @@ -1,10 +0,0 @@ -prefix=@prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: Nix -Description: Nix Language Evaluator - C API -Version: @PACKAGE_VERSION@ -Requires: nix-store-c -Libs: -L${libdir} -lnixexprc -Cflags: -I${includedir}/nix diff --git a/src/libexpr-test-support/local.mk b/src/libexpr-test-support/local.mk deleted file mode 100644 index 0501de33c..000000000 --- a/src/libexpr-test-support/local.mk +++ /dev/null @@ -1,23 +0,0 @@ -libraries += libexpr-test-support - -libexpr-test-support_NAME = libnixexpr-test-support - -libexpr-test-support_DIR := $(d) - -ifeq ($(INSTALL_UNIT_TESTS), yes) - libexpr-test-support_INSTALL_DIR := $(checklibdir) -else - libexpr-test-support_INSTALL_DIR := -endif - -libexpr-test-support_SOURCES := \ - $(wildcard $(d)/tests/*.cc) \ - $(wildcard $(d)/tests/value/*.cc) - -libexpr-test-support_CXXFLAGS += $(libexpr-tests_EXTRA_INCLUDES) - -libexpr-test-support_LIBS = \ - libstore-test-support libutil-test-support \ - libexpr libstore libutil - -libexpr-test-support_LDFLAGS := $(THREAD_LDFLAGS) -lrapidcheck diff --git a/src/libexpr-tests/local.mk b/src/libexpr-tests/local.mk deleted file mode 100644 index 79583a9ee..000000000 --- a/src/libexpr-tests/local.mk +++ /dev/null @@ -1,45 +0,0 @@ -check: libexpr-tests_RUN - -programs += libexpr-tests - -libexpr-tests_NAME := libnixexpr-tests - -libexpr-tests_ENV := _NIX_TEST_UNIT_DATA=$(d)/data GTEST_OUTPUT=xml:$$testresults/libexpr-tests.xml - -libexpr-tests_DIR := $(d) - -ifeq ($(INSTALL_UNIT_TESTS), yes) - libexpr-tests_INSTALL_DIR := $(checkbindir) -else - libexpr-tests_INSTALL_DIR := -endif - -libexpr-tests_SOURCES := \ - $(wildcard $(d)/*.cc) \ - $(wildcard $(d)/value/*.cc) \ - $(wildcard $(d)/flake/*.cc) - -libexpr-tests_EXTRA_INCLUDES = \ - -I src/libexpr-test-support \ - -I src/libstore-test-support \ - -I src/libutil-test-support \ - $(INCLUDE_libexpr) \ - $(INCLUDE_libexprc) \ - $(INCLUDE_libfetchers) \ - $(INCLUDE_libstore) \ - $(INCLUDE_libstorec) \ - $(INCLUDE_libutil) \ - $(INCLUDE_libutilc) - -libexpr-tests_CXXFLAGS += $(libexpr-tests_EXTRA_INCLUDES) - -libexpr-tests_LIBS = \ - libexpr-test-support libstore-test-support libutil-test-support \ - libexpr libexprc libfetchers libstore libstorec libutil libutilc - -libexpr-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) -lgmock - -ifdef HOST_WINDOWS - # Increase the default reserved stack size to 65 MB so Nix doesn't run out of space - libexpr-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024))) -endif diff --git a/src/libexpr/local.mk b/src/libexpr/local.mk deleted file mode 100644 index 68518e184..000000000 --- a/src/libexpr/local.mk +++ /dev/null @@ -1,50 +0,0 @@ -libraries += libexpr - -libexpr_NAME = libnixexpr - -libexpr_DIR := $(d) - -libexpr_SOURCES := \ - $(wildcard $(d)/*.cc) \ - $(wildcard $(d)/value/*.cc) \ - $(wildcard $(d)/primops/*.cc) \ - $(d)/lexer-tab.cc \ - $(d)/parser-tab.cc -# Not just for this library itself, but also for downstream libraries using this library - -INCLUDE_libexpr := -I $(d) - -libexpr_CXXFLAGS += \ - $(INCLUDE_libutil) $(INCLUDE_libstore) $(INCLUDE_libfetchers) $(INCLUDE_libexpr) \ - -DGC_THREADS - -libexpr_LIBS = libutil libstore libfetchers - -libexpr_LDFLAGS += -lboost_context $(THREAD_LDFLAGS) -ifdef HOST_LINUX - libexpr_LDFLAGS += -ldl -endif - -# The dependency on libgc must be propagated (i.e. meaning that -# programs/libraries that use libexpr must explicitly pass -lgc), -# because inline functions in libexpr's header files call libgc. -libexpr_LDFLAGS_PROPAGATED = $(BDW_GC_LIBS) - -libexpr_ORDER_AFTER := $(d)/parser-tab.cc $(d)/parser-tab.hh $(d)/lexer-tab.cc $(d)/lexer-tab.hh - -$(d)/parser-tab.cc $(d)/parser-tab.hh: $(d)/parser.y - $(trace-gen) bison -v -o $(libexpr_DIR)/parser-tab.cc $< -d - -$(d)/lexer-tab.cc $(d)/lexer-tab.hh: $(d)/lexer.l - $(trace-gen) flex --outfile $(libexpr_DIR)/lexer-tab.cc --header-file=$(libexpr_DIR)/lexer-tab.hh $< - -clean-files += $(d)/parser-tab.cc $(d)/parser-tab.hh $(d)/lexer-tab.cc $(d)/lexer-tab.hh - -$(eval $(call install-file-in, $(buildprefix)$(d)/nix-expr.pc, $(libdir)/pkgconfig, 0644)) - -$(foreach i, $(wildcard src/libexpr/value/*.hh), \ - $(eval $(call install-file-in, $(i), $(includedir)/nix/value, 0644))) - -$(d)/primops.cc: $(d)/imported-drv-to-derivation.nix.gen.hh - -$(d)/eval.cc: $(d)/primops/derivation.nix.gen.hh $(d)/fetchurl.nix.gen.hh $(d)/call-flake.nix.gen.hh diff --git a/src/libexpr/nix-expr.pc.in b/src/libexpr/nix-expr.pc.in deleted file mode 100644 index 60ffb5dba..000000000 --- a/src/libexpr/nix-expr.pc.in +++ /dev/null @@ -1,10 +0,0 @@ -prefix=@prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: Nix -Description: Nix Package Manager -Version: @PACKAGE_VERSION@ -Requires: nix-store bdw-gc -Libs: -L${libdir} -lnixexpr -Cflags: -I${includedir}/nix -std=c++2a diff --git a/src/libexpr/package.nix b/src/libexpr/package.nix index ca1f8bf21..d97e7f3a8 100644 --- a/src/libexpr/package.nix +++ b/src/libexpr/package.nix @@ -71,6 +71,10 @@ mkMesonLibrary (finalAttrs: { nix-util nix-store nix-fetchers + ] ++ finalAttrs.passthru.externalPropagatedBuildInputs; + + # Hack for sake of the dev shell + passthru.externalPropagatedBuildInputs = [ boost nlohmann_json ] ++ lib.optional enableGC boehmgc; diff --git a/src/libfetchers-tests/local.mk b/src/libfetchers-tests/local.mk deleted file mode 100644 index 5c90f1fc7..000000000 --- a/src/libfetchers-tests/local.mk +++ /dev/null @@ -1,37 +0,0 @@ -check: libfetchers-tests_RUN - -programs += libfetchers-tests - -libfetchers-tests_NAME = libnixfetchers-tests - -libfetchers-tests_ENV := _NIX_TEST_UNIT_DATA=$(d)/data GTEST_OUTPUT=xml:$$testresults/libfetchers-tests.xml - -libfetchers-tests_DIR := $(d) - -ifeq ($(INSTALL_UNIT_TESTS), yes) - libfetchers-tests_INSTALL_DIR := $(checkbindir) -else - libfetchers-tests_INSTALL_DIR := -endif - -libfetchers-tests_SOURCES := $(wildcard $(d)/*.cc) - -libfetchers-tests_EXTRA_INCLUDES = \ - -I src/libstore-test-support \ - -I src/libutil-test-support \ - $(INCLUDE_libfetchers) \ - $(INCLUDE_libstore) \ - $(INCLUDE_libutil) - -libfetchers-tests_CXXFLAGS += $(libfetchers-tests_EXTRA_INCLUDES) - -libfetchers-tests_LIBS = \ - libstore-test-support libutil-test-support \ - libfetchers libstore libutil - -libfetchers-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) $(LIBGIT2_LIBS) - -ifdef HOST_WINDOWS - # Increase the default reserved stack size to 65 MB so Nix doesn't run out of space - libfetchers-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024))) -endif diff --git a/src/libfetchers/local.mk b/src/libfetchers/local.mk deleted file mode 100644 index e229a0993..000000000 --- a/src/libfetchers/local.mk +++ /dev/null @@ -1,17 +0,0 @@ -libraries += libfetchers - -libfetchers_NAME = libnixfetchers - -libfetchers_DIR := $(d) - -libfetchers_SOURCES := $(wildcard $(d)/*.cc) - -# Not just for this library itself, but also for downstream libraries using this library - -INCLUDE_libfetchers := -I $(d) - -libfetchers_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libstore) $(INCLUDE_libfetchers) - -libfetchers_LDFLAGS += $(THREAD_LDFLAGS) $(LIBGIT2_LIBS) -larchive - -libfetchers_LIBS = libutil libstore diff --git a/src/libflake-tests/local.mk b/src/libflake-tests/local.mk deleted file mode 100644 index 8599b43f6..000000000 --- a/src/libflake-tests/local.mk +++ /dev/null @@ -1,43 +0,0 @@ -check: libflake-tests_RUN - -programs += libflake-tests - -libflake-tests_NAME := libnixflake-tests - -libflake-tests_ENV := _NIX_TEST_UNIT_DATA=$(d)/data GTEST_OUTPUT=xml:$$testresults/libflake-tests.xml - -libflake-tests_DIR := $(d) - -ifeq ($(INSTALL_UNIT_TESTS), yes) - libflake-tests_INSTALL_DIR := $(checkbindir) -else - libflake-tests_INSTALL_DIR := -endif - -libflake-tests_SOURCES := \ - $(wildcard $(d)/*.cc) \ - $(wildcard $(d)/value/*.cc) \ - $(wildcard $(d)/flake/*.cc) - -libflake-tests_EXTRA_INCLUDES = \ - -I src/libflake-test-support \ - -I src/libstore-test-support \ - -I src/libutil-test-support \ - $(INCLUDE_libflake) \ - $(INCLUDE_libexpr) \ - $(INCLUDE_libfetchers) \ - $(INCLUDE_libstore) \ - $(INCLUDE_libutil) \ - -libflake-tests_CXXFLAGS += $(libflake-tests_EXTRA_INCLUDES) - -libflake-tests_LIBS = \ - libexpr-test-support libstore-test-support libutil-test-support \ - libflake libexpr libfetchers libstore libutil - -libflake-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) -lgmock - -ifdef HOST_WINDOWS - # Increase the default reserved stack size to 65 MB so Nix doesn't run out of space - libflake-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024))) -endif diff --git a/src/libflake/flake/nix-flake.pc.in b/src/libflake/flake/nix-flake.pc.in deleted file mode 100644 index 10c52f5e9..000000000 --- a/src/libflake/flake/nix-flake.pc.in +++ /dev/null @@ -1,10 +0,0 @@ -prefix=@prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: Nix -Description: Nix Package Manager -Version: @PACKAGE_VERSION@ -Requires: nix-util nix-store nix-expr -Libs: -L${libdir} -lnixflake -Cflags: -I${includedir}/nix -std=c++2a diff --git a/src/libflake/local.mk b/src/libflake/local.mk deleted file mode 100644 index 5e604ef3a..000000000 --- a/src/libflake/local.mk +++ /dev/null @@ -1,22 +0,0 @@ -libraries += libflake - -libflake_NAME = libnixflake - -libflake_DIR := $(d) - -libflake_SOURCES := $(wildcard $(d)/*.cc $(d)/flake/*.cc) - -# Not just for this library itself, but also for downstream libraries using this library - -INCLUDE_libflake := -I $(d) - -libflake_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libstore) $(INCLUDE_libfetchers) $(INCLUDE_libexpr) $(INCLUDE_libflake) - -libflake_LDFLAGS += $(THREAD_LDFLAGS) - -libflake_LIBS = libutil libstore libfetchers libexpr - -$(eval $(call install-file-in, $(buildprefix)$(d)/flake/nix-flake.pc, $(libdir)/pkgconfig, 0644)) - -$(foreach i, $(wildcard src/libflake/flake/*.hh), \ - $(eval $(call install-file-in, $(i), $(includedir)/nix/flake, 0644))) diff --git a/src/libmain/local.mk b/src/libmain/local.mk deleted file mode 100644 index d41c49dd7..000000000 --- a/src/libmain/local.mk +++ /dev/null @@ -1,22 +0,0 @@ -libraries += libmain - -libmain_NAME = libnixmain - -libmain_DIR := $(d) - -libmain_SOURCES := $(wildcard $(d)/*.cc) -ifdef HOST_UNIX - libmain_SOURCES += $(wildcard $(d)/unix/*.cc) -endif - -INCLUDE_libmain := -I $(d) - -libmain_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libstore) $(INCLUDE_libmain) - -libmain_LDFLAGS += $(OPENSSL_LIBS) - -libmain_LIBS = libstore libutil - -libmain_ALLOW_UNDEFINED = 1 - -$(eval $(call install-file-in, $(buildprefix)$(d)/nix-main.pc, $(libdir)/pkgconfig, 0644)) diff --git a/src/libmain/nix-main.pc.in b/src/libmain/nix-main.pc.in deleted file mode 100644 index fb3ead6fa..000000000 --- a/src/libmain/nix-main.pc.in +++ /dev/null @@ -1,9 +0,0 @@ -prefix=@prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: Nix -Description: Nix Package Manager -Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lnixmain -Cflags: -I${includedir}/nix -std=c++2a diff --git a/src/libstore-c/local.mk b/src/libstore-c/local.mk deleted file mode 100644 index 5e3eff06a..000000000 --- a/src/libstore-c/local.mk +++ /dev/null @@ -1,21 +0,0 @@ -libraries += libstorec - -libstorec_NAME = libnixstorec - -libstorec_DIR := $(d) - -libstorec_SOURCES := $(wildcard $(d)/*.cc) - -libstorec_LIBS = libutil libstore libutilc - -libstorec_LDFLAGS += $(THREAD_LDFLAGS) - -# Not just for this library itself, but also for downstream libraries using this library - -INCLUDE_libstorec := -I $(d) -libstorec_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libutilc) \ - $(INCLUDE_libstore) $(INCLUDE_libstorec) - -$(eval $(call install-file-in, $(d)/nix-store-c.pc, $(libdir)/pkgconfig, 0644)) - -libstorec_FORCE_INSTALL := 1 diff --git a/src/libstore-c/nix-store-c.pc.in b/src/libstore-c/nix-store-c.pc.in deleted file mode 100644 index de3c7b4c6..000000000 --- a/src/libstore-c/nix-store-c.pc.in +++ /dev/null @@ -1,9 +0,0 @@ -prefix=@prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: Nix -Description: Nix Store - C API -Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lnixstorec -lnixutilc -Cflags: -I${includedir}/nix diff --git a/src/libstore-test-support/local.mk b/src/libstore-test-support/local.mk deleted file mode 100644 index 56dedd825..000000000 --- a/src/libstore-test-support/local.mk +++ /dev/null @@ -1,21 +0,0 @@ -libraries += libstore-test-support - -libstore-test-support_NAME = libnixstore-test-support - -libstore-test-support_DIR := $(d) - -ifeq ($(INSTALL_UNIT_TESTS), yes) - libstore-test-support_INSTALL_DIR := $(checklibdir) -else - libstore-test-support_INSTALL_DIR := -endif - -libstore-test-support_SOURCES := $(wildcard $(d)/tests/*.cc) - -libstore-test-support_CXXFLAGS += $(libstore-tests_EXTRA_INCLUDES) - -libstore-test-support_LIBS = \ - libutil-test-support \ - libstore libutil - -libstore-test-support_LDFLAGS := $(THREAD_LDFLAGS) -lrapidcheck diff --git a/src/libstore-tests/local.mk b/src/libstore-tests/local.mk deleted file mode 100644 index b565ff0be..000000000 --- a/src/libstore-tests/local.mk +++ /dev/null @@ -1,38 +0,0 @@ -check: libstore-tests_RUN - -programs += libstore-tests - -libstore-tests_NAME = libnixstore-tests - -libstore-tests_ENV := _NIX_TEST_UNIT_DATA=$(d)/data GTEST_OUTPUT=xml:$$testresults/libstore-tests.xml - -libstore-tests_DIR := $(d) - -ifeq ($(INSTALL_UNIT_TESTS), yes) - libstore-tests_INSTALL_DIR := $(checkbindir) -else - libstore-tests_INSTALL_DIR := -endif - -libstore-tests_SOURCES := $(wildcard $(d)/*.cc) - -libstore-tests_EXTRA_INCLUDES = \ - -I src/libstore-test-support \ - -I src/libutil-test-support \ - $(INCLUDE_libstore) \ - $(INCLUDE_libstorec) \ - $(INCLUDE_libutil) \ - $(INCLUDE_libutilc) - -libstore-tests_CXXFLAGS += $(libstore-tests_EXTRA_INCLUDES) - -libstore-tests_LIBS = \ - libstore-test-support libutil-test-support \ - libstore libstorec libutil libutilc - -libstore-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) - -ifdef HOST_WINDOWS - # Increase the default reserved stack size to 65 MB so Nix doesn't run out of space - libstore-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024))) -endif diff --git a/src/libstore/local.mk b/src/libstore/local.mk deleted file mode 100644 index 43d8993ba..000000000 --- a/src/libstore/local.mk +++ /dev/null @@ -1,103 +0,0 @@ -libraries += libstore - -libstore_NAME = libnixstore - -libstore_DIR := $(d) - -libstore_SOURCES := $(wildcard $(d)/*.cc $(d)/builtins/*.cc $(d)/build/*.cc) -ifdef HOST_UNIX - libstore_SOURCES += $(wildcard $(d)/unix/*.cc $(d)/unix/build/*.cc) -endif -ifdef HOST_LINUX - libstore_SOURCES += $(wildcard $(d)/linux/*.cc) -endif -ifdef HOST_WINDOWS - libstore_SOURCES += $(wildcard $(d)/windows/*.cc) -endif - -libstore_LIBS = libutil - -libstore_LDFLAGS += $(SQLITE3_LIBS) $(LIBCURL_LIBS) $(THREAD_LDFLAGS) -ifdef HOST_LINUX - libstore_LDFLAGS += -ldl -endif -ifdef HOST_WINDOWS - libstore_LDFLAGS += -lws2_32 -endif - -$(foreach file,$(libstore_FILES),$(eval $(call install-data-in,$(d)/$(file),$(datadir)/nix/sandbox))) - -ifeq ($(ENABLE_S3), 1) - libstore_LDFLAGS += -laws-cpp-sdk-transfer -laws-cpp-sdk-s3 -laws-cpp-sdk-core -laws-crt-cpp -endif - -ifdef HOST_SOLARIS - libstore_LDFLAGS += -lsocket -endif - -ifeq ($(HAVE_SECCOMP), 1) - libstore_LDFLAGS += $(LIBSECCOMP_LIBS) -endif - -# Not just for this library itself, but also for downstream libraries using this library - -INCLUDE_libstore := -I $(d) -I $(d)/build -ifdef HOST_UNIX - INCLUDE_libstore += -I $(d)/unix -I $(d)/unix/build -endif -ifdef HOST_LINUX - INCLUDE_libstore += -I $(d)/linux -endif -ifdef HOST_WINDOWS - INCLUDE_libstore += -I $(d)/windows -endif - -ifdef HOST_WINDOWS -NIX_ROOT = N:\\\\ -else -NIX_ROOT = -endif - -# Prefix all but `NIX_STORE_DIR`, since we aren't doing a local store -# yet so a "logical" store dir that is the same as unix is preferred. -# -# Also, it keeps the unit tests working. - -libstore_CXXFLAGS += \ - $(INCLUDE_libutil) $(INCLUDE_libstore) $(INCLUDE_libstore) \ - -DNIX_PREFIX=\"$(NIX_ROOT)$(prefix)\" \ - -DNIX_STORE_DIR=\"$(storedir)\" \ - -DNIX_DATA_DIR=\"$(NIX_ROOT)$(datadir)\" \ - -DNIX_STATE_DIR=\"$(NIX_ROOT)$(localstatedir)/nix\" \ - -DNIX_LOG_DIR=\"$(NIX_ROOT)$(localstatedir)/log/nix\" \ - -DNIX_CONF_DIR=\"$(NIX_ROOT)$(sysconfdir)/nix\" \ - -DNIX_MAN_DIR=\"$(NIX_ROOT)$(mandir)\" \ - -DLSOF=\"$(NIX_ROOT)$(lsof)\" - -ifeq ($(embedded_sandbox_shell),yes) -libstore_CXXFLAGS += -DSANDBOX_SHELL=\"__embedded_sandbox_shell__\" - -$(d)/unix/build/local-derivation-goal.cc: $(d)/unix/embedded-sandbox-shell.gen.hh - -$(d)/unix/embedded-sandbox-shell.gen.hh: $(sandbox_shell) - $(trace-gen) hexdump -v -e '1/1 "0x%x," "\n"' < $< > $@.tmp - @mv $@.tmp $@ -else - ifneq ($(sandbox_shell),) - libstore_CXXFLAGS += -DSANDBOX_SHELL="\"$(sandbox_shell)\"" - endif -endif - -$(d)/local-store.cc: $(d)/schema.sql.gen.hh $(d)/ca-specific-schema.sql.gen.hh - -$(d)/unix/build.cc: - -clean-files += $(d)/schema.sql.gen.hh $(d)/ca-specific-schema.sql.gen.hh - -$(eval $(call install-file-in, $(buildprefix)$(d)/nix-store.pc, $(libdir)/pkgconfig, 0644)) - -$(foreach i, $(wildcard src/libstore/builtins/*.hh), \ - $(eval $(call install-file-in, $(i), $(includedir)/nix/builtins, 0644))) - -$(foreach i, $(wildcard src/libstore/build/*.hh), \ - $(eval $(call install-file-in, $(i), $(includedir)/nix/build, 0644))) diff --git a/src/libstore/nix-store.pc.in b/src/libstore/nix-store.pc.in deleted file mode 100644 index cd3f2b8da..000000000 --- a/src/libstore/nix-store.pc.in +++ /dev/null @@ -1,10 +0,0 @@ -prefix=@prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: Nix -Description: Nix Package Manager -Version: @PACKAGE_VERSION@ -Requires: nix-util -Libs: -L${libdir} -lnixstore -Cflags: -I${includedir}/nix -std=c++2a diff --git a/src/libutil-c/local.mk b/src/libutil-c/local.mk deleted file mode 100644 index f2df1ef43..000000000 --- a/src/libutil-c/local.mk +++ /dev/null @@ -1,18 +0,0 @@ -libraries += libutilc - -libutilc_NAME = libnixutilc - -libutilc_DIR := $(d) - -libutilc_SOURCES := $(wildcard $(d)/*.cc) - -# Not just for this library itself, but also for downstream libraries using this library - -INCLUDE_libutilc := -I $(d) -libutilc_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libutilc) - -libutilc_LIBS = libutil - -libutilc_LDFLAGS += $(THREAD_LDFLAGS) - -libutilc_FORCE_INSTALL := 1 diff --git a/src/libutil-c/nix-util-c.pc.in b/src/libutil-c/nix-util-c.pc.in deleted file mode 100644 index 0ccae3f8a..000000000 --- a/src/libutil-c/nix-util-c.pc.in +++ /dev/null @@ -1,9 +0,0 @@ -prefix=@prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: Nix libutil C API -Description: Common functions for the Nix C API, such as error handling -Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lnixutil -Cflags: -I${includedir}/nix -std=c++2a diff --git a/src/libutil-test-support/local.mk b/src/libutil-test-support/local.mk deleted file mode 100644 index 5f7835c9f..000000000 --- a/src/libutil-test-support/local.mk +++ /dev/null @@ -1,19 +0,0 @@ -libraries += libutil-test-support - -libutil-test-support_NAME = libnixutil-test-support - -libutil-test-support_DIR := $(d) - -ifeq ($(INSTALL_UNIT_TESTS), yes) - libutil-test-support_INSTALL_DIR := $(checklibdir) -else - libutil-test-support_INSTALL_DIR := -endif - -libutil-test-support_SOURCES := $(wildcard $(d)/tests/*.cc) - -libutil-test-support_CXXFLAGS += $(libutil-tests_EXTRA_INCLUDES) - -libutil-test-support_LIBS = libutil - -libutil-test-support_LDFLAGS := $(THREAD_LDFLAGS) -lrapidcheck diff --git a/src/libutil-tests/local.mk b/src/libutil-tests/local.mk deleted file mode 100644 index c747863a4..000000000 --- a/src/libutil-tests/local.mk +++ /dev/null @@ -1,37 +0,0 @@ -check: libutil-tests_RUN - -programs += libutil-tests - -libutil-tests_NAME = libnixutil-tests - -libutil-tests_ENV := _NIX_TEST_UNIT_DATA=$(d)/data GTEST_OUTPUT=xml:$$testresults/libutil-tests.xml - -libutil-tests_DIR := $(d) - -ifeq ($(INSTALL_UNIT_TESTS), yes) - libutil-tests_INSTALL_DIR := $(checkbindir) -else - libutil-tests_INSTALL_DIR := -endif - -libutil-tests_SOURCES := $(wildcard $(d)/*.cc) - -libutil-tests_EXTRA_INCLUDES = \ - -I src/libutil-test-support \ - $(INCLUDE_libutil) \ - $(INCLUDE_libutilc) - -libutil-tests_CXXFLAGS += $(libutil-tests_EXTRA_INCLUDES) - -libutil-tests_LIBS = libutil-test-support libutil libutilc - -libutil-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) - -ifdef HOST_WINDOWS - # Increase the default reserved stack size to 65 MB so Nix doesn't run out of space - libutil-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024))) -endif - -check: $(d)/data/git/check-data.sh.test - -$(eval $(call run-test,$(d)/data/git/check-data.sh)) diff --git a/src/libutil/local.mk b/src/libutil/local.mk deleted file mode 100644 index e9b498e65..000000000 --- a/src/libutil/local.mk +++ /dev/null @@ -1,44 +0,0 @@ -libraries += libutil - -libutil_NAME = libnixutil - -libutil_DIR := $(d) - -libutil_SOURCES := $(wildcard $(d)/*.cc $(d)/signature/*.cc) -ifdef HOST_UNIX - libutil_SOURCES += $(wildcard $(d)/unix/*.cc) -endif -ifdef HOST_LINUX - libutil_SOURCES += $(wildcard $(d)/linux/*.cc) -endif -ifdef HOST_WINDOWS - libutil_SOURCES += $(wildcard $(d)/windows/*.cc) -endif - -# Not just for this library itself, but also for downstream libraries using this library - -INCLUDE_libutil := -I $(d) -ifdef HOST_UNIX - INCLUDE_libutil += -I $(d)/unix -endif -ifdef HOST_LINUX - INCLUDE_libutil += -I $(d)/linux -endif -ifdef HOST_WINDOWS - INCLUDE_libutil += -I $(d)/windows -endif -libutil_CXXFLAGS += $(INCLUDE_libutil) - -libutil_LDFLAGS += $(THREAD_LDFLAGS) $(LIBCURL_LIBS) $(SODIUM_LIBS) $(OPENSSL_LIBS) $(LIBBROTLI_LIBS) $(LIBARCHIVE_LIBS) $(BOOST_LDFLAGS) -lboost_context - -$(foreach i, $(wildcard $(d)/args/*.hh), \ - $(eval $(call install-file-in, $(i), $(includedir)/nix/args, 0644))) -$(foreach i, $(wildcard $(d)/signature/*.hh), \ - $(eval $(call install-file-in, $(i), $(includedir)/nix/signature, 0644))) - - -ifeq ($(HAVE_LIBCPUID), 1) - libutil_LDFLAGS += -lcpuid -endif - -$(eval $(call install-file-in, $(buildprefix)$(d)/nix-util.pc, $(libdir)/pkgconfig, 0644)) diff --git a/src/libutil/nix-util.pc.in b/src/libutil/nix-util.pc.in deleted file mode 100644 index 85bb1e70e..000000000 --- a/src/libutil/nix-util.pc.in +++ /dev/null @@ -1,9 +0,0 @@ -prefix=@prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: Nix -Description: Nix Package Manager -Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lnixutil -Cflags: -I${includedir}/nix -std=c++2a diff --git a/src/nix/local.mk b/src/nix/local.mk deleted file mode 100644 index b57f6b3e2..000000000 --- a/src/nix/local.mk +++ /dev/null @@ -1,59 +0,0 @@ -programs += nix - -nix_DIR := $(d) - -nix_SOURCES := \ - $(wildcard $(d)/*.cc) \ - $(wildcard src/nix-build/*.cc) \ - $(wildcard src/nix-env/*.cc) \ - $(wildcard src/nix-instantiate/*.cc) \ - $(wildcard src/nix-store/*.cc) - -ifdef HOST_UNIX -nix_SOURCES += \ - $(wildcard $(d)/unix/*.cc) \ - $(wildcard src/build-remote/*.cc) \ - $(wildcard src/nix-channel/*.cc) \ - $(wildcard src/nix-collect-garbage/*.cc) \ - $(wildcard src/nix-copy-closure/*.cc) \ - $(wildcard src/nix-daemon/*.cc) -endif - -INCLUDE_nix := -I $(d) -ifdef HOST_UNIX - INCLUDE_nix += -I $(d)/unix -endif - -nix_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libstore) $(INCLUDE_libfetchers) $(INCLUDE_libexpr) $(INCLUDE_libflake) $(INCLUDE_libmain) -I src/libcmd -I doc/manual $(INCLUDE_nix) - -nix_CXXFLAGS += -DNIX_BIN_DIR=\"$(NIX_ROOT)$(bindir)\" - -nix_LIBS = libexpr libmain libfetchers libflake libstore libutil libcmd - -nix_LDFLAGS = $(THREAD_LDFLAGS) $(SODIUM_LIBS) $(EDITLINE_LIBS) $(BOOST_LDFLAGS) $(LOWDOWN_LIBS) - -ifdef HOST_WINDOWS - # Increase the default reserved stack size to 65 MB so Nix doesn't run out of space - nix_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024))) -endif - -$(foreach name, \ - nix-build nix-channel nix-collect-garbage nix-copy-closure nix-daemon nix-env nix-hash nix-instantiate nix-prefetch-url nix-shell nix-store, \ - $(eval $(call install-symlink, nix, $(bindir)/$(name)))) -$(eval $(call install-symlink, $(bindir)/nix, $(libexecdir)/nix/build-remote)) - -src/nix-env/user-env.cc: src/nix-env/buildenv.nix.gen.hh - -$(d)/develop.cc: $(d)/get-env.sh.gen.hh - -src/nix-channel/nix-channel.cc: src/nix-channel/unpack-channel.nix.gen.hh - -$(d)/main.cc: \ - doc/manual/generate-manpage.nix.gen.hh \ - doc/manual/utils.nix.gen.hh doc/manual/generate-settings.nix.gen.hh \ - doc/manual/generate-store-info.nix.gen.hh \ - $(d)/help-stores.md.gen.hh - -$(d)/profile.cc: $(d)/profile.md - -$(d)/profile.md: $(d)/profiles.md.gen.hh diff --git a/src/perl/package.nix b/src/perl/package.nix index fe617fd47..5ee0df13c 100644 --- a/src/perl/package.nix +++ b/src/perl/package.nix @@ -40,6 +40,10 @@ perl.pkgs.toPerlModule (mkMesonDerivation (finalAttrs: { buildInputs = [ nix-store + ] ++ finalAttrs.passthru.externalBuildInputs; + + # Hack for sake of the dev shell + passthru.externalBuildInputs = [ bzip2 libsodium ]; diff --git a/tests/functional/build-hook-ca-fixed.nix b/tests/functional/build-hook-ca-fixed.nix index 427ec2c31..0ce6d9b12 100644 --- a/tests/functional/build-hook-ca-fixed.nix +++ b/tests/functional/build-hook-ca-fixed.nix @@ -1,6 +1,6 @@ { busybox }: -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; let diff --git a/tests/functional/build-hook.nix b/tests/functional/build-hook.nix index 1f0e17a3b..99a13aee4 100644 --- a/tests/functional/build-hook.nix +++ b/tests/functional/build-hook.nix @@ -1,6 +1,6 @@ { busybox, contentAddressed ? false }: -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; let diff --git a/tests/functional/ca/config.nix b/tests/functional/ca/config.nix new file mode 100644 index 000000000..451fbae4f --- /dev/null +++ b/tests/functional/ca/config.nix @@ -0,0 +1,2 @@ +# Shim to get generated file +import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/ca/config.nix" diff --git a/tests/functional/ca/content-addressed.nix b/tests/functional/ca/content-addressed.nix index 411ebb86b..2559c562f 100644 --- a/tests/functional/ca/content-addressed.nix +++ b/tests/functional/ca/content-addressed.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/ca/config.nix"; +with import ./config.nix; let mkCADerivation = args: mkDerivation ({ __contentAddressed = true; diff --git a/tests/functional/ca/local.mk b/tests/functional/ca/local.mk deleted file mode 100644 index 7c2fcc451..000000000 --- a/tests/functional/ca/local.mk +++ /dev/null @@ -1,29 +0,0 @@ -ca-tests := \ - $(d)/build-with-garbage-path.sh \ - $(d)/build.sh \ - $(d)/build-cache.sh \ - $(d)/concurrent-builds.sh \ - $(d)/derivation-json.sh \ - $(d)/duplicate-realisation-in-closure.sh \ - $(d)/eval-store.sh \ - $(d)/gc.sh \ - $(d)/import-from-derivation.sh \ - $(d)/new-build-cmd.sh \ - $(d)/nix-copy.sh \ - $(d)/nix-run.sh \ - $(d)/nix-shell.sh \ - $(d)/post-hook.sh \ - $(d)/recursive.sh \ - $(d)/repl.sh \ - $(d)/selfref-gc.sh \ - $(d)/signatures.sh \ - $(d)/substitute.sh \ - $(d)/why-depends.sh - -install-tests-groups += ca - -clean-files += \ - $(d)/config.nix - -test-deps += \ - tests/functional/ca/config.nix diff --git a/tests/functional/ca/nix-run.sh b/tests/functional/ca/nix-run.sh index 21c09117e..e6638cc91 100755 --- a/tests/functional/ca/nix-run.sh +++ b/tests/functional/ca/nix-run.sh @@ -6,7 +6,4 @@ flakeDir="$TEST_HOME/flake" mkdir -p "${flakeDir}" cp flake.nix "${_NIX_TEST_BUILD_DIR}/ca/config.nix" content-addressed.nix "${flakeDir}" -# `config.nix` cannot be gotten via build dir / env var (runs afoul pure eval). Instead get from flake. -removeBuildDirRef "$flakeDir"/*.nix - nix run --no-write-lock-file "path:${flakeDir}#runnable" diff --git a/tests/functional/ca/nondeterministic.nix b/tests/functional/ca/nondeterministic.nix index 740be4bd2..d6d099a3e 100644 --- a/tests/functional/ca/nondeterministic.nix +++ b/tests/functional/ca/nondeterministic.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/ca/config.nix"; +with import ./config.nix; let mkCADerivation = args: mkDerivation ({ __contentAddressed = true; diff --git a/tests/functional/ca/racy.nix b/tests/functional/ca/racy.nix index cadd98675..555a15484 100644 --- a/tests/functional/ca/racy.nix +++ b/tests/functional/ca/racy.nix @@ -2,7 +2,7 @@ # build it at once. -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/ca/config.nix"; +with import ./config.nix; mkDerivation { name = "simple"; diff --git a/tests/functional/check-refs.nix b/tests/functional/check-refs.nix index 54957f635..89690e456 100644 --- a/tests/functional/check-refs.nix +++ b/tests/functional/check-refs.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; rec { diff --git a/tests/functional/check-reqs.nix b/tests/functional/check-reqs.nix index 4e059f5a4..41436cb48 100644 --- a/tests/functional/check-reqs.nix +++ b/tests/functional/check-reqs.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; rec { dep1 = mkDerivation { diff --git a/tests/functional/check.nix b/tests/functional/check.nix index 13638eae8..ddab8eea9 100644 --- a/tests/functional/check.nix +++ b/tests/functional/check.nix @@ -1,6 +1,6 @@ {checkBuildId ? 0}: -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; { nondeterministic = mkDerivation { diff --git a/tests/functional/chroot-store.sh b/tests/functional/chroot-store.sh index 8c2a969d3..46e91f0aa 100755 --- a/tests/functional/chroot-store.sh +++ b/tests/functional/chroot-store.sh @@ -39,9 +39,6 @@ EOF cp simple.nix shell.nix simple.builder.sh "${config_nix}" "$flakeDir/" - # `config.nix` cannot be gotten via build dir / env var (runs afoul pure eval). Instead get from flake. - removeBuildDirRef "$flakeDir"/*.nix - TODO_NixOS outPath=$(nix build --print-out-paths --no-link --sandbox-paths '/nix? /bin? /lib? /lib64? /usr?' --store "$TEST_ROOT/x" path:"$flakeDir") diff --git a/tests/functional/common/functions.sh b/tests/functional/common/functions.sh index 286bb58e8..7195149cb 100644 --- a/tests/functional/common/functions.sh +++ b/tests/functional/common/functions.sh @@ -343,15 +343,6 @@ count() { echo $# } -# Sometimes, e.g. due to pure eval, restricted eval, or sandboxing, we -# cannot look up `config.nix` in the build dir, and have to instead get -# it from the current directory. (In this case, the current directly -# will be somewhere in `$TEST_ROOT`.) -removeBuildDirRef() { - # shellcheck disable=SC2016 # The ${} in this is Nix, not shell - sed -i -e 's,"${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/[^ ]*config.nix",./config.nix,' "$@" -} - trap onError ERR fi # COMMON_FUNCTIONS_SH_SOURCED diff --git a/tests/functional/config.nix b/tests/functional/config.nix new file mode 100644 index 000000000..5d1cb74ec --- /dev/null +++ b/tests/functional/config.nix @@ -0,0 +1,2 @@ +# Shim to get generated file +import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix" diff --git a/tests/functional/dependencies.nix b/tests/functional/dependencies.nix index db06321da..be1a7ae9a 100644 --- a/tests/functional/dependencies.nix +++ b/tests/functional/dependencies.nix @@ -1,5 +1,5 @@ { hashInvalidator ? "" }: -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; let { diff --git a/tests/functional/dyn-drv/config.nix b/tests/functional/dyn-drv/config.nix new file mode 100644 index 000000000..8ec2c67ea --- /dev/null +++ b/tests/functional/dyn-drv/config.nix @@ -0,0 +1,2 @@ +# Shim to get generated file +import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/dyn-drv/config.nix" diff --git a/tests/functional/dyn-drv/local.mk b/tests/functional/dyn-drv/local.mk deleted file mode 100644 index c87534944..000000000 --- a/tests/functional/dyn-drv/local.mk +++ /dev/null @@ -1,15 +0,0 @@ -dyn-drv-tests := \ - $(d)/text-hashed-output.sh \ - $(d)/recursive-mod-json.sh \ - $(d)/build-built-drv.sh \ - $(d)/eval-outputOf.sh \ - $(d)/dep-built-drv.sh \ - $(d)/old-daemon-error-hack.sh - -install-tests-groups += dyn-drv - -clean-files += \ - $(d)/config.nix - -test-deps += \ - tests/functional/dyn-drv/config.nix diff --git a/tests/functional/dyn-drv/old-daemon-error-hack.nix b/tests/functional/dyn-drv/old-daemon-error-hack.nix index 7d3ccf7e4..c9d4a62d4 100644 --- a/tests/functional/dyn-drv/old-daemon-error-hack.nix +++ b/tests/functional/dyn-drv/old-daemon-error-hack.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/dyn-drv/config.nix"; +with import ./config.nix; # A simple content-addressed derivation. # The derivation can be arbitrarily modified by passing a different `seed`, diff --git a/tests/functional/dyn-drv/recursive-mod-json.nix b/tests/functional/dyn-drv/recursive-mod-json.nix index 0e778aa7f..c6a24ca4f 100644 --- a/tests/functional/dyn-drv/recursive-mod-json.nix +++ b/tests/functional/dyn-drv/recursive-mod-json.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/dyn-drv/config.nix"; +with import ./config.nix; let innerName = "foo"; in diff --git a/tests/functional/dyn-drv/text-hashed-output.nix b/tests/functional/dyn-drv/text-hashed-output.nix index aa46fff61..99203b518 100644 --- a/tests/functional/dyn-drv/text-hashed-output.nix +++ b/tests/functional/dyn-drv/text-hashed-output.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/dyn-drv/config.nix"; +with import ./config.nix; # A simple content-addressed derivation. # The derivation can be arbitrarily modified by passing a different `seed`, diff --git a/tests/functional/export-graph.nix b/tests/functional/export-graph.nix index 97ffe73a9..64fe36bd1 100644 --- a/tests/functional/export-graph.nix +++ b/tests/functional/export-graph.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; rec { diff --git a/tests/functional/extra-sandbox-profile.nix b/tests/functional/extra-sandbox-profile.nix index 5f0e4753f..aa680b918 100644 --- a/tests/functional/extra-sandbox-profile.nix +++ b/tests/functional/extra-sandbox-profile.nix @@ -1,6 +1,6 @@ { destFile, seed }: -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; mkDerivation { name = "simple"; diff --git a/tests/functional/failing.nix b/tests/functional/failing.nix index 8b7990679..d25e2d6b6 100644 --- a/tests/functional/failing.nix +++ b/tests/functional/failing.nix @@ -1,5 +1,5 @@ { busybox }: -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; let mkDerivation = args: diff --git a/tests/functional/filter-source.nix b/tests/functional/filter-source.nix index dcef9c4e2..907163639 100644 --- a/tests/functional/filter-source.nix +++ b/tests/functional/filter-source.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; mkDerivation { name = "filter"; diff --git a/tests/functional/fixed.nix b/tests/functional/fixed.nix index f70b89091..a920a2167 100644 --- a/tests/functional/fixed.nix +++ b/tests/functional/fixed.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; rec { diff --git a/tests/functional/flakes/bundle.sh b/tests/functional/flakes/bundle.sh index 61aa040e7..2946aea35 100755 --- a/tests/functional/flakes/bundle.sh +++ b/tests/functional/flakes/bundle.sh @@ -4,9 +4,6 @@ source common.sh cp ../simple.nix ../simple.builder.sh "${config_nix}" "$TEST_HOME" -# `config.nix` cannot be gotten via build dir / env var (runs afoul pure eval). Instead get from flake. -removeBuildDirRef "$TEST_HOME"/*.nix - cd "$TEST_HOME" cat < flake.nix diff --git a/tests/functional/flakes/common.sh b/tests/functional/flakes/common.sh index 8af72f2ad..cc9b2e466 100644 --- a/tests/functional/flakes/common.sh +++ b/tests/functional/flakes/common.sh @@ -35,9 +35,6 @@ writeSimpleFlake() { EOF cp ../simple.nix ../shell.nix ../simple.builder.sh "${config_nix}" "$flakeDir/" - - # `config.nix` cannot be gotten via build dir / env var (runs afoul pure eval). Instead get from flake. - removeBuildDirRef "$flakeDir"/*.nix } createSimpleGitFlake() { diff --git a/tests/functional/flakes/config.sh b/tests/functional/flakes/config.sh index 48f1c7a85..ab2d9f47c 100755 --- a/tests/functional/flakes/config.sh +++ b/tests/functional/flakes/config.sh @@ -3,7 +3,6 @@ source common.sh cp ../simple.nix ../simple.builder.sh "${config_nix}" $TEST_HOME -removeBuildDirRef "$TEST_HOME/simple.nix" cd $TEST_HOME diff --git a/tests/functional/flakes/develop.sh b/tests/functional/flakes/develop.sh index 2e75081d4..b3e438e99 100755 --- a/tests/functional/flakes/develop.sh +++ b/tests/functional/flakes/develop.sh @@ -27,9 +27,6 @@ EOF mkdir -p "$TEST_HOME/nixpkgs" cp "${config_nix}" ../shell.nix "$TEST_HOME/nixpkgs" -# `config.nix` cannot be gotten via build dir / env var (runs afoul pure eval). Instead get from flake. -removeBuildDirRef "$TEST_HOME/nixpkgs"/*.nix - cat <"$TEST_HOME/nixpkgs/flake.nix" { outputs = {self}: { diff --git a/tests/functional/flakes/local.mk b/tests/functional/flakes/local.mk deleted file mode 100644 index a37840240..000000000 --- a/tests/functional/flakes/local.mk +++ /dev/null @@ -1,25 +0,0 @@ -flake-tests := \ - $(d)/flakes.sh \ - $(d)/develop.sh \ - $(d)/edit.sh \ - $(d)/run.sh \ - $(d)/mercurial.sh \ - $(d)/circular.sh \ - $(d)/init.sh \ - $(d)/inputs.sh \ - $(d)/follow-paths.sh \ - $(d)/bundle.sh \ - $(d)/check.sh \ - $(d)/unlocked-override.sh \ - $(d)/absolute-paths.sh \ - $(d)/absolute-attr-paths.sh \ - $(d)/build-paths.sh \ - $(d)/flake-in-submodule.sh \ - $(d)/prefetch.sh \ - $(d)/eval-cache.sh \ - $(d)/search-root.sh \ - $(d)/config.sh \ - $(d)/show.sh \ - $(d)/dubious-query.sh - -install-tests-groups += flake diff --git a/tests/functional/flakes/run.sh b/tests/functional/flakes/run.sh index 2077c965b..c92ddca2b 100755 --- a/tests/functional/flakes/run.sh +++ b/tests/functional/flakes/run.sh @@ -8,8 +8,6 @@ clearStore rm -rf $TEST_HOME/.cache $TEST_HOME/.config $TEST_HOME/.local cp ../shell-hello.nix "${config_nix}" $TEST_HOME -# `config.nix` cannot be gotten via build dir / env var (runs afoul pure eval). Instead get from flake. -removeBuildDirRef "$TEST_HOME"/*.nix cd $TEST_HOME cat < flake.nix diff --git a/tests/functional/fod-failing.nix b/tests/functional/fod-failing.nix index 7881a3fbf..37c04fe12 100644 --- a/tests/functional/fod-failing.nix +++ b/tests/functional/fod-failing.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; rec { x1 = mkDerivation { name = "x1"; diff --git a/tests/functional/gc-concurrent.nix b/tests/functional/gc-concurrent.nix index a5c3c97c3..0aba1f983 100644 --- a/tests/functional/gc-concurrent.nix +++ b/tests/functional/gc-concurrent.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; { lockFifo ? null }: diff --git a/tests/functional/gc-runtime.nix b/tests/functional/gc-runtime.nix index 2603fafdf..ee5980bdf 100644 --- a/tests/functional/gc-runtime.nix +++ b/tests/functional/gc-runtime.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; mkDerivation { name = "gc-runtime"; diff --git a/tests/functional/git-hashing/local.mk b/tests/functional/git-hashing/local.mk deleted file mode 100644 index ebec01940..000000000 --- a/tests/functional/git-hashing/local.mk +++ /dev/null @@ -1,7 +0,0 @@ -git-hashing-tests := \ - $(d)/simple.sh - -install-tests-groups += git-hashing - -clean-files += \ - $(d)/config.nix diff --git a/tests/functional/hermetic.nix b/tests/functional/hermetic.nix index dafe8ad9f..d1dccdff3 100644 --- a/tests/functional/hermetic.nix +++ b/tests/functional/hermetic.nix @@ -5,7 +5,7 @@ , withFinalRefs ? false }: -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; let contentAddressedByDefault = builtins.getEnv "NIX_TESTS_CA_BY_DEFAULT" == "1"; diff --git a/tests/functional/ifd.nix b/tests/functional/ifd.nix index c84ffbc66..d0b9b54ad 100644 --- a/tests/functional/ifd.nix +++ b/tests/functional/ifd.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; import ( mkDerivation { name = "foo"; diff --git a/tests/functional/import-from-derivation.nix b/tests/functional/import-from-derivation.nix index 8864fb30a..cc53451cf 100644 --- a/tests/functional/import-from-derivation.nix +++ b/tests/functional/import-from-derivation.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; rec { bar = mkDerivation { diff --git a/tests/functional/impure-derivations.nix b/tests/functional/impure-derivations.nix index 04710323f..98547e6c1 100644 --- a/tests/functional/impure-derivations.nix +++ b/tests/functional/impure-derivations.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; rec { diff --git a/tests/functional/impure-env.nix b/tests/functional/impure-env.nix index 6b9e5a825..2b0380ed7 100644 --- a/tests/functional/impure-env.nix +++ b/tests/functional/impure-env.nix @@ -1,6 +1,6 @@ { var, value }: -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; mkDerivation { name = "test"; diff --git a/tests/functional/linux-sandbox-cert-test.nix b/tests/functional/linux-sandbox-cert-test.nix index e506b6a0f..2fc083ea9 100644 --- a/tests/functional/linux-sandbox-cert-test.nix +++ b/tests/functional/linux-sandbox-cert-test.nix @@ -1,6 +1,6 @@ { mode }: -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; mkDerivation ( { diff --git a/tests/functional/local-overlay-store/local.mk b/tests/functional/local-overlay-store/local.mk deleted file mode 100644 index 6348a4423..000000000 --- a/tests/functional/local-overlay-store/local.mk +++ /dev/null @@ -1,14 +0,0 @@ -local-overlay-store-tests := \ - $(d)/check-post-init.sh \ - $(d)/redundant-add.sh \ - $(d)/build.sh \ - $(d)/bad-uris.sh \ - $(d)/add-lower.sh \ - $(d)/delete-refs.sh \ - $(d)/delete-duplicate.sh \ - $(d)/gc.sh \ - $(d)/verify.sh \ - $(d)/optimise.sh \ - $(d)/stale-file-handle.sh - -install-tests-groups += local-overlay-store diff --git a/tests/functional/local.mk b/tests/functional/local.mk deleted file mode 100644 index e50b5eaf1..000000000 --- a/tests/functional/local.mk +++ /dev/null @@ -1,146 +0,0 @@ -nix_tests = \ - test-infra.sh \ - gc.sh \ - nix-collect-garbage-d.sh \ - remote-store.sh \ - legacy-ssh-store.sh \ - lang.sh \ - lang-gc.sh \ - characterisation-test-infra.sh \ - experimental-features.sh \ - fetchMercurial.sh \ - gc-auto.sh \ - user-envs.sh \ - user-envs-migration.sh \ - binary-cache.sh \ - multiple-outputs.sh \ - nix-build.sh \ - gc-concurrent.sh \ - repair.sh \ - fixed.sh \ - export-graph.sh \ - timeout.sh \ - fetchGitRefs.sh \ - gc-runtime.sh \ - tarball.sh \ - fetchGit.sh \ - fetchurl.sh \ - fetchPath.sh \ - fetchTree-file.sh \ - simple.sh \ - referrers.sh \ - optimise-store.sh \ - substitute-with-invalid-ca.sh \ - signing.sh \ - hash-convert.sh \ - hash-path.sh \ - gc-non-blocking.sh \ - check.sh \ - nix-shell.sh \ - check-refs.sh \ - build-remote-input-addressed.sh \ - secure-drv-outputs.sh \ - restricted.sh \ - fetchGitSubmodules.sh \ - fetchGitVerification.sh \ - readfile-context.sh \ - nix-channel.sh \ - recursive.sh \ - dependencies.sh \ - check-reqs.sh \ - build-remote-content-addressed-fixed.sh \ - build-remote-content-addressed-floating.sh \ - build-remote-trustless-should-pass-0.sh \ - build-remote-trustless-should-pass-1.sh \ - build-remote-trustless-should-pass-2.sh \ - build-remote-trustless-should-pass-3.sh \ - build-remote-trustless-should-fail-0.sh \ - build-remote-with-mounted-ssh-ng.sh \ - nar-access.sh \ - impure-eval.sh \ - pure-eval.sh \ - eval.sh \ - repl.sh \ - binary-cache-build-remote.sh \ - search.sh \ - logging.sh \ - export.sh \ - config.sh \ - add.sh \ - chroot-store.sh \ - filter-source.sh \ - misc.sh \ - dump-db.sh \ - linux-sandbox.sh \ - supplementary-groups.sh \ - build-dry.sh \ - structured-attrs.sh \ - shell.sh \ - brotli.sh \ - zstd.sh \ - compression-levels.sh \ - nix-copy-ssh.sh \ - nix-copy-ssh-ng.sh \ - post-hook.sh \ - function-trace.sh \ - fmt.sh \ - eval-store.sh \ - why-depends.sh \ - derivation-json.sh \ - derivation-advanced-attributes.sh \ - import-from-derivation.sh \ - nix_path.sh \ - nars.sh \ - placeholders.sh \ - ssh-relay.sh \ - build.sh \ - build-delete.sh \ - output-normalization.sh \ - selfref-gc.sh \ - db-migration.sh \ - bash-profile.sh \ - pass-as-file.sh \ - nix-profile.sh \ - suggestions.sh \ - store-info.sh \ - fetchClosure.sh \ - completions.sh \ - impure-derivations.sh \ - path-from-hash-part.sh \ - path-info.sh \ - toString-path.sh \ - read-only-store.sh \ - nested-sandboxing.sh \ - impure-env.sh \ - debugger.sh \ - extra-sandbox-profile.sh \ - -ifeq ($(HAVE_LIBCPUID), 1) - nix_tests += compute-levels.sh -endif - -ifeq ($(ENABLE_BUILD), yes) - nix_tests += test-libstoreconsumer.sh - - ifeq ($(BUILD_SHARED_LIBS), 1) - nix_tests += plugins.sh - endif -endif - -ifeq ($(ENABLE_DOC_GEN), yes) - nix_tests += help.sh -endif - -$(d)/test-libstoreconsumer.sh.test $(d)/test-libstoreconsumer.sh.test-debug: \ - $(buildprefix)$(d)/test-libstoreconsumer/test-libstoreconsumer -$(d)/plugins.sh.test $(d)/plugins.sh.test-debug: \ - $(buildprefix)$(d)/plugins/libplugintest.$(SO_EXT) - -install-tests += $(foreach x, $(nix_tests), $(d)/$(x)) - -test-clean-files := \ - $(d)/common/subst-vars.sh \ - $(d)/config.nix - -clean-files += $(test-clean-files) -test-deps += $(test-clean-files) diff --git a/tests/functional/multiple-outputs.nix b/tests/functional/multiple-outputs.nix index 19ae2a45d..6ba7c523d 100644 --- a/tests/functional/multiple-outputs.nix +++ b/tests/functional/multiple-outputs.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; rec { diff --git a/tests/functional/nar-access.nix b/tests/functional/nar-access.nix index 78972bd36..9948abe59 100644 --- a/tests/functional/nar-access.nix +++ b/tests/functional/nar-access.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; rec { a = mkDerivation { diff --git a/tests/functional/nix-build-examples.nix b/tests/functional/nix-build-examples.nix index aaea8fc07..e54dbbf62 100644 --- a/tests/functional/nix-build-examples.nix +++ b/tests/functional/nix-build-examples.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; rec { diff --git a/tests/functional/parallel.nix b/tests/functional/parallel.nix index 1f2411c92..23f142059 100644 --- a/tests/functional/parallel.nix +++ b/tests/functional/parallel.nix @@ -1,6 +1,6 @@ {sleepTime ? 3}: -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; let diff --git a/tests/functional/path.nix b/tests/functional/path.nix index b23300f90..883c3c41b 100644 --- a/tests/functional/path.nix +++ b/tests/functional/path.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; mkDerivation { name = "filter"; diff --git a/tests/functional/plugins/local.mk b/tests/functional/plugins/local.mk deleted file mode 100644 index 2314e1341..000000000 --- a/tests/functional/plugins/local.mk +++ /dev/null @@ -1,11 +0,0 @@ -libraries += libplugintest - -libplugintest_DIR := $(d) - -libplugintest_SOURCES := $(d)/plugintest.cc - -libplugintest_ALLOW_UNDEFINED := 1 - -libplugintest_EXCLUDE_FROM_LIBRARY_LIST := 1 - -libplugintest_CXXFLAGS := $(INCLUDE_libutil) $(INCLUDE_libstore) $(INCLUDE_libexpr) $(INCLUDE_libfetchers) diff --git a/tests/functional/readfile-context.nix b/tests/functional/readfile-context.nix index b8f4a4c27..54cd1afd9 100644 --- a/tests/functional/readfile-context.nix +++ b/tests/functional/readfile-context.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; let diff --git a/tests/functional/restricted.sh b/tests/functional/restricted.sh index 63bf56cd7..00ee4ddc8 100755 --- a/tests/functional/restricted.sh +++ b/tests/functional/restricted.sh @@ -12,10 +12,6 @@ mkdir -p "$TEST_ROOT/nix" cp ./simple.nix "$TEST_ROOT/nix" cp ./simple.builder.sh "$TEST_ROOT/nix" cp "${config_nix}" "$TEST_ROOT/nix" -simple_nix="$TEST_ROOT/nix/simple.nix" -# N.B. redefine -config_nix="$TEST_ROOT/nix/config.nix" -removeBuildDirRef "${simple_nix}" cd "$TEST_ROOT/nix" nix-instantiate --restrict-eval ./simple.nix -I src=. diff --git a/tests/functional/search.nix b/tests/functional/search.nix index 3c3564bda..fea6e7a7a 100644 --- a/tests/functional/search.nix +++ b/tests/functional/search.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; { hello = mkDerivation rec { diff --git a/tests/functional/secure-drv-outputs.nix b/tests/functional/secure-drv-outputs.nix index cd111c315..b4ac8ff53 100644 --- a/tests/functional/secure-drv-outputs.nix +++ b/tests/functional/secure-drv-outputs.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; { diff --git a/tests/functional/shell-hello.nix b/tests/functional/shell-hello.nix index fa02e2bb4..c920d7cb4 100644 --- a/tests/functional/shell-hello.nix +++ b/tests/functional/shell-hello.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; rec { hello = mkDerivation { diff --git a/tests/functional/shell.nix b/tests/functional/shell.nix index f6622a487..9cae14b78 100644 --- a/tests/functional/shell.nix +++ b/tests/functional/shell.nix @@ -1,6 +1,6 @@ { inNixShell ? false, contentAddressed ? false, fooContents ? "foo" }: -let cfg = import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; in +let cfg = import ./config.nix; in with cfg; let diff --git a/tests/functional/simple-failing.nix b/tests/functional/simple-failing.nix index 228971734..d176c9c51 100644 --- a/tests/functional/simple-failing.nix +++ b/tests/functional/simple-failing.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; mkDerivation { name = "simple-failing"; diff --git a/tests/functional/simple.nix b/tests/functional/simple.nix index 96237695c..2035ca294 100644 --- a/tests/functional/simple.nix +++ b/tests/functional/simple.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; mkDerivation { name = "simple"; diff --git a/tests/functional/structured-attrs-shell.nix b/tests/functional/structured-attrs-shell.nix index 7ed28c03f..57c1e6bd2 100644 --- a/tests/functional/structured-attrs-shell.nix +++ b/tests/functional/structured-attrs-shell.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; let dep = mkDerivation { name = "dep"; diff --git a/tests/functional/structured-attrs.nix b/tests/functional/structured-attrs.nix index ae461c21a..e93139a44 100644 --- a/tests/functional/structured-attrs.nix +++ b/tests/functional/structured-attrs.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; let diff --git a/tests/functional/symlink-derivation.nix b/tests/functional/symlink-derivation.nix index 96765d355..e9a74cdce 100644 --- a/tests/functional/symlink-derivation.nix +++ b/tests/functional/symlink-derivation.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; let foo_in_store = builtins.toFile "foo" "foo"; diff --git a/tests/functional/test-libstoreconsumer/local.mk b/tests/functional/test-libstoreconsumer/local.mk deleted file mode 100644 index 3e8581c57..000000000 --- a/tests/functional/test-libstoreconsumer/local.mk +++ /dev/null @@ -1,15 +0,0 @@ -programs += test-libstoreconsumer - -test-libstoreconsumer_DIR := $(d) - -# do not install -test-libstoreconsumer_INSTALL_DIR := - -test-libstoreconsumer_SOURCES := \ - $(wildcard $(d)/*.cc) \ - -test-libstoreconsumer_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libstore) - -test-libstoreconsumer_LIBS = libstore libutil - -test-libstoreconsumer_LDFLAGS = $(THREAD_LDFLAGS) $(SODIUM_LIBS) $(EDITLINE_LIBS) $(BOOST_LDFLAGS) $(LOWDOWN_LIBS) diff --git a/tests/functional/timeout.nix b/tests/functional/timeout.nix index ad71e61e2..d0e949e31 100644 --- a/tests/functional/timeout.nix +++ b/tests/functional/timeout.nix @@ -1,4 +1,4 @@ -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; { diff --git a/tests/functional/user-envs.nix b/tests/functional/user-envs.nix index c8e846d4b..46f8b51dd 100644 --- a/tests/functional/user-envs.nix +++ b/tests/functional/user-envs.nix @@ -2,7 +2,7 @@ { foo ? "foo" }: -with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +with import ./config.nix; assert foo == "foo"; From fa0adbd83872a670bd95305164576ecef6cc299e Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 11 Nov 2024 17:08:58 +0100 Subject: [PATCH 426/718] Bump version --- .version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.version b/.version index 5c18f9195..7a25c70f9 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -2.25.0 +2.26.0 From 1cfb226b7269b14c34b2ef42e4c501e1ba851bb4 Mon Sep 17 00:00:00 2001 From: WxNzEMof <143541718+WxNzEMof@users.noreply.github.com> Date: Sun, 10 Nov 2024 21:31:02 +0000 Subject: [PATCH 427/718] tests/nixos: add nix-docker test --- tests/nixos/default.nix | 2 ++ tests/nixos/nix-docker.nix | 39 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 tests/nixos/nix-docker.nix diff --git a/tests/nixos/default.nix b/tests/nixos/default.nix index 17bfdea38..c5f4a23aa 100644 --- a/tests/nixos/default.nix +++ b/tests/nixos/default.nix @@ -124,6 +124,8 @@ in nix-copy = runNixOSTestFor "x86_64-linux" ./nix-copy.nix; + nix-docker = runNixOSTestFor "x86_64-linux" ./nix-docker.nix; + nssPreload = runNixOSTestFor "x86_64-linux" ./nss-preload.nix; githubFlakes = runNixOSTestFor "x86_64-linux" ./github-flakes.nix; diff --git a/tests/nixos/nix-docker.nix b/tests/nixos/nix-docker.nix new file mode 100644 index 000000000..5c21dfff6 --- /dev/null +++ b/tests/nixos/nix-docker.nix @@ -0,0 +1,39 @@ +# Test the container built by ../../docker.nix. + +{ lib, config, nixpkgs, hostPkgs, ... }: + +let + pkgs = config.nodes.machine.nixpkgs.pkgs; + + nixImage = import ../../docker.nix { + inherit (config.nodes.machine.nixpkgs) pkgs; + }; + nixUserImage = import ../../docker.nix { + inherit (config.nodes.machine.nixpkgs) pkgs; + name = "nix-user"; + uid = 1000; + gid = 1000; + uname = "user"; + gname = "user"; + }; + +in { + name = "nix-docker"; + + nodes.machine = + { config, lib, pkgs, ... }: + { virtualisation.diskSize = 4096; + }; + + testScript = { nodes }: '' + machine.succeed("mkdir -p /etc/containers") + machine.succeed("""echo '{"default":[{"type":"insecureAcceptAnything"}]}' > /etc/containers/policy.json""") + + machine.succeed("${pkgs.podman}/bin/podman load -i ${nixImage}") + machine.succeed("${pkgs.podman}/bin/podman run --rm nix nix --version") + + machine.succeed("${pkgs.podman}/bin/podman load -i ${nixUserImage}") + machine.succeed("${pkgs.podman}/bin/podman run --rm nix-user nix --version") + machine.succeed("[[ $(${pkgs.podman}/bin/podman run --rm nix-user stat -c %u /nix/store) = 1000 ]]") + ''; +} From 1dda18ef0a3c6d109b6e9fc2e1c7f93c9c1a4471 Mon Sep 17 00:00:00 2001 From: WxNzEMof <143541718+WxNzEMof@users.noreply.github.com> Date: Sun, 10 Nov 2024 21:31:32 +0000 Subject: [PATCH 428/718] doc/manual: add documentation for non-root container images --- .../source/installation/installing-docker.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/doc/manual/source/installation/installing-docker.md b/doc/manual/source/installation/installing-docker.md index 6f77d6a57..9354c1a72 100644 --- a/doc/manual/source/installation/installing-docker.md +++ b/doc/manual/source/installation/installing-docker.md @@ -57,3 +57,21 @@ $ nix build ./\#hydraJobs.dockerImage.x86_64-linux $ docker load -i ./result/image.tar.gz $ docker run -ti nix:2.5pre20211105 ``` + +# Docker image with non-root Nix + +If you would like to run Nix in a container under a user other than `root`, +you can build an image with a non-root single-user installation of Nix +by specifying the `uid`, `gid`, `uname`, and `gname` arguments to `docker.nix`: + +```console +$ nix build --file docker.nix \ + --arg uid 1000 \ + --arg gid 1000 \ + --argstr uname user \ + --argstr gname user \ + --argstr name nix-user \ + --out-link nix-user.tar.gz +$ docker load -i nix-user.tar.gz +$ docker run -ti nix-user +``` From 11d3b017cfdce506bf46edf7f11ba923a67adee9 Mon Sep 17 00:00:00 2001 From: WxNzEMof <143541718+WxNzEMof@users.noreply.github.com> Date: Sun, 10 Nov 2024 23:20:31 +0000 Subject: [PATCH 429/718] tests/nixos: add more thorough nix-docker tests --- tests/nixos/nix-docker-test.sh | 47 ++++++++++++++++++++++++++++++++++ tests/nixos/nix-docker.nix | 20 ++++++++++++--- 2 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 tests/nixos/nix-docker-test.sh diff --git a/tests/nixos/nix-docker-test.sh b/tests/nixos/nix-docker-test.sh new file mode 100644 index 000000000..1f65e1a94 --- /dev/null +++ b/tests/nixos/nix-docker-test.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash +# docker.nix test script. Runs inside a built docker.nix container. + +set -eEuo pipefail + +export NIX_CONFIG='substituters = http://cache:5000?trusted=1' + +cd /tmp + +# Test getting a fetched derivation +test "$("$(nix-build -E '(import {}).hello')"/bin/hello)" = "Hello, world!" + +# Test building a simple derivation +# shellcheck disable=SC2016 +nix-build -E ' +let + pkgs = import {}; +in +builtins.derivation { + name = "test"; + system = builtins.currentSystem; + builder = "${pkgs.bash}/bin/bash"; + args = ["-c" "echo OK > $out"]; +}' +test "$(cat result)" = OK + +# Ensure #!/bin/sh shebang works +echo '#!/bin/sh' > ./shebang-test +echo 'echo OK' >> ./shebang-test +chmod +x ./shebang-test +test "$(./shebang-test)" = OK + +# Ensure #!/usr/bin/env shebang works +echo '#!/usr/bin/env bash' > ./shebang-test +echo 'echo OK' >> ./shebang-test +chmod +x ./shebang-test +test "$(./shebang-test)" = OK + +# Test nix-shell +{ + echo '#!/usr/bin/env nix-shell' + echo '#! nix-shell -i bash' + echo '#! nix-shell -p hello' + echo 'hello' +} > ./nix-shell-test +chmod +x ./nix-shell-test +test "$(./nix-shell-test)" = "Hello, world!" diff --git a/tests/nixos/nix-docker.nix b/tests/nixos/nix-docker.nix index 5c21dfff6..dfd508988 100644 --- a/tests/nixos/nix-docker.nix +++ b/tests/nixos/nix-docker.nix @@ -17,23 +17,37 @@ let gname = "user"; }; + containerTestScript = ./nix-docker-test.sh; + in { name = "nix-docker"; - nodes.machine = - { config, lib, pkgs, ... }: - { virtualisation.diskSize = 4096; + nodes = + { machine = + { config, lib, pkgs, ... }: + { virtualisation.diskSize = 4096; + }; + cache = + { config, lib, pkgs, ... }: + { virtualisation.additionalPaths = [ pkgs.stdenv pkgs.hello ]; + services.harmonia.enable = true; + networking.firewall.allowedTCPPorts = [ 5000 ]; + }; }; testScript = { nodes }: '' + cache.wait_for_unit("harmonia.service") + machine.succeed("mkdir -p /etc/containers") machine.succeed("""echo '{"default":[{"type":"insecureAcceptAnything"}]}' > /etc/containers/policy.json""") machine.succeed("${pkgs.podman}/bin/podman load -i ${nixImage}") machine.succeed("${pkgs.podman}/bin/podman run --rm nix nix --version") + machine.succeed("${pkgs.podman}/bin/podman run --rm -i nix < ${containerTestScript}") machine.succeed("${pkgs.podman}/bin/podman load -i ${nixUserImage}") machine.succeed("${pkgs.podman}/bin/podman run --rm nix-user nix --version") + machine.succeed("${pkgs.podman}/bin/podman run --rm -i nix-user < ${containerTestScript}") machine.succeed("[[ $(${pkgs.podman}/bin/podman run --rm nix-user stat -c %u /nix/store) = 1000 ]]") ''; } From 355f08a728f73f21e287926c3fded19ed975e40d Mon Sep 17 00:00:00 2001 From: John Ericson Date: Tue, 12 Nov 2024 00:48:40 -0500 Subject: [PATCH 430/718] Fix argument order in the Windows implementation of `getEnvOs` See the build failure in https://github.com/msys2/MINGW-packages/pull/22499 --- src/libutil/windows/environment-variables.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libutil/windows/environment-variables.cc b/src/libutil/windows/environment-variables.cc index 525d08c64..5ce8a1395 100644 --- a/src/libutil/windows/environment-variables.cc +++ b/src/libutil/windows/environment-variables.cc @@ -13,7 +13,7 @@ std::optional getEnvOs(const OsString & key) } // Allocate a buffer to hold the environment variable value - std::wstring value{L'\0', bufferSize}; + std::wstring value{bufferSize, L'\0'}; // Retrieve the environment variable value DWORD resultSize = GetEnvironmentVariableW(key.c_str(), &value[0], bufferSize); From 02f0294be09a2acf6b79ef88d9e8bcb231b99254 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 12 Nov 2024 15:31:37 +0100 Subject: [PATCH 431/718] Fix most DoxyGen warnings Helps with #11841. --- src/external-api-docs/doxygen.cfg.in | 6 ++-- src/internal-api-docs/doxygen.cfg.in | 26 +++++++++++---- src/internal-api-docs/meson.build | 1 + src/libexpr-c/nix_api_expr.h | 2 +- src/libexpr-c/nix_api_value.h | 7 ++-- src/libexpr/eval.hh | 2 +- src/libexpr/nixexpr.hh | 2 +- src/libexpr/value/context.hh | 12 +++---- src/libfetchers/fetchers.cc | 10 ++++-- src/libstore-c/nix_api_store.h | 2 +- .../tests/derived-path.cc | 2 +- src/libstore-tests/serve-protocol.cc | 4 +++ src/libstore-tests/worker-protocol.cc | 4 +++ src/libstore/build/goal.hh | 10 +++--- src/libstore/build/worker.hh | 2 +- src/libstore/content-address.hh | 11 ++++--- .../length-prefixed-protocol-helper.hh | 32 +++++++++---------- src/libstore/machines.hh | 4 +-- src/libstore/outputs-spec.cc | 17 +++++++--- src/libstore/path.hh | 2 +- src/libstore/profiles.hh | 4 ++- src/libstore/serve-protocol-impl.hh | 7 ++-- src/libstore/ssh.hh | 2 +- src/libstore/store-api.hh | 8 ++--- src/libstore/store-dir-config.hh | 8 ++--- src/libstore/store-reference.hh | 22 ++++++------- src/libstore/worker-protocol-connection.hh | 12 +++---- src/libstore/worker-protocol-impl.hh | 7 ++-- src/libutil-c/nix_api_util.h | 2 +- .../tests/gtest-with-params.hh | 4 ++- src/libutil/args.cc | 3 -- src/libutil/args.hh | 2 +- src/libutil/checked-arithmetic.hh | 4 ++- src/libutil/file-content-address.hh | 2 +- src/libutil/file-system.cc | 4 +-- src/libutil/file-system.hh | 6 +--- src/libutil/git.hh | 2 +- src/libutil/json-utils.hh | 9 ++++-- src/libutil/std-hash.hh | 11 ++++--- src/libutil/tarfile.cc | 6 ++-- src/nix/eval.cc | 2 +- 41 files changed, 161 insertions(+), 124 deletions(-) diff --git a/src/external-api-docs/doxygen.cfg.in b/src/external-api-docs/doxygen.cfg.in index 7ae4c83df..8e235dae5 100644 --- a/src/external-api-docs/doxygen.cfg.in +++ b/src/external-api-docs/doxygen.cfg.in @@ -41,7 +41,7 @@ INPUT = \ @src@/src/libutil-c \ @src@/src/libexpr-c \ @src@/src/libstore-c \ - @src@/doc/external-api/README.md + @src@/src/external-api-docs/README.md FILE_PATTERNS = nix_api_*.h *.md @@ -55,6 +55,8 @@ EXCLUDE_PATTERNS = *_internal.h GENERATE_TREEVIEW = YES OPTIMIZE_OUTPUT_FOR_C = YES -USE_MDFILE_AS_MAINPAGE = doc/external-api/README.md +USE_MDFILE_AS_MAINPAGE = @src@/src/external-api-docs/README.md +WARN_IF_UNDOCUMENTED = NO +WARN_IF_INCOMPLETE_DOC = NO QUIET = YES diff --git a/src/internal-api-docs/doxygen.cfg.in b/src/internal-api-docs/doxygen.cfg.in index bf4c42d11..950497ca3 100644 --- a/src/internal-api-docs/doxygen.cfg.in +++ b/src/internal-api-docs/doxygen.cfg.in @@ -43,8 +43,8 @@ INPUT = \ @src@/libexpr/flake \ @src@/libexpr-tests \ @src@/libexpr-tests/value \ - @src@/libexpr-test-support/test \ - @src@/libexpr-test-support/test/value \ + @src@/libexpr-test-support/tests \ + @src@/libexpr-test-support/tests/value \ @src@/libexpr/value \ @src@/libfetchers \ @src@/libmain \ @@ -52,10 +52,11 @@ INPUT = \ @src@/libstore/build \ @src@/libstore/builtins \ @src@/libstore-tests \ - @src@/libstore-test-support/test \ + @src@/libstore-test-support/tests \ @src@/libutil \ + @src@/libutil/args \ @src@/libutil-tests \ - @src@/libutil-test-support/test \ + @src@/libutil-test-support/tests \ @src@/nix \ @src@/nix-env \ @src@/nix-store @@ -83,7 +84,9 @@ EXPAND_ONLY_PREDEF = YES # RECURSIVE has no effect here. # This tag requires that the tag SEARCH_INCLUDES is set to YES. -INCLUDE_PATH = +INCLUDE_PATH = \ + @BUILD_ROOT@/src/libexpr/libnixexpr.so.p \ + @BUILD_ROOT@/src/nix/nix.p \ # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this # tag can be used to specify a list of macro names that should be expanded. The @@ -96,7 +99,18 @@ EXPAND_AS_DEFINED = \ DECLARE_COMMON_SERIALISER \ DECLARE_WORKER_SERIALISER \ DECLARE_SERVE_SERIALISER \ - LENGTH_PREFIXED_PROTO_HELPER + LENGTH_PREFIXED_PROTO_HELPER \ + LENGTH_PREFIXED_PROTO_HELPER_X \ + WORKER_USE_LENGTH_PREFIX_SERIALISER \ + WORKER_USE_LENGTH_PREFIX_SERIALISER_COMMA \ + SERVE_USE_LENGTH_PREFIX_SERIALISER \ + SERVE_USE_LENGTH_PREFIX_SERIALISER_COMMA \ + COMMON_METHODS \ + JSON_IMPL \ + MakeBinOp + +PREDEFINED = DOXYGEN_SKIP WARN_IF_UNDOCUMENTED = NO +WARN_IF_INCOMPLETE_DOC = NO QUIET = YES diff --git a/src/internal-api-docs/meson.build b/src/internal-api-docs/meson.build index 54eb7e5dd..c0426621e 100644 --- a/src/internal-api-docs/meson.build +++ b/src/internal-api-docs/meson.build @@ -12,6 +12,7 @@ doxygen_cfg = configure_file( configuration : { 'PROJECT_NUMBER': meson.project_version(), 'OUTPUT_DIRECTORY' : meson.current_build_dir(), + 'BUILD_ROOT' : meson.build_root(), 'src' : fs.parent(fs.parent(meson.project_source_root())) / 'src', }, ) diff --git a/src/libexpr-c/nix_api_expr.h b/src/libexpr-c/nix_api_expr.h index 1764b49f3..e680f5ff1 100644 --- a/src/libexpr-c/nix_api_expr.h +++ b/src/libexpr-c/nix_api_expr.h @@ -129,7 +129,7 @@ nix_err nix_value_call_multi( * @param[in] state The state of the evaluation. * @param[out] value The result of the function call. * @param[in] fn The Nix function to call. - * @param[in] args The arguments to pass to the function. + * @param[in] ... The arguments to pass to the function. * * @see nix_value_call_multi */ diff --git a/src/libexpr-c/nix_api_value.h b/src/libexpr-c/nix_api_value.h index 044f68c9e..8a0813ebe 100644 --- a/src/libexpr-c/nix_api_value.h +++ b/src/libexpr-c/nix_api_value.h @@ -77,8 +77,7 @@ typedef struct ExternalValue ExternalValue; */ typedef struct nix_realised_string nix_realised_string; -/** @defgroup primops - * @brief Create your own primops +/** @defgroup primops Adding primops * @{ */ /** @brief Function pointer for primops @@ -252,7 +251,7 @@ int64_t nix_get_int(nix_c_context * context, const nix_value * value); * @param[in] value Nix value to inspect * @return reference to external, NULL in case of error */ -ExternalValue * nix_get_external(nix_c_context * context, nix_value *); +ExternalValue * nix_get_external(nix_c_context * context, nix_value * value); /** @brief Get the ix'th element of a list * @@ -423,7 +422,7 @@ nix_list_builder_insert(nix_c_context * context, ListBuilder * list_builder, uns /** @brief Free a list builder * * Does not fail. - * @param[in] builder the builder to free + * @param[in] list_builder The builder to free. */ void nix_list_builder_free(ListBuilder * list_builder); diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 7fe70af31..a1882dded 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -91,7 +91,7 @@ struct PrimOp const char * doc = nullptr; /** - * Add a trace item, `while calling the '' builtin` + * Add a trace item, while calling the `` builtin. * * This is used to remove the redundant item for `builtins.addErrorContext`. */ diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh index bdf4e214a..948839bd9 100644 --- a/src/libexpr/nixexpr.hh +++ b/src/libexpr/nixexpr.hh @@ -206,7 +206,7 @@ struct ExprSelect : Expr /** * Evaluate the `a.b.c` part of `a.b.c.d`. This exists mostly for the purpose of :doc in the repl. * - * @param[out] v The attribute set that should contain the last attribute name (if it exists). + * @param[out] attrs The attribute set that should contain the last attribute name (if it exists). * @return The last attribute name in `attrPath` * * @note This does *not* evaluate the final attribute, and does not fail if that's the only attribute that does not exist. diff --git a/src/libexpr/value/context.hh b/src/libexpr/value/context.hh index 7f23cd3a4..d6791c6e4 100644 --- a/src/libexpr/value/context.hh +++ b/src/libexpr/value/context.hh @@ -28,7 +28,7 @@ struct NixStringContextElem { /** * Plain opaque path to some store object. * - * Encoded as just the path: ‘’. + * Encoded as just the path: ``. */ using Opaque = SingleDerivedPath::Opaque; @@ -39,7 +39,7 @@ struct NixStringContextElem { * also all outputs of all derivations in that closure (including the * root derivation). * - * Encoded in the form ‘=’. + * Encoded in the form `=`. */ struct DrvDeep { StorePath drvPath; @@ -50,7 +50,7 @@ struct NixStringContextElem { /** * Derivation output. * - * Encoded in the form ‘!!’. + * Encoded in the form `!!`. */ using Built = SingleDerivedPath::Built; @@ -68,9 +68,9 @@ struct NixStringContextElem { /** * Decode a context string, one of: - * - ‘’ - * - ‘=’ - * - ‘!!’ + * - `` + * - `=` + * - `!!` * * @param xpSettings Stop-gap to avoid globals during unit tests. */ diff --git a/src/libfetchers/fetchers.cc b/src/libfetchers/fetchers.cc index 5c06a6bcb..e15a460d0 100644 --- a/src/libfetchers/fetchers.cc +++ b/src/libfetchers/fetchers.cc @@ -475,7 +475,10 @@ namespace nlohmann { using namespace nix; -fetchers::PublicKey adl_serializer::from_json(const json & json) { +#ifndef DOXYGEN_SKIP + +fetchers::PublicKey adl_serializer::from_json(const json & json) +{ fetchers::PublicKey res = { }; if (auto type = optionalValueAt(json, "type")) res.type = getString(*type); @@ -485,9 +488,12 @@ fetchers::PublicKey adl_serializer::from_json(const json & return res; } -void adl_serializer::to_json(json & json, fetchers::PublicKey p) { +void adl_serializer::to_json(json & json, fetchers::PublicKey p) +{ json["type"] = p.type; json["key"] = p.key; } +#endif + } diff --git a/src/libstore-c/nix_api_store.h b/src/libstore-c/nix_api_store.h index 93208cb7c..282ccc285 100644 --- a/src/libstore-c/nix_api_store.h +++ b/src/libstore-c/nix_api_store.h @@ -166,7 +166,7 @@ nix_store_get_version(nix_c_context * context, Store * store, nix_get_string_cal * * @param[out] context Optional, stores error information * @param[in] srcStore nix source store reference - * @param[in] srcStore nix destination store reference + * @param[in] dstStore nix destination store reference * @param[in] path Path to copy */ nix_err nix_store_copy_closure(nix_c_context * context, Store * srcStore, Store * dstStore, StorePath * path); diff --git a/src/libstore-test-support/tests/derived-path.cc b/src/libstore-test-support/tests/derived-path.cc index 091706dba..078615bbd 100644 --- a/src/libstore-test-support/tests/derived-path.cc +++ b/src/libstore-test-support/tests/derived-path.cc @@ -7,7 +7,7 @@ namespace rc { using namespace nix; -Gen Arbitrary::arbitrary() +Gen Arbitrary::arbitrary() { return gen::just(DerivedPath::Opaque { .path = *gen::arbitrary(), diff --git a/src/libstore-tests/serve-protocol.cc b/src/libstore-tests/serve-protocol.cc index 5171fea0f..3dbbf3879 100644 --- a/src/libstore-tests/serve-protocol.cc +++ b/src/libstore-tests/serve-protocol.cc @@ -38,6 +38,8 @@ VERSIONED_CHARACTERIZATION_TEST( "oh no \0\0\0 what was that!", })) +#ifndef DOXYGEN_SKIP + VERSIONED_CHARACTERIZATION_TEST( ServeProtoTest, storePath, @@ -84,6 +86,8 @@ VERSIONED_CHARACTERIZATION_TEST( }, })) +#endif + VERSIONED_CHARACTERIZATION_TEST( ServeProtoTest, realisation, diff --git a/src/libstore-tests/worker-protocol.cc b/src/libstore-tests/worker-protocol.cc index 1185c37f4..99b042d5b 100644 --- a/src/libstore-tests/worker-protocol.cc +++ b/src/libstore-tests/worker-protocol.cc @@ -39,6 +39,8 @@ VERSIONED_CHARACTERIZATION_TEST( "oh no \0\0\0 what was that!", })) +#ifndef DOXYGEN_SKIP + VERSIONED_CHARACTERIZATION_TEST( WorkerProtoTest, storePath, @@ -69,6 +71,8 @@ VERSIONED_CHARACTERIZATION_TEST( }, })) +#endif + VERSIONED_CHARACTERIZATION_TEST( WorkerProtoTest, derivedPath_1_29, diff --git a/src/libstore/build/goal.hh b/src/libstore/build/goal.hh index 9c6a40c84..1dd7ed525 100644 --- a/src/libstore/build/goal.hh +++ b/src/libstore/build/goal.hh @@ -107,7 +107,7 @@ protected: public: /** - * Suspend our goal and wait until we get @ref work()-ed again. + * Suspend our goal and wait until we get `work`-ed again. * `co_await`-able by @ref Co. */ struct Suspend {}; @@ -192,7 +192,7 @@ public: bool await_ready() { return false; }; /** - * When we `co_await` another @ref Co-returning coroutine, + * When we `co_await` another `Co`-returning coroutine, * we tell the caller of `caller_coroutine.resume()` to switch to our coroutine (@ref handle). * To make sure we return to the original coroutine, we set it as the continuation of our * coroutine. In @ref promise_type::final_awaiter we check if it's set and if so we return to it. @@ -208,7 +208,7 @@ public: }; /** - * Used on initial suspend, does the same as @ref std::suspend_always, + * Used on initial suspend, does the same as `std::suspend_always`, * but asserts that everything has been set correctly. */ struct InitialSuspend { @@ -269,8 +269,8 @@ public: }; /** - * Called by compiler generated code to construct the @ref Co - * that is returned from a @ref Co-returning coroutine. + * Called by compiler generated code to construct the `Co` + * that is returned from a `Co`-returning coroutine. */ Co get_return_object(); diff --git a/src/libstore/build/worker.hh b/src/libstore/build/worker.hh index e083dbea6..f5e617208 100644 --- a/src/libstore/build/worker.hh +++ b/src/libstore/build/worker.hh @@ -208,7 +208,7 @@ public: const OutputsSpec & wantedOutputs, BuildMode buildMode = bmNormal); /** - * @ref SubstitutionGoal "substitution goal" + * @ref PathSubstitutionGoal "substitution goal" */ std::shared_ptr makePathSubstitutionGoal(const StorePath & storePath, RepairFlag repair = NoRepair, std::optional ca = std::nullopt); std::shared_ptr makeDrvOutputSubstitutionGoal(const DrvOutput & id, RepairFlag repair = NoRepair, std::optional ca = std::nullopt); diff --git a/src/libstore/content-address.hh b/src/libstore/content-address.hh index bb515013a..2b5d1296a 100644 --- a/src/libstore/content-address.hh +++ b/src/libstore/content-address.hh @@ -97,8 +97,9 @@ struct ContentAddressMethod * were ingested, with the fixed output case not prefixed for back * compat. * - * @param [in] m A string that should begin with the prefix. - * @param [out] m The remainder of the string after the prefix. + * @param m A string that should begin with the + * prefix. On return, the remainder of the string after the + * prefix. */ static ContentAddressMethod parsePrefix(std::string_view & m); @@ -139,14 +140,14 @@ struct ContentAddressMethod /** * We've accumulated several types of content-addressed paths over the * years; fixed-output derivations support multiple hash algorithms and - * serialisation methods (flat file vs NAR). Thus, ‘ca’ has one of the + * serialisation methods (flat file vs NAR). Thus, `ca` has one of the * following forms: * * - `TextIngestionMethod`: - * ‘text:sha256:’ + * `text:sha256:` * * - `FixedIngestionMethod`: - * ‘fixed:::’ + * `fixed:::` */ struct ContentAddress { diff --git a/src/libstore/length-prefixed-protocol-helper.hh b/src/libstore/length-prefixed-protocol-helper.hh index 0cf950a47..7e977bbf1 100644 --- a/src/libstore/length-prefixed-protocol-helper.hh +++ b/src/libstore/length-prefixed-protocol-helper.hh @@ -1,6 +1,8 @@ #pragma once /** - * @file Reusable serialisers for serialization container types in a + * @file + * + * Reusable serialisers for serialization container types in a * length-prefixed manner. * * Used by both the Worker and Serve protocols. @@ -28,25 +30,22 @@ struct StoreDirConfig; template struct LengthPrefixedProtoHelper; -/*! - * \typedef LengthPrefixedProtoHelper::S - * - * Read this as simply `using S = Inner::Serialise;`. - * - * It would be nice to use that directly, but C++ doesn't seem to allow - * it. The `typename` keyword needed to refer to `Inner` seems to greedy - * (low precedence), and then C++ complains that `Serialise` is not a - * type parameter but a real type. - * - * Making this `S` alias seems to be the only way to avoid these issues. - */ - #define LENGTH_PREFIXED_PROTO_HELPER(Inner, T) \ struct LengthPrefixedProtoHelper< Inner, T > \ { \ static T read(const StoreDirConfig & store, typename Inner::ReadConn conn); \ static void write(const StoreDirConfig & store, typename Inner::WriteConn conn, const T & str); \ private: \ + /*! \ + * Read this as simply `using S = Inner::Serialise;`. \ + * \ + * It would be nice to use that directly, but C++ doesn't seem to allow \ + * it. The `typename` keyword needed to refer to `Inner` seems to greedy \ + * (low precedence), and then C++ complains that `Serialise` is not a \ + * type parameter but a real type. \ + * \ + * Making this `S` alias seems to be the only way to avoid these issues. \ + */ \ template using S = typename Inner::template Serialise; \ } @@ -60,9 +59,8 @@ template LENGTH_PREFIXED_PROTO_HELPER(Inner, std::tuple); template -#define _X std::map -LENGTH_PREFIXED_PROTO_HELPER(Inner, _X); -#undef _X +#define LENGTH_PREFIXED_PROTO_HELPER_X std::map +LENGTH_PREFIXED_PROTO_HELPER(Inner, LENGTH_PREFIXED_PROTO_HELPER_X); template std::vector diff --git a/src/libstore/machines.hh b/src/libstore/machines.hh index 983652d5f..b70ab9078 100644 --- a/src/libstore/machines.hh +++ b/src/libstore/machines.hh @@ -32,12 +32,12 @@ struct Machine { /** * @return Whether `features` is a subset of the union of `supportedFeatures` and - * `mandatoryFeatures` + * `mandatoryFeatures`. */ bool allSupported(const std::set & features) const; /** - * @return @Whether `mandatoryFeatures` is a subset of `features` + * @return Whether `mandatoryFeatures` is a subset of `features`. */ bool mandatoryMet(const std::set & features) const; diff --git a/src/libstore/outputs-spec.cc b/src/libstore/outputs-spec.cc index f5ecbd74b..b623a975c 100644 --- a/src/libstore/outputs-spec.cc +++ b/src/libstore/outputs-spec.cc @@ -153,7 +153,10 @@ namespace nlohmann { using namespace nix; -OutputsSpec adl_serializer::from_json(const json & json) { +#ifndef DOXYGEN_SKIP + +OutputsSpec adl_serializer::from_json(const json & json) +{ auto names = json.get(); if (names == StringSet({"*"})) return OutputsSpec::All {}; @@ -161,7 +164,8 @@ OutputsSpec adl_serializer::from_json(const json & json) { return OutputsSpec::Names { std::move(names) }; } -void adl_serializer::to_json(json & json, OutputsSpec t) { +void adl_serializer::to_json(json & json, OutputsSpec t) +{ std::visit(overloaded { [&](const OutputsSpec::All &) { json = std::vector({"*"}); @@ -172,8 +176,8 @@ void adl_serializer::to_json(json & json, OutputsSpec t) { }, t.raw); } - -ExtendedOutputsSpec adl_serializer::from_json(const json & json) { +ExtendedOutputsSpec adl_serializer::from_json(const json & json) +{ if (json.is_null()) return ExtendedOutputsSpec::Default {}; else { @@ -181,7 +185,8 @@ ExtendedOutputsSpec adl_serializer::from_json(const json & } } -void adl_serializer::to_json(json & json, ExtendedOutputsSpec t) { +void adl_serializer::to_json(json & json, ExtendedOutputsSpec t) +{ std::visit(overloaded { [&](const ExtendedOutputsSpec::Default &) { json = nullptr; @@ -192,4 +197,6 @@ void adl_serializer::to_json(json & json, ExtendedOutputsSp }, t.raw); } +#endif + } diff --git a/src/libstore/path.hh b/src/libstore/path.hh index 2380dc6a2..902262362 100644 --- a/src/libstore/path.hh +++ b/src/libstore/path.hh @@ -81,7 +81,7 @@ typedef std::set StorePathSet; typedef std::vector StorePaths; /** - * The file extension of \ref Derivation derivations when serialized + * The file extension of \ref nix::Derivation derivations when serialized * into store objects. */ constexpr std::string_view drvExtension = ".drv"; diff --git a/src/libstore/profiles.hh b/src/libstore/profiles.hh index b10a72330..33fcf04b3 100644 --- a/src/libstore/profiles.hh +++ b/src/libstore/profiles.hh @@ -1,6 +1,8 @@ #pragma once /** - * @file Implementation of Profiles. + * @file + * + * Implementation of Profiles. * * See the manual for additional information. */ diff --git a/src/libstore/serve-protocol-impl.hh b/src/libstore/serve-protocol-impl.hh index 6f3b177ac..099eade64 100644 --- a/src/libstore/serve-protocol-impl.hh +++ b/src/libstore/serve-protocol-impl.hh @@ -29,11 +29,10 @@ SERVE_USE_LENGTH_PREFIX_SERIALISER(template, std::vector) SERVE_USE_LENGTH_PREFIX_SERIALISER(template, std::set) SERVE_USE_LENGTH_PREFIX_SERIALISER(template, std::tuple) -#define COMMA_ , +#define SERVE_USE_LENGTH_PREFIX_SERIALISER_COMMA , SERVE_USE_LENGTH_PREFIX_SERIALISER( - template, - std::map) -#undef COMMA_ + template, + std::map) /** * Use `CommonProto` where possible. diff --git a/src/libstore/ssh.hh b/src/libstore/ssh.hh index 4097134d0..85be704ec 100644 --- a/src/libstore/ssh.hh +++ b/src/libstore/ssh.hh @@ -59,7 +59,7 @@ public: /** * @param command The command (arg vector) to execute. * - * @param extraSShArgs Extra args to pass to SSH (not the command to + * @param extraSshArgs Extra arguments to pass to SSH (not the command to * execute). Will not be used when "fake SSHing" to the local * machine. */ diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh index 8288cfdf0..f45012061 100644 --- a/src/libstore/store-api.hh +++ b/src/libstore/store-api.hh @@ -260,11 +260,11 @@ public: /** * Query the set of all valid paths. Note that for some store - * backends, the name part of store paths may be replaced by 'x' - * (i.e. you'll get /nix/store/-x rather than - * /nix/store/-). Use queryPathInfo() to obtain the + * backends, the name part of store paths may be replaced by `x` + * (i.e. you'll get `/nix/store/-x` rather than + * `/nix/store/-`). Use queryPathInfo() to obtain the * full store path. FIXME: should return a set of - * std::variant to get rid of this hack. + * `std::variant` to get rid of this hack. */ virtual StorePathSet queryAllValidPaths() { unsupported("queryAllValidPaths"); } diff --git a/src/libstore/store-dir-config.hh b/src/libstore/store-dir-config.hh index 64c0dd8b7..fd4332b91 100644 --- a/src/libstore/store-dir-config.hh +++ b/src/libstore/store-dir-config.hh @@ -59,20 +59,20 @@ struct StoreDirConfig : public Config std::string showPaths(const StorePathSet & paths); /** - * @return true if ‘path’ is in the Nix store (but not the Nix + * @return true if *path* is in the Nix store (but not the Nix * store itself). */ bool isInStore(PathView path) const; /** - * @return true if ‘path’ is a store path, i.e. a direct child of the + * @return true if *path* is a store path, i.e. a direct child of the * Nix store. */ bool isStorePath(std::string_view path) const; /** - * Split a path like /nix/store/-/ into - * /nix/store/- and /. + * Split a path like `/nix/store/-/` into + * `/nix/store/-` and `/`. */ std::pair toStorePath(PathView path) const; diff --git a/src/libstore/store-reference.hh b/src/libstore/store-reference.hh index 459cea9c2..7100a1db0 100644 --- a/src/libstore/store-reference.hh +++ b/src/libstore/store-reference.hh @@ -13,31 +13,31 @@ namespace nix { * * Supported values are: * - * - ‘local’: The Nix store in /nix/store and database in + * - `local`: The Nix store in /nix/store and database in * /nix/var/nix/db, accessed directly. * - * - ‘daemon’: The Nix store accessed via a Unix domain socket + * - `daemon`: The Nix store accessed via a Unix domain socket * connection to nix-daemon. * - * - ‘unix://’: The Nix store accessed via a Unix domain socket - * connection to nix-daemon, with the socket located at . + * - `unix://`: The Nix store accessed via a Unix domain socket + * connection to nix-daemon, with the socket located at ``. * - * - ‘auto’ or ‘’: Equivalent to ‘local’ or ‘daemon’ depending on + * - `auto` or ``: Equivalent to `local` or `daemon` depending on * whether the user has write access to the local Nix * store/database. * - * - ‘file://’: A binary cache stored in . + * - `file://`: A binary cache stored in ``. * - * - ‘https://’: A binary cache accessed via HTTP. + * - `https://`: A binary cache accessed via HTTP. * - * - ‘s3://’: A writable binary cache stored on Amazon's Simple + * - `s3://`: A writable binary cache stored on Amazon's Simple * Storage Service. * - * - ‘ssh://[user@]’: A remote Nix store accessed by running - * ‘nix-store --serve’ via SSH. + * - `ssh://[user@]`: A remote Nix store accessed by running + * `nix-store --serve` via SSH. * * You can pass parameters to the store type by appending - * ‘?key=value&key=value&...’ to the URI. + * `?key=value&key=value&...` to the URI. */ struct StoreReference { diff --git a/src/libstore/worker-protocol-connection.hh b/src/libstore/worker-protocol-connection.hh index 9665067dd..c2f446db1 100644 --- a/src/libstore/worker-protocol-connection.hh +++ b/src/libstore/worker-protocol-connection.hh @@ -78,7 +78,7 @@ struct WorkerProto::BasicClientConnection : WorkerProto::BasicConnection /** * Establishes connection, negotiating version. * - * @return the minimum version supported by both sides and the set + * @return The minimum version supported by both sides and the set * of protocol features supported by both sides. * * @param to Taken by reference to allow for various error handling @@ -87,9 +87,9 @@ struct WorkerProto::BasicClientConnection : WorkerProto::BasicConnection * @param from Taken by reference to allow for various error * handling mechanisms. * - * @param localVersion Our version which is sent over + * @param localVersion Our version which is sent over. * - * @param features The protocol features that we support + * @param supportedFeatures The protocol features that we support. */ // FIXME: this should probably be a constructor. static std::tuple> handshake( @@ -141,7 +141,7 @@ struct WorkerProto::BasicServerConnection : WorkerProto::BasicConnection /** * Establishes connection, negotiating version. * - * @return the version provided by the other side of the + * @return The version provided by the other side of the * connection. * * @param to Taken by reference to allow for various error handling @@ -150,9 +150,9 @@ struct WorkerProto::BasicServerConnection : WorkerProto::BasicConnection * @param from Taken by reference to allow for various error * handling mechanisms. * - * @param localVersion Our version which is sent over + * @param localVersion Our version which is sent over. * - * @param features The protocol features that we support + * @param supportedFeatures The protocol features that we support. */ // FIXME: this should probably be a constructor. static std::tuple> handshake( diff --git a/src/libstore/worker-protocol-impl.hh b/src/libstore/worker-protocol-impl.hh index 026cc37bc..87398df90 100644 --- a/src/libstore/worker-protocol-impl.hh +++ b/src/libstore/worker-protocol-impl.hh @@ -29,11 +29,10 @@ WORKER_USE_LENGTH_PREFIX_SERIALISER(template, std::vector) WORKER_USE_LENGTH_PREFIX_SERIALISER(template, std::set) WORKER_USE_LENGTH_PREFIX_SERIALISER(template, std::tuple) -#define COMMA_ , +#define WORKER_USE_LENGTH_PREFIX_SERIALISER_COMMA , WORKER_USE_LENGTH_PREFIX_SERIALISER( - template, - std::map) -#undef COMMA_ + template, + std::map) /** * Use `CommonProto` where possible. diff --git a/src/libutil-c/nix_api_util.h b/src/libutil-c/nix_api_util.h index 6790a6964..43f9fa9dc 100644 --- a/src/libutil-c/nix_api_util.h +++ b/src/libutil-c/nix_api_util.h @@ -162,7 +162,7 @@ void nix_c_context_free(nix_c_context * context); */ nix_err nix_libutil_init(nix_c_context * context); -/** @defgroup settings +/** @defgroup settings Nix configuration settings * @{ */ /** diff --git a/src/libutil-test-support/tests/gtest-with-params.hh b/src/libutil-test-support/tests/gtest-with-params.hh index 323a083fe..d72aec4fd 100644 --- a/src/libutil-test-support/tests/gtest-with-params.hh +++ b/src/libutil-test-support/tests/gtest-with-params.hh @@ -6,7 +6,9 @@ // The lion's share of this code is copy pasted directly out of RapidCheck // headers, so the copyright is set accordingly. /** - * @file Implements the ability to run a RapidCheck test under gtest with changed + * @file + * + * Implements the ability to run a RapidCheck test under gtest with changed * test parameters such as the number of tests to run. This is useful for * running very large numbers of the extremely cheap property tests. */ diff --git a/src/libutil/args.cc b/src/libutil/args.cc index 4e87389d6..385b6cd34 100644 --- a/src/libutil/args.cc +++ b/src/libutil/args.cc @@ -91,9 +91,6 @@ struct Parser { /** * @brief Parse the next character(s) - * - * @param r - * @return std::shared_ptr */ virtual void operator()(std::shared_ptr & state, Strings & r) = 0; diff --git a/src/libutil/args.hh b/src/libutil/args.hh index 127a0809e..c30d6cef8 100644 --- a/src/libutil/args.hh +++ b/src/libutil/args.hh @@ -371,7 +371,7 @@ using Commands = std::map()>>; /** * An argument parser that supports multiple subcommands, - * i.e. ‘ ’. + * i.e. ` `. */ class MultiCommand : virtual public Args { diff --git a/src/libutil/checked-arithmetic.hh b/src/libutil/checked-arithmetic.hh index 55d6ad205..dcc6d86af 100644 --- a/src/libutil/checked-arithmetic.hh +++ b/src/libutil/checked-arithmetic.hh @@ -1,6 +1,8 @@ #pragma once /** - * @file Checked arithmetic with classes that make it hard to accidentally make something an unchecked operation. + * @file + * + * Checked arithmetic with classes that make it hard to accidentally make something an unchecked operation. */ #include diff --git a/src/libutil/file-content-address.hh b/src/libutil/file-content-address.hh index 0c584ea8a..226068387 100644 --- a/src/libutil/file-content-address.hh +++ b/src/libutil/file-content-address.hh @@ -65,7 +65,7 @@ void dumpPath( /** * Restore a serialisation of the given file system object. * - * @TODO use an arbitrary `FileSystemObjectSink`. + * \todo use an arbitrary `FileSystemObjectSink`. */ void restorePath( const Path & path, diff --git a/src/libutil/file-system.cc b/src/libutil/file-system.cc index fd51d7d3c..2802bbf98 100644 --- a/src/libutil/file-system.cc +++ b/src/libutil/file-system.cc @@ -29,7 +29,7 @@ namespace nix { -namespace fs { using namespace std::filesystem; } +namespace fs = std::filesystem; /** * Treat the string as possibly an absolute path, by inspecting the @@ -501,7 +501,7 @@ void deletePath(const fs::path & path, uint64_t & bytesFreed) AutoDelete::AutoDelete() : del{false} {} -AutoDelete::AutoDelete(const fs::path & p, bool recursive) : _path(p) +AutoDelete::AutoDelete(const std::filesystem::path & p, bool recursive) : _path(p) { del = true; this->recursive = recursive; diff --git a/src/libutil/file-system.hh b/src/libutil/file-system.hh index eb3e4ec66..da864d500 100644 --- a/src/libutil/file-system.hh +++ b/src/libutil/file-system.hh @@ -126,8 +126,6 @@ std::optional maybeLstat(const Path & path); */ bool pathExists(const Path & path); -namespace fs { - /** * ``` * symlink_exists(p) = std::filesystem::exists(std::filesystem::symlink_status(p)) @@ -141,8 +139,6 @@ inline bool symlink_exists(const std::filesystem::path & path) { return std::filesystem::exists(std::filesystem::symlink_status(path)); } -} // namespace fs - /** * A version of pathExists that returns false on a permission error. * Useful for inferring default paths across directories that might not @@ -227,7 +223,7 @@ void createDir(const Path & path, mode_t mode = 0755); * Set the access and modification times of the given path, not * following symlinks. * - * @param accessTime Specified in seconds. + * @param accessedTime Specified in seconds. * * @param modificationTime Specified in seconds. * diff --git a/src/libutil/git.hh b/src/libutil/git.hh index 1dbdb7335..1a6a7c333 100644 --- a/src/libutil/git.hh +++ b/src/libutil/git.hh @@ -104,7 +104,7 @@ void parseTree( /** * Helper putting the previous three `parse*` functions together. * - * @rootModeIfBlob How to interpret a root blob, for which there is no + * @param rootModeIfBlob How to interpret a root blob, for which there is no * disambiguating dir entry to answer that questino. If the root it not * a blob, this is ignored. */ diff --git a/src/libutil/json-utils.hh b/src/libutil/json-utils.hh index a61c9cada..546334e1e 100644 --- a/src/libutil/json-utils.hh +++ b/src/libutil/json-utils.hh @@ -91,12 +91,14 @@ namespace nlohmann { * round trip. We do that with a static assert. */ template -struct adl_serializer> { +struct adl_serializer> +{ /** * @brief Convert a JSON type to an `optional` treating * `null` as `std::nullopt`. */ - static void from_json(const json & json, std::optional & t) { + static void from_json(const json & json, std::optional & t) + { static_assert( nix::json_avoids_null::value, "null is already in use for underlying type's JSON"); @@ -109,7 +111,8 @@ struct adl_serializer> { * @brief Convert an optional type to a JSON type treating `std::nullopt` * as `null`. */ - static void to_json(json & json, const std::optional & t) { + static void to_json(json & json, const std::optional & t) + { static_assert( nix::json_avoids_null::value, "null is already in use for underlying type's JSON"); diff --git a/src/libutil/std-hash.hh b/src/libutil/std-hash.hh index c359d11ca..f99faac46 100644 --- a/src/libutil/std-hash.hh +++ b/src/libutil/std-hash.hh @@ -1,14 +1,17 @@ #pragma once - -//!@file Hashing utilities for use with unordered_map, etc. (ie low level implementation logic, not domain logic like -//! Nix hashing) +/** + * @file + * + * Hashing utilities for use with `std::unordered_map`, etc. (i.e. low + * level implementation logic, not domain logic like Nix hashing). + */ #include namespace nix { /** - * hash_combine() from Boost. Hash several hashable values together + * `hash_combine()` from Boost. Hash several hashable values together * into a single hash. */ inline void hash_combine(std::size_t & seed) {} diff --git a/src/libutil/tarfile.cc b/src/libutil/tarfile.cc index a8a22d283..397169757 100644 --- a/src/libutil/tarfile.cc +++ b/src/libutil/tarfile.cc @@ -8,9 +8,7 @@ namespace nix { -namespace fs { -using namespace std::filesystem; -} +namespace fs = std::filesystem; namespace { @@ -106,7 +104,7 @@ TarArchive::TarArchive(Source & source, bool raw, std::optional com "Failed to open archive (%s)"); } -TarArchive::TarArchive(const fs::path & path) +TarArchive::TarArchive(const std::filesystem::path & path) : archive{archive_read_new()} , buffer(defaultBufferSize) { diff --git a/src/nix/eval.cc b/src/nix/eval.cc index 7811b77ed..a8c18fef6 100644 --- a/src/nix/eval.cc +++ b/src/nix/eval.cc @@ -77,7 +77,7 @@ struct CmdEval : MixJSON, InstallableValueCommand, MixReadOnlyOption if (writeTo) { stopProgressBar(); - if (fs::symlink_exists(*writeTo)) + if (nix::symlink_exists(*writeTo)) throw Error("path '%s' already exists", writeTo->string()); std::function recurse; From 000d06d85b0b3676b255c466837a00555b39d581 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 12 Nov 2024 16:42:43 +0100 Subject: [PATCH 432/718] Provide a "nix" package --- flake.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 4d339f6e7..06025e3b7 100644 --- a/flake.nix +++ b/flake.nix @@ -218,8 +218,9 @@ # for which we don't apply the full build matrix such as cross or static. inherit (nixpkgsFor.${system}.native) changelog-d; + default = self.packages.${system}.nix; # TODO probably should be `nix-cli` - default = self.packages.${system}.nix-everything; + nix = self.packages.${system}.nix-everything; nix-manual = nixpkgsFor.${system}.native.nixComponents.nix-manual; nix-internal-api-docs = nixpkgsFor.${system}.native.nixComponents.nix-internal-api-docs; nix-external-api-docs = nixpkgsFor.${system}.native.nixComponents.nix-external-api-docs; From 06769eb2bf5084b7a1cadfccc18050b831519383 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 12 Nov 2024 16:42:59 +0100 Subject: [PATCH 433/718] nix-everything: Pass through a version attribute The existence of this attribute is assumed by the Determinate Installer packaging and maybe others. --- packaging/everything.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packaging/everything.nix b/packaging/everything.nix index ae2f93da0..6f6bbc6aa 100644 --- a/packaging/everything.nix +++ b/packaging/everything.nix @@ -95,6 +95,8 @@ nix-functional-tests ]; passthru = prevAttrs.passthru // { + inherit (nix-cli) version; + /** These are the libraries that are part of the Nix project. They are used by the Nix CLI and other tools. From a2e4a4c2384789d92b300959995a7d9d0e9d725f Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 12 Nov 2024 19:26:39 +0100 Subject: [PATCH 434/718] callFunction: Use std::span This is a bit safer than having a separate nrArgs argument. --- src/libexpr-c/nix_api_expr.cc | 2 +- src/libexpr/eval.cc | 32 ++++++++++++++------------------ src/libexpr/eval.hh | 5 ++--- src/libexpr/primops.cc | 8 ++++---- src/libflake/flake/flake.cc | 2 +- 5 files changed, 22 insertions(+), 27 deletions(-) diff --git a/src/libexpr-c/nix_api_expr.cc b/src/libexpr-c/nix_api_expr.cc index 333e99460..6144a7986 100644 --- a/src/libexpr-c/nix_api_expr.cc +++ b/src/libexpr-c/nix_api_expr.cc @@ -67,7 +67,7 @@ nix_err nix_value_call_multi(nix_c_context * context, EvalState * state, nix_val if (context) context->last_err_code = NIX_OK; try { - state->state.callFunction(fn->value, nargs, (nix::Value * *)args, value->value, nix::noPos); + state->state.callFunction(fn->value, {(nix::Value * *) args, nargs}, value->value, nix::noPos); state->state.forceValue(value->value, nix::noPos); } NIXC_CATCH_ERRS diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index e21f70553..6e82af1d8 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -588,14 +588,14 @@ std::optional EvalState::getDoc(Value & v) if (isFunctor(v)) { try { Value & functor = *v.attrs()->find(sFunctor)->value; - Value * vp = &v; + Value * vp[] = {&v}; Value partiallyApplied; // The first paramater is not user-provided, and may be // handled by code that is opaque to the user, like lib.const = x: y: y; // So preferably we show docs that are relevant to the // "partially applied" function returned by e.g. `const`. // We apply the first argument: - callFunction(functor, 1, &vp, partiallyApplied, noPos); + callFunction(functor, vp, partiallyApplied, noPos); auto _level = addCallDepth(noPos); return getDoc(partiallyApplied); } @@ -1460,7 +1460,7 @@ void ExprLambda::eval(EvalState & state, Env & env, Value & v) v.mkLambda(&env, this); } -void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value & vRes, const PosIdx pos) +void EvalState::callFunction(Value & fun, std::span args, Value & vRes, const PosIdx pos) { auto _level = addCallDepth(pos); @@ -1475,7 +1475,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value & auto makeAppChain = [&]() { vRes = vCur; - for (size_t i = 0; i < nrArgs; ++i) { + for (size_t i = 0; i < args.size(); ++i) { auto fun2 = allocValue(); *fun2 = vRes; vRes.mkPrimOpApp(fun2, args[i]); @@ -1484,7 +1484,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value & const Attr * functor; - while (nrArgs > 0) { + while (args.size() > 0) { if (vCur.isLambda()) { @@ -1587,15 +1587,14 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value & throw; } - nrArgs--; - args += 1; + args = args.subspan(1); } else if (vCur.isPrimOp()) { size_t argsLeft = vCur.primOp()->arity; - if (nrArgs < argsLeft) { + if (args.size() < argsLeft) { /* We don't have enough arguments, so create a tPrimOpApp chain. */ makeAppChain(); return; @@ -1607,15 +1606,14 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value & if (countCalls) primOpCalls[fn->name]++; try { - fn->fun(*this, vCur.determinePos(noPos), args, vCur); + fn->fun(*this, vCur.determinePos(noPos), args.data(), vCur); } catch (Error & e) { if (fn->addTrace) addErrorTrace(e, pos, "while calling the '%1%' builtin", fn->name); throw; } - nrArgs -= argsLeft; - args += argsLeft; + args = args.subspan(argsLeft); } } @@ -1631,7 +1629,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value & auto arity = primOp->primOp()->arity; auto argsLeft = arity - argsDone; - if (nrArgs < argsLeft) { + if (args.size() < argsLeft) { /* We still don't have enough arguments, so extend the tPrimOpApp chain. */ makeAppChain(); return; @@ -1663,8 +1661,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value & throw; } - nrArgs -= argsLeft; - args += argsLeft; + args = args.subspan(argsLeft); } } @@ -1675,13 +1672,12 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value & Value * args2[] = {allocValue(), args[0]}; *args2[0] = vCur; try { - callFunction(*functor->value, 2, args2, vCur, functor->pos); + callFunction(*functor->value, args2, vCur, functor->pos); } catch (Error & e) { e.addTrace(positions[pos], "while calling a functor (an attribute set with a '__functor' attribute)"); throw; } - nrArgs--; - args++; + args = args.subspan(1); } else @@ -1724,7 +1720,7 @@ void ExprCall::eval(EvalState & state, Env & env, Value & v) for (size_t i = 0; i < args.size(); ++i) vArgs[i] = args[i]->maybeThunk(state, env); - state.callFunction(vFun, args.size(), vArgs.data(), v, pos); + state.callFunction(vFun, vArgs, v, pos); } diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 7fe70af31..b0c79ab86 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -690,13 +690,12 @@ public: bool isFunctor(Value & fun); - // FIXME: use std::span - void callFunction(Value & fun, size_t nrArgs, Value * * args, Value & vRes, const PosIdx pos); + void callFunction(Value & fun, std::span args, Value & vRes, const PosIdx pos); void callFunction(Value & fun, Value & arg, Value & vRes, const PosIdx pos) { Value * args[] = {&arg}; - callFunction(fun, 1, args, vRes, pos); + callFunction(fun, args, vRes, pos); } /** diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 45d9f86ac..aea623435 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -724,7 +724,7 @@ static void prim_genericClosure(EvalState & state, const PosIdx pos, Value * * a /* Call the `operator' function with `e' as argument. */ Value newElements; - state.callFunction(*op->value, 1, &e, newElements, noPos); + state.callFunction(*op->value, {&e, 1}, newElements, noPos); state.forceList(newElements, noPos, "while evaluating the return value of the `operator` passed to builtins.genericClosure"); /* Add the values returned by the operator to the work set. */ @@ -2450,7 +2450,7 @@ bool EvalState::callPathFilter( // assert that type is not "unknown" Value * args []{&arg1, fileTypeToString(*this, st.type)}; Value res; - callFunction(*filterFun, 2, args, res, pos); + callFunction(*filterFun, args, res, pos); return forceBool(res, pos, "while evaluating the return value of the path filter function"); } @@ -3487,7 +3487,7 @@ static void prim_foldlStrict(EvalState & state, const PosIdx pos, Value * * args for (auto [n, elem] : enumerate(args[2]->listItems())) { Value * vs []{vCur, elem}; vCur = n == args[2]->listSize() - 1 ? &v : state.allocValue(); - state.callFunction(*args[0], 2, vs, *vCur, pos); + state.callFunction(*args[0], vs, *vCur, pos); } state.forceValue(v, pos); } else { @@ -3637,7 +3637,7 @@ static void prim_sort(EvalState & state, const PosIdx pos, Value * * args, Value Value * vs[] = {a, b}; Value vBool; - state.callFunction(*args[0], 2, vs, vBool, noPos); + state.callFunction(*args[0], vs, vBool, noPos); return state.forceBool(vBool, pos, "while evaluating the return value of the sorting function passed to builtins.sort"); }; diff --git a/src/libflake/flake/flake.cc b/src/libflake/flake/flake.cc index edb76f861..19b622a34 100644 --- a/src/libflake/flake/flake.cc +++ b/src/libflake/flake/flake.cc @@ -816,7 +816,7 @@ void callFlake(EvalState & state, assert(vFetchFinalTree); Value * args[] = {vLocks, &vOverrides, *vFetchFinalTree}; - state.callFunction(*vCallFlake, 3, args, vRes, noPos); + state.callFunction(*vCallFlake, args, vRes, noPos); } void initLib(const Settings & settings) From d4cec7511db159523a0101f36033393533bb4309 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Tue, 12 Nov 2024 19:49:39 +0100 Subject: [PATCH 435/718] nix-everything: Remove libs, add dev and devdoc package outputs The new package output attributes are somewhat experimental, and provided for compatibility most of all. We'll see how well this goes before the changes proposed in https://github.com/NixOS/nix/issues/6507 --- packaging/everything.nix | 139 +++++++++++++++++++++++++++++---------- 1 file changed, 104 insertions(+), 35 deletions(-) diff --git a/packaging/everything.nix b/packaging/everything.nix index 6f6bbc6aa..458d26c30 100644 --- a/packaging/everything.nix +++ b/packaging/everything.nix @@ -5,12 +5,10 @@ nix-util, nix-util-c, - nix-util-test-support, nix-util-tests, nix-store, nix-store-c, - nix-store-test-support, nix-store-tests, nix-fetchers, @@ -18,7 +16,6 @@ nix-expr, nix-expr-c, - nix-expr-test-support, nix-expr-tests, nix-flake, @@ -38,45 +35,84 @@ nix-external-api-docs, nix-perl-bindings, + + testers, + runCommand, }: +let + dev = stdenv.mkDerivation (finalAttrs: { + name = "nix-${nix-cli.version}-dev"; + pname = "nix"; + version = nix-cli.version; + dontUnpack = true; + dontBuild = true; + libs = map lib.getDev [ + nix-cmd + nix-expr + nix-expr-c + nix-fetchers + nix-flake + nix-main + nix-main-c + nix-store + nix-store-c + nix-util + nix-util-c + nix-perl-bindings + ]; + installPhase = '' + mkdir -p $out/nix-support + echo $libs >> $out/nix-support/propagated-build-inputs + ''; + passthru = { + tests = { + pkg-config = + testers.hasPkgConfigModules { + package = finalAttrs.finalPackage; + }; + }; + + # If we were to fully emulate output selection here, we'd confuse the Nix CLIs, + # because they rely on `drvPath`. + dev = finalAttrs.finalPackage.out; + + libs = throw "`nix.dev.libs` is not meant to be used; use `nix.libs` instead."; + }; + meta = { + pkgConfigModules = [ + "nix-cmd" + "nix-expr" + "nix-expr-c" + "nix-fetchers" + "nix-flake" + "nix-main" + "nix-main-c" + "nix-store" + "nix-store-c" + "nix-util" + "nix-util-c" + ]; + }; + }); + devdoc = buildEnv { + name = "nix-${nix-cli.version}-devdoc"; + paths = [ + nix-internal-api-docs + nix-external-api-docs + ]; + }; + +in (buildEnv { name = "nix-${nix-cli.version}"; paths = [ - nix-util - nix-util-c - nix-util-test-support - nix-util-tests - - nix-store - nix-store-c - nix-store-test-support - nix-store-tests - - nix-fetchers - nix-fetchers-tests - - nix-expr - nix-expr-c - nix-expr-test-support - nix-expr-tests - - nix-flake - nix-flake-tests - - nix-main - nix-main-c - - nix-cmd + # unfortunately, `buildEnv` doesn't support multiple outputs nix-cli + # TODO: separate doc output attribute? nix-manual - nix-internal-api-docs - nix-external-api-docs - - ] ++ lib.optionals (stdenv.buildPlatform.canExecute stdenv.hostPlatform) [ - nix-perl-bindings ]; meta.mainProgram = "nix"; @@ -85,12 +121,25 @@ doInstallCheck = true; checkInputs = [ - # Actually run the unit tests too + # Make sure the unit tests have passed nix-util-tests.tests.run nix-store-tests.tests.run nix-expr-tests.tests.run + nix-fetchers-tests.tests.run nix-flake-tests.tests.run - ]; + + # dev bundle is ok + # (checkInputs must be empty paths??) + (runCommand "check-pkg-config" { checked = dev.tests.pkg-config; } "mkdir $out") + ] ++ + (if stdenv.buildPlatform.canExecute stdenv.hostPlatform + then [ + # TODO: add perl.tests + nix-perl-bindings + ] + else [ + nix-perl-bindings + ]); installCheckInputs = [ nix-functional-tests ]; @@ -128,5 +177,25 @@ nix-main-c ; }; + + tests = prevAttrs.passthru.tests or {} // { + # TODO: create a proper fixpoint and: + # pkg-config = + # testers.hasPkgConfigModules { + # package = finalPackage; + # }; + }; + + /** + A derivation referencing the `dev` outputs of the Nix libraries. + */ + inherit dev; + inherit devdoc; + outputs = [ "out" "dev" "devdoc" ]; + all = lib.attrValues (lib.genAttrs finalAttrs.passthru.outputs (outName: finalAttrs.finalPackage.${outName})); + }; + meta = prevAttrs.meta // { + description = "The Nix package manager"; + pkgConfigModules = dev.meta.pkgConfigModules; }; }) From f312a7cfffbe2959fd2698489284ff8081834a5c Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Tue, 12 Nov 2024 20:05:29 +0100 Subject: [PATCH 436/718] nix-everything: Make doc a separate package output --- packaging/everything.nix | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/packaging/everything.nix b/packaging/everything.nix index 458d26c30..b09b9d2a9 100644 --- a/packaging/everything.nix +++ b/packaging/everything.nix @@ -107,12 +107,8 @@ in (buildEnv { name = "nix-${nix-cli.version}"; paths = [ - # unfortunately, `buildEnv` doesn't support multiple outputs - nix-cli - - # TODO: separate doc output attribute? - nix-manual + nix-manual.man ]; meta.mainProgram = "nix"; @@ -191,7 +187,8 @@ in */ inherit dev; inherit devdoc; - outputs = [ "out" "dev" "devdoc" ]; + doc = nix-manual; + outputs = [ "out" "dev" "devdoc" "doc" ]; all = lib.attrValues (lib.genAttrs finalAttrs.passthru.outputs (outName: finalAttrs.finalPackage.${outName})); }; meta = prevAttrs.meta // { From 850ccb72cc3f44f0f23f2887988bc8dd3b32b745 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 12 Nov 2024 20:08:27 +0100 Subject: [PATCH 437/718] Don't build the API docs in the devshell The API docs build is extremely noisy (#11841) and probably not many people care about it anyway. Also, they get rebuild on *every* ninja invocation which is generally a waste of time. Of course, you can still build the docs via `nix build .#nix-{internal,external}-api-docs`, which is pretty fast. --- meson.options | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.options b/meson.options index b3b3b4043..329fe06bf 100644 --- a/meson.options +++ b/meson.options @@ -1,6 +1,6 @@ # vim: filetype=meson -option('doc-gen', type : 'boolean', value : true, +option('doc-gen', type : 'boolean', value : false, description : 'Generate documentation', ) From e6aae64318d437e77074114b6d7ffb6d838a4446 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 12 Nov 2024 20:42:53 +0100 Subject: [PATCH 438/718] Make the default stdenv phases do the right thing Fixes #11858. --- doc/manual/source/development/building.md | 24 +++++++-------- .../source/development/documentation.md | 4 +-- doc/manual/source/development/testing.md | 2 +- packaging/dev-shell.nix | 29 +++++++++++++++++++ 4 files changed, 44 insertions(+), 15 deletions(-) diff --git a/doc/manual/source/development/building.md b/doc/manual/source/development/building.md index dbf080296..409294682 100644 --- a/doc/manual/source/development/building.md +++ b/doc/manual/source/development/building.md @@ -35,20 +35,20 @@ To build Nix itself in this shell: ```console [nix-shell]$ mesonFlags+=" --prefix=$(pwd)/outputs/out" -[nix-shell]$ dontAddPrefix=1 mesonConfigurePhase -[nix-shell]$ ninjaBuildPhase +[nix-shell]$ dontAddPrefix=1 configurePhase +[nix-shell]$ buildPhase ``` To test it: ```console -[nix-shell]$ mesonCheckPhase +[nix-shell]$ checkPhase ``` To install it in `$(pwd)/outputs`: ```console -[nix-shell]$ ninjaInstallPhase +[nix-shell]$ installPhase [nix-shell]$ ./outputs/out/bin/nix --version nix (Nix) 2.12 ``` @@ -90,20 +90,20 @@ $ nix develop .#native-clangStdenvPackages To build Nix itself in this shell: ```console -[nix-shell]$ mesonConfigurePhase -[nix-shell]$ ninjaBuildPhase +[nix-shell]$ configurePhase +[nix-shell]$ buildPhase ``` To test it: ```console -[nix-shell]$ mesonCheckPhase +[nix-shell]$ checkPhase ``` To install it in `$(pwd)/outputs`: ```console -[nix-shell]$ ninjaInstallPhase +[nix-shell]$ installPhase [nix-shell]$ nix --version nix (Nix) 2.12 ``` @@ -167,7 +167,7 @@ It is useful to perform multiple cross and native builds on the same source tree for example to ensure that better support for one platform doesn't break the build for another. Meson thankfully makes this very easy by confining all build products to the build directory --- one simple shares the source directory between multiple build directories, each of which contains the build for Nix to a different platform. -Nixpkgs's `mesonConfigurePhase` always chooses `build` in the current directory as the name and location of the build. +Nixpkgs's `configurePhase` always chooses `build` in the current directory as the name and location of the build. This makes having multiple build directories slightly more inconvenient. The good news is that Meson/Ninja seem to cope well with relocating the build directory after it is created. @@ -176,13 +176,13 @@ Here's how to do that 1. Configure as usual ```bash - mesonConfigurePhase + configurePhase ``` 2. Rename the build directory ```bash - cd .. # since `mesonConfigurePhase` cd'd inside + cd .. # since `configurePhase` cd'd inside mv build build-linux # or whatever name we want cd build-linux ``` @@ -190,7 +190,7 @@ Here's how to do that 3. Build as usual ```bash - ninjaBuildPhase + buildPhase ``` > **N.B.** diff --git a/doc/manual/source/development/documentation.md b/doc/manual/source/development/documentation.md index d51373e7b..2e188f232 100644 --- a/doc/manual/source/development/documentation.md +++ b/doc/manual/source/development/documentation.md @@ -203,7 +203,7 @@ $ xdg-open ./result/share/doc/nix/internal-api/html/index.html or inside `nix-shell` or `nix develop`: ```console -$ mesonConfigurePhase +$ configurePhase $ ninja src/internal-api-docs/html $ xdg-open src/internal-api-docs/html/index.html ``` @@ -224,7 +224,7 @@ $ xdg-open ./result/share/doc/nix/external-api/html/index.html or inside `nix-shell` or `nix develop`: ``` -$ mesonConfigurePhase +$ configurePhase $ ninja src/external-api-docs/html $ xdg-open src/external-api-docs/html/index.html ``` diff --git a/doc/manual/source/development/testing.md b/doc/manual/source/development/testing.md index a9f7c939c..30aa7d0d5 100644 --- a/doc/manual/source/development/testing.md +++ b/doc/manual/source/development/testing.md @@ -137,7 +137,7 @@ Functional tests are run during `installCheck` in the `nix` package build, as we The whole test suite (functional and unit tests) can be run with: ```shell-session -$ mesonCheckPhase +$ checkPhase ``` ### Grouping tests diff --git a/packaging/dev-shell.nix b/packaging/dev-shell.nix index 8ac17f61a..30ac518d5 100644 --- a/packaging/dev-shell.nix +++ b/packaging/dev-shell.nix @@ -31,6 +31,35 @@ in { # Make bash completion work. XDG_DATA_DIRS+=:$out/share + + # Make the default phases do the right thing. + # FIXME: this wouldn't be needed if the ninja package set buildPhase() instead of $buildPhase. + # FIXME: mesonConfigurePhase shouldn't cd to the build directory. It would be better to pass '-C ' to ninja. + + cdToBuildDir() { + if [[ ! -e build.ninja ]]; then + cd build + fi + } + + configurePhase() { + mesonConfigurePhase + } + + buildPhase() { + cdToBuildDir + ninjaBuildPhase + } + + checkPhase() { + cdToBuildDir + mesonCheckPhase + } + + installPhase() { + cdToBuildDir + ninjaInstallPhase + } ''; # We use this shell with the local checkout, not unpackPhase. From 37f4c71d1cea16cbcfc0080a7b25d549f14e39e7 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 12 Nov 2024 21:10:01 +0100 Subject: [PATCH 439/718] Don't change nix::fs for now --- src/libutil/file-system.cc | 2 +- src/libutil/file-system.hh | 4 ++++ src/libutil/tarfile.cc | 4 +++- src/nix/eval.cc | 2 +- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/libutil/file-system.cc b/src/libutil/file-system.cc index 2802bbf98..92996ea47 100644 --- a/src/libutil/file-system.cc +++ b/src/libutil/file-system.cc @@ -29,7 +29,7 @@ namespace nix { -namespace fs = std::filesystem; +namespace fs { using namespace std::filesystem; } /** * Treat the string as possibly an absolute path, by inspecting the diff --git a/src/libutil/file-system.hh b/src/libutil/file-system.hh index da864d500..4c08cdf58 100644 --- a/src/libutil/file-system.hh +++ b/src/libutil/file-system.hh @@ -126,6 +126,8 @@ std::optional maybeLstat(const Path & path); */ bool pathExists(const Path & path); +namespace fs { + /** * ``` * symlink_exists(p) = std::filesystem::exists(std::filesystem::symlink_status(p)) @@ -139,6 +141,8 @@ inline bool symlink_exists(const std::filesystem::path & path) { return std::filesystem::exists(std::filesystem::symlink_status(path)); } +} // namespace fs + /** * A version of pathExists that returns false on a permission error. * Useful for inferring default paths across directories that might not diff --git a/src/libutil/tarfile.cc b/src/libutil/tarfile.cc index 397169757..e412930bb 100644 --- a/src/libutil/tarfile.cc +++ b/src/libutil/tarfile.cc @@ -8,7 +8,9 @@ namespace nix { -namespace fs = std::filesystem; +namespace fs { +using namespace std::filesystem; +} namespace { diff --git a/src/nix/eval.cc b/src/nix/eval.cc index a8c18fef6..7811b77ed 100644 --- a/src/nix/eval.cc +++ b/src/nix/eval.cc @@ -77,7 +77,7 @@ struct CmdEval : MixJSON, InstallableValueCommand, MixReadOnlyOption if (writeTo) { stopProgressBar(); - if (nix::symlink_exists(*writeTo)) + if (fs::symlink_exists(*writeTo)) throw Error("path '%s' already exists", writeTo->string()); std::function recurse; From 1301f8434d041be060fa5789effc0fac17a31879 Mon Sep 17 00:00:00 2001 From: Jack Wilsdon Date: Wed, 13 Nov 2024 00:49:46 +0000 Subject: [PATCH 440/718] Filter OSC 8 correctly This allows Nix to use lowdown 1.2.0 which outputs OSC-8 links. --- src/libutil-tests/terminal.cc | 5 +++++ src/libutil/terminal.cc | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/src/libutil-tests/terminal.cc b/src/libutil-tests/terminal.cc index cdeb9fd94..714d5a237 100644 --- a/src/libutil-tests/terminal.cc +++ b/src/libutil-tests/terminal.cc @@ -57,4 +57,9 @@ TEST(filterANSIEscapes, utf8) ASSERT_EQ(filterANSIEscapes("f𐍈𐍈bär", true, 4), "f𐍈𐍈b"); } +TEST(filterANSIEscapes, osc8) +{ + ASSERT_EQ(filterANSIEscapes("\e]8;;http://example.com\e\\This is a link\e]8;;\e\\"), "This is a link"); +} + } // namespace nix diff --git a/src/libutil/terminal.cc b/src/libutil/terminal.cc index 5d5ff7dcb..db7a6fcd1 100644 --- a/src/libutil/terminal.cc +++ b/src/libutil/terminal.cc @@ -45,6 +45,13 @@ std::string filterANSIEscapes(std::string_view s, bool filterAll, unsigned int w while (i != s.end() && *i >= 0x20 && *i <= 0x2f) e += *i++; // eat final byte if (i != s.end() && *i >= 0x40 && *i <= 0x7e) e += last = *i++; + } else if (i != s.end() && *i == ']') { + // OSC + e += *i++; + // eat ESC + while (i != s.end() && *i != '\e') e += *i++; + // eat backslash + if (i != s.end() && *i == '\\') e += last = *i++; } else { if (i != s.end() && *i >= 0x40 && *i <= 0x5f) e += *i++; } From f534a7a52440609c0d0b84b2f378753a5d85bd68 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 13 Nov 2024 16:25:31 +0100 Subject: [PATCH 441/718] Remove warning that interpretation of .drv has changed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This was first tagged as 2.15.0, 1½ years ago; plenty of time for everyone to catch up. By now, the warning is causing more confusion than that it is helpful, because passing a `.drv` or `drvPath` has legitimate use cases. --- src/libcmd/installable-derived-path.cc | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/libcmd/installable-derived-path.cc b/src/libcmd/installable-derived-path.cc index 4d1f83a1c..abacd7350 100644 --- a/src/libcmd/installable-derived-path.cc +++ b/src/libcmd/installable-derived-path.cc @@ -32,16 +32,6 @@ InstallableDerivedPath InstallableDerivedPath::parse( // store path. [&](const ExtendedOutputsSpec::Default &) -> DerivedPath { auto storePath = store->followLinksToStorePath(prefix); - // Remove this prior to stabilizing the new CLI. - if (storePath.isDerivation()) { - auto oldDerivedPath = DerivedPath::Built { - .drvPath = makeConstantStorePathRef(storePath), - .outputs = OutputsSpec::All { }, - }; - warn( - "The interpretation of store paths arguments ending in `.drv` recently changed. If this command is now failing try again with '%s'", - oldDerivedPath.to_string(*store)); - }; return DerivedPath::Opaque { .path = std::move(storePath), }; From b9f8c4af4057c2ed0ec5d1ff16ac49e0612ad57c Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman <145775305+xokdvium@users.noreply.github.com> Date: Thu, 14 Nov 2024 02:06:59 +0300 Subject: [PATCH 442/718] fix(libmain/common-args): do not exceed maximum allowed verbosity This patch gets rid of UB when verbosity exceeds the maximum logging value of `lvlVomit = 7` and reaches invalid values (e.g. 8). This is actually triggered in functional tests. There are too many occurrences to list, but here's one from the UBSAN log: ../src/libstore/gc.cc:610:5: runtime error: load of value 8, which is not a valid value for type 'Verbosity' --- src/libmain/common-args.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libmain/common-args.cc b/src/libmain/common-args.cc index 768b2177c..13d358623 100644 --- a/src/libmain/common-args.cc +++ b/src/libmain/common-args.cc @@ -17,7 +17,9 @@ MixCommonArgs::MixCommonArgs(const std::string & programName) .shortName = 'v', .description = "Increase the logging verbosity level.", .category = loggingCategory, - .handler = {[]() { verbosity = (Verbosity) (verbosity + 1); }}, + .handler = {[]() { + verbosity = (Verbosity) std::min>(verbosity + 1, lvlVomit); + }}, }); addFlag({ From e53e0a04f4be61ac085d87480fb89c96f7ae9261 Mon Sep 17 00:00:00 2001 From: dbdr Date: Thu, 14 Nov 2024 09:16:00 +0100 Subject: [PATCH 443/718] Fix typo in nix-collect-garbage.md --- doc/manual/source/command-ref/nix-collect-garbage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/manual/source/command-ref/nix-collect-garbage.md b/doc/manual/source/command-ref/nix-collect-garbage.md index 2136d28e9..bd05f2816 100644 --- a/doc/manual/source/command-ref/nix-collect-garbage.md +++ b/doc/manual/source/command-ref/nix-collect-garbage.md @@ -36,7 +36,7 @@ Instead, it looks in a few locations, and acts on all profiles it finds there: > > Not stable; subject to change > - > Do not rely on this functionality; it just exists for migration purposes and is may change in the future. + > Do not rely on this functionality; it just exists for migration purposes and may change in the future. > These deprecated paths remain a private implementation detail of Nix. `$NIX_STATE_DIR/profiles` and `$NIX_STATE_DIR/profiles/per-user`. From 33a0fa882f868102f3fca8f0d7547f3727be1244 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 14 Nov 2024 15:40:33 +0100 Subject: [PATCH 444/718] nix path-info: Don't write to std::cout directly This interferes with the progress bar, resulting in output like evaluating derivation 'git+file:///home/eelco/Dev/nix-master#packages.x86_64-linux.default'/nix/store/zz8v96j5md952x0mxfix12xqnvq5qv5x-nix-2.26.0pre20241114_a95f6ea.drv --- src/nix/path-info.cc | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/nix/path-info.cc b/src/nix/path-info.cc index e7cfb6e7a..8e3d0406d 100644 --- a/src/nix/path-info.cc +++ b/src/nix/path-info.cc @@ -139,12 +139,12 @@ struct CmdPathInfo : StorePathsCommand, MixJSON Category category() override { return catSecondary; } - void printSize(uint64_t value) + void printSize(std::ostream & str, uint64_t value) { if (humanReadable) - std::cout << fmt("\t%s", renderSize(value, true)); + str << fmt("\t%s", renderSize(value, true)); else - std::cout << fmt("\t%11d", value); + str << fmt("\t%11d", value); } void run(ref store, StorePaths && storePaths) override @@ -154,11 +154,11 @@ struct CmdPathInfo : StorePathsCommand, MixJSON pathLen = std::max(pathLen, store->printStorePath(storePath).size()); if (json) { - std::cout << pathInfoToJSON( + logger->cout(pathInfoToJSON( *store, // FIXME: preserve order? StorePathSet(storePaths.begin(), storePaths.end()), - showClosureSize).dump(); + showClosureSize).dump()); } else { @@ -167,30 +167,32 @@ struct CmdPathInfo : StorePathsCommand, MixJSON auto info = store->queryPathInfo(storePath); auto storePathS = store->printStorePath(info->path); - std::cout << storePathS; + std::ostringstream str; + + str << storePathS; if (showSize || showClosureSize || showSigs) - std::cout << std::string(std::max(0, (int) pathLen - (int) storePathS.size()), ' '); + str << std::string(std::max(0, (int) pathLen - (int) storePathS.size()), ' '); if (showSize) - printSize(info->narSize); + printSize(str, info->narSize); if (showClosureSize) { StorePathSet closure; store->computeFSClosure(storePath, closure, false, false); - printSize(getStoreObjectsTotalSize(*store, closure)); + printSize(str, getStoreObjectsTotalSize(*store, closure)); } if (showSigs) { - std::cout << '\t'; + str << '\t'; Strings ss; if (info->ultimate) ss.push_back("ultimate"); if (info->ca) ss.push_back("ca:" + renderContentAddress(*info->ca)); for (auto & sig : info->sigs) ss.push_back(sig); - std::cout << concatStringsSep(" ", ss); + str << concatStringsSep(" ", ss); } - std::cout << std::endl; + logger->cout(str.str()); } } From 3e4a83f53b343a7fe2ba4faaf4e3932c99ee438b Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 14 Nov 2024 16:12:14 +0100 Subject: [PATCH 445/718] Use range-based for --- src/libexpr/eval.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 6e82af1d8..0283a14d6 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -1475,10 +1475,10 @@ void EvalState::callFunction(Value & fun, std::span args, Value & vRes, auto makeAppChain = [&]() { vRes = vCur; - for (size_t i = 0; i < args.size(); ++i) { + for (auto arg : args) { auto fun2 = allocValue(); *fun2 = vRes; - vRes.mkPrimOpApp(fun2, args[i]); + vRes.mkPrimOpApp(fun2, arg); } }; From 2f3764acbb96ab687e612fdd81bdf58ac5f0e605 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Fri, 15 Nov 2024 11:35:27 +0100 Subject: [PATCH 446/718] .github/ci: Add nix-docker test We still have room to spare in vm_tests, as it's quicker than `nix flake check` --- .github/workflows/ci.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 27f60574e..a3b7b06d4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -194,7 +194,13 @@ jobs: - uses: actions/checkout@v4 - uses: DeterminateSystems/nix-installer-action@main - uses: DeterminateSystems/magic-nix-cache-action@main - - run: nix build -L .#hydraJobs.tests.githubFlakes .#hydraJobs.tests.tarballFlakes .#hydraJobs.tests.functional_user + - run: | + nix build -L \ + .#hydraJobs.tests.functional_user \ + .#hydraJobs.tests.githubFlakes \ + .#hydraJobs.tests.nix-docker \ + .#hydraJobs.tests.tarballFlakes \ + ; flake_regressions: needs: vm_tests From c9433c0d1834362305c4f5ca2802fca97d999044 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Fri, 15 Nov 2024 11:37:17 +0100 Subject: [PATCH 447/718] .github/ci: Push docker only when test succeeds --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a3b7b06d4..cb97fd211 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -128,7 +128,7 @@ jobs: - run: exec bash -c "nix-channel --update && nix-env -iA nixpkgs.hello && hello" docker_push_image: - needs: [check_secrets, tests] + needs: [check_secrets, tests, vm_tests] permissions: contents: read packages: write From 3f6855c31b8d35b39148a86c2c28c7e2f367b739 Mon Sep 17 00:00:00 2001 From: myclevorname <140354451+myclevorname@users.noreply.github.com> Date: Sun, 17 Nov 2024 14:12:27 -0500 Subject: [PATCH 448/718] doc/nix fmt: Mention nixfmt-rfc-style instead of nixfmt(-classic) --- src/nix/fmt.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nix/fmt.md b/src/nix/fmt.md index a2afde61c..b4693eb65 100644 --- a/src/nix/fmt.md +++ b/src/nix/fmt.md @@ -22,13 +22,13 @@ With [nixpkgs-fmt](https://github.com/nix-community/nixpkgs-fmt): } ``` -With [nixfmt](https://github.com/serokell/nixfmt): +With [nixfmt](https://github.com/NixOS/nixfmt): ```nix # flake.nix { outputs = { nixpkgs, self }: { - formatter.x86_64-linux = nixpkgs.legacyPackages.x86_64-linux.nixfmt; + formatter.x86_64-linux = nixpkgs.legacyPackages.x86_64-linux.nixfmt-rfc-style; }; } ``` From d65fac0fc461e5b62373b86401b845df6c698177 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 18 Nov 2024 15:08:32 +0100 Subject: [PATCH 449/718] Add --print-errorlogs to mesonCheckFlags This prints the error logs in the tests, including when they're run with `checkPhase` in the dev shell. --- packaging/dependencies.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packaging/dependencies.nix b/packaging/dependencies.nix index 13766f2c0..a8005ce16 100644 --- a/packaging/dependencies.nix +++ b/packaging/dependencies.nix @@ -70,6 +70,9 @@ let pkgs.buildPackages.meson pkgs.buildPackages.ninja ] ++ prevAttrs.nativeBuildInputs or []; + mesonCheckFlags = prevAttrs.mesonCheckFlags or [] ++ [ + "--print-errorlogs" + ]; }; mesonBuildLayer = finalAttrs: prevAttrs: From 428af8c66f0918f5852080b06268498e5021bfe8 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 18 Nov 2024 16:28:12 +0100 Subject: [PATCH 450/718] tests/functional/flakes/develop.sh: Don't hang The bash shell started by `nix develop` waited forever for stdin input. Fixes #11827. --- tests/functional/flakes/develop.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/functional/flakes/develop.sh b/tests/functional/flakes/develop.sh index b3e438e99..c222f0fbb 100755 --- a/tests/functional/flakes/develop.sh +++ b/tests/functional/flakes/develop.sh @@ -122,7 +122,7 @@ expectStderr 1 nix develop --unset-env-var FOO --set-env-var FOO 'BAR' --no-writ grepQuiet "error: Cannot set environment variable 'FOO' that is unset with '--unset-env-var'" # Check that multiple `--ignore-env`'s are okay. -expectStderr 0 nix develop --ignore-env --set-env-var FOO 'BAR' --ignore-env .#hello +expectStderr 0 nix develop --ignore-env --set-env-var FOO 'BAR' --ignore-env .#hello < /dev/null # Determine the bashInteractive executable. nix build --no-write-lock-file './nixpkgs#bashInteractive' --out-link ./bash-interactive From c4b95dbdd1fb45bbc7ad1fc921ebdf81789e22b3 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 18 Nov 2024 16:45:18 +0100 Subject: [PATCH 451/718] Fix issue 11892 It seems that I copied the expression for baseDir thoughtlessly and did not come back to it. - `baseDir` was only used in the `fromArgs` branch. - `fromArgs` is true when `packages` is true. --- src/nix-build/nix-build.cc | 10 ++++++---- tests/functional/nix-shell.sh | 29 +++++++++++++++++++++++++++++ tests/functional/shell.nix | 6 +++++- 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc index c394836da..de01e1afc 100644 --- a/src/nix-build/nix-build.cc +++ b/src/nix-build/nix-build.cc @@ -340,13 +340,15 @@ static void main_nix_build(int argc, char * * argv) exprs = {state->parseStdin()}; else for (auto i : remainingArgs) { - auto baseDir = inShebang && !packages ? absPath(dirOf(script)) : i; - - if (fromArgs) + if (fromArgs) { + auto shebangBaseDir = absPath(dirOf(script)); exprs.push_back(state->parseExprFromString( std::move(i), - (inShebang && compatibilitySettings.nixShellShebangArgumentsRelativeToScript) ? lookupFileArg(*state, baseDir) : state->rootPath(".") + (inShebang && compatibilitySettings.nixShellShebangArgumentsRelativeToScript) + ? lookupFileArg(*state, shebangBaseDir) + : state->rootPath(".") )); + } else { auto absolute = i; try { diff --git a/tests/functional/nix-shell.sh b/tests/functional/nix-shell.sh index 2b78216f4..b054b7f75 100755 --- a/tests/functional/nix-shell.sh +++ b/tests/functional/nix-shell.sh @@ -167,6 +167,35 @@ EOF chmod a+x $TEST_ROOT/marco/polo/default.nix (cd $TEST_ROOT/marco && ./polo/default.nix | grepQuiet "Polo") +# https://github.com/NixOS/nix/issues/11892 +mkdir $TEST_ROOT/issue-11892 +cat >$TEST_ROOT/issue-11892/shebangscript <$TEST_ROOT/issue-11892/my_package.nix < \$out/bin/my_package + cat \$out/bin/my_package + chmod a+x \$out/bin/my_package + ''; +} +EOF +chmod a+x $TEST_ROOT/issue-11892/shebangscript +$TEST_ROOT/issue-11892/shebangscript \ + | tee /dev/stderr \ + | grepQuiet "ok baz11892" + ##################### # Flake equivalents # diff --git a/tests/functional/shell.nix b/tests/functional/shell.nix index 9cae14b78..4b1a0623a 100644 --- a/tests/functional/shell.nix +++ b/tests/functional/shell.nix @@ -37,7 +37,7 @@ let pkgs = rec { mkdir -p $out ln -s ${setupSh} $out/setup ''; - }; + } // { inherit mkDerivation; }; shellDrv = mkDerivation { name = "shellDrv"; @@ -94,5 +94,9 @@ let pkgs = rec { chmod a+rx $out/bin/ruby ''; + inherit (cfg) shell; + + callPackage = f: args: f (pkgs // args); + inherit pkgs; }; in pkgs From e224a35a77b588aed2bc29bf36cc4274098e7a5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Tue, 19 Nov 2024 11:25:26 +0100 Subject: [PATCH 452/718] docs/flake: document how to build a pull request It's not so common knowledge that forges also expose pull requests as git refs. But it's actually a cool way of quickly testing someones contribution, so I found it worth specifically mentioning it. --- src/nix/flake.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/nix/flake.md b/src/nix/flake.md index 2b999431c..8f0f9936c 100644 --- a/src/nix/flake.md +++ b/src/nix/flake.md @@ -84,6 +84,8 @@ Here are some examples of flake references in their URL-like representation: repository on GitHub. * `github:NixOS/nixpkgs/nixos-20.09`: The `nixos-20.09` branch of the `nixpkgs` repository. +* `github:NixOS/nixpkgs/pull/357207/head`: The `357207` pull request + of the nixpkgs repository. * `github:NixOS/nixpkgs/a3a3dda3bacf61e8a39258a0ed9c924eeca8e293`: A specific revision of the `nixpkgs` repository. * `github:edolstra/nix-warez?dir=blender`: A flake in a subdirectory From dd4838974eb8afbde4cf3dc60ffd327084affb06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Tue, 19 Nov 2024 13:24:11 +0100 Subject: [PATCH 453/718] document shallow clone options in git fetchers --- src/nix/flake.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/nix/flake.md b/src/nix/flake.md index 8f0f9936c..5412afcdd 100644 --- a/src/nix/flake.md +++ b/src/nix/flake.md @@ -245,6 +245,9 @@ Currently the `type` attribute can be one of the following: * `./sub/dir` (when used on the command line and `dir/flake.nix` is in a git repository) * `git+https://example.org/my/repo` * `git+https://example.org/my/repo?dir=flake1` + * `git+https://example.org/my/repo?shallow=1` A shallow clone of the repository. + For large repositories, the shallow clone option can significantly speed up fresh clones compared + to non-shallow clones, while still providing faster updates than other fetch methods such as `tarball:` or `github:`. * `git+ssh://git@github.com/NixOS/nix?ref=v1.2.3` * `git://github.com/edolstra/dwarffs?ref=unstable&rev=e486d8d40e626a20e06d792db8cc5ac5aba9a5b4` * `git+file:///home/my-user/some-repo/some-repo` From 850281908cd65b7ccfdfe17b1e4a43f8ec59ef9a Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 19 Nov 2024 16:50:13 +0100 Subject: [PATCH 454/718] Clean up flakeref parsing This factors out some commonality in calling fromURL() and handling the "dir" parameter into a fromParsedURL() helper function. --- src/libflake/flake/flakeref.cc | 43 ++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/src/libflake/flake/flakeref.cc b/src/libflake/flake/flakeref.cc index 01fe747f9..ed47ad737 100644 --- a/src/libflake/flake/flakeref.cc +++ b/src/libflake/flake/flakeref.cc @@ -67,6 +67,20 @@ std::optional maybeParseFlakeRef( } } +static std::pair fromParsedURL( + const fetchers::Settings & fetchSettings, + ParsedURL && parsedURL, + bool isFlake) +{ + auto dir = getOr(parsedURL.query, "dir", ""); + parsedURL.query.erase("dir"); + + std::string fragment; + std::swap(fragment, parsedURL.fragment); + + return std::make_pair(FlakeRef(fetchers::Input::fromURL(fetchSettings, parsedURL, isFlake), dir), fragment); +} + std::pair parsePathFlakeRefWithFragment( const fetchers::Settings & fetchSettings, const std::string & url, @@ -89,7 +103,7 @@ std::pair parsePathFlakeRefWithFragment( fragment = percentDecode(url.substr(fragmentStart+1)); } if (pathEnd != std::string::npos && fragmentStart != std::string::npos && url[pathEnd] == '?') { - query = decodeQuery(url.substr(pathEnd+1, fragmentStart-pathEnd-1)); + query = decodeQuery(url.substr(pathEnd + 1, fragmentStart - pathEnd - 1)); } if (baseDir) { @@ -153,6 +167,7 @@ std::pair parsePathFlakeRefWithFragment( .authority = "", .path = flakeRoot, .query = query, + .fragment = fragment, }; if (subdir != "") { @@ -164,9 +179,7 @@ std::pair parsePathFlakeRefWithFragment( if (pathExists(flakeRoot + "/.git/shallow")) parsedURL.query.insert_or_assign("shallow", "1"); - return std::make_pair( - FlakeRef(fetchers::Input::fromURL(fetchSettings, parsedURL), getOr(parsedURL.query, "dir", "")), - fragment); + return fromParsedURL(fetchSettings, std::move(parsedURL), isFlake); } subdir = std::string(baseNameOf(flakeRoot)) + (subdir.empty() ? "" : "/" + subdir); @@ -185,11 +198,12 @@ std::pair parsePathFlakeRefWithFragment( attrs.insert_or_assign("path", path); return std::make_pair(FlakeRef(fetchers::Input::fromAttrs(fetchSettings, std::move(attrs)), ""), fragment); -}; +} - -/* Check if 'url' is a flake ID. This is an abbreviated syntax for - 'flake:?ref=&rev='. */ +/** + * Check if `url` is a flake ID. This is an abbreviated syntax for + * `flake:?ref=&rev=`. + */ static std::optional> parseFlakeIdRef( const fetchers::Settings & fetchSettings, const std::string & url, @@ -227,22 +241,11 @@ std::optional> parseURLFlakeRef( bool isFlake ) { - ParsedURL parsedURL; try { - parsedURL = parseURL(url); + return fromParsedURL(fetchSettings, parseURL(url), isFlake); } catch (BadURL &) { return std::nullopt; } - - std::string fragment; - std::swap(fragment, parsedURL.fragment); - - auto input = fetchers::Input::fromURL(fetchSettings, parsedURL, isFlake); - input.parent = baseDir; - - return std::make_pair( - FlakeRef(std::move(input), getOr(parsedURL.query, "dir", "")), - fragment); } std::pair parseFlakeRefWithFragment( From 868b4d37ea8e59d76afbaef4c82315e23b5fa8f4 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 19 Nov 2024 16:59:38 +0100 Subject: [PATCH 455/718] nix flake init: Operate on a SourcePath Cherry-picked from lazy-trees. --- src/nix/flake.cc | 45 ++++++++++++++++++++------------------------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 3a54763a1..ce2faacb0 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -891,37 +891,32 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand auto cursor = installable.getCursor(*evalState); - auto templateDirAttr = cursor->getAttr("path"); - auto templateDir = templateDirAttr->getString(); - - if (!store->isInStore(templateDir)) - evalState->error( - "'%s' was not found in the Nix store\n" - "If you've set '%s' to a string, try using a path instead.", - templateDir, templateDirAttr->getAttrPathStr()).debugThrow(); + auto templateDirAttr = cursor->getAttr("path")->forceValue(); + NixStringContext context; + auto templateDir = evalState->coerceToPath(noPos, templateDirAttr, context, ""); std::vector changedFiles; std::vector conflictedFiles; - std::function copyDir; - copyDir = [&](const fs::path & from, const fs::path & to) + std::function copyDir; + copyDir = [&](const SourcePath & from, const fs::path & to) { fs::create_directories(to); - for (auto & entry : fs::directory_iterator{from}) { + for (auto & [name, entry] : from.readDirectory()) { checkInterrupt(); - auto from2 = entry.path(); - auto to2 = to / entry.path().filename(); - auto st = entry.symlink_status(); + auto from2 = from / name; + auto to2 = to / name; + auto st = from2.lstat(); auto to_st = fs::symlink_status(to2); - if (fs::is_directory(st)) + if (st.type == SourceAccessor::tDirectory) copyDir(from2, to2); - else if (fs::is_regular_file(st)) { - auto contents = readFile(from2.string()); + else if (st.type == SourceAccessor::tRegular) { + auto contents = from2.readFile(); if (fs::exists(to_st)) { auto contents2 = readFile(to2.string()); if (contents != contents2) { - printError("refusing to overwrite existing file '%s'\n please merge it manually with '%s'", to2.string(), from2.string()); + printError("refusing to overwrite existing file '%s'\n please merge it manually with '%s'", to2.string(), from2); conflictedFiles.push_back(to2); } else { notice("skipping identical file: %s", from2); @@ -930,18 +925,18 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand } else writeFile(to2, contents); } - else if (fs::is_symlink(st)) { - auto target = fs::read_symlink(from2); + else if (st.type == SourceAccessor::tSymlink) { + auto target = from2.readLink(); if (fs::exists(to_st)) { if (fs::read_symlink(to2) != target) { - printError("refusing to overwrite existing file '%s'\n please merge it manually with '%s'", to2.string(), from2.string()); + printError("refusing to overwrite existing file '%s'\n please merge it manually with '%s'", to2.string(), from2); conflictedFiles.push_back(to2); } else { notice("skipping identical file: %s", from2); } continue; } else - fs::create_symlink(target, to2); + fs::create_symlink(target, to2); } else throw Error("file '%s' has unsupported type", from2); @@ -957,14 +952,14 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand for (auto & s : changedFiles) args.emplace_back(s.string()); runProgram("git", true, args); } - auto welcomeText = cursor->maybeGetAttr("welcomeText"); - if (welcomeText) { + + if (auto welcomeText = cursor->maybeGetAttr("welcomeText")) { notice("\n"); notice(renderMarkdownToTerminal(welcomeText->getString())); } if (!conflictedFiles.empty()) - throw Error("Encountered %d conflicts - see above", conflictedFiles.size()); + throw Error("encountered %d conflicts - see above", conflictedFiles.size()); } }; From f1b4f14055077e660b7aa5b4859ce6965b62b886 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 19 Nov 2024 17:30:38 +0100 Subject: [PATCH 456/718] Trivial changes from lazy-trees --- src/libexpr/primops.cc | 7 ++++--- src/libfetchers/fetch-to-store.cc | 2 ++ src/libfetchers/meson.build | 6 +++--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index aea623435..42136b467 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -1603,7 +1603,8 @@ static RegisterPrimOp primop_placeholder({ *************************************************************/ -/* Convert the argument to a path. !!! obsolete? */ +/* Convert the argument to a path and then to a string (confusing, + eh?). !!! obsolete? */ static void prim_toPath(EvalState & state, const PosIdx pos, Value * * args, Value & v) { NixStringContext context; @@ -2614,13 +2615,13 @@ static void prim_path(EvalState & state, const PosIdx pos, Value * * args, Value expectedHash = newHashAllowEmpty(state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the `sha256` attribute passed to builtins.path"), HashAlgorithm::SHA256); else state.error( - "unsupported argument '%1%' to 'addPath'", + "unsupported argument '%1%' to 'builtins.path'", state.symbols[attr.name] ).atPos(attr.pos).debugThrow(); } if (!path) state.error( - "missing required 'path' attribute in the first argument to builtins.path" + "missing required 'path' attribute in the first argument to 'builtins.path'" ).atPos(pos).debugThrow(); if (name.empty()) name = path->baseName(); diff --git a/src/libfetchers/fetch-to-store.cc b/src/libfetchers/fetch-to-store.cc index 65aa72a6c..fe347a59d 100644 --- a/src/libfetchers/fetch-to-store.cc +++ b/src/libfetchers/fetch-to-store.cc @@ -44,6 +44,8 @@ StorePath fetchToStore( : store.addToStore( name, path, method, HashAlgorithm::SHA256, {}, filter2, repair); + debug(mode == FetchMode::DryRun ? "hashed '%s'" : "copied '%s' to '%s'", path, store.printStorePath(storePath)); + if (cacheKey && mode == FetchMode::Copy) fetchers::getCache()->upsert(*cacheKey, store, {}, storePath); diff --git a/src/libfetchers/meson.build b/src/libfetchers/meson.build index d4f202796..ff638578d 100644 --- a/src/libfetchers/meson.build +++ b/src/libfetchers/meson.build @@ -52,15 +52,15 @@ sources = files( 'fetch-to-store.cc', 'fetchers.cc', 'filtering-source-accessor.cc', - 'git.cc', 'git-utils.cc', + 'git.cc', 'github.cc', 'indirect.cc', 'mercurial.cc', 'mounted-source-accessor.cc', 'path.cc', - 'store-path-accessor.cc', 'registry.cc', + 'store-path-accessor.cc', 'tarball.cc', ) @@ -71,10 +71,10 @@ headers = files( 'cache.hh', 'fetch-settings.hh', 'fetch-to-store.hh', + 'fetchers.hh', 'filtering-source-accessor.hh', 'git-utils.hh', 'mounted-source-accessor.hh', - 'fetchers.hh', 'registry.hh', 'store-path-accessor.hh', 'tarball.hh', From a58e38dab7f6a9b9d217f6163fe8b565f19a6405 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Tue, 19 Nov 2024 17:30:58 +0100 Subject: [PATCH 457/718] Make EvalState::getBuiltin safe for missing attr --- src/libexpr/eval.cc | 6 +++++- src/libexpr/eval.hh | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 0283a14d6..dd14f485e 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -525,7 +525,11 @@ Value * EvalState::addPrimOp(PrimOp && primOp) Value & EvalState::getBuiltin(const std::string & name) { - return *baseEnv.values[0]->attrs()->find(symbols.create(name))->value; + auto it = baseEnv.values[0]->attrs()->get(symbols.create(name)); + if (it) + return *it->value; + else + throw EvalError("builtin '%1%' not found", name); } diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 742f1cafe..01c725930 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -623,6 +623,11 @@ private: public: + /** + * Retrieve a specific builtin, equivalent to evaluating `builtins.${name}`. + * @param name The attribute name of the builtin to retrieve. + * @throws EvalError if the builtin does not exist. + */ Value & getBuiltin(const std::string & name); struct Doc From af07f33d37410de8c97bb64f2d77214c1f4640b4 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 19 Nov 2024 18:03:31 +0100 Subject: [PATCH 458/718] resolveLookupPathPath(): Return a SourcePath instead of a string Cherry-picked from lazy-trees. --- src/libcmd/common-eval-args.cc | 6 +++--- src/libexpr/eval-settings.hh | 8 +++----- src/libexpr/eval.cc | 23 +++++++++++------------ src/libexpr/eval.hh | 6 +++--- tests/functional/restricted.sh | 2 +- 5 files changed, 21 insertions(+), 24 deletions(-) diff --git a/src/libcmd/common-eval-args.cc b/src/libcmd/common-eval-args.cc index ccbf957d9..de967e3fe 100644 --- a/src/libcmd/common-eval-args.cc +++ b/src/libcmd/common-eval-args.cc @@ -29,13 +29,13 @@ EvalSettings evalSettings { { { "flake", - [](ref store, std::string_view rest) { + [](EvalState & state, std::string_view rest) { experimentalFeatureSettings.require(Xp::Flakes); // FIXME `parseFlakeRef` should take a `std::string_view`. auto flakeRef = parseFlakeRef(fetchSettings, std::string { rest }, {}, true, false); debug("fetching flake search path element '%s''", rest); - auto storePath = flakeRef.resolve(store).fetchTree(store).first; - return store->toRealPath(storePath); + auto storePath = flakeRef.resolve(state.store).fetchTree(state.store).first; + return state.rootPath(state.store->toRealPath(storePath)); }, }, }, diff --git a/src/libexpr/eval-settings.hh b/src/libexpr/eval-settings.hh index 115e3ee50..a8fcce539 100644 --- a/src/libexpr/eval-settings.hh +++ b/src/libexpr/eval-settings.hh @@ -3,10 +3,11 @@ #include "config.hh" #include "ref.hh" +#include "source-path.hh" namespace nix { -class Store; +class EvalState; struct EvalSettings : Config { @@ -18,11 +19,8 @@ struct EvalSettings : Config * * The return value is (a) whether the entry was valid, and, if so, * what does it map to. - * - * @todo Return (`std::optional` of) `SourceAccssor` or something - * more structured instead of mere `std::string`? */ - using LookupPathHook = std::optional(ref store, std::string_view); + using LookupPathHook = std::optional(EvalState & state, std::string_view); /** * Map from "scheme" to a `LookupPathHook`. diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 0283a14d6..83a1cf4e9 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -3025,8 +3025,8 @@ SourcePath EvalState::findFile(const LookupPath & lookupPath, const std::string_ if (!rOpt) continue; auto r = *rOpt; - Path res = suffix == "" ? r : concatStrings(r, "/", suffix); - if (pathExists(res)) return rootPath(CanonPath(canonPath(res))); + auto res = (r / CanonPath(suffix)).resolveSymlinks(); + if (res.pathExists()) return res; } if (hasPrefix(path, "nix/")) @@ -3041,13 +3041,13 @@ SourcePath EvalState::findFile(const LookupPath & lookupPath, const std::string_ } -std::optional EvalState::resolveLookupPathPath(const LookupPath::Path & value0, bool initAccessControl) +std::optional EvalState::resolveLookupPathPath(const LookupPath::Path & value0, bool initAccessControl) { auto & value = value0.s; auto i = lookupPathResolved.find(value); if (i != lookupPathResolved.end()) return i->second; - auto finish = [&](std::string res) { + auto finish = [&](SourcePath res) { debug("resolved search path element '%s' to '%s'", value, res); lookupPathResolved.emplace(value, res); return res; @@ -3060,7 +3060,7 @@ std::optional EvalState::resolveLookupPathPath(const LookupPath::Pa fetchSettings, EvalSettings::resolvePseudoUrl(value)); auto storePath = fetchToStore(*store, SourcePath(accessor), FetchMode::Copy); - return finish(store->toRealPath(storePath)); + return finish(rootPath(store->toRealPath(storePath))); } catch (Error & e) { logWarning({ .msg = HintFmt("Nix search path entry '%1%' cannot be downloaded, ignoring", value) @@ -3072,29 +3072,29 @@ std::optional EvalState::resolveLookupPathPath(const LookupPath::Pa auto scheme = value.substr(0, colPos); auto rest = value.substr(colPos + 1); if (auto * hook = get(settings.lookupPathHooks, scheme)) { - auto res = (*hook)(store, rest); + auto res = (*hook)(*this, rest); if (res) return finish(std::move(*res)); } } { - auto path = absPath(value); + auto path = rootPath(value); /* Allow access to paths in the search path. */ if (initAccessControl) { - allowPath(path); - if (store->isInStore(path)) { + allowPath(path.path.abs()); + if (store->isInStore(path.path.abs())) { try { StorePathSet closure; - store->computeFSClosure(store->toStorePath(path).first, closure); + store->computeFSClosure(store->toStorePath(path.path.abs()).first, closure); for (auto & p : closure) allowPath(p); } catch (InvalidPath &) { } } } - if (pathExists(path)) + if (path.pathExists()) return finish(std::move(path)); else { logWarning({ @@ -3105,7 +3105,6 @@ std::optional EvalState::resolveLookupPathPath(const LookupPath::Pa debug("failed to resolve search path element '%s'", value); return std::nullopt; - } diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 742f1cafe..6c0bae451 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -347,7 +347,7 @@ private: LookupPath lookupPath; - std::map> lookupPathResolved; + std::map> lookupPathResolved; /** * Cache used by prim_match(). @@ -452,9 +452,9 @@ public: * * If the specified search path element is a URI, download it. * - * If it is not found, return `std::nullopt` + * If it is not found, return `std::nullopt`. */ - std::optional resolveLookupPathPath( + std::optional resolveLookupPathPath( const LookupPath::Path & elem, bool initAccessControl = false); diff --git a/tests/functional/restricted.sh b/tests/functional/restricted.sh index 00ee4ddc8..a92a9b8a3 100755 --- a/tests/functional/restricted.sh +++ b/tests/functional/restricted.sh @@ -23,7 +23,7 @@ nix-instantiate --restrict-eval ./simple.nix -I src1=./simple.nix -I src2=./conf (! nix-instantiate --restrict-eval --eval -E 'builtins.readFile ./simple.nix') nix-instantiate --restrict-eval --eval -E 'builtins.readFile ./simple.nix' -I src=../.. -expectStderr 1 nix-instantiate --restrict-eval --eval -E 'let __nixPath = [ { prefix = "foo"; path = ./.; } ]; in builtins.readFile ' | grepQuiet "forbidden in restricted mode" +expectStderr 1 nix-instantiate --restrict-eval --eval -E 'let __nixPath = [ { prefix = "foo"; path = ./.; } ]; in builtins.readFile ' | grepQuiet "was not found in the Nix search path" nix-instantiate --restrict-eval --eval -E 'let __nixPath = [ { prefix = "foo"; path = ./.; } ]; in builtins.readFile ' -I src=. p=$(nix eval --raw --expr "builtins.fetchurl file://${_NIX_TEST_SOURCE_DIR}/restricted.sh" --impure --restrict-eval --allowed-uris "file://${_NIX_TEST_SOURCE_DIR}") From 8a36d2d8a77dc3f3214ac6f7fd67cbe15ec6c706 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Tue, 19 Nov 2024 18:23:05 +0100 Subject: [PATCH 459/718] Add EvalState::getBuiltins --- src/libexpr-test-support/tests/libexpr.hh | 6 ++++++ src/libexpr-tests/eval.cc | 25 ++++++++++++++++++++++- src/libexpr/eval.cc | 8 +++++++- src/libexpr/eval.hh | 6 ++++++ 4 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/libexpr-test-support/tests/libexpr.hh b/src/libexpr-test-support/tests/libexpr.hh index 045607e87..095ea1d0e 100644 --- a/src/libexpr-test-support/tests/libexpr.hh +++ b/src/libexpr-test-support/tests/libexpr.hh @@ -40,6 +40,12 @@ namespace nix { return v; } + Value * maybeThunk(std::string input, bool forceValue = true) { + Expr * e = state.parseExprFromString(input, state.rootPath(CanonPath::root)); + assert(e); + return e->maybeThunk(state, state.baseEnv); + } + Symbol createSymbol(const char * value) { return state.symbols.create(value); } diff --git a/src/libexpr-tests/eval.cc b/src/libexpr-tests/eval.cc index 93d3f658f..61f6be0db 100644 --- a/src/libexpr-tests/eval.cc +++ b/src/libexpr-tests/eval.cc @@ -138,4 +138,27 @@ TEST(nix_isAllowedURI, non_scheme_colon) { ASSERT_FALSE(isAllowedURI("https://foo/bar:baz", allowed)); } -} // namespace nix \ No newline at end of file +class EvalStateTest : public LibExprTest {}; + +TEST_F(EvalStateTest, getBuiltins_ok) { + auto evaled = maybeThunk("builtins"); + auto & builtins = state.getBuiltins(); + ASSERT_TRUE(builtins.type() == nAttrs); + ASSERT_EQ(evaled, &builtins); +} + +TEST_F(EvalStateTest, getBuiltin_ok) { + auto & builtin = state.getBuiltin("toString"); + ASSERT_TRUE(builtin.type() == nFunction); + // FIXME + // auto evaled = maybeThunk("builtins.toString"); + // ASSERT_EQ(evaled, &builtin); + auto & builtin2 = state.getBuiltin("true"); + ASSERT_EQ(state.forceBool(builtin2, noPos, "in unit test"), true); +} + +TEST_F(EvalStateTest, getBuiltin_fail) { + ASSERT_THROW(state.getBuiltin("nonexistent"), EvalError); +} + +} // namespace nix diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index dd14f485e..b1b7a0fe6 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -523,13 +523,19 @@ Value * EvalState::addPrimOp(PrimOp && primOp) } +Value & EvalState::getBuiltins() +{ + return *baseEnv.values[0]; +} + + Value & EvalState::getBuiltin(const std::string & name) { auto it = baseEnv.values[0]->attrs()->get(symbols.create(name)); if (it) return *it->value; else - throw EvalError("builtin '%1%' not found", name); + error("builtin '%1%' not found", name).debugThrow(); } diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 01c725930..a14e88f0e 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -630,6 +630,12 @@ public: */ Value & getBuiltin(const std::string & name); + /** + * Retrieve the `builtins` attrset, equivalent to evaluating the reference `builtins`. + * Always returns an attribute set value. + */ + Value & getBuiltins(); + struct Doc { Pos pos; From 5c258d7e255946c5d78ca8116966160e07455347 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Tue, 19 Nov 2024 18:32:09 +0100 Subject: [PATCH 460/718] refactor: Use EvalState::getBuiltins() --- src/libexpr/eval.cc | 6 +++--- src/libexpr/primops.cc | 2 +- src/nix/main.cc | 3 ++- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index b1b7a0fe6..63c2e8a71 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -448,7 +448,7 @@ void EvalState::addConstant(const std::string & name, Value * v, Constant info) /* Install value the base environment. */ staticBaseEnv->vars.emplace_back(symbols.create(name), baseEnvDispl); baseEnv.values[baseEnvDispl++] = v; - baseEnv.values[0]->payload.attrs->push_back(Attr(symbols.create(name2), v)); + getBuiltins().payload.attrs->push_back(Attr(symbols.create(name2), v)); } } @@ -516,7 +516,7 @@ Value * EvalState::addPrimOp(PrimOp && primOp) else { staticBaseEnv->vars.emplace_back(envName, baseEnvDispl); baseEnv.values[baseEnvDispl++] = v; - baseEnv.values[0]->payload.attrs->push_back(Attr(symbols.create(primOp.name), v)); + getBuiltins().payload.attrs->push_back(Attr(symbols.create(primOp.name), v)); } return v; @@ -531,7 +531,7 @@ Value & EvalState::getBuiltins() Value & EvalState::getBuiltin(const std::string & name) { - auto it = baseEnv.values[0]->attrs()->get(symbols.create(name)); + auto it = getBuiltins().attrs()->get(symbols.create(name)); if (it) return *it->value; else diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index aea623435..50709b18a 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -4937,7 +4937,7 @@ void EvalState::createBaseEnv() /* Now that we've added all primops, sort the `builtins' set, because attribute lookups expect it to be sorted. */ - baseEnv.values[0]->payload.attrs->sort(); + getBuiltins().payload.attrs->sort(); staticBaseEnv->sort(); diff --git a/src/nix/main.cc b/src/nix/main.cc index eff2d60a4..b0e26e093 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -435,7 +435,8 @@ void mainWrapped(int argc, char * * argv) evalSettings.pureEval = false; EvalState state({}, openStore("dummy://"), fetchSettings, evalSettings); auto builtinsJson = nlohmann::json::object(); - for (auto & builtin : *state.baseEnv.values[0]->attrs()) { + for (auto & builtinPtr : state.getBuiltins().attrs()->lexicographicOrder(state.symbols)) { + auto & builtin = *builtinPtr; auto b = nlohmann::json::object(); if (!builtin.value->isPrimOp()) continue; auto primOp = builtin.value->primOp(); From e948c8e03304a899893fffc1238d0d6025ed2564 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Tue, 19 Nov 2024 18:59:08 +0100 Subject: [PATCH 461/718] Bump fetcher cache version We're getting more reports in https://github.com/NixOS/nix/issues/10985 It appears that something hasn't gone right process-wise. I find this mistake not to be worth investigating, but rather something to pay attention to going forward. Let's nip this in the bud. Closes https://github.com/NixOS/nix/issues/10985 --- src/libfetchers/cache.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libfetchers/cache.cc b/src/libfetchers/cache.cc index b0b6cb887..6c2241f3a 100644 --- a/src/libfetchers/cache.cc +++ b/src/libfetchers/cache.cc @@ -36,7 +36,7 @@ struct CacheImpl : Cache { auto state(_state.lock()); - auto dbPath = getCacheDir() + "/fetcher-cache-v2.sqlite"; + auto dbPath = getCacheDir() + "/fetcher-cache-v3.sqlite"; createDirs(dirOf(dbPath)); state->db = SQLite(dbPath); From 4fca22b0dc6fe8054cb18e4e622b6dd2e3b8635c Mon Sep 17 00:00:00 2001 From: Gavin John Date: Tue, 19 Nov 2024 11:52:45 -0800 Subject: [PATCH 462/718] Update issue and pull request templates --- .github/ISSUE_TEMPLATE/bug_report.md | 39 +++++++++++++------ .github/ISSUE_TEMPLATE/feature_request.md | 35 ++++++++++++----- .github/ISSUE_TEMPLATE/installer.md | 17 ++++++-- .../ISSUE_TEMPLATE/missing_documentation.md | 2 +- .github/PULL_REQUEST_TEMPLATE.md | 8 ++-- 5 files changed, 72 insertions(+), 29 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 984f9a9ea..7ea82dcbc 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,36 +1,51 @@ --- name: Bug report -about: Create a report to help us improve +about: Report unexpected or incorrect behaviour title: '' labels: bug assignees: '' --- -**Describe the bug** +## Describe the bug -A clear and concise description of what the bug is. + -**Steps To Reproduce** +## Steps To Reproduce 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' 4. See error -**Expected behavior** +## Expected behavior -A clear and concise description of what you expected to happen. + -**`nix-env --version` output** +## Metadata -**Additional context** + -Add any other context about the problem here. +## Additional context -**Priorities** + + +## Checklist + + + +- [ ] checked [latest Nix manual] \([source]) +- [ ] checked [open bug issues and pull requests] for possible duplicates + +[latest Nix manual]: https://nixos.org/manual/nix/unstable/ +[source]: https://github.com/NixOS/nix/tree/master/doc/manual/source +[open bug issues and pull requests]: https://github.com/NixOS/nix/labels/bug + +--- Add :+1: to [issues you find important](https://github.com/NixOS/nix/issues?q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc). diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 42c658b52..c75a46951 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,24 +1,39 @@ --- name: Feature request -about: Suggest an idea for this project +about: Suggest a new feature title: '' labels: feature assignees: '' --- -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] +## Is your feature request related to a problem? -**Describe the solution you'd like** -A clear and concise description of what you want to happen. + -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. +## Proposed solution -**Additional context** -Add any other context or screenshots about the feature request here. + -**Priorities** +## Alternative solutions + + + +## Additional context + + + +## Checklist + + + +- [ ] checked [latest Nix manual] \([source]) +- [ ] checked [open feature issues and pull requests] for possible duplicates + +[latest Nix manual]: https://nixos.org/manual/nix/unstable/ +[source]: https://github.com/NixOS/nix/tree/master/doc/manual/source +[open feature issues and pull requests]: https://github.com/NixOS/nix/labels/feature + +--- Add :+1: to [issues you find important](https://github.com/NixOS/nix/issues?q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc). diff --git a/.github/ISSUE_TEMPLATE/installer.md b/.github/ISSUE_TEMPLATE/installer.md index 3768a49c9..ed5e1ce87 100644 --- a/.github/ISSUE_TEMPLATE/installer.md +++ b/.github/ISSUE_TEMPLATE/installer.md @@ -23,14 +23,25 @@ assignees: ''
Output -```log + - +```log ```
-## Priorities +## Checklist + + + +- [ ] checked [latest Nix manual] \([source]) +- [ ] checked [open installer issues and pull requests] for possible duplicates + +[latest Nix manual]: https://nixos.org/manual/nix/unstable/ +[source]: https://github.com/NixOS/nix/tree/master/doc/manual/source +[open installer issues and pull requests]: https://github.com/NixOS/nix/labels/installer + +--- Add :+1: to [issues you find important](https://github.com/NixOS/nix/issues?q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc). diff --git a/.github/ISSUE_TEMPLATE/missing_documentation.md b/.github/ISSUE_TEMPLATE/missing_documentation.md index cf663e28d..6c334b722 100644 --- a/.github/ISSUE_TEMPLATE/missing_documentation.md +++ b/.github/ISSUE_TEMPLATE/missing_documentation.md @@ -26,6 +26,6 @@ assignees: '' [source]: https://github.com/NixOS/nix/tree/master/doc/manual/source [open documentation issues and pull requests]: https://github.com/NixOS/nix/labels/documentation -## Priorities +--- Add :+1: to [issues you find important](https://github.com/NixOS/nix/issues?q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc). diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 69da87db7..c6843d86f 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -17,10 +17,12 @@ so you understand the process and the expectations. --> -# Motivation +## Motivation + -# Context +## Context + @@ -29,7 +31,7 @@ so you understand the process and the expectations. -# Priorities and Process +--- Add :+1: to [pull requests you find important](https://github.com/NixOS/nix/pulls?q=is%3Aopen+sort%3Areactions-%2B1-desc). From df9ccdf31b24439c0aac4c2fad6a04529aaf6f50 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 19 Nov 2024 17:35:32 +0100 Subject: [PATCH 463/718] BasicDerivation: Add applyRewrites() method This is the first part of rewriteDerivation() factored out into its own method. It's not used anywhere else at the moment, but it's useful on lazy-trees for rewriting virtual paths. --- src/libstore/derivations.cc | 26 ++++++++++++++------------ src/libstore/derivations.hh | 6 ++++++ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc index 9b6f67852..1f37b0c38 100644 --- a/src/libstore/derivations.cc +++ b/src/libstore/derivations.cc @@ -1017,29 +1017,31 @@ std::string hashPlaceholder(const OutputNameView outputName) return "/" + hashString(HashAlgorithm::SHA256, concatStrings("nix-output:", outputName)).to_string(HashFormat::Nix32, false); } - - - -static void rewriteDerivation(Store & store, BasicDerivation & drv, const StringMap & rewrites) +void BasicDerivation::applyRewrites(const StringMap & rewrites) { - debug("Rewriting the derivation"); + if (rewrites.empty()) return; - for (auto & rewrite : rewrites) { + debug("rewriting the derivation"); + + for (auto & rewrite : rewrites) debug("rewriting %s as %s", rewrite.first, rewrite.second); - } - drv.builder = rewriteStrings(drv.builder, rewrites); - for (auto & arg : drv.args) { + builder = rewriteStrings(builder, rewrites); + for (auto & arg : args) arg = rewriteStrings(arg, rewrites); - } StringPairs newEnv; - for (auto & envVar : drv.env) { + for (auto & envVar : env) { auto envName = rewriteStrings(envVar.first, rewrites); auto envValue = rewriteStrings(envVar.second, rewrites); newEnv.emplace(envName, envValue); } - drv.env = newEnv; + env = std::move(newEnv); +} + +static void rewriteDerivation(Store & store, BasicDerivation & drv, const StringMap & rewrites) +{ + drv.applyRewrites(rewrites); auto hashModulo = hashDerivationModulo(store, Derivation(drv), true); for (auto & [outputName, output] : drv.outputs) { diff --git a/src/libstore/derivations.hh b/src/libstore/derivations.hh index 40740d545..765b66ade 100644 --- a/src/libstore/derivations.hh +++ b/src/libstore/derivations.hh @@ -325,6 +325,12 @@ struct BasicDerivation static std::string_view nameFromPath(const StorePath & storePath); + /** + * Apply string rewrites to the `env`, `args` and `builder` + * fields. + */ + void applyRewrites(const StringMap & rewrites); + bool operator == (const BasicDerivation &) const = default; // TODO libc++ 16 (used by darwin) missing `std::map::operator <=>`, can't do yet. //auto operator <=> (const BasicDerivation &) const = default; From ced8d311a593fcf9c3823e4e118474ac132d8e60 Mon Sep 17 00:00:00 2001 From: Picnoir Date: Wed, 20 Nov 2024 13:33:00 +0100 Subject: [PATCH 464/718] gc: resume GC after a pathinuse error First the motivation: I recently faced a bug that I assume is coming from the topoSortPaths function where the GC was trying to delete a path having some alive referrers. I resolved this by manually deleting the faulty path referrers using nix-store --query --referrers. I sadly did not manage to reproduce this bug. This bug alone is not a big deal. However, this bug is triggering a cascading failure: invalidatePathChecked is throwing a PathInUse exception. This exception is not catched and fails the whole GC run. From there, the machine (a builder machine) was unable to GC its Nix store, which led to an almost full disk with no way to automatically delete the dead Nix paths. Instead, I think we should log the error for the specific store path we're trying to delete, specifying we can't delete this path because it still has referrers. Once we're done with logging that, the GC run should continue to delete the dead store paths it can delete. --- src/libstore/gc.cc | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index 73195794a..45dfe4ad8 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -4,6 +4,7 @@ #include "finally.hh" #include "unix-domain-socket.hh" #include "signals.hh" +#include "posix-fs-canonicalise.hh" #if !defined(__linux__) // For shelling out to lsof @@ -763,13 +764,18 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) } } } - for (auto & path : topoSortPaths(visited)) { if (!dead.insert(path).second) continue; if (shouldDelete) { - invalidatePathChecked(path); - deleteFromStore(path.to_string()); - referrersCache.erase(path); + try { + invalidatePathChecked(path); + deleteFromStore(path.to_string()); + referrersCache.erase(path); + } catch (PathInUse &e) { + // If we end up here, it's likely a new occurence + // of https://github.com/NixOS/nix/issues/11923 + printError("BUG: %s", e.what()); + } } } }; From 1800853b2a450b8f80514d2f4acb8ab394a22705 Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman <145775305+xokdvium@users.noreply.github.com> Date: Thu, 14 Nov 2024 11:03:58 +0300 Subject: [PATCH 465/718] fix(libexpr/eval-inline): get rid of references to nullptr env When diagnosing infinite recursion references to nullptr `Env` can be formed. This happens only with `ExprBlackHole` is evaluated, which always leads to `InfiniteRecursionError`. UBSAN log for one such case: ``` ../src/libexpr/eval-inline.hh:94:31: runtime error: reference binding to null pointer of type 'Env' SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior ../src/libexpr/eval-inline.hh:94:31 in ``` --- src/libexpr/eval-inline.hh | 6 +++++- src/libexpr/eval.cc | 7 +++++-- src/libexpr/nixexpr.hh | 1 + 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/libexpr/eval-inline.hh b/src/libexpr/eval-inline.hh index d5ce238b2..631c0f396 100644 --- a/src/libexpr/eval-inline.hh +++ b/src/libexpr/eval-inline.hh @@ -87,11 +87,15 @@ void EvalState::forceValue(Value & v, const PosIdx pos) { if (v.isThunk()) { Env * env = v.payload.thunk.env; + assert(env || v.isBlackhole()); Expr * expr = v.payload.thunk.expr; try { v.mkBlackhole(); //checkInterrupt(); - expr->eval(*this, *env, v); + if (env) [[likely]] + expr->eval(*this, *env, v); + else + ExprBlackHole::throwInfiniteRecursionError(*this, v); } catch (...) { v.mkThunk(env, expr); tryFixupBlackHolePos(v, pos); diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 2fe2d5249..05f58957e 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -2052,9 +2052,12 @@ void ExprPos::eval(EvalState & state, Env & env, Value & v) state.mkPos(v, pos); } - -void ExprBlackHole::eval(EvalState & state, Env & env, Value & v) +void ExprBlackHole::eval(EvalState & state, [[maybe_unused]] Env & env, Value & v) { + throwInfiniteRecursionError(state, v); +} + +[[gnu::noinline]] [[noreturn]] void ExprBlackHole::throwInfiniteRecursionError(EvalState & state, Value &v) { state.error("infinite recursion encountered") .atPos(v.determinePos(noPos)) .debugThrow(); diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh index 948839bd9..2950ff1fd 100644 --- a/src/libexpr/nixexpr.hh +++ b/src/libexpr/nixexpr.hh @@ -468,6 +468,7 @@ struct ExprBlackHole : Expr void show(const SymbolTable & symbols, std::ostream & str) const override {} void eval(EvalState & state, Env & env, Value & v) override; void bindVars(EvalState & es, const std::shared_ptr & env) override {} + [[noreturn]] static void throwInfiniteRecursionError(EvalState & state, Value & v); }; extern ExprBlackHole eBlackHole; From ad7ad017ea5a7f7835148a03e81ef63a2689e8c3 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 20 Nov 2024 16:35:47 +0100 Subject: [PATCH 466/718] EvalState::callPathFilter(): Remove unnecessary pathArg argument --- src/libexpr/eval.hh | 1 - src/libexpr/primops.cc | 5 ++--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 107334ffe..3ac3c8a8a 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -819,7 +819,6 @@ public: bool callPathFilter( Value * filterFun, const SourcePath & path, - std::string_view pathArg, PosIdx pos); DocComment getDocCommentForPos(PosIdx pos); diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 503632328..53bfce6c5 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -2438,7 +2438,6 @@ static RegisterPrimOp primop_toFile({ bool EvalState::callPathFilter( Value * filterFun, const SourcePath & path, - std::string_view pathArg, PosIdx pos) { auto st = path.lstat(); @@ -2446,7 +2445,7 @@ bool EvalState::callPathFilter( /* Call the filter function. The first argument is the path, the second is a string indicating the type of the file. */ Value arg1; - arg1.mkString(pathArg); + arg1.mkString(path.path.abs()); // assert that type is not "unknown" Value * args []{&arg1, fileTypeToString(*this, st.type)}; @@ -2489,7 +2488,7 @@ static void addPath( if (filterFun) filter = std::make_unique([&](const Path & p) { auto p2 = CanonPath(p); - return state.callPathFilter(filterFun, {path.accessor, p2}, p2.abs(), pos); + return state.callPathFilter(filterFun, {path.accessor, p2}, pos); }); std::optional expectedStorePath; From 5533b0c735bea0e7277b75ba1024bfbc2521c635 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 20 Nov 2024 18:08:31 +0100 Subject: [PATCH 467/718] Move shebang flake tests into a separate test --- tests/functional/flakes/flakes.sh | 102 +----------------------- tests/functional/flakes/meson.build | 1 + tests/functional/flakes/shebang.sh | 117 ++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+), 101 deletions(-) create mode 100644 tests/functional/flakes/shebang.sh diff --git a/tests/functional/flakes/flakes.sh b/tests/functional/flakes/flakes.sh index 5e901c5d1..2b503df02 100755 --- a/tests/functional/flakes/flakes.sh +++ b/tests/functional/flakes/flakes.sh @@ -74,100 +74,9 @@ cat > "$nonFlakeDir/README.md" < "$nonFlakeDir/shebang.sh" < $nonFlakeDir/shebang-comments.sh < $nonFlakeDir/shebang-different-comments.sh < $nonFlakeDir/shebang-reject.sh < $nonFlakeDir/shebang-inline-expr.sh <> $nonFlakeDir/shebang-inline-expr.sh <<"EOF" -#! nix --offline shell -#! nix --impure --expr `` -#! nix let flake = (builtins.getFlake (toString ../flake1)).packages; -#! nix fooScript = flake.${builtins.currentSystem}.fooScript; -#! nix /* just a comment !@#$%^&*()__+ # */ -#! nix in fooScript -#! nix `` -#! nix --no-write-lock-file --command bash -set -ex -foo -echo "$@" -EOF -chmod +x $nonFlakeDir/shebang-inline-expr.sh - -cat > $nonFlakeDir/fooScript.nix <<"EOF" -let flake = (builtins.getFlake (toString ../flake1)).packages; - fooScript = flake.${builtins.currentSystem}.fooScript; - in fooScript -EOF - -cat > $nonFlakeDir/shebang-file.sh <> $nonFlakeDir/shebang-file.sh <<"EOF" -#! nix --offline shell -#! nix --impure --file ./fooScript.nix -#! nix --no-write-lock-file --command bash -set -ex -foo -echo "$@" -EOF -chmod +x $nonFlakeDir/shebang-file.sh - # Construct a custom registry, additionally test the --registry flag nix registry add --registry "$registry" flake1 "git+file://$flake1Dir" nix registry add --registry "$registry" flake2 "git+file://$percentEncodedFlake2Dir" @@ -644,15 +553,6 @@ nix flake metadata "$flake2Dir" --reference-lock-file $TEST_ROOT/flake2-overridd # reference-lock-file can only be used if allow-dirty is set. expectStderr 1 nix flake metadata "$flake2Dir" --no-allow-dirty --reference-lock-file $TEST_ROOT/flake2-overridden.lock -# Test shebang -[[ $($nonFlakeDir/shebang.sh) = "foo" ]] -[[ $($nonFlakeDir/shebang.sh "bar") = "foo"$'\n'"bar" ]] -[[ $($nonFlakeDir/shebang-comments.sh ) = "foo" ]] -[[ "$($nonFlakeDir/shebang-different-comments.sh)" = "$(cat $nonFlakeDir/shebang-different-comments.sh)" ]] -[[ $($nonFlakeDir/shebang-inline-expr.sh baz) = "foo"$'\n'"baz" ]] -[[ $($nonFlakeDir/shebang-file.sh baz) = "foo"$'\n'"baz" ]] -expect 1 $nonFlakeDir/shebang-reject.sh 2>&1 | grepQuiet -F 'error: unsupported unquoted character in nix shebang: *. Use double backticks to escape?' - # Test that the --commit-lock-file-summary flag and its alias work cat > "$lockfileSummaryFlake/flake.nix" < "$nonFlakeDir/shebang.sh" < $nonFlakeDir/shebang-comments.sh < $nonFlakeDir/shebang-different-comments.sh < $nonFlakeDir/shebang-reject.sh < $nonFlakeDir/shebang-inline-expr.sh <> $nonFlakeDir/shebang-inline-expr.sh <<"EOF" +#! nix --offline shell +#! nix --impure --expr `` +#! nix let flake = (builtins.getFlake (toString ../flake1)).packages; +#! nix fooScript = flake.${builtins.currentSystem}.fooScript; +#! nix /* just a comment !@#$%^&*()__+ # */ +#! nix in fooScript +#! nix `` +#! nix --no-write-lock-file --command bash +set -ex +foo +echo "$@" +EOF +chmod +x $nonFlakeDir/shebang-inline-expr.sh + +cat > $nonFlakeDir/fooScript.nix <<"EOF" +let flake = (builtins.getFlake (toString ../flake1)).packages; + fooScript = flake.${builtins.currentSystem}.fooScript; + in fooScript +EOF + +cat > $nonFlakeDir/shebang-file.sh <> $nonFlakeDir/shebang-file.sh <<"EOF" +#! nix --offline shell +#! nix --impure --file ./fooScript.nix +#! nix --no-write-lock-file --command bash +set -ex +foo +echo "$@" +EOF +chmod +x $nonFlakeDir/shebang-file.sh + +[[ $($nonFlakeDir/shebang.sh) = "foo" ]] +[[ $($nonFlakeDir/shebang.sh "bar") = "foo"$'\n'"bar" ]] +[[ $($nonFlakeDir/shebang-comments.sh ) = "foo" ]] +[[ "$($nonFlakeDir/shebang-different-comments.sh)" = "$(cat $nonFlakeDir/shebang-different-comments.sh)" ]] +[[ $($nonFlakeDir/shebang-inline-expr.sh baz) = "foo"$'\n'"baz" ]] +[[ $($nonFlakeDir/shebang-file.sh baz) = "foo"$'\n'"baz" ]] +expect 1 $nonFlakeDir/shebang-reject.sh 2>&1 | grepQuiet -F 'error: unsupported unquoted character in nix shebang: *. Use double backticks to escape?' From fd2df5f02f59f5f739c1e1931f8ff8c11a7720e0 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 20 Nov 2024 18:23:20 +0100 Subject: [PATCH 468/718] Rename nonFlakeDir -> scriptDir --- tests/functional/flakes/shebang.sh | 50 +++++++++++++++--------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/tests/functional/flakes/shebang.sh b/tests/functional/flakes/shebang.sh index ac00ca764..23db19baa 100644 --- a/tests/functional/flakes/shebang.sh +++ b/tests/functional/flakes/shebang.sh @@ -7,15 +7,15 @@ TODO_NixOS requireGit flake1Dir=$TEST_ROOT/flake1 -nonFlakeDir=$TEST_ROOT/nonFlake +scriptDir=$TEST_ROOT/nonFlake createGitRepo "$flake1Dir" "" createSimpleGitFlake "$flake1Dir" nix registry add --registry "$registry" flake1 "git+file://$flake1Dir" -mkdir -p "$nonFlakeDir" +mkdir -p "$scriptDir" -cat > "$nonFlakeDir/shebang.sh" < "$scriptDir/shebang.sh" < $nonFlakeDir/shebang-comments.sh < $scriptDir/shebang-comments.sh < $nonFlakeDir/shebang-comments.sh < $nonFlakeDir/shebang-different-comments.sh < $scriptDir/shebang-different-comments.sh < $nonFlakeDir/shebang-different-comments.sh < $nonFlakeDir/shebang-reject.sh < $scriptDir/shebang-reject.sh < $nonFlakeDir/shebang-reject.sh < $nonFlakeDir/shebang-inline-expr.sh < $scriptDir/shebang-inline-expr.sh <> $nonFlakeDir/shebang-inline-expr.sh <<"EOF" +cat >> $scriptDir/shebang-inline-expr.sh <<"EOF" #! nix --offline shell #! nix --impure --expr `` #! nix let flake = (builtins.getFlake (toString ../flake1)).packages; @@ -87,18 +87,18 @@ set -ex foo echo "$@" EOF -chmod +x $nonFlakeDir/shebang-inline-expr.sh +chmod +x $scriptDir/shebang-inline-expr.sh -cat > $nonFlakeDir/fooScript.nix <<"EOF" +cat > $scriptDir/fooScript.nix <<"EOF" let flake = (builtins.getFlake (toString ../flake1)).packages; fooScript = flake.${builtins.currentSystem}.fooScript; in fooScript EOF -cat > $nonFlakeDir/shebang-file.sh < $scriptDir/shebang-file.sh <> $nonFlakeDir/shebang-file.sh <<"EOF" +cat >> $scriptDir/shebang-file.sh <<"EOF" #! nix --offline shell #! nix --impure --file ./fooScript.nix #! nix --no-write-lock-file --command bash @@ -106,12 +106,12 @@ set -ex foo echo "$@" EOF -chmod +x $nonFlakeDir/shebang-file.sh +chmod +x $scriptDir/shebang-file.sh -[[ $($nonFlakeDir/shebang.sh) = "foo" ]] -[[ $($nonFlakeDir/shebang.sh "bar") = "foo"$'\n'"bar" ]] -[[ $($nonFlakeDir/shebang-comments.sh ) = "foo" ]] -[[ "$($nonFlakeDir/shebang-different-comments.sh)" = "$(cat $nonFlakeDir/shebang-different-comments.sh)" ]] -[[ $($nonFlakeDir/shebang-inline-expr.sh baz) = "foo"$'\n'"baz" ]] -[[ $($nonFlakeDir/shebang-file.sh baz) = "foo"$'\n'"baz" ]] -expect 1 $nonFlakeDir/shebang-reject.sh 2>&1 | grepQuiet -F 'error: unsupported unquoted character in nix shebang: *. Use double backticks to escape?' +[[ $($scriptDir/shebang.sh) = "foo" ]] +[[ $($scriptDir/shebang.sh "bar") = "foo"$'\n'"bar" ]] +[[ $($scriptDir/shebang-comments.sh ) = "foo" ]] +[[ "$($scriptDir/shebang-different-comments.sh)" = "$(cat $scriptDir/shebang-different-comments.sh)" ]] +[[ $($scriptDir/shebang-inline-expr.sh baz) = "foo"$'\n'"baz" ]] +[[ $($scriptDir/shebang-file.sh baz) = "foo"$'\n'"baz" ]] +expect 1 $scriptDir/shebang-reject.sh 2>&1 | grepQuiet -F 'error: unsupported unquoted character in nix shebang: *. Use double backticks to escape?' From e1cb905acae40b6bb55d30312ba9997c418eebf8 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 20 Nov 2024 18:42:33 +0100 Subject: [PATCH 469/718] Move --commit-lock-file-summary tests into a separate file --- .../flakes/commit-lock-file-summary.sh | 50 +++++++++++++++++++ tests/functional/flakes/flakes.sh | 40 +-------------- tests/functional/flakes/meson.build | 1 + 3 files changed, 52 insertions(+), 39 deletions(-) create mode 100644 tests/functional/flakes/commit-lock-file-summary.sh diff --git a/tests/functional/flakes/commit-lock-file-summary.sh b/tests/functional/flakes/commit-lock-file-summary.sh new file mode 100644 index 000000000..21504eb21 --- /dev/null +++ b/tests/functional/flakes/commit-lock-file-summary.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash + +source ./common.sh + +TODO_NixOS + +requireGit + +flake1Dir=$TEST_ROOT/flake1 +lockfileSummaryFlake=$TEST_ROOT/lockfileSummaryFlake + +createGitRepo "$flake1Dir" "" +createSimpleGitFlake "$flake1Dir" +nix registry add --registry "$registry" flake1 "git+file://$flake1Dir" + +createGitRepo "$lockfileSummaryFlake" "--initial-branch=main" + +# Test that the --commit-lock-file-summary flag and its alias work +cat > "$lockfileSummaryFlake/flake.nix" < "$lockfileSummaryFlake/flake.nix" < Date: Wed, 20 Nov 2024 18:51:23 +0100 Subject: [PATCH 470/718] Add a utility function for creating/registering a simple flake --- tests/functional/flakes/commit-lock-file-summary.sh | 8 +------- tests/functional/flakes/common.sh | 9 +++++++++ tests/functional/flakes/dubious-query.sh | 7 ++----- tests/functional/flakes/edit.sh | 7 +------ tests/functional/flakes/shebang.sh | 8 +------- 5 files changed, 14 insertions(+), 25 deletions(-) diff --git a/tests/functional/flakes/commit-lock-file-summary.sh b/tests/functional/flakes/commit-lock-file-summary.sh index 21504eb21..314d43ec3 100644 --- a/tests/functional/flakes/commit-lock-file-summary.sh +++ b/tests/functional/flakes/commit-lock-file-summary.sh @@ -4,15 +4,9 @@ source ./common.sh TODO_NixOS -requireGit +createFlake1 -flake1Dir=$TEST_ROOT/flake1 lockfileSummaryFlake=$TEST_ROOT/lockfileSummaryFlake - -createGitRepo "$flake1Dir" "" -createSimpleGitFlake "$flake1Dir" -nix registry add --registry "$registry" flake1 "git+file://$flake1Dir" - createGitRepo "$lockfileSummaryFlake" "--initial-branch=main" # Test that the --commit-lock-file-summary flag and its alias work diff --git a/tests/functional/flakes/common.sh b/tests/functional/flakes/common.sh index cc9b2e466..0a020a1d7 100644 --- a/tests/functional/flakes/common.sh +++ b/tests/functional/flakes/common.sh @@ -38,12 +38,21 @@ EOF } createSimpleGitFlake() { + requireGit local flakeDir="$1" writeSimpleFlake "$flakeDir" git -C "$flakeDir" add flake.nix simple.nix shell.nix simple.builder.sh config.nix git -C "$flakeDir" commit -m 'Initial' } +# Create a simple Git flake and add it to the registry as "flake1". +createFlake1() { + flake1Dir="$TEST_ROOT/flake1" + createGitRepo "$flake1Dir" "" + createSimpleGitFlake "$flake1Dir" + nix registry add --registry "$registry" flake1 "git+file://$flake1Dir" +} + writeDependentFlake() { local flakeDir="$1" cat > "$flakeDir/flake.nix" < "$scriptDir/shebang.sh" < Date: Wed, 20 Nov 2024 19:51:04 +0100 Subject: [PATCH 471/718] Move non-flake input tests into a separate file --- tests/functional/flakes/common.sh | 23 +++ tests/functional/flakes/flakes.sh | 166 ++------------------ tests/functional/flakes/meson.build | 1 + tests/functional/flakes/non-flake-inputs.sh | 126 +++++++++++++++ 4 files changed, 164 insertions(+), 152 deletions(-) create mode 100644 tests/functional/flakes/non-flake-inputs.sh diff --git a/tests/functional/flakes/common.sh b/tests/functional/flakes/common.sh index 0a020a1d7..b1c3988e3 100644 --- a/tests/functional/flakes/common.sh +++ b/tests/functional/flakes/common.sh @@ -53,6 +53,29 @@ createFlake1() { nix registry add --registry "$registry" flake1 "git+file://$flake1Dir" } +createFlake2() { + flake2Dir="$TEST_ROOT/flake 2" + percentEncodedFlake2Dir="$TEST_ROOT/flake%202" + + # Give one repo a non-main initial branch. + createGitRepo "$flake2Dir" "--initial-branch=main" + + cat > "$flake2Dir/flake.nix" < "$flakeDir/flake.nix" < "$flake2Dir/flake.nix" < "$flake3Dir/flake.nix" < "$nonFlakeDir/README.md" < "$flake3Dir/flake.nix" < \$out - [[ \$(cat \${inputs.nonFlake}/README.md) = \$(cat \${inputs.nonFlakeFile}) ]] - [[ \${inputs.nonFlakeFile} = \${inputs.nonFlakeFile2} ]] - ''; - }; - }; -} -EOF - -cp "${config_nix}" "$flake3Dir" - -git -C "$flake3Dir" add flake.nix config.nix -git -C "$flake3Dir" commit -m 'Add nonFlakeInputs' - -# Check whether `nix build` works with a lockfile which is missing a -# nonFlakeInputs. -nix build -o "$TEST_ROOT/result" "$flake3Dir#sth" --commit-lock-file - -nix build -o "$TEST_ROOT/result" flake3#fnord -[[ $(cat $TEST_ROOT/result) = FNORD ]] - -# Check whether flake input fetching is lazy: flake3#sth does not -# depend on flake2, so this shouldn't fail. -rm -rf "$TEST_HOME/.cache" -clearStore -mv "$flake2Dir" "$flake2Dir.tmp" -mv "$nonFlakeDir" "$nonFlakeDir.tmp" -nix build -o "$TEST_ROOT/result" flake3#sth -(! nix build -o "$TEST_ROOT/result" flake3#xyzzy) -(! nix build -o "$TEST_ROOT/result" flake3#fnord) -mv "$flake2Dir.tmp" "$flake2Dir" -mv "$nonFlakeDir.tmp" "$nonFlakeDir" -nix build -o "$TEST_ROOT/result" flake3#xyzzy flake3#fnord - # Test doing multiple `lookupFlake`s -nix build -o "$TEST_ROOT/result" flake4#xyzzy +nix build -o "$TEST_ROOT/result" flake3#xyzzy # Test 'nix flake update' and --override-flake. nix flake lock "$flake3Dir" @@ -330,53 +230,15 @@ nix flake lock "$flake3Dir" nix flake update --flake "$flake3Dir" --override-flake flake2 nixpkgs [[ ! -z $(git -C "$flake3Dir" diff master || echo failed) ]] -# Make branch "removeXyzzy" where flake3 doesn't have xyzzy anymore -git -C "$flake3Dir" checkout -b removeXyzzy -rm "$flake3Dir/flake.nix" - -cat > "$flake3Dir/flake.nix" < \$out - ''; - }; - }; -} -EOF -nix flake lock "$flake3Dir" -git -C "$flake3Dir" add flake.nix flake.lock -git -C "$flake3Dir" commit -m 'Remove packages.xyzzy' -git -C "$flake3Dir" checkout master - -# Test whether fuzzy-matching works for registry entries. -(! nix build -o "$TEST_ROOT/result" flake4/removeXyzzy#xyzzy) -nix build -o "$TEST_ROOT/result" flake4/removeXyzzy#sth - # Testing the nix CLI nix registry add flake1 flake3 -[[ $(nix registry list | wc -l) == 6 ]] -nix registry pin flake1 -[[ $(nix registry list | wc -l) == 6 ]] -nix registry pin flake1 flake3 -[[ $(nix registry list | wc -l) == 6 ]] -nix registry remove flake1 [[ $(nix registry list | wc -l) == 5 ]] +nix registry pin flake1 +[[ $(nix registry list | wc -l) == 5 ]] +nix registry pin flake1 flake3 +[[ $(nix registry list | wc -l) == 5 ]] +nix registry remove flake1 +[[ $(nix registry list | wc -l) == 4 ]] # Test 'nix registry list' with a disabled global registry. nix registry add user-flake1 git+file://$flake1Dir @@ -386,7 +248,7 @@ nix --flake-registry "" registry list | grepQuietInverse '^global' # nothing in nix --flake-registry "" registry list | grepQuiet '^user' nix registry remove user-flake1 nix registry remove user-flake2 -[[ $(nix registry list | wc -l) == 5 ]] +[[ $(nix registry list | wc -l) == 4 ]] # Test 'nix flake clone'. rm -rf $TEST_ROOT/flake1-v2 diff --git a/tests/functional/flakes/meson.build b/tests/functional/flakes/meson.build index a646abc00..00060e3c9 100644 --- a/tests/functional/flakes/meson.build +++ b/tests/functional/flakes/meson.build @@ -26,6 +26,7 @@ suites += { 'dubious-query.sh', 'shebang.sh', 'commit-lock-file-summary.sh', + 'non-flake-inputs.sh', ], 'workdir': meson.current_source_dir(), } diff --git a/tests/functional/flakes/non-flake-inputs.sh b/tests/functional/flakes/non-flake-inputs.sh new file mode 100644 index 000000000..66dc74e0c --- /dev/null +++ b/tests/functional/flakes/non-flake-inputs.sh @@ -0,0 +1,126 @@ +#!/usr/bin/env bash + +source ./common.sh + +createFlake1 +createFlake2 + +nonFlakeDir=$TEST_ROOT/nonFlake +createGitRepo "$nonFlakeDir" "" + +cat > "$nonFlakeDir/README.md" < "$flake3Dir/flake.nix" < \$out + [[ \$(cat \${inputs.nonFlake}/README.md) = \$(cat \${inputs.nonFlakeFile}) ]] + [[ \${inputs.nonFlakeFile} = \${inputs.nonFlakeFile2} ]] + ''; + }; + }; +} +EOF + +cp "${config_nix}" "$flake3Dir" + +git -C "$flake3Dir" add flake.nix config.nix +git -C "$flake3Dir" commit -m 'Add nonFlakeInputs' + +# Check whether `nix build` works with a lockfile which is missing a +# nonFlakeInputs. +nix build -o "$TEST_ROOT/result" "$flake3Dir#sth" --commit-lock-file + +nix registry add --registry "$registry" flake3 "git+file://$flake3Dir" + +nix build -o "$TEST_ROOT/result" flake3#fnord +[[ $(cat $TEST_ROOT/result) = FNORD ]] + +# Check whether flake input fetching is lazy: flake3#sth does not +# depend on flake2, so this shouldn't fail. +rm -rf "$TEST_HOME/.cache" +clearStore +mv "$flake2Dir" "$flake2Dir.tmp" +mv "$nonFlakeDir" "$nonFlakeDir.tmp" +nix build -o "$TEST_ROOT/result" flake3#sth +(! nix build -o "$TEST_ROOT/result" flake3#xyzzy) +(! nix build -o "$TEST_ROOT/result" flake3#fnord) +mv "$flake2Dir.tmp" "$flake2Dir" +mv "$nonFlakeDir.tmp" "$nonFlakeDir" +nix build -o "$TEST_ROOT/result" flake3#xyzzy flake3#fnord + +# Make branch "removeXyzzy" where flake3 doesn't have xyzzy anymore +git -C "$flake3Dir" checkout -b removeXyzzy +rm "$flake3Dir/flake.nix" + +cat > "$flake3Dir/flake.nix" < \$out + ''; + }; + }; +} +EOF +nix flake lock "$flake3Dir" +git -C "$flake3Dir" add flake.nix flake.lock +git -C "$flake3Dir" commit -m 'Remove packages.xyzzy' +git -C "$flake3Dir" checkout master + +# Test whether fuzzy-matching works for registry entries. +nix registry add --registry "$registry" flake4 flake3 +(! nix build -o "$TEST_ROOT/result" flake4/removeXyzzy#xyzzy) +nix build -o "$TEST_ROOT/result" flake4/removeXyzzy#sth From db0525692dcb94e4f274e033091ad1ce54a30cf3 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 20 Nov 2024 21:07:22 +0100 Subject: [PATCH 472/718] Formatting --- src/libcmd/command.cc | 36 +++++++++++++++++++----------------- src/libcmd/command.hh | 5 +---- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/src/libcmd/command.cc b/src/libcmd/command.cc index 0a3a516c2..86d13fab7 100644 --- a/src/libcmd/command.cc +++ b/src/libcmd/command.cc @@ -369,28 +369,30 @@ void MixEnvironment::setEnviron() return; } -void createOutLinks( - const std::filesystem::path & outLink, - const BuiltPaths & buildables, - LocalFSStore & store) +void createOutLinks(const std::filesystem::path & outLink, const BuiltPaths & buildables, LocalFSStore & store) { for (const auto & [_i, buildable] : enumerate(buildables)) { auto i = _i; - std::visit(overloaded { - [&](const BuiltPath::Opaque & bo) { - auto symlink = outLink; - if (i) symlink += fmt("-%d", i); - store.addPermRoot(bo.path, absPath(symlink.string())); - }, - [&](const BuiltPath::Built & bfd) { - for (auto & output : bfd.outputs) { + std::visit( + overloaded{ + [&](const BuiltPath::Opaque & bo) { auto symlink = outLink; - if (i) symlink += fmt("-%d", i); - if (output.first != "out") symlink += fmt("-%s", output.first); - store.addPermRoot(output.second, absPath(symlink.string())); - } + if (i) + symlink += fmt("-%d", i); + store.addPermRoot(bo.path, absPath(symlink.string())); + }, + [&](const BuiltPath::Built & bfd) { + for (auto & output : bfd.outputs) { + auto symlink = outLink; + if (i) + symlink += fmt("-%d", i); + if (output.first != "out") + symlink += fmt("-%s", output.first); + store.addPermRoot(output.second, absPath(symlink.string())); + } + }, }, - }, buildable.raw()); + buildable.raw()); } } diff --git a/src/libcmd/command.hh b/src/libcmd/command.hh index 67c208d28..23529848f 100644 --- a/src/libcmd/command.hh +++ b/src/libcmd/command.hh @@ -372,9 +372,6 @@ void printClosureDiff( * Create symlinks prefixed by `outLink` to the store paths in * `buildables`. */ -void createOutLinks( - const std::filesystem::path & outLink, - const BuiltPaths & buildables, - LocalFSStore & store); +void createOutLinks(const std::filesystem::path & outLink, const BuiltPaths & buildables, LocalFSStore & store); } From 2f24030bffa8f8f6769ac8ce0002d6c201312933 Mon Sep 17 00:00:00 2001 From: Gavin John Date: Wed, 20 Nov 2024 13:23:02 -0800 Subject: [PATCH 473/718] Move bug report list to comment and make it more nix-specific --- .github/ISSUE_TEMPLATE/bug_report.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 7ea82dcbc..a5005f8a0 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -18,10 +18,13 @@ assignees: '' ## Steps To Reproduce -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error + ## Expected behavior From 671df02bf7d0cbf339d2626266260e0b7ccf5988 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 20 Nov 2024 20:42:13 +0100 Subject: [PATCH 474/718] shellcheck --- tests/functional/flakes/non-flake-inputs.sh | 2 +- tests/functional/flakes/shebang.sh | 44 ++++++++++----------- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/tests/functional/flakes/non-flake-inputs.sh b/tests/functional/flakes/non-flake-inputs.sh index 66dc74e0c..c9c9803d3 100644 --- a/tests/functional/flakes/non-flake-inputs.sh +++ b/tests/functional/flakes/non-flake-inputs.sh @@ -71,7 +71,7 @@ nix build -o "$TEST_ROOT/result" "$flake3Dir#sth" --commit-lock-file nix registry add --registry "$registry" flake3 "git+file://$flake3Dir" nix build -o "$TEST_ROOT/result" flake3#fnord -[[ $(cat $TEST_ROOT/result) = FNORD ]] +[[ $(cat "$TEST_ROOT/result") = FNORD ]] # Check whether flake input fetching is lazy: flake3#sth does not # depend on flake2, so this shouldn't fail. diff --git a/tests/functional/flakes/shebang.sh b/tests/functional/flakes/shebang.sh index 645b1fa38..576a62e2c 100644 --- a/tests/functional/flakes/shebang.sh +++ b/tests/functional/flakes/shebang.sh @@ -6,7 +6,7 @@ TODO_NixOS createFlake1 -scriptDir=$TEST_ROOT/nonFlake +scriptDir="$TEST_ROOT/nonFlake" mkdir -p "$scriptDir" cat > "$scriptDir/shebang.sh" < $scriptDir/shebang-comments.sh < "$scriptDir/shebang-comments.sh" < $scriptDir/shebang-comments.sh < $scriptDir/shebang-different-comments.sh < "$scriptDir/shebang-different-comments.sh" < $scriptDir/shebang-different-comments.sh < $scriptDir/shebang-reject.sh < "$scriptDir/shebang-reject.sh" < $scriptDir/shebang-reject.sh < $scriptDir/shebang-inline-expr.sh < "$scriptDir/shebang-inline-expr.sh" <> $scriptDir/shebang-inline-expr.sh <<"EOF" +cat >> "$scriptDir/shebang-inline-expr.sh" <<"EOF" #! nix --offline shell #! nix --impure --expr `` #! nix let flake = (builtins.getFlake (toString ../flake1)).packages; @@ -81,18 +79,18 @@ set -ex foo echo "$@" EOF -chmod +x $scriptDir/shebang-inline-expr.sh +chmod +x "$scriptDir/shebang-inline-expr.sh" -cat > $scriptDir/fooScript.nix <<"EOF" +cat > "$scriptDir/fooScript.nix" <<"EOF" let flake = (builtins.getFlake (toString ../flake1)).packages; fooScript = flake.${builtins.currentSystem}.fooScript; in fooScript EOF -cat > $scriptDir/shebang-file.sh < "$scriptDir/shebang-file.sh" <> $scriptDir/shebang-file.sh <<"EOF" +cat >> "$scriptDir/shebang-file.sh" <<"EOF" #! nix --offline shell #! nix --impure --file ./fooScript.nix #! nix --no-write-lock-file --command bash @@ -100,12 +98,12 @@ set -ex foo echo "$@" EOF -chmod +x $scriptDir/shebang-file.sh +chmod +x "$scriptDir/shebang-file.sh" -[[ $($scriptDir/shebang.sh) = "foo" ]] -[[ $($scriptDir/shebang.sh "bar") = "foo"$'\n'"bar" ]] -[[ $($scriptDir/shebang-comments.sh ) = "foo" ]] -[[ "$($scriptDir/shebang-different-comments.sh)" = "$(cat $scriptDir/shebang-different-comments.sh)" ]] -[[ $($scriptDir/shebang-inline-expr.sh baz) = "foo"$'\n'"baz" ]] -[[ $($scriptDir/shebang-file.sh baz) = "foo"$'\n'"baz" ]] -expect 1 $scriptDir/shebang-reject.sh 2>&1 | grepQuiet -F 'error: unsupported unquoted character in nix shebang: *. Use double backticks to escape?' +[[ $("$scriptDir/shebang.sh") = "foo" ]] +[[ $("$scriptDir/shebang.sh" "bar") = "foo"$'\n'"bar" ]] +[[ $("$scriptDir/shebang-comments.sh" ) = "foo" ]] +[[ "$("$scriptDir/shebang-different-comments.sh")" = "$(cat "$scriptDir/shebang-different-comments.sh")" ]] +[[ $("$scriptDir/shebang-inline-expr.sh" baz) = "foo"$'\n'"baz" ]] +[[ $("$scriptDir/shebang-file.sh" baz) = "foo"$'\n'"baz" ]] +expect 1 "$scriptDir/shebang-reject.sh" 2>&1 | grepQuiet -F 'error: unsupported unquoted character in nix shebang: *. Use double backticks to escape?' From e122acef97edd4a1190dba63e8f91b2b363a7df2 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 20 Nov 2024 20:55:45 +0100 Subject: [PATCH 475/718] Fix VM test --- tests/functional/flakes/non-flake-inputs.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/functional/flakes/non-flake-inputs.sh b/tests/functional/flakes/non-flake-inputs.sh index c9c9803d3..f5e12cd01 100644 --- a/tests/functional/flakes/non-flake-inputs.sh +++ b/tests/functional/flakes/non-flake-inputs.sh @@ -2,6 +2,8 @@ source ./common.sh +TODO_NixOS + createFlake1 createFlake2 From 4a18c783853858b7bf897ac0a69baa3be7248237 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 20 Nov 2024 21:26:20 +0100 Subject: [PATCH 476/718] flake_regressions: Pass -L to nix build --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cb97fd211..9918875d9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -220,4 +220,4 @@ jobs: path: flake-regressions/tests - uses: DeterminateSystems/nix-installer-action@main - uses: DeterminateSystems/magic-nix-cache-action@main - - run: nix build --out-link ./new-nix && PATH=$(pwd)/new-nix/bin:$PATH MAX_FLAKES=25 flake-regressions/eval-all.sh + - run: nix build -L --out-link ./new-nix && PATH=$(pwd)/new-nix/bin:$PATH MAX_FLAKES=25 flake-regressions/eval-all.sh From f4f4b698f6bbd19cec767686eb3f017567d9fef2 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 21 Nov 2024 16:53:34 +0100 Subject: [PATCH 477/718] fetchTree: Don't crash if narHash is missing Fixes nix: ../src/libexpr/primops/fetchTree.cc:37: void nix::emitTreeAttrs(EvalState&, const StorePath&, const fetchers::Input&, Value&, bool, bool): Assertion `narHash' failed. on a lock file with an input that doesn't have a narHash. This can happen when using a lock file created by the lazy-trees branch. Cherry-picked from lazy-trees. --- src/libexpr/primops/fetchTree.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc index c207da8ad..47d1be1cc 100644 --- a/src/libexpr/primops/fetchTree.cc +++ b/src/libexpr/primops/fetchTree.cc @@ -33,9 +33,8 @@ void emitTreeAttrs( // FIXME: support arbitrary input attributes. - auto narHash = input.getNarHash(); - assert(narHash); - attrs.alloc("narHash").mkString(narHash->to_string(HashFormat::SRI, true)); + if (auto narHash = input.getNarHash()) + attrs.alloc("narHash").mkString(narHash->to_string(HashFormat::SRI, true)); if (input.getType() == "git") attrs.alloc("submodules").mkBool( From 965ca18db85638d6a04f4ecaff16b48fd661fe33 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 21 Nov 2024 18:44:57 +0100 Subject: [PATCH 478/718] Merge build-utils-meson/{diagnostics,threads} into build-utils-meson/common This reduces the amount of boilerplate. More importantly, it provides a place to add compiler flags (such as -O3) without having to add it to every subproject (and the risk of forgetting to include it). --- build-utils-meson/{diagnostics => common}/meson.build | 7 +++++++ build-utils-meson/threads/meson.build | 6 ------ src/libcmd/meson.build | 4 +--- src/libexpr-c/meson.build | 4 +--- src/libexpr-test-support/meson.build | 4 +--- src/libexpr-tests/meson.build | 4 +--- src/libexpr/meson.build | 4 +--- src/libfetchers-tests/meson.build | 4 +--- src/libfetchers/meson.build | 4 +--- src/libflake-tests/meson.build | 4 +--- src/libflake/meson.build | 4 +--- src/libmain-c/meson.build | 4 +--- src/libmain/meson.build | 4 +--- src/libstore-c/meson.build | 4 +--- src/libstore-test-support/meson.build | 4 +--- src/libstore-tests/meson.build | 4 +--- src/libstore/meson.build | 3 +-- src/libutil-c/meson.build | 4 +--- src/libutil-test-support/meson.build | 4 +--- src/libutil-tests/meson.build | 4 +--- src/libutil/meson.build | 3 +-- src/nix/meson.build | 4 +--- 22 files changed, 27 insertions(+), 64 deletions(-) rename build-utils-meson/{diagnostics => common}/meson.build (51%) delete mode 100644 build-utils-meson/threads/meson.build diff --git a/build-utils-meson/diagnostics/meson.build b/build-utils-meson/common/meson.build similarity index 51% rename from build-utils-meson/diagnostics/meson.build rename to build-utils-meson/common/meson.build index 30eedfc13..67b6658f5 100644 --- a/build-utils-meson/diagnostics/meson.build +++ b/build-utils-meson/common/meson.build @@ -1,3 +1,10 @@ +# This is only conditional to work around +# https://github.com/mesonbuild/meson/issues/13293. It should be +# unconditional. +if not (host_machine.system() == 'windows' and cxx.get_id() == 'gcc') + deps_private += dependency('threads') +endif + add_project_arguments( '-Wdeprecated-copy', '-Werror=suggest-override', diff --git a/build-utils-meson/threads/meson.build b/build-utils-meson/threads/meson.build deleted file mode 100644 index 294160de1..000000000 --- a/build-utils-meson/threads/meson.build +++ /dev/null @@ -1,6 +0,0 @@ -# This is only conditional to work around -# https://github.com/mesonbuild/meson/issues/13293. It should be -# unconditional. -if not (host_machine.system() == 'windows' and cxx.get_id() == 'gcc') - deps_private += dependency('threads') -endif diff --git a/src/libcmd/meson.build b/src/libcmd/meson.build index c484cf998..1f27c1614 100644 --- a/src/libcmd/meson.build +++ b/src/libcmd/meson.build @@ -30,8 +30,6 @@ deps_public_maybe_subproject = [ ] subdir('build-utils-meson/subprojects') -subdir('build-utils-meson/threads') - nlohmann_json = dependency('nlohmann_json', version : '>= 3.9') deps_public += nlohmann_json @@ -72,7 +70,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') sources = files( 'built-path.cc', diff --git a/src/libexpr-c/meson.build b/src/libexpr-c/meson.build index 4160f0d5a..5bcca29e0 100644 --- a/src/libexpr-c/meson.build +++ b/src/libexpr-c/meson.build @@ -29,8 +29,6 @@ deps_public_maybe_subproject = [ ] subdir('build-utils-meson/subprojects') -subdir('build-utils-meson/threads') - # TODO rename, because it will conflict with downstream projects configdata.set_quoted('PACKAGE_VERSION', meson.project_version()) @@ -55,7 +53,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') sources = files( 'nix_api_expr.cc', diff --git a/src/libexpr-test-support/meson.build b/src/libexpr-test-support/meson.build index b9e7f390d..bdfd435a8 100644 --- a/src/libexpr-test-support/meson.build +++ b/src/libexpr-test-support/meson.build @@ -27,8 +27,6 @@ deps_public_maybe_subproject = [ ] subdir('build-utils-meson/subprojects') -subdir('build-utils-meson/threads') - rapidcheck = dependency('rapidcheck') deps_public += rapidcheck @@ -41,7 +39,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') sources = files( 'tests/value/context.cc', diff --git a/src/libexpr-tests/meson.build b/src/libexpr-tests/meson.build index 5a5c9f1d4..b50c18c9c 100644 --- a/src/libexpr-tests/meson.build +++ b/src/libexpr-tests/meson.build @@ -25,8 +25,6 @@ deps_public_maybe_subproject = [ ] subdir('build-utils-meson/subprojects') -subdir('build-utils-meson/threads') - subdir('build-utils-meson/export-all-symbols') subdir('build-utils-meson/windows-version') @@ -51,7 +49,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') sources = files( 'derived-path.cc', diff --git a/src/libexpr/meson.build b/src/libexpr/meson.build index 4d8a38b43..28318579e 100644 --- a/src/libexpr/meson.build +++ b/src/libexpr/meson.build @@ -27,8 +27,6 @@ deps_public_maybe_subproject = [ ] subdir('build-utils-meson/subprojects') -subdir('build-utils-meson/threads') - boost = dependency( 'boost', modules : ['container', 'context'], @@ -79,7 +77,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') parser_tab = custom_target( input : 'parser.y', diff --git a/src/libfetchers-tests/meson.build b/src/libfetchers-tests/meson.build index d948dbad6..fdab6ba6c 100644 --- a/src/libfetchers-tests/meson.build +++ b/src/libfetchers-tests/meson.build @@ -24,8 +24,6 @@ deps_public_maybe_subproject = [ ] subdir('build-utils-meson/subprojects') -subdir('build-utils-meson/threads') - subdir('build-utils-meson/export-all-symbols') subdir('build-utils-meson/windows-version') @@ -44,7 +42,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') sources = files( 'public-key.cc', diff --git a/src/libfetchers/meson.build b/src/libfetchers/meson.build index ff638578d..07a1178cc 100644 --- a/src/libfetchers/meson.build +++ b/src/libfetchers/meson.build @@ -26,8 +26,6 @@ deps_public_maybe_subproject = [ ] subdir('build-utils-meson/subprojects') -subdir('build-utils-meson/threads') - nlohmann_json = dependency('nlohmann_json', version : '>= 3.9') deps_public += nlohmann_json @@ -43,7 +41,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') sources = files( 'attrs.cc', diff --git a/src/libflake-tests/meson.build b/src/libflake-tests/meson.build index 592a7493b..c0a9b8847 100644 --- a/src/libflake-tests/meson.build +++ b/src/libflake-tests/meson.build @@ -24,8 +24,6 @@ deps_public_maybe_subproject = [ ] subdir('build-utils-meson/subprojects') -subdir('build-utils-meson/threads') - subdir('build-utils-meson/export-all-symbols') subdir('build-utils-meson/windows-version') @@ -44,7 +42,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') sources = files( 'flakeref.cc', diff --git a/src/libflake/meson.build b/src/libflake/meson.build index d2bb179df..2c1a70a18 100644 --- a/src/libflake/meson.build +++ b/src/libflake/meson.build @@ -26,8 +26,6 @@ deps_public_maybe_subproject = [ ] subdir('build-utils-meson/subprojects') -subdir('build-utils-meson/threads') - nlohmann_json = dependency('nlohmann_json', version : '>= 3.9') deps_public += nlohmann_json @@ -41,7 +39,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') sources = files( 'flake/config.cc', diff --git a/src/libmain-c/meson.build b/src/libmain-c/meson.build index 0ec0e3f6d..3cb1e4baa 100644 --- a/src/libmain-c/meson.build +++ b/src/libmain-c/meson.build @@ -29,8 +29,6 @@ deps_public_maybe_subproject = [ ] subdir('build-utils-meson/subprojects') -subdir('build-utils-meson/threads') - # TODO rename, because it will conflict with downstream projects configdata.set_quoted('PACKAGE_VERSION', meson.project_version()) @@ -55,7 +53,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') sources = files( 'nix_api_main.cc', diff --git a/src/libmain/meson.build b/src/libmain/meson.build index 7fcadf06d..6c6298e2b 100644 --- a/src/libmain/meson.build +++ b/src/libmain/meson.build @@ -26,8 +26,6 @@ deps_public_maybe_subproject = [ ] subdir('build-utils-meson/subprojects') -subdir('build-utils-meson/threads') - pubsetbuf_test = ''' #include @@ -60,7 +58,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') sources = files( 'common-args.cc', diff --git a/src/libstore-c/meson.build b/src/libstore-c/meson.build index d4f86eeff..44b5fe11d 100644 --- a/src/libstore-c/meson.build +++ b/src/libstore-c/meson.build @@ -27,8 +27,6 @@ deps_public_maybe_subproject = [ ] subdir('build-utils-meson/subprojects') -subdir('build-utils-meson/threads') - # TODO rename, because it will conflict with downstream projects configdata.set_quoted('PACKAGE_VERSION', meson.project_version()) @@ -51,7 +49,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') sources = files( 'nix_api_store.cc', diff --git a/src/libstore-test-support/meson.build b/src/libstore-test-support/meson.build index 98ec9882e..f8308e7bb 100644 --- a/src/libstore-test-support/meson.build +++ b/src/libstore-test-support/meson.build @@ -25,8 +25,6 @@ deps_public_maybe_subproject = [ ] subdir('build-utils-meson/subprojects') -subdir('build-utils-meson/threads') - rapidcheck = dependency('rapidcheck') deps_public += rapidcheck @@ -38,7 +36,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') sources = files( 'tests/derived-path.cc', diff --git a/src/libstore-tests/meson.build b/src/libstore-tests/meson.build index f4f67d73a..fc9152f2f 100644 --- a/src/libstore-tests/meson.build +++ b/src/libstore-tests/meson.build @@ -25,8 +25,6 @@ deps_public_maybe_subproject = [ ] subdir('build-utils-meson/subprojects') -subdir('build-utils-meson/threads') - subdir('build-utils-meson/export-all-symbols') subdir('build-utils-meson/windows-version') @@ -52,7 +50,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') sources = files( 'common-protocol.cc', diff --git a/src/libstore/meson.build b/src/libstore/meson.build index 101879e90..f836b8d4f 100644 --- a/src/libstore/meson.build +++ b/src/libstore/meson.build @@ -82,7 +82,6 @@ if host_machine.system() == 'windows' endif subdir('build-utils-meson/libatomic') -subdir('build-utils-meson/threads') boost = dependency( 'boost', @@ -180,7 +179,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') sources = files( 'binary-cache-store.cc', diff --git a/src/libutil-c/meson.build b/src/libutil-c/meson.build index 3d5a0b9c2..d44453676 100644 --- a/src/libutil-c/meson.build +++ b/src/libutil-c/meson.build @@ -25,8 +25,6 @@ deps_public_maybe_subproject = [ ] subdir('build-utils-meson/subprojects') -subdir('build-utils-meson/threads') - # TODO rename, because it will conflict with downstream projects configdata.set_quoted('PACKAGE_VERSION', meson.project_version()) @@ -47,7 +45,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') sources = files( 'nix_api_util.cc', diff --git a/src/libutil-test-support/meson.build b/src/libutil-test-support/meson.build index c5e1ba80b..fa1df7320 100644 --- a/src/libutil-test-support/meson.build +++ b/src/libutil-test-support/meson.build @@ -23,8 +23,6 @@ deps_public_maybe_subproject = [ ] subdir('build-utils-meson/subprojects') -subdir('build-utils-meson/threads') - rapidcheck = dependency('rapidcheck') deps_public += rapidcheck @@ -35,7 +33,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') sources = files( 'tests/hash.cc', diff --git a/src/libutil-tests/meson.build b/src/libutil-tests/meson.build index 5c3b5e5a3..f59350774 100644 --- a/src/libutil-tests/meson.build +++ b/src/libutil-tests/meson.build @@ -25,8 +25,6 @@ deps_public_maybe_subproject = [ ] subdir('build-utils-meson/subprojects') -subdir('build-utils-meson/threads') - subdir('build-utils-meson/export-all-symbols') subdir('build-utils-meson/windows-version') @@ -44,7 +42,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') sources = files( 'args.cc', diff --git a/src/libutil/meson.build b/src/libutil/meson.build index a6dc86394..11b4ea592 100644 --- a/src/libutil/meson.build +++ b/src/libutil/meson.build @@ -54,7 +54,6 @@ endforeach configdata.set('HAVE_DECL_AT_SYMLINK_NOFOLLOW', cxx.has_header_symbol('fcntl.h', 'AT_SYMLINK_NOFOLLOW').to_int()) subdir('build-utils-meson/libatomic') -subdir('build-utils-meson/threads') if host_machine.system() == 'windows' socket = cxx.find_library('ws2_32') @@ -121,7 +120,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') sources = files( 'archive.cc', diff --git a/src/nix/meson.build b/src/nix/meson.build index 60ee48035..5c70c8216 100644 --- a/src/nix/meson.build +++ b/src/nix/meson.build @@ -32,8 +32,6 @@ deps_public_maybe_subproject = [ ] subdir('build-utils-meson/subprojects') -subdir('build-utils-meson/threads') - subdir('build-utils-meson/export-all-symbols') subdir('build-utils-meson/windows-version') @@ -65,7 +63,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') subdir('build-utils-meson/generate-header') nix_sources = [config_h] + files( From ed120a61abc35b2a0a782dfce3935013cc108d50 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 21 Nov 2024 19:16:27 +0100 Subject: [PATCH 479/718] Use -O3 again This was lost in the switch to the new build system. -O3 provides around a 10% performance gain compared to -O2, see e.g. nix-env.qaAggressive.time in https://hydra.nixos.org/job/nix/master/metrics.nixpkgs#tabs-charts. --- build-utils-meson/common/meson.build | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build-utils-meson/common/meson.build b/build-utils-meson/common/meson.build index 67b6658f5..f0322183e 100644 --- a/build-utils-meson/common/meson.build +++ b/build-utils-meson/common/meson.build @@ -16,3 +16,7 @@ add_project_arguments( '-Wno-deprecated-declarations', language : 'cpp', ) + +if get_option('buildtype') not in ['debug'] + add_project_arguments('-O3', language : 'cpp') +endif From ba074465ba249da4df0752d0dc53529d0ab1a60d Mon Sep 17 00:00:00 2001 From: Vladimir Panteleev Date: Thu, 21 Nov 2024 20:08:13 +0000 Subject: [PATCH 480/718] doc: Clarify that nix-shell still uses shell from host environment (#8809) * doc: Clarify that nix-shell still uses shell from host environment * doc: Fix NIX_BUILD_SHELL description * doc: Add anchor and link to NIX_BUILD_SHELL * doc: Add example of default shell trickiness Co-authored-by: Valentin Gagarin --- doc/manual/source/command-ref/nix-shell.md | 31 ++++++++++++++++++---- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/doc/manual/source/command-ref/nix-shell.md b/doc/manual/source/command-ref/nix-shell.md index 69a711bd5..e95db9bea 100644 --- a/doc/manual/source/command-ref/nix-shell.md +++ b/doc/manual/source/command-ref/nix-shell.md @@ -88,7 +88,9 @@ All options not listed here are passed to `nix-store cleared before the interactive shell is started, so you get an environment that more closely corresponds to the “real” Nix build. A few variables, in particular `HOME`, `USER` and `DISPLAY`, are - retained. + retained. Note that the shell used to run commands is obtained from + [`NIX_BUILD_SHELL`](#env-NIX_BUILD_SHELL) / `` from + `NIX_PATH`, and therefore not affected by `--pure`. - `--packages` / `-p` *packages*… @@ -112,11 +114,30 @@ All options not listed here are passed to `nix-store # Environment variables -- `NIX_BUILD_SHELL` +- [`NIX_BUILD_SHELL`](#env-NIX_BUILD_SHELL) - Shell used to start the interactive environment. Defaults to the - `bash` found in ``, falling back to the `bash` found in - `PATH` if not found. + Shell used to start the interactive environment. + Defaults to the `bash` from `bashInteractive` found in ``, falling back to the `bash` found in `PATH` if not found. + + > **Note** + > + > The shell obtained using this method may not necessarily be the same as any shells requested in *path*. + + + + > **Example + > + > Despite `--pure`, this invocation will not result in a fully reproducible shell environment: + > + > ```nix + > #!/usr/bin/env -S nix-shell --pure + > let + > pkgs = import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/854fdc68881791812eddd33b2fed94b954979a8e.tar.gz") {}; + > in + > pkgs.mkShell { + > buildInputs = pkgs.bashInteractive; + > } + > ``` {{#include ./env-common.md}} From ebb19cc1cdc2f04c291e2e8e34f434e5defa5bbd Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 22 Nov 2024 09:14:01 +0100 Subject: [PATCH 481/718] Drop std::make_pair MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jörg Thalheim --- src/libflake/flake/flakeref.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libflake/flake/flakeref.cc b/src/libflake/flake/flakeref.cc index ed47ad737..cdcdcf87f 100644 --- a/src/libflake/flake/flakeref.cc +++ b/src/libflake/flake/flakeref.cc @@ -78,7 +78,7 @@ static std::pair fromParsedURL( std::string fragment; std::swap(fragment, parsedURL.fragment); - return std::make_pair(FlakeRef(fetchers::Input::fromURL(fetchSettings, parsedURL, isFlake), dir), fragment); + return {FlakeRef(fetchers::Input::fromURL(fetchSettings, parsedURL, isFlake), dir), fragment}; } std::pair parsePathFlakeRefWithFragment( From 756758d968375c3f346412f8f01c82a9178689fb Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman <145775305+xokdvium@users.noreply.github.com> Date: Fri, 22 Nov 2024 18:05:52 +0300 Subject: [PATCH 482/718] chore: get rid of dead code and unused variables where appropriate Looks like some cruft has been left over from previous refactorings. This removes dead variables, which should not have side effects in their constructors. In cases where the variable initialization has a purpose [[maybe_unused]] is inserted to silence compiler warnings. --- src/libexpr/attr-path.cc | 1 - src/libexpr/primops.cc | 2 -- src/libfetchers/git.cc | 2 -- src/libflake/flake/flakeref.cc | 2 -- src/libstore/build/derivation-goal.cc | 2 +- src/libstore/export-import.cc | 5 ----- src/libstore/unix/build/local-derivation-goal.cc | 2 +- src/libutil-tests/nix_api_util.cc | 1 - src/libutil/serialise.cc | 3 +-- src/libutil/terminal.cc | 2 +- src/nix/search.cc | 1 - src/nix/sigs.cc | 1 - 12 files changed, 4 insertions(+), 20 deletions(-) diff --git a/src/libexpr/attr-path.cc b/src/libexpr/attr-path.cc index 2f67260c5..822ec7620 100644 --- a/src/libexpr/attr-path.cc +++ b/src/libexpr/attr-path.cc @@ -129,7 +129,6 @@ std::pair findPackageFilename(EvalState & state, Value & v try { auto colon = fn.rfind(':'); if (colon == std::string::npos) fail(); - std::string filename(fn, 0, colon); auto lineno = std::stoi(std::string(fn, colon + 1, std::string::npos)); return {SourcePath{path.accessor, CanonPath(fn.substr(0, colon))}, lineno}; } catch (std::invalid_argument & e) { diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 53bfce6c5..5d2f75373 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -66,14 +66,12 @@ StringMap EvalState::realiseContext(const NixStringContext & context, StorePathS ensureValid(b.drvPath->getBaseStorePath()); }, [&](const NixStringContextElem::Opaque & o) { - auto ctxS = store->printStorePath(o.path); ensureValid(o.path); if (maybePathsOut) maybePathsOut->emplace(o.path); }, [&](const NixStringContextElem::DrvDeep & d) { /* Treat same as Opaque */ - auto ctxS = store->printStorePath(d.drvPath); ensureValid(d.drvPath); if (maybePathsOut) maybePathsOut->emplace(d.drvPath); diff --git a/src/libfetchers/git.cc b/src/libfetchers/git.cc index 99d91919e..a6883a2d3 100644 --- a/src/libfetchers/git.cc +++ b/src/libfetchers/git.cc @@ -514,8 +514,6 @@ struct GitInputScheme : InputScheme auto origRev = input.getRev(); - std::string name = input.getName(); - auto originalRef = input.getRef(); auto ref = originalRef ? *originalRef : getDefaultRef(repoInfo); input.attrs.insert_or_assign("ref", ref); diff --git a/src/libflake/flake/flakeref.cc b/src/libflake/flake/flakeref.cc index cdcdcf87f..9616fe0ea 100644 --- a/src/libflake/flake/flakeref.cc +++ b/src/libflake/flake/flakeref.cc @@ -257,8 +257,6 @@ std::pair parseFlakeRefWithFragment( { using namespace fetchers; - std::smatch match; - if (auto res = parseFlakeIdRef(fetchSettings, url, isFlake)) { return *res; } else if (auto res = parseURLFlakeRef(fetchSettings, url, baseDir, isFlake)) { diff --git a/src/libstore/build/derivation-goal.cc b/src/libstore/build/derivation-goal.cc index 794be1568..bf1a25db1 100644 --- a/src/libstore/build/derivation-goal.cc +++ b/src/libstore/build/derivation-goal.cc @@ -1229,7 +1229,7 @@ HookReply DerivationGoal::tryBuildHook() hook->toHook.writeSide.close(); /* Create the log file and pipe. */ - Path logFile = openLogFile(); + [[maybe_unused]] Path logFile = openLogFile(); std::set fds; fds.insert(hook->fromHook.readSide.get()); diff --git a/src/libstore/export-import.cc b/src/libstore/export-import.cc index cb36c0c1b..1c62cdfad 100644 --- a/src/libstore/export-import.cc +++ b/src/libstore/export-import.cc @@ -13,14 +13,9 @@ void Store::exportPaths(const StorePathSet & paths, Sink & sink) auto sorted = topoSortPaths(paths); std::reverse(sorted.begin(), sorted.end()); - std::string doneLabel("paths exported"); - //logger->incExpected(doneLabel, sorted.size()); - for (auto & path : sorted) { - //Activity act(*logger, lvlInfo, "exporting path '%s'", path); sink << 1; exportPath(path, sink); - //logger->incProgress(doneLabel); } sink << 0; diff --git a/src/libstore/unix/build/local-derivation-goal.cc b/src/libstore/unix/build/local-derivation-goal.cc index dcfaadeef..06a2f85be 100644 --- a/src/libstore/unix/build/local-derivation-goal.cc +++ b/src/libstore/unix/build/local-derivation-goal.cc @@ -883,7 +883,7 @@ void LocalDerivationGoal::startBuilder() printMsg(lvlVomit, "setting builder env variable '%1%'='%2%'", i.first, i.second); /* Create the log file. */ - Path logFile = openLogFile(); + [[maybe_unused]] Path logFile = openLogFile(); /* Create a pseudoterminal to get the output of the builder. */ builderOut = posix_openpt(O_RDWR | O_NOCTTY); diff --git a/src/libutil-tests/nix_api_util.cc b/src/libutil-tests/nix_api_util.cc index b36f71042..7b77bd87f 100644 --- a/src/libutil-tests/nix_api_util.cc +++ b/src/libutil-tests/nix_api_util.cc @@ -136,7 +136,6 @@ TEST_F(nix_api_util_context, nix_err_name) // no error EXPECT_THROW(nix_err_name(NULL, ctx, OBSERVE_STRING(err_name)), nix::Error); - std::string err_msg_ref; try { throw nix::Error("testing error"); } catch (...) { diff --git a/src/libutil/serialise.cc b/src/libutil/serialise.cc index 168d2ed32..381e7ae38 100644 --- a/src/libutil/serialise.cc +++ b/src/libutil/serialise.cc @@ -90,7 +90,6 @@ void Source::operator () (std::string_view data) void Source::drainInto(Sink & sink) { - std::string s; std::array buf; while (true) { size_t n; @@ -427,7 +426,7 @@ Error readError(Source & source) auto type = readString(source); assert(type == "Error"); auto level = (Verbosity) readInt(source); - auto name = readString(source); // removed + [[maybe_unused]] auto name = readString(source); // removed auto msg = readString(source); ErrorInfo info { .level = level, diff --git a/src/libutil/terminal.cc b/src/libutil/terminal.cc index db7a6fcd1..4c127ddb0 100644 --- a/src/libutil/terminal.cc +++ b/src/libutil/terminal.cc @@ -26,7 +26,7 @@ bool isTTY() std::string filterANSIEscapes(std::string_view s, bool filterAll, unsigned int width) { - std::string t, e; + std::string t; size_t w = 0; auto i = s.begin(); diff --git a/src/nix/search.cc b/src/nix/search.cc index c8d0b9e96..30b96c500 100644 --- a/src/nix/search.cc +++ b/src/nix/search.cc @@ -161,7 +161,6 @@ struct CmdSearch : InstallableValueCommand, MixJSON {"description", description}, }; } else { - auto name2 = hiliteMatches(name.name, nameMatches, ANSI_GREEN, "\e[0;2m"); if (results > 1) logger->cout(""); logger->cout( "* %s%s", diff --git a/src/nix/sigs.cc b/src/nix/sigs.cc index 2afe4b267..134d4f34a 100644 --- a/src/nix/sigs.cc +++ b/src/nix/sigs.cc @@ -41,7 +41,6 @@ struct CmdCopySigs : StorePathsCommand ThreadPool pool; - std::string doneLabel = "done"; std::atomic added{0}; //logger->setExpected(doneLabel, storePaths.size()); From 00b99b8bc0aa7f5f0a1a04b9704c2120e5eca6db Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 22 Nov 2024 16:23:34 +0100 Subject: [PATCH 483/718] Remove FIXME --- src/libflake/flake/flake.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libflake/flake/flake.cc b/src/libflake/flake/flake.cc index e49333f25..8e381c0d2 100644 --- a/src/libflake/flake/flake.cc +++ b/src/libflake/flake/flake.cc @@ -470,7 +470,7 @@ LockedFlake lockFlake( Override { .input = inputOverride, .sourcePath = sourcePath, - .parentInputPath = inputPathPrefix // FIXME: should this be inputPath? + .parentInputPath = inputPathPrefix }); } } From 09ddc34b62bf762cbe7e0a9adce4bdea9ff7fc6a Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman <145775305+xokdvium@users.noreply.github.com> Date: Sun, 24 Nov 2024 00:01:11 +0300 Subject: [PATCH 484/718] refactor(libfetchers/registry): use standard remove_if + erase Get rid of this fixme. This does not appear to be used anywhere in the nix codebase itself. Not sure why the comment mentioned C++20 erase member function with predicate, but iterator-based algorithms are also fine. --- src/libfetchers/registry.cc | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/libfetchers/registry.cc b/src/libfetchers/registry.cc index 7f7a09053..c761028ab 100644 --- a/src/libfetchers/registry.cc +++ b/src/libfetchers/registry.cc @@ -94,12 +94,9 @@ void Registry::add( void Registry::remove(const Input & input) { - // FIXME: use C++20 std::erase. - for (auto i = entries.begin(); i != entries.end(); ) - if (i->from == input) - i = entries.erase(i); - else - ++i; + entries.erase( + std::remove_if(entries.begin(), entries.end(), [&](const Entry & entry) { return entry.from == input; }), + entries.end()); } static Path getSystemRegistryPath() From fbffd47fb715396f47be21ae0ed1a7f484852b4b Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman <145775305+xokdvium@users.noreply.github.com> Date: Sun, 24 Nov 2024 00:35:47 +0300 Subject: [PATCH 485/718] build(lib{expr,store,util}-test-support): depend on -c libraries Since lib{expr,store,util}-test-support subprojects define nix_api_* helpers for testing nix c bindings, they need to publicly depend on -c counterparts. This makes their headers self-sufficient and does not rely on the -tests to add necessary dependencies. --- src/libexpr-test-support/meson.build | 1 + src/libexpr-test-support/package.nix | 2 ++ src/libstore-test-support/meson.build | 1 + src/libstore-test-support/package.nix | 2 ++ src/libutil-test-support/meson.build | 1 + src/libutil-test-support/package.nix | 2 ++ 6 files changed, 9 insertions(+) diff --git a/src/libexpr-test-support/meson.build b/src/libexpr-test-support/meson.build index bdfd435a8..33d9e17a6 100644 --- a/src/libexpr-test-support/meson.build +++ b/src/libexpr-test-support/meson.build @@ -24,6 +24,7 @@ deps_public_maybe_subproject = [ dependency('nix-store'), dependency('nix-store-test-support'), dependency('nix-expr'), + dependency('nix-expr-c'), ] subdir('build-utils-meson/subprojects') diff --git a/src/libexpr-test-support/package.nix b/src/libexpr-test-support/package.nix index bcf6118e0..7e92d145f 100644 --- a/src/libexpr-test-support/package.nix +++ b/src/libexpr-test-support/package.nix @@ -4,6 +4,7 @@ , nix-store-test-support , nix-expr +, nix-expr-c , rapidcheck @@ -35,6 +36,7 @@ mkMesonLibrary (finalAttrs: { propagatedBuildInputs = [ nix-store-test-support nix-expr + nix-expr-c rapidcheck ]; diff --git a/src/libstore-test-support/meson.build b/src/libstore-test-support/meson.build index f8308e7bb..1f230914f 100644 --- a/src/libstore-test-support/meson.build +++ b/src/libstore-test-support/meson.build @@ -22,6 +22,7 @@ deps_public_maybe_subproject = [ dependency('nix-util'), dependency('nix-util-test-support'), dependency('nix-store'), + dependency('nix-store-c'), ] subdir('build-utils-meson/subprojects') diff --git a/src/libstore-test-support/package.nix b/src/libstore-test-support/package.nix index 48f8b5e6b..2543049fe 100644 --- a/src/libstore-test-support/package.nix +++ b/src/libstore-test-support/package.nix @@ -4,6 +4,7 @@ , nix-util-test-support , nix-store +, nix-store-c , rapidcheck @@ -35,6 +36,7 @@ mkMesonLibrary (finalAttrs: { propagatedBuildInputs = [ nix-util-test-support nix-store + nix-store-c rapidcheck ]; diff --git a/src/libutil-test-support/meson.build b/src/libutil-test-support/meson.build index fa1df7320..4afed01ca 100644 --- a/src/libutil-test-support/meson.build +++ b/src/libutil-test-support/meson.build @@ -20,6 +20,7 @@ deps_private_maybe_subproject = [ ] deps_public_maybe_subproject = [ dependency('nix-util'), + dependency('nix-util-c'), ] subdir('build-utils-meson/subprojects') diff --git a/src/libutil-test-support/package.nix b/src/libutil-test-support/package.nix index 2525e1602..c403e762c 100644 --- a/src/libutil-test-support/package.nix +++ b/src/libutil-test-support/package.nix @@ -3,6 +3,7 @@ , mkMesonLibrary , nix-util +, nix-util-c , rapidcheck @@ -33,6 +34,7 @@ mkMesonLibrary (finalAttrs: { propagatedBuildInputs = [ nix-util + nix-util-c rapidcheck ]; From 4145d18435f5e7073f0c99f813d45dd9058430dd Mon Sep 17 00:00:00 2001 From: Anatoli Babenia Date: Sat, 23 Nov 2024 08:36:51 +0300 Subject: [PATCH 486/718] Rename install-nix-from-closure.sh into install-nix-from-tarball.sh Because it is only used as /install script from tarball. --- maintainers/flake-module.nix | 2 +- scripts/binary-tarball.nix | 2 +- ...{install-nix-from-closure.sh => install-nix-from-tarball.sh} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename scripts/{install-nix-from-closure.sh => install-nix-from-tarball.sh} (100%) diff --git a/maintainers/flake-module.nix b/maintainers/flake-module.nix index fdb031302..ba6cd2816 100644 --- a/maintainers/flake-module.nix +++ b/maintainers/flake-module.nix @@ -496,7 +496,7 @@ ''^scripts/create-darwin-volume\.sh$'' ''^scripts/install-darwin-multi-user\.sh$'' ''^scripts/install-multi-user\.sh$'' - ''^scripts/install-nix-from-closure\.sh$'' + ''^scripts/install-nix-from-tarball\.sh$'' ''^scripts/install-systemd-multi-user\.sh$'' ''^src/nix/get-env\.sh$'' ''^tests/functional/ca/build-dry\.sh$'' diff --git a/scripts/binary-tarball.nix b/scripts/binary-tarball.nix index 104189b0c..671c8e96e 100644 --- a/scripts/binary-tarball.nix +++ b/scripts/binary-tarball.nix @@ -23,7 +23,7 @@ in runCommand "nix-binary-tarball-${version}" env '' cp ${installerClosureInfo}/registration $TMPDIR/reginfo cp ${./create-darwin-volume.sh} $TMPDIR/create-darwin-volume.sh - substitute ${./install-nix-from-closure.sh} $TMPDIR/install \ + substitute ${./install-nix-from-tarball.sh} $TMPDIR/install \ --subst-var-by nix ${nix} \ --subst-var-by cacert ${cacert} diff --git a/scripts/install-nix-from-closure.sh b/scripts/install-nix-from-tarball.sh similarity index 100% rename from scripts/install-nix-from-closure.sh rename to scripts/install-nix-from-tarball.sh From 82a23d9b6b96bf08e7c28008fcc346c0bdb671be Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Fri, 22 Nov 2024 16:24:20 +0100 Subject: [PATCH 487/718] libexpr-c: Add nix_eval_state_builder --- src/libexpr-c/nix_api_expr.cc | 79 ++++++++++++++++++++++++--- src/libexpr-c/nix_api_expr.h | 65 +++++++++++++++++++++- src/libexpr-c/nix_api_expr_internal.h | 11 ++++ src/libexpr-tests/nix_api_expr.cc | 37 +++++++++++++ 4 files changed, 183 insertions(+), 9 deletions(-) diff --git a/src/libexpr-c/nix_api_expr.cc b/src/libexpr-c/nix_api_expr.cc index 6144a7986..27a70afb6 100644 --- a/src/libexpr-c/nix_api_expr.cc +++ b/src/libexpr-c/nix_api_expr.cc @@ -6,6 +6,7 @@ #include "eval-gc.hh" #include "globals.hh" #include "eval-settings.hh" +#include "ref.hh" #include "nix_api_expr.h" #include "nix_api_expr_internal.h" @@ -93,7 +94,46 @@ nix_err nix_value_force_deep(nix_c_context * context, EvalState * state, nix_val NIXC_CATCH_ERRS } -EvalState * nix_state_create(nix_c_context * context, const char ** lookupPath_c, Store * store) +nix_eval_state_builder * nix_eval_state_builder_new(nix_c_context * context, Store * store) +{ + if (context) + context->last_err_code = NIX_OK; + try { + // Allocate ahead of time, because .settings needs self-reference + void * p = ::operator new( + sizeof(nix_eval_state_builder), + static_cast(alignof(nix_eval_state_builder))); + auto * p2 = static_cast(p); + new (p) nix_eval_state_builder{ + .store = nix::ref(store->ptr), + .settings = nix::EvalSettings{/* &bool */ p2->readOnlyMode}, + .fetchSettings = nix::fetchers::Settings{}, + .readOnlyMode = true, + }; + return p2; + } + NIXC_CATCH_ERRS_NULL +} + +void nix_eval_state_builder_free(nix_eval_state_builder * builder) +{ + delete builder; +} + +nix_err nix_eval_state_builder_load(nix_c_context * context, nix_eval_state_builder * builder) +{ + if (context) + context->last_err_code = NIX_OK; + try { + // TODO: load in one go? + builder->settings.readOnlyMode = nix::settings.readOnlyMode; + loadConfFile(builder->settings); + loadConfFile(builder->fetchSettings); + } + NIXC_CATCH_ERRS +} + +nix_err nix_eval_state_builder_set_lookup_path(nix_c_context * context, nix_eval_state_builder * builder, const char ** lookupPath_c) { if (context) context->last_err_code = NIX_OK; @@ -102,28 +142,51 @@ EvalState * nix_state_create(nix_c_context * context, const char ** lookupPath_c if (lookupPath_c != nullptr) for (size_t i = 0; lookupPath_c[i] != nullptr; i++) lookupPath.push_back(lookupPath_c[i]); + builder->lookupPath = nix::LookupPath::parse(lookupPath); + } + NIXC_CATCH_ERRS +} +EvalState * nix_eval_state_build(nix_c_context * context, nix_eval_state_builder * builder) +{ + if (context) + context->last_err_code = NIX_OK; + try { + // Allocate ahead of time, because .state init needs self-reference void * p = ::operator new( sizeof(EvalState), static_cast(alignof(EvalState))); auto * p2 = static_cast(p); new (p) EvalState { - .fetchSettings = nix::fetchers::Settings{}, - .settings = nix::EvalSettings{ - nix::settings.readOnlyMode, - }, + .fetchSettings = std::move(builder->fetchSettings), + .settings = std::move(builder->settings), .state = nix::EvalState( - nix::LookupPath::parse(lookupPath), - store->ptr, + builder->lookupPath, + builder->store, p2->fetchSettings, p2->settings), }; - loadConfFile(p2->settings); return p2; } NIXC_CATCH_ERRS_NULL } +EvalState * nix_state_create(nix_c_context * context, const char ** lookupPath_c, Store * store) +{ + auto builder = nix_eval_state_builder_new(context, store); + if (builder == nullptr) + return nullptr; + + if (nix_eval_state_builder_load(context, builder) != NIX_OK) + return nullptr; + + if (nix_eval_state_builder_set_lookup_path(context, builder, lookupPath_c) + != NIX_OK) + return nullptr; + + return nix_eval_state_build(context, builder); +} + void nix_state_free(EvalState * state) { delete state; diff --git a/src/libexpr-c/nix_api_expr.h b/src/libexpr-c/nix_api_expr.h index e680f5ff1..f8d181452 100644 --- a/src/libexpr-c/nix_api_expr.h +++ b/src/libexpr-c/nix_api_expr.h @@ -30,6 +30,11 @@ extern "C" { // cffi start // Type definitions +/** + * @brief Builder for EvalState + */ +typedef struct nix_eval_state_builder nix_eval_state_builder; + /** * @brief Represents a state of the Nix language evaluator. * @@ -174,12 +179,70 @@ nix_err nix_value_force(nix_c_context * context, EvalState * state, nix_value * nix_err nix_value_force_deep(nix_c_context * context, EvalState * state, nix_value * value); /** - * @brief Create a new Nix language evaluator state. + * @brief Create a new nix_eval_state_builder + * + * The settings are initialized to their default value. + * Values can be sourced elsewhere with nix_eval_state_builder_load. + * + * @param[out] context Optional, stores error information + * @param[in] store The Nix store to use. + * @return A new nix_eval_state_builder or NULL on failure. + */ +nix_eval_state_builder * nix_eval_state_builder_new(nix_c_context * context, Store * store); + +/** + * @brief Read settings from the ambient environment + * + * Settings are sourced from environment variables and configuration files, + * as documented in the Nix manual. + * + * @param[out] context Optional, stores error information + * @param[out] builder The builder to modify. + * @return NIX_OK if successful, an error code otherwise. + */ +nix_err nix_eval_state_builder_load(nix_c_context * context, nix_eval_state_builder * builder); + +/** + * @brief Set the lookup path for `<...>` expressions + * + * @param[in] context Optional, stores error information + * @param[in] builder The builder to modify. + * @param[in] lookupPath Null-terminated array of strings corresponding to entries in NIX_PATH. + */ +nix_err nix_eval_state_builder_set_lookup_path( + nix_c_context * context, nix_eval_state_builder * builder, const char ** lookupPath); + +/** + * @brief Create a new Nix language evaluator state + * + * Remember to nix_eval_state_builder_free after building the state. + * + * @param[out] context Optional, stores error information + * @param[in] builder The builder to use and free + * @return A new Nix state or NULL on failure. + * @see nix_eval_state_builder_new, nix_eval_state_builder_free + */ +EvalState * nix_eval_state_build(nix_c_context * context, nix_eval_state_builder * builder); + +/** + * @brief Free a nix_eval_state_builder + * + * Does not fail. + * + * @param[in] builder The builder to free. + */ +void nix_eval_state_builder_free(nix_eval_state_builder * builder); + +/** + * @brief Create a new Nix language evaluator state + * + * For more control, use nix_eval_state_builder * * @param[out] context Optional, stores error information * @param[in] lookupPath Null-terminated array of strings corresponding to entries in NIX_PATH. * @param[in] store The Nix store to use. * @return A new Nix state or NULL on failure. + * @see nix_state_builder_new */ EvalState * nix_state_create(nix_c_context * context, const char ** lookupPath, Store * store); diff --git a/src/libexpr-c/nix_api_expr_internal.h b/src/libexpr-c/nix_api_expr_internal.h index 12f24b6eb..f59664011 100644 --- a/src/libexpr-c/nix_api_expr_internal.h +++ b/src/libexpr-c/nix_api_expr_internal.h @@ -6,6 +6,17 @@ #include "eval-settings.hh" #include "attr-set.hh" #include "nix_api_value.h" +#include "search-path.hh" + +struct nix_eval_state_builder +{ + nix::ref store; + nix::EvalSettings settings; + nix::fetchers::Settings fetchSettings; + nix::LookupPath lookupPath; + // TODO: make an EvalSettings setting own this instead? + bool readOnlyMode; +}; struct EvalState { diff --git a/src/libexpr-tests/nix_api_expr.cc b/src/libexpr-tests/nix_api_expr.cc index b37ac44b3..5ed78d2fc 100644 --- a/src/libexpr-tests/nix_api_expr.cc +++ b/src/libexpr-tests/nix_api_expr.cc @@ -7,12 +7,49 @@ #include "tests/nix_api_expr.hh" #include "tests/string_callback.hh" +#include "file-system.hh" #include #include namespace nixC { +TEST_F(nix_api_store_test, nix_eval_state_lookup_path) +{ + auto tmpDir = nix::createTempDir(); + auto delTmpDir = std::make_unique(tmpDir, true); + auto nixpkgs = tmpDir + "/pkgs"; + auto nixos = tmpDir + "/cfg"; + std::filesystem::create_directories(nixpkgs); + std::filesystem::create_directories(nixos); + + std::string nixpkgsEntry = "nixpkgs=" + nixpkgs; + std::string nixosEntry = "nixos-config=" + nixos; + const char * lookupPath[] = {nixpkgsEntry.c_str(), nixosEntry.c_str(), nullptr}; + + auto builder = nix_eval_state_builder_new(ctx, store); + assert_ctx_ok(); + + ASSERT_EQ(NIX_OK, nix_eval_state_builder_set_lookup_path(ctx, builder, lookupPath)); + assert_ctx_ok(); + + auto state = nix_eval_state_build(ctx, builder); + assert_ctx_ok(); + + nix_eval_state_builder_free(builder); + + Value * value = nix_alloc_value(ctx, state); + nix_expr_eval_from_string(ctx, state, "builtins.seq ", ".", value); + assert_ctx_ok(); + + ASSERT_EQ(nix_get_type(ctx, value), NIX_TYPE_PATH); + assert_ctx_ok(); + + auto pathStr = nix_get_path_string(ctx, value); + assert_ctx_ok(); + ASSERT_EQ(0, strcmp(pathStr, nixpkgs.c_str())); +} + TEST_F(nix_api_expr_test, nix_expr_eval_from_string) { nix_expr_eval_from_string(nullptr, state, "builtins.nixVersion", ".", value); From 1bd75178017102e098e7b9a6aa2ddf858b486b53 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Fri, 22 Nov 2024 16:27:17 +0100 Subject: [PATCH 488/718] Doc nix_get_path_string --- src/libexpr-c/nix_api_value.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libexpr-c/nix_api_value.h b/src/libexpr-c/nix_api_value.h index 8a0813ebe..711b0adbc 100644 --- a/src/libexpr-c/nix_api_value.h +++ b/src/libexpr-c/nix_api_value.h @@ -213,7 +213,7 @@ nix_get_string(nix_c_context * context, const nix_value * value, nix_get_string_ /** @brief Get path as string * @param[out] context Optional, stores error information * @param[in] value Nix value to inspect - * @return string + * @return string, if the type is NIX_TYPE_PATH * @return NULL in case of error. */ const char * nix_get_path_string(nix_c_context * context, const nix_value * value); From f06f611ff3f1e7beee51171b3ab13d4883e187f3 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Fri, 22 Nov 2024 17:26:26 +0100 Subject: [PATCH 489/718] refactor: Extract unsafe_new_with_self --- src/libexpr-c/nix_api_expr.cc | 69 +++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 27 deletions(-) diff --git a/src/libexpr-c/nix_api_expr.cc b/src/libexpr-c/nix_api_expr.cc index 27a70afb6..a024248cd 100644 --- a/src/libexpr-c/nix_api_expr.cc +++ b/src/libexpr-c/nix_api_expr.cc @@ -19,6 +19,29 @@ # include #endif +/** + * @brief Allocate and initialize using self-reference + * + * This allows a brace initializer to reference the object being constructed. + * + * @warning Use with care, as the pointer points to an object that is not fully constructed yet. + * + * @tparam T Type to allocate + * @tparam F A function type for `init`, taking a T* and returning the initializer for T + * @param init Function that takes a T* and returns the initializer for T + * @return Pointer to allocated and initialized object + */ +template +static T * unsafe_new_with_self(F && init) +{ + // Allocate + void * p = ::operator new( + sizeof(T), + static_cast(alignof(T))); + // Initialize with placement new + return new (p) T(init(static_cast(p))); +} + nix_err nix_libexpr_init(nix_c_context * context) { if (context) @@ -99,18 +122,14 @@ nix_eval_state_builder * nix_eval_state_builder_new(nix_c_context * context, Sto if (context) context->last_err_code = NIX_OK; try { - // Allocate ahead of time, because .settings needs self-reference - void * p = ::operator new( - sizeof(nix_eval_state_builder), - static_cast(alignof(nix_eval_state_builder))); - auto * p2 = static_cast(p); - new (p) nix_eval_state_builder{ - .store = nix::ref(store->ptr), - .settings = nix::EvalSettings{/* &bool */ p2->readOnlyMode}, - .fetchSettings = nix::fetchers::Settings{}, - .readOnlyMode = true, - }; - return p2; + return unsafe_new_with_self([&](auto * self) { + return nix_eval_state_builder{ + .store = nix::ref(store->ptr), + .settings = nix::EvalSettings{/* &bool */ self->readOnlyMode}, + .fetchSettings = nix::fetchers::Settings{}, + .readOnlyMode = true, + }; + }); } NIXC_CATCH_ERRS_NULL } @@ -152,21 +171,17 @@ EvalState * nix_eval_state_build(nix_c_context * context, nix_eval_state_builder if (context) context->last_err_code = NIX_OK; try { - // Allocate ahead of time, because .state init needs self-reference - void * p = ::operator new( - sizeof(EvalState), - static_cast(alignof(EvalState))); - auto * p2 = static_cast(p); - new (p) EvalState { - .fetchSettings = std::move(builder->fetchSettings), - .settings = std::move(builder->settings), - .state = nix::EvalState( - builder->lookupPath, - builder->store, - p2->fetchSettings, - p2->settings), - }; - return p2; + return unsafe_new_with_self([&](auto * self) { + return EvalState{ + .fetchSettings = std::move(builder->fetchSettings), + .settings = std::move(builder->settings), + .state = nix::EvalState( + builder->lookupPath, + builder->store, + self->fetchSettings, + self->settings), + }; + }); } NIXC_CATCH_ERRS_NULL } From 4eecf3c20ab454b4427363a276d757298f9220dc Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Fri, 22 Nov 2024 16:18:55 +0100 Subject: [PATCH 490/718] Add nix-flake-c, nix_flake_init_global, nix_flake_settings_new --- meson.build | 1 + packaging/components.nix | 1 + packaging/everything.nix | 4 + src/external-api-docs/doxygen.cfg.in | 1 + src/external-api-docs/package.nix | 1 + src/libflake-c/.version | 1 + src/libflake-c/build-utils-meson | 1 + src/libflake-c/meson.build | 93 ++++++++++++++++++++++++ src/libflake-c/nix_api_flake.cc | 32 ++++++++ src/libflake-c/nix_api_flake.h | 46 ++++++++++++ src/libflake-c/nix_api_flake_internal.hh | 9 +++ src/libflake-c/package.nix | 60 +++++++++++++++ src/libflake-tests/meson.build | 3 + src/libflake-tests/nix_api_flake.cc | 51 +++++++++++++ src/libflake-tests/package.nix | 3 + 15 files changed, 307 insertions(+) create mode 120000 src/libflake-c/.version create mode 120000 src/libflake-c/build-utils-meson create mode 100644 src/libflake-c/meson.build create mode 100644 src/libflake-c/nix_api_flake.cc create mode 100644 src/libflake-c/nix_api_flake.h create mode 100644 src/libflake-c/nix_api_flake_internal.hh create mode 100644 src/libflake-c/package.nix create mode 100644 src/libflake-tests/nix_api_flake.cc diff --git a/meson.build b/meson.build index 8985b631e..49adf9832 100644 --- a/meson.build +++ b/meson.build @@ -34,6 +34,7 @@ endif subproject('libutil-c') subproject('libstore-c') subproject('libexpr-c') +subproject('libflake-c') subproject('libmain-c') # Language Bindings diff --git a/packaging/components.nix b/packaging/components.nix index c29e04ae9..e1f661be8 100644 --- a/packaging/components.nix +++ b/packaging/components.nix @@ -44,6 +44,7 @@ in nix-expr-tests = callPackage ../src/libexpr-tests/package.nix { }; nix-flake = callPackage ../src/libflake/package.nix { }; + nix-flake-c = callPackage ../src/libflake-c/package.nix { }; nix-flake-tests = callPackage ../src/libflake-tests/package.nix { }; nix-main = callPackage ../src/libmain/package.nix { }; diff --git a/packaging/everything.nix b/packaging/everything.nix index b09b9d2a9..0b04d2c6d 100644 --- a/packaging/everything.nix +++ b/packaging/everything.nix @@ -19,6 +19,7 @@ nix-expr-tests, nix-flake, + nix-flake-c, nix-flake-tests, nix-main, @@ -53,6 +54,7 @@ let nix-expr-c nix-fetchers nix-flake + nix-flake-c nix-main nix-main-c nix-store @@ -86,6 +88,7 @@ let "nix-expr-c" "nix-fetchers" "nix-flake" + "nix-flake-c" "nix-main" "nix-main-c" "nix-store" @@ -169,6 +172,7 @@ in nix-expr nix-expr-c nix-flake + nix-flake-c nix-main nix-main-c ; diff --git a/src/external-api-docs/doxygen.cfg.in b/src/external-api-docs/doxygen.cfg.in index 8e235dae5..3af2f5b81 100644 --- a/src/external-api-docs/doxygen.cfg.in +++ b/src/external-api-docs/doxygen.cfg.in @@ -40,6 +40,7 @@ GENERATE_LATEX = NO INPUT = \ @src@/src/libutil-c \ @src@/src/libexpr-c \ + @src@/src/libflake-c \ @src@/src/libstore-c \ @src@/src/external-api-docs/README.md diff --git a/src/external-api-docs/package.nix b/src/external-api-docs/package.nix index 0c592955a..57c5138cf 100644 --- a/src/external-api-docs/package.nix +++ b/src/external-api-docs/package.nix @@ -30,6 +30,7 @@ mkMesonDerivation (finalAttrs: { # Source is not compiled, but still must be available for Doxygen # to gather comments. (cpp ../libexpr-c) + (cpp ../libflake-c) (cpp ../libstore-c) (cpp ../libutil-c) ]; diff --git a/src/libflake-c/.version b/src/libflake-c/.version new file mode 120000 index 000000000..b7badcd0c --- /dev/null +++ b/src/libflake-c/.version @@ -0,0 +1 @@ +../../.version \ No newline at end of file diff --git a/src/libflake-c/build-utils-meson b/src/libflake-c/build-utils-meson new file mode 120000 index 000000000..91937f183 --- /dev/null +++ b/src/libflake-c/build-utils-meson @@ -0,0 +1 @@ +../../build-utils-meson/ \ No newline at end of file diff --git a/src/libflake-c/meson.build b/src/libflake-c/meson.build new file mode 100644 index 000000000..00d9650e7 --- /dev/null +++ b/src/libflake-c/meson.build @@ -0,0 +1,93 @@ +project('nix-flake-c', 'cpp', + version : files('.version'), + default_options : [ + 'cpp_std=c++2a', + # TODO(Qyriad): increase the warning level + 'warning_level=1', + 'debug=true', + 'optimization=2', + 'errorlogs=true', # Please print logs for tests that fail + ], + meson_version : '>= 1.1', + license : 'LGPL-2.1-or-later', +) + +cxx = meson.get_compiler('cpp') + +subdir('build-utils-meson/deps-lists') + +configdata = configuration_data() + +deps_private_maybe_subproject = [ + dependency('nix-util'), + dependency('nix-store'), + dependency('nix-expr'), + dependency('nix-flake'), +] +deps_public_maybe_subproject = [ + dependency('nix-util-c'), + dependency('nix-store-c'), + dependency('nix-expr-c'), +] +subdir('build-utils-meson/subprojects') + +# TODO rename, because it will conflict with downstream projects +configdata.set_quoted('PACKAGE_VERSION', meson.project_version()) + +config_h = configure_file( + configuration : configdata, + output : 'config-flake.h', +) + +add_project_arguments( + # TODO(Qyriad): Yes this is how the autoconf+Make system did it. + # It would be nice for our headers to be idempotent instead. + + # From C++ libraries, only for internals + '-include', 'config-util.hh', + '-include', 'config-store.hh', + '-include', 'config-expr.hh', + # not generated (yet?) + # '-include', 'config-flake.hh', + + # From C libraries, for our public, installed headers too + '-include', 'config-util.h', + '-include', 'config-store.h', + '-include', 'config-expr.h', + '-include', 'config-flake.h', + language : 'cpp', +) + +subdir('build-utils-meson/common') + +sources = files( + 'nix_api_flake.cc', +) + +include_dirs = [include_directories('.')] + +headers = [config_h] + files( + 'nix_api_flake.h', +) + +# TODO move this header to libexpr, maybe don't use it in tests? +headers += files('nix_api_flake.h') + +subdir('build-utils-meson/export-all-symbols') +subdir('build-utils-meson/windows-version') + +this_library = library( + 'nixflakec', + sources, + dependencies : deps_public + deps_private + deps_other, + include_directories : include_dirs, + link_args: linker_export_flags, + prelink : true, # For C++ static initializers + install : true, +) + +install_headers(headers, subdir : 'nix', preserve_path : true) + +libraries_private = [] + +subdir('build-utils-meson/export') diff --git a/src/libflake-c/nix_api_flake.cc b/src/libflake-c/nix_api_flake.cc new file mode 100644 index 000000000..17cf6572d --- /dev/null +++ b/src/libflake-c/nix_api_flake.cc @@ -0,0 +1,32 @@ +#include "nix_api_flake.h" +#include "nix_api_flake_internal.hh" +#include "nix_api_util_internal.h" + +#include "flake/flake.hh" + +nix_flake_settings * nix_flake_settings_new(nix_c_context * context) +{ + try { + auto settings = nix::make_ref(); + return new nix_flake_settings{settings}; + } + NIXC_CATCH_ERRS_NULL +} + +void nix_flake_settings_free(nix_flake_settings * settings) +{ + delete settings; +} + +nix_err nix_flake_init_global(nix_c_context * context, nix_flake_settings * settings) +{ + static std::shared_ptr registeredSettings; + try { + if (registeredSettings) + throw nix::Error("nix_flake_init_global already initialized"); + + registeredSettings = settings->settings; + nix::flake::initLib(*registeredSettings); + } + NIXC_CATCH_ERRS +} diff --git a/src/libflake-c/nix_api_flake.h b/src/libflake-c/nix_api_flake.h new file mode 100644 index 000000000..80051298d --- /dev/null +++ b/src/libflake-c/nix_api_flake.h @@ -0,0 +1,46 @@ +#ifndef NIX_API_FLAKE_H +#define NIX_API_FLAKE_H +/** @defgroup libflake libflake + * @brief Bindings to the Nix Flakes library + * + * @{ + */ +/** @file + * @brief Main entry for the libflake C bindings + */ + +#include "nix_api_store.h" +#include "nix_api_util.h" +#include "nix_api_expr.h" + +#ifdef __cplusplus +extern "C" { +#endif +// cffi start + +typedef struct nix_flake_settings nix_flake_settings; + +// Function prototypes +/** + * Create a nix_flake_settings initialized with default values. + * @param[out] context Optional, stores error information + * @return A new nix_flake_settings or NULL on failure. + * @see nix_flake_settings_free + */ +nix_flake_settings * nix_flake_settings_new(nix_c_context * context); + +/** + * @brief Release the resources associated with a nix_flake_settings. + */ +void nix_flake_settings_free(nix_flake_settings * settings); + +/** + * @brief Register Flakes support process-wide. + */ +nix_err nix_flake_init_global(nix_c_context * context, nix_flake_settings * settings); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/src/libflake-c/nix_api_flake_internal.hh b/src/libflake-c/nix_api_flake_internal.hh new file mode 100644 index 000000000..4c154a342 --- /dev/null +++ b/src/libflake-c/nix_api_flake_internal.hh @@ -0,0 +1,9 @@ +#pragma once + +#include "ref.hh" +#include "flake/settings.hh" + +struct nix_flake_settings +{ + nix::ref settings; +}; diff --git a/src/libflake-c/package.nix b/src/libflake-c/package.nix new file mode 100644 index 000000000..a70cbf94e --- /dev/null +++ b/src/libflake-c/package.nix @@ -0,0 +1,60 @@ +{ lib +, stdenv +, mkMesonLibrary + +, nix-store-c +, nix-expr-c +, nix-flake + +# Configuration Options + +, version +}: + +let + inherit (lib) fileset; +in + +mkMesonLibrary (finalAttrs: { + pname = "nix-flake-c"; + inherit version; + + workDir = ./.; + fileset = fileset.unions [ + ../../build-utils-meson + ./build-utils-meson + ../../.version + ./.version + ./meson.build + # ./meson.options + (fileset.fileFilter (file: file.hasExt "cc") ./.) + (fileset.fileFilter (file: file.hasExt "hh") ./.) + (fileset.fileFilter (file: file.hasExt "h") ./.) + ]; + + propagatedBuildInputs = [ + nix-expr-c + nix-store-c + nix-flake + ]; + + preConfigure = + # "Inline" .version so it's not a symlink, and includes the suffix. + # Do the meson utils, without modification. + '' + chmod u+w ./.version + echo ${version} > ../../.version + ''; + + mesonFlags = [ + ]; + + env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) { + LDFLAGS = "-fuse-ld=gold"; + }; + + meta = { + platforms = lib.platforms.unix ++ lib.platforms.windows; + }; + +}) diff --git a/src/libflake-tests/meson.build b/src/libflake-tests/meson.build index c0a9b8847..c494c414e 100644 --- a/src/libflake-tests/meson.build +++ b/src/libflake-tests/meson.build @@ -19,6 +19,7 @@ subdir('build-utils-meson/deps-lists') deps_private_maybe_subproject = [ dependency('nix-expr-test-support'), dependency('nix-flake'), + dependency('nix-flake-c'), ] deps_public_maybe_subproject = [ ] @@ -46,6 +47,7 @@ subdir('build-utils-meson/common') sources = files( 'flakeref.cc', + 'nix_api_flake.cc', 'url-name.cc', ) @@ -68,6 +70,7 @@ test( this_exe, env : { '_NIX_TEST_UNIT_DATA': meson.current_source_dir() / 'data', + 'NIX_CONFIG': 'extra-experimental-features = flakes', }, protocol : 'gtest', ) diff --git a/src/libflake-tests/nix_api_flake.cc b/src/libflake-tests/nix_api_flake.cc new file mode 100644 index 000000000..21109d181 --- /dev/null +++ b/src/libflake-tests/nix_api_flake.cc @@ -0,0 +1,51 @@ +#include "nix_api_store.h" +#include "nix_api_store_internal.h" +#include "nix_api_util.h" +#include "nix_api_util_internal.h" +#include "nix_api_expr.h" +#include "nix_api_value.h" +#include "nix_api_flake.h" + +#include "tests/nix_api_expr.hh" +#include "tests/string_callback.hh" + +#include +#include + +namespace nixC { + +TEST_F(nix_api_store_test, nix_api_init_global_getFlake_exists) +{ + nix_libstore_init(ctx); + assert_ctx_ok(); + nix_libexpr_init(ctx); + assert_ctx_ok(); + + auto settings = nix_flake_settings_new(ctx); + assert_ctx_ok(); + ASSERT_NE(nullptr, settings); + + nix_flake_init_global(ctx, settings); + assert_ctx_ok(); + + nix_eval_state_builder * builder = nix_eval_state_builder_new(ctx, store); + ASSERT_NE(nullptr, builder); + assert_ctx_ok(); + + auto state = nix_eval_state_build(ctx, builder); + assert_ctx_ok(); + ASSERT_NE(nullptr, state); + + nix_eval_state_builder_free(builder); + + auto value = nix_alloc_value(ctx, state); + assert_ctx_ok(); + ASSERT_NE(nullptr, value); + + nix_err err = nix_expr_eval_from_string(ctx, state, "builtins.getFlake", ".", value); + assert_ctx_ok(); + ASSERT_EQ(NIX_OK, err); + ASSERT_EQ(NIX_TYPE_FUNCTION, nix_get_type(ctx, value)); +} + +} // namespace nixC diff --git a/src/libflake-tests/package.nix b/src/libflake-tests/package.nix index 67e716979..b3a8ac466 100644 --- a/src/libflake-tests/package.nix +++ b/src/libflake-tests/package.nix @@ -4,6 +4,7 @@ , mkMesonExecutable , nix-flake +, nix-flake-c , nix-expr-test-support , rapidcheck @@ -38,6 +39,7 @@ mkMesonExecutable (finalAttrs: { buildInputs = [ nix-flake + nix-flake-c nix-expr-test-support rapidcheck gtest @@ -67,6 +69,7 @@ mkMesonExecutable (finalAttrs: { mkdir -p "$HOME" '' + '' export _NIX_TEST_UNIT_DATA=${resolvePath ./data} + export NIX_CONFIG="extra-experimental-features = flakes" ${stdenv.hostPlatform.emulator buildPackages} ${lib.getExe finalAttrs.finalPackage} touch $out ''); From d004c524b84651c2eebb5bbb55f6a3a8324437e9 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Sun, 24 Nov 2024 13:52:40 +0100 Subject: [PATCH 491/718] test: Change FAIL to throw [FAIL()] is a macro with `return`, making it unsuitable for helpers. This uses std::runtime_error, because gtest does not seem to provide an exception type of its own for this purpose. [AssertionException] is for a different use case. [FAIL()]: https://google.github.io/googletest/reference/assertions.html#FAIL [AssertionException]: https://github.com/google/googletest/blob/35d0c365609296fa4730d62057c487e3cfa030ff/docs/reference/testing.md#assertionexception-assertionexception --- src/libutil-test-support/tests/gtest-with-params.hh | 2 +- src/libutil-test-support/tests/nix_api_util.hh | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/libutil-test-support/tests/gtest-with-params.hh b/src/libutil-test-support/tests/gtest-with-params.hh index d72aec4fd..a6e23ad89 100644 --- a/src/libutil-test-support/tests/gtest-with-params.hh +++ b/src/libutil-test-support/tests/gtest-with-params.hh @@ -40,7 +40,7 @@ void checkGTestWith(Testable && testable, MakeTestParams makeTestParams) } else { std::ostringstream ss; printResultMessage(result, ss); - FAIL() << ss.str() << std::endl; + throw std::runtime_error(ss.str()); } } } diff --git a/src/libutil-test-support/tests/nix_api_util.hh b/src/libutil-test-support/tests/nix_api_util.hh index efd200116..006dc497c 100644 --- a/src/libutil-test-support/tests/nix_api_util.hh +++ b/src/libutil-test-support/tests/nix_api_util.hh @@ -26,14 +26,13 @@ protected: inline void assert_ctx_ok() { - if (nix_err_code(ctx) == NIX_OK) { return; } unsigned int n; const char * p = nix_err_msg(nullptr, ctx, &n); std::string msg(p, n); - FAIL() << "nix_err_code(ctx) != NIX_OK, message: " << msg; + throw std::runtime_error(std::string("nix_err_code(ctx) != NIX_OK, message: ") + msg); } inline void assert_ctx_err() @@ -41,7 +40,7 @@ protected: if (nix_err_code(ctx) != NIX_OK) { return; } - FAIL() << "Got NIX_OK, but expected an error!"; + throw std::runtime_error("Got NIX_OK, but expected an error!"); } }; From 6db6b269ed70788314209d35499812c90949057f Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 25 Nov 2024 01:16:02 +0100 Subject: [PATCH 492/718] .github/ci: Set max-jobs to 1, to reduce peak memory usage --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9918875d9..be96bb484 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,9 @@ jobs: - uses: cachix/install-nix-action@v30 with: # The sandbox would otherwise be disabled by default on Darwin - extra_nix_config: "sandbox = true" + extra_nix_config: | + sandbox = true + max-jobs = 1 - run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV - uses: cachix/cachix-action@v15 if: needs.check_secrets.outputs.cachix == 'true' From 6502dc4d6af5baad369578ee0b4d2e1295d199a7 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 25 Nov 2024 12:06:54 +0100 Subject: [PATCH 493/718] ci(Mergify): configuration update Signed-off-by: Robert Hensing --- .mergify.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.mergify.yml b/.mergify.yml index c297d3d5e..86623a138 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -90,3 +90,13 @@ pull_request_rules: - "2.24-maintenance" labels: - merge-queue + + - name: backport patches to 2.25 + conditions: + - label=backport 2.25-maintenance + actions: + backport: + branches: + - "2.25-maintenance" + labels: + - merge-queue From 3fb7481e64fc22313211c6c4ea79ac314457f81b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sun, 24 Nov 2024 11:17:17 +0100 Subject: [PATCH 494/718] source-accessor: fix case where normalization goes beyond root fixes https://github.com/NixOS/nix/issues/11936 --- src/libutil/source-accessor.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/libutil/source-accessor.cc b/src/libutil/source-accessor.cc index e797951c7..d3e304f74 100644 --- a/src/libutil/source-accessor.cc +++ b/src/libutil/source-accessor.cc @@ -84,9 +84,10 @@ CanonPath SourceAccessor::resolveSymlinks( todo.pop_front(); if (c == "" || c == ".") ; - else if (c == "..") - res.pop(); - else { + else if (c == "..") { + if (!res.isRoot()) + res.pop(); + } else { res.push(c); if (mode == SymlinkResolution::Full || !todo.empty()) { if (auto st = maybeLstat(res); st && st->type == SourceAccessor::tSymlink) { From 57fea81f8a6ab3b91b1003d27bd48effad30b25a Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 25 Nov 2024 15:59:43 +0100 Subject: [PATCH 495/718] Work around gcc warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This shuts up a 300-line warning that includes /nix/store/fg7ass3a5m5pgl26qzfdniicbwbgzccy-gcc-13.2.0/include/c++/13.2.0/bits/stl_tree.h:182:25: warning: ‘*(std::_Rb_tree_header*)((char*)& + offsetof(nix::value_type, nix::DerivedPath::.std::variant::.std::__detail::__variant::_Variant_base::.std::__detail::__variant::_Move_assign_base::.std::__detail::__variant::_Copy_assign_base::.std::__detail::__variant::_Move_ctor_base::.std::__detail::__variant::_Copy_ctor_base::.std::__detail::__variant::_Variant_storage::_M_u) + 24).std::_Rb_tree_header::_M_header.std::_Rb_tree_node_base::_M_parent’ may be used uninitialized [-Wmaybe-uninitialized] 182 | if (__x._M_header._M_parent != nullptr) | ~~~~~~~~~~~~~~^~~~~~~~~ --- src/nix/flake.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/nix/flake.cc b/src/nix/flake.cc index ce2faacb0..925b66d3e 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -643,10 +643,11 @@ struct CmdFlakeCheck : FlakeCommand fmt("%s.%s.%s", name, attr_name, state->symbols[attr2.name]), *attr2.value, attr2.pos); if (drvPath && attr_name == settings.thisSystem.get()) { - drvPaths.push_back(DerivedPath::Built { + auto path = DerivedPath::Built { .drvPath = makeConstantStorePathRef(*drvPath), .outputs = OutputsSpec::All { }, - }); + }; + drvPaths.push_back(std::move(path)); } } } From fafaec5ac35d517a6e6217416336346b7353ea05 Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman <145775305+xokdvium@users.noreply.github.com> Date: Sun, 24 Nov 2024 01:05:08 +0300 Subject: [PATCH 496/718] fix(treewide): remove unnecessary copying in range for loops This gets rid of unnecessary copies in range-based-for loops and local variables, when they are used solely as `const &`. Also added a fixme comment about a suspicious move out of const, which might not be intended. --- src/libcmd/installables.cc | 2 +- src/libexpr/primops.cc | 2 +- src/libexpr/primops/context.cc | 2 ++ src/libexpr/primops/fetchClosure.cc | 2 +- src/libstore/build/drv-output-substitution-goal.cc | 2 +- src/libstore/build/substitution-goal.cc | 2 +- src/libstore/keys.cc | 4 ++-- src/libstore/local-overlay-store.cc | 2 +- src/libstore/nar-info.cc | 2 +- src/libstore/s3-binary-cache-store.cc | 2 +- src/libstore/store-api.cc | 4 ++-- src/libutil-tests/hilite.cc | 3 +-- src/libutil/args.cc | 2 +- src/libutil/url.cc | 2 +- src/nix-store/nix-store.cc | 2 +- src/nix/develop.cc | 2 +- src/nix/flake.cc | 2 +- src/nix/hash.cc | 4 ++-- src/nix/run.cc | 4 ++-- src/nix/verify.cc | 2 +- 20 files changed, 25 insertions(+), 24 deletions(-) diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc index f2b27af7c..250cd1413 100644 --- a/src/libcmd/installables.cc +++ b/src/libcmd/installables.cc @@ -858,7 +858,7 @@ std::vector RawInstallablesCommand::getFlakeRefsForCompletion() applyDefaultInstallables(rawInstallables); std::vector res; res.reserve(rawInstallables.size()); - for (auto i : rawInstallables) + for (const auto & i : rawInstallables) res.push_back(parseFlakeRefWithFragment( fetchSettings, expandTilde(i), diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 5d2f75373..7e13e945c 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -4383,7 +4383,7 @@ void prim_split(EvalState & state, const PosIdx pos, Value * * args, Value & v) for (auto i = begin; i != end; ++i) { assert(idx <= 2 * len + 1 - 3); - auto match = *i; + const auto & match = *i; // Add a string for non-matched characters. list[idx++] = mkString(state, match.prefix()); diff --git a/src/libexpr/primops/context.cc b/src/libexpr/primops/context.cc index 02683b173..ede7d97ba 100644 --- a/src/libexpr/primops/context.cc +++ b/src/libexpr/primops/context.cc @@ -132,6 +132,8 @@ static void prim_addDrvOutputDependencies(EvalState & state, const PosIdx pos, V }, [&](const NixStringContextElem::DrvDeep & c) -> NixStringContextElem::DrvDeep { /* Reuse original item because we want this to be idempotent. */ + /* FIXME: Suspicious move out of const. This is actually a copy, so the comment + above does not make much sense. */ return std::move(c); }, }, context.begin()->raw) }), diff --git a/src/libexpr/primops/fetchClosure.cc b/src/libexpr/primops/fetchClosure.cc index fc5bb3145..04b8d0595 100644 --- a/src/libexpr/primops/fetchClosure.cc +++ b/src/libexpr/primops/fetchClosure.cc @@ -40,7 +40,7 @@ static void runFetchClosureWithRewrite(EvalState & state, const PosIdx pos, Stor }); } - auto toPath = *toPathMaybe; + const auto & toPath = *toPathMaybe; // check and return diff --git a/src/libstore/build/drv-output-substitution-goal.cc b/src/libstore/build/drv-output-substitution-goal.cc index dedcad2b1..f069c0d94 100644 --- a/src/libstore/build/drv-output-substitution-goal.cc +++ b/src/libstore/build/drv-output-substitution-goal.cc @@ -32,7 +32,7 @@ Goal::Co DrvOutputSubstitutionGoal::init() bool substituterFailed = false; - for (auto sub : subs) { + for (const auto & sub : subs) { trace("trying next substituter"); /* The callback of the curl download below can outlive `this` (if diff --git a/src/libstore/build/substitution-goal.cc b/src/libstore/build/substitution-goal.cc index 315500719..983c86601 100644 --- a/src/libstore/build/substitution-goal.cc +++ b/src/libstore/build/substitution-goal.cc @@ -57,7 +57,7 @@ Goal::Co PathSubstitutionGoal::init() bool substituterFailed = false; - for (auto sub : subs) { + for (const auto & sub : subs) { trace("trying next substituter"); cleanup(); diff --git a/src/libstore/keys.cc b/src/libstore/keys.cc index 70478e7ad..668725fc7 100644 --- a/src/libstore/keys.cc +++ b/src/libstore/keys.cc @@ -10,12 +10,12 @@ PublicKeys getDefaultPublicKeys() // FIXME: filter duplicates - for (auto s : settings.trustedPublicKeys.get()) { + for (const auto & s : settings.trustedPublicKeys.get()) { PublicKey key(s); publicKeys.emplace(key.name, key); } - for (auto secretKeyFile : settings.secretKeyFiles.get()) { + for (const auto & secretKeyFile : settings.secretKeyFiles.get()) { try { SecretKey secretKey(readFile(secretKeyFile)); publicKeys.emplace(secretKey.name, secretKey.toPublicKey()); diff --git a/src/libstore/local-overlay-store.cc b/src/libstore/local-overlay-store.cc index b86beba2c..56ff6bef3 100644 --- a/src/libstore/local-overlay-store.cc +++ b/src/libstore/local-overlay-store.cc @@ -156,7 +156,7 @@ void LocalOverlayStore::queryGCReferrers(const StorePath & path, StorePathSet & StorePathSet LocalOverlayStore::queryValidDerivers(const StorePath & path) { auto res = LocalStore::queryValidDerivers(path); - for (auto p : lowerStore->queryValidDerivers(path)) + for (const auto & p : lowerStore->queryValidDerivers(path)) res.insert(p); return res; } diff --git a/src/libstore/nar-info.cc b/src/libstore/nar-info.cc index 8b2557060..27fcc2864 100644 --- a/src/libstore/nar-info.cc +++ b/src/libstore/nar-info.cc @@ -118,7 +118,7 @@ std::string NarInfo::to_string(const Store & store) const if (deriver) res += "Deriver: " + std::string(deriver->to_string()) + "\n"; - for (auto sig : sigs) + for (const auto & sig : sigs) res += "Sig: " + sig + "\n"; if (ca) diff --git a/src/libstore/s3-binary-cache-store.cc b/src/libstore/s3-binary-cache-store.cc index bcbf0b55e..bf351a56d 100644 --- a/src/libstore/s3-binary-cache-store.cc +++ b/src/libstore/s3-binary-cache-store.cc @@ -454,7 +454,7 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual debug("got %d keys, next marker '%s'", contents.size(), res.GetNextMarker()); - for (auto object : contents) { + for (const auto & object : contents) { auto & key = object.GetKey(); if (key.size() != 40 || !hasSuffix(key, ".narinfo")) continue; paths.insert(parseStorePath(storeDir + "/" + key.substr(0, key.size() - 8) + "-" + MissingName)); diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index 10577fa2a..78cc3b917 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -1332,7 +1332,7 @@ ref openStore(StoreReference && storeURI) return std::make_shared(params); }, [&](const StoreReference::Specified & g) { - for (auto implem : *Implementations::registered) + for (const auto & implem : *Implementations::registered) if (implem.uriSchemes.count(g.scheme)) return implem.create(g.scheme, g.authority, params); @@ -1363,7 +1363,7 @@ std::list> getDefaultSubstituters() } }; - for (auto uri : settings.substituters.get()) + for (const auto & uri : settings.substituters.get()) addStore(uri); stores.sort([](ref & a, ref & b) { diff --git a/src/libutil-tests/hilite.cc b/src/libutil-tests/hilite.cc index 1ff5980d5..5ef581888 100644 --- a/src/libutil-tests/hilite.cc +++ b/src/libutil-tests/hilite.cc @@ -52,8 +52,7 @@ namespace nix { std::regex("pt"), }; std::vector matches; - for(auto regex : regexes) - { + for (const auto & regex : regexes) { for(auto it = std::sregex_iterator(str.begin(), str.end(), regex); it != std::sregex_iterator(); ++it) { matches.push_back(*it); } diff --git a/src/libutil/args.cc b/src/libutil/args.cc index 385b6cd34..05ecf724e 100644 --- a/src/libutil/args.cc +++ b/src/libutil/args.cc @@ -348,7 +348,7 @@ void RootArgs::parseCmdline(const Strings & _cmdline, bool allowShebang) /* Now that all the other args are processed, run the deferred completions. */ - for (auto d : deferredCompletions) + for (const auto & d : deferredCompletions) d.completer(*completions, d.n, d.prefix); } diff --git a/src/libutil/url.cc b/src/libutil/url.cc index 9ed49dcbe..63b9734ee 100644 --- a/src/libutil/url.cc +++ b/src/libutil/url.cc @@ -77,7 +77,7 @@ std::map decodeQuery(const std::string & query) { std::map result; - for (auto s : tokenizeString(query, "&")) { + for (const auto & s : tokenizeString(query, "&")) { auto e = s.find('='); if (e == std::string::npos) { warn("dubious URI query '%s' is missing equal sign '%s', ignoring", s, "="); diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc index c823c930e..b731b25af 100644 --- a/src/nix-store/nix-store.cc +++ b/src/nix-store/nix-store.cc @@ -222,7 +222,7 @@ static void opPrintFixedPath(Strings opFlags, Strings opArgs) { auto method = FileIngestionMethod::Flat; - for (auto i : opFlags) + for (const auto & i : opFlags) if (i == "--recursive") method = FileIngestionMethod::NixArchive; else throw UsageError("unknown flag '%1%'", i); diff --git a/src/nix/develop.cc b/src/nix/develop.cc index 9a95bc695..1736add9a 100644 --- a/src/nix/develop.cc +++ b/src/nix/develop.cc @@ -611,7 +611,7 @@ struct CmdDevelop : Common, MixEnvironment else if (!command.empty()) { std::vector args; args.reserve(command.size()); - for (auto s : command) + for (const auto & s : command) args.push_back(shellEscape(s)); script += fmt("exec %s\n", concatStringsSep(" ", args)); } diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 925b66d3e..cbc3cdb65 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -94,7 +94,7 @@ public: .label="inputs", .optional=true, .handler={[&](std::vector inputsToUpdate){ - for (auto inputToUpdate : inputsToUpdate) { + for (const auto & inputToUpdate : inputsToUpdate) { InputPath inputPath; try { inputPath = flake::parseInputPath(inputToUpdate); diff --git a/src/nix/hash.cc b/src/nix/hash.cc index 62266fda1..2f9b3fe7c 100644 --- a/src/nix/hash.cc +++ b/src/nix/hash.cc @@ -79,7 +79,7 @@ struct CmdHashBase : Command void run() override { - for (auto path : paths) { + for (const auto & path : paths) { auto makeSink = [&]() -> std::unique_ptr { if (modulus) return std::make_unique(hashAlgo, *modulus); @@ -182,7 +182,7 @@ struct CmdToBase : Command void run() override { warn("The old format conversion sub commands of `nix hash` were deprecated in favor of `nix hash convert`."); - for (auto s : args) + for (const auto & s : args) logger->cout(Hash::parseAny(s, hashAlgo).to_string(hashFormat, hashFormat == HashFormat::SRI)); } }; diff --git a/src/nix/run.cc b/src/nix/run.cc index c9857e13e..a9f9ef60f 100644 --- a/src/nix/run.cc +++ b/src/nix/run.cc @@ -180,9 +180,9 @@ void chrootHelper(int argc, char * * argv) if (mount(realStoreDir.c_str(), (tmpDir + storeDir).c_str(), "", MS_BIND, 0) == -1) throw SysError("mounting '%s' on '%s'", realStoreDir, storeDir); - for (auto entry : fs::directory_iterator{"/"}) { + for (const auto & entry : fs::directory_iterator{"/"}) { checkInterrupt(); - auto src = entry.path(); + const auto & src = entry.path(); fs::path dst = tmpDir / entry.path().filename(); if (pathExists(dst)) continue; auto st = entry.symlink_status(); diff --git a/src/nix/verify.cc b/src/nix/verify.cc index 124a05bed..52585fe08 100644 --- a/src/nix/verify.cc +++ b/src/nix/verify.cc @@ -129,7 +129,7 @@ struct CmdVerify : StorePathsCommand size_t validSigs = 0; auto doSigs = [&](StringSet sigs) { - for (auto sig : sigs) { + for (const auto & sig : sigs) { if (!sigsSeen.insert(sig).second) continue; if (validSigs < ValidPathInfo::maxSigs && info->checkSignature(*store, publicKeys, sig)) validSigs++; From f9980b5715fc403383f8e99d5da8bb91538c996d Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman <145775305+xokdvium@users.noreply.github.com> Date: Tue, 26 Nov 2024 00:13:54 +0300 Subject: [PATCH 497/718] fix(libutil/config): declare virtual dtor for AbstractConfig This prevents any potential cases of deletion through base pointer and its non-virtual dtor, which might leak memory. Also gets rid of the warning: /nix/store/fg7ass3a5m5pgl26qzfdniicbwbgzccy-gcc-13.2.0/include/c++/13.2.0/bits/stl_construct.h:88:2: warning: destructor called on non-final 'nix::flake::Settings' that has virtual functions but non-virtual destructor [-Wdelete-non-abstract-non-virtual-dtor] 88 | __location->~_Tp(); .... ../src/libflake-c/nix_api_flake.cc:10:30: note: in instantiation of function template specialization 'nix::make_ref' requested here 10 | auto settings = nix::make_ref(); --- src/libutil/config.hh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libutil/config.hh b/src/libutil/config.hh index c0c59ac68..e98e09bf7 100644 --- a/src/libutil/config.hh +++ b/src/libutil/config.hh @@ -115,6 +115,8 @@ public: * Re-applies all previously attempted changes to unknown settings */ void reapplyUnknownSettings(); + + virtual ~AbstractConfig() = default; }; /** From 5b8728d393dd1c9bbbf6737500669853da7de1b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Tue, 26 Nov 2024 07:07:31 +0100 Subject: [PATCH 498/718] more readable errors if symlinks cannot be created Before: filesystem error: cannot create symlink: Permission denied [/nix/store/1s2p3a4rs172336hj2l8n20nz74hf71j-nix-eval-jobs-2.24.1.drv] [/1s2p3a4rs172336hj2l8n20nz74hf71j-nix-eval-jobs-2.24.1.drv.tmp-2772352-1316231068] Now: creating symlink '/wfxz2q489c811n08cdqj7ywxm3n4z6m5-nix-eval-jobs-2.24.1.drv.tmp-2971297-324653080' -> '/nix/store/wfxz2q489c811n08cdqj7ywxm3n4z6m5-nix-eval-jobs-2.24.1.drv': Permission denied --- src/libutil/file-system.cc | 16 +++++++++++++--- src/libutil/file-system.hh | 2 -- src/nix/flake.cc | 2 +- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/libutil/file-system.cc b/src/libutil/file-system.cc index 92996ea47..829700336 100644 --- a/src/libutil/file-system.cc +++ b/src/libutil/file-system.cc @@ -602,7 +602,11 @@ std::pair createTempFile(const Path & prefix) void createSymlink(const Path & target, const Path & link) { - fs::create_symlink(target, link); + try { + fs::create_symlink(target, link); + } catch (fs::filesystem_error & e) { + throw SysError("creating symlink '%1%' -> '%2%'", link, target); + } } void replaceSymlink(const fs::path & target, const fs::path & link) @@ -615,10 +619,16 @@ void replaceSymlink(const fs::path & target, const fs::path & link) fs::create_symlink(target, tmp); } catch (fs::filesystem_error & e) { if (e.code() == std::errc::file_exists) continue; - throw; + throw SysError("creating symlink '%1%' -> '%2%'", tmp, target); + } + + try { + fs::rename(tmp, link); + } catch (fs::filesystem_error & e) { + if (e.code() == std::errc::file_exists) continue; + throw SysError("renaming '%1%' to '%2%'", tmp, link); } - fs::rename(tmp, link); break; } diff --git a/src/libutil/file-system.hh b/src/libutil/file-system.hh index 4c08cdf58..3c49181a0 100644 --- a/src/libutil/file-system.hh +++ b/src/libutil/file-system.hh @@ -250,8 +250,6 @@ void setWriteTime(const std::filesystem::path & path, const struct stat & st); /** * Create a symlink. * - * In the process of being deprecated for - * `std::filesystem::create_symlink`. */ void createSymlink(const Path & target, const Path & link); diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 925b66d3e..4bb5c329e 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -937,7 +937,7 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand } continue; } else - fs::create_symlink(target, to2); + createSymlink(target, to2); } else throw Error("file '%s' has unsupported type", from2); From d67aa03414ad6e75b2ac2145406fcc936c0f1798 Mon Sep 17 00:00:00 2001 From: Sergei Trofimovich Date: Tue, 26 Nov 2024 18:35:18 +0000 Subject: [PATCH 499/718] src/perl/meson.build: fall back to 'bz2' library lookup Upstream `bzip2` does not provide `pkg-config` files. As a result an attempt to build `nix` on some distributions like Gentoo failos the configure as: $ meson setup .. ... Executing subproject perl ... perl| Run-time dependency bzip2 found: NO (tried pkgconfig and cmake) ../src/perl/meson.build:68:12: ERROR: Dependency "bzip2" not found, tried pkgconfig and cmake The change falls back to `bz2` library for such cases. --- src/perl/meson.build | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/perl/meson.build b/src/perl/meson.build index dcb6a68a4..52d85fd60 100644 --- a/src/perl/meson.build +++ b/src/perl/meson.build @@ -65,7 +65,13 @@ yath = find_program('yath', required : false) # Required Libraries #------------------------------------------------- -bzip2_dep = dependency('bzip2') +bzip2_dep = dependency('bzip2', required: false) +if not bzip2_dep.found() + bzip2_dep = cpp.find_library('bz2') + if not bzip2_dep.found() + error('No "bzip2" pkg-config or "bz2" library found') + endif +endif curl_dep = dependency('libcurl') libsodium_dep = dependency('libsodium') From 2679e55232af74b0325877b6a49ed83502711fc0 Mon Sep 17 00:00:00 2001 From: Sergei Trofimovich Date: Tue, 26 Nov 2024 23:08:10 +0000 Subject: [PATCH 500/718] tests/functional/meson.build: always look up `ls` as a `coreutils` proxy Without the change `meson setup` fails on `Gentoo or Debian as those don't use multicall binary: $ meson setup .. ... Executing subproject nix-functional-tests ... ../src/nix-functional-tests/meson.build:24:14: ERROR: Program 'coreutils' not found or not executable The change always uses `ls` to look `coreutils` up. Closes: https://github.com/NixOS/nix/issues/11975 --- tests/functional/meson.build | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/tests/functional/meson.build b/tests/functional/meson.build index 0d46f9ce2..933595cd5 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -17,12 +17,10 @@ fs = import('fs') nix = find_program('nix') bash = find_program('bash', native : true) busybox = find_program('busybox', native : true, required : false) -if host_machine.system() == 'windows' - # Because of the state of symlinks on Windows, coreutils.exe doesn't usually exist, but things like ls.exe will - coreutils = find_program('ls', native : true) -else - coreutils = find_program('coreutils', native : true) -endif +# Look up `coreutils` package by searching for `ls` binary. +# Previously we looked up `coreutils` on `linux`, but that is not +# guaranteed to exist either. +coreutils = find_program('ls', native : true) dot = find_program('dot', native : true, required : false) nix_bin_dir = fs.parent(nix.full_path()) From 21ddd2022e40d4727684cadf7aca44b0b4ec622c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Wed, 27 Nov 2024 07:39:30 +0100 Subject: [PATCH 501/718] mergify: drop installer test --- .mergify.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.mergify.yml b/.mergify.yml index c297d3d5e..ac1bee111 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -2,9 +2,6 @@ queue_rules: - name: default # all required tests need to go here merge_conditions: - - check-success=installer - - check-success=installer_test (macos-latest) - - check-success=installer_test (ubuntu-latest) - check-success=tests (macos-latest) - check-success=tests (ubuntu-latest) - check-success=vm_tests From a5c7709f97ceb567ffd1903aa1cd921ca70d7c7b Mon Sep 17 00:00:00 2001 From: h0nIg Date: Wed, 27 Nov 2024 13:24:46 +0100 Subject: [PATCH 502/718] docker: Fix command "nix profile install", Don't require --impure --- docker.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docker.nix b/docker.nix index 19479e57c..e2e9da728 100644 --- a/docker.nix +++ b/docker.nix @@ -258,14 +258,14 @@ let mkdir -p $out/nix/var/nix/profiles/per-user/${uname} ln -s ${profile} $out/nix/var/nix/profiles/default-1-link - ln -s $out/nix/var/nix/profiles/default-1-link $out/nix/var/nix/profiles/default + ln -s /nix/var/nix/profiles/default-1-link $out/nix/var/nix/profiles/default ln -s /nix/var/nix/profiles/default $out${userHome}/.nix-profile ln -s ${channel} $out/nix/var/nix/profiles/per-user/${uname}/channels-1-link - ln -s $out/nix/var/nix/profiles/per-user/${uname}/channels-1-link $out/nix/var/nix/profiles/per-user/${uname}/channels + ln -s /nix/var/nix/profiles/per-user/${uname}/channels-1-link $out/nix/var/nix/profiles/per-user/${uname}/channels mkdir -p $out${userHome}/.nix-defexpr - ln -s $out/nix/var/nix/profiles/per-user/${uname}/channels $out${userHome}/.nix-defexpr/channels + ln -s /nix/var/nix/profiles/per-user/${uname}/channels $out${userHome}/.nix-defexpr/channels echo "${channelURL} ${channelName}" > $out${userHome}/.nix-channels mkdir -p $out/bin $out/usr/bin From 37fd80588fff0ee5e9e27c9d6a1dbc7d2f740b6d Mon Sep 17 00:00:00 2001 From: Anatoli Babenia Date: Wed, 27 Nov 2024 17:11:36 +0300 Subject: [PATCH 503/718] shellcheck: simplify install-nix-from-tarball.sh --- maintainers/flake-module.nix | 1 - scripts/install-nix-from-tarball.sh | 15 +++++---------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/maintainers/flake-module.nix b/maintainers/flake-module.nix index ba6cd2816..1d4e85c8c 100644 --- a/maintainers/flake-module.nix +++ b/maintainers/flake-module.nix @@ -496,7 +496,6 @@ ''^scripts/create-darwin-volume\.sh$'' ''^scripts/install-darwin-multi-user\.sh$'' ''^scripts/install-multi-user\.sh$'' - ''^scripts/install-nix-from-tarball\.sh$'' ''^scripts/install-systemd-multi-user\.sh$'' ''^src/nix/get-env\.sh$'' ''^tests/functional/ca/build-dry\.sh$'' diff --git a/scripts/install-nix-from-tarball.sh b/scripts/install-nix-from-tarball.sh index 794622530..007fe85ee 100644 --- a/scripts/install-nix-from-tarball.sh +++ b/scripts/install-nix-from-tarball.sh @@ -48,15 +48,14 @@ case "$(uname -s)" in INSTALL_MODE=no-daemon;; esac -# space-separated string -ACTIONS= +ACTION= # handle the command line flags while [ $# -gt 0 ]; do case $1 in --daemon) INSTALL_MODE=daemon - ACTIONS="${ACTIONS}install " + ACTION=install ;; --no-daemon) if [ "$(uname -s)" = "Darwin" ]; then @@ -65,18 +64,14 @@ while [ $# -gt 0 ]; do fi INSTALL_MODE=no-daemon # intentional tail space - ACTIONS="${ACTIONS}install " + ACTION=install ;; - # --uninstall) - # # intentional tail space - # ACTIONS="${ACTIONS}uninstall " - # ;; --yes) export NIX_INSTALLER_YES=1;; --no-channel-add) export NIX_INSTALLER_NO_CHANNEL_ADD=1;; --daemon-user-count) - export NIX_USER_COUNT=$2 + export NIX_USER_COUNT="$2" shift;; --no-modify-profile) NIX_INSTALLER_NO_MODIFY_PROFILE=1;; @@ -128,7 +123,7 @@ done if [ "$INSTALL_MODE" = "daemon" ]; then printf '\e[1;31mSwitching to the Multi-user Installer\e[0m\n' - exec "$self/install-multi-user" $ACTIONS # let ACTIONS split + exec "$self/install-multi-user" $ACTION exit 0 fi From 985b2f9df30e62a21c32d7ffaae7aebfe4c56d3a Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 27 Nov 2024 15:23:56 +0100 Subject: [PATCH 504/718] Remove FIXME --- src/libflake/flake/flake.cc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/libflake/flake/flake.cc b/src/libflake/flake/flake.cc index 8e381c0d2..9d5760ed1 100644 --- a/src/libflake/flake/flake.cc +++ b/src/libflake/flake/flake.cc @@ -638,10 +638,6 @@ LockedFlake lockFlake( nodePaths.emplace(childNode, inputFlake.path.parent()); computeLocks(inputFlake.inputs, childNode, inputPath, oldLock, lockRootPath, inputFlake.path, false); } else { - // FIXME: sourcePath is wrong here, we - // should pass a lambda that lazily - // fetches the parent flake if needed - // (i.e. getInputFlake()). computeLocks(fakeInputs, childNode, inputPath, oldLock, lockRootPath, sourcePath, true); } From 8034589d7eb299c126f169ff0780b5242936acdd Mon Sep 17 00:00:00 2001 From: Ryan Hendrickson Date: Wed, 14 Aug 2024 00:05:06 -0400 Subject: [PATCH 505/718] parser-state: fix attribute merging --- src/libexpr-tests/trivial.cc | 51 +++++++++ src/libexpr/parser-state.hh | 108 +++++++++++------- ...fail-attrset-merge-drops-later-rec.err.exp | 5 + ...val-fail-attrset-merge-drops-later-rec.nix | 1 + ...val-okay-regrettable-rec-attrset-merge.exp | 1 + ...val-okay-regrettable-rec-attrset-merge.nix | 3 + .../parse-fail-mixed-nested-attrs1.err.exp | 8 +- .../parse-fail-mixed-nested-attrs2.err.exp | 8 +- 8 files changed, 133 insertions(+), 52 deletions(-) create mode 100644 tests/functional/lang/eval-fail-attrset-merge-drops-later-rec.err.exp create mode 100644 tests/functional/lang/eval-fail-attrset-merge-drops-later-rec.nix create mode 100644 tests/functional/lang/eval-okay-regrettable-rec-attrset-merge.exp create mode 100644 tests/functional/lang/eval-okay-regrettable-rec-attrset-merge.nix diff --git a/src/libexpr-tests/trivial.cc b/src/libexpr-tests/trivial.cc index e455a571b..d77b4d53b 100644 --- a/src/libexpr-tests/trivial.cc +++ b/src/libexpr-tests/trivial.cc @@ -177,6 +177,57 @@ namespace nix { ) ); +// The following macros ultimately define 48 tests (16 variations on three +// templates). Each template tests an expression that can be written in 2^4 +// different ways, by making four choices about whether to write a particular +// attribute path segment as `x.y = ...;` (collapsed) or `x = { y = ...; };` +// (expanded). +// +// The nestedAttrsetMergeXXXX tests check that the expression +// `{ a.b.c = 1; a.b.d = 2; }` has the same value regardless of how it is +// expanded. (That exact expression is exercised in test +// nestedAttrsetMerge0000, because it is fully collapsed. The test +// nestedAttrsetMerge1001 would instead examine +// `{ a = { b.c = 1; }; a.b = { d = 2; }; }`.) +// +// The nestedAttrsetMergeDupXXXX tests check that the expression +// `{ a.b.c = 1; a.b.c = 2; }` throws a duplicate attribute error, again +// regardless of how it is expanded. +// +// The nestedAttrsetMergeLetXXXX tests check that the expression +// `let a.b.c = 1; a.b.d = 2; in a` has the same value regardless of how it is +// expanded. +#define X_EXPAND_IF0(k, v) k "." v +#define X_EXPAND_IF1(k, v) k " = { " v " };" +#define X4(w, x, y, z) \ + TEST_F(TrivialExpressionTest, nestedAttrsetMerge##w##x##y##z) { \ + auto v = eval("{ a.b = { c = 1; d = 2; }; } == { " \ + X_EXPAND_IF##w("a", X_EXPAND_IF##x("b", "c = 1;")) " " \ + X_EXPAND_IF##y("a", X_EXPAND_IF##z("b", "d = 2;")) " }"); \ + ASSERT_THAT(v, IsTrue()); \ + }; \ + TEST_F(TrivialExpressionTest, nestedAttrsetMergeDup##w##x##y##z) { \ + ASSERT_THROW(eval("{ " \ + X_EXPAND_IF##w("a", X_EXPAND_IF##x("b", "c = 1;")) " " \ + X_EXPAND_IF##y("a", X_EXPAND_IF##z("b", "c = 2;")) " }"), Error); \ + }; \ + TEST_F(TrivialExpressionTest, nestedAttrsetMergeLet##w##x##y##z) { \ + auto v = eval("{ b = { c = 1; d = 2; }; } == (let " \ + X_EXPAND_IF##w("a", X_EXPAND_IF##x("b", "c = 1;")) " " \ + X_EXPAND_IF##y("a", X_EXPAND_IF##z("b", "d = 2;")) " in a)"); \ + ASSERT_THAT(v, IsTrue()); \ + }; +#define X3(...) X4(__VA_ARGS__, 0) X4(__VA_ARGS__, 1) +#define X2(...) X3(__VA_ARGS__, 0) X3(__VA_ARGS__, 1) +#define X1(...) X2(__VA_ARGS__, 0) X2(__VA_ARGS__, 1) + X1(0) X1(1) +#undef X_EXPAND_IF0 +#undef X_EXPAND_IF1 +#undef X1 +#undef X2 +#undef X3 +#undef X4 + TEST_F(TrivialExpressionTest, functor) { auto v = eval("{ __functor = self: arg: self.v + arg; v = 10; } 5"); ASSERT_THAT(v, IsIntEq(15)); diff --git a/src/libexpr/parser-state.hh b/src/libexpr/parser-state.hh index 8ad0d9ad7..21a880e8e 100644 --- a/src/libexpr/parser-state.hh +++ b/src/libexpr/parser-state.hh @@ -88,6 +88,7 @@ struct ParserState void dupAttr(const AttrPath & attrPath, const PosIdx pos, const PosIdx prevPos); void dupAttr(Symbol attr, const PosIdx pos, const PosIdx prevPos); void addAttr(ExprAttrs * attrs, AttrPath && attrPath, const ParserLocation & loc, Expr * e, const ParserLocation & exprLoc); + void addAttr(ExprAttrs * attrs, AttrPath & attrPath, const Symbol & symbol, ExprAttrs::AttrDef && def); Formals * validateFormals(Formals * formals, PosIdx pos = noPos, Symbol arg = {}); Expr * stripIndentation(const PosIdx pos, std::vector>> && es); @@ -120,64 +121,29 @@ inline void ParserState::addAttr(ExprAttrs * attrs, AttrPath && attrPath, const // Checking attrPath validity. // =========================== for (i = attrPath.begin(); i + 1 < attrPath.end(); i++) { + ExprAttrs * nested; if (i->symbol) { ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(i->symbol); if (j != attrs->attrs.end()) { - if (j->second.kind != ExprAttrs::AttrDef::Kind::Inherited) { - ExprAttrs * attrs2 = dynamic_cast(j->second.e); - if (!attrs2) dupAttr(attrPath, pos, j->second.pos); - attrs = attrs2; - } else + nested = dynamic_cast(j->second.e); + if (!nested) { + attrPath.erase(i + 1, attrPath.end()); dupAttr(attrPath, pos, j->second.pos); + } } else { - ExprAttrs * nested = new ExprAttrs; + nested = new ExprAttrs; attrs->attrs[i->symbol] = ExprAttrs::AttrDef(nested, pos); - attrs = nested; } } else { - ExprAttrs *nested = new ExprAttrs; + nested = new ExprAttrs; attrs->dynamicAttrs.push_back(ExprAttrs::DynamicAttrDef(i->expr, nested, pos)); - attrs = nested; } + attrs = nested; } // Expr insertion. // ========================== if (i->symbol) { - ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(i->symbol); - if (j != attrs->attrs.end()) { - // This attr path is already defined. However, if both - // e and the expr pointed by the attr path are two attribute sets, - // we want to merge them. - // Otherwise, throw an error. - auto ae = dynamic_cast(e); - auto jAttrs = dynamic_cast(j->second.e); - if (jAttrs && ae) { - if (ae->inheritFromExprs && !jAttrs->inheritFromExprs) - jAttrs->inheritFromExprs = std::make_unique>(); - for (auto & ad : ae->attrs) { - auto j2 = jAttrs->attrs.find(ad.first); - if (j2 != jAttrs->attrs.end()) // Attr already defined in iAttrs, error. - dupAttr(ad.first, j2->second.pos, ad.second.pos); - jAttrs->attrs.emplace(ad.first, ad.second); - if (ad.second.kind == ExprAttrs::AttrDef::Kind::InheritedFrom) { - auto & sel = dynamic_cast(*ad.second.e); - auto & from = dynamic_cast(*sel.e); - from.displ += jAttrs->inheritFromExprs->size(); - } - } - jAttrs->dynamicAttrs.insert(jAttrs->dynamicAttrs.end(), ae->dynamicAttrs.begin(), ae->dynamicAttrs.end()); - if (ae->inheritFromExprs) { - jAttrs->inheritFromExprs->insert(jAttrs->inheritFromExprs->end(), - ae->inheritFromExprs->begin(), ae->inheritFromExprs->end()); - } - } else { - dupAttr(attrPath, pos, j->second.pos); - } - } else { - // This attr path is not defined. Let's create it. - attrs->attrs.emplace(i->symbol, ExprAttrs::AttrDef(e, pos)); - e->setName(i->symbol); - } + addAttr(attrs, attrPath, i->symbol, ExprAttrs::AttrDef(e, pos)); } else { attrs->dynamicAttrs.push_back(ExprAttrs::DynamicAttrDef(i->expr, e, pos)); } @@ -189,6 +155,60 @@ inline void ParserState::addAttr(ExprAttrs * attrs, AttrPath && attrPath, const } } +/** + * Precondition: attrPath is used for error messages and should already contain + * symbol as its last element. + */ +inline void ParserState::addAttr(ExprAttrs * attrs, AttrPath & attrPath, const Symbol & symbol, ExprAttrs::AttrDef && def) +{ + ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(symbol); + if (j != attrs->attrs.end()) { + // This attr path is already defined. However, if both + // e and the expr pointed by the attr path are two attribute sets, + // we want to merge them. + // Otherwise, throw an error. + auto ae = dynamic_cast(def.e); + auto jAttrs = dynamic_cast(j->second.e); + + // N.B. In a world in which we are less bound by our past mistakes, we + // would also test that jAttrs and ae are not recursive. The effect of + // not doing so is that any `rec` marker on ae is discarded, and any + // `rec` marker on jAttrs will apply to the attributes in ae. + // See https://github.com/NixOS/nix/issues/9020. + if (jAttrs && ae) { + if (ae->inheritFromExprs && !jAttrs->inheritFromExprs) + jAttrs->inheritFromExprs = std::make_unique>(); + for (auto & ad : ae->attrs) { + if (ad.second.kind == ExprAttrs::AttrDef::Kind::InheritedFrom) { + auto & sel = dynamic_cast(*ad.second.e); + auto & from = dynamic_cast(*sel.e); + from.displ += jAttrs->inheritFromExprs->size(); + } + attrPath.emplace_back(AttrName(ad.first)); + addAttr(jAttrs, attrPath, ad.first, std::move(ad.second)); + attrPath.pop_back(); + } + ae->attrs.clear(); + jAttrs->dynamicAttrs.insert(jAttrs->dynamicAttrs.end(), + std::make_move_iterator(ae->dynamicAttrs.begin()), + std::make_move_iterator(ae->dynamicAttrs.end())); + ae->dynamicAttrs.clear(); + if (ae->inheritFromExprs) { + jAttrs->inheritFromExprs->insert(jAttrs->inheritFromExprs->end(), + std::make_move_iterator(ae->inheritFromExprs->begin()), + std::make_move_iterator(ae->inheritFromExprs->end())); + ae->inheritFromExprs = nullptr; + } + } else { + dupAttr(attrPath, def.pos, j->second.pos); + } + } else { + // This attr path is not defined. Let's create it. + attrs->attrs.emplace(symbol, def); + def.e->setName(symbol); + } +} + inline Formals * ParserState::validateFormals(Formals * formals, PosIdx pos, Symbol arg) { std::sort(formals->formals.begin(), formals->formals.end(), diff --git a/tests/functional/lang/eval-fail-attrset-merge-drops-later-rec.err.exp b/tests/functional/lang/eval-fail-attrset-merge-drops-later-rec.err.exp new file mode 100644 index 000000000..d1cdc7b76 --- /dev/null +++ b/tests/functional/lang/eval-fail-attrset-merge-drops-later-rec.err.exp @@ -0,0 +1,5 @@ +error: undefined variable 'd' + at /pwd/lang/eval-fail-attrset-merge-drops-later-rec.nix:1:26: + 1| { a.b = 1; a = rec { c = d + 2; d = 3; }; }.c + | ^ + 2| diff --git a/tests/functional/lang/eval-fail-attrset-merge-drops-later-rec.nix b/tests/functional/lang/eval-fail-attrset-merge-drops-later-rec.nix new file mode 100644 index 000000000..fdb314b91 --- /dev/null +++ b/tests/functional/lang/eval-fail-attrset-merge-drops-later-rec.nix @@ -0,0 +1 @@ +{ a.b = 1; a = rec { c = d + 2; d = 3; }; }.c diff --git a/tests/functional/lang/eval-okay-regrettable-rec-attrset-merge.exp b/tests/functional/lang/eval-okay-regrettable-rec-attrset-merge.exp new file mode 100644 index 000000000..1e8b31496 --- /dev/null +++ b/tests/functional/lang/eval-okay-regrettable-rec-attrset-merge.exp @@ -0,0 +1 @@ +6 diff --git a/tests/functional/lang/eval-okay-regrettable-rec-attrset-merge.nix b/tests/functional/lang/eval-okay-regrettable-rec-attrset-merge.nix new file mode 100644 index 000000000..8df6a2ad8 --- /dev/null +++ b/tests/functional/lang/eval-okay-regrettable-rec-attrset-merge.nix @@ -0,0 +1,3 @@ +# This is for backwards compatibility, not because we like it. +# See https://github.com/NixOS/nix/issues/9020. +{ a = rec { b = c + 1; d = 2; }; a.c = d + 3; }.a.b diff --git a/tests/functional/lang/parse-fail-mixed-nested-attrs1.err.exp b/tests/functional/lang/parse-fail-mixed-nested-attrs1.err.exp index a4472156b..49a07323f 100644 --- a/tests/functional/lang/parse-fail-mixed-nested-attrs1.err.exp +++ b/tests/functional/lang/parse-fail-mixed-nested-attrs1.err.exp @@ -1,6 +1,6 @@ -error: attribute 'z' already defined at «stdin»:3:16 - at «stdin»:2:3: - 1| { +error: attribute 'x.z' already defined at «stdin»:2:3 + at «stdin»:3:16: 2| x.z = 3; - | ^ 3| x = { y = 3; z = 3; }; + | ^ + 4| } diff --git a/tests/functional/lang/parse-fail-mixed-nested-attrs2.err.exp b/tests/functional/lang/parse-fail-mixed-nested-attrs2.err.exp index ead1f0dbd..36fab2fe6 100644 --- a/tests/functional/lang/parse-fail-mixed-nested-attrs2.err.exp +++ b/tests/functional/lang/parse-fail-mixed-nested-attrs2.err.exp @@ -1,6 +1,6 @@ -error: attribute 'y' already defined at «stdin»:3:9 - at «stdin»:2:3: - 1| { +error: attribute 'x.y.y' already defined at «stdin»:2:3 + at «stdin»:3:9: 2| x.y.y = 3; - | ^ 3| x = { y.y= 3; z = 3; }; + | ^ + 4| } From e5e09006f97700f35c68411df6fe4f8a9d7dc807 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 28 Nov 2024 15:25:51 +0100 Subject: [PATCH 506/718] Work around gcc warning Same as 57fea81f8a6ab3b91b1003d27bd48effad30b25a. --- src/nix-env/nix-env.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index ba2baccee..e9eb52708 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -481,12 +481,13 @@ static void printMissing(EvalState & state, PackageInfos & elems) { std::vector targets; for (auto & i : elems) - if (auto drvPath = i.queryDrvPath()) - targets.emplace_back(DerivedPath::Built{ + if (auto drvPath = i.queryDrvPath()) { + auto path = DerivedPath::Built{ .drvPath = makeConstantStorePathRef(*drvPath), .outputs = OutputsSpec::All { }, - }); - else + }; + targets.emplace_back(std::move(path)); + } else targets.emplace_back(DerivedPath::Opaque{ .path = i.queryOutPath(), }); From 04975f7c32e91cda35adc0c3257c98542be97d0e Mon Sep 17 00:00:00 2001 From: Anatoli Babenia Date: Mon, 28 Oct 2024 09:53:44 +0300 Subject: [PATCH 507/718] install: Allow to specify alternative `sudo` command --- scripts/install-multi-user.sh | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/scripts/install-multi-user.sh b/scripts/install-multi-user.sh index a487d459f..518c955b4 100644 --- a/scripts/install-multi-user.sh +++ b/scripts/install-multi-user.sh @@ -56,6 +56,9 @@ readonly NIX_INSTALLED_CACERT="@cacert@" #readonly NIX_INSTALLED_CACERT="/nix/store/7dxhzymvy330i28ii676fl1pqwcahv2f-nss-cacert-3.49.2" readonly EXTRACTED_NIX_PATH="$(dirname "$0")" +# allow to override identity change command +readonly NIX_BECOME=${NIX_BECOME:-sudo} + readonly ROOT_HOME=~root if [ -t 0 ] && [ -z "${NIX_INSTALLER_YES:-}" ]; then @@ -123,7 +126,7 @@ uninstall_directions() { cat < Date: Sat, 23 Nov 2024 09:51:56 +0300 Subject: [PATCH 508/718] Allow `sudo` alternatives when installing from tarball --- scripts/install-nix-from-tarball.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/scripts/install-nix-from-tarball.sh b/scripts/install-nix-from-tarball.sh index 007fe85ee..8d127a9c5 100644 --- a/scripts/install-nix-from-tarball.sh +++ b/scripts/install-nix-from-tarball.sh @@ -9,6 +9,8 @@ self="$(dirname "$0")" nix="@nix@" cacert="@cacert@" +# allow to override identity change command +readonly NIX_BECOME="${NIX_BECOME:-sudo}" if ! [ -e "$self/.reginfo" ]; then echo "$0: incomplete installer (.reginfo is missing)" >&2 @@ -63,7 +65,6 @@ while [ $# -gt 0 ]; do exit 1 fi INSTALL_MODE=no-daemon - # intentional tail space ACTION=install ;; --yes) @@ -135,8 +136,8 @@ echo "performing a single-user installation of Nix..." >&2 if ! [ -e "$dest" ]; then cmd="mkdir -m 0755 $dest && chown $USER $dest" - echo "directory $dest does not exist; creating it by running '$cmd' using sudo" >&2 - if ! sudo sh -c "$cmd"; then + echo "directory $dest does not exist; creating it by running '$cmd' using $NIX_BECOME" >&2 + if ! $NIX_BECOME sh -c "$cmd"; then echo "$0: please manually run '$cmd' as root to create $dest" >&2 exit 1 fi From 747cf4e50f43b510ff054ec14bdef87634231237 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 6 Nov 2024 22:49:04 +0100 Subject: [PATCH 509/718] fix: Add splicing to fix the manual in cross We *could* use a "native" manual instead - ie reusing a native `nixpkgsFor.${buildPlatform}`, but this works, and also works for possible cases where we have a custom or patched build tool. --- flake.nix | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/flake.nix b/flake.nix index 06025e3b7..794736af4 100644 --- a/flake.nix +++ b/flake.nix @@ -124,18 +124,36 @@ # without "polluting" the top level "`pkgs`" attrset. # This also has the benefit of providing us with a distinct set of packages # we can iterate over. - nixComponents = lib.makeScope final.nixDependencies.newScope (import ./packaging/components.nix { - inherit (final) lib; - inherit officialRelease; - src = self; - }); + nixComponents = + lib.makeScopeWithSplicing' + { + inherit (final) splicePackages; + inherit (final.nixDependencies) newScope; + } + { + otherSplices = final.generateSplicesForMkScope "nixComponents"; + f = import ./packaging/components.nix { + inherit (final) lib; + inherit officialRelease; + src = self; + }; + }; # The dependencies are in their own scope, so that they don't have to be # in Nixpkgs top level `pkgs` or `nixComponents`. - nixDependencies = lib.makeScope final.newScope (import ./packaging/dependencies.nix { - inherit inputs stdenv; - pkgs = final; - }); + nixDependencies = + lib.makeScopeWithSplicing' + { + inherit (final) splicePackages; + inherit (final) newScope; # layered directly on pkgs, unlike nixComponents above + } + { + otherSplices = final.generateSplicesForMkScope "nixDependencies"; + f = import ./packaging/dependencies.nix { + inherit inputs stdenv; + pkgs = final; + }; + }; nix = final.nixComponents.nix-cli; From d67e24afec185eee740180b5f023fc4df462013c Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 2 Dec 2024 17:42:11 +0100 Subject: [PATCH 510/718] fix: Add missing manpages to meson.build --- doc/manual/meson.build | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/manual/meson.build b/doc/manual/meson.build index 3630e2dc8..c4cc9b893 100644 --- a/doc/manual/meson.build +++ b/doc/manual/meson.build @@ -199,6 +199,7 @@ nix3_manpages = [ 'nix3-build', 'nix3-bundle', 'nix3-config', + 'nix3-config-check', 'nix3-config-show', 'nix3-copy', 'nix3-daemon', @@ -206,8 +207,8 @@ nix3_manpages = [ 'nix3-derivation', 'nix3-derivation-show', 'nix3-develop', - #'nix3-doctor', 'nix3-edit', + 'nix3-env-shell', 'nix3-eval', 'nix3-flake-archive', 'nix3-flake-check', @@ -224,6 +225,7 @@ nix3_manpages = [ 'nix3-fmt', 'nix3-hash-file', 'nix3-hash', + 'nix3-hash-convert', 'nix3-hash-path', 'nix3-hash-to-base16', 'nix3-hash-to-base32', @@ -238,6 +240,7 @@ nix3_manpages = [ 'nix3-nar-cat', 'nix3-nar-dump-path', 'nix3-nar-ls', + 'nix3-nar-pack', 'nix3-nar', 'nix3-path-info', 'nix3-print-dev-env', @@ -260,7 +263,7 @@ nix3_manpages = [ 'nix3-repl', 'nix3-run', 'nix3-search', - #'nix3-shell', + 'nix3-store-add', 'nix3-store-add-file', 'nix3-store-add-path', 'nix3-store-cat', @@ -270,6 +273,7 @@ nix3_manpages = [ 'nix3-store-diff-closures', 'nix3-store-dump-path', 'nix3-store-gc', + 'nix3-store-info', 'nix3-store-ls', 'nix3-store-make-content-addressed', 'nix3-store', From 038ab46d7a08b34e9706a5f7a3c75995cd145899 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Tue, 3 Dec 2024 16:37:07 +0100 Subject: [PATCH 511/718] Restore org.nixos.nix-daemon.plist installation --- misc/launchd/meson.build | 13 +++++++++++++ misc/meson.build | 1 + 2 files changed, 14 insertions(+) create mode 100644 misc/launchd/meson.build diff --git a/misc/launchd/meson.build b/misc/launchd/meson.build new file mode 100644 index 000000000..5168131d1 --- /dev/null +++ b/misc/launchd/meson.build @@ -0,0 +1,13 @@ +configure_file( + input : 'org.nixos.nix-daemon.plist.in', + output : 'org.nixos.nix-daemon.plist', + install : true, + install_dir : get_option('prefix') / 'Library/LaunchDaemons', + install_mode : 'rw-r--r--', + configuration : { + # TODO: unhardcode paths with something like: + # 'storedir' : store_dir, + # 'localstatedir' : localstatedir, + # 'bindir' : bindir, + }, +) diff --git a/misc/meson.build b/misc/meson.build index a6d1f944b..78ae3c06c 100644 --- a/misc/meson.build +++ b/misc/meson.build @@ -2,4 +2,5 @@ subdir('bash') subdir('fish') subdir('zsh') +subdir('launchd') subdir('systemd') From 63c0f0dcd258b6763970a80c43bed431e691e5ba Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Tue, 3 Dec 2024 16:51:01 +0100 Subject: [PATCH 512/718] Install init system configs only when relevant --- misc/meson.build | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/misc/meson.build b/misc/meson.build index 78ae3c06c..82f2b0c65 100644 --- a/misc/meson.build +++ b/misc/meson.build @@ -2,5 +2,10 @@ subdir('bash') subdir('fish') subdir('zsh') -subdir('launchd') -subdir('systemd') +if host_machine.system() == 'linux' + subdir('systemd') +endif + +if host_machine.system() == 'darwin' + subdir('launchd') +endif From abcfdb4bdab966016d3c9d725fafdad8eadbbf5d Mon Sep 17 00:00:00 2001 From: mupdt <25388474+mupdt@users.noreply.github.com> Date: Wed, 4 Dec 2024 05:49:21 -0500 Subject: [PATCH 513/718] s3-binary-cache: show the error's request ID The request ID is essential for traceability and debugging purposes. It allows us to connect client-side to server-side events. --- src/libstore/s3-binary-cache-store.cc | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/libstore/s3-binary-cache-store.cc b/src/libstore/s3-binary-cache-store.cc index bf351a56d..cfa713b00 100644 --- a/src/libstore/s3-binary-cache-store.cc +++ b/src/libstore/s3-binary-cache-store.cc @@ -48,7 +48,11 @@ R && checkAws(std::string_view s, Aws::Utils::Outcome && outcome) if (!outcome.IsSuccess()) throw S3Error( outcome.GetError().GetErrorType(), - s + ": " + outcome.GetError().GetMessage()); + fmt( + "%s: %s (request id: %s)", + s, + outcome.GetError().GetMessage(), + outcome.GetError().GetRequestId())); return outcome.GetResultWithOwnership(); } @@ -121,9 +125,10 @@ class RetryStrategy : public Aws::Client::DefaultRetryStrategy checkInterrupt(); auto retry = Aws::Client::DefaultRetryStrategy::ShouldRetry(error, attemptedRetries); if (retry) - printError("AWS error '%s' (%s), will retry in %d ms", + printError("AWS error '%s' (%s; request id: %s), will retry in %d ms", error.GetExceptionName(), error.GetMessage(), + error.GetRequestId(), CalculateDelayBeforeNextRetry(error, attemptedRetries)); return retry; } From 3b21ea40cc6b6b9d512c15facb2e24c32a368993 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 4 Dec 2024 16:52:30 +0100 Subject: [PATCH 514/718] HttpBinaryCacheStore: Improve error message for unauthorized caches Instead of the unhelpful warning: 'https://cache.flakehub.com' does not appear to be a binary cache you now get warning: unable to download 'https://cache.flakehub.com/nix-cache-info': HTTP error 401 response body: {"code":401,"error":"Unauthorized","message":"Unauthorized."} --- src/libstore/binary-cache-store.cc | 13 ++++++++----- src/libstore/binary-cache-store.hh | 8 ++++++++ src/libstore/http-binary-cache-store.cc | 13 +++++++++++++ 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/libstore/binary-cache-store.cc b/src/libstore/binary-cache-store.cc index e8c8892b3..896779f85 100644 --- a/src/libstore/binary-cache-store.cc +++ b/src/libstore/binary-cache-store.cc @@ -39,15 +39,13 @@ BinaryCacheStore::BinaryCacheStore(const Params & params) void BinaryCacheStore::init() { - std::string cacheInfoFile = "nix-cache-info"; - - auto cacheInfo = getFile(cacheInfoFile); + auto cacheInfo = getNixCacheInfo(); if (!cacheInfo) { upsertFile(cacheInfoFile, "StoreDir: " + storeDir + "\n", "text/x-nix-cache-info"); } else { for (auto & line : tokenizeString(*cacheInfo, "\n")) { - size_t colon= line.find(':'); - if (colon ==std::string::npos) continue; + size_t colon = line.find(':'); + if (colon == std::string::npos) continue; auto name = line.substr(0, colon); auto value = trim(line.substr(colon + 1, std::string::npos)); if (name == "StoreDir") { @@ -63,6 +61,11 @@ void BinaryCacheStore::init() } } +std::optional BinaryCacheStore::getNixCacheInfo() +{ + return getFile(cacheInfoFile); +} + void BinaryCacheStore::upsertFile(const std::string & path, std::string && data, const std::string & mimeType) diff --git a/src/libstore/binary-cache-store.hh b/src/libstore/binary-cache-store.hh index 695bc9252..6bd7fd14a 100644 --- a/src/libstore/binary-cache-store.hh +++ b/src/libstore/binary-cache-store.hh @@ -64,6 +64,8 @@ protected: // The prefix under which realisation infos will be stored const std::string realisationsPrefix = "realisations"; + const std::string cacheInfoFile = "nix-cache-info"; + BinaryCacheStore(const Params & params); public: @@ -84,6 +86,12 @@ public: */ virtual void getFile(const std::string & path, Sink & sink); + /** + * Get the contents of /nix-cache-info. Return std::nullopt if it + * doesn't exist. + */ + virtual std::optional getNixCacheInfo(); + /** * Fetch the specified file and call the specified callback with * the result. A subclass may implement this asynchronously. diff --git a/src/libstore/http-binary-cache-store.cc b/src/libstore/http-binary-cache-store.cc index fc7ac2dea..f32616f94 100644 --- a/src/libstore/http-binary-cache-store.cc +++ b/src/libstore/http-binary-cache-store.cc @@ -194,6 +194,19 @@ protected: } } + std::optional getNixCacheInfo() override + { + try { + auto result = getFileTransfer()->download(makeRequest(cacheInfoFile)); + return result.data; + } catch (FileTransferError & e) { + if (e.error == FileTransfer::NotFound) + return std::nullopt; + maybeDisable(); + throw; + } + } + /** * This isn't actually necessary read only. We support "upsert" now, so we * have a notion of authentication via HTTP POST/PUT. From d1894f34566cb1a7c56b4225e0faf700dfd5b22d Mon Sep 17 00:00:00 2001 From: wh0 Date: Wed, 4 Dec 2024 23:21:07 -0800 Subject: [PATCH 515/718] tests: derivation-advanced-attributes unset NIX_STORE when built by nix, NIX_STORE is set, which breaks $got when it is not the default /nix/store --- tests/functional/derivation-advanced-attributes.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/functional/derivation-advanced-attributes.sh b/tests/functional/derivation-advanced-attributes.sh index 271f17dc6..6707b345c 100755 --- a/tests/functional/derivation-advanced-attributes.sh +++ b/tests/functional/derivation-advanced-attributes.sh @@ -13,7 +13,7 @@ badExitCode=0 store="$TEST_ROOT/store" for nixFile in derivation/*.nix; do - drvPath=$(nix-instantiate --store "$store" --pure-eval --expr "$(< "$nixFile")") + drvPath=$(env -u NIX_STORE nix-instantiate --store "$store" --pure-eval --expr "$(< "$nixFile")") testName=$(basename "$nixFile" .nix) got="${store}${drvPath}" expected="derivation/$testName.drv" From 52f1cd05956b7745985c5565a463633f0b805639 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 5 Dec 2024 16:02:35 +0100 Subject: [PATCH 516/718] nix hash convert: Support SRI hashes that lack trailing '=' characters Fixes #11996. --- src/libutil/hash.cc | 3 ++- src/nix/hash.cc | 9 ++++++--- tests/functional/hash-convert.sh | 14 ++++++++------ 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/libutil/hash.cc b/src/libutil/hash.cc index 748176d33..b69dec685 100644 --- a/src/libutil/hash.cc +++ b/src/libutil/hash.cc @@ -134,7 +134,8 @@ std::string Hash::to_string(HashFormat hashFormat, bool includeAlgo) const Hash Hash::dummy(HashAlgorithm::SHA256); -Hash Hash::parseSRI(std::string_view original) { +Hash Hash::parseSRI(std::string_view original) +{ auto rest = original; // Parse the has type before the separater, if there was one. diff --git a/src/nix/hash.cc b/src/nix/hash.cc index 2f9b3fe7c..654e67437 100644 --- a/src/nix/hash.cc +++ b/src/nix/hash.cc @@ -222,9 +222,12 @@ struct CmdHashConvert : Command Category category() override { return catUtility; } void run() override { - for (const auto& s: hashStrings) { - Hash h = Hash::parseAny(s, algo); - if (from && h.to_string(*from, from == HashFormat::SRI) != s) { + for (const auto & s: hashStrings) { + Hash h = + from == HashFormat::SRI + ? Hash::parseSRI(s) + : Hash::parseAny(s, algo); + if (from && from != HashFormat::SRI && h.to_string(*from, false) != s) { auto from_as_string = printHashFormat(*from); throw BadHash("input hash '%s' does not have the expected format '--from %s'", s, from_as_string); } diff --git a/tests/functional/hash-convert.sh b/tests/functional/hash-convert.sh index 3a099950f..1cbe864f3 100755 --- a/tests/functional/hash-convert.sh +++ b/tests/functional/hash-convert.sh @@ -93,15 +93,17 @@ try3() { # Asserting input format fails. # - fail=$(nix hash convert --hash-algo "$1" --from nix32 "$2" 2>&1 || echo "exit: $?") - [[ "$fail" == *"error: input hash"*"exit: 1" ]] - fail=$(nix hash convert --hash-algo "$1" --from base16 "$3" 2>&1 || echo "exit: $?") - [[ "$fail" == *"error: input hash"*"exit: 1" ]] - fail=$(nix hash convert --hash-algo "$1" --from nix32 "$4" 2>&1 || echo "exit: $?") - [[ "$fail" == *"error: input hash"*"exit: 1" ]] + expectStderr 1 nix hash convert --hash-algo "$1" --from sri "$2" | grepQuiet "is not SRI" + expectStderr 1 nix hash convert --hash-algo "$1" --from nix32 "$2" | grepQuiet "input hash" + expectStderr 1 nix hash convert --hash-algo "$1" --from base16 "$3" | grepQuiet "input hash" + expectStderr 1 nix hash convert --hash-algo "$1" --from nix32 "$4" | grepQuiet "input hash" } try3 sha1 "800d59cfcd3c05e900cb4e214be48f6b886a08df" "vw46m23bizj4n8afrc0fj19wrp7mj3c0" "gA1Zz808BekAy04hS+SPa4hqCN8=" try3 sha256 "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" "1b8m03r63zqhnjf7l5wnldhh7c134ap5vpj0850ymkq1iyzicy5s" "ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0=" try3 sha512 "204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445" "12k9jiq29iyqm03swfsgiw5mlqs173qazm3n7daz43infy12pyrcdf30fkk3qwv4yl2ick8yipc2mqnlh48xsvvxl60lbx8vp38yji0" "IEqPxt2oLwoM7XvrjgikFlfBbvRosiioJ5vjMacDwzWW/RXBOxsH+aodO+pXeJygMa2Fx6cd1wNU7GMSOMo0RQ==" + +# Test SRI hashes that lack trailing '=' characters. These are incorrect but we need to support them for backward compatibility. +[[ $(nix hash convert --from sri "sha256-ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0") = sha256-ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0= ]] +[[ $(nix hash convert --from sri "sha512-IEqPxt2oLwoM7XvrjgikFlfBbvRosiioJ5vjMacDwzWW/RXBOxsH+aodO+pXeJygMa2Fx6cd1wNU7GMSOMo0RQ") = sha512-IEqPxt2oLwoM7XvrjgikFlfBbvRosiioJ5vjMacDwzWW/RXBOxsH+aodO+pXeJygMa2Fx6cd1wNU7GMSOMo0RQ== ]] From 33b645cedfabd4f275644ac4df0eac220f444278 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 5 Dec 2024 16:19:21 +0100 Subject: [PATCH 517/718] nix hash convert: Don't fail on uppercase base-16 hashes --- src/nix/hash.cc | 10 +++++++--- tests/functional/hash-convert.sh | 2 ++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/nix/hash.cc b/src/nix/hash.cc index 654e67437..fd07fa7d1 100644 --- a/src/nix/hash.cc +++ b/src/nix/hash.cc @@ -222,14 +222,18 @@ struct CmdHashConvert : Command Category category() override { return catUtility; } void run() override { - for (const auto & s: hashStrings) { + for (const auto & s : hashStrings) { Hash h = from == HashFormat::SRI ? Hash::parseSRI(s) : Hash::parseAny(s, algo); - if (from && from != HashFormat::SRI && h.to_string(*from, false) != s) { + if (from + && from != HashFormat::SRI + && h.to_string(*from, false) != + (from == HashFormat::Base16 ? toLower(s) : s)) + { auto from_as_string = printHashFormat(*from); - throw BadHash("input hash '%s' does not have the expected format '--from %s'", s, from_as_string); + throw BadHash("input hash '%s' does not have the expected format for '--from %s'", s, from_as_string); } logger->cout(h.to_string(to, to == HashFormat::SRI)); } diff --git a/tests/functional/hash-convert.sh b/tests/functional/hash-convert.sh index 1cbe864f3..c40cb469c 100755 --- a/tests/functional/hash-convert.sh +++ b/tests/functional/hash-convert.sh @@ -98,6 +98,8 @@ try3() { expectStderr 1 nix hash convert --hash-algo "$1" --from base16 "$3" | grepQuiet "input hash" expectStderr 1 nix hash convert --hash-algo "$1" --from nix32 "$4" | grepQuiet "input hash" + # Base-16 hashes can be in uppercase. + nix hash convert --hash-algo "$1" --from base16 "$(echo $2 | tr [a-z] [A-Z])" } try3 sha1 "800d59cfcd3c05e900cb4e214be48f6b886a08df" "vw46m23bizj4n8afrc0fj19wrp7mj3c0" "gA1Zz808BekAy04hS+SPa4hqCN8=" From 408c2faf9365ab1b6f9e28551429d9352f9e7f1a Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 5 Dec 2024 16:25:05 +0100 Subject: [PATCH 518/718] nix hash: Don't print 'nix hash' deprecation message Fixes #11997. --- src/nix/hash.cc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/nix/hash.cc b/src/nix/hash.cc index fd07fa7d1..416cd19b3 100644 --- a/src/nix/hash.cc +++ b/src/nix/hash.cc @@ -163,8 +163,11 @@ struct CmdToBase : Command HashFormat hashFormat; std::optional hashAlgo; std::vector args; + bool legacyCli; - CmdToBase(HashFormat hashFormat) : hashFormat(hashFormat) + CmdToBase(HashFormat hashFormat, bool legacyCli = false) + : hashFormat(hashFormat) + , legacyCli(legacyCli) { addFlag(flag::hashAlgoOpt("type", &hashAlgo)); expectArgs("strings", &args); @@ -181,7 +184,8 @@ struct CmdToBase : Command void run() override { - warn("The old format conversion sub commands of `nix hash` were deprecated in favor of `nix hash convert`."); + if (!legacyCli) + warn("The old format conversion subcommands of `nix hash` were deprecated in favor of `nix hash convert`."); for (const auto & s : args) logger->cout(Hash::parseAny(s, hashAlgo).to_string(hashFormat, hashFormat == HashFormat::SRI)); } @@ -328,7 +332,7 @@ static int compatNixHash(int argc, char * * argv) } else { - CmdToBase cmd(hashFormat); + CmdToBase cmd(hashFormat, true); cmd.args = ss; if (hashAlgo.has_value()) cmd.hashAlgo = hashAlgo; cmd.run(); From 4137ead7a1011c3f410899be089822e8cf33862e Mon Sep 17 00:00:00 2001 From: Graham Christensen Date: Thu, 5 Dec 2024 14:01:00 -0500 Subject: [PATCH 519/718] Disable suid and atime on the /nix mount point on Darwin The Determinate Nix Installer has set nosuid and noatime in https://github.com/DeterminateSystems/nix-installer/pull/1338, and figured this perf and security improvement is worthy of upstreaming. The /nix volume shouldn't have setuid binaries anyway, and filesystems seem to generally be noatime on macOS. Further, the garbage collector doesn't use atime. --- scripts/create-darwin-volume.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/create-darwin-volume.sh b/scripts/create-darwin-volume.sh index 103e1e391..7a61764d4 100755 --- a/scripts/create-darwin-volume.sh +++ b/scripts/create-darwin-volume.sh @@ -463,7 +463,7 @@ EOF EDITOR="$SCRATCH/ex_cleanroom_wrapper" _sudo "to add nix to fstab" "$@" < Date: Thu, 5 Dec 2024 20:10:59 +0100 Subject: [PATCH 520/718] Fix typo (#12015) --- src/libexpr/primops.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 7e13e945c..5202ef7d7 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -1100,7 +1100,7 @@ static RegisterPrimOp primop_warn({ .name = "__warn", .args = {"e1", "e2"}, .doc = R"( - Evaluate *e1*, which must be a string and print iton standard error as a warning. + Evaluate *e1*, which must be a string, and print it on standard error as a warning. Then return *e2*. This function is useful for non-critical situations where attention is advisable. From ad296eae2a1f1b6ad6399f364f8dc91c80923922 Mon Sep 17 00:00:00 2001 From: "Shahar \"Dawn\" Or" Date: Sat, 7 Dec 2024 06:37:30 +0700 Subject: [PATCH 521/718] Test: more specific error message for `head` Sorry, I'm not sure how to implement this. So just a test change. And hopefully will be picked up by someone who is paying attention. A hero. --- src/libexpr-tests/error_traces.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libexpr-tests/error_traces.cc b/src/libexpr-tests/error_traces.cc index be379a909..011a0848d 100644 --- a/src/libexpr-tests/error_traces.cc +++ b/src/libexpr-tests/error_traces.cc @@ -712,7 +712,7 @@ namespace nix { ASSERT_TRACE1("head []", Error, - HintFmt("list index %d is out of bounds", 0)); + HintFmt("'head' called on an empty list")); } From ad3a67a2a0dc815219593a7aae306db8ed8ec3a3 Mon Sep 17 00:00:00 2001 From: Philipp Otterbein Date: Sat, 7 Dec 2024 04:42:04 +0100 Subject: [PATCH 522/718] optimize string concat --- src/libutil/util.hh | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/libutil/util.hh b/src/libutil/util.hh index 0fb6ff837..4d5683e2b 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -338,7 +338,9 @@ std::string showBytes(uint64_t bytes); */ inline std::string operator + (const std::string & s1, std::string_view s2) { - auto s = s1; + std::string s; + s.reserve(s1.size() + s2.size()); + s.append(s1); s.append(s2); return s; } @@ -351,10 +353,11 @@ inline std::string operator + (std::string && s, std::string_view s2) inline std::string operator + (std::string_view s1, const char * s2) { + auto s2Size = strlen(s2); std::string s; - s.reserve(s1.size() + strlen(s2)); + s.reserve(s1.size() + s2Size); s.append(s1); - s.append(s2); + s.append(s2, s2Size); return s; } From 8b9e0f86e406b53911b6c2d1ec4066a767c44b3c Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 9 Dec 2024 13:56:03 +0100 Subject: [PATCH 523/718] nix flake lock: Fail if there is an unlocked input Since the only purpose of `nix flake lock` is to write a new lock file, it should be a fatal error if we can't write the lock file. --- src/libflake/flake/flake.cc | 2 ++ src/libflake/flake/flake.hh | 5 +++++ src/nix/flake.cc | 1 + tests/functional/flakes/unlocked-override.sh | 3 +++ 4 files changed, 11 insertions(+) diff --git a/src/libflake/flake/flake.cc b/src/libflake/flake/flake.cc index 19b622a34..2165ffd8d 100644 --- a/src/libflake/flake/flake.cc +++ b/src/libflake/flake/flake.cc @@ -672,6 +672,8 @@ LockedFlake lockFlake( if (lockFlags.writeLockFile) { if (sourcePath || lockFlags.outputLockFilePath) { if (auto unlockedInput = newLockFile.isUnlocked()) { + if (lockFlags.failOnUnlocked) + throw Error("cannot write lock file of flake '%s' because it has an unlocked input ('%s').\n", topRef, *unlockedInput); if (state.fetchSettings.warnDirty) warn("will not write lock file of flake '%s' because it has an unlocked input ('%s')", topRef, *unlockedInput); } else { diff --git a/src/libflake/flake/flake.hh b/src/libflake/flake/flake.hh index cc2bea76e..0dfd9440d 100644 --- a/src/libflake/flake/flake.hh +++ b/src/libflake/flake/flake.hh @@ -156,6 +156,11 @@ struct LockFlags */ bool writeLockFile = true; + /** + * Throw an exception when the flake has an unlocked input. + */ + bool failOnUnlocked = false; + /** * Whether to use the registries to lookup indirect flake * references like 'nixpkgs'. diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 9f3584a11..55aa8971e 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -162,6 +162,7 @@ struct CmdFlakeLock : FlakeCommand settings.tarballTtl = 0; lockFlags.writeLockFile = true; + lockFlags.failOnUnlocked = true; lockFlags.applyNixConfig = true; lockFlake(); diff --git a/tests/functional/flakes/unlocked-override.sh b/tests/functional/flakes/unlocked-override.sh index a17a0c2af..ebad332d0 100755 --- a/tests/functional/flakes/unlocked-override.sh +++ b/tests/functional/flakes/unlocked-override.sh @@ -30,3 +30,6 @@ git -C "$flake2Dir" add flake.nix echo 456 > "$flake1Dir"/x.nix [[ $(nix eval --json "$flake2Dir#x" --override-input flake1 "$TEST_ROOT/flake1") = 456 ]] + +expectStderr 1 nix flake lock "$flake2Dir" --override-input flake1 "$TEST_ROOT/flake1" | + grepQuiet "cannot write lock file.*because it has an unlocked input" From e82ff51726b33b95152c4c64dc870eab831936f9 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 20 Nov 2024 11:05:55 +0100 Subject: [PATCH 524/718] tests/functional/dependencies.nix: Refactor, replace arcane let --- tests/functional/dependencies.nix | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/tests/functional/dependencies.nix b/tests/functional/dependencies.nix index be1a7ae9a..4ff29227f 100644 --- a/tests/functional/dependencies.nix +++ b/tests/functional/dependencies.nix @@ -1,7 +1,7 @@ { hashInvalidator ? "" }: with import ./config.nix; -let { +let input0 = mkDerivation { name = "dependencies-input-0"; @@ -33,16 +33,15 @@ let { outputHash = "1dq9p0hnm1y75q2x40fws5887bq1r840hzdxak0a9djbwvx0b16d"; }; - body = mkDerivation { - name = "dependencies-top"; - builder = ./dependencies.builder0.sh + "/FOOBAR/../."; - input1 = input1 + "/."; - input2 = "${input2}/."; - input1_drv = input1; - input2_drv = input2; - input0_drv = input0; - fod_input_drv = fod_input; - meta.description = "Random test package"; - }; - +in +mkDerivation { + name = "dependencies-top"; + builder = ./dependencies.builder0.sh + "/FOOBAR/../."; + input1 = input1 + "/."; + input2 = "${input2}/."; + input1_drv = input1; + input2_drv = input2; + input0_drv = input0; + fod_input_drv = fod_input; + meta.description = "Random test package"; } From ee03fd478e99d90eb02baefda6dee7eb9a3c347f Mon Sep 17 00:00:00 2001 From: Linus Heckemann Date: Fri, 11 Oct 2024 17:16:32 +0200 Subject: [PATCH 525/718] libutil: handle json builder log messages with unexpected format Before this change, expressions like: with import {}; runCommand "foo" {} '' echo '@nix {}' >&$NIX_LOG_FD '' would result in Lix crashing, because accessing nonexistent fields of a JSON object throws an exception. Rather than handling each field individually, we just catch JSON exceptions wholesale. Since these log messages are an unusual circumstance, log a warning when this happens. Fixes #544. Change-Id: Idc2d8acf6e37046b3ec212f42e29269163dca893 (cherry picked from commit e55cd3beea710db727fd966f265a1b715b7285f3) --- src/libutil/logging.cc | 66 +++++++++++++++++-------------- tests/functional/dependencies.nix | 13 ++++++ 2 files changed, 50 insertions(+), 29 deletions(-) diff --git a/src/libutil/logging.cc b/src/libutil/logging.cc index 80c107ef5..0eceee6d4 100644 --- a/src/libutil/logging.cc +++ b/src/libutil/logging.cc @@ -295,37 +295,45 @@ bool handleJSONLogMessage(nlohmann::json & json, const Activity & act, std::map & activities, bool trusted) { - std::string action = json["action"]; + try { + std::string action = json["action"]; - if (action == "start") { - auto type = (ActivityType) json["type"]; - if (trusted || type == actFileTransfer) - activities.emplace(std::piecewise_construct, - std::forward_as_tuple(json["id"]), - std::forward_as_tuple(*logger, (Verbosity) json["level"], type, - json["text"], getFields(json["fields"]), act.id)); + if (action == "start") { + auto type = (ActivityType) json["type"]; + if (trusted || type == actFileTransfer) + activities.emplace(std::piecewise_construct, + std::forward_as_tuple(json["id"]), + std::forward_as_tuple(*logger, (Verbosity) json["level"], type, + json["text"], getFields(json["fields"]), act.id)); + } + + else if (action == "stop") + activities.erase((ActivityId) json["id"]); + + else if (action == "result") { + auto i = activities.find((ActivityId) json["id"]); + if (i != activities.end()) + i->second.result((ResultType) json["type"], getFields(json["fields"])); + } + + else if (action == "setPhase") { + std::string phase = json["phase"]; + act.result(resSetPhase, phase); + } + + else if (action == "msg") { + std::string msg = json["msg"]; + logger->log((Verbosity) json["level"], msg); + } + + return true; + } catch (const nlohmann::json::exception &e) { + warn( + "warning: Unable to handle a JSON message from the builder: %s", + e.what() + ); + return false; } - - else if (action == "stop") - activities.erase((ActivityId) json["id"]); - - else if (action == "result") { - auto i = activities.find((ActivityId) json["id"]); - if (i != activities.end()) - i->second.result((ResultType) json["type"], getFields(json["fields"])); - } - - else if (action == "setPhase") { - std::string phase = json["phase"]; - act.result(resSetPhase, phase); - } - - else if (action == "msg") { - std::string msg = json["msg"]; - logger->log((Verbosity) json["level"], msg); - } - - return true; } bool handleJSONLogMessage(const std::string & msg, diff --git a/tests/functional/dependencies.nix b/tests/functional/dependencies.nix index 4ff29227f..64d9d2360 100644 --- a/tests/functional/dependencies.nix +++ b/tests/functional/dependencies.nix @@ -33,6 +33,18 @@ let outputHash = "1dq9p0hnm1y75q2x40fws5887bq1r840hzdxak0a9djbwvx0b16d"; }; + unusual-logging = mkDerivation { + name = "unusual-logging"; + buildCommand = '' + { + echo "@nix 1" + echo "@nix {}" + echo '@nix {"action": null}' + } >&$NIX_LOG_FD + touch $out + ''; + }; + in mkDerivation { name = "dependencies-top"; @@ -42,6 +54,7 @@ mkDerivation { input1_drv = input1; input2_drv = input2; input0_drv = input0; + unusual_logging_drv = unusual-logging; fod_input_drv = fod_input; meta.description = "Random test package"; } From 1485937b897bc88cda0848b54b8ad9310230c47b Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 20 Nov 2024 11:16:39 +0100 Subject: [PATCH 526/718] tests/functional/dependencies.nix: Check that we tolerate syntax and type errors --- tests/functional/dependencies.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/functional/dependencies.nix b/tests/functional/dependencies.nix index 64d9d2360..d177f5b63 100644 --- a/tests/functional/dependencies.nix +++ b/tests/functional/dependencies.nix @@ -40,6 +40,8 @@ let echo "@nix 1" echo "@nix {}" echo '@nix {"action": null}' + echo '@nix {"action": 123}' + echo '@nix ][' } >&$NIX_LOG_FD touch $out ''; From 03d4bfd852dce9a050f984e887c887a43581796c Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Thu, 21 Nov 2024 16:03:21 +0100 Subject: [PATCH 527/718] Push log source description out of libutil and report build hook @nix warning correctly --- src/libstore/build/derivation-goal.cc | 8 ++++---- src/libutil/logging.cc | 17 ++++++++++------- src/libutil/logging.hh | 13 ++++++++++++- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/libstore/build/derivation-goal.cc b/src/libstore/build/derivation-goal.cc index bf1a25db1..2ff0ef92f 100644 --- a/src/libstore/build/derivation-goal.cc +++ b/src/libstore/build/derivation-goal.cc @@ -1161,7 +1161,7 @@ HookReply DerivationGoal::tryBuildHook() throw; } }(); - if (handleJSONLogMessage(s, worker.act, worker.hook->activities, true)) + if (handleJSONLogMessage(s, worker.act, worker.hook->activities, "the build hook", true)) ; else if (s.substr(0, 2) == "# ") { reply = s.substr(2); @@ -1346,9 +1346,9 @@ void DerivationGoal::handleChildOutput(Descriptor fd, std::string_view data) if (hook && fd == hook->fromHook.readSide.get()) { for (auto c : data) if (c == '\n') { - auto json = parseJSONMessage(currentHookLine); + auto json = parseJSONMessage(currentHookLine, "the derivation builder"); if (json) { - auto s = handleJSONLogMessage(*json, worker.act, hook->activities, true); + auto s = handleJSONLogMessage(*json, worker.act, hook->activities, "the derivation builder", true); // ensure that logs from a builder using `ssh-ng://` as protocol // are also available to `nix log`. if (s && !isWrittenToLog && logSink) { @@ -1390,7 +1390,7 @@ void DerivationGoal::handleEOF(Descriptor fd) void DerivationGoal::flushLine() { - if (handleJSONLogMessage(currentLogLine, *act, builderActivities, false)) + if (handleJSONLogMessage(currentLogLine, *act, builderActivities, "the derivation builder", false)) ; else { diff --git a/src/libutil/logging.cc b/src/libutil/logging.cc index 0eceee6d4..4c7061016 100644 --- a/src/libutil/logging.cc +++ b/src/libutil/logging.cc @@ -280,20 +280,22 @@ static Logger::Fields getFields(nlohmann::json & json) return fields; } -std::optional parseJSONMessage(const std::string & msg) +std::optional parseJSONMessage(const std::string & msg, std::string_view source) { if (!hasPrefix(msg, "@nix ")) return std::nullopt; try { return nlohmann::json::parse(std::string(msg, 5)); } catch (std::exception & e) { - printError("bad JSON log message from builder: %s", e.what()); + printError("bad JSON log message from %s: %s", + Uncolored(source), + e.what()); } return std::nullopt; } bool handleJSONLogMessage(nlohmann::json & json, const Activity & act, std::map & activities, - bool trusted) + std::string_view source, bool trusted) { try { std::string action = json["action"]; @@ -329,7 +331,8 @@ bool handleJSONLogMessage(nlohmann::json & json, return true; } catch (const nlohmann::json::exception &e) { warn( - "warning: Unable to handle a JSON message from the builder: %s", + "warning: Unable to handle a JSON message from %s: %s", + Uncolored(source), e.what() ); return false; @@ -337,12 +340,12 @@ bool handleJSONLogMessage(nlohmann::json & json, } bool handleJSONLogMessage(const std::string & msg, - const Activity & act, std::map & activities, bool trusted) + const Activity & act, std::map & activities, std::string_view source, bool trusted) { - auto json = parseJSONMessage(msg); + auto json = parseJSONMessage(msg, source); if (!json) return false; - return handleJSONLogMessage(*json, act, activities, trusted); + return handleJSONLogMessage(*json, act, activities, source, trusted); } Activity::~Activity() diff --git a/src/libutil/logging.hh b/src/libutil/logging.hh index 250f92099..11e4033a5 100644 --- a/src/libutil/logging.hh +++ b/src/libutil/logging.hh @@ -185,14 +185,25 @@ Logger * makeSimpleLogger(bool printBuildLogs = true); Logger * makeJSONLogger(Logger & prevLogger); -std::optional parseJSONMessage(const std::string & msg); +/** + * @param source A noun phrase describing the source of the message, e.g. "the builder". + */ +std::optional parseJSONMessage(const std::string & msg, std::string_view source); +/** + * @param source A noun phrase describing the source of the message, e.g. "the builder". + */ bool handleJSONLogMessage(nlohmann::json & json, const Activity & act, std::map & activities, + std::string_view source, bool trusted); +/** + * @param source A noun phrase describing the source of the message, e.g. "the builder". + */ bool handleJSONLogMessage(const std::string & msg, const Activity & act, std::map & activities, + std::string_view source, bool trusted); /** From 8490fba42d49cec068eea0a442bdc125c0030cd2 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 9 Dec 2024 16:15:23 +0100 Subject: [PATCH 528/718] Improve error messages for head/elemAt --- src/libexpr-tests/error_traces.cc | 14 ++++++------ src/libexpr/primops.cc | 36 ++++++++++++++++--------------- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/libexpr-tests/error_traces.cc b/src/libexpr-tests/error_traces.cc index 011a0848d..2aa13cf62 100644 --- a/src/libexpr-tests/error_traces.cc +++ b/src/libexpr-tests/error_traces.cc @@ -691,15 +691,15 @@ namespace nix { ASSERT_TRACE2("elemAt \"foo\" (-1)", TypeError, HintFmt("expected a list but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)), - HintFmt("while evaluating the first argument passed to builtins.elemAt")); + HintFmt("while evaluating the first argument passed to 'builtins.elemAt'")); ASSERT_TRACE1("elemAt [] (-1)", Error, - HintFmt("list index %d is out of bounds", -1)); + HintFmt("'builtins.elemAt' called with index %d on a list of size %d", -1, 0)); ASSERT_TRACE1("elemAt [\"foo\"] 3", Error, - HintFmt("list index %d is out of bounds", 3)); + HintFmt("'builtins.elemAt' called with index %d on a list of size %d", 3, 1)); } @@ -708,11 +708,11 @@ namespace nix { ASSERT_TRACE2("head 1", TypeError, HintFmt("expected a list but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating the first argument passed to builtins.elemAt")); + HintFmt("while evaluating the first argument passed to 'builtins.head'")); ASSERT_TRACE1("head []", Error, - HintFmt("'head' called on an empty list")); + HintFmt("'builtins.head' called on an empty list")); } @@ -721,11 +721,11 @@ namespace nix { ASSERT_TRACE2("tail 1", TypeError, HintFmt("expected a list but found %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)), - HintFmt("while evaluating the first argument passed to builtins.tail")); + HintFmt("while evaluating the first argument passed to 'builtins.tail'")); ASSERT_TRACE1("tail []", Error, - HintFmt("'tail' called on an empty list")); + HintFmt("'builtins.tail' called on an empty list")); } diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 5202ef7d7..7c5c6ea9b 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -3259,23 +3259,19 @@ static RegisterPrimOp primop_isList({ .fun = prim_isList, }); -static void elemAt(EvalState & state, const PosIdx pos, Value & list, int n, Value & v) -{ - state.forceList(list, pos, "while evaluating the first argument passed to builtins.elemAt"); - if (n < 0 || (unsigned int) n >= list.listSize()) - state.error( - "list index %1% is out of bounds", - n - ).atPos(pos).debugThrow(); - state.forceValue(*list.listElems()[n], pos); - v = *list.listElems()[n]; -} - /* Return the n-1'th element of a list. */ static void prim_elemAt(EvalState & state, const PosIdx pos, Value * * args, Value & v) { - NixInt::Inner elem = state.forceInt(*args[1], pos, "while evaluating the second argument passed to builtins.elemAt").value; - elemAt(state, pos, *args[0], elem, v); + NixInt::Inner n = state.forceInt(*args[1], pos, "while evaluating the second argument passed to 'builtins.elemAt'").value; + state.forceList(*args[0], pos, "while evaluating the first argument passed to 'builtins.elemAt'"); + if (n < 0 || (unsigned int) n >= args[0]->listSize()) + state.error( + "'builtins.elemAt' called with index %d on a list of size %d", + n, + args[0]->listSize() + ).atPos(pos).debugThrow(); + state.forceValue(*args[0]->listElems()[n], pos); + v = *args[0]->listElems()[n]; } static RegisterPrimOp primop_elemAt({ @@ -3291,7 +3287,13 @@ static RegisterPrimOp primop_elemAt({ /* Return the first element of a list. */ static void prim_head(EvalState & state, const PosIdx pos, Value * * args, Value & v) { - elemAt(state, pos, *args[0], 0, v); + state.forceList(*args[0], pos, "while evaluating the first argument passed to 'builtins.head'"); + if (args[0]->listSize() == 0) + state.error( + "'builtins.head' called on an empty list" + ).atPos(pos).debugThrow(); + state.forceValue(*args[0]->listElems()[0], pos); + v = *args[0]->listElems()[0]; } static RegisterPrimOp primop_head({ @@ -3310,9 +3312,9 @@ static RegisterPrimOp primop_head({ don't want to use it! */ static void prim_tail(EvalState & state, const PosIdx pos, Value * * args, Value & v) { - state.forceList(*args[0], pos, "while evaluating the first argument passed to builtins.tail"); + state.forceList(*args[0], pos, "while evaluating the first argument passed to 'builtins.tail'"); if (args[0]->listSize() == 0) - state.error("'tail' called on an empty list").atPos(pos).debugThrow(); + state.error("'builtins.tail' called on an empty list").atPos(pos).debugThrow(); auto list = state.buildList(args[0]->listSize() - 1); for (const auto & [n, v] : enumerate(list)) From 1edf868213a5462b67c3c269f34bf8555c77758a Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 9 Dec 2024 16:49:02 +0100 Subject: [PATCH 529/718] rename: nix-tests -> nix-daemon-compat-tests I think I have failed to read the very long version-garbage-like string for the second time now, leaving me oblivious to the crucial info that a test failure happens in the context of an older daemon. --- packaging/hydra.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packaging/hydra.nix b/packaging/hydra.nix index 81406a249..6109f479e 100644 --- a/packaging/hydra.nix +++ b/packaging/hydra.nix @@ -19,11 +19,11 @@ let testNixVersions = pkgs: daemon: pkgs.nixComponents.nix-functional-tests.override { pname = - "nix-tests" + "nix-daemon-compat-tests" + lib.optionalString (lib.versionAtLeast daemon.version "2.4pre20211005" && lib.versionAtLeast pkgs.nix.version "2.4pre20211005") - "-${pkgs.nix.version}-against-${daemon.version}"; + "-${pkgs.nix.version}-with-daemon-${daemon.version}"; test-daemon = daemon; }; From d0b4db924a80d74540b81a6b717aa01498df8ceb Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 9 Dec 2024 16:39:48 +0100 Subject: [PATCH 530/718] rename: build-utils-meson -> nix-meson-build-support Fix a footgun. In my case, I had a couple of build ("output") directories sitting around. rm -rf build-* Was confused for a bit why a meson.build file was missing. Probably also helps with autocompletion. I tried meson-build-support first, but I had to add something like a nix- prefix, in order to make meson happy. They've reserved the meson- prefix. --- .../common/meson.build | 0 .../deps-lists/meson.build | 0 .../export-all-symbols/meson.build | 0 .../export/meson.build | 0 .../generate-header/meson.build | 0 .../libatomic/meson.build | 0 .../subprojects/meson.build | 0 .../windows-version/meson.build | 0 src/libcmd/build-utils-meson | 1 - src/libcmd/meson.build | 8 ++++---- src/libcmd/nix-meson-build-support | 1 + src/libcmd/package.nix | 4 ++-- src/libexpr-c/build-utils-meson | 1 - src/libexpr-c/meson.build | 12 ++++++------ src/libexpr-c/nix-meson-build-support | 1 + src/libexpr-c/package.nix | 4 ++-- src/libexpr-test-support/build-utils-meson | 1 - src/libexpr-test-support/meson.build | 12 ++++++------ src/libexpr-test-support/nix-meson-build-support | 1 + src/libexpr-test-support/package.nix | 4 ++-- src/libexpr-tests/build-utils-meson | 1 - src/libexpr-tests/meson.build | 10 +++++----- src/libexpr-tests/nix-meson-build-support | 1 + src/libexpr-tests/package.nix | 4 ++-- src/libexpr/build-utils-meson | 1 - src/libexpr/meson.build | 10 +++++----- src/libexpr/nix-meson-build-support | 1 + src/libexpr/package.nix | 4 ++-- src/libfetchers-tests/build-utils-meson | 1 - src/libfetchers-tests/meson.build | 10 +++++----- src/libfetchers-tests/nix-meson-build-support | 1 + src/libfetchers-tests/package.nix | 4 ++-- src/libfetchers/build-utils-meson | 1 - src/libfetchers/meson.build | 8 ++++---- src/libfetchers/nix-meson-build-support | 1 + src/libfetchers/package.nix | 4 ++-- src/libflake-c/build-utils-meson | 1 - src/libflake-c/meson.build | 12 ++++++------ src/libflake-c/nix-meson-build-support | 1 + src/libflake-c/package.nix | 4 ++-- src/libflake-tests/build-utils-meson | 1 - src/libflake-tests/meson.build | 10 +++++----- src/libflake-tests/nix-meson-build-support | 1 + src/libflake-tests/package.nix | 4 ++-- src/libflake/build-utils-meson | 1 - src/libflake/meson.build | 8 ++++---- src/libflake/nix-meson-build-support | 1 + src/libflake/package.nix | 4 ++-- src/libmain-c/build-utils-meson | 1 - src/libmain-c/meson.build | 12 ++++++------ src/libmain-c/nix-meson-build-support | 1 + src/libmain-c/package.nix | 4 ++-- src/libmain/build-utils-meson | 1 - src/libmain/meson.build | 8 ++++---- src/libmain/nix-meson-build-support | 1 + src/libmain/package.nix | 4 ++-- src/libstore-c/build-utils-meson | 1 - src/libstore-c/meson.build | 12 ++++++------ src/libstore-c/nix-meson-build-support | 1 + src/libstore-c/package.nix | 4 ++-- src/libstore-test-support/build-utils-meson | 1 - src/libstore-test-support/meson.build | 12 ++++++------ .../nix-meson-build-support | 1 + src/libstore-test-support/package.nix | 4 ++-- src/libstore-tests/build-utils-meson | 1 - src/libstore-tests/meson.build | 10 +++++----- src/libstore-tests/nix-meson-build-support | 1 + src/libstore-tests/package.nix | 4 ++-- src/libstore/build-utils-meson | 1 - src/libstore/meson.build | 16 ++++++++-------- src/libstore/nix-meson-build-support | 1 + src/libstore/package.nix | 4 ++-- src/libutil-c/build-utils-meson | 1 - src/libutil-c/meson.build | 12 ++++++------ src/libutil-c/nix-meson-build-support | 1 + src/libutil-c/package.nix | 4 ++-- src/libutil-test-support/build-utils-meson | 1 - src/libutil-test-support/meson.build | 12 ++++++------ src/libutil-test-support/nix-meson-build-support | 1 + src/libutil-test-support/package.nix | 4 ++-- src/libutil-tests/build-utils-meson | 1 - src/libutil-tests/meson.build | 10 +++++----- src/libutil-tests/nix-meson-build-support | 1 + src/libutil-tests/package.nix | 4 ++-- src/libutil/build-utils-meson | 1 - src/libutil/meson.build | 14 +++++++------- src/libutil/nix-meson-build-support | 1 + src/libutil/package.nix | 4 ++-- src/nix/build-utils-meson | 1 - src/nix/meson.build | 12 ++++++------ src/nix/nix-meson-build-support | 1 + src/nix/package.nix | 4 ++-- 92 files changed, 178 insertions(+), 178 deletions(-) rename {build-utils-meson => nix-meson-build-support}/common/meson.build (100%) rename {build-utils-meson => nix-meson-build-support}/deps-lists/meson.build (100%) rename {build-utils-meson => nix-meson-build-support}/export-all-symbols/meson.build (100%) rename {build-utils-meson => nix-meson-build-support}/export/meson.build (100%) rename {build-utils-meson => nix-meson-build-support}/generate-header/meson.build (100%) rename {build-utils-meson => nix-meson-build-support}/libatomic/meson.build (100%) rename {build-utils-meson => nix-meson-build-support}/subprojects/meson.build (100%) rename {build-utils-meson => nix-meson-build-support}/windows-version/meson.build (100%) delete mode 120000 src/libcmd/build-utils-meson create mode 120000 src/libcmd/nix-meson-build-support delete mode 120000 src/libexpr-c/build-utils-meson create mode 120000 src/libexpr-c/nix-meson-build-support delete mode 120000 src/libexpr-test-support/build-utils-meson create mode 120000 src/libexpr-test-support/nix-meson-build-support delete mode 120000 src/libexpr-tests/build-utils-meson create mode 120000 src/libexpr-tests/nix-meson-build-support delete mode 120000 src/libexpr/build-utils-meson create mode 120000 src/libexpr/nix-meson-build-support delete mode 120000 src/libfetchers-tests/build-utils-meson create mode 120000 src/libfetchers-tests/nix-meson-build-support delete mode 120000 src/libfetchers/build-utils-meson create mode 120000 src/libfetchers/nix-meson-build-support delete mode 120000 src/libflake-c/build-utils-meson create mode 120000 src/libflake-c/nix-meson-build-support delete mode 120000 src/libflake-tests/build-utils-meson create mode 120000 src/libflake-tests/nix-meson-build-support delete mode 120000 src/libflake/build-utils-meson create mode 120000 src/libflake/nix-meson-build-support delete mode 120000 src/libmain-c/build-utils-meson create mode 120000 src/libmain-c/nix-meson-build-support delete mode 120000 src/libmain/build-utils-meson create mode 120000 src/libmain/nix-meson-build-support delete mode 120000 src/libstore-c/build-utils-meson create mode 120000 src/libstore-c/nix-meson-build-support delete mode 120000 src/libstore-test-support/build-utils-meson create mode 120000 src/libstore-test-support/nix-meson-build-support delete mode 120000 src/libstore-tests/build-utils-meson create mode 120000 src/libstore-tests/nix-meson-build-support delete mode 120000 src/libstore/build-utils-meson create mode 120000 src/libstore/nix-meson-build-support delete mode 120000 src/libutil-c/build-utils-meson create mode 120000 src/libutil-c/nix-meson-build-support delete mode 120000 src/libutil-test-support/build-utils-meson create mode 120000 src/libutil-test-support/nix-meson-build-support delete mode 120000 src/libutil-tests/build-utils-meson create mode 120000 src/libutil-tests/nix-meson-build-support delete mode 120000 src/libutil/build-utils-meson create mode 120000 src/libutil/nix-meson-build-support delete mode 120000 src/nix/build-utils-meson create mode 120000 src/nix/nix-meson-build-support diff --git a/build-utils-meson/common/meson.build b/nix-meson-build-support/common/meson.build similarity index 100% rename from build-utils-meson/common/meson.build rename to nix-meson-build-support/common/meson.build diff --git a/build-utils-meson/deps-lists/meson.build b/nix-meson-build-support/deps-lists/meson.build similarity index 100% rename from build-utils-meson/deps-lists/meson.build rename to nix-meson-build-support/deps-lists/meson.build diff --git a/build-utils-meson/export-all-symbols/meson.build b/nix-meson-build-support/export-all-symbols/meson.build similarity index 100% rename from build-utils-meson/export-all-symbols/meson.build rename to nix-meson-build-support/export-all-symbols/meson.build diff --git a/build-utils-meson/export/meson.build b/nix-meson-build-support/export/meson.build similarity index 100% rename from build-utils-meson/export/meson.build rename to nix-meson-build-support/export/meson.build diff --git a/build-utils-meson/generate-header/meson.build b/nix-meson-build-support/generate-header/meson.build similarity index 100% rename from build-utils-meson/generate-header/meson.build rename to nix-meson-build-support/generate-header/meson.build diff --git a/build-utils-meson/libatomic/meson.build b/nix-meson-build-support/libatomic/meson.build similarity index 100% rename from build-utils-meson/libatomic/meson.build rename to nix-meson-build-support/libatomic/meson.build diff --git a/build-utils-meson/subprojects/meson.build b/nix-meson-build-support/subprojects/meson.build similarity index 100% rename from build-utils-meson/subprojects/meson.build rename to nix-meson-build-support/subprojects/meson.build diff --git a/build-utils-meson/windows-version/meson.build b/nix-meson-build-support/windows-version/meson.build similarity index 100% rename from build-utils-meson/windows-version/meson.build rename to nix-meson-build-support/windows-version/meson.build diff --git a/src/libcmd/build-utils-meson b/src/libcmd/build-utils-meson deleted file mode 120000 index 5fff21bab..000000000 --- a/src/libcmd/build-utils-meson +++ /dev/null @@ -1 +0,0 @@ -../../build-utils-meson \ No newline at end of file diff --git a/src/libcmd/meson.build b/src/libcmd/meson.build index 1f27c1614..222817c81 100644 --- a/src/libcmd/meson.build +++ b/src/libcmd/meson.build @@ -14,7 +14,7 @@ project('nix-cmd', 'cpp', cxx = meson.get_compiler('cpp') -subdir('build-utils-meson/deps-lists') +subdir('nix-meson-build-support/deps-lists') configdata = configuration_data() @@ -28,7 +28,7 @@ deps_public_maybe_subproject = [ dependency('nix-flake'), dependency('nix-main'), ] -subdir('build-utils-meson/subprojects') +subdir('nix-meson-build-support/subprojects') nlohmann_json = dependency('nlohmann_json', version : '>= 3.9') deps_public += nlohmann_json @@ -70,7 +70,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/common') +subdir('nix-meson-build-support/common') sources = files( 'built-path.cc', @@ -125,4 +125,4 @@ install_headers(headers, subdir : 'nix', preserve_path : true) libraries_private = [] -subdir('build-utils-meson/export') +subdir('nix-meson-build-support/export') diff --git a/src/libcmd/nix-meson-build-support b/src/libcmd/nix-meson-build-support new file mode 120000 index 000000000..0b140f56b --- /dev/null +++ b/src/libcmd/nix-meson-build-support @@ -0,0 +1 @@ +../../nix-meson-build-support \ No newline at end of file diff --git a/src/libcmd/package.nix b/src/libcmd/package.nix index 244179ee4..53e54d2f8 100644 --- a/src/libcmd/package.nix +++ b/src/libcmd/package.nix @@ -39,8 +39,8 @@ mkMesonLibrary (finalAttrs: { workDir = ./.; fileset = fileset.unions [ - ../../build-utils-meson - ./build-utils-meson + ../../nix-meson-build-support + ./nix-meson-build-support ../../.version ./.version ./meson.build diff --git a/src/libexpr-c/build-utils-meson b/src/libexpr-c/build-utils-meson deleted file mode 120000 index 5fff21bab..000000000 --- a/src/libexpr-c/build-utils-meson +++ /dev/null @@ -1 +0,0 @@ -../../build-utils-meson \ No newline at end of file diff --git a/src/libexpr-c/meson.build b/src/libexpr-c/meson.build index 5bcca29e0..1556dae51 100644 --- a/src/libexpr-c/meson.build +++ b/src/libexpr-c/meson.build @@ -14,7 +14,7 @@ project('nix-expr-c', 'cpp', cxx = meson.get_compiler('cpp') -subdir('build-utils-meson/deps-lists') +subdir('nix-meson-build-support/deps-lists') configdata = configuration_data() @@ -27,7 +27,7 @@ deps_public_maybe_subproject = [ dependency('nix-util-c'), dependency('nix-store-c'), ] -subdir('build-utils-meson/subprojects') +subdir('nix-meson-build-support/subprojects') # TODO rename, because it will conflict with downstream projects configdata.set_quoted('PACKAGE_VERSION', meson.project_version()) @@ -53,7 +53,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/common') +subdir('nix-meson-build-support/common') sources = files( 'nix_api_expr.cc', @@ -72,8 +72,8 @@ headers = [config_h] + files( # TODO move this header to libexpr, maybe don't use it in tests? headers += files('nix_api_expr_internal.h') -subdir('build-utils-meson/export-all-symbols') -subdir('build-utils-meson/windows-version') +subdir('nix-meson-build-support/export-all-symbols') +subdir('nix-meson-build-support/windows-version') this_library = library( 'nixexprc', @@ -89,4 +89,4 @@ install_headers(headers, subdir : 'nix', preserve_path : true) libraries_private = [] -subdir('build-utils-meson/export') +subdir('nix-meson-build-support/export') diff --git a/src/libexpr-c/nix-meson-build-support b/src/libexpr-c/nix-meson-build-support new file mode 120000 index 000000000..0b140f56b --- /dev/null +++ b/src/libexpr-c/nix-meson-build-support @@ -0,0 +1 @@ +../../nix-meson-build-support \ No newline at end of file diff --git a/src/libexpr-c/package.nix b/src/libexpr-c/package.nix index df49a8bdc..727b3a811 100644 --- a/src/libexpr-c/package.nix +++ b/src/libexpr-c/package.nix @@ -20,8 +20,8 @@ mkMesonLibrary (finalAttrs: { workDir = ./.; fileset = fileset.unions [ - ../../build-utils-meson - ./build-utils-meson + ../../nix-meson-build-support + ./nix-meson-build-support ../../.version ./.version ./meson.build diff --git a/src/libexpr-test-support/build-utils-meson b/src/libexpr-test-support/build-utils-meson deleted file mode 120000 index 5fff21bab..000000000 --- a/src/libexpr-test-support/build-utils-meson +++ /dev/null @@ -1 +0,0 @@ -../../build-utils-meson \ No newline at end of file diff --git a/src/libexpr-test-support/meson.build b/src/libexpr-test-support/meson.build index 33d9e17a6..64d4fe218 100644 --- a/src/libexpr-test-support/meson.build +++ b/src/libexpr-test-support/meson.build @@ -14,7 +14,7 @@ project('nix-expr-test-support', 'cpp', cxx = meson.get_compiler('cpp') -subdir('build-utils-meson/deps-lists') +subdir('nix-meson-build-support/deps-lists') deps_private_maybe_subproject = [ ] @@ -26,7 +26,7 @@ deps_public_maybe_subproject = [ dependency('nix-expr'), dependency('nix-expr-c'), ] -subdir('build-utils-meson/subprojects') +subdir('nix-meson-build-support/subprojects') rapidcheck = dependency('rapidcheck') deps_public += rapidcheck @@ -40,7 +40,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/common') +subdir('nix-meson-build-support/common') sources = files( 'tests/value/context.cc', @@ -54,8 +54,8 @@ headers = files( 'tests/value/context.hh', ) -subdir('build-utils-meson/export-all-symbols') -subdir('build-utils-meson/windows-version') +subdir('nix-meson-build-support/export-all-symbols') +subdir('nix-meson-build-support/windows-version') this_library = library( 'nix-expr-test-support', @@ -73,4 +73,4 @@ install_headers(headers, subdir : 'nix', preserve_path : true) libraries_private = [] -subdir('build-utils-meson/export') +subdir('nix-meson-build-support/export') diff --git a/src/libexpr-test-support/nix-meson-build-support b/src/libexpr-test-support/nix-meson-build-support new file mode 120000 index 000000000..0b140f56b --- /dev/null +++ b/src/libexpr-test-support/nix-meson-build-support @@ -0,0 +1 @@ +../../nix-meson-build-support \ No newline at end of file diff --git a/src/libexpr-test-support/package.nix b/src/libexpr-test-support/package.nix index 7e92d145f..4842f5f17 100644 --- a/src/libexpr-test-support/package.nix +++ b/src/libexpr-test-support/package.nix @@ -23,8 +23,8 @@ mkMesonLibrary (finalAttrs: { workDir = ./.; fileset = fileset.unions [ - ../../build-utils-meson - ./build-utils-meson + ../../nix-meson-build-support + ./nix-meson-build-support ../../.version ./.version ./meson.build diff --git a/src/libexpr-tests/build-utils-meson b/src/libexpr-tests/build-utils-meson deleted file mode 120000 index 5fff21bab..000000000 --- a/src/libexpr-tests/build-utils-meson +++ /dev/null @@ -1 +0,0 @@ -../../build-utils-meson \ No newline at end of file diff --git a/src/libexpr-tests/meson.build b/src/libexpr-tests/meson.build index b50c18c9c..f37e85e57 100644 --- a/src/libexpr-tests/meson.build +++ b/src/libexpr-tests/meson.build @@ -14,7 +14,7 @@ project('nix-expr-tests', 'cpp', cxx = meson.get_compiler('cpp') -subdir('build-utils-meson/deps-lists') +subdir('nix-meson-build-support/deps-lists') deps_private_maybe_subproject = [ dependency('nix-expr'), @@ -23,10 +23,10 @@ deps_private_maybe_subproject = [ ] deps_public_maybe_subproject = [ ] -subdir('build-utils-meson/subprojects') +subdir('nix-meson-build-support/subprojects') -subdir('build-utils-meson/export-all-symbols') -subdir('build-utils-meson/windows-version') +subdir('nix-meson-build-support/export-all-symbols') +subdir('nix-meson-build-support/windows-version') rapidcheck = dependency('rapidcheck') deps_private += rapidcheck @@ -49,7 +49,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/common') +subdir('nix-meson-build-support/common') sources = files( 'derived-path.cc', diff --git a/src/libexpr-tests/nix-meson-build-support b/src/libexpr-tests/nix-meson-build-support new file mode 120000 index 000000000..0b140f56b --- /dev/null +++ b/src/libexpr-tests/nix-meson-build-support @@ -0,0 +1 @@ +../../nix-meson-build-support \ No newline at end of file diff --git a/src/libexpr-tests/package.nix b/src/libexpr-tests/package.nix index 959d6b84e..70e497b7e 100644 --- a/src/libexpr-tests/package.nix +++ b/src/libexpr-tests/package.nix @@ -27,8 +27,8 @@ mkMesonExecutable (finalAttrs: { workDir = ./.; fileset = fileset.unions [ - ../../build-utils-meson - ./build-utils-meson + ../../nix-meson-build-support + ./nix-meson-build-support ../../.version ./.version ./meson.build diff --git a/src/libexpr/build-utils-meson b/src/libexpr/build-utils-meson deleted file mode 120000 index 5fff21bab..000000000 --- a/src/libexpr/build-utils-meson +++ /dev/null @@ -1 +0,0 @@ -../../build-utils-meson \ No newline at end of file diff --git a/src/libexpr/meson.build b/src/libexpr/meson.build index 28318579e..b3c559ba7 100644 --- a/src/libexpr/meson.build +++ b/src/libexpr/meson.build @@ -14,7 +14,7 @@ project('nix-expr', 'cpp', cxx = meson.get_compiler('cpp') -subdir('build-utils-meson/deps-lists') +subdir('nix-meson-build-support/deps-lists') configdata = configuration_data() @@ -25,7 +25,7 @@ deps_public_maybe_subproject = [ dependency('nix-store'), dependency('nix-fetchers'), ] -subdir('build-utils-meson/subprojects') +subdir('nix-meson-build-support/subprojects') boost = dependency( 'boost', @@ -77,7 +77,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/common') +subdir('nix-meson-build-support/common') parser_tab = custom_target( input : 'parser.y', @@ -121,7 +121,7 @@ lexer_tab = custom_target( install_dir : get_option('includedir') / 'nix', ) -subdir('build-utils-meson/generate-header') +subdir('nix-meson-build-support/generate-header') generated_headers = [] foreach header : [ @@ -205,4 +205,4 @@ install_headers(headers, subdir : 'nix', preserve_path : true) libraries_private = [] -subdir('build-utils-meson/export') +subdir('nix-meson-build-support/export') diff --git a/src/libexpr/nix-meson-build-support b/src/libexpr/nix-meson-build-support new file mode 120000 index 000000000..0b140f56b --- /dev/null +++ b/src/libexpr/nix-meson-build-support @@ -0,0 +1 @@ +../../nix-meson-build-support \ No newline at end of file diff --git a/src/libexpr/package.nix b/src/libexpr/package.nix index d97e7f3a8..5171d70fd 100644 --- a/src/libexpr/package.nix +++ b/src/libexpr/package.nix @@ -40,8 +40,8 @@ mkMesonLibrary (finalAttrs: { workDir = ./.; fileset = fileset.unions [ - ../../build-utils-meson - ./build-utils-meson + ../../nix-meson-build-support + ./nix-meson-build-support ../../.version ./.version ./meson.build diff --git a/src/libfetchers-tests/build-utils-meson b/src/libfetchers-tests/build-utils-meson deleted file mode 120000 index 5fff21bab..000000000 --- a/src/libfetchers-tests/build-utils-meson +++ /dev/null @@ -1 +0,0 @@ -../../build-utils-meson \ No newline at end of file diff --git a/src/libfetchers-tests/meson.build b/src/libfetchers-tests/meson.build index fdab6ba6c..3e82c6111 100644 --- a/src/libfetchers-tests/meson.build +++ b/src/libfetchers-tests/meson.build @@ -14,7 +14,7 @@ project('nix-fetchers-tests', 'cpp', cxx = meson.get_compiler('cpp') -subdir('build-utils-meson/deps-lists') +subdir('nix-meson-build-support/deps-lists') deps_private_maybe_subproject = [ dependency('nix-store-test-support'), @@ -22,10 +22,10 @@ deps_private_maybe_subproject = [ ] deps_public_maybe_subproject = [ ] -subdir('build-utils-meson/subprojects') +subdir('nix-meson-build-support/subprojects') -subdir('build-utils-meson/export-all-symbols') -subdir('build-utils-meson/windows-version') +subdir('nix-meson-build-support/export-all-symbols') +subdir('nix-meson-build-support/windows-version') rapidcheck = dependency('rapidcheck') deps_private += rapidcheck @@ -42,7 +42,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/common') +subdir('nix-meson-build-support/common') sources = files( 'public-key.cc', diff --git a/src/libfetchers-tests/nix-meson-build-support b/src/libfetchers-tests/nix-meson-build-support new file mode 120000 index 000000000..0b140f56b --- /dev/null +++ b/src/libfetchers-tests/nix-meson-build-support @@ -0,0 +1 @@ +../../nix-meson-build-support \ No newline at end of file diff --git a/src/libfetchers-tests/package.nix b/src/libfetchers-tests/package.nix index 7b2ba8f2c..e18d644ed 100644 --- a/src/libfetchers-tests/package.nix +++ b/src/libfetchers-tests/package.nix @@ -26,8 +26,8 @@ mkMesonExecutable (finalAttrs: { workDir = ./.; fileset = fileset.unions [ - ../../build-utils-meson - ./build-utils-meson + ../../nix-meson-build-support + ./nix-meson-build-support ../../.version ./.version ./meson.build diff --git a/src/libfetchers/build-utils-meson b/src/libfetchers/build-utils-meson deleted file mode 120000 index 5fff21bab..000000000 --- a/src/libfetchers/build-utils-meson +++ /dev/null @@ -1 +0,0 @@ -../../build-utils-meson \ No newline at end of file diff --git a/src/libfetchers/meson.build b/src/libfetchers/meson.build index 07a1178cc..b4408e943 100644 --- a/src/libfetchers/meson.build +++ b/src/libfetchers/meson.build @@ -14,7 +14,7 @@ project('nix-fetchers', 'cpp', cxx = meson.get_compiler('cpp') -subdir('build-utils-meson/deps-lists') +subdir('nix-meson-build-support/deps-lists') configdata = configuration_data() @@ -24,7 +24,7 @@ deps_public_maybe_subproject = [ dependency('nix-util'), dependency('nix-store'), ] -subdir('build-utils-meson/subprojects') +subdir('nix-meson-build-support/subprojects') nlohmann_json = dependency('nlohmann_json', version : '>= 3.9') deps_public += nlohmann_json @@ -41,7 +41,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/common') +subdir('nix-meson-build-support/common') sources = files( 'attrs.cc', @@ -90,4 +90,4 @@ install_headers(headers, subdir : 'nix', preserve_path : true) libraries_private = [] -subdir('build-utils-meson/export') +subdir('nix-meson-build-support/export') diff --git a/src/libfetchers/nix-meson-build-support b/src/libfetchers/nix-meson-build-support new file mode 120000 index 000000000..0b140f56b --- /dev/null +++ b/src/libfetchers/nix-meson-build-support @@ -0,0 +1 @@ +../../nix-meson-build-support \ No newline at end of file diff --git a/src/libfetchers/package.nix b/src/libfetchers/package.nix index 70973bdb2..7dad00025 100644 --- a/src/libfetchers/package.nix +++ b/src/libfetchers/package.nix @@ -22,8 +22,8 @@ mkMesonLibrary (finalAttrs: { workDir = ./.; fileset = fileset.unions [ - ../../build-utils-meson - ./build-utils-meson + ../../nix-meson-build-support + ./nix-meson-build-support ../../.version ./.version ./meson.build diff --git a/src/libflake-c/build-utils-meson b/src/libflake-c/build-utils-meson deleted file mode 120000 index 91937f183..000000000 --- a/src/libflake-c/build-utils-meson +++ /dev/null @@ -1 +0,0 @@ -../../build-utils-meson/ \ No newline at end of file diff --git a/src/libflake-c/meson.build b/src/libflake-c/meson.build index 00d9650e7..b7669fe97 100644 --- a/src/libflake-c/meson.build +++ b/src/libflake-c/meson.build @@ -14,7 +14,7 @@ project('nix-flake-c', 'cpp', cxx = meson.get_compiler('cpp') -subdir('build-utils-meson/deps-lists') +subdir('nix-meson-build-support/deps-lists') configdata = configuration_data() @@ -29,7 +29,7 @@ deps_public_maybe_subproject = [ dependency('nix-store-c'), dependency('nix-expr-c'), ] -subdir('build-utils-meson/subprojects') +subdir('nix-meson-build-support/subprojects') # TODO rename, because it will conflict with downstream projects configdata.set_quoted('PACKAGE_VERSION', meson.project_version()) @@ -58,7 +58,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/common') +subdir('nix-meson-build-support/common') sources = files( 'nix_api_flake.cc', @@ -73,8 +73,8 @@ headers = [config_h] + files( # TODO move this header to libexpr, maybe don't use it in tests? headers += files('nix_api_flake.h') -subdir('build-utils-meson/export-all-symbols') -subdir('build-utils-meson/windows-version') +subdir('nix-meson-build-support/export-all-symbols') +subdir('nix-meson-build-support/windows-version') this_library = library( 'nixflakec', @@ -90,4 +90,4 @@ install_headers(headers, subdir : 'nix', preserve_path : true) libraries_private = [] -subdir('build-utils-meson/export') +subdir('nix-meson-build-support/export') diff --git a/src/libflake-c/nix-meson-build-support b/src/libflake-c/nix-meson-build-support new file mode 120000 index 000000000..0b140f56b --- /dev/null +++ b/src/libflake-c/nix-meson-build-support @@ -0,0 +1 @@ +../../nix-meson-build-support \ No newline at end of file diff --git a/src/libflake-c/package.nix b/src/libflake-c/package.nix index a70cbf94e..7425d6140 100644 --- a/src/libflake-c/package.nix +++ b/src/libflake-c/package.nix @@ -21,8 +21,8 @@ mkMesonLibrary (finalAttrs: { workDir = ./.; fileset = fileset.unions [ - ../../build-utils-meson - ./build-utils-meson + ../../nix-meson-build-support + ./nix-meson-build-support ../../.version ./.version ./meson.build diff --git a/src/libflake-tests/build-utils-meson b/src/libflake-tests/build-utils-meson deleted file mode 120000 index 5fff21bab..000000000 --- a/src/libflake-tests/build-utils-meson +++ /dev/null @@ -1 +0,0 @@ -../../build-utils-meson \ No newline at end of file diff --git a/src/libflake-tests/meson.build b/src/libflake-tests/meson.build index c494c414e..5c3c58e53 100644 --- a/src/libflake-tests/meson.build +++ b/src/libflake-tests/meson.build @@ -14,7 +14,7 @@ project('nix-flake-tests', 'cpp', cxx = meson.get_compiler('cpp') -subdir('build-utils-meson/deps-lists') +subdir('nix-meson-build-support/deps-lists') deps_private_maybe_subproject = [ dependency('nix-expr-test-support'), @@ -23,10 +23,10 @@ deps_private_maybe_subproject = [ ] deps_public_maybe_subproject = [ ] -subdir('build-utils-meson/subprojects') +subdir('nix-meson-build-support/subprojects') -subdir('build-utils-meson/export-all-symbols') -subdir('build-utils-meson/windows-version') +subdir('nix-meson-build-support/export-all-symbols') +subdir('nix-meson-build-support/windows-version') rapidcheck = dependency('rapidcheck') deps_private += rapidcheck @@ -43,7 +43,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/common') +subdir('nix-meson-build-support/common') sources = files( 'flakeref.cc', diff --git a/src/libflake-tests/nix-meson-build-support b/src/libflake-tests/nix-meson-build-support new file mode 120000 index 000000000..0b140f56b --- /dev/null +++ b/src/libflake-tests/nix-meson-build-support @@ -0,0 +1 @@ +../../nix-meson-build-support \ No newline at end of file diff --git a/src/libflake-tests/package.nix b/src/libflake-tests/package.nix index b3a8ac466..f1abbb32d 100644 --- a/src/libflake-tests/package.nix +++ b/src/libflake-tests/package.nix @@ -27,8 +27,8 @@ mkMesonExecutable (finalAttrs: { workDir = ./.; fileset = fileset.unions [ - ../../build-utils-meson - ./build-utils-meson + ../../nix-meson-build-support + ./nix-meson-build-support ../../.version ./.version ./meson.build diff --git a/src/libflake/build-utils-meson b/src/libflake/build-utils-meson deleted file mode 120000 index 5fff21bab..000000000 --- a/src/libflake/build-utils-meson +++ /dev/null @@ -1 +0,0 @@ -../../build-utils-meson \ No newline at end of file diff --git a/src/libflake/meson.build b/src/libflake/meson.build index 2c1a70a18..f9e217729 100644 --- a/src/libflake/meson.build +++ b/src/libflake/meson.build @@ -14,7 +14,7 @@ project('nix-flake', 'cpp', cxx = meson.get_compiler('cpp') -subdir('build-utils-meson/deps-lists') +subdir('nix-meson-build-support/deps-lists') deps_private_maybe_subproject = [ ] @@ -24,7 +24,7 @@ deps_public_maybe_subproject = [ dependency('nix-fetchers'), dependency('nix-expr'), ] -subdir('build-utils-meson/subprojects') +subdir('nix-meson-build-support/subprojects') nlohmann_json = dependency('nlohmann_json', version : '>= 3.9') deps_public += nlohmann_json @@ -39,7 +39,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/common') +subdir('nix-meson-build-support/common') sources = files( 'flake/config.cc', @@ -72,4 +72,4 @@ install_headers(headers, subdir : 'nix', preserve_path : true) libraries_private = [] -subdir('build-utils-meson/export') +subdir('nix-meson-build-support/export') diff --git a/src/libflake/nix-meson-build-support b/src/libflake/nix-meson-build-support new file mode 120000 index 000000000..0b140f56b --- /dev/null +++ b/src/libflake/nix-meson-build-support @@ -0,0 +1 @@ +../../nix-meson-build-support \ No newline at end of file diff --git a/src/libflake/package.nix b/src/libflake/package.nix index fff481720..92445739f 100644 --- a/src/libflake/package.nix +++ b/src/libflake/package.nix @@ -23,8 +23,8 @@ mkMesonLibrary (finalAttrs: { workDir = ./.; fileset = fileset.unions [ - ../../build-utils-meson - ./build-utils-meson + ../../nix-meson-build-support + ./nix-meson-build-support ../../.version ./.version ./meson.build diff --git a/src/libmain-c/build-utils-meson b/src/libmain-c/build-utils-meson deleted file mode 120000 index 5fff21bab..000000000 --- a/src/libmain-c/build-utils-meson +++ /dev/null @@ -1 +0,0 @@ -../../build-utils-meson \ No newline at end of file diff --git a/src/libmain-c/meson.build b/src/libmain-c/meson.build index 3cb1e4baa..5a5684b8d 100644 --- a/src/libmain-c/meson.build +++ b/src/libmain-c/meson.build @@ -14,7 +14,7 @@ project('nix-main-c', 'cpp', cxx = meson.get_compiler('cpp') -subdir('build-utils-meson/deps-lists') +subdir('nix-meson-build-support/deps-lists') configdata = configuration_data() @@ -27,7 +27,7 @@ deps_public_maybe_subproject = [ dependency('nix-util-c'), dependency('nix-store-c'), ] -subdir('build-utils-meson/subprojects') +subdir('nix-meson-build-support/subprojects') # TODO rename, because it will conflict with downstream projects configdata.set_quoted('PACKAGE_VERSION', meson.project_version()) @@ -53,7 +53,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/common') +subdir('nix-meson-build-support/common') sources = files( 'nix_api_main.cc', @@ -65,8 +65,8 @@ headers = [config_h] + files( 'nix_api_main.h', ) -subdir('build-utils-meson/export-all-symbols') -subdir('build-utils-meson/windows-version') +subdir('nix-meson-build-support/export-all-symbols') +subdir('nix-meson-build-support/windows-version') this_library = library( 'nixmainc', @@ -82,4 +82,4 @@ install_headers(headers, subdir : 'nix', preserve_path : true) libraries_private = [] -subdir('build-utils-meson/export') +subdir('nix-meson-build-support/export') diff --git a/src/libmain-c/nix-meson-build-support b/src/libmain-c/nix-meson-build-support new file mode 120000 index 000000000..0b140f56b --- /dev/null +++ b/src/libmain-c/nix-meson-build-support @@ -0,0 +1 @@ +../../nix-meson-build-support \ No newline at end of file diff --git a/src/libmain-c/package.nix b/src/libmain-c/package.nix index 5522037f3..d65792921 100644 --- a/src/libmain-c/package.nix +++ b/src/libmain-c/package.nix @@ -22,8 +22,8 @@ mkMesonLibrary (finalAttrs: { workDir = ./.; fileset = fileset.unions [ - ../../build-utils-meson - ./build-utils-meson + ../../nix-meson-build-support + ./nix-meson-build-support ../../.version ./.version ./meson.build diff --git a/src/libmain/build-utils-meson b/src/libmain/build-utils-meson deleted file mode 120000 index 5fff21bab..000000000 --- a/src/libmain/build-utils-meson +++ /dev/null @@ -1 +0,0 @@ -../../build-utils-meson \ No newline at end of file diff --git a/src/libmain/meson.build b/src/libmain/meson.build index 6c6298e2b..87fc8b8d2 100644 --- a/src/libmain/meson.build +++ b/src/libmain/meson.build @@ -14,7 +14,7 @@ project('nix-main', 'cpp', cxx = meson.get_compiler('cpp') -subdir('build-utils-meson/deps-lists') +subdir('nix-meson-build-support/deps-lists') configdata = configuration_data() @@ -24,7 +24,7 @@ deps_public_maybe_subproject = [ dependency('nix-util'), dependency('nix-store'), ] -subdir('build-utils-meson/subprojects') +subdir('nix-meson-build-support/subprojects') pubsetbuf_test = ''' #include @@ -58,7 +58,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/common') +subdir('nix-meson-build-support/common') sources = files( 'common-args.cc', @@ -96,4 +96,4 @@ install_headers(headers, subdir : 'nix', preserve_path : true) libraries_private = [] -subdir('build-utils-meson/export') +subdir('nix-meson-build-support/export') diff --git a/src/libmain/nix-meson-build-support b/src/libmain/nix-meson-build-support new file mode 120000 index 000000000..0b140f56b --- /dev/null +++ b/src/libmain/nix-meson-build-support @@ -0,0 +1 @@ +../../nix-meson-build-support \ No newline at end of file diff --git a/src/libmain/package.nix b/src/libmain/package.nix index 7e7b80472..7d9d99b61 100644 --- a/src/libmain/package.nix +++ b/src/libmain/package.nix @@ -22,8 +22,8 @@ mkMesonLibrary (finalAttrs: { workDir = ./.; fileset = fileset.unions [ - ../../build-utils-meson - ./build-utils-meson + ../../nix-meson-build-support + ./nix-meson-build-support ../../.version ./.version ./meson.build diff --git a/src/libstore-c/build-utils-meson b/src/libstore-c/build-utils-meson deleted file mode 120000 index 5fff21bab..000000000 --- a/src/libstore-c/build-utils-meson +++ /dev/null @@ -1 +0,0 @@ -../../build-utils-meson \ No newline at end of file diff --git a/src/libstore-c/meson.build b/src/libstore-c/meson.build index 44b5fe11d..1ac331ad0 100644 --- a/src/libstore-c/meson.build +++ b/src/libstore-c/meson.build @@ -14,7 +14,7 @@ project('nix-store-c', 'cpp', cxx = meson.get_compiler('cpp') -subdir('build-utils-meson/deps-lists') +subdir('nix-meson-build-support/deps-lists') configdata = configuration_data() @@ -25,7 +25,7 @@ deps_private_maybe_subproject = [ deps_public_maybe_subproject = [ dependency('nix-util-c'), ] -subdir('build-utils-meson/subprojects') +subdir('nix-meson-build-support/subprojects') # TODO rename, because it will conflict with downstream projects configdata.set_quoted('PACKAGE_VERSION', meson.project_version()) @@ -49,7 +49,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/common') +subdir('nix-meson-build-support/common') sources = files( 'nix_api_store.cc', @@ -64,8 +64,8 @@ headers = [config_h] + files( # TODO don't install this once tests don't use it and/or move the header into `libstore`, non-`c` headers += files('nix_api_store_internal.h') -subdir('build-utils-meson/export-all-symbols') -subdir('build-utils-meson/windows-version') +subdir('nix-meson-build-support/export-all-symbols') +subdir('nix-meson-build-support/windows-version') this_library = library( 'nixstorec', @@ -81,4 +81,4 @@ install_headers(headers, subdir : 'nix', preserve_path : true) libraries_private = [] -subdir('build-utils-meson/export') +subdir('nix-meson-build-support/export') diff --git a/src/libstore-c/nix-meson-build-support b/src/libstore-c/nix-meson-build-support new file mode 120000 index 000000000..0b140f56b --- /dev/null +++ b/src/libstore-c/nix-meson-build-support @@ -0,0 +1 @@ +../../nix-meson-build-support \ No newline at end of file diff --git a/src/libstore-c/package.nix b/src/libstore-c/package.nix index 896a1a39f..351d4510a 100644 --- a/src/libstore-c/package.nix +++ b/src/libstore-c/package.nix @@ -20,8 +20,8 @@ mkMesonLibrary (finalAttrs: { workDir = ./.; fileset = fileset.unions [ - ../../build-utils-meson - ./build-utils-meson + ../../nix-meson-build-support + ./nix-meson-build-support ../../.version ./.version ./meson.build diff --git a/src/libstore-test-support/build-utils-meson b/src/libstore-test-support/build-utils-meson deleted file mode 120000 index 5fff21bab..000000000 --- a/src/libstore-test-support/build-utils-meson +++ /dev/null @@ -1 +0,0 @@ -../../build-utils-meson \ No newline at end of file diff --git a/src/libstore-test-support/meson.build b/src/libstore-test-support/meson.build index 1f230914f..2a07e56ac 100644 --- a/src/libstore-test-support/meson.build +++ b/src/libstore-test-support/meson.build @@ -14,7 +14,7 @@ project('nix-store-test-support', 'cpp', cxx = meson.get_compiler('cpp') -subdir('build-utils-meson/deps-lists') +subdir('nix-meson-build-support/deps-lists') deps_private_maybe_subproject = [ ] @@ -24,7 +24,7 @@ deps_public_maybe_subproject = [ dependency('nix-store'), dependency('nix-store-c'), ] -subdir('build-utils-meson/subprojects') +subdir('nix-meson-build-support/subprojects') rapidcheck = dependency('rapidcheck') deps_public += rapidcheck @@ -37,7 +37,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/common') +subdir('nix-meson-build-support/common') sources = files( 'tests/derived-path.cc', @@ -56,8 +56,8 @@ headers = files( 'tests/protocol.hh', ) -subdir('build-utils-meson/export-all-symbols') -subdir('build-utils-meson/windows-version') +subdir('nix-meson-build-support/export-all-symbols') +subdir('nix-meson-build-support/windows-version') this_library = library( 'nix-store-test-support', @@ -75,4 +75,4 @@ install_headers(headers, subdir : 'nix', preserve_path : true) libraries_private = [] -subdir('build-utils-meson/export') +subdir('nix-meson-build-support/export') diff --git a/src/libstore-test-support/nix-meson-build-support b/src/libstore-test-support/nix-meson-build-support new file mode 120000 index 000000000..0b140f56b --- /dev/null +++ b/src/libstore-test-support/nix-meson-build-support @@ -0,0 +1 @@ +../../nix-meson-build-support \ No newline at end of file diff --git a/src/libstore-test-support/package.nix b/src/libstore-test-support/package.nix index 2543049fe..62f783c4f 100644 --- a/src/libstore-test-support/package.nix +++ b/src/libstore-test-support/package.nix @@ -23,8 +23,8 @@ mkMesonLibrary (finalAttrs: { workDir = ./.; fileset = fileset.unions [ - ../../build-utils-meson - ./build-utils-meson + ../../nix-meson-build-support + ./nix-meson-build-support ../../.version ./.version ./meson.build diff --git a/src/libstore-tests/build-utils-meson b/src/libstore-tests/build-utils-meson deleted file mode 120000 index 5fff21bab..000000000 --- a/src/libstore-tests/build-utils-meson +++ /dev/null @@ -1 +0,0 @@ -../../build-utils-meson \ No newline at end of file diff --git a/src/libstore-tests/meson.build b/src/libstore-tests/meson.build index fc9152f2f..c4e42634d 100644 --- a/src/libstore-tests/meson.build +++ b/src/libstore-tests/meson.build @@ -14,7 +14,7 @@ project('nix-store-tests', 'cpp', cxx = meson.get_compiler('cpp') -subdir('build-utils-meson/deps-lists') +subdir('nix-meson-build-support/deps-lists') deps_private_maybe_subproject = [ dependency('nix-store'), @@ -23,10 +23,10 @@ deps_private_maybe_subproject = [ ] deps_public_maybe_subproject = [ ] -subdir('build-utils-meson/subprojects') +subdir('nix-meson-build-support/subprojects') -subdir('build-utils-meson/export-all-symbols') -subdir('build-utils-meson/windows-version') +subdir('nix-meson-build-support/export-all-symbols') +subdir('nix-meson-build-support/windows-version') sqlite = dependency('sqlite3', 'sqlite', version : '>=3.6.19') deps_private += sqlite @@ -50,7 +50,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/common') +subdir('nix-meson-build-support/common') sources = files( 'common-protocol.cc', diff --git a/src/libstore-tests/nix-meson-build-support b/src/libstore-tests/nix-meson-build-support new file mode 120000 index 000000000..0b140f56b --- /dev/null +++ b/src/libstore-tests/nix-meson-build-support @@ -0,0 +1 @@ +../../nix-meson-build-support \ No newline at end of file diff --git a/src/libstore-tests/package.nix b/src/libstore-tests/package.nix index 3704d8c5c..4937b5329 100644 --- a/src/libstore-tests/package.nix +++ b/src/libstore-tests/package.nix @@ -28,8 +28,8 @@ mkMesonExecutable (finalAttrs: { workDir = ./.; fileset = fileset.unions [ - ../../build-utils-meson - ./build-utils-meson + ../../nix-meson-build-support + ./nix-meson-build-support ../../.version ./.version ./meson.build diff --git a/src/libstore/build-utils-meson b/src/libstore/build-utils-meson deleted file mode 120000 index 5fff21bab..000000000 --- a/src/libstore/build-utils-meson +++ /dev/null @@ -1 +0,0 @@ -../../build-utils-meson \ No newline at end of file diff --git a/src/libstore/meson.build b/src/libstore/meson.build index f836b8d4f..12a0e6376 100644 --- a/src/libstore/meson.build +++ b/src/libstore/meson.build @@ -15,7 +15,7 @@ project('nix-store', 'cpp', cxx = meson.get_compiler('cpp') -subdir('build-utils-meson/deps-lists') +subdir('nix-meson-build-support/deps-lists') configdata = configuration_data() @@ -29,7 +29,7 @@ deps_private_maybe_subproject = [ deps_public_maybe_subproject = [ dependency('nix-util'), ] -subdir('build-utils-meson/subprojects') +subdir('nix-meson-build-support/subprojects') run_command('ln', '-s', meson.project_build_root() / '__nothing_link_target', @@ -81,7 +81,7 @@ if host_machine.system() == 'windows' deps_other += [wsock32] endif -subdir('build-utils-meson/libatomic') +subdir('nix-meson-build-support/libatomic') boost = dependency( 'boost', @@ -131,7 +131,7 @@ if aws_s3.found() endif deps_other += aws_s3 -subdir('build-utils-meson/generate-header') +subdir('nix-meson-build-support/generate-header') generated_headers = [] foreach header : [ @@ -179,7 +179,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/common') +subdir('nix-meson-build-support/common') sources = files( 'binary-cache-store.cc', @@ -416,8 +416,8 @@ foreach name, value : cpp_str_defines ] endforeach -subdir('build-utils-meson/export-all-symbols') -subdir('build-utils-meson/windows-version') +subdir('nix-meson-build-support/export-all-symbols') +subdir('nix-meson-build-support/windows-version') this_library = library( 'nixstore', @@ -446,4 +446,4 @@ if host_machine.system() != 'darwin' } endif -subdir('build-utils-meson/export') +subdir('nix-meson-build-support/export') diff --git a/src/libstore/nix-meson-build-support b/src/libstore/nix-meson-build-support new file mode 120000 index 000000000..0b140f56b --- /dev/null +++ b/src/libstore/nix-meson-build-support @@ -0,0 +1 @@ +../../nix-meson-build-support \ No newline at end of file diff --git a/src/libstore/package.nix b/src/libstore/package.nix index f04e3b95f..47a203f83 100644 --- a/src/libstore/package.nix +++ b/src/libstore/package.nix @@ -32,8 +32,8 @@ mkMesonLibrary (finalAttrs: { workDir = ./.; fileset = fileset.unions [ - ../../build-utils-meson - ./build-utils-meson + ../../nix-meson-build-support + ./nix-meson-build-support ../../.version ./.version ./meson.build diff --git a/src/libutil-c/build-utils-meson b/src/libutil-c/build-utils-meson deleted file mode 120000 index 5fff21bab..000000000 --- a/src/libutil-c/build-utils-meson +++ /dev/null @@ -1 +0,0 @@ -../../build-utils-meson \ No newline at end of file diff --git a/src/libutil-c/meson.build b/src/libutil-c/meson.build index d44453676..44cec1afc 100644 --- a/src/libutil-c/meson.build +++ b/src/libutil-c/meson.build @@ -14,7 +14,7 @@ project('nix-util-c', 'cpp', cxx = meson.get_compiler('cpp') -subdir('build-utils-meson/deps-lists') +subdir('nix-meson-build-support/deps-lists') configdata = configuration_data() @@ -23,7 +23,7 @@ deps_private_maybe_subproject = [ ] deps_public_maybe_subproject = [ ] -subdir('build-utils-meson/subprojects') +subdir('nix-meson-build-support/subprojects') # TODO rename, because it will conflict with downstream projects configdata.set_quoted('PACKAGE_VERSION', meson.project_version()) @@ -45,7 +45,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/common') +subdir('nix-meson-build-support/common') sources = files( 'nix_api_util.cc', @@ -60,8 +60,8 @@ headers = [config_h] + files( # TODO don't install this once tests don't use it. headers += files('nix_api_util_internal.h') -subdir('build-utils-meson/export-all-symbols') -subdir('build-utils-meson/windows-version') +subdir('nix-meson-build-support/export-all-symbols') +subdir('nix-meson-build-support/windows-version') this_library = library( 'nixutilc', @@ -77,4 +77,4 @@ install_headers(headers, subdir : 'nix', preserve_path : true) libraries_private = [] -subdir('build-utils-meson/export') +subdir('nix-meson-build-support/export') diff --git a/src/libutil-c/nix-meson-build-support b/src/libutil-c/nix-meson-build-support new file mode 120000 index 000000000..0b140f56b --- /dev/null +++ b/src/libutil-c/nix-meson-build-support @@ -0,0 +1 @@ +../../nix-meson-build-support \ No newline at end of file diff --git a/src/libutil-c/package.nix b/src/libutil-c/package.nix index 35533f981..4caf96804 100644 --- a/src/libutil-c/package.nix +++ b/src/libutil-c/package.nix @@ -19,8 +19,8 @@ mkMesonLibrary (finalAttrs: { workDir = ./.; fileset = fileset.unions [ - ../../build-utils-meson - ./build-utils-meson + ../../nix-meson-build-support + ./nix-meson-build-support ../../.version ./.version ./meson.build diff --git a/src/libutil-test-support/build-utils-meson b/src/libutil-test-support/build-utils-meson deleted file mode 120000 index 5fff21bab..000000000 --- a/src/libutil-test-support/build-utils-meson +++ /dev/null @@ -1 +0,0 @@ -../../build-utils-meson \ No newline at end of file diff --git a/src/libutil-test-support/meson.build b/src/libutil-test-support/meson.build index 4afed01ca..03ae63f1a 100644 --- a/src/libutil-test-support/meson.build +++ b/src/libutil-test-support/meson.build @@ -14,7 +14,7 @@ project('nix-util-test-support', 'cpp', cxx = meson.get_compiler('cpp') -subdir('build-utils-meson/deps-lists') +subdir('nix-meson-build-support/deps-lists') deps_private_maybe_subproject = [ ] @@ -22,7 +22,7 @@ deps_public_maybe_subproject = [ dependency('nix-util'), dependency('nix-util-c'), ] -subdir('build-utils-meson/subprojects') +subdir('nix-meson-build-support/subprojects') rapidcheck = dependency('rapidcheck') deps_public += rapidcheck @@ -34,7 +34,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/common') +subdir('nix-meson-build-support/common') sources = files( 'tests/hash.cc', @@ -51,8 +51,8 @@ headers = files( 'tests/string_callback.hh', ) -subdir('build-utils-meson/export-all-symbols') -subdir('build-utils-meson/windows-version') +subdir('nix-meson-build-support/export-all-symbols') +subdir('nix-meson-build-support/windows-version') this_library = library( 'nix-util-test-support', @@ -70,4 +70,4 @@ install_headers(headers, subdir : 'nix', preserve_path : true) libraries_private = [] -subdir('build-utils-meson/export') +subdir('nix-meson-build-support/export') diff --git a/src/libutil-test-support/nix-meson-build-support b/src/libutil-test-support/nix-meson-build-support new file mode 120000 index 000000000..0b140f56b --- /dev/null +++ b/src/libutil-test-support/nix-meson-build-support @@ -0,0 +1 @@ +../../nix-meson-build-support \ No newline at end of file diff --git a/src/libutil-test-support/package.nix b/src/libutil-test-support/package.nix index c403e762c..19b5d6b77 100644 --- a/src/libutil-test-support/package.nix +++ b/src/libutil-test-support/package.nix @@ -22,8 +22,8 @@ mkMesonLibrary (finalAttrs: { workDir = ./.; fileset = fileset.unions [ - ../../build-utils-meson - ./build-utils-meson + ../../nix-meson-build-support + ./nix-meson-build-support ../../.version ./.version ./meson.build diff --git a/src/libutil-tests/build-utils-meson b/src/libutil-tests/build-utils-meson deleted file mode 120000 index 5fff21bab..000000000 --- a/src/libutil-tests/build-utils-meson +++ /dev/null @@ -1 +0,0 @@ -../../build-utils-meson \ No newline at end of file diff --git a/src/libutil-tests/meson.build b/src/libutil-tests/meson.build index f59350774..83ac79e92 100644 --- a/src/libutil-tests/meson.build +++ b/src/libutil-tests/meson.build @@ -14,7 +14,7 @@ project('nix-util-tests', 'cpp', cxx = meson.get_compiler('cpp') -subdir('build-utils-meson/deps-lists') +subdir('nix-meson-build-support/deps-lists') deps_private_maybe_subproject = [ dependency('nix-util'), @@ -23,10 +23,10 @@ deps_private_maybe_subproject = [ ] deps_public_maybe_subproject = [ ] -subdir('build-utils-meson/subprojects') +subdir('nix-meson-build-support/subprojects') -subdir('build-utils-meson/export-all-symbols') -subdir('build-utils-meson/windows-version') +subdir('nix-meson-build-support/export-all-symbols') +subdir('nix-meson-build-support/windows-version') rapidcheck = dependency('rapidcheck') deps_private += rapidcheck @@ -42,7 +42,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/common') +subdir('nix-meson-build-support/common') sources = files( 'args.cc', diff --git a/src/libutil-tests/nix-meson-build-support b/src/libutil-tests/nix-meson-build-support new file mode 120000 index 000000000..0b140f56b --- /dev/null +++ b/src/libutil-tests/nix-meson-build-support @@ -0,0 +1 @@ +../../nix-meson-build-support \ No newline at end of file diff --git a/src/libutil-tests/package.nix b/src/libutil-tests/package.nix index b099037ee..f06704e26 100644 --- a/src/libutil-tests/package.nix +++ b/src/libutil-tests/package.nix @@ -26,8 +26,8 @@ mkMesonExecutable (finalAttrs: { workDir = ./.; fileset = fileset.unions [ - ../../build-utils-meson - ./build-utils-meson + ../../nix-meson-build-support + ./nix-meson-build-support ../../.version ./.version ./meson.build diff --git a/src/libutil/build-utils-meson b/src/libutil/build-utils-meson deleted file mode 120000 index 5fff21bab..000000000 --- a/src/libutil/build-utils-meson +++ /dev/null @@ -1 +0,0 @@ -../../build-utils-meson \ No newline at end of file diff --git a/src/libutil/meson.build b/src/libutil/meson.build index 11b4ea592..bbe7872cf 100644 --- a/src/libutil/meson.build +++ b/src/libutil/meson.build @@ -14,7 +14,7 @@ project('nix-util', 'cpp', cxx = meson.get_compiler('cpp') -subdir('build-utils-meson/deps-lists') +subdir('nix-meson-build-support/deps-lists') configdata = configuration_data() @@ -22,7 +22,7 @@ deps_private_maybe_subproject = [ ] deps_public_maybe_subproject = [ ] -subdir('build-utils-meson/subprojects') +subdir('nix-meson-build-support/subprojects') # Check for each of these functions, and create a define like `#define # HAVE_LUTIMES 1`. The `#define` is unconditional, 0 for not found and 1 @@ -53,7 +53,7 @@ endforeach configdata.set('HAVE_DECL_AT_SYMLINK_NOFOLLOW', cxx.has_header_symbol('fcntl.h', 'AT_SYMLINK_NOFOLLOW').to_int()) -subdir('build-utils-meson/libatomic') +subdir('nix-meson-build-support/libatomic') if host_machine.system() == 'windows' socket = cxx.find_library('ws2_32') @@ -120,7 +120,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/common') +subdir('nix-meson-build-support/common') sources = files( 'archive.cc', @@ -256,8 +256,8 @@ else subdir('unix') endif -subdir('build-utils-meson/export-all-symbols') -subdir('build-utils-meson/windows-version') +subdir('nix-meson-build-support/export-all-symbols') +subdir('nix-meson-build-support/windows-version') this_library = library( 'nixutil', @@ -278,4 +278,4 @@ if host_machine.system() == 'windows' libraries_private += ['-lws2_32'] endif -subdir('build-utils-meson/export') +subdir('nix-meson-build-support/export') diff --git a/src/libutil/nix-meson-build-support b/src/libutil/nix-meson-build-support new file mode 120000 index 000000000..0b140f56b --- /dev/null +++ b/src/libutil/nix-meson-build-support @@ -0,0 +1 @@ +../../nix-meson-build-support \ No newline at end of file diff --git a/src/libutil/package.nix b/src/libutil/package.nix index 17a156740..69ebbf726 100644 --- a/src/libutil/package.nix +++ b/src/libutil/package.nix @@ -25,8 +25,8 @@ mkMesonLibrary (finalAttrs: { workDir = ./.; fileset = fileset.unions [ - ../../build-utils-meson - ./build-utils-meson + ../../nix-meson-build-support + ./nix-meson-build-support ../../.version ./.version ./meson.build diff --git a/src/nix/build-utils-meson b/src/nix/build-utils-meson deleted file mode 120000 index 91937f183..000000000 --- a/src/nix/build-utils-meson +++ /dev/null @@ -1 +0,0 @@ -../../build-utils-meson/ \ No newline at end of file diff --git a/src/nix/meson.build b/src/nix/meson.build index 5c70c8216..1d4840b12 100644 --- a/src/nix/meson.build +++ b/src/nix/meson.build @@ -15,7 +15,7 @@ project('nix', 'cpp', cxx = meson.get_compiler('cpp') -subdir('build-utils-meson/deps-lists') +subdir('nix-meson-build-support/deps-lists') nix_store = dependency('nix-store') @@ -30,10 +30,10 @@ deps_private_maybe_subproject = [ ] deps_public_maybe_subproject = [ ] -subdir('build-utils-meson/subprojects') +subdir('nix-meson-build-support/subprojects') -subdir('build-utils-meson/export-all-symbols') -subdir('build-utils-meson/windows-version') +subdir('nix-meson-build-support/export-all-symbols') +subdir('nix-meson-build-support/windows-version') configdata = configuration_data() @@ -63,8 +63,8 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/common') -subdir('build-utils-meson/generate-header') +subdir('nix-meson-build-support/common') +subdir('nix-meson-build-support/generate-header') nix_sources = [config_h] + files( 'add-to-store.cc', diff --git a/src/nix/nix-meson-build-support b/src/nix/nix-meson-build-support new file mode 120000 index 000000000..0b140f56b --- /dev/null +++ b/src/nix/nix-meson-build-support @@ -0,0 +1 @@ +../../nix-meson-build-support \ No newline at end of file diff --git a/src/nix/package.nix b/src/nix/package.nix index c7b24efce..9bc139c3b 100644 --- a/src/nix/package.nix +++ b/src/nix/package.nix @@ -22,8 +22,8 @@ mkMesonExecutable (finalAttrs: { workDir = ./.; fileset = fileset.unions ([ - ../../build-utils-meson - ./build-utils-meson + ../../nix-meson-build-support + ./nix-meson-build-support ../../.version ./.version ./meson.build From 1421420e862434321c46511a3152016e443dd479 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 9 Dec 2024 17:18:10 +0100 Subject: [PATCH 531/718] test: Move unusual-logging to run only in logging test case --- tests/functional/dependencies.nix | 15 --------------- tests/functional/logging.sh | 3 +++ tests/functional/logging/unusual-logging.nix | 16 ++++++++++++++++ 3 files changed, 19 insertions(+), 15 deletions(-) create mode 100644 tests/functional/logging/unusual-logging.nix diff --git a/tests/functional/dependencies.nix b/tests/functional/dependencies.nix index d177f5b63..4ff29227f 100644 --- a/tests/functional/dependencies.nix +++ b/tests/functional/dependencies.nix @@ -33,20 +33,6 @@ let outputHash = "1dq9p0hnm1y75q2x40fws5887bq1r840hzdxak0a9djbwvx0b16d"; }; - unusual-logging = mkDerivation { - name = "unusual-logging"; - buildCommand = '' - { - echo "@nix 1" - echo "@nix {}" - echo '@nix {"action": null}' - echo '@nix {"action": 123}' - echo '@nix ][' - } >&$NIX_LOG_FD - touch $out - ''; - }; - in mkDerivation { name = "dependencies-top"; @@ -56,7 +42,6 @@ mkDerivation { input1_drv = input1; input2_drv = input2; input0_drv = input0; - unusual_logging_drv = unusual-logging; fod_input_drv = fod_input; meta.description = "Random test package"; } diff --git a/tests/functional/logging.sh b/tests/functional/logging.sh index c026ac9c2..bbc1bac96 100755 --- a/tests/functional/logging.sh +++ b/tests/functional/logging.sh @@ -28,3 +28,6 @@ outp="$(nix-build -E \ test -d "$outp" nix log "$outp" + +# Build works despite ill-formed structured build log entries. +expectStderr 0 nix build -f ./logging/unusual-logging.nix --no-link | grepQuiet 'warning: Unable to handle a JSON message from the derivation builder:' diff --git a/tests/functional/logging/unusual-logging.nix b/tests/functional/logging/unusual-logging.nix new file mode 100644 index 000000000..ddb8aa530 --- /dev/null +++ b/tests/functional/logging/unusual-logging.nix @@ -0,0 +1,16 @@ +let + inherit (import ../config.nix) mkDerivation; +in +mkDerivation { + name = "unusual-logging"; + buildCommand = '' + { + echo "@nix 1" + echo "@nix {}" + echo '@nix {"action": null}' + echo '@nix {"action": 123}' + echo '@nix ][' + } >&$NIX_LOG_FD + touch $out + ''; +} From f3c722cab24f7a0de8c3573d25e91749f4f16234 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 9 Dec 2024 17:20:27 +0100 Subject: [PATCH 532/718] Remove redundant warning: prefix from structured build log warning --- src/libutil/logging.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libutil/logging.cc b/src/libutil/logging.cc index 4c7061016..a5add5565 100644 --- a/src/libutil/logging.cc +++ b/src/libutil/logging.cc @@ -331,7 +331,7 @@ bool handleJSONLogMessage(nlohmann::json & json, return true; } catch (const nlohmann::json::exception &e) { warn( - "warning: Unable to handle a JSON message from %s: %s", + "Unable to handle a JSON message from %s: %s", Uncolored(source), e.what() ); From c783cd22ac1c693871979c4248d7f7b2b7f6bacd Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 9 Dec 2024 17:29:45 +0100 Subject: [PATCH 533/718] tests: Make unusual logging test conditional on fixed daemon version --- tests/functional/logging.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/functional/logging.sh b/tests/functional/logging.sh index bbc1bac96..ddb1913ad 100755 --- a/tests/functional/logging.sh +++ b/tests/functional/logging.sh @@ -29,5 +29,7 @@ test -d "$outp" nix log "$outp" -# Build works despite ill-formed structured build log entries. -expectStderr 0 nix build -f ./logging/unusual-logging.nix --no-link | grepQuiet 'warning: Unable to handle a JSON message from the derivation builder:' +if isDaemonNewer "2.26"; then + # Build works despite ill-formed structured build log entries. + expectStderr 0 nix build -f ./logging/unusual-logging.nix --no-link | grepQuiet 'warning: Unable to handle a JSON message from the derivation builder:' +fi From 6d86839a0265cf06a384499d9d9aac0daf31a8ad Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 9 Dec 2024 17:34:56 +0100 Subject: [PATCH 534/718] Use version correctly in nix-daemon-compat-tests derivation Previously, a version would be appended to the pname which already contained a version. --- packaging/hydra.nix | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packaging/hydra.nix b/packaging/hydra.nix index 6109f479e..e4562cd21 100644 --- a/packaging/hydra.nix +++ b/packaging/hydra.nix @@ -18,12 +18,12 @@ let testNixVersions = pkgs: daemon: pkgs.nixComponents.nix-functional-tests.override { - pname = - "nix-daemon-compat-tests" - + lib.optionalString + pname = "nix-daemon-compat-tests"; + version = + lib.optionalString (lib.versionAtLeast daemon.version "2.4pre20211005" && lib.versionAtLeast pkgs.nix.version "2.4pre20211005") - "-${pkgs.nix.version}-with-daemon-${daemon.version}"; + "${pkgs.nix.version}-with-daemon-${daemon.version}"; test-daemon = daemon; }; From 62d3957268399ef20c517801fd8672b863ceb16d Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 9 Dec 2024 17:35:57 +0100 Subject: [PATCH 535/718] Remove dead code from nix-daemon-compat-tests packaging We're not testing against these versions anymore. If we bring that back (I would support that), we could do so in a clean way, by making sure that the packaging we test against has a proper version attribute. --- packaging/hydra.nix | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packaging/hydra.nix b/packaging/hydra.nix index e4562cd21..17ba72032 100644 --- a/packaging/hydra.nix +++ b/packaging/hydra.nix @@ -19,11 +19,7 @@ let testNixVersions = pkgs: daemon: pkgs.nixComponents.nix-functional-tests.override { pname = "nix-daemon-compat-tests"; - version = - lib.optionalString - (lib.versionAtLeast daemon.version "2.4pre20211005" && - lib.versionAtLeast pkgs.nix.version "2.4pre20211005") - "${pkgs.nix.version}-with-daemon-${daemon.version}"; + version = "${pkgs.nix.version}-with-daemon-${daemon.version}"; test-daemon = daemon; }; From 8768239517dd75955979fc43cee0d411b4e04139 Mon Sep 17 00:00:00 2001 From: Cole Helbling Date: Mon, 9 Dec 2024 11:15:53 -0800 Subject: [PATCH 536/718] Install .nix-channels and nix.conf with 644 instead of 664 As far as I can tell, there's no real reason either of these need to be 664. I'm willing to bet they were just a typo that has lasted for 7 years. While this shouldn't change anything, this is, IMHO, more correct, so let's stop perpetuating the wrong mode! --- scripts/install-multi-user.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/install-multi-user.sh b/scripts/install-multi-user.sh index a487d459f..19f787ab5 100644 --- a/scripts/install-multi-user.sh +++ b/scripts/install-multi-user.sh @@ -690,7 +690,7 @@ place_channel_configuration() { if [ -z "${NIX_INSTALLER_NO_CHANNEL_ADD:-}" ]; then echo "https://nixos.org/channels/nixpkgs-unstable nixpkgs" > "$SCRATCH/.nix-channels" _sudo "to set up the default system channel (part 1)" \ - install -m 0664 "$SCRATCH/.nix-channels" "$ROOT_HOME/.nix-channels" + install -m 0644 "$SCRATCH/.nix-channels" "$ROOT_HOME/.nix-channels" fi } @@ -964,7 +964,7 @@ $NIX_EXTRA_CONF build-users-group = $NIX_BUILD_GROUP_NAME EOF _sudo "to place the default nix daemon configuration (part 2)" \ - install -m 0664 "$SCRATCH/nix.conf" /etc/nix/nix.conf + install -m 0644 "$SCRATCH/nix.conf" /etc/nix/nix.conf } From 35dd19d7851fea20eebcd3cd7cbb6e64cdc47a8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Mon, 9 Dec 2024 15:37:17 +0100 Subject: [PATCH 537/718] ensure clang-format is using the same version on all platforms --- maintainers/flake-module.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/maintainers/flake-module.nix b/maintainers/flake-module.nix index 1d4e85c8c..1a134b91a 100644 --- a/maintainers/flake-module.nix +++ b/maintainers/flake-module.nix @@ -12,6 +12,8 @@ hooks = { clang-format = { enable = true; + # https://github.com/cachix/git-hooks.nix/pull/532 + package = pkgs.llvmPackages_latest.clang-tools; excludes = [ # We don't want to format test data # ''tests/(?!nixos/).*\.nix'' From 9b40618d2e455951b699e2e181e4b93ca97e7b08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Mon, 9 Dec 2024 16:05:37 +0100 Subject: [PATCH 538/718] tests/nixos: disable documentation to improve eval speed we are not testing any nixos modules, so we don't need to generate documentation. This will give us a bit of speed up. --- tests/nixos/default.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/nixos/default.nix b/tests/nixos/default.nix index c5f4a23aa..ff1220f35 100644 --- a/tests/nixos/default.nix +++ b/tests/nixos/default.nix @@ -23,6 +23,9 @@ let nix.checkAllErrors = false; # TODO: decide which packaging stage to use. `nix-cli` is efficient, but not the same as the user-facing `everything.nix` package (`default`). Perhaps a good compromise is `everything.nix` + `noTests` defined above? nix.package = nixpkgsFor.${system}.native.nixComponents.nix-cli; + + # Evaluate VMs faster + documentation.enable = false; }; _module.args.nixpkgs = nixpkgs; _module.args.system = system; From 3a9d64b8e354176b41936b2b9e1d3b20fe0290f2 Mon Sep 17 00:00:00 2001 From: Philipp Otterbein Date: Sat, 7 Dec 2024 20:46:11 +0100 Subject: [PATCH 539/718] fromJSON/fromTOML: throw if string contains null byte --- src/libexpr/eval.cc | 9 +++++++++ src/libexpr/json-to-value.cc | 2 ++ src/libexpr/primops/fromTOML.cc | 14 +++++++++++--- src/libexpr/value.hh | 2 ++ .../eval-fail-fromJSON-keyWithNullByte.err.exp | 8 ++++++++ .../lang/eval-fail-fromJSON-keyWithNullByte.nix | 1 + .../eval-fail-fromJSON-valueWithNullByte.err.exp | 8 ++++++++ .../lang/eval-fail-fromJSON-valueWithNullByte.nix | 1 + .../eval-fail-fromTOML-keyWithNullByte.err.exp | 8 ++++++++ .../lang/eval-fail-fromTOML-keyWithNullByte.nix | 1 + .../eval-fail-fromTOML-valueWithNullByte.err.exp | 8 ++++++++ .../lang/eval-fail-fromTOML-valueWithNullByte.nix | 1 + 12 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 tests/functional/lang/eval-fail-fromJSON-keyWithNullByte.err.exp create mode 100644 tests/functional/lang/eval-fail-fromJSON-keyWithNullByte.nix create mode 100644 tests/functional/lang/eval-fail-fromJSON-valueWithNullByte.err.exp create mode 100644 tests/functional/lang/eval-fail-fromJSON-valueWithNullByte.nix create mode 100644 tests/functional/lang/eval-fail-fromTOML-keyWithNullByte.err.exp create mode 100644 tests/functional/lang/eval-fail-fromTOML-keyWithNullByte.nix create mode 100644 tests/functional/lang/eval-fail-fromTOML-valueWithNullByte.err.exp create mode 100644 tests/functional/lang/eval-fail-fromTOML-valueWithNullByte.nix diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 05f58957e..7b6e89534 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -3178,5 +3178,14 @@ std::ostream & operator << (std::ostream & str, const ExternalValueBase & v) { return v.print(str); } +void forceNoNullByte(std::string_view s) +{ + if (s.find('\0') != s.npos) { + using namespace std::string_view_literals; + auto str = replaceStrings(std::string(s), "\0"sv, "␀"sv); + throw Error("input string '%s' cannot be represented as Nix string because it contains null bytes", str); + } +} + } diff --git a/src/libexpr/json-to-value.cc b/src/libexpr/json-to-value.cc index 9ac56541a..17cab7ad5 100644 --- a/src/libexpr/json-to-value.cc +++ b/src/libexpr/json-to-value.cc @@ -50,6 +50,7 @@ class JSONSax : nlohmann::json_sax { public: void key(string_t & name, EvalState & state) { + forceNoNullByte(name); attrs.insert_or_assign(state.symbols.create(name), &value(state)); } }; @@ -122,6 +123,7 @@ public: bool string(string_t & val) override { + forceNoNullByte(val); rs->value(state).mkString(val); rs->add(); return true; diff --git a/src/libexpr/primops/fromTOML.cc b/src/libexpr/primops/fromTOML.cc index 264046711..404425054 100644 --- a/src/libexpr/primops/fromTOML.cc +++ b/src/libexpr/primops/fromTOML.cc @@ -28,8 +28,10 @@ static void prim_fromTOML(EvalState & state, const PosIdx pos, Value * * args, V auto attrs = state.buildBindings(size); - for(auto & elem : table) + for(auto & elem : table) { + forceNoNullByte(elem.first); visit(attrs.alloc(elem.first), elem.second); + } v.mkAttrs(attrs); } @@ -54,7 +56,11 @@ static void prim_fromTOML(EvalState & state, const PosIdx pos, Value * * args, V v.mkFloat(toml::get(t)); break;; case toml::value_t::string: - v.mkString(toml::get(t)); + { + auto s = toml::get(t); + forceNoNullByte(s); + v.mkString(s); + } break;; case toml::value_t::local_datetime: case toml::value_t::offset_datetime: @@ -66,7 +72,9 @@ static void prim_fromTOML(EvalState & state, const PosIdx pos, Value * * args, V attrs.alloc("_type").mkString("timestamp"); std::ostringstream s; s << t; - attrs.alloc("value").mkString(toView(s)); + auto str = toView(s); + forceNoNullByte(str); + attrs.alloc("value").mkString(str); v.mkAttrs(attrs); } else { throw std::runtime_error("Dates and times are not supported"); diff --git a/src/libexpr/value.hh b/src/libexpr/value.hh index d98161488..88fcae986 100644 --- a/src/libexpr/value.hh +++ b/src/libexpr/value.hh @@ -510,4 +510,6 @@ typedef std::shared_ptr RootValue; RootValue allocRootValue(Value * v); +void forceNoNullByte(std::string_view s); + } diff --git a/tests/functional/lang/eval-fail-fromJSON-keyWithNullByte.err.exp b/tests/functional/lang/eval-fail-fromJSON-keyWithNullByte.err.exp new file mode 100644 index 000000000..a16192c59 --- /dev/null +++ b/tests/functional/lang/eval-fail-fromJSON-keyWithNullByte.err.exp @@ -0,0 +1,8 @@ +error: + … while calling the 'fromJSON' builtin + at /pwd/lang/eval-fail-fromJSON-keyWithNullByte.nix:1:1: + 1| builtins.fromJSON ''{"a\u0000b": 1}'' + | ^ + 2| + + error: input string 'a␀b' cannot be represented as Nix string because it contains null bytes diff --git a/tests/functional/lang/eval-fail-fromJSON-keyWithNullByte.nix b/tests/functional/lang/eval-fail-fromJSON-keyWithNullByte.nix new file mode 100644 index 000000000..ffaa6a97d --- /dev/null +++ b/tests/functional/lang/eval-fail-fromJSON-keyWithNullByte.nix @@ -0,0 +1 @@ +builtins.fromJSON ''{"a\u0000b": 1}'' diff --git a/tests/functional/lang/eval-fail-fromJSON-valueWithNullByte.err.exp b/tests/functional/lang/eval-fail-fromJSON-valueWithNullByte.err.exp new file mode 100644 index 000000000..c5c08e6ff --- /dev/null +++ b/tests/functional/lang/eval-fail-fromJSON-valueWithNullByte.err.exp @@ -0,0 +1,8 @@ +error: + … while calling the 'fromJSON' builtin + at /pwd/lang/eval-fail-fromJSON-valueWithNullByte.nix:1:1: + 1| builtins.fromJSON ''"a\u0000b"'' + | ^ + 2| + + error: input string 'a␀b' cannot be represented as Nix string because it contains null bytes diff --git a/tests/functional/lang/eval-fail-fromJSON-valueWithNullByte.nix b/tests/functional/lang/eval-fail-fromJSON-valueWithNullByte.nix new file mode 100644 index 000000000..c71ab990d --- /dev/null +++ b/tests/functional/lang/eval-fail-fromJSON-valueWithNullByte.nix @@ -0,0 +1 @@ +builtins.fromJSON ''"a\u0000b"'' diff --git a/tests/functional/lang/eval-fail-fromTOML-keyWithNullByte.err.exp b/tests/functional/lang/eval-fail-fromTOML-keyWithNullByte.err.exp new file mode 100644 index 000000000..dc2180f0b --- /dev/null +++ b/tests/functional/lang/eval-fail-fromTOML-keyWithNullByte.err.exp @@ -0,0 +1,8 @@ +error: + … while calling the 'fromTOML' builtin + at /pwd/lang/eval-fail-fromTOML-keyWithNullByte.nix:1:1: + 1| builtins.fromTOML ''"a\u0000b" = 1'' + | ^ + 2| + + error: while parsing TOML: error: input string 'a␀b' cannot be represented as Nix string because it contains null bytes diff --git a/tests/functional/lang/eval-fail-fromTOML-keyWithNullByte.nix b/tests/functional/lang/eval-fail-fromTOML-keyWithNullByte.nix new file mode 100644 index 000000000..b622dc4dc --- /dev/null +++ b/tests/functional/lang/eval-fail-fromTOML-keyWithNullByte.nix @@ -0,0 +1 @@ +builtins.fromTOML ''"a\u0000b" = 1'' diff --git a/tests/functional/lang/eval-fail-fromTOML-valueWithNullByte.err.exp b/tests/functional/lang/eval-fail-fromTOML-valueWithNullByte.err.exp new file mode 100644 index 000000000..0235692a8 --- /dev/null +++ b/tests/functional/lang/eval-fail-fromTOML-valueWithNullByte.err.exp @@ -0,0 +1,8 @@ +error: + … while calling the 'fromTOML' builtin + at /pwd/lang/eval-fail-fromTOML-valueWithNullByte.nix:1:1: + 1| builtins.fromTOML ''k = "a\u0000b"'' + | ^ + 2| + + error: while parsing TOML: error: input string 'a␀b' cannot be represented as Nix string because it contains null bytes diff --git a/tests/functional/lang/eval-fail-fromTOML-valueWithNullByte.nix b/tests/functional/lang/eval-fail-fromTOML-valueWithNullByte.nix new file mode 100644 index 000000000..183cab6b3 --- /dev/null +++ b/tests/functional/lang/eval-fail-fromTOML-valueWithNullByte.nix @@ -0,0 +1 @@ +builtins.fromTOML ''k = "a\u0000b"'' From 41a464c68de54d637f086c9a5f97111feacfa328 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Tue, 24 Sep 2024 11:18:19 +0200 Subject: [PATCH 540/718] tests/libstore.hh: reformat with clang-format after update --- src/libstore-test-support/tests/libstore.hh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libstore-test-support/tests/libstore.hh b/src/libstore-test-support/tests/libstore.hh index 84be52c23..699ba957e 100644 --- a/src/libstore-test-support/tests/libstore.hh +++ b/src/libstore-test-support/tests/libstore.hh @@ -19,12 +19,12 @@ public: protected: LibStoreTest() : store(openStore({ - .variant = - StoreReference::Specified{ - .scheme = "dummy", - }, - .params = {}, - })) + .variant = + StoreReference::Specified{ + .scheme = "dummy", + }, + .params = {}, + })) { } From b5cdf2e268c7dce5933dbbcc8cae64d170a04b73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Tue, 10 Dec 2024 05:33:32 +0100 Subject: [PATCH 541/718] mergify: don't use rebase merge method The repository configuration doesn't allow rebase merge method. --- .mergify.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.mergify.yml b/.mergify.yml index c545bbe6a..5b41c5c8d 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -5,7 +5,6 @@ queue_rules: - check-success=tests (macos-latest) - check-success=tests (ubuntu-latest) - check-success=vm_tests - merge_method: rebase batch_size: 5 pull_request_rules: From 6d97d57dc78c156c2dfd1fb830cfbc0152683827 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 11 Dec 2024 16:20:29 +0100 Subject: [PATCH 542/718] Prune unneeded .gitignore entries --- .gitignore | 122 +-------------------------------------- tests/functional/repl.sh | 2 +- 2 files changed, 4 insertions(+), 120 deletions(-) diff --git a/.gitignore b/.gitignore index de1183977..337a7c154 100644 --- a/.gitignore +++ b/.gitignore @@ -1,110 +1,12 @@ -Makefile.config -perl/Makefile.config - -# / -/aclocal.m4 -/autom4te.cache -/precompiled-headers.h.gch -/config.* -/configure -/stamp-h1 -/svn-revision -/libtool -/config/config.* # Default meson build dir /build -# /doc/manual/ -/doc/manual/*.1 -/doc/manual/*.5 -/doc/manual/*.8 -/doc/manual/generated/* -/doc/manual/nix.json -/doc/manual/conf-file.json -/doc/manual/language.json -/doc/manual/xp-features.json -/doc/manual/source/SUMMARY.md -/doc/manual/source/SUMMARY-rl-next.md -/doc/manual/source/store/types/* -!/doc/manual/source/store/types/index.md.in -/doc/manual/source/command-ref/new-cli -/doc/manual/source/command-ref/conf-file.md -/doc/manual/source/command-ref/experimental-features-shortlist.md -/doc/manual/source/contributing/experimental-feature-descriptions.md -/doc/manual/source/language/builtins.md -/doc/manual/source/language/builtin-constants.md -/doc/manual/source/release-notes/rl-next.md - -# /scripts/ -/scripts/nix-profile.sh -/scripts/nix-profile-daemon.sh -/scripts/nix-profile.fish -/scripts/nix-profile-daemon.fish - -# /src/libexpr/ -/src/libexpr/lexer-tab.cc -/src/libexpr/lexer-tab.hh -/src/libexpr/parser-tab.cc -/src/libexpr/parser-tab.hh -/src/libexpr/parser-tab.output -/src/libexpr/nix.tbl -/src/libexpr/tests -/src/libexpr-tests/libnixexpr-tests - -# /src/libfetchers -/src/libfetchers-tests/libnixfetchers-tests - -# /src/libflake -/src/libflake-tests/libnixflake-tests - -# /src/libstore/ -*.gen.* -/src/libstore/tests -/src/libstore-tests/libnixstore-tests - -# /src/libutil/ -/src/libutil/tests -/src/libutil-tests/libnixutil-tests - -/src/nix/nix - -/src/nix/generated-doc - -# /src/nix-env/ -/src/nix-env/nix-env - -# /src/nix-instantiate/ -/src/nix-instantiate/nix-instantiate - -# /src/nix-store/ -/src/nix-store/nix-store - -/src/nix-prefetch-url/nix-prefetch-url - -/src/nix-collect-garbage/nix-collect-garbage - -# /src/nix-channel/ -/src/nix-channel/nix-channel - -# /src/nix-build/ -/src/nix-build/nix-build - -/src/nix-copy-closure/nix-copy-closure - -/src/error-demo/error-demo - -/src/build-remote/build-remote - # /tests/functional/ -/tests/functional/test-tmp /tests/functional/common/subst-vars.sh -/tests/functional/result* /tests/functional/restricted-innocent -/tests/functional/shell -/tests/functional/shell.drv -/tests/functional/repl-result-out /tests/functional/debugger-test-out /tests/functional/test-libstoreconsumer/test-libstoreconsumer +/tests/functional/nix-shell # /tests/functional/lang/ /tests/functional/lang/*.out @@ -112,27 +14,9 @@ perl/Makefile.config /tests/functional/lang/*.err /tests/functional/lang/*.ast -/perl/lib/Nix/Config.pm -/perl/lib/Nix/Store.cc - -/misc/systemd/nix-daemon.service -/misc/systemd/nix-daemon.socket -/misc/systemd/nix-daemon.conf -/misc/upstart/nix-daemon.conf - outputs/ -*.a -*.o -*.o.tmp -*.so -*.dylib -*.dll -*.exe -*.dep *~ -*.pc -*.plist # GNU Global GPATH @@ -147,8 +31,6 @@ GTAGS compile_commands.json *.compile_commands.json -nix-rust/target - result result-* @@ -163,3 +45,5 @@ result-* # Mac OS .DS_Store + +flake-regressions diff --git a/tests/functional/repl.sh b/tests/functional/repl.sh index 706e0f5db..59d1f1be0 100755 --- a/tests/functional/repl.sh +++ b/tests/functional/repl.sh @@ -309,7 +309,7 @@ runRepl () { for test in $(cd "$testDir/repl"; echo *.in); do test="$(basename "$test" .in)" in="$testDir/repl/$test.in" - actual="$testDir/repl/$test.actual" + actual="$TEST_ROOT/$test.actual" expected="$testDir/repl/$test.expected" (cd "$testDir/repl"; set +x; runRepl 2>&1) < "$in" > "$actual" || { echo "FAIL: $test (exit code $?)" >&2 From 691b1ea237427845f073fbc790f960023bacdfe9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sat, 14 Dec 2024 09:44:36 +0100 Subject: [PATCH 543/718] speed up ci by splitting off eval and build - This speeds up macOS builds from 30 minutes to 11 minutes (3x faster). - Also improve error reporting e.g. printing out what actually failed to build. - As a result we also no longer need swap. --- .github/workflows/ci.yml | 28 +++++++++------------------- scripts/build-checks | 6 ++++++ 2 files changed, 15 insertions(+), 19 deletions(-) create mode 100755 scripts/build-checks diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index be96bb484..5fb672769 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,6 +7,14 @@ on: permissions: read-all jobs: + eval: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: cachix/install-nix-action@v30 + - run: nix --experimental-features 'nix-command flakes' flake show --all-systems --json tests: needs: [check_secrets] @@ -33,25 +41,7 @@ jobs: name: '${{ env.CACHIX_NAME }}' signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}' authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' - - if: matrix.os == 'ubuntu-latest' - run: | - free -h - swapon --show - swap=$(swapon --show --noheadings | head -n 1 | awk '{print $1}') - echo "Found swap: $swap" - sudo swapoff $swap - # resize it (fallocate) - sudo fallocate -l 10G $swap - sudo mkswap $swap - sudo swapon $swap - free -h - ( - while sleep 60; do - free -h - done - ) & - - run: nix --experimental-features 'nix-command flakes' flake check -L - - run: nix --experimental-features 'nix-command flakes' flake show --all-systems --json + - run: scripts/build-checks # Steps to test CI automation in your own fork. # Cachix: diff --git a/scripts/build-checks b/scripts/build-checks new file mode 100755 index 000000000..e0ee70631 --- /dev/null +++ b/scripts/build-checks @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +set -euo pipefail +system=$(nix eval --raw --impure --expr builtins.currentSystem) +nix eval --json ".#checks.$system" --apply builtins.attrNames | \ + jq -r '.[]' | \ + xargs -P0 -I '{}' sh -c "nix build -L .#checks.$system.{} || { echo 'FAILED: \033[0;31mnix build -L .#checks.$system.{}\\033[0m'; kill 0; }" From 31b3a34e5bb761a9eb84454bbb4d45261f0247ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sat, 14 Dec 2024 10:47:41 +0100 Subject: [PATCH 544/718] binary-tarball: create tarball without listing files This is producing quite a bit of log output in CI. --- scripts/binary-tarball.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/binary-tarball.nix b/scripts/binary-tarball.nix index 671c8e96e..9de90b7fb 100644 --- a/scripts/binary-tarball.nix +++ b/scripts/binary-tarball.nix @@ -65,7 +65,7 @@ runCommand "nix-binary-tarball-${version}" env '' fn=$out/$dir.tar.xz mkdir -p $out/nix-support echo "file binary-dist $fn" >> $out/nix-support/hydra-build-products - tar cvfJ $fn \ + tar cfJ $fn \ --owner=0 --group=0 --mode=u+rw,uga+r \ --mtime='1970-01-01' \ --absolute-names \ From 9f2b9256b6107a2db1f77c6eb7576c7d155e9644 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sat, 14 Dec 2024 12:05:49 +0100 Subject: [PATCH 545/718] ci: disable apparmor restrictions For our tests we need to map the root user for some tests. However ubuntu no longer allows this by default: https://ubuntu.com/blog/ubuntu-23-10-restricted-unprivileged-user-namespaces --- .github/workflows/ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5fb672769..3af1e8524 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,6 +41,10 @@ jobs: name: '${{ env.CACHIX_NAME }}' signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}' authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' + # Since ubuntu 22.30, unprivileged usernamespaces are no longer allowed to map to the root user: + # https://ubuntu.com/blog/ubuntu-23-10-restricted-unprivileged-user-namespaces + - run: sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 + if: matrix.os == 'ubuntu-latest' - run: scripts/build-checks # Steps to test CI automation in your own fork. From 4f831e2be5ec5ec82b42c838522ff3d285b88cb0 Mon Sep 17 00:00:00 2001 From: Greg Curtis Date: Thu, 12 Dec 2024 16:29:17 -0500 Subject: [PATCH 546/718] Fix `nix upgrade-nix` profile search Commit cfe66dbec updated `nix upgrade-nix` to use `ExecutablePath::load().find`, which broke the logic for finding the profile associated with the nix executable. The error looks something like: ``` $ sudo -i nix upgrade-nix --debug found Nix in '"/nix/store/46p1z0w9ad605kky62dr53z4h24k2a5r-nix-2.25.2/bin/nix"' found profile '/nix/store/46p1z0w9ad605kky62dr53z4h24k2a5r-nix-2.25.2/bin' error: directory '"/nix/store/46p1z0w9ad605kky62dr53z4h24k2a5r-nix-2.25.2/bin/nix"' does not appear to be part of a Nix profile ``` This seems to happen for two reasons: 1. The original PATH search resulted in a directory, but `find` returns the path to the executable. Fixed by getting the path's parent. 2. The profile symlink cannot be found because `ExecutablePath::load().find` canonicalizes the executable path. I updated find to normalize the path instead, which seems more in line with how other programs resolve paths. I'm not sure if this affects other callers though. I manually tested this on macOS and Linux, and it seemed to fix upgrading from 2.25.2 to 2.25.3. --- src/libutil/executable-path.cc | 2 +- src/nix/upgrade-nix.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libutil/executable-path.cc b/src/libutil/executable-path.cc index ebd522a41..8d665c7df 100644 --- a/src/libutil/executable-path.cc +++ b/src/libutil/executable-path.cc @@ -73,7 +73,7 @@ ExecutablePath::findName(const OsString & exe, std::functionparent_path(); printInfo("found Nix in '%s'", where); From 366611391ec749ff02545ab147a9d4f2792490aa Mon Sep 17 00:00:00 2001 From: Eli Kogan-Wang Date: Fri, 6 Dec 2024 15:54:47 +0100 Subject: [PATCH 547/718] Implement shellSplitString for proper handling of NIX_SSHOPTS with spaces and quotes --- doc/manual/rl-next/nix-sshopts-parsing.md | 21 +++++ src/libstore/ssh.cc | 13 ++- src/libutil-tests/strings.cc | 107 +++++++++++++++++++++- src/libutil/strings.cc | 104 +++++++++++++++++++++ src/libutil/strings.hh | 7 ++ 5 files changed, 248 insertions(+), 4 deletions(-) create mode 100644 doc/manual/rl-next/nix-sshopts-parsing.md diff --git a/doc/manual/rl-next/nix-sshopts-parsing.md b/doc/manual/rl-next/nix-sshopts-parsing.md new file mode 100644 index 000000000..65fe6f562 --- /dev/null +++ b/doc/manual/rl-next/nix-sshopts-parsing.md @@ -0,0 +1,21 @@ +--- +synopsis: "Improved `NIX_SSHOPTS` parsing for better SSH option handling" +issues: [5181] +prs: [12020] +--- + +The parsing of the `NIX_SSHOPTS` environment variable has been improved to handle spaces and quotes correctly. +Previously, incorrectly split SSH options could cause failures in CLIs like `nix-copy-closure`, +especially when using complex ssh invocations such as `-o ProxyCommand="ssh -W %h:%p ..."`. + +This change introduces a `shellSplitString` function to ensure +that `NIX_SSHOPTS` is parsed in a manner consistent with shell +behavior, addressing common parsing errors. + +For example, the following now works as expected: + +```bash +export NIX_SSHOPTS='-o ProxyCommand="ssh -W %h:%p ..."' +``` + +This update improves the reliability of SSH-related operations using `NIX_SSHOPTS` across Nix CLIs. diff --git a/src/libstore/ssh.cc b/src/libstore/ssh.cc index dec733fd5..116a480ba 100644 --- a/src/libstore/ssh.cc +++ b/src/libstore/ssh.cc @@ -41,8 +41,17 @@ void SSHMaster::addCommonSSHOpts(Strings & args) { auto state(state_.lock()); - for (auto & i : tokenizeString(getEnv("NIX_SSHOPTS").value_or(""))) - args.push_back(i); + std::string sshOpts = getEnv("NIX_SSHOPTS").value_or(""); + + try { + std::list opts = shellSplitString(sshOpts); + for (auto & i : opts) + args.push_back(i); + } catch (Error & e) { + e.addTrace({}, "while splitting NIX_SSHOPTS '%s'", sshOpts); + throw; + } + if (!keyFile.empty()) args.insert(args.end(), {"-i", keyFile}); if (!sshPublicHostKey.empty()) { diff --git a/src/libutil-tests/strings.cc b/src/libutil-tests/strings.cc index 8ceb16767..206890bcf 100644 --- a/src/libutil-tests/strings.cc +++ b/src/libutil-tests/strings.cc @@ -2,11 +2,10 @@ #include #include "strings.hh" +#include "error.hh" namespace nix { -using Strings = std::vector; - /* ---------------------------------------------------------------------------- * concatStringsSep * --------------------------------------------------------------------------*/ @@ -345,4 +344,108 @@ RC_GTEST_PROP(splitString, recoveredByConcatStringsSep, (const std::string & s)) RC_ASSERT(concatStringsSep("a", splitString(s, "a")) == s); } +/* ---------------------------------------------------------------------------- + * shellSplitString + * --------------------------------------------------------------------------*/ + +TEST(shellSplitString, empty) +{ + std::list expected = {}; + + ASSERT_EQ(shellSplitString(""), expected); +} + +TEST(shellSplitString, oneWord) +{ + std::list expected = {"foo"}; + + ASSERT_EQ(shellSplitString("foo"), expected); +} + +TEST(shellSplitString, oneWordQuotedWithSpaces) +{ + std::list expected = {"foo bar"}; + + ASSERT_EQ(shellSplitString("'foo bar'"), expected); +} + +TEST(shellSplitString, oneWordQuotedWithSpacesAndDoubleQuoteInSingleQuote) +{ + std::list expected = {"foo bar\""}; + + ASSERT_EQ(shellSplitString("'foo bar\"'"), expected); +} + +TEST(shellSplitString, oneWordQuotedWithDoubleQuotes) +{ + std::list expected = {"foo bar"}; + + ASSERT_EQ(shellSplitString("\"foo bar\""), expected); +} + +TEST(shellSplitString, twoWords) +{ + std::list expected = {"foo", "bar"}; + + ASSERT_EQ(shellSplitString("foo bar"), expected); +} + +TEST(shellSplitString, twoWordsWithSpacesAndQuotesQuoted) +{ + std::list expected = {"foo bar'", "baz\""}; + + ASSERT_EQ(shellSplitString("\"foo bar'\" 'baz\"'"), expected); +} + +TEST(shellSplitString, emptyArgumentsAreAllowedSingleQuotes) +{ + std::list expected = {"foo", "", "bar", "baz", ""}; + + ASSERT_EQ(shellSplitString("foo '' bar baz ''"), expected); +} + +TEST(shellSplitString, emptyArgumentsAreAllowedDoubleQuotes) +{ + std::list expected = {"foo", "", "bar", "baz", ""}; + + ASSERT_EQ(shellSplitString("foo \"\" bar baz \"\""), expected); +} + +TEST(shellSplitString, singleQuoteDoesNotUseEscapes) +{ + std::list expected = {"foo\\\"bar"}; + + ASSERT_EQ(shellSplitString("'foo\\\"bar'"), expected); +} + +TEST(shellSplitString, doubleQuoteDoesUseEscapes) +{ + std::list expected = {"foo\"bar"}; + + ASSERT_EQ(shellSplitString("\"foo\\\"bar\""), expected); +} + +TEST(shellSplitString, backslashEscapesSpaces) +{ + std::list expected = {"foo bar", "baz", "qux quux"}; + + ASSERT_EQ(shellSplitString("foo\\ bar baz qux\\ quux"), expected); +} + +TEST(shellSplitString, backslashEscapesQuotes) +{ + std::list expected = {"foo\"bar", "baz", "qux'quux"}; + + ASSERT_EQ(shellSplitString("foo\\\"bar baz qux\\'quux"), expected); +} + +TEST(shellSplitString, testUnbalancedQuotes) +{ + ASSERT_THROW(shellSplitString("foo'"), Error); + ASSERT_THROW(shellSplitString("foo\""), Error); + ASSERT_THROW(shellSplitString("foo'bar"), Error); + ASSERT_THROW(shellSplitString("foo\"bar"), Error); + ASSERT_THROW(shellSplitString("foo\"bar\\\""), Error); +} + } // namespace nix diff --git a/src/libutil/strings.cc b/src/libutil/strings.cc index c221a43c6..402b7ae98 100644 --- a/src/libutil/strings.cc +++ b/src/libutil/strings.cc @@ -4,6 +4,7 @@ #include "strings-inline.hh" #include "os-string.hh" +#include "error.hh" namespace nix { @@ -48,4 +49,107 @@ template std::string dropEmptyInitThenConcatStringsSep(std::string_view, const s template std::string dropEmptyInitThenConcatStringsSep(std::string_view, const std::set &); template std::string dropEmptyInitThenConcatStringsSep(std::string_view, const std::vector &); +/** + * Shell split string: split a string into shell arguments, respecting quotes and backslashes. + * + * Used for NIX_SSHOPTS handling, which previously used `tokenizeString` and was broken by + * Arguments that need to be passed to ssh with spaces in them. + * + * Read https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html for the + * POSIX shell specification, which is technically what we are implementing here. + */ +std::list shellSplitString(std::string_view s) +{ + std::list result; + std::string current; + bool startedCurrent = false; + bool escaping = false; + + auto pushCurrent = [&]() { + if (startedCurrent) { + result.push_back(current); + current.clear(); + startedCurrent = false; + } + }; + + auto pushChar = [&](char c) { + current.push_back(c); + startedCurrent = true; + }; + + auto pop = [&]() { + auto c = s[0]; + s.remove_prefix(1); + return c; + }; + + auto inDoubleQuotes = [&]() { + startedCurrent = true; + // in double quotes, escaping with backslash is only effective for $, `, ", and backslash + while (!s.empty()) { + auto c = pop(); + if (escaping) { + switch (c) { + case '$': + case '`': + case '"': + case '\\': + pushChar(c); + break; + default: + pushChar('\\'); + pushChar(c); + break; + } + escaping = false; + } else if (c == '\\') { + escaping = true; + } else if (c == '"') { + return; + } else { + pushChar(c); + } + } + if (s.empty()) { + throw Error("unterminated double quote"); + } + }; + + auto inSingleQuotes = [&]() { + startedCurrent = true; + while (!s.empty()) { + auto c = pop(); + if (c == '\'') { + return; + } + pushChar(c); + } + if (s.empty()) { + throw Error("unterminated single quote"); + } + }; + + while (!s.empty()) { + auto c = pop(); + if (escaping) { + pushChar(c); + escaping = false; + } else if (c == '\\') { + escaping = true; + } else if (c == ' ' || c == '\t') { + pushCurrent(); + } else if (c == '"') { + inDoubleQuotes(); + } else if (c == '\'') { + inSingleQuotes(); + } else { + pushChar(c); + } + } + + pushCurrent(); + + return result; +} } // namespace nix diff --git a/src/libutil/strings.hh b/src/libutil/strings.hh index 533126be1..c4fd3daa1 100644 --- a/src/libutil/strings.hh +++ b/src/libutil/strings.hh @@ -71,4 +71,11 @@ extern template std::string dropEmptyInitThenConcatStringsSep(std::string_view, extern template std::string dropEmptyInitThenConcatStringsSep(std::string_view, const std::set &); extern template std::string dropEmptyInitThenConcatStringsSep(std::string_view, const std::vector &); +/** + * Shell split string: split a string into shell arguments, respecting quotes and backslashes. + * + * Used for NIX_SSHOPTS handling, which previously used `tokenizeString` and was broken by + * Arguments that need to be passed to ssh with spaces in them. + */ +std::list shellSplitString(std::string_view s); } From 7d1c41f74cc02c6a941c690b655d3d5338074bc5 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Fri, 13 Dec 2024 13:09:03 +0100 Subject: [PATCH 548/718] C API: typo --- src/libutil-c/nix_api_util.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libutil-c/nix_api_util.h b/src/libutil-c/nix_api_util.h index 43f9fa9dc..5f42641d4 100644 --- a/src/libutil-c/nix_api_util.h +++ b/src/libutil-c/nix_api_util.h @@ -47,7 +47,7 @@ extern "C" { */ // Error codes /** - * @brief Type for error codes in the NIX system + * @brief Type for error codes in the Nix system * * This type can have one of several predefined constants: * - NIX_OK: No error occurred (0) From 80ee736b02bb3f400e656f65e3beb1b80a932cf7 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Fri, 13 Dec 2024 13:05:46 +0100 Subject: [PATCH 549/718] C API: document nix_store_open NULL URI tl;dr NULL is better than "auto" --- src/libstore-c/nix_api_store.h | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/libstore-c/nix_api_store.h b/src/libstore-c/nix_api_store.h index 282ccc285..60a287559 100644 --- a/src/libstore-c/nix_api_store.h +++ b/src/libstore-c/nix_api_store.h @@ -48,12 +48,27 @@ nix_err nix_libstore_init_no_load_config(nix_c_context * context); * Store instances may share state and resources behind the scenes. * * @param[out] context Optional, stores error information - * @param[in] uri URI of the Nix store, copied. See [*Store URL format* in the Nix Reference + * + * @param[in] uri @parblock + * URI of the Nix store, copied. + * + * If `NULL`, the store from the settings will be used. + * Note that `"auto"` holds a strange middle ground, reading part of the general environment, but not all of it. It + * ignores `NIX_REMOTE` and the `store` option. For this reason, `NULL` is most likely the better choice. + * + * For supported store URLs, see [*Store URL format* in the Nix Reference * Manual](https://nixos.org/manual/nix/stable/store/types/#store-url-format). - * @param[in] params optional, null-terminated array of key-value pairs, e.g. {{"endpoint", - * "https://s3.local"}}. See [*Store Types* in the Nix Reference - * Manual](https://nixos.org/manual/nix/stable/store/types). + * @endparblock + * + * @param[in] params @parblock + * optional, null-terminated array of key-value pairs, e.g. {{"endpoint", + * "https://s3.local"}}. + * + * See [*Store Types* in the Nix Reference Manual](https://nixos.org/manual/nix/stable/store/types). + * @endparblock + * * @return a Store pointer, NULL in case of errors + * * @see nix_store_free */ Store * nix_store_open(nix_c_context * context, const char * uri, const char *** params); From 472912f7ca9dbf90fdee18bc0a9b0994974c6660 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Thu, 12 Dec 2024 17:43:01 +0100 Subject: [PATCH 550/718] C API: Add nix_store_get_storedir --- src/libstore-c/nix_api_store.cc | 11 ++++++++++ src/libstore-c/nix_api_store.h | 13 +++++++++++- src/libstore-tests/meson.build | 5 ++++- src/libstore-tests/nix_api_store.cc | 33 +++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 2 deletions(-) diff --git a/src/libstore-c/nix_api_store.cc b/src/libstore-c/nix_api_store.cc index fb7391276..6e5dd559f 100644 --- a/src/libstore-c/nix_api_store.cc +++ b/src/libstore-c/nix_api_store.cc @@ -67,6 +67,17 @@ nix_err nix_store_get_uri(nix_c_context * context, Store * store, nix_get_string NIXC_CATCH_ERRS } +nix_err +nix_store_get_storedir(nix_c_context * context, Store * store, nix_get_string_callback callback, void * user_data) +{ + if (context) + context->last_err_code = NIX_OK; + try { + return call_nix_get_string_callback(store->ptr->storeDir, callback, user_data); + } + NIXC_CATCH_ERRS +} + nix_err nix_store_get_version(nix_c_context * context, Store * store, nix_get_string_callback callback, void * user_data) { diff --git a/src/libstore-c/nix_api_store.h b/src/libstore-c/nix_api_store.h index 60a287559..d421ee4d3 100644 --- a/src/libstore-c/nix_api_store.h +++ b/src/libstore-c/nix_api_store.h @@ -93,7 +93,18 @@ void nix_store_free(Store * store); */ nix_err nix_store_get_uri(nix_c_context * context, Store * store, nix_get_string_callback callback, void * user_data); -// returns: owned StorePath* +/** + * @brief get the storeDir of a Nix store, typically `"/nix/store"` + * @param[out] context Optional, stores error information + * @param[in] store nix store reference + * @param[in] callback Called with the URI. + * @param[in] user_data optional, arbitrary data, passed to the callback when it's called. + * @see nix_get_string_callback + * @return error code, NIX_OK on success. + */ +nix_err +nix_store_get_storedir(nix_c_context * context, Store * store, nix_get_string_callback callback, void * user_data); + /** * @brief Parse a Nix store path into a StorePath * diff --git a/src/libstore-tests/meson.build b/src/libstore-tests/meson.build index c4e42634d..b706fa12c 100644 --- a/src/libstore-tests/meson.build +++ b/src/libstore-tests/meson.build @@ -16,8 +16,10 @@ cxx = meson.get_compiler('cpp') subdir('nix-meson-build-support/deps-lists') +nix_store = dependency('nix-store') + deps_private_maybe_subproject = [ - dependency('nix-store'), + nix_store, dependency('nix-store-c'), dependency('nix-store-test-support'), ] @@ -90,6 +92,7 @@ this_exe = executable( include_directories : include_dirs, # TODO: -lrapidcheck, see ../libutil-support/build.meson link_args: linker_export_flags + ['-lrapidcheck'], + cpp_args : [ '-DNIX_STORE_DIR="' + nix_store.get_variable('storedir') + '"' ], # get main from gtest install : true, ) diff --git a/src/libstore-tests/nix_api_store.cc b/src/libstore-tests/nix_api_store.cc index 7c6ec0780..d47cd1dfd 100644 --- a/src/libstore-tests/nix_api_store.cc +++ b/src/libstore-tests/nix_api_store.cc @@ -24,6 +24,39 @@ TEST_F(nix_api_store_test, nix_store_get_uri) ASSERT_STREQ("local", str.c_str()); } +TEST_F(nix_api_util_context, nix_store_get_storedir_default) +{ + if (nix::getEnv("HOME").value_or("") == "/homeless-shelter") { + // skipping test in sandbox because nix_store_open tries to create /nix/var/nix/profiles + GTEST_SKIP(); + } + nix_libstore_init(ctx); + Store * store = nix_store_open(ctx, nullptr, nullptr); + assert_ctx_ok(); + ASSERT_NE(store, nullptr); + + std::string str; + auto ret = nix_store_get_storedir(ctx, store, OBSERVE_STRING(str)); + assert_ctx_ok(); + ASSERT_EQ(NIX_OK, ret); + + // These tests run with a unique storeDir, but not a relocated store + ASSERT_STREQ(NIX_STORE_DIR, str.c_str()); + + nix_store_free(store); +} + +TEST_F(nix_api_store_test, nix_store_get_storedir) +{ + std::string str; + auto ret = nix_store_get_storedir(ctx, store, OBSERVE_STRING(str)); + assert_ctx_ok(); + ASSERT_EQ(NIX_OK, ret); + + // These tests run with a unique storeDir, but not a relocated store + ASSERT_STREQ(nixStoreDir.c_str(), str.c_str()); +} + TEST_F(nix_api_store_test, InvalidPathFails) { nix_store_parse_path(ctx, store, "invalid-path"); From 2a981689423a531f5462f51aea17774ed4f17d0d Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Thu, 12 Dec 2024 18:51:11 +0100 Subject: [PATCH 551/718] C API: Add nix_store_real_path --- src/libstore-c/nix_api_store.cc | 12 +++++ src/libstore-c/nix_api_store.h | 20 ++++++++ src/libstore-tests/nix_api_store.cc | 80 +++++++++++++++++++++++++++++ 3 files changed, 112 insertions(+) diff --git a/src/libstore-c/nix_api_store.cc b/src/libstore-c/nix_api_store.cc index 6e5dd559f..bc306e0d0 100644 --- a/src/libstore-c/nix_api_store.cc +++ b/src/libstore-c/nix_api_store.cc @@ -100,6 +100,18 @@ bool nix_store_is_valid_path(nix_c_context * context, Store * store, StorePath * NIXC_CATCH_ERRS_RES(false); } +nix_err nix_store_real_path( + nix_c_context * context, Store * store, StorePath * path, nix_get_string_callback callback, void * user_data) +{ + if (context) + context->last_err_code = NIX_OK; + try { + auto res = store->ptr->toRealPath(path->path); + return call_nix_get_string_callback(res, callback, user_data); + } + NIXC_CATCH_ERRS +} + StorePath * nix_store_parse_path(nix_c_context * context, Store * store, const char * path) { if (context) diff --git a/src/libstore-c/nix_api_store.h b/src/libstore-c/nix_api_store.h index d421ee4d3..e55bc3f59 100644 --- a/src/libstore-c/nix_api_store.h +++ b/src/libstore-c/nix_api_store.h @@ -149,6 +149,26 @@ void nix_store_path_free(StorePath * p); * @return true or false, error info in context */ bool nix_store_is_valid_path(nix_c_context * context, Store * store, StorePath * path); + +/** + * @brief Get the physical location of a store path + * + * A store may reside at a different location than its `storeDir` suggests. + * This situation is called a relocated store. + * Relocated stores are used during NixOS installation, as well as in restricted computing environments that don't offer + * a writable `/nix/store`. + * + * Not all types of stores support this operation. + * + * @param[in] context Optional, stores error information + * @param[in] store nix store reference + * @param[in] path the path to get the real path from + * @param[in] callback called with the real path + * @param[in] user_data arbitrary data, passed to the callback when it's called. + */ +nix_err nix_store_real_path( + nix_c_context * context, Store * store, StorePath * path, nix_get_string_callback callback, void * user_data); + // nix_err nix_store_ensure(Store*, const char*); // nix_err nix_store_build_paths(Store*); /** diff --git a/src/libstore-tests/nix_api_store.cc b/src/libstore-tests/nix_api_store.cc index d47cd1dfd..a8b7b8e5f 100644 --- a/src/libstore-tests/nix_api_store.cc +++ b/src/libstore-tests/nix_api_store.cc @@ -119,4 +119,84 @@ TEST_F(nix_api_store_test, nix_store_is_valid_path_not_in_store) ASSERT_EQ(false, nix_store_is_valid_path(ctx, store, path)); } +TEST_F(nix_api_store_test, nix_store_real_path) +{ + StorePath * path = nix_store_parse_path(ctx, store, (nixStoreDir + PATH_SUFFIX).c_str()); + std::string rp; + auto ret = nix_store_real_path(ctx, store, path, OBSERVE_STRING(rp)); + assert_ctx_ok(); + ASSERT_EQ(NIX_OK, ret); + // Assumption: we're not testing with a relocated store + ASSERT_STREQ((nixStoreDir + PATH_SUFFIX).c_str(), rp.c_str()); + + nix_store_path_free(path); } + +TEST_F(nix_api_util_context, nix_store_real_path_relocated) +{ + if (nix::getEnv("HOME").value_or("") == "/homeless-shelter") { + // Can't open default store from within sandbox + GTEST_SKIP(); + } + auto tmp = nix::createTempDir(); + std::string storeRoot = tmp + "/store"; + std::string stateDir = tmp + "/state"; + std::string logDir = tmp + "/log"; + const char * rootkv[] = {"root", storeRoot.c_str()}; + const char * statekv[] = {"state", stateDir.c_str()}; + const char * logkv[] = {"log", logDir.c_str()}; + // const char * rokv[] = {"read-only", "true"}; + const char ** kvs[] = {rootkv, statekv, logkv, NULL}; + + nix_libstore_init(ctx); + assert_ctx_ok(); + + Store * store = nix_store_open(ctx, "local", kvs); + assert_ctx_ok(); + ASSERT_NE(store, nullptr); + + std::string nixStoreDir; + auto ret = nix_store_get_storedir(ctx, store, OBSERVE_STRING(nixStoreDir)); + ASSERT_EQ(NIX_OK, ret); + ASSERT_STREQ(NIX_STORE_DIR, nixStoreDir.c_str()); + + StorePath * path = nix_store_parse_path(ctx, store, (nixStoreDir + PATH_SUFFIX).c_str()); + assert_ctx_ok(); + ASSERT_NE(path, nullptr); + + std::string rp; + ret = nix_store_real_path(ctx, store, path, OBSERVE_STRING(rp)); + assert_ctx_ok(); + ASSERT_EQ(NIX_OK, ret); + + // Assumption: we're not testing with a relocated store + ASSERT_STREQ((storeRoot + NIX_STORE_DIR + PATH_SUFFIX).c_str(), rp.c_str()); + + nix_store_path_free(path); +} + +TEST_F(nix_api_util_context, nix_store_real_path_binary_cache) +{ + if (nix::getEnv("HOME").value_or("") == "/homeless-shelter") { + // TODO: override NIX_CACHE_HOME? + // skipping test in sandbox because narinfo cache can't be written + GTEST_SKIP(); + } + + Store * store = nix_store_open(ctx, "https://cache.nixos.org", nullptr); + assert_ctx_ok(); + ASSERT_NE(store, nullptr); + + std::string path_raw = std::string(NIX_STORE_DIR) + PATH_SUFFIX; + StorePath * path = nix_store_parse_path(ctx, store, path_raw.c_str()); + assert_ctx_ok(); + ASSERT_NE(path, nullptr); + + std::string rp; + auto ret = nix_store_real_path(ctx, store, path, OBSERVE_STRING(rp)); + assert_ctx_ok(); + ASSERT_EQ(NIX_OK, ret); + ASSERT_STREQ(path_raw.c_str(), rp.c_str()); +} + +} // namespace nixC From da7f7ba810e8fbcdc28bca490b5a5c618b1cef2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sat, 14 Dec 2024 12:55:45 +0100 Subject: [PATCH 552/718] functional-tests: skip tests if the kernel restricts unprivileged user namespaces Update tests/functional/common/functions.sh Co-authored-by: Robert Hensing --- .../build-remote-trustless-should-fail-0.sh | 1 + tests/functional/build-remote-trustless.sh | 1 + tests/functional/build-remote.sh | 2 ++ tests/functional/chroot-store.sh | 1 + tests/functional/common/functions.sh | 11 +++++++++++ tests/functional/linux-sandbox.sh | 1 + tests/functional/local-overlay-store/bad-uris.sh | 2 +- tests/functional/local-overlay-store/common.sh | 4 ---- tests/functional/nested-sandboxing.sh | 1 + tests/functional/nested-sandboxing/command.sh | 1 + tests/functional/shell.sh | 1 + tests/functional/supplementary-groups.sh | 2 +- 12 files changed, 22 insertions(+), 6 deletions(-) diff --git a/tests/functional/build-remote-trustless-should-fail-0.sh b/tests/functional/build-remote-trustless-should-fail-0.sh index 4eccb73e0..3401de1b0 100755 --- a/tests/functional/build-remote-trustless-should-fail-0.sh +++ b/tests/functional/build-remote-trustless-should-fail-0.sh @@ -8,6 +8,7 @@ TODO_NixOS restartDaemon requireSandboxSupport +requiresUnprivilegedUserNamespaces [[ $busybox =~ busybox ]] || skipTest "no busybox" unset NIX_STORE_DIR diff --git a/tests/functional/build-remote-trustless.sh b/tests/functional/build-remote-trustless.sh index c498d46c3..9f91a91a9 100644 --- a/tests/functional/build-remote-trustless.sh +++ b/tests/functional/build-remote-trustless.sh @@ -5,6 +5,7 @@ # shellcheck disable=SC2154 requireSandboxSupport +requiresUnprivilegedUserNamespaces [[ "$busybox" =~ busybox ]] || skipTest "no busybox" unset NIX_STORE_DIR diff --git a/tests/functional/build-remote.sh b/tests/functional/build-remote.sh index 1a5334577..3231341cb 100644 --- a/tests/functional/build-remote.sh +++ b/tests/functional/build-remote.sh @@ -3,6 +3,7 @@ : "${file?must be defined by caller (remote building test case using this)}" requireSandboxSupport +requiresUnprivilegedUserNamespaces [[ "${busybox-}" =~ busybox ]] || skipTest "no busybox" # Avoid store dir being inside sandbox build-dir @@ -27,6 +28,7 @@ builders=( chmod -R +w "$TEST_ROOT/machine"* || true rm -rf "$TEST_ROOT/machine"* || true + # Note: ssh://localhost bypasses ssh, directly invoking nix-store as a # child process. This allows us to test LegacySSHStore::buildDerivation(). # ssh-ng://... likewise allows us to test RemoteStore::buildDerivation(). diff --git a/tests/functional/chroot-store.sh b/tests/functional/chroot-store.sh index 46e91f0aa..ccde3e90b 100755 --- a/tests/functional/chroot-store.sh +++ b/tests/functional/chroot-store.sh @@ -40,6 +40,7 @@ EOF cp simple.nix shell.nix simple.builder.sh "${config_nix}" "$flakeDir/" TODO_NixOS + requiresUnprivilegedUserNamespaces outPath=$(nix build --print-out-paths --no-link --sandbox-paths '/nix? /bin? /lib? /lib64? /usr?' --store "$TEST_ROOT/x" path:"$flakeDir") diff --git a/tests/functional/common/functions.sh b/tests/functional/common/functions.sh index 7195149cb..bf3dd2ca8 100644 --- a/tests/functional/common/functions.sh +++ b/tests/functional/common/functions.sh @@ -345,4 +345,15 @@ count() { trap onError ERR +requiresUnprivilegedUserNamespaces() { + if [[ -f /proc/sys/kernel/apparmor_restrict_unprivileged_userns ]] && [[ $(< /proc/sys/kernel/apparmor_restrict_unprivileged_userns) -eq 1 ]]; then + skipTest "Unprivileged user namespaces are disabled. Run 'sudo sysctl -w /proc/sys/kernel/apparmor_restrict_unprivileged_userns=0' to allow, and run these tests." + fi +} + +execUnshare () { + requiresUnprivilegedUserNamespaces + exec unshare --mount --map-root-user "$SHELL" "$@" +} + fi # COMMON_FUNCTIONS_SH_SOURCED diff --git a/tests/functional/linux-sandbox.sh b/tests/functional/linux-sandbox.sh index 81ef36237..abb635f11 100755 --- a/tests/functional/linux-sandbox.sh +++ b/tests/functional/linux-sandbox.sh @@ -9,6 +9,7 @@ TODO_NixOS clearStore requireSandboxSupport +requiresUnprivilegedUserNamespaces # Note: we need to bind-mount $SHELL into the chroot. Currently we # only support the case where $SHELL is in the Nix store, because diff --git a/tests/functional/local-overlay-store/bad-uris.sh b/tests/functional/local-overlay-store/bad-uris.sh index b7930e32e..f0c6a151c 100644 --- a/tests/functional/local-overlay-store/bad-uris.sh +++ b/tests/functional/local-overlay-store/bad-uris.sh @@ -19,7 +19,7 @@ TODO_NixOS for i in "${storesBad[@]}"; do echo $i - unshare --mount --map-root-user bash < Date: Sat, 14 Dec 2024 17:17:29 +0100 Subject: [PATCH 553/718] installer: make sure we can always test the installer in ci and locally Just now there is a dependency on cachix, which means we cannot test the installer in CI if forks do not have the necessary secrets set up. We replace this with a simple http server that serves the installer and can be both used in CI and locally. --- .github/workflows/ci.yml | 119 +++++++------------ flake.nix | 4 +- packaging/hydra.nix | 13 +- scripts/prepare-installer-for-github-actions | 13 +- scripts/serve-installer-for-github-actions | 22 ++++ 5 files changed, 82 insertions(+), 89 deletions(-) create mode 100755 scripts/serve-installer-for-github-actions diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3af1e8524..addafb9f8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,7 +17,6 @@ jobs: - run: nix --experimental-features 'nix-command flakes' flake show --all-systems --json tests: - needs: [check_secrets] strategy: fail-fast: false matrix: @@ -34,72 +33,21 @@ jobs: extra_nix_config: | sandbox = true max-jobs = 1 - - run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV - - uses: cachix/cachix-action@v15 - if: needs.check_secrets.outputs.cachix == 'true' - with: - name: '${{ env.CACHIX_NAME }}' - signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}' - authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' + - uses: DeterminateSystems/magic-nix-cache-action@main # Since ubuntu 22.30, unprivileged usernamespaces are no longer allowed to map to the root user: # https://ubuntu.com/blog/ubuntu-23-10-restricted-unprivileged-user-namespaces - run: sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 if: matrix.os == 'ubuntu-latest' - run: scripts/build-checks - - # Steps to test CI automation in your own fork. - # Cachix: - # 1. Sign-up for https://www.cachix.org/ - # 2. Create a cache for $githubuser-nix-install-tests - # 3. Create a cachix auth token and save it in https://github.com/$githubuser/nix/settings/secrets/actions in "Repository secrets" as CACHIX_AUTH_TOKEN - # Dockerhub: - # 1. Sign-up for https://hub.docker.com/ - # 2. Store your dockerhub username as DOCKERHUB_USERNAME in "Repository secrets" of your fork repository settings (https://github.com/$githubuser/nix/settings/secrets/actions) - # 3. Create an access token in https://hub.docker.com/settings/security and store it as DOCKERHUB_TOKEN in "Repository secrets" of your fork - check_secrets: - permissions: - contents: none - name: Check Cachix and Docker secrets present for installer tests - runs-on: ubuntu-latest - outputs: - cachix: ${{ steps.secret.outputs.cachix }} - docker: ${{ steps.secret.outputs.docker }} - steps: - - name: Check for secrets - id: secret - env: - _CACHIX_SECRETS: ${{ secrets.CACHIX_SIGNING_KEY }}${{ secrets.CACHIX_AUTH_TOKEN }} - _DOCKER_SECRETS: ${{ secrets.DOCKERHUB_USERNAME }}${{ secrets.DOCKERHUB_TOKEN }} - run: | - echo "::set-output name=cachix::${{ env._CACHIX_SECRETS != '' }}" - echo "::set-output name=docker::${{ env._DOCKER_SECRETS != '' }}" - - installer: - needs: [tests, check_secrets] - if: github.event_name == 'push' && needs.check_secrets.outputs.cachix == 'true' - runs-on: ubuntu-latest - outputs: - installerURL: ${{ steps.prepare-installer.outputs.installerURL }} - steps: - - uses: actions/checkout@v4 + - run: scripts/prepare-installer-for-github-actions + - name: Upload installer tarball + uses: actions/upload-artifact@v4 with: - fetch-depth: 0 - - run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV - - uses: cachix/install-nix-action@v30 - with: - install_url: https://releases.nixos.org/nix/nix-2.20.3/install - - uses: cachix/cachix-action@v15 - with: - name: '${{ env.CACHIX_NAME }}' - signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}' - authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' - cachixArgs: '-v' - - id: prepare-installer - run: scripts/prepare-installer-for-github-actions + name: installer-${{matrix.os}} + path: out/* installer_test: - needs: [installer, check_secrets] - if: github.event_name == 'push' && needs.check_secrets.outputs.cachix == 'true' + needs: [tests] strategy: fail-fast: false matrix: @@ -107,11 +55,18 @@ jobs: runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - - run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV + - name: Download installer tarball + uses: actions/download-artifact@v4 + with: + name: installer-${{matrix.os}} + path: out + - name: Serving installer + id: serving_installer + run: ./scripts/serve-installer-for-github-actions - uses: cachix/install-nix-action@v30 with: - install_url: '${{needs.installer.outputs.installerURL}}' - install_options: "--tarball-url-prefix https://${{ env.CACHIX_NAME }}.cachix.org/serve" + install_url: 'http://localhost:8126/install' + install_options: "--tarball-url-prefix http://localhost:8126/" - run: sudo apt install fish zsh if: matrix.os == 'ubuntu-latest' - run: brew install fish @@ -123,32 +78,50 @@ jobs: - run: exec bash -c "nix-channel --add https://releases.nixos.org/nixos/unstable/nixos-23.05pre466020.60c1d71f2ba nixpkgs" - run: exec bash -c "nix-channel --update && nix-env -iA nixpkgs.hello && hello" + # Steps to test CI automation in your own fork. + # 1. Sign-up for https://hub.docker.com/ + # 2. Store your dockerhub username as DOCKERHUB_USERNAME in "Repository secrets" of your fork repository settings (https://github.com/$githubuser/nix/settings/secrets/actions) + # 3. Create an access token in https://hub.docker.com/settings/security and store it as DOCKERHUB_TOKEN in "Repository secrets" of your fork + check_secrets: + permissions: + contents: none + name: Check Docker secrets present for installer tests + runs-on: ubuntu-latest + outputs: + docker: ${{ steps.secret.outputs.docker }} + steps: + - name: Check for secrets + id: secret + env: + _DOCKER_SECRETS: ${{ secrets.DOCKERHUB_USERNAME }}${{ secrets.DOCKERHUB_TOKEN }} + run: | + echo "::set-output name=docker::${{ env._DOCKER_SECRETS != '' }}" + docker_push_image: - needs: [check_secrets, tests, vm_tests] + needs: [tests, vm_tests, check_secrets] permissions: contents: read packages: write if: >- + needs.check_secrets.outputs.docker == 'true' && github.event_name == 'push' && - github.ref_name == 'master' && - needs.check_secrets.outputs.cachix == 'true' && - needs.check_secrets.outputs.docker == 'true' + github.ref_name == 'master' runs-on: ubuntu-latest steps: + - name: Check for secrets + id: secret + env: + _DOCKER_SECRETS: ${{ secrets.DOCKERHUB_USERNAME }}${{ secrets.DOCKERHUB_TOKEN }} + run: | + echo "::set-output name=docker::${{ env._DOCKER_SECRETS != '' }}" - uses: actions/checkout@v4 with: fetch-depth: 0 - uses: cachix/install-nix-action@v30 with: install_url: https://releases.nixos.org/nix/nix-2.20.3/install - - run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV + - uses: DeterminateSystems/magic-nix-cache-action@main - run: echo NIX_VERSION="$(nix --experimental-features 'nix-command flakes' eval .\#nix.version | tr -d \")" >> $GITHUB_ENV - - uses: cachix/cachix-action@v15 - if: needs.check_secrets.outputs.cachix == 'true' - with: - name: '${{ env.CACHIX_NAME }}' - signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}' - authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' - run: nix --experimental-features 'nix-command flakes' build .#dockerImage -L - run: docker load -i ./result/image.tar.gz - run: docker tag nix:$NIX_VERSION ${{ secrets.DOCKERHUB_USERNAME }}/nix:$NIX_VERSION diff --git a/flake.nix b/flake.nix index 794736af4..a5e68609e 100644 --- a/flake.nix +++ b/flake.nix @@ -186,7 +186,7 @@ }; checks = forAllSystems (system: { - binaryTarball = self.hydraJobs.binaryTarball.${system}; + installerScriptForGHA = self.hydraJobs.installerScriptForGHA.${system}; installTests = self.hydraJobs.installTests.${system}; nixpkgsLibTests = self.hydraJobs.tests.nixpkgsLibTests.${system}; rl-next = @@ -237,6 +237,8 @@ inherit (nixpkgsFor.${system}.native) changelog-d; default = self.packages.${system}.nix; + installerScriptForGHA = self.hydraJobs.installerScriptForGHA.${system}; + binaryTarball = self.hydraJobs.binaryTarball.${system}; # TODO probably should be `nix-cli` nix = self.packages.${system}.nix-everything; nix-manual = nixpkgsFor.${system}.native.nixComponents.nix-manual; diff --git a/packaging/hydra.nix b/packaging/hydra.nix index 17ba72032..5b1e47559 100644 --- a/packaging/hydra.nix +++ b/packaging/hydra.nix @@ -123,15 +123,10 @@ in self.hydraJobs.binaryTarballCross."x86_64-linux"."armv7l-unknown-linux-gnueabihf" self.hydraJobs.binaryTarballCross."x86_64-linux"."riscv64-unknown-linux-gnu" ]; - installerScriptForGHA = installScriptFor [ - # Native - self.hydraJobs.binaryTarball."x86_64-linux" - self.hydraJobs.binaryTarball."aarch64-darwin" - # Cross - self.hydraJobs.binaryTarballCross."x86_64-linux"."armv6l-unknown-linux-gnueabihf" - self.hydraJobs.binaryTarballCross."x86_64-linux"."armv7l-unknown-linux-gnueabihf" - self.hydraJobs.binaryTarballCross."x86_64-linux"."riscv64-unknown-linux-gnu" - ]; + + installerScriptForGHA = forAllSystems (system: nixpkgsFor.${system}.native.callPackage ../scripts/installer.nix { + tarballs = [ self.hydraJobs.binaryTarball.${system} ]; + }); # docker image with Nix inside dockerImage = lib.genAttrs linux64BitSystems (system: self.packages.${system}.dockerImage); diff --git a/scripts/prepare-installer-for-github-actions b/scripts/prepare-installer-for-github-actions index 4b994a753..0fbecf25c 100755 --- a/scripts/prepare-installer-for-github-actions +++ b/scripts/prepare-installer-for-github-actions @@ -1,10 +1,11 @@ #!/usr/bin/env bash -set -e +set -euo pipefail -script=$(nix-build -A outputs.hydraJobs.installerScriptForGHA --no-out-link) -installerHash=$(echo "$script" | cut -b12-43 -) +nix build -L ".#installerScriptForGHA" ".#binaryTarball" -installerURL=https://$CACHIX_NAME.cachix.org/serve/$installerHash/install - -echo "::set-output name=installerURL::$installerURL" +mkdir -p out +cp ./result/install "out/install" +name="$(basename "$(realpath ./result-1)")" +# everything before the first dash +cp -r ./result-1 "out/${name%%-*}" diff --git a/scripts/serve-installer-for-github-actions b/scripts/serve-installer-for-github-actions new file mode 100755 index 000000000..2efd2aa32 --- /dev/null +++ b/scripts/serve-installer-for-github-actions @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +set -euo pipefail +if [[ ! -d out ]]; then + echo "run prepare-installer-for-github-actions first" + exit 1 +fi +cd out +PORT=${PORT:-8126} +nohup python -m http.server "$PORT" >/dev/null 2>&1 & +pid=$! + +while ! curl -s "http://localhost:$PORT"; do + sleep 1 + if ! kill -0 $pid; then + echo "Failed to start http server" + exit 1 + fi +done + +echo 'To install nix, run the following command:' +echo "sh <(curl http://localhost:$PORT/install) --tarball-url-prefix http://localhost:$PORT" From df3eb4f3f6e80fa3bdcd17f36ec6b0a9156825fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sun, 15 Dec 2024 18:45:03 +0100 Subject: [PATCH 554/718] mergify: updated required tests --- .mergify.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.mergify.yml b/.mergify.yml index 5b41c5c8d..70fccae49 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -4,6 +4,8 @@ queue_rules: merge_conditions: - check-success=tests (macos-latest) - check-success=tests (ubuntu-latest) + - check-success=installer_test (macos-latest) + - check-success=installer_test (ubuntu-latest) - check-success=vm_tests batch_size: 5 From ccaa4c259ad33d5378e0641f9bb891430bf9bbd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sun, 15 Dec 2024 21:04:26 +0100 Subject: [PATCH 555/718] upgrade-nix: don't double quote path on error the format error already adds quotes. --- src/nix/upgrade-nix.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nix/upgrade-nix.cc b/src/nix/upgrade-nix.cc index a4722abf5..77fb798a7 100644 --- a/src/nix/upgrade-nix.cc +++ b/src/nix/upgrade-nix.cc @@ -126,7 +126,7 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand if (where.filename() != "bin" || !hasSuffix(userEnv, "user-environment")) - throw Error("directory '%s' does not appear to be part of a Nix profile", where); + throw Error("directory %s does not appear to be part of a Nix profile", where); if (!store->isValidPath(store->parseStorePath(userEnv))) throw Error("directory '%s' is not in the Nix store", userEnv); From 7ddf7300b52c8500718ca1fbaca76bab017f6edf Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 6 Dec 2024 11:45:26 +0100 Subject: [PATCH 556/718] Ignore local registries for lock file generation When resolving indirect flake references like `nixpkgs` in `flake.nix` files, Nix will no longer use the system and user flake registries. It will only use the global flake registry and overrides given on the command line via `--override-flake`. --- doc/manual/rl-next/ignore-local-registries.md | 22 +++++++++++++++++++ src/libfetchers/registry.cc | 4 +++- src/libfetchers/registry.hh | 9 +++++++- src/libflake/flake/flake.cc | 8 ++++++- src/libflake/flake/flakeref.cc | 5 +++-- src/libflake/flake/flakeref.hh | 5 ++++- src/nix/flake.md | 3 ++- src/nix/registry.md | 2 ++ 8 files changed, 51 insertions(+), 7 deletions(-) create mode 100644 doc/manual/rl-next/ignore-local-registries.md diff --git a/doc/manual/rl-next/ignore-local-registries.md b/doc/manual/rl-next/ignore-local-registries.md new file mode 100644 index 000000000..8d5e333dd --- /dev/null +++ b/doc/manual/rl-next/ignore-local-registries.md @@ -0,0 +1,22 @@ +--- +synopsis: "Flake lock file generation now ignores local registries" +prs: [12019] +--- + +When resolving indirect flake references like `nixpkgs` in `flake.nix` files, Nix will no longer use the system and user flake registries. It will only use the global flake registry and overrides given on the command line via `--override-flake`. + +This avoids accidents where users have local registry overrides that map `nixpkgs` to a `path:` flake in the local file system, which then end up in committed lock files pushed to other users. + +In the future, we may remove the use of the registry during lock file generation altogether. It's better to explicitly specify the URL of a flake input. For example, instead of +```nix +{ + outputs = { self, nixpkgs }: { ... }; +} +``` +write +```nix +{ + inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11"; + outputs = { self, nixpkgs }: { ... }; +} +``` diff --git a/src/libfetchers/registry.cc b/src/libfetchers/registry.cc index c761028ab..171afcea7 100644 --- a/src/libfetchers/registry.cc +++ b/src/libfetchers/registry.cc @@ -178,7 +178,8 @@ Registries getRegistries(const Settings & settings, ref store) std::pair lookupInRegistries( ref store, - const Input & _input) + const Input & _input, + const RegistryFilter & filter) { Attrs extraAttrs; int n = 0; @@ -190,6 +191,7 @@ std::pair lookupInRegistries( if (n > 100) throw Error("cycle detected in flake registry for '%s'", input.to_string()); for (auto & registry : getRegistries(*input.settings, store)) { + if (filter && !filter(registry->type)) continue; // FIXME: O(n) for (auto & entry : registry->entries) { if (entry.exact) { diff --git a/src/libfetchers/registry.hh b/src/libfetchers/registry.hh index 0d68ac395..8f47e1590 100644 --- a/src/libfetchers/registry.hh +++ b/src/libfetchers/registry.hh @@ -65,8 +65,15 @@ void overrideRegistry( const Input & to, const Attrs & extraAttrs); +using RegistryFilter = std::function; + +/** + * Rewrite a flakeref using the registries. If `filter` is set, only + * use the registries for which the filter function returns true. + */ std::pair lookupInRegistries( ref store, - const Input & input); + const Input & input, + const RegistryFilter & filter = {}); } diff --git a/src/libflake/flake/flake.cc b/src/libflake/flake/flake.cc index 19b622a34..01cd8db65 100644 --- a/src/libflake/flake/flake.cc +++ b/src/libflake/flake/flake.cc @@ -54,7 +54,13 @@ static std::tuple fetchOrSubstituteTree( fetched.emplace(originalRef.fetchTree(state.store)); } else { if (allowLookup) { - resolvedRef = originalRef.resolve(state.store); + resolvedRef = originalRef.resolve( + state.store, + [](fetchers::Registry::RegistryType type) { + /* Only use the global registry and CLI flags + to resolve indirect flakerefs. */ + return type == fetchers::Registry::Flag || type == fetchers::Registry::Global; + }); auto fetchedResolved = lookupInFlakeCache(flakeCache, originalRef); if (!fetchedResolved) fetchedResolved.emplace(resolvedRef.fetchTree(state.store)); flakeCache.push_back({resolvedRef, *fetchedResolved}); diff --git a/src/libflake/flake/flakeref.cc b/src/libflake/flake/flakeref.cc index 9616fe0ea..ab882fdab 100644 --- a/src/libflake/flake/flakeref.cc +++ b/src/libflake/flake/flakeref.cc @@ -3,7 +3,6 @@ #include "url.hh" #include "url-parts.hh" #include "fetchers.hh" -#include "registry.hh" namespace nix { @@ -36,7 +35,9 @@ std::ostream & operator << (std::ostream & str, const FlakeRef & flakeRef) return str; } -FlakeRef FlakeRef::resolve(ref store) const +FlakeRef FlakeRef::resolve( + ref store, + const fetchers::RegistryFilter & filter) const { auto [input2, extraAttrs] = lookupInRegistries(store, input); return FlakeRef(std::move(input2), fetchers::maybeGetStrAttr(extraAttrs, "dir").value_or(subdir)); diff --git a/src/libflake/flake/flakeref.hh b/src/libflake/flake/flakeref.hh index 1064538a7..80013e87e 100644 --- a/src/libflake/flake/flakeref.hh +++ b/src/libflake/flake/flakeref.hh @@ -6,6 +6,7 @@ #include "types.hh" #include "fetchers.hh" #include "outputs-spec.hh" +#include "registry.hh" namespace nix { @@ -57,7 +58,9 @@ struct FlakeRef fetchers::Attrs toAttrs() const; - FlakeRef resolve(ref store) const; + FlakeRef resolve( + ref store, + const fetchers::RegistryFilter & filter = {}) const; static FlakeRef fromAttrs( const fetchers::Settings & fetchSettings, diff --git a/src/nix/flake.md b/src/nix/flake.md index 1e9895f6e..1028dc807 100644 --- a/src/nix/flake.md +++ b/src/nix/flake.md @@ -165,7 +165,8 @@ can occur in *locked* flake references and are available to Nix code: Currently the `type` attribute can be one of the following: -* `indirect`: *The default*. Indirection through the flake registry. +* `indirect`: *The default*. These are symbolic references to flakes + that are looked up in [the flake registries](./nix3-registry.md). These have the form ``` diff --git a/src/nix/registry.md b/src/nix/registry.md index bd3575d1b..d6f8af5e9 100644 --- a/src/nix/registry.md +++ b/src/nix/registry.md @@ -34,6 +34,8 @@ highest precedence: * Overrides specified on the command line using the option `--override-flake`. +Note that the system and user registries are not used to resolve flake references in `flake.nix`. They are only used to resolve flake references on the command line. + # Registry format A registry is a JSON file with the following format: From d8117c8c0de0a533a42b563ed01e67976368da09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Mon, 16 Dec 2024 11:46:02 +0100 Subject: [PATCH 557/718] libexpr: always initialize displacement Otherwise the value is undefined in some cases. --- src/libexpr/nixexpr.hh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh index 2950ff1fd..a7ad580d2 100644 --- a/src/libexpr/nixexpr.hh +++ b/src/libexpr/nixexpr.hh @@ -168,7 +168,7 @@ struct ExprVar : Expr the set stored in the environment that is `level` levels up from the current one.*/ Level level; - Displacement displ; + Displacement displ = 0; ExprVar(Symbol name) : name(name) { }; ExprVar(const PosIdx & pos, Symbol name) : pos(pos), name(name) { }; @@ -242,7 +242,7 @@ struct ExprAttrs : Expr Kind kind; Expr * e; PosIdx pos; - Displacement displ; // displacement + Displacement displ = 0; // displacement AttrDef(Expr * e, const PosIdx & pos, Kind kind = Kind::Plain) : kind(kind), e(e), pos(pos) { }; AttrDef() { }; From d1f20e3510ef39bc36287773cff35383e824ebc0 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 16 Dec 2024 14:58:25 +0100 Subject: [PATCH 558/718] Make FetchedFlake a struct --- src/libflake/flake/flake.cc | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/libflake/flake/flake.cc b/src/libflake/flake/flake.cc index bc62e0bc5..0bdaeb789 100644 --- a/src/libflake/flake/flake.cc +++ b/src/libflake/flake/flake.cc @@ -21,7 +21,12 @@ using namespace flake; namespace flake { -typedef std::pair FetchedFlake; +struct FetchedFlake +{ + FlakeRef lockedRef; + StorePath storePath; +}; + typedef std::vector> FlakeCache; static std::optional lookupInFlakeCache( @@ -32,7 +37,7 @@ static std::optional lookupInFlakeCache( for (auto & i : flakeCache) { if (flakeRef == i.first) { debug("mapping '%s' to previously seen input '%s' -> '%s", - flakeRef, i.first, i.second.second); + flakeRef, i.first, i.second.lockedRef); return i.second; } } @@ -51,7 +56,8 @@ static std::tuple fetchOrSubstituteTree( if (!fetched) { if (originalRef.input.isDirect()) { - fetched.emplace(originalRef.fetchTree(state.store)); + auto [storePath, lockedRef] = originalRef.fetchTree(state.store); + fetched.emplace(FetchedFlake{.lockedRef = lockedRef, .storePath = storePath}); } else { if (allowLookup) { resolvedRef = originalRef.resolve( @@ -61,10 +67,12 @@ static std::tuple fetchOrSubstituteTree( to resolve indirect flakerefs. */ return type == fetchers::Registry::Flag || type == fetchers::Registry::Global; }); - auto fetchedResolved = lookupInFlakeCache(flakeCache, originalRef); - if (!fetchedResolved) fetchedResolved.emplace(resolvedRef.fetchTree(state.store)); - flakeCache.push_back({resolvedRef, *fetchedResolved}); - fetched.emplace(*fetchedResolved); + fetched = lookupInFlakeCache(flakeCache, originalRef); + if (!fetched) { + auto [storePath, lockedRef] = resolvedRef.fetchTree(state.store); + fetched.emplace(FetchedFlake{.lockedRef = lockedRef, .storePath = storePath}); + } + flakeCache.push_back({resolvedRef, *fetched}); } else { throw Error("'%s' is an indirect flake reference, but registry lookups are not allowed", originalRef); @@ -73,16 +81,14 @@ static std::tuple fetchOrSubstituteTree( flakeCache.push_back({originalRef, *fetched}); } - auto [storePath, lockedRef] = *fetched; - debug("got tree '%s' from '%s'", - state.store->printStorePath(storePath), lockedRef); + state.store->printStorePath(fetched->storePath), fetched->lockedRef); - state.allowPath(storePath); + state.allowPath(fetched->storePath); - assert(!originalRef.input.getNarHash() || storePath == originalRef.input.computeStorePath(*state.store)); + assert(!originalRef.input.getNarHash() || fetched->storePath == originalRef.input.computeStorePath(*state.store)); - return {std::move(storePath), resolvedRef, lockedRef}; + return {fetched->storePath, resolvedRef, fetched->lockedRef}; } static void forceTrivialValue(EvalState & state, Value & value, const PosIdx pos) From d2e1d4916a7a74ba75dbbdff0f696acb0859dbfd Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 10 Dec 2024 15:30:55 +0100 Subject: [PATCH 559/718] lookupInFlakeCache(): Fix O(n) time lookup --- src/libfetchers/fetchers.hh | 5 +++++ src/libflake/flake/flake.cc | 21 ++++++++------------- src/libflake/flake/flakeref.hh | 2 ++ src/libutil/types.hh | 7 +++---- 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/libfetchers/fetchers.hh b/src/libfetchers/fetchers.hh index b28ec4568..94b2320f9 100644 --- a/src/libfetchers/fetchers.hh +++ b/src/libfetchers/fetchers.hh @@ -104,6 +104,11 @@ public: bool operator ==(const Input & other) const noexcept; + auto operator <=>(const Input & other) const + { + return attrs <=> other.attrs; + } + bool contains(const Input & other) const; /** diff --git a/src/libflake/flake/flake.cc b/src/libflake/flake/flake.cc index 0bdaeb789..29090b900 100644 --- a/src/libflake/flake/flake.cc +++ b/src/libflake/flake/flake.cc @@ -27,22 +27,17 @@ struct FetchedFlake StorePath storePath; }; -typedef std::vector> FlakeCache; +typedef std::map FlakeCache; static std::optional lookupInFlakeCache( const FlakeCache & flakeCache, const FlakeRef & flakeRef) { - // FIXME: inefficient. - for (auto & i : flakeCache) { - if (flakeRef == i.first) { - debug("mapping '%s' to previously seen input '%s' -> '%s", - flakeRef, i.first, i.second.lockedRef); - return i.second; - } - } - - return std::nullopt; + auto i = flakeCache.find(flakeRef); + if (i == flakeCache.end()) return std::nullopt; + debug("mapping '%s' to previously seen input '%s' -> '%s", + flakeRef, i->first, i->second.lockedRef); + return i->second; } static std::tuple fetchOrSubstituteTree( @@ -72,13 +67,13 @@ static std::tuple fetchOrSubstituteTree( auto [storePath, lockedRef] = resolvedRef.fetchTree(state.store); fetched.emplace(FetchedFlake{.lockedRef = lockedRef, .storePath = storePath}); } - flakeCache.push_back({resolvedRef, *fetched}); + flakeCache.insert_or_assign(resolvedRef, *fetched); } else { throw Error("'%s' is an indirect flake reference, but registry lookups are not allowed", originalRef); } } - flakeCache.push_back({originalRef, *fetched}); + flakeCache.insert_or_assign(originalRef, *fetched); } debug("got tree '%s' from '%s'", diff --git a/src/libflake/flake/flakeref.hh b/src/libflake/flake/flakeref.hh index 80013e87e..2ba01c72b 100644 --- a/src/libflake/flake/flakeref.hh +++ b/src/libflake/flake/flakeref.hh @@ -49,6 +49,8 @@ struct FlakeRef bool operator ==(const FlakeRef & other) const = default; + auto operator <=>(const FlakeRef &) const = default; + FlakeRef(fetchers::Input && input, const Path & subdir) : input(std::move(input)), subdir(subdir) { } diff --git a/src/libutil/types.hh b/src/libutil/types.hh index 325e3ea73..f30dd910e 100644 --- a/src/libutil/types.hh +++ b/src/libutil/types.hh @@ -43,10 +43,9 @@ template struct Explicit { T t; - bool operator ==(const Explicit & other) const - { - return t == other.t; - } + bool operator ==(const Explicit & other) const = default; + + auto operator <=>(const Explicit & other) const = default; }; From b167e2c415684518626265abfbdb3b756f04ee1b Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 11 Dec 2024 20:59:59 +0100 Subject: [PATCH 560/718] Work around clang/libc++ issue --- src/libfetchers/fetchers.hh | 4 ++-- src/libflake/flake/flakeref.hh | 5 ++++- src/libutil/types.hh | 5 ++++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/libfetchers/fetchers.hh b/src/libfetchers/fetchers.hh index 94b2320f9..ff04d5551 100644 --- a/src/libfetchers/fetchers.hh +++ b/src/libfetchers/fetchers.hh @@ -104,9 +104,9 @@ public: bool operator ==(const Input & other) const noexcept; - auto operator <=>(const Input & other) const + bool operator <(const Input & other) const { - return attrs <=> other.attrs; + return attrs < other.attrs; } bool contains(const Input & other) const; diff --git a/src/libflake/flake/flakeref.hh b/src/libflake/flake/flakeref.hh index 2ba01c72b..ec755399d 100644 --- a/src/libflake/flake/flakeref.hh +++ b/src/libflake/flake/flakeref.hh @@ -49,7 +49,10 @@ struct FlakeRef bool operator ==(const FlakeRef & other) const = default; - auto operator <=>(const FlakeRef &) const = default; + bool operator <(const FlakeRef & other) const + { + return std::tie(input, subdir) < std::tie(other.input, other.subdir); + } FlakeRef(fetchers::Input && input, const Path & subdir) : input(std::move(input)), subdir(subdir) diff --git a/src/libutil/types.hh b/src/libutil/types.hh index f30dd910e..9f5c75827 100644 --- a/src/libutil/types.hh +++ b/src/libutil/types.hh @@ -45,7 +45,10 @@ struct Explicit { bool operator ==(const Explicit & other) const = default; - auto operator <=>(const Explicit & other) const = default; + bool operator <(const Explicit & other) const + { + return t < other.t; + } }; From 08361f031d65703aa35cb3b7e7715ff63256e311 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 13 Dec 2024 16:49:48 +0100 Subject: [PATCH 561/718] EvalState::realiseContext(): Allow access to the entire closure Fixes #11030. --- src/libexpr/eval.cc | 15 +++++++++++---- src/libexpr/eval.hh | 5 +++++ src/libexpr/primops.cc | 8 +++----- tests/functional/import-from-derivation.nix | 21 ++++++++++++++++++++- tests/functional/import-from-derivation.sh | 5 +++++ 5 files changed, 44 insertions(+), 10 deletions(-) diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 7b6e89534..fe5f05ab8 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -347,6 +347,16 @@ void EvalState::allowPath(const StorePath & storePath) rootFS2->allowPrefix(CanonPath(store->toRealPath(storePath))); } +void EvalState::allowClosure(const StorePath & storePath) +{ + if (!rootFS.dynamic_pointer_cast()) return; + + StorePathSet closure; + store->computeFSClosure(storePath, closure); + for (auto & p : closure) + allowPath(p); +} + void EvalState::allowAndSetStorePathString(const StorePath & storePath, Value & v) { allowPath(storePath); @@ -3099,10 +3109,7 @@ std::optional EvalState::resolveLookupPathPath(const LookupPath::Pat allowPath(path.path.abs()); if (store->isInStore(path.path.abs())) { try { - StorePathSet closure; - store->computeFSClosure(store->toStorePath(path.path.abs()).first, closure); - for (auto & p : closure) - allowPath(p); + allowClosure(store->toStorePath(path.path.abs()).first); } catch (InvalidPath &) { } } } diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 3ac3c8a8a..84b7d823c 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -400,6 +400,11 @@ public: */ void allowPath(const StorePath & storePath); + /** + * Allow access to the closure of a store path. + */ + void allowClosure(const StorePath & storePath); + /** * Allow access to a store path and return it as a string. */ diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 7c5c6ea9b..c1f1cf4c1 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -119,11 +119,9 @@ StringMap EvalState::realiseContext(const NixStringContext & context, StorePathS if (store != buildStore) copyClosure(*buildStore, *store, outputsToCopyAndAllow); if (isIFD) { - for (auto & outputPath : outputsToCopyAndAllow) { - /* Add the output of this derivations to the allowed - paths. */ - allowPath(outputPath); - } + /* Allow access to the output closures of this derivation. */ + for (auto & outputPath : outputsToCopyAndAllow) + allowClosure(outputPath); } return res; diff --git a/tests/functional/import-from-derivation.nix b/tests/functional/import-from-derivation.nix index cc53451cf..770dd86cf 100644 --- a/tests/functional/import-from-derivation.nix +++ b/tests/functional/import-from-derivation.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import ; rec { bar = mkDerivation { @@ -30,4 +30,23 @@ rec { echo -n BLA$(cat $src) > $out ''; }; + + step1 = mkDerivation { + name = "step1"; + buildCommand = '' + mkdir -p $out + echo 'foo' > $out/bla + ''; + }; + + addPathExpr = mkDerivation { + name = "add-path"; + inherit step1; + buildCommand = '' + mkdir -p $out + echo "builtins.path { path = \"$step1\"; sha256 = \"7ptL+pnrZXnSa5hwwB+2SXTLkcSb5264WGGokN8OXto=\"; }" > $out/default.nix + ''; + }; + + importAddPathExpr = import addPathExpr; } diff --git a/tests/functional/import-from-derivation.sh b/tests/functional/import-from-derivation.sh index 83ef92a6f..a00761235 100755 --- a/tests/functional/import-from-derivation.sh +++ b/tests/functional/import-from-derivation.sh @@ -6,6 +6,8 @@ TODO_NixOS clearStoreIfPossible +export NIX_PATH=config="${config_nix}" + if nix-instantiate --readonly-mode ./import-from-derivation.nix -A result; then echo "read-only evaluation of an imported derivation unexpectedly failed" exit 1 @@ -15,6 +17,9 @@ outPath=$(nix-build ./import-from-derivation.nix -A result --no-out-link) [ "$(cat "$outPath")" = FOO579 ] +# Check that we can have access to the entire closure of a derivation output. +nix build --no-link --restrict-eval -I src=. -f ./import-from-derivation.nix importAddPathExpr -v + # FIXME: the next tests are broken on CA. if [[ -n "${NIX_TESTS_CA_BY_DEFAULT:-}" ]]; then exit 0 From cd002ae6dda7be6e339d7e573ee122b5cdc50861 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sun, 22 Sep 2024 16:48:23 +0200 Subject: [PATCH 562/718] flake.nix: switch to nixpkgs 24.11 --- flake.lock | 20 ++++++++++---------- flake.nix | 3 ++- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/flake.lock b/flake.lock index b5d0b881c..10957359a 100644 --- a/flake.lock +++ b/flake.lock @@ -23,11 +23,11 @@ ] }, "locked": { - "lastModified": 1719994518, - "narHash": "sha256-pQMhCCHyQGRzdfAkdJ4cIWiw+JNuWsTX7f0ZYSyz0VY=", + "lastModified": 1733312601, + "narHash": "sha256-4pDvzqnegAfRkPwO3wmwBhVi/Sye1mzps0zHWYnP88c=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "9227223f6d922fee3c7b190b2cc238a99527bbb7", + "rev": "205b12d8b7cd4802fbcb8e8ef6a0f1408781a4f9", "type": "github" }, "original": { @@ -48,11 +48,11 @@ ] }, "locked": { - "lastModified": 1721042469, - "narHash": "sha256-6FPUl7HVtvRHCCBQne7Ylp4p+dpP3P/OYuzjztZ4s70=", + "lastModified": 1734279981, + "narHash": "sha256-NdaCraHPp8iYMWzdXAt5Nv6sA3MUzlCiGiR586TCwo0=", "owner": "cachix", "repo": "git-hooks.nix", - "rev": "f451c19376071a90d8c58ab1a953c6e9840527fd", + "rev": "aa9f40c906904ebd83da78e7f328cd8aeaeae785", "type": "github" }, "original": { @@ -80,16 +80,16 @@ }, "nixpkgs": { "locked": { - "lastModified": 1723688146, - "narHash": "sha256-sqLwJcHYeWLOeP/XoLwAtYjr01TISlkOfz+NG82pbdg=", + "lastModified": 1734359947, + "narHash": "sha256-1Noao/H+N8nFB4Beoy8fgwrcOQLVm9o4zKW1ODaqK9E=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "c3d4ac725177c030b1e289015989da2ad9d56af0", + "rev": "48d12d5e70ee91fe8481378e540433a7303dbf6a", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-24.05", + "ref": "release-24.11", "repo": "nixpkgs", "type": "github" } diff --git a/flake.nix b/flake.nix index a5e68609e..ba3cd3b82 100644 --- a/flake.nix +++ b/flake.nix @@ -1,7 +1,8 @@ { description = "The purely functional package manager"; - inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05"; + inputs.nixpkgs.url = "github:NixOS/nixpkgs/release-24.11"; + inputs.nixpkgs-regression.url = "github:NixOS/nixpkgs/215d4d0fd80ca5163643b03a33fde804a29cc1e2"; inputs.nixpkgs-23-11.url = "github:NixOS/nixpkgs/a62e6edd6d5e1fa0329b8653c801147986f8d446"; inputs.flake-compat = { url = "github:edolstra/flake-compat"; flake = false; }; From 9131905185129034aa12839809ffd8f843107940 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sun, 22 Sep 2024 16:51:29 +0200 Subject: [PATCH 563/718] use libgit2 from nixpkgs --- flake.lock | 24 +++--------------------- flake.nix | 4 +--- packaging/dependencies.nix | 2 -- 3 files changed, 4 insertions(+), 26 deletions(-) diff --git a/flake.lock b/flake.lock index 10957359a..ce484a67a 100644 --- a/flake.lock +++ b/flake.lock @@ -3,11 +3,11 @@ "flake-compat": { "flake": false, "locked": { - "lastModified": 1696426674, - "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "lastModified": 1733328505, + "narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=", "owner": "edolstra", "repo": "flake-compat", - "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec", "type": "github" }, "original": { @@ -61,23 +61,6 @@ "type": "github" } }, - "libgit2": { - "flake": false, - "locked": { - "lastModified": 1715853528, - "narHash": "sha256-J2rCxTecyLbbDdsyBWn9w7r3pbKRMkI9E7RvRgAqBdY=", - "owner": "libgit2", - "repo": "libgit2", - "rev": "36f7e21ad757a3dacc58cf7944329da6bc1d6e96", - "type": "github" - }, - "original": { - "owner": "libgit2", - "ref": "v1.8.1", - "repo": "libgit2", - "type": "github" - } - }, "nixpkgs": { "locked": { "lastModified": 1734359947, @@ -131,7 +114,6 @@ "flake-compat": "flake-compat", "flake-parts": "flake-parts", "git-hooks-nix": "git-hooks-nix", - "libgit2": "libgit2", "nixpkgs": "nixpkgs", "nixpkgs-23-11": "nixpkgs-23-11", "nixpkgs-regression": "nixpkgs-regression" diff --git a/flake.nix b/flake.nix index ba3cd3b82..156eb71cd 100644 --- a/flake.nix +++ b/flake.nix @@ -6,7 +6,6 @@ inputs.nixpkgs-regression.url = "github:NixOS/nixpkgs/215d4d0fd80ca5163643b03a33fde804a29cc1e2"; inputs.nixpkgs-23-11.url = "github:NixOS/nixpkgs/a62e6edd6d5e1fa0329b8653c801147986f8d446"; inputs.flake-compat = { url = "github:edolstra/flake-compat"; flake = false; }; - inputs.libgit2 = { url = "github:libgit2/libgit2/v1.8.1"; flake = false; }; # dev tooling inputs.flake-parts.url = "github:hercules-ci/flake-parts"; @@ -19,7 +18,7 @@ inputs.git-hooks-nix.inputs.flake-compat.follows = ""; inputs.git-hooks-nix.inputs.gitignore.follows = ""; - outputs = inputs@{ self, nixpkgs, nixpkgs-regression, libgit2, ... }: + outputs = inputs@{ self, nixpkgs, nixpkgs-regression, ... }: let @@ -164,7 +163,6 @@ if prev.stdenv.hostPlatform.system == "i686-linux" then (prev.pre-commit.override (o: { dotnet-sdk = ""; })).overridePythonAttrs (o: { doCheck = false; }) else prev.pre-commit; - }; in { diff --git a/packaging/dependencies.nix b/packaging/dependencies.nix index a8005ce16..78451e549 100644 --- a/packaging/dependencies.nix +++ b/packaging/dependencies.nix @@ -140,8 +140,6 @@ scope: { }); libgit2 = pkgs.libgit2.overrideAttrs (attrs: { - src = inputs.libgit2; - version = inputs.libgit2.lastModifiedDate; cmakeFlags = attrs.cmakeFlags or [] ++ [ "-DUSE_SSH=exec" ]; nativeBuildInputs = attrs.nativeBuildInputs or [] From 1a8bd84f558c44feff234652669e1474a78289fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sun, 22 Sep 2024 16:53:06 +0200 Subject: [PATCH 564/718] remove upstreamed busybox-sandbox-shell --- packaging/dependencies.nix | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/packaging/dependencies.nix b/packaging/dependencies.nix index 78451e549..785480921 100644 --- a/packaging/dependencies.nix +++ b/packaging/dependencies.nix @@ -167,30 +167,6 @@ scope: { ]; }); - busybox-sandbox-shell = pkgs.busybox-sandbox-shell or (pkgs.busybox.override { - useMusl = true; - enableStatic = true; - enableMinimal = true; - extraConfig = '' - CONFIG_FEATURE_FANCY_ECHO y - CONFIG_FEATURE_SH_MATH y - CONFIG_FEATURE_SH_MATH_64 y - - CONFIG_ASH y - CONFIG_ASH_OPTIMIZE_FOR_SIZE y - - CONFIG_ASH_ALIAS y - CONFIG_ASH_BASH_COMPAT y - CONFIG_ASH_CMDCMD y - CONFIG_ASH_ECHO y - CONFIG_ASH_GETOPTS y - CONFIG_ASH_INTERNAL_GLOB y - CONFIG_ASH_JOB_CONTROL y - CONFIG_ASH_PRINTF y - CONFIG_ASH_TEST y - ''; - }); - # TODO change in Nixpkgs, Windows works fine. First commit of # https://github.com/NixOS/nixpkgs/pull/322977 backported will fix. toml11 = pkgs.toml11.overrideAttrs (old: { From 81b6b79a5641aaa29244be29bc506e86de51c87e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sun, 22 Sep 2024 16:53:50 +0200 Subject: [PATCH 565/718] remove upstreamed libseccomp --- packaging/dependencies.nix | 8 -------- 1 file changed, 8 deletions(-) diff --git a/packaging/dependencies.nix b/packaging/dependencies.nix index 785480921..531052107 100644 --- a/packaging/dependencies.nix +++ b/packaging/dependencies.nix @@ -114,14 +114,6 @@ scope: { requiredSystemFeatures = [ ]; }; - libseccomp = pkgs.libseccomp.overrideAttrs (_: rec { - version = "2.5.5"; - src = pkgs.fetchurl { - url = "https://github.com/seccomp/libseccomp/releases/download/v${version}/libseccomp-${version}.tar.gz"; - hash = "sha256-JIosik2bmFiqa69ScSw0r+/PnJ6Ut23OAsHJqiX7M3U="; - }; - }); - boehmgc = pkgs.boehmgc.override { enableLargeConfig = true; }; From b5ad051b6c705fe9a6fe442371d9f19257d68724 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sun, 22 Sep 2024 16:56:01 +0200 Subject: [PATCH 566/718] remove upstreamed toml11 package override --- packaging/dependencies.nix | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packaging/dependencies.nix b/packaging/dependencies.nix index 531052107..2c7cf701f 100644 --- a/packaging/dependencies.nix +++ b/packaging/dependencies.nix @@ -159,12 +159,6 @@ scope: { ]; }); - # TODO change in Nixpkgs, Windows works fine. First commit of - # https://github.com/NixOS/nixpkgs/pull/322977 backported will fix. - toml11 = pkgs.toml11.overrideAttrs (old: { - meta.platforms = lib.platforms.all; - }); - inherit resolvePath filesetToSource; mkMesonDerivation = From cf0ba0d20ebdf190141ddc1a114a4a1cf1988bd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Wed, 25 Sep 2024 14:13:33 +0200 Subject: [PATCH 567/718] netbsd: disable cross-compilation Cross-compilation of curl is broken in nixpkgs. Therefore we disable it until nixpkgs fixes the underlying issues. --- flake.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 156eb71cd..104cbc34b 100644 --- a/flake.nix +++ b/flake.nix @@ -36,7 +36,8 @@ "armv6l-unknown-linux-gnueabihf" "armv7l-unknown-linux-gnueabihf" "riscv64-unknown-linux-gnu" - "x86_64-unknown-netbsd" + # Disabled because of https://github.com/NixOS/nixpkgs/issues/344423 + # "x86_64-unknown-netbsd" "x86_64-unknown-freebsd" "x86_64-w64-mingw32" ]; From 2512619cb6b7b5fad7c5024a985996e6c875dfe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Tue, 3 Dec 2024 15:51:29 +0100 Subject: [PATCH 568/718] switch to lowdown-unsandboxed package This is needed for macos support as the sandboxed version of lowdown doesn't work in the nix sandbox. --- doc/manual/package.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/manual/package.nix b/doc/manual/package.nix index 2e6fcede3..f8133f2e1 100644 --- a/doc/manual/package.nix +++ b/doc/manual/package.nix @@ -3,7 +3,7 @@ , meson , ninja -, lowdown +, lowdown-unsandboxed , mdbook , mdbook-linkcheck , jq @@ -42,7 +42,7 @@ mkMesonDerivation (finalAttrs: { passthru.externalNativeBuildInputs = [ meson ninja - (lib.getBin lowdown) + (lib.getBin lowdown-unsandboxed) mdbook mdbook-linkcheck jq From 20ee83fffde3d5892cf012dedeacaf11ce45cf7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Mon, 9 Dec 2024 16:03:36 +0100 Subject: [PATCH 569/718] tests/nixos: disable nixos-option --- tests/nixos/default.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/nixos/default.nix b/tests/nixos/default.nix index ff1220f35..a9a438a32 100644 --- a/tests/nixos/default.nix +++ b/tests/nixos/default.nix @@ -26,6 +26,8 @@ let # Evaluate VMs faster documentation.enable = false; + # this links against nix and might break with our git version. + system.tools.nixos-option.enable = false; }; _module.args.nixpkgs = nixpkgs; _module.args.system = system; From 51463d228010360e91366e2fc06f8d54ccfc9288 Mon Sep 17 00:00:00 2001 From: Jason Yundt Date: Mon, 16 Dec 2024 13:55:41 -0500 Subject: [PATCH 570/718] Fix flake.lock/flake.nix mix-up MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit src/nix/flake.md describes the format of flake.lock files. Before this change, it said that the original field was “The original input specification from `flake.lock`[…]” The original input specification is in flake.nix, not flake.lock. --- src/nix/flake.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nix/flake.md b/src/nix/flake.md index 1028dc807..fa17375df 100644 --- a/src/nix/flake.md +++ b/src/nix/flake.md @@ -654,7 +654,7 @@ following fields: * `inputs`: The dependencies of this node, as a mapping from input names (e.g. `nixpkgs`) to node labels (e.g. `n2`). -* `original`: The original input specification from `flake.lock`, as a +* `original`: The original input specification from `flake.nix`, as a set of `builtins.fetchTree` arguments. * `locked`: The locked input specification, as a set of From 331bf3e2613d2b1f730f3867dd32bd0dc1ca43a6 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 29 Nov 2024 16:55:27 +0100 Subject: [PATCH 571/718] Git fetcher: Calculate a fingerprint for dirty workdirs This restores evaluation caching for dirty Git workdirs. --- src/libfetchers/git-utils.cc | 18 ++++++++++++++++-- src/libfetchers/git-utils.hh | 7 ++++++- src/libfetchers/git.cc | 30 +++++++++++++++++++++++++++--- 3 files changed, 49 insertions(+), 6 deletions(-) diff --git a/src/libfetchers/git-utils.cc b/src/libfetchers/git-utils.cc index 74e68fe12..bd5786857 100644 --- a/src/libfetchers/git-utils.cc +++ b/src/libfetchers/git-utils.cc @@ -437,7 +437,12 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this { if (!(statusFlags & GIT_STATUS_INDEX_DELETED) && !(statusFlags & GIT_STATUS_WT_DELETED)) - info.files.insert(CanonPath(path)); + info.files.emplace(CanonPath(path), + statusFlags == GIT_STATUS_CURRENT + ? WorkdirInfo::State::Clean + : WorkdirInfo::State::Dirty); + else + info.deletedFiles.insert(CanonPath(path)); if (statusFlags != GIT_STATUS_CURRENT) info.isDirty = true; return 0; @@ -1202,6 +1207,15 @@ ref GitRepoImpl::getAccessor(const Hash & rev, bool exportIgnore } } +template +std::set getKeys(const std::map & c) +{ + std::set res; + for (auto & i : c) + res.insert(i.first); + return res; +} + ref GitRepoImpl::getAccessor(const WorkdirInfo & wd, bool exportIgnore, MakeNotAllowedError makeNotAllowedError) { auto self = ref(shared_from_this()); @@ -1214,7 +1228,7 @@ ref GitRepoImpl::getAccessor(const WorkdirInfo & wd, bool export ? makeEmptySourceAccessor() : AllowListSourceAccessor::create( makeFSSourceAccessor(path), - std::set { wd.files }, + std::set { getKeys(wd.files) }, std::move(makeNotAllowedError)).cast(); if (exportIgnore) return make_ref(self, fileAccessor, std::nullopt); diff --git a/src/libfetchers/git-utils.hh b/src/libfetchers/git-utils.hh index f45b5a504..12cee5db1 100644 --- a/src/libfetchers/git-utils.hh +++ b/src/libfetchers/git-utils.hh @@ -55,9 +55,14 @@ struct GitRepo in the repo yet. */ std::optional headRev; + enum State { Clean, Dirty }; + /* All files in the working directory that are unchanged, modified or added, but excluding deleted files. */ - std::set files; + std::map files; + + /* The deleted files. */ + std::set deletedFiles; /* The submodules listed in .gitmodules of this workdir. */ std::vector submodules; diff --git a/src/libfetchers/git.cc b/src/libfetchers/git.cc index a6883a2d3..eec134980 100644 --- a/src/libfetchers/git.cc +++ b/src/libfetchers/git.cc @@ -685,7 +685,7 @@ struct GitInputScheme : InputScheme if (getSubmodulesAttr(input)) /* Create mountpoints for the submodules. */ for (auto & submodule : repoInfo.workdirInfo.submodules) - repoInfo.workdirInfo.files.insert(submodule.path); + repoInfo.workdirInfo.files.emplace(submodule.path, GitRepo::WorkdirInfo::State::Clean); auto repo = GitRepo::openRepo(repoInfo.url, false, false); @@ -793,10 +793,34 @@ struct GitInputScheme : InputScheme std::optional getFingerprint(ref store, const Input & input) const override { + auto makeFingerprint = [&](const Hash & rev) + { + return rev.gitRev() + (getSubmodulesAttr(input) ? ";s" : "") + (getExportIgnoreAttr(input) ? ";e" : ""); + }; + if (auto rev = input.getRev()) - return rev->gitRev() + (getSubmodulesAttr(input) ? ";s" : "") + (getExportIgnoreAttr(input) ? ";e" : ""); - else + return makeFingerprint(*rev); + else { + auto repoInfo = getRepoInfo(input); + if (repoInfo.isLocal && repoInfo.workdirInfo.headRev) { + /* Calculate a fingerprint that takes into account the + deleted and modified/added files. */ + HashSink hashSink{HashAlgorithm::SHA512}; + for (auto & file : repoInfo.workdirInfo.files) + if (file.second == GitRepo::WorkdirInfo::State::Dirty) { + writeString("modified:", hashSink); + writeString(file.first.abs(), hashSink); + readFile(std::filesystem::path(repoInfo.url) + file.first.abs(), hashSink); + } + for (auto & file : repoInfo.workdirInfo.deletedFiles) { + writeString("deleted:", hashSink); + writeString(file.abs(), hashSink); + } + return makeFingerprint(*repoInfo.workdirInfo.headRev) + + ";d=" + hashSink.finish().first.to_string(HashFormat::Base16, false); + } return std::nullopt; + } } bool isLocked(const Input & input) const override From d044a05197c1d4066ef0c0b67ff0461ee3d5fa6c Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 3 Dec 2024 15:50:39 +0100 Subject: [PATCH 572/718] Don't fingerprint dirty repos with submodules for now Fixes nixpkgsLibTests. --- src/libfetchers/git.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libfetchers/git.cc b/src/libfetchers/git.cc index eec134980..d47e731f1 100644 --- a/src/libfetchers/git.cc +++ b/src/libfetchers/git.cc @@ -15,6 +15,7 @@ #include "finally.hh" #include "fetch-settings.hh" #include "json-utils.hh" +#include "archive.hh" #include #include @@ -802,7 +803,7 @@ struct GitInputScheme : InputScheme return makeFingerprint(*rev); else { auto repoInfo = getRepoInfo(input); - if (repoInfo.isLocal && repoInfo.workdirInfo.headRev) { + if (repoInfo.isLocal && repoInfo.workdirInfo.headRev && repoInfo.workdirInfo.submodules.empty()) { /* Calculate a fingerprint that takes into account the deleted and modified/added files. */ HashSink hashSink{HashAlgorithm::SHA512}; @@ -810,7 +811,7 @@ struct GitInputScheme : InputScheme if (file.second == GitRepo::WorkdirInfo::State::Dirty) { writeString("modified:", hashSink); writeString(file.first.abs(), hashSink); - readFile(std::filesystem::path(repoInfo.url) + file.first.abs(), hashSink); + dumpPath(repoInfo.url + "/" + file.first.abs(), hashSink); } for (auto & file : repoInfo.workdirInfo.deletedFiles) { writeString("deleted:", hashSink); From f469bc2ae4a221d0397775b2663ba90a2dff0b9c Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 4 Dec 2024 13:17:31 +0100 Subject: [PATCH 573/718] Cache result of Input::getFingerprint() The fingerprint calculation can be expensive (especially for dirty Git trees) so we need to cache it. --- src/libfetchers/fetchers.cc | 14 +++++++++++--- src/libfetchers/fetchers.hh | 5 +++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/libfetchers/fetchers.cc b/src/libfetchers/fetchers.cc index e15a460d0..b105c252a 100644 --- a/src/libfetchers/fetchers.cc +++ b/src/libfetchers/fetchers.cc @@ -113,7 +113,15 @@ Input Input::fromAttrs(const Settings & settings, Attrs && attrs) std::optional Input::getFingerprint(ref store) const { - return scheme ? scheme->getFingerprint(store, *this) : std::nullopt; + if (!scheme) return std::nullopt; + + if (cachedFingerprint) return *cachedFingerprint; + + auto fingerprint = scheme->getFingerprint(store, *this); + + cachedFingerprint = fingerprint; + + return fingerprint; } ParsedURL Input::toURL() const @@ -307,7 +315,7 @@ std::pair, Input> Input::getAccessorUnchecked(ref sto auto accessor = makeStorePathAccessor(store, storePath); - accessor->fingerprint = scheme->getFingerprint(store, *this); + accessor->fingerprint = getFingerprint(store); return {accessor, *this}; } catch (Error & e) { @@ -318,7 +326,7 @@ std::pair, Input> Input::getAccessorUnchecked(ref sto auto [accessor, result] = scheme->getAccessor(store, *this); assert(!accessor->fingerprint); - accessor->fingerprint = scheme->getFingerprint(store, result); + accessor->fingerprint = result.getFingerprint(store); return {accessor, std::move(result)}; } diff --git a/src/libfetchers/fetchers.hh b/src/libfetchers/fetchers.hh index ff04d5551..841a44041 100644 --- a/src/libfetchers/fetchers.hh +++ b/src/libfetchers/fetchers.hh @@ -46,6 +46,11 @@ struct Input */ std::optional parent; + /** + * Cached result of getFingerprint(). + */ + mutable std::optional> cachedFingerprint; + public: /** * Create an `Input` from a URL. From 7ba933e989b9baf56c2b542c7788b38f6d9ccb50 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 4 Dec 2024 13:56:03 +0100 Subject: [PATCH 574/718] Cache calls to GitRepo::getWorkdirInfo() A command like `nix flake metadata` was causing about 4 calls to getWorkdirInfo(), which is slow for large repos (even when they're not dirty). --- src/libfetchers/git-utils.cc | 14 ++++++++++++++ src/libfetchers/git-utils.hh | 2 ++ src/libfetchers/git.cc | 2 +- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/libfetchers/git-utils.cc b/src/libfetchers/git-utils.cc index bd5786857..15fa540b3 100644 --- a/src/libfetchers/git-utils.cc +++ b/src/libfetchers/git-utils.cc @@ -5,6 +5,7 @@ #include "signals.hh" #include "users.hh" #include "fs-sink.hh" +#include "sync.hh" #include #include @@ -1276,4 +1277,17 @@ ref getTarballCache() return GitRepo::openRepo(repoDir, true, true); } +GitRepo::WorkdirInfo GitRepo::getCachedWorkdirInfo(const std::filesystem::path & path) +{ + static Sync> _cache; + { + auto cache(_cache.lock()); + auto i = cache->find(path); + if (i != cache->end()) return i->second; + } + auto workdirInfo = GitRepo::openRepo(path)->getWorkdirInfo(); + _cache.lock()->emplace(path, workdirInfo); + return workdirInfo; +} + } diff --git a/src/libfetchers/git-utils.hh b/src/libfetchers/git-utils.hh index 12cee5db1..2db64e438 100644 --- a/src/libfetchers/git-utils.hh +++ b/src/libfetchers/git-utils.hh @@ -70,6 +70,8 @@ struct GitRepo virtual WorkdirInfo getWorkdirInfo() = 0; + static WorkdirInfo getCachedWorkdirInfo(const std::filesystem::path & path); + /* Get the ref that HEAD points to. */ virtual std::optional getWorkdirRef() = 0; diff --git a/src/libfetchers/git.cc b/src/libfetchers/git.cc index d47e731f1..a584542d1 100644 --- a/src/libfetchers/git.cc +++ b/src/libfetchers/git.cc @@ -431,7 +431,7 @@ struct GitInputScheme : InputScheme // If this is a local directory and no ref or revision is // given, then allow the use of an unclean working tree. if (!input.getRef() && !input.getRev() && repoInfo.isLocal) - repoInfo.workdirInfo = GitRepo::openRepo(repoInfo.url)->getWorkdirInfo(); + repoInfo.workdirInfo = GitRepo::getCachedWorkdirInfo(repoInfo.url); return repoInfo; } From b9f60faab50f79c9d5fd4d11d1bf06feeb62edc5 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 4 Dec 2024 14:51:41 +0100 Subject: [PATCH 575/718] Fix macOS build --- src/libfetchers/git-utils.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libfetchers/git-utils.cc b/src/libfetchers/git-utils.cc index 15fa540b3..a41546c44 100644 --- a/src/libfetchers/git-utils.cc +++ b/src/libfetchers/git-utils.cc @@ -1279,7 +1279,7 @@ ref getTarballCache() GitRepo::WorkdirInfo GitRepo::getCachedWorkdirInfo(const std::filesystem::path & path) { - static Sync> _cache; + static Sync> _cache; { auto cache(_cache.lock()); auto i = cache->find(path); From 33852ead6b01b58cd66a474b6615595244dc56d5 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 4 Dec 2024 15:31:19 +0100 Subject: [PATCH 576/718] Optimisation --- src/libfetchers/git-utils.cc | 21 ++++++--------------- src/libfetchers/git-utils.hh | 7 ++++--- src/libfetchers/git.cc | 13 ++++++------- 3 files changed, 16 insertions(+), 25 deletions(-) diff --git a/src/libfetchers/git-utils.cc b/src/libfetchers/git-utils.cc index a41546c44..b54416b10 100644 --- a/src/libfetchers/git-utils.cc +++ b/src/libfetchers/git-utils.cc @@ -438,11 +438,11 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this { if (!(statusFlags & GIT_STATUS_INDEX_DELETED) && !(statusFlags & GIT_STATUS_WT_DELETED)) - info.files.emplace(CanonPath(path), - statusFlags == GIT_STATUS_CURRENT - ? WorkdirInfo::State::Clean - : WorkdirInfo::State::Dirty); - else + { + info.files.insert(CanonPath(path)); + if (statusFlags != GIT_STATUS_CURRENT) + info.dirtyFiles.insert(CanonPath(path)); + } else info.deletedFiles.insert(CanonPath(path)); if (statusFlags != GIT_STATUS_CURRENT) info.isDirty = true; @@ -1208,15 +1208,6 @@ ref GitRepoImpl::getAccessor(const Hash & rev, bool exportIgnore } } -template -std::set getKeys(const std::map & c) -{ - std::set res; - for (auto & i : c) - res.insert(i.first); - return res; -} - ref GitRepoImpl::getAccessor(const WorkdirInfo & wd, bool exportIgnore, MakeNotAllowedError makeNotAllowedError) { auto self = ref(shared_from_this()); @@ -1229,7 +1220,7 @@ ref GitRepoImpl::getAccessor(const WorkdirInfo & wd, bool export ? makeEmptySourceAccessor() : AllowListSourceAccessor::create( makeFSSourceAccessor(path), - std::set { getKeys(wd.files) }, + std::set { wd.files }, std::move(makeNotAllowedError)).cast(); if (exportIgnore) return make_ref(self, fileAccessor, std::nullopt); diff --git a/src/libfetchers/git-utils.hh b/src/libfetchers/git-utils.hh index 2db64e438..ff115143f 100644 --- a/src/libfetchers/git-utils.hh +++ b/src/libfetchers/git-utils.hh @@ -55,11 +55,12 @@ struct GitRepo in the repo yet. */ std::optional headRev; - enum State { Clean, Dirty }; - /* All files in the working directory that are unchanged, modified or added, but excluding deleted files. */ - std::map files; + std::set files; + + /* All modified or added files. */ + std::set dirtyFiles; /* The deleted files. */ std::set deletedFiles; diff --git a/src/libfetchers/git.cc b/src/libfetchers/git.cc index a584542d1..c73f53765 100644 --- a/src/libfetchers/git.cc +++ b/src/libfetchers/git.cc @@ -686,7 +686,7 @@ struct GitInputScheme : InputScheme if (getSubmodulesAttr(input)) /* Create mountpoints for the submodules. */ for (auto & submodule : repoInfo.workdirInfo.submodules) - repoInfo.workdirInfo.files.emplace(submodule.path, GitRepo::WorkdirInfo::State::Clean); + repoInfo.workdirInfo.files.insert(submodule.path); auto repo = GitRepo::openRepo(repoInfo.url, false, false); @@ -807,12 +807,11 @@ struct GitInputScheme : InputScheme /* Calculate a fingerprint that takes into account the deleted and modified/added files. */ HashSink hashSink{HashAlgorithm::SHA512}; - for (auto & file : repoInfo.workdirInfo.files) - if (file.second == GitRepo::WorkdirInfo::State::Dirty) { - writeString("modified:", hashSink); - writeString(file.first.abs(), hashSink); - dumpPath(repoInfo.url + "/" + file.first.abs(), hashSink); - } + for (auto & file : repoInfo.workdirInfo.dirtyFiles) { + writeString("modified:", hashSink); + writeString(file.abs(), hashSink); + dumpPath(repoInfo.url + "/" + file.abs(), hashSink); + } for (auto & file : repoInfo.workdirInfo.deletedFiles) { writeString("deleted:", hashSink); writeString(file.abs(), hashSink); From 757ea706449925636a99dfbcb09a09c62b1de319 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 17 Dec 2024 13:13:39 +0100 Subject: [PATCH 577/718] Add a test --- tests/functional/flakes/flakes.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/functional/flakes/flakes.sh b/tests/functional/flakes/flakes.sh index de37ae1b7..6c466a0c7 100755 --- a/tests/functional/flakes/flakes.sh +++ b/tests/functional/flakes/flakes.sh @@ -77,6 +77,7 @@ hash1=$(echo "$json" | jq -r .revision) echo foo > "$flake1Dir/foo" git -C "$flake1Dir" add $flake1Dir/foo [[ $(nix flake metadata flake1 --json --refresh | jq -r .dirtyRevision) == "$hash1-dirty" ]] +[[ "$(nix flake metadata flake1 --json | jq -r .fingerprint)" != null ]] echo -n '# foo' >> "$flake1Dir/flake.nix" flake1OriginalCommit=$(git -C "$flake1Dir" rev-parse HEAD) From b33814093100ca15a2afdc1be207fcd4d1328a78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Mon, 16 Dec 2024 11:49:43 +0100 Subject: [PATCH 578/718] fix missing includes in various headers --- src/libexpr/lexer-helpers.hh | 8 ++++++++ src/libexpr/print-options.hh | 1 + src/libstore/path-regex.hh | 2 ++ src/libutil/callback.hh | 1 + src/libutil/config-impl.hh | 1 + src/libutil/regex-combinators.hh | 1 + src/libutil/unix/signals-impl.hh | 1 + src/nix/self-exe.hh | 2 ++ 8 files changed, 17 insertions(+) diff --git a/src/libexpr/lexer-helpers.hh b/src/libexpr/lexer-helpers.hh index caba6e18f..b4a166f46 100644 --- a/src/libexpr/lexer-helpers.hh +++ b/src/libexpr/lexer-helpers.hh @@ -1,5 +1,13 @@ #pragma once +#include + +// inluding the generated headers twice leads to errors +#ifndef BISON_HEADER +#include "lexer-tab.hh" +#include "parser-tab.hh" +#endif + namespace nix::lexer::internal { void initLoc(YYLTYPE * loc); diff --git a/src/libexpr/print-options.hh b/src/libexpr/print-options.hh index 080ba26b8..9ad54e532 100644 --- a/src/libexpr/print-options.hh +++ b/src/libexpr/print-options.hh @@ -5,6 +5,7 @@ */ #include +#include namespace nix { diff --git a/src/libstore/path-regex.hh b/src/libstore/path-regex.hh index 56c2cfc1d..e34a305c5 100644 --- a/src/libstore/path-regex.hh +++ b/src/libstore/path-regex.hh @@ -1,6 +1,8 @@ #pragma once ///@file +#include + namespace nix { diff --git a/src/libutil/callback.hh b/src/libutil/callback.hh index 26c386d80..c2cada2f6 100644 --- a/src/libutil/callback.hh +++ b/src/libutil/callback.hh @@ -1,6 +1,7 @@ #pragma once ///@file +#include #include #include diff --git a/src/libutil/config-impl.hh b/src/libutil/config-impl.hh index c3aa61ddb..94c2cb2e4 100644 --- a/src/libutil/config-impl.hh +++ b/src/libutil/config-impl.hh @@ -13,6 +13,7 @@ */ #include "config.hh" +#include "args.hh" namespace nix { diff --git a/src/libutil/regex-combinators.hh b/src/libutil/regex-combinators.hh index 87d6aa678..8a7b2c2c0 100644 --- a/src/libutil/regex-combinators.hh +++ b/src/libutil/regex-combinators.hh @@ -2,6 +2,7 @@ ///@file #include +#include namespace nix::regex { diff --git a/src/libutil/unix/signals-impl.hh b/src/libutil/unix/signals-impl.hh index 2193922be..037416e7d 100644 --- a/src/libutil/unix/signals-impl.hh +++ b/src/libutil/unix/signals-impl.hh @@ -14,6 +14,7 @@ #include "error.hh" #include "logging.hh" #include "ansicolor.hh" +#include "signals.hh" #include #include diff --git a/src/nix/self-exe.hh b/src/nix/self-exe.hh index 3161553ec..91e260f0b 100644 --- a/src/nix/self-exe.hh +++ b/src/nix/self-exe.hh @@ -2,6 +2,8 @@ ///@file #include +#include +#include namespace nix { From b9bbdbeb0b5ec0bb3231d1e04d1825fdc1f6c4c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Mon, 16 Dec 2024 11:50:03 +0100 Subject: [PATCH 579/718] ca-fd-leak: add missing c casts --- tests/nixos/ca-fd-leak/sender.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/nixos/ca-fd-leak/sender.c b/tests/nixos/ca-fd-leak/sender.c index 75e54fc8f..8356b2479 100644 --- a/tests/nixos/ca-fd-leak/sender.c +++ b/tests/nixos/ca-fd-leak/sender.c @@ -49,8 +49,8 @@ int main(int argc, char **argv) { msg.msg_controllen = CMSG_SPACE(sizeof(int)); // Write a single null byte too. - msg.msg_iov = malloc(sizeof(struct iovec)); - msg.msg_iov[0].iov_base = ""; + msg.msg_iov = (struct iovec*) malloc(sizeof(struct iovec)); + msg.msg_iov[0].iov_base = (void*) ""; msg.msg_iov[0].iov_len = 1; msg.msg_iovlen = 1; From eda331e53fc6322922f467263ded0b69c28dd427 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Mon, 16 Dec 2024 12:43:28 +0100 Subject: [PATCH 580/718] libutil/windows: only define headers/code if we are actually on windows all those includes otherwise break linters. --- src/libexpr/lexer-helpers.hh | 4 ++-- src/libstore/windows/pathlocks.cc | 11 +++++++---- src/libutil/windows/environment-variables.cc | 4 +++- src/libutil/windows/file-descriptor.cc | 2 ++ src/libutil/windows/file-system.cc | 2 ++ src/libutil/windows/muxable-pipe.cc | 12 +++++++----- src/libutil/windows/os-string.cc | 4 ++++ src/libutil/windows/processes.cc | 4 ++++ src/libutil/windows/users.cc | 2 ++ src/libutil/windows/windows-async-pipe.cc | 4 ++++ src/libutil/windows/windows-async-pipe.hh | 2 ++ src/libutil/windows/windows-error.cc | 2 ++ src/libutil/windows/windows-error.hh | 2 ++ 13 files changed, 43 insertions(+), 12 deletions(-) diff --git a/src/libexpr/lexer-helpers.hh b/src/libexpr/lexer-helpers.hh index b4a166f46..d40f7b874 100644 --- a/src/libexpr/lexer-helpers.hh +++ b/src/libexpr/lexer-helpers.hh @@ -4,8 +4,8 @@ // inluding the generated headers twice leads to errors #ifndef BISON_HEADER -#include "lexer-tab.hh" -#include "parser-tab.hh" +# include "lexer-tab.hh" +# include "parser-tab.hh" #endif namespace nix::lexer::internal { diff --git a/src/libstore/windows/pathlocks.cc b/src/libstore/windows/pathlocks.cc index 00761a8c3..197f5a1c4 100644 --- a/src/libstore/windows/pathlocks.cc +++ b/src/libstore/windows/pathlocks.cc @@ -2,10 +2,12 @@ #include "pathlocks.hh" #include "signals.hh" #include "util.hh" -#include -#include -#include -#include "windows-error.hh" + +#ifdef WIN32 +# include +# include +# include +# include "windows-error.hh" namespace nix { @@ -154,3 +156,4 @@ FdLock::FdLock(Descriptor desc, LockType lockType, bool wait, std::string_view w } } +#endif diff --git a/src/libutil/windows/environment-variables.cc b/src/libutil/windows/environment-variables.cc index 5ce8a1395..308a432e4 100644 --- a/src/libutil/windows/environment-variables.cc +++ b/src/libutil/windows/environment-variables.cc @@ -1,6 +1,7 @@ #include "environment-variables.hh" -#include "processenv.h" +#ifdef WIN32 +# include "processenv.h" namespace nix { @@ -43,3 +44,4 @@ int setEnvOs(const OsString & name, const OsString & value) } } +#endif diff --git a/src/libutil/windows/file-descriptor.cc b/src/libutil/windows/file-descriptor.cc index 7b8a712e8..71f53ccb8 100644 --- a/src/libutil/windows/file-descriptor.cc +++ b/src/libutil/windows/file-descriptor.cc @@ -5,6 +5,7 @@ #include "windows-error.hh" #include "file-path.hh" +#ifdef WIN32 #include #include #include @@ -152,3 +153,4 @@ Path windows::handleToPath(HANDLE handle) { #endif } +#endif diff --git a/src/libutil/windows/file-system.cc b/src/libutil/windows/file-system.cc index b15355efe..53271cef3 100644 --- a/src/libutil/windows/file-system.cc +++ b/src/libutil/windows/file-system.cc @@ -1,5 +1,6 @@ #include "file-system.hh" +#ifdef WIN32 namespace nix { Descriptor openDirectory(const std::filesystem::path & path) @@ -15,3 +16,4 @@ Descriptor openDirectory(const std::filesystem::path & path) } } +#endif diff --git a/src/libutil/windows/muxable-pipe.cc b/src/libutil/windows/muxable-pipe.cc index 91a321f7c..af7e987e9 100644 --- a/src/libutil/windows/muxable-pipe.cc +++ b/src/libutil/windows/muxable-pipe.cc @@ -1,9 +1,10 @@ -#include -#include "windows-error.hh" +#ifdef WIN32 +# include +# include "windows-error.hh" -#include "logging.hh" -#include "util.hh" -#include "muxable-pipe.hh" +# include "logging.hh" +# include "util.hh" +# include "muxable-pipe.hh" namespace nix { @@ -68,3 +69,4 @@ void MuxablePipePollState::iterate( } } +#endif diff --git a/src/libutil/windows/os-string.cc b/src/libutil/windows/os-string.cc index 7507f9030..26ad9cba0 100644 --- a/src/libutil/windows/os-string.cc +++ b/src/libutil/windows/os-string.cc @@ -7,6 +7,8 @@ #include "file-path-impl.hh" #include "util.hh" +#ifdef WIN32 + namespace nix { std::string os_string_to_string(PathViewNG::string_view path) @@ -22,3 +24,5 @@ std::filesystem::path::string_type string_to_os_string(std::string_view s) } } + +#endif diff --git a/src/libutil/windows/processes.cc b/src/libutil/windows/processes.cc index 7f34c5632..e69f1ed45 100644 --- a/src/libutil/windows/processes.cc +++ b/src/libutil/windows/processes.cc @@ -23,6 +23,8 @@ #include #include +#ifdef WIN32 + #define WIN32_LEAN_AND_MEAN #include @@ -386,3 +388,5 @@ int execvpe(const wchar_t * file0, const wchar_t * const argv[], const wchar_t * } } + +#endif diff --git a/src/libutil/windows/users.cc b/src/libutil/windows/users.cc index db6c42df3..2780e45f4 100644 --- a/src/libutil/windows/users.cc +++ b/src/libutil/windows/users.cc @@ -4,6 +4,7 @@ #include "file-system.hh" #include "windows-error.hh" +#ifdef WIN32 #define WIN32_LEAN_AND_MEAN #include @@ -50,3 +51,4 @@ bool isRootUser() { } } +#endif diff --git a/src/libutil/windows/windows-async-pipe.cc b/src/libutil/windows/windows-async-pipe.cc index 4fa57ca36..13b563510 100644 --- a/src/libutil/windows/windows-async-pipe.cc +++ b/src/libutil/windows/windows-async-pipe.cc @@ -1,6 +1,8 @@ #include "windows-async-pipe.hh" #include "windows-error.hh" +#ifdef WIN32 + namespace nix::windows { void AsyncPipe::createAsyncPipe(HANDLE iocp) @@ -47,3 +49,5 @@ void AsyncPipe::close() } } + +#endif diff --git a/src/libutil/windows/windows-async-pipe.hh b/src/libutil/windows/windows-async-pipe.hh index 8f554e403..277336ed7 100644 --- a/src/libutil/windows/windows-async-pipe.hh +++ b/src/libutil/windows/windows-async-pipe.hh @@ -2,6 +2,7 @@ ///@file #include "file-descriptor.hh" +#ifdef WIN32 namespace nix::windows { @@ -25,3 +26,4 @@ public: }; } +#endif diff --git a/src/libutil/windows/windows-error.cc b/src/libutil/windows/windows-error.cc index aead4af23..4cf4274da 100644 --- a/src/libutil/windows/windows-error.cc +++ b/src/libutil/windows/windows-error.cc @@ -1,5 +1,6 @@ #include "windows-error.hh" +#ifdef WIN32 #include #define WIN32_LEAN_AND_MEAN #include @@ -29,3 +30,4 @@ std::string WinError::renderError(DWORD lastError) } } +#endif diff --git a/src/libutil/windows/windows-error.hh b/src/libutil/windows/windows-error.hh index 624b4c4cb..4e48ee859 100644 --- a/src/libutil/windows/windows-error.hh +++ b/src/libutil/windows/windows-error.hh @@ -1,6 +1,7 @@ #pragma once ///@file +#ifdef WIN32 #include #include "error.hh" @@ -49,3 +50,4 @@ private: }; } +#endif From 3392a96901bfde94142fbfffd9d7d12549522ad2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Mon, 16 Dec 2024 12:07:35 +0000 Subject: [PATCH 581/718] ca-fd-leak: fix various unsafe c handling --- tests/nixos/ca-fd-leak/smuggler.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/nixos/ca-fd-leak/smuggler.c b/tests/nixos/ca-fd-leak/smuggler.c index 82acf37e6..3f89af5bb 100644 --- a/tests/nixos/ca-fd-leak/smuggler.c +++ b/tests/nixos/ca-fd-leak/smuggler.c @@ -16,7 +16,7 @@ int main(int argc, char **argv) { struct sockaddr_un data; data.sun_family = AF_UNIX; data.sun_path[0] = 0; - strcpy(data.sun_path + 1, argv[1]); + strncpy(data.sun_path + 1, argv[1], sizeof(data.sun_path) - 1); int res = bind(sock, (const struct sockaddr *)&data, offsetof(struct sockaddr_un, sun_path) + strlen(argv[1]) @@ -57,10 +57,11 @@ int main(int argc, char **argv) { // Wait for a second connection, which will tell us that the build is // done a = accept(sock, 0, 0); + if (a < 0) perror("accept"); fprintf(stderr, "%s\n", "Got a second connection, rewriting the file"); // Write a new content to the file if (ftruncate(smuggling_fd, 0)) perror("ftruncate"); - char * new_content = "Pwned\n"; + const char * new_content = "Pwned\n"; int written_bytes = write(smuggling_fd, new_content, strlen(new_content)); if (written_bytes != strlen(new_content)) perror("write"); } From 6848154b2e657e64a592b60f00b68db8d911b89f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Mon, 16 Dec 2024 12:47:20 +0000 Subject: [PATCH 582/718] regex-combinators: fix linter error when adding string_view and string --- src/libutil/regex-combinators.hh | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/libutil/regex-combinators.hh b/src/libutil/regex-combinators.hh index 8a7b2c2c0..75ccd4e6c 100644 --- a/src/libutil/regex-combinators.hh +++ b/src/libutil/regex-combinators.hh @@ -3,6 +3,7 @@ #include #include +#include namespace nix::regex { @@ -11,22 +12,23 @@ namespace nix::regex { static inline std::string either(std::string_view a, std::string_view b) { - return std::string { a } + "|" + b; + std::stringstream ss; + ss << a << "|" << b; + return ss.str(); } static inline std::string group(std::string_view a) { - return std::string { "(" } + a + ")"; -} - -static inline std::string many(std::string_view a) -{ - return std::string { "(?:" } + a + ")*"; + std::stringstream ss; + ss << "(" << a << ")"; + return ss.str(); } static inline std::string list(std::string_view a) { - return std::string { a } + many(group("," + a)); + std::stringstream ss; + ss << a << "(," << a << ")*"; + return ss.str(); } } From 5cd5391dd8055bc0876204b6b38274f8c821c751 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sun, 15 Dec 2024 20:41:39 +0100 Subject: [PATCH 583/718] checks: re-enable perlBindings --- flake.nix | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/flake.nix b/flake.nix index a5e68609e..44a764dd7 100644 --- a/flake.nix +++ b/flake.nix @@ -201,11 +201,7 @@ # Some perl dependencies are broken on i686-linux. # Since the support is only best-effort there, disable the perl # bindings - - # Temporarily disabled because GitHub Actions OOM issues. Once - # the old build system is gone and we are back to one build - # system, we should reenable this. - #perlBindings = self.hydraJobs.perlBindings.${system}; + perlBindings = self.hydraJobs.perlBindings.${system}; } # Add "passthru" tests // flatMapAttrs ({ From a8e1b4757e3022dff433693eb8ed3e757dd317c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Thu, 19 Dec 2024 18:35:28 +0100 Subject: [PATCH 584/718] filesystem/deletePath: remove unnecessary quotes from error message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Paths are already quoted: error: … while fetching the input 'path:/nix/store/rs2s2ca7xs87v82aps54m1p3sqrfz6c8-source' error: chmod '"/nix/store/rs2s2ca7xs87v82aps54m1p3sqrfz6c8-source"': Read-only file system --- src/libutil/file-system.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libutil/file-system.cc b/src/libutil/file-system.cc index 829700336..50e90bb57 100644 --- a/src/libutil/file-system.cc +++ b/src/libutil/file-system.cc @@ -384,7 +384,7 @@ static void _deletePath(Descriptor parentfd, const fs::path & path, uint64_t & b if (fstatat(parentfd, name.c_str(), &st, AT_SYMLINK_NOFOLLOW) == -1) { if (errno == ENOENT) return; - throw SysError("getting status of '%1%'", path); + throw SysError("getting status of %1%", path); } if (!S_ISDIR(st.st_mode)) { @@ -416,15 +416,15 @@ static void _deletePath(Descriptor parentfd, const fs::path & path, uint64_t & b const auto PERM_MASK = S_IRUSR | S_IWUSR | S_IXUSR; if ((st.st_mode & PERM_MASK) != PERM_MASK) { if (fchmodat(parentfd, name.c_str(), st.st_mode | PERM_MASK, 0) == -1) - throw SysError("chmod '%1%'", path); + throw SysError("chmod %1%", path); } int fd = openat(parentfd, path.c_str(), O_RDONLY); if (fd == -1) - throw SysError("opening directory '%1%'", path); + throw SysError("opening directory %1%", path); AutoCloseDir dir(fdopendir(fd)); if (!dir) - throw SysError("opening directory '%1%'", path); + throw SysError("opening directory %1%", path); struct dirent * dirent; while (errno = 0, dirent = readdir(dir.get())) { /* sic */ @@ -433,13 +433,13 @@ static void _deletePath(Descriptor parentfd, const fs::path & path, uint64_t & b if (childName == "." || childName == "..") continue; _deletePath(dirfd(dir.get()), path + "/" + childName, bytesFreed); } - if (errno) throw SysError("reading directory '%1%'", path); + if (errno) throw SysError("reading directory %1%", path); } int flags = S_ISDIR(st.st_mode) ? AT_REMOVEDIR : 0; if (unlinkat(parentfd, name.c_str(), flags) == -1) { if (errno == ENOENT) return; - throw SysError("cannot unlink '%1%'", path); + throw SysError("cannot unlink %1%", path); } #else // TODO implement From 535724fd7953e9b465af419d66536dc810e3e6c2 Mon Sep 17 00:00:00 2001 From: Cole Helbling Date: Thu, 19 Dec 2024 11:14:04 -0800 Subject: [PATCH 585/718] tests/nixos/s3-binary-cache-store: test that "object does not exist" error message is properly formatted --- tests/nixos/s3-binary-cache-store.nix | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/nixos/s3-binary-cache-store.nix b/tests/nixos/s3-binary-cache-store.nix index 6c51fcba5..45f234645 100644 --- a/tests/nixos/s3-binary-cache-store.nix +++ b/tests/nixos/s3-binary-cache-store.nix @@ -10,6 +10,7 @@ let env = "AWS_ACCESS_KEY_ID=${accessKey} AWS_SECRET_ACCESS_KEY=${secretKey}"; storeUrl = "s3://my-cache?endpoint=http://server:9000®ion=eu-west-1"; + objectThatDoesNotExist = "s3://my-cache/foo-that-does-not-exist?endpoint=http://server:9000®ion=eu-west-1"; in { name = "s3-binary-cache-store"; @@ -54,6 +55,12 @@ in { # Test fetchurl on s3:// URLs while we're at it. client.succeed("${env} nix eval --impure --expr 'builtins.fetchurl { name = \"foo\"; url = \"s3://my-cache/nix-cache-info?endpoint=http://server:9000®ion=eu-west-1\"; }'") + # Test that the format string in the error message is properly setup and won't display `%s` instead of the failed URI + msg = client.fail("${env} nix eval --impure --expr 'builtins.fetchurl { name = \"foo\"; url = \"${objectThatDoesNotExist}\"; }' 2>&1") + if "S3 object '${objectThatDoesNotExist}' does not exist" not in msg: + print(msg) # So that you can see the message that was improperly formatted + raise Exception("Error message formatting didn't work") + # Copy a package from the binary cache. client.fail("nix path-info ${pkgA}") From f0c1262d2319ff6967139d8f8599ed6176ad1263 Mon Sep 17 00:00:00 2001 From: Cole Helbling Date: Thu, 19 Dec 2024 11:15:25 -0800 Subject: [PATCH 586/718] tests/nixos/s3-binary-cache-store: disable default substituter so it runs faster Since networking is disabled in these VMs, trying to talk to the default cache.nixos.org slows the test down (since it can't resolve it). --- tests/nixos/s3-binary-cache-store.nix | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/nixos/s3-binary-cache-store.nix b/tests/nixos/s3-binary-cache-store.nix index 45f234645..83b85c032 100644 --- a/tests/nixos/s3-binary-cache-store.nix +++ b/tests/nixos/s3-binary-cache-store.nix @@ -21,7 +21,10 @@ in { { virtualisation.writableStore = true; virtualisation.additionalPaths = [ pkgA ]; environment.systemPackages = [ pkgs.minio-client ]; - nix.extraOptions = "experimental-features = nix-command"; + nix.extraOptions = '' + experimental-features = nix-command + substituters = + ''; services.minio = { enable = true; region = "eu-west-1"; @@ -36,7 +39,10 @@ in { client = { config, pkgs, ... }: { virtualisation.writableStore = true; - nix.extraOptions = "experimental-features = nix-command"; + nix.extraOptions = '' + experimental-features = nix-command + substituters = + ''; }; }; From b978fa845022d448c11a1d2e9d0347a57edecbd8 Mon Sep 17 00:00:00 2001 From: Cole Helbling Date: Thu, 19 Dec 2024 10:16:47 -0800 Subject: [PATCH 587/718] libstore: fixup unformatted uri when S3 getObject fails --- src/libstore/filetransfer.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstore/filetransfer.cc b/src/libstore/filetransfer.cc index 42b93cfe0..8439cc39c 100644 --- a/src/libstore/filetransfer.cc +++ b/src/libstore/filetransfer.cc @@ -767,7 +767,7 @@ struct curlFileTransfer : public FileTransfer auto s3Res = s3Helper.getObject(bucketName, key); FileTransferResult res; if (!s3Res.data) - throw FileTransferError(NotFound, "S3 object '%s' does not exist", request.uri); + throw FileTransferError(NotFound, {}, "S3 object '%s' does not exist", request.uri); res.data = std::move(*s3Res.data); res.urls.push_back(request.uri); callback(std::move(res)); From 9223d64ac62385d3b75cfbf5bac491fc14d033ad Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 23 Dec 2024 16:03:13 +0100 Subject: [PATCH 588/718] Remove dead code --- src/libflake/flake/flakeref.cc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/libflake/flake/flakeref.cc b/src/libflake/flake/flakeref.cc index 41e991c20..3a43a51f8 100644 --- a/src/libflake/flake/flakeref.cc +++ b/src/libflake/flake/flakeref.cc @@ -195,10 +195,6 @@ std::pair parsePathFlakeRefWithFragment( throw BadURL("flake reference '%s' is not an absolute path", url); } - fetchers::Attrs attrs; - attrs.insert_or_assign("type", "path"); - attrs.insert_or_assign("path", path); - return fromParsedURL(fetchSettings, { .url = path, .base = path, From 4a91e627a7617cc3d654967358fd29df076ab853 Mon Sep 17 00:00:00 2001 From: Yaroslav Bolyukin Date: Wed, 25 Dec 2024 02:41:20 +0100 Subject: [PATCH 589/718] fix: ignore symlinks in fsync-store-paths Fixes: https://github.com/NixOS/nix/issues/12099 --- src/libutil/file-system.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libutil/file-system.cc b/src/libutil/file-system.cc index 50e90bb57..793eb2d9f 100644 --- a/src/libutil/file-system.cc +++ b/src/libutil/file-system.cc @@ -331,7 +331,7 @@ void syncParent(const Path & path) void recursiveSync(const Path & path) { - /* If it's a file, just fsync and return. */ + /* If it's a file or symlink, just fsync and return. */ auto st = lstat(path); if (S_ISREG(st.st_mode)) { AutoCloseFD fd = toDescriptor(open(path.c_str(), O_RDONLY, 0)); @@ -339,7 +339,8 @@ void recursiveSync(const Path & path) throw SysError("opening file '%1%'", path); fd.fsync(); return; - } + } else if (S_ISLNK(st.st_mode)) + return; /* Otherwise, perform a depth-first traversal of the directory and fsync all the files. */ From fe5f02c2c274e8f48a1072807fc9bb3f892584a4 Mon Sep 17 00:00:00 2001 From: NAHO <90870942+trueNAHO@users.noreply.github.com> Date: Fri, 27 Dec 2024 01:56:12 +0100 Subject: [PATCH 590/718] ci: lock Ubuntu runner to ubuntu-22.04 Lock the Ubuntu runner to ubuntu-22.04 to avoid accidental updates [1] and increase reproducibility. [1]: https://github.com/actions/runner-images/issues/10636 --- .github/workflows/ci.yml | 14 +++++++------- .github/workflows/labels.yml | 2 +- .mergify.yml | 4 ++-- doc/manual/source/development/testing.md | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index addafb9f8..2426ab166 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,7 +8,7 @@ permissions: read-all jobs: eval: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 with: @@ -20,7 +20,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-latest] + os: [ubuntu-22.04, macos-latest] runs-on: ${{ matrix.os }} timeout-minutes: 60 steps: @@ -37,7 +37,7 @@ jobs: # Since ubuntu 22.30, unprivileged usernamespaces are no longer allowed to map to the root user: # https://ubuntu.com/blog/ubuntu-23-10-restricted-unprivileged-user-namespaces - run: sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 - if: matrix.os == 'ubuntu-latest' + if: matrix.os == 'ubuntu-22.04' - run: scripts/build-checks - run: scripts/prepare-installer-for-github-actions - name: Upload installer tarball @@ -51,7 +51,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-latest] + os: [ubuntu-22.04, macos-latest] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 @@ -68,7 +68,7 @@ jobs: install_url: 'http://localhost:8126/install' install_options: "--tarball-url-prefix http://localhost:8126/" - run: sudo apt install fish zsh - if: matrix.os == 'ubuntu-latest' + if: matrix.os == 'ubuntu-22.04' - run: brew install fish if: matrix.os == 'macos-latest' - run: exec bash -c "nix-instantiate -E 'builtins.currentTime' --eval" @@ -86,7 +86,7 @@ jobs: permissions: contents: none name: Check Docker secrets present for installer tests - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 outputs: docker: ${{ steps.secret.outputs.docker }} steps: @@ -106,7 +106,7 @@ jobs: needs.check_secrets.outputs.docker == 'true' && github.event_name == 'push' && github.ref_name == 'master' - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Check for secrets id: secret diff --git a/.github/workflows/labels.yml b/.github/workflows/labels.yml index 34aa4e6bd..9d2ac80a3 100644 --- a/.github/workflows/labels.yml +++ b/.github/workflows/labels.yml @@ -15,7 +15,7 @@ permissions: jobs: labels: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 if: github.repository_owner == 'NixOS' steps: - uses: actions/labeler@v5 diff --git a/.mergify.yml b/.mergify.yml index 70fccae49..c2e115487 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -3,9 +3,9 @@ queue_rules: # all required tests need to go here merge_conditions: - check-success=tests (macos-latest) - - check-success=tests (ubuntu-latest) + - check-success=tests (ubuntu-22.04) - check-success=installer_test (macos-latest) - - check-success=installer_test (ubuntu-latest) + - check-success=installer_test (ubuntu-22.04) - check-success=vm_tests batch_size: 5 diff --git a/doc/manual/source/development/testing.md b/doc/manual/source/development/testing.md index 30aa7d0d5..7e8762fe0 100644 --- a/doc/manual/source/development/testing.md +++ b/doc/manual/source/development/testing.md @@ -297,7 +297,7 @@ Creating a Cachix cache for your installer tests and adding its authorisation to - `armv7l-linux` - `x86_64-darwin` -- The `installer_test` job (which runs on `ubuntu-latest` and `macos-latest`) will try to install Nix with the cached installer and run a trivial Nix command. +- The `installer_test` job (which runs on `ubuntu-22.04` and `macos-latest`) will try to install Nix with the cached installer and run a trivial Nix command. ### One-time setup From cf69c99f3ec16deb25ae7a57ee579431828da249 Mon Sep 17 00:00:00 2001 From: Parker Jones <49885263+knotapun@users.noreply.github.com> Date: Fri, 27 Dec 2024 01:11:36 -0500 Subject: [PATCH 591/718] Make `readFileType` doc string consistent The primitive `readFileType p` has a list of acceptable types, and so does `readDir path` This edit makes the formatting of the list consistent between themselves, and other parts of the documentation. --- src/libexpr/primops.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index c1f1cf4c1..f19dd473a 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -2045,7 +2045,7 @@ static RegisterPrimOp primop_readFileType({ .args = {"p"}, .doc = R"( Determine the directory entry type of a filesystem node, being - one of "directory", "regular", "symlink", or "unknown". + one of `"directory"`, `"regular"`, `"symlink"`, or `"unknown"`. )", .fun = prim_readFileType, }); From 92e30955b9a4acbc01cd6519552ada3385ef3c7e Mon Sep 17 00:00:00 2001 From: Philipp Otterbein Date: Sun, 15 Dec 2024 02:29:56 +0100 Subject: [PATCH 592/718] try to calculate character width --- maintainers/flake-module.nix | 1 + src/libutil-tests/terminal.cc | 4 + src/libutil/meson.build | 6 + src/libutil/package.nix | 1 + src/libutil/terminal.cc | 90 +- src/libutil/widecharwidth/LICENSE | 4 + src/libutil/widecharwidth/widechar_width.h | 1559 ++++++++++++++++++++ 7 files changed, 1636 insertions(+), 29 deletions(-) create mode 100644 src/libutil/widecharwidth/LICENSE create mode 100644 src/libutil/widecharwidth/widechar_width.h diff --git a/maintainers/flake-module.nix b/maintainers/flake-module.nix index 1a134b91a..6b311c62e 100644 --- a/maintainers/flake-module.nix +++ b/maintainers/flake-module.nix @@ -356,6 +356,7 @@ ''^src/libutil/util\.cc$'' ''^src/libutil/util\.hh$'' ''^src/libutil/variant-wrapper\.hh$'' + ''^src/libutil/widecharwidth/widechar_width\.h$'' # vendored source ''^src/libutil/windows/file-descriptor\.cc$'' ''^src/libutil/windows/file-path\.cc$'' ''^src/libutil/windows/processes\.cc$'' diff --git a/src/libutil-tests/terminal.cc b/src/libutil-tests/terminal.cc index 714d5a237..f4fc6e770 100644 --- a/src/libutil-tests/terminal.cc +++ b/src/libutil-tests/terminal.cc @@ -55,6 +55,10 @@ TEST(filterANSIEscapes, utf8) ASSERT_EQ(filterANSIEscapes("fóóbär", true, 3), "fóó"); ASSERT_EQ(filterANSIEscapes("f€€bär", true, 4), "f€€b"); ASSERT_EQ(filterANSIEscapes("f𐍈𐍈bär", true, 4), "f𐍈𐍈b"); + ASSERT_EQ(filterANSIEscapes("f🔍bar", true, 6), "f🔍bar"); + ASSERT_EQ(filterANSIEscapes("f🔍bar", true, 3), "f🔍"); + ASSERT_EQ(filterANSIEscapes("f🔍bar", true, 2), "f"); + ASSERT_EQ(filterANSIEscapes("foo\u0301", true, 3), "foó"); } TEST(filterANSIEscapes, osc8) diff --git a/src/libutil/meson.build b/src/libutil/meson.build index bbe7872cf..2c3e3a954 100644 --- a/src/libutil/meson.build +++ b/src/libutil/meson.build @@ -108,6 +108,8 @@ deps_private += cpuid nlohmann_json = dependency('nlohmann_json', version : '>= 3.9') deps_public += nlohmann_json +cxx = meson.get_compiler('cpp') + config_h = configure_file( configuration : configdata, output : 'config-util.hh', @@ -168,6 +170,10 @@ sources = files( ) include_dirs = [include_directories('.')] +if not cxx.has_header('widechar_width.h', required : false) + # use vendored widechar_width.h + include_dirs += include_directories('./widecharwidth') +endif headers = [config_h] + files( 'abstract-setting-to-json.hh', diff --git a/src/libutil/package.nix b/src/libutil/package.nix index 69ebbf726..0a9f65782 100644 --- a/src/libutil/package.nix +++ b/src/libutil/package.nix @@ -29,6 +29,7 @@ mkMesonLibrary (finalAttrs: { ./nix-meson-build-support ../../.version ./.version + ./widecharwidth ./meson.build ./meson.options ./linux/meson.build diff --git a/src/libutil/terminal.cc b/src/libutil/terminal.cc index 4c127ddb0..8a8373f1b 100644 --- a/src/libutil/terminal.cc +++ b/src/libutil/terminal.cc @@ -11,6 +11,53 @@ # include #endif #include +#include + +namespace { + +inline std::pair charWidthUTF8Helper(std::string_view s) +{ + size_t bytes = 1; + uint32_t ch = s[0]; + uint32_t max = 1U << 7; + if ((ch & 0x80U) == 0U) { + } else if ((ch & 0xe0U) == 0xc0U) { + ch &= 0x1fU; + bytes = 2; + max = 1U << 11; + } else if ((ch & 0xf0U) == 0xe0U) { + ch &= 0x0fU; + bytes = 3; + max = 1U << 16; + } else if ((ch & 0xf8U) == 0xf0U) { + ch &= 0x07U; + bytes = 4; + max = 0x110000U; + } else { + return {bytes, bytes}; // invalid UTF-8 start byte + } + for (size_t i = 1; i < bytes; i++) { + if (i < s.size() && (s[i] & 0xc0) == 0x80) { + ch = (ch << 6) | (s[i] & 0x3f); + } else { + return {i, i}; // invalid UTF-8 encoding; assume one character per byte + } + } + int width = bytes; // in case of overlong encoding + if (ch < max) { + width = widechar_wcwidth(ch); + if (width == widechar_ambiguous) { + width = 1; // just a guess... + } else if (width == widechar_widened_in_9) { + width = 2; + } else if (width < 0) { + width = 0; + } + } + return {width, bytes}; +} + +} namespace nix { @@ -30,7 +77,7 @@ std::string filterANSIEscapes(std::string_view s, bool filterAll, unsigned int w size_t w = 0; auto i = s.begin(); - while (w < (size_t) width && i != s.end()) { + while (i != s.end()) { if (*i == '\e') { std::string e; @@ -61,10 +108,12 @@ std::string filterANSIEscapes(std::string_view s, bool filterAll, unsigned int w } else if (*i == '\t') { - i++; t += ' '; w++; - while (w < (size_t) width && w % 8) { - t += ' '; w++; - } + do { + if (++w > (size_t) width) + return t; + t += ' '; + } while (w % 8); + i++; } else if (*i == '\r' || *i == '\a') @@ -72,35 +121,18 @@ std::string filterANSIEscapes(std::string_view s, bool filterAll, unsigned int w i++; else { - w++; - // Copy one UTF-8 character. - if ((*i & 0xe0) == 0xc0) { - t += *i++; - if (i != s.end() && ((*i & 0xc0) == 0x80)) t += *i++; - } else if ((*i & 0xf0) == 0xe0) { - t += *i++; - if (i != s.end() && ((*i & 0xc0) == 0x80)) { - t += *i++; - if (i != s.end() && ((*i & 0xc0) == 0x80)) t += *i++; - } - } else if ((*i & 0xf8) == 0xf0) { - t += *i++; - if (i != s.end() && ((*i & 0xc0) == 0x80)) { - t += *i++; - if (i != s.end() && ((*i & 0xc0) == 0x80)) { - t += *i++; - if (i != s.end() && ((*i & 0xc0) == 0x80)) t += *i++; - } - } - } else - t += *i++; + auto [chWidth, bytes] = charWidthUTF8Helper({i, s.end()}); + w += chWidth; + if (w > (size_t) width) { + break; + } + t += {i, i + bytes}; + i += bytes; } } - return t; } - ////////////////////////////////////////////////////////////////////// static Sync> windowSize{{0, 0}}; diff --git a/src/libutil/widecharwidth/LICENSE b/src/libutil/widecharwidth/LICENSE new file mode 100644 index 000000000..d3b1dd767 --- /dev/null +++ b/src/libutil/widecharwidth/LICENSE @@ -0,0 +1,4 @@ +widecharwidth - wcwidth implementation +Written in 2018 by ridiculous_fish +To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to the public domain worldwide. This software is distributed without any warranty. +You should have received a copy of the CC0 Public Domain Dedication along with this software. If not, see . diff --git a/src/libutil/widecharwidth/widechar_width.h b/src/libutil/widecharwidth/widechar_width.h new file mode 100644 index 000000000..92e63e913 --- /dev/null +++ b/src/libutil/widecharwidth/widechar_width.h @@ -0,0 +1,1559 @@ +/** + * widechar_width.h for Unicode 16.0.0 + * See https://github.com/ridiculousfish/widecharwidth/ + * + * SHA1 file hashes: + * ( + * the hashes for generate.py and the template are git object hashes, + * use `git log --all --find-object=` in the widecharwidth repository + * to see which commit they correspond to, + * or run `git hash-object` on the file to compare. + * The other hashes are simple `sha1sum` style hashes. + * ) + * + * generate.py: 2747bb9402d8eeeca8e566ff947f14308511ecb1 + * template.js: 1249763c5b7c1e308aeb4ca64f1e15bce1fab9b3 + * UnicodeData.txt: 91df83276154240bcedef82a09bde77aa182cf8d + * EastAsianWidth.txt: 0885c0fc1c21eb58954a3bfb785d78559b361d92 + * emoji-data.txt: 1df2f8329dd9f5c238674807de736f316c6b9d87 + */ + +#ifndef WIDECHAR_WIDTH_H +#define WIDECHAR_WIDTH_H + +#include +#include +#include +#include + +namespace { + +/* Special width values */ +enum { + widechar_nonprint = -1, // The character is not printable. + widechar_combining = -2, // The character is a zero-width combiner. + widechar_ambiguous = -3, // The character is East-Asian ambiguous width. + widechar_private_use = -4, // The character is for private use. + widechar_unassigned = -5, // The character is unassigned. + widechar_widened_in_9 = -6, // Width is 1 in Unicode 8, 2 in Unicode 9+. + widechar_non_character = -7 // The character is a noncharacter. +}; + +/* An inclusive range of characters. */ +struct widechar_range { + uint32_t lo; + uint32_t hi; +}; + +/* Simple ASCII characters - used a lot, so we check them first. */ +static const struct widechar_range widechar_ascii_table[] = { + {0x00020, 0x0007E} +}; + +/* Private usage range. */ +static const struct widechar_range widechar_private_table[] = { + {0x0E000, 0x0F8FF}, + {0xF0000, 0xFFFFD}, + {0x100000, 0x10FFFD} +}; + +/* Nonprinting characters. */ +static const struct widechar_range widechar_nonprint_table[] = { + {0x00000, 0x0001F}, + {0x0007F, 0x0009F}, + {0x000AD, 0x000AD}, + {0x00600, 0x00605}, + {0x0061C, 0x0061C}, + {0x006DD, 0x006DD}, + {0x0070F, 0x0070F}, + {0x00890, 0x00891}, + {0x008E2, 0x008E2}, + {0x0180E, 0x0180E}, + {0x0200B, 0x0200F}, + {0x02028, 0x0202E}, + {0x02060, 0x02064}, + {0x02066, 0x0206F}, + {0x0D800, 0x0DFFF}, + {0x0FEFF, 0x0FEFF}, + {0x0FFF9, 0x0FFFB}, + {0x110BD, 0x110BD}, + {0x110CD, 0x110CD}, + {0x13430, 0x1343F}, + {0x1BCA0, 0x1BCA3}, + {0x1D173, 0x1D17A}, + {0xE0001, 0xE0001}, + {0xE0020, 0xE007F} +}; + +/* Width 0 combining marks. */ +static const struct widechar_range widechar_combining_table[] = { + {0x00300, 0x0036F}, + {0x00483, 0x00489}, + {0x00591, 0x005BD}, + {0x005BF, 0x005BF}, + {0x005C1, 0x005C2}, + {0x005C4, 0x005C5}, + {0x005C7, 0x005C7}, + {0x00610, 0x0061A}, + {0x0064B, 0x0065F}, + {0x00670, 0x00670}, + {0x006D6, 0x006DC}, + {0x006DF, 0x006E4}, + {0x006E7, 0x006E8}, + {0x006EA, 0x006ED}, + {0x00711, 0x00711}, + {0x00730, 0x0074A}, + {0x007A6, 0x007B0}, + {0x007EB, 0x007F3}, + {0x007FD, 0x007FD}, + {0x00816, 0x00819}, + {0x0081B, 0x00823}, + {0x00825, 0x00827}, + {0x00829, 0x0082D}, + {0x00859, 0x0085B}, + {0x00897, 0x0089F}, + {0x008CA, 0x008E1}, + {0x008E3, 0x00903}, + {0x0093A, 0x0093C}, + {0x0093E, 0x0094F}, + {0x00951, 0x00957}, + {0x00962, 0x00963}, + {0x00981, 0x00983}, + {0x009BC, 0x009BC}, + {0x009BE, 0x009C4}, + {0x009C7, 0x009C8}, + {0x009CB, 0x009CD}, + {0x009D7, 0x009D7}, + {0x009E2, 0x009E3}, + {0x009FE, 0x009FE}, + {0x00A01, 0x00A03}, + {0x00A3C, 0x00A3C}, + {0x00A3E, 0x00A42}, + {0x00A47, 0x00A48}, + {0x00A4B, 0x00A4D}, + {0x00A51, 0x00A51}, + {0x00A70, 0x00A71}, + {0x00A75, 0x00A75}, + {0x00A81, 0x00A83}, + {0x00ABC, 0x00ABC}, + {0x00ABE, 0x00AC5}, + {0x00AC7, 0x00AC9}, + {0x00ACB, 0x00ACD}, + {0x00AE2, 0x00AE3}, + {0x00AFA, 0x00AFF}, + {0x00B01, 0x00B03}, + {0x00B3C, 0x00B3C}, + {0x00B3E, 0x00B44}, + {0x00B47, 0x00B48}, + {0x00B4B, 0x00B4D}, + {0x00B55, 0x00B57}, + {0x00B62, 0x00B63}, + {0x00B82, 0x00B82}, + {0x00BBE, 0x00BC2}, + {0x00BC6, 0x00BC8}, + {0x00BCA, 0x00BCD}, + {0x00BD7, 0x00BD7}, + {0x00C00, 0x00C04}, + {0x00C3C, 0x00C3C}, + {0x00C3E, 0x00C44}, + {0x00C46, 0x00C48}, + {0x00C4A, 0x00C4D}, + {0x00C55, 0x00C56}, + {0x00C62, 0x00C63}, + {0x00C81, 0x00C83}, + {0x00CBC, 0x00CBC}, + {0x00CBE, 0x00CC4}, + {0x00CC6, 0x00CC8}, + {0x00CCA, 0x00CCD}, + {0x00CD5, 0x00CD6}, + {0x00CE2, 0x00CE3}, + {0x00CF3, 0x00CF3}, + {0x00D00, 0x00D03}, + {0x00D3B, 0x00D3C}, + {0x00D3E, 0x00D44}, + {0x00D46, 0x00D48}, + {0x00D4A, 0x00D4D}, + {0x00D57, 0x00D57}, + {0x00D62, 0x00D63}, + {0x00D81, 0x00D83}, + {0x00DCA, 0x00DCA}, + {0x00DCF, 0x00DD4}, + {0x00DD6, 0x00DD6}, + {0x00DD8, 0x00DDF}, + {0x00DF2, 0x00DF3}, + {0x00E31, 0x00E31}, + {0x00E34, 0x00E3A}, + {0x00E47, 0x00E4E}, + {0x00EB1, 0x00EB1}, + {0x00EB4, 0x00EBC}, + {0x00EC8, 0x00ECE}, + {0x00F18, 0x00F19}, + {0x00F35, 0x00F35}, + {0x00F37, 0x00F37}, + {0x00F39, 0x00F39}, + {0x00F3E, 0x00F3F}, + {0x00F71, 0x00F84}, + {0x00F86, 0x00F87}, + {0x00F8D, 0x00F97}, + {0x00F99, 0x00FBC}, + {0x00FC6, 0x00FC6}, + {0x0102B, 0x0103E}, + {0x01056, 0x01059}, + {0x0105E, 0x01060}, + {0x01062, 0x01064}, + {0x01067, 0x0106D}, + {0x01071, 0x01074}, + {0x01082, 0x0108D}, + {0x0108F, 0x0108F}, + {0x0109A, 0x0109D}, + {0x0135D, 0x0135F}, + {0x01712, 0x01715}, + {0x01732, 0x01734}, + {0x01752, 0x01753}, + {0x01772, 0x01773}, + {0x017B4, 0x017D3}, + {0x017DD, 0x017DD}, + {0x0180B, 0x0180D}, + {0x0180F, 0x0180F}, + {0x01885, 0x01886}, + {0x018A9, 0x018A9}, + {0x01920, 0x0192B}, + {0x01930, 0x0193B}, + {0x01A17, 0x01A1B}, + {0x01A55, 0x01A5E}, + {0x01A60, 0x01A7C}, + {0x01A7F, 0x01A7F}, + {0x01AB0, 0x01ACE}, + {0x01B00, 0x01B04}, + {0x01B34, 0x01B44}, + {0x01B6B, 0x01B73}, + {0x01B80, 0x01B82}, + {0x01BA1, 0x01BAD}, + {0x01BE6, 0x01BF3}, + {0x01C24, 0x01C37}, + {0x01CD0, 0x01CD2}, + {0x01CD4, 0x01CE8}, + {0x01CED, 0x01CED}, + {0x01CF4, 0x01CF4}, + {0x01CF7, 0x01CF9}, + {0x01DC0, 0x01DFF}, + {0x020D0, 0x020F0}, + {0x02CEF, 0x02CF1}, + {0x02D7F, 0x02D7F}, + {0x02DE0, 0x02DFF}, + {0x0302A, 0x0302F}, + {0x03099, 0x0309A}, + {0x0A66F, 0x0A672}, + {0x0A674, 0x0A67D}, + {0x0A69E, 0x0A69F}, + {0x0A6F0, 0x0A6F1}, + {0x0A802, 0x0A802}, + {0x0A806, 0x0A806}, + {0x0A80B, 0x0A80B}, + {0x0A823, 0x0A827}, + {0x0A82C, 0x0A82C}, + {0x0A880, 0x0A881}, + {0x0A8B4, 0x0A8C5}, + {0x0A8E0, 0x0A8F1}, + {0x0A8FF, 0x0A8FF}, + {0x0A926, 0x0A92D}, + {0x0A947, 0x0A953}, + {0x0A980, 0x0A983}, + {0x0A9B3, 0x0A9C0}, + {0x0A9E5, 0x0A9E5}, + {0x0AA29, 0x0AA36}, + {0x0AA43, 0x0AA43}, + {0x0AA4C, 0x0AA4D}, + {0x0AA7B, 0x0AA7D}, + {0x0AAB0, 0x0AAB0}, + {0x0AAB2, 0x0AAB4}, + {0x0AAB7, 0x0AAB8}, + {0x0AABE, 0x0AABF}, + {0x0AAC1, 0x0AAC1}, + {0x0AAEB, 0x0AAEF}, + {0x0AAF5, 0x0AAF6}, + {0x0ABE3, 0x0ABEA}, + {0x0ABEC, 0x0ABED}, + {0x0FB1E, 0x0FB1E}, + {0x0FE00, 0x0FE0F}, + {0x0FE20, 0x0FE2F}, + {0x101FD, 0x101FD}, + {0x102E0, 0x102E0}, + {0x10376, 0x1037A}, + {0x10A01, 0x10A03}, + {0x10A05, 0x10A06}, + {0x10A0C, 0x10A0F}, + {0x10A38, 0x10A3A}, + {0x10A3F, 0x10A3F}, + {0x10AE5, 0x10AE6}, + {0x10D24, 0x10D27}, + {0x10D69, 0x10D6D}, + {0x10EAB, 0x10EAC}, + {0x10EFC, 0x10EFF}, + {0x10F46, 0x10F50}, + {0x10F82, 0x10F85}, + {0x11000, 0x11002}, + {0x11038, 0x11046}, + {0x11070, 0x11070}, + {0x11073, 0x11074}, + {0x1107F, 0x11082}, + {0x110B0, 0x110BA}, + {0x110C2, 0x110C2}, + {0x11100, 0x11102}, + {0x11127, 0x11134}, + {0x11145, 0x11146}, + {0x11173, 0x11173}, + {0x11180, 0x11182}, + {0x111B3, 0x111C0}, + {0x111C9, 0x111CC}, + {0x111CE, 0x111CF}, + {0x1122C, 0x11237}, + {0x1123E, 0x1123E}, + {0x11241, 0x11241}, + {0x112DF, 0x112EA}, + {0x11300, 0x11303}, + {0x1133B, 0x1133C}, + {0x1133E, 0x11344}, + {0x11347, 0x11348}, + {0x1134B, 0x1134D}, + {0x11357, 0x11357}, + {0x11362, 0x11363}, + {0x11366, 0x1136C}, + {0x11370, 0x11374}, + {0x113B8, 0x113C0}, + {0x113C2, 0x113C2}, + {0x113C5, 0x113C5}, + {0x113C7, 0x113CA}, + {0x113CC, 0x113D0}, + {0x113D2, 0x113D2}, + {0x113E1, 0x113E2}, + {0x11435, 0x11446}, + {0x1145E, 0x1145E}, + {0x114B0, 0x114C3}, + {0x115AF, 0x115B5}, + {0x115B8, 0x115C0}, + {0x115DC, 0x115DD}, + {0x11630, 0x11640}, + {0x116AB, 0x116B7}, + {0x1171D, 0x1172B}, + {0x1182C, 0x1183A}, + {0x11930, 0x11935}, + {0x11937, 0x11938}, + {0x1193B, 0x1193E}, + {0x11940, 0x11940}, + {0x11942, 0x11943}, + {0x119D1, 0x119D7}, + {0x119DA, 0x119E0}, + {0x119E4, 0x119E4}, + {0x11A01, 0x11A0A}, + {0x11A33, 0x11A39}, + {0x11A3B, 0x11A3E}, + {0x11A47, 0x11A47}, + {0x11A51, 0x11A5B}, + {0x11A8A, 0x11A99}, + {0x11C2F, 0x11C36}, + {0x11C38, 0x11C3F}, + {0x11C92, 0x11CA7}, + {0x11CA9, 0x11CB6}, + {0x11D31, 0x11D36}, + {0x11D3A, 0x11D3A}, + {0x11D3C, 0x11D3D}, + {0x11D3F, 0x11D45}, + {0x11D47, 0x11D47}, + {0x11D8A, 0x11D8E}, + {0x11D90, 0x11D91}, + {0x11D93, 0x11D97}, + {0x11EF3, 0x11EF6}, + {0x11F00, 0x11F01}, + {0x11F03, 0x11F03}, + {0x11F34, 0x11F3A}, + {0x11F3E, 0x11F42}, + {0x11F5A, 0x11F5A}, + {0x13440, 0x13440}, + {0x13447, 0x13455}, + {0x1611E, 0x1612F}, + {0x16AF0, 0x16AF4}, + {0x16B30, 0x16B36}, + {0x16F4F, 0x16F4F}, + {0x16F51, 0x16F87}, + {0x16F8F, 0x16F92}, + {0x16FE4, 0x16FE4}, + {0x16FF0, 0x16FF1}, + {0x1BC9D, 0x1BC9E}, + {0x1CF00, 0x1CF2D}, + {0x1CF30, 0x1CF46}, + {0x1D165, 0x1D169}, + {0x1D16D, 0x1D172}, + {0x1D17B, 0x1D182}, + {0x1D185, 0x1D18B}, + {0x1D1AA, 0x1D1AD}, + {0x1D242, 0x1D244}, + {0x1DA00, 0x1DA36}, + {0x1DA3B, 0x1DA6C}, + {0x1DA75, 0x1DA75}, + {0x1DA84, 0x1DA84}, + {0x1DA9B, 0x1DA9F}, + {0x1DAA1, 0x1DAAF}, + {0x1E000, 0x1E006}, + {0x1E008, 0x1E018}, + {0x1E01B, 0x1E021}, + {0x1E023, 0x1E024}, + {0x1E026, 0x1E02A}, + {0x1E08F, 0x1E08F}, + {0x1E130, 0x1E136}, + {0x1E2AE, 0x1E2AE}, + {0x1E2EC, 0x1E2EF}, + {0x1E4EC, 0x1E4EF}, + {0x1E5EE, 0x1E5EF}, + {0x1E8D0, 0x1E8D6}, + {0x1E944, 0x1E94A}, + {0xE0100, 0xE01EF} +}; + +/* Width 0 combining letters. */ +static const struct widechar_range widechar_combiningletters_table[] = { + {0x01160, 0x011FF}, + {0x0D7B0, 0x0D7FF} +}; + +/* Width 2 characters. */ +static const struct widechar_range widechar_doublewide_table[] = { + {0x01100, 0x0115F}, + {0x02329, 0x0232A}, + {0x02630, 0x02637}, + {0x0268A, 0x0268F}, + {0x02E80, 0x02E99}, + {0x02E9B, 0x02EF3}, + {0x02F00, 0x02FD5}, + {0x02FF0, 0x0303E}, + {0x03041, 0x03096}, + {0x03099, 0x030FF}, + {0x03105, 0x0312F}, + {0x03131, 0x0318E}, + {0x03190, 0x031E5}, + {0x031EF, 0x0321E}, + {0x03220, 0x03247}, + {0x03250, 0x0A48C}, + {0x0A490, 0x0A4C6}, + {0x0A960, 0x0A97C}, + {0x0AC00, 0x0D7A3}, + {0x0F900, 0x0FAFF}, + {0x0FE10, 0x0FE19}, + {0x0FE30, 0x0FE52}, + {0x0FE54, 0x0FE66}, + {0x0FE68, 0x0FE6B}, + {0x0FF01, 0x0FF60}, + {0x0FFE0, 0x0FFE6}, + {0x16FE0, 0x16FE4}, + {0x16FF0, 0x16FF1}, + {0x17000, 0x187F7}, + {0x18800, 0x18CD5}, + {0x18CFF, 0x18D08}, + {0x1AFF0, 0x1AFF3}, + {0x1AFF5, 0x1AFFB}, + {0x1AFFD, 0x1AFFE}, + {0x1B000, 0x1B122}, + {0x1B132, 0x1B132}, + {0x1B150, 0x1B152}, + {0x1B155, 0x1B155}, + {0x1B164, 0x1B167}, + {0x1B170, 0x1B2FB}, + {0x1D300, 0x1D356}, + {0x1D360, 0x1D376}, + {0x1F200, 0x1F200}, + {0x1F202, 0x1F202}, + {0x1F210, 0x1F219}, + {0x1F21B, 0x1F22E}, + {0x1F230, 0x1F231}, + {0x1F237, 0x1F237}, + {0x1F23B, 0x1F23B}, + {0x1F240, 0x1F248}, + {0x1F260, 0x1F265}, + {0x1F57A, 0x1F57A}, + {0x1F5A4, 0x1F5A4}, + {0x1F6D1, 0x1F6D2}, + {0x1F6D5, 0x1F6D7}, + {0x1F6DC, 0x1F6DF}, + {0x1F6F4, 0x1F6FC}, + {0x1F7E0, 0x1F7EB}, + {0x1F7F0, 0x1F7F0}, + {0x1F90C, 0x1F90F}, + {0x1F919, 0x1F93A}, + {0x1F93C, 0x1F945}, + {0x1F947, 0x1F97F}, + {0x1F985, 0x1F9BF}, + {0x1F9C1, 0x1F9FF}, + {0x1FA70, 0x1FA7C}, + {0x1FA80, 0x1FA89}, + {0x1FA8F, 0x1FAC6}, + {0x1FACE, 0x1FADC}, + {0x1FADF, 0x1FAE9}, + {0x1FAF0, 0x1FAF8}, + {0x20000, 0x2FFFD}, + {0x30000, 0x3FFFD} +}; + +/* Ambiguous-width characters. */ +static const struct widechar_range widechar_ambiguous_table[] = { + {0x000A1, 0x000A1}, + {0x000A4, 0x000A4}, + {0x000A7, 0x000A8}, + {0x000AA, 0x000AA}, + {0x000AD, 0x000AE}, + {0x000B0, 0x000B4}, + {0x000B6, 0x000BA}, + {0x000BC, 0x000BF}, + {0x000C6, 0x000C6}, + {0x000D0, 0x000D0}, + {0x000D7, 0x000D8}, + {0x000DE, 0x000E1}, + {0x000E6, 0x000E6}, + {0x000E8, 0x000EA}, + {0x000EC, 0x000ED}, + {0x000F0, 0x000F0}, + {0x000F2, 0x000F3}, + {0x000F7, 0x000FA}, + {0x000FC, 0x000FC}, + {0x000FE, 0x000FE}, + {0x00101, 0x00101}, + {0x00111, 0x00111}, + {0x00113, 0x00113}, + {0x0011B, 0x0011B}, + {0x00126, 0x00127}, + {0x0012B, 0x0012B}, + {0x00131, 0x00133}, + {0x00138, 0x00138}, + {0x0013F, 0x00142}, + {0x00144, 0x00144}, + {0x00148, 0x0014B}, + {0x0014D, 0x0014D}, + {0x00152, 0x00153}, + {0x00166, 0x00167}, + {0x0016B, 0x0016B}, + {0x001CE, 0x001CE}, + {0x001D0, 0x001D0}, + {0x001D2, 0x001D2}, + {0x001D4, 0x001D4}, + {0x001D6, 0x001D6}, + {0x001D8, 0x001D8}, + {0x001DA, 0x001DA}, + {0x001DC, 0x001DC}, + {0x00251, 0x00251}, + {0x00261, 0x00261}, + {0x002C4, 0x002C4}, + {0x002C7, 0x002C7}, + {0x002C9, 0x002CB}, + {0x002CD, 0x002CD}, + {0x002D0, 0x002D0}, + {0x002D8, 0x002DB}, + {0x002DD, 0x002DD}, + {0x002DF, 0x002DF}, + {0x00300, 0x0036F}, + {0x00391, 0x003A1}, + {0x003A3, 0x003A9}, + {0x003B1, 0x003C1}, + {0x003C3, 0x003C9}, + {0x00401, 0x00401}, + {0x00410, 0x0044F}, + {0x00451, 0x00451}, + {0x02010, 0x02010}, + {0x02013, 0x02016}, + {0x02018, 0x02019}, + {0x0201C, 0x0201D}, + {0x02020, 0x02022}, + {0x02024, 0x02027}, + {0x02030, 0x02030}, + {0x02032, 0x02033}, + {0x02035, 0x02035}, + {0x0203B, 0x0203B}, + {0x0203E, 0x0203E}, + {0x02074, 0x02074}, + {0x0207F, 0x0207F}, + {0x02081, 0x02084}, + {0x020AC, 0x020AC}, + {0x02103, 0x02103}, + {0x02105, 0x02105}, + {0x02109, 0x02109}, + {0x02113, 0x02113}, + {0x02116, 0x02116}, + {0x02121, 0x02122}, + {0x02126, 0x02126}, + {0x0212B, 0x0212B}, + {0x02153, 0x02154}, + {0x0215B, 0x0215E}, + {0x02160, 0x0216B}, + {0x02170, 0x02179}, + {0x02189, 0x02189}, + {0x02190, 0x02199}, + {0x021B8, 0x021B9}, + {0x021D2, 0x021D2}, + {0x021D4, 0x021D4}, + {0x021E7, 0x021E7}, + {0x02200, 0x02200}, + {0x02202, 0x02203}, + {0x02207, 0x02208}, + {0x0220B, 0x0220B}, + {0x0220F, 0x0220F}, + {0x02211, 0x02211}, + {0x02215, 0x02215}, + {0x0221A, 0x0221A}, + {0x0221D, 0x02220}, + {0x02223, 0x02223}, + {0x02225, 0x02225}, + {0x02227, 0x0222C}, + {0x0222E, 0x0222E}, + {0x02234, 0x02237}, + {0x0223C, 0x0223D}, + {0x02248, 0x02248}, + {0x0224C, 0x0224C}, + {0x02252, 0x02252}, + {0x02260, 0x02261}, + {0x02264, 0x02267}, + {0x0226A, 0x0226B}, + {0x0226E, 0x0226F}, + {0x02282, 0x02283}, + {0x02286, 0x02287}, + {0x02295, 0x02295}, + {0x02299, 0x02299}, + {0x022A5, 0x022A5}, + {0x022BF, 0x022BF}, + {0x02312, 0x02312}, + {0x02460, 0x024E9}, + {0x024EB, 0x0254B}, + {0x02550, 0x02573}, + {0x02580, 0x0258F}, + {0x02592, 0x02595}, + {0x025A0, 0x025A1}, + {0x025A3, 0x025A9}, + {0x025B2, 0x025B3}, + {0x025B6, 0x025B7}, + {0x025BC, 0x025BD}, + {0x025C0, 0x025C1}, + {0x025C6, 0x025C8}, + {0x025CB, 0x025CB}, + {0x025CE, 0x025D1}, + {0x025E2, 0x025E5}, + {0x025EF, 0x025EF}, + {0x02605, 0x02606}, + {0x02609, 0x02609}, + {0x0260E, 0x0260F}, + {0x0261C, 0x0261C}, + {0x0261E, 0x0261E}, + {0x02640, 0x02640}, + {0x02642, 0x02642}, + {0x02660, 0x02661}, + {0x02663, 0x02665}, + {0x02667, 0x0266A}, + {0x0266C, 0x0266D}, + {0x0266F, 0x0266F}, + {0x0269E, 0x0269F}, + {0x026BF, 0x026BF}, + {0x026C6, 0x026CD}, + {0x026CF, 0x026D3}, + {0x026D5, 0x026E1}, + {0x026E3, 0x026E3}, + {0x026E8, 0x026E9}, + {0x026EB, 0x026F1}, + {0x026F4, 0x026F4}, + {0x026F6, 0x026F9}, + {0x026FB, 0x026FC}, + {0x026FE, 0x026FF}, + {0x0273D, 0x0273D}, + {0x02776, 0x0277F}, + {0x02B56, 0x02B59}, + {0x03248, 0x0324F}, + {0x0E000, 0x0F8FF}, + {0x0FE00, 0x0FE0F}, + {0x0FFFD, 0x0FFFD}, + {0x1F100, 0x1F10A}, + {0x1F110, 0x1F12D}, + {0x1F130, 0x1F169}, + {0x1F170, 0x1F18D}, + {0x1F18F, 0x1F190}, + {0x1F19B, 0x1F1AC}, + {0xE0100, 0xE01EF}, + {0xF0000, 0xFFFFD}, + {0x100000, 0x10FFFD} +}; + +/* Unassigned characters. */ +static const struct widechar_range widechar_unassigned_table[] = { + {0x00378, 0x00379}, + {0x00380, 0x00383}, + {0x0038B, 0x0038B}, + {0x0038D, 0x0038D}, + {0x003A2, 0x003A2}, + {0x00530, 0x00530}, + {0x00557, 0x00558}, + {0x0058B, 0x0058C}, + {0x00590, 0x00590}, + {0x005C8, 0x005CF}, + {0x005EB, 0x005EE}, + {0x005F5, 0x005FF}, + {0x0070E, 0x0070E}, + {0x0074B, 0x0074C}, + {0x007B2, 0x007BF}, + {0x007FB, 0x007FC}, + {0x0082E, 0x0082F}, + {0x0083F, 0x0083F}, + {0x0085C, 0x0085D}, + {0x0085F, 0x0085F}, + {0x0086B, 0x0086F}, + {0x0088F, 0x0088F}, + {0x00892, 0x00896}, + {0x00984, 0x00984}, + {0x0098D, 0x0098E}, + {0x00991, 0x00992}, + {0x009A9, 0x009A9}, + {0x009B1, 0x009B1}, + {0x009B3, 0x009B5}, + {0x009BA, 0x009BB}, + {0x009C5, 0x009C6}, + {0x009C9, 0x009CA}, + {0x009CF, 0x009D6}, + {0x009D8, 0x009DB}, + {0x009DE, 0x009DE}, + {0x009E4, 0x009E5}, + {0x009FF, 0x00A00}, + {0x00A04, 0x00A04}, + {0x00A0B, 0x00A0E}, + {0x00A11, 0x00A12}, + {0x00A29, 0x00A29}, + {0x00A31, 0x00A31}, + {0x00A34, 0x00A34}, + {0x00A37, 0x00A37}, + {0x00A3A, 0x00A3B}, + {0x00A3D, 0x00A3D}, + {0x00A43, 0x00A46}, + {0x00A49, 0x00A4A}, + {0x00A4E, 0x00A50}, + {0x00A52, 0x00A58}, + {0x00A5D, 0x00A5D}, + {0x00A5F, 0x00A65}, + {0x00A77, 0x00A80}, + {0x00A84, 0x00A84}, + {0x00A8E, 0x00A8E}, + {0x00A92, 0x00A92}, + {0x00AA9, 0x00AA9}, + {0x00AB1, 0x00AB1}, + {0x00AB4, 0x00AB4}, + {0x00ABA, 0x00ABB}, + {0x00AC6, 0x00AC6}, + {0x00ACA, 0x00ACA}, + {0x00ACE, 0x00ACF}, + {0x00AD1, 0x00ADF}, + {0x00AE4, 0x00AE5}, + {0x00AF2, 0x00AF8}, + {0x00B00, 0x00B00}, + {0x00B04, 0x00B04}, + {0x00B0D, 0x00B0E}, + {0x00B11, 0x00B12}, + {0x00B29, 0x00B29}, + {0x00B31, 0x00B31}, + {0x00B34, 0x00B34}, + {0x00B3A, 0x00B3B}, + {0x00B45, 0x00B46}, + {0x00B49, 0x00B4A}, + {0x00B4E, 0x00B54}, + {0x00B58, 0x00B5B}, + {0x00B5E, 0x00B5E}, + {0x00B64, 0x00B65}, + {0x00B78, 0x00B81}, + {0x00B84, 0x00B84}, + {0x00B8B, 0x00B8D}, + {0x00B91, 0x00B91}, + {0x00B96, 0x00B98}, + {0x00B9B, 0x00B9B}, + {0x00B9D, 0x00B9D}, + {0x00BA0, 0x00BA2}, + {0x00BA5, 0x00BA7}, + {0x00BAB, 0x00BAD}, + {0x00BBA, 0x00BBD}, + {0x00BC3, 0x00BC5}, + {0x00BC9, 0x00BC9}, + {0x00BCE, 0x00BCF}, + {0x00BD1, 0x00BD6}, + {0x00BD8, 0x00BE5}, + {0x00BFB, 0x00BFF}, + {0x00C0D, 0x00C0D}, + {0x00C11, 0x00C11}, + {0x00C29, 0x00C29}, + {0x00C3A, 0x00C3B}, + {0x00C45, 0x00C45}, + {0x00C49, 0x00C49}, + {0x00C4E, 0x00C54}, + {0x00C57, 0x00C57}, + {0x00C5B, 0x00C5C}, + {0x00C5E, 0x00C5F}, + {0x00C64, 0x00C65}, + {0x00C70, 0x00C76}, + {0x00C8D, 0x00C8D}, + {0x00C91, 0x00C91}, + {0x00CA9, 0x00CA9}, + {0x00CB4, 0x00CB4}, + {0x00CBA, 0x00CBB}, + {0x00CC5, 0x00CC5}, + {0x00CC9, 0x00CC9}, + {0x00CCE, 0x00CD4}, + {0x00CD7, 0x00CDC}, + {0x00CDF, 0x00CDF}, + {0x00CE4, 0x00CE5}, + {0x00CF0, 0x00CF0}, + {0x00CF4, 0x00CFF}, + {0x00D0D, 0x00D0D}, + {0x00D11, 0x00D11}, + {0x00D45, 0x00D45}, + {0x00D49, 0x00D49}, + {0x00D50, 0x00D53}, + {0x00D64, 0x00D65}, + {0x00D80, 0x00D80}, + {0x00D84, 0x00D84}, + {0x00D97, 0x00D99}, + {0x00DB2, 0x00DB2}, + {0x00DBC, 0x00DBC}, + {0x00DBE, 0x00DBF}, + {0x00DC7, 0x00DC9}, + {0x00DCB, 0x00DCE}, + {0x00DD5, 0x00DD5}, + {0x00DD7, 0x00DD7}, + {0x00DE0, 0x00DE5}, + {0x00DF0, 0x00DF1}, + {0x00DF5, 0x00E00}, + {0x00E3B, 0x00E3E}, + {0x00E5C, 0x00E80}, + {0x00E83, 0x00E83}, + {0x00E85, 0x00E85}, + {0x00E8B, 0x00E8B}, + {0x00EA4, 0x00EA4}, + {0x00EA6, 0x00EA6}, + {0x00EBE, 0x00EBF}, + {0x00EC5, 0x00EC5}, + {0x00EC7, 0x00EC7}, + {0x00ECF, 0x00ECF}, + {0x00EDA, 0x00EDB}, + {0x00EE0, 0x00EFF}, + {0x00F48, 0x00F48}, + {0x00F6D, 0x00F70}, + {0x00F98, 0x00F98}, + {0x00FBD, 0x00FBD}, + {0x00FCD, 0x00FCD}, + {0x00FDB, 0x00FFF}, + {0x010C6, 0x010C6}, + {0x010C8, 0x010CC}, + {0x010CE, 0x010CF}, + {0x01249, 0x01249}, + {0x0124E, 0x0124F}, + {0x01257, 0x01257}, + {0x01259, 0x01259}, + {0x0125E, 0x0125F}, + {0x01289, 0x01289}, + {0x0128E, 0x0128F}, + {0x012B1, 0x012B1}, + {0x012B6, 0x012B7}, + {0x012BF, 0x012BF}, + {0x012C1, 0x012C1}, + {0x012C6, 0x012C7}, + {0x012D7, 0x012D7}, + {0x01311, 0x01311}, + {0x01316, 0x01317}, + {0x0135B, 0x0135C}, + {0x0137D, 0x0137F}, + {0x0139A, 0x0139F}, + {0x013F6, 0x013F7}, + {0x013FE, 0x013FF}, + {0x0169D, 0x0169F}, + {0x016F9, 0x016FF}, + {0x01716, 0x0171E}, + {0x01737, 0x0173F}, + {0x01754, 0x0175F}, + {0x0176D, 0x0176D}, + {0x01771, 0x01771}, + {0x01774, 0x0177F}, + {0x017DE, 0x017DF}, + {0x017EA, 0x017EF}, + {0x017FA, 0x017FF}, + {0x0181A, 0x0181F}, + {0x01879, 0x0187F}, + {0x018AB, 0x018AF}, + {0x018F6, 0x018FF}, + {0x0191F, 0x0191F}, + {0x0192C, 0x0192F}, + {0x0193C, 0x0193F}, + {0x01941, 0x01943}, + {0x0196E, 0x0196F}, + {0x01975, 0x0197F}, + {0x019AC, 0x019AF}, + {0x019CA, 0x019CF}, + {0x019DB, 0x019DD}, + {0x01A1C, 0x01A1D}, + {0x01A5F, 0x01A5F}, + {0x01A7D, 0x01A7E}, + {0x01A8A, 0x01A8F}, + {0x01A9A, 0x01A9F}, + {0x01AAE, 0x01AAF}, + {0x01ACF, 0x01AFF}, + {0x01B4D, 0x01B4D}, + {0x01BF4, 0x01BFB}, + {0x01C38, 0x01C3A}, + {0x01C4A, 0x01C4C}, + {0x01C8B, 0x01C8F}, + {0x01CBB, 0x01CBC}, + {0x01CC8, 0x01CCF}, + {0x01CFB, 0x01CFF}, + {0x01F16, 0x01F17}, + {0x01F1E, 0x01F1F}, + {0x01F46, 0x01F47}, + {0x01F4E, 0x01F4F}, + {0x01F58, 0x01F58}, + {0x01F5A, 0x01F5A}, + {0x01F5C, 0x01F5C}, + {0x01F5E, 0x01F5E}, + {0x01F7E, 0x01F7F}, + {0x01FB5, 0x01FB5}, + {0x01FC5, 0x01FC5}, + {0x01FD4, 0x01FD5}, + {0x01FDC, 0x01FDC}, + {0x01FF0, 0x01FF1}, + {0x01FF5, 0x01FF5}, + {0x01FFF, 0x01FFF}, + {0x02065, 0x02065}, + {0x02072, 0x02073}, + {0x0208F, 0x0208F}, + {0x0209D, 0x0209F}, + {0x020C1, 0x020CF}, + {0x020F1, 0x020FF}, + {0x0218C, 0x0218F}, + {0x0242A, 0x0243F}, + {0x0244B, 0x0245F}, + {0x02B74, 0x02B75}, + {0x02B96, 0x02B96}, + {0x02CF4, 0x02CF8}, + {0x02D26, 0x02D26}, + {0x02D28, 0x02D2C}, + {0x02D2E, 0x02D2F}, + {0x02D68, 0x02D6E}, + {0x02D71, 0x02D7E}, + {0x02D97, 0x02D9F}, + {0x02DA7, 0x02DA7}, + {0x02DAF, 0x02DAF}, + {0x02DB7, 0x02DB7}, + {0x02DBF, 0x02DBF}, + {0x02DC7, 0x02DC7}, + {0x02DCF, 0x02DCF}, + {0x02DD7, 0x02DD7}, + {0x02DDF, 0x02DDF}, + {0x02E5E, 0x02E7F}, + {0x02E9A, 0x02E9A}, + {0x02EF4, 0x02EFF}, + {0x02FD6, 0x02FEF}, + {0x03040, 0x03040}, + {0x03097, 0x03098}, + {0x03100, 0x03104}, + {0x03130, 0x03130}, + {0x0318F, 0x0318F}, + {0x031E6, 0x031EE}, + {0x0321F, 0x0321F}, + {0x03401, 0x04DBE}, + {0x04E01, 0x09FFE}, + {0x0A48D, 0x0A48F}, + {0x0A4C7, 0x0A4CF}, + {0x0A62C, 0x0A63F}, + {0x0A6F8, 0x0A6FF}, + {0x0A7CE, 0x0A7CF}, + {0x0A7D2, 0x0A7D2}, + {0x0A7D4, 0x0A7D4}, + {0x0A7DD, 0x0A7F1}, + {0x0A82D, 0x0A82F}, + {0x0A83A, 0x0A83F}, + {0x0A878, 0x0A87F}, + {0x0A8C6, 0x0A8CD}, + {0x0A8DA, 0x0A8DF}, + {0x0A954, 0x0A95E}, + {0x0A97D, 0x0A97F}, + {0x0A9CE, 0x0A9CE}, + {0x0A9DA, 0x0A9DD}, + {0x0A9FF, 0x0A9FF}, + {0x0AA37, 0x0AA3F}, + {0x0AA4E, 0x0AA4F}, + {0x0AA5A, 0x0AA5B}, + {0x0AAC3, 0x0AADA}, + {0x0AAF7, 0x0AB00}, + {0x0AB07, 0x0AB08}, + {0x0AB0F, 0x0AB10}, + {0x0AB17, 0x0AB1F}, + {0x0AB27, 0x0AB27}, + {0x0AB2F, 0x0AB2F}, + {0x0AB6C, 0x0AB6F}, + {0x0ABEE, 0x0ABEF}, + {0x0ABFA, 0x0ABFF}, + {0x0AC01, 0x0D7A2}, + {0x0D7A4, 0x0D7AF}, + {0x0D7C7, 0x0D7CA}, + {0x0D7FC, 0x0D7FF}, + {0x0FA6E, 0x0FA6F}, + {0x0FADA, 0x0FAFF}, + {0x0FB07, 0x0FB12}, + {0x0FB18, 0x0FB1C}, + {0x0FB37, 0x0FB37}, + {0x0FB3D, 0x0FB3D}, + {0x0FB3F, 0x0FB3F}, + {0x0FB42, 0x0FB42}, + {0x0FB45, 0x0FB45}, + {0x0FBC3, 0x0FBD2}, + {0x0FD90, 0x0FD91}, + {0x0FDC8, 0x0FDCE}, + {0x0FE1A, 0x0FE1F}, + {0x0FE53, 0x0FE53}, + {0x0FE67, 0x0FE67}, + {0x0FE6C, 0x0FE6F}, + {0x0FE75, 0x0FE75}, + {0x0FEFD, 0x0FEFE}, + {0x0FF00, 0x0FF00}, + {0x0FFBF, 0x0FFC1}, + {0x0FFC8, 0x0FFC9}, + {0x0FFD0, 0x0FFD1}, + {0x0FFD8, 0x0FFD9}, + {0x0FFDD, 0x0FFDF}, + {0x0FFE7, 0x0FFE7}, + {0x0FFEF, 0x0FFF8}, + {0x1000C, 0x1000C}, + {0x10027, 0x10027}, + {0x1003B, 0x1003B}, + {0x1003E, 0x1003E}, + {0x1004E, 0x1004F}, + {0x1005E, 0x1007F}, + {0x100FB, 0x100FF}, + {0x10103, 0x10106}, + {0x10134, 0x10136}, + {0x1018F, 0x1018F}, + {0x1019D, 0x1019F}, + {0x101A1, 0x101CF}, + {0x101FE, 0x1027F}, + {0x1029D, 0x1029F}, + {0x102D1, 0x102DF}, + {0x102FC, 0x102FF}, + {0x10324, 0x1032C}, + {0x1034B, 0x1034F}, + {0x1037B, 0x1037F}, + {0x1039E, 0x1039E}, + {0x103C4, 0x103C7}, + {0x103D6, 0x103FF}, + {0x1049E, 0x1049F}, + {0x104AA, 0x104AF}, + {0x104D4, 0x104D7}, + {0x104FC, 0x104FF}, + {0x10528, 0x1052F}, + {0x10564, 0x1056E}, + {0x1057B, 0x1057B}, + {0x1058B, 0x1058B}, + {0x10593, 0x10593}, + {0x10596, 0x10596}, + {0x105A2, 0x105A2}, + {0x105B2, 0x105B2}, + {0x105BA, 0x105BA}, + {0x105BD, 0x105BF}, + {0x105F4, 0x105FF}, + {0x10737, 0x1073F}, + {0x10756, 0x1075F}, + {0x10768, 0x1077F}, + {0x10786, 0x10786}, + {0x107B1, 0x107B1}, + {0x107BB, 0x107FF}, + {0x10806, 0x10807}, + {0x10809, 0x10809}, + {0x10836, 0x10836}, + {0x10839, 0x1083B}, + {0x1083D, 0x1083E}, + {0x10856, 0x10856}, + {0x1089F, 0x108A6}, + {0x108B0, 0x108DF}, + {0x108F3, 0x108F3}, + {0x108F6, 0x108FA}, + {0x1091C, 0x1091E}, + {0x1093A, 0x1093E}, + {0x10940, 0x1097F}, + {0x109B8, 0x109BB}, + {0x109D0, 0x109D1}, + {0x10A04, 0x10A04}, + {0x10A07, 0x10A0B}, + {0x10A14, 0x10A14}, + {0x10A18, 0x10A18}, + {0x10A36, 0x10A37}, + {0x10A3B, 0x10A3E}, + {0x10A49, 0x10A4F}, + {0x10A59, 0x10A5F}, + {0x10AA0, 0x10ABF}, + {0x10AE7, 0x10AEA}, + {0x10AF7, 0x10AFF}, + {0x10B36, 0x10B38}, + {0x10B56, 0x10B57}, + {0x10B73, 0x10B77}, + {0x10B92, 0x10B98}, + {0x10B9D, 0x10BA8}, + {0x10BB0, 0x10BFF}, + {0x10C49, 0x10C7F}, + {0x10CB3, 0x10CBF}, + {0x10CF3, 0x10CF9}, + {0x10D28, 0x10D2F}, + {0x10D3A, 0x10D3F}, + {0x10D66, 0x10D68}, + {0x10D86, 0x10D8D}, + {0x10D90, 0x10E5F}, + {0x10E7F, 0x10E7F}, + {0x10EAA, 0x10EAA}, + {0x10EAE, 0x10EAF}, + {0x10EB2, 0x10EC1}, + {0x10EC5, 0x10EFB}, + {0x10F28, 0x10F2F}, + {0x10F5A, 0x10F6F}, + {0x10F8A, 0x10FAF}, + {0x10FCC, 0x10FDF}, + {0x10FF7, 0x10FFF}, + {0x1104E, 0x11051}, + {0x11076, 0x1107E}, + {0x110C3, 0x110CC}, + {0x110CE, 0x110CF}, + {0x110E9, 0x110EF}, + {0x110FA, 0x110FF}, + {0x11135, 0x11135}, + {0x11148, 0x1114F}, + {0x11177, 0x1117F}, + {0x111E0, 0x111E0}, + {0x111F5, 0x111FF}, + {0x11212, 0x11212}, + {0x11242, 0x1127F}, + {0x11287, 0x11287}, + {0x11289, 0x11289}, + {0x1128E, 0x1128E}, + {0x1129E, 0x1129E}, + {0x112AA, 0x112AF}, + {0x112EB, 0x112EF}, + {0x112FA, 0x112FF}, + {0x11304, 0x11304}, + {0x1130D, 0x1130E}, + {0x11311, 0x11312}, + {0x11329, 0x11329}, + {0x11331, 0x11331}, + {0x11334, 0x11334}, + {0x1133A, 0x1133A}, + {0x11345, 0x11346}, + {0x11349, 0x1134A}, + {0x1134E, 0x1134F}, + {0x11351, 0x11356}, + {0x11358, 0x1135C}, + {0x11364, 0x11365}, + {0x1136D, 0x1136F}, + {0x11375, 0x1137F}, + {0x1138A, 0x1138A}, + {0x1138C, 0x1138D}, + {0x1138F, 0x1138F}, + {0x113B6, 0x113B6}, + {0x113C1, 0x113C1}, + {0x113C3, 0x113C4}, + {0x113C6, 0x113C6}, + {0x113CB, 0x113CB}, + {0x113D6, 0x113D6}, + {0x113D9, 0x113E0}, + {0x113E3, 0x113FF}, + {0x1145C, 0x1145C}, + {0x11462, 0x1147F}, + {0x114C8, 0x114CF}, + {0x114DA, 0x1157F}, + {0x115B6, 0x115B7}, + {0x115DE, 0x115FF}, + {0x11645, 0x1164F}, + {0x1165A, 0x1165F}, + {0x1166D, 0x1167F}, + {0x116BA, 0x116BF}, + {0x116CA, 0x116CF}, + {0x116E4, 0x116FF}, + {0x1171B, 0x1171C}, + {0x1172C, 0x1172F}, + {0x11747, 0x117FF}, + {0x1183C, 0x1189F}, + {0x118F3, 0x118FE}, + {0x11907, 0x11908}, + {0x1190A, 0x1190B}, + {0x11914, 0x11914}, + {0x11917, 0x11917}, + {0x11936, 0x11936}, + {0x11939, 0x1193A}, + {0x11947, 0x1194F}, + {0x1195A, 0x1199F}, + {0x119A8, 0x119A9}, + {0x119D8, 0x119D9}, + {0x119E5, 0x119FF}, + {0x11A48, 0x11A4F}, + {0x11AA3, 0x11AAF}, + {0x11AF9, 0x11AFF}, + {0x11B0A, 0x11BBF}, + {0x11BE2, 0x11BEF}, + {0x11BFA, 0x11BFF}, + {0x11C09, 0x11C09}, + {0x11C37, 0x11C37}, + {0x11C46, 0x11C4F}, + {0x11C6D, 0x11C6F}, + {0x11C90, 0x11C91}, + {0x11CA8, 0x11CA8}, + {0x11CB7, 0x11CFF}, + {0x11D07, 0x11D07}, + {0x11D0A, 0x11D0A}, + {0x11D37, 0x11D39}, + {0x11D3B, 0x11D3B}, + {0x11D3E, 0x11D3E}, + {0x11D48, 0x11D4F}, + {0x11D5A, 0x11D5F}, + {0x11D66, 0x11D66}, + {0x11D69, 0x11D69}, + {0x11D8F, 0x11D8F}, + {0x11D92, 0x11D92}, + {0x11D99, 0x11D9F}, + {0x11DAA, 0x11EDF}, + {0x11EF9, 0x11EFF}, + {0x11F11, 0x11F11}, + {0x11F3B, 0x11F3D}, + {0x11F5B, 0x11FAF}, + {0x11FB1, 0x11FBF}, + {0x11FF2, 0x11FFE}, + {0x1239A, 0x123FF}, + {0x1246F, 0x1246F}, + {0x12475, 0x1247F}, + {0x12544, 0x12F8F}, + {0x12FF3, 0x12FFF}, + {0x13456, 0x1345F}, + {0x143FB, 0x143FF}, + {0x14647, 0x160FF}, + {0x1613A, 0x167FF}, + {0x16A39, 0x16A3F}, + {0x16A5F, 0x16A5F}, + {0x16A6A, 0x16A6D}, + {0x16ABF, 0x16ABF}, + {0x16ACA, 0x16ACF}, + {0x16AEE, 0x16AEF}, + {0x16AF6, 0x16AFF}, + {0x16B46, 0x16B4F}, + {0x16B5A, 0x16B5A}, + {0x16B62, 0x16B62}, + {0x16B78, 0x16B7C}, + {0x16B90, 0x16D3F}, + {0x16D7A, 0x16E3F}, + {0x16E9B, 0x16EFF}, + {0x16F4B, 0x16F4E}, + {0x16F88, 0x16F8E}, + {0x16FA0, 0x16FDF}, + {0x16FE5, 0x16FEF}, + {0x16FF2, 0x16FFF}, + {0x17001, 0x187F6}, + {0x187F8, 0x187FF}, + {0x18CD6, 0x18CFE}, + {0x18D01, 0x18D07}, + {0x18D09, 0x1AFEF}, + {0x1AFF4, 0x1AFF4}, + {0x1AFFC, 0x1AFFC}, + {0x1AFFF, 0x1AFFF}, + {0x1B123, 0x1B131}, + {0x1B133, 0x1B14F}, + {0x1B153, 0x1B154}, + {0x1B156, 0x1B163}, + {0x1B168, 0x1B16F}, + {0x1B2FC, 0x1BBFF}, + {0x1BC6B, 0x1BC6F}, + {0x1BC7D, 0x1BC7F}, + {0x1BC89, 0x1BC8F}, + {0x1BC9A, 0x1BC9B}, + {0x1BCA4, 0x1CBFF}, + {0x1CCFA, 0x1CCFF}, + {0x1CEB4, 0x1CEFF}, + {0x1CF2E, 0x1CF2F}, + {0x1CF47, 0x1CF4F}, + {0x1CFC4, 0x1CFFF}, + {0x1D0F6, 0x1D0FF}, + {0x1D127, 0x1D128}, + {0x1D1EB, 0x1D1FF}, + {0x1D246, 0x1D2BF}, + {0x1D2D4, 0x1D2DF}, + {0x1D2F4, 0x1D2FF}, + {0x1D357, 0x1D35F}, + {0x1D379, 0x1D3FF}, + {0x1D455, 0x1D455}, + {0x1D49D, 0x1D49D}, + {0x1D4A0, 0x1D4A1}, + {0x1D4A3, 0x1D4A4}, + {0x1D4A7, 0x1D4A8}, + {0x1D4AD, 0x1D4AD}, + {0x1D4BA, 0x1D4BA}, + {0x1D4BC, 0x1D4BC}, + {0x1D4C4, 0x1D4C4}, + {0x1D506, 0x1D506}, + {0x1D50B, 0x1D50C}, + {0x1D515, 0x1D515}, + {0x1D51D, 0x1D51D}, + {0x1D53A, 0x1D53A}, + {0x1D53F, 0x1D53F}, + {0x1D545, 0x1D545}, + {0x1D547, 0x1D549}, + {0x1D551, 0x1D551}, + {0x1D6A6, 0x1D6A7}, + {0x1D7CC, 0x1D7CD}, + {0x1DA8C, 0x1DA9A}, + {0x1DAA0, 0x1DAA0}, + {0x1DAB0, 0x1DEFF}, + {0x1DF1F, 0x1DF24}, + {0x1DF2B, 0x1DFFF}, + {0x1E007, 0x1E007}, + {0x1E019, 0x1E01A}, + {0x1E022, 0x1E022}, + {0x1E025, 0x1E025}, + {0x1E02B, 0x1E02F}, + {0x1E06E, 0x1E08E}, + {0x1E090, 0x1E0FF}, + {0x1E12D, 0x1E12F}, + {0x1E13E, 0x1E13F}, + {0x1E14A, 0x1E14D}, + {0x1E150, 0x1E28F}, + {0x1E2AF, 0x1E2BF}, + {0x1E2FA, 0x1E2FE}, + {0x1E300, 0x1E4CF}, + {0x1E4FA, 0x1E5CF}, + {0x1E5FB, 0x1E5FE}, + {0x1E600, 0x1E7DF}, + {0x1E7E7, 0x1E7E7}, + {0x1E7EC, 0x1E7EC}, + {0x1E7EF, 0x1E7EF}, + {0x1E7FF, 0x1E7FF}, + {0x1E8C5, 0x1E8C6}, + {0x1E8D7, 0x1E8FF}, + {0x1E94C, 0x1E94F}, + {0x1E95A, 0x1E95D}, + {0x1E960, 0x1EC70}, + {0x1ECB5, 0x1ED00}, + {0x1ED3E, 0x1EDFF}, + {0x1EE04, 0x1EE04}, + {0x1EE20, 0x1EE20}, + {0x1EE23, 0x1EE23}, + {0x1EE25, 0x1EE26}, + {0x1EE28, 0x1EE28}, + {0x1EE33, 0x1EE33}, + {0x1EE38, 0x1EE38}, + {0x1EE3A, 0x1EE3A}, + {0x1EE3C, 0x1EE41}, + {0x1EE43, 0x1EE46}, + {0x1EE48, 0x1EE48}, + {0x1EE4A, 0x1EE4A}, + {0x1EE4C, 0x1EE4C}, + {0x1EE50, 0x1EE50}, + {0x1EE53, 0x1EE53}, + {0x1EE55, 0x1EE56}, + {0x1EE58, 0x1EE58}, + {0x1EE5A, 0x1EE5A}, + {0x1EE5C, 0x1EE5C}, + {0x1EE5E, 0x1EE5E}, + {0x1EE60, 0x1EE60}, + {0x1EE63, 0x1EE63}, + {0x1EE65, 0x1EE66}, + {0x1EE6B, 0x1EE6B}, + {0x1EE73, 0x1EE73}, + {0x1EE78, 0x1EE78}, + {0x1EE7D, 0x1EE7D}, + {0x1EE7F, 0x1EE7F}, + {0x1EE8A, 0x1EE8A}, + {0x1EE9C, 0x1EEA0}, + {0x1EEA4, 0x1EEA4}, + {0x1EEAA, 0x1EEAA}, + {0x1EEBC, 0x1EEEF}, + {0x1EEF2, 0x1EFFF}, + {0x1F02C, 0x1F02F}, + {0x1F094, 0x1F09F}, + {0x1F0AF, 0x1F0B0}, + {0x1F0C0, 0x1F0C0}, + {0x1F0D0, 0x1F0D0}, + {0x1F0F6, 0x1F0FF}, + {0x1F1AE, 0x1F1E5}, + {0x1F203, 0x1F20F}, + {0x1F23C, 0x1F23F}, + {0x1F249, 0x1F24F}, + {0x1F252, 0x1F25F}, + {0x1F266, 0x1F2FF}, + {0x1F6D8, 0x1F6DB}, + {0x1F6ED, 0x1F6EF}, + {0x1F6FD, 0x1F6FF}, + {0x1F777, 0x1F77A}, + {0x1F7DA, 0x1F7DF}, + {0x1F7EC, 0x1F7EF}, + {0x1F7F1, 0x1F7FF}, + {0x1F80C, 0x1F80F}, + {0x1F848, 0x1F84F}, + {0x1F85A, 0x1F85F}, + {0x1F888, 0x1F88F}, + {0x1F8AE, 0x1F8AF}, + {0x1F8BC, 0x1F8BF}, + {0x1F8C2, 0x1F8FF}, + {0x1FA54, 0x1FA5F}, + {0x1FA6E, 0x1FA6F}, + {0x1FA7D, 0x1FA7F}, + {0x1FA8A, 0x1FA8E}, + {0x1FAC7, 0x1FACD}, + {0x1FADD, 0x1FADE}, + {0x1FAEA, 0x1FAEF}, + {0x1FAF9, 0x1FAFF}, + {0x1FB93, 0x1FB93}, + {0x1FBFA, 0x1FFFD}, + {0x20001, 0x2A6DE}, + {0x2A6E0, 0x2A6FF}, + {0x2A701, 0x2B738}, + {0x2B73A, 0x2B73F}, + {0x2B741, 0x2B81C}, + {0x2B81E, 0x2B81F}, + {0x2B821, 0x2CEA0}, + {0x2CEA2, 0x2CEAF}, + {0x2CEB1, 0x2EBDF}, + {0x2EBE1, 0x2EBEF}, + {0x2EBF1, 0x2EE5C}, + {0x2EE5E, 0x2F7FF}, + {0x2FA1E, 0x2FFFD}, + {0x30001, 0x31349}, + {0x3134B, 0x3134F}, + {0x31351, 0x323AE}, + {0x323B0, 0x3FFFD}, + {0x40000, 0x4FFFD}, + {0x50000, 0x5FFFD}, + {0x60000, 0x6FFFD}, + {0x70000, 0x7FFFD}, + {0x80000, 0x8FFFD}, + {0x90000, 0x9FFFD}, + {0xA0000, 0xAFFFD}, + {0xB0000, 0xBFFFD}, + {0xC0000, 0xCFFFD}, + {0xD0000, 0xDFFFD}, + {0xE0000, 0xE0000}, + {0xE0002, 0xE001F}, + {0xE0080, 0xE00FF}, + {0xE01F0, 0xEFFFD} +}; + +/* Non-characters. */ +static const struct widechar_range widechar_nonchar_table[] = { + {0x0FDD0, 0x0FDEF}, + {0x0FFFE, 0x0FFFF}, + {0x1FFFE, 0x1FFFF}, + {0x2FFFE, 0x2FFFF}, + {0x3FFFE, 0x3FFFF}, + {0x4FFFE, 0x4FFFF}, + {0x5FFFE, 0x5FFFF}, + {0x6FFFE, 0x6FFFF}, + {0x7FFFE, 0x7FFFF}, + {0x8FFFE, 0x8FFFF}, + {0x9FFFE, 0x9FFFF}, + {0xAFFFE, 0xAFFFF}, + {0xBFFFE, 0xBFFFF}, + {0xCFFFE, 0xCFFFF}, + {0xDFFFE, 0xDFFFF}, + {0xEFFFE, 0xEFFFF}, + {0xFFFFE, 0xFFFFF}, + {0x10FFFE, 0x10FFFF} +}; + +/* Characters that were widened from width 1 to 2 in Unicode 9. */ +static const struct widechar_range widechar_widened_table[] = { + {0x0231A, 0x0231B}, + {0x023E9, 0x023EC}, + {0x023F0, 0x023F0}, + {0x023F3, 0x023F3}, + {0x025FD, 0x025FE}, + {0x02614, 0x02615}, + {0x02648, 0x02653}, + {0x0267F, 0x0267F}, + {0x02693, 0x02693}, + {0x026A1, 0x026A1}, + {0x026AA, 0x026AB}, + {0x026BD, 0x026BE}, + {0x026C4, 0x026C5}, + {0x026CE, 0x026CE}, + {0x026D4, 0x026D4}, + {0x026EA, 0x026EA}, + {0x026F2, 0x026F3}, + {0x026F5, 0x026F5}, + {0x026FA, 0x026FA}, + {0x026FD, 0x026FD}, + {0x02705, 0x02705}, + {0x0270A, 0x0270B}, + {0x02728, 0x02728}, + {0x0274C, 0x0274C}, + {0x0274E, 0x0274E}, + {0x02753, 0x02755}, + {0x02757, 0x02757}, + {0x02795, 0x02797}, + {0x027B0, 0x027B0}, + {0x027BF, 0x027BF}, + {0x02B1B, 0x02B1C}, + {0x02B50, 0x02B50}, + {0x02B55, 0x02B55}, + {0x1F004, 0x1F004}, + {0x1F0CF, 0x1F0CF}, + {0x1F18E, 0x1F18E}, + {0x1F191, 0x1F19A}, + {0x1F201, 0x1F201}, + {0x1F21A, 0x1F21A}, + {0x1F22F, 0x1F22F}, + {0x1F232, 0x1F236}, + {0x1F238, 0x1F23A}, + {0x1F250, 0x1F251}, + {0x1F300, 0x1F320}, + {0x1F32D, 0x1F335}, + {0x1F337, 0x1F37C}, + {0x1F37E, 0x1F393}, + {0x1F3A0, 0x1F3CA}, + {0x1F3CF, 0x1F3D3}, + {0x1F3E0, 0x1F3F0}, + {0x1F3F4, 0x1F3F4}, + {0x1F3F8, 0x1F43E}, + {0x1F440, 0x1F440}, + {0x1F442, 0x1F4FC}, + {0x1F4FF, 0x1F53D}, + {0x1F54B, 0x1F54E}, + {0x1F550, 0x1F567}, + {0x1F595, 0x1F596}, + {0x1F5FB, 0x1F64F}, + {0x1F680, 0x1F6C5}, + {0x1F6CC, 0x1F6CC}, + {0x1F6D0, 0x1F6D0}, + {0x1F6EB, 0x1F6EC}, + {0x1F910, 0x1F918}, + {0x1F980, 0x1F984}, + {0x1F9C0, 0x1F9C0} +}; + +template +bool widechar_in_table(const Collection &arr, uint32_t c) { + auto where = std::lower_bound(std::begin(arr), std::end(arr), c, + [](widechar_range p, uint32_t c) { return p.hi < c; }); + return where != std::end(arr) && where->lo <= c; +} + +/* Return the width of character c, or a special negative value. */ +int widechar_wcwidth(uint32_t c) { + if (widechar_in_table(widechar_ascii_table, c)) + return 1; + if (widechar_in_table(widechar_private_table, c)) + return widechar_private_use; + if (widechar_in_table(widechar_nonprint_table, c)) + return widechar_nonprint; + if (widechar_in_table(widechar_nonchar_table, c)) + return widechar_non_character; + if (widechar_in_table(widechar_combining_table, c)) + return widechar_combining; + if (widechar_in_table(widechar_combiningletters_table, c)) + return widechar_combining; + if (widechar_in_table(widechar_doublewide_table, c)) + return 2; + if (widechar_in_table(widechar_ambiguous_table, c)) + return widechar_ambiguous; + if (widechar_in_table(widechar_unassigned_table, c)) + return widechar_unassigned; + if (widechar_in_table(widechar_widened_table, c)) + return widechar_widened_in_9; + return 1; +} + +} // namespace +#endif // WIDECHAR_WIDTH_H From 1e2cace5f1dbd55ed76afbad7519100b76af5d88 Mon Sep 17 00:00:00 2001 From: Philipp Otterbein Date: Sat, 28 Dec 2024 23:40:25 +0100 Subject: [PATCH 593/718] fix documentation of substring --- src/libexpr/primops.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index f19dd473a..a0e2753b5 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -4059,7 +4059,7 @@ static RegisterPrimOp primop_toString({ }); /* `substring start len str' returns the substring of `str' starting - at character position `min(start, stringLength str)' inclusive and + at byte position `min(start, stringLength str)' inclusive and ending at `min(start + len, stringLength str)'. `start' must be non-negative. */ static void prim_substring(EvalState & state, const PosIdx pos, Value * * args, Value & v) @@ -4098,7 +4098,7 @@ static RegisterPrimOp primop_substring({ .name = "__substring", .args = {"start", "len", "s"}, .doc = R"( - Return the substring of *s* from character position *start* + Return the substring of *s* from byte position *start* (zero-based) up to but not including *start + len*. If *start* is greater than the length of the string, an empty string is returned. If *start + len* lies beyond the end of the string or *len* is `-1`, From b5f10655ede1c5f8986f622de7ad73daeda7d5fc Mon Sep 17 00:00:00 2001 From: NAHO <90870942+trueNAHO@users.noreply.github.com> Date: Fri, 27 Dec 2024 01:56:53 +0100 Subject: [PATCH 594/718] ci: update Ubuntu runner to ubuntu-24.04 Link: https://github.com/actions/runner-images/issues/10636 --- .github/workflows/ci.yml | 18 +++++++++--------- .github/workflows/labels.yml | 2 +- .mergify.yml | 4 ++-- doc/manual/source/development/testing.md | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2426ab166..7592f60b9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,7 +8,7 @@ permissions: read-all jobs: eval: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 with: @@ -20,7 +20,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-22.04, macos-latest] + os: [ubuntu-24.04, macos-latest] runs-on: ${{ matrix.os }} timeout-minutes: 60 steps: @@ -37,7 +37,7 @@ jobs: # Since ubuntu 22.30, unprivileged usernamespaces are no longer allowed to map to the root user: # https://ubuntu.com/blog/ubuntu-23-10-restricted-unprivileged-user-namespaces - run: sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 - if: matrix.os == 'ubuntu-22.04' + if: matrix.os == 'ubuntu-24.04' - run: scripts/build-checks - run: scripts/prepare-installer-for-github-actions - name: Upload installer tarball @@ -51,7 +51,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-22.04, macos-latest] + os: [ubuntu-24.04, macos-latest] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 @@ -68,7 +68,7 @@ jobs: install_url: 'http://localhost:8126/install' install_options: "--tarball-url-prefix http://localhost:8126/" - run: sudo apt install fish zsh - if: matrix.os == 'ubuntu-22.04' + if: matrix.os == 'ubuntu-24.04' - run: brew install fish if: matrix.os == 'macos-latest' - run: exec bash -c "nix-instantiate -E 'builtins.currentTime' --eval" @@ -86,7 +86,7 @@ jobs: permissions: contents: none name: Check Docker secrets present for installer tests - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 outputs: docker: ${{ steps.secret.outputs.docker }} steps: @@ -106,7 +106,7 @@ jobs: needs.check_secrets.outputs.docker == 'true' && github.event_name == 'push' && github.ref_name == 'master' - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - name: Check for secrets id: secret @@ -158,7 +158,7 @@ jobs: docker push $IMAGE_ID:master vm_tests: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - uses: DeterminateSystems/nix-installer-action@main @@ -173,7 +173,7 @@ jobs: flake_regressions: needs: vm_tests - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - name: Checkout nix uses: actions/checkout@v4 diff --git a/.github/workflows/labels.yml b/.github/workflows/labels.yml index 9d2ac80a3..23a5d9e51 100644 --- a/.github/workflows/labels.yml +++ b/.github/workflows/labels.yml @@ -15,7 +15,7 @@ permissions: jobs: labels: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 if: github.repository_owner == 'NixOS' steps: - uses: actions/labeler@v5 diff --git a/.mergify.yml b/.mergify.yml index c2e115487..827e97290 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -3,9 +3,9 @@ queue_rules: # all required tests need to go here merge_conditions: - check-success=tests (macos-latest) - - check-success=tests (ubuntu-22.04) + - check-success=tests (ubuntu-24.04) - check-success=installer_test (macos-latest) - - check-success=installer_test (ubuntu-22.04) + - check-success=installer_test (ubuntu-24.04) - check-success=vm_tests batch_size: 5 diff --git a/doc/manual/source/development/testing.md b/doc/manual/source/development/testing.md index 7e8762fe0..082863bcc 100644 --- a/doc/manual/source/development/testing.md +++ b/doc/manual/source/development/testing.md @@ -297,7 +297,7 @@ Creating a Cachix cache for your installer tests and adding its authorisation to - `armv7l-linux` - `x86_64-darwin` -- The `installer_test` job (which runs on `ubuntu-22.04` and `macos-latest`) will try to install Nix with the cached installer and run a trivial Nix command. +- The `installer_test` job (which runs on `ubuntu-24.04` and `macos-latest`) will try to install Nix with the cached installer and run a trivial Nix command. ### One-time setup From ce1e9ba85a1937ba695aab4da34bf310c5a8ecc9 Mon Sep 17 00:00:00 2001 From: NAHO <90870942+trueNAHO@users.noreply.github.com> Date: Fri, 27 Dec 2024 02:14:55 +0100 Subject: [PATCH 595/718] ci: lock macOS runner to macos-14 --- .github/workflows/ci.yml | 6 +++--- .mergify.yml | 4 ++-- doc/manual/source/development/testing.md | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7592f60b9..cd567cd63 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-24.04, macos-latest] + os: [ubuntu-24.04, macos-14] runs-on: ${{ matrix.os }} timeout-minutes: 60 steps: @@ -51,7 +51,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-24.04, macos-latest] + os: [ubuntu-24.04, macos-14] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 @@ -70,7 +70,7 @@ jobs: - run: sudo apt install fish zsh if: matrix.os == 'ubuntu-24.04' - run: brew install fish - if: matrix.os == 'macos-latest' + if: matrix.os == 'macos-14' - run: exec bash -c "nix-instantiate -E 'builtins.currentTime' --eval" - run: exec sh -c "nix-instantiate -E 'builtins.currentTime' --eval" - run: exec zsh -c "nix-instantiate -E 'builtins.currentTime' --eval" diff --git a/.mergify.yml b/.mergify.yml index 827e97290..13d2002ea 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -2,9 +2,9 @@ queue_rules: - name: default # all required tests need to go here merge_conditions: - - check-success=tests (macos-latest) + - check-success=tests (macos-14) - check-success=tests (ubuntu-24.04) - - check-success=installer_test (macos-latest) + - check-success=installer_test (macos-14) - check-success=installer_test (ubuntu-24.04) - check-success=vm_tests batch_size: 5 diff --git a/doc/manual/source/development/testing.md b/doc/manual/source/development/testing.md index 082863bcc..d582ce4b4 100644 --- a/doc/manual/source/development/testing.md +++ b/doc/manual/source/development/testing.md @@ -297,7 +297,7 @@ Creating a Cachix cache for your installer tests and adding its authorisation to - `armv7l-linux` - `x86_64-darwin` -- The `installer_test` job (which runs on `ubuntu-24.04` and `macos-latest`) will try to install Nix with the cached installer and run a trivial Nix command. +- The `installer_test` job (which runs on `ubuntu-24.04` and `macos-14`) will try to install Nix with the cached installer and run a trivial Nix command. ### One-time setup From 5c968be16288b7ad54b8c6d94cd0566be811ba50 Mon Sep 17 00:00:00 2001 From: Sergei Trofimovich Date: Sun, 29 Dec 2024 16:05:16 +0000 Subject: [PATCH 596/718] m4/gcc_bug_80431.m4: drop unused file As autotools-based build system is gone the file is not used anymore. --- m4/gcc_bug_80431.m4 | 66 --------------------------------------------- 1 file changed, 66 deletions(-) delete mode 100644 m4/gcc_bug_80431.m4 diff --git a/m4/gcc_bug_80431.m4 b/m4/gcc_bug_80431.m4 deleted file mode 100644 index cdc4ddb40..000000000 --- a/m4/gcc_bug_80431.m4 +++ /dev/null @@ -1,66 +0,0 @@ -# Ensure that this bug is not present in the C++ toolchain we are using. -# -# URL for bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80431 -# -# The test program is from that issue, with only a slight modification -# to set an exit status instead of printing strings. -AC_DEFUN([ENSURE_NO_GCC_BUG_80431], -[ - AC_MSG_CHECKING([that GCC bug 80431 is fixed]) - AC_LANG_PUSH(C++) - AC_RUN_IFELSE( - [AC_LANG_PROGRAM( - [[ - #include - - static bool a = true; - static bool b = true; - - struct Options { }; - - struct Option - { - Option(Options * options) - { - a = false; - } - - ~Option() - { - b = false; - } - }; - - struct MyOptions : Options { }; - - struct MyOptions2 : virtual MyOptions - { - Option foo{this}; - }; - ]], - [[ - { - MyOptions2 opts; - } - return (a << 1) | b; - ]])], - [status_80431=0], - [status_80431=$?], - [status_80431='']) - AC_LANG_POP(C++) - AS_CASE([$status_80431], - [''],[ - AC_MSG_RESULT(cannot check because cross compiling) - AC_MSG_NOTICE(assume we are bug free) - ], - [0],[ - AC_MSG_RESULT(yes) - ], - [2],[ - AC_MSG_RESULT(no) - AC_MSG_ERROR(Cannot build Nix with C++ compiler with this bug) - ], - [ - AC_MSG_RESULT(unexpected result $status_80431: not expected failure with bug, ignoring) - ]) -]) From edbfe863ce4ae4b89e554f29807e62674055f251 Mon Sep 17 00:00:00 2001 From: Sergei Trofimovich Date: Sun, 29 Dec 2024 15:54:53 +0000 Subject: [PATCH 597/718] libcmd: update to support lowdown-1.4 API Upstream change https://github.com/kristapsdz/lowdown/commit/bab1d75079ac3866fc14e1fa4825ae64a94a7c0e moved a few fields from `lowdown_opts` toa new `lowdown_opts_term` struct. As a result the build started failing as: nix-cmd> [2/17] Compiling C++ object libnixcmd.so.p/markdown.cc.o nix-cmd> FAILED: libnixcmd.so.p/markdown.cc.o nix-cmd> g++ -Ilibnixcmd.so.p -I. -I.. -I/nix/store/b0bnrk5lacxbpgxgnc28r8q3wcazrgxj-nix-util-2.26.0pre-dev/include/nix -I/nix/store/cxnynq9ykyj4xxv6wf6dw7r0aw5x6n9k-libarchive-3.7.7-dev/include -I/nix/store/bfgjwkcb8snkizx578rzdahi75m8zyh4-nlohmann_json-3.11.3/include -I/nix/store/3sx8bq3sip6j2nv1m5xx4gbdp33v7iy6-nix-store-2.26.0pre-dev/include/nix -I/nix/store/sih2dgqzvsbv7p510lkfmas7s7wbsl4j-nix-fetchers-2.26.0pre-dev/include/nix -I/nix/store/68p8s20fsiiakj7nys7grbaixfnhsdzs-nix-expr-2.26.0pre-dev/include/nix -I/nix/store/gw7wknhzhfzzj9zww2kyi5xrzgf1ndki-boehm-gc-8.2.8-dev/include -I/nix/store/3jwb9j4vnsk5saq3wfyyp9il3mhs41l9-nix-flake-2.26.0pre-dev/include/nix -I/nix/store/8nwjvmq7m48v8g646jrxkikv6x47bc3m-nix-main-2.26.0pre-dev/include/nix -I/nix/store/rb0hzsw5wc1a7daizhpj824mbxlvijrq-lowdown-1.4.0-dev/include -I/nix/store/m388ywpk53fsp8r98brfd7nf1f5sskv0-editline-1.17.1-dev/include -fdiagnostics-color=always -D_GLIBCXX_ASSERTIONS=1 -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -std=c++2a -include config-util.hh -include config-store.hh -include config-expr.hh -include config-main.hh -include config-cmd.hh -Wdeprecated-copy -Werror=suggest-override -Werror=switch -Werror=switch-enum -Werror=unused-result -Wignored-qualifiers -Wimplicit-fallthrough -Wno-deprecated-declarations -O3 -fPIC -pthread -std=c++2a -std=c++2a -std=c++2a -std=c++2a -std=c++2a -std=c++2a -MD -MQ libnixcmd.so.p/markdown.cc.o -MF libnixcmd.so.p/markdown.cc.o.d -o libnixcmd.so.p/markdown.cc.o -c ../markdown.cc nix-cmd> ../markdown.cc: In function 'std::string nix::doRenderMarkdownToTerminal(std::string_view)': nix-cmd> ../markdown.cc:28:5: error: 'lowdown_opts' has no non-static data member named 'cols' nix-cmd> 28 | }; nix-cmd> | ^ The change adds version-based conditional to support both pre-1.4 and 1.4 forms of the initialization. Closes: https://github.com/NixOS/nix/issues/12113 --- src/libcmd/markdown.cc | 20 ++++++++++++++++---- src/libcmd/meson.build | 2 ++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/libcmd/markdown.cc b/src/libcmd/markdown.cc index 6a0d05d9f..4566e6ba6 100644 --- a/src/libcmd/markdown.cc +++ b/src/libcmd/markdown.cc @@ -16,13 +16,25 @@ static std::string doRenderMarkdownToTerminal(std::string_view markdown) { int windowWidth = getWindowSize().second; - struct lowdown_opts opts - { - .type = LOWDOWN_TERM, - .maxdepth = 20, +#if HAVE_LOWDOWN_1_4 + struct lowdown_opts_term opts_term { .cols = (size_t) std::max(windowWidth - 5, 60), .hmargin = 0, .vmargin = 0, + }; +#endif + struct lowdown_opts opts + { + .type = LOWDOWN_TERM, +#if HAVE_LOWDOWN_1_4 + .term = opts_term, +#endif + .maxdepth = 20, +#if !HAVE_LOWDOWN_1_4 + .cols = (size_t) std::max(windowWidth - 5, 60), + .hmargin = 0, + .vmargin = 0, +#endif .feat = LOWDOWN_COMMONMARK | LOWDOWN_FENCED | LOWDOWN_DEFLIST | LOWDOWN_TABLES, .oflags = LOWDOWN_TERM_NOLINK, }; diff --git a/src/libcmd/meson.build b/src/libcmd/meson.build index 222817c81..914db0108 100644 --- a/src/libcmd/meson.build +++ b/src/libcmd/meson.build @@ -36,6 +36,8 @@ deps_public += nlohmann_json lowdown = dependency('lowdown', version : '>= 0.9.0', required : get_option('markdown')) deps_private += lowdown configdata.set('HAVE_LOWDOWN', lowdown.found().to_int()) +# The API changed slightly around terminal initialization. +configdata.set('HAVE_LOWDOWN_1_4', lowdown.version().version_compare('>= 1.4.0').to_int()) readline_flavor = get_option('readline-flavor') if readline_flavor == 'editline' From 1a402e0c53609df25539ae852ca7db6696e6f174 Mon Sep 17 00:00:00 2001 From: Martin Fischer Date: Tue, 31 Dec 2024 13:52:18 +0100 Subject: [PATCH 598/718] test: test eval of newlines with raw output --- tests/functional/eval.nix | 2 +- tests/functional/eval.sh | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/functional/eval.nix b/tests/functional/eval.nix index befbd17a9..cabf28c29 100644 --- a/tests/functional/eval.nix +++ b/tests/functional/eval.nix @@ -1,5 +1,5 @@ { int = 123; - str = "foo"; + str = "foo\nbar"; attr.foo = "bar"; } diff --git a/tests/functional/eval.sh b/tests/functional/eval.sh index 7af49d7fd..18f8589df 100755 --- a/tests/functional/eval.sh +++ b/tests/functional/eval.sh @@ -16,8 +16,8 @@ EOF nix eval --expr 'assert 1 + 2 == 3; true' [[ $(nix eval int -f "./eval.nix") == 123 ]] -[[ $(nix eval str -f "./eval.nix") == '"foo"' ]] -[[ $(nix eval str --raw -f "./eval.nix") == 'foo' ]] +[[ $(nix eval str -f "./eval.nix") == '"foo\nbar"' ]] +[[ $(nix eval str --raw -f "./eval.nix") == $'foo\nbar' ]] [[ "$(nix eval attr -f "./eval.nix")" == '{ foo = "bar"; }' ]] [[ $(nix eval attr --json -f "./eval.nix") == '{"foo":"bar"}' ]] [[ $(nix eval int -f - < "./eval.nix") == 123 ]] @@ -28,7 +28,7 @@ nix eval --expr 'assert 1 + 2 == 3; true' nix-instantiate --eval -E 'assert 1 + 2 == 3; true' [[ $(nix-instantiate -A int --eval "./eval.nix") == 123 ]] -[[ $(nix-instantiate -A str --eval "./eval.nix") == '"foo"' ]] +[[ $(nix-instantiate -A str --eval "./eval.nix") == '"foo\nbar"' ]] [[ "$(nix-instantiate -A attr --eval "./eval.nix")" == '{ foo = "bar"; }' ]] [[ $(nix-instantiate -A attr --eval --json "./eval.nix") == '{"foo":"bar"}' ]] [[ $(nix-instantiate -A int --eval - < "./eval.nix") == 123 ]] From 7a8a28629c61c75af010ff0a5a88c16c4ce536c7 Mon Sep 17 00:00:00 2001 From: Martin Fischer Date: Tue, 31 Dec 2024 14:04:50 +0100 Subject: [PATCH 599/718] feat(nix-instantiate): add --raw flag The experimental `nix eval` command already supports a `--raw` flag. This commit implements the same flag for the stable nix-instantiate command. Until now instructions and scripts that didn't want to rely on experimental features had to use workarounds such as: nix-instantiate --eval | tr -d \" (which also undesirably also removes double quotation marks within the string), or nix-instantiate --eval | jq -j (which undesirably depends on another package). Co-authored-by: Silvan Mosberger --- doc/manual/rl-next/nix-instantiate-raw.md | 8 ++++++++ doc/manual/source/command-ref/nix-copy-closure.md | 2 +- doc/manual/source/command-ref/nix-instantiate.md | 7 ++++++- src/nix-instantiate/nix-instantiate.cc | 10 ++++++++-- tests/functional/eval.sh | 1 + 5 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 doc/manual/rl-next/nix-instantiate-raw.md diff --git a/doc/manual/rl-next/nix-instantiate-raw.md b/doc/manual/rl-next/nix-instantiate-raw.md new file mode 100644 index 000000000..fb4a72b88 --- /dev/null +++ b/doc/manual/rl-next/nix-instantiate-raw.md @@ -0,0 +1,8 @@ +--- +synopsis: "`nix-instantiate --eval` now supports `--raw`" +prs: [12119] +--- + +The `nix-instantiate --eval` command now supports a `--raw` flag, when used +the evaluation result must be a string, which is printed verbatim without +quotation marks or escaping. diff --git a/doc/manual/source/command-ref/nix-copy-closure.md b/doc/manual/source/command-ref/nix-copy-closure.md index 8cfd6ebad..b7e31d93b 100644 --- a/doc/manual/source/command-ref/nix-copy-closure.md +++ b/doc/manual/source/command-ref/nix-copy-closure.md @@ -84,7 +84,7 @@ When using public key authentication, you can avoid typing the passphrase with ` > Copy GNU Hello from a remote machine using a known store path, and run it: > > ```shell-session -> $ storePath="$(nix-instantiate --eval '' -I nixpkgs=channel:nixpkgs-unstable -A hello.outPath | tr -d '"')" +> $ storePath="$(nix-instantiate --eval --raw '' -I nixpkgs=channel:nixpkgs-unstable -A hello.outPath)" > $ nix-copy-closure --from alice@itchy.example.org "$storePath" > $ "$storePath"/bin/hello > Hello, world! diff --git a/doc/manual/source/command-ref/nix-instantiate.md b/doc/manual/source/command-ref/nix-instantiate.md index 6f6fcdc1f..487ef8f10 100644 --- a/doc/manual/source/command-ref/nix-instantiate.md +++ b/doc/manual/source/command-ref/nix-instantiate.md @@ -5,7 +5,7 @@ # Synopsis `nix-instantiate` - [`--parse` | `--eval` [`--strict`] [`--json`] [`--xml`] ] + [`--parse` | `--eval` [`--strict`] [`--raw` | `--json` | `--xml`] ] [`--read-write-mode`] [`--arg` *name* *value*] [{`--attr`| `-A`} *attrPath*] @@ -102,6 +102,11 @@ standard input. > This option can cause non-termination, because lazy data > structures can be infinitely large. +- `--raw` + + When used with `--eval`, the evaluation result must be a string, + which is printed verbatim, without quoting, escaping or trailing newline. + - `--json` When used with `--eval`, print the resulting value as an JSON diff --git a/src/nix-instantiate/nix-instantiate.cc b/src/nix-instantiate/nix-instantiate.cc index c48549511..09d354832 100644 --- a/src/nix-instantiate/nix-instantiate.cc +++ b/src/nix-instantiate/nix-instantiate.cc @@ -24,7 +24,7 @@ static Path gcRoot; static int rootNr = 0; -enum OutputKind { okPlain, okXML, okJSON }; +enum OutputKind { okPlain, okRaw, okXML, okJSON }; void processExpr(EvalState & state, const Strings & attrPaths, bool parseOnly, bool strict, Bindings & autoArgs, @@ -50,7 +50,11 @@ void processExpr(EvalState & state, const Strings & attrPaths, vRes = v; else state.autoCallFunction(autoArgs, v, vRes); - if (output == okXML) + if (output == okRaw) + std::cout << *state.coerceToString(noPos, vRes, context, "while generating the nix-instantiate output"); + // We intentionally don't output a newline here. The default PS1 for Bash in NixOS starts with a newline + // and other interactive shells like Zsh are smart enough to print a missing newline before the prompt. + else if (output == okXML) printValueAsXML(state, strict, location, vRes, std::cout, context, noPos); else if (output == okJSON) { printValueAsJSON(state, strict, vRes, v.determinePos(noPos), std::cout, context); @@ -132,6 +136,8 @@ static int main_nix_instantiate(int argc, char * * argv) gcRoot = getArg(*arg, arg, end); else if (*arg == "--indirect") ; + else if (*arg == "--raw") + outputKind = okRaw; else if (*arg == "--xml") outputKind = okXML; else if (*arg == "--json") diff --git a/tests/functional/eval.sh b/tests/functional/eval.sh index 18f8589df..ed9c214f5 100755 --- a/tests/functional/eval.sh +++ b/tests/functional/eval.sh @@ -29,6 +29,7 @@ nix eval --expr 'assert 1 + 2 == 3; true' nix-instantiate --eval -E 'assert 1 + 2 == 3; true' [[ $(nix-instantiate -A int --eval "./eval.nix") == 123 ]] [[ $(nix-instantiate -A str --eval "./eval.nix") == '"foo\nbar"' ]] +[[ $(nix-instantiate -A str --raw --eval "./eval.nix") == $'foo\nbar' ]] [[ "$(nix-instantiate -A attr --eval "./eval.nix")" == '{ foo = "bar"; }' ]] [[ $(nix-instantiate -A attr --eval --json "./eval.nix") == '{"foo":"bar"}' ]] [[ $(nix-instantiate -A int --eval - < "./eval.nix") == 123 ]] From 5e21bdc623939a5b44f679f1436cb9e9e5d6eef5 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Tue, 31 Dec 2024 17:24:36 +0100 Subject: [PATCH 600/718] .github/ci: Use fixed names This lets us update "runs-on" without creating a mismatch with the required checks that are configured for the repo in the github ui. --- .github/workflows/ci.yml | 28 +++++++++++++++++++++------- .mergify.yml | 8 ++++---- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cd567cd63..6169c0924 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,8 +20,15 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-24.04, macos-14] - runs-on: ${{ matrix.os }} + include: + - scenario: on ubuntu + runs-on: ubuntu-24.04 + os: linux + - scenario: on macos + runs-on: macos-14 + os: darwin + name: tests ${{ matrix.scenario }} + runs-on: ${{ matrix.runs-on }} timeout-minutes: 60 steps: - uses: actions/checkout@v4 @@ -37,7 +44,7 @@ jobs: # Since ubuntu 22.30, unprivileged usernamespaces are no longer allowed to map to the root user: # https://ubuntu.com/blog/ubuntu-23-10-restricted-unprivileged-user-namespaces - run: sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 - if: matrix.os == 'ubuntu-24.04' + if: matrix.os == 'linux' - run: scripts/build-checks - run: scripts/prepare-installer-for-github-actions - name: Upload installer tarball @@ -51,8 +58,15 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-24.04, macos-14] - runs-on: ${{ matrix.os }} + include: + - scenario: on ubuntu + runs-on: ubuntu-24.04 + os: linux + - scenario: on macos + runs-on: macos-14 + os: darwin + name: installer test ${{ matrix.scenario }} + runs-on: ${{ matrix.runs-on }} steps: - uses: actions/checkout@v4 - name: Download installer tarball @@ -68,9 +82,9 @@ jobs: install_url: 'http://localhost:8126/install' install_options: "--tarball-url-prefix http://localhost:8126/" - run: sudo apt install fish zsh - if: matrix.os == 'ubuntu-24.04' + if: matrix.os == 'linux' - run: brew install fish - if: matrix.os == 'macos-14' + if: matrix.os == 'darwin' - run: exec bash -c "nix-instantiate -E 'builtins.currentTime' --eval" - run: exec sh -c "nix-instantiate -E 'builtins.currentTime' --eval" - run: exec zsh -c "nix-instantiate -E 'builtins.currentTime' --eval" diff --git a/.mergify.yml b/.mergify.yml index 13d2002ea..bed17f516 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -2,10 +2,10 @@ queue_rules: - name: default # all required tests need to go here merge_conditions: - - check-success=tests (macos-14) - - check-success=tests (ubuntu-24.04) - - check-success=installer_test (macos-14) - - check-success=installer_test (ubuntu-24.04) + - check-success=tests on macos + - check-success=tests on ubuntu + - check-success=installer_test on macos + - check-success=installer_test on ubuntu - check-success=vm_tests batch_size: 5 From 4a2310a3a09a4e9bde51b003c2a562a4a49cfabf Mon Sep 17 00:00:00 2001 From: Philipp Otterbein Date: Tue, 31 Dec 2024 17:52:06 +0100 Subject: [PATCH 601/718] toJSON: re-throw serialization exception --- src/libexpr/value-to-json.cc | 6 +++++- src/libexpr/value-to-json.hh | 3 +++ tests/functional/lang/eval-fail-toJSON-non-utf-8.err.exp | 8 ++++++++ tests/functional/lang/eval-fail-toJSON-non-utf-8.nix | 1 + 4 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 tests/functional/lang/eval-fail-toJSON-non-utf-8.err.exp create mode 100644 tests/functional/lang/eval-fail-toJSON-non-utf-8.nix diff --git a/src/libexpr/value-to-json.cc b/src/libexpr/value-to-json.cc index 8044fe347..5aa4fe4fd 100644 --- a/src/libexpr/value-to-json.cc +++ b/src/libexpr/value-to-json.cc @@ -108,7 +108,11 @@ json printValueAsJSON(EvalState & state, bool strict, void printValueAsJSON(EvalState & state, bool strict, Value & v, const PosIdx pos, std::ostream & str, NixStringContext & context, bool copyToStore) { - str << printValueAsJSON(state, strict, v, pos, context, copyToStore); + try { + str << printValueAsJSON(state, strict, v, pos, context, copyToStore); + } catch (nlohmann::json::exception & e) { + throw JSONSerializationError("JSON serialization error: %s", e.what()); + } } json ExternalValueBase::printValueAsJSON(EvalState & state, bool strict, diff --git a/src/libexpr/value-to-json.hh b/src/libexpr/value-to-json.hh index 47ac90313..867c4e3a8 100644 --- a/src/libexpr/value-to-json.hh +++ b/src/libexpr/value-to-json.hh @@ -16,4 +16,7 @@ nlohmann::json printValueAsJSON(EvalState & state, bool strict, void printValueAsJSON(EvalState & state, bool strict, Value & v, const PosIdx pos, std::ostream & str, NixStringContext & context, bool copyToStore = true); + +MakeError(JSONSerializationError, Error); + } diff --git a/tests/functional/lang/eval-fail-toJSON-non-utf-8.err.exp b/tests/functional/lang/eval-fail-toJSON-non-utf-8.err.exp new file mode 100644 index 000000000..129d58bcb --- /dev/null +++ b/tests/functional/lang/eval-fail-toJSON-non-utf-8.err.exp @@ -0,0 +1,8 @@ +error: + … while calling the 'toJSON' builtin + at /pwd/lang/eval-fail-toJSON-non-utf-8.nix:1:1: + 1| builtins.toJSON "_invalid UTF-8: _" + | ^ + 2| + + error: JSON serialization error: [json.exception.type_error.316] invalid UTF-8 byte at index 16: 0xFF diff --git a/tests/functional/lang/eval-fail-toJSON-non-utf-8.nix b/tests/functional/lang/eval-fail-toJSON-non-utf-8.nix new file mode 100644 index 000000000..bd1f74de7 --- /dev/null +++ b/tests/functional/lang/eval-fail-toJSON-non-utf-8.nix @@ -0,0 +1 @@ +builtins.toJSON "_invalid UTF-8: _" From 01c96f9fd587912a50e746309580f75e95c56a97 Mon Sep 17 00:00:00 2001 From: Mutsuha Asada Date: Thu, 2 Jan 2025 13:26:13 +0900 Subject: [PATCH 602/718] libmain: fix ignoring empty lines in the print-build-logs option --- src/libmain/progress-bar.cc | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/src/libmain/progress-bar.cc b/src/libmain/progress-bar.cc index fa0b73ebe..961850b58 100644 --- a/src/libmain/progress-bar.cc +++ b/src/libmain/progress-bar.cc @@ -287,23 +287,21 @@ public: else if (type == resBuildLogLine || type == resPostBuildLogLine) { auto lastLine = chomp(getS(fields, 0)); - if (!lastLine.empty()) { - auto i = state->its.find(act); - assert(i != state->its.end()); - ActInfo info = *i->second; - if (printBuildLogs) { - auto suffix = "> "; - if (type == resPostBuildLogLine) { - suffix = " (post)> "; - } - log(*state, lvlInfo, ANSI_FAINT + info.name.value_or("unnamed") + suffix + ANSI_NORMAL + lastLine); - } else { - state->activities.erase(i->second); - info.lastLine = lastLine; - state->activities.emplace_back(info); - i->second = std::prev(state->activities.end()); - update(*state); + auto i = state->its.find(act); + assert(i != state->its.end()); + ActInfo info = *i->second; + if (printBuildLogs) { + auto suffix = "> "; + if (type == resPostBuildLogLine) { + suffix = " (post)> "; } + log(*state, lvlInfo, ANSI_FAINT + info.name.value_or("unnamed") + suffix + ANSI_NORMAL + lastLine); + } else { + state->activities.erase(i->second); + info.lastLine = lastLine; + state->activities.emplace_back(info); + i->second = std::prev(state->activities.end()); + update(*state); } } From 359a0840e26fed25a2e978f6b3035436948430e6 Mon Sep 17 00:00:00 2001 From: Connor Baker Date: Sat, 21 Dec 2024 04:22:27 +0000 Subject: [PATCH 603/718] packaging: use optimization level 3 and LTO by default --- nix-meson-build-support/common/meson.build | 4 ---- packaging/dependencies.nix | 15 +++++++++++++++ src/libcmd/meson.build | 2 -- src/libexpr-c/meson.build | 2 -- src/libexpr-test-support/meson.build | 2 -- src/libexpr-tests/meson.build | 2 -- src/libexpr/meson.build | 2 -- src/libfetchers-tests/meson.build | 2 -- src/libfetchers/meson.build | 2 -- src/libflake-c/meson.build | 2 -- src/libflake-tests/meson.build | 2 -- src/libflake/meson.build | 2 -- src/libmain-c/meson.build | 2 -- src/libmain/meson.build | 2 -- src/libstore-c/meson.build | 2 -- src/libstore-test-support/meson.build | 2 -- src/libstore-tests/meson.build | 2 -- src/libstore/meson.build | 2 -- src/libutil-c/meson.build | 2 -- src/libutil-test-support/meson.build | 2 -- src/libutil-tests/meson.build | 2 -- src/libutil/meson.build | 2 -- src/nix/meson.build | 2 -- tests/functional/meson.build | 2 -- 24 files changed, 15 insertions(+), 48 deletions(-) diff --git a/nix-meson-build-support/common/meson.build b/nix-meson-build-support/common/meson.build index f0322183e..67b6658f5 100644 --- a/nix-meson-build-support/common/meson.build +++ b/nix-meson-build-support/common/meson.build @@ -16,7 +16,3 @@ add_project_arguments( '-Wno-deprecated-declarations', language : 'cpp', ) - -if get_option('buildtype') not in ['debug'] - add_project_arguments('-O3', language : 'cpp') -endif diff --git a/packaging/dependencies.nix b/packaging/dependencies.nix index 2c7cf701f..4bc7495e7 100644 --- a/packaging/dependencies.nix +++ b/packaging/dependencies.nix @@ -66,6 +66,21 @@ let mesonLayer = finalAttrs: prevAttrs: { + # NOTE: + # As of https://github.com/NixOS/nixpkgs/blob/8baf8241cea0c7b30e0b8ae73474cb3de83c1a30/pkgs/by-name/me/meson/setup-hook.sh#L26, + # `mesonBuildType` defaults to `plain` if not specified. We want our Nix-built binaries to be optimized by default. + # More on build types here: https://mesonbuild.com/Builtin-options.html#details-for-buildtype. + mesonBuildType = "release"; + # NOTE: + # Users who are debugging Nix builds are expected to set the environment variable `mesonBuildType`, per the + # guidance in https://github.com/NixOS/nix/blob/8a3fc27f1b63a08ac983ee46435a56cf49ebaf4a/doc/manual/source/development/debugging.md?plain=1#L10. + # For this reason, we don't want to refer to `finalAttrs.mesonBuildType` here, but rather use the environment variable. + preConfigure = prevAttrs.preConfigure or "" + '' + case "$mesonBuildType" in + release|minsize) appendToVar mesonFlags "-Db_lto=true" ;; + *) appendToVar mesonFlags "-Db_lto=false" ;; + esac + ''; nativeBuildInputs = [ pkgs.buildPackages.meson pkgs.buildPackages.ninja diff --git a/src/libcmd/meson.build b/src/libcmd/meson.build index 914db0108..4145f408a 100644 --- a/src/libcmd/meson.build +++ b/src/libcmd/meson.build @@ -4,8 +4,6 @@ project('nix-cmd', 'cpp', 'cpp_std=c++2a', # TODO(Qyriad): increase the warning level 'warning_level=1', - 'debug=true', - 'optimization=2', 'errorlogs=true', # Please print logs for tests that fail ], meson_version : '>= 1.1', diff --git a/src/libexpr-c/meson.build b/src/libexpr-c/meson.build index 1556dae51..9487132cf 100644 --- a/src/libexpr-c/meson.build +++ b/src/libexpr-c/meson.build @@ -4,8 +4,6 @@ project('nix-expr-c', 'cpp', 'cpp_std=c++2a', # TODO(Qyriad): increase the warning level 'warning_level=1', - 'debug=true', - 'optimization=2', 'errorlogs=true', # Please print logs for tests that fail ], meson_version : '>= 1.1', diff --git a/src/libexpr-test-support/meson.build b/src/libexpr-test-support/meson.build index 64d4fe218..56e814cd1 100644 --- a/src/libexpr-test-support/meson.build +++ b/src/libexpr-test-support/meson.build @@ -4,8 +4,6 @@ project('nix-expr-test-support', 'cpp', 'cpp_std=c++2a', # TODO(Qyriad): increase the warning level 'warning_level=1', - 'debug=true', - 'optimization=2', 'errorlogs=true', # Please print logs for tests that fail ], meson_version : '>= 1.1', diff --git a/src/libexpr-tests/meson.build b/src/libexpr-tests/meson.build index f37e85e57..667a0d7b7 100644 --- a/src/libexpr-tests/meson.build +++ b/src/libexpr-tests/meson.build @@ -4,8 +4,6 @@ project('nix-expr-tests', 'cpp', 'cpp_std=c++2a', # TODO(Qyriad): increase the warning level 'warning_level=1', - 'debug=true', - 'optimization=2', 'errorlogs=true', # Please print logs for tests that fail ], meson_version : '>= 1.1', diff --git a/src/libexpr/meson.build b/src/libexpr/meson.build index b3c559ba7..b33aebc86 100644 --- a/src/libexpr/meson.build +++ b/src/libexpr/meson.build @@ -4,8 +4,6 @@ project('nix-expr', 'cpp', 'cpp_std=c++2a', # TODO(Qyriad): increase the warning level 'warning_level=1', - 'debug=true', - 'optimization=2', 'errorlogs=true', # Please print logs for tests that fail ], meson_version : '>= 1.1', diff --git a/src/libfetchers-tests/meson.build b/src/libfetchers-tests/meson.build index 3e82c6111..739435501 100644 --- a/src/libfetchers-tests/meson.build +++ b/src/libfetchers-tests/meson.build @@ -4,8 +4,6 @@ project('nix-fetchers-tests', 'cpp', 'cpp_std=c++2a', # TODO(Qyriad): increase the warning level 'warning_level=1', - 'debug=true', - 'optimization=2', 'errorlogs=true', # Please print logs for tests that fail ], meson_version : '>= 1.1', diff --git a/src/libfetchers/meson.build b/src/libfetchers/meson.build index b4408e943..58afbb7d0 100644 --- a/src/libfetchers/meson.build +++ b/src/libfetchers/meson.build @@ -4,8 +4,6 @@ project('nix-fetchers', 'cpp', 'cpp_std=c++2a', # TODO(Qyriad): increase the warning level 'warning_level=1', - 'debug=true', - 'optimization=2', 'errorlogs=true', # Please print logs for tests that fail ], meson_version : '>= 1.1', diff --git a/src/libflake-c/meson.build b/src/libflake-c/meson.build index b7669fe97..85d20644d 100644 --- a/src/libflake-c/meson.build +++ b/src/libflake-c/meson.build @@ -4,8 +4,6 @@ project('nix-flake-c', 'cpp', 'cpp_std=c++2a', # TODO(Qyriad): increase the warning level 'warning_level=1', - 'debug=true', - 'optimization=2', 'errorlogs=true', # Please print logs for tests that fail ], meson_version : '>= 1.1', diff --git a/src/libflake-tests/meson.build b/src/libflake-tests/meson.build index 5c3c58e53..1c8765f21 100644 --- a/src/libflake-tests/meson.build +++ b/src/libflake-tests/meson.build @@ -4,8 +4,6 @@ project('nix-flake-tests', 'cpp', 'cpp_std=c++2a', # TODO(Qyriad): increase the warning level 'warning_level=1', - 'debug=true', - 'optimization=2', 'errorlogs=true', # Please print logs for tests that fail ], meson_version : '>= 1.1', diff --git a/src/libflake/meson.build b/src/libflake/meson.build index f9e217729..b757d0d76 100644 --- a/src/libflake/meson.build +++ b/src/libflake/meson.build @@ -4,8 +4,6 @@ project('nix-flake', 'cpp', 'cpp_std=c++2a', # TODO(Qyriad): increase the warning level 'warning_level=1', - 'debug=true', - 'optimization=2', 'errorlogs=true', # Please print logs for tests that fail ], meson_version : '>= 1.1', diff --git a/src/libmain-c/meson.build b/src/libmain-c/meson.build index 5a5684b8d..d875d2c3f 100644 --- a/src/libmain-c/meson.build +++ b/src/libmain-c/meson.build @@ -4,8 +4,6 @@ project('nix-main-c', 'cpp', 'cpp_std=c++2a', # TODO(Qyriad): increase the warning level 'warning_level=1', - 'debug=true', - 'optimization=2', 'errorlogs=true', # Please print logs for tests that fail ], meson_version : '>= 1.1', diff --git a/src/libmain/meson.build b/src/libmain/meson.build index 87fc8b8d2..00f945f49 100644 --- a/src/libmain/meson.build +++ b/src/libmain/meson.build @@ -4,8 +4,6 @@ project('nix-main', 'cpp', 'cpp_std=c++2a', # TODO(Qyriad): increase the warning level 'warning_level=1', - 'debug=true', - 'optimization=2', 'errorlogs=true', # Please print logs for tests that fail ], meson_version : '>= 1.1', diff --git a/src/libstore-c/meson.build b/src/libstore-c/meson.build index 1ac331ad0..17d18609f 100644 --- a/src/libstore-c/meson.build +++ b/src/libstore-c/meson.build @@ -4,8 +4,6 @@ project('nix-store-c', 'cpp', 'cpp_std=c++2a', # TODO(Qyriad): increase the warning level 'warning_level=1', - 'debug=true', - 'optimization=2', 'errorlogs=true', # Please print logs for tests that fail ], meson_version : '>= 1.1', diff --git a/src/libstore-test-support/meson.build b/src/libstore-test-support/meson.build index 2a07e56ac..59d649889 100644 --- a/src/libstore-test-support/meson.build +++ b/src/libstore-test-support/meson.build @@ -4,8 +4,6 @@ project('nix-store-test-support', 'cpp', 'cpp_std=c++2a', # TODO(Qyriad): increase the warning level 'warning_level=1', - 'debug=true', - 'optimization=2', 'errorlogs=true', # Please print logs for tests that fail ], meson_version : '>= 1.1', diff --git a/src/libstore-tests/meson.build b/src/libstore-tests/meson.build index b706fa12c..3ba0795e9 100644 --- a/src/libstore-tests/meson.build +++ b/src/libstore-tests/meson.build @@ -4,8 +4,6 @@ project('nix-store-tests', 'cpp', 'cpp_std=c++2a', # TODO(Qyriad): increase the warning level 'warning_level=1', - 'debug=true', - 'optimization=2', 'errorlogs=true', # Please print logs for tests that fail ], meson_version : '>= 1.1', diff --git a/src/libstore/meson.build b/src/libstore/meson.build index 12a0e6376..79d912497 100644 --- a/src/libstore/meson.build +++ b/src/libstore/meson.build @@ -4,8 +4,6 @@ project('nix-store', 'cpp', 'cpp_std=c++2a', # TODO(Qyriad): increase the warning level 'warning_level=1', - 'debug=true', - 'optimization=2', 'errorlogs=true', # Please print logs for tests that fail 'localstatedir=/nix/var', ], diff --git a/src/libutil-c/meson.build b/src/libutil-c/meson.build index 44cec1afc..ac1297665 100644 --- a/src/libutil-c/meson.build +++ b/src/libutil-c/meson.build @@ -4,8 +4,6 @@ project('nix-util-c', 'cpp', 'cpp_std=c++2a', # TODO(Qyriad): increase the warning level 'warning_level=1', - 'debug=true', - 'optimization=2', 'errorlogs=true', # Please print logs for tests that fail ], meson_version : '>= 1.1', diff --git a/src/libutil-test-support/meson.build b/src/libutil-test-support/meson.build index 03ae63f1a..db944cf06 100644 --- a/src/libutil-test-support/meson.build +++ b/src/libutil-test-support/meson.build @@ -4,8 +4,6 @@ project('nix-util-test-support', 'cpp', 'cpp_std=c++2a', # TODO(Qyriad): increase the warning level 'warning_level=1', - 'debug=true', - 'optimization=2', 'errorlogs=true', # Please print logs for tests that fail ], meson_version : '>= 1.1', diff --git a/src/libutil-tests/meson.build b/src/libutil-tests/meson.build index 83ac79e92..ad2c61711 100644 --- a/src/libutil-tests/meson.build +++ b/src/libutil-tests/meson.build @@ -4,8 +4,6 @@ project('nix-util-tests', 'cpp', 'cpp_std=c++2a', # TODO(Qyriad): increase the warning level 'warning_level=1', - 'debug=true', - 'optimization=2', 'errorlogs=true', # Please print logs for tests that fail ], meson_version : '>= 1.1', diff --git a/src/libutil/meson.build b/src/libutil/meson.build index 2c3e3a954..ac701d8fd 100644 --- a/src/libutil/meson.build +++ b/src/libutil/meson.build @@ -4,8 +4,6 @@ project('nix-util', 'cpp', 'cpp_std=c++2a', # TODO(Qyriad): increase the warning level 'warning_level=1', - 'debug=true', - 'optimization=2', 'errorlogs=true', # Please print logs for tests that fail ], meson_version : '>= 1.1', diff --git a/src/nix/meson.build b/src/nix/meson.build index 1d4840b12..2698cc873 100644 --- a/src/nix/meson.build +++ b/src/nix/meson.build @@ -4,8 +4,6 @@ project('nix', 'cpp', 'cpp_std=c++2a', # TODO(Qyriad): increase the warning level 'warning_level=1', - 'debug=true', - 'optimization=2', 'errorlogs=true', # Please print logs for tests that fail 'localstatedir=/nix/var', ], diff --git a/tests/functional/meson.build b/tests/functional/meson.build index 933595cd5..83e08c4f5 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -4,8 +4,6 @@ project('nix-functional-tests', 'cpp_std=c++2a', # TODO(Qyriad): increase the warning level 'warning_level=1', - 'debug=true', - 'optimization=2', 'errorlogs=true', # Please print logs for tests that fail ], meson_version : '>= 1.3', From a44e9dd1ea664a9616d7dabb548095bb3f375f7e Mon Sep 17 00:00:00 2001 From: Philipp Otterbein Date: Sat, 4 Jan 2025 16:14:06 +0100 Subject: [PATCH 604/718] correctly parse strings with null bytes and throw error --- src/libexpr/eval.cc | 8 ++++-- src/libexpr/lexer.l | 25 +++++++++++------- src/libexpr/value.hh | 2 +- .../lang/eval-fail-string-nul-1.err.exp | Bin 0 -> 209 bytes .../lang/eval-fail-string-nul-1.nix | Bin 0 -> 10 bytes .../lang/eval-fail-string-nul-2.err.exp | Bin 0 -> 256 bytes .../lang/eval-fail-string-nul-2.nix | Bin 0 -> 22 bytes 7 files changed, 22 insertions(+), 13 deletions(-) create mode 100644 tests/functional/lang/eval-fail-string-nul-1.err.exp create mode 100644 tests/functional/lang/eval-fail-string-nul-1.nix create mode 100644 tests/functional/lang/eval-fail-string-nul-2.err.exp create mode 100644 tests/functional/lang/eval-fail-string-nul-2.nix diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index fe5f05ab8..21dd5a294 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -3185,12 +3185,16 @@ std::ostream & operator << (std::ostream & str, const ExternalValueBase & v) { return v.print(str); } -void forceNoNullByte(std::string_view s) +void forceNoNullByte(std::string_view s, std::function pos) { if (s.find('\0') != s.npos) { using namespace std::string_view_literals; auto str = replaceStrings(std::string(s), "\0"sv, "␀"sv); - throw Error("input string '%s' cannot be represented as Nix string because it contains null bytes", str); + Error error("input string '%s' cannot be represented as Nix string because it contains null bytes", str); + if (pos) { + error.atPos(pos()); + } + throw error; } } diff --git a/src/libexpr/lexer.l b/src/libexpr/lexer.l index a7e44cb72..067f86e01 100644 --- a/src/libexpr/lexer.l +++ b/src/libexpr/lexer.l @@ -41,16 +41,18 @@ namespace nix { // we make use of the fact that the parser receives a private copy of the input // string and can munge around in it. -static StringToken unescapeStr(SymbolTable & symbols, char * s, size_t length) +// getting the position is expensive and thus it is implemented lazily. +static StringToken unescapeStr(char * const s, size_t length, std::function && pos) { - char * result = s; + bool noNullByte = true; char * t = s; - char c; // the input string is terminated with *two* NULs, so we can safely take // *one* character after the one being checked against. - while ((c = *s++)) { + for (size_t i = 0; i < length; t++) { + char c = s[i++]; + noNullByte &= c != '\0'; if (c == '\\') { - c = *s++; + c = s[i++]; if (c == 'n') *t = '\n'; else if (c == 'r') *t = '\r'; else if (c == 't') *t = '\t'; @@ -59,12 +61,14 @@ static StringToken unescapeStr(SymbolTable & symbols, char * s, size_t length) else if (c == '\r') { /* Normalise CR and CR/LF into LF. */ *t = '\n'; - if (*s == '\n') s++; /* cr/lf */ + if (s[i] == '\n') i++; /* cr/lf */ } else *t = c; - t++; } - return {result, size_t(t - result)}; + if (!noNullByte) { + forceNoNullByte({s, size_t(t - s)}, std::move(pos)); + } + return {s, size_t(t - s)}; } static void requireExperimentalFeature(const ExperimentalFeature & feature, const Pos & pos) @@ -175,7 +179,7 @@ or { return OR_KW; } /* It is impossible to match strings ending with '$' with one regex because trailing contexts are only valid at the end of a rule. (A sane but undocumented limitation.) */ - yylval->str = unescapeStr(state->symbols, yytext, yyleng); + yylval->str = unescapeStr(yytext, yyleng, [&]() { return state->positions[CUR_POS]; }); return STR; } \$\{ { PUSH_STATE(DEFAULT); return DOLLAR_CURLY; } @@ -191,6 +195,7 @@ or { return OR_KW; } \'\'(\ *\n)? { PUSH_STATE(IND_STRING); return IND_STRING_OPEN; } ([^\$\']|\$[^\{\']|\'[^\'\$])+ { yylval->str = {yytext, (size_t) yyleng, true}; + forceNoNullByte(yylval->str, [&]() { return state->positions[CUR_POS]; }); return IND_STR; } \'\'\$ | @@ -203,7 +208,7 @@ or { return OR_KW; } return IND_STR; } \'\'\\{ANY} { - yylval->str = unescapeStr(state->symbols, yytext + 2, yyleng - 2); + yylval->str = unescapeStr(yytext + 2, yyleng - 2, [&]() { return state->positions[CUR_POS]; }); return IND_STR; } \$\{ { PUSH_STATE(DEFAULT); return DOLLAR_CURLY; } diff --git a/src/libexpr/value.hh b/src/libexpr/value.hh index 88fcae986..8925693e3 100644 --- a/src/libexpr/value.hh +++ b/src/libexpr/value.hh @@ -510,6 +510,6 @@ typedef std::shared_ptr RootValue; RootValue allocRootValue(Value * v); -void forceNoNullByte(std::string_view s); +void forceNoNullByte(std::string_view s, std::function = nullptr); } diff --git a/tests/functional/lang/eval-fail-string-nul-1.err.exp b/tests/functional/lang/eval-fail-string-nul-1.err.exp new file mode 100644 index 0000000000000000000000000000000000000000..2dfbea0635c8c2ea159249879c4d89523c2a7366 GIT binary patch literal 209 zcmY+8F%E+;6hk|63X6p)MKIDq_H+{VbbPipj#u zG%KVo2L&^b4`$yq8*iGc_{BE1wMXaQY*v)pqs#WEJOx;R`^jn7;s?AsKQI6Q literal 0 HcmV?d00001 diff --git a/tests/functional/lang/eval-fail-string-nul-1.nix b/tests/functional/lang/eval-fail-string-nul-1.nix new file mode 100644 index 0000000000000000000000000000000000000000..3689409171139a7d310eac52df0be4315b6ba786 GIT binary patch literal 10 RcmY#N%g<*>N-R?10ss()0>}UW literal 0 HcmV?d00001 diff --git a/tests/functional/lang/eval-fail-string-nul-2.err.exp b/tests/functional/lang/eval-fail-string-nul-2.err.exp new file mode 100644 index 0000000000000000000000000000000000000000..b1cae5325d90a2c05f7304db89bca0826c2f98f0 GIT binary patch literal 256 zcmY+9K?=e!5Jg>kioeS$meySk;Sq#MJ1v1QDM_joy6^~|(UaIJK{~rX^XBtE#~7l4 zlX1#OIXW4jfIfsH%Di9CzpxaGP-sacWLQSzF>+$b+<_7t7IF*eHqEjgb_F(Y!F5NS IH|lWw0QY`GT>t<8 literal 0 HcmV?d00001 diff --git a/tests/functional/lang/eval-fail-string-nul-2.nix b/tests/functional/lang/eval-fail-string-nul-2.nix new file mode 100644 index 0000000000000000000000000000000000000000..fd6b3258a5e414e6e4812113aed4ece422aa76bc GIT binary patch literal 22 acmY#a=TcBe%g+ar3_zTeSj45S&IJH2l>`U? literal 0 HcmV?d00001 From 98d75de1ea00b31cdff9a22e881ac01be5ac2ae9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sun, 5 Jan 2025 19:02:28 +0000 Subject: [PATCH 605/718] windows: fix conditional compilation variable --- src/libstore/windows/pathlocks.cc | 2 +- src/libutil/windows/environment-variables.cc | 2 +- src/libutil/windows/file-descriptor.cc | 2 +- src/libutil/windows/file-system.cc | 2 +- src/libutil/windows/muxable-pipe.cc | 2 +- src/libutil/windows/os-string.cc | 2 +- src/libutil/windows/processes.cc | 2 +- src/libutil/windows/users.cc | 2 +- src/libutil/windows/windows-async-pipe.cc | 2 +- src/libutil/windows/windows-async-pipe.hh | 2 +- src/libutil/windows/windows-error.cc | 2 +- src/libutil/windows/windows-error.hh | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/libstore/windows/pathlocks.cc b/src/libstore/windows/pathlocks.cc index 197f5a1c4..29a98d8e2 100644 --- a/src/libstore/windows/pathlocks.cc +++ b/src/libstore/windows/pathlocks.cc @@ -3,7 +3,7 @@ #include "signals.hh" #include "util.hh" -#ifdef WIN32 +#ifdef _WIN32 # include # include # include diff --git a/src/libutil/windows/environment-variables.cc b/src/libutil/windows/environment-variables.cc index 308a432e4..d1093597c 100644 --- a/src/libutil/windows/environment-variables.cc +++ b/src/libutil/windows/environment-variables.cc @@ -1,6 +1,6 @@ #include "environment-variables.hh" -#ifdef WIN32 +#ifdef _WIN32 # include "processenv.h" namespace nix { diff --git a/src/libutil/windows/file-descriptor.cc b/src/libutil/windows/file-descriptor.cc index 71f53ccb8..e2a473a7c 100644 --- a/src/libutil/windows/file-descriptor.cc +++ b/src/libutil/windows/file-descriptor.cc @@ -5,7 +5,7 @@ #include "windows-error.hh" #include "file-path.hh" -#ifdef WIN32 +#ifdef _WIN32 #include #include #include diff --git a/src/libutil/windows/file-system.cc b/src/libutil/windows/file-system.cc index 53271cef3..7ed1c04a6 100644 --- a/src/libutil/windows/file-system.cc +++ b/src/libutil/windows/file-system.cc @@ -1,6 +1,6 @@ #include "file-system.hh" -#ifdef WIN32 +#ifdef _WIN32 namespace nix { Descriptor openDirectory(const std::filesystem::path & path) diff --git a/src/libutil/windows/muxable-pipe.cc b/src/libutil/windows/muxable-pipe.cc index af7e987e9..ac2882120 100644 --- a/src/libutil/windows/muxable-pipe.cc +++ b/src/libutil/windows/muxable-pipe.cc @@ -1,4 +1,4 @@ -#ifdef WIN32 +#ifdef _WIN32 # include # include "windows-error.hh" diff --git a/src/libutil/windows/os-string.cc b/src/libutil/windows/os-string.cc index 26ad9cba0..b09ef8b90 100644 --- a/src/libutil/windows/os-string.cc +++ b/src/libutil/windows/os-string.cc @@ -7,7 +7,7 @@ #include "file-path-impl.hh" #include "util.hh" -#ifdef WIN32 +#ifdef _WIN32 namespace nix { diff --git a/src/libutil/windows/processes.cc b/src/libutil/windows/processes.cc index e69f1ed45..fd4d7c43a 100644 --- a/src/libutil/windows/processes.cc +++ b/src/libutil/windows/processes.cc @@ -23,7 +23,7 @@ #include #include -#ifdef WIN32 +#ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include diff --git a/src/libutil/windows/users.cc b/src/libutil/windows/users.cc index 2780e45f4..438c4221c 100644 --- a/src/libutil/windows/users.cc +++ b/src/libutil/windows/users.cc @@ -4,7 +4,7 @@ #include "file-system.hh" #include "windows-error.hh" -#ifdef WIN32 +#ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include diff --git a/src/libutil/windows/windows-async-pipe.cc b/src/libutil/windows/windows-async-pipe.cc index 13b563510..4e139d5cf 100644 --- a/src/libutil/windows/windows-async-pipe.cc +++ b/src/libutil/windows/windows-async-pipe.cc @@ -1,7 +1,7 @@ #include "windows-async-pipe.hh" #include "windows-error.hh" -#ifdef WIN32 +#ifdef _WIN32 namespace nix::windows { diff --git a/src/libutil/windows/windows-async-pipe.hh b/src/libutil/windows/windows-async-pipe.hh index 277336ed7..53715e260 100644 --- a/src/libutil/windows/windows-async-pipe.hh +++ b/src/libutil/windows/windows-async-pipe.hh @@ -2,7 +2,7 @@ ///@file #include "file-descriptor.hh" -#ifdef WIN32 +#ifdef _WIN32 namespace nix::windows { diff --git a/src/libutil/windows/windows-error.cc b/src/libutil/windows/windows-error.cc index 4cf4274da..b92f9155f 100644 --- a/src/libutil/windows/windows-error.cc +++ b/src/libutil/windows/windows-error.cc @@ -1,6 +1,6 @@ #include "windows-error.hh" -#ifdef WIN32 +#ifdef _WIN32 #include #define WIN32_LEAN_AND_MEAN #include diff --git a/src/libutil/windows/windows-error.hh b/src/libutil/windows/windows-error.hh index 4e48ee859..66c67b43a 100644 --- a/src/libutil/windows/windows-error.hh +++ b/src/libutil/windows/windows-error.hh @@ -1,7 +1,7 @@ #pragma once ///@file -#ifdef WIN32 +#ifdef _WIN32 #include #include "error.hh" From 1eba904b7994985996f6ee1571ef70c6e9a91ef3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sun, 5 Jan 2025 19:14:29 +0000 Subject: [PATCH 606/718] nix/flake: fix build on windows --- src/nix/flake.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 55aa8971e..7189689cc 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -938,7 +938,7 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand } continue; } else - createSymlink(target, to2); + createSymlink(target, os_string_to_string(PathViewNG { to2 })); } else throw Error("file '%s' has unsupported type", from2); From 438a20427f40e8ec458444fb156e984f8137ec13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Mon, 6 Jan 2025 22:53:39 +0100 Subject: [PATCH 607/718] mergify: fix installer test name --- .mergify.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.mergify.yml b/.mergify.yml index bed17f516..5d2bf8520 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -4,8 +4,8 @@ queue_rules: merge_conditions: - check-success=tests on macos - check-success=tests on ubuntu - - check-success=installer_test on macos - - check-success=installer_test on ubuntu + - check-success=installer test on macos + - check-success=installer test on ubuntu - check-success=vm_tests batch_size: 5 From 69853c067c74e9421cfa41e48bf8af04266206d3 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Fri, 13 Dec 2024 18:37:25 +0100 Subject: [PATCH 608/718] Add makeParentCanonical() --- src/libutil/file-system.cc | 15 +++++++++++++++ src/libutil/file-system.hh | 17 +++++++++++++++++ src/libutil/posix-source-accessor.hh | 12 ++++++++++++ 3 files changed, 44 insertions(+) diff --git a/src/libutil/file-system.cc b/src/libutil/file-system.cc index 793eb2d9f..923220fd0 100644 --- a/src/libutil/file-system.cc +++ b/src/libutil/file-system.cc @@ -766,4 +766,19 @@ bool isExecutableFileAmbient(const fs::path & exe) { ) == 0; } +std::filesystem::path makeParentCanonical(const std::filesystem::path & rawPath) +{ + std::filesystem::path path(absPath(rawPath));; + try { + auto parent = path.parent_path(); + if (parent == path) { + // `path` is a root directory => trivially canonical + return parent; + } + return std::filesystem::canonical(parent) / path.filename(); + } catch (fs::filesystem_error & e) { + throw SysError("canonicalising parent path of '%1%'", path); + } } + +} // namespace nix diff --git a/src/libutil/file-system.hh b/src/libutil/file-system.hh index 3c49181a0..7fdaba811 100644 --- a/src/libutil/file-system.hh +++ b/src/libutil/file-system.hh @@ -143,6 +143,23 @@ inline bool symlink_exists(const std::filesystem::path & path) { } // namespace fs +/** + * Canonicalize a path except for the last component. + * + * This is useful for getting the canonical location of a symlink. + * + * Consider the case where `foo/l` is a symlink. `canonical("foo/l")` will + * resolve the symlink `l` to its target. + * `makeParentCanonical("foo/l")` will not resolve the symlink `l` to its target, + * but does ensure that the returned parent part of the path, `foo` is resolved + * to `canonical("foo")`, and can therefore be retrieved without traversing any + * symlinks. + * + * If a relative path is passed, it will be made absolute, so that the parent + * can always be canonicalized. + */ +std::filesystem::path makeParentCanonical(const std::filesystem::path & path); + /** * A version of pathExists that returns false on a permission error. * Useful for inferring default paths across directories that might not diff --git a/src/libutil/posix-source-accessor.hh b/src/libutil/posix-source-accessor.hh index 40f60bb54..d60abdd9a 100644 --- a/src/libutil/posix-source-accessor.hh +++ b/src/libutil/posix-source-accessor.hh @@ -50,6 +50,18 @@ struct PosixSourceAccessor : virtual SourceAccessor * possible, (e.g. on Windows it could scoped to a drive like * `C:\`). This allows more `..` parent accessing to work. * + * @note When `path` is trusted user input, canonicalize it using + * `std::filesystem::canonical`, `makeParentCanonical`, `std::filesystem::weakly_canonical`, etc, + * as appropriate for the use case. At least weak canonicalization is + * required for the `SourcePath` to do anything useful at the location it + * points to. + * + * @note A canonicalizing behavior is not built in `createAtRoot` so that + * callers do not accidentally introduce symlink-related security vulnerabilities. + * Furthermore, `createAtRoot` does not know whether the file pointed to by + * `path` should be resolved if it is itself a symlink. In other words, + * `createAtRoot` can not decide between aforementioned `canonical`, `makeParentCanonical`, etc. for its callers. + * * See * [`std::filesystem::path::root_path`](https://en.cppreference.com/w/cpp/filesystem/path/root_path) * and From 36563c69a48a47d8b58340f22d82d542f6b9f025 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Fri, 13 Dec 2024 17:21:56 +0100 Subject: [PATCH 609/718] fix: Handle symlinks and FIFOs in `nix hash` where possible Fixes https://github.com/NixOS/nix/issues/11756 Fixes https://github.com/NixOS/nix/issues/11681 --- src/libutil/posix-source-accessor.hh | 2 +- src/nix/hash.cc | 23 ++++++++++++++++++++--- tests/functional/hash-path.sh | 24 ++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/libutil/posix-source-accessor.hh b/src/libutil/posix-source-accessor.hh index d60abdd9a..5d491e633 100644 --- a/src/libutil/posix-source-accessor.hh +++ b/src/libutil/posix-source-accessor.hh @@ -43,7 +43,7 @@ struct PosixSourceAccessor : virtual SourceAccessor std::optional getPhysicalPath(const CanonPath & path) override; /** - * Create a `PosixSourceAccessor` and `CanonPath` corresponding to + * Create a `PosixSourceAccessor` and `SourcePath` corresponding to * some native path. * * The `PosixSourceAccessor` is rooted as far up the tree as diff --git a/src/nix/hash.cc b/src/nix/hash.cc index 416cd19b3..eac421d12 100644 --- a/src/nix/hash.cc +++ b/src/nix/hash.cc @@ -87,18 +87,35 @@ struct CmdHashBase : Command return std::make_unique(hashAlgo); }; - auto path2 = PosixSourceAccessor::createAtRoot(path); + auto makeSourcePath = [&]() -> SourcePath { + return PosixSourceAccessor::createAtRoot(makeParentCanonical(path)); + }; + Hash h { HashAlgorithm::SHA256 }; // throwaway def to appease C++ switch (mode) { case FileIngestionMethod::Flat: + { + // While usually we could use the some code as for NixArchive, + // the Flat method needs to support FIFOs, such as those + // produced by bash process substitution, e.g.: + // nix hash --mode flat <(echo hi) + // Also symlinks semantics are unambiguous in the flat case, + // so we don't need to go low-level, or reject symlink `path`s. + auto hashSink = makeSink(); + readFile(path, *hashSink); + h = hashSink->finish().first; + break; + } case FileIngestionMethod::NixArchive: { + auto sourcePath = makeSourcePath(); auto hashSink = makeSink(); - dumpPath(path2, *hashSink, (FileSerialisationMethod) mode); + dumpPath(sourcePath, *hashSink, (FileSerialisationMethod) mode); h = hashSink->finish().first; break; } case FileIngestionMethod::Git: { + auto sourcePath = makeSourcePath(); std::function hook; hook = [&](const SourcePath & path) -> git::TreeEntry { auto hashSink = makeSink(); @@ -109,7 +126,7 @@ struct CmdHashBase : Command .hash = hash, }; }; - h = hook(path2).hash; + h = hook(sourcePath).hash; break; } } diff --git a/tests/functional/hash-path.sh b/tests/functional/hash-path.sh index 86d782a95..74e319504 100755 --- a/tests/functional/hash-path.sh +++ b/tests/functional/hash-path.sh @@ -92,3 +92,27 @@ try2 md5 "20f3ffe011d4cfa7d72bfabef7882836" rm "$TEST_ROOT/hash-path/hello" ln -s x "$TEST_ROOT/hash-path/hello" try2 md5 "f78b733a68f5edbdf9413899339eaa4a" + +# Flat mode supports process substitution +h=$(nix hash path --mode flat --type sha256 --base32 <(printf "SMASH THE STATE")) +[[ 0d9n3r2i4m1zgy0wpqbsyabsfzgs952066bfp8gwvcg4mkr4r5g8 == "$h" ]] + +# Flat mode supports process substitution (hash file) +h=$(nix hash file --type sha256 --base32 <(printf "SMASH THE STATE")) +[[ 0d9n3r2i4m1zgy0wpqbsyabsfzgs952066bfp8gwvcg4mkr4r5g8 == "$h" ]] + +# Symlinks in the ancestry are ok and don't affect the result +mkdir -p "$TEST_ROOT/simple" "$TEST_ROOT/try/to/mess/with/it" +echo hi > "$TEST_ROOT/simple/hi" +ln -s "$TEST_ROOT/simple" "$TEST_ROOT/try/to/mess/with/it/simple-link" +h=$(nix hash path --type sha256 --base32 "$TEST_ROOT/simple/hi") +[[ 1xmr8jicvzszfzpz46g37mlpvbzjl2wpwvl2b05psipssyp1sm8h == "$h" ]] +h=$(nix hash path --type sha256 --base32 "$TEST_ROOT/try/to/mess/with/it/simple-link/hi") +[[ 1xmr8jicvzszfzpz46g37mlpvbzjl2wpwvl2b05psipssyp1sm8h == "$h" ]] + +# nix hash --mode nar does not canonicalize a symlink argument. +# Otherwise it can't generate a NAR whose root is a symlink. +# If you want to follow the symlink, pass $(realpath -s ...) instead. +ln -s /non-existent-48cujwe8ndf4as0bne "$TEST_ROOT/symlink-to-nowhere" +h=$(nix hash path --mode nar --type sha256 --base32 "$TEST_ROOT/symlink-to-nowhere") +[[ 1bl5ry3x1fcbwgr5c2x50bn572iixh4j1p6ax5isxly2ddgn8pbp == "$h" ]] # manually verified hash From 91e91f62fa2187f49073851f9a3dbff740092859 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Fri, 13 Dec 2024 18:38:47 +0100 Subject: [PATCH 610/718] doc: Document `nix-store --add-fixed` symlink behavior Tested with nix run nix/2.3-maintenance#nix-store -- --add some_symlink nix run nix/2.3-maintenance#nix-store -- --add-fixed sha256 --recursive some_symlink --- doc/manual/source/command-ref/nix-store/add-fixed.md | 3 +++ doc/manual/source/command-ref/nix-store/add.md | 3 +++ 2 files changed, 6 insertions(+) diff --git a/doc/manual/source/command-ref/nix-store/add-fixed.md b/doc/manual/source/command-ref/nix-store/add-fixed.md index bebf15026..2ea90a135 100644 --- a/doc/manual/source/command-ref/nix-store/add-fixed.md +++ b/doc/manual/source/command-ref/nix-store/add-fixed.md @@ -21,6 +21,9 @@ This operation has the following options: Use recursive instead of flat hashing mode, used when adding directories to the store. + *paths* that refer to symlinks are not dereferenced, but added to the store + as symlinks with the same target. + {{#include ./opt-common.md}} {{#include ../opt-common.md}} diff --git a/doc/manual/source/command-ref/nix-store/add.md b/doc/manual/source/command-ref/nix-store/add.md index 87d504cd3..ab4740723 100644 --- a/doc/manual/source/command-ref/nix-store/add.md +++ b/doc/manual/source/command-ref/nix-store/add.md @@ -11,6 +11,9 @@ The operation `--add` adds the specified paths to the Nix store. It prints the resulting paths in the Nix store on standard output. +*paths* that refer to symlinks are not dereferenced, but added to the store +as symlinks with the same target. + {{#include ./opt-common.md}} {{#include ../opt-common.md}} From c0b64f3377b37c036c574b731c3aeffb3fddc614 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Fri, 13 Dec 2024 18:46:47 +0100 Subject: [PATCH 611/718] refactor: Don't re-construct SourcePath unnecessarily --- src/nix-store/nix-store.cc | 8 ++++---- src/nix/add-to-store.cc | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc index b731b25af..659a237f9 100644 --- a/src/nix-store/nix-store.cc +++ b/src/nix-store/nix-store.cc @@ -183,9 +183,9 @@ static void opAdd(Strings opFlags, Strings opArgs) if (!opFlags.empty()) throw UsageError("unknown flag"); for (auto & i : opArgs) { - auto [accessor, canonPath] = PosixSourceAccessor::createAtRoot(i); + auto sourcePath = PosixSourceAccessor::createAtRoot(i); cout << fmt("%s\n", store->printStorePath(store->addToStore( - std::string(baseNameOf(i)), {accessor, canonPath}))); + std::string(baseNameOf(i)), sourcePath))); } } @@ -207,10 +207,10 @@ static void opAddFixed(Strings opFlags, Strings opArgs) opArgs.pop_front(); for (auto & i : opArgs) { - auto [accessor, canonPath] = PosixSourceAccessor::createAtRoot(i); + auto sourcePath = PosixSourceAccessor::createAtRoot(i); std::cout << fmt("%s\n", store->printStorePath(store->addToStoreSlow( baseNameOf(i), - {accessor, canonPath}, + sourcePath, method, hashAlgo).path)); } diff --git a/src/nix/add-to-store.cc b/src/nix/add-to-store.cc index 5c08f7616..45563cb2b 100644 --- a/src/nix/add-to-store.cc +++ b/src/nix/add-to-store.cc @@ -37,13 +37,13 @@ struct CmdAddToStore : MixDryRun, StoreCommand { if (!namePart) namePart = baseNameOf(path); - auto [accessor, path2] = PosixSourceAccessor::createAtRoot(path); + auto sourcePath = PosixSourceAccessor::createAtRoot(path); auto storePath = dryRun ? store->computeStorePath( - *namePart, {accessor, path2}, caMethod, hashAlgo, {}).first + *namePart, sourcePath, caMethod, hashAlgo, {}).first : store->addToStoreSlow( - *namePart, {accessor, path2}, caMethod, hashAlgo, {}).path; + *namePart, sourcePath, caMethod, hashAlgo, {}).path; logger->cout("%s", store->printStorePath(storePath)); } From ddbbf537676441ff5c09bd64310fec0f2619a820 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Fri, 13 Dec 2024 18:54:36 +0100 Subject: [PATCH 612/718] fix: Resolve CLI parent symlinks before adding to store Fixes https://github.com/NixOS/nix/issues/11941 --- src/nix-store/nix-store.cc | 4 ++-- src/nix/add-to-store.cc | 2 +- tests/functional/add.sh | 41 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc index 659a237f9..99bb2c726 100644 --- a/src/nix-store/nix-store.cc +++ b/src/nix-store/nix-store.cc @@ -183,7 +183,7 @@ static void opAdd(Strings opFlags, Strings opArgs) if (!opFlags.empty()) throw UsageError("unknown flag"); for (auto & i : opArgs) { - auto sourcePath = PosixSourceAccessor::createAtRoot(i); + auto sourcePath = PosixSourceAccessor::createAtRoot(makeParentCanonical(i)); cout << fmt("%s\n", store->printStorePath(store->addToStore( std::string(baseNameOf(i)), sourcePath))); } @@ -207,7 +207,7 @@ static void opAddFixed(Strings opFlags, Strings opArgs) opArgs.pop_front(); for (auto & i : opArgs) { - auto sourcePath = PosixSourceAccessor::createAtRoot(i); + auto sourcePath = PosixSourceAccessor::createAtRoot(makeParentCanonical(i)); std::cout << fmt("%s\n", store->printStorePath(store->addToStoreSlow( baseNameOf(i), sourcePath, diff --git a/src/nix/add-to-store.cc b/src/nix/add-to-store.cc index 45563cb2b..7f15de374 100644 --- a/src/nix/add-to-store.cc +++ b/src/nix/add-to-store.cc @@ -37,7 +37,7 @@ struct CmdAddToStore : MixDryRun, StoreCommand { if (!namePart) namePart = baseNameOf(path); - auto sourcePath = PosixSourceAccessor::createAtRoot(path); + auto sourcePath = PosixSourceAccessor::createAtRoot(makeParentCanonical(path)); auto storePath = dryRun ? store->computeStorePath( diff --git a/tests/functional/add.sh b/tests/functional/add.sh index 3b37ee7d4..0e6868d8f 100755 --- a/tests/functional/add.sh +++ b/tests/functional/add.sh @@ -29,6 +29,47 @@ echo "$hash2" test "$hash1" = "sha256:$hash2" +# The contents can be accessed through a symlink, and this symlink has no effect on the hash +# https://github.com/NixOS/nix/issues/11941 +test_issue_11941() { + local expected actual + mkdir -p "$TEST_ROOT/foo/bar" && ln -s "$TEST_ROOT/foo" "$TEST_ROOT/foo-link" + + # legacy + expected=$(nix-store --add-fixed --recursive sha256 "$TEST_ROOT/foo/bar") + actual=$(nix-store --add-fixed --recursive sha256 "$TEST_ROOT/foo-link/bar") + [[ "$expected" == "$actual" ]] + actual=$(nix-store --add "$TEST_ROOT/foo-link/bar") + [[ "$expected" == "$actual" ]] + + # nix store add + actual=$(nix store add --hash-algo sha256 --mode nar "$TEST_ROOT/foo/bar") + [[ "$expected" == "$actual" ]] + + # cleanup + rm -r "$TEST_ROOT/foo" "$TEST_ROOT/foo-link" +} +test_issue_11941 + +# A symlink is added to the store as a symlink, not as a copy of the target +test_add_symlink() { + ln -s /bin "$TEST_ROOT/my-bin" + + # legacy + path=$(nix-store --add-fixed --recursive sha256 "$TEST_ROOT/my-bin") + [[ "$(readlink "$path")" == /bin ]] + path=$(nix-store --add "$TEST_ROOT/my-bin") + [[ "$(readlink "$path")" == /bin ]] + + # nix store add + path=$(nix store add --hash-algo sha256 --mode nar "$TEST_ROOT/my-bin") + [[ "$(readlink "$path")" == /bin ]] + + # cleanup + rm "$TEST_ROOT/my-bin" +} +test_add_symlink + #### New style commands clearStoreIfPossible From 628c11d237dc38bf4e35c498d418026c215de5cf Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 16 Dec 2024 09:53:36 +0100 Subject: [PATCH 613/718] test: Add hydraJobs.tests.functional_symlinked-home --- tests/nixos/default.nix | 2 ++ tests/nixos/functional/symlinked-home.nix | 36 +++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 tests/nixos/functional/symlinked-home.nix diff --git a/tests/nixos/default.nix b/tests/nixos/default.nix index a9a438a32..8e0cb1b22 100644 --- a/tests/nixos/default.nix +++ b/tests/nixos/default.nix @@ -159,6 +159,8 @@ in functional_root = runNixOSTestFor "x86_64-linux" ./functional/as-root.nix; + functional_symlinked-home = runNixOSTestFor "x86_64-linux" ./functional/symlinked-home.nix; + user-sandboxing = runNixOSTestFor "x86_64-linux" ./user-sandboxing; s3-binary-cache-store = runNixOSTestFor "x86_64-linux" ./s3-binary-cache-store.nix; diff --git a/tests/nixos/functional/symlinked-home.nix b/tests/nixos/functional/symlinked-home.nix new file mode 100644 index 000000000..57c45d5d5 --- /dev/null +++ b/tests/nixos/functional/symlinked-home.nix @@ -0,0 +1,36 @@ +/** + This test runs the functional tests on a NixOS system where the home directory + is symlinked to another location. + + The purpose of this test is to find cases where Nix uses low-level operations + that don't support symlinks on paths that include them. + + It is not a substitute for more intricate, use case-specific tests, but helps + catch common issues. +*/ +# TODO: add symlinked tmpdir +{ ... }: +{ + name = "functional-tests-on-nixos_user_symlinked-home"; + + imports = [ ./common.nix ]; + + nodes.machine = { + users.users.alice = { isNormalUser = true; }; + }; + + testScript = '' + machine.wait_for_unit("multi-user.target") + with subtest("prepare symlinked home"): + machine.succeed(""" + ( + set -x + mv /home/alice /home/alice.real + ln -s alice.real /home/alice + ) 1>&2 + """) + machine.succeed(""" + su --login --command "run-test-suite" alice >&2 + """) + ''; +} From 5a5a86949a2fca18f61d1117ab29cc87281c48d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sun, 15 Dec 2024 19:03:14 +0100 Subject: [PATCH 614/718] makeParentCanonical: test case where parent is empty --- src/libutil-tests/file-system.cc | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/libutil-tests/file-system.cc b/src/libutil-tests/file-system.cc index 7ef804f34..2c10d4869 100644 --- a/src/libutil-tests/file-system.cc +++ b/src/libutil-tests/file-system.cc @@ -261,4 +261,18 @@ TEST(pathExists, bogusPathDoesNotExist) { ASSERT_FALSE(pathExists("/schnitzel/darmstadt/pommes")); } + +/* ---------------------------------------------------------------------------- + * makeParentCanonical + * --------------------------------------------------------------------------*/ + +TEST(makeParentCanonical, noParent) +{ + ASSERT_EQ(makeParentCanonical("file"), absPath(std::filesystem::path("file"))); +} + +TEST(makeParentCanonical, root) +{ + ASSERT_EQ(makeParentCanonical("/"), "/"); +} } From 4c74d679b6b4db9eccea94afc285176871253967 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 23 Dec 2024 16:55:27 +0100 Subject: [PATCH 615/718] test: Avoid regressing accidental use of weakly_canonical instead of makeParentCanonical I'd messed up a rebase in my previous iteration, causing `weakly_canonical` to reappear, but not trigger a test failure. These two functions behave similarly when the argument is a path that points to a broken symlink. `weakly_canonical` would not resolve it because the target doesn't exist, and `makeParentCanonical` would not resolve it, because it never resolves the final path element. This new test case now also tests a valid symlink, "differentiating" the two. --- tests/functional/hash-path.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/functional/hash-path.sh b/tests/functional/hash-path.sh index 74e319504..4894ae391 100755 --- a/tests/functional/hash-path.sh +++ b/tests/functional/hash-path.sh @@ -116,3 +116,8 @@ h=$(nix hash path --type sha256 --base32 "$TEST_ROOT/try/to/mess/with/it/simple- ln -s /non-existent-48cujwe8ndf4as0bne "$TEST_ROOT/symlink-to-nowhere" h=$(nix hash path --mode nar --type sha256 --base32 "$TEST_ROOT/symlink-to-nowhere") [[ 1bl5ry3x1fcbwgr5c2x50bn572iixh4j1p6ax5isxly2ddgn8pbp == "$h" ]] # manually verified hash +if [[ -e /bin ]]; then + ln -s /bin "$TEST_ROOT/symlink-to-bin" + h=$(nix hash path --mode nar --type sha256 --base32 "$TEST_ROOT/symlink-to-bin") + [[ 0z2mdmkd43l0ijdxfbj1y8vzli15yh9b09n3a3rrygmjshbyypsw == "$h" ]] # manually verified hash +fi From 75cda2da7fbd6283f88cf0fd0b934e1047ca1408 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 7 Jan 2025 13:40:18 +0100 Subject: [PATCH 616/718] Document path values in inputs Co-authored-by: Robert Hensing --- src/nix/flake.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/nix/flake.md b/src/nix/flake.md index a55bba4fc..5bb18328d 100644 --- a/src/nix/flake.md +++ b/src/nix/flake.md @@ -212,6 +212,13 @@ Currently the `type` attribute can be one of the following: root of a tree can use `path:./foo` to access the flake in subdirectory `foo`, but `path:../bar` is illegal. +Path inputs can be specified with path values in `flake.nix`. Path values are a syntax for `path` inputs, and they are converted by +1. resolving them into relative paths, relative to the base directory of `flake.nix` +2. escaping URL characters (refer to IETF RFC?) +3. prepending `path:` + +Note that the allowed syntax for path values in flake `inputs` may be more restrictive than general Nix, so you may need to use `path:` if your path contains certain special characters. See [Path literals](@docroot@/language/syntax#path-literal) + Note that if you omit `path:`, relative paths must start with `.` to avoid ambiguity with registry lookups (e.g. `nixpkgs` is a registry lookup; `./nixpkgs` is a relative path). From e8c7dd9971aaac0ac14e08f299a41ef0a93afef7 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 7 Jan 2025 13:43:56 +0100 Subject: [PATCH 617/718] Rename allowRelative -> preserveRelativePaths --- src/libflake/flake/flakeref.cc | 12 ++++++------ src/libflake/flake/flakeref.hh | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/libflake/flake/flakeref.cc b/src/libflake/flake/flakeref.cc index 3a43a51f8..06198b10c 100644 --- a/src/libflake/flake/flakeref.cc +++ b/src/libflake/flake/flakeref.cc @@ -49,9 +49,9 @@ FlakeRef parseFlakeRef( const std::optional & baseDir, bool allowMissing, bool isFlake, - bool allowRelative) + bool preserveRelativePaths) { - auto [flakeRef, fragment] = parseFlakeRefWithFragment(fetchSettings, url, baseDir, allowMissing, isFlake, allowRelative); + auto [flakeRef, fragment] = parseFlakeRefWithFragment(fetchSettings, url, baseDir, allowMissing, isFlake, preserveRelativePaths); if (fragment != "") throw Error("unexpected fragment '%s' in flake reference '%s'", fragment, url); return flakeRef; @@ -89,7 +89,7 @@ std::pair parsePathFlakeRefWithFragment( const std::optional & baseDir, bool allowMissing, bool isFlake, - bool allowRelative) + bool preserveRelativePaths) { std::string path = url; std::string fragment = ""; @@ -191,7 +191,7 @@ std::pair parsePathFlakeRefWithFragment( } } else { - if (!allowRelative && !hasPrefix(path, "/")) + if (!preserveRelativePaths && !hasPrefix(path, "/")) throw BadURL("flake reference '%s' is not an absolute path", url); } @@ -258,7 +258,7 @@ std::pair parseFlakeRefWithFragment( const std::optional & baseDir, bool allowMissing, bool isFlake, - bool allowRelative) + bool preserveRelativePaths) { using namespace fetchers; @@ -267,7 +267,7 @@ std::pair parseFlakeRefWithFragment( } else if (auto res = parseURLFlakeRef(fetchSettings, url, baseDir, isFlake)) { return *res; } else { - return parsePathFlakeRefWithFragment(fetchSettings, url, baseDir, allowMissing, isFlake, allowRelative); + return parsePathFlakeRefWithFragment(fetchSettings, url, baseDir, allowMissing, isFlake, preserveRelativePaths); } } diff --git a/src/libflake/flake/flakeref.hh b/src/libflake/flake/flakeref.hh index 32094d381..c9cf7952d 100644 --- a/src/libflake/flake/flakeref.hh +++ b/src/libflake/flake/flakeref.hh @@ -85,7 +85,7 @@ FlakeRef parseFlakeRef( const std::optional & baseDir = {}, bool allowMissing = false, bool isFlake = true, - bool allowRelative = false); + bool preserveRelativePaths = false); /** * @param baseDir Optional [base directory](https://nixos.org/manual/nix/unstable/glossary#gloss-base-directory) @@ -104,7 +104,7 @@ std::pair parseFlakeRefWithFragment( const std::optional & baseDir = {}, bool allowMissing = false, bool isFlake = true, - bool allowRelative = false); + bool preserveRelativePaths = false); /** * @param baseDir Optional [base directory](https://nixos.org/manual/nix/unstable/glossary#gloss-base-directory) From 0792152627a94dbb2fbbbd8f0f05ff36a480dabf Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 7 Jan 2025 13:54:19 +0100 Subject: [PATCH 618/718] Rename Override -> OverrideTarget --- src/libflake/flake/flake.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libflake/flake/flake.cc b/src/libflake/flake/flake.cc index e9fa28f06..4f0b922ab 100644 --- a/src/libflake/flake/flake.cc +++ b/src/libflake/flake/flake.cc @@ -408,14 +408,14 @@ LockedFlake lockFlake( debug("old lock file: %s", oldLockFile); - struct Override + struct OverrideTarget { FlakeInput input; SourcePath sourcePath; std::optional parentInputPath; // FIXME: rename to inputPathPrefix? }; - std::map overrides; + std::map overrides; std::set explicitCliOverrides; std::set overridesUsed, updatesUsed; std::map, SourcePath> nodePaths; @@ -423,7 +423,7 @@ LockedFlake lockFlake( for (auto & i : lockFlags.inputOverrides) { overrides.emplace( i.first, - Override { + OverrideTarget { .input = FlakeInput { .ref = i.second }, /* Note: any relative overrides (e.g. `--override-input B/C "path:./foo/bar"`) @@ -474,7 +474,7 @@ LockedFlake lockFlake( inputPath.push_back(id); inputPath.push_back(idOverride); overrides.emplace(inputPath, - Override { + OverrideTarget { .input = inputOverride, .sourcePath = sourcePath, .parentInputPath = inputPathPrefix From ef2739b7c9071149fb9333865bd3cc2ab60f2178 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 7 Jan 2025 14:01:49 +0100 Subject: [PATCH 619/718] Example of referencing parent directories --- src/nix/flake.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/nix/flake.md b/src/nix/flake.md index 5bb18328d..35ac3ea9b 100644 --- a/src/nix/flake.md +++ b/src/nix/flake.md @@ -210,7 +210,9 @@ Currently the `type` attribute can be one of the following: the directory containing that `flake.nix`. However, the resolved path must be in the same tree. For instance, a `flake.nix` in the root of a tree can use `path:./foo` to access the flake in - subdirectory `foo`, but `path:../bar` is illegal. + subdirectory `foo`, but `path:../bar` is illegal. On the other + hand, a flake in the `/foo` directory of a tree can use + `path:../bar` to refer to the flake in `/bar`. Path inputs can be specified with path values in `flake.nix`. Path values are a syntax for `path` inputs, and they are converted by 1. resolving them into relative paths, relative to the base directory of `flake.nix` From f705ce7f9a95bc37df236d88eef1dbd9e2ae5f31 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 7 Jan 2025 14:45:58 +0100 Subject: [PATCH 620/718] ParsedURL: Remove url field This prevents a 'url' field that is out of sync with the other fields. You can use to_string() to get the full URL. --- src/libfetchers/fetchers.cc | 2 +- src/libfetchers/github.cc | 16 ++++++++-------- src/libfetchers/indirect.cc | 8 ++++---- src/libfetchers/path.cc | 6 +++--- src/libflake/flake/flakeref.cc | 2 -- src/libutil-tests/url.cc | 22 ---------------------- src/libutil/url.cc | 7 ++++++- src/libutil/url.hh | 5 +++-- 8 files changed, 25 insertions(+), 43 deletions(-) diff --git a/src/libfetchers/fetchers.cc b/src/libfetchers/fetchers.cc index b105c252a..87bf0dd71 100644 --- a/src/libfetchers/fetchers.cc +++ b/src/libfetchers/fetchers.cc @@ -66,7 +66,7 @@ Input Input::fromURL( } } - throw Error("input '%s' is unsupported", url.url); + throw Error("input '%s' is unsupported", url); } Input Input::fromAttrs(const Settings & settings, Attrs && attrs) diff --git a/src/libfetchers/github.cc b/src/libfetchers/github.cc index 308cff33a..185941988 100644 --- a/src/libfetchers/github.cc +++ b/src/libfetchers/github.cc @@ -50,7 +50,7 @@ struct GitArchiveInputScheme : InputScheme else if (std::regex_match(path[2], refRegex)) ref = path[2]; else - throw BadURL("in URL '%s', '%s' is not a commit hash or branch/tag name", url.url, path[2]); + throw BadURL("in URL '%s', '%s' is not a commit hash or branch/tag name", url, path[2]); } else if (size > 3) { std::string rs; for (auto i = std::next(path.begin(), 2); i != path.end(); i++) { @@ -63,34 +63,34 @@ struct GitArchiveInputScheme : InputScheme if (std::regex_match(rs, refRegex)) { ref = rs; } else { - throw BadURL("in URL '%s', '%s' is not a branch/tag name", url.url, rs); + throw BadURL("in URL '%s', '%s' is not a branch/tag name", url, rs); } } else if (size < 2) - throw BadURL("URL '%s' is invalid", url.url); + throw BadURL("URL '%s' is invalid", url); for (auto &[name, value] : url.query) { if (name == "rev") { if (rev) - throw BadURL("URL '%s' contains multiple commit hashes", url.url); + throw BadURL("URL '%s' contains multiple commit hashes", url); rev = Hash::parseAny(value, HashAlgorithm::SHA1); } else if (name == "ref") { if (!std::regex_match(value, refRegex)) - throw BadURL("URL '%s' contains an invalid branch/tag name", url.url); + throw BadURL("URL '%s' contains an invalid branch/tag name", url); if (ref) - throw BadURL("URL '%s' contains multiple branch/tag names", url.url); + throw BadURL("URL '%s' contains multiple branch/tag names", url); ref = value; } else if (name == "host") { if (!std::regex_match(value, hostRegex)) - throw BadURL("URL '%s' contains an invalid instance host", url.url); + throw BadURL("URL '%s' contains an invalid instance host", url); host_url = value; } // FIXME: barf on unsupported attributes } if (ref && rev) - throw BadURL("URL '%s' contains both a commit hash and a branch/tag name %s %s", url.url, *ref, rev->gitRev()); + throw BadURL("URL '%s' contains both a commit hash and a branch/tag name %s %s", url, *ref, rev->gitRev()); Input input{settings}; input.attrs.insert_or_assign("type", std::string { schemeName() }); diff --git a/src/libfetchers/indirect.cc b/src/libfetchers/indirect.cc index 2e5cd82c7..0e1b86711 100644 --- a/src/libfetchers/indirect.cc +++ b/src/libfetchers/indirect.cc @@ -26,16 +26,16 @@ struct IndirectInputScheme : InputScheme else if (std::regex_match(path[1], refRegex)) ref = path[1]; else - throw BadURL("in flake URL '%s', '%s' is not a commit hash or branch/tag name", url.url, path[1]); + throw BadURL("in flake URL '%s', '%s' is not a commit hash or branch/tag name", url, path[1]); } else if (path.size() == 3) { if (!std::regex_match(path[1], refRegex)) - throw BadURL("in flake URL '%s', '%s' is not a branch/tag name", url.url, path[1]); + throw BadURL("in flake URL '%s', '%s' is not a branch/tag name", url, path[1]); ref = path[1]; if (!std::regex_match(path[2], revRegex)) - throw BadURL("in flake URL '%s', '%s' is not a commit hash", url.url, path[2]); + throw BadURL("in flake URL '%s', '%s' is not a commit hash", url, path[2]); rev = Hash::parseAny(path[2], HashAlgorithm::SHA1); } else - throw BadURL("GitHub URL '%s' is invalid", url.url); + throw BadURL("GitHub URL '%s' is invalid", url); std::string id = path[0]; if (!std::regex_match(id, flakeRegex)) diff --git a/src/libfetchers/path.cc b/src/libfetchers/path.cc index 246b68c3a..f628e042c 100644 --- a/src/libfetchers/path.cc +++ b/src/libfetchers/path.cc @@ -14,7 +14,7 @@ struct PathInputScheme : InputScheme if (url.scheme != "path") return {}; if (url.authority && *url.authority != "") - throw Error("path URL '%s' should not have an authority ('%s')", url.url, *url.authority); + throw Error("path URL '%s' should not have an authority ('%s')", url, *url.authority); Input input{settings}; input.attrs.insert_or_assign("type", "path"); @@ -27,10 +27,10 @@ struct PathInputScheme : InputScheme if (auto n = string2Int(value)) input.attrs.insert_or_assign(name, *n); else - throw Error("path URL '%s' has invalid parameter '%s'", url.to_string(), name); + throw Error("path URL '%s' has invalid parameter '%s'", url, name); } else - throw Error("path URL '%s' has unsupported parameter '%s'", url.to_string(), name); + throw Error("path URL '%s' has unsupported parameter '%s'", url, name); return input; } diff --git a/src/libflake/flake/flakeref.cc b/src/libflake/flake/flakeref.cc index ab882fdab..957495795 100644 --- a/src/libflake/flake/flakeref.cc +++ b/src/libflake/flake/flakeref.cc @@ -162,7 +162,6 @@ std::pair parsePathFlakeRefWithFragment( auto base = std::string("git+file://") + flakeRoot; auto parsedURL = ParsedURL{ - .url = base, // FIXME .base = base, .scheme = "git+file", .authority = "", @@ -220,7 +219,6 @@ static std::optional> parseFlakeIdRef( if (std::regex_match(url, match, flakeRegex)) { auto parsedURL = ParsedURL{ - .url = url, .base = "flake:" + match.str(1), .scheme = "flake", .authority = "", diff --git a/src/libutil-tests/url.cc b/src/libutil-tests/url.cc index 7d08f467e..6ffae4f3e 100644 --- a/src/libutil-tests/url.cc +++ b/src/libutil-tests/url.cc @@ -20,23 +20,11 @@ namespace nix { } - std::ostream& operator<<(std::ostream& os, const ParsedURL& p) { - return os << "\n" - << "url: " << p.url << "\n" - << "base: " << p.base << "\n" - << "scheme: " << p.scheme << "\n" - << "authority: " << p.authority.value() << "\n" - << "path: " << p.path << "\n" - << "query: " << print_map(p.query) << "\n" - << "fragment: " << p.fragment << "\n"; - } - TEST(parseURL, parsesSimpleHttpUrl) { auto s = "http://www.example.org/file.tar.gz"; auto parsed = parseURL(s); ParsedURL expected { - .url = "http://www.example.org/file.tar.gz", .base = "http://www.example.org/file.tar.gz", .scheme = "http", .authority = "www.example.org", @@ -53,7 +41,6 @@ namespace nix { auto parsed = parseURL(s); ParsedURL expected { - .url = "https://www.example.org/file.tar.gz", .base = "https://www.example.org/file.tar.gz", .scheme = "https", .authority = "www.example.org", @@ -70,7 +57,6 @@ namespace nix { auto parsed = parseURL(s); ParsedURL expected { - .url = "https://www.example.org/file.tar.gz", .base = "https://www.example.org/file.tar.gz", .scheme = "https", .authority = "www.example.org", @@ -87,7 +73,6 @@ namespace nix { auto parsed = parseURL(s); ParsedURL expected { - .url = "http://www.example.org/file.tar.gz", .base = "http://www.example.org/file.tar.gz", .scheme = "http", .authority = "www.example.org", @@ -104,7 +89,6 @@ namespace nix { auto parsed = parseURL(s); ParsedURL expected { - .url = "file+https://www.example.org/video.mp4", .base = "https://www.example.org/video.mp4", .scheme = "file+https", .authority = "www.example.org", @@ -126,7 +110,6 @@ namespace nix { auto parsed = parseURL(s); ParsedURL expected { - .url = "http://127.0.0.1:8080/file.tar.gz", .base = "https://127.0.0.1:8080/file.tar.gz", .scheme = "http", .authority = "127.0.0.1:8080", @@ -143,7 +126,6 @@ namespace nix { auto parsed = parseURL(s); ParsedURL expected { - .url = "http://[fe80::818c:da4d:8975:415c\%enp0s25]:8080", .base = "http://[fe80::818c:da4d:8975:415c\%enp0s25]:8080", .scheme = "http", .authority = "[fe80::818c:da4d:8975:415c\%enp0s25]:8080", @@ -161,7 +143,6 @@ namespace nix { auto parsed = parseURL(s); ParsedURL expected { - .url = "http://[2a02:8071:8192:c100:311d:192d:81ac:11ea]:8080", .base = "http://[2a02:8071:8192:c100:311d:192d:81ac:11ea]:8080", .scheme = "http", .authority = "[2a02:8071:8192:c100:311d:192d:81ac:11ea]:8080", @@ -185,7 +166,6 @@ namespace nix { auto parsed = parseURL(s); ParsedURL expected { - .url = "http://user:pass@www.example.org/file.tar.gz", .base = "http://user:pass@www.example.org/file.tar.gz", .scheme = "http", .authority = "user:pass@www.example.org:8080", @@ -203,7 +183,6 @@ namespace nix { auto parsed = parseURL(s); ParsedURL expected { - .url = "", .base = "", .scheme = "file", .authority = "", @@ -228,7 +207,6 @@ namespace nix { auto parsed = parseURL(s); ParsedURL expected { - .url = "ftp://ftp.nixos.org/downloads/nixos.iso", .base = "ftp://ftp.nixos.org/downloads/nixos.iso", .scheme = "ftp", .authority = "ftp.nixos.org", diff --git a/src/libutil/url.cc b/src/libutil/url.cc index 63b9734ee..86ca035b9 100644 --- a/src/libutil/url.cc +++ b/src/libutil/url.cc @@ -40,7 +40,6 @@ ParsedURL parseURL(const std::string & url) path = "/"; return ParsedURL{ - .url = url, .base = base, .scheme = scheme, .authority = authority, @@ -136,6 +135,12 @@ std::string ParsedURL::to_string() const + (fragment.empty() ? "" : "#" + percentEncode(fragment)); } +std::ostream & operator << (std::ostream & os, const ParsedURL & url) +{ + os << url.to_string(); + return os; +} + bool ParsedURL::operator ==(const ParsedURL & other) const noexcept { return diff --git a/src/libutil/url.hh b/src/libutil/url.hh index 738ee9f82..d85001185 100644 --- a/src/libutil/url.hh +++ b/src/libutil/url.hh @@ -7,9 +7,8 @@ namespace nix { struct ParsedURL { - std::string url; /// URL without query/fragment - std::string base; + std::string base; // FIXME: remove std::string scheme; std::optional authority; std::string path; @@ -26,6 +25,8 @@ struct ParsedURL ParsedURL canonicalise(); }; +std::ostream & operator << (std::ostream & os, const ParsedURL & url); + MakeError(BadURL, Error); std::string percentDecode(std::string_view in); From 4077aa43a803db33108ce39e799089608707dcbb Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 7 Jan 2025 14:52:00 +0100 Subject: [PATCH 621/718] ParsedURL: Remove base field --- src/libfetchers/git.cc | 2 +- src/libfetchers/mercurial.cc | 2 +- src/libflake/flake/flakeref.cc | 4 ---- src/libutil-tests/url.cc | 11 ----------- src/libutil/url.cc | 1 - src/libutil/url.hh | 2 -- 6 files changed, 2 insertions(+), 20 deletions(-) diff --git a/src/libfetchers/git.cc b/src/libfetchers/git.cc index c73f53765..d894550c0 100644 --- a/src/libfetchers/git.cc +++ b/src/libfetchers/git.cc @@ -426,7 +426,7 @@ struct GitInputScheme : InputScheme auto url = parseURL(getStrAttr(input.attrs, "url")); bool isBareRepository = url.scheme == "file" && !pathExists(url.path + "/.git"); repoInfo.isLocal = url.scheme == "file" && !forceHttp && !isBareRepository; - repoInfo.url = repoInfo.isLocal ? url.path : url.base; + repoInfo.url = repoInfo.isLocal ? url.path : url.to_string(); // If this is a local directory and no ref or revision is // given, then allow the use of an unclean working tree. diff --git a/src/libfetchers/mercurial.cc b/src/libfetchers/mercurial.cc index 2c987f79d..c2fd8139c 100644 --- a/src/libfetchers/mercurial.cc +++ b/src/libfetchers/mercurial.cc @@ -161,7 +161,7 @@ struct MercurialInputScheme : InputScheme { auto url = parseURL(getStrAttr(input.attrs, "url")); bool isLocal = url.scheme == "file"; - return {isLocal, isLocal ? url.path : url.base}; + return {isLocal, isLocal ? url.path : url.to_string()}; } StorePath fetchToStore(ref store, Input & input) const diff --git a/src/libflake/flake/flakeref.cc b/src/libflake/flake/flakeref.cc index 957495795..60efe1612 100644 --- a/src/libflake/flake/flakeref.cc +++ b/src/libflake/flake/flakeref.cc @@ -159,10 +159,7 @@ std::pair parsePathFlakeRefWithFragment( while (flakeRoot != "/") { if (pathExists(flakeRoot + "/.git")) { - auto base = std::string("git+file://") + flakeRoot; - auto parsedURL = ParsedURL{ - .base = base, .scheme = "git+file", .authority = "", .path = flakeRoot, @@ -219,7 +216,6 @@ static std::optional> parseFlakeIdRef( if (std::regex_match(url, match, flakeRegex)) { auto parsedURL = ParsedURL{ - .base = "flake:" + match.str(1), .scheme = "flake", .authority = "", .path = match[1], diff --git a/src/libutil-tests/url.cc b/src/libutil-tests/url.cc index 6ffae4f3e..7e1d2aa15 100644 --- a/src/libutil-tests/url.cc +++ b/src/libutil-tests/url.cc @@ -25,7 +25,6 @@ namespace nix { auto parsed = parseURL(s); ParsedURL expected { - .base = "http://www.example.org/file.tar.gz", .scheme = "http", .authority = "www.example.org", .path = "/file.tar.gz", @@ -41,7 +40,6 @@ namespace nix { auto parsed = parseURL(s); ParsedURL expected { - .base = "https://www.example.org/file.tar.gz", .scheme = "https", .authority = "www.example.org", .path = "/file.tar.gz", @@ -57,7 +55,6 @@ namespace nix { auto parsed = parseURL(s); ParsedURL expected { - .base = "https://www.example.org/file.tar.gz", .scheme = "https", .authority = "www.example.org", .path = "/file.tar.gz", @@ -73,7 +70,6 @@ namespace nix { auto parsed = parseURL(s); ParsedURL expected { - .base = "http://www.example.org/file.tar.gz", .scheme = "http", .authority = "www.example.org", .path = "/file.tar.gz", @@ -89,7 +85,6 @@ namespace nix { auto parsed = parseURL(s); ParsedURL expected { - .base = "https://www.example.org/video.mp4", .scheme = "file+https", .authority = "www.example.org", .path = "/video.mp4", @@ -110,7 +105,6 @@ namespace nix { auto parsed = parseURL(s); ParsedURL expected { - .base = "https://127.0.0.1:8080/file.tar.gz", .scheme = "http", .authority = "127.0.0.1:8080", .path = "/file.tar.gz", @@ -126,7 +120,6 @@ namespace nix { auto parsed = parseURL(s); ParsedURL expected { - .base = "http://[fe80::818c:da4d:8975:415c\%enp0s25]:8080", .scheme = "http", .authority = "[fe80::818c:da4d:8975:415c\%enp0s25]:8080", .path = "", @@ -143,7 +136,6 @@ namespace nix { auto parsed = parseURL(s); ParsedURL expected { - .base = "http://[2a02:8071:8192:c100:311d:192d:81ac:11ea]:8080", .scheme = "http", .authority = "[2a02:8071:8192:c100:311d:192d:81ac:11ea]:8080", .path = "", @@ -166,7 +158,6 @@ namespace nix { auto parsed = parseURL(s); ParsedURL expected { - .base = "http://user:pass@www.example.org/file.tar.gz", .scheme = "http", .authority = "user:pass@www.example.org:8080", .path = "/file.tar.gz", @@ -183,7 +174,6 @@ namespace nix { auto parsed = parseURL(s); ParsedURL expected { - .base = "", .scheme = "file", .authority = "", .path = "/none/of//your/business", @@ -207,7 +197,6 @@ namespace nix { auto parsed = parseURL(s); ParsedURL expected { - .base = "ftp://ftp.nixos.org/downloads/nixos.iso", .scheme = "ftp", .authority = "ftp.nixos.org", .path = "/downloads/nixos.iso", diff --git a/src/libutil/url.cc b/src/libutil/url.cc index 86ca035b9..4d4d983b8 100644 --- a/src/libutil/url.cc +++ b/src/libutil/url.cc @@ -40,7 +40,6 @@ ParsedURL parseURL(const std::string & url) path = "/"; return ParsedURL{ - .base = base, .scheme = scheme, .authority = authority, .path = percentDecode(path), diff --git a/src/libutil/url.hh b/src/libutil/url.hh index d85001185..2b12f5af2 100644 --- a/src/libutil/url.hh +++ b/src/libutil/url.hh @@ -7,8 +7,6 @@ namespace nix { struct ParsedURL { - /// URL without query/fragment - std::string base; // FIXME: remove std::string scheme; std::optional authority; std::string path; From d329b2632a91b05e1151decbb2b4c4011ebf5aa1 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 7 Jan 2025 17:04:06 +0100 Subject: [PATCH 622/718] Fix manual --- src/nix/flake.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nix/flake.md b/src/nix/flake.md index 35ac3ea9b..e79a8ee0b 100644 --- a/src/nix/flake.md +++ b/src/nix/flake.md @@ -219,7 +219,7 @@ Path inputs can be specified with path values in `flake.nix`. Path values are a 2. escaping URL characters (refer to IETF RFC?) 3. prepending `path:` -Note that the allowed syntax for path values in flake `inputs` may be more restrictive than general Nix, so you may need to use `path:` if your path contains certain special characters. See [Path literals](@docroot@/language/syntax#path-literal) +Note that the allowed syntax for path values in flake `inputs` may be more restrictive than general Nix, so you may need to use `path:` if your path contains certain special characters. See [Path literals](@docroot@/language/syntax.md#path-literal) Note that if you omit `path:`, relative paths must start with `.` to avoid ambiguity with registry lookups (e.g. `nixpkgs` is a registry From 3a5fccc41881a20c183038c02dea7f4995d4eabb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Domagoj=20Mi=C5=A1kovi=C4=87?= <157494086+allrealmsoflife@users.noreply.github.com> Date: Wed, 8 Jan 2025 09:42:26 +0100 Subject: [PATCH 623/718] outdated building instructions, update documentation.md The current instructions for building the Nix manual include a command that doesn't work as described. Specifically: ``` nix build .#nix^doc ``` Running this command results in the error: ``` error: derivation '/nix/store/hddqxzfqgx2fhj8q66ss3idym7pk7aj1-nix-2.26.0pre20250107_383ab87.drv' does not have wanted outputs 'doc' ``` However, this command works if you specify the Nix version explicitly, such as: ``` nix build nix/2.24.11#nix^doc ``` Additionally, these commands are run within the Nix root directory. However, the nix build .#nix^doc command does work when run from the nixpkgs directory and generates the NixOS manual. I'm not sure if I'm missing something. Is the `nix^doc` supposed to be added somehow to flake outputs? The incremental build section does not work since as make has been decommissioned in favor of Meson. Should this be simply deleted? --- doc/manual/source/development/documentation.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/manual/source/development/documentation.md b/doc/manual/source/development/documentation.md index 2e188f232..30cc8adc4 100644 --- a/doc/manual/source/development/documentation.md +++ b/doc/manual/source/development/documentation.md @@ -19,10 +19,11 @@ nix-build -E '(import ./.).packages.${builtins.currentSystem}.nix.doc' or ```console -nix build .#nix^doc +nix build .#nix-manual ``` -and open `./result-doc/share/doc/nix/manual/index.html`. +and open `./result/share/doc/nix/manual/index.html`. + To build the manual incrementally, [enter the development shell](./building.md) and run: From 5230d3ecc4cd3a3d965902a56b5a21bcc99821c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Domagoj=20Mi=C5=A1kovi=C4=87?= <157494086+allrealmsoflife@users.noreply.github.com> Date: Wed, 8 Jan 2025 14:20:44 +0100 Subject: [PATCH 624/718] Document `--max-freed` for `nix-collect-garbage` (#12155) * Update nix-collect-garbage.md Referencing issue at: https://github.com/NixOS/nix/issues/12132 Copied the description of `--max-freed` option from https://github.com/NixOS/nix/blob/442a2623e48357ff72c77bb11cf2cf06d94d2f90/doc/manual/source/command-ref/nix-store/gc.md?plain=1#L39-L44 --- doc/manual/source/command-ref/nix-collect-garbage.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/doc/manual/source/command-ref/nix-collect-garbage.md b/doc/manual/source/command-ref/nix-collect-garbage.md index bd05f2816..763179b8e 100644 --- a/doc/manual/source/command-ref/nix-collect-garbage.md +++ b/doc/manual/source/command-ref/nix-collect-garbage.md @@ -62,6 +62,15 @@ These options are for deleting old [profiles] prior to deleting unreachable [sto This is the equivalent of invoking [`nix-env --delete-generations `](@docroot@/command-ref/nix-env/delete-generations.md#generations-time) on each found profile. See the documentation of that command for additional information about the *period* argument. + - [`--max-freed`](#opt-max-freed) *bytes* + + + + Keep deleting paths until at least *bytes* bytes have been deleted, + then stop. The argument *bytes* can be followed by the + multiplicative suffix `K`, `M`, `G` or `T`, denoting KiB, MiB, GiB + or TiB units. + {{#include ./opt-common.md}} {{#include ./env-common.md}} From ed4f2c32040afcc7f1e5adb89b67b3f28e384f40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Tue, 7 Jan 2025 21:47:55 +0100 Subject: [PATCH 625/718] scripts/install-darwin-multi-user: workaround dscl failing sometimes --- scripts/install-darwin-multi-user.sh | 31 +++++++++++++++++++++------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/scripts/install-darwin-multi-user.sh b/scripts/install-darwin-multi-user.sh index 89c66b8f4..c74999512 100644 --- a/scripts/install-darwin-multi-user.sh +++ b/scripts/install-darwin-multi-user.sh @@ -145,13 +145,28 @@ poly_user_id_get() { dsclattr "/Users/$1" "UniqueID" } +dscl_create() { + # workaround a bug in dscl where it sometimes fails with eNotYetImplemented: + # https://github.com/NixOS/nix/issues/12140 + while ! _sudo "$1" /usr/bin/dscl . -create "$2" "$3" "$4" 2> "$SCRATCH/dscl.err"; do + local err=$? + if [[ $err -eq 140 ]] && grep -q "-14988 (eNotYetImplemented)" "$SCRATCH/dscl.err"; then + echo "dscl failed with eNotYetImplemented, retrying..." + sleep 1 + continue + fi + cat "$SCRATCH/dscl.err" + return $err + done +} + poly_user_hidden_get() { dsclattr "/Users/$1" "IsHidden" } poly_user_hidden_set() { - _sudo "in order to make $1 a hidden user" \ - /usr/bin/dscl . -create "/Users/$1" "IsHidden" "1" + dscl_create "in order to make $1 a hidden user" \ + "/Users/$1" "IsHidden" "1" } poly_user_home_get() { @@ -161,8 +176,8 @@ poly_user_home_get() { poly_user_home_set() { # This can trigger a permission prompt now: # "Terminal" would like to administer your computer. Administration can include modifying passwords, networking, and system settings. - _sudo "in order to give $1 a safe home directory" \ - /usr/bin/dscl . -create "/Users/$1" "NFSHomeDirectory" "$2" + dscl_create "in order to give $1 a safe home directory" \ + "/Users/$1" "NFSHomeDirectory" "$2" } poly_user_note_get() { @@ -170,8 +185,8 @@ poly_user_note_get() { } poly_user_note_set() { - _sudo "in order to give $username a useful note" \ - /usr/bin/dscl . -create "/Users/$1" "RealName" "$2" + dscl_create "in order to give $1 a useful note" \ + "/Users/$1" "RealName" "$2" } poly_user_shell_get() { @@ -179,8 +194,8 @@ poly_user_shell_get() { } poly_user_shell_set() { - _sudo "in order to give $1 a safe shell" \ - /usr/bin/dscl . -create "/Users/$1" "UserShell" "$2" + dscl_create "in order to give $1 a safe shell" \ + "/Users/$1" "UserShell" "$2" } poly_user_in_group_check() { From 28caa35a97ed4837a62cb054f66cf02041292cc5 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 8 Jan 2025 18:38:53 +0100 Subject: [PATCH 626/718] parsePathFlakeRefWithFragment(): Handle 'path?query' without a fragment Commands like `nix flake metadata '.?submodules=1'` ignored the query part of the URL, while `nix build '.?submodules=1#foo'` did work correctly because of the presence of the fragment part. --- src/libflake/flake/flakeref.cc | 27 +++++++------------ tests/functional/flakes/flake-in-submodule.sh | 13 +++++++++ 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/libflake/flake/flakeref.cc b/src/libflake/flake/flakeref.cc index 60efe1612..58cd45632 100644 --- a/src/libflake/flake/flakeref.cc +++ b/src/libflake/flake/flakeref.cc @@ -89,23 +89,16 @@ std::pair parsePathFlakeRefWithFragment( bool allowMissing, bool isFlake) { - std::string path = url; - std::string fragment = ""; - std::map query; - auto pathEnd = url.find_first_of("#?"); - auto fragmentStart = pathEnd; - if (pathEnd != std::string::npos && url[pathEnd] == '?') { - fragmentStart = url.find("#"); - } - if (pathEnd != std::string::npos) { - path = url.substr(0, pathEnd); - } - if (fragmentStart != std::string::npos) { - fragment = percentDecode(url.substr(fragmentStart+1)); - } - if (pathEnd != std::string::npos && fragmentStart != std::string::npos && url[pathEnd] == '?') { - query = decodeQuery(url.substr(pathEnd + 1, fragmentStart - pathEnd - 1)); - } + static std::regex pathFlakeRegex( + R"(([^?#]*)(\?([^#]*))?(#(.*))?)", + std::regex::ECMAScript); + + std::smatch match; + auto succeeds = std::regex_match(url, match, pathFlakeRegex); + assert(succeeds); + auto path = match[1].str(); + auto query = decodeQuery(match[3]); + auto fragment = percentDecode(match[5].str()); if (baseDir) { /* Check if 'url' is a path (either absolute or relative diff --git a/tests/functional/flakes/flake-in-submodule.sh b/tests/functional/flakes/flake-in-submodule.sh index 817f77783..643d729ff 100755 --- a/tests/functional/flakes/flake-in-submodule.sh +++ b/tests/functional/flakes/flake-in-submodule.sh @@ -63,3 +63,16 @@ flakeref=git+file://$rootRepo\?submodules=1\&dir=submodule echo '"foo"' > "$rootRepo"/submodule/sub.nix [[ $(nix eval --json "$flakeref#sub" ) = '"foo"' ]] [[ $(nix flake metadata --json "$flakeref" | jq -r .locked.rev) = null ]] + +# Test that `nix flake metadata` parses `submodule` correctly. +cat > "$rootRepo"/flake.nix < Date: Wed, 8 Jan 2025 22:15:45 +0100 Subject: [PATCH 627/718] derivation-goal: unlock output lock to avoid deadlock guix discovered in their code base. Maybe we should do the same. --- src/libstore/build/derivation-goal.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libstore/build/derivation-goal.cc b/src/libstore/build/derivation-goal.cc index 2ff0ef92f..4d97250d3 100644 --- a/src/libstore/build/derivation-goal.cc +++ b/src/libstore/build/derivation-goal.cc @@ -701,6 +701,7 @@ Goal::Co DerivationGoal::tryToBuild() if (buildMode != bmCheck && allValid) { debug("skipping build of derivation '%s', someone beat us to it", worker.store.printStorePath(drvPath)); outputLocks.setDeletion(true); + outputLocks.unlock(); co_return done(BuildResult::AlreadyValid, std::move(validOutputs)); } From 83ff523865f87f61b0b2046bd3bb2d793e09911d Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 9 Jan 2025 12:17:09 +0100 Subject: [PATCH 628/718] parsePathFlakeRefWithFragment(): Handle query params in the non-git case Backported from lazy-trees. --- src/libflake/flake/flakeref.cc | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/libflake/flake/flakeref.cc b/src/libflake/flake/flakeref.cc index 58cd45632..cdf0a40e8 100644 --- a/src/libflake/flake/flakeref.cc +++ b/src/libflake/flake/flakeref.cc @@ -183,11 +183,13 @@ std::pair parsePathFlakeRefWithFragment( path = canonPath(path + "/" + getOr(query, "dir", "")); } - fetchers::Attrs attrs; - attrs.insert_or_assign("type", "path"); - attrs.insert_or_assign("path", path); - - return std::make_pair(FlakeRef(fetchers::Input::fromAttrs(fetchSettings, std::move(attrs)), ""), fragment); + return fromParsedURL(fetchSettings, { + .scheme = "path", + .authority = "", + .path = path, + .query = query, + .fragment = fragment + }, isFlake); } /** From 5f7b535b819fb2ad5f7f05bf73fee7a2e7f7c9c8 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 9 Jan 2025 12:18:16 +0100 Subject: [PATCH 629/718] parsePathFlakeRefWithFragment(): Add unit tests --- src/libflake-tests/flakeref.cc | 50 ++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/src/libflake-tests/flakeref.cc b/src/libflake-tests/flakeref.cc index d704a26d3..c7007a7af 100644 --- a/src/libflake-tests/flakeref.cc +++ b/src/libflake-tests/flakeref.cc @@ -7,18 +7,58 @@ namespace nix { /* ----------- tests for flake/flakeref.hh --------------------------------------------------*/ - /* ---------------------------------------------------------------------------- - * to_string - * --------------------------------------------------------------------------*/ + TEST(parseFlakeRef, path) { + fetchers::Settings fetchSettings; + + { + auto s = "/foo/bar"; + auto flakeref = parseFlakeRef(fetchSettings, s); + ASSERT_EQ(flakeref.to_string(), "path:/foo/bar"); + } + + { + auto s = "/foo/bar?revCount=123&rev=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + auto flakeref = parseFlakeRef(fetchSettings, s); + ASSERT_EQ(flakeref.to_string(), "path:/foo/bar?rev=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&revCount=123"); + } + + { + auto s = "/foo/bar?xyzzy=123"; + EXPECT_THROW( + parseFlakeRef(fetchSettings, s), + Error); + } + + { + auto s = "/foo/bar#bla"; + EXPECT_THROW( + parseFlakeRef(fetchSettings, s), + Error); + } + + { + auto s = "/foo/bar#bla"; + auto [flakeref, fragment] = parseFlakeRefWithFragment(fetchSettings, s); + ASSERT_EQ(flakeref.to_string(), "path:/foo/bar"); + ASSERT_EQ(fragment, "bla"); + } + + { + auto s = "/foo/bar?revCount=123#bla"; + auto [flakeref, fragment] = parseFlakeRefWithFragment(fetchSettings, s); + ASSERT_EQ(flakeref.to_string(), "path:/foo/bar?revCount=123"); + ASSERT_EQ(fragment, "bla"); + } + } TEST(to_string, doesntReencodeUrl) { fetchers::Settings fetchSettings; auto s = "http://localhost:8181/test/+3d.tar.gz"; auto flakeref = parseFlakeRef(fetchSettings, s); - auto parsed = flakeref.to_string(); + auto unparsed = flakeref.to_string(); auto expected = "http://localhost:8181/test/%2B3d.tar.gz"; - ASSERT_EQ(parsed, expected); + ASSERT_EQ(unparsed, expected); } } From 1a38e62a094f332776ab8b60bd3274e762f7b2cb Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 9 Jan 2025 16:38:33 +0100 Subject: [PATCH 630/718] Remove unused variable --- src/libutil/url.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libutil/url.cc b/src/libutil/url.cc index 4d4d983b8..8fb1eecfb 100644 --- a/src/libutil/url.cc +++ b/src/libutil/url.cc @@ -22,7 +22,6 @@ ParsedURL parseURL(const std::string & url) std::smatch match; if (std::regex_match(url, match, uriRegex)) { - auto & base = match[1]; std::string scheme = match[2]; auto authority = match[3].matched ? std::optional(match[3]) : std::nullopt; From 3ad0f45e79bc1abc96a7c05d5979552e5f936d47 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 9 Jan 2025 16:42:37 +0100 Subject: [PATCH 631/718] Attempt to make the FlakeRef test succeed on macOS --- src/libflake-tests/flakeref.cc | 2 ++ src/libutil/config.hh | 1 + 2 files changed, 3 insertions(+) diff --git a/src/libflake-tests/flakeref.cc b/src/libflake-tests/flakeref.cc index c7007a7af..2b1f5124b 100644 --- a/src/libflake-tests/flakeref.cc +++ b/src/libflake-tests/flakeref.cc @@ -8,6 +8,8 @@ namespace nix { /* ----------- tests for flake/flakeref.hh --------------------------------------------------*/ TEST(parseFlakeRef, path) { + experimentalFeatureSettings.experimentalFeatures.get().insert(Xp::Flakes); + fetchers::Settings fetchSettings; { diff --git a/src/libutil/config.hh b/src/libutil/config.hh index e98e09bf7..502d2823e 100644 --- a/src/libutil/config.hh +++ b/src/libutil/config.hh @@ -262,6 +262,7 @@ public: operator const T &() const { return value; } operator T &() { return value; } const T & get() const { return value; } + T & get() { return value; } template bool operator ==(const U & v2) const { return value == v2; } template From fccfdbea5719f66b01870d483195f66146553b19 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 9 Jan 2025 20:44:25 +0100 Subject: [PATCH 632/718] nix upgrade-nix: Give a better error message if the profile is using 'nix profile' --- src/nix/upgrade-nix.cc | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/nix/upgrade-nix.cc b/src/nix/upgrade-nix.cc index 77fb798a7..28174c4fb 100644 --- a/src/nix/upgrade-nix.cc +++ b/src/nix/upgrade-nix.cc @@ -15,7 +15,7 @@ using namespace nix; struct CmdUpgradeNix : MixDryRun, StoreCommand { - Path profileDir; + std::filesystem::path profileDir; CmdUpgradeNix() { @@ -64,7 +64,7 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand if (profileDir == "") profileDir = getProfileDir(store); - printInfo("upgrading Nix in profile '%s'", profileDir); + printInfo("upgrading Nix in profile %s", profileDir); auto storePath = getLatestNix(store); @@ -93,7 +93,9 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand { Activity act(*logger, lvlInfo, actUnknown, - fmt("installing '%s' into profile '%s'...", store->printStorePath(storePath), profileDir)); + fmt("installing '%s' into profile %s...", store->printStorePath(storePath), profileDir)); + + // FIXME: don't call an external process. runProgram(getNixBin("nix-env").string(), false, {"--profile", profileDir, "-i", store->printStorePath(storePath), "--no-sandbox"}); } @@ -102,31 +104,33 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand } /* Return the profile in which Nix is installed. */ - Path getProfileDir(ref store) + std::filesystem::path getProfileDir(ref store) { auto whereOpt = ExecutablePath::load().findName(OS_STR("nix-env")); if (!whereOpt) throw Error("couldn't figure out how Nix is installed, so I can't upgrade it"); const auto & where = whereOpt->parent_path(); - printInfo("found Nix in '%s'", where); + printInfo("found Nix in %s", where); if (hasPrefix(where.string(), "/run/current-system")) throw Error("Nix on NixOS must be upgraded via 'nixos-rebuild'"); - Path profileDir = where.parent_path().string(); + auto profileDir = where.parent_path(); // Resolve profile to /nix/var/nix/profiles/ link. - while (canonPath(profileDir).find("/profiles/") == std::string::npos && std::filesystem::is_symlink(profileDir)) + while (canonPath(profileDir.string()).find("/profiles/") == std::string::npos && std::filesystem::is_symlink(profileDir)) profileDir = readLink(profileDir); - printInfo("found profile '%s'", profileDir); + printInfo("found profile %s", profileDir); - Path userEnv = canonPath(profileDir, true); + Path userEnv = canonPath(profileDir.string(), true); - if (where.filename() != "bin" || - !hasSuffix(userEnv, "user-environment")) - throw Error("directory %s does not appear to be part of a Nix profile", where); + if (std::filesystem::exists(profileDir / "manifest.json")) + throw Error("directory %s is managed by 'nix profile' and currently cannot be upgraded by 'nix upgrade-nix'", profileDir); + + if (!std::filesystem::exists(profileDir / "manifest.nix")) + throw Error("directory %s does not appear to be part of a Nix profile", profileDir); if (!store->isValidPath(store->parseStorePath(userEnv))) throw Error("directory '%s' is not in the Nix store", userEnv); From 96bd9bad2f434fe3489b039ac665679878460b0c Mon Sep 17 00:00:00 2001 From: Bryan Lai Date: Thu, 26 Dec 2024 20:50:36 +0800 Subject: [PATCH 633/718] fetchers/git: make path absolute for local repo --- src/libfetchers/git.cc | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/libfetchers/git.cc b/src/libfetchers/git.cc index d894550c0..c4dfc27a2 100644 --- a/src/libfetchers/git.cc +++ b/src/libfetchers/git.cc @@ -426,7 +426,16 @@ struct GitInputScheme : InputScheme auto url = parseURL(getStrAttr(input.attrs, "url")); bool isBareRepository = url.scheme == "file" && !pathExists(url.path + "/.git"); repoInfo.isLocal = url.scheme == "file" && !forceHttp && !isBareRepository; - repoInfo.url = repoInfo.isLocal ? url.path : url.to_string(); + // + // FIXME: here we turn a possibly relative path into an absolute path. + // This allows relative git flake inputs to be resolved against the + // **current working directory** (as in POSIX), which tends to work out + // ok in the context of flakes, but is the wrong behavior, + // as it should resolve against the flake.nix base directory instead. + // + // See: https://discourse.nixos.org/t/57783 and #9708 + // + repoInfo.url = repoInfo.isLocal ? std::filesystem::absolute(url.path).string() : url.to_string(); // If this is a local directory and no ref or revision is // given, then allow the use of an unclean working tree. From 9d088fa50242c5fe2ad94bffb61a4742f232ff0b Mon Sep 17 00:00:00 2001 From: Bryan Lai Date: Fri, 27 Dec 2024 17:35:44 +0800 Subject: [PATCH 634/718] tests/flakes: check git+file:./${submodule} protocol Relative, local git repo used to work (for submodules), but it fails after 3e0129ce3b9eb094d4a3cc8023884f372f1d7ff6. This commit adds a test to prevent such failure in the future. --- tests/functional/flakes/flakes.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/functional/flakes/flakes.sh b/tests/functional/flakes/flakes.sh index 6c466a0c7..acbd32a91 100755 --- a/tests/functional/flakes/flakes.sh +++ b/tests/functional/flakes/flakes.sh @@ -106,6 +106,14 @@ nix build -o "$TEST_ROOT/result" "git+file://$flake1Dir#default" nix build -o "$TEST_ROOT/result" "$flake1Dir?ref=HEAD#default" nix build -o "$TEST_ROOT/result" "git+file://$flake1Dir?ref=HEAD#default" +# Check that relative paths are allowed for git flakes. +# This may change in the future once git submodule support is refined. +# See: https://discourse.nixos.org/t/57783 and #9708. +( + cd "$flake1Dir/.." + nix build -o "$TEST_ROOT/result" "git+file:./$(basename "$flake1Dir")" +) + # Check that store symlinks inside a flake are not interpreted as flakes. nix build -o "$flake1Dir/result" "git+file://$flake1Dir" nix path-info "$flake1Dir/result" From 37ac18d1d9faba24ce09653723342465bcac3e0b Mon Sep 17 00:00:00 2001 From: Bryan Lai Date: Wed, 1 Jan 2025 14:53:04 +0800 Subject: [PATCH 635/718] tests/flake-in-submodule: git+file:./* input --- tests/functional/flakes/flake-in-submodule.sh | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/functional/flakes/flake-in-submodule.sh b/tests/functional/flakes/flake-in-submodule.sh index 643d729ff..f98c19aa8 100755 --- a/tests/functional/flakes/flake-in-submodule.sh +++ b/tests/functional/flakes/flake-in-submodule.sh @@ -76,3 +76,21 @@ git -C "$rootRepo" commit -m "Add flake.nix" storePath=$(nix flake metadata --json "$rootRepo?submodules=1" | jq -r .path) [[ -e "$storePath/submodule" ]] + +# The root repo may use the submodule repo as an input +# through the relative path. This may change in the future; +# see: https://discourse.nixos.org/t/57783 and #9708. +cat > "$rootRepo"/flake.nix < Date: Fri, 10 Jan 2025 09:57:54 +0100 Subject: [PATCH 636/718] Clarify cd call in tests/functional/flakes/flakes.sh --- tests/functional/flakes/flakes.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/functional/flakes/flakes.sh b/tests/functional/flakes/flakes.sh index acbd32a91..995ca03b0 100755 --- a/tests/functional/flakes/flakes.sh +++ b/tests/functional/flakes/flakes.sh @@ -110,6 +110,7 @@ nix build -o "$TEST_ROOT/result" "git+file://$flake1Dir?ref=HEAD#default" # This may change in the future once git submodule support is refined. # See: https://discourse.nixos.org/t/57783 and #9708. ( + # This `cd` should not be required and is indicative of aforementioned bug. cd "$flake1Dir/.." nix build -o "$TEST_ROOT/result" "git+file:./$(basename "$flake1Dir")" ) From 22adffec347d551919eb53a3ec7a57039915346b Mon Sep 17 00:00:00 2001 From: Tristan Ross Date: Thu, 9 Jan 2025 12:50:05 -0800 Subject: [PATCH 637/718] nix flake: clarify error message when file is an unknown type --- src/libstore/nar-accessor.cc | 6 +++++- src/libutil/fs-sink.cc | 10 ++++++---- src/libutil/git.cc | 14 +++++++++++--- src/libutil/posix-source-accessor.cc | 12 ++++++++++-- src/libutil/source-accessor.cc | 20 ++++++++++++++++++++ src/libutil/source-accessor.hh | 8 ++++++-- src/nix/flake.cc | 2 +- 7 files changed, 59 insertions(+), 13 deletions(-) diff --git a/src/libstore/nar-accessor.cc b/src/libstore/nar-accessor.cc index 9a541bb77..c4e0b137b 100644 --- a/src/libstore/nar-accessor.cc +++ b/src/libstore/nar-accessor.cc @@ -291,7 +291,11 @@ json listNar(ref accessor, const CanonPath & path, bool recurse) obj["type"] = "symlink"; obj["target"] = accessor->readLink(path); break; - case SourceAccessor::Type::tMisc: + case SourceAccessor::Type::tBlock: + case SourceAccessor::Type::tChar: + case SourceAccessor::Type::tSocket: + case SourceAccessor::Type::tFifo: + case SourceAccessor::Type::tUnknown: assert(false); // cannot happen for NARs } return obj; diff --git a/src/libutil/fs-sink.cc b/src/libutil/fs-sink.cc index 72e5c731f..dd979f83f 100644 --- a/src/libutil/fs-sink.cc +++ b/src/libutil/fs-sink.cc @@ -49,11 +49,13 @@ void copyRecursive( break; } - case SourceAccessor::tMisc: - throw Error("file '%1%' has an unsupported type", from); - + case SourceAccessor::tChar: + case SourceAccessor::tBlock: + case SourceAccessor::tSocket: + case SourceAccessor::tFifo: + case SourceAccessor::tUnknown: default: - unreachable(); + throw Error("file '%1%' has an unsupported type of %2%", from, stat.typeString()); } } diff --git a/src/libutil/git.cc b/src/libutil/git.cc index af91fa643..3303dbc32 100644 --- a/src/libutil/git.cc +++ b/src/libutil/git.cc @@ -200,7 +200,11 @@ std::optional convertMode(SourceAccessor::Type type) case SourceAccessor::tSymlink: return Mode::Symlink; case SourceAccessor::tRegular: return Mode::Regular; case SourceAccessor::tDirectory: return Mode::Directory; - case SourceAccessor::tMisc: return std::nullopt; + case SourceAccessor::tChar: + case SourceAccessor::tBlock: + case SourceAccessor::tSocket: + case SourceAccessor::tFifo: return std::nullopt; + case SourceAccessor::tUnknown: default: unreachable(); } } @@ -314,9 +318,13 @@ Mode dump( return Mode::Symlink; } - case SourceAccessor::tMisc: + case SourceAccessor::tChar: + case SourceAccessor::tBlock: + case SourceAccessor::tSocket: + case SourceAccessor::tFifo: + case SourceAccessor::tUnknown: default: - throw Error("file '%1%' has an unsupported type", path); + throw Error("file '%1%' has an unsupported type of %2%", path, st.typeString()); } } diff --git a/src/libutil/posix-source-accessor.cc b/src/libutil/posix-source-accessor.cc index 50b436893..8ee986d3f 100644 --- a/src/libutil/posix-source-accessor.cc +++ b/src/libutil/posix-source-accessor.cc @@ -122,7 +122,11 @@ std::optional PosixSourceAccessor::maybeLstat(const CanonP S_ISREG(st->st_mode) ? tRegular : S_ISDIR(st->st_mode) ? tDirectory : S_ISLNK(st->st_mode) ? tSymlink : - tMisc, + S_ISCHR(st->st_mode) ? tChar : + S_ISBLK(st->st_mode) ? tBlock : + S_ISSOCK(st->st_mode) ? tSocket : + S_ISFIFO(st->st_mode) ? tFifo : + tUnknown, .fileSize = S_ISREG(st->st_mode) ? std::optional(st->st_size) : std::nullopt, .isExecutable = S_ISREG(st->st_mode) && st->st_mode & S_IXUSR, }; @@ -156,7 +160,11 @@ SourceAccessor::DirEntries PosixSourceAccessor::readDirectory(const CanonPath & case std::filesystem::file_type::regular: return Type::tRegular; break; case std::filesystem::file_type::symlink: return Type::tSymlink; break; case std::filesystem::file_type::directory: return Type::tDirectory; break; - default: return tMisc; + case std::filesystem::file_type::character: return Type::tChar; break; + case std::filesystem::file_type::block: return Type::tBlock; break; + case std::filesystem::file_type::fifo: return Type::tFifo; break; + case std::filesystem::file_type::socket: return Type::tSocket; break; + default: return tUnknown; } #pragma GCC diagnostic pop }(); diff --git a/src/libutil/source-accessor.cc b/src/libutil/source-accessor.cc index d3e304f74..aa8dcf9fd 100644 --- a/src/libutil/source-accessor.cc +++ b/src/libutil/source-accessor.cc @@ -5,6 +5,26 @@ namespace nix { static std::atomic nextNumber{0}; +bool SourceAccessor::Stat::isNotNARSerialisable() +{ + return this->type != tRegular && this->type != tSymlink && this->type != tDirectory; +} + +std::string SourceAccessor::Stat::typeString() { + switch (this->type) { + case tRegular: return "regular"; + case tSymlink: return "symlink"; + case tDirectory: return "directory"; + case tChar: return "character device"; + case tBlock: return "block device"; + case tSocket: return "socket"; + case tFifo: return "fifo"; + case tUnknown: + default: return "unknown"; + } + return "unknown"; +} + SourceAccessor::SourceAccessor() : number(++nextNumber) , displayPrefix{"«unknown»"} diff --git a/src/libutil/source-accessor.hh b/src/libutil/source-accessor.hh index b16960d4a..42af8256a 100644 --- a/src/libutil/source-accessor.hh +++ b/src/libutil/source-accessor.hh @@ -88,12 +88,13 @@ struct SourceAccessor : std::enable_shared_from_this Unlike `DT_UNKNOWN`, this must not be used for deferring the lookup of types. */ - tMisc + tChar, tBlock, tSocket, tFifo, + tUnknown }; struct Stat { - Type type = tMisc; + Type type = tUnknown; /** * For regular files only: the size of the file. Not all @@ -112,6 +113,9 @@ struct SourceAccessor : std::enable_shared_from_this * file in the NAR. Only returned by NAR accessors. */ std::optional narOffset; + + bool isNotNARSerialisable(); + std::string typeString(); }; Stat lstat(const CanonPath & path); diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 7189689cc..3da194bcc 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -941,7 +941,7 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand createSymlink(target, os_string_to_string(PathViewNG { to2 })); } else - throw Error("file '%s' has unsupported type", from2); + throw Error("path '%s' needs to be a symlink, file, or directory but instead is a %s", from2, st.typeString()); changedFiles.push_back(to2); notice("wrote: %s", to2); } From e1613932991b719854a0b23ff0ab0b42fc9fc747 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 10 Jan 2025 16:27:40 +0100 Subject: [PATCH 638/718] Add setting 'allow-dirty-locks' This allows writing lock files with dirty inputs, so long as they have a NAR hash. (Currently they always have a NAR hash, but with lazy trees that may not always be the case.) Generally dirty locks are bad for reproducibility (we can detect if the dirty input has changed, but we have no way to fetch it except substitution). Hence we don't allow them by default. Fixes #11181. --- src/libcmd/installables.cc | 2 +- src/libexpr/primops/fetchTree.cc | 2 +- src/libfetchers/fetch-settings.hh | 16 ++++++++++++++++ src/libfetchers/fetchers.cc | 7 +++++++ src/libfetchers/fetchers.hh | 9 +++++++++ src/libflake/flake/flake.cc | 16 +++++++++++----- src/libflake/flake/flake.hh | 4 +++- src/libflake/flake/lockfile.cc | 9 +++++---- src/libflake/flake/lockfile.hh | 2 +- src/libflake/flake/settings.hh | 2 +- src/nix/flake.cc | 4 ++-- tests/functional/flakes/unlocked-override.sh | 11 ++++++++++- 12 files changed, 67 insertions(+), 17 deletions(-) diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc index 250cd1413..ab3ab3104 100644 --- a/src/libcmd/installables.cc +++ b/src/libcmd/installables.cc @@ -450,7 +450,7 @@ ref openEvalCache( std::shared_ptr lockedFlake) { auto fingerprint = evalSettings.useEvalCache && evalSettings.pureEval - ? lockedFlake->getFingerprint(state.store) + ? lockedFlake->getFingerprint(state.store, state.fetchSettings) : std::nullopt; auto rootLoader = [&state, lockedFlake]() { diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc index 47d1be1cc..fe42b88f1 100644 --- a/src/libexpr/primops/fetchTree.cc +++ b/src/libexpr/primops/fetchTree.cc @@ -182,7 +182,7 @@ static void fetchTree( if (!state.settings.pureEval && !input.isDirect() && experimentalFeatureSettings.isEnabled(Xp::Flakes)) input = lookupInRegistries(state.store, input).first; - if (state.settings.pureEval && !input.isLocked()) { + if (state.settings.pureEval && !input.isConsideredLocked(state.fetchSettings)) { auto fetcher = "fetchTree"; if (params.isFetchGit) fetcher = "fetchGit"; diff --git a/src/libfetchers/fetch-settings.hh b/src/libfetchers/fetch-settings.hh index f7cb34a02..2ad8aa327 100644 --- a/src/libfetchers/fetch-settings.hh +++ b/src/libfetchers/fetch-settings.hh @@ -70,6 +70,22 @@ struct Settings : public Config Setting warnDirty{this, true, "warn-dirty", "Whether to warn about dirty Git/Mercurial trees."}; + Setting allowDirtyLocks{ + this, + false, + "allow-dirty-locks", + R"( + Whether to allow dirty inputs (such as dirty Git workdirs) + to be locked via their NAR hash. This is generally bad + practice since Nix has no way to obtain such inputs if they + are subsequently modified. Therefore lock files with dirty + locks should generally only be used for local testing, and + should not be pushed to other users. + )", + {}, + true, + Xp::Flakes}; + Setting trustTarballsFromGitForges{ this, true, "trust-tarballs-from-git-forges", R"( diff --git a/src/libfetchers/fetchers.cc b/src/libfetchers/fetchers.cc index 87bf0dd71..35976f6a3 100644 --- a/src/libfetchers/fetchers.cc +++ b/src/libfetchers/fetchers.cc @@ -4,6 +4,7 @@ #include "fetch-to-store.hh" #include "json-utils.hh" #include "store-path-accessor.hh" +#include "fetch-settings.hh" #include @@ -154,6 +155,12 @@ bool Input::isLocked() const return scheme && scheme->isLocked(*this); } +bool Input::isConsideredLocked( + const Settings & settings) const +{ + return isLocked() || (settings.allowDirtyLocks && getNarHash()); +} + bool Input::isFinal() const { return maybeGetBoolAttr(attrs, "__final").value_or(false); diff --git a/src/libfetchers/fetchers.hh b/src/libfetchers/fetchers.hh index 841a44041..8cabd5103 100644 --- a/src/libfetchers/fetchers.hh +++ b/src/libfetchers/fetchers.hh @@ -95,6 +95,15 @@ public: */ bool isLocked() const; + /** + * Return whether the input is either locked, or, if + * `allow-dirty-locks` is enabled, it has a NAR hash. In the + * latter case, we can verify the input but we may not be able to + * fetch it from anywhere. + */ + bool isConsideredLocked( + const Settings & settings) const; + /** * Return whether this is a "final" input, meaning that fetching * it will not add, remove or change any attributes. (See diff --git a/src/libflake/flake/flake.cc b/src/libflake/flake/flake.cc index 29090b900..8c0c36eb3 100644 --- a/src/libflake/flake/flake.cc +++ b/src/libflake/flake/flake.cc @@ -345,6 +345,7 @@ Flake getFlake(EvalState & state, const FlakeRef & originalRef, bool allowLookup } static LockFile readLockFile( + const Settings & settings, const fetchers::Settings & fetchSettings, const SourcePath & lockFilePath) { @@ -380,6 +381,7 @@ LockedFlake lockFlake( } auto oldLockFile = readLockFile( + settings, state.fetchSettings, lockFlags.referenceLockFilePath.value_or( flake.lockFilePath())); @@ -616,7 +618,7 @@ LockedFlake lockFlake( inputFlake.inputs, childNode, inputPath, oldLock ? std::dynamic_pointer_cast(oldLock) - : readLockFile(state.fetchSettings, inputFlake.lockFilePath()).root.get_ptr(), + : readLockFile(settings, state.fetchSettings, inputFlake.lockFilePath()).root.get_ptr(), oldLock ? lockRootPath : inputPath, localPath, false); @@ -678,9 +680,11 @@ LockedFlake lockFlake( if (lockFlags.writeLockFile) { if (sourcePath || lockFlags.outputLockFilePath) { - if (auto unlockedInput = newLockFile.isUnlocked()) { + if (auto unlockedInput = newLockFile.isUnlocked(state.fetchSettings)) { if (lockFlags.failOnUnlocked) - throw Error("cannot write lock file of flake '%s' because it has an unlocked input ('%s').\n", topRef, *unlockedInput); + throw Error( + "Will not write lock file of flake '%s' because it has an unlocked input ('%s'). " + "Use '--allow-dirty-locks' to allow this anyway.", topRef, *unlockedInput); if (state.fetchSettings.warnDirty) warn("will not write lock file of flake '%s' because it has an unlocked input ('%s')", topRef, *unlockedInput); } else { @@ -979,9 +983,11 @@ static RegisterPrimOp r4({ } -std::optional LockedFlake::getFingerprint(ref store) const +std::optional LockedFlake::getFingerprint( + ref store, + const fetchers::Settings & fetchSettings) const { - if (lockFile.isUnlocked()) return std::nullopt; + if (lockFile.isUnlocked(fetchSettings)) return std::nullopt; auto fingerprint = flake.lockedRef.input.getFingerprint(store); if (!fingerprint) return std::nullopt; diff --git a/src/libflake/flake/flake.hh b/src/libflake/flake/flake.hh index 0dfd9440d..f85671a41 100644 --- a/src/libflake/flake/flake.hh +++ b/src/libflake/flake/flake.hh @@ -129,7 +129,9 @@ struct LockedFlake */ std::map, SourcePath> nodePaths; - std::optional getFingerprint(ref store) const; + std::optional getFingerprint( + ref store, + const fetchers::Settings & fetchSettings) const; }; struct LockFlags diff --git a/src/libflake/flake/lockfile.cc b/src/libflake/flake/lockfile.cc index 668ed165f..336054f5b 100644 --- a/src/libflake/flake/lockfile.cc +++ b/src/libflake/flake/lockfile.cc @@ -10,6 +10,7 @@ #include #include "strings.hh" +#include "flake/settings.hh" namespace nix::flake { @@ -43,8 +44,8 @@ LockedNode::LockedNode( , originalRef(getFlakeRef(fetchSettings, json, "original", nullptr)) , isFlake(json.find("flake") != json.end() ? (bool) json["flake"] : true) { - if (!lockedRef.input.isLocked()) - throw Error("lock file contains unlocked input '%s'", + if (!lockedRef.input.isConsideredLocked(fetchSettings)) + throw Error("Lock file contains unlocked input '%s'. Use '--allow-dirty-locks' to accept this lock file.", fetchers::attrsToJSON(lockedRef.input.toAttrs())); // For backward compatibility, lock file entries are implicitly final. @@ -228,7 +229,7 @@ std::ostream & operator <<(std::ostream & stream, const LockFile & lockFile) return stream; } -std::optional LockFile::isUnlocked() const +std::optional LockFile::isUnlocked(const fetchers::Settings & fetchSettings) const { std::set> nodes; @@ -247,7 +248,7 @@ std::optional LockFile::isUnlocked() const for (auto & i : nodes) { if (i == ref(root)) continue; auto node = i.dynamic_pointer_cast(); - if (node && (!node->lockedRef.input.isLocked() || !node->lockedRef.input.isFinal())) + if (node && (!node->lockedRef.input.isConsideredLocked(fetchSettings) || !node->lockedRef.input.isFinal())) return node->lockedRef; } diff --git a/src/libflake/flake/lockfile.hh b/src/libflake/flake/lockfile.hh index a2711a516..bcc3c460c 100644 --- a/src/libflake/flake/lockfile.hh +++ b/src/libflake/flake/lockfile.hh @@ -71,7 +71,7 @@ struct LockFile * Check whether this lock file has any unlocked or non-final * inputs. If so, return one. */ - std::optional isUnlocked() const; + std::optional isUnlocked(const fetchers::Settings & fetchSettings) const; bool operator ==(const LockFile & other) const; diff --git a/src/libflake/flake/settings.hh b/src/libflake/flake/settings.hh index fee247a7d..991eaca1f 100644 --- a/src/libflake/flake/settings.hh +++ b/src/libflake/flake/settings.hh @@ -29,7 +29,7 @@ struct Settings : public Config this, false, "accept-flake-config", - "Whether to accept nix configuration from a flake without prompting.", + "Whether to accept Nix configuration settings from a flake without prompting.", {}, true, Xp::Flakes}; diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 7189689cc..d92f644d9 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -238,7 +238,7 @@ struct CmdFlakeMetadata : FlakeCommand, MixJSON j["lastModified"] = *lastModified; j["path"] = storePath; j["locks"] = lockedFlake.lockFile.toJSON().first; - if (auto fingerprint = lockedFlake.getFingerprint(store)) + if (auto fingerprint = lockedFlake.getFingerprint(store, fetchSettings)) j["fingerprint"] = fingerprint->to_string(HashFormat::Base16, false); logger->cout("%s", j.dump()); } else { @@ -272,7 +272,7 @@ struct CmdFlakeMetadata : FlakeCommand, MixJSON logger->cout( ANSI_BOLD "Last modified:" ANSI_NORMAL " %s", std::put_time(std::localtime(&*lastModified), "%F %T")); - if (auto fingerprint = lockedFlake.getFingerprint(store)) + if (auto fingerprint = lockedFlake.getFingerprint(store, fetchSettings)) logger->cout( ANSI_BOLD "Fingerprint:" ANSI_NORMAL " %s", fingerprint->to_string(HashFormat::Base16, false)); diff --git a/tests/functional/flakes/unlocked-override.sh b/tests/functional/flakes/unlocked-override.sh index ebad332d0..dcb427a8f 100755 --- a/tests/functional/flakes/unlocked-override.sh +++ b/tests/functional/flakes/unlocked-override.sh @@ -31,5 +31,14 @@ echo 456 > "$flake1Dir"/x.nix [[ $(nix eval --json "$flake2Dir#x" --override-input flake1 "$TEST_ROOT/flake1") = 456 ]] +# Dirty overrides require --allow-dirty-locks. expectStderr 1 nix flake lock "$flake2Dir" --override-input flake1 "$TEST_ROOT/flake1" | - grepQuiet "cannot write lock file.*because it has an unlocked input" + grepQuiet "Will not write lock file.*because it has an unlocked input" + +nix flake lock "$flake2Dir" --override-input flake1 "$TEST_ROOT/flake1" --allow-dirty-locks + +# Using a lock file with a dirty lock requires --allow-dirty-locks as well. +expectStderr 1 nix eval "$flake2Dir#x" | + grepQuiet "Lock file contains unlocked input" + +[[ $(nix eval "$flake2Dir#x" --allow-dirty-locks) = 456 ]] From 47cf93ba80b8be3701589a25ba5d8e8382b3962f Mon Sep 17 00:00:00 2001 From: Tristan Ross Date: Fri, 10 Jan 2025 18:08:27 -0800 Subject: [PATCH 639/718] Add LLVM to Flake --- flake.nix | 5 +++++ src/libcmd/package.nix | 2 +- src/libexpr/package.nix | 2 +- src/libfetchers/package.nix | 2 +- src/libflake/package.nix | 2 +- src/libmain/package.nix | 2 +- src/libstore/package.nix | 2 +- src/libutil/package.nix | 2 +- src/nix/package.nix | 2 +- 9 files changed, 13 insertions(+), 8 deletions(-) diff --git a/flake.nix b/flake.nix index 83bdc5ecc..8edc2266f 100644 --- a/flake.nix +++ b/flake.nix @@ -107,6 +107,7 @@ in { inherit stdenvs native; static = native.pkgsStatic; + llvm = native.pkgsLLVM; cross = forAllCrossSystems (crossSystem: make-pkgs crossSystem "stdenv"); }); @@ -282,6 +283,7 @@ # These attributes go right into `packages.`. "${pkgName}" = nixpkgsFor.${system}.native.nixComponents.${pkgName}; "${pkgName}-static" = nixpkgsFor.${system}.static.nixComponents.${pkgName}; + "${pkgName}-llvm" = nixpkgsFor.${system}.llvm.nixComponents.${pkgName}; } // lib.optionalAttrs supportsCross (flatMapAttrs (lib.genAttrs crossSystems (_: { })) (crossSystem: {}: { # These attributes go right into `packages.`. @@ -321,6 +323,9 @@ prefixAttrs "static" (forAllStdenvs (stdenvName: makeShell { pkgs = nixpkgsFor.${system}.stdenvs."${stdenvName}Packages".pkgsStatic; })) // + prefixAttrs "llvm" (forAllStdenvs (stdenvName: makeShell { + pkgs = nixpkgsFor.${system}.stdenvs."${stdenvName}Packages".pkgsLLVM; + })) // prefixAttrs "cross" (forAllCrossSystems (crossSystem: makeShell { pkgs = nixpkgsFor.${system}.cross.${crossSystem}; })) diff --git a/src/libcmd/package.nix b/src/libcmd/package.nix index 53e54d2f8..9244a780a 100644 --- a/src/libcmd/package.nix +++ b/src/libcmd/package.nix @@ -76,7 +76,7 @@ mkMesonLibrary (finalAttrs: { (lib.mesonOption "readline-flavor" readlineFlavor) ]; - env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) { + env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux") && !(stdenv.hostPlatform.useLLVM or false)) { LDFLAGS = "-fuse-ld=gold"; }; diff --git a/src/libexpr/package.nix b/src/libexpr/package.nix index 5171d70fd..9ef56b28c 100644 --- a/src/libexpr/package.nix +++ b/src/libexpr/package.nix @@ -96,7 +96,7 @@ mkMesonLibrary (finalAttrs: { # https://github.com/NixOS/nixpkgs/issues/86131. BOOST_INCLUDEDIR = "${lib.getDev boost}/include"; BOOST_LIBRARYDIR = "${lib.getLib boost}/lib"; - } // lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) { + } // lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux") && !(stdenv.hostPlatform.useLLVM or false)) { LDFLAGS = "-fuse-ld=gold"; }; diff --git a/src/libfetchers/package.nix b/src/libfetchers/package.nix index 7dad00025..86d505fbf 100644 --- a/src/libfetchers/package.nix +++ b/src/libfetchers/package.nix @@ -49,7 +49,7 @@ mkMesonLibrary (finalAttrs: { echo ${version} > ../../.version ''; - env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) { + env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux") && !(stdenv.hostPlatform.useLLVM or false)) { LDFLAGS = "-fuse-ld=gold"; }; diff --git a/src/libflake/package.nix b/src/libflake/package.nix index 92445739f..29c9fdd80 100644 --- a/src/libflake/package.nix +++ b/src/libflake/package.nix @@ -48,7 +48,7 @@ mkMesonLibrary (finalAttrs: { echo ${version} > ../../.version ''; - env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) { + env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux") && !(stdenv.hostPlatform.useLLVM or false)) { LDFLAGS = "-fuse-ld=gold"; }; diff --git a/src/libmain/package.nix b/src/libmain/package.nix index 7d9d99b61..ede1f005b 100644 --- a/src/libmain/package.nix +++ b/src/libmain/package.nix @@ -45,7 +45,7 @@ mkMesonLibrary (finalAttrs: { echo ${version} > ../../.version ''; - env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) { + env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux") && !(stdenv.hostPlatform.useLLVM or false)) { LDFLAGS = "-fuse-ld=gold"; }; diff --git a/src/libstore/package.nix b/src/libstore/package.nix index 47a203f83..195efbb8a 100644 --- a/src/libstore/package.nix +++ b/src/libstore/package.nix @@ -87,7 +87,7 @@ mkMesonLibrary (finalAttrs: { # https://github.com/NixOS/nixpkgs/issues/86131. BOOST_INCLUDEDIR = "${lib.getDev boost}/include"; BOOST_LIBRARYDIR = "${lib.getLib boost}/lib"; - } // lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) { + } // lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux") && !(stdenv.hostPlatform.useLLVM or false)) { LDFLAGS = "-fuse-ld=gold"; }; diff --git a/src/libutil/package.nix b/src/libutil/package.nix index 0a9f65782..11f7249ee 100644 --- a/src/libutil/package.nix +++ b/src/libutil/package.nix @@ -72,7 +72,7 @@ mkMesonLibrary (finalAttrs: { # https://github.com/NixOS/nixpkgs/issues/86131. BOOST_INCLUDEDIR = "${lib.getDev boost}/include"; BOOST_LIBRARYDIR = "${lib.getLib boost}/lib"; - } // lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) { + } // lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux") && !(stdenv.hostPlatform.useLLVM or false)) { LDFLAGS = "-fuse-ld=gold"; }; diff --git a/src/nix/package.nix b/src/nix/package.nix index 9bc139c3b..67bf79f3f 100644 --- a/src/nix/package.nix +++ b/src/nix/package.nix @@ -99,7 +99,7 @@ mkMesonExecutable (finalAttrs: { mesonFlags = [ ]; - env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) { + env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux") && !(stdenv.hostPlatform.useLLVM)) { LDFLAGS = "-fuse-ld=gold"; }; From afac093b347dbc8a745d9fbee92257bd1623426f Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Sun, 12 Jan 2025 15:01:49 +0900 Subject: [PATCH 640/718] libutil: thread-pool: ensure threads finished on error This fixes segfaults with nix copy when there was an error processing addMultipleToStore. Running with ASAN/TSAN pointed at an use-after-free with threads from the pool accessing the graph declared in processGraph after the function was exiting and destructing the variables. It turns out that if there is an error before pool.process() is called, for example while we are still enqueuing tasks, then pool.process() isn't called and threads are still left to run. By creating the pool last we ensure that it is stopped first before running other destructors even if an exception happens early. [ lix porting note: nix does not name threads so the patch has been adapted to not pass thread name ] Link: https://git.lix.systems/lix-project/lix/issues/618 Link: https://gerrit.lix.systems/c/lix/+/2355 --- src/libstore/store-api.cc | 8 ++------ src/libutil/thread-pool.hh | 5 ++++- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index 78cc3b917..3b5167730 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -246,9 +246,7 @@ void Store::addMultipleToStore( act.progress(nrDone, pathsToCopy.size(), nrRunning, nrFailed); }; - ThreadPool pool; - - processGraph(pool, + processGraph( storePathsToAdd, [&](const StorePath & path) { @@ -1028,12 +1026,10 @@ std::map copyPaths( } auto pathsMap = copyPaths(srcStore, dstStore, storePaths, repair, checkSigs, substitute); - ThreadPool pool; - try { // Copy the realisation closure processGraph( - pool, Realisation::closure(srcStore, toplevelRealisations), + Realisation::closure(srcStore, toplevelRealisations), [&](const Realisation & current) -> std::set { std::set children; for (const auto & [drvOutput, _] : current.dependentRealisations) { diff --git a/src/libutil/thread-pool.hh b/src/libutil/thread-pool.hh index 02765badc..dc056481a 100644 --- a/src/libutil/thread-pool.hh +++ b/src/libutil/thread-pool.hh @@ -83,7 +83,6 @@ private: */ template void processGraph( - ThreadPool & pool, const std::set & nodes, std::function(const T &)> getEdges, std::function processNode) @@ -97,6 +96,10 @@ void processGraph( std::function worker; + /* Create pool last to ensure threads are stopped before other destructors + * run */ + ThreadPool pool; + worker = [&](const T & node) { { From 29a1a21ce4448bc00c63d26a0c4238031c612cba Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Sun, 12 Jan 2025 13:50:55 +0100 Subject: [PATCH 641/718] Reject merge conflicts They're usually found by other checks, but docs would remain susceptible. --- maintainers/flake-module.nix | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/maintainers/flake-module.nix b/maintainers/flake-module.nix index 6b311c62e..fcf370b71 100644 --- a/maintainers/flake-module.nix +++ b/maintainers/flake-module.nix @@ -10,6 +10,27 @@ # https://flake.parts/options/git-hooks-nix#options pre-commit.settings = { hooks = { + # Conflicts are usually found by other checks, but not those in docs, + # and potentially other places. + check-merge-conflicts.enable = true; + # built-in check-merge-conflicts seems ineffective against those produced by mergify backports + check-merge-conflicts-2 = { + enable = true; + entry = "${pkgs.writeScript "check-merge-conflicts" '' + #!${pkgs.runtimeShell} + conflicts=false + for file in "$@"; do + if grep --with-filename --line-number -E '^>>>>>>> ' -- "$file"; then + conflicts=true + fi + done + if $conflicts; then + echo "ERROR: found merge/patch conflicts in files" + exit 1 + fi + touch $out + ''}"; + }; clang-format = { enable = true; # https://github.com/cachix/git-hooks.nix/pull/532 From 4fac767b5295542da040d02807dc4b3a175c0337 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Sun, 12 Jan 2025 18:36:32 +0000 Subject: [PATCH 642/718] gc: replace ordered sets with unordered sets for in-memory caches During garbage collection we cache several things -- a set of known-dead paths, a set of known-alive paths, and a map of paths to their derivers. Currently they use STL maps and sets, which are ordered structures that typically are backed by binary trees. Since we are putting pseudorandom paths into these and looking them up by exact key, we don't need the ordering, and we're paying a nontrivial cost per insertion. The existing maps require O(n log n) memory and have O(log n) insertion and lookup time. We could instead use unordered maps, which are typically backed by hashmaps. These require O(n) memory and have O(1) insertion and lookup time. On my system this appears to result in a dramatic speedup -- prior to this patch I was able to delete 400k paths out of 9.5 million over the course of 34.5 hours. After this patch the same result took 89 minutes. This result should NOT be taken at face value because the two runs aren't really comparable; in particular the first started when I had 9.5 million store paths and the seconcd started with 7.8 million, so we are deleting a different set of paths starting from a much cleaner filesystem. But I do think it's indicative. Related: https://github.com/NixOS/nix/issues/9581 --- src/libstore/gc.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index 45dfe4ad8..ac354f3fa 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -455,7 +455,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) bool gcKeepOutputs = settings.gcKeepOutputs; bool gcKeepDerivations = settings.gcKeepDerivations; - StorePathSet roots, dead, alive; + std::unordered_set roots, dead, alive; struct Shared { @@ -661,7 +661,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) } }; - std::map referrersCache; + std::unordered_map referrersCache; /* Helper function that visits all paths reachable from `start` via the referrers edges and optionally derivers and derivation From fd053fdcad7bbd0dcff7a2daefd8011235653f06 Mon Sep 17 00:00:00 2001 From: Siddarth Kumar Date: Mon, 13 Jan 2025 14:12:41 +0530 Subject: [PATCH 643/718] scripts/install-multi-user: fix typo --- scripts/install-multi-user.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/install-multi-user.sh b/scripts/install-multi-user.sh index b65e08682..f051ccc46 100644 --- a/scripts/install-multi-user.sh +++ b/scripts/install-multi-user.sh @@ -562,7 +562,7 @@ create_build_user_for_core() { if [ "$actual_uid" != "$uid" ]; then failure < Date: Fri, 15 Nov 2024 10:51:22 +1100 Subject: [PATCH 644/718] windows: create files if they don't exist, and with write permission --- src/libutil/fs-sink.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libutil/fs-sink.cc b/src/libutil/fs-sink.cc index dd979f83f..fadba5972 100644 --- a/src/libutil/fs-sink.cc +++ b/src/libutil/fs-sink.cc @@ -112,7 +112,7 @@ void RestoreSink::createRegularFile(const CanonPath & path, std::function Date: Tue, 14 Jan 2025 14:51:49 +0100 Subject: [PATCH 645/718] Add release note --- doc/manual/rl-next/relative-path-flakes.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 doc/manual/rl-next/relative-path-flakes.md diff --git a/doc/manual/rl-next/relative-path-flakes.md b/doc/manual/rl-next/relative-path-flakes.md new file mode 100644 index 000000000..5a4412316 --- /dev/null +++ b/doc/manual/rl-next/relative-path-flakes.md @@ -0,0 +1,12 @@ +--- +synopsis: "Support for relative path inputs" +prs: [10089] +--- + +Flakes can now refer to other flakes in the same repository using relative paths, e.g. +```nix +inputs.foo.url = "path:./foo"; +``` +uses the flake in the `foo` subdirectory of the referring flake. + +This feature required a change to the lock file format. Previous Nix versions will not be able to use lock files that have locks for relative path inputs in them. From ff8e2fe84e4950cd20dbc513cf6eaa1d40d6bf65 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 14 Jan 2025 17:30:13 +0100 Subject: [PATCH 646/718] Fix relative 'path:' flakerefs in the CLI And handle relative 'git+file:' flakerefs while we're at it (these crashed with an assertion failure). Fixes #12248. --- src/libflake/flake/flakeref.cc | 11 ++++++++--- tests/functional/flakes/flakes.sh | 3 +++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/libflake/flake/flakeref.cc b/src/libflake/flake/flakeref.cc index cdf0a40e8..15d1191b3 100644 --- a/src/libflake/flake/flakeref.cc +++ b/src/libflake/flake/flakeref.cc @@ -102,8 +102,8 @@ std::pair parsePathFlakeRefWithFragment( if (baseDir) { /* Check if 'url' is a path (either absolute or relative - to 'baseDir'). If so, search upward to the root of the - repo (i.e. the directory containing .git). */ + to 'baseDir'). If so, search upward to the root of the + repo (i.e. the directory containing .git). */ path = absPath(path, baseDir); @@ -232,7 +232,12 @@ std::optional> parseURLFlakeRef( ) { try { - return fromParsedURL(fetchSettings, parseURL(url), isFlake); + auto parsed = parseURL(url); + if (baseDir + && (parsed.scheme == "path" || parsed.scheme == "git+file") + && !hasPrefix(parsed.path, "/")) + parsed.path = absPath(parsed.path, *baseDir); + return fromParsedURL(fetchSettings, std::move(parsed), isFlake); } catch (BadURL &) { return std::nullopt; } diff --git a/tests/functional/flakes/flakes.sh b/tests/functional/flakes/flakes.sh index 6c466a0c7..342c075a8 100755 --- a/tests/functional/flakes/flakes.sh +++ b/tests/functional/flakes/flakes.sh @@ -97,6 +97,9 @@ nix build -o "$TEST_ROOT/result" flake1 nix build -o "$TEST_ROOT/result" "$flake1Dir" nix build -o "$TEST_ROOT/result" "git+file://$flake1Dir" +(cd "$flake1Dir" && nix build -o "$TEST_ROOT/result" ".") +(cd "$flake1Dir" && nix build -o "$TEST_ROOT/result" "path:.") +(cd "$flake1Dir" && nix build -o "$TEST_ROOT/result" "git+file:.") # Test explicit packages.default. nix build -o "$TEST_ROOT/result" "$flake1Dir#default" From ff9d886f3cb28db13bfb88d1dc4d6fe3dc83270f Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 14 Jan 2025 17:42:26 +0100 Subject: [PATCH 647/718] Use isAbsolute() --- src/libexpr/eval.cc | 2 +- src/libfetchers/path.cc | 2 +- src/libfetchers/registry.cc | 2 +- src/libflake/flake/flakeref.cc | 4 ++-- src/libutil/file-system.cc | 7 +------ src/libutil/file-system.hh | 5 +++++ src/libutil/source-accessor.cc | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 21dd5a294..345c09e7e 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -406,7 +406,7 @@ void EvalState::checkURI(const std::string & uri) /* If the URI is a path, then check it against allowedPaths as well. */ - if (hasPrefix(uri, "/")) { + if (isAbsolute(uri)) { if (auto rootFS2 = rootFS.dynamic_pointer_cast()) rootFS2->checkAccess(CanonPath(uri)); return; diff --git a/src/libfetchers/path.cc b/src/libfetchers/path.cc index f628e042c..340e7f4fa 100644 --- a/src/libfetchers/path.cc +++ b/src/libfetchers/path.cc @@ -97,7 +97,7 @@ struct PathInputScheme : InputScheme std::optional isRelative(const Input & input) const { auto path = getStrAttr(input.attrs, "path"); - if (hasPrefix(path, "/")) + if (isAbsolute(path)) return std::nullopt; else return path; diff --git a/src/libfetchers/registry.cc b/src/libfetchers/registry.cc index 171afcea7..c18e12d23 100644 --- a/src/libfetchers/registry.cc +++ b/src/libfetchers/registry.cc @@ -153,7 +153,7 @@ static std::shared_ptr getGlobalRegistry(const Settings & settings, re return std::make_shared(settings, Registry::Global); // empty registry } - if (!hasPrefix(path, "/")) { + if (!isAbsolute(path)) { auto storePath = downloadFile(store, path, "flake-registry.json").storePath; if (auto store2 = store.dynamic_pointer_cast()) store2->addPermRoot(storePath, getCacheDir() + "/flake-registry.json"); diff --git a/src/libflake/flake/flakeref.cc b/src/libflake/flake/flakeref.cc index 15d1191b3..b81eb1292 100644 --- a/src/libflake/flake/flakeref.cc +++ b/src/libflake/flake/flakeref.cc @@ -178,7 +178,7 @@ std::pair parsePathFlakeRefWithFragment( } } else { - if (!hasPrefix(path, "/")) + if (!isAbsolute(path)) throw BadURL("flake reference '%s' is not an absolute path", url); path = canonPath(path + "/" + getOr(query, "dir", "")); } @@ -235,7 +235,7 @@ std::optional> parseURLFlakeRef( auto parsed = parseURL(url); if (baseDir && (parsed.scheme == "path" || parsed.scheme == "git+file") - && !hasPrefix(parsed.path, "/")) + && !isAbsolute(parsed.path)) parsed.path = absPath(parsed.path, *baseDir); return fromParsedURL(fetchSettings, std::move(parsed), isFlake); } catch (BadURL &) { diff --git a/src/libutil/file-system.cc b/src/libutil/file-system.cc index 923220fd0..a86f1ba4f 100644 --- a/src/libutil/file-system.cc +++ b/src/libutil/file-system.cc @@ -31,12 +31,7 @@ namespace nix { namespace fs { using namespace std::filesystem; } -/** - * Treat the string as possibly an absolute path, by inspecting the - * start of it. Return whether it was probably intended to be - * absolute. - */ -static bool isAbsolute(PathView path) +bool isAbsolute(PathView path) { return fs::path { path }.is_absolute(); } diff --git a/src/libutil/file-system.hh b/src/libutil/file-system.hh index 7fdaba811..204907339 100644 --- a/src/libutil/file-system.hh +++ b/src/libutil/file-system.hh @@ -42,6 +42,11 @@ namespace nix { struct Sink; struct Source; +/** + * Return whether the path denotes an absolute path. + */ +bool isAbsolute(PathView path); + /** * @return An absolutized path, resolving paths relative to the * specified directory, or the current directory otherwise. The path diff --git a/src/libutil/source-accessor.cc b/src/libutil/source-accessor.cc index aa8dcf9fd..78f038cf3 100644 --- a/src/libutil/source-accessor.cc +++ b/src/libutil/source-accessor.cc @@ -115,7 +115,7 @@ CanonPath SourceAccessor::resolveSymlinks( throw Error("infinite symlink recursion in path '%s'", showPath(path)); auto target = readLink(res); res.pop(); - if (hasPrefix(target, "/")) + if (isAbsolute(target)) res = CanonPath::root; todo.splice(todo.begin(), tokenizeString>(target, "/")); } From 6a874c2865636348d192f436d22cd5a10f26a29a Mon Sep 17 00:00:00 2001 From: "Travis A. Everett" Date: Wed, 15 Jan 2025 08:59:14 -0600 Subject: [PATCH 648/718] sequoia-nixbld-user-migration: nail down PATH Fixes a user report of trouble with toybox grep and avoids potential of same basic issue with other utils. --- scripts/sequoia-nixbld-user-migration.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/sequoia-nixbld-user-migration.sh b/scripts/sequoia-nixbld-user-migration.sh index 88e801706..58b5fea64 100755 --- a/scripts/sequoia-nixbld-user-migration.sh +++ b/scripts/sequoia-nixbld-user-migration.sh @@ -2,6 +2,9 @@ set -eo pipefail +# stock path to avoid unexpected command versions +PATH="$(/usr/bin/getconf PATH)" + ((NEW_NIX_FIRST_BUILD_UID=351)) ((TEMP_NIX_FIRST_BUILD_UID=31000)) From 3d078cd508cf9fa3b623cffc2d26a6942b44b720 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 15 Jan 2025 20:00:23 +0100 Subject: [PATCH 649/718] Add RossComputerGuy as `-llvm` maintainer --- flake.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/flake.nix b/flake.nix index 8edc2266f..9d224310b 100644 --- a/flake.nix +++ b/flake.nix @@ -283,6 +283,10 @@ # These attributes go right into `packages.`. "${pkgName}" = nixpkgsFor.${system}.native.nixComponents.${pkgName}; "${pkgName}-static" = nixpkgsFor.${system}.static.nixComponents.${pkgName}; + /** + Nix and dependencies built with LLVM and Clang, maintainers: + @RossComputerGuy, Nix team + */ "${pkgName}-llvm" = nixpkgsFor.${system}.llvm.nixComponents.${pkgName}; } // lib.optionalAttrs supportsCross (flatMapAttrs (lib.genAttrs crossSystems (_: { })) (crossSystem: {}: { From cab347b4ebb2f8fe2e06a84a29c1c3027b9edc85 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 15 Jan 2025 19:54:02 +0100 Subject: [PATCH 650/718] refactor: Move ld=gold rule to mesonBuildLayer --- flake.nix | 4 ---- packaging/dependencies.nix | 6 ++++++ src/libcmd/package.nix | 4 ---- src/libexpr-c/package.nix | 4 ---- src/libexpr-test-support/package.nix | 4 ---- src/libexpr-tests/package.nix | 4 ---- src/libexpr/package.nix | 2 -- src/libfetchers-tests/package.nix | 4 ---- src/libfetchers/package.nix | 4 ---- src/libflake-c/package.nix | 4 ---- src/libflake-tests/package.nix | 4 ---- src/libflake/package.nix | 4 ---- src/libmain-c/package.nix | 4 ---- src/libmain/package.nix | 4 ---- src/libstore-c/package.nix | 4 ---- src/libstore-test-support/package.nix | 4 ---- src/libstore-tests/package.nix | 4 ---- src/libstore/package.nix | 2 -- src/libutil-c/package.nix | 4 ---- src/libutil-test-support/package.nix | 4 ---- src/libutil-tests/package.nix | 4 ---- src/libutil/package.nix | 2 -- src/nix/package.nix | 4 ---- 23 files changed, 6 insertions(+), 82 deletions(-) diff --git a/flake.nix b/flake.nix index 9d224310b..8edc2266f 100644 --- a/flake.nix +++ b/flake.nix @@ -283,10 +283,6 @@ # These attributes go right into `packages.`. "${pkgName}" = nixpkgsFor.${system}.native.nixComponents.${pkgName}; "${pkgName}-static" = nixpkgsFor.${system}.static.nixComponents.${pkgName}; - /** - Nix and dependencies built with LLVM and Clang, maintainers: - @RossComputerGuy, Nix team - */ "${pkgName}-llvm" = nixpkgsFor.${system}.llvm.nixComponents.${pkgName}; } // lib.optionalAttrs supportsCross (flatMapAttrs (lib.genAttrs crossSystems (_: { })) (crossSystem: {}: { diff --git a/packaging/dependencies.nix b/packaging/dependencies.nix index 4bc7495e7..08d179b82 100644 --- a/packaging/dependencies.nix +++ b/packaging/dependencies.nix @@ -97,6 +97,12 @@ let ]; separateDebugInfo = !stdenv.hostPlatform.isStatic; hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie"; + env = prevAttrs.env or {} + // lib.optionalAttrs + (stdenv.isLinux + && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux") + && !(stdenv.hostPlatform.useLLVM or false)) + { LDFLAGS = "-fuse-ld=gold"; }; }; mesonLibraryLayer = finalAttrs: prevAttrs: diff --git a/src/libcmd/package.nix b/src/libcmd/package.nix index 9244a780a..5cafb4dc1 100644 --- a/src/libcmd/package.nix +++ b/src/libcmd/package.nix @@ -76,10 +76,6 @@ mkMesonLibrary (finalAttrs: { (lib.mesonOption "readline-flavor" readlineFlavor) ]; - env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux") && !(stdenv.hostPlatform.useLLVM or false)) { - LDFLAGS = "-fuse-ld=gold"; - }; - meta = { platforms = lib.platforms.unix ++ lib.platforms.windows; }; diff --git a/src/libexpr-c/package.nix b/src/libexpr-c/package.nix index 727b3a811..22726ac36 100644 --- a/src/libexpr-c/package.nix +++ b/src/libexpr-c/package.nix @@ -47,10 +47,6 @@ mkMesonLibrary (finalAttrs: { mesonFlags = [ ]; - env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) { - LDFLAGS = "-fuse-ld=gold"; - }; - meta = { platforms = lib.platforms.unix ++ lib.platforms.windows; }; diff --git a/src/libexpr-test-support/package.nix b/src/libexpr-test-support/package.nix index 4842f5f17..9726fa57a 100644 --- a/src/libexpr-test-support/package.nix +++ b/src/libexpr-test-support/package.nix @@ -51,10 +51,6 @@ mkMesonLibrary (finalAttrs: { mesonFlags = [ ]; - env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) { - LDFLAGS = "-fuse-ld=gold"; - }; - meta = { platforms = lib.platforms.unix ++ lib.platforms.windows; }; diff --git a/src/libexpr-tests/package.nix b/src/libexpr-tests/package.nix index 70e497b7e..a4a3bb0e7 100644 --- a/src/libexpr-tests/package.nix +++ b/src/libexpr-tests/package.nix @@ -56,10 +56,6 @@ mkMesonExecutable (finalAttrs: { mesonFlags = [ ]; - env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) { - LDFLAGS = "-fuse-ld=gold"; - }; - passthru = { tests = { run = runCommand "${finalAttrs.pname}-run" { diff --git a/src/libexpr/package.nix b/src/libexpr/package.nix index 9ef56b28c..3d5b78e35 100644 --- a/src/libexpr/package.nix +++ b/src/libexpr/package.nix @@ -96,8 +96,6 @@ mkMesonLibrary (finalAttrs: { # https://github.com/NixOS/nixpkgs/issues/86131. BOOST_INCLUDEDIR = "${lib.getDev boost}/include"; BOOST_LIBRARYDIR = "${lib.getLib boost}/lib"; - } // lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux") && !(stdenv.hostPlatform.useLLVM or false)) { - LDFLAGS = "-fuse-ld=gold"; }; meta = { diff --git a/src/libfetchers-tests/package.nix b/src/libfetchers-tests/package.nix index e18d644ed..5336672a2 100644 --- a/src/libfetchers-tests/package.nix +++ b/src/libfetchers-tests/package.nix @@ -54,10 +54,6 @@ mkMesonExecutable (finalAttrs: { mesonFlags = [ ]; - env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) { - LDFLAGS = "-fuse-ld=gold"; - }; - passthru = { tests = { run = runCommand "${finalAttrs.pname}-run" { diff --git a/src/libfetchers/package.nix b/src/libfetchers/package.nix index 86d505fbf..79dd81cc9 100644 --- a/src/libfetchers/package.nix +++ b/src/libfetchers/package.nix @@ -49,10 +49,6 @@ mkMesonLibrary (finalAttrs: { echo ${version} > ../../.version ''; - env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux") && !(stdenv.hostPlatform.useLLVM or false)) { - LDFLAGS = "-fuse-ld=gold"; - }; - meta = { platforms = lib.platforms.unix ++ lib.platforms.windows; }; diff --git a/src/libflake-c/package.nix b/src/libflake-c/package.nix index 7425d6140..9d339dd0a 100644 --- a/src/libflake-c/package.nix +++ b/src/libflake-c/package.nix @@ -49,10 +49,6 @@ mkMesonLibrary (finalAttrs: { mesonFlags = [ ]; - env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) { - LDFLAGS = "-fuse-ld=gold"; - }; - meta = { platforms = lib.platforms.unix ++ lib.platforms.windows; }; diff --git a/src/libflake-tests/package.nix b/src/libflake-tests/package.nix index f1abbb32d..51b68ad58 100644 --- a/src/libflake-tests/package.nix +++ b/src/libflake-tests/package.nix @@ -56,10 +56,6 @@ mkMesonExecutable (finalAttrs: { mesonFlags = [ ]; - env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) { - LDFLAGS = "-fuse-ld=gold"; - }; - passthru = { tests = { run = runCommand "${finalAttrs.pname}-run" { diff --git a/src/libflake/package.nix b/src/libflake/package.nix index 29c9fdd80..868832b75 100644 --- a/src/libflake/package.nix +++ b/src/libflake/package.nix @@ -48,10 +48,6 @@ mkMesonLibrary (finalAttrs: { echo ${version} > ../../.version ''; - env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux") && !(stdenv.hostPlatform.useLLVM or false)) { - LDFLAGS = "-fuse-ld=gold"; - }; - meta = { platforms = lib.platforms.unix ++ lib.platforms.windows; }; diff --git a/src/libmain-c/package.nix b/src/libmain-c/package.nix index d65792921..ba47d5cb9 100644 --- a/src/libmain-c/package.nix +++ b/src/libmain-c/package.nix @@ -51,10 +51,6 @@ mkMesonLibrary (finalAttrs: { mesonFlags = [ ]; - env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) { - LDFLAGS = "-fuse-ld=gold"; - }; - meta = { platforms = lib.platforms.unix ++ lib.platforms.windows; }; diff --git a/src/libmain/package.nix b/src/libmain/package.nix index ede1f005b..856aa660f 100644 --- a/src/libmain/package.nix +++ b/src/libmain/package.nix @@ -45,10 +45,6 @@ mkMesonLibrary (finalAttrs: { echo ${version} > ../../.version ''; - env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux") && !(stdenv.hostPlatform.useLLVM or false)) { - LDFLAGS = "-fuse-ld=gold"; - }; - meta = { platforms = lib.platforms.unix ++ lib.platforms.windows; }; diff --git a/src/libstore-c/package.nix b/src/libstore-c/package.nix index 351d4510a..e9b548473 100644 --- a/src/libstore-c/package.nix +++ b/src/libstore-c/package.nix @@ -47,10 +47,6 @@ mkMesonLibrary (finalAttrs: { mesonFlags = [ ]; - env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) { - LDFLAGS = "-fuse-ld=gold"; - }; - meta = { platforms = lib.platforms.unix ++ lib.platforms.windows; }; diff --git a/src/libstore-test-support/package.nix b/src/libstore-test-support/package.nix index 62f783c4f..705297b4c 100644 --- a/src/libstore-test-support/package.nix +++ b/src/libstore-test-support/package.nix @@ -51,10 +51,6 @@ mkMesonLibrary (finalAttrs: { mesonFlags = [ ]; - env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) { - LDFLAGS = "-fuse-ld=gold"; - }; - meta = { platforms = lib.platforms.unix ++ lib.platforms.windows; }; diff --git a/src/libstore-tests/package.nix b/src/libstore-tests/package.nix index 4937b5329..3acf4e25c 100644 --- a/src/libstore-tests/package.nix +++ b/src/libstore-tests/package.nix @@ -62,10 +62,6 @@ mkMesonExecutable (finalAttrs: { mesonFlags = [ ]; - env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) { - LDFLAGS = "-fuse-ld=gold"; - }; - passthru = { tests = { run = let diff --git a/src/libstore/package.nix b/src/libstore/package.nix index 195efbb8a..4fbaea4ac 100644 --- a/src/libstore/package.nix +++ b/src/libstore/package.nix @@ -87,8 +87,6 @@ mkMesonLibrary (finalAttrs: { # https://github.com/NixOS/nixpkgs/issues/86131. BOOST_INCLUDEDIR = "${lib.getDev boost}/include"; BOOST_LIBRARYDIR = "${lib.getLib boost}/lib"; - } // lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux") && !(stdenv.hostPlatform.useLLVM or false)) { - LDFLAGS = "-fuse-ld=gold"; }; meta = { diff --git a/src/libutil-c/package.nix b/src/libutil-c/package.nix index 4caf96804..294593b52 100644 --- a/src/libutil-c/package.nix +++ b/src/libutil-c/package.nix @@ -45,10 +45,6 @@ mkMesonLibrary (finalAttrs: { mesonFlags = [ ]; - env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) { - LDFLAGS = "-fuse-ld=gold"; - }; - meta = { platforms = lib.platforms.unix ++ lib.platforms.windows; }; diff --git a/src/libutil-test-support/package.nix b/src/libutil-test-support/package.nix index 19b5d6b77..8185a701f 100644 --- a/src/libutil-test-support/package.nix +++ b/src/libutil-test-support/package.nix @@ -49,10 +49,6 @@ mkMesonLibrary (finalAttrs: { mesonFlags = [ ]; - env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) { - LDFLAGS = "-fuse-ld=gold"; - }; - meta = { platforms = lib.platforms.unix ++ lib.platforms.windows; }; diff --git a/src/libutil-tests/package.nix b/src/libutil-tests/package.nix index f06704e26..28769e115 100644 --- a/src/libutil-tests/package.nix +++ b/src/libutil-tests/package.nix @@ -55,10 +55,6 @@ mkMesonExecutable (finalAttrs: { mesonFlags = [ ]; - env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) { - LDFLAGS = "-fuse-ld=gold"; - }; - passthru = { tests = { run = runCommand "${finalAttrs.pname}-run" { diff --git a/src/libutil/package.nix b/src/libutil/package.nix index 11f7249ee..679872a75 100644 --- a/src/libutil/package.nix +++ b/src/libutil/package.nix @@ -72,8 +72,6 @@ mkMesonLibrary (finalAttrs: { # https://github.com/NixOS/nixpkgs/issues/86131. BOOST_INCLUDEDIR = "${lib.getDev boost}/include"; BOOST_LIBRARYDIR = "${lib.getLib boost}/lib"; - } // lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux") && !(stdenv.hostPlatform.useLLVM or false)) { - LDFLAGS = "-fuse-ld=gold"; }; meta = { diff --git a/src/nix/package.nix b/src/nix/package.nix index 67bf79f3f..ac0181529 100644 --- a/src/nix/package.nix +++ b/src/nix/package.nix @@ -99,10 +99,6 @@ mkMesonExecutable (finalAttrs: { mesonFlags = [ ]; - env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux") && !(stdenv.hostPlatform.useLLVM)) { - LDFLAGS = "-fuse-ld=gold"; - }; - meta = { platforms = lib.platforms.unix ++ lib.platforms.windows; }; From 7ad02b62e04e8845243f2c80d9891375b465d0af Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 15 Jan 2025 19:58:36 +0100 Subject: [PATCH 651/718] refactor: Remove redundant parameters --- src/libexpr-c/package.nix | 1 - src/libexpr-test-support/package.nix | 1 - src/libfetchers/package.nix | 1 - src/libflake-c/package.nix | 1 - src/libflake/package.nix | 1 - src/libmain-c/package.nix | 1 - src/libmain/package.nix | 1 - src/libstore-c/package.nix | 1 - src/libstore-test-support/package.nix | 1 - src/libutil-c/package.nix | 1 - src/libutil-test-support/package.nix | 1 - src/nix/package.nix | 1 - 12 files changed, 12 deletions(-) diff --git a/src/libexpr-c/package.nix b/src/libexpr-c/package.nix index 22726ac36..5047f3e2e 100644 --- a/src/libexpr-c/package.nix +++ b/src/libexpr-c/package.nix @@ -1,5 +1,4 @@ { lib -, stdenv , mkMesonLibrary , nix-store-c diff --git a/src/libexpr-test-support/package.nix b/src/libexpr-test-support/package.nix index 9726fa57a..48118fa0c 100644 --- a/src/libexpr-test-support/package.nix +++ b/src/libexpr-test-support/package.nix @@ -1,5 +1,4 @@ { lib -, stdenv , mkMesonLibrary , nix-store-test-support diff --git a/src/libfetchers/package.nix b/src/libfetchers/package.nix index 79dd81cc9..d4ca18555 100644 --- a/src/libfetchers/package.nix +++ b/src/libfetchers/package.nix @@ -1,5 +1,4 @@ { lib -, stdenv , mkMesonLibrary , nix-util diff --git a/src/libflake-c/package.nix b/src/libflake-c/package.nix index 9d339dd0a..dcd6c4966 100644 --- a/src/libflake-c/package.nix +++ b/src/libflake-c/package.nix @@ -1,5 +1,4 @@ { lib -, stdenv , mkMesonLibrary , nix-store-c diff --git a/src/libflake/package.nix b/src/libflake/package.nix index 868832b75..3fc96a20e 100644 --- a/src/libflake/package.nix +++ b/src/libflake/package.nix @@ -1,5 +1,4 @@ { lib -, stdenv , mkMesonLibrary , nix-util diff --git a/src/libmain-c/package.nix b/src/libmain-c/package.nix index ba47d5cb9..b96901bb4 100644 --- a/src/libmain-c/package.nix +++ b/src/libmain-c/package.nix @@ -1,5 +1,4 @@ { lib -, stdenv , mkMesonLibrary , nix-util-c diff --git a/src/libmain/package.nix b/src/libmain/package.nix index 856aa660f..9a5b9e8c2 100644 --- a/src/libmain/package.nix +++ b/src/libmain/package.nix @@ -1,5 +1,4 @@ { lib -, stdenv , mkMesonLibrary , openssl diff --git a/src/libstore-c/package.nix b/src/libstore-c/package.nix index e9b548473..c2413c389 100644 --- a/src/libstore-c/package.nix +++ b/src/libstore-c/package.nix @@ -1,5 +1,4 @@ { lib -, stdenv , mkMesonLibrary , nix-util-c diff --git a/src/libstore-test-support/package.nix b/src/libstore-test-support/package.nix index 705297b4c..5d3f41b3e 100644 --- a/src/libstore-test-support/package.nix +++ b/src/libstore-test-support/package.nix @@ -1,5 +1,4 @@ { lib -, stdenv , mkMesonLibrary , nix-util-test-support diff --git a/src/libutil-c/package.nix b/src/libutil-c/package.nix index 294593b52..f80e0b7f0 100644 --- a/src/libutil-c/package.nix +++ b/src/libutil-c/package.nix @@ -1,5 +1,4 @@ { lib -, stdenv , mkMesonLibrary , nix-util diff --git a/src/libutil-test-support/package.nix b/src/libutil-test-support/package.nix index 8185a701f..a8a239717 100644 --- a/src/libutil-test-support/package.nix +++ b/src/libutil-test-support/package.nix @@ -1,5 +1,4 @@ { lib -, stdenv , mkMesonLibrary , nix-util diff --git a/src/nix/package.nix b/src/nix/package.nix index ac0181529..171621af9 100644 --- a/src/nix/package.nix +++ b/src/nix/package.nix @@ -1,5 +1,4 @@ { lib -, stdenv , mkMesonExecutable , nix-store From 521667eb8908843925dc57e195f7702d66d0ac16 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 16 Jan 2025 11:19:20 +0100 Subject: [PATCH 652/718] Fix follow-paths test Since ff8e2fe84e4950cd20dbc513cf6eaa1d40d6bf65, 'path:' URLs on the CLI are interpreted as relative to the current directory of the user, not the path of the flake we're overriding. --- tests/functional/flakes/follow-paths.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/functional/flakes/follow-paths.sh b/tests/functional/flakes/follow-paths.sh index 966f69cf7..a71d4c6d7 100755 --- a/tests/functional/flakes/follow-paths.sh +++ b/tests/functional/flakes/follow-paths.sh @@ -356,6 +356,6 @@ json=$(nix flake metadata "$flakeFollowsCustomUrlA" --json) rm "$flakeFollowsCustomUrlA"/flake.lock # if override-input is specified, lock "original" entry should contain original url -json=$(nix flake metadata "$flakeFollowsCustomUrlA" --override-input B/C "path:./flakeB/flakeD" --json) +json=$(nix flake metadata "$flakeFollowsCustomUrlA" --override-input B/C "$flakeFollowsCustomUrlD" --json) echo "$json" | jq .locks.nodes.C.original [[ $(echo "$json" | jq -r .locks.nodes.C.original.path) = './flakeC' ]] From 5d03ef9caf136de06b79298b4a5f8c80a4abadbf Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 16 Jan 2025 11:26:14 +0100 Subject: [PATCH 653/718] PathInputSchema::getAbsPath(): Return std::filesystem::path --- src/libfetchers/path.cc | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libfetchers/path.cc b/src/libfetchers/path.cc index 9691cc9c5..351e21a1b 100644 --- a/src/libfetchers/path.cc +++ b/src/libfetchers/path.cc @@ -91,7 +91,7 @@ struct PathInputScheme : InputScheme std::string_view contents, std::optional commitMsg) const override { - writeFile((CanonPath(getAbsPath(input)) / path).abs(), contents); + writeFile(getAbsPath(input) / path.rel(), contents); } std::optional isRelative(const Input & input) const override @@ -108,12 +108,12 @@ struct PathInputScheme : InputScheme return (bool) input.getNarHash(); } - CanonPath getAbsPath(const Input & input) const + std::filesystem::path getAbsPath(const Input & input) const { auto path = getStrAttr(input.attrs, "path"); - if (path[0] == '/') - return CanonPath(path); + if (isAbsolute(path)) + return canonPath(path); throw Error("cannot fetch input '%s' because it uses a relative path", input.to_string()); } @@ -128,7 +128,7 @@ struct PathInputScheme : InputScheme Activity act(*logger, lvlTalkative, actUnknown, fmt("copying '%s' to the store", absPath)); // FIXME: check whether access to 'path' is allowed. - auto storePath = store->maybeParseStorePath(absPath.abs()); + auto storePath = store->maybeParseStorePath(absPath.string()); if (storePath) store->addTempRoot(*storePath); @@ -137,7 +137,7 @@ struct PathInputScheme : InputScheme if (!storePath || storePath->name() != "source" || !store->isValidPath(*storePath)) { // FIXME: try to substitute storePath. auto src = sinkToSource([&](Sink & sink) { - mtime = dumpPathAndGetMtime(absPath.abs(), sink, defaultPathFilter); + mtime = dumpPathAndGetMtime(absPath.string(), sink, defaultPathFilter); }); storePath = store->addToStoreFromDump(*src, "source"); } @@ -159,7 +159,7 @@ struct PathInputScheme : InputScheme store object and the subpath. */ auto path = getAbsPath(input); try { - auto [storePath, subPath] = store->toStorePath(path.abs()); + auto [storePath, subPath] = store->toStorePath(path.string()); auto info = store->queryPathInfo(storePath); return fmt("path:%s:%s", info->narHash.to_string(HashFormat::Base16, false), subPath); } catch (Error &) { From 8b1fb92a0ce7fd8c0ad7955de1a59bb42866339e Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 16 Jan 2025 11:31:22 +0100 Subject: [PATCH 654/718] flakes.md: Fix indentation that broke the list --- src/nix/flake.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/nix/flake.md b/src/nix/flake.md index e79a8ee0b..2072dd3dd 100644 --- a/src/nix/flake.md +++ b/src/nix/flake.md @@ -214,12 +214,12 @@ Currently the `type` attribute can be one of the following: hand, a flake in the `/foo` directory of a tree can use `path:../bar` to refer to the flake in `/bar`. -Path inputs can be specified with path values in `flake.nix`. Path values are a syntax for `path` inputs, and they are converted by -1. resolving them into relative paths, relative to the base directory of `flake.nix` -2. escaping URL characters (refer to IETF RFC?) -3. prepending `path:` + Path inputs can be specified with path values in `flake.nix`. Path values are a syntax for `path` inputs, and they are converted by + 1. resolving them into relative paths, relative to the base directory of `flake.nix` + 2. escaping URL characters (refer to IETF RFC?) + 3. prepending `path:` -Note that the allowed syntax for path values in flake `inputs` may be more restrictive than general Nix, so you may need to use `path:` if your path contains certain special characters. See [Path literals](@docroot@/language/syntax.md#path-literal) + Note that the allowed syntax for path values in flake `inputs` may be more restrictive than general Nix, so you may need to use `path:` if your path contains certain special characters. See [Path literals](@docroot@/language/syntax.md#path-literal) Note that if you omit `path:`, relative paths must start with `.` to avoid ambiguity with registry lookups (e.g. `nixpkgs` is a registry From db46d40b12cc57de47c468a73262f1c20b0374c8 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 16 Jan 2025 13:15:20 +0100 Subject: [PATCH 655/718] Update release note --- doc/manual/rl-next/relative-path-flakes.md | 2 +- src/nix/flake.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/manual/rl-next/relative-path-flakes.md b/doc/manual/rl-next/relative-path-flakes.md index 5a4412316..3616f3467 100644 --- a/doc/manual/rl-next/relative-path-flakes.md +++ b/doc/manual/rl-next/relative-path-flakes.md @@ -7,6 +7,6 @@ Flakes can now refer to other flakes in the same repository using relative paths ```nix inputs.foo.url = "path:./foo"; ``` -uses the flake in the `foo` subdirectory of the referring flake. +uses the flake in the `foo` subdirectory of the referring flake. For more information, see the documentation on [the `path` flake input type](@docroot@/command-ref/new-cli/nix3-flake.md#path-fetcher). This feature required a change to the lock file format. Previous Nix versions will not be able to use lock files that have locks for relative path inputs in them. diff --git a/src/nix/flake.md b/src/nix/flake.md index 2072dd3dd..364302b61 100644 --- a/src/nix/flake.md +++ b/src/nix/flake.md @@ -187,7 +187,7 @@ Currently the `type` attribute can be one of the following: * `nixpkgs/nixos-unstable/a3a3dda3bacf61e8a39258a0ed9c924eeca8e293` * `sub/dir` (if a flake named `sub` is in the registry) -* `path`: arbitrary local directories. The required attribute `path` +* `path`: arbitrary local directories. The required attribute `path` specifies the path of the flake. The URL form is ``` From 2ca0c62a8d577e9b4bc1e6d313239e0cb9452ca2 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 16 Jan 2025 17:06:59 +0100 Subject: [PATCH 656/718] Remove some unnecessary quotes around std::filesystem::path --- src/libutil/file-system.cc | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libutil/file-system.cc b/src/libutil/file-system.cc index a86f1ba4f..6fe93b63a 100644 --- a/src/libutil/file-system.cc +++ b/src/libutil/file-system.cc @@ -643,7 +643,7 @@ void setWriteTime( // doesn't support access time just modification time. // // System clock vs File clock issues also make that annoying. - warn("Changing file times is not yet implemented on Windows, path is '%s'", path); + warn("Changing file times is not yet implemented on Windows, path is %s", path); #elif HAVE_UTIMENSAT && HAVE_DECL_AT_SYMLINK_NOFOLLOW struct timespec times[2] = { { @@ -656,7 +656,7 @@ void setWriteTime( }, }; if (utimensat(AT_FDCWD, path.c_str(), times, AT_SYMLINK_NOFOLLOW) == -1) - throw SysError("changing modification time of '%s' (using `utimensat`)", path); + throw SysError("changing modification time of %s (using `utimensat`)", path); #else struct timeval times[2] = { { @@ -670,7 +670,7 @@ void setWriteTime( }; #if HAVE_LUTIMES if (lutimes(path.c_str(), times) == -1) - throw SysError("changing modification time of '%s'", path); + throw SysError("changing modification time of %s", path); #else bool isSymlink = optIsSymlink ? *optIsSymlink @@ -678,9 +678,9 @@ void setWriteTime( if (!isSymlink) { if (utimes(path.c_str(), times) == -1) - throw SysError("changing modification time of '%s' (not a symlink)", path); + throw SysError("changing modification time of %s (not a symlink)", path); } else { - throw Error("Cannot modification time of symlink '%s'", path); + throw Error("Cannot modification time of symlink %s", path); } #endif #endif @@ -709,7 +709,7 @@ void copyFile(const fs::path & from, const fs::path & to, bool andDelete) copyFile(entry, to / entry.path().filename(), andDelete); } } else { - throw Error("file '%s' has an unsupported type", from); + throw Error("file %s has an unsupported type", from); } setWriteTime(to, lstat(from.string().c_str())); @@ -736,7 +736,7 @@ void moveFile(const Path & oldName, const Path & newName) auto tempCopyTarget = temp / "copy-target"; if (e.code().value() == EXDEV) { fs::remove(newPath); - warn("Can’t rename %s as %s, copying instead", oldName, newName); + warn("can’t rename %s as %s, copying instead", oldName, newName); copyFile(oldPath, tempCopyTarget, true); std::filesystem::rename( os_string_to_string(PathViewNG { tempCopyTarget }), From 12e14956e22a42c26715ca084bb6b17d35628bb9 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 16 Jan 2025 17:22:54 +0100 Subject: [PATCH 657/718] Warn against the use of relative 'git+file:' flake inputs --- src/libfetchers/git.cc | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/libfetchers/git.cc b/src/libfetchers/git.cc index c4dfc27a2..3f196da54 100644 --- a/src/libfetchers/git.cc +++ b/src/libfetchers/git.cc @@ -435,7 +435,16 @@ struct GitInputScheme : InputScheme // // See: https://discourse.nixos.org/t/57783 and #9708 // - repoInfo.url = repoInfo.isLocal ? std::filesystem::absolute(url.path).string() : url.to_string(); + if (repoInfo.isLocal) { + if (!isAbsolute(url.path)) { + warn( + "Fetching Git repository '%s', which uses a path relative to the current directory. " + "This is not supported and will stop working in a future release.", + url); + } + repoInfo.url = std::filesystem::absolute(url.path).string(); + } else + repoInfo.url = url.to_string(); // If this is a local directory and no ref or revision is // given, then allow the use of an unclean working tree. From 3716ded8df6de1f38527b6b3fab72427f92c73f3 Mon Sep 17 00:00:00 2001 From: Andy Hamon Date: Thu, 16 Jan 2025 00:24:47 -0800 Subject: [PATCH 658/718] nix-env: add a --priority flag to --install nix-env can read priorities from a derivations meta attributes, but this only works when installing a nix expression. nix-env can also install bare store paths, however meta attributes are not readable in that case. This means that a store path can not be installed with a specific priority. Some cases where it is advantageous to install a store path: a remote host following a `nix copy`, or any time you want to save some evaluation time and happen to already know the store path. This PR addresses this shortcoming by adding a --priority flag to nix-env --install. --- .../source/command-ref/nix-env/install.md | 6 +++- src/nix-env/nix-env.cc | 35 ++++++++++++------- tests/functional/user-envs-test-case.sh | 10 +++++- 3 files changed, 37 insertions(+), 14 deletions(-) diff --git a/doc/manual/source/command-ref/nix-env/install.md b/doc/manual/source/command-ref/nix-env/install.md index 748dd1e7a..aa5c2fbba 100644 --- a/doc/manual/source/command-ref/nix-env/install.md +++ b/doc/manual/source/command-ref/nix-env/install.md @@ -11,6 +11,7 @@ [`--from-profile` *path*] [`--preserve-installed` | `-P`] [`--remove-all` | `-r`] + [`--priority` *priority*] # Description @@ -61,6 +62,10 @@ The arguments *args* map to store paths in a number of possible ways: The derivations returned by those function calls are installed. This allows derivations to be specified in an unambiguous way, which is necessary if there are multiple derivations with the same name. +- If `--priority` *priority* is given, the priority of the derivations being installed is set to *priority*. + This can be used to override the priority of the derivations being installed. + This is useful if *args* are [store paths], which don't have any priority information. + - If *args* are [store derivations](@docroot@/glossary.md#gloss-store-derivation), then these are [realised], and the resulting output paths are installed. - If *args* are [store paths] that are not store derivations, then these are [realised] and installed. @@ -235,4 +240,3 @@ channel: ```console $ nix-env --file https://github.com/NixOS/nixpkgs/archive/nixos-14.12.tar.gz --install --attr firefox ``` - diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index e9eb52708..fa6d6afb3 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -501,9 +501,17 @@ static bool keep(PackageInfo & drv) return drv.queryMetaBool("keep", false); } +static void setMetaFlag(EvalState & state, PackageInfo & drv, + const std::string & name, const std::string & value) +{ + auto v = state.allocValue(); + v->mkString(value); + drv.setMeta(name, v); +} + static void installDerivations(Globals & globals, - const Strings & args, const Path & profile) + const Strings & args, const Path & profile, std::optional priority) { debug("installing derivations"); @@ -527,6 +535,11 @@ static void installDerivations(Globals & globals, newNames.insert(DrvName(i.queryName()).name); } + if (priority) { + for (auto & drv : newElems) { + setMetaFlag(*globals.state, drv, "priority", std::to_string((priority.value()))); + } + } while (true) { auto lockToken = optimisticLockProfile(profile); @@ -564,6 +577,7 @@ static void installDerivations(Globals & globals, static void opInstall(Globals & globals, Strings opFlags, Strings opArgs) { + std::optional priority; for (Strings::iterator i = opFlags.begin(); i != opFlags.end(); ) { auto arg = *i++; if (parseInstallSourceOptions(globals, i, opFlags, arg)) ; @@ -571,10 +585,15 @@ static void opInstall(Globals & globals, Strings opFlags, Strings opArgs) globals.preserveInstalled = true; else if (arg == "--remove-all" || arg == "-r") globals.removeAll = true; + else if (arg == "--priority") { + if (i == opFlags.end()) + throw UsageError("'%1%' requires an argument", arg); + priority = std::stoi(*i++); + } else throw UsageError("unknown flag '%1%'", arg); } - installDerivations(globals, opArgs, globals.profile); + installDerivations(globals, opArgs, globals.profile, priority); } @@ -689,15 +708,6 @@ static void opUpgrade(Globals & globals, Strings opFlags, Strings opArgs) } -static void setMetaFlag(EvalState & state, PackageInfo & drv, - const std::string & name, const std::string & value) -{ - auto v = state.allocValue(); - v->mkString(value); - drv.setMeta(name, v); -} - - static void opSetFlag(Globals & globals, Strings opFlags, Strings opArgs) { if (opFlags.size() > 0) @@ -1507,7 +1517,8 @@ static int main_nix_env(int argc, char * * argv) opFlags.push_back(*arg); /* FIXME: hacky */ if (*arg == "--from-profile" || - (op == opQuery && (*arg == "--attr" || *arg == "-A"))) + (op == opQuery && (*arg == "--attr" || *arg == "-A")) || + (op == opInstall && (*arg == "--priority"))) opFlags.push_back(getArg(*arg, arg, end)); } else diff --git a/tests/functional/user-envs-test-case.sh b/tests/functional/user-envs-test-case.sh index 117c6c7a4..3483a4600 100644 --- a/tests/functional/user-envs-test-case.sh +++ b/tests/functional/user-envs-test-case.sh @@ -173,13 +173,21 @@ nix-env -q '*' | grepQuiet bar-0.1.1 # Test priorities: foo-0.1 has a lower priority than foo-1.0, so it # should be possible to install both without a collision. Also test -# ‘--set-flag priority’ to manually override the declared priorities. +# '-i --priority' and '--set-flag priority' to manually override the +# declared priorities. nix-env -e '*' nix-env -i foo-0.1 foo-1.0 [ "$($profiles/test/bin/foo)" = "foo-1.0" ] nix-env --set-flag priority 1 foo-0.1 [ "$($profiles/test/bin/foo)" = "foo-0.1" ] +# Priorities can be overridden with the --priority flag +nix-env -e '*' +nix-env -i foo-1.0 +[ "$($profiles/test/bin/foo)" = "foo-1.0" ] +nix-env -i --priority 1 foo-0.1 +[ "$($profiles/test/bin/foo)" = "foo-0.1" ] + # Test nix-env --set. nix-env --set $outPath10 [ "$(nix-store -q --resolve $profiles/test)" = $outPath10 ] From 6ea339ce8a5f0e925f601990c9fb0c700be29187 Mon Sep 17 00:00:00 2001 From: Andy Hamon Date: Thu, 16 Jan 2025 11:53:43 -0800 Subject: [PATCH 659/718] Update src/nix-env/nix-env.cc Co-authored-by: Eelco Dolstra --- src/nix-env/nix-env.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index fa6d6afb3..c99c1088e 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -588,7 +588,9 @@ static void opInstall(Globals & globals, Strings opFlags, Strings opArgs) else if (arg == "--priority") { if (i == opFlags.end()) throw UsageError("'%1%' requires an argument", arg); - priority = std::stoi(*i++); + priority = string2Int(*i++); + if (!priority) + throw UsageError("'--priority' requires an integer argument"); } else throw UsageError("unknown flag '%1%'", arg); } From 5807b5cda0198ec96688039eab42ec0e6a86ed27 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 16 Jan 2025 23:44:18 +0100 Subject: [PATCH 660/718] Trivial changes from lazy-trees Rename allowLookup -> useRegistries, rename lockRootPath -> followsPrefix, drop an unnecessary getFlake() variant. --- src/libflake/flake/flake.cc | 53 ++++++++++++++++++++----------------- src/libflake/flake/flake.hh | 2 +- 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/src/libflake/flake/flake.cc b/src/libflake/flake/flake.cc index 4e70b4089..cac39f8ab 100644 --- a/src/libflake/flake/flake.cc +++ b/src/libflake/flake/flake.cc @@ -43,7 +43,7 @@ static std::optional lookupInFlakeCache( static std::tuple fetchOrSubstituteTree( EvalState & state, const FlakeRef & originalRef, - bool allowLookup, + bool useRegistries, FlakeCache & flakeCache) { auto fetched = lookupInFlakeCache(flakeCache, originalRef); @@ -54,7 +54,7 @@ static std::tuple fetchOrSubstituteTree( auto [storePath, lockedRef] = originalRef.fetchTree(state.store); fetched.emplace(FetchedFlake{.lockedRef = lockedRef, .storePath = storePath}); } else { - if (allowLookup) { + if (useRegistries) { resolvedRef = originalRef.resolve( state.store, [](fetchers::Registry::RegistryType type) { @@ -105,7 +105,7 @@ static std::map parseFlakeInputs( EvalState & state, Value * value, const PosIdx pos, - InputPath lockRootPath, + const InputPath & lockRootPath, const SourcePath & flakeDir); static FlakeInput parseFlakeInput( @@ -113,7 +113,7 @@ static FlakeInput parseFlakeInput( std::string_view inputName, Value * value, const PosIdx pos, - InputPath lockRootPath, + const InputPath & lockRootPath, const SourcePath & flakeDir) { expectType(state, nAttrs, *value, pos); @@ -220,7 +220,7 @@ static std::map parseFlakeInputs( EvalState & state, Value * value, const PosIdx pos, - InputPath lockRootPath, + const InputPath & lockRootPath, const SourcePath & flakeDir) { std::map inputs; @@ -345,25 +345,20 @@ static Flake readFlake( static Flake getFlake( EvalState & state, const FlakeRef & originalRef, - bool allowLookup, + bool useRegistries, FlakeCache & flakeCache, - InputPath lockRootPath) + const InputPath & lockRootPath) { auto [storePath, resolvedRef, lockedRef] = fetchOrSubstituteTree( - state, originalRef, allowLookup, flakeCache); + state, originalRef, useRegistries, flakeCache); return readFlake(state, originalRef, resolvedRef, lockedRef, state.rootPath(state.store->toRealPath(storePath)), lockRootPath); } -Flake getFlake(EvalState & state, const FlakeRef & originalRef, bool allowLookup, FlakeCache & flakeCache) -{ - return getFlake(state, originalRef, allowLookup, flakeCache, {}); -} - -Flake getFlake(EvalState & state, const FlakeRef & originalRef, bool allowLookup) +Flake getFlake(EvalState & state, const FlakeRef & originalRef, bool useRegistries) { FlakeCache flakeCache; - return getFlake(state, originalRef, allowLookup, flakeCache); + return getFlake(state, originalRef, useRegistries, flakeCache, {}); } static LockFile readLockFile( @@ -390,7 +385,7 @@ LockedFlake lockFlake( auto useRegistries = lockFlags.useRegistries.value_or(settings.useRegistries); - auto flake = getFlake(state, topRef, useRegistries, flakeCache); + auto flake = getFlake(state, topRef, useRegistries, flakeCache, {}); if (lockFlags.applyNixConfig) { flake.config.apply(settings); @@ -445,7 +440,7 @@ LockedFlake lockFlake( ref node, const InputPath & inputPathPrefix, std::shared_ptr oldNode, - const InputPath & lockRootPath, + const InputPath & followsPrefix, const SourcePath & sourcePath, bool trustLock)> computeLocks; @@ -461,7 +456,11 @@ LockedFlake lockFlake( /* The old node, if any, from which locks can be copied. */ std::shared_ptr oldNode, - const InputPath & lockRootPath, + /* The prefix relative to which 'follows' should be + interpreted. When a node is initially locked, it's + relative to the node's flake; when it's already locked, + it's relative to the root of the lock file. */ + const InputPath & followsPrefix, /* The source path of this node's flake. */ const SourcePath & sourcePath, bool trustLock) @@ -633,7 +632,7 @@ LockedFlake lockFlake( break; } } - auto absoluteFollows(lockRootPath); + auto absoluteFollows(followsPrefix); absoluteFollows.insert(absoluteFollows.end(), follows->begin(), follows->end()); fakeInputs.emplace(i.first, FlakeInput { .follows = absoluteFollows, @@ -645,9 +644,10 @@ LockedFlake lockFlake( if (mustRefetch) { auto inputFlake = getInputFlake(); nodePaths.emplace(childNode, inputFlake.path.parent()); - computeLocks(inputFlake.inputs, childNode, inputPath, oldLock, lockRootPath, inputFlake.path, false); + computeLocks(inputFlake.inputs, childNode, inputPath, oldLock, followsPrefix, + inputFlake.path, false); } else { - computeLocks(fakeInputs, childNode, inputPath, oldLock, lockRootPath, sourcePath, true); + computeLocks(fakeInputs, childNode, inputPath, oldLock, followsPrefix, sourcePath, true); } } else { @@ -672,7 +672,11 @@ LockedFlake lockFlake( if (input.isFlake) { auto inputFlake = getInputFlake(); - auto childNode = make_ref(inputFlake.lockedRef, ref, true, overridenParentPath); + auto childNode = make_ref( + inputFlake.lockedRef, + ref, + true, + overridenParentPath); node->inputs.insert_or_assign(id, childNode); @@ -693,7 +697,7 @@ LockedFlake lockFlake( oldLock ? std::dynamic_pointer_cast(oldLock) : readLockFile(settings, state.fetchSettings, inputFlake.lockFilePath()).root.get_ptr(), - oldLock ? lockRootPath : inputPath, + oldLock ? followsPrefix : inputPath, inputFlake.path, false); } @@ -817,8 +821,7 @@ LockedFlake lockFlake( repo, so we should re-read it. FIXME: we could also just clear the 'rev' field... */ auto prevLockedRef = flake.lockedRef; - FlakeCache dummyCache; - flake = getFlake(state, topRef, useRegistries, dummyCache); + flake = getFlake(state, topRef, useRegistries); if (lockFlags.commitLockFile && flake.lockedRef.input.getRev() && diff --git a/src/libflake/flake/flake.hh b/src/libflake/flake/flake.hh index f85671a41..9ab661fce 100644 --- a/src/libflake/flake/flake.hh +++ b/src/libflake/flake/flake.hh @@ -110,7 +110,7 @@ struct Flake } }; -Flake getFlake(EvalState & state, const FlakeRef & flakeRef, bool allowLookup); +Flake getFlake(EvalState & state, const FlakeRef & flakeRef, bool useRegistries); /** * Fingerprint of a locked flake; used as a cache key. From f0271090b24035ff5f19899f9971519854738e3b Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 16 Jan 2025 23:47:57 +0100 Subject: [PATCH 661/718] Drop unused 'settings' argument --- src/libflake/flake/flake.cc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libflake/flake/flake.cc b/src/libflake/flake/flake.cc index cac39f8ab..873a26d5c 100644 --- a/src/libflake/flake/flake.cc +++ b/src/libflake/flake/flake.cc @@ -362,7 +362,6 @@ Flake getFlake(EvalState & state, const FlakeRef & originalRef, bool useRegistri } static LockFile readLockFile( - const Settings & settings, const fetchers::Settings & fetchSettings, const SourcePath & lockFilePath) { @@ -398,7 +397,6 @@ LockedFlake lockFlake( } auto oldLockFile = readLockFile( - settings, state.fetchSettings, lockFlags.referenceLockFilePath.value_or( flake.lockFilePath())); @@ -696,7 +694,7 @@ LockedFlake lockFlake( inputFlake.inputs, childNode, inputPath, oldLock ? std::dynamic_pointer_cast(oldLock) - : readLockFile(settings, state.fetchSettings, inputFlake.lockFilePath()).root.get_ptr(), + : readLockFile(state.fetchSettings, inputFlake.lockFilePath()).root.get_ptr(), oldLock ? followsPrefix : inputPath, inputFlake.path, false); From 3197c19a31f5ce42b099d257b6ba22fb25e707c4 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 17 Jan 2025 12:33:23 +0100 Subject: [PATCH 662/718] Add link to tracking issue --- src/libfetchers/git.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libfetchers/git.cc b/src/libfetchers/git.cc index 3f196da54..5a9679199 100644 --- a/src/libfetchers/git.cc +++ b/src/libfetchers/git.cc @@ -439,7 +439,8 @@ struct GitInputScheme : InputScheme if (!isAbsolute(url.path)) { warn( "Fetching Git repository '%s', which uses a path relative to the current directory. " - "This is not supported and will stop working in a future release.", + "This is not supported and will stop working in a future release. " + "See https://github.com/NixOS/nix/issues/12281 for details.", url); } repoInfo.url = std::filesystem::absolute(url.path).string(); From 9003343b5345622399571d8e232b7f94ec3aec28 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 17 Jan 2025 13:11:07 +0100 Subject: [PATCH 663/718] Git fetcher: Replace RepoInfo::url by a std::variant Previously the 'url' field was either a path or a URL, depending on 'isLocal'. This replaces both fields by a std::variant, which is more type-safe. --- src/libfetchers/git.cc | 122 +++++++++++++++++++++++++---------------- 1 file changed, 74 insertions(+), 48 deletions(-) diff --git a/src/libfetchers/git.cc b/src/libfetchers/git.cc index 5a9679199..bca4b2d38 100644 --- a/src/libfetchers/git.cc +++ b/src/libfetchers/git.cc @@ -297,7 +297,7 @@ struct GitInputScheme : InputScheme Strings args = {"clone"}; - args.push_back(repoInfo.url); + args.push_back(repoInfo.locationToArg()); if (auto ref = input.getRef()) { args.push_back("--branch"); @@ -311,11 +311,14 @@ struct GitInputScheme : InputScheme runProgram("git", true, args, {}, true); } + // FIXME: return std::filesystem::path std::optional getSourcePath(const Input & input) const override { auto repoInfo = getRepoInfo(input); - if (repoInfo.isLocal) return repoInfo.url; - return std::nullopt; + if (auto path = repoInfo.getPath()) + return *path; + else + return std::nullopt; } void putFile( @@ -325,14 +328,15 @@ struct GitInputScheme : InputScheme std::optional commitMsg) const override { auto repoInfo = getRepoInfo(input); - if (!repoInfo.isLocal) + auto repoPath = repoInfo.getPath(); + if (!repoPath) throw Error("cannot commit '%s' to Git repository '%s' because it's not a working tree", path, input.to_string()); - writeFile((CanonPath(repoInfo.url) / path).abs(), contents); + writeFile(*repoPath / path.rel(), contents); auto result = runProgram(RunOptions { .program = "git", - .args = {"-C", repoInfo.url, "--git-dir", repoInfo.gitDir, "check-ignore", "--quiet", std::string(path.rel())}, + .args = {"-C", *repoPath, "--git-dir", repoInfo.gitDir, "check-ignore", "--quiet", std::string(path.rel())}, }); auto exitCode = #ifndef WIN32 // TODO abstract over exit status handling on Windows @@ -345,7 +349,7 @@ struct GitInputScheme : InputScheme if (exitCode != 0) { // The path is not `.gitignore`d, we can add the file. runProgram("git", true, - { "-C", repoInfo.url, "--git-dir", repoInfo.gitDir, "add", "--intent-to-add", "--", std::string(path.rel()) }); + { "-C", *repoPath, "--git-dir", repoInfo.gitDir, "add", "--intent-to-add", "--", std::string(path.rel()) }); if (commitMsg) { @@ -353,7 +357,7 @@ struct GitInputScheme : InputScheme logger->pause(); Finally restoreLogger([]() { logger->resume(); }); runProgram("git", true, - { "-C", repoInfo.url, "--git-dir", repoInfo.gitDir, "commit", std::string(path.rel()), "-F", "-" }, + { "-C", *repoPath, "--git-dir", repoInfo.gitDir, "commit", std::string(path.rel()), "-F", "-" }, *commitMsg); } } @@ -361,24 +365,41 @@ struct GitInputScheme : InputScheme struct RepoInfo { - /* Whether this is a local, non-bare repository. */ - bool isLocal = false; + /* Either the path of the repo (for local, non-bare repos), or + the URL (which is never a `file` URL). */ + std::variant location; /* Working directory info: the complete list of files, and whether the working directory is dirty compared to HEAD. */ GitRepo::WorkdirInfo workdirInfo; - /* URL of the repo, or its path if isLocal. Never a `file` URL. */ - std::string url; + std::string locationToArg() const + { + return std::visit( + overloaded { + [&](const std::filesystem::path & path) + { return path.string(); }, + [&](const ParsedURL & url) + { return url.to_string(); } + }, location); + } + + std::optional getPath() const + { + if (auto path = std::get_if(&location)) + return *path; + else + return std::nullopt; + } void warnDirty(const Settings & settings) const { if (workdirInfo.isDirty) { if (!settings.allowDirty) - throw Error("Git tree '%s' is dirty", url); + throw Error("Git tree '%s' is dirty", locationToArg()); if (settings.warnDirty) - warn("Git tree '%s' is dirty", url); + warn("Git tree '%s' is dirty", locationToArg()); } } @@ -425,7 +446,6 @@ struct GitInputScheme : InputScheme static bool forceHttp = getEnv("_NIX_FORCE_HTTP") == "1"; // for testing auto url = parseURL(getStrAttr(input.attrs, "url")); bool isBareRepository = url.scheme == "file" && !pathExists(url.path + "/.git"); - repoInfo.isLocal = url.scheme == "file" && !forceHttp && !isBareRepository; // // FIXME: here we turn a possibly relative path into an absolute path. // This allows relative git flake inputs to be resolved against the @@ -435,7 +455,7 @@ struct GitInputScheme : InputScheme // // See: https://discourse.nixos.org/t/57783 and #9708 // - if (repoInfo.isLocal) { + if (url.scheme == "file" && !forceHttp && !isBareRepository) { if (!isAbsolute(url.path)) { warn( "Fetching Git repository '%s', which uses a path relative to the current directory. " @@ -443,14 +463,14 @@ struct GitInputScheme : InputScheme "See https://github.com/NixOS/nix/issues/12281 for details.", url); } - repoInfo.url = std::filesystem::absolute(url.path).string(); + repoInfo.location = std::filesystem::absolute(url.path); } else - repoInfo.url = url.to_string(); + repoInfo.location = url; // If this is a local directory and no ref or revision is // given, then allow the use of an unclean working tree. - if (!input.getRef() && !input.getRev() && repoInfo.isLocal) - repoInfo.workdirInfo = GitRepo::getCachedWorkdirInfo(repoInfo.url); + if (auto repoPath = repoInfo.getPath(); !input.getRef() && !input.getRev() && repoPath) + repoInfo.workdirInfo = GitRepo::getCachedWorkdirInfo(*repoPath); return repoInfo; } @@ -480,7 +500,7 @@ struct GitInputScheme : InputScheme if (auto revCountAttrs = cache->lookup(key)) return getIntAttr(*revCountAttrs, "revCount"); - Activity act(*logger, lvlChatty, actUnknown, fmt("getting Git revision count of '%s'", repoInfo.url)); + Activity act(*logger, lvlChatty, actUnknown, fmt("getting Git revision count of '%s'", repoInfo.locationToArg())); auto revCount = GitRepo::openRepo(repoDir)->getRevCount(rev); @@ -491,11 +511,15 @@ struct GitInputScheme : InputScheme std::string getDefaultRef(const RepoInfo & repoInfo) const { - auto head = repoInfo.isLocal - ? GitRepo::openRepo(repoInfo.url)->getWorkdirRef() - : readHeadCached(repoInfo.url); + auto head = std::visit( + overloaded { + [&](const std::filesystem::path & path) + { return GitRepo::openRepo(path)->getWorkdirRef(); }, + [&](const ParsedURL & url) + { return readHeadCached(url.to_string()); } + }, repoInfo.location); if (!head) { - warn("could not read HEAD ref from repo at '%s', using 'master'", repoInfo.url); + warn("could not read HEAD ref from repo at '%s', using 'master'", repoInfo.locationToArg()); return "master"; } return *head; @@ -540,12 +564,13 @@ struct GitInputScheme : InputScheme Path repoDir; - if (repoInfo.isLocal) { - repoDir = repoInfo.url; + if (auto repoPath = repoInfo.getPath()) { + repoDir = *repoPath; if (!input.getRev()) input.attrs.insert_or_assign("rev", GitRepo::openRepo(repoDir)->resolveRef(ref).gitRev()); } else { - Path cacheDir = getCachePath(repoInfo.url, getShallowAttr(input)); + auto repoUrl = std::get(repoInfo.location); + Path cacheDir = getCachePath(repoUrl.to_string(), getShallowAttr(input)); repoDir = cacheDir; repoInfo.gitDir = "."; @@ -555,7 +580,7 @@ struct GitInputScheme : InputScheme auto repo = GitRepo::openRepo(cacheDir, true, true); // We need to set the origin so resolving submodule URLs works - repo->setRemote("origin", repoInfo.url); + repo->setRemote("origin", repoUrl.to_string()); Path localRefFile = ref.compare(0, 5, "refs/") == 0 @@ -594,11 +619,11 @@ struct GitInputScheme : InputScheme ? ref : "refs/heads/" + ref; - repo->fetch(repoInfo.url, fmt("%s:%s", fetchRef, fetchRef), getShallowAttr(input)); + repo->fetch(repoUrl.to_string(), fmt("%s:%s", fetchRef, fetchRef), getShallowAttr(input)); } catch (Error & e) { if (!pathExists(localRefFile)) throw; logError(e.info()); - warn("could not update local clone of Git repository '%s'; continuing with the most recent version", repoInfo.url); + warn("could not update local clone of Git repository '%s'; continuing with the most recent version", repoInfo.locationToArg()); } try { @@ -607,8 +632,8 @@ struct GitInputScheme : InputScheme } catch (Error & e) { warn("could not update mtime for file '%s': %s", localRefFile, e.info().msg); } - if (!originalRef && !storeCachedHead(repoInfo.url, ref)) - warn("could not update cached head '%s' for '%s'", ref, repoInfo.url); + if (!originalRef && !storeCachedHead(repoUrl.to_string(), ref)) + warn("could not update cached head '%s' for '%s'", ref, repoInfo.locationToArg()); } if (auto rev = input.getRev()) { @@ -620,8 +645,7 @@ struct GitInputScheme : InputScheme "allRefs = true;" ANSI_NORMAL " to " ANSI_BOLD "fetchGit" ANSI_NORMAL ".", rev->gitRev(), ref, - repoInfo.url - ); + repoInfo.locationToArg()); } else input.attrs.insert_or_assign("rev", repo->resolveRef(ref).gitRev()); @@ -633,7 +657,7 @@ struct GitInputScheme : InputScheme auto isShallow = repo->isShallow(); if (isShallow && !getShallowAttr(input)) - throw Error("'%s' is a shallow Git repository, but shallow repositories are only allowed when `shallow = true;` is specified", repoInfo.url); + throw Error("'%s' is a shallow Git repository, but shallow repositories are only allowed when `shallow = true;` is specified", repoInfo.locationToArg()); // FIXME: check whether rev is an ancestor of ref? @@ -648,7 +672,7 @@ struct GitInputScheme : InputScheme infoAttrs.insert_or_assign("revCount", getRevCount(repoInfo, repoDir, rev)); - printTalkative("using revision %s of repo '%s'", rev.gitRev(), repoInfo.url); + printTalkative("using revision %s of repo '%s'", rev.gitRev(), repoInfo.locationToArg()); verifyCommit(input, repo); @@ -702,21 +726,23 @@ struct GitInputScheme : InputScheme RepoInfo & repoInfo, Input && input) const { + auto repoPath = repoInfo.getPath().value(); + if (getSubmodulesAttr(input)) /* Create mountpoints for the submodules. */ for (auto & submodule : repoInfo.workdirInfo.submodules) repoInfo.workdirInfo.files.insert(submodule.path); - auto repo = GitRepo::openRepo(repoInfo.url, false, false); + auto repo = GitRepo::openRepo(repoPath, false, false); auto exportIgnore = getExportIgnoreAttr(input); ref accessor = repo->getAccessor(repoInfo.workdirInfo, exportIgnore, - makeNotAllowedError(repoInfo.url)); + makeNotAllowedError(repoInfo.locationToArg())); - accessor->setPathDisplay(repoInfo.url); + accessor->setPathDisplay(repoInfo.locationToArg()); /* If the repo has submodules, return a mounted input accessor consisting of the accessor for the top-level repo and the @@ -725,10 +751,10 @@ struct GitInputScheme : InputScheme std::map> mounts; for (auto & submodule : repoInfo.workdirInfo.submodules) { - auto submodulePath = CanonPath(repoInfo.url) / submodule.path; + auto submodulePath = repoPath / submodule.path.rel(); fetchers::Attrs attrs; attrs.insert_or_assign("type", "git"); - attrs.insert_or_assign("url", submodulePath.abs()); + attrs.insert_or_assign("url", submodulePath.string()); attrs.insert_or_assign("exportIgnore", Explicit{ exportIgnore }); attrs.insert_or_assign("submodules", Explicit{ true }); // TODO: fall back to getAccessorFromCommit-like fetch when submodules aren't checked out @@ -752,7 +778,7 @@ struct GitInputScheme : InputScheme } if (!repoInfo.workdirInfo.isDirty) { - auto repo = GitRepo::openRepo(repoInfo.url); + auto repo = GitRepo::openRepo(repoPath); if (auto ref = repo->getWorkdirRef()) input.attrs.insert_or_assign("ref", *ref); @@ -762,7 +788,7 @@ struct GitInputScheme : InputScheme input.attrs.insert_or_assign("rev", rev.gitRev()); input.attrs.insert_or_assign("revCount", - rev == nullRev ? 0 : getRevCount(repoInfo, repoInfo.url, rev)); + rev == nullRev ? 0 : getRevCount(repoInfo, repoPath, rev)); verifyCommit(input, repo); } else { @@ -781,7 +807,7 @@ struct GitInputScheme : InputScheme input.attrs.insert_or_assign( "lastModified", repoInfo.workdirInfo.headRev - ? getLastModified(repoInfo, repoInfo.url, *repoInfo.workdirInfo.headRev) + ? getLastModified(repoInfo, repoPath, *repoInfo.workdirInfo.headRev) : 0); return {accessor, std::move(input)}; @@ -804,7 +830,7 @@ struct GitInputScheme : InputScheme } auto [accessor, final] = - input.getRef() || input.getRev() || !repoInfo.isLocal + input.getRef() || input.getRev() || !repoInfo.getPath() ? getAccessorFromCommit(store, repoInfo, std::move(input)) : getAccessorFromWorkdir(store, repoInfo, std::move(input)); @@ -822,14 +848,14 @@ struct GitInputScheme : InputScheme return makeFingerprint(*rev); else { auto repoInfo = getRepoInfo(input); - if (repoInfo.isLocal && repoInfo.workdirInfo.headRev && repoInfo.workdirInfo.submodules.empty()) { + if (auto repoPath = repoInfo.getPath(); repoPath && repoInfo.workdirInfo.headRev && repoInfo.workdirInfo.submodules.empty()) { /* Calculate a fingerprint that takes into account the deleted and modified/added files. */ HashSink hashSink{HashAlgorithm::SHA512}; for (auto & file : repoInfo.workdirInfo.dirtyFiles) { writeString("modified:", hashSink); writeString(file.abs(), hashSink); - dumpPath(repoInfo.url + "/" + file.abs(), hashSink); + dumpPath(*repoPath / file.rel(), hashSink); } for (auto & file : repoInfo.workdirInfo.deletedFiles) { writeString("deleted:", hashSink); From f5548c17ed61bf6e6392ece9c83eb76c9f31cf66 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 17 Jan 2025 13:17:58 +0100 Subject: [PATCH 664/718] getSourcePath(): Return std::filesystem::path --- src/libfetchers/fetchers.cc | 4 ++-- src/libfetchers/fetchers.hh | 4 ++-- src/libfetchers/git.cc | 9 ++------- src/libfetchers/mercurial.cc | 2 +- src/libfetchers/path.cc | 4 ++-- src/libflake/flake/flake.cc | 2 +- src/nix/develop.cc | 2 +- 7 files changed, 11 insertions(+), 16 deletions(-) diff --git a/src/libfetchers/fetchers.cc b/src/libfetchers/fetchers.cc index 1cfc48d52..9459db087 100644 --- a/src/libfetchers/fetchers.cc +++ b/src/libfetchers/fetchers.cc @@ -358,7 +358,7 @@ void Input::clone(const Path & destDir) const scheme->clone(*this, destDir); } -std::optional Input::getSourcePath() const +std::optional Input::getSourcePath() const { assert(scheme); return scheme->getSourcePath(*this); @@ -461,7 +461,7 @@ Input InputScheme::applyOverrides( return input; } -std::optional InputScheme::getSourcePath(const Input & input) const +std::optional InputScheme::getSourcePath(const Input & input) const { return {}; } diff --git a/src/libfetchers/fetchers.hh b/src/libfetchers/fetchers.hh index 87c7b08c0..644c267c1 100644 --- a/src/libfetchers/fetchers.hh +++ b/src/libfetchers/fetchers.hh @@ -164,7 +164,7 @@ public: void clone(const Path & destDir) const; - std::optional getSourcePath() const; + std::optional getSourcePath() const; /** * Write a file to this input, for input types that support @@ -247,7 +247,7 @@ struct InputScheme virtual void clone(const Input & input, const Path & destDir) const; - virtual std::optional getSourcePath(const Input & input) const; + virtual std::optional getSourcePath(const Input & input) const; virtual void putFile( const Input & input, diff --git a/src/libfetchers/git.cc b/src/libfetchers/git.cc index bca4b2d38..4523f49ca 100644 --- a/src/libfetchers/git.cc +++ b/src/libfetchers/git.cc @@ -311,14 +311,9 @@ struct GitInputScheme : InputScheme runProgram("git", true, args, {}, true); } - // FIXME: return std::filesystem::path - std::optional getSourcePath(const Input & input) const override + std::optional getSourcePath(const Input & input) const override { - auto repoInfo = getRepoInfo(input); - if (auto path = repoInfo.getPath()) - return *path; - else - return std::nullopt; + return getRepoInfo(input).getPath(); } void putFile( diff --git a/src/libfetchers/mercurial.cc b/src/libfetchers/mercurial.cc index c2fd8139c..61cbca202 100644 --- a/src/libfetchers/mercurial.cc +++ b/src/libfetchers/mercurial.cc @@ -126,7 +126,7 @@ struct MercurialInputScheme : InputScheme return res; } - std::optional getSourcePath(const Input & input) const override + std::optional getSourcePath(const Input & input) const override { auto url = parseURL(getStrAttr(input.attrs, "url")); if (url.scheme == "file" && !input.getRef() && !input.getRev()) diff --git a/src/libfetchers/path.cc b/src/libfetchers/path.cc index 351e21a1b..9d1cce0f3 100644 --- a/src/libfetchers/path.cc +++ b/src/libfetchers/path.cc @@ -80,9 +80,9 @@ struct PathInputScheme : InputScheme }; } - std::optional getSourcePath(const Input & input) const override + std::optional getSourcePath(const Input & input) const override { - return getStrAttr(input.attrs, "path"); + return getAbsPath(input); } void putFile( diff --git a/src/libflake/flake/flake.cc b/src/libflake/flake/flake.cc index 873a26d5c..c2145ab39 100644 --- a/src/libflake/flake/flake.cc +++ b/src/libflake/flake/flake.cc @@ -781,7 +781,7 @@ LockedFlake lockFlake( writeFile(*lockFlags.outputLockFilePath, newLockFileS); } else { auto relPath = (topRef.subdir == "" ? "" : topRef.subdir + "/") + "flake.lock"; - auto outputLockFilePath = *sourcePath + "/" + relPath; + auto outputLockFilePath = *sourcePath / relPath; bool lockFileExists = pathExists(outputLockFilePath); diff --git a/src/nix/develop.cc b/src/nix/develop.cc index 1736add9a..deee89aa1 100644 --- a/src/nix/develop.cc +++ b/src/nix/develop.cc @@ -696,7 +696,7 @@ struct CmdDevelop : Common, MixEnvironment auto sourcePath = installableFlake->getLockedFlake()->flake.resolvedRef.input.getSourcePath(); if (sourcePath) { if (chdir(sourcePath->c_str()) == -1) { - throw SysError("chdir to '%s' failed", *sourcePath); + throw SysError("chdir to %s failed", *sourcePath); } } } From c59aa3ec8723cc0afe2f7dda4755a3951710c851 Mon Sep 17 00:00:00 2001 From: Ilja Kotirinta Date: Mon, 20 Jan 2025 14:03:29 +0200 Subject: [PATCH 665/718] Remove character not needed for a command --- doc/manual/source/installation/uninstall.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/manual/source/installation/uninstall.md b/doc/manual/source/installation/uninstall.md index 47689a16e..8d45da6bb 100644 --- a/doc/manual/source/installation/uninstall.md +++ b/doc/manual/source/installation/uninstall.md @@ -160,6 +160,6 @@ which you may remove. To remove a [single-user installation](./installing-binary.md#single-user-installation) of Nix, run: ```console -$ rm -rf /nix ~/.nix-channels ~/.nix-defexpr ~/.nix-profile +rm -rf /nix ~/.nix-channels ~/.nix-defexpr ~/.nix-profile ``` You might also want to manually remove references to Nix from your `~/.profile`. From a8c69cc907044565f9e43371663cc8315602b28a Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 20 Jan 2025 13:22:50 +0100 Subject: [PATCH 666/718] processGraph(): Don't throw ThreadPoolShutDown if there is an exception Fixes $ nix copy --derivation --to /tmp/nix /nix/store/... error: cannot enqueue a work item while the thread pool is shutting down The ThreadPoolShutDown exception was hiding the reason for the thread pool shut down, e.g. error: cannot add path '/nix/store/03sl46khd8gmjpsad7223m32ma965vy9-fix-static.patch' because it lacks a signature by a trusted key --- src/libutil/thread-pool.hh | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/libutil/thread-pool.hh b/src/libutil/thread-pool.hh index dc056481a..4adc48657 100644 --- a/src/libutil/thread-pool.hh +++ b/src/libutil/thread-pool.hh @@ -150,8 +150,16 @@ void processGraph( } }; - for (auto & node : nodes) - pool.enqueue(std::bind(worker, std::ref(node))); + for (auto & node : nodes) { + try { + pool.enqueue(std::bind(worker, std::ref(node))); + } catch (ThreadPoolShutDown &) { + /* Stop if the thread pool is shutting down. It means a + previous work item threw an exception, so process() + below will rethrow it. */ + break; + } + } pool.process(); From cc838e81818fa6d78fb2e2686eb83dacac07d7d6 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 20 Jan 2025 14:23:02 +0100 Subject: [PATCH 667/718] addMultipleToStore(): Move pathsToCopy This allows RemoteStore::addMultipleToStore() to free the Source objects early (and in particular the associated sinkToSource() buffers). This should fix #7359. For example, memory consumption of nix copy --derivation --to ssh-ng://localhost?remote-store=/tmp/nix --derivation --no-check-sigs \ /nix/store/4p9xmfgnvclqpii8pxqcwcvl9bxqy2xf-nixos-system-...drv went from 353 MB to 74 MB. --- src/libstore/remote-store.cc | 7 +++++-- src/libstore/remote-store.hh | 2 +- src/libstore/store-api.cc | 4 ++-- src/libstore/store-api.hh | 2 +- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index 69bbc64fc..87c58a690 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -534,14 +534,16 @@ void RemoteStore::addToStore(const ValidPathInfo & info, Source & source, void RemoteStore::addMultipleToStore( - PathsSource & pathsToCopy, + PathsSource && pathsToCopy, Activity & act, RepairFlag repair, CheckSigsFlag checkSigs) { auto source = sinkToSource([&](Sink & sink) { sink << pathsToCopy.size(); - for (auto & [pathInfo, pathSource] : pathsToCopy) { + std::reverse(pathsToCopy.begin(), pathsToCopy.end()); + while (!pathsToCopy.empty()) { + auto & [pathInfo, pathSource] = pathsToCopy.back(); WorkerProto::Serialise::write(*this, WorkerProto::WriteConn { .to = sink, @@ -549,6 +551,7 @@ void RemoteStore::addMultipleToStore( }, pathInfo); pathSource->drainInto(sink); + pathsToCopy.pop_back(); } }); diff --git a/src/libstore/remote-store.hh b/src/libstore/remote-store.hh index 4e1896268..ea6cd471e 100644 --- a/src/libstore/remote-store.hh +++ b/src/libstore/remote-store.hh @@ -102,7 +102,7 @@ public: CheckSigsFlag checkSigs) override; void addMultipleToStore( - PathsSource & pathsToCopy, + PathsSource && pathsToCopy, Activity & act, RepairFlag repair, CheckSigsFlag checkSigs) override; diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index 3b5167730..6cd8e47f0 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -223,7 +223,7 @@ StorePath Store::addToStore( } void Store::addMultipleToStore( - PathsSource & pathsToCopy, + PathsSource && pathsToCopy, Activity & act, RepairFlag repair, CheckSigsFlag checkSigs) @@ -1138,7 +1138,7 @@ std::map copyPaths( pathsToCopy.push_back(std::pair{infoForDst, std::move(source)}); } - dstStore.addMultipleToStore(pathsToCopy, act, repair, checkSigs); + dstStore.addMultipleToStore(std::move(pathsToCopy), act, repair, checkSigs); return pathsMap; } diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh index f45012061..474dffcb5 100644 --- a/src/libstore/store-api.hh +++ b/src/libstore/store-api.hh @@ -425,7 +425,7 @@ public: CheckSigsFlag checkSigs = CheckSigs); virtual void addMultipleToStore( - PathsSource & pathsToCopy, + PathsSource && pathsToCopy, Activity & act, RepairFlag repair = NoRepair, CheckSigsFlag checkSigs = CheckSigs); From c656725a1521e9bb6f7a1e80e00459ac05a181e4 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 20 Jan 2025 14:52:23 +0100 Subject: [PATCH 668/718] mingw: Check for S_ISSOCK --- src/libutil/posix-source-accessor.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libutil/posix-source-accessor.cc b/src/libutil/posix-source-accessor.cc index 8ee986d3f..70ad6474f 100644 --- a/src/libutil/posix-source-accessor.cc +++ b/src/libutil/posix-source-accessor.cc @@ -124,7 +124,9 @@ std::optional PosixSourceAccessor::maybeLstat(const CanonP S_ISLNK(st->st_mode) ? tSymlink : S_ISCHR(st->st_mode) ? tChar : S_ISBLK(st->st_mode) ? tBlock : +#ifdef S_ISSOCK S_ISSOCK(st->st_mode) ? tSocket : +#endif S_ISFIFO(st->st_mode) ? tFifo : tUnknown, .fileSize = S_ISREG(st->st_mode) ? std::optional(st->st_size) : std::nullopt, From d8636843b1d20ec8067281efb8082dfcd3797db5 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 20 Jan 2025 14:52:50 +0100 Subject: [PATCH 669/718] mingw: Don't do LTO This breaks the build with "symbol wrong type (4 vs 3)". https://stackoverflow.com/questions/28267100/dll-linking-failed-with-lto-using-mingw-w64 --- packaging/dependencies.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/dependencies.nix b/packaging/dependencies.nix index 08d179b82..a3d7a73e4 100644 --- a/packaging/dependencies.nix +++ b/packaging/dependencies.nix @@ -75,7 +75,7 @@ let # Users who are debugging Nix builds are expected to set the environment variable `mesonBuildType`, per the # guidance in https://github.com/NixOS/nix/blob/8a3fc27f1b63a08ac983ee46435a56cf49ebaf4a/doc/manual/source/development/debugging.md?plain=1#L10. # For this reason, we don't want to refer to `finalAttrs.mesonBuildType` here, but rather use the environment variable. - preConfigure = prevAttrs.preConfigure or "" + '' + preConfigure = prevAttrs.preConfigure or "" + lib.optionalString (!stdenv.hostPlatform.isWindows) '' case "$mesonBuildType" in release|minsize) appendToVar mesonFlags "-Db_lto=true" ;; *) appendToVar mesonFlags "-Db_lto=false" ;; From 2669e4ac4f8b1deda501587fb8d4d41b5dc9064c Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 20 Jan 2025 14:57:56 +0100 Subject: [PATCH 670/718] Add comment Co-authored-by: Robert Hensing --- src/libstore/remote-store.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index 87c58a690..6781e4743 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -541,6 +541,7 @@ void RemoteStore::addMultipleToStore( { auto source = sinkToSource([&](Sink & sink) { sink << pathsToCopy.size(); + // Reverse, so we can release memory at the original start std::reverse(pathsToCopy.begin(), pathsToCopy.end()); while (!pathsToCopy.empty()) { auto & [pathInfo, pathSource] = pathsToCopy.back(); From a78f55ef978b59419366590871966d6aa35a5959 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 20 Jan 2025 15:36:19 +0100 Subject: [PATCH 671/718] GitInputScheme: Fix mingw build Mingw apparently is less smart about coercing std::filesystem::path into strings. --- src/libfetchers/git.cc | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/libfetchers/git.cc b/src/libfetchers/git.cc index 4523f49ca..b411e112f 100644 --- a/src/libfetchers/git.cc +++ b/src/libfetchers/git.cc @@ -331,7 +331,7 @@ struct GitInputScheme : InputScheme auto result = runProgram(RunOptions { .program = "git", - .args = {"-C", *repoPath, "--git-dir", repoInfo.gitDir, "check-ignore", "--quiet", std::string(path.rel())}, + .args = {"-C", repoPath->string(), "--git-dir", repoInfo.gitDir, "check-ignore", "--quiet", std::string(path.rel())}, }); auto exitCode = #ifndef WIN32 // TODO abstract over exit status handling on Windows @@ -344,7 +344,7 @@ struct GitInputScheme : InputScheme if (exitCode != 0) { // The path is not `.gitignore`d, we can add the file. runProgram("git", true, - { "-C", *repoPath, "--git-dir", repoInfo.gitDir, "add", "--intent-to-add", "--", std::string(path.rel()) }); + { "-C", repoPath->string(), "--git-dir", repoInfo.gitDir, "add", "--intent-to-add", "--", std::string(path.rel()) }); if (commitMsg) { @@ -352,7 +352,7 @@ struct GitInputScheme : InputScheme logger->pause(); Finally restoreLogger([]() { logger->resume(); }); runProgram("git", true, - { "-C", *repoPath, "--git-dir", repoInfo.gitDir, "commit", std::string(path.rel()), "-F", "-" }, + { "-C", repoPath->string(), "--git-dir", repoInfo.gitDir, "commit", std::string(path.rel()), "-F", "-" }, *commitMsg); } } @@ -470,7 +470,7 @@ struct GitInputScheme : InputScheme return repoInfo; } - uint64_t getLastModified(const RepoInfo & repoInfo, const std::string & repoDir, const Hash & rev) const + uint64_t getLastModified(const RepoInfo & repoInfo, const std::filesystem::path & repoDir, const Hash & rev) const { Cache::Key key{"gitLastModified", {{"rev", rev.gitRev()}}}; @@ -486,7 +486,7 @@ struct GitInputScheme : InputScheme return lastModified; } - uint64_t getRevCount(const RepoInfo & repoInfo, const std::string & repoDir, const Hash & rev) const + uint64_t getRevCount(const RepoInfo & repoInfo, const std::filesystem::path & repoDir, const Hash & rev) const { Cache::Key key{"gitRevCount", {{"rev", rev.gitRev()}}}; @@ -557,7 +557,7 @@ struct GitInputScheme : InputScheme auto ref = originalRef ? *originalRef : getDefaultRef(repoInfo); input.attrs.insert_or_assign("ref", ref); - Path repoDir; + std::filesystem::path repoDir; if (auto repoPath = repoInfo.getPath()) { repoDir = *repoPath; @@ -565,22 +565,22 @@ struct GitInputScheme : InputScheme input.attrs.insert_or_assign("rev", GitRepo::openRepo(repoDir)->resolveRef(ref).gitRev()); } else { auto repoUrl = std::get(repoInfo.location); - Path cacheDir = getCachePath(repoUrl.to_string(), getShallowAttr(input)); + std::filesystem::path cacheDir = getCachePath(repoUrl.to_string(), getShallowAttr(input)); repoDir = cacheDir; repoInfo.gitDir = "."; - createDirs(dirOf(cacheDir)); - PathLocks cacheDirLock({cacheDir}); + std::filesystem::create_directories(cacheDir.parent_path()); + PathLocks cacheDirLock({cacheDir.string()}); auto repo = GitRepo::openRepo(cacheDir, true, true); // We need to set the origin so resolving submodule URLs works repo->setRemote("origin", repoUrl.to_string()); - Path localRefFile = + auto localRefFile = ref.compare(0, 5, "refs/") == 0 - ? cacheDir + "/" + ref - : cacheDir + "/refs/heads/" + ref; + ? cacheDir / ref + : cacheDir / "refs/heads" / ref; bool doFetch; time_t now = time(0); @@ -596,7 +596,7 @@ struct GitInputScheme : InputScheme /* If the local ref is older than ‘tarball-ttl’ seconds, do a git fetch to update the local ref to the remote ref. */ struct stat st; - doFetch = stat(localRefFile.c_str(), &st) != 0 || + doFetch = stat(localRefFile.string().c_str(), &st) != 0 || !isCacheFileWithinTtl(now, st); } } @@ -616,7 +616,7 @@ struct GitInputScheme : InputScheme repo->fetch(repoUrl.to_string(), fmt("%s:%s", fetchRef, fetchRef), getShallowAttr(input)); } catch (Error & e) { - if (!pathExists(localRefFile)) throw; + if (!std::filesystem::exists(localRefFile)) throw; logError(e.info()); warn("could not update local clone of Git repository '%s'; continuing with the most recent version", repoInfo.locationToArg()); } @@ -850,7 +850,7 @@ struct GitInputScheme : InputScheme for (auto & file : repoInfo.workdirInfo.dirtyFiles) { writeString("modified:", hashSink); writeString(file.abs(), hashSink); - dumpPath(*repoPath / file.rel(), hashSink); + dumpPath((*repoPath / file.rel()).string(), hashSink); } for (auto & file : repoInfo.workdirInfo.deletedFiles) { writeString("deleted:", hashSink); From 15073e86a88cd03935591dde4448354836a6b632 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 20 Jan 2025 15:47:10 +0100 Subject: [PATCH 672/718] tests: Wait for network *online* and multi-user targets This should help prevent some test stalls. By default, multi-user.target does not imply that the network is fully up. --- tests/nixos/git-submodules.nix | 4 +++- tests/nixos/nix-copy-closure.nix | 5 ++++- tests/nixos/nix-copy.nix | 5 ++++- tests/nixos/remote-builds-ssh-ng.nix | 5 ++++- tests/nixos/remote-builds.nix | 3 ++- 5 files changed, 17 insertions(+), 5 deletions(-) diff --git a/tests/nixos/git-submodules.nix b/tests/nixos/git-submodules.nix index 570b1822b..b18300a91 100644 --- a/tests/nixos/git-submodules.nix +++ b/tests/nixos/git-submodules.nix @@ -39,11 +39,13 @@ client.succeed("chmod 600 /root/.ssh/id_ed25519") # Install the SSH key on the builders. - client.wait_for_unit("network.target") + client.wait_for_unit("network-online.target") remote.succeed("mkdir -p -m 700 /root/.ssh") remote.copy_from_host("key.pub", "/root/.ssh/authorized_keys") remote.wait_for_unit("sshd") + remote.wait_for_unit("multi-user.target") + remote.wait_for_unit("network-online.target") client.succeed(f"ssh -o StrictHostKeyChecking=no {remote.name} 'echo hello world'") remote.succeed(""" diff --git a/tests/nixos/nix-copy-closure.nix b/tests/nixos/nix-copy-closure.nix index b9daa0a1f..44324e989 100644 --- a/tests/nixos/nix-copy-closure.nix +++ b/tests/nixos/nix-copy-closure.nix @@ -48,7 +48,10 @@ in { server.succeed("mkdir -m 700 /root/.ssh") server.copy_from_host("key.pub", "/root/.ssh/authorized_keys") server.wait_for_unit("sshd") - client.wait_for_unit("network.target") + server.wait_for_unit("multi-user.target") + server.wait_for_unit("network-online.target") + + client.wait_for_unit("network-online.target") client.succeed(f"ssh -o StrictHostKeyChecking=no {server.name} 'echo hello world'") # Copy the closure of package A from the client to the server. diff --git a/tests/nixos/nix-copy.nix b/tests/nixos/nix-copy.nix index 8691d0138..a6a04b52c 100644 --- a/tests/nixos/nix-copy.nix +++ b/tests/nixos/nix-copy.nix @@ -56,7 +56,10 @@ in { start_all() server.wait_for_unit("sshd") - client.wait_for_unit("network.target") + server.wait_for_unit("multi-user.target") + server.wait_for_unit("network-online.target") + + client.wait_for_unit("network-online.target") client.wait_for_unit("getty@tty1.service") # Either the prompt: ]# # or an OCR misreading of it: 1# diff --git a/tests/nixos/remote-builds-ssh-ng.nix b/tests/nixos/remote-builds-ssh-ng.nix index 926ec00fe..3562d2d2f 100644 --- a/tests/nixos/remote-builds-ssh-ng.nix +++ b/tests/nixos/remote-builds-ssh-ng.nix @@ -89,10 +89,13 @@ in client.succeed("chmod 600 /root/.ssh/id_ed25519") # Install the SSH key on the builder. - client.wait_for_unit("network.target") + client.wait_for_unit("network-online.target") builder.succeed("mkdir -p -m 700 /root/.ssh") builder.copy_from_host("key.pub", "/root/.ssh/authorized_keys") builder.wait_for_unit("sshd") + builder.wait_for_unit("multi-user.target") + builder.wait_for_unit("network-online.target") + client.succeed(f"ssh -o StrictHostKeyChecking=no {builder.name} 'echo hello world'") # Perform a build diff --git a/tests/nixos/remote-builds.nix b/tests/nixos/remote-builds.nix index 84e5176b7..4fca4b938 100644 --- a/tests/nixos/remote-builds.nix +++ b/tests/nixos/remote-builds.nix @@ -112,11 +112,12 @@ in client.succeed("chmod 600 /root/.ssh/id_ed25519") # Install the SSH key on the builders. - client.wait_for_unit("network.target") + client.wait_for_unit("network-online.target") for builder in [builder1, builder2]: builder.succeed("mkdir -p -m 700 /root/.ssh") builder.copy_from_host("key.pub", "/root/.ssh/authorized_keys") builder.wait_for_unit("sshd") + builder.wait_for_unit("network-online.target") # Make sure the builder can handle our login correctly builder.wait_for_unit("multi-user.target") # Make sure there's no funny business on the client either From 89e5047e12a9da201f35f0dc4852082b0d188392 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 20 Jan 2025 15:50:04 +0100 Subject: [PATCH 673/718] Fix libflake build on mingw --- src/libflake/flake/flake.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libflake/flake/flake.cc b/src/libflake/flake/flake.cc index c2145ab39..d4708e1f1 100644 --- a/src/libflake/flake/flake.cc +++ b/src/libflake/flake/flake.cc @@ -783,7 +783,7 @@ LockedFlake lockFlake( auto relPath = (topRef.subdir == "" ? "" : topRef.subdir + "/") + "flake.lock"; auto outputLockFilePath = *sourcePath / relPath; - bool lockFileExists = pathExists(outputLockFilePath); + bool lockFileExists = std::filesystem::exists(outputLockFilePath); auto s = chomp(diff); if (lockFileExists) { From 0c85477f8e4f77307c9e63ac9d80973370dd46b9 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 20 Jan 2025 14:48:06 +0100 Subject: [PATCH 674/718] maint: Remove perl bindings from static build for now --- packaging/everything.nix | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packaging/everything.nix b/packaging/everything.nix index 0b04d2c6d..33d1bec7f 100644 --- a/packaging/everything.nix +++ b/packaging/everything.nix @@ -61,6 +61,8 @@ let nix-store-c nix-util nix-util-c + ] ++ lib.optionals (!stdenv.hostPlatform.isStatic) [ + # Currently fails in static build nix-perl-bindings ]; installPhase = '' @@ -131,6 +133,8 @@ in # (checkInputs must be empty paths??) (runCommand "check-pkg-config" { checked = dev.tests.pkg-config; } "mkdir $out") ] ++ + lib.optionals (!stdenv.hostPlatform.isStatic) ( + # Perl currently fails in static build (if stdenv.buildPlatform.canExecute stdenv.hostPlatform then [ # TODO: add perl.tests @@ -138,7 +142,7 @@ in ] else [ nix-perl-bindings - ]); + ])); installCheckInputs = [ nix-functional-tests ]; From 2cb494f56119e202c31f59bf6f7fd8b7ad0a47c0 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 20 Jan 2025 16:06:55 +0100 Subject: [PATCH 675/718] nix upgrade-nix: Fix build on mingw --- src/nix/upgrade-nix.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nix/upgrade-nix.cc b/src/nix/upgrade-nix.cc index 28174c4fb..1e8032af6 100644 --- a/src/nix/upgrade-nix.cc +++ b/src/nix/upgrade-nix.cc @@ -97,7 +97,7 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand // FIXME: don't call an external process. runProgram(getNixBin("nix-env").string(), false, - {"--profile", profileDir, "-i", store->printStorePath(storePath), "--no-sandbox"}); + {"--profile", profileDir.string(), "-i", store->printStorePath(storePath), "--no-sandbox"}); } printInfo(ANSI_GREEN "upgrade to version %s done" ANSI_NORMAL, version); @@ -120,7 +120,7 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand // Resolve profile to /nix/var/nix/profiles/ link. while (canonPath(profileDir.string()).find("/profiles/") == std::string::npos && std::filesystem::is_symlink(profileDir)) - profileDir = readLink(profileDir); + profileDir = readLink(profileDir.string()); printInfo("found profile %s", profileDir); From 809f157a49dc0851b3199f972b0ee3a70dc4262f Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 20 Jan 2025 16:11:48 +0100 Subject: [PATCH 676/718] maint: Disable LTO for static due to build failure --- packaging/dependencies.nix | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packaging/dependencies.nix b/packaging/dependencies.nix index a3d7a73e4..22d4cf9e3 100644 --- a/packaging/dependencies.nix +++ b/packaging/dependencies.nix @@ -75,7 +75,11 @@ let # Users who are debugging Nix builds are expected to set the environment variable `mesonBuildType`, per the # guidance in https://github.com/NixOS/nix/blob/8a3fc27f1b63a08ac983ee46435a56cf49ebaf4a/doc/manual/source/development/debugging.md?plain=1#L10. # For this reason, we don't want to refer to `finalAttrs.mesonBuildType` here, but rather use the environment variable. - preConfigure = prevAttrs.preConfigure or "" + lib.optionalString (!stdenv.hostPlatform.isWindows) '' + preConfigure = prevAttrs.preConfigure or "" + lib.optionalString ( + !stdenv.hostPlatform.isWindows + # build failure + && !stdenv.hostPlatform.isStatic + ) '' case "$mesonBuildType" in release|minsize) appendToVar mesonFlags "-Db_lto=true" ;; *) appendToVar mesonFlags "-Db_lto=false" ;; From 8e05ddfd84caec7e1e0461490b2e4bc4d3ec25f5 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 20 Jan 2025 16:33:52 +0100 Subject: [PATCH 677/718] Use fs::symlink_exists --- src/libflake/flake/flake.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libflake/flake/flake.cc b/src/libflake/flake/flake.cc index d4708e1f1..06260c67a 100644 --- a/src/libflake/flake/flake.cc +++ b/src/libflake/flake/flake.cc @@ -783,7 +783,7 @@ LockedFlake lockFlake( auto relPath = (topRef.subdir == "" ? "" : topRef.subdir + "/") + "flake.lock"; auto outputLockFilePath = *sourcePath / relPath; - bool lockFileExists = std::filesystem::exists(outputLockFilePath); + bool lockFileExists = fs::symlink_exists(outputLockFilePath); auto s = chomp(diff); if (lockFileExists) { From fcc501b73025bb1be796661bbb2545c7697553aa Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 20 Jan 2025 17:06:20 +0100 Subject: [PATCH 678/718] mergify: Add automatic backport label This label will be useful for constructing queries to find backportable PRs. Specifically, those should omit both automatic backports and "backports reviewed" PRs. --- .mergify.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.mergify.yml b/.mergify.yml index 5d2bf8520..5b03feca0 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -27,6 +27,7 @@ pull_request_rules: branches: - 2.18-maintenance labels: + - automatic backport - merge-queue - name: backport patches to 2.19 @@ -37,6 +38,7 @@ pull_request_rules: branches: - 2.19-maintenance labels: + - automatic backport - merge-queue - name: backport patches to 2.20 @@ -47,6 +49,7 @@ pull_request_rules: branches: - 2.20-maintenance labels: + - automatic backport - merge-queue - name: backport patches to 2.21 @@ -57,6 +60,7 @@ pull_request_rules: branches: - 2.21-maintenance labels: + - automatic backport - merge-queue - name: backport patches to 2.22 @@ -67,6 +71,7 @@ pull_request_rules: branches: - 2.22-maintenance labels: + - automatic backport - merge-queue - name: backport patches to 2.23 @@ -77,6 +82,7 @@ pull_request_rules: branches: - 2.23-maintenance labels: + - automatic backport - merge-queue - name: backport patches to 2.24 @@ -87,6 +93,7 @@ pull_request_rules: branches: - "2.24-maintenance" labels: + - automatic backport - merge-queue - name: backport patches to 2.25 @@ -97,4 +104,5 @@ pull_request_rules: branches: - "2.25-maintenance" labels: + - automatic backport - merge-queue From 0fe92067fbdc4c40663189a39412866dddb18faa Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 20 Jan 2025 11:18:27 -0500 Subject: [PATCH 679/718] Fixes for `nix-everything` wrapper 1. Fix this eval error: https://hydra.nixos.org/jobset/nix/master#tabs-errors The dev package output (actually a separate derivation) needs to skip this for cross just as the main package output does. 2. Deduplicate libs attrset and list. 3. Move `nix-functional-tests` to `checkInputs`. With the Meson build system, we no longer need a `check` vs `install-check` distinction, so it is simpler to just keeep everything in one place. --- packaging/everything.nix | 73 ++++++++++++++++------------------------ src/perl/meson.build | 3 ++ 2 files changed, 32 insertions(+), 44 deletions(-) diff --git a/packaging/everything.nix b/packaging/everything.nix index 33d1bec7f..5761cc40b 100644 --- a/packaging/everything.nix +++ b/packaging/everything.nix @@ -42,29 +42,34 @@ }: let + libs = { + inherit + nix-util + nix-util-c + nix-store + nix-store-c + nix-fetchers + nix-expr + nix-expr-c + nix-flake + nix-flake-c + nix-main + nix-main-c + ; + } // lib.optionalAttrs (!stdenv.hostPlatform.isStatic && stdenv.buildPlatform.canExecute stdenv.hostPlatform) { + # Currently fails in static build + inherit + nix-perl-bindings + ; + }; + dev = stdenv.mkDerivation (finalAttrs: { name = "nix-${nix-cli.version}-dev"; pname = "nix"; version = nix-cli.version; dontUnpack = true; dontBuild = true; - libs = map lib.getDev [ - nix-cmd - nix-expr - nix-expr-c - nix-fetchers - nix-flake - nix-flake-c - nix-main - nix-main-c - nix-store - nix-store-c - nix-util - nix-util-c - ] ++ lib.optionals (!stdenv.hostPlatform.isStatic) [ - # Currently fails in static build - nix-perl-bindings - ]; + libs = map lib.getDev (lib.attrValues libs); installPhase = '' mkdir -p $out/nix-support echo $libs >> $out/nix-support/propagated-build-inputs @@ -129,22 +134,16 @@ in nix-fetchers-tests.tests.run nix-flake-tests.tests.run + # Make sure the functional tests have passed + nix-functional-tests + # dev bundle is ok # (checkInputs must be empty paths??) (runCommand "check-pkg-config" { checked = dev.tests.pkg-config; } "mkdir $out") - ] ++ - lib.optionals (!stdenv.hostPlatform.isStatic) ( + ] ++ lib.optionals (!stdenv.hostPlatform.isStatic && stdenv.buildPlatform.canExecute stdenv.hostPlatform) [ # Perl currently fails in static build - (if stdenv.buildPlatform.canExecute stdenv.hostPlatform - then [ - # TODO: add perl.tests - nix-perl-bindings - ] - else [ - nix-perl-bindings - ])); - installCheckInputs = [ - nix-functional-tests + # TODO: Split out tests into a separate derivation? + nix-perl-bindings ]; passthru = prevAttrs.passthru // { inherit (nix-cli) version; @@ -166,21 +165,7 @@ in disallowedReferences = nix.all; ``` */ - libs = { - inherit - nix-util - nix-util-c - nix-store - nix-store-c - nix-fetchers - nix-expr - nix-expr-c - nix-flake - nix-flake-c - nix-main - nix-main-c - ; - }; + inherit libs; tests = prevAttrs.passthru.tests or {} // { # TODO: create a proper fixpoint and: diff --git a/src/perl/meson.build b/src/perl/meson.build index 52d85fd60..7b3716c17 100644 --- a/src/perl/meson.build +++ b/src/perl/meson.build @@ -82,6 +82,9 @@ nix_store_dep = dependency('nix-store') # pkgconfig available, are not in a standard location, # and are installed into a version folder. Use the # Perl binary to give hints about perl include dir. +# +# Note that until we have a better solution for this, cross-compiling +# the perl bindings does not appear to be possible. #------------------------------------------------- perl_archname = run_command( perl, '-e', 'use Config; print $Config{archname};', check: true).stdout() From 6f0bdd9ae70c9bda2d9e2e9c641c9f193429fcd3 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 20 Jan 2025 18:21:07 +0100 Subject: [PATCH 680/718] tests: Wait for network *online* targets More prevalent than I thought in 15073e86a See also https://github.com/NixOS/nix/actions/runs/12872412321/job/35887830320?pr=12310 which is a failed github-flakes test without "Network is Online" --- tests/nixos/git-submodules.nix | 1 + tests/nixos/github-flakes.nix | 2 ++ tests/nixos/nix-docker.nix | 1 + tests/nixos/nss-preload.nix | 2 ++ tests/nixos/s3-binary-cache-store.nix | 3 +++ tests/nixos/sourcehut-flakes.nix | 2 ++ 6 files changed, 11 insertions(+) diff --git a/tests/nixos/git-submodules.nix b/tests/nixos/git-submodules.nix index b18300a91..a82ddf418 100644 --- a/tests/nixos/git-submodules.nix +++ b/tests/nixos/git-submodules.nix @@ -46,6 +46,7 @@ remote.wait_for_unit("sshd") remote.wait_for_unit("multi-user.target") remote.wait_for_unit("network-online.target") + client.wait_for_unit("network-online.target") client.succeed(f"ssh -o StrictHostKeyChecking=no {remote.name} 'echo hello world'") remote.succeed(""" diff --git a/tests/nixos/github-flakes.nix b/tests/nixos/github-flakes.nix index 8e646f6dd..69d1df410 100644 --- a/tests/nixos/github-flakes.nix +++ b/tests/nixos/github-flakes.nix @@ -161,7 +161,9 @@ in github.succeed("cat /var/log/httpd/*.log >&2") github.wait_for_unit("httpd.service") + github.wait_for_unit("network-online.target") + client.wait_for_unit("network-online.target") client.succeed("curl -v https://github.com/ >&2") out = client.succeed("nix registry list") print(out) diff --git a/tests/nixos/nix-docker.nix b/tests/nixos/nix-docker.nix index dfd508988..00b04482c 100644 --- a/tests/nixos/nix-docker.nix +++ b/tests/nixos/nix-docker.nix @@ -37,6 +37,7 @@ in { testScript = { nodes }: '' cache.wait_for_unit("harmonia.service") + cache.wait_for_unit("network-online.target") machine.succeed("mkdir -p /etc/containers") machine.succeed("""echo '{"default":[{"type":"insecureAcceptAnything"}]}' > /etc/containers/policy.json""") diff --git a/tests/nixos/nss-preload.nix b/tests/nixos/nss-preload.nix index 610769c8d..b7e704f39 100644 --- a/tests/nixos/nss-preload.nix +++ b/tests/nixos/nss-preload.nix @@ -102,6 +102,7 @@ in }; testScript = { nodes, ... }: '' + http_dns.wait_for_unit("network-online.target") http_dns.wait_for_unit("nginx") http_dns.wait_for_open_port(80) http_dns.wait_for_unit("unbound") @@ -109,6 +110,7 @@ in client.start() client.wait_for_unit('multi-user.target') + client.wait_for_unit('network-online.target') with subtest("can fetch data from a remote server outside sandbox"): client.succeed("nix --version >&2") diff --git a/tests/nixos/s3-binary-cache-store.nix b/tests/nixos/s3-binary-cache-store.nix index 83b85c032..f8659b830 100644 --- a/tests/nixos/s3-binary-cache-store.nix +++ b/tests/nixos/s3-binary-cache-store.nix @@ -52,12 +52,15 @@ in { # Create a binary cache. server.wait_for_unit("minio") + server.wait_for_unit("network-online.target") server.succeed("mc config host add minio http://localhost:9000 ${accessKey} ${secretKey} --api s3v4") server.succeed("mc mb minio/my-cache") server.succeed("${env} nix copy --to '${storeUrl}' ${pkgA}") + client.wait_for_unit("network-online.target") + # Test fetchurl on s3:// URLs while we're at it. client.succeed("${env} nix eval --impure --expr 'builtins.fetchurl { name = \"foo\"; url = \"s3://my-cache/nix-cache-info?endpoint=http://server:9000®ion=eu-west-1\"; }'") diff --git a/tests/nixos/sourcehut-flakes.nix b/tests/nixos/sourcehut-flakes.nix index 04f3590e1..2f469457a 100644 --- a/tests/nixos/sourcehut-flakes.nix +++ b/tests/nixos/sourcehut-flakes.nix @@ -122,6 +122,8 @@ in start_all() sourcehut.wait_for_unit("httpd.service") + sourcehut.wait_for_unit("network-online.target") + client.wait_for_unit("network-online.target") client.succeed("curl -v https://git.sr.ht/ >&2") client.succeed("nix registry list | grep nixpkgs") From 6b987206ce51839a41cd0540236e5f5ecdc6940e Mon Sep 17 00:00:00 2001 From: Mike Kusold Date: Mon, 20 Jan 2025 11:04:53 -0700 Subject: [PATCH 681/718] Add unit of measurement for download-buffer-size I started getting these warnings `warning: download buffer is full; consider increasing the 'download-buffer-size' setting` but the documentation does not make it obvious what unit of measurement it accepts. --- src/libstore/filetransfer.hh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libstore/filetransfer.hh b/src/libstore/filetransfer.hh index d836ab2c4..e9a166af7 100644 --- a/src/libstore/filetransfer.hh +++ b/src/libstore/filetransfer.hh @@ -50,8 +50,9 @@ struct FileTransferSettings : Config Setting downloadBufferSize{this, 64 * 1024 * 1024, "download-buffer-size", R"( - The size of Nix's internal download buffer during `curl` transfers. If data is + The size of Nix's internal download buffer in bytes during `curl` transfers. If data is not processed quickly enough to exceed the size of this buffer, downloads may stall. + The default is 67108864 (64MB). )"}; }; From f0c209fb14cb511370ea2b7787d9a8dd90070162 Mon Sep 17 00:00:00 2001 From: Mike Kusold Date: Mon, 20 Jan 2025 11:32:47 -0700 Subject: [PATCH 682/718] Use standardize units for megabytes Co-authored-by: Eelco Dolstra --- src/libstore/filetransfer.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstore/filetransfer.hh b/src/libstore/filetransfer.hh index e9a166af7..43a384d71 100644 --- a/src/libstore/filetransfer.hh +++ b/src/libstore/filetransfer.hh @@ -52,7 +52,7 @@ struct FileTransferSettings : Config R"( The size of Nix's internal download buffer in bytes during `curl` transfers. If data is not processed quickly enough to exceed the size of this buffer, downloads may stall. - The default is 67108864 (64MB). + The default is 67108864 (64 MiB). )"}; }; From a82c63f5d8bdc916dc01a77c177f58d766d38680 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 21 Jan 2025 09:54:45 +0100 Subject: [PATCH 683/718] Fix nix-everything build https://hydra.nixos.org/build/286306734 --- packaging/everything.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/packaging/everything.nix b/packaging/everything.nix index 5761cc40b..7ca878d8d 100644 --- a/packaging/everything.nix +++ b/packaging/everything.nix @@ -55,6 +55,7 @@ let nix-flake-c nix-main nix-main-c + nix-cmd ; } // lib.optionalAttrs (!stdenv.hostPlatform.isStatic && stdenv.buildPlatform.canExecute stdenv.hostPlatform) { # Currently fails in static build From 27c9f7ef78d0119e9e76d7c3ab987c547709ef73 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 21 Jan 2025 14:07:20 +0100 Subject: [PATCH 684/718] Fix name --- tests/nixos/fetchurl.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/nixos/fetchurl.nix b/tests/nixos/fetchurl.nix index 243c0cacc..7d56fd7d7 100644 --- a/tests/nixos/fetchurl.nix +++ b/tests/nixos/fetchurl.nix @@ -22,7 +22,7 @@ let in { - name = "nss-preload"; + name = "fetchurl"; nodes = { machine = { pkgs, ... }: { From 9e324df3834148d559929549f6546661f6c53137 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 21 Jan 2025 14:09:17 +0100 Subject: [PATCH 685/718] Fix fetchurl test https://hydra.nixos.org/build/286311974 --- tests/nixos/fetchurl.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/nixos/fetchurl.nix b/tests/nixos/fetchurl.nix index 7d56fd7d7..bfae8deec 100644 --- a/tests/nixos/fetchurl.nix +++ b/tests/nixos/fetchurl.nix @@ -76,7 +76,7 @@ in # Fetching from a server with an untrusted cert should fail. err = machine.fail("nix build --no-substitute --expr 'import { url = \"https://bad/index.html\"; hash = \"sha256-rsBwZF/lPuOzdjBZN2E08FjMM3JHyXit0Xi2zN+wAZ8=\"; }' 2>&1") print(err) - assert "SSL certificate problem: self-signed certificate" in err + assert "SSL peer certificate or SSH remote key was not OK" in err # Fetching from a server with a trusted cert should work via environment variable override. machine.succeed("NIX_SSL_CERT_FILE=/tmp/cafile.pem nix build --no-substitute --expr 'import { url = \"https://bad/index.html\"; hash = \"sha256-rsBwZF/lPuOzdjBZN2E08FjMM3JHyXit0Xi2zN+wAZ8=\"; }'") From b09b4dc99561cb69deee2fa30f2a32d76fec8b6e Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 21 Jan 2025 18:10:12 +0100 Subject: [PATCH 686/718] x86_64-darwin: Disable LTO LTO on x86_64-darwin appears to break the ability to catch exceptions correctly (maybe just for exception types defined in different libraries). This leads to many weird test failures, e.g. https://hydra.nixos.org/build/286312387 and https://hydra.nixos.org/build/286312341. --- packaging/dependencies.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packaging/dependencies.nix b/packaging/dependencies.nix index 22d4cf9e3..acdbc9cfc 100644 --- a/packaging/dependencies.nix +++ b/packaging/dependencies.nix @@ -79,6 +79,8 @@ let !stdenv.hostPlatform.isWindows # build failure && !stdenv.hostPlatform.isStatic + # LTO breaks exception handling on x86-64-darwin. + && stdenv.system != "x86_64-darwin" ) '' case "$mesonBuildType" in release|minsize) appendToVar mesonFlags "-Db_lto=true" ;; From d8dbb71c92ec60bf872b7c33d9ffa9c563233be8 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 22 Jan 2025 11:39:09 +0100 Subject: [PATCH 687/718] release notes: 2.26.0 --- doc/manual/rl-next/ignore-local-registries.md | 22 ------ doc/manual/rl-next/nix-copy-flags.md | 18 ----- doc/manual/rl-next/nix-instantiate-raw.md | 8 -- doc/manual/rl-next/nix-sshopts-parsing.md | 21 ------ doc/manual/rl-next/relative-path-flakes.md | 12 --- doc/manual/source/SUMMARY.md.in | 1 + doc/manual/source/release-notes/rl-2.26.md | 75 +++++++++++++++++++ 7 files changed, 76 insertions(+), 81 deletions(-) delete mode 100644 doc/manual/rl-next/ignore-local-registries.md delete mode 100644 doc/manual/rl-next/nix-copy-flags.md delete mode 100644 doc/manual/rl-next/nix-instantiate-raw.md delete mode 100644 doc/manual/rl-next/nix-sshopts-parsing.md delete mode 100644 doc/manual/rl-next/relative-path-flakes.md create mode 100644 doc/manual/source/release-notes/rl-2.26.md diff --git a/doc/manual/rl-next/ignore-local-registries.md b/doc/manual/rl-next/ignore-local-registries.md deleted file mode 100644 index 8d5e333dd..000000000 --- a/doc/manual/rl-next/ignore-local-registries.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -synopsis: "Flake lock file generation now ignores local registries" -prs: [12019] ---- - -When resolving indirect flake references like `nixpkgs` in `flake.nix` files, Nix will no longer use the system and user flake registries. It will only use the global flake registry and overrides given on the command line via `--override-flake`. - -This avoids accidents where users have local registry overrides that map `nixpkgs` to a `path:` flake in the local file system, which then end up in committed lock files pushed to other users. - -In the future, we may remove the use of the registry during lock file generation altogether. It's better to explicitly specify the URL of a flake input. For example, instead of -```nix -{ - outputs = { self, nixpkgs }: { ... }; -} -``` -write -```nix -{ - inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11"; - outputs = { self, nixpkgs }: { ... }; -} -``` diff --git a/doc/manual/rl-next/nix-copy-flags.md b/doc/manual/rl-next/nix-copy-flags.md deleted file mode 100644 index f5b2b9716..000000000 --- a/doc/manual/rl-next/nix-copy-flags.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -synopsis: "`nix copy` supports `--profile` and `--out-link`" -prs: [11657] ---- - -The `nix copy` command now has flags `--profile` and `--out-link`, similar to `nix build`. `--profile` makes a profile point to the -top-level store path, while `--out-link` create symlinks to the top-level store paths. - -For example, when updating the local NixOS system profile from a NixOS system closure on a remote machine, instead of -``` -# nix copy --from ssh://server $path -# nix build --profile /nix/var/nix/profiles/system $path -``` -you can now do -``` -# nix copy --from ssh://server --profile /nix/var/nix/profiles/system $path -``` -The advantage is that this avoids a time window where *path* is not a garbage collector root, and so could be deleted by a concurrent `nix store gc` process. diff --git a/doc/manual/rl-next/nix-instantiate-raw.md b/doc/manual/rl-next/nix-instantiate-raw.md deleted file mode 100644 index fb4a72b88..000000000 --- a/doc/manual/rl-next/nix-instantiate-raw.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -synopsis: "`nix-instantiate --eval` now supports `--raw`" -prs: [12119] ---- - -The `nix-instantiate --eval` command now supports a `--raw` flag, when used -the evaluation result must be a string, which is printed verbatim without -quotation marks or escaping. diff --git a/doc/manual/rl-next/nix-sshopts-parsing.md b/doc/manual/rl-next/nix-sshopts-parsing.md deleted file mode 100644 index 65fe6f562..000000000 --- a/doc/manual/rl-next/nix-sshopts-parsing.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -synopsis: "Improved `NIX_SSHOPTS` parsing for better SSH option handling" -issues: [5181] -prs: [12020] ---- - -The parsing of the `NIX_SSHOPTS` environment variable has been improved to handle spaces and quotes correctly. -Previously, incorrectly split SSH options could cause failures in CLIs like `nix-copy-closure`, -especially when using complex ssh invocations such as `-o ProxyCommand="ssh -W %h:%p ..."`. - -This change introduces a `shellSplitString` function to ensure -that `NIX_SSHOPTS` is parsed in a manner consistent with shell -behavior, addressing common parsing errors. - -For example, the following now works as expected: - -```bash -export NIX_SSHOPTS='-o ProxyCommand="ssh -W %h:%p ..."' -``` - -This update improves the reliability of SSH-related operations using `NIX_SSHOPTS` across Nix CLIs. diff --git a/doc/manual/rl-next/relative-path-flakes.md b/doc/manual/rl-next/relative-path-flakes.md deleted file mode 100644 index 3616f3467..000000000 --- a/doc/manual/rl-next/relative-path-flakes.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -synopsis: "Support for relative path inputs" -prs: [10089] ---- - -Flakes can now refer to other flakes in the same repository using relative paths, e.g. -```nix -inputs.foo.url = "path:./foo"; -``` -uses the flake in the `foo` subdirectory of the referring flake. For more information, see the documentation on [the `path` flake input type](@docroot@/command-ref/new-cli/nix3-flake.md#path-fetcher). - -This feature required a change to the lock file format. Previous Nix versions will not be able to use lock files that have locks for relative path inputs in them. diff --git a/doc/manual/source/SUMMARY.md.in b/doc/manual/source/SUMMARY.md.in index 244bf582d..a92bca42f 100644 --- a/doc/manual/source/SUMMARY.md.in +++ b/doc/manual/source/SUMMARY.md.in @@ -130,6 +130,7 @@ - [Contributing](development/contributing.md) - [Releases](release-notes/index.md) {{#include ./SUMMARY-rl-next.md}} + - [Release 2.26 (2025-01-22)](release-notes/rl-2.26.md) - [Release 2.25 (2024-11-07)](release-notes/rl-2.25.md) - [Release 2.24 (2024-07-31)](release-notes/rl-2.24.md) - [Release 2.23 (2024-06-03)](release-notes/rl-2.23.md) diff --git a/doc/manual/source/release-notes/rl-2.26.md b/doc/manual/source/release-notes/rl-2.26.md new file mode 100644 index 000000000..6bd77003a --- /dev/null +++ b/doc/manual/source/release-notes/rl-2.26.md @@ -0,0 +1,75 @@ +# Release 2.26.0 (2025-01-22) + +- Support for relative path inputs [#10089](https://github.com/NixOS/nix/pull/10089) + + Flakes can now refer to other flakes in the same repository using relative paths, e.g. + ```nix + inputs.foo.url = "path:./foo"; + ``` + uses the flake in the `foo` subdirectory of the referring flake. For more information, see the documentation on [the `path` flake input type](@docroot@/command-ref/new-cli/nix3-flake.md#path-fetcher). + + This feature required a change to the lock file format. Previous Nix versions will not be able to use lock files that have locks for relative path inputs in them. + +- Flake lock file generation now ignores local registries [#12019](https://github.com/NixOS/nix/pull/12019) + + When resolving indirect flake references like `nixpkgs` in `flake.nix` files, Nix will no longer use the system and user flake registries. It will only use the global flake registry and overrides given on the command line via `--override-flake`. + + This avoids accidents where users have local registry overrides that map `nixpkgs` to a `path:` flake in the local file system, which then end up in committed lock files pushed to other users. + + In the future, we may remove the use of the registry during lock file generation altogether. It's better to explicitly specify the URL of a flake input. For example, instead of + ```nix + { + outputs = { self, nixpkgs }: { ... }; + } + ``` + write + ```nix + { + inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11"; + outputs = { self, nixpkgs }: { ... }; + } + ``` + +- `nix copy` supports `--profile` and `--out-link` [#11657](https://github.com/NixOS/nix/pull/11657) + + The `nix copy` command now has flags `--profile` and `--out-link`, similar to `nix build`. `--profile` makes a profile point to the + top-level store path, while `--out-link` create symlinks to the top-level store paths. + + For example, when updating the local NixOS system profile from a NixOS system closure on a remote machine, instead of + ``` + # nix copy --from ssh://server $path + # nix build --profile /nix/var/nix/profiles/system $path + ``` + you can now do + ``` + # nix copy --from ssh://server --profile /nix/var/nix/profiles/system $path + ``` + The advantage is that this avoids a time window where *path* is not a garbage collector root, and so could be deleted by a concurrent `nix store gc` process. + +- `nix-instantiate --eval` now supports `--raw` [#12119](https://github.com/NixOS/nix/pull/12119) + + The `nix-instantiate --eval` command now supports a `--raw` flag, when used + the evaluation result must be a string, which is printed verbatim without + quotation marks or escaping. + +- Improved `NIX_SSHOPTS` parsing for better SSH option handling [#5181](https://github.com/NixOS/nix/issues/5181) [#12020](https://github.com/NixOS/nix/pull/12020) + + The parsing of the `NIX_SSHOPTS` environment variable has been improved to handle spaces and quotes correctly. + Previously, incorrectly split SSH options could cause failures in commands like `nix-copy-closure`, + especially when using complex SSH invocations such as `-o ProxyCommand="ssh -W %h:%p ..."`. + + This change introduces a `shellSplitString` function to ensure + that `NIX_SSHOPTS` is parsed in a manner consistent with shell + behavior, addressing common parsing errors. + + For example, the following now works as expected: + + ```bash + export NIX_SSHOPTS='-o ProxyCommand="ssh -W %h:%p ..."' + ``` + + This update improves the reliability of SSH-related operations using `NIX_SSHOPTS` across Nix CLIs. + +# Contributors + +Querying GitHub API for f0c209fb14cb511370ea2b7787d9a8dd90070162, to get handle for kusold@users.noreply.github.com From 617bf845180678a00e0b4cfac74b9e9516475772 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 22 Jan 2025 11:55:20 +0100 Subject: [PATCH 688/718] Add a few more release notes --- doc/manual/source/release-notes/rl-2.26.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/manual/source/release-notes/rl-2.26.md b/doc/manual/source/release-notes/rl-2.26.md index 6bd77003a..85e4546e6 100644 --- a/doc/manual/source/release-notes/rl-2.26.md +++ b/doc/manual/source/release-notes/rl-2.26.md @@ -70,6 +70,12 @@ This update improves the reliability of SSH-related operations using `NIX_SSHOPTS` across Nix CLIs. +- Nix is now built using Meson + + As proposed in [RFC 132](https://github.com/NixOS/rfcs/pull/132), Nix's build system now uses Meson/Ninja. The old Make-based build system has been removed. + +- Evaluation caching now works for dirty Git workdirs [#11992](https://github.com/NixOS/nix/pull/11992) + # Contributors Querying GitHub API for f0c209fb14cb511370ea2b7787d9a8dd90070162, to get handle for kusold@users.noreply.github.com From 21f2e291762a41f55edcbb2c0789d3b741f1bad5 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 22 Jan 2025 12:01:00 +0100 Subject: [PATCH 689/718] Add release credits --- doc/manual/source/release-notes/rl-2.26.md | 49 ++++++++++++++++++- .../data/release-credits-email-to-handle.json | 36 +++++++++++++- .../data/release-credits-handle-to-name.json | 34 ++++++++++++- 3 files changed, 116 insertions(+), 3 deletions(-) diff --git a/doc/manual/source/release-notes/rl-2.26.md b/doc/manual/source/release-notes/rl-2.26.md index 85e4546e6..d2a890eb6 100644 --- a/doc/manual/source/release-notes/rl-2.26.md +++ b/doc/manual/source/release-notes/rl-2.26.md @@ -78,4 +78,51 @@ # Contributors -Querying GitHub API for f0c209fb14cb511370ea2b7787d9a8dd90070162, to get handle for kusold@users.noreply.github.com +This release was made possible by the following 45 contributors: + +- Anatoli Babenia [**(@abitrolly)**](https://github.com/abitrolly) +- Domagoj Mišković [**(@allrealmsoflife)**](https://github.com/allrealmsoflife) +- Yaroslav Bolyukin [**(@CertainLach)**](https://github.com/CertainLach) +- bryango [**(@bryango)**](https://github.com/bryango) +- tomberek [**(@tomberek)**](https://github.com/tomberek) +- Matej Urbas [**(@mupdt)**](https://github.com/mupdt) +- elikoga [**(@elikoga)**](https://github.com/elikoga) +- wh0 [**(@wh0)**](https://github.com/wh0) +- Félix [**(@picnoir)**](https://github.com/picnoir) +- Valentin Gagarin [**(@fricklerhandwerk)**](https://github.com/fricklerhandwerk) +- Gavin John [**(@Pandapip1)**](https://github.com/Pandapip1) +- Travis A. Everett [**(@abathur)**](https://github.com/abathur) +- Vladimir Panteleev [**(@CyberShadow)**](https://github.com/CyberShadow) +- Ilja [**(@suruaku)**](https://github.com/suruaku) +- Jason Yundt [**(@Jayman2000)**](https://github.com/Jayman2000) +- Mike Kusold [**(@kusold)**](https://github.com/kusold) +- Andy Hamon [**(@andrewhamon)**](https://github.com/andrewhamon) +- Brian McKenna [**(@puffnfresh)**](https://github.com/puffnfresh) +- Greg Curtis [**(@gcurtis)**](https://github.com/gcurtis) +- Andrew Poelstra [**(@apoelstra)**](https://github.com/apoelstra) +- Linus Heckemann [**(@lheckemann)**](https://github.com/lheckemann) +- Tristan Ross [**(@RossComputerGuy)**](https://github.com/RossComputerGuy) +- Dominique Martinet [**(@martinetd)**](https://github.com/martinetd) +- h0nIg [**(@h0nIg)**](https://github.com/h0nIg) +- Eelco Dolstra [**(@edolstra)**](https://github.com/edolstra) +- Shahar "Dawn" Or [**(@mightyiam)**](https://github.com/mightyiam) +- NAHO [**(@trueNAHO)**](https://github.com/trueNAHO) +- Ryan Hendrickson [**(@rhendric)**](https://github.com/rhendric) +- the-sun-will-rise-tomorrow [**(@the-sun-will-rise-tomorrow)**](https://github.com/the-sun-will-rise-tomorrow) +- Connor Baker [**(@ConnorBaker)**](https://github.com/ConnorBaker) +- Cole Helbling [**(@cole-h)**](https://github.com/cole-h) +- Jack Wilsdon [**(@jackwilsdon)**](https://github.com/jackwilsdon) +- ‮rekcäH nitraM‮ [**(@dwt)**](https://github.com/dwt) +- Martin Fischer [**(@not-my-profile)**](https://github.com/not-my-profile) +- John Ericson [**(@Ericson2314)**](https://github.com/Ericson2314) +- Graham Christensen [**(@grahamc)**](https://github.com/grahamc) +- Sergei Zimmerman [**(@xokdvium)**](https://github.com/xokdvium) +- Siddarth Kumar [**(@siddarthkay)**](https://github.com/siddarthkay) +- Sergei Trofimovich [**(@trofi)**](https://github.com/trofi) +- Robert Hensing [**(@roberth)**](https://github.com/roberth) +- Mutsuha Asada [**(@momeemt)**](https://github.com/momeemt) +- Parker Jones [**(@knotapun)**](https://github.com/knotapun) +- Jörg Thalheim [**(@Mic92)**](https://github.com/Mic92) +- dbdr [**(@dbdr)**](https://github.com/dbdr) +- myclevorname [**(@myclevorname)**](https://github.com/myclevorname) +- Philipp Otterbein diff --git a/maintainers/data/release-credits-email-to-handle.json b/maintainers/data/release-credits-email-to-handle.json index d7a238ebd..85f61f7e3 100644 --- a/maintainers/data/release-credits-email-to-handle.json +++ b/maintainers/data/release-credits-email-to-handle.json @@ -98,5 +98,39 @@ "aks.kenji@protonmail.com": "a-kenji", "54070204+0x5a4@users.noreply.github.com": "0x5a4", "brian@bmcgee.ie": "brianmcgee", - "squalus@squalus.net": "squalus" + "squalus@squalus.net": "squalus", + "kusold@users.noreply.github.com": "kusold", + "37929162+mergify[bot]@users.noreply.github.com": "mergify[bot]", + "ilja@mailbox.org": "suruaku", + "and.ham95@gmail.com": "andrewhamon", + "andy.hamon@discordapp.com": "andrewhamon", + "siddarthkay@gmail.com": "siddarthkay", + "apoelstra@wpsoftware.net": "apoelstra", + "asmadeus@codewreck.org": "martinetd", + "tristan.ross@midstall.com": "RossComputerGuy", + "bryanlais@gmail.com": "bryango", + "157494086+allrealmsoflife@users.noreply.github.com": "allrealmsoflife", + "ConnorBaker01@gmail.com": "ConnorBaker", + "me@momee.mt": "momeemt", + "martin@push-f.com": "not-my-profile", + "90870942+trueNAHO@users.noreply.github.com": "trueNAHO", + "49885263+knotapun@users.noreply.github.com": "knotapun", + "iam@lach.pw": "CertainLach", + "elikowa@gmail.com": "elikoga", + "greg.curtis@jetpack.io": "gcurtis", + "git@sphalerite.org": "lheckemann", + "mightyiampresence@gmail.com": "mightyiam", + "spamfaenger@gmx.de": "dwt", + "graham@grahamc.com": "grahamc", + "wh0@users.noreply.github.com": "wh0", + "25388474+mupdt@users.noreply.github.com": "mupdt", + "anatoli@rainforce.org": "abitrolly", + "h0nIg@users.noreply.github.com": "h0nIg", + "CyberShadow@users.noreply.github.com": "CyberShadow", + "gavinnjohn@gmail.com": "Pandapip1", + "picnoir@alternativebit.fr": "picnoir", + "140354451+myclevorname@users.noreply.github.com": "myclevorname", + "bonniot@gmail.com": "dbdr", + "jack@wilsdon.me": "jackwilsdon", + "143541718+WxNzEMof@users.noreply.github.com": "the-sun-will-rise-tomorrow" } \ No newline at end of file diff --git a/maintainers/data/release-credits-handle-to-name.json b/maintainers/data/release-credits-handle-to-name.json index 765771668..c517933eb 100644 --- a/maintainers/data/release-credits-handle-to-name.json +++ b/maintainers/data/release-credits-handle-to-name.json @@ -86,5 +86,37 @@ "Aleksanaa": "Aleksana", "YorikSar": "Yuriy Taraday", "kjeremy": "Jeremy Kolb", - "artemist": "Artemis Tosini" + "artemist": "Artemis Tosini", + "the-sun-will-rise-tomorrow": null, + "gcurtis": "Greg Curtis", + "ConnorBaker": "Connor Baker", + "abitrolly": "Anatoli Babenia", + "allrealmsoflife": "Domagoj Mi\u0161kovi\u0107", + "andrewhamon": "Andy Hamon", + "picnoir": "F\u00e9lix", + "dbdr": null, + "suruaku": "Ilja", + "jackwilsdon": "Jack Wilsdon", + "mergify[bot]": null, + "kusold": "Mike Kusold", + "lheckemann": "Linus Heckemann", + "h0nIg": null, + "grahamc": "Graham Christensen", + "not-my-profile": "Martin Fischer", + "CyberShadow": "Vladimir Panteleev", + "Pandapip1": "Gavin John", + "RossComputerGuy": "Tristan Ross", + "elikoga": null, + "martinetd": "Dominique Martinet", + "knotapun": "Parker Jones", + "mightyiam": "Shahar \"Dawn\" Or", + "siddarthkay": "Siddarth Kumar", + "apoelstra": "Andrew Poelstra", + "myclevorname": null, + "CertainLach": "Yaroslav Bolyukin", + "trueNAHO": "NAHO", + "wh0": null, + "mupdt": "Matej Urbas", + "momeemt": "Mutsuha Asada", + "dwt": "\u202erekc\u00e4H nitraM\u202e" } \ No newline at end of file From 28752fe28868f2c1a4d3c8a86a1ada94b99cce35 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 22 Jan 2025 12:16:44 +0100 Subject: [PATCH 690/718] Mark official release --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 8edc2266f..d8a458c1f 100644 --- a/flake.nix +++ b/flake.nix @@ -24,7 +24,7 @@ let inherit (nixpkgs) lib; - officialRelease = false; + officialRelease = true; linux32BitSystems = [ "i686-linux" ]; linux64BitSystems = [ "x86_64-linux" "aarch64-linux" ]; From 91e60321f617990c06216abcc6a836e12e04aa0f Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 22 Jan 2025 13:36:30 +0100 Subject: [PATCH 691/718] Bump version --- .version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.version b/.version index 7a25c70f9..f34083e03 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -2.26.0 +2.26.1 From 2301d86f32625ea9dfe87061203da45f2476afdc Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 22 Jan 2025 17:42:52 +0100 Subject: [PATCH 692/718] GitRepo::fetch(): Cleanup (cherry picked from commit bd10b859f71751e349af59349385af27aea40a13) --- src/libfetchers/git-utils.cc | 14 ++++++-------- src/libutil/util.hh | 11 +++++++++++ 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/libfetchers/git-utils.cc b/src/libfetchers/git-utils.cc index b54416b10..3b15a85ce 100644 --- a/src/libfetchers/git-utils.cc +++ b/src/libfetchers/git-utils.cc @@ -206,7 +206,8 @@ static git_packbuilder_progress PACKBUILDER_PROGRESS_CHECK_INTERRUPT = &packBuil } // extern "C" -static void initRepoAtomically(std::filesystem::path &path, bool bare) { +static void initRepoAtomically(std::filesystem::path &path, bool bare) +{ if (pathExists(path.string())) return; Path tmpDir = createTempDir(os_string_to_string(PathViewNG { std::filesystem::path(path).parent_path() })); @@ -544,13 +545,10 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this // then use code that was removed in this commit (see blame) auto dir = this->path; - Strings gitArgs; - if (shallow) { - gitArgs = { "-C", dir.string(), "fetch", "--quiet", "--force", "--depth", "1", "--", url, refspec }; - } - else { - gitArgs = { "-C", dir.string(), "fetch", "--quiet", "--force", "--", url, refspec }; - } + Strings gitArgs{"-C", dir.string(), "fetch", "--quiet", "--force"}; + if (shallow) + append(gitArgs, {"--depth", "1"}); + append(gitArgs, {std::string("--"), url, refspec}); runProgram(RunOptions { .program = "git", diff --git a/src/libutil/util.hh b/src/libutil/util.hh index 4d5683e2b..0d55cf93b 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -274,6 +274,17 @@ std::optional pop(T & c) } +/** + * Append items to a container. TODO: remove this once we can use + * C++23's `append_range()`. + */ +template +void append(C & c, std::initializer_list l) +{ + c.insert(c.end(), l.begin(), l.end()); +} + + template class Callback; From 832221650b4cf74d7f05f92e7e8cfcd1cbf5d6ad Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 22 Jan 2025 17:54:19 +0100 Subject: [PATCH 693/718] GitRepo::fetch(): Ignore $GIT_DIR Fixes #12325. (cherry picked from commit 41983dba8febc89a506d407ee9c597347bdd91b5) --- src/libfetchers/git-utils.cc | 2 +- tests/functional/common/vars.sh | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libfetchers/git-utils.cc b/src/libfetchers/git-utils.cc index 3b15a85ce..6a75daf61 100644 --- a/src/libfetchers/git-utils.cc +++ b/src/libfetchers/git-utils.cc @@ -545,7 +545,7 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this // then use code that was removed in this commit (see blame) auto dir = this->path; - Strings gitArgs{"-C", dir.string(), "fetch", "--quiet", "--force"}; + Strings gitArgs{"-C", dir.string(), "--git-dir", ".", "fetch", "--quiet", "--force"}; if (shallow) append(gitArgs, {"--depth", "1"}); append(gitArgs, {std::string("--"), url, refspec}); diff --git a/tests/functional/common/vars.sh b/tests/functional/common/vars.sh index 4b88e8526..ed4b47727 100644 --- a/tests/functional/common/vars.sh +++ b/tests/functional/common/vars.sh @@ -60,6 +60,7 @@ unset XDG_DATA_HOME unset XDG_CONFIG_HOME unset XDG_CONFIG_DIRS unset XDG_CACHE_HOME +unset GIT_DIR export IMPURE_VAR1=foo export IMPURE_VAR2=bar From 9cf3d3368e8de1083f11d9521e8331f80bcf2e98 Mon Sep 17 00:00:00 2001 From: Philipp Otterbein Date: Thu, 23 Jan 2025 02:18:27 +0100 Subject: [PATCH 694/718] libstore: fix progress bars (cherry picked from commit be97dc1efc4276e41ced2014c0a909a27f1fb848) --- src/libstore/remote-store.cc | 12 +++++++++++- src/libstore/store-api.cc | 14 ++++++-------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index 6781e4743..b230079eb 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -539,11 +539,21 @@ void RemoteStore::addMultipleToStore( RepairFlag repair, CheckSigsFlag checkSigs) { + // `addMultipleToStore` is single threaded + size_t bytesExpected = 0; + for (auto & [pathInfo, _] : pathsToCopy) { + bytesExpected += pathInfo.narSize; + } + act.setExpected(actCopyPath, bytesExpected); + auto source = sinkToSource([&](Sink & sink) { - sink << pathsToCopy.size(); + size_t nrTotal = pathsToCopy.size(); + sink << nrTotal; // Reverse, so we can release memory at the original start std::reverse(pathsToCopy.begin(), pathsToCopy.end()); while (!pathsToCopy.empty()) { + act.progress(nrTotal - pathsToCopy.size(), nrTotal, size_t(1), size_t(0)); + auto & [pathInfo, pathSource] = pathsToCopy.back(); WorkerProto::Serialise::write(*this, WorkerProto::WriteConn { diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index 6cd8e47f0..236622eae 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -242,8 +242,8 @@ void Store::addMultipleToStore( storePathsToAdd.insert(thingToAdd.first.path); } - auto showProgress = [&]() { - act.progress(nrDone, pathsToCopy.size(), nrRunning, nrFailed); + auto showProgress = [&, nrTotal = pathsToCopy.size()]() { + act.progress(nrDone, nrTotal, nrRunning, nrFailed); }; processGraph( @@ -1104,9 +1104,6 @@ std::map copyPaths( return storePathForDst; }; - // total is accessed by each copy, which are each handled in separate threads - std::atomic total = 0; - for (auto & missingPath : sortedMissing) { auto info = srcStore.queryPathInfo(missingPath); @@ -1116,9 +1113,10 @@ std::map copyPaths( ValidPathInfo infoForDst = *info; infoForDst.path = storePathForDst; - auto source = sinkToSource([&](Sink & sink) { + auto source = sinkToSource([&, narSize = info->narSize](Sink & sink) { // We can reasonably assume that the copy will happen whenever we // read the path, so log something about that at that point + uint64_t total = 0; auto srcUri = srcStore.getUri(); auto dstUri = dstStore.getUri(); auto storePathS = srcStore.printStorePath(missingPath); @@ -1129,13 +1127,13 @@ std::map copyPaths( LambdaSink progressSink([&](std::string_view data) { total += data.size(); - act.progress(total, info->narSize); + act.progress(total, narSize); }); TeeSink tee { sink, progressSink }; srcStore.narFromPath(missingPath, tee); }); - pathsToCopy.push_back(std::pair{infoForDst, std::move(source)}); + pathsToCopy.emplace_back(std::move(infoForDst), std::move(source)); } dstStore.addMultipleToStore(std::move(pathsToCopy), act, repair, checkSigs); From 90159cb197de1e2f816be716f5af09d25e316c1d Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 24 Jan 2025 12:15:07 +0100 Subject: [PATCH 695/718] EvalState::resolveLookupPathPath(): Call resolveSymlinks() before pathExists() Fixes #12339. (cherry picked from commit 00d9e7e1f43e3051b793ce1c21f6e902386b93fe) --- src/libexpr/eval.cc | 2 +- tests/functional/restricted.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 345c09e7e..19ca1a359 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -3114,7 +3114,7 @@ std::optional EvalState::resolveLookupPathPath(const LookupPath::Pat } } - if (path.pathExists()) + if (path.resolveSymlinks().pathExists()) return finish(std::move(path)); else { logWarning({ diff --git a/tests/functional/restricted.sh b/tests/functional/restricted.sh index a92a9b8a3..00ee4ddc8 100755 --- a/tests/functional/restricted.sh +++ b/tests/functional/restricted.sh @@ -23,7 +23,7 @@ nix-instantiate --restrict-eval ./simple.nix -I src1=./simple.nix -I src2=./conf (! nix-instantiate --restrict-eval --eval -E 'builtins.readFile ./simple.nix') nix-instantiate --restrict-eval --eval -E 'builtins.readFile ./simple.nix' -I src=../.. -expectStderr 1 nix-instantiate --restrict-eval --eval -E 'let __nixPath = [ { prefix = "foo"; path = ./.; } ]; in builtins.readFile ' | grepQuiet "was not found in the Nix search path" +expectStderr 1 nix-instantiate --restrict-eval --eval -E 'let __nixPath = [ { prefix = "foo"; path = ./.; } ]; in builtins.readFile ' | grepQuiet "forbidden in restricted mode" nix-instantiate --restrict-eval --eval -E 'let __nixPath = [ { prefix = "foo"; path = ./.; } ]; in builtins.readFile ' -I src=. p=$(nix eval --raw --expr "builtins.fetchurl file://${_NIX_TEST_SOURCE_DIR}/restricted.sh" --impure --restrict-eval --allowed-uris "file://${_NIX_TEST_SOURCE_DIR}") From 6cb17fd8360535413ec40bac2909885baf2c2754 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 24 Jan 2025 16:20:43 +0100 Subject: [PATCH 696/718] Bump version --- .version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.version b/.version index f34083e03..ed1d60050 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -2.26.1 +2.26.2 From 32aed360b8cb5ea4d28d7bf1ecb8300b9ceb5c2b Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Fri, 24 Jan 2025 20:40:21 +0100 Subject: [PATCH 697/718] Format .nix files This does not include any automation for the release branch, but is based on the configuration of https://github.com/NixOS/nix/pull/12349 pre-commit run -a nixfmt-rfc-style --- default.nix | 19 +- doc/manual/generate-builtins.nix | 10 +- doc/manual/generate-manpage.nix | 152 +- doc/manual/generate-settings.nix | 116 +- doc/manual/generate-store-info.nix | 51 +- doc/manual/generate-store-types.nix | 28 +- doc/manual/generate-xp-features-shortlist.nix | 10 +- doc/manual/generate-xp-features.nix | 3 +- doc/manual/package.nix | 60 +- doc/manual/utils.nix | 44 +- docker.nix | 438 +++--- flake.nix | 418 ++++-- maintainers/flake-module.nix | 1311 +++++++++-------- packaging/components.nix | 12 +- packaging/dependencies.nix | 239 +-- packaging/dev-shell.nix | 224 +-- packaging/everything.nix | 183 +-- packaging/hydra.nix | 205 ++- scripts/binary-tarball.nix | 16 +- scripts/installer.nix | 68 +- src/external-api-docs/package.nix | 20 +- src/internal-api-docs/package.nix | 44 +- src/libcmd/package.nix | 49 +- src/libexpr-c/package.nix | 13 +- src/libexpr-test-support/package.nix | 17 +- src/libexpr-tests/package.nix | 53 +- src/libexpr/call-flake.nix | 108 +- src/libexpr/fetchurl.nix | 92 +- src/libexpr/imported-drv-to-derivation.nix | 36 +- src/libexpr/package.nix | 56 +- src/libexpr/primops/derivation.nix | 31 +- src/libfetchers-tests/package.nix | 51 +- src/libfetchers/package.nix | 17 +- src/libflake-c/package.nix | 15 +- src/libflake-tests/package.nix | 55 +- src/libflake/package.nix | 19 +- src/libmain-c/package.nix | 17 +- src/libmain/package.nix | 15 +- src/libstore-c/package.nix | 13 +- src/libstore-test-support/package.nix | 17 +- src/libstore-tests/package.nix | 76 +- src/libstore/package.nix | 68 +- src/libutil-c/package.nix | 11 +- src/libutil-test-support/package.nix | 15 +- src/libutil-tests/package.nix | 51 +- src/libutil/package.nix | 28 +- src/nix-channel/unpack-channel.nix | 6 +- src/nix-env/buildenv.nix | 16 +- src/nix/package.nix | 132 +- src/perl/package.nix | 126 +- tests/functional/big-derivation-attr.nix | 21 +- tests/functional/build-hook-ca-fixed.nix | 68 +- tests/functional/build-hook.nix | 83 +- tests/functional/ca-shell.nix | 6 +- tests/functional/ca/content-addressed.nix | 26 +- tests/functional/ca/flake.nix | 2 +- tests/functional/ca/nondeterministic.nix | 33 +- tests/functional/ca/racy.nix | 1 - tests/functional/check-refs.nix | 29 +- tests/functional/check-reqs.nix | 42 +- tests/functional/check.nix | 51 +- tests/functional/dependencies.nix | 4 +- .../advanced-attributes-defaults.nix | 5 +- ...d-attributes-structured-attrs-defaults.nix | 10 +- .../advanced-attributes-structured-attrs.nix | 38 +- .../derivation/advanced-attributes.nix | 32 +- .../functional/dyn-drv/recursive-mod-json.nix | 4 +- tests/functional/export-graph.nix | 31 +- tests/functional/failing.nix | 33 +- tests/functional/filter-source.nix | 13 +- tests/functional/fixed.nix | 26 +- tests/functional/fod-failing.nix | 30 +- tests/functional/gc-concurrent.nix | 4 +- tests/functional/hash-check.nix | 20 +- tests/functional/hermetic.nix | 85 +- tests/functional/ifd.nix | 12 +- tests/functional/import-from-derivation.nix | 21 +- tests/functional/impure-derivations.nix | 64 +- .../lang-gc/issue-11141-gc-coroutine-test.nix | 94 +- ...vOutputDependencies-multi-elem-context.nix | 13 +- ...vOutputDependencies-wrong-element-kind.nix | 8 +- .../eval-fail-addErrorContext-example.nix | 14 +- .../eval-fail-assert-equal-attrs-names-2.nix | 8 +- .../eval-fail-assert-equal-attrs-names.nix | 8 +- ...al-fail-assert-equal-derivations-extra.nix | 17 +- .../eval-fail-assert-equal-derivations.nix | 18 +- ...eval-fail-assert-equal-function-direct.nix | 7 +- .../eval-fail-assert-equal-list-length.nix | 8 +- .../lang/eval-fail-assert-equal-paths.nix | 2 +- .../lang/eval-fail-assert-nested-bool.nix | 7 +- tests/functional/lang/eval-fail-assert.nix | 7 +- .../lang/eval-fail-attr-name-type.nix | 4 +- ...val-fail-attrset-merge-drops-later-rec.nix | 9 +- .../eval-fail-bad-string-interpolation-4.nix | 12 +- .../lang/eval-fail-dup-dynamic-attrs.nix | 8 +- .../lang/eval-fail-duplicate-traces.nix | 7 +- ...eval-fail-fetchurl-baseName-attrs-name.nix | 5 +- ...l-flake-ref-to-string-negative-integer.nix | 19 +- ...fail-foldlStrict-strict-op-application.nix | 8 +- .../lang/eval-fail-hashfile-missing.nix | 17 +- tests/functional/lang/eval-fail-list.nix | 2 +- .../functional/lang/eval-fail-missing-arg.nix | 13 +- .../lang/eval-fail-mutual-recursion.nix | 30 +- .../lang/eval-fail-nested-list-items.nix | 25 +- .../functional/lang/eval-fail-not-throws.nix | 2 +- .../lang/eval-fail-overflowing-add.nix | 3 +- .../lang/eval-fail-overflowing-div.nix | 3 +- .../lang/eval-fail-overflowing-mul.nix | 3 +- .../lang/eval-fail-overflowing-sub.nix | 3 +- tests/functional/lang/eval-fail-recursion.nix | 5 +- tests/functional/lang/eval-fail-remove.nix | 9 +- tests/functional/lang/eval-fail-scope-5.nix | 9 +- .../lang/eval-fail-undeclared-arg.nix | 6 +- .../lang/eval-fail-using-set-as-attr-name.nix | 8 +- tests/functional/lang/eval-okay-any-all.nix | 39 +- .../functional/lang/eval-okay-arithmetic.nix | 77 +- tests/functional/lang/eval-okay-attrnames.nix | 15 +- tests/functional/lang/eval-okay-attrs.nix | 19 +- tests/functional/lang/eval-okay-attrs2.nix | 21 +- tests/functional/lang/eval-okay-attrs3.nix | 34 +- tests/functional/lang/eval-okay-attrs4.nix | 17 +- tests/functional/lang/eval-okay-attrs6.nix | 4 +- tests/functional/lang/eval-okay-autoargs.nix | 15 +- .../lang/eval-okay-builtins-add.nix | 12 +- tests/functional/lang/eval-okay-builtins.nix | 2 +- .../lang/eval-okay-callable-attrs.nix | 11 +- tests/functional/lang/eval-okay-catattrs.nix | 6 +- tests/functional/lang/eval-okay-closure.nix | 24 +- tests/functional/lang/eval-okay-concat.nix | 16 +- tests/functional/lang/eval-okay-concatmap.nix | 8 +- .../lang/eval-okay-concatstringssep.nix | 19 +- .../lang/eval-okay-context-introspection.nix | 39 +- tests/functional/lang/eval-okay-context.nix | 11 +- .../functional/lang/eval-okay-convertHash.nix | 130 +- tests/functional/lang/eval-okay-deepseq.nix | 10 +- .../lang/eval-okay-delayed-with-inherit.nix | 13 +- .../lang/eval-okay-delayed-with.nix | 20 +- .../lang/eval-okay-dynamic-attrs-2.nix | 6 +- .../lang/eval-okay-dynamic-attrs-bare.nix | 17 +- .../lang/eval-okay-dynamic-attrs.nix | 17 +- tests/functional/lang/eval-okay-elem.nix | 11 +- .../functional/lang/eval-okay-empty-args.nix | 5 +- .../lang/eval-okay-eq-derivations.nix | 44 +- tests/functional/lang/eval-okay-eq.nix | 16 +- tests/functional/lang/eval-okay-filter.nix | 9 +- .../lang/eval-okay-flake-ref-to-string.nix | 8 +- tests/functional/lang/eval-okay-flatten.nix | 14 +- .../functional/lang/eval-okay-floor-ceil.nix | 9 +- .../eval-okay-foldlStrict-lazy-elements.nix | 5 +- ...y-foldlStrict-lazy-initial-accumulator.nix | 8 +- .../lang/eval-okay-fromjson-escapes.nix | 3 +- tests/functional/lang/eval-okay-fromjson.nix | 94 +- .../lang/eval-okay-functionargs.nix | 140 +- .../eval-okay-getattrpos-functionargs.nix | 8 +- .../functional/lang/eval-okay-getattrpos.nix | 6 +- tests/functional/lang/eval-okay-groupBy.nix | 6 +- tests/functional/lang/eval-okay-hashfile.nix | 14 +- .../functional/lang/eval-okay-hashstring.nix | 15 +- tests/functional/lang/eval-okay-if.nix | 7 +- tests/functional/lang/eval-okay-import.nix | 3 +- .../lang/eval-okay-inherit-attr-pos.nix | 12 +- .../lang/eval-okay-inherit-from.nix | 21 +- .../lang/eval-okay-intersectAttrs.nix | 45 +- tests/functional/lang/eval-okay-list.nix | 11 +- .../functional/lang/eval-okay-listtoattrs.nix | 27 +- tests/functional/lang/eval-okay-logic.nix | 3 +- tests/functional/lang/eval-okay-map.nix | 8 +- tests/functional/lang/eval-okay-mapattrs.nix | 5 +- .../lang/eval-okay-merge-dynamic-attrs.nix | 16 +- .../functional/lang/eval-okay-nested-with.nix | 4 +- tests/functional/lang/eval-okay-new-let.nix | 8 +- .../lang/eval-okay-null-dynamic-attrs.nix | 2 +- tests/functional/lang/eval-okay-overrides.nix | 8 +- .../lang/eval-okay-parse-flake-ref.nix | 2 +- tests/functional/lang/eval-okay-partition.nix | 9 +- tests/functional/lang/eval-okay-path.nix | 26 +- tests/functional/lang/eval-okay-patterns.nix | 61 +- tests/functional/lang/eval-okay-print.nix | 16 +- .../lang/eval-okay-readFileType.nix | 6 +- .../lang/eval-okay-redefine-builtin.nix | 3 +- .../functional/lang/eval-okay-regex-match.nix | 30 +- .../functional/lang/eval-okay-regex-split.nix | 213 ++- .../lang/eval-okay-regression-20220125.nix | 1 - ...val-okay-regrettable-rec-attrset-merge.nix | 9 +- tests/functional/lang/eval-okay-remove.nix | 9 +- .../lang/eval-okay-repeated-empty-attrs.nix | 5 +- .../lang/eval-okay-repeated-empty-list.nix | 5 +- .../lang/eval-okay-replacestrings.nix | 19 +- tests/functional/lang/eval-okay-scope-1.nix | 17 +- tests/functional/lang/eval-okay-scope-2.nix | 18 +- tests/functional/lang/eval-okay-scope-3.nix | 19 +- tests/functional/lang/eval-okay-scope-4.nix | 9 +- tests/functional/lang/eval-okay-scope-6.nix | 9 +- tests/functional/lang/eval-okay-scope-7.nix | 3 +- .../functional/lang/eval-okay-search-path.nix | 15 +- tests/functional/lang/eval-okay-sort.nix | 62 +- tests/functional/lang/eval-okay-string.nix | 21 +- .../lang/eval-okay-strings-as-attrs-names.nix | 6 +- .../lang/eval-okay-substring-context.nix | 13 +- .../functional/lang/eval-okay-tail-call-1.nix | 3 +- tests/functional/lang/eval-okay-tojson.nix | 39 +- tests/functional/lang/eval-okay-toxml2.nix | 9 +- tests/functional/lang/eval-okay-tryeval.nix | 5 +- tests/functional/lang/eval-okay-types.nix | 9 +- tests/functional/lang/eval-okay-versions.nix | 14 +- tests/functional/lang/eval-okay-xml.nix | 25 +- .../lang/eval-okay-zipAttrsWith.nix | 7 +- tests/functional/lang/lib.nix | 84 +- tests/functional/linux-sandbox-cert-test.nix | 11 +- tests/functional/multiple-outputs.nix | 153 +- tests/functional/nar-access.nix | 35 +- tests/functional/nested-sandboxing/runner.nix | 41 +- tests/functional/package.nix | 169 ++- tests/functional/parallel.nix | 38 +- tests/functional/path.nix | 16 +- tests/functional/readfile-context.nix | 3 +- tests/functional/recursive.nix | 8 +- .../functional/repl/doc-comment-function.nix | 7 +- tests/functional/repl/doc-comments.nix | 101 +- tests/functional/repl/doc-functor.nix | 45 +- tests/functional/secure-drv-outputs.nix | 18 +- tests/functional/shell-hello.nix | 90 +- tests/functional/shell.nix | 204 +-- tests/functional/simple-failing.nix | 9 +- tests/functional/structured-attrs-shell.nix | 11 +- tests/functional/structured-attrs.nix | 21 +- tests/functional/undefined-variable.nix | 5 +- tests/functional/user-envs.nix | 57 +- tests/installer/default.nix | 63 +- tests/nixos/authorization.nix | 157 +- tests/nixos/ca-fd-leak/default.nix | 90 +- tests/nixos/cgroups/default.nix | 57 +- tests/nixos/cgroups/hang.nix | 5 +- tests/nixos/chroot-store.nix | 52 +- tests/nixos/containers/containers.nix | 97 +- tests/nixos/containers/id-test.nix | 14 +- tests/nixos/containers/systemd-nspawn.nix | 16 +- tests/nixos/default.nix | 133 +- tests/nixos/fetch-git/default.nix | 31 +- .../test-cases/http-auth/default.nix | 3 +- .../test-cases/http-simple/default.nix | 3 +- .../test-cases/ssh-simple/default.nix | 3 +- .../fetch-git/testsupport/gitea-repo.nix | 34 +- tests/nixos/fetch-git/testsupport/gitea.nix | 74 +- tests/nixos/fetch-git/testsupport/setup.nix | 77 +- tests/nixos/fetchurl.nix | 87 +- tests/nixos/fsync.nix | 60 +- tests/nixos/functional/as-trusted-user.nix | 6 +- tests/nixos/functional/as-user.nix | 4 +- tests/nixos/functional/common.nix | 112 +- tests/nixos/functional/symlinked-home.nix | 4 +- tests/nixos/git-submodules.nix | 114 +- tests/nixos/github-flakes.nix | 318 ++-- tests/nixos/gzip-content-encoding.nix | 59 +- tests/nixos/nix-copy-closure.nix | 135 +- tests/nixos/nix-copy.nix | 184 ++- tests/nixos/nix-docker.nix | 78 +- tests/nixos/nss-preload.nix | 175 ++- tests/nixos/remote-builds-ssh-ng.nix | 157 +- tests/nixos/remote-builds.nix | 201 +-- tests/nixos/s3-binary-cache-store.nix | 121 +- tests/nixos/setuid.nix | 186 +-- tests/nixos/sourcehut-flakes.nix | 165 ++- tests/nixos/tarball-flakes.nix | 150 +- tests/nixos/user-sandboxing/default.nix | 134 +- tests/repl-completion.nix | 73 +- 266 files changed, 7443 insertions(+), 5118 deletions(-) diff --git a/default.nix b/default.nix index 2cccff28d..6466507b7 100644 --- a/default.nix +++ b/default.nix @@ -1,10 +1,9 @@ -(import - ( - let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in - fetchTarball { - url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; - sha256 = lock.nodes.flake-compat.locked.narHash; - } - ) - { src = ./.; } -).defaultNix +(import ( + let + lock = builtins.fromJSON (builtins.readFile ./flake.lock); + in + fetchTarball { + url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; + sha256 = lock.nodes.flake-compat.locked.narHash; + } +) { src = ./.; }).defaultNix diff --git a/doc/manual/generate-builtins.nix b/doc/manual/generate-builtins.nix index 37ed12a43..3649560f7 100644 --- a/doc/manual/generate-builtins.nix +++ b/doc/manual/generate-builtins.nix @@ -5,7 +5,15 @@ in builtinsInfo: let - showBuiltin = name: { doc, type ? null, args ? [ ], experimental-feature ? null, impure-only ? false }: + showBuiltin = + name: + { + doc, + type ? null, + args ? [ ], + experimental-feature ? null, + impure-only ? false, + }: let type' = optionalString (type != null) " (${type})"; diff --git a/doc/manual/generate-manpage.nix b/doc/manual/generate-manpage.nix index 791bfd2c7..31e74e17d 100644 --- a/doc/manual/generate-manpage.nix +++ b/doc/manual/generate-manpage.nix @@ -32,7 +32,13 @@ let commandInfo = fromJSON commandDump; - showCommand = { command, details, filename, toplevel }: + showCommand = + { + command, + details, + filename, + toplevel, + }: let result = '' @@ -56,26 +62,27 @@ let ${maybeOptions} ''; - showSynopsis = command: args: + showSynopsis = + command: args: let - showArgument = arg: "*${arg.label}*" + optionalString (! arg ? arity) "..."; + showArgument = arg: "*${arg.label}*" + optionalString (!arg ? arity) "..."; arguments = concatStringsSep " " (map showArgument args); - in '' + in + '' `${command}` [*option*...] ${arguments} ''; - maybeSubcommands = optionalString (details ? commands && details.commands != {}) - '' - where *subcommand* is one of the following: + maybeSubcommands = optionalString (details ? commands && details.commands != { }) '' + where *subcommand* is one of the following: - ${subcommands} - ''; + ${subcommands} + ''; - subcommands = if length categories > 1 - then listCategories - else listSubcommands details.commands; + subcommands = if length categories > 1 then listCategories else listSubcommands details.commands; - categories = sort (x: y: x.id < y.id) (unique (map (cmd: cmd.category) (attrValues details.commands))); + categories = sort (x: y: x.id < y.id) ( + unique (map (cmd: cmd.category) (attrValues details.commands)) + ); listCategories = concatStrings (map showCategory categories); @@ -99,38 +106,39 @@ let ${allStores} ''; - index = replaceStrings - [ "@store-types@" "./local-store.md" "./local-daemon-store.md" ] - [ storesOverview "#local-store" "#local-daemon-store" ] - details.doc; + index = + replaceStrings + [ "@store-types@" "./local-store.md" "./local-daemon-store.md" ] + [ storesOverview "#local-store" "#local-daemon-store" ] + details.doc; storesOverview = let - showEntry = store: - "- [${store.name}](#${store.slug})"; + showEntry = store: "- [${store.name}](#${store.slug})"; in concatStringsSep "\n" (map showEntry storesList) + "\n"; allStores = concatStringsSep "\n" (attrValues storePages); - storePages = listToAttrs - (map (s: { name = s.filename; value = s.page; }) storesList); + storePages = listToAttrs ( + map (s: { + name = s.filename; + value = s.page; + }) storesList + ); storesList = showStoreDocs { storeInfo = commandInfo.stores; inherit inlineHTML; }; - hasInfix = infix: content: + hasInfix = + infix: content: builtins.stringLength content != builtins.stringLength (replaceStrings [ infix ] [ "" ] content); in optionalString (details ? doc) ( # An alternate implementation with builtins.match stack overflowed on some systems. - if hasInfix "@store-types@" details.doc - then help-stores - else details.doc + if hasInfix "@store-types@" details.doc then help-stores else details.doc ); maybeOptions = let - allVisibleOptions = filterAttrs - (_: o: ! o.hiddenCategory) - (details.flags // toplevel.flags); + allVisibleOptions = filterAttrs (_: o: !o.hiddenCategory) (details.flags // toplevel.flags); in optionalString (allVisibleOptions != { }) '' # Options @@ -142,55 +150,73 @@ let > See [`man nix.conf`](@docroot@/command-ref/conf-file.md#command-line-flags) for overriding configuration settings with command line flags. ''; - showOptions = inlineHTML: allOptions: + showOptions = + inlineHTML: allOptions: let showCategory = cat: opts: '' ${optionalString (cat != "") "## ${cat}"} ${concatStringsSep "\n" (attrValues (mapAttrs showOption opts))} ''; - showOption = name: option: + showOption = + name: option: let result = trim '' - ${item} ${option.description} ''; - item = if inlineHTML - then ''[`--${name}`](#opt-${name}) ${shortName} ${labels}'' - else "`--${name}` ${shortName} ${labels}"; - shortName = optionalString - (option ? shortName) - ("/ `-${option.shortName}`"); - labels = optionalString - (option ? labels) - (concatStringsSep " " (map (s: "*${s}*") option.labels)); - in result; - categories = mapAttrs - # Convert each group from a list of key-value pairs back to an attrset - (_: listToAttrs) - (groupBy - (cmd: cmd.value.category) - (attrsToList allOptions)); - in concatStrings (attrValues (mapAttrs showCategory categories)); - in squash result; + item = + if inlineHTML then + ''[`--${name}`](#opt-${name}) ${shortName} ${labels}'' + else + "`--${name}` ${shortName} ${labels}"; + shortName = optionalString (option ? shortName) ("/ `-${option.shortName}`"); + labels = optionalString (option ? labels) (concatStringsSep " " (map (s: "*${s}*") option.labels)); + in + result; + categories = + mapAttrs + # Convert each group from a list of key-value pairs back to an attrset + (_: listToAttrs) + (groupBy (cmd: cmd.value.category) (attrsToList allOptions)); + in + concatStrings (attrValues (mapAttrs showCategory categories)); + in + squash result; appendName = filename: name: (if filename == "nix" then "nix3" else filename) + "-" + name; - processCommand = { command, details, filename, toplevel }: + processCommand = + { + command, + details, + filename, + toplevel, + }: let cmd = { inherit command; name = filename + ".md"; - value = showCommand { inherit command details filename toplevel; }; + value = showCommand { + inherit + command + details + filename + toplevel + ; + }; }; - subcommand = subCmd: processCommand { - command = command + " " + subCmd; - details = details.commands.${subCmd}; - filename = appendName filename subCmd; - inherit toplevel; - }; - in [ cmd ] ++ concatMap subcommand (attrNames details.commands or {}); + subcommand = + subCmd: + processCommand { + command = command + " " + subCmd; + details = details.commands.${subCmd}; + filename = appendName filename subCmd; + inherit toplevel; + }; + in + [ cmd ] ++ concatMap subcommand (attrNames details.commands or { }); manpages = processCommand { command = "nix"; @@ -199,9 +225,11 @@ let toplevel = commandInfo.args; }; - tableOfContents = let - showEntry = page: - " - [${page.command}](command-ref/new-cli/${page.name})"; - in concatStringsSep "\n" (map showEntry manpages) + "\n"; + tableOfContents = + let + showEntry = page: " - [${page.command}](command-ref/new-cli/${page.name})"; + in + concatStringsSep "\n" (map showEntry manpages) + "\n"; -in (listToAttrs manpages) // { "SUMMARY.md" = tableOfContents; } +in +(listToAttrs manpages) // { "SUMMARY.md" = tableOfContents; } diff --git a/doc/manual/generate-settings.nix b/doc/manual/generate-settings.nix index 93a8e093e..35ae73e5d 100644 --- a/doc/manual/generate-settings.nix +++ b/doc/manual/generate-settings.nix @@ -1,67 +1,99 @@ let - inherit (builtins) attrValues concatStringsSep isAttrs isBool mapAttrs; - inherit (import ) concatStrings indent optionalString squash; + inherit (builtins) + attrValues + concatStringsSep + isAttrs + isBool + mapAttrs + ; + inherit (import ) + concatStrings + indent + optionalString + squash + ; in # `inlineHTML` is a hack to accommodate inconsistent output from `lowdown` -{ prefix, inlineHTML ? true }: settingsInfo: +{ + prefix, + inlineHTML ? true, +}: +settingsInfo: let - showSetting = prefix: setting: { description, documentDefault, defaultValue, aliases, value, experimentalFeature }: + showSetting = + prefix: setting: + { + description, + documentDefault, + defaultValue, + aliases, + value, + experimentalFeature, + }: let result = squash '' - - ${item} + - ${item} - ${indent " " body} - ''; - item = if inlineHTML - then ''[`${setting}`](#${prefix}-${setting})'' - else "`${setting}`"; + ${indent " " body} + ''; + item = + if inlineHTML then + ''[`${setting}`](#${prefix}-${setting})'' + else + "`${setting}`"; # separate body to cleanly handle indentation body = '' - ${experimentalFeatureNote} + ${experimentalFeatureNote} - ${description} + ${description} - **Default:** ${showDefault documentDefault defaultValue} + **Default:** ${showDefault documentDefault defaultValue} - ${showAliases aliases} - ''; + ${showAliases aliases} + ''; experimentalFeatureNote = optionalString (experimentalFeature != null) '' - > **Warning** - > - > This setting is part of an - > [experimental feature](@docroot@/development/experimental-features.md). - > - > To change this setting, make sure the - > [`${experimentalFeature}` experimental feature](@docroot@/development/experimental-features.md#xp-feature-${experimentalFeature}) - > is enabled. - > For example, include the following in [`nix.conf`](@docroot@/command-ref/conf-file.md): - > - > ``` - > extra-experimental-features = ${experimentalFeature} - > ${setting} = ... - > ``` - ''; + > **Warning** + > + > This setting is part of an + > [experimental feature](@docroot@/development/experimental-features.md). + > + > To change this setting, make sure the + > [`${experimentalFeature}` experimental feature](@docroot@/development/experimental-features.md#xp-feature-${experimentalFeature}) + > is enabled. + > For example, include the following in [`nix.conf`](@docroot@/command-ref/conf-file.md): + > + > ``` + > extra-experimental-features = ${experimentalFeature} + > ${setting} = ... + > ``` + ''; - showDefault = documentDefault: defaultValue: + showDefault = + documentDefault: defaultValue: if documentDefault then # a StringMap value type is specified as a string, but # this shows the value type. The empty stringmap is `null` in # JSON, but that converts to `{ }` here. - if defaultValue == "" || defaultValue == [] || isAttrs defaultValue - then "*empty*" - else if isBool defaultValue then - if defaultValue then "`true`" else "`false`" - else "`${toString defaultValue}`" - else "*machine-specific*"; + if defaultValue == "" || defaultValue == [ ] || isAttrs defaultValue then + "*empty*" + else if isBool defaultValue then + if defaultValue then "`true`" else "`false`" + else + "`${toString defaultValue}`" + else + "*machine-specific*"; - showAliases = aliases: - optionalString (aliases != []) - "**Deprecated alias:** ${(concatStringsSep ", " (map (s: "`${s}`") aliases))}"; + showAliases = + aliases: + optionalString (aliases != [ ]) + "**Deprecated alias:** ${(concatStringsSep ", " (map (s: "`${s}`") aliases))}"; - in result; + in + result; -in concatStrings (attrValues (mapAttrs (showSetting prefix) settingsInfo)) +in +concatStrings (attrValues (mapAttrs (showSetting prefix) settingsInfo)) diff --git a/doc/manual/generate-store-info.nix b/doc/manual/generate-store-info.nix index cc3704124..e8b7377da 100644 --- a/doc/manual/generate-store-info.nix +++ b/doc/manual/generate-store-info.nix @@ -1,6 +1,20 @@ let - inherit (builtins) attrNames listToAttrs concatStringsSep readFile replaceStrings; - inherit (import ) optionalString filterAttrs trim squash toLower unique indent; + inherit (builtins) + attrNames + listToAttrs + concatStringsSep + readFile + replaceStrings + ; + inherit (import ) + optionalString + filterAttrs + trim + squash + toLower + unique + indent + ; showSettings = import ; in @@ -14,7 +28,13 @@ in let - showStore = { name, slug }: { settings, doc, experimentalFeature }: + showStore = + { name, slug }: + { + settings, + doc, + experimentalFeature, + }: let result = squash '' # ${name} @@ -25,7 +45,10 @@ let ## Settings - ${showSettings { prefix = "store-${slug}"; inherit inlineHTML; } settings} + ${showSettings { + prefix = "store-${slug}"; + inherit inlineHTML; + } settings} ''; experimentalFeatureNote = optionalString (experimentalFeature != null) '' @@ -43,15 +66,15 @@ let > extra-experimental-features = ${experimentalFeature} > ``` ''; - in result; + in + result; - storesList = map - (name: rec { - inherit name; - slug = replaceStrings [ " " ] [ "-" ] (toLower name); - filename = "${slug}.md"; - page = showStore { inherit name slug; } storeInfo.${name}; - }) - (attrNames storeInfo); + storesList = map (name: rec { + inherit name; + slug = replaceStrings [ " " ] [ "-" ] (toLower name); + filename = "${slug}.md"; + page = showStore { inherit name slug; } storeInfo.${name}; + }) (attrNames storeInfo); -in storesList +in +storesList diff --git a/doc/manual/generate-store-types.nix b/doc/manual/generate-store-types.nix index 46179abc5..a03d3d621 100644 --- a/doc/manual/generate-store-types.nix +++ b/doc/manual/generate-store-types.nix @@ -1,5 +1,11 @@ let - inherit (builtins) attrNames listToAttrs concatStringsSep readFile replaceStrings; + inherit (builtins) + attrNames + listToAttrs + concatStringsSep + readFile + replaceStrings + ; showSettings = import ; showStoreDocs = import ; in @@ -14,26 +20,28 @@ let index = let - showEntry = store: - "- [${store.name}](./${store.filename})"; + showEntry = store: "- [${store.name}](./${store.filename})"; in concatStringsSep "\n" (map showEntry storesList); - "index.md" = replaceStrings - [ "@store-types@" ] [ index ] - (readFile ./source/store/types/index.md.in); + "index.md" = + replaceStrings [ "@store-types@" ] [ index ] + (readFile ./source/store/types/index.md.in); tableOfContents = let - showEntry = store: - " - [${store.name}](store/types/${store.filename})"; + showEntry = store: " - [${store.name}](store/types/${store.filename})"; in concatStringsSep "\n" (map showEntry storesList) + "\n"; "SUMMARY.md" = tableOfContents; - storePages = listToAttrs - (map (s: { name = s.filename; value = s.page; }) storesList); + storePages = listToAttrs ( + map (s: { + name = s.filename; + value = s.page; + }) storesList + ); in storePages // { inherit "index.md" "SUMMARY.md"; } diff --git a/doc/manual/generate-xp-features-shortlist.nix b/doc/manual/generate-xp-features-shortlist.nix index eb735ba5f..1520fc2f8 100644 --- a/doc/manual/generate-xp-features-shortlist.nix +++ b/doc/manual/generate-xp-features-shortlist.nix @@ -2,8 +2,8 @@ with builtins; with import ; let - showExperimentalFeature = name: doc: - '' - - [`${name}`](@docroot@/development/experimental-features.md#xp-feature-${name}) - ''; -in xps: indent " " (concatStrings (attrValues (mapAttrs showExperimentalFeature xps))) + showExperimentalFeature = name: doc: '' + - [`${name}`](@docroot@/development/experimental-features.md#xp-feature-${name}) + ''; +in +xps: indent " " (concatStrings (attrValues (mapAttrs showExperimentalFeature xps))) diff --git a/doc/manual/generate-xp-features.nix b/doc/manual/generate-xp-features.nix index 0eec0e1da..468d253ba 100644 --- a/doc/manual/generate-xp-features.nix +++ b/doc/manual/generate-xp-features.nix @@ -2,7 +2,8 @@ with builtins; with import ; let - showExperimentalFeature = name: doc: + showExperimentalFeature = + name: doc: squash '' ## [`${name}`]{#xp-feature-${name}} diff --git a/doc/manual/package.nix b/doc/manual/package.nix index f8133f2e1..8f5d0dfe1 100644 --- a/doc/manual/package.nix +++ b/doc/manual/package.nix @@ -1,19 +1,20 @@ -{ lib -, mkMesonDerivation +{ + lib, + mkMesonDerivation, -, meson -, ninja -, lowdown-unsandboxed -, mdbook -, mdbook-linkcheck -, jq -, python3 -, rsync -, nix-cli + meson, + ninja, + lowdown-unsandboxed, + mdbook, + mdbook-linkcheck, + jq, + python3, + rsync, + nix-cli, -# Configuration Options + # Configuration Options -, version + version, }: let @@ -25,18 +26,22 @@ mkMesonDerivation (finalAttrs: { inherit version; workDir = ./.; - fileset = fileset.difference - (fileset.unions [ - ../../.version - # Too many different types of files to filter for now - ../../doc/manual - ./. - ]) - # Do a blacklist instead - ../../doc/manual/package.nix; + fileset = + fileset.difference + (fileset.unions [ + ../../.version + # Too many different types of files to filter for now + ../../doc/manual + ./. + ]) + # Do a blacklist instead + ../../doc/manual/package.nix; # TODO the man pages should probably be separate - outputs = [ "out" "man" ]; + outputs = [ + "out" + "man" + ]; # Hack for sake of the dev shell passthru.externalNativeBuildInputs = [ @@ -54,11 +59,10 @@ mkMesonDerivation (finalAttrs: { nix-cli ]; - preConfigure = - '' - chmod u+w ./.version - echo ${finalAttrs.version} > ./.version - ''; + preConfigure = '' + chmod u+w ./.version + echo ${finalAttrs.version} > ./.version + ''; postInstall = '' mkdir -p ''$out/nix-support diff --git a/doc/manual/utils.nix b/doc/manual/utils.nix index 19ff49b64..db3a0e67a 100644 --- a/doc/manual/utils.nix +++ b/doc/manual/utils.nix @@ -11,10 +11,15 @@ rec { concatStrings = concatStringsSep ""; - attrsToList = a: - map (name: { inherit name; value = a.${name}; }) (builtins.attrNames a); + attrsToList = + a: + map (name: { + inherit name; + value = a.${name}; + }) (builtins.attrNames a); - replaceStringsRec = from: to: string: + replaceStringsRec = + from: to: string: # recursively replace occurrences of `from` with `to` within `string` # example: # replaceStringRec "--" "-" "hello-----world" @@ -22,16 +27,18 @@ rec { let replaced = replaceStrings [ from ] [ to ] string; in - if replaced == string then string else replaceStringsRec from to replaced; + if replaced == string then string else replaceStringsRec from to replaced; toLower = replaceStrings upperChars lowerChars; squash = replaceStringsRec "\n\n\n" "\n\n"; - trim = string: + trim = + string: # trim trailing spaces and squash non-leading spaces let - trimLine = line: + trimLine = + line: let # separate leading spaces from the rest parts = split "(^ *)" line; @@ -39,19 +46,30 @@ rec { rest = elemAt parts 2; # drop trailing spaces body = head (split " *$" rest); - in spaces + replaceStringsRec " " " " body; - in concatStringsSep "\n" (map trimLine (splitLines string)); + in + spaces + replaceStringsRec " " " " body; + in + concatStringsSep "\n" (map trimLine (splitLines string)); # FIXME: O(n^2) - unique = foldl' (acc: e: if elem e acc then acc else acc ++ [ e ]) []; + unique = foldl' (acc: e: if elem e acc then acc else acc ++ [ e ]) [ ]; nameValuePair = name: value: { inherit name value; }; - filterAttrs = pred: set: - listToAttrs (concatMap (name: let v = set.${name}; in if pred name v then [(nameValuePair name v)] else []) (attrNames set)); + filterAttrs = + pred: set: + listToAttrs ( + concatMap ( + name: + let + v = set.${name}; + in + if pred name v then [ (nameValuePair name v) ] else [ ] + ) (attrNames set) + ); optionalString = cond: string: if cond then string else ""; - indent = prefix: s: - concatStringsSep "\n" (map (x: if x == "" then x else "${prefix}${x}") (splitLines s)); + indent = + prefix: s: concatStringsSep "\n" (map (x: if x == "" then x else "${prefix}${x}") (splitLines s)); } diff --git a/docker.nix b/docker.nix index e2e9da728..d52c317d6 100644 --- a/docker.nix +++ b/docker.nix @@ -1,112 +1,113 @@ -{ pkgs ? import { } -, lib ? pkgs.lib -, name ? "nix" -, tag ? "latest" -, bundleNixpkgs ? true -, channelName ? "nixpkgs" -, channelURL ? "https://nixos.org/channels/nixpkgs-unstable" -, extraPkgs ? [] -, maxLayers ? 100 -, nixConf ? {} -, flake-registry ? null -, uid ? 0 -, gid ? 0 -, uname ? "root" -, gname ? "root" +{ + pkgs ? import { }, + lib ? pkgs.lib, + name ? "nix", + tag ? "latest", + bundleNixpkgs ? true, + channelName ? "nixpkgs", + channelURL ? "https://nixos.org/channels/nixpkgs-unstable", + extraPkgs ? [ ], + maxLayers ? 100, + nixConf ? { }, + flake-registry ? null, + uid ? 0, + gid ? 0, + uname ? "root", + gname ? "root", }: let - defaultPkgs = with pkgs; [ - nix - bashInteractive - coreutils-full - gnutar - gzip - gnugrep - which - curl - less - wget - man - cacert.out - findutils - iana-etc - git - openssh - ] ++ extraPkgs; + defaultPkgs = + with pkgs; + [ + nix + bashInteractive + coreutils-full + gnutar + gzip + gnugrep + which + curl + less + wget + man + cacert.out + findutils + iana-etc + git + openssh + ] + ++ extraPkgs; - users = { + users = + { - root = { - uid = 0; - shell = "${pkgs.bashInteractive}/bin/bash"; - home = "/root"; - gid = 0; - groups = [ "root" ]; - description = "System administrator"; + root = { + uid = 0; + shell = "${pkgs.bashInteractive}/bin/bash"; + home = "/root"; + gid = 0; + groups = [ "root" ]; + description = "System administrator"; + }; + + nobody = { + uid = 65534; + shell = "${pkgs.shadow}/bin/nologin"; + home = "/var/empty"; + gid = 65534; + groups = [ "nobody" ]; + description = "Unprivileged account (don't use!)"; + }; + + } + // lib.optionalAttrs (uid != 0) { + "${uname}" = { + uid = uid; + shell = "${pkgs.bashInteractive}/bin/bash"; + home = "/home/${uname}"; + gid = gid; + groups = [ "${gname}" ]; + description = "Nix user"; + }; + } + // lib.listToAttrs ( + map (n: { + name = "nixbld${toString n}"; + value = { + uid = 30000 + n; + gid = 30000; + groups = [ "nixbld" ]; + description = "Nix build user ${toString n}"; + }; + }) (lib.lists.range 1 32) + ); + + groups = + { + root.gid = 0; + nixbld.gid = 30000; + nobody.gid = 65534; + } + // lib.optionalAttrs (gid != 0) { + "${gname}".gid = gid; }; - nobody = { - uid = 65534; - shell = "${pkgs.shadow}/bin/nologin"; - home = "/var/empty"; - gid = 65534; - groups = [ "nobody" ]; - description = "Unprivileged account (don't use!)"; - }; - - } // lib.optionalAttrs (uid != 0) { - "${uname}" = { - uid = uid; - shell = "${pkgs.bashInteractive}/bin/bash"; - home = "/home/${uname}"; - gid = gid; - groups = [ "${gname}" ]; - description = "Nix user"; - }; - } // lib.listToAttrs ( - map - ( - n: { - name = "nixbld${toString n}"; - value = { - uid = 30000 + n; - gid = 30000; - groups = [ "nixbld" ]; - description = "Nix build user ${toString n}"; - }; - } - ) - (lib.lists.range 1 32) - ); - - groups = { - root.gid = 0; - nixbld.gid = 30000; - nobody.gid = 65534; - } // lib.optionalAttrs (gid != 0) { - "${gname}".gid = gid; - }; - userToPasswd = ( k: - { uid - , gid ? 65534 - , home ? "/var/empty" - , description ? "" - , shell ? "/bin/false" - , groups ? [ ] - }: "${k}:x:${toString uid}:${toString gid}:${description}:${home}:${shell}" - ); - passwdContents = ( - lib.concatStringsSep "\n" - (lib.attrValues (lib.mapAttrs userToPasswd users)) + { + uid, + gid ? 65534, + home ? "/var/empty", + description ? "", + shell ? "/bin/false", + groups ? [ ], + }: + "${k}:x:${toString uid}:${toString gid}:${description}:${home}:${shell}" ); + passwdContents = (lib.concatStringsSep "\n" (lib.attrValues (lib.mapAttrs userToPasswd users))); userToShadow = k: { ... }: "${k}:!:1::::::"; - shadowContents = ( - lib.concatStringsSep "\n" - (lib.attrValues (lib.mapAttrs userToShadow users)) - ); + shadowContents = (lib.concatStringsSep "\n" (lib.attrValues (lib.mapAttrs userToShadow users))); # Map groups to members # { @@ -116,42 +117,35 @@ let let # Create a flat list of user/group mappings mappings = ( - builtins.foldl' - ( - acc: user: - let - groups = users.${user}.groups or [ ]; - in - acc ++ map - (group: { - inherit user group; - }) - groups - ) - [ ] - (lib.attrNames users) + builtins.foldl' ( + acc: user: + let + groups = users.${user}.groups or [ ]; + in + acc + ++ map (group: { + inherit user group; + }) groups + ) [ ] (lib.attrNames users) ); in - ( - builtins.foldl' - ( - acc: v: acc // { - ${v.group} = acc.${v.group} or [ ] ++ [ v.user ]; - } - ) - { } - mappings) + (builtins.foldl' ( + acc: v: + acc + // { + ${v.group} = acc.${v.group} or [ ] ++ [ v.user ]; + } + ) { } mappings) ); - groupToGroup = k: { gid }: + groupToGroup = + k: + { gid }: let members = groupMemberMap.${k} or [ ]; in "${k}:x:${toString gid}:${lib.concatStringsSep "," members}"; - groupContents = ( - lib.concatStringsSep "\n" - (lib.attrValues (lib.mapAttrs groupToGroup groups)) - ); + groupContents = (lib.concatStringsSep "\n" (lib.attrValues (lib.mapAttrs groupToGroup groups))); defaultNixConf = { sandbox = "false"; @@ -159,11 +153,17 @@ let trusted-public-keys = [ "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" ]; }; - nixConfContents = (lib.concatStringsSep "\n" (lib.mapAttrsFlatten (n: v: - let - vStr = if builtins.isList v then lib.concatStringsSep " " v else v; - in - "${n} = ${vStr}") (defaultNixConf // nixConf))) + "\n"; + nixConfContents = + (lib.concatStringsSep "\n" ( + lib.mapAttrsFlatten ( + n: v: + let + vStr = if builtins.isList v then lib.concatStringsSep " " v else v; + in + "${n} = ${vStr}" + ) (defaultNixConf // nixConf) + )) + + "\n"; userHome = if uid == 0 then "/root" else "/home/${uname}"; @@ -184,21 +184,29 @@ let manifest = pkgs.buildPackages.runCommand "manifest.nix" { } '' cat > $out < $out/etc/passwd - echo "" >> $out/etc/passwd + cat $passwdContentsPath > $out/etc/passwd + echo "" >> $out/etc/passwd - cat $groupContentsPath > $out/etc/group - echo "" >> $out/etc/group + cat $groupContentsPath > $out/etc/group + echo "" >> $out/etc/group - cat $shadowContentsPath > $out/etc/shadow - echo "" >> $out/etc/shadow + cat $shadowContentsPath > $out/etc/shadow + echo "" >> $out/etc/shadow - mkdir -p $out/usr - ln -s /nix/var/nix/profiles/share $out/usr/ + mkdir -p $out/usr + ln -s /nix/var/nix/profiles/share $out/usr/ - mkdir -p $out/nix/var/nix/gcroots + mkdir -p $out/nix/var/nix/gcroots - mkdir $out/tmp + mkdir $out/tmp - mkdir -p $out/var/tmp + mkdir -p $out/var/tmp - mkdir -p $out/etc/nix - cat $nixConfContentsPath > $out/etc/nix/nix.conf + mkdir -p $out/etc/nix + cat $nixConfContentsPath > $out/etc/nix/nix.conf - mkdir -p $out${userHome} - mkdir -p $out/nix/var/nix/profiles/per-user/${uname} + mkdir -p $out${userHome} + mkdir -p $out/nix/var/nix/profiles/per-user/${uname} - ln -s ${profile} $out/nix/var/nix/profiles/default-1-link - ln -s /nix/var/nix/profiles/default-1-link $out/nix/var/nix/profiles/default - ln -s /nix/var/nix/profiles/default $out${userHome}/.nix-profile + ln -s ${profile} $out/nix/var/nix/profiles/default-1-link + ln -s /nix/var/nix/profiles/default-1-link $out/nix/var/nix/profiles/default + ln -s /nix/var/nix/profiles/default $out${userHome}/.nix-profile - ln -s ${channel} $out/nix/var/nix/profiles/per-user/${uname}/channels-1-link - ln -s /nix/var/nix/profiles/per-user/${uname}/channels-1-link $out/nix/var/nix/profiles/per-user/${uname}/channels + ln -s ${channel} $out/nix/var/nix/profiles/per-user/${uname}/channels-1-link + ln -s /nix/var/nix/profiles/per-user/${uname}/channels-1-link $out/nix/var/nix/profiles/per-user/${uname}/channels - mkdir -p $out${userHome}/.nix-defexpr - ln -s /nix/var/nix/profiles/per-user/${uname}/channels $out${userHome}/.nix-defexpr/channels - echo "${channelURL} ${channelName}" > $out${userHome}/.nix-channels + mkdir -p $out${userHome}/.nix-defexpr + ln -s /nix/var/nix/profiles/per-user/${uname}/channels $out${userHome}/.nix-defexpr/channels + echo "${channelURL} ${channelName}" > $out${userHome}/.nix-channels - mkdir -p $out/bin $out/usr/bin - ln -s ${pkgs.coreutils}/bin/env $out/usr/bin/env - ln -s ${pkgs.bashInteractive}/bin/bash $out/bin/sh + mkdir -p $out/bin $out/usr/bin + ln -s ${pkgs.coreutils}/bin/env $out/usr/bin/env + ln -s ${pkgs.bashInteractive}/bin/bash $out/bin/sh - '' + (lib.optionalString (flake-registry-path != null) '' - nixCacheDir="${userHome}/.cache/nix" - mkdir -p $out$nixCacheDir - globalFlakeRegistryPath="$nixCacheDir/flake-registry.json" - ln -s ${flake-registry-path} $out$globalFlakeRegistryPath - mkdir -p $out/nix/var/nix/gcroots/auto - rootName=$(${pkgs.nix}/bin/nix --extra-experimental-features nix-command hash file --type sha1 --base32 <(echo -n $globalFlakeRegistryPath)) - ln -s $globalFlakeRegistryPath $out/nix/var/nix/gcroots/auto/$rootName - '')); + '' + + (lib.optionalString (flake-registry-path != null) '' + nixCacheDir="${userHome}/.cache/nix" + mkdir -p $out$nixCacheDir + globalFlakeRegistryPath="$nixCacheDir/flake-registry.json" + ln -s ${flake-registry-path} $out$globalFlakeRegistryPath + mkdir -p $out/nix/var/nix/gcroots/auto + rootName=$(${pkgs.nix}/bin/nix --extra-experimental-features nix-command hash file --type sha1 --base32 <(echo -n $globalFlakeRegistryPath)) + ln -s $globalFlakeRegistryPath $out/nix/var/nix/gcroots/auto/$rootName + '') + ); in pkgs.dockerTools.buildLayeredImageWithNixDb { - inherit name tag maxLayers uid gid uname gname; + inherit + name + tag + maxLayers + uid + gid + uname + gname + ; contents = [ baseSystem ]; @@ -305,15 +331,19 @@ pkgs.dockerTools.buildLayeredImageWithNixDb { User = "${toString uid}:${toString gid}"; Env = [ "USER=${uname}" - "PATH=${lib.concatStringsSep ":" [ - "${userHome}/.nix-profile/bin" - "/nix/var/nix/profiles/default/bin" - "/nix/var/nix/profiles/default/sbin" - ]}" - "MANPATH=${lib.concatStringsSep ":" [ - "${userHome}/.nix-profile/share/man" - "/nix/var/nix/profiles/default/share/man" - ]}" + "PATH=${ + lib.concatStringsSep ":" [ + "${userHome}/.nix-profile/bin" + "/nix/var/nix/profiles/default/bin" + "/nix/var/nix/profiles/default/sbin" + ] + }" + "MANPATH=${ + lib.concatStringsSep ":" [ + "${userHome}/.nix-profile/share/man" + "/nix/var/nix/profiles/default/share/man" + ] + }" "SSL_CERT_FILE=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt" "GIT_SSL_CAINFO=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt" "NIX_SSL_CERT_FILE=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt" diff --git a/flake.nix b/flake.nix index d8a458c1f..eafb65353 100644 --- a/flake.nix +++ b/flake.nix @@ -5,7 +5,10 @@ inputs.nixpkgs-regression.url = "github:NixOS/nixpkgs/215d4d0fd80ca5163643b03a33fde804a29cc1e2"; inputs.nixpkgs-23-11.url = "github:NixOS/nixpkgs/a62e6edd6d5e1fa0329b8653c801147986f8d446"; - inputs.flake-compat = { url = "github:edolstra/flake-compat"; flake = false; }; + inputs.flake-compat = { + url = "github:edolstra/flake-compat"; + flake = false; + }; # dev tooling inputs.flake-parts.url = "github:hercules-ci/flake-parts"; @@ -18,8 +21,13 @@ inputs.git-hooks-nix.inputs.flake-compat.follows = ""; inputs.git-hooks-nix.inputs.gitignore.follows = ""; - outputs = inputs@{ self, nixpkgs, nixpkgs-regression, ... }: - + outputs = + inputs@{ + self, + nixpkgs, + nixpkgs-regression, + ... + }: let inherit (nixpkgs) lib; @@ -27,9 +35,15 @@ officialRelease = true; linux32BitSystems = [ "i686-linux" ]; - linux64BitSystems = [ "x86_64-linux" "aarch64-linux" ]; + linux64BitSystems = [ + "x86_64-linux" + "aarch64-linux" + ]; linuxSystems = linux32BitSystems ++ linux64BitSystems; - darwinSystems = [ "x86_64-darwin" "aarch64-darwin" ]; + darwinSystems = [ + "x86_64-darwin" + "aarch64-darwin" + ]; systems = linuxSystems ++ darwinSystems; crossSystems = [ @@ -59,63 +73,77 @@ (Provided that the names are unique.) See https://nixos.org/manual/nixpkgs/stable/index.html#function-library-lib.attrsets.concatMapAttrs - */ + */ flatMapAttrs = attrs: f: lib.concatMapAttrs f attrs; forAllSystems = lib.genAttrs systems; forAllCrossSystems = lib.genAttrs crossSystems; - forAllStdenvs = f: - lib.listToAttrs - (map - (stdenvName: { - name = "${stdenvName}Packages"; - value = f stdenvName; - }) - stdenvs); - + forAllStdenvs = + f: + lib.listToAttrs ( + map (stdenvName: { + name = "${stdenvName}Packages"; + value = f stdenvName; + }) stdenvs + ); # We don't apply flake-parts to the whole flake so that non-development attributes # load without fetching any development inputs. devFlake = inputs.flake-parts.lib.mkFlake { inherit inputs; } { imports = [ ./maintainers/flake-module.nix ]; systems = lib.subtractLists crossSystems systems; - perSystem = { system, ... }: { - _module.args.pkgs = nixpkgsFor.${system}.native; - }; + perSystem = + { system, ... }: + { + _module.args.pkgs = nixpkgsFor.${system}.native; + }; }; # Memoize nixpkgs for different platforms for efficiency. - nixpkgsFor = forAllSystems - (system: let - make-pkgs = crossSystem: stdenv: import nixpkgs { - localSystem = { - inherit system; + nixpkgsFor = forAllSystems ( + system: + let + make-pkgs = + crossSystem: stdenv: + import nixpkgs { + localSystem = { + inherit system; + }; + crossSystem = + if crossSystem == null then + null + else + { + config = crossSystem; + } + // lib.optionalAttrs (crossSystem == "x86_64-unknown-freebsd13") { + useLLVM = true; + }; + overlays = [ + (overlayFor (p: p.${stdenv})) + ]; }; - crossSystem = if crossSystem == null then null else { - config = crossSystem; - } // lib.optionalAttrs (crossSystem == "x86_64-unknown-freebsd13") { - useLLVM = true; - }; - overlays = [ - (overlayFor (p: p.${stdenv})) - ]; - }; stdenvs = forAllStdenvs (make-pkgs null); native = stdenvs.stdenvPackages; - in { + in + { inherit stdenvs native; static = native.pkgsStatic; llvm = native.pkgsLLVM; cross = forAllCrossSystems (crossSystem: make-pkgs crossSystem "stdenv"); - }); + } + ); - binaryTarball = nix: pkgs: pkgs.callPackage ./scripts/binary-tarball.nix { - inherit nix; - }; + binaryTarball = + nix: pkgs: + pkgs.callPackage ./scripts/binary-tarball.nix { + inherit nix; + }; - overlayFor = getStdenv: final: prev: + overlayFor = + getStdenv: final: prev: let stdenv = getStdenv final; in @@ -162,12 +190,19 @@ # See https://github.com/NixOS/nixpkgs/pull/214409 # Remove when fixed in this flake's nixpkgs pre-commit = - if prev.stdenv.hostPlatform.system == "i686-linux" - then (prev.pre-commit.override (o: { dotnet-sdk = ""; })).overridePythonAttrs (o: { doCheck = false; }) - else prev.pre-commit; + if prev.stdenv.hostPlatform.system == "i686-linux" then + (prev.pre-commit.override (o: { + dotnet-sdk = ""; + })).overridePythonAttrs + (o: { + doCheck = false; + }) + else + prev.pre-commit; }; - in { + in + { # A Nixpkgs overlay that overrides the 'nix' and # 'nix-perl-bindings' packages. overlays.default = overlayFor (p: p.stdenv); @@ -186,53 +221,69 @@ ; }; - checks = forAllSystems (system: { - installerScriptForGHA = self.hydraJobs.installerScriptForGHA.${system}; - installTests = self.hydraJobs.installTests.${system}; - nixpkgsLibTests = self.hydraJobs.tests.nixpkgsLibTests.${system}; - rl-next = - let pkgs = nixpkgsFor.${system}.native; - in pkgs.buildPackages.runCommand "test-rl-next-release-notes" { } '' - LANG=C.UTF-8 ${pkgs.changelog-d}/bin/changelog-d ${./doc/manual/rl-next} >$out - ''; - repl-completion = nixpkgsFor.${system}.native.callPackage ./tests/repl-completion.nix { }; - } // (lib.optionalAttrs (builtins.elem system linux64BitSystems)) { - dockerImage = self.hydraJobs.dockerImage.${system}; - } // (lib.optionalAttrs (!(builtins.elem system linux32BitSystems))) { - # Some perl dependencies are broken on i686-linux. - # Since the support is only best-effort there, disable the perl - # bindings - perlBindings = self.hydraJobs.perlBindings.${system}; - } - # Add "passthru" tests - // flatMapAttrs ({ - "" = nixpkgsFor.${system}.native; - } // lib.optionalAttrs (! nixpkgsFor.${system}.native.stdenv.hostPlatform.isDarwin) { - # TODO: enable static builds for darwin, blocked on: - # https://github.com/NixOS/nixpkgs/issues/320448 - # TODO: disabled to speed up GHA CI. - #"static-" = nixpkgsFor.${system}.static; - }) - (nixpkgsPrefix: nixpkgs: - flatMapAttrs nixpkgs.nixComponents - (pkgName: pkg: - flatMapAttrs pkg.tests or {} - (testName: test: { - "${nixpkgsPrefix}${pkgName}-${testName}" = test; - }) + checks = forAllSystems ( + system: + { + installerScriptForGHA = self.hydraJobs.installerScriptForGHA.${system}; + installTests = self.hydraJobs.installTests.${system}; + nixpkgsLibTests = self.hydraJobs.tests.nixpkgsLibTests.${system}; + rl-next = + let + pkgs = nixpkgsFor.${system}.native; + in + pkgs.buildPackages.runCommand "test-rl-next-release-notes" { } '' + LANG=C.UTF-8 ${pkgs.changelog-d}/bin/changelog-d ${./doc/manual/rl-next} >$out + ''; + repl-completion = nixpkgsFor.${system}.native.callPackage ./tests/repl-completion.nix { }; + } + // (lib.optionalAttrs (builtins.elem system linux64BitSystems)) { + dockerImage = self.hydraJobs.dockerImage.${system}; + } + // (lib.optionalAttrs (!(builtins.elem system linux32BitSystems))) { + # Some perl dependencies are broken on i686-linux. + # Since the support is only best-effort there, disable the perl + # bindings + perlBindings = self.hydraJobs.perlBindings.${system}; + } + # Add "passthru" tests + // + flatMapAttrs + ( + { + "" = nixpkgsFor.${system}.native; + } + // lib.optionalAttrs (!nixpkgsFor.${system}.native.stdenv.hostPlatform.isDarwin) { + # TODO: enable static builds for darwin, blocked on: + # https://github.com/NixOS/nixpkgs/issues/320448 + # TODO: disabled to speed up GHA CI. + #"static-" = nixpkgsFor.${system}.static; + } ) - // lib.optionalAttrs (nixpkgs.stdenv.hostPlatform == nixpkgs.stdenv.buildPlatform) { - "${nixpkgsPrefix}nix-functional-tests" = nixpkgs.nixComponents.nix-functional-tests; - } - ) - // devFlake.checks.${system} or {} + ( + nixpkgsPrefix: nixpkgs: + flatMapAttrs nixpkgs.nixComponents ( + pkgName: pkg: + flatMapAttrs pkg.tests or { } ( + testName: test: { + "${nixpkgsPrefix}${pkgName}-${testName}" = test; + } + ) + ) + // lib.optionalAttrs (nixpkgs.stdenv.hostPlatform == nixpkgs.stdenv.buildPlatform) { + "${nixpkgsPrefix}nix-functional-tests" = nixpkgs.nixComponents.nix-functional-tests; + } + ) + // devFlake.checks.${system} or { } ); - packages = forAllSystems (system: - { # Here we put attributes that map 1:1 into packages., ie + packages = forAllSystems ( + system: + { + # Here we put attributes that map 1:1 into packages., ie # for which we don't apply the full build matrix such as cross or static. inherit (nixpkgsFor.${system}.native) - changelog-d; + changelog-d + ; default = self.packages.${system}.nix; installerScriptForGHA = self.hydraJobs.installerScriptForGHA.${system}; binaryTarball = self.hydraJobs.binaryTarball.${system}; @@ -243,96 +294,143 @@ nix-external-api-docs = nixpkgsFor.${system}.native.nixComponents.nix-external-api-docs; } # We need to flatten recursive attribute sets of derivations to pass `flake check`. - // flatMapAttrs - { # Components we'll iterate over in the upcoming lambda - "nix-util" = { }; - "nix-util-c" = { }; - "nix-util-test-support" = { }; - "nix-util-tests" = { }; + // + flatMapAttrs + { + # Components we'll iterate over in the upcoming lambda + "nix-util" = { }; + "nix-util-c" = { }; + "nix-util-test-support" = { }; + "nix-util-tests" = { }; - "nix-store" = { }; - "nix-store-c" = { }; - "nix-store-test-support" = { }; - "nix-store-tests" = { }; + "nix-store" = { }; + "nix-store-c" = { }; + "nix-store-test-support" = { }; + "nix-store-tests" = { }; - "nix-fetchers" = { }; - "nix-fetchers-tests" = { }; + "nix-fetchers" = { }; + "nix-fetchers-tests" = { }; - "nix-expr" = { }; - "nix-expr-c" = { }; - "nix-expr-test-support" = { }; - "nix-expr-tests" = { }; + "nix-expr" = { }; + "nix-expr-c" = { }; + "nix-expr-test-support" = { }; + "nix-expr-tests" = { }; - "nix-flake" = { }; - "nix-flake-tests" = { }; + "nix-flake" = { }; + "nix-flake-tests" = { }; - "nix-main" = { }; - "nix-main-c" = { }; + "nix-main" = { }; + "nix-main-c" = { }; - "nix-cmd" = { }; + "nix-cmd" = { }; - "nix-cli" = { }; + "nix-cli" = { }; - "nix-everything" = { }; + "nix-everything" = { }; - "nix-functional-tests" = { supportsCross = false; }; + "nix-functional-tests" = { + supportsCross = false; + }; - "nix-perl-bindings" = { supportsCross = false; }; - } - (pkgName: { supportsCross ? true }: { - # These attributes go right into `packages.`. - "${pkgName}" = nixpkgsFor.${system}.native.nixComponents.${pkgName}; - "${pkgName}-static" = nixpkgsFor.${system}.static.nixComponents.${pkgName}; - "${pkgName}-llvm" = nixpkgsFor.${system}.llvm.nixComponents.${pkgName}; + "nix-perl-bindings" = { + supportsCross = false; + }; } - // lib.optionalAttrs supportsCross (flatMapAttrs (lib.genAttrs crossSystems (_: { })) (crossSystem: {}: { - # These attributes go right into `packages.`. - "${pkgName}-${crossSystem}" = nixpkgsFor.${system}.cross.${crossSystem}.nixComponents.${pkgName}; - })) - // flatMapAttrs (lib.genAttrs stdenvs (_: { })) (stdenvName: {}: { - # These attributes go right into `packages.`. - "${pkgName}-${stdenvName}" = nixpkgsFor.${system}.stdenvs."${stdenvName}Packages".nixComponents.${pkgName}; - }) - ) + ( + pkgName: + { + supportsCross ? true, + }: + { + # These attributes go right into `packages.`. + "${pkgName}" = nixpkgsFor.${system}.native.nixComponents.${pkgName}; + "${pkgName}-static" = nixpkgsFor.${system}.static.nixComponents.${pkgName}; + "${pkgName}-llvm" = nixpkgsFor.${system}.llvm.nixComponents.${pkgName}; + } + // lib.optionalAttrs supportsCross ( + flatMapAttrs (lib.genAttrs crossSystems (_: { })) ( + crossSystem: + { }: + { + # These attributes go right into `packages.`. + "${pkgName}-${crossSystem}" = nixpkgsFor.${system}.cross.${crossSystem}.nixComponents.${pkgName}; + } + ) + ) + // flatMapAttrs (lib.genAttrs stdenvs (_: { })) ( + stdenvName: + { }: + { + # These attributes go right into `packages.`. + "${pkgName}-${stdenvName}" = + nixpkgsFor.${system}.stdenvs."${stdenvName}Packages".nixComponents.${pkgName}; + } + ) + ) // lib.optionalAttrs (builtins.elem system linux64BitSystems) { - dockerImage = - let - pkgs = nixpkgsFor.${system}.native; - image = import ./docker.nix { inherit pkgs; tag = pkgs.nix.version; }; - in - pkgs.runCommand - "docker-image-tarball-${pkgs.nix.version}" - { meta.description = "Docker image with Nix for ${system}"; } - '' - mkdir -p $out/nix-support - image=$out/image.tar.gz - ln -s ${image} $image - echo "file binary-dist $image" >> $out/nix-support/hydra-build-products - ''; - }); + dockerImage = + let + pkgs = nixpkgsFor.${system}.native; + image = import ./docker.nix { + inherit pkgs; + tag = pkgs.nix.version; + }; + in + pkgs.runCommand "docker-image-tarball-${pkgs.nix.version}" + { meta.description = "Docker image with Nix for ${system}"; } + '' + mkdir -p $out/nix-support + image=$out/image.tar.gz + ln -s ${image} $image + echo "file binary-dist $image" >> $out/nix-support/hydra-build-products + ''; + } + ); - devShells = let - makeShell = import ./packaging/dev-shell.nix { inherit lib devFlake; }; - prefixAttrs = prefix: lib.concatMapAttrs (k: v: { "${prefix}-${k}" = v; }); - in - forAllSystems (system: - prefixAttrs "native" (forAllStdenvs (stdenvName: makeShell { - pkgs = nixpkgsFor.${system}.stdenvs."${stdenvName}Packages"; - })) // - lib.optionalAttrs (!nixpkgsFor.${system}.native.stdenv.isDarwin) ( - prefixAttrs "static" (forAllStdenvs (stdenvName: makeShell { - pkgs = nixpkgsFor.${system}.stdenvs."${stdenvName}Packages".pkgsStatic; - })) // - prefixAttrs "llvm" (forAllStdenvs (stdenvName: makeShell { - pkgs = nixpkgsFor.${system}.stdenvs."${stdenvName}Packages".pkgsLLVM; - })) // - prefixAttrs "cross" (forAllCrossSystems (crossSystem: makeShell { - pkgs = nixpkgsFor.${system}.cross.${crossSystem}; - })) - ) // - { + devShells = + let + makeShell = import ./packaging/dev-shell.nix { inherit lib devFlake; }; + prefixAttrs = prefix: lib.concatMapAttrs (k: v: { "${prefix}-${k}" = v; }); + in + forAllSystems ( + system: + prefixAttrs "native" ( + forAllStdenvs ( + stdenvName: + makeShell { + pkgs = nixpkgsFor.${system}.stdenvs."${stdenvName}Packages"; + } + ) + ) + // lib.optionalAttrs (!nixpkgsFor.${system}.native.stdenv.isDarwin) ( + prefixAttrs "static" ( + forAllStdenvs ( + stdenvName: + makeShell { + pkgs = nixpkgsFor.${system}.stdenvs."${stdenvName}Packages".pkgsStatic; + } + ) + ) + // prefixAttrs "llvm" ( + forAllStdenvs ( + stdenvName: + makeShell { + pkgs = nixpkgsFor.${system}.stdenvs."${stdenvName}Packages".pkgsLLVM; + } + ) + ) + // prefixAttrs "cross" ( + forAllCrossSystems ( + crossSystem: + makeShell { + pkgs = nixpkgsFor.${system}.cross.${crossSystem}; + } + ) + ) + ) + // { default = self.devShells.${system}.native-stdenvPackages; } ); - }; + }; } diff --git a/maintainers/flake-module.nix b/maintainers/flake-module.nix index fcf370b71..9b2c6dcbf 100644 --- a/maintainers/flake-module.nix +++ b/maintainers/flake-module.nix @@ -1,669 +1,676 @@ -{ lib, getSystem, inputs, ... }: +{ + lib, + getSystem, + inputs, + ... +}: { imports = [ inputs.git-hooks-nix.flakeModule ]; - perSystem = { config, pkgs, ... }: { + perSystem = + { config, pkgs, ... }: + { - # https://flake.parts/options/git-hooks-nix#options - pre-commit.settings = { - hooks = { - # Conflicts are usually found by other checks, but not those in docs, - # and potentially other places. - check-merge-conflicts.enable = true; - # built-in check-merge-conflicts seems ineffective against those produced by mergify backports - check-merge-conflicts-2 = { - enable = true; - entry = "${pkgs.writeScript "check-merge-conflicts" '' - #!${pkgs.runtimeShell} - conflicts=false - for file in "$@"; do - if grep --with-filename --line-number -E '^>>>>>>> ' -- "$file"; then - conflicts=true + # https://flake.parts/options/git-hooks-nix#options + pre-commit.settings = { + hooks = { + # Conflicts are usually found by other checks, but not those in docs, + # and potentially other places. + check-merge-conflicts.enable = true; + # built-in check-merge-conflicts seems ineffective against those produced by mergify backports + check-merge-conflicts-2 = { + enable = true; + entry = "${pkgs.writeScript "check-merge-conflicts" '' + #!${pkgs.runtimeShell} + conflicts=false + for file in "$@"; do + if grep --with-filename --line-number -E '^>>>>>>> ' -- "$file"; then + conflicts=true + fi + done + if $conflicts; then + echo "ERROR: found merge/patch conflicts in files" + exit 1 fi - done - if $conflicts; then - echo "ERROR: found merge/patch conflicts in files" - exit 1 - fi - touch $out - ''}"; - }; - clang-format = { - enable = true; - # https://github.com/cachix/git-hooks.nix/pull/532 - package = pkgs.llvmPackages_latest.clang-tools; - excludes = [ - # We don't want to format test data - # ''tests/(?!nixos/).*\.nix'' - ''^src/[^/]*-tests/data/.*$'' + touch $out + ''}"; + }; + clang-format = { + enable = true; + # https://github.com/cachix/git-hooks.nix/pull/532 + package = pkgs.llvmPackages_latest.clang-tools; + excludes = [ + # We don't want to format test data + # ''tests/(?!nixos/).*\.nix'' + ''^src/[^/]*-tests/data/.*$'' - # Don't format vendored code - ''^doc/manual/redirects\.js$'' - ''^doc/manual/theme/highlight\.js$'' + # Don't format vendored code + ''^doc/manual/redirects\.js$'' + ''^doc/manual/theme/highlight\.js$'' - # We haven't applied formatting to these files yet - ''^doc/manual/redirects\.js$'' - ''^doc/manual/theme/highlight\.js$'' - ''^precompiled-headers\.h$'' - ''^src/build-remote/build-remote\.cc$'' - ''^src/libcmd/built-path\.cc$'' - ''^src/libcmd/built-path\.hh$'' - ''^src/libcmd/common-eval-args\.cc$'' - ''^src/libcmd/common-eval-args\.hh$'' - ''^src/libcmd/editor-for\.cc$'' - ''^src/libcmd/installable-attr-path\.cc$'' - ''^src/libcmd/installable-attr-path\.hh$'' - ''^src/libcmd/installable-derived-path\.cc$'' - ''^src/libcmd/installable-derived-path\.hh$'' - ''^src/libcmd/installable-flake\.cc$'' - ''^src/libcmd/installable-flake\.hh$'' - ''^src/libcmd/installable-value\.cc$'' - ''^src/libcmd/installable-value\.hh$'' - ''^src/libcmd/installables\.cc$'' - ''^src/libcmd/installables\.hh$'' - ''^src/libcmd/legacy\.hh$'' - ''^src/libcmd/markdown\.cc$'' - ''^src/libcmd/misc-store-flags\.cc$'' - ''^src/libcmd/repl-interacter\.cc$'' - ''^src/libcmd/repl-interacter\.hh$'' - ''^src/libcmd/repl\.cc$'' - ''^src/libcmd/repl\.hh$'' - ''^src/libexpr-c/nix_api_expr\.cc$'' - ''^src/libexpr-c/nix_api_external\.cc$'' - ''^src/libexpr/attr-path\.cc$'' - ''^src/libexpr/attr-path\.hh$'' - ''^src/libexpr/attr-set\.cc$'' - ''^src/libexpr/attr-set\.hh$'' - ''^src/libexpr/eval-cache\.cc$'' - ''^src/libexpr/eval-cache\.hh$'' - ''^src/libexpr/eval-error\.cc$'' - ''^src/libexpr/eval-inline\.hh$'' - ''^src/libexpr/eval-settings\.cc$'' - ''^src/libexpr/eval-settings\.hh$'' - ''^src/libexpr/eval\.cc$'' - ''^src/libexpr/eval\.hh$'' - ''^src/libexpr/function-trace\.cc$'' - ''^src/libexpr/gc-small-vector\.hh$'' - ''^src/libexpr/get-drvs\.cc$'' - ''^src/libexpr/get-drvs\.hh$'' - ''^src/libexpr/json-to-value\.cc$'' - ''^src/libexpr/nixexpr\.cc$'' - ''^src/libexpr/nixexpr\.hh$'' - ''^src/libexpr/parser-state\.hh$'' - ''^src/libexpr/pos-table\.hh$'' - ''^src/libexpr/primops\.cc$'' - ''^src/libexpr/primops\.hh$'' - ''^src/libexpr/primops/context\.cc$'' - ''^src/libexpr/primops/fetchClosure\.cc$'' - ''^src/libexpr/primops/fetchMercurial\.cc$'' - ''^src/libexpr/primops/fetchTree\.cc$'' - ''^src/libexpr/primops/fromTOML\.cc$'' - ''^src/libexpr/print-ambiguous\.cc$'' - ''^src/libexpr/print-ambiguous\.hh$'' - ''^src/libexpr/print-options\.hh$'' - ''^src/libexpr/print\.cc$'' - ''^src/libexpr/print\.hh$'' - ''^src/libexpr/search-path\.cc$'' - ''^src/libexpr/symbol-table\.hh$'' - ''^src/libexpr/value-to-json\.cc$'' - ''^src/libexpr/value-to-json\.hh$'' - ''^src/libexpr/value-to-xml\.cc$'' - ''^src/libexpr/value-to-xml\.hh$'' - ''^src/libexpr/value\.hh$'' - ''^src/libexpr/value/context\.cc$'' - ''^src/libexpr/value/context\.hh$'' - ''^src/libfetchers/attrs\.cc$'' - ''^src/libfetchers/cache\.cc$'' - ''^src/libfetchers/cache\.hh$'' - ''^src/libfetchers/fetch-settings\.cc$'' - ''^src/libfetchers/fetch-settings\.hh$'' - ''^src/libfetchers/fetch-to-store\.cc$'' - ''^src/libfetchers/fetchers\.cc$'' - ''^src/libfetchers/fetchers\.hh$'' - ''^src/libfetchers/filtering-source-accessor\.cc$'' - ''^src/libfetchers/filtering-source-accessor\.hh$'' - ''^src/libfetchers/fs-source-accessor\.cc$'' - ''^src/libfetchers/fs-source-accessor\.hh$'' - ''^src/libfetchers/git-utils\.cc$'' - ''^src/libfetchers/git-utils\.hh$'' - ''^src/libfetchers/github\.cc$'' - ''^src/libfetchers/indirect\.cc$'' - ''^src/libfetchers/memory-source-accessor\.cc$'' - ''^src/libfetchers/path\.cc$'' - ''^src/libfetchers/registry\.cc$'' - ''^src/libfetchers/registry\.hh$'' - ''^src/libfetchers/tarball\.cc$'' - ''^src/libfetchers/tarball\.hh$'' - ''^src/libfetchers/git\.cc$'' - ''^src/libfetchers/mercurial\.cc$'' - ''^src/libflake/flake/config\.cc$'' - ''^src/libflake/flake/flake\.cc$'' - ''^src/libflake/flake/flake\.hh$'' - ''^src/libflake/flake/flakeref\.cc$'' - ''^src/libflake/flake/flakeref\.hh$'' - ''^src/libflake/flake/lockfile\.cc$'' - ''^src/libflake/flake/lockfile\.hh$'' - ''^src/libflake/flake/url-name\.cc$'' - ''^src/libmain/common-args\.cc$'' - ''^src/libmain/common-args\.hh$'' - ''^src/libmain/loggers\.cc$'' - ''^src/libmain/loggers\.hh$'' - ''^src/libmain/progress-bar\.cc$'' - ''^src/libmain/shared\.cc$'' - ''^src/libmain/shared\.hh$'' - ''^src/libmain/unix/stack\.cc$'' - ''^src/libstore/binary-cache-store\.cc$'' - ''^src/libstore/binary-cache-store\.hh$'' - ''^src/libstore/build-result\.hh$'' - ''^src/libstore/builtins\.hh$'' - ''^src/libstore/builtins/buildenv\.cc$'' - ''^src/libstore/builtins/buildenv\.hh$'' - ''^src/libstore/common-protocol-impl\.hh$'' - ''^src/libstore/common-protocol\.cc$'' - ''^src/libstore/common-protocol\.hh$'' - ''^src/libstore/common-ssh-store-config\.hh$'' - ''^src/libstore/content-address\.cc$'' - ''^src/libstore/content-address\.hh$'' - ''^src/libstore/daemon\.cc$'' - ''^src/libstore/daemon\.hh$'' - ''^src/libstore/derivations\.cc$'' - ''^src/libstore/derivations\.hh$'' - ''^src/libstore/derived-path-map\.cc$'' - ''^src/libstore/derived-path-map\.hh$'' - ''^src/libstore/derived-path\.cc$'' - ''^src/libstore/derived-path\.hh$'' - ''^src/libstore/downstream-placeholder\.cc$'' - ''^src/libstore/downstream-placeholder\.hh$'' - ''^src/libstore/dummy-store\.cc$'' - ''^src/libstore/export-import\.cc$'' - ''^src/libstore/filetransfer\.cc$'' - ''^src/libstore/filetransfer\.hh$'' - ''^src/libstore/gc-store\.hh$'' - ''^src/libstore/globals\.cc$'' - ''^src/libstore/globals\.hh$'' - ''^src/libstore/http-binary-cache-store\.cc$'' - ''^src/libstore/legacy-ssh-store\.cc$'' - ''^src/libstore/legacy-ssh-store\.hh$'' - ''^src/libstore/length-prefixed-protocol-helper\.hh$'' - ''^src/libstore/linux/personality\.cc$'' - ''^src/libstore/linux/personality\.hh$'' - ''^src/libstore/local-binary-cache-store\.cc$'' - ''^src/libstore/local-fs-store\.cc$'' - ''^src/libstore/local-fs-store\.hh$'' - ''^src/libstore/log-store\.cc$'' - ''^src/libstore/log-store\.hh$'' - ''^src/libstore/machines\.cc$'' - ''^src/libstore/machines\.hh$'' - ''^src/libstore/make-content-addressed\.cc$'' - ''^src/libstore/make-content-addressed\.hh$'' - ''^src/libstore/misc\.cc$'' - ''^src/libstore/names\.cc$'' - ''^src/libstore/names\.hh$'' - ''^src/libstore/nar-accessor\.cc$'' - ''^src/libstore/nar-accessor\.hh$'' - ''^src/libstore/nar-info-disk-cache\.cc$'' - ''^src/libstore/nar-info-disk-cache\.hh$'' - ''^src/libstore/nar-info\.cc$'' - ''^src/libstore/nar-info\.hh$'' - ''^src/libstore/outputs-spec\.cc$'' - ''^src/libstore/outputs-spec\.hh$'' - ''^src/libstore/parsed-derivations\.cc$'' - ''^src/libstore/path-info\.cc$'' - ''^src/libstore/path-info\.hh$'' - ''^src/libstore/path-references\.cc$'' - ''^src/libstore/path-regex\.hh$'' - ''^src/libstore/path-with-outputs\.cc$'' - ''^src/libstore/path\.cc$'' - ''^src/libstore/path\.hh$'' - ''^src/libstore/pathlocks\.cc$'' - ''^src/libstore/pathlocks\.hh$'' - ''^src/libstore/profiles\.cc$'' - ''^src/libstore/profiles\.hh$'' - ''^src/libstore/realisation\.cc$'' - ''^src/libstore/realisation\.hh$'' - ''^src/libstore/remote-fs-accessor\.cc$'' - ''^src/libstore/remote-fs-accessor\.hh$'' - ''^src/libstore/remote-store-connection\.hh$'' - ''^src/libstore/remote-store\.cc$'' - ''^src/libstore/remote-store\.hh$'' - ''^src/libstore/s3-binary-cache-store\.cc$'' - ''^src/libstore/s3\.hh$'' - ''^src/libstore/serve-protocol-impl\.cc$'' - ''^src/libstore/serve-protocol-impl\.hh$'' - ''^src/libstore/serve-protocol\.cc$'' - ''^src/libstore/serve-protocol\.hh$'' - ''^src/libstore/sqlite\.cc$'' - ''^src/libstore/sqlite\.hh$'' - ''^src/libstore/ssh-store\.cc$'' - ''^src/libstore/ssh\.cc$'' - ''^src/libstore/ssh\.hh$'' - ''^src/libstore/store-api\.cc$'' - ''^src/libstore/store-api\.hh$'' - ''^src/libstore/store-dir-config\.hh$'' - ''^src/libstore/build/derivation-goal\.cc$'' - ''^src/libstore/build/derivation-goal\.hh$'' - ''^src/libstore/build/drv-output-substitution-goal\.cc$'' - ''^src/libstore/build/drv-output-substitution-goal\.hh$'' - ''^src/libstore/build/entry-points\.cc$'' - ''^src/libstore/build/goal\.cc$'' - ''^src/libstore/build/goal\.hh$'' - ''^src/libstore/unix/build/hook-instance\.cc$'' - ''^src/libstore/unix/build/local-derivation-goal\.cc$'' - ''^src/libstore/unix/build/local-derivation-goal\.hh$'' - ''^src/libstore/build/substitution-goal\.cc$'' - ''^src/libstore/build/substitution-goal\.hh$'' - ''^src/libstore/build/worker\.cc$'' - ''^src/libstore/build/worker\.hh$'' - ''^src/libstore/builtins/fetchurl\.cc$'' - ''^src/libstore/builtins/unpack-channel\.cc$'' - ''^src/libstore/gc\.cc$'' - ''^src/libstore/local-overlay-store\.cc$'' - ''^src/libstore/local-overlay-store\.hh$'' - ''^src/libstore/local-store\.cc$'' - ''^src/libstore/local-store\.hh$'' - ''^src/libstore/unix/user-lock\.cc$'' - ''^src/libstore/unix/user-lock\.hh$'' - ''^src/libstore/optimise-store\.cc$'' - ''^src/libstore/unix/pathlocks\.cc$'' - ''^src/libstore/posix-fs-canonicalise\.cc$'' - ''^src/libstore/posix-fs-canonicalise\.hh$'' - ''^src/libstore/uds-remote-store\.cc$'' - ''^src/libstore/uds-remote-store\.hh$'' - ''^src/libstore/windows/build\.cc$'' - ''^src/libstore/worker-protocol-impl\.hh$'' - ''^src/libstore/worker-protocol\.cc$'' - ''^src/libstore/worker-protocol\.hh$'' - ''^src/libutil-c/nix_api_util_internal\.h$'' - ''^src/libutil/archive\.cc$'' - ''^src/libutil/archive\.hh$'' - ''^src/libutil/args\.cc$'' - ''^src/libutil/args\.hh$'' - ''^src/libutil/args/root\.hh$'' - ''^src/libutil/callback\.hh$'' - ''^src/libutil/canon-path\.cc$'' - ''^src/libutil/canon-path\.hh$'' - ''^src/libutil/chunked-vector\.hh$'' - ''^src/libutil/closure\.hh$'' - ''^src/libutil/comparator\.hh$'' - ''^src/libutil/compute-levels\.cc$'' - ''^src/libutil/config-impl\.hh$'' - ''^src/libutil/config\.cc$'' - ''^src/libutil/config\.hh$'' - ''^src/libutil/current-process\.cc$'' - ''^src/libutil/current-process\.hh$'' - ''^src/libutil/english\.cc$'' - ''^src/libutil/english\.hh$'' - ''^src/libutil/error\.cc$'' - ''^src/libutil/error\.hh$'' - ''^src/libutil/exit\.hh$'' - ''^src/libutil/experimental-features\.cc$'' - ''^src/libutil/experimental-features\.hh$'' - ''^src/libutil/file-content-address\.cc$'' - ''^src/libutil/file-content-address\.hh$'' - ''^src/libutil/file-descriptor\.cc$'' - ''^src/libutil/file-descriptor\.hh$'' - ''^src/libutil/file-path-impl\.hh$'' - ''^src/libutil/file-path\.hh$'' - ''^src/libutil/file-system\.cc$'' - ''^src/libutil/file-system\.hh$'' - ''^src/libutil/finally\.hh$'' - ''^src/libutil/fmt\.hh$'' - ''^src/libutil/fs-sink\.cc$'' - ''^src/libutil/fs-sink\.hh$'' - ''^src/libutil/git\.cc$'' - ''^src/libutil/git\.hh$'' - ''^src/libutil/hash\.cc$'' - ''^src/libutil/hash\.hh$'' - ''^src/libutil/hilite\.cc$'' - ''^src/libutil/hilite\.hh$'' - ''^src/libutil/source-accessor\.hh$'' - ''^src/libutil/json-impls\.hh$'' - ''^src/libutil/json-utils\.cc$'' - ''^src/libutil/json-utils\.hh$'' - ''^src/libutil/linux/cgroup\.cc$'' - ''^src/libutil/linux/namespaces\.cc$'' - ''^src/libutil/logging\.cc$'' - ''^src/libutil/logging\.hh$'' - ''^src/libutil/lru-cache\.hh$'' - ''^src/libutil/memory-source-accessor\.cc$'' - ''^src/libutil/memory-source-accessor\.hh$'' - ''^src/libutil/pool\.hh$'' - ''^src/libutil/position\.cc$'' - ''^src/libutil/position\.hh$'' - ''^src/libutil/posix-source-accessor\.cc$'' - ''^src/libutil/posix-source-accessor\.hh$'' - ''^src/libutil/processes\.hh$'' - ''^src/libutil/ref\.hh$'' - ''^src/libutil/references\.cc$'' - ''^src/libutil/references\.hh$'' - ''^src/libutil/regex-combinators\.hh$'' - ''^src/libutil/serialise\.cc$'' - ''^src/libutil/serialise\.hh$'' - ''^src/libutil/signals\.hh$'' - ''^src/libutil/signature/local-keys\.cc$'' - ''^src/libutil/signature/local-keys\.hh$'' - ''^src/libutil/signature/signer\.cc$'' - ''^src/libutil/signature/signer\.hh$'' - ''^src/libutil/source-accessor\.cc$'' - ''^src/libutil/source-accessor\.hh$'' - ''^src/libutil/source-path\.cc$'' - ''^src/libutil/source-path\.hh$'' - ''^src/libutil/split\.hh$'' - ''^src/libutil/suggestions\.cc$'' - ''^src/libutil/suggestions\.hh$'' - ''^src/libutil/sync\.hh$'' - ''^src/libutil/terminal\.cc$'' - ''^src/libutil/terminal\.hh$'' - ''^src/libutil/thread-pool\.cc$'' - ''^src/libutil/thread-pool\.hh$'' - ''^src/libutil/topo-sort\.hh$'' - ''^src/libutil/types\.hh$'' - ''^src/libutil/unix/file-descriptor\.cc$'' - ''^src/libutil/unix/file-path\.cc$'' - ''^src/libutil/unix/monitor-fd\.hh$'' - ''^src/libutil/unix/processes\.cc$'' - ''^src/libutil/unix/signals-impl\.hh$'' - ''^src/libutil/unix/signals\.cc$'' - ''^src/libutil/unix-domain-socket\.cc$'' - ''^src/libutil/unix/users\.cc$'' - ''^src/libutil/url-parts\.hh$'' - ''^src/libutil/url\.cc$'' - ''^src/libutil/url\.hh$'' - ''^src/libutil/users\.cc$'' - ''^src/libutil/users\.hh$'' - ''^src/libutil/util\.cc$'' - ''^src/libutil/util\.hh$'' - ''^src/libutil/variant-wrapper\.hh$'' - ''^src/libutil/widecharwidth/widechar_width\.h$'' # vendored source - ''^src/libutil/windows/file-descriptor\.cc$'' - ''^src/libutil/windows/file-path\.cc$'' - ''^src/libutil/windows/processes\.cc$'' - ''^src/libutil/windows/users\.cc$'' - ''^src/libutil/windows/windows-error\.cc$'' - ''^src/libutil/windows/windows-error\.hh$'' - ''^src/libutil/xml-writer\.cc$'' - ''^src/libutil/xml-writer\.hh$'' - ''^src/nix-build/nix-build\.cc$'' - ''^src/nix-channel/nix-channel\.cc$'' - ''^src/nix-collect-garbage/nix-collect-garbage\.cc$'' - ''^src/nix-env/buildenv.nix$'' - ''^src/nix-env/nix-env\.cc$'' - ''^src/nix-env/user-env\.cc$'' - ''^src/nix-env/user-env\.hh$'' - ''^src/nix-instantiate/nix-instantiate\.cc$'' - ''^src/nix-store/dotgraph\.cc$'' - ''^src/nix-store/graphml\.cc$'' - ''^src/nix-store/nix-store\.cc$'' - ''^src/nix/add-to-store\.cc$'' - ''^src/nix/app\.cc$'' - ''^src/nix/build\.cc$'' - ''^src/nix/bundle\.cc$'' - ''^src/nix/cat\.cc$'' - ''^src/nix/config-check\.cc$'' - ''^src/nix/config\.cc$'' - ''^src/nix/copy\.cc$'' - ''^src/nix/derivation-add\.cc$'' - ''^src/nix/derivation-show\.cc$'' - ''^src/nix/derivation\.cc$'' - ''^src/nix/develop\.cc$'' - ''^src/nix/diff-closures\.cc$'' - ''^src/nix/dump-path\.cc$'' - ''^src/nix/edit\.cc$'' - ''^src/nix/eval\.cc$'' - ''^src/nix/flake\.cc$'' - ''^src/nix/fmt\.cc$'' - ''^src/nix/hash\.cc$'' - ''^src/nix/log\.cc$'' - ''^src/nix/ls\.cc$'' - ''^src/nix/main\.cc$'' - ''^src/nix/make-content-addressed\.cc$'' - ''^src/nix/nar\.cc$'' - ''^src/nix/optimise-store\.cc$'' - ''^src/nix/path-from-hash-part\.cc$'' - ''^src/nix/path-info\.cc$'' - ''^src/nix/prefetch\.cc$'' - ''^src/nix/profile\.cc$'' - ''^src/nix/realisation\.cc$'' - ''^src/nix/registry\.cc$'' - ''^src/nix/repl\.cc$'' - ''^src/nix/run\.cc$'' - ''^src/nix/run\.hh$'' - ''^src/nix/search\.cc$'' - ''^src/nix/sigs\.cc$'' - ''^src/nix/store-copy-log\.cc$'' - ''^src/nix/store-delete\.cc$'' - ''^src/nix/store-gc\.cc$'' - ''^src/nix/store-info\.cc$'' - ''^src/nix/store-repair\.cc$'' - ''^src/nix/store\.cc$'' - ''^src/nix/unix/daemon\.cc$'' - ''^src/nix/upgrade-nix\.cc$'' - ''^src/nix/verify\.cc$'' - ''^src/nix/why-depends\.cc$'' + # We haven't applied formatting to these files yet + ''^doc/manual/redirects\.js$'' + ''^doc/manual/theme/highlight\.js$'' + ''^precompiled-headers\.h$'' + ''^src/build-remote/build-remote\.cc$'' + ''^src/libcmd/built-path\.cc$'' + ''^src/libcmd/built-path\.hh$'' + ''^src/libcmd/common-eval-args\.cc$'' + ''^src/libcmd/common-eval-args\.hh$'' + ''^src/libcmd/editor-for\.cc$'' + ''^src/libcmd/installable-attr-path\.cc$'' + ''^src/libcmd/installable-attr-path\.hh$'' + ''^src/libcmd/installable-derived-path\.cc$'' + ''^src/libcmd/installable-derived-path\.hh$'' + ''^src/libcmd/installable-flake\.cc$'' + ''^src/libcmd/installable-flake\.hh$'' + ''^src/libcmd/installable-value\.cc$'' + ''^src/libcmd/installable-value\.hh$'' + ''^src/libcmd/installables\.cc$'' + ''^src/libcmd/installables\.hh$'' + ''^src/libcmd/legacy\.hh$'' + ''^src/libcmd/markdown\.cc$'' + ''^src/libcmd/misc-store-flags\.cc$'' + ''^src/libcmd/repl-interacter\.cc$'' + ''^src/libcmd/repl-interacter\.hh$'' + ''^src/libcmd/repl\.cc$'' + ''^src/libcmd/repl\.hh$'' + ''^src/libexpr-c/nix_api_expr\.cc$'' + ''^src/libexpr-c/nix_api_external\.cc$'' + ''^src/libexpr/attr-path\.cc$'' + ''^src/libexpr/attr-path\.hh$'' + ''^src/libexpr/attr-set\.cc$'' + ''^src/libexpr/attr-set\.hh$'' + ''^src/libexpr/eval-cache\.cc$'' + ''^src/libexpr/eval-cache\.hh$'' + ''^src/libexpr/eval-error\.cc$'' + ''^src/libexpr/eval-inline\.hh$'' + ''^src/libexpr/eval-settings\.cc$'' + ''^src/libexpr/eval-settings\.hh$'' + ''^src/libexpr/eval\.cc$'' + ''^src/libexpr/eval\.hh$'' + ''^src/libexpr/function-trace\.cc$'' + ''^src/libexpr/gc-small-vector\.hh$'' + ''^src/libexpr/get-drvs\.cc$'' + ''^src/libexpr/get-drvs\.hh$'' + ''^src/libexpr/json-to-value\.cc$'' + ''^src/libexpr/nixexpr\.cc$'' + ''^src/libexpr/nixexpr\.hh$'' + ''^src/libexpr/parser-state\.hh$'' + ''^src/libexpr/pos-table\.hh$'' + ''^src/libexpr/primops\.cc$'' + ''^src/libexpr/primops\.hh$'' + ''^src/libexpr/primops/context\.cc$'' + ''^src/libexpr/primops/fetchClosure\.cc$'' + ''^src/libexpr/primops/fetchMercurial\.cc$'' + ''^src/libexpr/primops/fetchTree\.cc$'' + ''^src/libexpr/primops/fromTOML\.cc$'' + ''^src/libexpr/print-ambiguous\.cc$'' + ''^src/libexpr/print-ambiguous\.hh$'' + ''^src/libexpr/print-options\.hh$'' + ''^src/libexpr/print\.cc$'' + ''^src/libexpr/print\.hh$'' + ''^src/libexpr/search-path\.cc$'' + ''^src/libexpr/symbol-table\.hh$'' + ''^src/libexpr/value-to-json\.cc$'' + ''^src/libexpr/value-to-json\.hh$'' + ''^src/libexpr/value-to-xml\.cc$'' + ''^src/libexpr/value-to-xml\.hh$'' + ''^src/libexpr/value\.hh$'' + ''^src/libexpr/value/context\.cc$'' + ''^src/libexpr/value/context\.hh$'' + ''^src/libfetchers/attrs\.cc$'' + ''^src/libfetchers/cache\.cc$'' + ''^src/libfetchers/cache\.hh$'' + ''^src/libfetchers/fetch-settings\.cc$'' + ''^src/libfetchers/fetch-settings\.hh$'' + ''^src/libfetchers/fetch-to-store\.cc$'' + ''^src/libfetchers/fetchers\.cc$'' + ''^src/libfetchers/fetchers\.hh$'' + ''^src/libfetchers/filtering-source-accessor\.cc$'' + ''^src/libfetchers/filtering-source-accessor\.hh$'' + ''^src/libfetchers/fs-source-accessor\.cc$'' + ''^src/libfetchers/fs-source-accessor\.hh$'' + ''^src/libfetchers/git-utils\.cc$'' + ''^src/libfetchers/git-utils\.hh$'' + ''^src/libfetchers/github\.cc$'' + ''^src/libfetchers/indirect\.cc$'' + ''^src/libfetchers/memory-source-accessor\.cc$'' + ''^src/libfetchers/path\.cc$'' + ''^src/libfetchers/registry\.cc$'' + ''^src/libfetchers/registry\.hh$'' + ''^src/libfetchers/tarball\.cc$'' + ''^src/libfetchers/tarball\.hh$'' + ''^src/libfetchers/git\.cc$'' + ''^src/libfetchers/mercurial\.cc$'' + ''^src/libflake/flake/config\.cc$'' + ''^src/libflake/flake/flake\.cc$'' + ''^src/libflake/flake/flake\.hh$'' + ''^src/libflake/flake/flakeref\.cc$'' + ''^src/libflake/flake/flakeref\.hh$'' + ''^src/libflake/flake/lockfile\.cc$'' + ''^src/libflake/flake/lockfile\.hh$'' + ''^src/libflake/flake/url-name\.cc$'' + ''^src/libmain/common-args\.cc$'' + ''^src/libmain/common-args\.hh$'' + ''^src/libmain/loggers\.cc$'' + ''^src/libmain/loggers\.hh$'' + ''^src/libmain/progress-bar\.cc$'' + ''^src/libmain/shared\.cc$'' + ''^src/libmain/shared\.hh$'' + ''^src/libmain/unix/stack\.cc$'' + ''^src/libstore/binary-cache-store\.cc$'' + ''^src/libstore/binary-cache-store\.hh$'' + ''^src/libstore/build-result\.hh$'' + ''^src/libstore/builtins\.hh$'' + ''^src/libstore/builtins/buildenv\.cc$'' + ''^src/libstore/builtins/buildenv\.hh$'' + ''^src/libstore/common-protocol-impl\.hh$'' + ''^src/libstore/common-protocol\.cc$'' + ''^src/libstore/common-protocol\.hh$'' + ''^src/libstore/common-ssh-store-config\.hh$'' + ''^src/libstore/content-address\.cc$'' + ''^src/libstore/content-address\.hh$'' + ''^src/libstore/daemon\.cc$'' + ''^src/libstore/daemon\.hh$'' + ''^src/libstore/derivations\.cc$'' + ''^src/libstore/derivations\.hh$'' + ''^src/libstore/derived-path-map\.cc$'' + ''^src/libstore/derived-path-map\.hh$'' + ''^src/libstore/derived-path\.cc$'' + ''^src/libstore/derived-path\.hh$'' + ''^src/libstore/downstream-placeholder\.cc$'' + ''^src/libstore/downstream-placeholder\.hh$'' + ''^src/libstore/dummy-store\.cc$'' + ''^src/libstore/export-import\.cc$'' + ''^src/libstore/filetransfer\.cc$'' + ''^src/libstore/filetransfer\.hh$'' + ''^src/libstore/gc-store\.hh$'' + ''^src/libstore/globals\.cc$'' + ''^src/libstore/globals\.hh$'' + ''^src/libstore/http-binary-cache-store\.cc$'' + ''^src/libstore/legacy-ssh-store\.cc$'' + ''^src/libstore/legacy-ssh-store\.hh$'' + ''^src/libstore/length-prefixed-protocol-helper\.hh$'' + ''^src/libstore/linux/personality\.cc$'' + ''^src/libstore/linux/personality\.hh$'' + ''^src/libstore/local-binary-cache-store\.cc$'' + ''^src/libstore/local-fs-store\.cc$'' + ''^src/libstore/local-fs-store\.hh$'' + ''^src/libstore/log-store\.cc$'' + ''^src/libstore/log-store\.hh$'' + ''^src/libstore/machines\.cc$'' + ''^src/libstore/machines\.hh$'' + ''^src/libstore/make-content-addressed\.cc$'' + ''^src/libstore/make-content-addressed\.hh$'' + ''^src/libstore/misc\.cc$'' + ''^src/libstore/names\.cc$'' + ''^src/libstore/names\.hh$'' + ''^src/libstore/nar-accessor\.cc$'' + ''^src/libstore/nar-accessor\.hh$'' + ''^src/libstore/nar-info-disk-cache\.cc$'' + ''^src/libstore/nar-info-disk-cache\.hh$'' + ''^src/libstore/nar-info\.cc$'' + ''^src/libstore/nar-info\.hh$'' + ''^src/libstore/outputs-spec\.cc$'' + ''^src/libstore/outputs-spec\.hh$'' + ''^src/libstore/parsed-derivations\.cc$'' + ''^src/libstore/path-info\.cc$'' + ''^src/libstore/path-info\.hh$'' + ''^src/libstore/path-references\.cc$'' + ''^src/libstore/path-regex\.hh$'' + ''^src/libstore/path-with-outputs\.cc$'' + ''^src/libstore/path\.cc$'' + ''^src/libstore/path\.hh$'' + ''^src/libstore/pathlocks\.cc$'' + ''^src/libstore/pathlocks\.hh$'' + ''^src/libstore/profiles\.cc$'' + ''^src/libstore/profiles\.hh$'' + ''^src/libstore/realisation\.cc$'' + ''^src/libstore/realisation\.hh$'' + ''^src/libstore/remote-fs-accessor\.cc$'' + ''^src/libstore/remote-fs-accessor\.hh$'' + ''^src/libstore/remote-store-connection\.hh$'' + ''^src/libstore/remote-store\.cc$'' + ''^src/libstore/remote-store\.hh$'' + ''^src/libstore/s3-binary-cache-store\.cc$'' + ''^src/libstore/s3\.hh$'' + ''^src/libstore/serve-protocol-impl\.cc$'' + ''^src/libstore/serve-protocol-impl\.hh$'' + ''^src/libstore/serve-protocol\.cc$'' + ''^src/libstore/serve-protocol\.hh$'' + ''^src/libstore/sqlite\.cc$'' + ''^src/libstore/sqlite\.hh$'' + ''^src/libstore/ssh-store\.cc$'' + ''^src/libstore/ssh\.cc$'' + ''^src/libstore/ssh\.hh$'' + ''^src/libstore/store-api\.cc$'' + ''^src/libstore/store-api\.hh$'' + ''^src/libstore/store-dir-config\.hh$'' + ''^src/libstore/build/derivation-goal\.cc$'' + ''^src/libstore/build/derivation-goal\.hh$'' + ''^src/libstore/build/drv-output-substitution-goal\.cc$'' + ''^src/libstore/build/drv-output-substitution-goal\.hh$'' + ''^src/libstore/build/entry-points\.cc$'' + ''^src/libstore/build/goal\.cc$'' + ''^src/libstore/build/goal\.hh$'' + ''^src/libstore/unix/build/hook-instance\.cc$'' + ''^src/libstore/unix/build/local-derivation-goal\.cc$'' + ''^src/libstore/unix/build/local-derivation-goal\.hh$'' + ''^src/libstore/build/substitution-goal\.cc$'' + ''^src/libstore/build/substitution-goal\.hh$'' + ''^src/libstore/build/worker\.cc$'' + ''^src/libstore/build/worker\.hh$'' + ''^src/libstore/builtins/fetchurl\.cc$'' + ''^src/libstore/builtins/unpack-channel\.cc$'' + ''^src/libstore/gc\.cc$'' + ''^src/libstore/local-overlay-store\.cc$'' + ''^src/libstore/local-overlay-store\.hh$'' + ''^src/libstore/local-store\.cc$'' + ''^src/libstore/local-store\.hh$'' + ''^src/libstore/unix/user-lock\.cc$'' + ''^src/libstore/unix/user-lock\.hh$'' + ''^src/libstore/optimise-store\.cc$'' + ''^src/libstore/unix/pathlocks\.cc$'' + ''^src/libstore/posix-fs-canonicalise\.cc$'' + ''^src/libstore/posix-fs-canonicalise\.hh$'' + ''^src/libstore/uds-remote-store\.cc$'' + ''^src/libstore/uds-remote-store\.hh$'' + ''^src/libstore/windows/build\.cc$'' + ''^src/libstore/worker-protocol-impl\.hh$'' + ''^src/libstore/worker-protocol\.cc$'' + ''^src/libstore/worker-protocol\.hh$'' + ''^src/libutil-c/nix_api_util_internal\.h$'' + ''^src/libutil/archive\.cc$'' + ''^src/libutil/archive\.hh$'' + ''^src/libutil/args\.cc$'' + ''^src/libutil/args\.hh$'' + ''^src/libutil/args/root\.hh$'' + ''^src/libutil/callback\.hh$'' + ''^src/libutil/canon-path\.cc$'' + ''^src/libutil/canon-path\.hh$'' + ''^src/libutil/chunked-vector\.hh$'' + ''^src/libutil/closure\.hh$'' + ''^src/libutil/comparator\.hh$'' + ''^src/libutil/compute-levels\.cc$'' + ''^src/libutil/config-impl\.hh$'' + ''^src/libutil/config\.cc$'' + ''^src/libutil/config\.hh$'' + ''^src/libutil/current-process\.cc$'' + ''^src/libutil/current-process\.hh$'' + ''^src/libutil/english\.cc$'' + ''^src/libutil/english\.hh$'' + ''^src/libutil/error\.cc$'' + ''^src/libutil/error\.hh$'' + ''^src/libutil/exit\.hh$'' + ''^src/libutil/experimental-features\.cc$'' + ''^src/libutil/experimental-features\.hh$'' + ''^src/libutil/file-content-address\.cc$'' + ''^src/libutil/file-content-address\.hh$'' + ''^src/libutil/file-descriptor\.cc$'' + ''^src/libutil/file-descriptor\.hh$'' + ''^src/libutil/file-path-impl\.hh$'' + ''^src/libutil/file-path\.hh$'' + ''^src/libutil/file-system\.cc$'' + ''^src/libutil/file-system\.hh$'' + ''^src/libutil/finally\.hh$'' + ''^src/libutil/fmt\.hh$'' + ''^src/libutil/fs-sink\.cc$'' + ''^src/libutil/fs-sink\.hh$'' + ''^src/libutil/git\.cc$'' + ''^src/libutil/git\.hh$'' + ''^src/libutil/hash\.cc$'' + ''^src/libutil/hash\.hh$'' + ''^src/libutil/hilite\.cc$'' + ''^src/libutil/hilite\.hh$'' + ''^src/libutil/source-accessor\.hh$'' + ''^src/libutil/json-impls\.hh$'' + ''^src/libutil/json-utils\.cc$'' + ''^src/libutil/json-utils\.hh$'' + ''^src/libutil/linux/cgroup\.cc$'' + ''^src/libutil/linux/namespaces\.cc$'' + ''^src/libutil/logging\.cc$'' + ''^src/libutil/logging\.hh$'' + ''^src/libutil/lru-cache\.hh$'' + ''^src/libutil/memory-source-accessor\.cc$'' + ''^src/libutil/memory-source-accessor\.hh$'' + ''^src/libutil/pool\.hh$'' + ''^src/libutil/position\.cc$'' + ''^src/libutil/position\.hh$'' + ''^src/libutil/posix-source-accessor\.cc$'' + ''^src/libutil/posix-source-accessor\.hh$'' + ''^src/libutil/processes\.hh$'' + ''^src/libutil/ref\.hh$'' + ''^src/libutil/references\.cc$'' + ''^src/libutil/references\.hh$'' + ''^src/libutil/regex-combinators\.hh$'' + ''^src/libutil/serialise\.cc$'' + ''^src/libutil/serialise\.hh$'' + ''^src/libutil/signals\.hh$'' + ''^src/libutil/signature/local-keys\.cc$'' + ''^src/libutil/signature/local-keys\.hh$'' + ''^src/libutil/signature/signer\.cc$'' + ''^src/libutil/signature/signer\.hh$'' + ''^src/libutil/source-accessor\.cc$'' + ''^src/libutil/source-accessor\.hh$'' + ''^src/libutil/source-path\.cc$'' + ''^src/libutil/source-path\.hh$'' + ''^src/libutil/split\.hh$'' + ''^src/libutil/suggestions\.cc$'' + ''^src/libutil/suggestions\.hh$'' + ''^src/libutil/sync\.hh$'' + ''^src/libutil/terminal\.cc$'' + ''^src/libutil/terminal\.hh$'' + ''^src/libutil/thread-pool\.cc$'' + ''^src/libutil/thread-pool\.hh$'' + ''^src/libutil/topo-sort\.hh$'' + ''^src/libutil/types\.hh$'' + ''^src/libutil/unix/file-descriptor\.cc$'' + ''^src/libutil/unix/file-path\.cc$'' + ''^src/libutil/unix/monitor-fd\.hh$'' + ''^src/libutil/unix/processes\.cc$'' + ''^src/libutil/unix/signals-impl\.hh$'' + ''^src/libutil/unix/signals\.cc$'' + ''^src/libutil/unix-domain-socket\.cc$'' + ''^src/libutil/unix/users\.cc$'' + ''^src/libutil/url-parts\.hh$'' + ''^src/libutil/url\.cc$'' + ''^src/libutil/url\.hh$'' + ''^src/libutil/users\.cc$'' + ''^src/libutil/users\.hh$'' + ''^src/libutil/util\.cc$'' + ''^src/libutil/util\.hh$'' + ''^src/libutil/variant-wrapper\.hh$'' + ''^src/libutil/widecharwidth/widechar_width\.h$'' # vendored source + ''^src/libutil/windows/file-descriptor\.cc$'' + ''^src/libutil/windows/file-path\.cc$'' + ''^src/libutil/windows/processes\.cc$'' + ''^src/libutil/windows/users\.cc$'' + ''^src/libutil/windows/windows-error\.cc$'' + ''^src/libutil/windows/windows-error\.hh$'' + ''^src/libutil/xml-writer\.cc$'' + ''^src/libutil/xml-writer\.hh$'' + ''^src/nix-build/nix-build\.cc$'' + ''^src/nix-channel/nix-channel\.cc$'' + ''^src/nix-collect-garbage/nix-collect-garbage\.cc$'' + ''^src/nix-env/buildenv.nix$'' + ''^src/nix-env/nix-env\.cc$'' + ''^src/nix-env/user-env\.cc$'' + ''^src/nix-env/user-env\.hh$'' + ''^src/nix-instantiate/nix-instantiate\.cc$'' + ''^src/nix-store/dotgraph\.cc$'' + ''^src/nix-store/graphml\.cc$'' + ''^src/nix-store/nix-store\.cc$'' + ''^src/nix/add-to-store\.cc$'' + ''^src/nix/app\.cc$'' + ''^src/nix/build\.cc$'' + ''^src/nix/bundle\.cc$'' + ''^src/nix/cat\.cc$'' + ''^src/nix/config-check\.cc$'' + ''^src/nix/config\.cc$'' + ''^src/nix/copy\.cc$'' + ''^src/nix/derivation-add\.cc$'' + ''^src/nix/derivation-show\.cc$'' + ''^src/nix/derivation\.cc$'' + ''^src/nix/develop\.cc$'' + ''^src/nix/diff-closures\.cc$'' + ''^src/nix/dump-path\.cc$'' + ''^src/nix/edit\.cc$'' + ''^src/nix/eval\.cc$'' + ''^src/nix/flake\.cc$'' + ''^src/nix/fmt\.cc$'' + ''^src/nix/hash\.cc$'' + ''^src/nix/log\.cc$'' + ''^src/nix/ls\.cc$'' + ''^src/nix/main\.cc$'' + ''^src/nix/make-content-addressed\.cc$'' + ''^src/nix/nar\.cc$'' + ''^src/nix/optimise-store\.cc$'' + ''^src/nix/path-from-hash-part\.cc$'' + ''^src/nix/path-info\.cc$'' + ''^src/nix/prefetch\.cc$'' + ''^src/nix/profile\.cc$'' + ''^src/nix/realisation\.cc$'' + ''^src/nix/registry\.cc$'' + ''^src/nix/repl\.cc$'' + ''^src/nix/run\.cc$'' + ''^src/nix/run\.hh$'' + ''^src/nix/search\.cc$'' + ''^src/nix/sigs\.cc$'' + ''^src/nix/store-copy-log\.cc$'' + ''^src/nix/store-delete\.cc$'' + ''^src/nix/store-gc\.cc$'' + ''^src/nix/store-info\.cc$'' + ''^src/nix/store-repair\.cc$'' + ''^src/nix/store\.cc$'' + ''^src/nix/unix/daemon\.cc$'' + ''^src/nix/upgrade-nix\.cc$'' + ''^src/nix/verify\.cc$'' + ''^src/nix/why-depends\.cc$'' - ''^tests/functional/plugins/plugintest\.cc'' - ''^tests/functional/test-libstoreconsumer/main\.cc'' - ''^tests/nixos/ca-fd-leak/sender\.c'' - ''^tests/nixos/ca-fd-leak/smuggler\.c'' - ''^tests/nixos/user-sandboxing/attacker\.c'' - ''^src/libexpr-test-support/tests/libexpr\.hh'' - ''^src/libexpr-test-support/tests/value/context\.cc'' - ''^src/libexpr-test-support/tests/value/context\.hh'' - ''^src/libexpr-tests/derived-path\.cc'' - ''^src/libexpr-tests/error_traces\.cc'' - ''^src/libexpr-tests/eval\.cc'' - ''^src/libexpr-tests/json\.cc'' - ''^src/libexpr-tests/main\.cc'' - ''^src/libexpr-tests/primops\.cc'' - ''^src/libexpr-tests/search-path\.cc'' - ''^src/libexpr-tests/trivial\.cc'' - ''^src/libexpr-tests/value/context\.cc'' - ''^src/libexpr-tests/value/print\.cc'' - ''^src/libfetchers-tests/public-key\.cc'' - ''^src/libflake-tests/flakeref\.cc'' - ''^src/libflake-tests/url-name\.cc'' - ''^src/libstore-test-support/tests/derived-path\.cc'' - ''^src/libstore-test-support/tests/derived-path\.hh'' - ''^src/libstore-test-support/tests/nix_api_store\.hh'' - ''^src/libstore-test-support/tests/outputs-spec\.cc'' - ''^src/libstore-test-support/tests/outputs-spec\.hh'' - ''^src/libstore-test-support/tests/path\.cc'' - ''^src/libstore-test-support/tests/path\.hh'' - ''^src/libstore-test-support/tests/protocol\.hh'' - ''^src/libstore-tests/common-protocol\.cc'' - ''^src/libstore-tests/content-address\.cc'' - ''^src/libstore-tests/derivation\.cc'' - ''^src/libstore-tests/derived-path\.cc'' - ''^src/libstore-tests/downstream-placeholder\.cc'' - ''^src/libstore-tests/machines\.cc'' - ''^src/libstore-tests/nar-info-disk-cache\.cc'' - ''^src/libstore-tests/nar-info\.cc'' - ''^src/libstore-tests/outputs-spec\.cc'' - ''^src/libstore-tests/path-info\.cc'' - ''^src/libstore-tests/path\.cc'' - ''^src/libstore-tests/serve-protocol\.cc'' - ''^src/libstore-tests/worker-protocol\.cc'' - ''^src/libutil-test-support/tests/characterization\.hh'' - ''^src/libutil-test-support/tests/hash\.cc'' - ''^src/libutil-test-support/tests/hash\.hh'' - ''^src/libutil-tests/args\.cc'' - ''^src/libutil-tests/canon-path\.cc'' - ''^src/libutil-tests/chunked-vector\.cc'' - ''^src/libutil-tests/closure\.cc'' - ''^src/libutil-tests/compression\.cc'' - ''^src/libutil-tests/config\.cc'' - ''^src/libutil-tests/file-content-address\.cc'' - ''^src/libutil-tests/git\.cc'' - ''^src/libutil-tests/hash\.cc'' - ''^src/libutil-tests/hilite\.cc'' - ''^src/libutil-tests/json-utils\.cc'' - ''^src/libutil-tests/logging\.cc'' - ''^src/libutil-tests/lru-cache\.cc'' - ''^src/libutil-tests/pool\.cc'' - ''^src/libutil-tests/references\.cc'' - ''^src/libutil-tests/suggestions\.cc'' - ''^src/libutil-tests/url\.cc'' - ''^src/libutil-tests/xml-writer\.cc'' - ]; + ''^tests/functional/plugins/plugintest\.cc'' + ''^tests/functional/test-libstoreconsumer/main\.cc'' + ''^tests/nixos/ca-fd-leak/sender\.c'' + ''^tests/nixos/ca-fd-leak/smuggler\.c'' + ''^tests/nixos/user-sandboxing/attacker\.c'' + ''^src/libexpr-test-support/tests/libexpr\.hh'' + ''^src/libexpr-test-support/tests/value/context\.cc'' + ''^src/libexpr-test-support/tests/value/context\.hh'' + ''^src/libexpr-tests/derived-path\.cc'' + ''^src/libexpr-tests/error_traces\.cc'' + ''^src/libexpr-tests/eval\.cc'' + ''^src/libexpr-tests/json\.cc'' + ''^src/libexpr-tests/main\.cc'' + ''^src/libexpr-tests/primops\.cc'' + ''^src/libexpr-tests/search-path\.cc'' + ''^src/libexpr-tests/trivial\.cc'' + ''^src/libexpr-tests/value/context\.cc'' + ''^src/libexpr-tests/value/print\.cc'' + ''^src/libfetchers-tests/public-key\.cc'' + ''^src/libflake-tests/flakeref\.cc'' + ''^src/libflake-tests/url-name\.cc'' + ''^src/libstore-test-support/tests/derived-path\.cc'' + ''^src/libstore-test-support/tests/derived-path\.hh'' + ''^src/libstore-test-support/tests/nix_api_store\.hh'' + ''^src/libstore-test-support/tests/outputs-spec\.cc'' + ''^src/libstore-test-support/tests/outputs-spec\.hh'' + ''^src/libstore-test-support/tests/path\.cc'' + ''^src/libstore-test-support/tests/path\.hh'' + ''^src/libstore-test-support/tests/protocol\.hh'' + ''^src/libstore-tests/common-protocol\.cc'' + ''^src/libstore-tests/content-address\.cc'' + ''^src/libstore-tests/derivation\.cc'' + ''^src/libstore-tests/derived-path\.cc'' + ''^src/libstore-tests/downstream-placeholder\.cc'' + ''^src/libstore-tests/machines\.cc'' + ''^src/libstore-tests/nar-info-disk-cache\.cc'' + ''^src/libstore-tests/nar-info\.cc'' + ''^src/libstore-tests/outputs-spec\.cc'' + ''^src/libstore-tests/path-info\.cc'' + ''^src/libstore-tests/path\.cc'' + ''^src/libstore-tests/serve-protocol\.cc'' + ''^src/libstore-tests/worker-protocol\.cc'' + ''^src/libutil-test-support/tests/characterization\.hh'' + ''^src/libutil-test-support/tests/hash\.cc'' + ''^src/libutil-test-support/tests/hash\.hh'' + ''^src/libutil-tests/args\.cc'' + ''^src/libutil-tests/canon-path\.cc'' + ''^src/libutil-tests/chunked-vector\.cc'' + ''^src/libutil-tests/closure\.cc'' + ''^src/libutil-tests/compression\.cc'' + ''^src/libutil-tests/config\.cc'' + ''^src/libutil-tests/file-content-address\.cc'' + ''^src/libutil-tests/git\.cc'' + ''^src/libutil-tests/hash\.cc'' + ''^src/libutil-tests/hilite\.cc'' + ''^src/libutil-tests/json-utils\.cc'' + ''^src/libutil-tests/logging\.cc'' + ''^src/libutil-tests/lru-cache\.cc'' + ''^src/libutil-tests/pool\.cc'' + ''^src/libutil-tests/references\.cc'' + ''^src/libutil-tests/suggestions\.cc'' + ''^src/libutil-tests/url\.cc'' + ''^src/libutil-tests/xml-writer\.cc'' + ]; + }; + shellcheck = { + enable = true; + excludes = [ + # We haven't linted these files yet + ''^config/install-sh$'' + ''^misc/bash/completion\.sh$'' + ''^misc/fish/completion\.fish$'' + ''^misc/zsh/completion\.zsh$'' + ''^scripts/create-darwin-volume\.sh$'' + ''^scripts/install-darwin-multi-user\.sh$'' + ''^scripts/install-multi-user\.sh$'' + ''^scripts/install-systemd-multi-user\.sh$'' + ''^src/nix/get-env\.sh$'' + ''^tests/functional/ca/build-dry\.sh$'' + ''^tests/functional/ca/build-with-garbage-path\.sh$'' + ''^tests/functional/ca/common\.sh$'' + ''^tests/functional/ca/concurrent-builds\.sh$'' + ''^tests/functional/ca/eval-store\.sh$'' + ''^tests/functional/ca/gc\.sh$'' + ''^tests/functional/ca/import-from-derivation\.sh$'' + ''^tests/functional/ca/new-build-cmd\.sh$'' + ''^tests/functional/ca/nix-shell\.sh$'' + ''^tests/functional/ca/post-hook\.sh$'' + ''^tests/functional/ca/recursive\.sh$'' + ''^tests/functional/ca/repl\.sh$'' + ''^tests/functional/ca/selfref-gc\.sh$'' + ''^tests/functional/ca/why-depends\.sh$'' + ''^tests/functional/characterisation-test-infra\.sh$'' + ''^tests/functional/common/vars-and-functions\.sh$'' + ''^tests/functional/completions\.sh$'' + ''^tests/functional/compute-levels\.sh$'' + ''^tests/functional/config\.sh$'' + ''^tests/functional/db-migration\.sh$'' + ''^tests/functional/debugger\.sh$'' + ''^tests/functional/dependencies\.builder0\.sh$'' + ''^tests/functional/dependencies\.sh$'' + ''^tests/functional/dump-db\.sh$'' + ''^tests/functional/dyn-drv/build-built-drv\.sh$'' + ''^tests/functional/dyn-drv/common\.sh$'' + ''^tests/functional/dyn-drv/dep-built-drv\.sh$'' + ''^tests/functional/dyn-drv/eval-outputOf\.sh$'' + ''^tests/functional/dyn-drv/old-daemon-error-hack\.sh$'' + ''^tests/functional/dyn-drv/recursive-mod-json\.sh$'' + ''^tests/functional/eval-store\.sh$'' + ''^tests/functional/export-graph\.sh$'' + ''^tests/functional/export\.sh$'' + ''^tests/functional/extra-sandbox-profile\.sh$'' + ''^tests/functional/fetchClosure\.sh$'' + ''^tests/functional/fetchGit\.sh$'' + ''^tests/functional/fetchGitRefs\.sh$'' + ''^tests/functional/fetchGitSubmodules\.sh$'' + ''^tests/functional/fetchGitVerification\.sh$'' + ''^tests/functional/fetchMercurial\.sh$'' + ''^tests/functional/fixed\.builder1\.sh$'' + ''^tests/functional/fixed\.builder2\.sh$'' + ''^tests/functional/fixed\.sh$'' + ''^tests/functional/flakes/absolute-paths\.sh$'' + ''^tests/functional/flakes/check\.sh$'' + ''^tests/functional/flakes/config\.sh$'' + ''^tests/functional/flakes/flakes\.sh$'' + ''^tests/functional/flakes/follow-paths\.sh$'' + ''^tests/functional/flakes/prefetch\.sh$'' + ''^tests/functional/flakes/run\.sh$'' + ''^tests/functional/flakes/show\.sh$'' + ''^tests/functional/fmt\.sh$'' + ''^tests/functional/fmt\.simple\.sh$'' + ''^tests/functional/gc-auto\.sh$'' + ''^tests/functional/gc-concurrent\.builder\.sh$'' + ''^tests/functional/gc-concurrent\.sh$'' + ''^tests/functional/gc-concurrent2\.builder\.sh$'' + ''^tests/functional/gc-non-blocking\.sh$'' + ''^tests/functional/git-hashing/common\.sh$'' + ''^tests/functional/git-hashing/simple\.sh$'' + ''^tests/functional/hash-convert\.sh$'' + ''^tests/functional/impure-derivations\.sh$'' + ''^tests/functional/impure-eval\.sh$'' + ''^tests/functional/install-darwin\.sh$'' + ''^tests/functional/legacy-ssh-store\.sh$'' + ''^tests/functional/linux-sandbox\.sh$'' + ''^tests/functional/local-overlay-store/add-lower-inner\.sh$'' + ''^tests/functional/local-overlay-store/add-lower\.sh$'' + ''^tests/functional/local-overlay-store/bad-uris\.sh$'' + ''^tests/functional/local-overlay-store/build-inner\.sh$'' + ''^tests/functional/local-overlay-store/build\.sh$'' + ''^tests/functional/local-overlay-store/check-post-init-inner\.sh$'' + ''^tests/functional/local-overlay-store/check-post-init\.sh$'' + ''^tests/functional/local-overlay-store/common\.sh$'' + ''^tests/functional/local-overlay-store/delete-duplicate-inner\.sh$'' + ''^tests/functional/local-overlay-store/delete-duplicate\.sh$'' + ''^tests/functional/local-overlay-store/delete-refs-inner\.sh$'' + ''^tests/functional/local-overlay-store/delete-refs\.sh$'' + ''^tests/functional/local-overlay-store/gc-inner\.sh$'' + ''^tests/functional/local-overlay-store/gc\.sh$'' + ''^tests/functional/local-overlay-store/optimise-inner\.sh$'' + ''^tests/functional/local-overlay-store/optimise\.sh$'' + ''^tests/functional/local-overlay-store/redundant-add-inner\.sh$'' + ''^tests/functional/local-overlay-store/redundant-add\.sh$'' + ''^tests/functional/local-overlay-store/remount\.sh$'' + ''^tests/functional/local-overlay-store/stale-file-handle-inner\.sh$'' + ''^tests/functional/local-overlay-store/stale-file-handle\.sh$'' + ''^tests/functional/local-overlay-store/verify-inner\.sh$'' + ''^tests/functional/local-overlay-store/verify\.sh$'' + ''^tests/functional/logging\.sh$'' + ''^tests/functional/misc\.sh$'' + ''^tests/functional/multiple-outputs\.sh$'' + ''^tests/functional/nested-sandboxing\.sh$'' + ''^tests/functional/nested-sandboxing/command\.sh$'' + ''^tests/functional/nix-build\.sh$'' + ''^tests/functional/nix-channel\.sh$'' + ''^tests/functional/nix-collect-garbage-d\.sh$'' + ''^tests/functional/nix-copy-ssh-common\.sh$'' + ''^tests/functional/nix-copy-ssh-ng\.sh$'' + ''^tests/functional/nix-copy-ssh\.sh$'' + ''^tests/functional/nix-daemon-untrusting\.sh$'' + ''^tests/functional/nix-profile\.sh$'' + ''^tests/functional/nix-shell\.sh$'' + ''^tests/functional/nix_path\.sh$'' + ''^tests/functional/optimise-store\.sh$'' + ''^tests/functional/output-normalization\.sh$'' + ''^tests/functional/parallel\.builder\.sh$'' + ''^tests/functional/parallel\.sh$'' + ''^tests/functional/pass-as-file\.sh$'' + ''^tests/functional/path-from-hash-part\.sh$'' + ''^tests/functional/path-info\.sh$'' + ''^tests/functional/placeholders\.sh$'' + ''^tests/functional/post-hook\.sh$'' + ''^tests/functional/pure-eval\.sh$'' + ''^tests/functional/push-to-store-old\.sh$'' + ''^tests/functional/push-to-store\.sh$'' + ''^tests/functional/read-only-store\.sh$'' + ''^tests/functional/readfile-context\.sh$'' + ''^tests/functional/recursive\.sh$'' + ''^tests/functional/referrers\.sh$'' + ''^tests/functional/remote-store\.sh$'' + ''^tests/functional/repair\.sh$'' + ''^tests/functional/restricted\.sh$'' + ''^tests/functional/search\.sh$'' + ''^tests/functional/secure-drv-outputs\.sh$'' + ''^tests/functional/selfref-gc\.sh$'' + ''^tests/functional/shell\.shebang\.sh$'' + ''^tests/functional/simple\.builder\.sh$'' + ''^tests/functional/supplementary-groups\.sh$'' + ''^tests/functional/toString-path\.sh$'' + ''^tests/functional/user-envs-migration\.sh$'' + ''^tests/functional/user-envs-test-case\.sh$'' + ''^tests/functional/user-envs\.builder\.sh$'' + ''^tests/functional/user-envs\.sh$'' + ''^tests/functional/why-depends\.sh$'' + ''^src/libutil-tests/data/git/check-data\.sh$'' + ]; + }; + # TODO: nixfmt, https://github.com/NixOS/nixfmt/issues/153 }; - shellcheck = { - enable = true; - excludes = [ - # We haven't linted these files yet - ''^config/install-sh$'' - ''^misc/bash/completion\.sh$'' - ''^misc/fish/completion\.fish$'' - ''^misc/zsh/completion\.zsh$'' - ''^scripts/create-darwin-volume\.sh$'' - ''^scripts/install-darwin-multi-user\.sh$'' - ''^scripts/install-multi-user\.sh$'' - ''^scripts/install-systemd-multi-user\.sh$'' - ''^src/nix/get-env\.sh$'' - ''^tests/functional/ca/build-dry\.sh$'' - ''^tests/functional/ca/build-with-garbage-path\.sh$'' - ''^tests/functional/ca/common\.sh$'' - ''^tests/functional/ca/concurrent-builds\.sh$'' - ''^tests/functional/ca/eval-store\.sh$'' - ''^tests/functional/ca/gc\.sh$'' - ''^tests/functional/ca/import-from-derivation\.sh$'' - ''^tests/functional/ca/new-build-cmd\.sh$'' - ''^tests/functional/ca/nix-shell\.sh$'' - ''^tests/functional/ca/post-hook\.sh$'' - ''^tests/functional/ca/recursive\.sh$'' - ''^tests/functional/ca/repl\.sh$'' - ''^tests/functional/ca/selfref-gc\.sh$'' - ''^tests/functional/ca/why-depends\.sh$'' - ''^tests/functional/characterisation-test-infra\.sh$'' - ''^tests/functional/common/vars-and-functions\.sh$'' - ''^tests/functional/completions\.sh$'' - ''^tests/functional/compute-levels\.sh$'' - ''^tests/functional/config\.sh$'' - ''^tests/functional/db-migration\.sh$'' - ''^tests/functional/debugger\.sh$'' - ''^tests/functional/dependencies\.builder0\.sh$'' - ''^tests/functional/dependencies\.sh$'' - ''^tests/functional/dump-db\.sh$'' - ''^tests/functional/dyn-drv/build-built-drv\.sh$'' - ''^tests/functional/dyn-drv/common\.sh$'' - ''^tests/functional/dyn-drv/dep-built-drv\.sh$'' - ''^tests/functional/dyn-drv/eval-outputOf\.sh$'' - ''^tests/functional/dyn-drv/old-daemon-error-hack\.sh$'' - ''^tests/functional/dyn-drv/recursive-mod-json\.sh$'' - ''^tests/functional/eval-store\.sh$'' - ''^tests/functional/export-graph\.sh$'' - ''^tests/functional/export\.sh$'' - ''^tests/functional/extra-sandbox-profile\.sh$'' - ''^tests/functional/fetchClosure\.sh$'' - ''^tests/functional/fetchGit\.sh$'' - ''^tests/functional/fetchGitRefs\.sh$'' - ''^tests/functional/fetchGitSubmodules\.sh$'' - ''^tests/functional/fetchGitVerification\.sh$'' - ''^tests/functional/fetchMercurial\.sh$'' - ''^tests/functional/fixed\.builder1\.sh$'' - ''^tests/functional/fixed\.builder2\.sh$'' - ''^tests/functional/fixed\.sh$'' - ''^tests/functional/flakes/absolute-paths\.sh$'' - ''^tests/functional/flakes/check\.sh$'' - ''^tests/functional/flakes/config\.sh$'' - ''^tests/functional/flakes/flakes\.sh$'' - ''^tests/functional/flakes/follow-paths\.sh$'' - ''^tests/functional/flakes/prefetch\.sh$'' - ''^tests/functional/flakes/run\.sh$'' - ''^tests/functional/flakes/show\.sh$'' - ''^tests/functional/fmt\.sh$'' - ''^tests/functional/fmt\.simple\.sh$'' - ''^tests/functional/gc-auto\.sh$'' - ''^tests/functional/gc-concurrent\.builder\.sh$'' - ''^tests/functional/gc-concurrent\.sh$'' - ''^tests/functional/gc-concurrent2\.builder\.sh$'' - ''^tests/functional/gc-non-blocking\.sh$'' - ''^tests/functional/git-hashing/common\.sh$'' - ''^tests/functional/git-hashing/simple\.sh$'' - ''^tests/functional/hash-convert\.sh$'' - ''^tests/functional/impure-derivations\.sh$'' - ''^tests/functional/impure-eval\.sh$'' - ''^tests/functional/install-darwin\.sh$'' - ''^tests/functional/legacy-ssh-store\.sh$'' - ''^tests/functional/linux-sandbox\.sh$'' - ''^tests/functional/local-overlay-store/add-lower-inner\.sh$'' - ''^tests/functional/local-overlay-store/add-lower\.sh$'' - ''^tests/functional/local-overlay-store/bad-uris\.sh$'' - ''^tests/functional/local-overlay-store/build-inner\.sh$'' - ''^tests/functional/local-overlay-store/build\.sh$'' - ''^tests/functional/local-overlay-store/check-post-init-inner\.sh$'' - ''^tests/functional/local-overlay-store/check-post-init\.sh$'' - ''^tests/functional/local-overlay-store/common\.sh$'' - ''^tests/functional/local-overlay-store/delete-duplicate-inner\.sh$'' - ''^tests/functional/local-overlay-store/delete-duplicate\.sh$'' - ''^tests/functional/local-overlay-store/delete-refs-inner\.sh$'' - ''^tests/functional/local-overlay-store/delete-refs\.sh$'' - ''^tests/functional/local-overlay-store/gc-inner\.sh$'' - ''^tests/functional/local-overlay-store/gc\.sh$'' - ''^tests/functional/local-overlay-store/optimise-inner\.sh$'' - ''^tests/functional/local-overlay-store/optimise\.sh$'' - ''^tests/functional/local-overlay-store/redundant-add-inner\.sh$'' - ''^tests/functional/local-overlay-store/redundant-add\.sh$'' - ''^tests/functional/local-overlay-store/remount\.sh$'' - ''^tests/functional/local-overlay-store/stale-file-handle-inner\.sh$'' - ''^tests/functional/local-overlay-store/stale-file-handle\.sh$'' - ''^tests/functional/local-overlay-store/verify-inner\.sh$'' - ''^tests/functional/local-overlay-store/verify\.sh$'' - ''^tests/functional/logging\.sh$'' - ''^tests/functional/misc\.sh$'' - ''^tests/functional/multiple-outputs\.sh$'' - ''^tests/functional/nested-sandboxing\.sh$'' - ''^tests/functional/nested-sandboxing/command\.sh$'' - ''^tests/functional/nix-build\.sh$'' - ''^tests/functional/nix-channel\.sh$'' - ''^tests/functional/nix-collect-garbage-d\.sh$'' - ''^tests/functional/nix-copy-ssh-common\.sh$'' - ''^tests/functional/nix-copy-ssh-ng\.sh$'' - ''^tests/functional/nix-copy-ssh\.sh$'' - ''^tests/functional/nix-daemon-untrusting\.sh$'' - ''^tests/functional/nix-profile\.sh$'' - ''^tests/functional/nix-shell\.sh$'' - ''^tests/functional/nix_path\.sh$'' - ''^tests/functional/optimise-store\.sh$'' - ''^tests/functional/output-normalization\.sh$'' - ''^tests/functional/parallel\.builder\.sh$'' - ''^tests/functional/parallel\.sh$'' - ''^tests/functional/pass-as-file\.sh$'' - ''^tests/functional/path-from-hash-part\.sh$'' - ''^tests/functional/path-info\.sh$'' - ''^tests/functional/placeholders\.sh$'' - ''^tests/functional/post-hook\.sh$'' - ''^tests/functional/pure-eval\.sh$'' - ''^tests/functional/push-to-store-old\.sh$'' - ''^tests/functional/push-to-store\.sh$'' - ''^tests/functional/read-only-store\.sh$'' - ''^tests/functional/readfile-context\.sh$'' - ''^tests/functional/recursive\.sh$'' - ''^tests/functional/referrers\.sh$'' - ''^tests/functional/remote-store\.sh$'' - ''^tests/functional/repair\.sh$'' - ''^tests/functional/restricted\.sh$'' - ''^tests/functional/search\.sh$'' - ''^tests/functional/secure-drv-outputs\.sh$'' - ''^tests/functional/selfref-gc\.sh$'' - ''^tests/functional/shell\.shebang\.sh$'' - ''^tests/functional/simple\.builder\.sh$'' - ''^tests/functional/supplementary-groups\.sh$'' - ''^tests/functional/toString-path\.sh$'' - ''^tests/functional/user-envs-migration\.sh$'' - ''^tests/functional/user-envs-test-case\.sh$'' - ''^tests/functional/user-envs\.builder\.sh$'' - ''^tests/functional/user-envs\.sh$'' - ''^tests/functional/why-depends\.sh$'' - ''^src/libutil-tests/data/git/check-data\.sh$'' - ]; - }; - # TODO: nixfmt, https://github.com/NixOS/nixfmt/issues/153 }; }; - }; # We'll be pulling from this in the main flake flake.getSystem = getSystem; diff --git a/packaging/components.nix b/packaging/components.nix index e1f661be8..d1bfe83bf 100644 --- a/packaging/components.nix +++ b/packaging/components.nix @@ -13,9 +13,11 @@ let versionSuffix = lib.optionalString (!officialRelease) "pre"; - fineVersionSuffix = lib.optionalString - (!officialRelease) - "pre${builtins.substring 0 8 (src.lastModifiedDate or src.lastModified or "19700101")}_${src.shortRev or "dirty"}"; + fineVersionSuffix = + lib.optionalString (!officialRelease) + "pre${ + builtins.substring 0 8 (src.lastModifiedDate or src.lastModified or "19700101") + }_${src.shortRev or "dirty"}"; fineVersion = baseVersion + fineVersionSuffix; in @@ -54,7 +56,9 @@ in nix-cli = callPackage ../src/nix/package.nix { version = fineVersion; }; - nix-functional-tests = callPackage ../src/nix-functional-tests/package.nix { version = fineVersion; }; + nix-functional-tests = callPackage ../src/nix-functional-tests/package.nix { + version = fineVersion; + }; nix-manual = callPackage ../doc/manual/package.nix { version = fineVersion; }; nix-internal-api-docs = callPackage ../src/internal-api-docs/package.nix { version = fineVersion; }; diff --git a/packaging/dependencies.nix b/packaging/dependencies.nix index acdbc9cfc..afbc31fc6 100644 --- a/packaging/dependencies.nix +++ b/packaging/dependencies.nix @@ -19,9 +19,7 @@ let root = ../.; - stdenv = if prevStdenv.isDarwin && prevStdenv.isx86_64 - then darwinStdenv - else prevStdenv; + stdenv = if prevStdenv.isDarwin && prevStdenv.isx86_64 then darwinStdenv else prevStdenv; # Fix the following error with the default x86_64-darwin SDK: # @@ -38,11 +36,14 @@ let # Indirection for Nixpkgs to override when package.nix files are vendored filesetToSource = lib.fileset.toSource; - /** Given a set of layers, create a mkDerivation-like function */ - mkPackageBuilder = exts: userFn: - stdenv.mkDerivation (lib.extends (lib.composeManyExtensions exts) userFn); + /** + Given a set of layers, create a mkDerivation-like function + */ + mkPackageBuilder = + exts: userFn: stdenv.mkDerivation (lib.extends (lib.composeManyExtensions exts) userFn); - localSourceLayer = finalAttrs: prevAttrs: + localSourceLayer = + finalAttrs: prevAttrs: let workDirPath = # Ideally we'd pick finalAttrs.workDir, but for now `mkDerivation` has @@ -51,8 +52,13 @@ let prevAttrs.workDir; workDirSubpath = lib.path.removePrefix root workDirPath; - sources = assert prevAttrs.fileset._type == "fileset"; prevAttrs.fileset; - src = lib.fileset.toSource { fileset = sources; inherit root; }; + sources = + assert prevAttrs.fileset._type == "fileset"; + prevAttrs.fileset; + src = lib.fileset.toSource { + fileset = sources; + inherit root; + }; in { @@ -64,117 +70,129 @@ let workDir = null; }; - mesonLayer = finalAttrs: prevAttrs: - { - # NOTE: - # As of https://github.com/NixOS/nixpkgs/blob/8baf8241cea0c7b30e0b8ae73474cb3de83c1a30/pkgs/by-name/me/meson/setup-hook.sh#L26, - # `mesonBuildType` defaults to `plain` if not specified. We want our Nix-built binaries to be optimized by default. - # More on build types here: https://mesonbuild.com/Builtin-options.html#details-for-buildtype. - mesonBuildType = "release"; - # NOTE: - # Users who are debugging Nix builds are expected to set the environment variable `mesonBuildType`, per the - # guidance in https://github.com/NixOS/nix/blob/8a3fc27f1b63a08ac983ee46435a56cf49ebaf4a/doc/manual/source/development/debugging.md?plain=1#L10. - # For this reason, we don't want to refer to `finalAttrs.mesonBuildType` here, but rather use the environment variable. - preConfigure = prevAttrs.preConfigure or "" + lib.optionalString ( - !stdenv.hostPlatform.isWindows - # build failure - && !stdenv.hostPlatform.isStatic - # LTO breaks exception handling on x86-64-darwin. - && stdenv.system != "x86_64-darwin" - ) '' - case "$mesonBuildType" in - release|minsize) appendToVar mesonFlags "-Db_lto=true" ;; - *) appendToVar mesonFlags "-Db_lto=false" ;; - esac - ''; - nativeBuildInputs = [ - pkgs.buildPackages.meson - pkgs.buildPackages.ninja - ] ++ prevAttrs.nativeBuildInputs or []; - mesonCheckFlags = prevAttrs.mesonCheckFlags or [] ++ [ - "--print-errorlogs" - ]; - }; + mesonLayer = finalAttrs: prevAttrs: { + # NOTE: + # As of https://github.com/NixOS/nixpkgs/blob/8baf8241cea0c7b30e0b8ae73474cb3de83c1a30/pkgs/by-name/me/meson/setup-hook.sh#L26, + # `mesonBuildType` defaults to `plain` if not specified. We want our Nix-built binaries to be optimized by default. + # More on build types here: https://mesonbuild.com/Builtin-options.html#details-for-buildtype. + mesonBuildType = "release"; + # NOTE: + # Users who are debugging Nix builds are expected to set the environment variable `mesonBuildType`, per the + # guidance in https://github.com/NixOS/nix/blob/8a3fc27f1b63a08ac983ee46435a56cf49ebaf4a/doc/manual/source/development/debugging.md?plain=1#L10. + # For this reason, we don't want to refer to `finalAttrs.mesonBuildType` here, but rather use the environment variable. + preConfigure = + prevAttrs.preConfigure or "" + + + lib.optionalString + ( + !stdenv.hostPlatform.isWindows + # build failure + && !stdenv.hostPlatform.isStatic + # LTO breaks exception handling on x86-64-darwin. + && stdenv.system != "x86_64-darwin" + ) + '' + case "$mesonBuildType" in + release|minsize) appendToVar mesonFlags "-Db_lto=true" ;; + *) appendToVar mesonFlags "-Db_lto=false" ;; + esac + ''; + nativeBuildInputs = [ + pkgs.buildPackages.meson + pkgs.buildPackages.ninja + ] ++ prevAttrs.nativeBuildInputs or [ ]; + mesonCheckFlags = prevAttrs.mesonCheckFlags or [ ] ++ [ + "--print-errorlogs" + ]; + }; - mesonBuildLayer = finalAttrs: prevAttrs: - { - nativeBuildInputs = prevAttrs.nativeBuildInputs or [] ++ [ - pkgs.buildPackages.pkg-config - ]; - separateDebugInfo = !stdenv.hostPlatform.isStatic; - hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie"; - env = prevAttrs.env or {} - // lib.optionalAttrs - (stdenv.isLinux - && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux") - && !(stdenv.hostPlatform.useLLVM or false)) - { LDFLAGS = "-fuse-ld=gold"; }; - }; + mesonBuildLayer = finalAttrs: prevAttrs: { + nativeBuildInputs = prevAttrs.nativeBuildInputs or [ ] ++ [ + pkgs.buildPackages.pkg-config + ]; + separateDebugInfo = !stdenv.hostPlatform.isStatic; + hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie"; + env = + prevAttrs.env or { } + // lib.optionalAttrs ( + stdenv.isLinux + && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux") + && !(stdenv.hostPlatform.useLLVM or false) + ) { LDFLAGS = "-fuse-ld=gold"; }; + }; - mesonLibraryLayer = finalAttrs: prevAttrs: - { - outputs = prevAttrs.outputs or [ "out" ] ++ [ "dev" ]; - }; + mesonLibraryLayer = finalAttrs: prevAttrs: { + outputs = prevAttrs.outputs or [ "out" ] ++ [ "dev" ]; + }; # Work around weird `--as-needed` linker behavior with BSD, see # https://github.com/mesonbuild/meson/issues/3593 - bsdNoLinkAsNeeded = finalAttrs: prevAttrs: + bsdNoLinkAsNeeded = + finalAttrs: prevAttrs: lib.optionalAttrs stdenv.hostPlatform.isBSD { - mesonFlags = [ (lib.mesonBool "b_asneeded" false) ] ++ prevAttrs.mesonFlags or []; + mesonFlags = [ (lib.mesonBool "b_asneeded" false) ] ++ prevAttrs.mesonFlags or [ ]; }; - miscGoodPractice = finalAttrs: prevAttrs: - { - strictDeps = prevAttrs.strictDeps or true; - enableParallelBuilding = true; - }; + miscGoodPractice = finalAttrs: prevAttrs: { + strictDeps = prevAttrs.strictDeps or true; + enableParallelBuilding = true; + }; in scope: { inherit stdenv; - aws-sdk-cpp = (pkgs.aws-sdk-cpp.override { - apis = [ "s3" "transfer" ]; - customMemoryManagement = false; - }).overrideAttrs { - # only a stripped down version is built, which takes a lot less resources - # to build, so we don't need a "big-parallel" machine. - requiredSystemFeatures = [ ]; - }; + aws-sdk-cpp = + (pkgs.aws-sdk-cpp.override { + apis = [ + "s3" + "transfer" + ]; + customMemoryManagement = false; + }).overrideAttrs + { + # only a stripped down version is built, which takes a lot less resources + # to build, so we don't need a "big-parallel" machine. + requiredSystemFeatures = [ ]; + }; boehmgc = pkgs.boehmgc.override { enableLargeConfig = true; }; # TODO Hack until https://github.com/NixOS/nixpkgs/issues/45462 is fixed. - boost = (pkgs.boost.override { - extraB2Args = [ - "--with-container" - "--with-context" - "--with-coroutine" - ]; - }).overrideAttrs (old: { - # Need to remove `--with-*` to use `--with-libraries=...` - buildPhase = lib.replaceStrings [ "--without-python" ] [ "" ] old.buildPhase; - installPhase = lib.replaceStrings [ "--without-python" ] [ "" ] old.installPhase; - }); + boost = + (pkgs.boost.override { + extraB2Args = [ + "--with-container" + "--with-context" + "--with-coroutine" + ]; + }).overrideAttrs + (old: { + # Need to remove `--with-*` to use `--with-libraries=...` + buildPhase = lib.replaceStrings [ "--without-python" ] [ "" ] old.buildPhase; + installPhase = lib.replaceStrings [ "--without-python" ] [ "" ] old.installPhase; + }); libgit2 = pkgs.libgit2.overrideAttrs (attrs: { - cmakeFlags = attrs.cmakeFlags or [] - ++ [ "-DUSE_SSH=exec" ]; - nativeBuildInputs = attrs.nativeBuildInputs or [] + cmakeFlags = attrs.cmakeFlags or [ ] ++ [ "-DUSE_SSH=exec" ]; + nativeBuildInputs = + attrs.nativeBuildInputs or [ ] # gitMinimal does not build on Windows. See packbuilder patch. ++ lib.optionals (!stdenv.hostPlatform.isWindows) [ # Needed for `git apply`; see `prePatch` pkgs.buildPackages.gitMinimal ]; # Only `git apply` can handle git binary patches - prePatch = attrs.prePatch or "" + prePatch = + attrs.prePatch or "" + lib.optionalString (!stdenv.hostPlatform.isWindows) '' patch() { git apply } ''; - patches = attrs.patches or [] + patches = + attrs.patches or [ ] ++ [ ./patches/libgit2-mempack-thin-packfile.patch ] @@ -188,27 +206,24 @@ scope: { inherit resolvePath filesetToSource; - mkMesonDerivation = - mkPackageBuilder [ - miscGoodPractice - localSourceLayer - mesonLayer - ]; - mkMesonExecutable = - mkPackageBuilder [ - miscGoodPractice - bsdNoLinkAsNeeded - localSourceLayer - mesonLayer - mesonBuildLayer - ]; - mkMesonLibrary = - mkPackageBuilder [ - miscGoodPractice - bsdNoLinkAsNeeded - localSourceLayer - mesonLayer - mesonBuildLayer - mesonLibraryLayer - ]; + mkMesonDerivation = mkPackageBuilder [ + miscGoodPractice + localSourceLayer + mesonLayer + ]; + mkMesonExecutable = mkPackageBuilder [ + miscGoodPractice + bsdNoLinkAsNeeded + localSourceLayer + mesonLayer + mesonBuildLayer + ]; + mkMesonLibrary = mkPackageBuilder [ + miscGoodPractice + bsdNoLinkAsNeeded + localSourceLayer + mesonLayer + mesonBuildLayer + mesonLibraryLayer + ]; } diff --git a/packaging/dev-shell.nix b/packaging/dev-shell.nix index 30ac518d5..1651a86be 100644 --- a/packaging/dev-shell.nix +++ b/packaging/dev-shell.nix @@ -2,127 +2,135 @@ { pkgs }: -pkgs.nixComponents.nix-util.overrideAttrs (attrs: +pkgs.nixComponents.nix-util.overrideAttrs ( + attrs: -let - stdenv = pkgs.nixDependencies.stdenv; - buildCanExecuteHost = stdenv.buildPlatform.canExecute stdenv.hostPlatform; - modular = devFlake.getSystem stdenv.buildPlatform.system; - transformFlag = prefix: flag: - assert builtins.isString flag; - let - rest = builtins.substring 2 (builtins.stringLength flag) flag; - in + let + stdenv = pkgs.nixDependencies.stdenv; + buildCanExecuteHost = stdenv.buildPlatform.canExecute stdenv.hostPlatform; + modular = devFlake.getSystem stdenv.buildPlatform.system; + transformFlag = + prefix: flag: + assert builtins.isString flag; + let + rest = builtins.substring 2 (builtins.stringLength flag) flag; + in "-D${prefix}:${rest}"; - havePerl = stdenv.buildPlatform == stdenv.hostPlatform && stdenv.hostPlatform.isUnix; - ignoreCrossFile = flags: builtins.filter (flag: !(lib.strings.hasInfix "cross-file" flag)) flags; -in { - pname = "shell-for-" + attrs.pname; + havePerl = stdenv.buildPlatform == stdenv.hostPlatform && stdenv.hostPlatform.isUnix; + ignoreCrossFile = flags: builtins.filter (flag: !(lib.strings.hasInfix "cross-file" flag)) flags; + in + { + pname = "shell-for-" + attrs.pname; - # Remove the version suffix to avoid unnecessary attempts to substitute in nix develop - version = lib.fileContents ../.version; - name = attrs.pname; + # Remove the version suffix to avoid unnecessary attempts to substitute in nix develop + version = lib.fileContents ../.version; + name = attrs.pname; - installFlags = "sysconfdir=$(out)/etc"; - shellHook = '' - PATH=$prefix/bin:$PATH - unset PYTHONPATH - export MANPATH=$out/share/man:$MANPATH + installFlags = "sysconfdir=$(out)/etc"; + shellHook = '' + PATH=$prefix/bin:$PATH + unset PYTHONPATH + export MANPATH=$out/share/man:$MANPATH - # Make bash completion work. - XDG_DATA_DIRS+=:$out/share + # Make bash completion work. + XDG_DATA_DIRS+=:$out/share - # Make the default phases do the right thing. - # FIXME: this wouldn't be needed if the ninja package set buildPhase() instead of $buildPhase. - # FIXME: mesonConfigurePhase shouldn't cd to the build directory. It would be better to pass '-C ' to ninja. + # Make the default phases do the right thing. + # FIXME: this wouldn't be needed if the ninja package set buildPhase() instead of $buildPhase. + # FIXME: mesonConfigurePhase shouldn't cd to the build directory. It would be better to pass '-C ' to ninja. - cdToBuildDir() { - if [[ ! -e build.ninja ]]; then - cd build - fi - } + cdToBuildDir() { + if [[ ! -e build.ninja ]]; then + cd build + fi + } - configurePhase() { - mesonConfigurePhase - } + configurePhase() { + mesonConfigurePhase + } - buildPhase() { - cdToBuildDir - ninjaBuildPhase - } + buildPhase() { + cdToBuildDir + ninjaBuildPhase + } - checkPhase() { - cdToBuildDir - mesonCheckPhase - } + checkPhase() { + cdToBuildDir + mesonCheckPhase + } - installPhase() { - cdToBuildDir - ninjaInstallPhase - } - ''; + installPhase() { + cdToBuildDir + ninjaInstallPhase + } + ''; - # We use this shell with the local checkout, not unpackPhase. - src = null; + # We use this shell with the local checkout, not unpackPhase. + src = null; - env = { - # Needed for Meson to find Boost. - # https://github.com/NixOS/nixpkgs/issues/86131. - BOOST_INCLUDEDIR = "${lib.getDev pkgs.nixDependencies.boost}/include"; - BOOST_LIBRARYDIR = "${lib.getLib pkgs.nixDependencies.boost}/lib"; - # For `make format`, to work without installing pre-commit - _NIX_PRE_COMMIT_HOOKS_CONFIG = - "${(pkgs.formats.yaml { }).generate "pre-commit-config.yaml" modular.pre-commit.settings.rawConfig}"; - }; + env = { + # Needed for Meson to find Boost. + # https://github.com/NixOS/nixpkgs/issues/86131. + BOOST_INCLUDEDIR = "${lib.getDev pkgs.nixDependencies.boost}/include"; + BOOST_LIBRARYDIR = "${lib.getLib pkgs.nixDependencies.boost}/lib"; + # For `make format`, to work without installing pre-commit + _NIX_PRE_COMMIT_HOOKS_CONFIG = "${(pkgs.formats.yaml { }).generate "pre-commit-config.yaml" + modular.pre-commit.settings.rawConfig + }"; + }; - mesonFlags = - map (transformFlag "libutil") (ignoreCrossFile pkgs.nixComponents.nix-util.mesonFlags) - ++ map (transformFlag "libstore") (ignoreCrossFile pkgs.nixComponents.nix-store.mesonFlags) - ++ map (transformFlag "libfetchers") (ignoreCrossFile pkgs.nixComponents.nix-fetchers.mesonFlags) - ++ lib.optionals havePerl (map (transformFlag "perl") (ignoreCrossFile pkgs.nixComponents.nix-perl-bindings.mesonFlags)) - ++ map (transformFlag "libexpr") (ignoreCrossFile pkgs.nixComponents.nix-expr.mesonFlags) - ++ map (transformFlag "libcmd") (ignoreCrossFile pkgs.nixComponents.nix-cmd.mesonFlags) - ; + mesonFlags = + map (transformFlag "libutil") (ignoreCrossFile pkgs.nixComponents.nix-util.mesonFlags) + ++ map (transformFlag "libstore") (ignoreCrossFile pkgs.nixComponents.nix-store.mesonFlags) + ++ map (transformFlag "libfetchers") (ignoreCrossFile pkgs.nixComponents.nix-fetchers.mesonFlags) + ++ lib.optionals havePerl ( + map (transformFlag "perl") (ignoreCrossFile pkgs.nixComponents.nix-perl-bindings.mesonFlags) + ) + ++ map (transformFlag "libexpr") (ignoreCrossFile pkgs.nixComponents.nix-expr.mesonFlags) + ++ map (transformFlag "libcmd") (ignoreCrossFile pkgs.nixComponents.nix-cmd.mesonFlags); - nativeBuildInputs = attrs.nativeBuildInputs or [] - ++ pkgs.nixComponents.nix-util.nativeBuildInputs - ++ pkgs.nixComponents.nix-store.nativeBuildInputs - ++ pkgs.nixComponents.nix-fetchers.nativeBuildInputs - ++ pkgs.nixComponents.nix-expr.nativeBuildInputs - ++ lib.optionals havePerl pkgs.nixComponents.nix-perl-bindings.nativeBuildInputs - ++ lib.optionals buildCanExecuteHost pkgs.nixComponents.nix-manual.externalNativeBuildInputs - ++ pkgs.nixComponents.nix-internal-api-docs.nativeBuildInputs - ++ pkgs.nixComponents.nix-external-api-docs.nativeBuildInputs - ++ pkgs.nixComponents.nix-functional-tests.externalNativeBuildInputs - ++ lib.optional - (!buildCanExecuteHost - # Hack around https://github.com/nixos/nixpkgs/commit/bf7ad8cfbfa102a90463433e2c5027573b462479 - && !(stdenv.hostPlatform.isWindows && stdenv.buildPlatform.isDarwin) - && stdenv.hostPlatform.emulatorAvailable pkgs.buildPackages - && lib.meta.availableOn stdenv.buildPlatform (stdenv.hostPlatform.emulator pkgs.buildPackages)) - pkgs.buildPackages.mesonEmulatorHook - ++ [ - pkgs.buildPackages.cmake - pkgs.buildPackages.shellcheck - pkgs.buildPackages.changelog-d - modular.pre-commit.settings.package - (pkgs.writeScriptBin "pre-commit-hooks-install" - modular.pre-commit.settings.installationScript) - ] - # TODO: Remove the darwin check once - # https://github.com/NixOS/nixpkgs/pull/291814 is available - ++ lib.optional (stdenv.cc.isClang && !stdenv.buildPlatform.isDarwin) pkgs.buildPackages.bear - ++ lib.optional (stdenv.cc.isClang && stdenv.hostPlatform == stdenv.buildPlatform) (lib.hiPrio pkgs.buildPackages.clang-tools); + nativeBuildInputs = + attrs.nativeBuildInputs or [ ] + ++ pkgs.nixComponents.nix-util.nativeBuildInputs + ++ pkgs.nixComponents.nix-store.nativeBuildInputs + ++ pkgs.nixComponents.nix-fetchers.nativeBuildInputs + ++ pkgs.nixComponents.nix-expr.nativeBuildInputs + ++ lib.optionals havePerl pkgs.nixComponents.nix-perl-bindings.nativeBuildInputs + ++ lib.optionals buildCanExecuteHost pkgs.nixComponents.nix-manual.externalNativeBuildInputs + ++ pkgs.nixComponents.nix-internal-api-docs.nativeBuildInputs + ++ pkgs.nixComponents.nix-external-api-docs.nativeBuildInputs + ++ pkgs.nixComponents.nix-functional-tests.externalNativeBuildInputs + ++ lib.optional ( + !buildCanExecuteHost + # Hack around https://github.com/nixos/nixpkgs/commit/bf7ad8cfbfa102a90463433e2c5027573b462479 + && !(stdenv.hostPlatform.isWindows && stdenv.buildPlatform.isDarwin) + && stdenv.hostPlatform.emulatorAvailable pkgs.buildPackages + && lib.meta.availableOn stdenv.buildPlatform (stdenv.hostPlatform.emulator pkgs.buildPackages) + ) pkgs.buildPackages.mesonEmulatorHook + ++ [ + pkgs.buildPackages.cmake + pkgs.buildPackages.shellcheck + pkgs.buildPackages.changelog-d + modular.pre-commit.settings.package + (pkgs.writeScriptBin "pre-commit-hooks-install" modular.pre-commit.settings.installationScript) + ] + # TODO: Remove the darwin check once + # https://github.com/NixOS/nixpkgs/pull/291814 is available + ++ lib.optional (stdenv.cc.isClang && !stdenv.buildPlatform.isDarwin) pkgs.buildPackages.bear + ++ lib.optional (stdenv.cc.isClang && stdenv.hostPlatform == stdenv.buildPlatform) ( + lib.hiPrio pkgs.buildPackages.clang-tools + ); - buildInputs = attrs.buildInputs or [] - ++ pkgs.nixComponents.nix-util.buildInputs - ++ pkgs.nixComponents.nix-store.buildInputs - ++ pkgs.nixComponents.nix-store-tests.externalBuildInputs - ++ pkgs.nixComponents.nix-fetchers.buildInputs - ++ pkgs.nixComponents.nix-expr.buildInputs - ++ pkgs.nixComponents.nix-expr.externalPropagatedBuildInputs - ++ pkgs.nixComponents.nix-cmd.buildInputs - ++ lib.optionals havePerl pkgs.nixComponents.nix-perl-bindings.externalBuildInputs - ++ lib.optional havePerl pkgs.perl - ; -}) + buildInputs = + attrs.buildInputs or [ ] + ++ pkgs.nixComponents.nix-util.buildInputs + ++ pkgs.nixComponents.nix-store.buildInputs + ++ pkgs.nixComponents.nix-store-tests.externalBuildInputs + ++ pkgs.nixComponents.nix-fetchers.buildInputs + ++ pkgs.nixComponents.nix-expr.buildInputs + ++ pkgs.nixComponents.nix-expr.externalPropagatedBuildInputs + ++ pkgs.nixComponents.nix-cmd.buildInputs + ++ lib.optionals havePerl pkgs.nixComponents.nix-perl-bindings.externalBuildInputs + ++ lib.optional havePerl pkgs.perl; + } +) diff --git a/packaging/everything.nix b/packaging/everything.nix index 7ca878d8d..2b47c31bb 100644 --- a/packaging/everything.nix +++ b/packaging/everything.nix @@ -42,27 +42,31 @@ }: let - libs = { - inherit - nix-util - nix-util-c - nix-store - nix-store-c - nix-fetchers - nix-expr - nix-expr-c - nix-flake - nix-flake-c - nix-main - nix-main-c - nix-cmd - ; - } // lib.optionalAttrs (!stdenv.hostPlatform.isStatic && stdenv.buildPlatform.canExecute stdenv.hostPlatform) { - # Currently fails in static build - inherit - nix-perl-bindings - ; - }; + libs = + { + inherit + nix-util + nix-util-c + nix-store + nix-store-c + nix-fetchers + nix-expr + nix-expr-c + nix-flake + nix-flake-c + nix-main + nix-main-c + nix-cmd + ; + } + // lib.optionalAttrs + (!stdenv.hostPlatform.isStatic && stdenv.buildPlatform.canExecute stdenv.hostPlatform) + { + # Currently fails in static build + inherit + nix-perl-bindings + ; + }; dev = stdenv.mkDerivation (finalAttrs: { name = "nix-${nix-cli.version}-dev"; @@ -77,10 +81,9 @@ let ''; passthru = { tests = { - pkg-config = - testers.hasPkgConfigModules { - package = finalAttrs.finalPackage; - }; + pkg-config = testers.hasPkgConfigModules { + package = finalAttrs.finalPackage; + }; }; # If we were to fully emulate output selection here, we'd confuse the Nix CLIs, @@ -123,70 +126,84 @@ in ]; meta.mainProgram = "nix"; -}).overrideAttrs (finalAttrs: prevAttrs: { - doCheck = true; - doInstallCheck = true; +}).overrideAttrs + ( + finalAttrs: prevAttrs: { + doCheck = true; + doInstallCheck = true; - checkInputs = [ - # Make sure the unit tests have passed - nix-util-tests.tests.run - nix-store-tests.tests.run - nix-expr-tests.tests.run - nix-fetchers-tests.tests.run - nix-flake-tests.tests.run + checkInputs = + [ + # Make sure the unit tests have passed + nix-util-tests.tests.run + nix-store-tests.tests.run + nix-expr-tests.tests.run + nix-fetchers-tests.tests.run + nix-flake-tests.tests.run - # Make sure the functional tests have passed - nix-functional-tests + # Make sure the functional tests have passed + nix-functional-tests - # dev bundle is ok - # (checkInputs must be empty paths??) - (runCommand "check-pkg-config" { checked = dev.tests.pkg-config; } "mkdir $out") - ] ++ lib.optionals (!stdenv.hostPlatform.isStatic && stdenv.buildPlatform.canExecute stdenv.hostPlatform) [ - # Perl currently fails in static build - # TODO: Split out tests into a separate derivation? - nix-perl-bindings - ]; - passthru = prevAttrs.passthru // { - inherit (nix-cli) version; + # dev bundle is ok + # (checkInputs must be empty paths??) + (runCommand "check-pkg-config" { checked = dev.tests.pkg-config; } "mkdir $out") + ] + ++ lib.optionals + (!stdenv.hostPlatform.isStatic && stdenv.buildPlatform.canExecute stdenv.hostPlatform) + [ + # Perl currently fails in static build + # TODO: Split out tests into a separate derivation? + nix-perl-bindings + ]; + passthru = prevAttrs.passthru // { + inherit (nix-cli) version; - /** - These are the libraries that are part of the Nix project. They are used - by the Nix CLI and other tools. + /** + These are the libraries that are part of the Nix project. They are used + by the Nix CLI and other tools. - If you need to use these libraries in your project, we recommend to use - the `-c` C API libraries exclusively, if possible. + If you need to use these libraries in your project, we recommend to use + the `-c` C API libraries exclusively, if possible. - We also recommend that you build the complete package to ensure that the unit tests pass. - You could do this in CI, or by passing it in an unused environment variable. e.g in a `mkDerivation` call: + We also recommend that you build the complete package to ensure that the unit tests pass. + You could do this in CI, or by passing it in an unused environment variable. e.g in a `mkDerivation` call: - ```nix - buildInputs = [ nix.libs.nix-util-c nix.libs.nix-store-c ]; - # Make sure the nix libs we use are ok - unusedInputsForTests = [ nix ]; - disallowedReferences = nix.all; - ``` - */ - inherit libs; + ```nix + buildInputs = [ nix.libs.nix-util-c nix.libs.nix-store-c ]; + # Make sure the nix libs we use are ok + unusedInputsForTests = [ nix ]; + disallowedReferences = nix.all; + ``` + */ + inherit libs; - tests = prevAttrs.passthru.tests or {} // { - # TODO: create a proper fixpoint and: - # pkg-config = - # testers.hasPkgConfigModules { - # package = finalPackage; - # }; - }; + tests = prevAttrs.passthru.tests or { } // { + # TODO: create a proper fixpoint and: + # pkg-config = + # testers.hasPkgConfigModules { + # package = finalPackage; + # }; + }; - /** - A derivation referencing the `dev` outputs of the Nix libraries. - */ - inherit dev; - inherit devdoc; - doc = nix-manual; - outputs = [ "out" "dev" "devdoc" "doc" ]; - all = lib.attrValues (lib.genAttrs finalAttrs.passthru.outputs (outName: finalAttrs.finalPackage.${outName})); - }; - meta = prevAttrs.meta // { - description = "The Nix package manager"; - pkgConfigModules = dev.meta.pkgConfigModules; - }; -}) + /** + A derivation referencing the `dev` outputs of the Nix libraries. + */ + inherit dev; + inherit devdoc; + doc = nix-manual; + outputs = [ + "out" + "dev" + "devdoc" + "doc" + ]; + all = lib.attrValues ( + lib.genAttrs finalAttrs.passthru.outputs (outName: finalAttrs.finalPackage.${outName}) + ); + }; + meta = prevAttrs.meta // { + description = "The Nix package manager"; + pkgConfigModules = dev.meta.pkgConfigModules; + }; + } + ) diff --git a/packaging/hydra.nix b/packaging/hydra.nix index 5b1e47559..764898515 100644 --- a/packaging/hydra.nix +++ b/packaging/hydra.nix @@ -1,22 +1,25 @@ -{ inputs -, binaryTarball -, forAllCrossSystems -, forAllSystems -, lib -, linux64BitSystems -, nixpkgsFor -, self -, officialRelease +{ + inputs, + binaryTarball, + forAllCrossSystems, + forAllSystems, + lib, + linux64BitSystems, + nixpkgsFor, + self, + officialRelease, }: let inherit (inputs) nixpkgs nixpkgs-regression; - installScriptFor = tarballs: + installScriptFor = + tarballs: nixpkgsFor.x86_64-linux.native.callPackage ../scripts/installer.nix { inherit tarballs; }; - testNixVersions = pkgs: daemon: + testNixVersions = + pkgs: daemon: pkgs.nixComponents.nix-functional-tests.override { pname = "nix-daemon-compat-tests"; version = "${pkgs.nix.version}-with-daemon-${daemon.version}"; @@ -54,44 +57,70 @@ let in { # Binary package for various platforms. - build = forAllPackages (pkgName: - forAllSystems (system: nixpkgsFor.${system}.native.nixComponents.${pkgName})); + build = forAllPackages ( + pkgName: forAllSystems (system: nixpkgsFor.${system}.native.nixComponents.${pkgName}) + ); - shellInputs = removeAttrs - (forAllSystems (system: self.devShells.${system}.default.inputDerivation)) - [ "i686-linux" ]; + shellInputs = removeAttrs (forAllSystems ( + system: self.devShells.${system}.default.inputDerivation + )) [ "i686-linux" ]; - buildStatic = forAllPackages (pkgName: - lib.genAttrs linux64BitSystems (system: nixpkgsFor.${system}.static.nixComponents.${pkgName})); + buildStatic = forAllPackages ( + pkgName: + lib.genAttrs linux64BitSystems (system: nixpkgsFor.${system}.static.nixComponents.${pkgName}) + ); - buildCross = forAllPackages (pkgName: + buildCross = forAllPackages ( + pkgName: # Hack to avoid non-evaling package - (if pkgName == "nix-functional-tests" then lib.flip builtins.removeAttrs ["x86_64-w64-mingw32"] else lib.id) - (forAllCrossSystems (crossSystem: - lib.genAttrs [ "x86_64-linux" ] (system: nixpkgsFor.${system}.cross.${crossSystem}.nixComponents.${pkgName})))); + ( + if pkgName == "nix-functional-tests" then + lib.flip builtins.removeAttrs [ "x86_64-w64-mingw32" ] + else + lib.id + ) + ( + forAllCrossSystems ( + crossSystem: + lib.genAttrs [ "x86_64-linux" ] ( + system: nixpkgsFor.${system}.cross.${crossSystem}.nixComponents.${pkgName} + ) + ) + ) + ); - buildNoGc = let - components = forAllSystems (system: - nixpkgsFor.${system}.native.nixComponents.overrideScope (self: super: { - nix-expr = super.nix-expr.override { enableGC = false; }; - }) - ); - in forAllPackages (pkgName: forAllSystems (system: components.${system}.${pkgName})); + buildNoGc = + let + components = forAllSystems ( + system: + nixpkgsFor.${system}.native.nixComponents.overrideScope ( + self: super: { + nix-expr = super.nix-expr.override { enableGC = false; }; + } + ) + ); + in + forAllPackages (pkgName: forAllSystems (system: components.${system}.${pkgName})); buildNoTests = forAllSystems (system: nixpkgsFor.${system}.native.nixComponents.nix-cli); # Toggles some settings for better coverage. Windows needs these # library combinations, and Debian build Nix with GNU readline too. - buildReadlineNoMarkdown = let - components = forAllSystems (system: - nixpkgsFor.${system}.native.nixComponents.overrideScope (self: super: { - nix-cmd = super.nix-cmd.override { - enableMarkdown = false; - readlineFlavor = "readline"; - }; - }) - ); - in forAllPackages (pkgName: forAllSystems (system: components.${system}.${pkgName})); + buildReadlineNoMarkdown = + let + components = forAllSystems ( + system: + nixpkgsFor.${system}.native.nixComponents.overrideScope ( + self: super: { + nix-cmd = super.nix-cmd.override { + enableMarkdown = false; + readlineFlavor = "readline"; + }; + } + ) + ); + in + forAllPackages (pkgName: forAllSystems (system: components.${system}.${pkgName})); # Perl bindings for various platforms. perlBindings = forAllSystems (system: nixpkgsFor.${system}.native.nixComponents.nix-perl-bindings); @@ -99,13 +128,18 @@ in # Binary tarball for various platforms, containing a Nix store # with the closure of 'nix' package, and the second half of # the installation script. - binaryTarball = forAllSystems (system: binaryTarball nixpkgsFor.${system}.native.nix nixpkgsFor.${system}.native); + binaryTarball = forAllSystems ( + system: binaryTarball nixpkgsFor.${system}.native.nix nixpkgsFor.${system}.native + ); - binaryTarballCross = lib.genAttrs [ "x86_64-linux" ] (system: - forAllCrossSystems (crossSystem: - binaryTarball - nixpkgsFor.${system}.cross.${crossSystem}.nix - nixpkgsFor.${system}.cross.${crossSystem})); + binaryTarballCross = lib.genAttrs [ "x86_64-linux" ] ( + system: + forAllCrossSystems ( + crossSystem: + binaryTarball nixpkgsFor.${system}.cross.${crossSystem}.nix + nixpkgsFor.${system}.cross.${crossSystem} + ) + ); # The first half of the installation script. This is uploaded # to https://nixos.org/nix/install. It downloads the binary @@ -124,9 +158,12 @@ in self.hydraJobs.binaryTarballCross."x86_64-linux"."riscv64-unknown-linux-gnu" ]; - installerScriptForGHA = forAllSystems (system: nixpkgsFor.${system}.native.callPackage ../scripts/installer.nix { - tarballs = [ self.hydraJobs.binaryTarball.${system} ]; - }); + installerScriptForGHA = forAllSystems ( + system: + nixpkgsFor.${system}.native.callPackage ../scripts/installer.nix { + tarballs = [ self.hydraJobs.binaryTarball.${system} ]; + } + ); # docker image with Nix inside dockerImage = lib.genAttrs linux64BitSystems (system: self.packages.${system}.dockerImage); @@ -147,16 +184,24 @@ in external-api-docs = nixpkgsFor.x86_64-linux.native.nixComponents.nix-external-api-docs; # System tests. - tests = import ../tests/nixos { inherit lib nixpkgs nixpkgsFor self; } // { + tests = + import ../tests/nixos { + inherit + lib + nixpkgs + nixpkgsFor + self + ; + } + // { - # Make sure that nix-env still produces the exact same result - # on a particular version of Nixpkgs. - evalNixpkgs = - let - inherit (nixpkgsFor.x86_64-linux.native) runCommand nix; - in - runCommand "eval-nixos" { buildInputs = [ nix ]; } - '' + # Make sure that nix-env still produces the exact same result + # on a particular version of Nixpkgs. + evalNixpkgs = + let + inherit (nixpkgsFor.x86_64-linux.native) runCommand nix; + in + runCommand "eval-nixos" { buildInputs = [ nix ]; } '' type -p nix-env # Note: we're filtering out nixos-install-tools because https://github.com/NixOS/nixpkgs/pull/153594#issuecomment-1020530593. ( @@ -167,36 +212,36 @@ in mkdir $out ''; - nixpkgsLibTests = - forAllSystems (system: - import (nixpkgs + "/lib/tests/test-with-nix.nix") - { - lib = nixpkgsFor.${system}.native.lib; - nix = self.packages.${system}.nix-cli; - pkgs = nixpkgsFor.${system}.native; - } + nixpkgsLibTests = forAllSystems ( + system: + import (nixpkgs + "/lib/tests/test-with-nix.nix") { + lib = nixpkgsFor.${system}.native.lib; + nix = self.packages.${system}.nix-cli; + pkgs = nixpkgsFor.${system}.native; + } ); - }; + }; metrics.nixpkgs = import "${nixpkgs-regression}/pkgs/top-level/metrics.nix" { pkgs = nixpkgsFor.x86_64-linux.native; nixpkgs = nixpkgs-regression; }; - installTests = forAllSystems (system: - let pkgs = nixpkgsFor.${system}.native; in - pkgs.runCommand "install-tests" - { - againstSelf = testNixVersions pkgs pkgs.nix; - againstCurrentLatest = - # FIXME: temporarily disable this on macOS because of #3605. - if system == "x86_64-linux" - then testNixVersions pkgs pkgs.nixVersions.latest - else null; - # Disabled because the latest stable version doesn't handle - # `NIX_DAEMON_SOCKET_PATH` which is required for the tests to work - # againstLatestStable = testNixVersions pkgs pkgs.nixStable; - } "touch $out"); + installTests = forAllSystems ( + system: + let + pkgs = nixpkgsFor.${system}.native; + in + pkgs.runCommand "install-tests" { + againstSelf = testNixVersions pkgs pkgs.nix; + againstCurrentLatest = + # FIXME: temporarily disable this on macOS because of #3605. + if system == "x86_64-linux" then testNixVersions pkgs pkgs.nixVersions.latest else null; + # Disabled because the latest stable version doesn't handle + # `NIX_DAEMON_SOCKET_PATH` which is required for the tests to work + # againstLatestStable = testNixVersions pkgs pkgs.nixStable; + } "touch $out" + ); installerTests = import ../tests/installer { binaryTarballs = self.hydraJobs.binaryTarball; diff --git a/scripts/binary-tarball.nix b/scripts/binary-tarball.nix index 9de90b7fb..580e3859f 100644 --- a/scripts/binary-tarball.nix +++ b/scripts/binary-tarball.nix @@ -1,14 +1,18 @@ -{ runCommand -, system -, buildPackages -, cacert -, nix +{ + runCommand, + system, + buildPackages, + cacert, + nix, }: let installerClosureInfo = buildPackages.closureInfo { - rootPaths = [ nix cacert ]; + rootPaths = [ + nix + cacert + ]; }; inherit (nix) version; diff --git a/scripts/installer.nix b/scripts/installer.nix index cc7759c2c..e171f36f9 100644 --- a/scripts/installer.nix +++ b/scripts/installer.nix @@ -1,36 +1,42 @@ -{ lib -, runCommand -, nix -, tarballs +{ + lib, + runCommand, + nix, + tarballs, }: -runCommand "installer-script" { - buildInputs = [ nix ]; -} '' - mkdir -p $out/nix-support - - # Converts /nix/store/50p3qk8k...-nix-2.4pre20201102_550e11f/bin/nix to 50p3qk8k.../bin/nix. - tarballPath() { - # Remove the store prefix - local path=''${1#${builtins.storeDir}/} - # Get the path relative to the derivation root - local rest=''${path#*/} - # Get the derivation hash - local drvHash=''${path%%-*} - echo "$drvHash/$rest" +runCommand "installer-script" + { + buildInputs = [ nix ]; } + '' + mkdir -p $out/nix-support - substitute ${./install.in} $out/install \ - ${lib.concatMapStrings - (tarball: let - inherit (tarball.stdenv.hostPlatform) system; - in '' \ - --replace '@tarballHash_${system}@' $(nix --experimental-features nix-command hash-file --base16 --type sha256 ${tarball}/*.tar.xz) \ - --replace '@tarballPath_${system}@' $(tarballPath ${tarball}/*.tar.xz) \ - '' - ) - tarballs - } --replace '@nixVersion@' ${nix.version} + # Converts /nix/store/50p3qk8k...-nix-2.4pre20201102_550e11f/bin/nix to 50p3qk8k.../bin/nix. + tarballPath() { + # Remove the store prefix + local path=''${1#${builtins.storeDir}/} + # Get the path relative to the derivation root + local rest=''${path#*/} + # Get the derivation hash + local drvHash=''${path%%-*} + echo "$drvHash/$rest" + } - echo "file installer $out/install" >> $out/nix-support/hydra-build-products -'' + substitute ${./install.in} $out/install \ + ${ + lib.concatMapStrings ( + tarball: + let + inherit (tarball.stdenv.hostPlatform) system; + in + '' + \ + --replace '@tarballHash_${system}@' $(nix --experimental-features nix-command hash-file --base16 --type sha256 ${tarball}/*.tar.xz) \ + --replace '@tarballPath_${system}@' $(tarballPath ${tarball}/*.tar.xz) \ + '' + ) tarballs + } --replace '@nixVersion@' ${nix.version} + + echo "file installer $out/install" >> $out/nix-support/hydra-build-products + '' diff --git a/src/external-api-docs/package.nix b/src/external-api-docs/package.nix index 57c5138cf..b194e16d4 100644 --- a/src/external-api-docs/package.nix +++ b/src/external-api-docs/package.nix @@ -1,11 +1,12 @@ -{ lib -, mkMesonDerivation +{ + lib, + mkMesonDerivation, -, doxygen + doxygen, -# Configuration Options + # Configuration Options -, version + version, }: let @@ -39,11 +40,10 @@ mkMesonDerivation (finalAttrs: { doxygen ]; - preConfigure = - '' - chmod u+w ./.version - echo ${finalAttrs.version} > ./.version - ''; + preConfigure = '' + chmod u+w ./.version + echo ${finalAttrs.version} > ./.version + ''; postInstall = '' mkdir -p ''${!outputDoc}/nix-support diff --git a/src/internal-api-docs/package.nix b/src/internal-api-docs/package.nix index 993a257a6..6c4f354ae 100644 --- a/src/internal-api-docs/package.nix +++ b/src/internal-api-docs/package.nix @@ -1,11 +1,12 @@ -{ lib -, mkMesonDerivation +{ + lib, + mkMesonDerivation, -, doxygen + doxygen, -# Configuration Options + # Configuration Options -, version + version, }: let @@ -17,27 +18,28 @@ mkMesonDerivation (finalAttrs: { inherit version; workDir = ./.; - fileset = let - cpp = fileset.fileFilter (file: file.hasExt "cc" || file.hasExt "hh"); - in fileset.unions [ - ./.version - ../../.version - ./meson.build - ./doxygen.cfg.in - # Source is not compiled, but still must be available for Doxygen - # to gather comments. - (cpp ../.) - ]; + fileset = + let + cpp = fileset.fileFilter (file: file.hasExt "cc" || file.hasExt "hh"); + in + fileset.unions [ + ./.version + ../../.version + ./meson.build + ./doxygen.cfg.in + # Source is not compiled, but still must be available for Doxygen + # to gather comments. + (cpp ../.) + ]; nativeBuildInputs = [ doxygen ]; - preConfigure = - '' - chmod u+w ./.version - echo ${finalAttrs.version} > ./.version - ''; + preConfigure = '' + chmod u+w ./.version + echo ${finalAttrs.version} > ./.version + ''; postInstall = '' mkdir -p ''${!outputDoc}/nix-support diff --git a/src/libcmd/package.nix b/src/libcmd/package.nix index 5cafb4dc1..d155d9f1e 100644 --- a/src/libcmd/package.nix +++ b/src/libcmd/package.nix @@ -1,32 +1,33 @@ -{ lib -, stdenv -, mkMesonLibrary +{ + lib, + stdenv, + mkMesonLibrary, -, nix-util -, nix-store -, nix-fetchers -, nix-expr -, nix-flake -, nix-main -, editline -, readline -, lowdown -, nlohmann_json + nix-util, + nix-store, + nix-fetchers, + nix-expr, + nix-flake, + nix-main, + editline, + readline, + lowdown, + nlohmann_json, -# Configuration Options + # Configuration Options -, version + version, -# Whether to enable Markdown rendering in the Nix binary. -, enableMarkdown ? !stdenv.hostPlatform.isWindows + # Whether to enable Markdown rendering in the Nix binary. + enableMarkdown ? !stdenv.hostPlatform.isWindows, -# Which interactive line editor library to use for Nix's repl. -# -# Currently supported choices are: -# -# - editline (default) -# - readline -, readlineFlavor ? if stdenv.hostPlatform.isWindows then "readline" else "editline" + # Which interactive line editor library to use for Nix's repl. + # + # Currently supported choices are: + # + # - editline (default) + # - readline + readlineFlavor ? if stdenv.hostPlatform.isWindows then "readline" else "editline", }: let diff --git a/src/libexpr-c/package.nix b/src/libexpr-c/package.nix index 5047f3e2e..ad1ea371c 100644 --- a/src/libexpr-c/package.nix +++ b/src/libexpr-c/package.nix @@ -1,12 +1,13 @@ -{ lib -, mkMesonLibrary +{ + lib, + mkMesonLibrary, -, nix-store-c -, nix-expr + nix-store-c, + nix-expr, -# Configuration Options + # Configuration Options -, version + version, }: let diff --git a/src/libexpr-test-support/package.nix b/src/libexpr-test-support/package.nix index 48118fa0c..5628d606a 100644 --- a/src/libexpr-test-support/package.nix +++ b/src/libexpr-test-support/package.nix @@ -1,15 +1,16 @@ -{ lib -, mkMesonLibrary +{ + lib, + mkMesonLibrary, -, nix-store-test-support -, nix-expr -, nix-expr-c + nix-store-test-support, + nix-expr, + nix-expr-c, -, rapidcheck + rapidcheck, -# Configuration Options + # Configuration Options -, version + version, }: let diff --git a/src/libexpr-tests/package.nix b/src/libexpr-tests/package.nix index a4a3bb0e7..bb5acb7c8 100644 --- a/src/libexpr-tests/package.nix +++ b/src/libexpr-tests/package.nix @@ -1,20 +1,21 @@ -{ lib -, buildPackages -, stdenv -, mkMesonExecutable +{ + lib, + buildPackages, + stdenv, + mkMesonExecutable, -, nix-expr -, nix-expr-c -, nix-expr-test-support + nix-expr, + nix-expr-c, + nix-expr-test-support, -, rapidcheck -, gtest -, runCommand + rapidcheck, + gtest, + runCommand, -# Configuration Options + # Configuration Options -, version -, resolvePath + version, + resolvePath, }: let @@ -58,16 +59,22 @@ mkMesonExecutable (finalAttrs: { passthru = { tests = { - run = runCommand "${finalAttrs.pname}-run" { - meta.broken = !stdenv.hostPlatform.emulatorAvailable buildPackages; - } (lib.optionalString stdenv.hostPlatform.isWindows '' - export HOME="$PWD/home-dir" - mkdir -p "$HOME" - '' + '' - export _NIX_TEST_UNIT_DATA=${resolvePath ./data} - ${stdenv.hostPlatform.emulator buildPackages} ${lib.getExe finalAttrs.finalPackage} - touch $out - ''); + run = + runCommand "${finalAttrs.pname}-run" + { + meta.broken = !stdenv.hostPlatform.emulatorAvailable buildPackages; + } + ( + lib.optionalString stdenv.hostPlatform.isWindows '' + export HOME="$PWD/home-dir" + mkdir -p "$HOME" + '' + + '' + export _NIX_TEST_UNIT_DATA=${resolvePath ./data} + ${stdenv.hostPlatform.emulator buildPackages} ${lib.getExe finalAttrs.finalPackage} + touch $out + '' + ); }; }; diff --git a/src/libexpr/call-flake.nix b/src/libexpr/call-flake.nix index 964ba2521..9b38644bb 100644 --- a/src/libexpr/call-flake.nix +++ b/src/libexpr/call-flake.nix @@ -20,77 +20,77 @@ let # Resolve a input spec into a node name. An input spec is # either a node name, or a 'follows' path from the root # node. - resolveInput = inputSpec: - if builtins.isList inputSpec - then getInputByPath lockFile.root inputSpec - else inputSpec; + resolveInput = + inputSpec: if builtins.isList inputSpec then getInputByPath lockFile.root inputSpec else inputSpec; # Follow an input path (e.g. ["dwarffs" "nixpkgs"]) from the # root node, returning the final node. - getInputByPath = nodeName: path: - if path == [] - then nodeName + getInputByPath = + nodeName: path: + if path == [ ] then + nodeName else getInputByPath # Since this could be a 'follows' input, call resolveInput. (resolveInput lockFile.nodes.${nodeName}.inputs.${builtins.head path}) (builtins.tail path); - allNodes = - builtins.mapAttrs - (key: node: - let + allNodes = builtins.mapAttrs ( + key: node: + let - parentNode = allNodes.${getInputByPath lockFile.root node.parent}; + parentNode = allNodes.${getInputByPath lockFile.root node.parent}; - sourceInfo = - if overrides ? ${key} - then - overrides.${key}.sourceInfo - else if node.locked.type == "path" && builtins.substring 0 1 node.locked.path != "/" - then - parentNode.sourceInfo // { - outPath = parentNode.outPath + ("/" + node.locked.path); - } - else - # FIXME: remove obsolete node.info. - # Note: lock file entries are always final. - fetchTreeFinal (node.info or {} // removeAttrs node.locked ["dir"]); + sourceInfo = + if overrides ? ${key} then + overrides.${key}.sourceInfo + else if node.locked.type == "path" && builtins.substring 0 1 node.locked.path != "/" then + parentNode.sourceInfo + // { + outPath = parentNode.outPath + ("/" + node.locked.path); + } + else + # FIXME: remove obsolete node.info. + # Note: lock file entries are always final. + fetchTreeFinal (node.info or { } // removeAttrs node.locked [ "dir" ]); - subdir = overrides.${key}.dir or node.locked.dir or ""; + subdir = overrides.${key}.dir or node.locked.dir or ""; - outPath = sourceInfo + ((if subdir == "" then "" else "/") + subdir); + outPath = sourceInfo + ((if subdir == "" then "" else "/") + subdir); - flake = import (outPath + "/flake.nix"); + flake = import (outPath + "/flake.nix"); - inputs = builtins.mapAttrs - (inputName: inputSpec: allNodes.${resolveInput inputSpec}) - (node.inputs or {}); + inputs = builtins.mapAttrs (inputName: inputSpec: allNodes.${resolveInput inputSpec}) ( + node.inputs or { } + ); - outputs = flake.outputs (inputs // { self = result; }); + outputs = flake.outputs (inputs // { self = result; }); - result = - outputs - # We add the sourceInfo attribute for its metadata, as they are - # relevant metadata for the flake. However, the outPath of the - # sourceInfo does not necessarily match the outPath of the flake, - # as the flake may be in a subdirectory of a source. - # This is shadowed in the next // - // sourceInfo - // { - # This shadows the sourceInfo.outPath - inherit outPath; + result = + outputs + # We add the sourceInfo attribute for its metadata, as they are + # relevant metadata for the flake. However, the outPath of the + # sourceInfo does not necessarily match the outPath of the flake, + # as the flake may be in a subdirectory of a source. + # This is shadowed in the next // + // sourceInfo + // { + # This shadows the sourceInfo.outPath + inherit outPath; - inherit inputs; inherit outputs; inherit sourceInfo; _type = "flake"; - }; + inherit inputs; + inherit outputs; + inherit sourceInfo; + _type = "flake"; + }; - in - if node.flake or true then - assert builtins.isFunction flake.outputs; - result - else - sourceInfo - ) - lockFile.nodes; + in + if node.flake or true then + assert builtins.isFunction flake.outputs; + result + else + sourceInfo + ) lockFile.nodes; -in allNodes.${lockFile.root} +in +allNodes.${lockFile.root} diff --git a/src/libexpr/fetchurl.nix b/src/libexpr/fetchurl.nix index 85a01d161..72b3b00df 100644 --- a/src/libexpr/fetchurl.nix +++ b/src/libexpr/fetchurl.nix @@ -1,40 +1,72 @@ -{ system ? "" # obsolete -, url -, hash ? "" # an SRI hash +{ + system ? "", # obsolete + url, + hash ? "", # an SRI hash -# Legacy hash specification -, md5 ? "", sha1 ? "", sha256 ? "", sha512 ? "" -, outputHash ? - if hash != "" then hash else if sha512 != "" then sha512 else if sha1 != "" then sha1 else if md5 != "" then md5 else sha256 -, outputHashAlgo ? - if hash != "" then "" else if sha512 != "" then "sha512" else if sha1 != "" then "sha1" else if md5 != "" then "md5" else "sha256" + # Legacy hash specification + md5 ? "", + sha1 ? "", + sha256 ? "", + sha512 ? "", + outputHash ? + if hash != "" then + hash + else if sha512 != "" then + sha512 + else if sha1 != "" then + sha1 + else if md5 != "" then + md5 + else + sha256, + outputHashAlgo ? + if hash != "" then + "" + else if sha512 != "" then + "sha512" + else if sha1 != "" then + "sha1" + else if md5 != "" then + "md5" + else + "sha256", -, executable ? false -, unpack ? false -, name ? baseNameOf (toString url) -, impure ? false + executable ? false, + unpack ? false, + name ? baseNameOf (toString url), + impure ? false, }: -derivation ({ - builder = "builtin:fetchurl"; +derivation ( + { + builder = "builtin:fetchurl"; - # New-style output content requirements. - outputHashMode = if unpack || executable then "recursive" else "flat"; + # New-style output content requirements. + outputHashMode = if unpack || executable then "recursive" else "flat"; - inherit name url executable unpack; + inherit + name + url + executable + unpack + ; - system = "builtin"; + system = "builtin"; - # No need to double the amount of network traffic - preferLocalBuild = true; + # No need to double the amount of network traffic + preferLocalBuild = true; - # This attribute does nothing; it's here to avoid changing evaluation results. - impureEnvVars = [ - "http_proxy" "https_proxy" "ftp_proxy" "all_proxy" "no_proxy" - ]; + # This attribute does nothing; it's here to avoid changing evaluation results. + impureEnvVars = [ + "http_proxy" + "https_proxy" + "ftp_proxy" + "all_proxy" + "no_proxy" + ]; - # To make "nix-prefetch-url" work. - urls = [ url ]; -} // (if impure - then { __impure = true; } - else { inherit outputHashAlgo outputHash; })) + # To make "nix-prefetch-url" work. + urls = [ url ]; + } + // (if impure then { __impure = true; } else { inherit outputHashAlgo outputHash; }) +) diff --git a/src/libexpr/imported-drv-to-derivation.nix b/src/libexpr/imported-drv-to-derivation.nix index eab8b050e..e2cf7fd26 100644 --- a/src/libexpr/imported-drv-to-derivation.nix +++ b/src/libexpr/imported-drv-to-derivation.nix @@ -1,21 +1,27 @@ -attrs @ { drvPath, outputs, name, ... }: +attrs@{ + drvPath, + outputs, + name, + ... +}: let - commonAttrs = (builtins.listToAttrs outputsList) // - { all = map (x: x.value) outputsList; - inherit drvPath name; - type = "derivation"; - }; + commonAttrs = (builtins.listToAttrs outputsList) // { + all = map (x: x.value) outputsList; + inherit drvPath name; + type = "derivation"; + }; - outputToAttrListElement = outputName: - { name = outputName; - value = commonAttrs // { - outPath = builtins.getAttr outputName attrs; - inherit outputName; - }; + outputToAttrListElement = outputName: { + name = outputName; + value = commonAttrs // { + outPath = builtins.getAttr outputName attrs; + inherit outputName; }; - + }; + outputsList = map outputToAttrListElement outputs; - -in (builtins.head outputsList).value + +in +(builtins.head outputsList).value diff --git a/src/libexpr/package.nix b/src/libexpr/package.nix index 3d5b78e35..afd01c384 100644 --- a/src/libexpr/package.nix +++ b/src/libexpr/package.nix @@ -1,33 +1,34 @@ -{ lib -, stdenv -, mkMesonLibrary +{ + lib, + stdenv, + mkMesonLibrary, -, bison -, flex -, cmake # for resolving toml11 dep + bison, + flex, + cmake, # for resolving toml11 dep -, nix-util -, nix-store -, nix-fetchers -, boost -, boehmgc -, nlohmann_json -, toml11 + nix-util, + nix-store, + nix-fetchers, + boost, + boehmgc, + nlohmann_json, + toml11, -# Configuration Options + # Configuration Options -, version + version, -# Whether to use garbage collection for the Nix language evaluator. -# -# If it is disabled, we just leak memory, but this is not as bad as it -# sounds so long as evaluation just takes places within short-lived -# processes. (When the process exits, the memory is reclaimed; it is -# only leaked *within* the process.) -# -# Temporarily disabled on Windows because the `GC_throw_bad_alloc` -# symbol is missing during linking. -, enableGC ? !stdenv.hostPlatform.isWindows + # Whether to use garbage collection for the Nix language evaluator. + # + # If it is disabled, we just leak memory, but this is not as bad as it + # sounds so long as evaluation just takes places within short-lived + # processes. (When the process exits, the memory is reclaimed; it is + # only leaked *within* the process.) + # + # Temporarily disabled on Windows because the `GC_throw_bad_alloc` + # symbol is missing during linking. + enableGC ? !stdenv.hostPlatform.isWindows, }: let @@ -51,10 +52,7 @@ mkMesonLibrary (finalAttrs: { (fileset.fileFilter (file: file.hasExt "hh") ./.) ./lexer.l ./parser.y - (fileset.difference - (fileset.fileFilter (file: file.hasExt "nix") ./.) - ./package.nix - ) + (fileset.difference (fileset.fileFilter (file: file.hasExt "nix") ./.) ./package.nix) ]; nativeBuildInputs = [ diff --git a/src/libexpr/primops/derivation.nix b/src/libexpr/primops/derivation.nix index f329ff71e..dbb8c2186 100644 --- a/src/libexpr/primops/derivation.nix +++ b/src/libexpr/primops/derivation.nix @@ -26,27 +26,34 @@ Note that `derivation` is very bare-bones, and provides almost no commands during the build. Most likely, you'll want to use functions like `stdenv.mkDerivation` in Nixpkgs to set up a basic environment. */ -drvAttrs @ { outputs ? [ "out" ], ... }: +drvAttrs@{ + outputs ? [ "out" ], + ... +}: let strict = derivationStrict drvAttrs; - commonAttrs = drvAttrs // (builtins.listToAttrs outputsList) // - { all = map (x: x.value) outputsList; + commonAttrs = + drvAttrs + // (builtins.listToAttrs outputsList) + // { + all = map (x: x.value) outputsList; inherit drvAttrs; }; - outputToAttrListElement = outputName: - { name = outputName; - value = commonAttrs // { - outPath = builtins.getAttr outputName strict; - drvPath = strict.drvPath; - type = "derivation"; - inherit outputName; - }; + outputToAttrListElement = outputName: { + name = outputName; + value = commonAttrs // { + outPath = builtins.getAttr outputName strict; + drvPath = strict.drvPath; + type = "derivation"; + inherit outputName; }; + }; outputsList = map outputToAttrListElement outputs; -in (builtins.head outputsList).value +in +(builtins.head outputsList).value diff --git a/src/libfetchers-tests/package.nix b/src/libfetchers-tests/package.nix index 5336672a2..f2680e9b3 100644 --- a/src/libfetchers-tests/package.nix +++ b/src/libfetchers-tests/package.nix @@ -1,19 +1,20 @@ -{ lib -, buildPackages -, stdenv -, mkMesonExecutable +{ + lib, + buildPackages, + stdenv, + mkMesonExecutable, -, nix-fetchers -, nix-store-test-support + nix-fetchers, + nix-store-test-support, -, rapidcheck -, gtest -, runCommand + rapidcheck, + gtest, + runCommand, -# Configuration Options + # Configuration Options -, version -, resolvePath + version, + resolvePath, }: let @@ -56,16 +57,22 @@ mkMesonExecutable (finalAttrs: { passthru = { tests = { - run = runCommand "${finalAttrs.pname}-run" { - meta.broken = !stdenv.hostPlatform.emulatorAvailable buildPackages; - } (lib.optionalString stdenv.hostPlatform.isWindows '' - export HOME="$PWD/home-dir" - mkdir -p "$HOME" - '' + '' - export _NIX_TEST_UNIT_DATA=${resolvePath ./data} - ${stdenv.hostPlatform.emulator buildPackages} ${lib.getExe finalAttrs.finalPackage} - touch $out - ''); + run = + runCommand "${finalAttrs.pname}-run" + { + meta.broken = !stdenv.hostPlatform.emulatorAvailable buildPackages; + } + ( + lib.optionalString stdenv.hostPlatform.isWindows '' + export HOME="$PWD/home-dir" + mkdir -p "$HOME" + '' + + '' + export _NIX_TEST_UNIT_DATA=${resolvePath ./data} + ${stdenv.hostPlatform.emulator buildPackages} ${lib.getExe finalAttrs.finalPackage} + touch $out + '' + ); }; }; diff --git a/src/libfetchers/package.nix b/src/libfetchers/package.nix index d4ca18555..b0aecd049 100644 --- a/src/libfetchers/package.nix +++ b/src/libfetchers/package.nix @@ -1,14 +1,15 @@ -{ lib -, mkMesonLibrary +{ + lib, + mkMesonLibrary, -, nix-util -, nix-store -, nlohmann_json -, libgit2 + nix-util, + nix-store, + nlohmann_json, + libgit2, -# Configuration Options + # Configuration Options -, version + version, }: let diff --git a/src/libflake-c/package.nix b/src/libflake-c/package.nix index dcd6c4966..f0615a427 100644 --- a/src/libflake-c/package.nix +++ b/src/libflake-c/package.nix @@ -1,13 +1,14 @@ -{ lib -, mkMesonLibrary +{ + lib, + mkMesonLibrary, -, nix-store-c -, nix-expr-c -, nix-flake + nix-store-c, + nix-expr-c, + nix-flake, -# Configuration Options + # Configuration Options -, version + version, }: let diff --git a/src/libflake-tests/package.nix b/src/libflake-tests/package.nix index 51b68ad58..f9d9b0bc0 100644 --- a/src/libflake-tests/package.nix +++ b/src/libflake-tests/package.nix @@ -1,20 +1,21 @@ -{ lib -, buildPackages -, stdenv -, mkMesonExecutable +{ + lib, + buildPackages, + stdenv, + mkMesonExecutable, -, nix-flake -, nix-flake-c -, nix-expr-test-support + nix-flake, + nix-flake-c, + nix-expr-test-support, -, rapidcheck -, gtest -, runCommand + rapidcheck, + gtest, + runCommand, -# Configuration Options + # Configuration Options -, version -, resolvePath + version, + resolvePath, }: let @@ -58,17 +59,23 @@ mkMesonExecutable (finalAttrs: { passthru = { tests = { - run = runCommand "${finalAttrs.pname}-run" { - meta.broken = !stdenv.hostPlatform.emulatorAvailable buildPackages; - } (lib.optionalString stdenv.hostPlatform.isWindows '' - export HOME="$PWD/home-dir" - mkdir -p "$HOME" - '' + '' - export _NIX_TEST_UNIT_DATA=${resolvePath ./data} - export NIX_CONFIG="extra-experimental-features = flakes" - ${stdenv.hostPlatform.emulator buildPackages} ${lib.getExe finalAttrs.finalPackage} - touch $out - ''); + run = + runCommand "${finalAttrs.pname}-run" + { + meta.broken = !stdenv.hostPlatform.emulatorAvailable buildPackages; + } + ( + lib.optionalString stdenv.hostPlatform.isWindows '' + export HOME="$PWD/home-dir" + mkdir -p "$HOME" + '' + + '' + export _NIX_TEST_UNIT_DATA=${resolvePath ./data} + export NIX_CONFIG="extra-experimental-features = flakes" + ${stdenv.hostPlatform.emulator buildPackages} ${lib.getExe finalAttrs.finalPackage} + touch $out + '' + ); }; }; diff --git a/src/libflake/package.nix b/src/libflake/package.nix index 3fc96a20e..ebd38e140 100644 --- a/src/libflake/package.nix +++ b/src/libflake/package.nix @@ -1,15 +1,16 @@ -{ lib -, mkMesonLibrary +{ + lib, + mkMesonLibrary, -, nix-util -, nix-store -, nix-fetchers -, nix-expr -, nlohmann_json + nix-util, + nix-store, + nix-fetchers, + nix-expr, + nlohmann_json, -# Configuration Options + # Configuration Options -, version + version, }: let diff --git a/src/libmain-c/package.nix b/src/libmain-c/package.nix index b96901bb4..cf710e03b 100644 --- a/src/libmain-c/package.nix +++ b/src/libmain-c/package.nix @@ -1,14 +1,15 @@ -{ lib -, mkMesonLibrary +{ + lib, + mkMesonLibrary, -, nix-util-c -, nix-store -, nix-store-c -, nix-main + nix-util-c, + nix-store, + nix-store-c, + nix-main, -# Configuration Options + # Configuration Options -, version + version, }: let diff --git a/src/libmain/package.nix b/src/libmain/package.nix index 9a5b9e8c2..046b505df 100644 --- a/src/libmain/package.nix +++ b/src/libmain/package.nix @@ -1,14 +1,15 @@ -{ lib -, mkMesonLibrary +{ + lib, + mkMesonLibrary, -, openssl + openssl, -, nix-util -, nix-store + nix-util, + nix-store, -# Configuration Options + # Configuration Options -, version + version, }: let diff --git a/src/libstore-c/package.nix b/src/libstore-c/package.nix index c2413c389..89abeaab8 100644 --- a/src/libstore-c/package.nix +++ b/src/libstore-c/package.nix @@ -1,12 +1,13 @@ -{ lib -, mkMesonLibrary +{ + lib, + mkMesonLibrary, -, nix-util-c -, nix-store + nix-util-c, + nix-store, -# Configuration Options + # Configuration Options -, version + version, }: let diff --git a/src/libstore-test-support/package.nix b/src/libstore-test-support/package.nix index 5d3f41b3e..7cc29795c 100644 --- a/src/libstore-test-support/package.nix +++ b/src/libstore-test-support/package.nix @@ -1,15 +1,16 @@ -{ lib -, mkMesonLibrary +{ + lib, + mkMesonLibrary, -, nix-util-test-support -, nix-store -, nix-store-c + nix-util-test-support, + nix-store, + nix-store-c, -, rapidcheck + rapidcheck, -# Configuration Options + # Configuration Options -, version + version, }: let diff --git a/src/libstore-tests/package.nix b/src/libstore-tests/package.nix index 3acf4e25c..670386c4a 100644 --- a/src/libstore-tests/package.nix +++ b/src/libstore-tests/package.nix @@ -1,21 +1,22 @@ -{ lib -, buildPackages -, stdenv -, mkMesonExecutable +{ + lib, + buildPackages, + stdenv, + mkMesonExecutable, -, nix-store -, nix-store-c -, nix-store-test-support -, sqlite + nix-store, + nix-store-c, + nix-store-test-support, + sqlite, -, rapidcheck -, gtest -, runCommand + rapidcheck, + gtest, + runCommand, -# Configuration Options + # Configuration Options -, version -, filesetToSource + version, + filesetToSource, }: let @@ -64,26 +65,33 @@ mkMesonExecutable (finalAttrs: { passthru = { tests = { - run = let - # Some data is shared with the functional tests: they create it, - # we consume it. - data = filesetToSource { - root = ../..; - fileset = lib.fileset.unions [ - ./data - ../../tests/functional/derivation - ]; - }; - in runCommand "${finalAttrs.pname}-run" { - meta.broken = !stdenv.hostPlatform.emulatorAvailable buildPackages; - } (lib.optionalString stdenv.hostPlatform.isWindows '' - export HOME="$PWD/home-dir" - mkdir -p "$HOME" - '' + '' - export _NIX_TEST_UNIT_DATA=${data + "/src/libstore-tests/data"} - ${stdenv.hostPlatform.emulator buildPackages} ${lib.getExe finalAttrs.finalPackage} - touch $out - ''); + run = + let + # Some data is shared with the functional tests: they create it, + # we consume it. + data = filesetToSource { + root = ../..; + fileset = lib.fileset.unions [ + ./data + ../../tests/functional/derivation + ]; + }; + in + runCommand "${finalAttrs.pname}-run" + { + meta.broken = !stdenv.hostPlatform.emulatorAvailable buildPackages; + } + ( + lib.optionalString stdenv.hostPlatform.isWindows '' + export HOME="$PWD/home-dir" + mkdir -p "$HOME" + '' + + '' + export _NIX_TEST_UNIT_DATA=${data + "/src/libstore-tests/data"} + ${stdenv.hostPlatform.emulator buildPackages} ${lib.getExe finalAttrs.finalPackage} + touch $out + '' + ); }; }; diff --git a/src/libstore/package.nix b/src/libstore/package.nix index 4fbaea4ac..c982b44f0 100644 --- a/src/libstore/package.nix +++ b/src/libstore/package.nix @@ -1,25 +1,26 @@ -{ lib -, stdenv -, mkMesonLibrary +{ + lib, + stdenv, + mkMesonLibrary, -, unixtools -, darwin + unixtools, + darwin, -, nix-util -, boost -, curl -, aws-sdk-cpp -, libseccomp -, nlohmann_json -, sqlite + nix-util, + boost, + curl, + aws-sdk-cpp, + libseccomp, + nlohmann_json, + sqlite, -, busybox-sandbox-shell ? null + busybox-sandbox-shell ? null, -# Configuration Options + # Configuration Options -, version + version, -, embeddedSandboxShell ? stdenv.hostPlatform.isStatic + embeddedSandboxShell ? stdenv.hostPlatform.isStatic, }: let @@ -48,19 +49,20 @@ mkMesonLibrary (finalAttrs: { (fileset.fileFilter (file: file.hasExt "sql") ./.) ]; - nativeBuildInputs = - lib.optional embeddedSandboxShell unixtools.hexdump; + nativeBuildInputs = lib.optional embeddedSandboxShell unixtools.hexdump; - buildInputs = [ - boost - curl - sqlite - ] ++ lib.optional stdenv.hostPlatform.isLinux libseccomp + buildInputs = + [ + boost + curl + sqlite + ] + ++ lib.optional stdenv.hostPlatform.isLinux libseccomp # There have been issues building these dependencies ++ lib.optional stdenv.hostPlatform.isDarwin darwin.apple_sdk.libs.sandbox - ++ lib.optional (stdenv.hostPlatform == stdenv.buildPlatform && (stdenv.isLinux || stdenv.isDarwin)) - aws-sdk-cpp - ; + ++ lib.optional ( + stdenv.hostPlatform == stdenv.buildPlatform && (stdenv.isLinux || stdenv.isDarwin) + ) aws-sdk-cpp; propagatedBuildInputs = [ nix-util @@ -75,12 +77,14 @@ mkMesonLibrary (finalAttrs: { echo ${version} > ../../.version ''; - mesonFlags = [ - (lib.mesonEnable "seccomp-sandboxing" stdenv.hostPlatform.isLinux) - (lib.mesonBool "embedded-sandbox-shell" embeddedSandboxShell) - ] ++ lib.optionals stdenv.hostPlatform.isLinux [ - (lib.mesonOption "sandbox-shell" "${busybox-sandbox-shell}/bin/busybox") - ]; + mesonFlags = + [ + (lib.mesonEnable "seccomp-sandboxing" stdenv.hostPlatform.isLinux) + (lib.mesonBool "embedded-sandbox-shell" embeddedSandboxShell) + ] + ++ lib.optionals stdenv.hostPlatform.isLinux [ + (lib.mesonOption "sandbox-shell" "${busybox-sandbox-shell}/bin/busybox") + ]; env = { # Needed for Meson to find Boost. diff --git a/src/libutil-c/package.nix b/src/libutil-c/package.nix index f80e0b7f0..72f57d6f9 100644 --- a/src/libutil-c/package.nix +++ b/src/libutil-c/package.nix @@ -1,11 +1,12 @@ -{ lib -, mkMesonLibrary +{ + lib, + mkMesonLibrary, -, nix-util + nix-util, -# Configuration Options + # Configuration Options -, version + version, }: let diff --git a/src/libutil-test-support/package.nix b/src/libutil-test-support/package.nix index a8a239717..33cd5217d 100644 --- a/src/libutil-test-support/package.nix +++ b/src/libutil-test-support/package.nix @@ -1,14 +1,15 @@ -{ lib -, mkMesonLibrary +{ + lib, + mkMesonLibrary, -, nix-util -, nix-util-c + nix-util, + nix-util-c, -, rapidcheck + rapidcheck, -# Configuration Options + # Configuration Options -, version + version, }: let diff --git a/src/libutil-tests/package.nix b/src/libutil-tests/package.nix index 28769e115..d89c54453 100644 --- a/src/libutil-tests/package.nix +++ b/src/libutil-tests/package.nix @@ -1,19 +1,20 @@ -{ lib -, buildPackages -, stdenv -, mkMesonExecutable +{ + lib, + buildPackages, + stdenv, + mkMesonExecutable, -, nix-util -, nix-util-c -, nix-util-test-support + nix-util, + nix-util-c, + nix-util-test-support, -, rapidcheck -, gtest -, runCommand + rapidcheck, + gtest, + runCommand, -# Configuration Options + # Configuration Options -, version + version, }: let @@ -57,16 +58,22 @@ mkMesonExecutable (finalAttrs: { passthru = { tests = { - run = runCommand "${finalAttrs.pname}-run" { - meta.broken = !stdenv.hostPlatform.emulatorAvailable buildPackages; - } (lib.optionalString stdenv.hostPlatform.isWindows '' - export HOME="$PWD/home-dir" - mkdir -p "$HOME" - '' + '' - export _NIX_TEST_UNIT_DATA=${./data} - ${stdenv.hostPlatform.emulator buildPackages} ${lib.getExe finalAttrs.finalPackage} - touch $out - ''); + run = + runCommand "${finalAttrs.pname}-run" + { + meta.broken = !stdenv.hostPlatform.emulatorAvailable buildPackages; + } + ( + lib.optionalString stdenv.hostPlatform.isWindows '' + export HOME="$PWD/home-dir" + mkdir -p "$HOME" + '' + + '' + export _NIX_TEST_UNIT_DATA=${./data} + ${stdenv.hostPlatform.emulator buildPackages} ${lib.getExe finalAttrs.finalPackage} + touch $out + '' + ); }; }; diff --git a/src/libutil/package.nix b/src/libutil/package.nix index 679872a75..586119a6e 100644 --- a/src/libutil/package.nix +++ b/src/libutil/package.nix @@ -1,18 +1,19 @@ -{ lib -, stdenv -, mkMesonLibrary +{ + lib, + stdenv, + mkMesonLibrary, -, boost -, brotli -, libarchive -, libcpuid -, libsodium -, nlohmann_json -, openssl + boost, + brotli, + libarchive, + libcpuid, + libsodium, + nlohmann_json, + openssl, -# Configuration Options + # Configuration Options -, version + version, }: let @@ -43,8 +44,7 @@ mkMesonLibrary (finalAttrs: { brotli libsodium openssl - ] ++ lib.optional stdenv.hostPlatform.isx86_64 libcpuid - ; + ] ++ lib.optional stdenv.hostPlatform.isx86_64 libcpuid; propagatedBuildInputs = [ boost diff --git a/src/nix-channel/unpack-channel.nix b/src/nix-channel/unpack-channel.nix index 10515bc8b..84e324a4d 100644 --- a/src/nix-channel/unpack-channel.nix +++ b/src/nix-channel/unpack-channel.nix @@ -1,4 +1,8 @@ -{ name, channelName, src }: +{ + name, + channelName, + src, +}: derivation { builder = "builtin:unpack-channel"; diff --git a/src/nix-env/buildenv.nix b/src/nix-env/buildenv.nix index 0bac4c44b..c8955a94e 100644 --- a/src/nix-env/buildenv.nix +++ b/src/nix-env/buildenv.nix @@ -8,13 +8,15 @@ derivation { inherit manifest; # !!! grmbl, need structured data for passing this in a clean way. - derivations = - map (d: - [ (d.meta.active or "true") - (d.meta.priority or 5) - (builtins.length d.outputs) - ] ++ map (output: builtins.getAttr output d) d.outputs) - derivations; + derivations = map ( + d: + [ + (d.meta.active or "true") + (d.meta.priority or 5) + (builtins.length d.outputs) + ] + ++ map (output: builtins.getAttr output d) d.outputs + ) derivations; # Building user environments remotely just causes huge amounts of # network traffic, so don't do that. diff --git a/src/nix/package.nix b/src/nix/package.nix index 171621af9..89c52c3bb 100644 --- a/src/nix/package.nix +++ b/src/nix/package.nix @@ -1,14 +1,15 @@ -{ lib -, mkMesonExecutable +{ + lib, + mkMesonExecutable, -, nix-store -, nix-expr -, nix-main -, nix-cmd + nix-store, + nix-expr, + nix-main, + nix-cmd, -# Configuration Options + # Configuration Options -, version + version, }: let @@ -20,64 +21,67 @@ mkMesonExecutable (finalAttrs: { inherit version; workDir = ./.; - fileset = fileset.unions ([ - ../../nix-meson-build-support - ./nix-meson-build-support - ../../.version - ./.version - ./meson.build - ./meson.options - - # Symbolic links to other dirs - ## exes - ./build-remote - ./doc - ./nix-build - ./nix-channel - ./nix-collect-garbage - ./nix-copy-closure - ./nix-env - ./nix-instantiate - ./nix-store - ## dirs - ./scripts - ../../scripts - ./misc - ../../misc - - # Doc nix files for --help - ../../doc/manual/generate-manpage.nix - ../../doc/manual/utils.nix - ../../doc/manual/generate-settings.nix - ../../doc/manual/generate-store-info.nix - - # Other files to be included as string literals - ../nix-channel/unpack-channel.nix - ../nix-env/buildenv.nix - ./get-env.sh - ./help-stores.md - ../../doc/manual/source/store/types/index.md.in - ./profiles.md - ../../doc/manual/source/command-ref/files/profiles.md - - # Files - ] ++ lib.concatMap - (dir: [ - (fileset.fileFilter (file: file.hasExt "cc") dir) - (fileset.fileFilter (file: file.hasExt "hh") dir) - (fileset.fileFilter (file: file.hasExt "md") dir) - ]) + fileset = fileset.unions ( [ - ./. - ../build-remote - ../nix-build - ../nix-channel - ../nix-collect-garbage - ../nix-copy-closure - ../nix-env - ../nix-instantiate - ../nix-store + ../../nix-meson-build-support + ./nix-meson-build-support + ../../.version + ./.version + ./meson.build + ./meson.options + + # Symbolic links to other dirs + ## exes + ./build-remote + ./doc + ./nix-build + ./nix-channel + ./nix-collect-garbage + ./nix-copy-closure + ./nix-env + ./nix-instantiate + ./nix-store + ## dirs + ./scripts + ../../scripts + ./misc + ../../misc + + # Doc nix files for --help + ../../doc/manual/generate-manpage.nix + ../../doc/manual/utils.nix + ../../doc/manual/generate-settings.nix + ../../doc/manual/generate-store-info.nix + + # Other files to be included as string literals + ../nix-channel/unpack-channel.nix + ../nix-env/buildenv.nix + ./get-env.sh + ./help-stores.md + ../../doc/manual/source/store/types/index.md.in + ./profiles.md + ../../doc/manual/source/command-ref/files/profiles.md + + # Files ] + ++ + lib.concatMap + (dir: [ + (fileset.fileFilter (file: file.hasExt "cc") dir) + (fileset.fileFilter (file: file.hasExt "hh") dir) + (fileset.fileFilter (file: file.hasExt "md") dir) + ]) + [ + ./. + ../build-remote + ../nix-build + ../nix-channel + ../nix-collect-garbage + ../nix-copy-closure + ../nix-env + ../nix-instantiate + ../nix-store + ] ); buildInputs = [ diff --git a/src/perl/package.nix b/src/perl/package.nix index 5ee0df13c..d95d13aa9 100644 --- a/src/perl/package.nix +++ b/src/perl/package.nix @@ -1,76 +1,82 @@ -{ lib -, stdenv -, mkMesonDerivation -, pkg-config -, perl -, perlPackages -, nix-store -, version -, curl -, bzip2 -, libsodium +{ + lib, + stdenv, + mkMesonDerivation, + pkg-config, + perl, + perlPackages, + nix-store, + version, + curl, + bzip2, + libsodium, }: let inherit (lib) fileset; in -perl.pkgs.toPerlModule (mkMesonDerivation (finalAttrs: { - pname = "nix-perl"; - inherit version; +perl.pkgs.toPerlModule ( + mkMesonDerivation (finalAttrs: { + pname = "nix-perl"; + inherit version; - workDir = ./.; - fileset = fileset.unions ([ - ./.version - ../../.version - ./MANIFEST - ./lib - ./meson.build - ./meson.options - ] ++ lib.optionals finalAttrs.doCheck [ - ./.yath.rc.in - ./t - ]); + workDir = ./.; + fileset = fileset.unions ( + [ + ./.version + ../../.version + ./MANIFEST + ./lib + ./meson.build + ./meson.options + ] + ++ lib.optionals finalAttrs.doCheck [ + ./.yath.rc.in + ./t + ] + ); - nativeBuildInputs = [ - pkg-config - perl - curl - ]; + nativeBuildInputs = [ + pkg-config + perl + curl + ]; - buildInputs = [ - nix-store - ] ++ finalAttrs.passthru.externalBuildInputs; + buildInputs = [ + nix-store + ] ++ finalAttrs.passthru.externalBuildInputs; - # Hack for sake of the dev shell - passthru.externalBuildInputs = [ - bzip2 - libsodium - ]; + # Hack for sake of the dev shell + passthru.externalBuildInputs = [ + bzip2 + libsodium + ]; - # `perlPackages.Test2Harness` is marked broken for Darwin - doCheck = !stdenv.isDarwin; + # `perlPackages.Test2Harness` is marked broken for Darwin + doCheck = !stdenv.isDarwin; - nativeCheckInputs = [ - perlPackages.Test2Harness - ]; + nativeCheckInputs = [ + perlPackages.Test2Harness + ]; - preConfigure = - # "Inline" .version so its not a symlink, and includes the suffix - '' - chmod u+w .version - echo ${finalAttrs.version} > .version - ''; + preConfigure = + # "Inline" .version so its not a symlink, and includes the suffix + '' + chmod u+w .version + echo ${finalAttrs.version} > .version + ''; - mesonFlags = [ - (lib.mesonOption "dbi_path" "${perlPackages.DBI}/${perl.libPrefix}") - (lib.mesonOption "dbd_sqlite_path" "${perlPackages.DBDSQLite}/${perl.libPrefix}") - (lib.mesonEnable "tests" finalAttrs.doCheck) - ]; + mesonFlags = [ + (lib.mesonOption "dbi_path" "${perlPackages.DBI}/${perl.libPrefix}") + (lib.mesonOption "dbd_sqlite_path" "${perlPackages.DBDSQLite}/${perl.libPrefix}") + (lib.mesonEnable "tests" finalAttrs.doCheck) + ]; - mesonCheckFlags = [ - "--print-errorlogs" - ]; + mesonCheckFlags = [ + "--print-errorlogs" + ]; - strictDeps = false; -})) + strictDeps = false; + }) +) diff --git a/tests/functional/big-derivation-attr.nix b/tests/functional/big-derivation-attr.nix index 35c1187f6..d370486d6 100644 --- a/tests/functional/big-derivation-attr.nix +++ b/tests/functional/big-derivation-attr.nix @@ -1,6 +1,25 @@ let sixteenBytes = "0123456789abcdef"; - times16 = s: builtins.concatStringsSep "" [s s s s s s s s s s s s s s s s]; + times16 = + s: + builtins.concatStringsSep "" [ + s + s + s + s + s + s + s + s + s + s + s + s + s + s + s + s + ]; exp = n: x: if n == 1 then x else times16 (exp (n - 1) x); sixteenMegabyte = exp 6 sixteenBytes; in diff --git a/tests/functional/build-hook-ca-fixed.nix b/tests/functional/build-hook-ca-fixed.nix index 0ce6d9b12..3d2643c13 100644 --- a/tests/functional/build-hook-ca-fixed.nix +++ b/tests/functional/build-hook-ca-fixed.nix @@ -4,24 +4,39 @@ with import ./config.nix; let - mkDerivation = args: - derivation ({ - inherit system; - builder = busybox; - args = ["sh" "-e" args.builder or (builtins.toFile "builder-${args.name}.sh" '' - if [ -e "$NIX_ATTRS_SH_FILE" ]; then source $NIX_ATTRS_SH_FILE; fi; - eval "$buildCommand" - '')]; - outputHashMode = "recursive"; - outputHashAlgo = "sha256"; - } // removeAttrs args ["builder" "meta" "passthru"]) - // { meta = args.meta or {}; passthru = args.passthru or {}; }; + mkDerivation = + args: + derivation ( + { + inherit system; + builder = busybox; + args = [ + "sh" + "-e" + args.builder or (builtins.toFile "builder-${args.name}.sh" '' + if [ -e "$NIX_ATTRS_SH_FILE" ]; then source $NIX_ATTRS_SH_FILE; fi; + eval "$buildCommand" + '') + ]; + outputHashMode = "recursive"; + outputHashAlgo = "sha256"; + } + // removeAttrs args [ + "builder" + "meta" + "passthru" + ] + ) + // { + meta = args.meta or { }; + passthru = args.passthru or { }; + }; input1 = mkDerivation { shell = busybox; name = "build-remote-input-1"; buildCommand = "echo hi-input1; echo FOO > $out"; - requiredSystemFeatures = ["foo"]; + requiredSystemFeatures = [ "foo" ]; outputHash = "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="; }; @@ -29,7 +44,7 @@ let shell = busybox; name = "build-remote-input-2"; buildCommand = "echo hi; echo BAR > $out"; - requiredSystemFeatures = ["bar"]; + requiredSystemFeatures = [ "bar" ]; outputHash = "sha256-XArauVH91AVwP9hBBQNlkX9ccuPpSYx9o0zeIHb6e+Q="; }; @@ -41,21 +56,20 @@ let read x < ${input2} echo $x BAZ > $out ''; - requiredSystemFeatures = ["baz"]; + requiredSystemFeatures = [ "baz" ]; outputHash = "sha256-daKAcPp/+BYMQsVi/YYMlCKoNAxCNDsaivwSHgQqD2s="; }; in - mkDerivation { - shell = busybox; - name = "build-remote"; - passthru = { inherit input1 input2 input3; }; - buildCommand = - '' - read x < ${input1} - read y < ${input3} - echo "$x $y" > $out - ''; - outputHash = "sha256-5SxbkUw6xe2l9TE1uwCvTtTDysD1vhRor38OtDF0LqQ="; - } +mkDerivation { + shell = busybox; + name = "build-remote"; + passthru = { inherit input1 input2 input3; }; + buildCommand = '' + read x < ${input1} + read y < ${input3} + echo "$x $y" > $out + ''; + outputHash = "sha256-5SxbkUw6xe2l9TE1uwCvTtTDysD1vhRor38OtDF0LqQ="; +} diff --git a/tests/functional/build-hook.nix b/tests/functional/build-hook.nix index 99a13aee4..45a2a84d6 100644 --- a/tests/functional/build-hook.nix +++ b/tests/functional/build-hook.nix @@ -1,39 +1,61 @@ -{ busybox, contentAddressed ? false }: +{ + busybox, + contentAddressed ? false, +}: with import ./config.nix; let - caArgs = if contentAddressed then { - outputHashMode = "recursive"; - outputHashAlgo = "sha256"; - __contentAddressed = true; - } else {}; + caArgs = + if contentAddressed then + { + outputHashMode = "recursive"; + outputHashAlgo = "sha256"; + __contentAddressed = true; + } + else + { }; - mkDerivation = args: - derivation ({ - inherit system; - builder = busybox; - args = ["sh" "-e" args.builder or (builtins.toFile "builder-${args.name}.sh" '' - if [ -e "$NIX_ATTRS_SH_FILE" ]; then source $NIX_ATTRS_SH_FILE; fi; - eval "$buildCommand" - '')]; - } // removeAttrs args ["builder" "meta" "passthru"] - // caArgs) - // { meta = args.meta or {}; passthru = args.passthru or {}; }; + mkDerivation = + args: + derivation ( + { + inherit system; + builder = busybox; + args = [ + "sh" + "-e" + args.builder or (builtins.toFile "builder-${args.name}.sh" '' + if [ -e "$NIX_ATTRS_SH_FILE" ]; then source $NIX_ATTRS_SH_FILE; fi; + eval "$buildCommand" + '') + ]; + } + // removeAttrs args [ + "builder" + "meta" + "passthru" + ] + // caArgs + ) + // { + meta = args.meta or { }; + passthru = args.passthru or { }; + }; input1 = mkDerivation { shell = busybox; name = "build-remote-input-1"; buildCommand = "echo hi-input1; echo FOO > $out"; - requiredSystemFeatures = ["foo"]; + requiredSystemFeatures = [ "foo" ]; }; input2 = mkDerivation { shell = busybox; name = "build-remote-input-2"; buildCommand = "echo hi; echo BAR > $out"; - requiredSystemFeatures = ["bar"]; + requiredSystemFeatures = [ "bar" ]; }; input3 = mkDerivation { @@ -44,19 +66,18 @@ let read x < ${input2} echo $x BAZ > $out ''; - requiredSystemFeatures = ["baz"]; + requiredSystemFeatures = [ "baz" ]; }; in - mkDerivation { - shell = busybox; - name = "build-remote"; - passthru = { inherit input1 input2 input3; }; - buildCommand = - '' - read x < ${input1} - read y < ${input3} - echo "$x $y" > $out - ''; - } +mkDerivation { + shell = busybox; + name = "build-remote"; + passthru = { inherit input1 input2 input3; }; + buildCommand = '' + read x < ${input1} + read y < ${input3} + echo "$x $y" > $out + ''; +} diff --git a/tests/functional/ca-shell.nix b/tests/functional/ca-shell.nix index 36e1d1526..69ce6b6f1 100644 --- a/tests/functional/ca-shell.nix +++ b/tests/functional/ca-shell.nix @@ -1 +1,5 @@ -{ inNixShell ? false, ... }@args: import ./shell.nix (args // { contentAddressed = true; }) +{ + inNixShell ? false, + ... +}@args: +import ./shell.nix (args // { contentAddressed = true; }) diff --git a/tests/functional/ca/content-addressed.nix b/tests/functional/ca/content-addressed.nix index 2559c562f..6ed9c185b 100644 --- a/tests/functional/ca/content-addressed.nix +++ b/tests/functional/ca/content-addressed.nix @@ -1,13 +1,21 @@ with import ./config.nix; -let mkCADerivation = args: mkDerivation ({ - __contentAddressed = true; - outputHashMode = "recursive"; - outputHashAlgo = "sha256"; -} // args); +let + mkCADerivation = + args: + mkDerivation ( + { + __contentAddressed = true; + outputHashMode = "recursive"; + outputHashAlgo = "sha256"; + } + // args + ); in -{ seed ? 0 }: +{ + seed ? 0, +}: # A simple content-addressed derivation. # The derivation can be arbitrarily modified by passing a different `seed`, # but the output will always be the same @@ -23,7 +31,11 @@ rec { }; rootCA = mkCADerivation { name = "rootCA"; - outputs = [ "out" "dev" "foo" ]; + outputs = [ + "out" + "dev" + "foo" + ]; buildCommand = '' echo "building a CA derivation" echo "The seed is ${toString seed}" diff --git a/tests/functional/ca/flake.nix b/tests/functional/ca/flake.nix index 332c92a67..28a27c4b3 100644 --- a/tests/functional/ca/flake.nix +++ b/tests/functional/ca/flake.nix @@ -1,3 +1,3 @@ { - outputs = { self }: import ./content-addressed.nix {}; + outputs = { self }: import ./content-addressed.nix { }; } diff --git a/tests/functional/ca/nondeterministic.nix b/tests/functional/ca/nondeterministic.nix index d6d099a3e..2af26f0ac 100644 --- a/tests/functional/ca/nondeterministic.nix +++ b/tests/functional/ca/nondeterministic.nix @@ -1,10 +1,16 @@ with import ./config.nix; -let mkCADerivation = args: mkDerivation ({ - __contentAddressed = true; - outputHashMode = "recursive"; - outputHashAlgo = "sha256"; -} // args); +let + mkCADerivation = + args: + mkDerivation ( + { + __contentAddressed = true; + outputHashMode = "recursive"; + outputHashAlgo = "sha256"; + } + // args + ); in rec { @@ -15,13 +21,15 @@ rec { echo $(date) > $out/current-time ''; }; - dep = seed: mkCADerivation { - name = "dep"; - inherit seed; - buildCommand = '' - echo ${currentTime} > $out - ''; - }; + dep = + seed: + mkCADerivation { + name = "dep"; + inherit seed; + buildCommand = '' + echo ${currentTime} > $out + ''; + }; dep1 = dep 1; dep2 = dep 2; toplevel = mkCADerivation { @@ -32,4 +40,3 @@ rec { ''; }; } - diff --git a/tests/functional/ca/racy.nix b/tests/functional/ca/racy.nix index 555a15484..cbc0e1643 100644 --- a/tests/functional/ca/racy.nix +++ b/tests/functional/ca/racy.nix @@ -1,7 +1,6 @@ # A derivation that would certainly fail if several builders tried to # build it at once. - with import ./config.nix; mkDerivation { diff --git a/tests/functional/check-refs.nix b/tests/functional/check-refs.nix index 89690e456..471d95753 100644 --- a/tests/functional/check-refs.nix +++ b/tests/functional/check-refs.nix @@ -2,11 +2,16 @@ with import ./config.nix; rec { - dep = import ./dependencies.nix {}; + dep = import ./dependencies.nix { }; - makeTest = nr: args: mkDerivation ({ - name = "check-refs-" + toString nr; - } // args); + makeTest = + nr: args: + mkDerivation ( + { + name = "check-refs-" + toString nr; + } + // args + ); src = builtins.toFile "aux-ref" "bla bla"; @@ -22,31 +27,31 @@ rec { test3 = makeTest 3 { builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $dep $out/link"; - allowedReferences = []; + allowedReferences = [ ]; inherit dep; }; test4 = makeTest 4 { builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $dep $out/link"; - allowedReferences = [dep]; + allowedReferences = [ dep ]; inherit dep; }; test5 = makeTest 5 { builder = builtins.toFile "builder.sh" "mkdir $out"; - allowedReferences = []; + allowedReferences = [ ]; inherit dep; }; test6 = makeTest 6 { builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $out $out/link"; - allowedReferences = []; + allowedReferences = [ ]; inherit dep; }; test7 = makeTest 7 { builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $out $out/link"; - allowedReferences = ["out"]; + allowedReferences = [ "out" ]; inherit dep; }; @@ -58,19 +63,19 @@ rec { test9 = makeTest 9 { builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $dep $out/link"; inherit dep; - disallowedReferences = [dep]; + disallowedReferences = [ dep ]; }; test10 = makeTest 10 { builder = builtins.toFile "builder.sh" "mkdir $out; echo $test5; ln -s $dep $out/link"; inherit dep test5; - disallowedReferences = [test5]; + disallowedReferences = [ test5 ]; }; test11 = makeTest 11 { __structuredAttrs = true; unsafeDiscardReferences.out = true; - outputChecks.out.allowedReferences = []; + outputChecks.out.allowedReferences = [ ]; buildCommand = ''echo ${dep} > "''${outputs[out]}"''; }; diff --git a/tests/functional/check-reqs.nix b/tests/functional/check-reqs.nix index 41436cb48..3cca76184 100644 --- a/tests/functional/check-reqs.nix +++ b/tests/functional/check-reqs.nix @@ -22,36 +22,48 @@ rec { ''; }; - makeTest = nr: allowreqs: mkDerivation { - name = "check-reqs-" + toString nr; - inherit deps; - builder = builtins.toFile "builder.sh" '' - mkdir $out - ln -s $deps $out/depdir1 - ''; - allowedRequisites = allowreqs; - }; + makeTest = + nr: allowreqs: + mkDerivation { + name = "check-reqs-" + toString nr; + inherit deps; + builder = builtins.toFile "builder.sh" '' + mkdir $out + ln -s $deps $out/depdir1 + ''; + allowedRequisites = allowreqs; + }; # When specifying all the requisites, the build succeeds. - test1 = makeTest 1 [ dep1 dep2 deps ]; + test1 = makeTest 1 [ + dep1 + dep2 + deps + ]; # But missing anything it fails. - test2 = makeTest 2 [ dep2 deps ]; - test3 = makeTest 3 [ dep1 deps ]; + test2 = makeTest 2 [ + dep2 + deps + ]; + test3 = makeTest 3 [ + dep1 + deps + ]; test4 = makeTest 4 [ deps ]; - test5 = makeTest 5 []; + test5 = makeTest 5 [ ]; test6 = mkDerivation { name = "check-reqs"; inherit deps; builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $deps $out/depdir1"; - disallowedRequisites = [dep1]; + disallowedRequisites = [ dep1 ]; }; test7 = mkDerivation { name = "check-reqs"; inherit deps; builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $deps $out/depdir1"; - disallowedRequisites = [test1]; + disallowedRequisites = [ test1 ]; }; } diff --git a/tests/functional/check.nix b/tests/functional/check.nix index ddab8eea9..d83c28ca2 100644 --- a/tests/functional/check.nix +++ b/tests/functional/check.nix @@ -1,4 +1,6 @@ -{checkBuildId ? 0}: +{ + checkBuildId ? 0, +}: with import ./config.nix; @@ -6,41 +8,38 @@ with import ./config.nix; nondeterministic = mkDerivation { inherit checkBuildId; name = "nondeterministic"; - buildCommand = - '' - mkdir $out - date +%s.%N > $out/date - echo "CHECK_TMPDIR=$TMPDIR" - echo "checkBuildId=$checkBuildId" - echo "$checkBuildId" > $TMPDIR/checkBuildId - ''; + buildCommand = '' + mkdir $out + date +%s.%N > $out/date + echo "CHECK_TMPDIR=$TMPDIR" + echo "checkBuildId=$checkBuildId" + echo "$checkBuildId" > $TMPDIR/checkBuildId + ''; }; deterministic = mkDerivation { inherit checkBuildId; name = "deterministic"; - buildCommand = - '' - mkdir $out - echo date > $out/date - echo "CHECK_TMPDIR=$TMPDIR" - echo "checkBuildId=$checkBuildId" - echo "$checkBuildId" > $TMPDIR/checkBuildId - ''; + buildCommand = '' + mkdir $out + echo date > $out/date + echo "CHECK_TMPDIR=$TMPDIR" + echo "checkBuildId=$checkBuildId" + echo "$checkBuildId" > $TMPDIR/checkBuildId + ''; }; failed = mkDerivation { inherit checkBuildId; name = "failed"; - buildCommand = - '' - mkdir $out - echo date > $out/date - echo "CHECK_TMPDIR=$TMPDIR" - echo "checkBuildId=$checkBuildId" - echo "$checkBuildId" > $TMPDIR/checkBuildId - false - ''; + buildCommand = '' + mkdir $out + echo date > $out/date + echo "CHECK_TMPDIR=$TMPDIR" + echo "checkBuildId=$checkBuildId" + echo "$checkBuildId" > $TMPDIR/checkBuildId + false + ''; }; hashmismatch = import { diff --git a/tests/functional/dependencies.nix b/tests/functional/dependencies.nix index 4ff29227f..570ea7431 100644 --- a/tests/functional/dependencies.nix +++ b/tests/functional/dependencies.nix @@ -1,4 +1,6 @@ -{ hashInvalidator ? "" }: +{ + hashInvalidator ? "", +}: with import ./config.nix; let diff --git a/tests/functional/derivation/advanced-attributes-defaults.nix b/tests/functional/derivation/advanced-attributes-defaults.nix index 51a8d0e7e..d466003b0 100644 --- a/tests/functional/derivation/advanced-attributes-defaults.nix +++ b/tests/functional/derivation/advanced-attributes-defaults.nix @@ -2,5 +2,8 @@ derivation { name = "advanced-attributes-defaults"; system = "my-system"; builder = "/bin/bash"; - args = [ "-c" "echo hello > $out" ]; + args = [ + "-c" + "echo hello > $out" + ]; } diff --git a/tests/functional/derivation/advanced-attributes-structured-attrs-defaults.nix b/tests/functional/derivation/advanced-attributes-structured-attrs-defaults.nix index 0c13a7691..3c6ad4900 100644 --- a/tests/functional/derivation/advanced-attributes-structured-attrs-defaults.nix +++ b/tests/functional/derivation/advanced-attributes-structured-attrs-defaults.nix @@ -2,7 +2,13 @@ derivation { name = "advanced-attributes-structured-attrs-defaults"; system = "my-system"; builder = "/bin/bash"; - args = [ "-c" "echo hello > $out" ]; - outputs = [ "out" "dev" ]; + args = [ + "-c" + "echo hello > $out" + ]; + outputs = [ + "out" + "dev" + ]; __structuredAttrs = true; } diff --git a/tests/functional/derivation/advanced-attributes-structured-attrs.nix b/tests/functional/derivation/advanced-attributes-structured-attrs.nix index 0044b65fd..4c596be45 100644 --- a/tests/functional/derivation/advanced-attributes-structured-attrs.nix +++ b/tests/functional/derivation/advanced-attributes-structured-attrs.nix @@ -4,42 +4,58 @@ let inherit system; name = "foo"; builder = "/bin/bash"; - args = ["-c" "echo foo > $out"]; + args = [ + "-c" + "echo foo > $out" + ]; }; bar = derivation { inherit system; name = "bar"; builder = "/bin/bash"; - args = ["-c" "echo bar > $out"]; + args = [ + "-c" + "echo bar > $out" + ]; }; in derivation { inherit system; name = "advanced-attributes-structured-attrs"; builder = "/bin/bash"; - args = [ "-c" "echo hello > $out" ]; + args = [ + "-c" + "echo hello > $out" + ]; __sandboxProfile = "sandcastle"; __noChroot = true; - __impureHostDeps = ["/usr/bin/ditto"]; - impureEnvVars = ["UNICORN"]; + __impureHostDeps = [ "/usr/bin/ditto" ]; + impureEnvVars = [ "UNICORN" ]; __darwinAllowLocalNetworking = true; - outputs = [ "out" "bin" "dev" ]; + outputs = [ + "out" + "bin" + "dev" + ]; __structuredAttrs = true; outputChecks = { out = { - allowedReferences = [foo]; - allowedRequisites = [foo]; + allowedReferences = [ foo ]; + allowedRequisites = [ foo ]; }; bin = { - disallowedReferences = [bar]; - disallowedRequisites = [bar]; + disallowedReferences = [ bar ]; + disallowedRequisites = [ bar ]; }; dev = { maxSize = 789; maxClosureSize = 5909; }; }; - requiredSystemFeatures = ["rainbow" "uid-range"]; + requiredSystemFeatures = [ + "rainbow" + "uid-range" + ]; preferLocalBuild = true; allowSubstitutes = false; } diff --git a/tests/functional/derivation/advanced-attributes.nix b/tests/functional/derivation/advanced-attributes.nix index ff680c567..7f365ce65 100644 --- a/tests/functional/derivation/advanced-attributes.nix +++ b/tests/functional/derivation/advanced-attributes.nix @@ -4,30 +4,42 @@ let inherit system; name = "foo"; builder = "/bin/bash"; - args = ["-c" "echo foo > $out"]; + args = [ + "-c" + "echo foo > $out" + ]; }; bar = derivation { inherit system; name = "bar"; builder = "/bin/bash"; - args = ["-c" "echo bar > $out"]; + args = [ + "-c" + "echo bar > $out" + ]; }; in derivation { inherit system; name = "advanced-attributes"; builder = "/bin/bash"; - args = [ "-c" "echo hello > $out" ]; + args = [ + "-c" + "echo hello > $out" + ]; __sandboxProfile = "sandcastle"; __noChroot = true; - __impureHostDeps = ["/usr/bin/ditto"]; - impureEnvVars = ["UNICORN"]; + __impureHostDeps = [ "/usr/bin/ditto" ]; + impureEnvVars = [ "UNICORN" ]; __darwinAllowLocalNetworking = true; - allowedReferences = [foo]; - allowedRequisites = [foo]; - disallowedReferences = [bar]; - disallowedRequisites = [bar]; - requiredSystemFeatures = ["rainbow" "uid-range"]; + allowedReferences = [ foo ]; + allowedRequisites = [ foo ]; + disallowedReferences = [ bar ]; + disallowedRequisites = [ bar ]; + requiredSystemFeatures = [ + "rainbow" + "uid-range" + ]; preferLocalBuild = true; allowSubstitutes = false; } diff --git a/tests/functional/dyn-drv/recursive-mod-json.nix b/tests/functional/dyn-drv/recursive-mod-json.nix index c6a24ca4f..2d46e4e2e 100644 --- a/tests/functional/dyn-drv/recursive-mod-json.nix +++ b/tests/functional/dyn-drv/recursive-mod-json.nix @@ -1,6 +1,8 @@ with import ./config.nix; -let innerName = "foo"; in +let + innerName = "foo"; +in mkDerivation rec { name = "${innerName}.drv"; diff --git a/tests/functional/export-graph.nix b/tests/functional/export-graph.nix index 64fe36bd1..5078eec83 100644 --- a/tests/functional/export-graph.nix +++ b/tests/functional/export-graph.nix @@ -2,28 +2,33 @@ with import ./config.nix; rec { - printRefs = - '' - echo $exportReferencesGraph - while read path; do - read drv - read nrRefs - echo "$path has $nrRefs references" - echo "$path" >> $out - for ((n = 0; n < $nrRefs; n++)); do read ref; echo "ref $ref"; test -e "$ref"; done - done < refs - ''; + printRefs = '' + echo $exportReferencesGraph + while read path; do + read drv + read nrRefs + echo "$path has $nrRefs references" + echo "$path" >> $out + for ((n = 0; n < $nrRefs; n++)); do read ref; echo "ref $ref"; test -e "$ref"; done + done < refs + ''; foo."bar.runtimeGraph" = mkDerivation { name = "dependencies"; builder = builtins.toFile "build-graph-builder" "${printRefs}"; - exportReferencesGraph = ["refs" (import ./dependencies.nix {})]; + exportReferencesGraph = [ + "refs" + (import ./dependencies.nix { }) + ]; }; foo."bar.buildGraph" = mkDerivation { name = "dependencies"; builder = builtins.toFile "build-graph-builder" "${printRefs}"; - exportReferencesGraph = ["refs" (import ./dependencies.nix {}).drvPath]; + exportReferencesGraph = [ + "refs" + (import ./dependencies.nix { }).drvPath + ]; }; } diff --git a/tests/functional/failing.nix b/tests/functional/failing.nix index d25e2d6b6..8abae1856 100644 --- a/tests/functional/failing.nix +++ b/tests/functional/failing.nix @@ -2,16 +2,29 @@ with import ./config.nix; let - mkDerivation = args: - derivation ({ - inherit system; - builder = busybox; - args = ["sh" "-e" args.builder or (builtins.toFile "builder-${args.name}.sh" '' - if [ -e "$NIX_ATTRS_SH_FILE" ]; then source $NIX_ATTRS_SH_FILE; fi; - eval "$buildCommand" - '')]; - } // removeAttrs args ["builder" "meta"]) - // { meta = args.meta or {}; }; + mkDerivation = + args: + derivation ( + { + inherit system; + builder = busybox; + args = [ + "sh" + "-e" + args.builder or (builtins.toFile "builder-${args.name}.sh" '' + if [ -e "$NIX_ATTRS_SH_FILE" ]; then source $NIX_ATTRS_SH_FILE; fi; + eval "$buildCommand" + '') + ]; + } + // removeAttrs args [ + "builder" + "meta" + ] + ) + // { + meta = args.meta or { }; + }; in { diff --git a/tests/functional/filter-source.nix b/tests/functional/filter-source.nix index 907163639..7bad263f8 100644 --- a/tests/functional/filter-source.nix +++ b/tests/functional/filter-source.nix @@ -4,9 +4,12 @@ mkDerivation { name = "filter"; builder = builtins.toFile "builder" "ln -s $input $out"; input = - let filter = path: type: - type != "symlink" - && baseNameOf path != "foo" - && !((import ./lang/lib.nix).hasSuffix ".bak" (baseNameOf path)); - in builtins.filterSource filter ((builtins.getEnv "TEST_ROOT") + "/filterin"); + let + filter = + path: type: + type != "symlink" + && baseNameOf path != "foo" + && !((import ./lang/lib.nix).hasSuffix ".bak" (baseNameOf path)); + in + builtins.filterSource filter ((builtins.getEnv "TEST_ROOT") + "/filterin"); } diff --git a/tests/functional/fixed.nix b/tests/functional/fixed.nix index a920a2167..4097a6374 100644 --- a/tests/functional/fixed.nix +++ b/tests/functional/fixed.nix @@ -2,15 +2,20 @@ with import ./config.nix; rec { - f2 = dummy: builder: mode: algo: hash: mkDerivation { - name = "fixed"; - inherit builder; - outputHashMode = mode; - outputHashAlgo = algo; - outputHash = hash; - inherit dummy; - impureEnvVars = ["IMPURE_VAR1" "IMPURE_VAR2"]; - }; + f2 = + dummy: builder: mode: algo: hash: + mkDerivation { + name = "fixed"; + inherit builder; + outputHashMode = mode; + outputHashAlgo = algo; + outputHash = hash; + inherit dummy; + impureEnvVars = [ + "IMPURE_VAR1" + "IMPURE_VAR2" + ]; + }; f = f2 ""; @@ -37,7 +42,8 @@ rec { ]; sameAsAdd = - f ./fixed.builder2.sh "recursive" "sha256" "1ixr6yd3297ciyp9im522dfxpqbkhcw0pylkb2aab915278fqaik"; + f ./fixed.builder2.sh "recursive" "sha256" + "1ixr6yd3297ciyp9im522dfxpqbkhcw0pylkb2aab915278fqaik"; bad = [ (f ./fixed.builder1.sh "flat" "md5" "0ddd8be4b179a529afa5f2ffae4b9858") diff --git a/tests/functional/fod-failing.nix b/tests/functional/fod-failing.nix index 37c04fe12..0de676c15 100644 --- a/tests/functional/fod-failing.nix +++ b/tests/functional/fod-failing.nix @@ -2,38 +2,34 @@ with import ./config.nix; rec { x1 = mkDerivation { name = "x1"; - builder = builtins.toFile "builder.sh" - '' - echo $name > $out - ''; + builder = builtins.toFile "builder.sh" '' + echo $name > $out + ''; outputHashMode = "recursive"; outputHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; }; x2 = mkDerivation { name = "x2"; - builder = builtins.toFile "builder.sh" - '' - echo $name > $out - ''; + builder = builtins.toFile "builder.sh" '' + echo $name > $out + ''; outputHashMode = "recursive"; outputHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; }; x3 = mkDerivation { name = "x3"; - builder = builtins.toFile "builder.sh" - '' - echo $name > $out - ''; + builder = builtins.toFile "builder.sh" '' + echo $name > $out + ''; outputHashMode = "recursive"; outputHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; }; x4 = mkDerivation { name = "x4"; inherit x2 x3; - builder = builtins.toFile "builder.sh" - '' - echo $x2 $x3 - exit 1 - ''; + builder = builtins.toFile "builder.sh" '' + echo $x2 $x3 + exit 1 + ''; }; } diff --git a/tests/functional/gc-concurrent.nix b/tests/functional/gc-concurrent.nix index 0aba1f983..d7483d88f 100644 --- a/tests/functional/gc-concurrent.nix +++ b/tests/functional/gc-concurrent.nix @@ -1,6 +1,8 @@ with import ./config.nix; -{ lockFifo ? null }: +{ + lockFifo ? null, +}: rec { diff --git a/tests/functional/hash-check.nix b/tests/functional/hash-check.nix index 4a8e9b8a8..7a48a620b 100644 --- a/tests/functional/hash-check.nix +++ b/tests/functional/hash-check.nix @@ -4,14 +4,22 @@ let { name = "dependencies-input-1"; system = "i086-msdos"; builder = "/bar/sh"; - args = ["-e" "-x" ./dummy]; + args = [ + "-e" + "-x" + ./dummy + ]; }; input2 = derivation { name = "dependencies-input-2"; system = "i086-msdos"; builder = "/bar/sh"; - args = ["-e" "-x" ./dummy]; + args = [ + "-e" + "-x" + ./dummy + ]; outputHashMode = "recursive"; outputHashAlgo = "md5"; outputHash = "ffffffffffffffffffffffffffffffff"; @@ -21,9 +29,13 @@ let { name = "dependencies"; system = "i086-msdos"; builder = "/bar/sh"; - args = ["-e" "-x" (./dummy + "/FOOBAR/../.")]; + args = [ + "-e" + "-x" + (./dummy + "/FOOBAR/../.") + ]; input1 = input1 + "/."; inherit input2; }; -} \ No newline at end of file +} diff --git a/tests/functional/hermetic.nix b/tests/functional/hermetic.nix index d1dccdff3..a50714664 100644 --- a/tests/functional/hermetic.nix +++ b/tests/functional/hermetic.nix @@ -1,31 +1,51 @@ -{ busybox -, seed -# If we want the final derivation output to have references to its -# dependencies. Some tests need/want this, other don't. -, withFinalRefs ? false +{ + busybox, + seed, + # If we want the final derivation output to have references to its + # dependencies. Some tests need/want this, other don't. + withFinalRefs ? false, }: with import ./config.nix; let contentAddressedByDefault = builtins.getEnv "NIX_TESTS_CA_BY_DEFAULT" == "1"; - caArgs = if contentAddressedByDefault then { - __contentAddressed = true; - outputHashMode = "recursive"; - outputHashAlgo = "sha256"; - } else {}; + caArgs = + if contentAddressedByDefault then + { + __contentAddressed = true; + outputHashMode = "recursive"; + outputHashAlgo = "sha256"; + } + else + { }; - mkDerivation = args: - derivation ({ - inherit system; - builder = busybox; - args = ["sh" "-e" args.builder or (builtins.toFile "builder-${args.name}.sh" '' - if [ -e "$NIX_ATTRS_SH_FILE" ]; then source $NIX_ATTRS_SH_FILE; fi; - eval "$buildCommand" - '')]; - } // removeAttrs args ["builder" "meta" "passthru"] - // caArgs) - // { meta = args.meta or {}; passthru = args.passthru or {}; }; + mkDerivation = + args: + derivation ( + { + inherit system; + builder = busybox; + args = [ + "sh" + "-e" + args.builder or (builtins.toFile "builder-${args.name}.sh" '' + if [ -e "$NIX_ATTRS_SH_FILE" ]; then source $NIX_ATTRS_SH_FILE; fi; + eval "$buildCommand" + '') + ]; + } + // removeAttrs args [ + "builder" + "meta" + "passthru" + ] + // caArgs + ) + // { + meta = args.meta or { }; + passthru = args.passthru or { }; + }; input1 = mkDerivation { shell = busybox; @@ -51,14 +71,15 @@ let in - mkDerivation { - shell = busybox; - name = "hermetic"; - passthru = { inherit input1 input2 input3; }; - buildCommand = - '' - read x < ${input1} - read y < ${input3} - echo ${if (builtins.trace withFinalRefs withFinalRefs) then "${input1} ${input3}" else ""} "$x $y" > $out - ''; - } +mkDerivation { + shell = busybox; + name = "hermetic"; + passthru = { inherit input1 input2 input3; }; + buildCommand = '' + read x < ${input1} + read y < ${input3} + echo ${ + if (builtins.trace withFinalRefs withFinalRefs) then "${input1} ${input3}" else "" + } "$x $y" > $out + ''; +} diff --git a/tests/functional/ifd.nix b/tests/functional/ifd.nix index d0b9b54ad..b8c04f72c 100644 --- a/tests/functional/ifd.nix +++ b/tests/functional/ifd.nix @@ -1,10 +1,8 @@ with import ./config.nix; -import ( - mkDerivation { - name = "foo"; - bla = import ./dependencies.nix {}; - buildCommand = " +import (mkDerivation { + name = "foo"; + bla = import ./dependencies.nix { }; + buildCommand = " echo \\\"hi\\\" > $out "; - } -) +}) diff --git a/tests/functional/import-from-derivation.nix b/tests/functional/import-from-derivation.nix index 770dd86cf..600f448a6 100644 --- a/tests/functional/import-from-derivation.nix +++ b/tests/functional/import-from-derivation.nix @@ -3,10 +3,9 @@ with import ; rec { bar = mkDerivation { name = "bar"; - builder = builtins.toFile "builder.sh" - '' - echo 'builtins.add 123 456' > $out - ''; + builder = builtins.toFile "builder.sh" '' + echo 'builtins.add 123 456' > $out + ''; }; value = @@ -16,19 +15,17 @@ rec { result = mkDerivation { name = "foo"; - builder = builtins.toFile "builder.sh" - '' - echo -n FOO${toString value} > $out - ''; + builder = builtins.toFile "builder.sh" '' + echo -n FOO${toString value} > $out + ''; }; addPath = mkDerivation { name = "add-path"; src = builtins.filterSource (path: type: true) result; - builder = builtins.toFile "builder.sh" - '' - echo -n BLA$(cat $src) > $out - ''; + builder = builtins.toFile "builder.sh" '' + echo -n BLA$(cat $src) > $out + ''; }; step1 = mkDerivation { diff --git a/tests/functional/impure-derivations.nix b/tests/functional/impure-derivations.nix index 98547e6c1..806f20577 100644 --- a/tests/functional/impure-derivations.nix +++ b/tests/functional/impure-derivations.nix @@ -4,60 +4,58 @@ rec { impure = mkDerivation { name = "impure"; - outputs = [ "out" "stuff" ]; - buildCommand = - '' - echo impure - x=$(< $TEST_ROOT/counter) - mkdir $out $stuff - echo $x > $out/n - ln -s $out/n $stuff/bla - printf $((x + 1)) > $TEST_ROOT/counter - ''; + outputs = [ + "out" + "stuff" + ]; + buildCommand = '' + echo impure + x=$(< $TEST_ROOT/counter) + mkdir $out $stuff + echo $x > $out/n + ln -s $out/n $stuff/bla + printf $((x + 1)) > $TEST_ROOT/counter + ''; __impure = true; impureEnvVars = [ "TEST_ROOT" ]; }; impureOnImpure = mkDerivation { name = "impure-on-impure"; - buildCommand = - '' - echo impure-on-impure - x=$(< ${impure}/n) - mkdir $out - printf X$x > $out/n - ln -s ${impure.stuff} $out/symlink - ln -s $out $out/self - ''; + buildCommand = '' + echo impure-on-impure + x=$(< ${impure}/n) + mkdir $out + printf X$x > $out/n + ln -s ${impure.stuff} $out/symlink + ln -s $out $out/self + ''; __impure = true; }; # This is not allowed. inputAddressed = mkDerivation { name = "input-addressed"; - buildCommand = - '' - cat ${impure} > $out - ''; + buildCommand = '' + cat ${impure} > $out + ''; }; contentAddressed = mkDerivation { name = "content-addressed"; - buildCommand = - '' - echo content-addressed - x=$(< ${impureOnImpure}/n) - printf ''${x:0:1} > $out - ''; + buildCommand = '' + echo content-addressed + x=$(< ${impureOnImpure}/n) + printf ''${x:0:1} > $out + ''; outputHashMode = "recursive"; outputHash = "sha256-eBYxcgkuWuiqs4cKNgKwkb3vY/HR0vVsJnqe8itJGcQ="; }; inputAddressedAfterCA = mkDerivation { name = "input-addressed-after-ca"; - buildCommand = - '' - cat ${contentAddressed} > $out - ''; + buildCommand = '' + cat ${contentAddressed} > $out + ''; }; } diff --git a/tests/functional/lang-gc/issue-11141-gc-coroutine-test.nix b/tests/functional/lang-gc/issue-11141-gc-coroutine-test.nix index 4f311af75..6dae5c155 100644 --- a/tests/functional/lang-gc/issue-11141-gc-coroutine-test.nix +++ b/tests/functional/lang-gc/issue-11141-gc-coroutine-test.nix @@ -1,4 +1,3 @@ - # Run: # GC_INITIAL_HEAP_SIZE=$[1024 * 1024] NIX_SHOW_STATS=1 nix eval -f gc-coroutine-test.nix -vvvv @@ -11,55 +10,56 @@ let # Generate a tree of numbers, n deep, such that the numbers add up to (1 + salt) * 10^n. # The salting makes the numbers all different, increasing the likelihood of catching # any memory corruptions that might be caused by the GC or otherwise. - garbage = salt: n: - if n == 0 - then [(1 + salt)] - else [ - (garbage (10 * salt + 1) (n - 1)) - (garbage (10 * salt - 1) (n - 1)) - (garbage (10 * salt + 2) (n - 1)) - (garbage (10 * salt - 2) (n - 1)) - (garbage (10 * salt + 3) (n - 1)) - (garbage (10 * salt - 3) (n - 1)) - (garbage (10 * salt + 4) (n - 1)) - (garbage (10 * salt - 4) (n - 1)) - (garbage (10 * salt + 5) (n - 1)) - (garbage (10 * salt - 5) (n - 1)) - ]; + garbage = + salt: n: + if n == 0 then + [ (1 + salt) ] + else + [ + (garbage (10 * salt + 1) (n - 1)) + (garbage (10 * salt - 1) (n - 1)) + (garbage (10 * salt + 2) (n - 1)) + (garbage (10 * salt - 2) (n - 1)) + (garbage (10 * salt + 3) (n - 1)) + (garbage (10 * salt - 3) (n - 1)) + (garbage (10 * salt + 4) (n - 1)) + (garbage (10 * salt - 4) (n - 1)) + (garbage (10 * salt + 5) (n - 1)) + (garbage (10 * salt - 5) (n - 1)) + ]; - pow = base: n: - if n == 0 - then 1 - else base * (pow base (n - 1)); + pow = base: n: if n == 0 then 1 else base * (pow base (n - 1)); - sumNestedLists = l: - if isList l - then foldl' (a: b: a + sumNestedLists b) 0 l - else l; + sumNestedLists = l: if isList l then foldl' (a: b: a + sumNestedLists b) 0 l else l; in - assert sumNestedLists (garbage 0 3) == pow 10 3; - assert sumNestedLists (garbage 0 6) == pow 10 6; - builtins.foldl' - (a: b: - assert - "${ - builtins.path { - path = ./src; - filter = path: type: - # We're not doing common subexpression elimination, so this reallocates - # the fairly big tree over and over, producing a lot of garbage during - # source filtering, whose filter runs in a coroutine. - assert sumNestedLists (garbage 0 3) == pow 10 3; - true; - } - }" - == "${./src}"; +assert sumNestedLists (garbage 0 3) == pow 10 3; +assert sumNestedLists (garbage 0 6) == pow 10 6; +builtins.foldl' + ( + a: b: + assert + "${builtins.path { + path = ./src; + filter = + path: type: + # We're not doing common subexpression elimination, so this reallocates + # the fairly big tree over and over, producing a lot of garbage during + # source filtering, whose filter runs in a coroutine. + assert sumNestedLists (garbage 0 3) == pow 10 3; + true; + }}" == "${./src}"; - # These asserts don't seem necessary, as the lambda value get corrupted first - assert a.okay; - assert b.okay; - { okay = true; } - ) + # These asserts don't seem necessary, as the lambda value get corrupted first + assert a.okay; + assert b.okay; + { + okay = true; + } + ) + { okay = true; } + [ { okay = true; } - [ { okay = true; } { okay = true; } { okay = true; } ] + { okay = true; } + { okay = true; } + ] diff --git a/tests/functional/lang/eval-fail-addDrvOutputDependencies-multi-elem-context.nix b/tests/functional/lang/eval-fail-addDrvOutputDependencies-multi-elem-context.nix index dbde264df..a1c3461cf 100644 --- a/tests/functional/lang/eval-fail-addDrvOutputDependencies-multi-elem-context.nix +++ b/tests/functional/lang/eval-fail-addDrvOutputDependencies-multi-elem-context.nix @@ -3,16 +3,23 @@ let name = "fail"; builder = "/bin/false"; system = "x86_64-linux"; - outputs = [ "out" "foo" ]; + outputs = [ + "out" + "foo" + ]; }; drv1 = derivation { name = "fail-2"; builder = "/bin/false"; system = "x86_64-linux"; - outputs = [ "out" "foo" ]; + outputs = [ + "out" + "foo" + ]; }; combo-path = "${drv0.drvPath}${drv1.drvPath}"; -in builtins.addDrvOutputDependencies combo-path +in +builtins.addDrvOutputDependencies combo-path diff --git a/tests/functional/lang/eval-fail-addDrvOutputDependencies-wrong-element-kind.nix b/tests/functional/lang/eval-fail-addDrvOutputDependencies-wrong-element-kind.nix index e379e1d95..6aab61c40 100644 --- a/tests/functional/lang/eval-fail-addDrvOutputDependencies-wrong-element-kind.nix +++ b/tests/functional/lang/eval-fail-addDrvOutputDependencies-wrong-element-kind.nix @@ -3,7 +3,11 @@ let name = "fail"; builder = "/bin/false"; system = "x86_64-linux"; - outputs = [ "out" "foo" ]; + outputs = [ + "out" + "foo" + ]; }; -in builtins.addDrvOutputDependencies drv.outPath +in +builtins.addDrvOutputDependencies drv.outPath diff --git a/tests/functional/lang/eval-fail-addErrorContext-example.nix b/tests/functional/lang/eval-fail-addErrorContext-example.nix index 996b24688..96a9cef84 100644 --- a/tests/functional/lang/eval-fail-addErrorContext-example.nix +++ b/tests/functional/lang/eval-fail-addErrorContext-example.nix @@ -1,9 +1,9 @@ let - countDown = n: - if n == 0 - then throw "kaboom" + countDown = + n: + if n == 0 then + throw "kaboom" else - builtins.addErrorContext - "while counting down; n = ${toString n}" - ("x" + countDown (n - 1)); -in countDown 10 + builtins.addErrorContext "while counting down; n = ${toString n}" ("x" + countDown (n - 1)); +in +countDown 10 diff --git a/tests/functional/lang/eval-fail-assert-equal-attrs-names-2.nix b/tests/functional/lang/eval-fail-assert-equal-attrs-names-2.nix index 8e7ac9cf2..4bce26456 100644 --- a/tests/functional/lang/eval-fail-assert-equal-attrs-names-2.nix +++ b/tests/functional/lang/eval-fail-assert-equal-attrs-names-2.nix @@ -1,2 +1,8 @@ -assert { a = true; } == { a = true; b = true; }; +assert + { + a = true; + } == { + a = true; + b = true; + }; throw "unreachable" diff --git a/tests/functional/lang/eval-fail-assert-equal-attrs-names.nix b/tests/functional/lang/eval-fail-assert-equal-attrs-names.nix index e2f53a85a..f9956999f 100644 --- a/tests/functional/lang/eval-fail-assert-equal-attrs-names.nix +++ b/tests/functional/lang/eval-fail-assert-equal-attrs-names.nix @@ -1,2 +1,8 @@ -assert { a = true; b = true; } == { a = true; }; +assert + { + a = true; + b = true; + } == { + a = true; + }; throw "unreachable" diff --git a/tests/functional/lang/eval-fail-assert-equal-derivations-extra.nix b/tests/functional/lang/eval-fail-assert-equal-derivations-extra.nix index fd8bc3f26..14a782a77 100644 --- a/tests/functional/lang/eval-fail-assert-equal-derivations-extra.nix +++ b/tests/functional/lang/eval-fail-assert-equal-derivations-extra.nix @@ -1,5 +1,14 @@ assert - { foo = { type = "derivation"; outPath = "/nix/store/0"; }; } - == - { foo = { type = "derivation"; outPath = "/nix/store/1"; devious = true; }; }; -throw "unreachable" \ No newline at end of file + { + foo = { + type = "derivation"; + outPath = "/nix/store/0"; + }; + } == { + foo = { + type = "derivation"; + outPath = "/nix/store/1"; + devious = true; + }; + }; +throw "unreachable" diff --git a/tests/functional/lang/eval-fail-assert-equal-derivations.nix b/tests/functional/lang/eval-fail-assert-equal-derivations.nix index c648eae37..0f6748c58 100644 --- a/tests/functional/lang/eval-fail-assert-equal-derivations.nix +++ b/tests/functional/lang/eval-fail-assert-equal-derivations.nix @@ -1,5 +1,15 @@ assert - { foo = { type = "derivation"; outPath = "/nix/store/0"; ignored = abort "not ignored"; }; } - == - { foo = { type = "derivation"; outPath = "/nix/store/1"; ignored = abort "not ignored"; }; }; -throw "unreachable" \ No newline at end of file + { + foo = { + type = "derivation"; + outPath = "/nix/store/0"; + ignored = abort "not ignored"; + }; + } == { + foo = { + type = "derivation"; + outPath = "/nix/store/1"; + ignored = abort "not ignored"; + }; + }; +throw "unreachable" diff --git a/tests/functional/lang/eval-fail-assert-equal-function-direct.nix b/tests/functional/lang/eval-fail-assert-equal-function-direct.nix index 68e5e3908..cd15c4a36 100644 --- a/tests/functional/lang/eval-fail-assert-equal-function-direct.nix +++ b/tests/functional/lang/eval-fail-assert-equal-function-direct.nix @@ -1,7 +1,4 @@ # Note: functions in nested structures, e.g. attributes, may be optimized away by pointer identity optimization. # This only compares a direct comparison and makes no claims about functions in nested structures. -assert - (x: x) - == - (x: x); -abort "unreachable" \ No newline at end of file +assert (x: x) == (x: x); +abort "unreachable" diff --git a/tests/functional/lang/eval-fail-assert-equal-list-length.nix b/tests/functional/lang/eval-fail-assert-equal-list-length.nix index 6d40f4d8e..bd74ccccd 100644 --- a/tests/functional/lang/eval-fail-assert-equal-list-length.nix +++ b/tests/functional/lang/eval-fail-assert-equal-list-length.nix @@ -1,2 +1,6 @@ -assert [ 1 0 ] == [ 10 ]; -throw "unreachable" \ No newline at end of file +assert + [ + 1 + 0 + ] == [ 10 ]; +throw "unreachable" diff --git a/tests/functional/lang/eval-fail-assert-equal-paths.nix b/tests/functional/lang/eval-fail-assert-equal-paths.nix index ef0b67024..647e891b8 100644 --- a/tests/functional/lang/eval-fail-assert-equal-paths.nix +++ b/tests/functional/lang/eval-fail-assert-equal-paths.nix @@ -1,2 +1,2 @@ assert ./foo == ./bar; -throw "unreachable" \ No newline at end of file +throw "unreachable" diff --git a/tests/functional/lang/eval-fail-assert-nested-bool.nix b/tests/functional/lang/eval-fail-assert-nested-bool.nix index 228576983..c75fe0610 100644 --- a/tests/functional/lang/eval-fail-assert-nested-bool.nix +++ b/tests/functional/lang/eval-fail-assert-nested-bool.nix @@ -1,6 +1,3 @@ -assert - { a.b = [ { c.d = true; } ]; } - == - { a.b = [ { c.d = false; } ]; }; +assert { a.b = [ { c.d = true; } ]; } == { a.b = [ { c.d = false; } ]; }; -abort "unreachable" \ No newline at end of file +abort "unreachable" diff --git a/tests/functional/lang/eval-fail-assert.nix b/tests/functional/lang/eval-fail-assert.nix index 3b7a1e8bf..7cb775045 100644 --- a/tests/functional/lang/eval-fail-assert.nix +++ b/tests/functional/lang/eval-fail-assert.nix @@ -1,5 +1,8 @@ let { - x = arg: assert arg == "y"; 123; + x = + arg: + assert arg == "y"; + 123; body = x "x"; -} \ No newline at end of file +} diff --git a/tests/functional/lang/eval-fail-attr-name-type.nix b/tests/functional/lang/eval-fail-attr-name-type.nix index a0e76004a..fb6ccdd41 100644 --- a/tests/functional/lang/eval-fail-attr-name-type.nix +++ b/tests/functional/lang/eval-fail-attr-name-type.nix @@ -1,7 +1,7 @@ let attrs = { - puppy.doggy = {}; + puppy.doggy = { }; }; key = 1; in - attrs.puppy.${key} +attrs.puppy.${key} diff --git a/tests/functional/lang/eval-fail-attrset-merge-drops-later-rec.nix b/tests/functional/lang/eval-fail-attrset-merge-drops-later-rec.nix index fdb314b91..b6b56bf7d 100644 --- a/tests/functional/lang/eval-fail-attrset-merge-drops-later-rec.nix +++ b/tests/functional/lang/eval-fail-attrset-merge-drops-later-rec.nix @@ -1 +1,8 @@ -{ a.b = 1; a = rec { c = d + 2; d = 3; }; }.c +{ + a.b = 1; + a = rec { + c = d + 2; + d = 3; + }; +} +.c diff --git a/tests/functional/lang/eval-fail-bad-string-interpolation-4.nix b/tests/functional/lang/eval-fail-bad-string-interpolation-4.nix index 457b5f06a..e8349bbdf 100644 --- a/tests/functional/lang/eval-fail-bad-string-interpolation-4.nix +++ b/tests/functional/lang/eval-fail-bad-string-interpolation-4.nix @@ -1,6 +1,16 @@ let # Basically a "billion laughs" attack, but toned down to simulated `pkgs`. - ha = x: y: { a = x y; b = x y; c = x y; d = x y; e = x y; f = x y; g = x y; h = x y; j = x y; }; + ha = x: y: { + a = x y; + b = x y; + c = x y; + d = x y; + e = x y; + f = x y; + g = x y; + h = x y; + j = x y; + }; has = ha (ha (ha (ha (x: x)))) "ha"; # A large structure that has already been evaluated. pkgs = builtins.deepSeq has has; diff --git a/tests/functional/lang/eval-fail-dup-dynamic-attrs.nix b/tests/functional/lang/eval-fail-dup-dynamic-attrs.nix index 7ea17f6c8..93cceefa4 100644 --- a/tests/functional/lang/eval-fail-dup-dynamic-attrs.nix +++ b/tests/functional/lang/eval-fail-dup-dynamic-attrs.nix @@ -1,4 +1,8 @@ { - set = { "${"" + "b"}" = 1; }; - set = { "${"b" + ""}" = 2; }; + set = { + "${"" + "b"}" = 1; + }; + set = { + "${"b" + ""}" = 2; + }; } diff --git a/tests/functional/lang/eval-fail-duplicate-traces.nix b/tests/functional/lang/eval-fail-duplicate-traces.nix index 17ce374ec..90526f6d4 100644 --- a/tests/functional/lang/eval-fail-duplicate-traces.nix +++ b/tests/functional/lang/eval-fail-duplicate-traces.nix @@ -1,9 +1,6 @@ # Check that we only omit duplicate stack traces when there's a bunch of them. # Here, there's only a couple duplicate entries, so we output them all. let - throwAfter = n: - if n > 0 - then throwAfter (n - 1) - else throw "Uh oh!"; + throwAfter = n: if n > 0 then throwAfter (n - 1) else throw "Uh oh!"; in - throwAfter 2 +throwAfter 2 diff --git a/tests/functional/lang/eval-fail-fetchurl-baseName-attrs-name.nix b/tests/functional/lang/eval-fail-fetchurl-baseName-attrs-name.nix index 583805539..dcaf7202b 100644 --- a/tests/functional/lang/eval-fail-fetchurl-baseName-attrs-name.nix +++ b/tests/functional/lang/eval-fail-fetchurl-baseName-attrs-name.nix @@ -1 +1,4 @@ -builtins.fetchurl { url = "https://example.com/foo.tar.gz"; name = "~wobble~"; } +builtins.fetchurl { + url = "https://example.com/foo.tar.gz"; + name = "~wobble~"; +} diff --git a/tests/functional/lang/eval-fail-flake-ref-to-string-negative-integer.nix b/tests/functional/lang/eval-fail-flake-ref-to-string-negative-integer.nix index e0208eb25..9cc9ef629 100644 --- a/tests/functional/lang/eval-fail-flake-ref-to-string-negative-integer.nix +++ b/tests/functional/lang/eval-fail-flake-ref-to-string-negative-integer.nix @@ -1,7 +1,12 @@ -let n = -1; in builtins.seq n (builtins.flakeRefToString { - type = "github"; - owner = "NixOS"; - repo = n; - ref = "23.05"; - dir = "lib"; -}) +let + n = -1; +in +builtins.seq n ( + builtins.flakeRefToString { + type = "github"; + owner = "NixOS"; + repo = n; + ref = "23.05"; + dir = "lib"; + } +) diff --git a/tests/functional/lang/eval-fail-foldlStrict-strict-op-application.nix b/tests/functional/lang/eval-fail-foldlStrict-strict-op-application.nix index 1620cc76e..f85486d44 100644 --- a/tests/functional/lang/eval-fail-foldlStrict-strict-op-application.nix +++ b/tests/functional/lang/eval-fail-foldlStrict-strict-op-application.nix @@ -1,5 +1,5 @@ # Tests that the result of applying op is forced even if the value is never used -builtins.foldl' - (_: f: f null) - null - [ (_: throw "Not the final value, but is still forced!") (_: 23) ] +builtins.foldl' (_: f: f null) null [ + (_: throw "Not the final value, but is still forced!") + (_: 23) +] diff --git a/tests/functional/lang/eval-fail-hashfile-missing.nix b/tests/functional/lang/eval-fail-hashfile-missing.nix index ce098b823..0f2872b71 100644 --- a/tests/functional/lang/eval-fail-hashfile-missing.nix +++ b/tests/functional/lang/eval-fail-hashfile-missing.nix @@ -1,5 +1,16 @@ let - paths = [ ./this-file-is-definitely-not-there-7392097 "/and/neither/is/this/37293620" ]; + paths = [ + ./this-file-is-definitely-not-there-7392097 + "/and/neither/is/this/37293620" + ]; in - toString (builtins.concatLists (map (hash: map (builtins.hashFile hash) paths) ["md5" "sha1" "sha256" "sha512"])) - +toString ( + builtins.concatLists ( + map (hash: map (builtins.hashFile hash) paths) [ + "md5" + "sha1" + "sha256" + "sha512" + ] + ) +) diff --git a/tests/functional/lang/eval-fail-list.nix b/tests/functional/lang/eval-fail-list.nix index fa749f2f7..14eb4efa9 100644 --- a/tests/functional/lang/eval-fail-list.nix +++ b/tests/functional/lang/eval-fail-list.nix @@ -1 +1 @@ -8++1 +8 ++ 1 diff --git a/tests/functional/lang/eval-fail-missing-arg.nix b/tests/functional/lang/eval-fail-missing-arg.nix index c4be9797c..9037aa40a 100644 --- a/tests/functional/lang/eval-fail-missing-arg.nix +++ b/tests/functional/lang/eval-fail-missing-arg.nix @@ -1 +1,12 @@ -({x, y, z}: x + y + z) {x = "foo"; z = "bar";} +( + { + x, + y, + z, + }: + x + y + z +) + { + x = "foo"; + z = "bar"; + } diff --git a/tests/functional/lang/eval-fail-mutual-recursion.nix b/tests/functional/lang/eval-fail-mutual-recursion.nix index d090d3158..421e464dd 100644 --- a/tests/functional/lang/eval-fail-mutual-recursion.nix +++ b/tests/functional/lang/eval-fail-mutual-recursion.nix @@ -19,18 +19,22 @@ # - a few frames of A (skip the rest) # - a few frames of B (skip the rest, _and_ skip the remaining frames of A) let - throwAfterB = recurse: n: - if n > 0 - then throwAfterB recurse (n - 1) - else if recurse - then throwAfterA false 10 - else throw "Uh oh!"; + throwAfterB = + recurse: n: + if n > 0 then + throwAfterB recurse (n - 1) + else if recurse then + throwAfterA false 10 + else + throw "Uh oh!"; - throwAfterA = recurse: n: - if n > 0 - then throwAfterA recurse (n - 1) - else if recurse - then throwAfterB true 10 - else throw "Uh oh!"; + throwAfterA = + recurse: n: + if n > 0 then + throwAfterA recurse (n - 1) + else if recurse then + throwAfterB true 10 + else + throw "Uh oh!"; in - throwAfterA true 10 +throwAfterA true 10 diff --git a/tests/functional/lang/eval-fail-nested-list-items.nix b/tests/functional/lang/eval-fail-nested-list-items.nix index af45b1dd4..d0aa1b5d3 100644 --- a/tests/functional/lang/eval-fail-nested-list-items.nix +++ b/tests/functional/lang/eval-fail-nested-list-items.nix @@ -8,4 +8,27 @@ # # error: cannot coerce a list to a string: [ [ 1 2 3 4 5 6 7 8 ] [ 1 «4294967290 items elided» ] ] -"" + (let v = [ [ 1 2 3 4 5 6 7 8 ] [1 2 3 4]]; in builtins.deepSeq v v) +"" ++ ( + let + v = [ + [ + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + ] + [ + 1 + 2 + 3 + 4 + ] + ]; + in + builtins.deepSeq v v +) diff --git a/tests/functional/lang/eval-fail-not-throws.nix b/tests/functional/lang/eval-fail-not-throws.nix index a74ce4ebe..2e024738b 100644 --- a/tests/functional/lang/eval-fail-not-throws.nix +++ b/tests/functional/lang/eval-fail-not-throws.nix @@ -1 +1 @@ -! (throw "uh oh!") +!(throw "uh oh!") diff --git a/tests/functional/lang/eval-fail-overflowing-add.nix b/tests/functional/lang/eval-fail-overflowing-add.nix index 24258fc20..9e1e8aa75 100644 --- a/tests/functional/lang/eval-fail-overflowing-add.nix +++ b/tests/functional/lang/eval-fail-overflowing-add.nix @@ -1,4 +1,5 @@ let a = 9223372036854775807; b = 1; -in a + b +in +a + b diff --git a/tests/functional/lang/eval-fail-overflowing-div.nix b/tests/functional/lang/eval-fail-overflowing-div.nix index 44fbe9d7e..e21b0b2e5 100644 --- a/tests/functional/lang/eval-fail-overflowing-div.nix +++ b/tests/functional/lang/eval-fail-overflowing-div.nix @@ -4,4 +4,5 @@ let # of range intMin = -9223372036854775807 - 1; b = -1; -in builtins.seq intMin (builtins.seq b (intMin / b)) +in +builtins.seq intMin (builtins.seq b (intMin / b)) diff --git a/tests/functional/lang/eval-fail-overflowing-mul.nix b/tests/functional/lang/eval-fail-overflowing-mul.nix index 6081d9c7b..95b1375bb 100644 --- a/tests/functional/lang/eval-fail-overflowing-mul.nix +++ b/tests/functional/lang/eval-fail-overflowing-mul.nix @@ -1,3 +1,4 @@ let a = 4294967297; -in a * a * a +in +a * a * a diff --git a/tests/functional/lang/eval-fail-overflowing-sub.nix b/tests/functional/lang/eval-fail-overflowing-sub.nix index 229b8c6d2..4f0203a6d 100644 --- a/tests/functional/lang/eval-fail-overflowing-sub.nix +++ b/tests/functional/lang/eval-fail-overflowing-sub.nix @@ -1,4 +1,5 @@ let a = -9223372036854775807; b = 2; -in a - b +in +a - b diff --git a/tests/functional/lang/eval-fail-recursion.nix b/tests/functional/lang/eval-fail-recursion.nix index 075b5ed06..88718a6e5 100644 --- a/tests/functional/lang/eval-fail-recursion.nix +++ b/tests/functional/lang/eval-fail-recursion.nix @@ -1 +1,4 @@ -let a = {} // a; in a.foo +let + a = { } // a; +in +a.foo diff --git a/tests/functional/lang/eval-fail-remove.nix b/tests/functional/lang/eval-fail-remove.nix index 539e0eb0a..9de066abe 100644 --- a/tests/functional/lang/eval-fail-remove.nix +++ b/tests/functional/lang/eval-fail-remove.nix @@ -1,5 +1,8 @@ let { - attrs = {x = 123; y = 456;}; + attrs = { + x = 123; + y = 456; + }; - body = (removeAttrs attrs ["x"]).x; -} \ No newline at end of file + body = (removeAttrs attrs [ "x" ]).x; +} diff --git a/tests/functional/lang/eval-fail-scope-5.nix b/tests/functional/lang/eval-fail-scope-5.nix index f89a65a99..ef6f1bb64 100644 --- a/tests/functional/lang/eval-fail-scope-5.nix +++ b/tests/functional/lang/eval-fail-scope-5.nix @@ -3,8 +3,13 @@ let { x = "a"; y = "b"; - f = {x ? y, y ? x}: x + y; + f = + { + x ? y, + y ? x, + }: + x + y; - body = f {}; + body = f { }; } diff --git a/tests/functional/lang/eval-fail-undeclared-arg.nix b/tests/functional/lang/eval-fail-undeclared-arg.nix index cafdf1636..aca4511bb 100644 --- a/tests/functional/lang/eval-fail-undeclared-arg.nix +++ b/tests/functional/lang/eval-fail-undeclared-arg.nix @@ -1 +1,5 @@ -({x, z}: x + z) {x = "foo"; y = "bla"; z = "bar";} +({ x, z }: x + z) { + x = "foo"; + y = "bla"; + z = "bar"; +} diff --git a/tests/functional/lang/eval-fail-using-set-as-attr-name.nix b/tests/functional/lang/eval-fail-using-set-as-attr-name.nix index 48e071a41..96390e35f 100644 --- a/tests/functional/lang/eval-fail-using-set-as-attr-name.nix +++ b/tests/functional/lang/eval-fail-using-set-as-attr-name.nix @@ -1,5 +1,7 @@ let - attr = {foo = "bar";}; - key = {}; + attr = { + foo = "bar"; + }; + key = { }; in - attr.${key} +attr.${key} diff --git a/tests/functional/lang/eval-okay-any-all.nix b/tests/functional/lang/eval-okay-any-all.nix index a3f26ea2a..643d36cb7 100644 --- a/tests/functional/lang/eval-okay-any-all.nix +++ b/tests/functional/lang/eval-okay-any-all.nix @@ -1,11 +1,34 @@ with builtins; -[ (any (x: x == 1) []) - (any (x: x == 1) [2 3 4]) - (any (x: x == 1) [1 2 3 4]) - (any (x: x == 1) [4 3 2 1]) - (all (x: x == 1) []) - (all (x: x == 1) [1]) - (all (x: x == 1) [1 2 3]) - (all (x: x == 1) [1 1 1]) +[ + (any (x: x == 1) [ ]) + (any (x: x == 1) [ + 2 + 3 + 4 + ]) + (any (x: x == 1) [ + 1 + 2 + 3 + 4 + ]) + (any (x: x == 1) [ + 4 + 3 + 2 + 1 + ]) + (all (x: x == 1) [ ]) + (all (x: x == 1) [ 1 ]) + (all (x: x == 1) [ + 1 + 2 + 3 + ]) + (all (x: x == 1) [ + 1 + 1 + 1 + ]) ] diff --git a/tests/functional/lang/eval-okay-arithmetic.nix b/tests/functional/lang/eval-okay-arithmetic.nix index 7e9e6a0b6..8160b4d84 100644 --- a/tests/functional/lang/eval-okay-arithmetic.nix +++ b/tests/functional/lang/eval-okay-arithmetic.nix @@ -2,58 +2,59 @@ with import ./lib.nix; let { - /* Supposedly tail recursive version: + /* + Supposedly tail recursive version: - range_ = accum: first: last: - if first == last then ([first] ++ accum) - else range_ ([first] ++ accum) (builtins.add first 1) last; + range_ = accum: first: last: + if first == last then ([first] ++ accum) + else range_ ([first] ++ accum) (builtins.add first 1) last; - range = range_ []; + range = range_ []; */ x = 12; err = abort "urgh"; - body = sum - [ (sum (range 1 50)) - (123 + 456) - (0 + -10 + -(-11) + -x) - (10 - 7 - -2) - (10 - (6 - -1)) - (10 - 1 + 2) - (3 * 4 * 5) - (56088 / 123 / 2) - (3 + 4 * const 5 0 - 6 / id 2) + body = sum [ + (sum (range 1 50)) + (123 + 456) + (0 + -10 + -(-11) + -x) + (10 - 7 - -2) + (10 - (6 - -1)) + (10 - 1 + 2) + (3 * 4 * 5) + (56088 / 123 / 2) + (3 + 4 * const 5 0 - 6 / id 2) - (builtins.bitAnd 12 10) # 0b1100 & 0b1010 = 8 - (builtins.bitOr 12 10) # 0b1100 | 0b1010 = 14 - (builtins.bitXor 12 10) # 0b1100 ^ 0b1010 = 6 + (builtins.bitAnd 12 10) # 0b1100 & 0b1010 = 8 + (builtins.bitOr 12 10) # 0b1100 | 0b1010 = 14 + (builtins.bitXor 12 10) # 0b1100 ^ 0b1010 = 6 - (if 3 < 7 then 1 else err) - (if 7 < 3 then err else 1) - (if 3 < 3 then err else 1) + (if 3 < 7 then 1 else err) + (if 7 < 3 then err else 1) + (if 3 < 3 then err else 1) - (if 3 <= 7 then 1 else err) - (if 7 <= 3 then err else 1) - (if 3 <= 3 then 1 else err) + (if 3 <= 7 then 1 else err) + (if 7 <= 3 then err else 1) + (if 3 <= 3 then 1 else err) - (if 3 > 7 then err else 1) - (if 7 > 3 then 1 else err) - (if 3 > 3 then err else 1) + (if 3 > 7 then err else 1) + (if 7 > 3 then 1 else err) + (if 3 > 3 then err else 1) - (if 3 >= 7 then err else 1) - (if 7 >= 3 then 1 else err) - (if 3 >= 3 then 1 else err) + (if 3 >= 7 then err else 1) + (if 7 >= 3 then 1 else err) + (if 3 >= 3 then 1 else err) - (if 2 > 1 == 1 < 2 then 1 else err) - (if 1 + 2 * 3 >= 7 then 1 else err) - (if 1 + 2 * 3 < 7 then err else 1) + (if 2 > 1 == 1 < 2 then 1 else err) + (if 1 + 2 * 3 >= 7 then 1 else err) + (if 1 + 2 * 3 < 7 then err else 1) - # Not integer, but so what. - (if "aa" < "ab" then 1 else err) - (if "aa" < "aa" then err else 1) - (if "foo" < "foobar" then 1 else err) - ]; + # Not integer, but so what. + (if "aa" < "ab" then 1 else err) + (if "aa" < "aa" then err else 1) + (if "foo" < "foobar" then 1 else err) + ]; } diff --git a/tests/functional/lang/eval-okay-attrnames.nix b/tests/functional/lang/eval-okay-attrnames.nix index e5b26e9f2..085e78084 100644 --- a/tests/functional/lang/eval-okay-attrnames.nix +++ b/tests/functional/lang/eval-okay-attrnames.nix @@ -2,10 +2,21 @@ with import ./lib.nix; let - attrs = {y = "y"; x = "x"; foo = "foo";} // rec {x = "newx"; bar = x;}; + attrs = + { + y = "y"; + x = "x"; + foo = "foo"; + } + // rec { + x = "newx"; + bar = x; + }; names = builtins.attrNames attrs; values = map (name: builtins.getAttr name attrs) names; -in assert values == builtins.attrValues attrs; concat values +in +assert values == builtins.attrValues attrs; +concat values diff --git a/tests/functional/lang/eval-okay-attrs.nix b/tests/functional/lang/eval-okay-attrs.nix index 810b31a5d..787b9a933 100644 --- a/tests/functional/lang/eval-okay-attrs.nix +++ b/tests/functional/lang/eval-okay-attrs.nix @@ -1,5 +1,20 @@ let { - as = { x = 123; y = 456; } // { z = 789; } // { z = 987; }; + as = + { + x = 123; + y = 456; + } + // { + z = 789; + } + // { + z = 987; + }; - body = if as ? a then as.a else assert as ? z; as.z; + body = + if as ? a then + as.a + else + assert as ? z; + as.z; } diff --git a/tests/functional/lang/eval-okay-attrs2.nix b/tests/functional/lang/eval-okay-attrs2.nix index 9e06b83ac..0896f9cf1 100644 --- a/tests/functional/lang/eval-okay-attrs2.nix +++ b/tests/functional/lang/eval-okay-attrs2.nix @@ -1,10 +1,23 @@ let { - as = { x = 123; y = 456; } // { z = 789; } // { z = 987; }; + as = + { + x = 123; + y = 456; + } + // { + z = 789; + } + // { + z = 987; + }; A = "a"; Z = "z"; - body = if builtins.hasAttr A as - then builtins.getAttr A as - else assert builtins.hasAttr Z as; builtins.getAttr Z as; + body = + if builtins.hasAttr A as then + builtins.getAttr A as + else + assert builtins.hasAttr Z as; + builtins.getAttr Z as; } diff --git a/tests/functional/lang/eval-okay-attrs3.nix b/tests/functional/lang/eval-okay-attrs3.nix index f29de11fe..cab345337 100644 --- a/tests/functional/lang/eval-okay-attrs3.nix +++ b/tests/functional/lang/eval-okay-attrs3.nix @@ -1,22 +1,22 @@ let - config = - { - services.sshd.enable = true; - services.sshd.port = 22; - services.httpd.port = 80; - hostName = "itchy"; - a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z = "x"; - foo = { - a = "a"; - b.c = "c"; - }; + config = { + services.sshd.enable = true; + services.sshd.port = 22; + services.httpd.port = 80; + hostName = "itchy"; + a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z = "x"; + foo = { + a = "a"; + b.c = "c"; }; + }; in - if config.services.sshd.enable - then "foo ${toString config.services.sshd.port} ${toString config.services.httpd.port} ${config.hostName}" - + "${config.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z}" - + "${config.foo.a}" - + "${config.foo.b.c}" - else "bar" +if config.services.sshd.enable then + "foo ${toString config.services.sshd.port} ${toString config.services.httpd.port} ${config.hostName}" + + "${config.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z}" + + "${config.foo.a}" + + "${config.foo.b.c}" +else + "bar" diff --git a/tests/functional/lang/eval-okay-attrs4.nix b/tests/functional/lang/eval-okay-attrs4.nix index 43ec81210..3e43e4bae 100644 --- a/tests/functional/lang/eval-okay-attrs4.nix +++ b/tests/functional/lang/eval-okay-attrs4.nix @@ -1,7 +1,20 @@ let - as = { x.y.z = 123; a.b.c = 456; }; + as = { + x.y.z = 123; + a.b.c = 456; + }; bs = null; -in [ (as ? x) (as ? y) (as ? x.y.z) (as ? x.y.z.a) (as ? x.y.a) (as ? a.b.c) (bs ? x) (bs ? x.y.z) ] +in +[ + (as ? x) + (as ? y) + (as ? x.y.z) + (as ? x.y.z.a) + (as ? x.y.a) + (as ? a.b.c) + (bs ? x) + (bs ? x.y.z) +] diff --git a/tests/functional/lang/eval-okay-attrs6.nix b/tests/functional/lang/eval-okay-attrs6.nix index 2e5c85483..76c94af78 100644 --- a/tests/functional/lang/eval-okay-attrs6.nix +++ b/tests/functional/lang/eval-okay-attrs6.nix @@ -1,4 +1,6 @@ rec { "${"foo"}" = "bar"; - __overrides = { bar = "qux"; }; + __overrides = { + bar = "qux"; + }; } diff --git a/tests/functional/lang/eval-okay-autoargs.nix b/tests/functional/lang/eval-okay-autoargs.nix index 815f51b1d..bc82c569b 100644 --- a/tests/functional/lang/eval-okay-autoargs.nix +++ b/tests/functional/lang/eval-okay-autoargs.nix @@ -4,12 +4,17 @@ let in -{ xyzzy2 ? xyzzy # mutually recursive args -, xyzzy ? "blaat" # will be overridden by --argstr -, fb ? foobar -, lib # will be set by --arg +{ + xyzzy2 ? xyzzy, # mutually recursive args + xyzzy ? "blaat", # will be overridden by --argstr + fb ? foobar, + lib, # will be set by --arg }: { - result = lib.concat [xyzzy xyzzy2 fb]; + result = lib.concat [ + xyzzy + xyzzy2 + fb + ]; } diff --git a/tests/functional/lang/eval-okay-builtins-add.nix b/tests/functional/lang/eval-okay-builtins-add.nix index c84181622..f678f640f 100644 --- a/tests/functional/lang/eval-okay-builtins-add.nix +++ b/tests/functional/lang/eval-okay-builtins-add.nix @@ -1,8 +1,8 @@ [ -(builtins.add 2 3) -(builtins.add 2 2) -(builtins.typeOf (builtins.add 2 2)) -("t" + "t") -(builtins.typeOf (builtins.add 2.0 2)) -(builtins.add 2.0 2) + (builtins.add 2 3) + (builtins.add 2 2) + (builtins.typeOf (builtins.add 2 2)) + ("t" + "t") + (builtins.typeOf (builtins.add 2.0 2)) + (builtins.add 2.0 2) ] diff --git a/tests/functional/lang/eval-okay-builtins.nix b/tests/functional/lang/eval-okay-builtins.nix index e9d65e88a..be4114116 100644 --- a/tests/functional/lang/eval-okay-builtins.nix +++ b/tests/functional/lang/eval-okay-builtins.nix @@ -8,5 +8,5 @@ let { y = if builtins ? fnord then builtins.fnord "foo" else ""; body = x + y; - + } diff --git a/tests/functional/lang/eval-okay-callable-attrs.nix b/tests/functional/lang/eval-okay-callable-attrs.nix index 310a030df..a4c1ace36 100644 --- a/tests/functional/lang/eval-okay-callable-attrs.nix +++ b/tests/functional/lang/eval-okay-callable-attrs.nix @@ -1 +1,10 @@ -({ __functor = self: x: self.foo && x; foo = false; } // { foo = true; }) true +( + { + __functor = self: x: self.foo && x; + foo = false; + } + // { + foo = true; + } +) + true diff --git a/tests/functional/lang/eval-okay-catattrs.nix b/tests/functional/lang/eval-okay-catattrs.nix index 2c3dc10da..7ec4ba7ae 100644 --- a/tests/functional/lang/eval-okay-catattrs.nix +++ b/tests/functional/lang/eval-okay-catattrs.nix @@ -1 +1,5 @@ -builtins.catAttrs "a" [ { a = 1; } { b = 0; } { a = 2; } ] +builtins.catAttrs "a" [ + { a = 1; } + { b = 0; } + { a = 2; } +] diff --git a/tests/functional/lang/eval-okay-closure.nix b/tests/functional/lang/eval-okay-closure.nix index cccd4dc35..67c53d089 100644 --- a/tests/functional/lang/eval-okay-closure.nix +++ b/tests/functional/lang/eval-okay-closure.nix @@ -1,13 +1,25 @@ let closure = builtins.genericClosure { - startSet = [{key = 80;}]; - operator = {key, foo ? false}: - if builtins.lessThan key 0 - then [] - else [{key = builtins.sub key 9;} {key = builtins.sub key 13; foo = true;}]; + startSet = [ { key = 80; } ]; + operator = + { + key, + foo ? false, + }: + if builtins.lessThan key 0 then + [ ] + else + [ + { key = builtins.sub key 9; } + { + key = builtins.sub key 13; + foo = true; + } + ]; }; sort = (import ./lib.nix).sortBy (a: b: builtins.lessThan a.key b.key); -in sort closure +in +sort closure diff --git a/tests/functional/lang/eval-okay-concat.nix b/tests/functional/lang/eval-okay-concat.nix index d158a9bf0..ce754ca00 100644 --- a/tests/functional/lang/eval-okay-concat.nix +++ b/tests/functional/lang/eval-okay-concat.nix @@ -1 +1,15 @@ -[1 2 3] ++ [4 5 6] ++ [7 8 9] +[ + 1 + 2 + 3 +] +++ [ + 4 + 5 + 6 +] +++ [ + 7 + 8 + 9 +] diff --git a/tests/functional/lang/eval-okay-concatmap.nix b/tests/functional/lang/eval-okay-concatmap.nix index 97da5d37a..14b546131 100644 --- a/tests/functional/lang/eval-okay-concatmap.nix +++ b/tests/functional/lang/eval-okay-concatmap.nix @@ -1,5 +1,9 @@ with import ./lib.nix; -[ (builtins.concatMap (x: if x / 2 * 2 == x then [] else [ x ]) (range 0 10)) - (builtins.concatMap (x: [x] ++ ["z"]) ["a" "b"]) +[ + (builtins.concatMap (x: if x / 2 * 2 == x then [ ] else [ x ]) (range 0 10)) + (builtins.concatMap (x: [ x ] ++ [ "z" ]) [ + "a" + "b" + ]) ] diff --git a/tests/functional/lang/eval-okay-concatstringssep.nix b/tests/functional/lang/eval-okay-concatstringssep.nix index adc4c41bd..2270d11b4 100644 --- a/tests/functional/lang/eval-okay-concatstringssep.nix +++ b/tests/functional/lang/eval-okay-concatstringssep.nix @@ -1,8 +1,17 @@ with builtins; -[ (concatStringsSep "" []) - (concatStringsSep "" ["foo" "bar" "xyzzy"]) - (concatStringsSep ", " ["foo" "bar" "xyzzy"]) - (concatStringsSep ", " ["foo"]) - (concatStringsSep ", " []) +[ + (concatStringsSep "" [ ]) + (concatStringsSep "" [ + "foo" + "bar" + "xyzzy" + ]) + (concatStringsSep ", " [ + "foo" + "bar" + "xyzzy" + ]) + (concatStringsSep ", " [ "foo" ]) + (concatStringsSep ", " [ ]) ] diff --git a/tests/functional/lang/eval-okay-context-introspection.nix b/tests/functional/lang/eval-okay-context-introspection.nix index 8886cf32e..5ed994719 100644 --- a/tests/functional/lang/eval-okay-context-introspection.nix +++ b/tests/functional/lang/eval-okay-context-introspection.nix @@ -3,7 +3,10 @@ let name = "fail"; builder = "/bin/false"; system = "x86_64-linux"; - outputs = [ "out" "foo" ]; + outputs = [ + "out" + "foo" + ]; }; path = "${./eval-okay-context-introspection.nix}"; @@ -13,7 +16,10 @@ let path = true; }; "${builtins.unsafeDiscardStringContext drv.drvPath}" = { - outputs = [ "foo" "out" ]; + outputs = [ + "foo" + "out" + ]; allOutputs = true; }; }; @@ -21,25 +27,22 @@ let combo-path = "${path}${drv.outPath}${drv.foo.outPath}${drv.drvPath}"; legit-context = builtins.getContext combo-path; - reconstructed-path = builtins.appendContext - (builtins.unsafeDiscardStringContext combo-path) - desired-context; + reconstructed-path = builtins.appendContext (builtins.unsafeDiscardStringContext combo-path) desired-context; # Eta rule for strings with context. - etaRule = str: - str == builtins.appendContext - (builtins.unsafeDiscardStringContext str) - (builtins.getContext str); + etaRule = + str: + str == builtins.appendContext (builtins.unsafeDiscardStringContext str) (builtins.getContext str); # Only holds true if string context contains both a `DrvDeep` and # `Opaque` element. - almostEtaRule = str: - str == builtins.addDrvOutputDependencies - (builtins.unsafeDiscardOutputDependency str); + almostEtaRule = + str: str == builtins.addDrvOutputDependencies (builtins.unsafeDiscardOutputDependency str); - addDrvOutputDependencies_idempotent = str: - builtins.addDrvOutputDependencies str == - builtins.addDrvOutputDependencies (builtins.addDrvOutputDependencies str); + addDrvOutputDependencies_idempotent = + str: + builtins.addDrvOutputDependencies str + == builtins.addDrvOutputDependencies (builtins.addDrvOutputDependencies str); rules = str: [ (etaRule str) @@ -47,12 +50,14 @@ let (addDrvOutputDependencies_idempotent str) ]; -in [ +in +[ (legit-context == desired-context) (reconstructed-path == combo-path) (etaRule "foo") (etaRule drv.foo.outPath) -] ++ builtins.concatMap rules [ +] +++ builtins.concatMap rules [ drv.drvPath (builtins.addDrvOutputDependencies drv.drvPath) (builtins.unsafeDiscardOutputDependency drv.drvPath) diff --git a/tests/functional/lang/eval-okay-context.nix b/tests/functional/lang/eval-okay-context.nix index 7b9531cfe..102bc2259 100644 --- a/tests/functional/lang/eval-okay-context.nix +++ b/tests/functional/lang/eval-okay-context.nix @@ -1,6 +1,7 @@ -let s = "foo ${builtins.substring 33 100 (baseNameOf "${./eval-okay-context.nix}")} bar"; +let + s = "foo ${builtins.substring 33 100 (baseNameOf "${./eval-okay-context.nix}")} bar"; in - if s != "foo eval-okay-context.nix bar" - then abort "context not discarded" - else builtins.unsafeDiscardStringContext s - +if s != "foo eval-okay-context.nix bar" then + abort "context not discarded" +else + builtins.unsafeDiscardStringContext s diff --git a/tests/functional/lang/eval-okay-convertHash.nix b/tests/functional/lang/eval-okay-convertHash.nix index a0191ee8d..6d5074fea 100644 --- a/tests/functional/lang/eval-okay-convertHash.nix +++ b/tests/functional/lang/eval-okay-convertHash.nix @@ -1,33 +1,131 @@ let - hashAlgos = [ "md5" "md5" "md5" "sha1" "sha1" "sha1" "sha256" "sha256" "sha256" "sha512" "sha512" "sha512" ]; + hashAlgos = [ + "md5" + "md5" + "md5" + "sha1" + "sha1" + "sha1" + "sha256" + "sha256" + "sha256" + "sha512" + "sha512" + "sha512" + ]; hashesBase16 = import ./eval-okay-hashstring.exp; - map2 = f: { fsts, snds }: if fsts == [ ] then [ ] else [ (f (builtins.head fsts) (builtins.head snds)) ] ++ map2 f { fsts = builtins.tail fsts; snds = builtins.tail snds; }; - map2' = f: fsts: snds: map2 f { inherit fsts snds; }; + map2 = + f: + { fsts, snds }: + if fsts == [ ] then + [ ] + else + [ (f (builtins.head fsts) (builtins.head snds)) ] + ++ map2 f { + fsts = builtins.tail fsts; + snds = builtins.tail snds; + }; + map2' = + f: fsts: snds: + map2 f { inherit fsts snds; }; getOutputHashes = hashes: { - hashesBase16 = map2' (hashAlgo: hash: builtins.convertHash { inherit hash hashAlgo; toHashFormat = "base16";}) hashAlgos hashes; - hashesNix32 = map2' (hashAlgo: hash: builtins.convertHash { inherit hash hashAlgo; toHashFormat = "nix32";}) hashAlgos hashes; - hashesBase32 = map2' (hashAlgo: hash: builtins.convertHash { inherit hash hashAlgo; toHashFormat = "base32";}) hashAlgos hashes; - hashesBase64 = map2' (hashAlgo: hash: builtins.convertHash { inherit hash hashAlgo; toHashFormat = "base64";}) hashAlgos hashes; - hashesSRI = map2' (hashAlgo: hash: builtins.convertHash { inherit hash hashAlgo; toHashFormat = "sri" ;}) hashAlgos hashes; + hashesBase16 = map2' ( + hashAlgo: hash: + builtins.convertHash { + inherit hash hashAlgo; + toHashFormat = "base16"; + } + ) hashAlgos hashes; + hashesNix32 = map2' ( + hashAlgo: hash: + builtins.convertHash { + inherit hash hashAlgo; + toHashFormat = "nix32"; + } + ) hashAlgos hashes; + hashesBase32 = map2' ( + hashAlgo: hash: + builtins.convertHash { + inherit hash hashAlgo; + toHashFormat = "base32"; + } + ) hashAlgos hashes; + hashesBase64 = map2' ( + hashAlgo: hash: + builtins.convertHash { + inherit hash hashAlgo; + toHashFormat = "base64"; + } + ) hashAlgos hashes; + hashesSRI = map2' ( + hashAlgo: hash: + builtins.convertHash { + inherit hash hashAlgo; + toHashFormat = "sri"; + } + ) hashAlgos hashes; }; getOutputHashesColon = hashes: { - hashesBase16 = map2' (hashAlgo: hashBody: builtins.convertHash { hash = hashAlgo + ":" + hashBody; toHashFormat = "base16";}) hashAlgos hashes; - hashesNix32 = map2' (hashAlgo: hashBody: builtins.convertHash { hash = hashAlgo + ":" + hashBody; toHashFormat = "nix32";}) hashAlgos hashes; - hashesBase32 = map2' (hashAlgo: hashBody: builtins.convertHash { hash = hashAlgo + ":" + hashBody; toHashFormat = "base32";}) hashAlgos hashes; - hashesBase64 = map2' (hashAlgo: hashBody: builtins.convertHash { hash = hashAlgo + ":" + hashBody; toHashFormat = "base64";}) hashAlgos hashes; - hashesSRI = map2' (hashAlgo: hashBody: builtins.convertHash { hash = hashAlgo + ":" + hashBody; toHashFormat = "sri" ;}) hashAlgos hashes; + hashesBase16 = map2' ( + hashAlgo: hashBody: + builtins.convertHash { + hash = hashAlgo + ":" + hashBody; + toHashFormat = "base16"; + } + ) hashAlgos hashes; + hashesNix32 = map2' ( + hashAlgo: hashBody: + builtins.convertHash { + hash = hashAlgo + ":" + hashBody; + toHashFormat = "nix32"; + } + ) hashAlgos hashes; + hashesBase32 = map2' ( + hashAlgo: hashBody: + builtins.convertHash { + hash = hashAlgo + ":" + hashBody; + toHashFormat = "base32"; + } + ) hashAlgos hashes; + hashesBase64 = map2' ( + hashAlgo: hashBody: + builtins.convertHash { + hash = hashAlgo + ":" + hashBody; + toHashFormat = "base64"; + } + ) hashAlgos hashes; + hashesSRI = map2' ( + hashAlgo: hashBody: + builtins.convertHash { + hash = hashAlgo + ":" + hashBody; + toHashFormat = "sri"; + } + ) hashAlgos hashes; }; outputHashes = getOutputHashes hashesBase16; in # map2'` -assert map2' (s1: s2: s1 + s2) [ "a" "b" ] [ "c" "d" ] == [ "ac" "bd" ]; +assert + map2' (s1: s2: s1 + s2) [ "a" "b" ] [ "c" "d" ] == [ + "ac" + "bd" + ]; # hashesBase16 assert outputHashes.hashesBase16 == hashesBase16; # standard SRI hashes -assert outputHashes.hashesSRI == (map2' (hashAlgo: hashBody: hashAlgo + "-" + hashBody) hashAlgos outputHashes.hashesBase64); +assert + outputHashes.hashesSRI + == (map2' (hashAlgo: hashBody: hashAlgo + "-" + hashBody) hashAlgos outputHashes.hashesBase64); # without prefix assert builtins.all (x: getOutputHashes x == outputHashes) (builtins.attrValues outputHashes); # colon-separated. # Note that colon prefix must not be applied to the standard SRI. e.g. "sha256:sha256-..." is illegal. -assert builtins.all (x: getOutputHashesColon x == outputHashes) (with outputHashes; [ hashesBase16 hashesBase32 hashesBase64 ]); +assert builtins.all (x: getOutputHashesColon x == outputHashes) ( + with outputHashes; + [ + hashesBase16 + hashesBase32 + hashesBase64 + ] +); outputHashes diff --git a/tests/functional/lang/eval-okay-deepseq.nix b/tests/functional/lang/eval-okay-deepseq.nix index 53aa4b1dc..f9aa5f720 100644 --- a/tests/functional/lang/eval-okay-deepseq.nix +++ b/tests/functional/lang/eval-okay-deepseq.nix @@ -1 +1,9 @@ -builtins.deepSeq (let as = { x = 123; y = as; }; in as) 456 +builtins.deepSeq ( + let + as = { + x = 123; + y = as; + }; + in + as +) 456 diff --git a/tests/functional/lang/eval-okay-delayed-with-inherit.nix b/tests/functional/lang/eval-okay-delayed-with-inherit.nix index 84b388c27..10ce7df13 100644 --- a/tests/functional/lang/eval-okay-delayed-with-inherit.nix +++ b/tests/functional/lang/eval-okay-delayed-with-inherit.nix @@ -4,7 +4,10 @@ let name = "a"; system = builtins.currentSystem; builder = "/bin/sh"; - args = [ "-c" "touch $out" ]; + args = [ + "-c" + "touch $out" + ]; inherit b; }; @@ -16,9 +19,13 @@ let name = "b-overridden"; system = builtins.currentSystem; builder = "/bin/sh"; - args = [ "-c" "touch $out" ]; + args = [ + "-c" + "touch $out" + ]; }; }; pkgs = pkgs_ // (packageOverrides pkgs_); -in pkgs.a.b.name +in +pkgs.a.b.name diff --git a/tests/functional/lang/eval-okay-delayed-with.nix b/tests/functional/lang/eval-okay-delayed-with.nix index 3fb023e1c..52ec24e12 100644 --- a/tests/functional/lang/eval-okay-delayed-with.nix +++ b/tests/functional/lang/eval-okay-delayed-with.nix @@ -5,7 +5,10 @@ let name = "a"; system = builtins.currentSystem; builder = "/bin/sh"; - args = [ "-c" "touch $out" ]; + args = [ + "-c" + "touch $out" + ]; inherit b; }; @@ -13,17 +16,22 @@ let name = "b"; system = builtins.currentSystem; builder = "/bin/sh"; - args = [ "-c" "touch $out" ]; + args = [ + "-c" + "touch $out" + ]; inherit a; }; c = b; }; - packageOverrides = pkgs: with pkgs; { - b = derivation (b.drvAttrs // { name = "${b.name}-overridden"; }); - }; + packageOverrides = + pkgs: with pkgs; { + b = derivation (b.drvAttrs // { name = "${b.name}-overridden"; }); + }; pkgs = pkgs_ // (packageOverrides pkgs_); -in "${pkgs.a.b.name} ${pkgs.c.name} ${pkgs.b.a.name}" +in +"${pkgs.a.b.name} ${pkgs.c.name} ${pkgs.b.a.name}" diff --git a/tests/functional/lang/eval-okay-dynamic-attrs-2.nix b/tests/functional/lang/eval-okay-dynamic-attrs-2.nix index 6d57bf854..95fe79e25 100644 --- a/tests/functional/lang/eval-okay-dynamic-attrs-2.nix +++ b/tests/functional/lang/eval-okay-dynamic-attrs-2.nix @@ -1 +1,5 @@ -{ a."${"b"}" = true; a."${"c"}" = false; }.a.b +{ + a."${"b"}" = true; + a."${"c"}" = false; +} +.a.b diff --git a/tests/functional/lang/eval-okay-dynamic-attrs-bare.nix b/tests/functional/lang/eval-okay-dynamic-attrs-bare.nix index 0dbe15e63..a612bf69d 100644 --- a/tests/functional/lang/eval-okay-dynamic-attrs-bare.nix +++ b/tests/functional/lang/eval-okay-dynamic-attrs-bare.nix @@ -2,7 +2,8 @@ let aString = "a"; bString = "b"; -in { +in +{ hasAttrs = { a.b = null; } ? ${aString}.b; selectAttrs = { a.b = true; }.a.${bString}; @@ -11,7 +12,17 @@ in { binds = { ${aString}."${bString}c" = true; }.a.bc; - recBinds = rec { ${bString} = a; a = true; }.b; + recBinds = + rec { + ${bString} = a; + a = true; + } + .b; - multiAttrs = { ${aString} = true; ${bString} = false; }.a; + multiAttrs = + { + ${aString} = true; + ${bString} = false; + } + .a; } diff --git a/tests/functional/lang/eval-okay-dynamic-attrs.nix b/tests/functional/lang/eval-okay-dynamic-attrs.nix index ee02ac7e6..f46e26b99 100644 --- a/tests/functional/lang/eval-okay-dynamic-attrs.nix +++ b/tests/functional/lang/eval-okay-dynamic-attrs.nix @@ -2,7 +2,8 @@ let aString = "a"; bString = "b"; -in { +in +{ hasAttrs = { a.b = null; } ? "${aString}".b; selectAttrs = { a.b = true; }.a."${bString}"; @@ -11,7 +12,17 @@ in { binds = { "${aString}"."${bString}c" = true; }.a.bc; - recBinds = rec { "${bString}" = a; a = true; }.b; + recBinds = + rec { + "${bString}" = a; + a = true; + } + .b; - multiAttrs = { "${aString}" = true; "${bString}" = false; }.a; + multiAttrs = + { + "${aString}" = true; + "${bString}" = false; + } + .a; } diff --git a/tests/functional/lang/eval-okay-elem.nix b/tests/functional/lang/eval-okay-elem.nix index 71ea7a4ed..004111dcc 100644 --- a/tests/functional/lang/eval-okay-elem.nix +++ b/tests/functional/lang/eval-okay-elem.nix @@ -1,6 +1,11 @@ with import ./lib.nix; -let xs = range 10 40; in - -[ (builtins.elem 23 xs) (builtins.elem 42 xs) (builtins.elemAt xs 20) ] +let + xs = range 10 40; +in +[ + (builtins.elem 23 xs) + (builtins.elem 42 xs) + (builtins.elemAt xs 20) +] diff --git a/tests/functional/lang/eval-okay-empty-args.nix b/tests/functional/lang/eval-okay-empty-args.nix index 78c133afd..9466749f6 100644 --- a/tests/functional/lang/eval-okay-empty-args.nix +++ b/tests/functional/lang/eval-okay-empty-args.nix @@ -1 +1,4 @@ -({}: {x,y,}: "${x}${y}") {} {x = "a"; y = "b";} +({ }: { x, y }: "${x}${y}") { } { + x = "a"; + y = "b"; +} diff --git a/tests/functional/lang/eval-okay-eq-derivations.nix b/tests/functional/lang/eval-okay-eq-derivations.nix index d526cb4a2..ac802f433 100644 --- a/tests/functional/lang/eval-okay-eq-derivations.nix +++ b/tests/functional/lang/eval-okay-eq-derivations.nix @@ -1,10 +1,40 @@ let - drvA1 = derivation { name = "a"; builder = "/foo"; system = "i686-linux"; }; - drvA2 = derivation { name = "a"; builder = "/foo"; system = "i686-linux"; }; - drvA3 = derivation { name = "a"; builder = "/foo"; system = "i686-linux"; } // { dummy = 1; }; - - drvC1 = derivation { name = "c"; builder = "/foo"; system = "i686-linux"; }; - drvC2 = derivation { name = "c"; builder = "/bar"; system = "i686-linux"; }; + drvA1 = derivation { + name = "a"; + builder = "/foo"; + system = "i686-linux"; + }; + drvA2 = derivation { + name = "a"; + builder = "/foo"; + system = "i686-linux"; + }; + drvA3 = + derivation { + name = "a"; + builder = "/foo"; + system = "i686-linux"; + } + // { + dummy = 1; + }; -in [ (drvA1 == drvA1) (drvA1 == drvA2) (drvA1 == drvA3) (drvC1 == drvC2) ] + drvC1 = derivation { + name = "c"; + builder = "/foo"; + system = "i686-linux"; + }; + drvC2 = derivation { + name = "c"; + builder = "/bar"; + system = "i686-linux"; + }; + +in +[ + (drvA1 == drvA1) + (drvA1 == drvA2) + (drvA1 == drvA3) + (drvC1 == drvC2) +] diff --git a/tests/functional/lang/eval-okay-eq.nix b/tests/functional/lang/eval-okay-eq.nix index 73d200b38..21cb08790 100644 --- a/tests/functional/lang/eval-okay-eq.nix +++ b/tests/functional/lang/eval-okay-eq.nix @@ -1,3 +1,13 @@ -["foobar" (rec {x = 1; y = x;})] -== -[("foo" + "bar") ({x = 1; y = 1;})] +[ + "foobar" + (rec { + x = 1; + y = x; + }) +] == [ + ("foo" + "bar") + ({ + x = 1; + y = 1; + }) +] diff --git a/tests/functional/lang/eval-okay-filter.nix b/tests/functional/lang/eval-okay-filter.nix index 85109b0d0..ef4e490c0 100644 --- a/tests/functional/lang/eval-okay-filter.nix +++ b/tests/functional/lang/eval-okay-filter.nix @@ -1,5 +1,8 @@ with import ./lib.nix; -builtins.filter - (x: x / 2 * 2 == x) - (builtins.concatLists [ (range 0 10) (range 100 110) ]) +builtins.filter (x: x / 2 * 2 == x) ( + builtins.concatLists [ + (range 0 10) + (range 100 110) + ] +) diff --git a/tests/functional/lang/eval-okay-flake-ref-to-string.nix b/tests/functional/lang/eval-okay-flake-ref-to-string.nix index dbb4e5b2a..f477ba52c 100644 --- a/tests/functional/lang/eval-okay-flake-ref-to-string.nix +++ b/tests/functional/lang/eval-okay-flake-ref-to-string.nix @@ -1,7 +1,7 @@ builtins.flakeRefToString { - type = "github"; + type = "github"; owner = "NixOS"; - repo = "nixpkgs"; - ref = "23.05"; - dir = "lib"; + repo = "nixpkgs"; + ref = "23.05"; + dir = "lib"; } diff --git a/tests/functional/lang/eval-okay-flatten.nix b/tests/functional/lang/eval-okay-flatten.nix index fe911e968..ade74c8e8 100644 --- a/tests/functional/lang/eval-okay-flatten.nix +++ b/tests/functional/lang/eval-okay-flatten.nix @@ -2,7 +2,19 @@ with import ./lib.nix; let { - l = ["1" "2" ["3" ["4"] ["5" "6"]] "7"]; + l = [ + "1" + "2" + [ + "3" + [ "4" ] + [ + "5" + "6" + ] + ] + "7" + ]; body = concat (flatten l); } diff --git a/tests/functional/lang/eval-okay-floor-ceil.nix b/tests/functional/lang/eval-okay-floor-ceil.nix index d76a0d86e..06f1a13d2 100644 --- a/tests/functional/lang/eval-okay-floor-ceil.nix +++ b/tests/functional/lang/eval-okay-floor-ceil.nix @@ -6,4 +6,11 @@ let n3 = builtins.floor 23; n4 = builtins.ceil 23; in - builtins.concatStringsSep ";" (map toString [ n1 n2 n3 n4 ]) +builtins.concatStringsSep ";" ( + map toString [ + n1 + n2 + n3 + n4 + ] +) diff --git a/tests/functional/lang/eval-okay-foldlStrict-lazy-elements.nix b/tests/functional/lang/eval-okay-foldlStrict-lazy-elements.nix index c666e07f3..49751c759 100644 --- a/tests/functional/lang/eval-okay-foldlStrict-lazy-elements.nix +++ b/tests/functional/lang/eval-okay-foldlStrict-lazy-elements.nix @@ -1,9 +1,6 @@ # Tests that the rhs argument of op is not forced unconditionally let - lst = builtins.foldl' - (acc: x: acc ++ [ x ]) - [ ] - [ 42 (throw "this shouldn't be evaluated") ]; + lst = builtins.foldl' (acc: x: acc ++ [ x ]) [ ] [ 42 (throw "this shouldn't be evaluated") ]; in builtins.head lst diff --git a/tests/functional/lang/eval-okay-foldlStrict-lazy-initial-accumulator.nix b/tests/functional/lang/eval-okay-foldlStrict-lazy-initial-accumulator.nix index abcd5366a..9cf0ef32c 100644 --- a/tests/functional/lang/eval-okay-foldlStrict-lazy-initial-accumulator.nix +++ b/tests/functional/lang/eval-okay-foldlStrict-lazy-initial-accumulator.nix @@ -1,6 +1,6 @@ # Checks that the nul value for the accumulator is not forced unconditionally. # Some languages provide a foldl' that is strict in this argument, but Nix does not. -builtins.foldl' - (_: x: x) - (throw "This is never forced") - [ "but the results of applying op are" 42 ] +builtins.foldl' (_: x: x) (throw "This is never forced") [ + "but the results of applying op are" + 42 +] diff --git a/tests/functional/lang/eval-okay-fromjson-escapes.nix b/tests/functional/lang/eval-okay-fromjson-escapes.nix index f00713507..6330e9c86 100644 --- a/tests/functional/lang/eval-okay-fromjson-escapes.nix +++ b/tests/functional/lang/eval-okay-fromjson-escapes.nix @@ -1,3 +1,4 @@ # This string contains all supported escapes in a JSON string, per json.org # \b and \f are not supported by Nix -builtins.fromJSON ''"quote \" reverse solidus \\ solidus \/ backspace \b formfeed \f newline \n carriage return \r horizontal tab \t 1 char unicode encoded backspace \u0008 1 char unicode encoded e with accent \u00e9 2 char unicode encoded s with caron \u0161 3 char unicode encoded rightwards arrow \u2192"'' +builtins.fromJSON + ''"quote \" reverse solidus \\ solidus \/ backspace \b formfeed \f newline \n carriage return \r horizontal tab \t 1 char unicode encoded backspace \u0008 1 char unicode encoded e with accent \u00e9 2 char unicode encoded s with caron \u0161 3 char unicode encoded rightwards arrow \u2192"'' diff --git a/tests/functional/lang/eval-okay-fromjson.nix b/tests/functional/lang/eval-okay-fromjson.nix index 4c526b9ae..0e8a2351f 100644 --- a/tests/functional/lang/eval-okay-fromjson.nix +++ b/tests/functional/lang/eval-okay-fromjson.nix @@ -1,41 +1,55 @@ -builtins.fromJSON - '' - { - "Video": { - "Title": "The Penguin Chronicles", - "Width": 1920, - "Height": 1080, - "EmbeddedData": [3.14159, 23493,null, true ,false, -10], - "Thumb": { - "Url": "http://www.example.com/video/5678931", - "Width": 200, - "Height": 250 - }, - "Animated" : false, - "IDs": [116, 943, 234, 38793, true ,false,null, -100], - "Escapes": "\"\\\/\t\n\r\t", - "Subtitle" : false, - "Latitude": 37.7668, - "Longitude": -122.3959 - } - } - '' -== - { Video = - { Title = "The Penguin Chronicles"; - Width = 1920; - Height = 1080; - EmbeddedData = [ 3.14159 23493 null true false (0-10) ]; - Thumb = - { Url = "http://www.example.com/video/5678931"; - Width = 200; - Height = 250; - }; - Animated = false; - IDs = [ 116 943 234 38793 true false null (0-100) ]; - Escapes = "\"\\\/\t\n\r\t"; # supported in JSON but not Nix: \b\f - Subtitle = false; - Latitude = 37.7668; - Longitude = -122.3959; - }; +builtins.fromJSON '' + { + "Video": { + "Title": "The Penguin Chronicles", + "Width": 1920, + "Height": 1080, + "EmbeddedData": [3.14159, 23493,null, true ,false, -10], + "Thumb": { + "Url": "http://www.example.com/video/5678931", + "Width": 200, + "Height": 250 + }, + "Animated" : false, + "IDs": [116, 943, 234, 38793, true ,false,null, -100], + "Escapes": "\"\\\/\t\n\r\t", + "Subtitle" : false, + "Latitude": 37.7668, + "Longitude": -122.3959 + } } +'' == { + Video = { + Title = "The Penguin Chronicles"; + Width = 1920; + Height = 1080; + EmbeddedData = [ + 3.14159 + 23493 + null + true + false + (0 - 10) + ]; + Thumb = { + Url = "http://www.example.com/video/5678931"; + Width = 200; + Height = 250; + }; + Animated = false; + IDs = [ + 116 + 943 + 234 + 38793 + true + false + null + (0 - 100) + ]; + Escapes = "\"\\\/\t\n\r\t"; # supported in JSON but not Nix: \b\f + Subtitle = false; + Latitude = 37.7668; + Longitude = -122.3959; + }; +} diff --git a/tests/functional/lang/eval-okay-functionargs.nix b/tests/functional/lang/eval-okay-functionargs.nix index 68dca62ee..7c11f19c2 100644 --- a/tests/functional/lang/eval-okay-functionargs.nix +++ b/tests/functional/lang/eval-okay-functionargs.nix @@ -1,29 +1,74 @@ let - stdenvFun = { }: { name = "stdenv"; }; - stdenv2Fun = { }: { name = "stdenv2"; }; - fetchurlFun = { stdenv }: assert stdenv.name == "stdenv"; { name = "fetchurl"; }; - atermFun = { stdenv, fetchurl }: { name = "aterm-${stdenv.name}"; }; - aterm2Fun = { stdenv, fetchurl }: { name = "aterm2-${stdenv.name}"; }; - nixFun = { stdenv, fetchurl, aterm }: { name = "nix-${stdenv.name}-${aterm.name}"; }; - + stdenvFun = + { }: + { + name = "stdenv"; + }; + stdenv2Fun = + { }: + { + name = "stdenv2"; + }; + fetchurlFun = + { stdenv }: + assert stdenv.name == "stdenv"; + { + name = "fetchurl"; + }; + atermFun = + { stdenv, fetchurl }: + { + name = "aterm-${stdenv.name}"; + }; + aterm2Fun = + { stdenv, fetchurl }: + { + name = "aterm2-${stdenv.name}"; + }; + nixFun = + { + stdenv, + fetchurl, + aterm, + }: + { + name = "nix-${stdenv.name}-${aterm.name}"; + }; + mplayerFun = - { stdenv, fetchurl, enableX11 ? false, xorg ? null, enableFoo ? true, foo ? null }: + { + stdenv, + fetchurl, + enableX11 ? false, + xorg ? null, + enableFoo ? true, + foo ? null, + }: assert stdenv.name == "stdenv2"; assert enableX11 -> xorg.libXv.name == "libXv"; assert enableFoo -> foo != null; - { name = "mplayer-${stdenv.name}.${xorg.libXv.name}-${xorg.libX11.name}"; }; + { + name = "mplayer-${stdenv.name}.${xorg.libXv.name}-${xorg.libX11.name}"; + }; - makeOverridable = f: origArgs: f origArgs // - { override = newArgs: + makeOverridable = + f: origArgs: + f origArgs + // { + override = + newArgs: makeOverridable f (origArgs // (if builtins.isFunction newArgs then newArgs origArgs else newArgs)); }; - - callPackage_ = pkgs: f: args: + + callPackage_ = + pkgs: f: args: makeOverridable f ((builtins.intersectAttrs (builtins.functionArgs f) pkgs) // args); allPackages = - { overrides ? (pkgs: pkgsPrev: { }) }: + { + overrides ? (pkgs: pkgsPrev: { }), + }: let callPackage = callPackage_ pkgs; pkgs = pkgsStd // (overrides pkgs pkgsStd); @@ -34,18 +79,40 @@ let fetchurl = callPackage fetchurlFun { }; aterm = callPackage atermFun { }; xorg = callPackage xorgFun { }; - mplayer = callPackage mplayerFun { stdenv = pkgs.stdenv2; enableFoo = false; }; + mplayer = callPackage mplayerFun { + stdenv = pkgs.stdenv2; + enableFoo = false; + }; nix = callPackage nixFun { }; }; - in pkgs; + in + pkgs; + + libX11Fun = + { stdenv, fetchurl }: + { + name = "libX11"; + }; + libX11_2Fun = + { stdenv, fetchurl }: + { + name = "libX11_2"; + }; + libXvFun = + { + stdenv, + fetchurl, + libX11, + }: + { + name = "libXv"; + }; - libX11Fun = { stdenv, fetchurl }: { name = "libX11"; }; - libX11_2Fun = { stdenv, fetchurl }: { name = "libX11_2"; }; - libXvFun = { stdenv, fetchurl, libX11 }: { name = "libXv"; }; - xorgFun = { pkgs }: - let callPackage = callPackage_ (pkgs // pkgs.xorg); in + let + callPackage = callPackage_ (pkgs // pkgs.xorg); + in { libX11 = callPackage libX11Fun { }; libXv = callPackage libXvFun { }; @@ -56,25 +123,28 @@ in let pkgs = allPackages { }; - + pkgs2 = allPackages { overrides = pkgs: pkgsPrev: { stdenv = pkgs.stdenv2; nix = pkgsPrev.nix.override { aterm = aterm2Fun { inherit (pkgs) stdenv fetchurl; }; }; - xorg = pkgsPrev.xorg // { libX11 = libX11_2Fun { inherit (pkgs) stdenv fetchurl; }; }; + xorg = pkgsPrev.xorg // { + libX11 = libX11_2Fun { inherit (pkgs) stdenv fetchurl; }; + }; }; }; - + in - [ pkgs.stdenv.name - pkgs.fetchurl.name - pkgs.aterm.name - pkgs2.aterm.name - pkgs.xorg.libX11.name - pkgs.xorg.libXv.name - pkgs.mplayer.name - pkgs2.mplayer.name - pkgs.nix.name - pkgs2.nix.name - ] +[ + pkgs.stdenv.name + pkgs.fetchurl.name + pkgs.aterm.name + pkgs2.aterm.name + pkgs.xorg.libX11.name + pkgs.xorg.libXv.name + pkgs.mplayer.name + pkgs2.mplayer.name + pkgs.nix.name + pkgs2.nix.name +] diff --git a/tests/functional/lang/eval-okay-getattrpos-functionargs.nix b/tests/functional/lang/eval-okay-getattrpos-functionargs.nix index 11d6bb0e3..9692911cf 100644 --- a/tests/functional/lang/eval-okay-getattrpos-functionargs.nix +++ b/tests/functional/lang/eval-okay-getattrpos-functionargs.nix @@ -1,4 +1,8 @@ let - fun = { foo }: {}; + fun = { foo }: { }; pos = builtins.unsafeGetAttrPos "foo" (builtins.functionArgs fun); -in { inherit (pos) column line; file = baseNameOf pos.file; } +in +{ + inherit (pos) column line; + file = baseNameOf pos.file; +} diff --git a/tests/functional/lang/eval-okay-getattrpos.nix b/tests/functional/lang/eval-okay-getattrpos.nix index ca6b07961..25bc57444 100644 --- a/tests/functional/lang/eval-okay-getattrpos.nix +++ b/tests/functional/lang/eval-okay-getattrpos.nix @@ -3,4 +3,8 @@ let foo = "bar"; }; pos = builtins.unsafeGetAttrPos "foo" as; -in { inherit (pos) column line; file = baseNameOf pos.file; } +in +{ + inherit (pos) column line; + file = baseNameOf pos.file; +} diff --git a/tests/functional/lang/eval-okay-groupBy.nix b/tests/functional/lang/eval-okay-groupBy.nix index 862d89dbd..f4de5444a 100644 --- a/tests/functional/lang/eval-okay-groupBy.nix +++ b/tests/functional/lang/eval-okay-groupBy.nix @@ -1,5 +1,5 @@ with import ./lib.nix; -builtins.groupBy (n: - builtins.substring 0 1 (builtins.hashString "sha256" (toString n)) -) (range 0 31) +builtins.groupBy (n: builtins.substring 0 1 (builtins.hashString "sha256" (toString n))) ( + range 0 31 +) diff --git a/tests/functional/lang/eval-okay-hashfile.nix b/tests/functional/lang/eval-okay-hashfile.nix index aff5a1856..aeaf09f43 100644 --- a/tests/functional/lang/eval-okay-hashfile.nix +++ b/tests/functional/lang/eval-okay-hashfile.nix @@ -1,4 +1,14 @@ let - paths = [ ./data ./binary-data ]; + paths = [ + ./data + ./binary-data + ]; in - builtins.concatLists (map (hash: map (builtins.hashFile hash) paths) ["md5" "sha1" "sha256" "sha512"]) +builtins.concatLists ( + map (hash: map (builtins.hashFile hash) paths) [ + "md5" + "sha1" + "sha256" + "sha512" + ] +) diff --git a/tests/functional/lang/eval-okay-hashstring.nix b/tests/functional/lang/eval-okay-hashstring.nix index b0f62b245..c760b0043 100644 --- a/tests/functional/lang/eval-okay-hashstring.nix +++ b/tests/functional/lang/eval-okay-hashstring.nix @@ -1,4 +1,15 @@ let - strings = [ "" "text 1" "text 2" ]; + strings = [ + "" + "text 1" + "text 2" + ]; in - builtins.concatLists (map (hash: map (builtins.hashString hash) strings) ["md5" "sha1" "sha256" "sha512"]) +builtins.concatLists ( + map (hash: map (builtins.hashString hash) strings) [ + "md5" + "sha1" + "sha256" + "sha512" + ] +) diff --git a/tests/functional/lang/eval-okay-if.nix b/tests/functional/lang/eval-okay-if.nix index 23e4c74d5..66b9d15b8 100644 --- a/tests/functional/lang/eval-okay-if.nix +++ b/tests/functional/lang/eval-okay-if.nix @@ -1 +1,6 @@ -if "foo" != "f" + "oo" then 1 else if false then 2 else 3 +if "foo" != "f" + "oo" then + 1 +else if false then + 2 +else + 3 diff --git a/tests/functional/lang/eval-okay-import.nix b/tests/functional/lang/eval-okay-import.nix index 0b18d9413..484dccac0 100644 --- a/tests/functional/lang/eval-okay-import.nix +++ b/tests/functional/lang/eval-okay-import.nix @@ -8,4 +8,5 @@ let builtins = builtins // overrides; } // import ./lib.nix; -in scopedImport overrides ./imported.nix +in +scopedImport overrides ./imported.nix diff --git a/tests/functional/lang/eval-okay-inherit-attr-pos.nix b/tests/functional/lang/eval-okay-inherit-attr-pos.nix index 017ab1d36..c162d1196 100644 --- a/tests/functional/lang/eval-okay-inherit-attr-pos.nix +++ b/tests/functional/lang/eval-okay-inherit-attr-pos.nix @@ -4,9 +4,9 @@ let y = { inherit d x; }; z = { inherit (y) d x; }; in - [ - (builtins.unsafeGetAttrPos "d" y) - (builtins.unsafeGetAttrPos "x" y) - (builtins.unsafeGetAttrPos "d" z) - (builtins.unsafeGetAttrPos "x" z) - ] +[ + (builtins.unsafeGetAttrPos "d" y) + (builtins.unsafeGetAttrPos "x" y) + (builtins.unsafeGetAttrPos "d" z) + (builtins.unsafeGetAttrPos "x" z) +] diff --git a/tests/functional/lang/eval-okay-inherit-from.nix b/tests/functional/lang/eval-okay-inherit-from.nix index b72a1c639..1a0980aaf 100644 --- a/tests/functional/lang/eval-okay-inherit-from.nix +++ b/tests/functional/lang/eval-okay-inherit-from.nix @@ -1,5 +1,12 @@ let - inherit (builtins.trace "used" { a = 1; b = 2; }) a b; + inherit + (builtins.trace "used" { + a = 1; + b = 2; + }) + a + b + ; x.c = 3; y.d = 4; @@ -13,4 +20,14 @@ let }; }; in - [ a b rec { x.c = []; inherit (x) c; inherit (y) d; __overrides.y.d = []; } merged ] +[ + a + b + rec { + x.c = [ ]; + inherit (x) c; + inherit (y) d; + __overrides.y.d = [ ]; + } + merged +] diff --git a/tests/functional/lang/eval-okay-intersectAttrs.nix b/tests/functional/lang/eval-okay-intersectAttrs.nix index 39d49938c..bf4d58a99 100644 --- a/tests/functional/lang/eval-okay-intersectAttrs.nix +++ b/tests/functional/lang/eval-okay-intersectAttrs.nix @@ -1,6 +1,6 @@ let - alphabet = - { a = "a"; + alphabet = { + a = "a"; b = "b"; c = "c"; d = "d"; @@ -28,23 +28,46 @@ let z = "z"; }; foo = { - inherit (alphabet) f o b a r z q u x; + inherit (alphabet) + f + o + b + a + r + z + q + u + x + ; aa = throw "aa"; }; alphabetFail = builtins.mapAttrs throw alphabet; in -[ (builtins.intersectAttrs { a = abort "l1"; } { b = abort "r1"; }) +[ + (builtins.intersectAttrs { a = abort "l1"; } { b = abort "r1"; }) (builtins.intersectAttrs { a = abort "l2"; } { a = 1; }) (builtins.intersectAttrs alphabetFail { a = 1; }) - (builtins.intersectAttrs { a = abort "laa"; } alphabet) + (builtins.intersectAttrs { a = abort "laa"; } alphabet) (builtins.intersectAttrs alphabetFail { m = 1; }) - (builtins.intersectAttrs { m = abort "lam"; } alphabet) + (builtins.intersectAttrs { m = abort "lam"; } alphabet) (builtins.intersectAttrs alphabetFail { n = 1; }) - (builtins.intersectAttrs { n = abort "lan"; } alphabet) - (builtins.intersectAttrs alphabetFail { n = 1; p = 2; }) - (builtins.intersectAttrs { n = abort "lan2"; p = abort "lap"; } alphabet) - (builtins.intersectAttrs alphabetFail { n = 1; p = 2; }) - (builtins.intersectAttrs { n = abort "lan2"; p = abort "lap"; } alphabet) + (builtins.intersectAttrs { n = abort "lan"; } alphabet) + (builtins.intersectAttrs alphabetFail { + n = 1; + p = 2; + }) + (builtins.intersectAttrs { + n = abort "lan2"; + p = abort "lap"; + } alphabet) + (builtins.intersectAttrs alphabetFail { + n = 1; + p = 2; + }) + (builtins.intersectAttrs { + n = abort "lan2"; + p = abort "lap"; + } alphabet) (builtins.intersectAttrs alphabetFail alphabet) (builtins.intersectAttrs alphabet foo == builtins.intersectAttrs foo alphabet) ] diff --git a/tests/functional/lang/eval-okay-list.nix b/tests/functional/lang/eval-okay-list.nix index d433bcf90..b5045a753 100644 --- a/tests/functional/lang/eval-okay-list.nix +++ b/tests/functional/lang/eval-okay-list.nix @@ -2,6 +2,11 @@ with import ./lib.nix; let { - body = concat ["foo" "bar" "bla" "test"]; - -} \ No newline at end of file + body = concat [ + "foo" + "bar" + "bla" + "test" + ]; + +} diff --git a/tests/functional/lang/eval-okay-listtoattrs.nix b/tests/functional/lang/eval-okay-listtoattrs.nix index 4186e029b..1de9d6d62 100644 --- a/tests/functional/lang/eval-okay-listtoattrs.nix +++ b/tests/functional/lang/eval-okay-listtoattrs.nix @@ -1,11 +1,24 @@ # this test shows how to use listToAttrs and that evaluation is still lazy (throw isn't called) with import ./lib.nix; -let - asi = name: value : { inherit name value; }; - list = [ ( asi "a" "A" ) ( asi "b" "B" ) ]; +let + asi = name: value: { inherit name value; }; + list = [ + (asi "a" "A") + (asi "b" "B") + ]; a = builtins.listToAttrs list; - b = builtins.listToAttrs ( list ++ list ); - r = builtins.listToAttrs [ (asi "result" [ a b ]) ( asi "throw" (throw "this should not be thrown")) ]; - x = builtins.listToAttrs [ (asi "foo" "bar") (asi "foo" "bla") ]; -in concat (map (x: x.a) r.result) + x.foo + b = builtins.listToAttrs (list ++ list); + r = builtins.listToAttrs [ + (asi "result" [ + a + b + ]) + (asi "throw" (throw "this should not be thrown")) + ]; + x = builtins.listToAttrs [ + (asi "foo" "bar") + (asi "foo" "bla") + ]; +in +concat (map (x: x.a) r.result) + x.foo diff --git a/tests/functional/lang/eval-okay-logic.nix b/tests/functional/lang/eval-okay-logic.nix index fbb127944..55cd2fc00 100644 --- a/tests/functional/lang/eval-okay-logic.nix +++ b/tests/functional/lang/eval-okay-logic.nix @@ -1 +1,2 @@ -assert !false && (true || false) -> true; 1 +assert !false && (true || false) -> true; +1 diff --git a/tests/functional/lang/eval-okay-map.nix b/tests/functional/lang/eval-okay-map.nix index a76c1d811..22059f37a 100644 --- a/tests/functional/lang/eval-okay-map.nix +++ b/tests/functional/lang/eval-okay-map.nix @@ -1,3 +1,9 @@ with import ./lib.nix; -concat (map (x: x + "bar") [ "foo" "bla" "xyzzy" ]) \ No newline at end of file +concat ( + map (x: x + "bar") [ + "foo" + "bla" + "xyzzy" + ] +) diff --git a/tests/functional/lang/eval-okay-mapattrs.nix b/tests/functional/lang/eval-okay-mapattrs.nix index f075b6275..c1182d13d 100644 --- a/tests/functional/lang/eval-okay-mapattrs.nix +++ b/tests/functional/lang/eval-okay-mapattrs.nix @@ -1,3 +1,6 @@ with import ./lib.nix; -builtins.mapAttrs (name: value: name + "-" + value) { x = "foo"; y = "bar"; } +builtins.mapAttrs (name: value: name + "-" + value) { + x = "foo"; + y = "bar"; +} diff --git a/tests/functional/lang/eval-okay-merge-dynamic-attrs.nix b/tests/functional/lang/eval-okay-merge-dynamic-attrs.nix index f459a554f..8ee8e503a 100644 --- a/tests/functional/lang/eval-okay-merge-dynamic-attrs.nix +++ b/tests/functional/lang/eval-okay-merge-dynamic-attrs.nix @@ -1,9 +1,17 @@ { - set1 = { a = 1; }; - set1 = { "${"b" + ""}" = 2; }; + set1 = { + a = 1; + }; + set1 = { + "${"b" + ""}" = 2; + }; - set2 = { "${"b" + ""}" = 2; }; - set2 = { a = 1; }; + set2 = { + "${"b" + ""}" = 2; + }; + set2 = { + a = 1; + }; set3.a = 1; set3."${"b" + ""}" = 2; diff --git a/tests/functional/lang/eval-okay-nested-with.nix b/tests/functional/lang/eval-okay-nested-with.nix index ba9d79aa7..ee069eaa1 100644 --- a/tests/functional/lang/eval-okay-nested-with.nix +++ b/tests/functional/lang/eval-okay-nested-with.nix @@ -1,3 +1 @@ -with { x = 1; }; -with { x = 2; }; -x +with { x = 1; }; with { x = 2; }; x diff --git a/tests/functional/lang/eval-okay-new-let.nix b/tests/functional/lang/eval-okay-new-let.nix index 738123141..1a938ce71 100644 --- a/tests/functional/lang/eval-okay-new-let.nix +++ b/tests/functional/lang/eval-okay-new-let.nix @@ -1,14 +1,16 @@ let - f = z: + f = + z: let x = "foo"; y = "bar"; body = 1; # compat test in - z + x + y; + z + x + y; arg = "xyzzy"; -in f arg +in +f arg diff --git a/tests/functional/lang/eval-okay-null-dynamic-attrs.nix b/tests/functional/lang/eval-okay-null-dynamic-attrs.nix index b060c0bc9..76286b622 100644 --- a/tests/functional/lang/eval-okay-null-dynamic-attrs.nix +++ b/tests/functional/lang/eval-okay-null-dynamic-attrs.nix @@ -1 +1 @@ -{ ${null} = true; } == {} +{ ${null} = true; } == { } diff --git a/tests/functional/lang/eval-okay-overrides.nix b/tests/functional/lang/eval-okay-overrides.nix index 719bdc9c0..1c0d5d7c2 100644 --- a/tests/functional/lang/eval-okay-overrides.nix +++ b/tests/functional/lang/eval-okay-overrides.nix @@ -1,8 +1,12 @@ let - overrides = { a = 2; b = 3; }; + overrides = { + a = 2; + b = 3; + }; -in (rec { +in +(rec { __overrides = overrides; x = a; a = 1; diff --git a/tests/functional/lang/eval-okay-parse-flake-ref.nix b/tests/functional/lang/eval-okay-parse-flake-ref.nix index db4ed2742..404c5df08 100644 --- a/tests/functional/lang/eval-okay-parse-flake-ref.nix +++ b/tests/functional/lang/eval-okay-parse-flake-ref.nix @@ -1 +1 @@ - builtins.parseFlakeRef "github:NixOS/nixpkgs/23.05?dir=lib" +builtins.parseFlakeRef "github:NixOS/nixpkgs/23.05?dir=lib" diff --git a/tests/functional/lang/eval-okay-partition.nix b/tests/functional/lang/eval-okay-partition.nix index 846d2ce49..b9566edf9 100644 --- a/tests/functional/lang/eval-okay-partition.nix +++ b/tests/functional/lang/eval-okay-partition.nix @@ -1,5 +1,8 @@ with import ./lib.nix; -builtins.partition - (x: x / 2 * 2 == x) - (builtins.concatLists [ (range 0 10) (range 100 110) ]) +builtins.partition (x: x / 2 * 2 == x) ( + builtins.concatLists [ + (range 0 10) + (range 100 110) + ] +) diff --git a/tests/functional/lang/eval-okay-path.nix b/tests/functional/lang/eval-okay-path.nix index 599b33541..b8b48aae1 100644 --- a/tests/functional/lang/eval-okay-path.nix +++ b/tests/functional/lang/eval-okay-path.nix @@ -1,15 +1,15 @@ [ - (builtins.path - { path = ./.; - filter = path: _: baseNameOf path == "data"; - recursive = true; - sha256 = "1yhm3gwvg5a41yylymgblsclk95fs6jy72w0wv925mmidlhcq4sw"; - name = "output"; - }) - (builtins.path - { path = ./data; - recursive = false; - sha256 = "0k4lwj58f2w5yh92ilrwy9917pycipbrdrr13vbb3yd02j09vfxm"; - name = "output"; - }) + (builtins.path { + path = ./.; + filter = path: _: baseNameOf path == "data"; + recursive = true; + sha256 = "1yhm3gwvg5a41yylymgblsclk95fs6jy72w0wv925mmidlhcq4sw"; + name = "output"; + }) + (builtins.path { + path = ./data; + recursive = false; + sha256 = "0k4lwj58f2w5yh92ilrwy9917pycipbrdrr13vbb3yd02j09vfxm"; + name = "output"; + }) ] diff --git a/tests/functional/lang/eval-okay-patterns.nix b/tests/functional/lang/eval-okay-patterns.nix index 96fd25a01..b92b232d2 100644 --- a/tests/functional/lang/eval-okay-patterns.nix +++ b/tests/functional/lang/eval-okay-patterns.nix @@ -1,16 +1,59 @@ let - f = args@{x, y, z}: x + args.y + z; + f = + args@{ + x, + y, + z, + }: + x + args.y + z; - g = {x, y, z}@args: f args; + g = + { + x, + y, + z, + }@args: + f args; - h = {x ? "d", y ? x, z ? args.x}@args: x + y + z; + h = + { + x ? "d", + y ? x, + z ? args.x, + }@args: + x + y + z; - j = {x, y, z, ...}: x + y + z; + j = + { + x, + y, + z, + ... + }: + x + y + z; in - f {x = "a"; y = "b"; z = "c";} + - g {x = "x"; y = "y"; z = "z";} + - h {x = "D";} + - h {x = "D"; y = "E"; z = "F";} + - j {x = "i"; y = "j"; z = "k"; bla = "bla"; foo = "bar";} +f { + x = "a"; + y = "b"; + z = "c"; +} ++ g { + x = "x"; + y = "y"; + z = "z"; +} ++ h { x = "D"; } ++ h { + x = "D"; + y = "E"; + z = "F"; +} ++ j { + x = "i"; + y = "j"; + z = "k"; + bla = "bla"; + foo = "bar"; +} diff --git a/tests/functional/lang/eval-okay-print.nix b/tests/functional/lang/eval-okay-print.nix index d36ba4da3..1ad465602 100644 --- a/tests/functional/lang/eval-okay-print.nix +++ b/tests/functional/lang/eval-okay-print.nix @@ -1 +1,15 @@ -with builtins; trace [(1+1)] [ null toString (deepSeq "x") (a: a) (let x=[x]; in x) ] +with builtins; +trace + [ (1 + 1) ] + [ + null + toString + (deepSeq "x") + (a: a) + ( + let + x = [ x ]; + in + x + ) + ] diff --git a/tests/functional/lang/eval-okay-readFileType.nix b/tests/functional/lang/eval-okay-readFileType.nix index 174fb6c3a..79beb9a6e 100644 --- a/tests/functional/lang/eval-okay-readFileType.nix +++ b/tests/functional/lang/eval-okay-readFileType.nix @@ -1,6 +1,6 @@ { - bar = builtins.readFileType ./readDir/bar; - foo = builtins.readFileType ./readDir/foo; + bar = builtins.readFileType ./readDir/bar; + foo = builtins.readFileType ./readDir/foo; linked = builtins.readFileType ./readDir/linked; - ldir = builtins.readFileType ./readDir/ldir; + ldir = builtins.readFileType ./readDir/ldir; } diff --git a/tests/functional/lang/eval-okay-redefine-builtin.nix b/tests/functional/lang/eval-okay-redefine-builtin.nix index df9fc3f37..ec95ffa93 100644 --- a/tests/functional/lang/eval-okay-redefine-builtin.nix +++ b/tests/functional/lang/eval-okay-redefine-builtin.nix @@ -1,3 +1,4 @@ let throw = abort "Error!"; -in (builtins.tryEval ).success +in +(builtins.tryEval ).success diff --git a/tests/functional/lang/eval-okay-regex-match.nix b/tests/functional/lang/eval-okay-regex-match.nix index 273e25907..54b995996 100644 --- a/tests/functional/lang/eval-okay-regex-match.nix +++ b/tests/functional/lang/eval-okay-regex-match.nix @@ -8,22 +8,34 @@ let in -assert matches "foobar" "foobar"; -assert matches "fo*" "f"; +assert matches "foobar" "foobar"; +assert matches "fo*" "f"; assert !matches "fo+" "f"; -assert matches "fo*" "fo"; -assert matches "fo*" "foo"; -assert matches "fo+" "foo"; -assert matches "fo{1,2}" "foo"; +assert matches "fo*" "fo"; +assert matches "fo*" "foo"; +assert matches "fo+" "foo"; +assert matches "fo{1,2}" "foo"; assert !matches "fo{1,2}" "fooo"; assert !matches "fo*" "foobar"; -assert matches "[[:space:]]+([^[:space:]]+)[[:space:]]+" " foo "; +assert matches "[[:space:]]+([^[:space:]]+)[[:space:]]+" " foo "; assert !matches "[[:space:]]+([[:upper:]]+)[[:space:]]+" " foo "; assert match "(.*)\\.nix" "foobar.nix" == [ "foobar" ]; assert match "[[:space:]]+([[:upper:]]+)[[:space:]]+" " FOO " == [ "FOO" ]; -assert splitFN "/path/to/foobar.nix" == [ "/path/to/" "/path/to" "foobar" "nix" ]; -assert splitFN "foobar.cc" == [ null null "foobar" "cc" ]; +assert + splitFN "/path/to/foobar.nix" == [ + "/path/to/" + "/path/to" + "foobar" + "nix" + ]; +assert + splitFN "foobar.cc" == [ + null + null + "foobar" + "cc" + ]; true diff --git a/tests/functional/lang/eval-okay-regex-split.nix b/tests/functional/lang/eval-okay-regex-split.nix index 0073e0577..8ab3e60cb 100644 --- a/tests/functional/lang/eval-okay-regex-split.nix +++ b/tests/functional/lang/eval-okay-regex-split.nix @@ -1,48 +1,197 @@ with builtins; # Non capturing regex returns empty lists -assert split "foobar" "foobar" == ["" [] ""]; -assert split "fo*" "f" == ["" [] ""]; -assert split "fo+" "f" == ["f"]; -assert split "fo*" "fo" == ["" [] ""]; -assert split "fo*" "foo" == ["" [] ""]; -assert split "fo+" "foo" == ["" [] ""]; -assert split "fo{1,2}" "foo" == ["" [] ""]; -assert split "fo{1,2}" "fooo" == ["" [] "o"]; -assert split "fo*" "foobar" == ["" [] "bar"]; +assert + split "foobar" "foobar" == [ + "" + [ ] + "" + ]; +assert + split "fo*" "f" == [ + "" + [ ] + "" + ]; +assert split "fo+" "f" == [ "f" ]; +assert + split "fo*" "fo" == [ + "" + [ ] + "" + ]; +assert + split "fo*" "foo" == [ + "" + [ ] + "" + ]; +assert + split "fo+" "foo" == [ + "" + [ ] + "" + ]; +assert + split "fo{1,2}" "foo" == [ + "" + [ ] + "" + ]; +assert + split "fo{1,2}" "fooo" == [ + "" + [ ] + "o" + ]; +assert + split "fo*" "foobar" == [ + "" + [ ] + "bar" + ]; # Capturing regex returns a list of sub-matches -assert split "(fo*)" "f" == ["" ["f"] ""]; -assert split "(fo+)" "f" == ["f"]; -assert split "(fo*)" "fo" == ["" ["fo"] ""]; -assert split "(f)(o*)" "f" == ["" ["f" ""] ""]; -assert split "(f)(o*)" "foo" == ["" ["f" "oo"] ""]; -assert split "(fo+)" "foo" == ["" ["foo"] ""]; -assert split "(fo{1,2})" "foo" == ["" ["foo"] ""]; -assert split "(fo{1,2})" "fooo" == ["" ["foo"] "o"]; -assert split "(fo*)" "foobar" == ["" ["foo"] "bar"]; +assert + split "(fo*)" "f" == [ + "" + [ "f" ] + "" + ]; +assert split "(fo+)" "f" == [ "f" ]; +assert + split "(fo*)" "fo" == [ + "" + [ "fo" ] + "" + ]; +assert + split "(f)(o*)" "f" == [ + "" + [ + "f" + "" + ] + "" + ]; +assert + split "(f)(o*)" "foo" == [ + "" + [ + "f" + "oo" + ] + "" + ]; +assert + split "(fo+)" "foo" == [ + "" + [ "foo" ] + "" + ]; +assert + split "(fo{1,2})" "foo" == [ + "" + [ "foo" ] + "" + ]; +assert + split "(fo{1,2})" "fooo" == [ + "" + [ "foo" ] + "o" + ]; +assert + split "(fo*)" "foobar" == [ + "" + [ "foo" ] + "bar" + ]; # Matches are greedy. -assert split "(o+)" "oooofoooo" == ["" ["oooo"] "f" ["oooo"] ""]; +assert + split "(o+)" "oooofoooo" == [ + "" + [ "oooo" ] + "f" + [ "oooo" ] + "" + ]; # Matches multiple times. -assert split "(b)" "foobarbaz" == ["foo" ["b"] "ar" ["b"] "az"]; +assert + split "(b)" "foobarbaz" == [ + "foo" + [ "b" ] + "ar" + [ "b" ] + "az" + ]; # Split large strings containing newlines. null are inserted when a # pattern within the current did not match anything. -assert split "[[:space:]]+|([',.!?])" '' - Nix Rocks! - That's why I use it. -'' == [ - "Nix" [ null ] "Rocks" ["!"] "" [ null ] - "That" ["'"] "s" [ null ] "why" [ null ] "I" [ null ] "use" [ null ] "it" ["."] "" [ null ] - "" -]; +assert + split "[[:space:]]+|([',.!?])" '' + Nix Rocks! + That's why I use it. + '' == [ + "Nix" + [ null ] + "Rocks" + [ "!" ] + "" + [ null ] + "That" + [ "'" ] + "s" + [ null ] + "why" + [ null ] + "I" + [ null ] + "use" + [ null ] + "it" + [ "." ] + "" + [ null ] + "" + ]; # Documentation examples -assert split "(a)b" "abc" == [ "" [ "a" ] "c" ]; -assert split "([ac])" "abc" == [ "" [ "a" ] "b" [ "c" ] "" ]; -assert split "(a)|(c)" "abc" == [ "" [ "a" null ] "b" [ null "c" ] "" ]; -assert split "([[:upper:]]+)" " FOO " == [ " " [ "FOO" ] " " ]; +assert + split "(a)b" "abc" == [ + "" + [ "a" ] + "c" + ]; +assert + split "([ac])" "abc" == [ + "" + [ "a" ] + "b" + [ "c" ] + "" + ]; +assert + split "(a)|(c)" "abc" == [ + "" + [ + "a" + null + ] + "b" + [ + null + "c" + ] + "" + ]; +assert + split "([[:upper:]]+)" " FOO " == [ + " " + [ "FOO" ] + " " + ]; true diff --git a/tests/functional/lang/eval-okay-regression-20220125.nix b/tests/functional/lang/eval-okay-regression-20220125.nix index 485502373..1c4b8e09f 100644 --- a/tests/functional/lang/eval-okay-regression-20220125.nix +++ b/tests/functional/lang/eval-okay-regression-20220125.nix @@ -1,2 +1 @@ ((__curPosFoo: __curPosFoo) 1) + ((__curPosBar: __curPosBar) 2) - diff --git a/tests/functional/lang/eval-okay-regrettable-rec-attrset-merge.nix b/tests/functional/lang/eval-okay-regrettable-rec-attrset-merge.nix index 8df6a2ad8..e92ae8125 100644 --- a/tests/functional/lang/eval-okay-regrettable-rec-attrset-merge.nix +++ b/tests/functional/lang/eval-okay-regrettable-rec-attrset-merge.nix @@ -1,3 +1,10 @@ # This is for backwards compatibility, not because we like it. # See https://github.com/NixOS/nix/issues/9020. -{ a = rec { b = c + 1; d = 2; }; a.c = d + 3; }.a.b +{ + a = rec { + b = c + 1; + d = 2; + }; + a.c = d + 3; +} +.a.b diff --git a/tests/functional/lang/eval-okay-remove.nix b/tests/functional/lang/eval-okay-remove.nix index 4ad5ba897..a7ee3a071 100644 --- a/tests/functional/lang/eval-okay-remove.nix +++ b/tests/functional/lang/eval-okay-remove.nix @@ -1,5 +1,8 @@ let { - attrs = {x = 123; y = 456;}; + attrs = { + x = 123; + y = 456; + }; - body = (removeAttrs attrs ["x"]).y; -} \ No newline at end of file + body = (removeAttrs attrs [ "x" ]).y; +} diff --git a/tests/functional/lang/eval-okay-repeated-empty-attrs.nix b/tests/functional/lang/eval-okay-repeated-empty-attrs.nix index 030a3b85c..0749e21a5 100644 --- a/tests/functional/lang/eval-okay-repeated-empty-attrs.nix +++ b/tests/functional/lang/eval-okay-repeated-empty-attrs.nix @@ -1,2 +1,5 @@ # Tests that empty attribute sets are not printed as `«repeated»`. -[ {} {} ] +[ + { } + { } +] diff --git a/tests/functional/lang/eval-okay-repeated-empty-list.nix b/tests/functional/lang/eval-okay-repeated-empty-list.nix index 376c51be8..7e24fe81b 100644 --- a/tests/functional/lang/eval-okay-repeated-empty-list.nix +++ b/tests/functional/lang/eval-okay-repeated-empty-list.nix @@ -1 +1,4 @@ -[ [] [] ] +[ + [ ] + [ ] +] diff --git a/tests/functional/lang/eval-okay-replacestrings.nix b/tests/functional/lang/eval-okay-replacestrings.nix index a803e6519..81a932a1d 100644 --- a/tests/functional/lang/eval-okay-replacestrings.nix +++ b/tests/functional/lang/eval-okay-replacestrings.nix @@ -1,12 +1,13 @@ with builtins; -[ (replaceStrings ["o"] ["a"] "foobar") - (replaceStrings ["o"] [""] "foobar") - (replaceStrings ["oo"] ["u"] "foobar") - (replaceStrings ["oo" "a"] ["a" "oo"] "foobar") - (replaceStrings ["oo" "oo"] ["u" "i"] "foobar") - (replaceStrings [""] ["X"] "abc") - (replaceStrings [""] ["X"] "") - (replaceStrings ["-"] ["_"] "a-b") - (replaceStrings ["oo" "XX"] ["u" (throw "unreachable")] "foobar") +[ + (replaceStrings [ "o" ] [ "a" ] "foobar") + (replaceStrings [ "o" ] [ "" ] "foobar") + (replaceStrings [ "oo" ] [ "u" ] "foobar") + (replaceStrings [ "oo" "a" ] [ "a" "oo" ] "foobar") + (replaceStrings [ "oo" "oo" ] [ "u" "i" ] "foobar") + (replaceStrings [ "" ] [ "X" ] "abc") + (replaceStrings [ "" ] [ "X" ] "") + (replaceStrings [ "-" ] [ "_" ] "a-b") + (replaceStrings [ "oo" "XX" ] [ "u" (throw "unreachable") ] "foobar") ] diff --git a/tests/functional/lang/eval-okay-scope-1.nix b/tests/functional/lang/eval-okay-scope-1.nix index fa38a7174..b7bbcc432 100644 --- a/tests/functional/lang/eval-okay-scope-1.nix +++ b/tests/functional/lang/eval-okay-scope-1.nix @@ -1,6 +1,13 @@ -(({x}: x: +( + ( + { x }: + x: - { x = 1; - y = x; - } -) {x = 2;} 3).y + { + x = 1; + y = x; + } + ) + { x = 2; } + 3 +).y diff --git a/tests/functional/lang/eval-okay-scope-2.nix b/tests/functional/lang/eval-okay-scope-2.nix index eb8b02bc4..54f7ec3b2 100644 --- a/tests/functional/lang/eval-okay-scope-2.nix +++ b/tests/functional/lang/eval-okay-scope-2.nix @@ -1,6 +1,12 @@ -((x: {x}: - rec { - x = 1; - y = x; - } -) 2 {x = 3;}).y +( + ( + x: + { x }: + rec { + x = 1; + y = x; + } + ) + 2 + { x = 3; } +).y diff --git a/tests/functional/lang/eval-okay-scope-3.nix b/tests/functional/lang/eval-okay-scope-3.nix index 10d6bc04d..6a77583b7 100644 --- a/tests/functional/lang/eval-okay-scope-3.nix +++ b/tests/functional/lang/eval-okay-scope-3.nix @@ -1,6 +1,13 @@ -((x: as: {x}: - rec { - inherit (as) x; - y = x; - } -) 2 {x = 4;} {x = 3;}).y +( + ( + x: as: + { x }: + rec { + inherit (as) x; + y = x; + } + ) + 2 + { x = 4; } + { x = 3; } +).y diff --git a/tests/functional/lang/eval-okay-scope-4.nix b/tests/functional/lang/eval-okay-scope-4.nix index dc8243bc8..ccae8564c 100644 --- a/tests/functional/lang/eval-okay-scope-4.nix +++ b/tests/functional/lang/eval-okay-scope-4.nix @@ -3,8 +3,13 @@ let { x = "a"; y = "b"; - f = {x ? y, y ? x}: x + y; + f = + { + x ? y, + y ? x, + }: + x + y; - body = f {x = "c";} + f {y = "d";}; + body = f { x = "c"; } + f { y = "d"; }; } diff --git a/tests/functional/lang/eval-okay-scope-6.nix b/tests/functional/lang/eval-okay-scope-6.nix index 0995d4e7e..be2cc31a1 100644 --- a/tests/functional/lang/eval-okay-scope-6.nix +++ b/tests/functional/lang/eval-okay-scope-6.nix @@ -1,7 +1,12 @@ let { - f = {x ? y, y ? x}: x + y; + f = + { + x ? y, + y ? x, + }: + x + y; - body = f {x = "c";} + f {y = "d";}; + body = f { x = "c"; } + f { y = "d"; }; } diff --git a/tests/functional/lang/eval-okay-scope-7.nix b/tests/functional/lang/eval-okay-scope-7.nix index 4da02968f..91f22f553 100644 --- a/tests/functional/lang/eval-okay-scope-7.nix +++ b/tests/functional/lang/eval-okay-scope-7.nix @@ -3,4 +3,5 @@ rec { x = { y = 1; }; -}.y +} +.y diff --git a/tests/functional/lang/eval-okay-search-path.nix b/tests/functional/lang/eval-okay-search-path.nix index 6fe33decc..702e1b64c 100644 --- a/tests/functional/lang/eval-okay-search-path.nix +++ b/tests/functional/lang/eval-okay-search-path.nix @@ -6,5 +6,16 @@ assert isFunction (import ); assert length __nixPath == 5; assert length (filter (x: baseNameOf x.path == "dir4") __nixPath) == 1; -import + import + import + import - + (let __nixPath = [ { path = ./dir2; } { path = ./dir1; } ]; in import ) +import ++ import ++ import ++ import ++ ( + let + __nixPath = [ + { path = ./dir2; } + { path = ./dir1; } + ]; + in + import +) diff --git a/tests/functional/lang/eval-okay-sort.nix b/tests/functional/lang/eval-okay-sort.nix index 50aa78e40..412bda4a0 100644 --- a/tests/functional/lang/eval-okay-sort.nix +++ b/tests/functional/lang/eval-okay-sort.nix @@ -1,20 +1,64 @@ with builtins; -[ (sort lessThan [ 483 249 526 147 42 77 ]) - (sort (x: y: y < x) [ 483 249 526 147 42 77 ]) - (sort lessThan [ "foo" "bar" "xyzzy" "fnord" ]) - (sort (x: y: x.key < y.key) - [ { key = 1; value = "foo"; } { key = 2; value = "bar"; } { key = 1; value = "fnord"; } ]) +[ (sort lessThan [ - [ 1 6 ] + 483 + 249 + 526 + 147 + 42 + 77 + ]) + (sort (x: y: y < x) [ + 483 + 249 + 526 + 147 + 42 + 77 + ]) + (sort lessThan [ + "foo" + "bar" + "xyzzy" + "fnord" + ]) + (sort (x: y: x.key < y.key) [ + { + key = 1; + value = "foo"; + } + { + key = 2; + value = "bar"; + } + { + key = 1; + value = "fnord"; + } + ]) + (sort lessThan [ + [ + 1 + 6 + ] [ ] - [ 2 3 ] + [ + 2 + 3 + ] [ 3 ] - [ 1 5 ] + [ + 1 + 5 + ] [ 2 ] [ 1 ] [ ] - [ 1 4 ] + [ + 1 + 4 + ] [ 3 ] ]) ] diff --git a/tests/functional/lang/eval-okay-string.nix b/tests/functional/lang/eval-okay-string.nix index 47cc989ad..d3b743fdb 100644 --- a/tests/functional/lang/eval-okay-string.nix +++ b/tests/functional/lang/eval-okay-string.nix @@ -1,12 +1,13 @@ -"foo" + "bar" - + toString (/a/b + /c/d) - + toString (/foo/bar + "/../xyzzy/." + "/foo.txt") - + ("/../foo" + toString /x/y) - + "escape: \"quote\" \n \\" - + "end +"foo" ++ "bar" ++ toString (/a/b + /c/d) ++ toString (/foo/bar + "/../xyzzy/." + "/foo.txt") ++ ("/../foo" + toString /x/y) ++ "escape: \"quote\" \n \\" ++ "end of line" - + "foo${if true then "b${"a" + "r"}" else "xyzzy"}blaat" - + "foo$bar" - + "$\"$\"" - + "$" ++ "foo${if true then "b${"a" + "r"}" else "xyzzy"}blaat" ++ "foo$bar" ++ "$\"$\"" ++ "$" diff --git a/tests/functional/lang/eval-okay-strings-as-attrs-names.nix b/tests/functional/lang/eval-okay-strings-as-attrs-names.nix index 5e40928db..158dc8e75 100644 --- a/tests/functional/lang/eval-okay-strings-as-attrs-names.nix +++ b/tests/functional/lang/eval-okay-strings-as-attrs-names.nix @@ -14,7 +14,5 @@ let # variable. "foo bar" = 1; -in t1 == "test" - && t2 == "caseok" - && t3 == true - && t4 == ["key 1"] +in +t1 == "test" && t2 == "caseok" && t3 == true && t4 == [ "key 1" ] diff --git a/tests/functional/lang/eval-okay-substring-context.nix b/tests/functional/lang/eval-okay-substring-context.nix index d0ef70d4e..9e9d3a1aa 100644 --- a/tests/functional/lang/eval-okay-substring-context.nix +++ b/tests/functional/lang/eval-okay-substring-context.nix @@ -2,10 +2,15 @@ with builtins; let - s = "${builtins.derivation { name = "test"; builder = "/bin/sh"; system = "x86_64-linux"; }}"; + s = "${builtins.derivation { + name = "test"; + builder = "/bin/sh"; + system = "x86_64-linux"; + }}"; in -if getContext s == getContext "${substring 0 0 s + unsafeDiscardStringContext s}" -then "okay" -else throw "empty substring should preserve context" +if getContext s == getContext "${substring 0 0 s + unsafeDiscardStringContext s}" then + "okay" +else + throw "empty substring should preserve context" diff --git a/tests/functional/lang/eval-okay-tail-call-1.nix b/tests/functional/lang/eval-okay-tail-call-1.nix index a3962ce3f..d3ec0c9ad 100644 --- a/tests/functional/lang/eval-okay-tail-call-1.nix +++ b/tests/functional/lang/eval-okay-tail-call-1.nix @@ -1,3 +1,4 @@ let f = n: if n == 100000 then n else f (n + 1); -in f 0 +in +f 0 diff --git a/tests/functional/lang/eval-okay-tojson.nix b/tests/functional/lang/eval-okay-tojson.nix index ce67943be..863c07663 100644 --- a/tests/functional/lang/eval-okay-tojson.nix +++ b/tests/functional/lang/eval-okay-tojson.nix @@ -1,13 +1,26 @@ -builtins.toJSON - { a = 123; - b = -456; - c = "foo"; - d = "foo\n\"bar\""; - e = true; - f = false; - g = [ 1 2 3 ]; - h = [ "a" [ "b" { "foo\nbar" = {}; } ] ]; - i = 1 + 2; - j = 1.44; - k = { __toString = self: self.a; a = "foo"; }; - } +builtins.toJSON { + a = 123; + b = -456; + c = "foo"; + d = "foo\n\"bar\""; + e = true; + f = false; + g = [ + 1 + 2 + 3 + ]; + h = [ + "a" + [ + "b" + { "foo\nbar" = { }; } + ] + ]; + i = 1 + 2; + j = 1.44; + k = { + __toString = self: self.a; + a = "foo"; + }; +} diff --git a/tests/functional/lang/eval-okay-toxml2.nix b/tests/functional/lang/eval-okay-toxml2.nix index ff1791b30..0d5989a50 100644 --- a/tests/functional/lang/eval-okay-toxml2.nix +++ b/tests/functional/lang/eval-okay-toxml2.nix @@ -1 +1,8 @@ -builtins.toXML [("a" + "b") 10 (rec {x = "x"; y = x;})] +builtins.toXML [ + ("a" + "b") + 10 + (rec { + x = "x"; + y = x; + }) +] diff --git a/tests/functional/lang/eval-okay-tryeval.nix b/tests/functional/lang/eval-okay-tryeval.nix index 629bc440a..22b23d883 100644 --- a/tests/functional/lang/eval-okay-tryeval.nix +++ b/tests/functional/lang/eval-okay-tryeval.nix @@ -1,5 +1,8 @@ { x = builtins.tryEval "x"; - y = builtins.tryEval (assert false; "y"); + y = builtins.tryEval ( + assert false; + "y" + ); z = builtins.tryEval (throw "bla"); } diff --git a/tests/functional/lang/eval-okay-types.nix b/tests/functional/lang/eval-okay-types.nix index 9b58be5d1..0814489ed 100644 --- a/tests/functional/lang/eval-okay-types.nix +++ b/tests/functional/lang/eval-okay-types.nix @@ -1,6 +1,7 @@ with builtins; -[ (isNull null) +[ + (isNull null) (isNull (x: x)) (isFunction (x: x)) (isFunction "fnord") @@ -29,7 +30,11 @@ with builtins; (typeOf "xyzzy") (typeOf null) (typeOf { x = 456; }) - (typeOf [ 1 2 3 ]) + (typeOf [ + 1 + 2 + 3 + ]) (typeOf (x: x)) (typeOf ((x: y: x) 1)) (typeOf map) diff --git a/tests/functional/lang/eval-okay-versions.nix b/tests/functional/lang/eval-okay-versions.nix index e9111f5f4..3456015e5 100644 --- a/tests/functional/lang/eval-okay-versions.nix +++ b/tests/functional/lang/eval-okay-versions.nix @@ -10,10 +10,13 @@ let lt = builtins.sub 0 1; gt = 1; - versionTest = v1: v2: expected: - let d1 = builtins.compareVersions v1 v2; - d2 = builtins.compareVersions v2 v1; - in d1 == builtins.sub 0 d2 && d1 == expected; + versionTest = + v1: v2: expected: + let + d1 = builtins.compareVersions v1 v2; + d2 = builtins.compareVersions v2 v1; + in + d1 == builtins.sub 0 d2 && d1 == expected; tests = [ ((builtins.parseDrvName name1).name == "hello") @@ -40,4 +43,5 @@ let (versionTest "2.3pre1" "2.3q" lt) ]; -in (import ./lib.nix).and tests +in +(import ./lib.nix).and tests diff --git a/tests/functional/lang/eval-okay-xml.nix b/tests/functional/lang/eval-okay-xml.nix index 9ee9f8a0b..9785c66ef 100644 --- a/tests/functional/lang/eval-okay-xml.nix +++ b/tests/functional/lang/eval-okay-xml.nix @@ -10,12 +10,31 @@ rec { c = "foo" + "bar"; - f = {z, x, y}: if y then x else z; + f = + { + z, + x, + y, + }: + if y then x else z; id = x: x; - at = args@{x, y, z}: x; + at = + args@{ + x, + y, + z, + }: + x; - ellipsis = {x, y, z, ...}: x; + ellipsis = + { + x, + y, + z, + ... + }: + x; } diff --git a/tests/functional/lang/eval-okay-zipAttrsWith.nix b/tests/functional/lang/eval-okay-zipAttrsWith.nix index 877d4e5fa..20f689111 100644 --- a/tests/functional/lang/eval-okay-zipAttrsWith.nix +++ b/tests/functional/lang/eval-okay-zipAttrsWith.nix @@ -3,7 +3,6 @@ with import ./lib.nix; let str = builtins.hashString "sha256" "test"; in -builtins.zipAttrsWith - (n: v: { inherit n v; }) - (map (n: { ${builtins.substring n 1 str} = n; }) - (range 0 31)) +builtins.zipAttrsWith (n: v: { inherit n v; }) ( + map (n: { ${builtins.substring n 1 str} = n; }) (range 0 31) +) diff --git a/tests/functional/lang/lib.nix b/tests/functional/lang/lib.nix index 028a53831..126128abe 100644 --- a/tests/functional/lang/lib.nix +++ b/tests/functional/lang/lib.nix @@ -2,60 +2,76 @@ with builtins; rec { - fold = op: nul: list: - if list == [] - then nul - else op (head list) (fold op nul (tail list)); + fold = + op: nul: list: + if list == [ ] then nul else op (head list) (fold op nul (tail list)); - concat = - fold (x: y: x + y) ""; + concat = fold (x: y: x + y) ""; and = fold (x: y: x && y) true; - flatten = x: - if isList x - then fold (x: y: (flatten x) ++ y) [] x - else [x]; + flatten = x: if isList x then fold (x: y: (flatten x) ++ y) [ ] x else [ x ]; sum = foldl' (x: y: add x y) 0; - hasSuffix = ext: fileName: - let lenFileName = stringLength fileName; - lenExt = stringLength ext; - in !(lessThan lenFileName lenExt) && - substring (sub lenFileName lenExt) lenFileName fileName == ext; + hasSuffix = + ext: fileName: + let + lenFileName = stringLength fileName; + lenExt = stringLength ext; + in + !(lessThan lenFileName lenExt) && substring (sub lenFileName lenExt) lenFileName fileName == ext; # Split a list at the given position. - splitAt = pos: list: - if pos == 0 then {first = []; second = list;} else - if list == [] then {first = []; second = [];} else - let res = splitAt (sub pos 1) (tail list); - in {first = [(head list)] ++ res.first; second = res.second;}; + splitAt = + pos: list: + if pos == 0 then + { + first = [ ]; + second = list; + } + else if list == [ ] then + { + first = [ ]; + second = [ ]; + } + else + let + res = splitAt (sub pos 1) (tail list); + in + { + first = [ (head list) ] ++ res.first; + second = res.second; + }; # Stable merge sort. - sortBy = comp: list: - if lessThan 1 (length list) - then + sortBy = + comp: list: + if lessThan 1 (length list) then let split = splitAt (div (length list) 2) list; first = sortBy comp split.first; second = sortBy comp split.second; - in mergeLists comp first second - else list; + in + mergeLists comp first second + else + list; - mergeLists = comp: list1: list2: - if list1 == [] then list2 else - if list2 == [] then list1 else - if comp (head list2) (head list1) then [(head list2)] ++ mergeLists comp list1 (tail list2) else - [(head list1)] ++ mergeLists comp (tail list1) list2; + mergeLists = + comp: list1: list2: + if list1 == [ ] then + list2 + else if list2 == [ ] then + list1 + else if comp (head list2) (head list1) then + [ (head list2) ] ++ mergeLists comp list1 (tail list2) + else + [ (head list1) ] ++ mergeLists comp (tail list1) list2; id = x: x; const = x: y: x; - range = first: last: - if first > last - then [] - else genList (n: first + n) (last - first + 1); + range = first: last: if first > last then [ ] else genList (n: first + n) (last - first + 1); } diff --git a/tests/functional/linux-sandbox-cert-test.nix b/tests/functional/linux-sandbox-cert-test.nix index 2fc083ea9..82989c64f 100644 --- a/tests/functional/linux-sandbox-cert-test.nix +++ b/tests/functional/linux-sandbox-cert-test.nix @@ -22,9 +22,12 @@ mkDerivation ( # derivations being cached, and do not want to compute the right hash. false; ''; - } // { - fixed-output = { outputHash = "sha256:0000000000000000000000000000000000000000000000000000000000000000"; }; + } + // { + fixed-output = { + outputHash = "sha256:0000000000000000000000000000000000000000000000000000000000000000"; + }; normal = { }; - }.${mode} + } + .${mode} ) - diff --git a/tests/functional/multiple-outputs.nix b/tests/functional/multiple-outputs.nix index 6ba7c523d..2c9243097 100644 --- a/tests/functional/multiple-outputs.nix +++ b/tests/functional/multiple-outputs.nix @@ -5,94 +5,111 @@ rec { # Want to ensure that "out" doesn't get a suffix on it's path. nameCheck = mkDerivation { name = "multiple-outputs-a"; - outputs = [ "out" "dev" ]; - builder = builtins.toFile "builder.sh" - '' - mkdir $first $second - test -z $all - echo "first" > $first/file - echo "second" > $second/file - ln -s $first $second/link - ''; + outputs = [ + "out" + "dev" + ]; + builder = builtins.toFile "builder.sh" '' + mkdir $first $second + test -z $all + echo "first" > $first/file + echo "second" > $second/file + ln -s $first $second/link + ''; helloString = "Hello, world!"; }; a = mkDerivation { name = "multiple-outputs-a"; - outputs = [ "first" "second" ]; - builder = builtins.toFile "builder.sh" - '' - mkdir $first $second - test -z $all - echo "first" > $first/file - echo "second" > $second/file - ln -s $first $second/link - ''; + outputs = [ + "first" + "second" + ]; + builder = builtins.toFile "builder.sh" '' + mkdir $first $second + test -z $all + echo "first" > $first/file + echo "second" > $second/file + ln -s $first $second/link + ''; helloString = "Hello, world!"; }; use-a = mkDerivation { name = "use-a"; inherit (a) first second; - builder = builtins.toFile "builder.sh" - '' - cat $first/file $second/file >$out - ''; + builder = builtins.toFile "builder.sh" '' + cat $first/file $second/file >$out + ''; }; b = mkDerivation { - defaultOutput = assert a.second.helloString == "Hello, world!"; a; - firstOutput = assert a.outputName == "first"; a.first.first; - secondOutput = assert a.second.outputName == "second"; a.second.first.first.second.second.first.second; + defaultOutput = + assert a.second.helloString == "Hello, world!"; + a; + firstOutput = + assert a.outputName == "first"; + a.first.first; + secondOutput = + assert a.second.outputName == "second"; + a.second.first.first.second.second.first.second; allOutputs = a.all; name = "multiple-outputs-b"; - builder = builtins.toFile "builder.sh" - '' - mkdir $out - test "$firstOutput $secondOutput" = "$allOutputs" - test "$defaultOutput" = "$firstOutput" - test "$(cat $firstOutput/file)" = "first" - test "$(cat $secondOutput/file)" = "second" - echo "success" > $out/file - ''; + builder = builtins.toFile "builder.sh" '' + mkdir $out + test "$firstOutput $secondOutput" = "$allOutputs" + test "$defaultOutput" = "$firstOutput" + test "$(cat $firstOutput/file)" = "first" + test "$(cat $secondOutput/file)" = "second" + echo "success" > $out/file + ''; }; c = mkDerivation { name = "multiple-outputs-c"; drv = b.drvPath; - builder = builtins.toFile "builder.sh" - '' - mkdir $out - ln -s $drv $out/drv - ''; + builder = builtins.toFile "builder.sh" '' + mkdir $out + ln -s $drv $out/drv + ''; }; d = mkDerivation { name = "multiple-outputs-d"; drv = builtins.unsafeDiscardOutputDependency b.drvPath; - builder = builtins.toFile "builder.sh" - '' - mkdir $out - echo $drv > $out/drv - ''; + builder = builtins.toFile "builder.sh" '' + mkdir $out + echo $drv > $out/drv + ''; }; - cyclic = (mkDerivation { - name = "cyclic-outputs"; - outputs = [ "a" "b" "c" ]; - builder = builtins.toFile "builder.sh" - '' + cyclic = + (mkDerivation { + name = "cyclic-outputs"; + outputs = [ + "a" + "b" + "c" + ]; + builder = builtins.toFile "builder.sh" '' mkdir $a $b $c echo $a > $b/foo echo $b > $c/bar echo $c > $a/baz ''; - }).a; + }).a; e = mkDerivation { name = "multiple-outputs-e"; - outputs = [ "a_a" "b" "c" ]; - meta.outputsToInstall = [ "a_a" "b" ]; + outputs = [ + "a_a" + "b" + "c" + ]; + meta.outputsToInstall = [ + "a_a" + "b" + ]; buildCommand = "mkdir $a_a $b $c"; }; @@ -104,33 +121,37 @@ rec { independent = mkDerivation { name = "multiple-outputs-independent"; - outputs = [ "first" "second" ]; - builder = builtins.toFile "builder.sh" - '' - mkdir $first $second - test -z $all - echo "first" > $first/file - echo "second" > $second/file - ''; + outputs = [ + "first" + "second" + ]; + builder = builtins.toFile "builder.sh" '' + mkdir $first $second + test -z $all + echo "first" > $first/file + echo "second" > $second/file + ''; }; use-independent = mkDerivation { name = "use-independent"; inherit (a) first second; - builder = builtins.toFile "builder.sh" - '' - cat $first/file $second/file >$out - ''; + builder = builtins.toFile "builder.sh" '' + cat $first/file $second/file >$out + ''; }; invalid-output-name-1 = mkDerivation { name = "invalid-output-name-1"; - outputs = [ "out/"]; + outputs = [ "out/" ]; }; invalid-output-name-2 = mkDerivation { name = "invalid-output-name-2"; - outputs = [ "x" "foo$"]; + outputs = [ + "x" + "foo$" + ]; }; } diff --git a/tests/functional/nar-access.nix b/tests/functional/nar-access.nix index 9948abe59..b1e88189a 100644 --- a/tests/functional/nar-access.nix +++ b/tests/functional/nar-access.nix @@ -1,23 +1,22 @@ with import ./config.nix; rec { - a = mkDerivation { - name = "nar-index-a"; - builder = builtins.toFile "builder.sh" - '' - mkdir $out - mkdir $out/foo - touch $out/foo-x - touch $out/foo/bar - touch $out/foo/baz - touch $out/qux - mkdir $out/zyx + a = mkDerivation { + name = "nar-index-a"; + builder = builtins.toFile "builder.sh" '' + mkdir $out + mkdir $out/foo + touch $out/foo-x + touch $out/foo/bar + touch $out/foo/baz + touch $out/qux + mkdir $out/zyx - cat >$out/foo/data <$out/foo/data < $out - '' else '' - cp -r ${../common} ./common - cp ${../common.sh} ./common.sh - cp ${../config.nix} ./config.nix - cp -r ${./.} ./nested-sandboxing + buildCommand = + '' + set -x + set -eu -o pipefail + '' + + ( + if altitude == 0 then + '' + echo Deep enough! > $out + '' + else + '' + cp -r ${../common} ./common + cp ${../common.sh} ./common.sh + cp ${../config.nix} ./config.nix + cp -r ${./.} ./nested-sandboxing - export PATH=${builtins.getEnv "NIX_BIN_DIR"}:$PATH + export PATH=${builtins.getEnv "NIX_BIN_DIR"}:$PATH - export _NIX_TEST_SOURCE_DIR=$PWD - export _NIX_TEST_BUILD_DIR=$PWD + export _NIX_TEST_SOURCE_DIR=$PWD + export _NIX_TEST_BUILD_DIR=$PWD - source common.sh - source ./nested-sandboxing/command.sh + source common.sh + source ./nested-sandboxing/command.sh - runNixBuild ${storeFun} ${toString altitude} >> $out - ''); + runNixBuild ${storeFun} ${toString altitude} >> $out + '' + ); } diff --git a/tests/functional/package.nix b/tests/functional/package.nix index d1582b05d..74c034196 100644 --- a/tests/functional/package.nix +++ b/tests/functional/package.nix @@ -1,103 +1,110 @@ -{ lib -, stdenv -, mkMesonDerivation +{ + lib, + stdenv, + mkMesonDerivation, -, meson -, ninja -, pkg-config + meson, + ninja, + pkg-config, -, jq -, git -, mercurial -, util-linux + jq, + git, + mercurial, + util-linux, -, nix-store -, nix-expr -, nix-cli + nix-store, + nix-expr, + nix-cli, -, busybox-sandbox-shell ? null + busybox-sandbox-shell ? null, -# Configuration Options + # Configuration Options -, pname ? "nix-functional-tests" -, version + pname ? "nix-functional-tests", + version, -# For running the functional tests against a different pre-built Nix. -, test-daemon ? null + # For running the functional tests against a different pre-built Nix. + test-daemon ? null, }: let inherit (lib) fileset; in -mkMesonDerivation (finalAttrs: { - inherit pname version; +mkMesonDerivation ( + finalAttrs: + { + inherit pname version; - workDir = ./.; - fileset = fileset.unions [ - ../../scripts/nix-profile.sh.in - ../../.version - ../../tests/functional - ./. - ]; + workDir = ./.; + fileset = fileset.unions [ + ../../scripts/nix-profile.sh.in + ../../.version + ../../tests/functional + ./. + ]; - # Hack for sake of the dev shell - passthru.externalNativeBuildInputs = [ - meson - ninja - pkg-config + # Hack for sake of the dev shell + passthru.externalNativeBuildInputs = + [ + meson + ninja + pkg-config - jq - git - mercurial - ] ++ lib.optionals stdenv.hostPlatform.isLinux [ - # For various sandboxing tests that needs a statically-linked shell, - # etc. - busybox-sandbox-shell - # For Overlay FS tests need `mount`, `umount`, and `unshare`. - # For `script` command (ensuring a TTY) - # TODO use `unixtools` to be precise over which executables instead? - util-linux - ]; + jq + git + mercurial + ] + ++ lib.optionals stdenv.hostPlatform.isLinux [ + # For various sandboxing tests that needs a statically-linked shell, + # etc. + busybox-sandbox-shell + # For Overlay FS tests need `mount`, `umount`, and `unshare`. + # For `script` command (ensuring a TTY) + # TODO use `unixtools` to be precise over which executables instead? + util-linux + ]; - nativeBuildInputs = finalAttrs.passthru.externalNativeBuildInputs ++ [ - nix-cli - ]; + nativeBuildInputs = finalAttrs.passthru.externalNativeBuildInputs ++ [ + nix-cli + ]; - buildInputs = [ - nix-store - nix-expr - ]; + buildInputs = [ + nix-store + nix-expr + ]; - preConfigure = - # "Inline" .version so it's not a symlink, and includes the suffix. - # Do the meson utils, without modification. - '' - chmod u+w ./.version - echo ${version} > ../../../.version - '' - # TEMP hack for Meson before make is gone, where - # `src/nix-functional-tests` is during the transition a symlink and - # not the actual directory directory. - + '' - cd $(readlink -e $PWD) - echo $PWD | grep tests/functional + preConfigure = + # "Inline" .version so it's not a symlink, and includes the suffix. + # Do the meson utils, without modification. + '' + chmod u+w ./.version + echo ${version} > ../../../.version + '' + # TEMP hack for Meson before make is gone, where + # `src/nix-functional-tests` is during the transition a symlink and + # not the actual directory directory. + + '' + cd $(readlink -e $PWD) + echo $PWD | grep tests/functional + ''; + + mesonCheckFlags = [ + "--print-errorlogs" + ]; + + doCheck = true; + + installPhase = '' + mkdir $out ''; - mesonCheckFlags = [ - "--print-errorlogs" - ]; + meta = { + platforms = lib.platforms.unix; + }; - doCheck = true; - - installPhase = '' - mkdir $out - ''; - - meta = { - platforms = lib.platforms.unix; - }; - -} // lib.optionalAttrs (test-daemon != null) { - NIX_DAEMON_PACKAGE = test-daemon; -}) + } + // lib.optionalAttrs (test-daemon != null) { + NIX_DAEMON_PACKAGE = test-daemon; + } +) diff --git a/tests/functional/parallel.nix b/tests/functional/parallel.nix index 23f142059..0adfe7d8e 100644 --- a/tests/functional/parallel.nix +++ b/tests/functional/parallel.nix @@ -1,19 +1,33 @@ -{sleepTime ? 3}: +{ + sleepTime ? 3, +}: with import ./config.nix; let - mkDrv = text: inputs: mkDerivation { - name = "parallel"; - builder = ./parallel.builder.sh; - inherit text inputs shared sleepTime; - }; + mkDrv = + text: inputs: + mkDerivation { + name = "parallel"; + builder = ./parallel.builder.sh; + inherit + text + inputs + shared + sleepTime + ; + }; - a = mkDrv "a" []; - b = mkDrv "b" [a]; - c = mkDrv "c" [a]; - d = mkDrv "d" [a]; - e = mkDrv "e" [b c d]; + a = mkDrv "a" [ ]; + b = mkDrv "b" [ a ]; + c = mkDrv "c" [ a ]; + d = mkDrv "d" [ a ]; + e = mkDrv "e" [ + b + c + d + ]; -in e +in +e diff --git a/tests/functional/path.nix b/tests/functional/path.nix index 883c3c41b..b554765e8 100644 --- a/tests/functional/path.nix +++ b/tests/functional/path.nix @@ -3,12 +3,12 @@ with import ./config.nix; mkDerivation { name = "filter"; builder = builtins.toFile "builder" "ln -s $input $out"; - input = - builtins.path { - path = ((builtins.getEnv "TEST_ROOT") + "/filterin"); - filter = path: type: - type != "symlink" - && baseNameOf path != "foo" - && !((import ./lang/lib.nix).hasSuffix ".bak" (baseNameOf path)); - }; + input = builtins.path { + path = ((builtins.getEnv "TEST_ROOT") + "/filterin"); + filter = + path: type: + type != "symlink" + && baseNameOf path != "foo" + && !((import ./lang/lib.nix).hasSuffix ".bak" (baseNameOf path)); + }; } diff --git a/tests/functional/readfile-context.nix b/tests/functional/readfile-context.nix index 54cd1afd9..d9880ca32 100644 --- a/tests/functional/readfile-context.nix +++ b/tests/functional/readfile-context.nix @@ -25,4 +25,5 @@ let input = builtins.readFile (dependent + "/file1"); }; -in readDependent +in +readDependent diff --git a/tests/functional/recursive.nix b/tests/functional/recursive.nix index fe438f0ba..be9e55da3 100644 --- a/tests/functional/recursive.nix +++ b/tests/functional/recursive.nix @@ -1,4 +1,6 @@ -let config_nix = /. + "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; in +let + config_nix = /. + "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; +in with import config_nix; mkDerivation rec { @@ -15,7 +17,9 @@ mkDerivation rec { buildCommand = '' mkdir $out - opts="--experimental-features nix-command ${if (NIX_TESTS_CA_BY_DEFAULT == "1") then "--extra-experimental-features ca-derivations" else ""}" + opts="--experimental-features nix-command ${ + if (NIX_TESTS_CA_BY_DEFAULT == "1") then "--extra-experimental-features ca-derivations" else "" + }" PATH=${builtins.getEnv "NIX_BIN_DIR"}:$PATH diff --git a/tests/functional/repl/doc-comment-function.nix b/tests/functional/repl/doc-comment-function.nix index cdd241347..a85d4a99f 100644 --- a/tests/functional/repl/doc-comment-function.nix +++ b/tests/functional/repl/doc-comment-function.nix @@ -1,3 +1,4 @@ -/** A doc comment for a file that only contains a function */ -{ ... }: -{ } +/** + A doc comment for a file that only contains a function +*/ +{ ... }: { } diff --git a/tests/functional/repl/doc-comments.nix b/tests/functional/repl/doc-comments.nix index e91ee0b51..a7a285d48 100644 --- a/tests/functional/repl/doc-comments.nix +++ b/tests/functional/repl/doc-comments.nix @@ -6,55 +6,106 @@ multiply 2 3 => 6 ``` - */ + */ multiply = x: y: x * y; - /**👈 precisely this wide 👉*/ + /** + 👈 precisely this wide 👉 + */ measurement = x: x; - floatedIn = /** This also works. */ + floatedIn = + /** + This also works. + */ x: y: x; - compact=/**boom*/x: x; - - # https://github.com/NixOS/rfcs/blob/master/rfcs/0145-doc-strings.md#ambiguous-placement - /** Ignore!!! */ - unambiguous = - /** Very close */ + compact = + /** + boom + */ x: x; - /** Firmly rigid. */ + # https://github.com/NixOS/rfcs/blob/master/rfcs/0145-doc-strings.md#ambiguous-placement + /** + Ignore!!! + */ + unambiguous = + /** + Very close + */ + x: x; + + /** + Firmly rigid. + */ constant = true; - /** Immovably fixed. */ + /** + Immovably fixed. + */ lib.version = "9000"; - /** Unchangeably constant. */ + /** + Unchangeably constant. + */ lib.attr.empty = { }; lib.attr.undocumented = { }; - nonStrict = /** My syntax is not strict, but I'm strict anyway. */ x: x; - strict = /** I don't have to be strict, but I am anyway. */ { ... }: null; + nonStrict = + /** + My syntax is not strict, but I'm strict anyway. + */ + x: x; + strict = + /** + I don't have to be strict, but I am anyway. + */ + { ... }: null; # Note that pre and post are the same here. I just had to name them somehow. - strictPre = /** Here's one way to do this */ a@{ ... }: a; - strictPost = /** Here's another way to do this */ { ... }@a: a; + strictPre = + /** + Here's one way to do this + */ + a@{ ... }: a; + strictPost = + /** + Here's another way to do this + */ + { ... }@a: a; # TODO - /** You won't see this. */ + /** + You won't see this. + */ curriedArgs = - /** A documented function. */ + /** + A documented function. + */ x: - /** The function returned by applying once */ + /** + The function returned by applying once + */ y: - /** A function body performing summation of two items */ + /** + A function body performing summation of two items + */ x + y; - /** Documented formals (but you won't see this comment) */ + /** + Documented formals (but you won't see this comment) + */ documentedFormals = - /** Finds x */ - { /** The x attribute */ - x - }: x; + /** + Finds x + */ + { + /** + The x attribute + */ + x, + }: + x; } diff --git a/tests/functional/repl/doc-functor.nix b/tests/functional/repl/doc-functor.nix index f526f453f..8a663886c 100644 --- a/tests/functional/repl/doc-functor.nix +++ b/tests/functional/repl/doc-functor.nix @@ -25,14 +25,14 @@ rec { makeOverridable = f: { /** This is a function that can be overridden. - */ + */ __functor = self: f; override = throw "not implemented"; }; /** Compute x^2 - */ + */ square = x: x * x; helper = makeOverridable square; @@ -41,8 +41,14 @@ rec { makeVeryOverridable = f: { /** This is a function that can be overridden. - */ - __functor = self: arg: f arg // { override = throw "not implemented"; overrideAttrs = throw "not implemented"; }; + */ + __functor = + self: arg: + f arg + // { + override = throw "not implemented"; + overrideAttrs = throw "not implemented"; + }; override = throw "not implemented"; }; @@ -64,7 +70,6 @@ rec { */ helper3 = makeVeryOverridable (x: x * x * x); - # ------ # getDoc traverses a potentially infinite structure in case of __functor, so @@ -73,7 +78,7 @@ rec { recursive = { /** This looks bad, but the docs are ok because of the eta expansion. - */ + */ __functor = self: x: self x; }; @@ -81,21 +86,23 @@ rec { /** Docs probably won't work in this case, because the "partial" application of self results in an infinite recursion. - */ + */ __functor = self: self.__functor self; }; - diverging = let - /** - Docs probably won't work in this case, because the "partial" application - of self results in an diverging computation that causes a stack overflow. - It's not an infinite recursion because each call is different. - This must be handled by the documentation retrieval logic, as it - reimplements the __functor invocation to be partial. - */ - f = x: { - __functor = self: (f (x + 1)); - }; - in f null; + diverging = + let + /** + Docs probably won't work in this case, because the "partial" application + of self results in an diverging computation that causes a stack overflow. + It's not an infinite recursion because each call is different. + This must be handled by the documentation retrieval logic, as it + reimplements the __functor invocation to be partial. + */ + f = x: { + __functor = self: (f (x + 1)); + }; + in + f null; } diff --git a/tests/functional/secure-drv-outputs.nix b/tests/functional/secure-drv-outputs.nix index b4ac8ff53..169c3c587 100644 --- a/tests/functional/secure-drv-outputs.nix +++ b/tests/functional/secure-drv-outputs.nix @@ -4,20 +4,18 @@ with import ./config.nix; good = mkDerivation { name = "good"; - builder = builtins.toFile "builder" - '' - mkdir $out - echo > $out/good - ''; + builder = builtins.toFile "builder" '' + mkdir $out + echo > $out/good + ''; }; bad = mkDerivation { name = "good"; - builder = builtins.toFile "builder" - '' - mkdir $out - echo > $out/bad - ''; + builder = builtins.toFile "builder" '' + mkdir $out + echo > $out/bad + ''; }; } diff --git a/tests/functional/shell-hello.nix b/tests/functional/shell-hello.nix index c920d7cb4..470798dd9 100644 --- a/tests/functional/shell-hello.nix +++ b/tests/functional/shell-hello.nix @@ -3,57 +3,56 @@ with import ./config.nix; rec { hello = mkDerivation { name = "hello"; - outputs = [ "out" "dev" ]; + outputs = [ + "out" + "dev" + ]; meta.outputsToInstall = [ "out" ]; - buildCommand = - '' - mkdir -p $out/bin $dev/bin + buildCommand = '' + mkdir -p $out/bin $dev/bin - cat > $out/bin/hello < $out/bin/hello < $dev/bin/hello2 < $dev/bin/hello2 < $out/bin/hello < $out/bin/hello < $out/bin/env <&2 - exit 1 - fi - exec env - EOF - chmod +x $out/bin/env - ''; + cat > $out/bin/env <&2 + exit 1 + fi + exec env + EOF + chmod +x $out/bin/env + ''; }; } diff --git a/tests/functional/shell.nix b/tests/functional/shell.nix index 4b1a0623a..5e9f48818 100644 --- a/tests/functional/shell.nix +++ b/tests/functional/shell.nix @@ -1,102 +1,130 @@ -{ inNixShell ? false, contentAddressed ? false, fooContents ? "foo" }: +{ + inNixShell ? false, + contentAddressed ? false, + fooContents ? "foo", +}: -let cfg = import ./config.nix; in +let + cfg = import ./config.nix; +in with cfg; let mkDerivation = if contentAddressed then - args: cfg.mkDerivation ({ - __contentAddressed = true; - outputHashMode = "recursive"; - outputHashAlgo = "sha256"; - } // args) - else cfg.mkDerivation; + args: + cfg.mkDerivation ( + { + __contentAddressed = true; + outputHashMode = "recursive"; + outputHashAlgo = "sha256"; + } + // args + ) + else + cfg.mkDerivation; in -let pkgs = rec { - setupSh = builtins.toFile "setup" '' - export VAR_FROM_STDENV_SETUP=foo - for pkg in $buildInputs; do - export PATH=$PATH:$pkg/bin - done +let + pkgs = rec { + setupSh = builtins.toFile "setup" '' + export VAR_FROM_STDENV_SETUP=foo + for pkg in $buildInputs; do + export PATH=$PATH:$pkg/bin + done - declare -a arr1=(1 2 "3 4" 5) - declare -a arr2=(x $'\n' $'x\ny') - fun() { - echo blabla - } - runHook() { - eval "''${!1}" - } - ''; - - stdenv = mkDerivation { - name = "stdenv"; - buildCommand = '' - mkdir -p $out - ln -s ${setupSh} $out/setup + declare -a arr1=(1 2 "3 4" 5) + declare -a arr2=(x $'\n' $'x\ny') + fun() { + echo blabla + } + runHook() { + eval "''${!1}" + } ''; - } // { inherit mkDerivation; }; - shellDrv = mkDerivation { - name = "shellDrv"; - builder = "/does/not/exist"; - VAR_FROM_NIX = "bar"; - ASCII_PERCENT = "%"; - ASCII_AT = "@"; - TEST_inNixShell = if inNixShell then "true" else "false"; - FOO = fooContents; - inherit stdenv; - outputs = ["dev" "out"]; - } // { - shellHook = abort "Ignore non-drv shellHook attr"; - }; + stdenv = + mkDerivation { + name = "stdenv"; + buildCommand = '' + mkdir -p $out + ln -s ${setupSh} $out/setup + ''; + } + // { + inherit mkDerivation; + }; - # https://github.com/NixOS/nix/issues/5431 - # See nix-shell.sh - polo = mkDerivation { - name = "polo"; - inherit stdenv; - shellHook = '' - echo Polo + shellDrv = + mkDerivation { + name = "shellDrv"; + builder = "/does/not/exist"; + VAR_FROM_NIX = "bar"; + ASCII_PERCENT = "%"; + ASCII_AT = "@"; + TEST_inNixShell = if inNixShell then "true" else "false"; + FOO = fooContents; + inherit stdenv; + outputs = [ + "dev" + "out" + ]; + } + // { + shellHook = abort "Ignore non-drv shellHook attr"; + }; + + # https://github.com/NixOS/nix/issues/5431 + # See nix-shell.sh + polo = mkDerivation { + name = "polo"; + inherit stdenv; + shellHook = '' + echo Polo + ''; + }; + + # Used by nix-shell -p + runCommand = + name: args: buildCommand: + mkDerivation ( + args + // { + inherit name buildCommand stdenv; + } + ); + + foo = runCommand "foo" { } '' + mkdir -p $out/bin + echo 'echo ${fooContents}' > $out/bin/foo + chmod a+rx $out/bin/foo + ln -s ${shell} $out/bin/bash ''; + + bar = runCommand "bar" { } '' + mkdir -p $out/bin + echo 'echo bar' > $out/bin/bar + chmod a+rx $out/bin/bar + ''; + + bash = shell; + bashInteractive = runCommand "bash" { } '' + mkdir -p $out/bin + ln -s ${shell} $out/bin/bash + ''; + + # ruby "interpreter" that outputs "$@" + ruby = runCommand "ruby" { } '' + mkdir -p $out/bin + echo 'printf %s "$*"' > $out/bin/ruby + chmod a+rx $out/bin/ruby + ''; + + inherit (cfg) shell; + + callPackage = f: args: f (pkgs // args); + + inherit pkgs; }; - - # Used by nix-shell -p - runCommand = name: args: buildCommand: mkDerivation (args // { - inherit name buildCommand stdenv; - }); - - foo = runCommand "foo" {} '' - mkdir -p $out/bin - echo 'echo ${fooContents}' > $out/bin/foo - chmod a+rx $out/bin/foo - ln -s ${shell} $out/bin/bash - ''; - - bar = runCommand "bar" {} '' - mkdir -p $out/bin - echo 'echo bar' > $out/bin/bar - chmod a+rx $out/bin/bar - ''; - - bash = shell; - bashInteractive = runCommand "bash" {} '' - mkdir -p $out/bin - ln -s ${shell} $out/bin/bash - ''; - - # ruby "interpreter" that outputs "$@" - ruby = runCommand "ruby" {} '' - mkdir -p $out/bin - echo 'printf %s "$*"' > $out/bin/ruby - chmod a+rx $out/bin/ruby - ''; - - inherit (cfg) shell; - - callPackage = f: args: f (pkgs // args); - - inherit pkgs; -}; in pkgs +in +pkgs diff --git a/tests/functional/simple-failing.nix b/tests/functional/simple-failing.nix index d176c9c51..6cf29ae38 100644 --- a/tests/functional/simple-failing.nix +++ b/tests/functional/simple-failing.nix @@ -2,11 +2,10 @@ with import ./config.nix; mkDerivation { name = "simple-failing"; - builder = builtins.toFile "builder.sh" - '' - echo "This should fail" - exit 1 - ''; + builder = builtins.toFile "builder.sh" '' + echo "This should fail" + exit 1 + ''; PATH = ""; goodPath = path; } diff --git a/tests/functional/structured-attrs-shell.nix b/tests/functional/structured-attrs-shell.nix index 57c1e6bd2..a819e39cd 100644 --- a/tests/functional/structured-attrs-shell.nix +++ b/tests/functional/structured-attrs-shell.nix @@ -12,8 +12,15 @@ mkDerivation { name = "structured2"; __structuredAttrs = true; inherit stdenv; - outputs = [ "out" "dev" ]; - my.list = [ "a" "b" "c" ]; + outputs = [ + "out" + "dev" + ]; + my.list = [ + "a" + "b" + "c" + ]; exportReferencesGraph.refs = [ dep ]; buildCommand = '' touch ''${outputs[out]}; touch ''${outputs[dev]} diff --git a/tests/functional/structured-attrs.nix b/tests/functional/structured-attrs.nix index e93139a44..4e1984517 100644 --- a/tests/functional/structured-attrs.nix +++ b/tests/functional/structured-attrs.nix @@ -16,7 +16,10 @@ mkDerivation { __structuredAttrs = true; - outputs = [ "out" "dev" ]; + outputs = [ + "out" + "dev" + ]; buildCommand = '' set -x @@ -43,12 +46,24 @@ mkDerivation { [[ $json =~ '"references":[]' ]] ''; - buildInputs = [ "a" "b" "c" 123 "'" "\"" null ]; + buildInputs = [ + "a" + "b" + "c" + 123 + "'" + "\"" + null + ]; hardening.format = true; hardening.fortify = false; - outer.inner = [ 1 2 3 ]; + outer.inner = [ + 1 + 2 + 3 + ]; int = 123456789; diff --git a/tests/functional/undefined-variable.nix b/tests/functional/undefined-variable.nix index 579985497..8e88dd8fe 100644 --- a/tests/functional/undefined-variable.nix +++ b/tests/functional/undefined-variable.nix @@ -1 +1,4 @@ -let f = builtins.toFile "test-file.nix" "asd"; in import f +let + f = builtins.toFile "test-file.nix" "asd"; +in +import f diff --git a/tests/functional/user-envs.nix b/tests/functional/user-envs.nix index 46f8b51dd..cc63812c4 100644 --- a/tests/functional/user-envs.nix +++ b/tests/functional/user-envs.nix @@ -1,5 +1,6 @@ # Some dummy arguments... -{ foo ? "foo" +{ + foo ? "foo", }: with import ./config.nix; @@ -8,27 +9,41 @@ assert foo == "foo"; let - platforms = let x = "foobar"; in [ x x ]; + platforms = + let + x = "foobar"; + in + [ + x + x + ]; - makeDrv = name: progName: (mkDerivation { - name = assert progName != "fail"; name; - inherit progName system; - builder = ./user-envs.builder.sh; - } // { - meta = { - description = "A silly test package with some \${escaped anti-quotation} in it"; - inherit platforms; - }; - }); + makeDrv = + name: progName: + ( + mkDerivation { + name = + assert progName != "fail"; + name; + inherit progName system; + builder = ./user-envs.builder.sh; + } + // { + meta = { + description = "A silly test package with some \${escaped anti-quotation} in it"; + inherit platforms; + }; + } + ); in - [ - (makeDrv "foo-1.0" "foo") - (makeDrv "foo-2.0pre1" "foo") - (makeDrv "bar-0.1" "bar") - (makeDrv "foo-2.0" "foo") - (makeDrv "bar-0.1.1" "bar") - (makeDrv "foo-0.1" "foo" // { meta.priority = 10; }) - (makeDrv "fail-0.1" "fail") - ] +[ + (makeDrv "foo-1.0" "foo") + (makeDrv "foo-2.0pre1" "foo") + (makeDrv "bar-0.1" "bar") + (makeDrv "foo-2.0" "foo") + (makeDrv "bar-0.1.1" "bar") + (makeDrv "foo-0.1" "foo" // { meta.priority = 10; }) + (makeDrv "fail-0.1" "fail") +] diff --git a/tests/installer/default.nix b/tests/installer/default.nix index 4aed6eae4..d48537dd0 100644 --- a/tests/installer/default.nix +++ b/tests/installer/default.nix @@ -1,5 +1,6 @@ -{ binaryTarballs -, nixpkgsFor +{ + binaryTarballs, + nixpkgsFor, }: let @@ -41,8 +42,9 @@ let }; }; - mockChannel = pkgs: - pkgs.runCommandNoCC "mock-channel" {} '' + mockChannel = + pkgs: + pkgs.runCommandNoCC "mock-channel" { } '' mkdir nixexprs mkdir -p $out/channel echo -n 'someContent' > nixexprs/someFile @@ -54,14 +56,14 @@ let images = { /* - "ubuntu-14-04" = { - image = import { - url = "https://app.vagrantup.com/ubuntu/boxes/trusty64/versions/20190514.0.0/providers/virtualbox.box"; - hash = "sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="; + "ubuntu-14-04" = { + image = import { + url = "https://app.vagrantup.com/ubuntu/boxes/trusty64/versions/20190514.0.0/providers/virtualbox.box"; + hash = "sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="; + }; + rootDisk = "box-disk1.vmdk"; + system = "x86_64-linux"; }; - rootDisk = "box-disk1.vmdk"; - system = "x86_64-linux"; - }; */ "ubuntu-16-04" = { @@ -95,14 +97,14 @@ let # Currently fails with 'error while loading shared libraries: # libsodium.so.23: cannot stat shared object: Invalid argument'. /* - "rhel-6" = { - image = import { - url = "https://app.vagrantup.com/generic/boxes/rhel6/versions/4.1.12/providers/libvirt.box"; - hash = "sha256-QwzbvRoRRGqUCQptM7X/InRWFSP2sqwRt2HaaO6zBGM="; + "rhel-6" = { + image = import { + url = "https://app.vagrantup.com/generic/boxes/rhel6/versions/4.1.12/providers/libvirt.box"; + hash = "sha256-QwzbvRoRRGqUCQptM7X/InRWFSP2sqwRt2HaaO6zBGM="; + }; + rootDisk = "box.img"; + system = "x86_64-linux"; }; - rootDisk = "box.img"; - system = "x86_64-linux"; - }; */ "rhel-7" = { @@ -137,12 +139,18 @@ let }; - makeTest = imageName: testName: - let image = images.${imageName}; in + makeTest = + imageName: testName: + let + image = images.${imageName}; + in with nixpkgsFor.${image.system}.native; - runCommand - "installer-test-${imageName}-${testName}" - { buildInputs = [ qemu_kvm openssh ]; + runCommand "installer-test-${imageName}-${testName}" + { + buildInputs = [ + qemu_kvm + openssh + ]; image = image.image; postBoot = image.postBoot or ""; installScript = installScripts.${testName}.script; @@ -247,9 +255,6 @@ let in -builtins.mapAttrs (imageName: image: - { ${image.system} = builtins.mapAttrs (testName: test: - makeTest imageName testName - ) installScripts; - } -) images +builtins.mapAttrs (imageName: image: { + ${image.system} = builtins.mapAttrs (testName: test: makeTest imageName testName) installScripts; +}) images diff --git a/tests/nixos/authorization.nix b/tests/nixos/authorization.nix index fdeae06ed..6540e9fa3 100644 --- a/tests/nixos/authorization.nix +++ b/tests/nixos/authorization.nix @@ -4,8 +4,11 @@ nodes.machine = { virtualisation.writableStore = true; # TODO add a test without allowed-users setting. allowed-users is uncommon among NixOS users. - nix.settings.allowed-users = ["alice" "bob"]; - nix.settings.trusted-users = ["alice"]; + nix.settings.allowed-users = [ + "alice" + "bob" + ]; + nix.settings.trusted-users = [ "alice" ]; users.users.alice.isNormalUser = true; users.users.bob.isNormalUser = true; @@ -15,80 +18,80 @@ }; testScript = - let - pathFour = "/nix/store/20xfy868aiic0r0flgzq4n5dq1yvmxkn-four"; - in - '' - machine.wait_for_unit("multi-user.target") - machine.succeed(""" - exec 1>&2 - echo kSELDhobKaF8/VdxIxdP7EQe+Q > one - diff $(nix store add-file one) one - """) - machine.succeed(""" - su --login alice -c ' - set -x - cd ~ - echo ehHtmfuULXYyBV6NBk6QUi8iE0 > two - ls - diff $(echo $(nix store add-file two)) two' 1>&2 - """) - machine.succeed(""" - su --login bob -c ' - set -x - cd ~ - echo 0Jw8RNp7cK0W2AdNbcquofcOVk > three - diff $(nix store add-file three) three - ' 1>&2 - """) - - # We're going to check that a path is not created - machine.succeed(""" - ! [[ -e ${pathFour} ]] - """) - machine.succeed(""" - su --login mallory -c ' - set -x - cd ~ - echo 5mgtDj0ohrWkT50TLR0f4tIIxY > four; - (! nix store add-file four 2>&1) | grep -F "cannot open connection to remote store" - (! nix store add-file four 2>&1) | grep -F "Connection reset by peer" - ! [[ -e ${pathFour} ]] - ' 1>&2 - """) - - # Check that the file _can_ be added, and matches the expected path we were checking - machine.succeed(""" - exec 1>&2 - echo 5mgtDj0ohrWkT50TLR0f4tIIxY > four - four="$(nix store add-file four)" - diff $four four - diff <(echo $four) <(echo ${pathFour}) - """) - - machine.succeed(""" - su --login alice -c 'nix-store --verify --repair' - """) - - machine.succeed(""" - set -x - su --login bob -c '(! nix-store --verify --repair 2>&1)' | tee diag 1>&2 - grep -F "you are not privileged to repair paths" diag - """) - - machine.succeed(""" - set -x - su --login mallory -c ' - nix-store --generate-binary-cache-key cache1.example.org sk1 pk1 - (! nix store sign --key-file sk1 ${pathFour} 2>&1)' | tee diag 1>&2 - grep -F "cannot open connection to remote store 'daemon'" diag - """) - - machine.succeed(""" + let + pathFour = "/nix/store/20xfy868aiic0r0flgzq4n5dq1yvmxkn-four"; + in + '' + machine.wait_for_unit("multi-user.target") + machine.succeed(""" + exec 1>&2 + echo kSELDhobKaF8/VdxIxdP7EQe+Q > one + diff $(nix store add-file one) one + """) + machine.succeed(""" + su --login alice -c ' + set -x + cd ~ + echo ehHtmfuULXYyBV6NBk6QUi8iE0 > two + ls + diff $(echo $(nix store add-file two)) two' 1>&2 + """) + machine.succeed(""" su --login bob -c ' - nix-store --generate-binary-cache-key cache1.example.org sk1 pk1 - nix store sign --key-file sk1 ${pathFour} - ' - """) - ''; + set -x + cd ~ + echo 0Jw8RNp7cK0W2AdNbcquofcOVk > three + diff $(nix store add-file three) three + ' 1>&2 + """) + + # We're going to check that a path is not created + machine.succeed(""" + ! [[ -e ${pathFour} ]] + """) + machine.succeed(""" + su --login mallory -c ' + set -x + cd ~ + echo 5mgtDj0ohrWkT50TLR0f4tIIxY > four; + (! nix store add-file four 2>&1) | grep -F "cannot open connection to remote store" + (! nix store add-file four 2>&1) | grep -F "Connection reset by peer" + ! [[ -e ${pathFour} ]] + ' 1>&2 + """) + + # Check that the file _can_ be added, and matches the expected path we were checking + machine.succeed(""" + exec 1>&2 + echo 5mgtDj0ohrWkT50TLR0f4tIIxY > four + four="$(nix store add-file four)" + diff $four four + diff <(echo $four) <(echo ${pathFour}) + """) + + machine.succeed(""" + su --login alice -c 'nix-store --verify --repair' + """) + + machine.succeed(""" + set -x + su --login bob -c '(! nix-store --verify --repair 2>&1)' | tee diag 1>&2 + grep -F "you are not privileged to repair paths" diag + """) + + machine.succeed(""" + set -x + su --login mallory -c ' + nix-store --generate-binary-cache-key cache1.example.org sk1 pk1 + (! nix store sign --key-file sk1 ${pathFour} 2>&1)' | tee diag 1>&2 + grep -F "cannot open connection to remote store 'daemon'" diag + """) + + machine.succeed(""" + su --login bob -c ' + nix-store --generate-binary-cache-key cache1.example.org sk1 pk1 + nix store sign --key-file sk1 ${pathFour} + ' + """) + ''; } diff --git a/tests/nixos/ca-fd-leak/default.nix b/tests/nixos/ca-fd-leak/default.nix index a6ae72adc..902aacdc6 100644 --- a/tests/nixos/ca-fd-leak/default.nix +++ b/tests/nixos/ca-fd-leak/default.nix @@ -27,12 +27,15 @@ let # domain socket. # Compiled statically so that we can easily send it to the VM and use it # inside the build sandbox. - sender = pkgs.runCommandWith { - name = "sender"; - stdenv = pkgs.pkgsStatic.stdenv; - } '' - $CC -static -o $out ${./sender.c} - ''; + sender = + pkgs.runCommandWith + { + name = "sender"; + stdenv = pkgs.pkgsStatic.stdenv; + } + '' + $CC -static -o $out ${./sender.c} + ''; # Okay, so we have a file descriptor shipped out of the FOD now. But the # Nix store is read-only, right? .. Well, yeah. But this file descriptor @@ -47,44 +50,57 @@ in name = "ca-fd-leak"; nodes.machine = - { config, lib, pkgs, ... }: - { virtualisation.writableStore = true; + { + config, + lib, + pkgs, + ... + }: + { + virtualisation.writableStore = true; nix.settings.substituters = lib.mkForce [ ]; - virtualisation.additionalPaths = [ pkgs.busybox-sandbox-shell sender smuggler pkgs.socat ]; + virtualisation.additionalPaths = [ + pkgs.busybox-sandbox-shell + sender + smuggler + pkgs.socat + ]; }; - testScript = { nodes }: '' - start_all() + testScript = + { nodes }: + '' + start_all() - machine.succeed("echo hello") - # Start the smuggler server - machine.succeed("${smuggler}/bin/smuggler ${socketName} >&2 &") + machine.succeed("echo hello") + # Start the smuggler server + machine.succeed("${smuggler}/bin/smuggler ${socketName} >&2 &") - # Build the smuggled derivation. - # This will connect to the smuggler server and send it the file descriptor - machine.succeed(r""" - nix-build -E ' - builtins.derivation { - name = "smuggled"; - system = builtins.currentSystem; - # look ma, no tricks! - outputHashMode = "flat"; - outputHashAlgo = "sha256"; - outputHash = builtins.hashString "sha256" "hello, world\n"; - builder = "${pkgs.busybox-sandbox-shell}/bin/sh"; - args = [ "-c" "echo \"hello, world\" > $out; ''${${sender}} ${socketName}" ]; - }' - """.strip()) + # Build the smuggled derivation. + # This will connect to the smuggler server and send it the file descriptor + machine.succeed(r""" + nix-build -E ' + builtins.derivation { + name = "smuggled"; + system = builtins.currentSystem; + # look ma, no tricks! + outputHashMode = "flat"; + outputHashAlgo = "sha256"; + outputHash = builtins.hashString "sha256" "hello, world\n"; + builder = "${pkgs.busybox-sandbox-shell}/bin/sh"; + args = [ "-c" "echo \"hello, world\" > $out; ''${${sender}} ${socketName}" ]; + }' + """.strip()) - # Tell the smuggler server that we're done - machine.execute("echo done | ${pkgs.socat}/bin/socat - ABSTRACT-CONNECT:${socketName}") + # Tell the smuggler server that we're done + machine.execute("echo done | ${pkgs.socat}/bin/socat - ABSTRACT-CONNECT:${socketName}") - # Check that the file was not modified - machine.succeed(r""" - cat ./result - test "$(cat ./result)" = "hello, world" - """.strip()) - ''; + # Check that the file was not modified + machine.succeed(r""" + cat ./result + test "$(cat ./result)" = "hello, world" + """.strip()) + ''; } diff --git a/tests/nixos/cgroups/default.nix b/tests/nixos/cgroups/default.nix index b8febbf4b..a6b4bca8c 100644 --- a/tests/nixos/cgroups/default.nix +++ b/tests/nixos/cgroups/default.nix @@ -3,38 +3,39 @@ { name = "cgroups"; - nodes = - { - host = - { config, pkgs, ... }: - { virtualisation.additionalPaths = [ pkgs.stdenvNoCC ]; - nix.extraOptions = - '' - extra-experimental-features = nix-command auto-allocate-uids cgroups - extra-system-features = uid-range - ''; - nix.settings.use-cgroups = true; - nix.nixPath = [ "nixpkgs=${nixpkgs}" ]; - }; - }; + nodes = { + host = + { config, pkgs, ... }: + { + virtualisation.additionalPaths = [ pkgs.stdenvNoCC ]; + nix.extraOptions = '' + extra-experimental-features = nix-command auto-allocate-uids cgroups + extra-system-features = uid-range + ''; + nix.settings.use-cgroups = true; + nix.nixPath = [ "nixpkgs=${nixpkgs}" ]; + }; + }; - testScript = { nodes }: '' - start_all() + testScript = + { nodes }: + '' + start_all() - host.wait_for_unit("multi-user.target") + host.wait_for_unit("multi-user.target") - # Start build in background - host.execute("NIX_REMOTE=daemon nix build --auto-allocate-uids --file ${./hang.nix} >&2 &") - service = "/sys/fs/cgroup/system.slice/nix-daemon.service" + # Start build in background + host.execute("NIX_REMOTE=daemon nix build --auto-allocate-uids --file ${./hang.nix} >&2 &") + service = "/sys/fs/cgroup/system.slice/nix-daemon.service" - # Wait for cgroups to be created - host.succeed(f"until [ -e {service}/nix-daemon ]; do sleep 1; done", timeout=30) - host.succeed(f"until [ -e {service}/nix-build-uid-* ]; do sleep 1; done", timeout=30) + # Wait for cgroups to be created + host.succeed(f"until [ -e {service}/nix-daemon ]; do sleep 1; done", timeout=30) + host.succeed(f"until [ -e {service}/nix-build-uid-* ]; do sleep 1; done", timeout=30) - # Check that there aren't processes where there shouldn't be, and that there are where there should be - host.succeed(f'[ -z "$(cat {service}/cgroup.procs)" ]') - host.succeed(f'[ -n "$(cat {service}/nix-daemon/cgroup.procs)" ]') - host.succeed(f'[ -n "$(cat {service}/nix-build-uid-*/cgroup.procs)" ]') - ''; + # Check that there aren't processes where there shouldn't be, and that there are where there should be + host.succeed(f'[ -z "$(cat {service}/cgroup.procs)" ]') + host.succeed(f'[ -n "$(cat {service}/nix-daemon/cgroup.procs)" ]') + host.succeed(f'[ -n "$(cat {service}/nix-build-uid-*/cgroup.procs)" ]') + ''; } diff --git a/tests/nixos/cgroups/hang.nix b/tests/nixos/cgroups/hang.nix index cefe2d031..d7b337b0c 100644 --- a/tests/nixos/cgroups/hang.nix +++ b/tests/nixos/cgroups/hang.nix @@ -1,9 +1,10 @@ { }: -with import {}; +with import { }; runCommand "hang" - { requiredSystemFeatures = "uid-range"; + { + requiredSystemFeatures = "uid-range"; } '' sleep infinity diff --git a/tests/nixos/chroot-store.nix b/tests/nixos/chroot-store.nix index 4b167fc38..f89a20bc4 100644 --- a/tests/nixos/chroot-store.nix +++ b/tests/nixos/chroot-store.nix @@ -1,31 +1,45 @@ -{ lib, config, nixpkgs, ... }: +{ + lib, + config, + nixpkgs, + ... +}: let pkgs = config.nodes.machine.nixpkgs.pkgs; pkgA = pkgs.hello; pkgB = pkgs.cowsay; -in { +in +{ name = "chroot-store"; - nodes = - { machine = - { config, lib, pkgs, ... }: - { virtualisation.writableStore = true; - virtualisation.additionalPaths = [ pkgA ]; - environment.systemPackages = [ pkgB ]; - nix.extraOptions = "experimental-features = nix-command"; - }; - }; + nodes = { + machine = + { + config, + lib, + pkgs, + ... + }: + { + virtualisation.writableStore = true; + virtualisation.additionalPaths = [ pkgA ]; + environment.systemPackages = [ pkgB ]; + nix.extraOptions = "experimental-features = nix-command"; + }; + }; - testScript = { nodes }: '' - # fmt: off - start_all() + testScript = + { nodes }: + '' + # fmt: off + start_all() - machine.succeed("nix copy --no-check-sigs --to /tmp/nix ${pkgA}") + machine.succeed("nix copy --no-check-sigs --to /tmp/nix ${pkgA}") - machine.succeed("nix shell --store /tmp/nix ${pkgA} --command hello >&2") + machine.succeed("nix shell --store /tmp/nix ${pkgA} --command hello >&2") - # Test that /nix/store is available via an overlayfs mount. - machine.succeed("nix shell --store /tmp/nix ${pkgA} --command cowsay foo >&2") - ''; + # Test that /nix/store is available via an overlayfs mount. + machine.succeed("nix shell --store /tmp/nix ${pkgA} --command cowsay foo >&2") + ''; } diff --git a/tests/nixos/containers/containers.nix b/tests/nixos/containers/containers.nix index 6773f5628..b590dc849 100644 --- a/tests/nixos/containers/containers.nix +++ b/tests/nixos/containers/containers.nix @@ -4,60 +4,67 @@ { name = "containers"; - nodes = - { - host = - { config, lib, pkgs, nodes, ... }: - { virtualisation.writableStore = true; - virtualisation.diskSize = 2048; - virtualisation.additionalPaths = - [ pkgs.stdenvNoCC - (import ./systemd-nspawn.nix { inherit nixpkgs; }).toplevel - ]; - virtualisation.memorySize = 4096; - nix.settings.substituters = lib.mkForce [ ]; - nix.extraOptions = - '' - extra-experimental-features = nix-command auto-allocate-uids cgroups - extra-system-features = uid-range - ''; - nix.nixPath = [ "nixpkgs=${nixpkgs}" ]; - }; - }; + nodes = { + host = + { + config, + lib, + pkgs, + nodes, + ... + }: + { + virtualisation.writableStore = true; + virtualisation.diskSize = 2048; + virtualisation.additionalPaths = [ + pkgs.stdenvNoCC + (import ./systemd-nspawn.nix { inherit nixpkgs; }).toplevel + ]; + virtualisation.memorySize = 4096; + nix.settings.substituters = lib.mkForce [ ]; + nix.extraOptions = '' + extra-experimental-features = nix-command auto-allocate-uids cgroups + extra-system-features = uid-range + ''; + nix.nixPath = [ "nixpkgs=${nixpkgs}" ]; + }; + }; - testScript = { nodes }: '' - start_all() + testScript = + { nodes }: + '' + start_all() - host.succeed("nix --version >&2") + host.succeed("nix --version >&2") - # Test that 'id' gives the expected result in various configurations. + # Test that 'id' gives the expected result in various configurations. - # Existing UIDs, sandbox. - host.succeed("nix build --no-auto-allocate-uids --sandbox -L --offline --impure --file ${./id-test.nix} --argstr name id-test-1") - host.succeed("[[ $(cat ./result) = 'uid=1000(nixbld) gid=100(nixbld) groups=100(nixbld)' ]]") + # Existing UIDs, sandbox. + host.succeed("nix build --no-auto-allocate-uids --sandbox -L --offline --impure --file ${./id-test.nix} --argstr name id-test-1") + host.succeed("[[ $(cat ./result) = 'uid=1000(nixbld) gid=100(nixbld) groups=100(nixbld)' ]]") - # Existing UIDs, no sandbox. - host.succeed("nix build --no-auto-allocate-uids --no-sandbox -L --offline --impure --file ${./id-test.nix} --argstr name id-test-2") - host.succeed("[[ $(cat ./result) = 'uid=30001(nixbld1) gid=30000(nixbld) groups=30000(nixbld)' ]]") + # Existing UIDs, no sandbox. + host.succeed("nix build --no-auto-allocate-uids --no-sandbox -L --offline --impure --file ${./id-test.nix} --argstr name id-test-2") + host.succeed("[[ $(cat ./result) = 'uid=30001(nixbld1) gid=30000(nixbld) groups=30000(nixbld)' ]]") - # Auto-allocated UIDs, sandbox. - host.succeed("nix build --auto-allocate-uids --sandbox -L --offline --impure --file ${./id-test.nix} --argstr name id-test-3") - host.succeed("[[ $(cat ./result) = 'uid=1000(nixbld) gid=100(nixbld) groups=100(nixbld)' ]]") + # Auto-allocated UIDs, sandbox. + host.succeed("nix build --auto-allocate-uids --sandbox -L --offline --impure --file ${./id-test.nix} --argstr name id-test-3") + host.succeed("[[ $(cat ./result) = 'uid=1000(nixbld) gid=100(nixbld) groups=100(nixbld)' ]]") - # Auto-allocated UIDs, no sandbox. - host.succeed("nix build --auto-allocate-uids --no-sandbox -L --offline --impure --file ${./id-test.nix} --argstr name id-test-4") - host.succeed("[[ $(cat ./result) = 'uid=872415232 gid=30000(nixbld) groups=30000(nixbld)' ]]") + # Auto-allocated UIDs, no sandbox. + host.succeed("nix build --auto-allocate-uids --no-sandbox -L --offline --impure --file ${./id-test.nix} --argstr name id-test-4") + host.succeed("[[ $(cat ./result) = 'uid=872415232 gid=30000(nixbld) groups=30000(nixbld)' ]]") - # Auto-allocated UIDs, UID range, sandbox. - host.succeed("nix build --auto-allocate-uids --sandbox -L --offline --impure --file ${./id-test.nix} --argstr name id-test-5 --arg uidRange true") - host.succeed("[[ $(cat ./result) = 'uid=0(root) gid=0(root) groups=0(root)' ]]") + # Auto-allocated UIDs, UID range, sandbox. + host.succeed("nix build --auto-allocate-uids --sandbox -L --offline --impure --file ${./id-test.nix} --argstr name id-test-5 --arg uidRange true") + host.succeed("[[ $(cat ./result) = 'uid=0(root) gid=0(root) groups=0(root)' ]]") - # Auto-allocated UIDs, UID range, no sandbox. - host.fail("nix build --auto-allocate-uids --no-sandbox -L --offline --impure --file ${./id-test.nix} --argstr name id-test-6 --arg uidRange true") + # Auto-allocated UIDs, UID range, no sandbox. + host.fail("nix build --auto-allocate-uids --no-sandbox -L --offline --impure --file ${./id-test.nix} --argstr name id-test-6 --arg uidRange true") - # Run systemd-nspawn in a Nix build. - host.succeed("nix build --auto-allocate-uids --sandbox -L --offline --impure --file ${./systemd-nspawn.nix} --argstr nixpkgs ${nixpkgs}") - host.succeed("[[ $(cat ./result/msg) = 'Hello World' ]]") - ''; + # Run systemd-nspawn in a Nix build. + host.succeed("nix build --auto-allocate-uids --sandbox -L --offline --impure --file ${./systemd-nspawn.nix} --argstr nixpkgs ${nixpkgs}") + host.succeed("[[ $(cat ./result/msg) = 'Hello World' ]]") + ''; } diff --git a/tests/nixos/containers/id-test.nix b/tests/nixos/containers/id-test.nix index 8eb9d38f9..2139327ad 100644 --- a/tests/nixos/containers/id-test.nix +++ b/tests/nixos/containers/id-test.nix @@ -1,8 +1,10 @@ -{ name, uidRange ? false }: +{ + name, + uidRange ? false, +}: -with import {}; +with import { }; -runCommand name - { requiredSystemFeatures = if uidRange then ["uid-range"] else []; - } - "id; id > $out" +runCommand name { + requiredSystemFeatures = if uidRange then [ "uid-range" ] else [ ]; +} "id; id > $out" diff --git a/tests/nixos/containers/systemd-nspawn.nix b/tests/nixos/containers/systemd-nspawn.nix index 1dad4ebd7..4516f4e13 100644 --- a/tests/nixos/containers/systemd-nspawn.nix +++ b/tests/nixos/containers/systemd-nspawn.nix @@ -2,7 +2,8 @@ let - machine = { config, pkgs, ... }: + machine = + { config, pkgs, ... }: { system.stateVersion = "22.05"; boot.isContainer = true; @@ -31,10 +32,12 @@ let }; }; - cfg = (import (nixpkgs + "/nixos/lib/eval-config.nix") { - modules = [ machine ]; - system = "x86_64-linux"; - }); + cfg = ( + import (nixpkgs + "/nixos/lib/eval-config.nix") { + modules = [ machine ]; + system = "x86_64-linux"; + } + ); config = cfg.config; @@ -43,7 +46,8 @@ in with cfg._module.args.pkgs; runCommand "test" - { buildInputs = [ config.system.path ]; + { + buildInputs = [ config.system.path ]; requiredSystemFeatures = [ "uid-range" ]; toplevel = config.system.build.toplevel; } diff --git a/tests/nixos/default.nix b/tests/nixos/default.nix index 8e0cb1b22..ca72034ec 100644 --- a/tests/nixos/default.nix +++ b/tests/nixos/default.nix @@ -1,17 +1,26 @@ -{ lib, nixpkgs, nixpkgsFor, self }: +{ + lib, + nixpkgs, + nixpkgsFor, + self, +}: let nixos-lib = import (nixpkgs + "/nixos/lib") { }; - noTests = pkg: pkg.overrideAttrs ( - finalAttrs: prevAttrs: { - doCheck = false; - doInstallCheck = false; - }); + noTests = + pkg: + pkg.overrideAttrs ( + finalAttrs: prevAttrs: { + doCheck = false; + doInstallCheck = false; + } + ); # https://nixos.org/manual/nixos/unstable/index.html#sec-calling-nixos-tests - runNixOSTestFor = system: test: + runNixOSTestFor = + system: test: (nixos-lib.runTest { imports = [ test @@ -36,44 +45,61 @@ let # allow running tests against older nix versions via `nix eval --apply` # Example: # nix build "$(nix eval --raw --impure .#hydraJobs.tests.fetch-git --apply 't: (t.forNix "2.19.2").drvPath')^*" - forNix = nixVersion: runNixOSTestFor system { - imports = [test]; - defaults.nixpkgs.overlays = [(curr: prev: { - nix = let - packages = (builtins.getFlake "nix/${nixVersion}").packages.${system}; - in packages.nix-cli or packages.nix; - })]; - }; + forNix = + nixVersion: + runNixOSTestFor system { + imports = [ test ]; + defaults.nixpkgs.overlays = [ + (curr: prev: { + nix = + let + packages = (builtins.getFlake "nix/${nixVersion}").packages.${system}; + in + packages.nix-cli or packages.nix; + }) + ]; + }; }; # Checks that a NixOS configuration does not contain any references to our # locally defined Nix version. - checkOverrideNixVersion = { pkgs, lib, ... }: { - # pkgs.nix: The new Nix in this repo - # We disallow it, to make sure we don't accidentally use it. - system.forbiddenDependenciesRegexes = [ - (lib.strings.escapeRegex "nix-${pkgs.nix.version}") - ]; - }; + checkOverrideNixVersion = + { pkgs, lib, ... }: + { + # pkgs.nix: The new Nix in this repo + # We disallow it, to make sure we don't accidentally use it. + system.forbiddenDependenciesRegexes = [ + (lib.strings.escapeRegex "nix-${pkgs.nix.version}") + ]; + }; - otherNixes.nix_2_3.setNixPackage = { lib, pkgs, ... }: { - imports = [ checkOverrideNixVersion ]; - nix.package = lib.mkForce pkgs.nixVersions.nix_2_3; - }; + otherNixes.nix_2_3.setNixPackage = + { lib, pkgs, ... }: + { + imports = [ checkOverrideNixVersion ]; + nix.package = lib.mkForce pkgs.nixVersions.nix_2_3; + }; - otherNixes.nix_2_13.setNixPackage = { lib, pkgs, ... }: { - imports = [ checkOverrideNixVersion ]; - nix.package = lib.mkForce ( - self.inputs.nixpkgs-23-11.legacyPackages.${pkgs.stdenv.hostPlatform.system}.nixVersions.nix_2_13.overrideAttrs (o: { - meta = o.meta // { knownVulnerabilities = []; }; - }) - ); - }; + otherNixes.nix_2_13.setNixPackage = + { lib, pkgs, ... }: + { + imports = [ checkOverrideNixVersion ]; + nix.package = lib.mkForce ( + self.inputs.nixpkgs-23-11.legacyPackages.${pkgs.stdenv.hostPlatform.system}.nixVersions.nix_2_13.overrideAttrs + (o: { + meta = o.meta // { + knownVulnerabilities = [ ]; + }; + }) + ); + }; - otherNixes.nix_2_18.setNixPackage = { lib, pkgs, ... }: { - imports = [ checkOverrideNixVersion ]; - nix.package = lib.mkForce pkgs.nixVersions.nix_2_18; - }; + otherNixes.nix_2_18.setNixPackage = + { lib, pkgs, ... }: + { + imports = [ checkOverrideNixVersion ]; + nix.package = lib.mkForce pkgs.nixVersions.nix_2_18; + }; in @@ -86,30 +112,37 @@ in } // lib.concatMapAttrs ( - nixVersion: { setNixPackage, ... }: + nixVersion: + { setNixPackage, ... }: { "remoteBuilds_remote_${nixVersion}" = runNixOSTestFor "x86_64-linux" { name = "remoteBuilds_remote_${nixVersion}"; imports = [ ./remote-builds.nix ]; - builders.config = { lib, pkgs, ... }: { - imports = [ setNixPackage ]; - }; + builders.config = + { lib, pkgs, ... }: + { + imports = [ setNixPackage ]; + }; }; "remoteBuilds_local_${nixVersion}" = runNixOSTestFor "x86_64-linux" { name = "remoteBuilds_local_${nixVersion}"; imports = [ ./remote-builds.nix ]; - nodes.client = { lib, pkgs, ... }: { - imports = [ setNixPackage ]; - }; + nodes.client = + { lib, pkgs, ... }: + { + imports = [ setNixPackage ]; + }; }; "remoteBuildsSshNg_remote_${nixVersion}" = runNixOSTestFor "x86_64-linux" { name = "remoteBuildsSshNg_remote_${nixVersion}"; imports = [ ./remote-builds-ssh-ng.nix ]; - builders.config = { lib, pkgs, ... }: { - imports = [ setNixPackage ]; - }; + builders.config = + { lib, pkgs, ... }: + { + imports = [ setNixPackage ]; + }; }; # FIXME: these tests don't work yet @@ -143,9 +176,7 @@ in containers = runNixOSTestFor "x86_64-linux" ./containers/containers.nix; - setuid = lib.genAttrs - ["x86_64-linux"] - (system: runNixOSTestFor system ./setuid.nix); + setuid = lib.genAttrs [ "x86_64-linux" ] (system: runNixOSTestFor system ./setuid.nix); fetch-git = runNixOSTestFor "x86_64-linux" ./fetch-git; diff --git a/tests/nixos/fetch-git/default.nix b/tests/nixos/fetch-git/default.nix index 1d6bcb637..329fb463e 100644 --- a/tests/nixos/fetch-git/default.nix +++ b/tests/nixos/fetch-git/default.nix @@ -7,26 +7,27 @@ ]; /* - Test cases + Test cases - Test cases are automatically imported from ./test-cases/{name} + Test cases are automatically imported from ./test-cases/{name} - The following is set up automatically for each test case: - - a repo with the {name} is created on the gitea server - - a repo with the {name} is created on the client - - the client repo is configured to push to the server repo + The following is set up automatically for each test case: + - a repo with the {name} is created on the gitea server + - a repo with the {name} is created on the client + - the client repo is configured to push to the server repo - Python variables: - - repo.path: the path to the directory of the client repo - - repo.git: the git command with the client repo as the working directory - - repo.remote: the url to the server repo + Python variables: + - repo.path: the path to the directory of the client repo + - repo.git: the git command with the client repo as the working directory + - repo.remote: the url to the server repo */ - testCases = - map - (testCaseName: {...}: { + testCases = map ( + testCaseName: + { ... }: + { imports = [ (./test-cases + "/${testCaseName}") ]; # ensures tests are named like their directories they are defined in name = testCaseName; - }) - (lib.attrNames (builtins.readDir ./test-cases)); + } + ) (lib.attrNames (builtins.readDir ./test-cases)); } diff --git a/tests/nixos/fetch-git/test-cases/http-auth/default.nix b/tests/nixos/fetch-git/test-cases/http-auth/default.nix index d483d54fb..7ad9a8914 100644 --- a/tests/nixos/fetch-git/test-cases/http-auth/default.nix +++ b/tests/nixos/fetch-git/test-cases/http-auth/default.nix @@ -5,7 +5,8 @@ script = '' # add a file to the repo client.succeed(f""" - echo ${config.name /* to make the git tree and store path unique */} > {repo.path}/test-case \ + echo ${config.name # to make the git tree and store path unique + } > {repo.path}/test-case \ && echo lutyabrook > {repo.path}/new-york-state \ && {repo.git} add test-case new-york-state \ && {repo.git} commit -m 'commit1' diff --git a/tests/nixos/fetch-git/test-cases/http-simple/default.nix b/tests/nixos/fetch-git/test-cases/http-simple/default.nix index dcab8067e..51b3882b5 100644 --- a/tests/nixos/fetch-git/test-cases/http-simple/default.nix +++ b/tests/nixos/fetch-git/test-cases/http-simple/default.nix @@ -4,7 +4,8 @@ script = '' # add a file to the repo client.succeed(f""" - echo ${config.name /* to make the git tree and store path unique */} > {repo.path}/test-case \ + echo ${config.name # to make the git tree and store path unique + } > {repo.path}/test-case \ && echo chiang-mai > {repo.path}/thailand \ && {repo.git} add test-case thailand \ && {repo.git} commit -m 'commit1' diff --git a/tests/nixos/fetch-git/test-cases/ssh-simple/default.nix b/tests/nixos/fetch-git/test-cases/ssh-simple/default.nix index f5fba1698..89285d00e 100644 --- a/tests/nixos/fetch-git/test-cases/ssh-simple/default.nix +++ b/tests/nixos/fetch-git/test-cases/ssh-simple/default.nix @@ -4,7 +4,8 @@ script = '' # add a file to the repo client.succeed(f""" - echo ${config.name /* to make the git tree and store path unique */} > {repo.path}/test-case \ + echo ${config.name # to make the git tree and store path unique + } > {repo.path}/test-case \ && echo chiang-mai > {repo.path}/thailand \ && {repo.git} add test-case thailand \ && {repo.git} commit -m 'commit1' diff --git a/tests/nixos/fetch-git/testsupport/gitea-repo.nix b/tests/nixos/fetch-git/testsupport/gitea-repo.nix index e9f4adcc1..c8244207f 100644 --- a/tests/nixos/fetch-git/testsupport/gitea-repo.nix +++ b/tests/nixos/fetch-git/testsupport/gitea-repo.nix @@ -8,25 +8,27 @@ let boolPyLiteral = b: if b then "True" else "False"; - testCaseExtension = { config, ... }: { - options = { - repo.enable = mkOption { - type = types.bool; - default = true; - description = "Whether to provide a repo variable - automatic repo creation."; + testCaseExtension = + { config, ... }: + { + options = { + repo.enable = mkOption { + type = types.bool; + default = true; + description = "Whether to provide a repo variable - automatic repo creation."; + }; + repo.private = mkOption { + type = types.bool; + default = false; + description = "Whether the repo should be private."; + }; }; - repo.private = mkOption { - type = types.bool; - default = false; - description = "Whether the repo should be private."; + config = mkIf config.repo.enable { + setupScript = '' + repo = Repo("${config.name}", private=${boolPyLiteral config.repo.private}) + ''; }; }; - config = mkIf config.repo.enable { - setupScript = '' - repo = Repo("${config.name}", private=${boolPyLiteral config.repo.private}) - ''; - }; - }; in { options = { diff --git a/tests/nixos/fetch-git/testsupport/gitea.nix b/tests/nixos/fetch-git/testsupport/gitea.nix index cf87bb466..9409acff7 100644 --- a/tests/nixos/fetch-git/testsupport/gitea.nix +++ b/tests/nixos/fetch-git/testsupport/gitea.nix @@ -1,4 +1,11 @@ -{ lib, nixpkgs, system, pkgs, ... }: let +{ + lib, + nixpkgs, + system, + pkgs, + ... +}: +let clientPrivateKey = pkgs.writeText "id_ed25519" '' -----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW @@ -9,41 +16,52 @@ -----END OPENSSH PRIVATE KEY----- ''; - clientPublicKey = - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFt5a8eH8BYZYjoQhzXGVKKHJe1pw1D0p7O2Vb9VTLzB"; + clientPublicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFt5a8eH8BYZYjoQhzXGVKKHJe1pw1D0p7O2Vb9VTLzB"; -in { +in +{ imports = [ ../testsupport/setup.nix ../testsupport/gitea-repo.nix ]; nodes = { - gitea = { pkgs, ... }: { - services.gitea.enable = true; - services.gitea.settings.service.DISABLE_REGISTRATION = true; - services.gitea.settings.log.LEVEL = "Info"; - services.gitea.settings.database.LOG_SQL = false; - services.openssh.enable = true; - networking.firewall.allowedTCPPorts = [ 3000 ]; - environment.systemPackages = [ pkgs.git pkgs.gitea ]; - - users.users.root.openssh.authorizedKeys.keys = [clientPublicKey]; - - # TODO: remove this after updating to nixos-23.11 - nixpkgs.pkgs = lib.mkForce (import nixpkgs { - inherit system; - config.permittedInsecurePackages = [ - "gitea-1.19.4" + gitea = + { pkgs, ... }: + { + services.gitea.enable = true; + services.gitea.settings.service.DISABLE_REGISTRATION = true; + services.gitea.settings.log.LEVEL = "Info"; + services.gitea.settings.database.LOG_SQL = false; + services.openssh.enable = true; + networking.firewall.allowedTCPPorts = [ 3000 ]; + environment.systemPackages = [ + pkgs.git + pkgs.gitea ]; - }); - }; - client = { pkgs, ... }: { - environment.systemPackages = [ pkgs.git ]; - }; - }; - defaults = { pkgs, ... }: { - environment.systemPackages = [ pkgs.jq ]; + + users.users.root.openssh.authorizedKeys.keys = [ clientPublicKey ]; + + # TODO: remove this after updating to nixos-23.11 + nixpkgs.pkgs = lib.mkForce ( + import nixpkgs { + inherit system; + config.permittedInsecurePackages = [ + "gitea-1.19.4" + ]; + } + ); + }; + client = + { pkgs, ... }: + { + environment.systemPackages = [ pkgs.git ]; + }; }; + defaults = + { pkgs, ... }: + { + environment.systemPackages = [ pkgs.jq ]; + }; setupScript = '' import shlex diff --git a/tests/nixos/fetch-git/testsupport/setup.nix b/tests/nixos/fetch-git/testsupport/setup.nix index a81d5614b..c13386c72 100644 --- a/tests/nixos/fetch-git/testsupport/setup.nix +++ b/tests/nixos/fetch-git/testsupport/setup.nix @@ -1,11 +1,16 @@ -{ lib, config, extendModules, ... }: +{ + lib, + config, + extendModules, + ... +}: let inherit (lib) mkOption types ; - indent = lib.replaceStrings ["\n"] ["\n "]; + indent = lib.replaceStrings [ "\n" ] [ "\n " ]; execTestCase = testCase: '' @@ -35,37 +40,39 @@ in description = '' The test cases. See `testScript`. ''; - type = types.listOf (types.submodule { - options.name = mkOption { - type = types.str; - description = '' - The name of the test case. + type = types.listOf ( + types.submodule { + options.name = mkOption { + type = types.str; + description = '' + The name of the test case. - A repository with that name will be set up on the gitea server and locally. - ''; - }; - options.description = mkOption { - type = types.str; - description = '' - A description of the test case. - ''; - }; - options.setupScript = mkOption { - type = types.lines; - description = '' - Python code that runs before the test case. - ''; - default = ""; - }; - options.script = mkOption { - type = types.lines; - description = '' - Python code that runs the test. + A repository with that name will be set up on the gitea server and locally. + ''; + }; + options.description = mkOption { + type = types.str; + description = '' + A description of the test case. + ''; + }; + options.setupScript = mkOption { + type = types.lines; + description = '' + Python code that runs before the test case. + ''; + default = ""; + }; + options.script = mkOption { + type = types.lines; + description = '' + Python code that runs the test. - Variables defined by the global `setupScript`, as well as `testCases.*.setupScript` will be available here. - ''; - }; - }); + Variables defined by the global `setupScript`, as well as `testCases.*.setupScript` will be available here. + ''; + }; + } + ); }; }; @@ -74,10 +81,12 @@ in environment.variables = { _NIX_FORCE_HTTP = "1"; }; - nix.settings.experimental-features = ["nix-command" "flakes"]; + nix.settings.experimental-features = [ + "nix-command" + "flakes" + ]; }; - setupScript = '' - ''; + setupScript = ''''; testScript = '' start_all(); diff --git a/tests/nixos/fetchurl.nix b/tests/nixos/fetchurl.nix index bfae8deec..e8663debb 100644 --- a/tests/nixos/fetchurl.nix +++ b/tests/nixos/fetchurl.nix @@ -5,16 +5,20 @@ let - makeTlsCert = name: pkgs.runCommand name { - nativeBuildInputs = with pkgs; [ openssl ]; - } '' - mkdir -p $out - openssl req -x509 \ - -subj '/CN=${name}/' -days 49710 \ - -addext 'subjectAltName = DNS:${name}' \ - -keyout "$out/key.pem" -newkey ed25519 \ - -out "$out/cert.pem" -noenc - ''; + makeTlsCert = + name: + pkgs.runCommand name + { + nativeBuildInputs = with pkgs; [ openssl ]; + } + '' + mkdir -p $out + openssl req -x509 \ + -subj '/CN=${name}/' -days 49710 \ + -addext 'subjectAltName = DNS:${name}' \ + -keyout "$out/key.pem" -newkey ed25519 \ + -out "$out/cert.pem" -noenc + ''; goodCert = makeTlsCert "good"; badCert = makeTlsCert "bad"; @@ -25,39 +29,44 @@ in name = "fetchurl"; nodes = { - machine = { pkgs, ... }: { - services.nginx = { - enable = true; + machine = + { pkgs, ... }: + { + services.nginx = { + enable = true; - virtualHosts."good" = { - addSSL = true; - sslCertificate = "${goodCert}/cert.pem"; - sslCertificateKey = "${goodCert}/key.pem"; - root = pkgs.runCommand "nginx-root" {} '' - mkdir "$out" - echo 'hello world' > "$out/index.html" - ''; + virtualHosts."good" = { + addSSL = true; + sslCertificate = "${goodCert}/cert.pem"; + sslCertificateKey = "${goodCert}/key.pem"; + root = pkgs.runCommand "nginx-root" { } '' + mkdir "$out" + echo 'hello world' > "$out/index.html" + ''; + }; + + virtualHosts."bad" = { + addSSL = true; + sslCertificate = "${badCert}/cert.pem"; + sslCertificateKey = "${badCert}/key.pem"; + root = pkgs.runCommand "nginx-root" { } '' + mkdir "$out" + echo 'foobar' > "$out/index.html" + ''; + }; }; - virtualHosts."bad" = { - addSSL = true; - sslCertificate = "${badCert}/cert.pem"; - sslCertificateKey = "${badCert}/key.pem"; - root = pkgs.runCommand "nginx-root" {} '' - mkdir "$out" - echo 'foobar' > "$out/index.html" - ''; - }; + security.pki.certificateFiles = [ "${goodCert}/cert.pem" ]; + + networking.hosts."127.0.0.1" = [ + "good" + "bad" + ]; + + virtualisation.writableStore = true; + + nix.settings.experimental-features = "nix-command"; }; - - security.pki.certificateFiles = [ "${goodCert}/cert.pem" ]; - - networking.hosts."127.0.0.1" = [ "good" "bad" ]; - - virtualisation.writableStore = true; - - nix.settings.experimental-features = "nix-command"; - }; }; testScript = '' diff --git a/tests/nixos/fsync.nix b/tests/nixos/fsync.nix index 99ac2b25d..e215e5b3c 100644 --- a/tests/nixos/fsync.nix +++ b/tests/nixos/fsync.nix @@ -1,4 +1,10 @@ -{ lib, config, nixpkgs, pkgs, ... }: +{ + lib, + config, + nixpkgs, + pkgs, + ... +}: let pkg1 = pkgs.go; @@ -8,32 +14,44 @@ in name = "fsync"; nodes.machine = - { config, lib, pkgs, ... }: - { virtualisation.emptyDiskImages = [ 1024 ]; + { + config, + lib, + pkgs, + ... + }: + { + virtualisation.emptyDiskImages = [ 1024 ]; environment.systemPackages = [ pkg1 ]; nix.settings.experimental-features = [ "nix-command" ]; nix.settings.fsync-store-paths = true; nix.settings.require-sigs = false; - boot.supportedFilesystems = [ "ext4" "btrfs" "xfs" ]; + boot.supportedFilesystems = [ + "ext4" + "btrfs" + "xfs" + ]; }; - testScript = { nodes }: '' - # fmt: off - for fs in ("ext4", "btrfs", "xfs"): - machine.succeed("mkfs.{} {} /dev/vdb".format(fs, "-F" if fs == "ext4" else "-f")) - machine.succeed("mkdir -p /mnt") - machine.succeed("mount /dev/vdb /mnt") - machine.succeed("sync") - machine.succeed("nix copy --offline ${pkg1} --to /mnt") - machine.crash() + testScript = + { nodes }: + '' + # fmt: off + for fs in ("ext4", "btrfs", "xfs"): + machine.succeed("mkfs.{} {} /dev/vdb".format(fs, "-F" if fs == "ext4" else "-f")) + machine.succeed("mkdir -p /mnt") + machine.succeed("mount /dev/vdb /mnt") + machine.succeed("sync") + machine.succeed("nix copy --offline ${pkg1} --to /mnt") + machine.crash() - machine.start() - machine.wait_for_unit("multi-user.target") - machine.succeed("mkdir -p /mnt") - machine.succeed("mount /dev/vdb /mnt") - machine.succeed("nix path-info --offline --store /mnt ${pkg1}") - machine.succeed("nix store verify --all --store /mnt --no-trust") + machine.start() + machine.wait_for_unit("multi-user.target") + machine.succeed("mkdir -p /mnt") + machine.succeed("mount /dev/vdb /mnt") + machine.succeed("nix path-info --offline --store /mnt ${pkg1}") + machine.succeed("nix store verify --all --store /mnt --no-trust") - machine.succeed("umount /dev/vdb") - ''; + machine.succeed("umount /dev/vdb") + ''; } diff --git a/tests/nixos/functional/as-trusted-user.nix b/tests/nixos/functional/as-trusted-user.nix index d6f825697..25c1b399c 100644 --- a/tests/nixos/functional/as-trusted-user.nix +++ b/tests/nixos/functional/as-trusted-user.nix @@ -4,7 +4,9 @@ imports = [ ./common.nix ]; nodes.machine = { - users.users.alice = { isNormalUser = true; }; + users.users.alice = { + isNormalUser = true; + }; nix.settings.trusted-users = [ "alice" ]; }; @@ -15,4 +17,4 @@ su --login --command "run-test-suite" alice >&2 """) ''; -} \ No newline at end of file +} diff --git a/tests/nixos/functional/as-user.nix b/tests/nixos/functional/as-user.nix index 1443f6e6c..b93c8d798 100644 --- a/tests/nixos/functional/as-user.nix +++ b/tests/nixos/functional/as-user.nix @@ -4,7 +4,9 @@ imports = [ ./common.nix ]; nodes.machine = { - users.users.alice = { isNormalUser = true; }; + users.users.alice = { + isNormalUser = true; + }; }; testScript = '' diff --git a/tests/nixos/functional/common.nix b/tests/nixos/functional/common.nix index 561271ba0..f3cab4725 100644 --- a/tests/nixos/functional/common.nix +++ b/tests/nixos/functional/common.nix @@ -2,9 +2,11 @@ let # FIXME (roberth) reference issue - inputDerivation = pkg: (pkg.overrideAttrs (o: { - disallowedReferences = [ ]; - })).inputDerivation; + inputDerivation = + pkg: + (pkg.overrideAttrs (o: { + disallowedReferences = [ ]; + })).inputDerivation; in { @@ -12,59 +14,63 @@ in # we skip it to save time. skipTypeCheck = true; - nodes.machine = { config, pkgs, ... }: { + nodes.machine = + { config, pkgs, ... }: + { - virtualisation.writableStore = true; - system.extraDependencies = [ - (inputDerivation config.nix.package) - ]; + virtualisation.writableStore = true; + system.extraDependencies = [ + (inputDerivation config.nix.package) + ]; - nix.settings.substituters = lib.mkForce []; + nix.settings.substituters = lib.mkForce [ ]; - environment.systemPackages = let - run-test-suite = pkgs.writeShellApplication { - name = "run-test-suite"; - runtimeInputs = [ - pkgs.meson - pkgs.ninja - pkgs.jq + environment.systemPackages = + let + run-test-suite = pkgs.writeShellApplication { + name = "run-test-suite"; + runtimeInputs = [ + pkgs.meson + pkgs.ninja + pkgs.jq + pkgs.git + + # Want to avoid `/run/current-system/sw/bin/bash` because we + # want a store path. Likewise for coreutils. + pkgs.bash + pkgs.coreutils + ]; + text = '' + set -x + + cat /proc/sys/fs/file-max + ulimit -Hn + ulimit -Sn + + cd ~ + + cp -r ${pkgs.nixComponents.nix-functional-tests.src} nix + chmod -R +w nix + + chmod u+w nix/.version + echo ${pkgs.nixComponents.version} > nix/.version + + export isTestOnNixOS=1 + + export NIX_REMOTE_=daemon + export NIX_REMOTE=daemon + + export NIX_STORE=${builtins.storeDir} + + meson setup nix/tests/functional build + cd build + meson test -j1 --print-errorlogs + ''; + }; + in + [ + run-test-suite pkgs.git - - # Want to avoid `/run/current-system/sw/bin/bash` because we - # want a store path. Likewise for coreutils. - pkgs.bash - pkgs.coreutils ]; - text = '' - set -x - - cat /proc/sys/fs/file-max - ulimit -Hn - ulimit -Sn - - cd ~ - - cp -r ${pkgs.nixComponents.nix-functional-tests.src} nix - chmod -R +w nix - - chmod u+w nix/.version - echo ${pkgs.nixComponents.version} > nix/.version - - export isTestOnNixOS=1 - - export NIX_REMOTE_=daemon - export NIX_REMOTE=daemon - - export NIX_STORE=${builtins.storeDir} - - meson setup nix/tests/functional build - cd build - meson test -j1 --print-errorlogs - ''; - }; - in [ - run-test-suite - pkgs.git - ]; - }; + }; } diff --git a/tests/nixos/functional/symlinked-home.nix b/tests/nixos/functional/symlinked-home.nix index 57c45d5d5..900543d0c 100644 --- a/tests/nixos/functional/symlinked-home.nix +++ b/tests/nixos/functional/symlinked-home.nix @@ -16,7 +16,9 @@ imports = [ ./common.nix ]; nodes.machine = { - users.users.alice = { isNormalUser = true; }; + users.users.alice = { + isNormalUser = true; + }; }; testScript = '' diff --git a/tests/nixos/git-submodules.nix b/tests/nixos/git-submodules.nix index a82ddf418..5b1d9ed5f 100644 --- a/tests/nixos/git-submodules.nix +++ b/tests/nixos/git-submodules.nix @@ -6,68 +6,74 @@ config = { name = lib.mkDefault "git-submodules"; - nodes = - { - remote = - { config, pkgs, ... }: - { - services.openssh.enable = true; - environment.systemPackages = [ pkgs.git ]; - }; + nodes = { + remote = + { config, pkgs, ... }: + { + services.openssh.enable = true; + environment.systemPackages = [ pkgs.git ]; + }; - client = - { config, lib, pkgs, ... }: - { - programs.ssh.extraConfig = "ConnectTimeout 30"; - environment.systemPackages = [ pkgs.git ]; - nix.extraOptions = "experimental-features = nix-command flakes"; - }; - }; + client = + { + config, + lib, + pkgs, + ... + }: + { + programs.ssh.extraConfig = "ConnectTimeout 30"; + environment.systemPackages = [ pkgs.git ]; + nix.extraOptions = "experimental-features = nix-command flakes"; + }; + }; - testScript = { nodes }: '' - # fmt: off - import subprocess + testScript = + { nodes }: + '' + # fmt: off + import subprocess - start_all() + start_all() - # Create an SSH key on the client. - subprocess.run([ - "${hostPkgs.openssh}/bin/ssh-keygen", "-t", "ed25519", "-f", "key", "-N", "" - ], capture_output=True, check=True) - client.succeed("mkdir -p -m 700 /root/.ssh") - client.copy_from_host("key", "/root/.ssh/id_ed25519") - client.succeed("chmod 600 /root/.ssh/id_ed25519") + # Create an SSH key on the client. + subprocess.run([ + "${hostPkgs.openssh}/bin/ssh-keygen", "-t", "ed25519", "-f", "key", "-N", "" + ], capture_output=True, check=True) + client.succeed("mkdir -p -m 700 /root/.ssh") + client.copy_from_host("key", "/root/.ssh/id_ed25519") + client.succeed("chmod 600 /root/.ssh/id_ed25519") - # Install the SSH key on the builders. - client.wait_for_unit("network-online.target") + # Install the SSH key on the builders. + client.wait_for_unit("network-online.target") - remote.succeed("mkdir -p -m 700 /root/.ssh") - remote.copy_from_host("key.pub", "/root/.ssh/authorized_keys") - remote.wait_for_unit("sshd") - remote.wait_for_unit("multi-user.target") - remote.wait_for_unit("network-online.target") - client.wait_for_unit("network-online.target") - client.succeed(f"ssh -o StrictHostKeyChecking=no {remote.name} 'echo hello world'") + remote.succeed("mkdir -p -m 700 /root/.ssh") + remote.copy_from_host("key.pub", "/root/.ssh/authorized_keys") + remote.wait_for_unit("sshd") + remote.wait_for_unit("multi-user.target") + remote.wait_for_unit("network-online.target") + client.wait_for_unit("network-online.target") + client.succeed(f"ssh -o StrictHostKeyChecking=no {remote.name} 'echo hello world'") - remote.succeed(""" - git init bar - git -C bar config user.email foobar@example.com - git -C bar config user.name Foobar - echo test >> bar/content - git -C bar add content - git -C bar commit -m 'Initial commit' - """) + remote.succeed(""" + git init bar + git -C bar config user.email foobar@example.com + git -C bar config user.name Foobar + echo test >> bar/content + git -C bar add content + git -C bar commit -m 'Initial commit' + """) - client.succeed(f""" - git init foo - git -C foo config user.email foobar@example.com - git -C foo config user.name Foobar - git -C foo submodule add root@{remote.name}:/tmp/bar sub - git -C foo add sub - git -C foo commit -m 'Add submodule' - """) + client.succeed(f""" + git init foo + git -C foo config user.email foobar@example.com + git -C foo config user.name Foobar + git -C foo submodule add root@{remote.name}:/tmp/bar sub + git -C foo add sub + git -C foo commit -m 'Add submodule' + """) - client.succeed("nix --flake-registry \"\" flake prefetch 'git+file:///tmp/foo?submodules=1&ref=master'") - ''; + client.succeed("nix --flake-registry \"\" flake prefetch 'git+file:///tmp/foo?submodules=1&ref=master'") + ''; }; } diff --git a/tests/nixos/github-flakes.nix b/tests/nixos/github-flakes.nix index 69d1df410..dcba464a3 100644 --- a/tests/nixos/github-flakes.nix +++ b/tests/nixos/github-flakes.nix @@ -1,21 +1,25 @@ -{ lib, config, nixpkgs, ... }: +{ + lib, + config, + nixpkgs, + ... +}: let pkgs = config.nodes.client.nixpkgs.pkgs; # Generate a fake root CA and a fake api.github.com / github.com / channels.nixos.org certificate. - cert = pkgs.runCommand "cert" { nativeBuildInputs = [ pkgs.openssl ]; } - '' - mkdir -p $out + cert = pkgs.runCommand "cert" { nativeBuildInputs = [ pkgs.openssl ]; } '' + mkdir -p $out - openssl genrsa -out ca.key 2048 - openssl req -new -x509 -days 36500 -key ca.key \ - -subj "/C=NL/ST=Denial/L=Springfield/O=Dis/CN=Root CA" -out $out/ca.crt + openssl genrsa -out ca.key 2048 + openssl req -new -x509 -days 36500 -key ca.key \ + -subj "/C=NL/ST=Denial/L=Springfield/O=Dis/CN=Root CA" -out $out/ca.crt - openssl req -newkey rsa:2048 -nodes -keyout $out/server.key \ - -subj "/C=CN/ST=Denial/L=Springfield/O=Dis/CN=github.com" -out server.csr - openssl x509 -req -extfile <(printf "subjectAltName=DNS:api.github.com,DNS:github.com,DNS:channels.nixos.org") \ - -days 36500 -in server.csr -CA $out/ca.crt -CAkey ca.key -CAcreateserial -out $out/server.crt - ''; + openssl req -newkey rsa:2048 -nodes -keyout $out/server.key \ + -subj "/C=CN/ST=Denial/L=Springfield/O=Dis/CN=github.com" -out server.csr + openssl x509 -req -extfile <(printf "subjectAltName=DNS:api.github.com,DNS:github.com,DNS:channels.nixos.org") \ + -days 36500 -in server.csr -CA $out/ca.crt -CAkey ca.key -CAcreateserial -out $out/server.crt + ''; registry = pkgs.writeTextFile { name = "registry"; @@ -53,168 +57,190 @@ let private-flake-rev = "9f1dd0df5b54a7dc75b618034482ed42ce34383d"; - private-flake-api = pkgs.runCommand "private-flake" {} - '' - mkdir -p $out/{commits,tarball} + private-flake-api = pkgs.runCommand "private-flake" { } '' + mkdir -p $out/{commits,tarball} - # Setup https://docs.github.com/en/rest/commits/commits#get-a-commit - echo '{"sha": "${private-flake-rev}", "commit": {"tree": {"sha": "ffffffffffffffffffffffffffffffffffffffff"}}}' > $out/commits/HEAD + # Setup https://docs.github.com/en/rest/commits/commits#get-a-commit + echo '{"sha": "${private-flake-rev}", "commit": {"tree": {"sha": "ffffffffffffffffffffffffffffffffffffffff"}}}' > $out/commits/HEAD - # Setup tarball download via API - dir=private-flake - mkdir $dir - echo '{ outputs = {...}: {}; }' > $dir/flake.nix - tar cfz $out/tarball/${private-flake-rev} $dir --hard-dereference - ''; + # Setup tarball download via API + dir=private-flake + mkdir $dir + echo '{ outputs = {...}: {}; }' > $dir/flake.nix + tar cfz $out/tarball/${private-flake-rev} $dir --hard-dereference + ''; - nixpkgs-api = pkgs.runCommand "nixpkgs-flake" {} - '' - mkdir -p $out/commits + nixpkgs-api = pkgs.runCommand "nixpkgs-flake" { } '' + mkdir -p $out/commits - # Setup https://docs.github.com/en/rest/commits/commits#get-a-commit - echo '{"sha": "${nixpkgs.rev}", "commit": {"tree": {"sha": "ffffffffffffffffffffffffffffffffffffffff"}}}' > $out/commits/HEAD - ''; + # Setup https://docs.github.com/en/rest/commits/commits#get-a-commit + echo '{"sha": "${nixpkgs.rev}", "commit": {"tree": {"sha": "ffffffffffffffffffffffffffffffffffffffff"}}}' > $out/commits/HEAD + ''; - archive = pkgs.runCommand "nixpkgs-flake" {} - '' - mkdir -p $out/archive + archive = pkgs.runCommand "nixpkgs-flake" { } '' + mkdir -p $out/archive - dir=NixOS-nixpkgs-${nixpkgs.shortRev} - cp -prd ${nixpkgs} $dir - # Set the correct timestamp in the tarball. - find $dir -print0 | xargs -0 touch -h -t ${builtins.substring 0 12 nixpkgs.lastModifiedDate}.${builtins.substring 12 2 nixpkgs.lastModifiedDate} -- - tar cfz $out/archive/${nixpkgs.rev}.tar.gz $dir --hard-dereference - ''; + dir=NixOS-nixpkgs-${nixpkgs.shortRev} + cp -prd ${nixpkgs} $dir + # Set the correct timestamp in the tarball. + find $dir -print0 | xargs -0 touch -h -t ${builtins.substring 0 12 nixpkgs.lastModifiedDate}.${ + builtins.substring 12 2 nixpkgs.lastModifiedDate + } -- + tar cfz $out/archive/${nixpkgs.rev}.tar.gz $dir --hard-dereference + ''; in { name = "github-flakes"; - nodes = - { - github = - { config, pkgs, ... }: - { networking.firewall.allowedTCPPorts = [ 80 443 ]; + nodes = { + github = + { config, pkgs, ... }: + { + networking.firewall.allowedTCPPorts = [ + 80 + 443 + ]; - services.httpd.enable = true; - services.httpd.adminAddr = "foo@example.org"; - services.httpd.extraConfig = '' - ErrorLog syslog:local6 - ''; - services.httpd.virtualHosts."channels.nixos.org" = - { forceSSL = true; - sslServerKey = "${cert}/server.key"; - sslServerCert = "${cert}/server.crt"; - servedDirs = - [ { urlPath = "/"; - dir = registry; - } - ]; - }; - services.httpd.virtualHosts."api.github.com" = - { forceSSL = true; - sslServerKey = "${cert}/server.key"; - sslServerCert = "${cert}/server.crt"; - servedDirs = - [ { urlPath = "/repos/NixOS/nixpkgs"; - dir = nixpkgs-api; - } - { urlPath = "/repos/fancy-enterprise/private-flake"; - dir = private-flake-api; - } - ]; - }; - services.httpd.virtualHosts."github.com" = - { forceSSL = true; - sslServerKey = "${cert}/server.key"; - sslServerCert = "${cert}/server.crt"; - servedDirs = - [ { urlPath = "/NixOS/nixpkgs"; - dir = archive; - } - ]; - }; + services.httpd.enable = true; + services.httpd.adminAddr = "foo@example.org"; + services.httpd.extraConfig = '' + ErrorLog syslog:local6 + ''; + services.httpd.virtualHosts."channels.nixos.org" = { + forceSSL = true; + sslServerKey = "${cert}/server.key"; + sslServerCert = "${cert}/server.crt"; + servedDirs = [ + { + urlPath = "/"; + dir = registry; + } + ]; }; - - client = - { config, lib, pkgs, nodes, ... }: - { virtualisation.writableStore = true; - virtualisation.diskSize = 2048; - virtualisation.additionalPaths = [ pkgs.hello pkgs.fuse ]; - virtualisation.memorySize = 4096; - nix.settings.substituters = lib.mkForce [ ]; - nix.extraOptions = "experimental-features = nix-command flakes"; - networking.hosts.${(builtins.head nodes.github.networking.interfaces.eth1.ipv4.addresses).address} = - [ "channels.nixos.org" "api.github.com" "github.com" ]; - security.pki.certificateFiles = [ "${cert}/ca.crt" ]; + services.httpd.virtualHosts."api.github.com" = { + forceSSL = true; + sslServerKey = "${cert}/server.key"; + sslServerCert = "${cert}/server.crt"; + servedDirs = [ + { + urlPath = "/repos/NixOS/nixpkgs"; + dir = nixpkgs-api; + } + { + urlPath = "/repos/fancy-enterprise/private-flake"; + dir = private-flake-api; + } + ]; }; - }; + services.httpd.virtualHosts."github.com" = { + forceSSL = true; + sslServerKey = "${cert}/server.key"; + sslServerCert = "${cert}/server.crt"; + servedDirs = [ + { + urlPath = "/NixOS/nixpkgs"; + dir = archive; + } + ]; + }; + }; - testScript = { nodes }: '' - # fmt: off - import json - import time + client = + { + config, + lib, + pkgs, + nodes, + ... + }: + { + virtualisation.writableStore = true; + virtualisation.diskSize = 2048; + virtualisation.additionalPaths = [ + pkgs.hello + pkgs.fuse + ]; + virtualisation.memorySize = 4096; + nix.settings.substituters = lib.mkForce [ ]; + nix.extraOptions = "experimental-features = nix-command flakes"; + networking.hosts.${(builtins.head nodes.github.networking.interfaces.eth1.ipv4.addresses).address} = + [ + "channels.nixos.org" + "api.github.com" + "github.com" + ]; + security.pki.certificateFiles = [ "${cert}/ca.crt" ]; + }; + }; - start_all() + testScript = + { nodes }: + '' + # fmt: off + import json + import time - def cat_log(): - github.succeed("cat /var/log/httpd/*.log >&2") + start_all() - github.wait_for_unit("httpd.service") - github.wait_for_unit("network-online.target") + def cat_log(): + github.succeed("cat /var/log/httpd/*.log >&2") - client.wait_for_unit("network-online.target") - client.succeed("curl -v https://github.com/ >&2") - out = client.succeed("nix registry list") - print(out) - assert "github:NixOS/nixpkgs" in out, "nixpkgs flake not found" - assert "github:fancy-enterprise/private-flake" in out, "private flake not found" - cat_log() + github.wait_for_unit("httpd.service") + github.wait_for_unit("network-online.target") - # If no github access token is provided, nix should use the public archive url... - out = client.succeed("nix flake metadata nixpkgs --json") - print(out) - info = json.loads(out) - assert info["revision"] == "${nixpkgs.rev}", f"revision mismatch: {info['revision']} != ${nixpkgs.rev}" - cat_log() + client.wait_for_unit("network-online.target") + client.succeed("curl -v https://github.com/ >&2") + out = client.succeed("nix registry list") + print(out) + assert "github:NixOS/nixpkgs" in out, "nixpkgs flake not found" + assert "github:fancy-enterprise/private-flake" in out, "private flake not found" + cat_log() - # ... otherwise it should use the API - out = client.succeed("nix flake metadata private-flake --json --access-tokens github.com=ghp_000000000000000000000000000000000000 --tarball-ttl 0") - print(out) - info = json.loads(out) - assert info["revision"] == "${private-flake-rev}", f"revision mismatch: {info['revision']} != ${private-flake-rev}" - assert info["fingerprint"] - cat_log() + # If no github access token is provided, nix should use the public archive url... + out = client.succeed("nix flake metadata nixpkgs --json") + print(out) + info = json.loads(out) + assert info["revision"] == "${nixpkgs.rev}", f"revision mismatch: {info['revision']} != ${nixpkgs.rev}" + cat_log() - # Fetching with the resolved URL should produce the same result. - info2 = json.loads(client.succeed(f"nix flake metadata {info['url']} --json --access-tokens github.com=ghp_000000000000000000000000000000000000 --tarball-ttl 0")) - print(info["fingerprint"], info2["fingerprint"]) - assert info["fingerprint"] == info2["fingerprint"], "fingerprint mismatch" + # ... otherwise it should use the API + out = client.succeed("nix flake metadata private-flake --json --access-tokens github.com=ghp_000000000000000000000000000000000000 --tarball-ttl 0") + print(out) + info = json.loads(out) + assert info["revision"] == "${private-flake-rev}", f"revision mismatch: {info['revision']} != ${private-flake-rev}" + assert info["fingerprint"] + cat_log() - client.succeed("nix registry pin nixpkgs") - client.succeed("nix flake metadata nixpkgs --tarball-ttl 0 >&2") + # Fetching with the resolved URL should produce the same result. + info2 = json.loads(client.succeed(f"nix flake metadata {info['url']} --json --access-tokens github.com=ghp_000000000000000000000000000000000000 --tarball-ttl 0")) + print(info["fingerprint"], info2["fingerprint"]) + assert info["fingerprint"] == info2["fingerprint"], "fingerprint mismatch" - # Test fetchTree on a github URL. - hash = client.succeed(f"nix eval --no-trust-tarballs-from-git-forges --raw --expr '(fetchTree {info['url']}).narHash'") - assert hash == info['locked']['narHash'] + client.succeed("nix registry pin nixpkgs") + client.succeed("nix flake metadata nixpkgs --tarball-ttl 0 >&2") - # Fetching without a narHash should succeed if trust-github is set and fail otherwise. - client.succeed(f"nix eval --raw --expr 'builtins.fetchTree github:github:fancy-enterprise/private-flake/{info['revision']}'") - out = client.fail(f"nix eval --no-trust-tarballs-from-git-forges --raw --expr 'builtins.fetchTree github:github:fancy-enterprise/private-flake/{info['revision']}' 2>&1") - assert "will not fetch unlocked input" in out, "--no-trust-tarballs-from-git-forges did not fail with the expected error" + # Test fetchTree on a github URL. + hash = client.succeed(f"nix eval --no-trust-tarballs-from-git-forges --raw --expr '(fetchTree {info['url']}).narHash'") + assert hash == info['locked']['narHash'] - # Shut down the web server. The flake should be cached on the client. - github.succeed("systemctl stop httpd.service") + # Fetching without a narHash should succeed if trust-github is set and fail otherwise. + client.succeed(f"nix eval --raw --expr 'builtins.fetchTree github:github:fancy-enterprise/private-flake/{info['revision']}'") + out = client.fail(f"nix eval --no-trust-tarballs-from-git-forges --raw --expr 'builtins.fetchTree github:github:fancy-enterprise/private-flake/{info['revision']}' 2>&1") + assert "will not fetch unlocked input" in out, "--no-trust-tarballs-from-git-forges did not fail with the expected error" - info = json.loads(client.succeed("nix flake metadata nixpkgs --json")) - date = time.strftime("%Y%m%d%H%M%S", time.gmtime(info['lastModified'])) - assert date == "${nixpkgs.lastModifiedDate}", "time mismatch" + # Shut down the web server. The flake should be cached on the client. + github.succeed("systemctl stop httpd.service") - client.succeed("nix build nixpkgs#hello") + info = json.loads(client.succeed("nix flake metadata nixpkgs --json")) + date = time.strftime("%Y%m%d%H%M%S", time.gmtime(info['lastModified'])) + assert date == "${nixpkgs.lastModifiedDate}", "time mismatch" - # The build shouldn't fail even with --tarball-ttl 0 (the server - # being down should not be a fatal error). - client.succeed("nix build nixpkgs#fuse --tarball-ttl 0") - ''; + client.succeed("nix build nixpkgs#hello") + + # The build shouldn't fail even with --tarball-ttl 0 (the server + # being down should not be a fatal error). + client.succeed("nix build nixpkgs#fuse --tarball-ttl 0") + ''; } diff --git a/tests/nixos/gzip-content-encoding.nix b/tests/nixos/gzip-content-encoding.nix index a5a0033fd..22d196c61 100644 --- a/tests/nixos/gzip-content-encoding.nix +++ b/tests/nixos/gzip-content-encoding.nix @@ -30,42 +30,45 @@ in { name = "gzip-content-encoding"; - nodes = - { machine = + nodes = { + machine = { config, pkgs, ... }: - { networking.firewall.allowedTCPPorts = [ 80 ]; + { + networking.firewall.allowedTCPPorts = [ 80 ]; services.nginx.enable = true; - services.nginx.virtualHosts."localhost" = - { root = "${ztdCompressedFile}/share/"; - # Make sure that nginx really tries to compress the - # file on the fly with no regard to size/mime. - # http://nginx.org/en/docs/http/ngx_http_gzip_module.html - extraConfig = '' - gzip on; - gzip_types *; - gzip_proxied any; - gzip_min_length 0; - ''; - }; + services.nginx.virtualHosts."localhost" = { + root = "${ztdCompressedFile}/share/"; + # Make sure that nginx really tries to compress the + # file on the fly with no regard to size/mime. + # http://nginx.org/en/docs/http/ngx_http_gzip_module.html + extraConfig = '' + gzip on; + gzip_types *; + gzip_proxied any; + gzip_min_length 0; + ''; + }; virtualisation.writableStore = true; virtualisation.additionalPaths = with pkgs; [ file ]; nix.settings.substituters = lib.mkForce [ ]; }; - }; + }; # Check that when nix-prefetch-url is used with a zst tarball it does not get decompressed. - testScript = { nodes }: '' - # fmt: off - start_all() + testScript = + { nodes }: + '' + # fmt: off + start_all() - machine.wait_for_unit("nginx.service") - machine.succeed(""" - # Make sure that the file is properly compressed as the test would be meaningless otherwise - curl --compressed -v http://localhost/archive |& tr -s ' ' |& grep --ignore-case 'content-encoding: gzip' - archive_path=$(nix-prefetch-url http://localhost/archive --print-path | tail -n1) - [[ $(${fileCmd} --brief --mime-type $archive_path) == "application/zstd" ]] - tar --zstd -xf $archive_path - """) - ''; + machine.wait_for_unit("nginx.service") + machine.succeed(""" + # Make sure that the file is properly compressed as the test would be meaningless otherwise + curl --compressed -v http://localhost/archive |& tr -s ' ' |& grep --ignore-case 'content-encoding: gzip' + archive_path=$(nix-prefetch-url http://localhost/archive --print-path | tail -n1) + [[ $(${fileCmd} --brief --mime-type $archive_path) == "application/zstd" ]] + tar --zstd -xf $archive_path + """) + ''; } diff --git a/tests/nixos/nix-copy-closure.nix b/tests/nixos/nix-copy-closure.nix index 44324e989..b6ec856e0 100644 --- a/tests/nixos/nix-copy-closure.nix +++ b/tests/nixos/nix-copy-closure.nix @@ -1,6 +1,11 @@ # Test ‘nix-copy-closure’. -{ lib, config, nixpkgs, ... }: +{ + lib, + config, + nixpkgs, + ... +}: let pkgs = config.nodes.client.nixpkgs.pkgs; @@ -10,74 +15,90 @@ let pkgC = pkgs.hello; pkgD = pkgs.tmux; -in { +in +{ name = "nix-copy-closure"; - nodes = - { client = - { config, lib, pkgs, ... }: - { virtualisation.writableStore = true; - virtualisation.additionalPaths = [ pkgA pkgD.drvPath ]; - nix.settings.substituters = lib.mkForce [ ]; - }; + nodes = { + client = + { + config, + lib, + pkgs, + ... + }: + { + virtualisation.writableStore = true; + virtualisation.additionalPaths = [ + pkgA + pkgD.drvPath + ]; + nix.settings.substituters = lib.mkForce [ ]; + }; - server = - { config, pkgs, ... }: - { services.openssh.enable = true; - virtualisation.writableStore = true; - virtualisation.additionalPaths = [ pkgB pkgC ]; - }; - }; + server = + { config, pkgs, ... }: + { + services.openssh.enable = true; + virtualisation.writableStore = true; + virtualisation.additionalPaths = [ + pkgB + pkgC + ]; + }; + }; - testScript = { nodes }: '' - # fmt: off - import subprocess + testScript = + { nodes }: + '' + # fmt: off + import subprocess - start_all() + start_all() - # Create an SSH key on the client. - subprocess.run([ - "${pkgs.openssh}/bin/ssh-keygen", "-t", "ed25519", "-f", "key", "-N", "" - ], capture_output=True, check=True) + # Create an SSH key on the client. + subprocess.run([ + "${pkgs.openssh}/bin/ssh-keygen", "-t", "ed25519", "-f", "key", "-N", "" + ], capture_output=True, check=True) - client.succeed("mkdir -m 700 /root/.ssh") - client.copy_from_host("key", "/root/.ssh/id_ed25519") - client.succeed("chmod 600 /root/.ssh/id_ed25519") + client.succeed("mkdir -m 700 /root/.ssh") + client.copy_from_host("key", "/root/.ssh/id_ed25519") + client.succeed("chmod 600 /root/.ssh/id_ed25519") - # Install the SSH key on the server. - server.succeed("mkdir -m 700 /root/.ssh") - server.copy_from_host("key.pub", "/root/.ssh/authorized_keys") - server.wait_for_unit("sshd") - server.wait_for_unit("multi-user.target") - server.wait_for_unit("network-online.target") + # Install the SSH key on the server. + server.succeed("mkdir -m 700 /root/.ssh") + server.copy_from_host("key.pub", "/root/.ssh/authorized_keys") + server.wait_for_unit("sshd") + server.wait_for_unit("multi-user.target") + server.wait_for_unit("network-online.target") - client.wait_for_unit("network-online.target") - client.succeed(f"ssh -o StrictHostKeyChecking=no {server.name} 'echo hello world'") + client.wait_for_unit("network-online.target") + client.succeed(f"ssh -o StrictHostKeyChecking=no {server.name} 'echo hello world'") - # Copy the closure of package A from the client to the server. - server.fail("nix-store --check-validity ${pkgA}") - client.succeed("nix-copy-closure --to server --gzip ${pkgA} >&2") - server.succeed("nix-store --check-validity ${pkgA}") + # Copy the closure of package A from the client to the server. + server.fail("nix-store --check-validity ${pkgA}") + client.succeed("nix-copy-closure --to server --gzip ${pkgA} >&2") + server.succeed("nix-store --check-validity ${pkgA}") - # Copy the closure of package B from the server to the client. - client.fail("nix-store --check-validity ${pkgB}") - client.succeed("nix-copy-closure --from server --gzip ${pkgB} >&2") - client.succeed("nix-store --check-validity ${pkgB}") + # Copy the closure of package B from the server to the client. + client.fail("nix-store --check-validity ${pkgB}") + client.succeed("nix-copy-closure --from server --gzip ${pkgB} >&2") + client.succeed("nix-store --check-validity ${pkgB}") - # Copy the closure of package C via the SSH substituter. - client.fail("nix-store -r ${pkgC}") + # Copy the closure of package C via the SSH substituter. + client.fail("nix-store -r ${pkgC}") - # Copy the derivation of package D's derivation from the client to the server. - server.fail("nix-store --check-validity ${pkgD.drvPath}") - client.succeed("nix-copy-closure --to server --gzip ${pkgD.drvPath} >&2") - server.succeed("nix-store --check-validity ${pkgD.drvPath}") + # Copy the derivation of package D's derivation from the client to the server. + server.fail("nix-store --check-validity ${pkgD.drvPath}") + client.succeed("nix-copy-closure --to server --gzip ${pkgD.drvPath} >&2") + server.succeed("nix-store --check-validity ${pkgD.drvPath}") - # FIXME - # client.succeed( - # "nix-store --option use-ssh-substituter true" - # " --option ssh-substituter-hosts root\@server" - # " -r ${pkgC} >&2" - # ) - # client.succeed("nix-store --check-validity ${pkgC}") - ''; + # FIXME + # client.succeed( + # "nix-store --option use-ssh-substituter true" + # " --option ssh-substituter-hosts root\@server" + # " -r ${pkgC} >&2" + # ) + # client.succeed("nix-store --check-validity ${pkgC}") + ''; } diff --git a/tests/nixos/nix-copy.nix b/tests/nixos/nix-copy.nix index a6a04b52c..3565e83e7 100644 --- a/tests/nixos/nix-copy.nix +++ b/tests/nixos/nix-copy.nix @@ -2,7 +2,13 @@ # Run interactively with: # rm key key.pub; nix run .#hydraJobs.tests.nix-copy.driverInteractive -{ lib, config, nixpkgs, hostPkgs, ... }: +{ + lib, + config, + nixpkgs, + hostPkgs, + ... +}: let pkgs = config.nodes.client.nixpkgs.pkgs; @@ -12,101 +18,117 @@ let pkgC = pkgs.hello; pkgD = pkgs.tmux; -in { +in +{ name = "nix-copy"; enableOCR = true; - nodes = - { client = - { config, lib, pkgs, ... }: - { virtualisation.writableStore = true; - virtualisation.additionalPaths = [ pkgA pkgD.drvPath ]; - nix.settings.substituters = lib.mkForce [ ]; - nix.settings.experimental-features = [ "nix-command" ]; - services.getty.autologinUser = "root"; - programs.ssh.extraConfig = '' - Host * - ControlMaster auto - ControlPath ~/.ssh/master-%h:%r@%n:%p - ControlPersist 15m - ''; - }; + nodes = { + client = + { + config, + lib, + pkgs, + ... + }: + { + virtualisation.writableStore = true; + virtualisation.additionalPaths = [ + pkgA + pkgD.drvPath + ]; + nix.settings.substituters = lib.mkForce [ ]; + nix.settings.experimental-features = [ "nix-command" ]; + services.getty.autologinUser = "root"; + programs.ssh.extraConfig = '' + Host * + ControlMaster auto + ControlPath ~/.ssh/master-%h:%r@%n:%p + ControlPersist 15m + ''; + }; - server = - { config, pkgs, ... }: - { services.openssh.enable = true; - services.openssh.settings.PermitRootLogin = "yes"; - users.users.root.hashedPasswordFile = null; - users.users.root.password = "foobar"; - virtualisation.writableStore = true; - virtualisation.additionalPaths = [ pkgB pkgC ]; - }; - }; + server = + { config, pkgs, ... }: + { + services.openssh.enable = true; + services.openssh.settings.PermitRootLogin = "yes"; + users.users.root.hashedPasswordFile = null; + users.users.root.password = "foobar"; + virtualisation.writableStore = true; + virtualisation.additionalPaths = [ + pkgB + pkgC + ]; + }; + }; - testScript = { nodes }: '' - # fmt: off - import subprocess + testScript = + { nodes }: + '' + # fmt: off + import subprocess - # Create an SSH key on the client. - subprocess.run([ - "${pkgs.openssh}/bin/ssh-keygen", "-t", "ed25519", "-f", "key", "-N", "" - ], capture_output=True, check=True) + # Create an SSH key on the client. + subprocess.run([ + "${pkgs.openssh}/bin/ssh-keygen", "-t", "ed25519", "-f", "key", "-N", "" + ], capture_output=True, check=True) - start_all() + start_all() - server.wait_for_unit("sshd") - server.wait_for_unit("multi-user.target") - server.wait_for_unit("network-online.target") + server.wait_for_unit("sshd") + server.wait_for_unit("multi-user.target") + server.wait_for_unit("network-online.target") - client.wait_for_unit("network-online.target") - client.wait_for_unit("getty@tty1.service") - # Either the prompt: ]# - # or an OCR misreading of it: 1# - client.wait_for_text("[]1]#") + client.wait_for_unit("network-online.target") + client.wait_for_unit("getty@tty1.service") + # Either the prompt: ]# + # or an OCR misreading of it: 1# + client.wait_for_text("[]1]#") - # Copy the closure of package A from the client to the server using password authentication, - # and check that all prompts are visible - server.fail("nix-store --check-validity ${pkgA}") - client.send_chars("nix copy --to ssh://server ${pkgA} >&2; echo -n do; echo ne\n") - client.wait_for_text("continue connecting") - client.send_chars("yes\n") - client.wait_for_text("Password:") - client.send_chars("foobar\n") - client.wait_for_text("done") - server.succeed("nix-store --check-validity ${pkgA}") + # Copy the closure of package A from the client to the server using password authentication, + # and check that all prompts are visible + server.fail("nix-store --check-validity ${pkgA}") + client.send_chars("nix copy --to ssh://server ${pkgA} >&2; echo -n do; echo ne\n") + client.wait_for_text("continue connecting") + client.send_chars("yes\n") + client.wait_for_text("Password:") + client.send_chars("foobar\n") + client.wait_for_text("done") + server.succeed("nix-store --check-validity ${pkgA}") - # Check that ControlMaster is working - client.send_chars("nix copy --to ssh://server ${pkgA} >&2; echo done\n") - client.wait_for_text("done") + # Check that ControlMaster is working + client.send_chars("nix copy --to ssh://server ${pkgA} >&2; echo done\n") + client.wait_for_text("done") - client.copy_from_host("key", "/root/.ssh/id_ed25519") - client.succeed("chmod 600 /root/.ssh/id_ed25519") + client.copy_from_host("key", "/root/.ssh/id_ed25519") + client.succeed("chmod 600 /root/.ssh/id_ed25519") - # Install the SSH key on the server. - server.copy_from_host("key.pub", "/root/.ssh/authorized_keys") - server.succeed("systemctl restart sshd") - client.succeed(f"ssh -o StrictHostKeyChecking=no {server.name} 'echo hello world'") - client.succeed(f"ssh -O check {server.name}") - client.succeed(f"ssh -O exit {server.name}") - client.fail(f"ssh -O check {server.name}") + # Install the SSH key on the server. + server.copy_from_host("key.pub", "/root/.ssh/authorized_keys") + server.succeed("systemctl restart sshd") + client.succeed(f"ssh -o StrictHostKeyChecking=no {server.name} 'echo hello world'") + client.succeed(f"ssh -O check {server.name}") + client.succeed(f"ssh -O exit {server.name}") + client.fail(f"ssh -O check {server.name}") - # Check that an explicit master will work - client.succeed(f"ssh -MNfS /tmp/master {server.name}") - client.succeed(f"ssh -S /tmp/master -O check {server.name}") - client.succeed("NIX_SSHOPTS='-oControlPath=/tmp/master' nix copy --to ssh://server ${pkgA} >&2") - client.succeed(f"ssh -S /tmp/master -O exit {server.name}") + # Check that an explicit master will work + client.succeed(f"ssh -MNfS /tmp/master {server.name}") + client.succeed(f"ssh -S /tmp/master -O check {server.name}") + client.succeed("NIX_SSHOPTS='-oControlPath=/tmp/master' nix copy --to ssh://server ${pkgA} >&2") + client.succeed(f"ssh -S /tmp/master -O exit {server.name}") - # Copy the closure of package B from the server to the client, using ssh-ng. - client.fail("nix-store --check-validity ${pkgB}") - # Shouldn't download untrusted paths by default - client.fail("nix copy --from ssh-ng://server ${pkgB} >&2") - client.succeed("nix copy --no-check-sigs --from ssh-ng://server ${pkgB} >&2") - client.succeed("nix-store --check-validity ${pkgB}") + # Copy the closure of package B from the server to the client, using ssh-ng. + client.fail("nix-store --check-validity ${pkgB}") + # Shouldn't download untrusted paths by default + client.fail("nix copy --from ssh-ng://server ${pkgB} >&2") + client.succeed("nix copy --no-check-sigs --from ssh-ng://server ${pkgB} >&2") + client.succeed("nix-store --check-validity ${pkgB}") - # Copy the derivation of package D's derivation from the client to the server. - server.fail("nix-store --check-validity ${pkgD.drvPath}") - client.succeed("nix copy --derivation --to ssh://server ${pkgD.drvPath} >&2") - server.succeed("nix-store --check-validity ${pkgD.drvPath}") - ''; + # Copy the derivation of package D's derivation from the client to the server. + server.fail("nix-store --check-validity ${pkgD.drvPath}") + client.succeed("nix copy --derivation --to ssh://server ${pkgD.drvPath} >&2") + server.succeed("nix-store --check-validity ${pkgD.drvPath}") + ''; } diff --git a/tests/nixos/nix-docker.nix b/tests/nixos/nix-docker.nix index 00b04482c..bd77b25c8 100644 --- a/tests/nixos/nix-docker.nix +++ b/tests/nixos/nix-docker.nix @@ -1,6 +1,12 @@ # Test the container built by ../../docker.nix. -{ lib, config, nixpkgs, hostPkgs, ... }: +{ + lib, + config, + nixpkgs, + hostPkgs, + ... +}: let pkgs = config.nodes.machine.nixpkgs.pkgs; @@ -19,36 +25,54 @@ let containerTestScript = ./nix-docker-test.sh; -in { +in +{ name = "nix-docker"; - nodes = - { machine = - { config, lib, pkgs, ... }: - { virtualisation.diskSize = 4096; - }; - cache = - { config, lib, pkgs, ... }: - { virtualisation.additionalPaths = [ pkgs.stdenv pkgs.hello ]; - services.harmonia.enable = true; - networking.firewall.allowedTCPPorts = [ 5000 ]; - }; - }; + nodes = { + machine = + { + config, + lib, + pkgs, + ... + }: + { + virtualisation.diskSize = 4096; + }; + cache = + { + config, + lib, + pkgs, + ... + }: + { + virtualisation.additionalPaths = [ + pkgs.stdenv + pkgs.hello + ]; + services.harmonia.enable = true; + networking.firewall.allowedTCPPorts = [ 5000 ]; + }; + }; - testScript = { nodes }: '' - cache.wait_for_unit("harmonia.service") - cache.wait_for_unit("network-online.target") + testScript = + { nodes }: + '' + cache.wait_for_unit("harmonia.service") + cache.wait_for_unit("network-online.target") - machine.succeed("mkdir -p /etc/containers") - machine.succeed("""echo '{"default":[{"type":"insecureAcceptAnything"}]}' > /etc/containers/policy.json""") + machine.succeed("mkdir -p /etc/containers") + machine.succeed("""echo '{"default":[{"type":"insecureAcceptAnything"}]}' > /etc/containers/policy.json""") - machine.succeed("${pkgs.podman}/bin/podman load -i ${nixImage}") - machine.succeed("${pkgs.podman}/bin/podman run --rm nix nix --version") - machine.succeed("${pkgs.podman}/bin/podman run --rm -i nix < ${containerTestScript}") + machine.succeed("${pkgs.podman}/bin/podman load -i ${nixImage}") + machine.succeed("${pkgs.podman}/bin/podman run --rm nix nix --version") + machine.succeed("${pkgs.podman}/bin/podman run --rm -i nix < ${containerTestScript}") - machine.succeed("${pkgs.podman}/bin/podman load -i ${nixUserImage}") - machine.succeed("${pkgs.podman}/bin/podman run --rm nix-user nix --version") - machine.succeed("${pkgs.podman}/bin/podman run --rm -i nix-user < ${containerTestScript}") - machine.succeed("[[ $(${pkgs.podman}/bin/podman run --rm nix-user stat -c %u /nix/store) = 1000 ]]") - ''; + machine.succeed("${pkgs.podman}/bin/podman load -i ${nixUserImage}") + machine.succeed("${pkgs.podman}/bin/podman run --rm nix-user nix --version") + machine.succeed("${pkgs.podman}/bin/podman run --rm -i nix-user < ${containerTestScript}") + machine.succeed("[[ $(${pkgs.podman}/bin/podman run --rm nix-user stat -c %u /nix/store) = 1000 ]]") + ''; } diff --git a/tests/nixos/nss-preload.nix b/tests/nixos/nss-preload.nix index b7e704f39..29cd5e6a2 100644 --- a/tests/nixos/nss-preload.nix +++ b/tests/nixos/nss-preload.nix @@ -1,4 +1,9 @@ -{ lib, config, nixpkgs, ... }: +{ + lib, + config, + nixpkgs, + ... +}: let @@ -44,81 +49,119 @@ in name = "nss-preload"; nodes = { - http_dns = { lib, pkgs, config, ... }: { - networking.firewall.enable = false; - networking.interfaces.eth1.ipv6.addresses = lib.mkForce [ - { address = "fd21::1"; prefixLength = 64; } - ]; - networking.interfaces.eth1.ipv4.addresses = lib.mkForce [ - { address = "192.168.0.1"; prefixLength = 24; } - ]; + http_dns = + { + lib, + pkgs, + config, + ... + }: + { + networking.firewall.enable = false; + networking.interfaces.eth1.ipv6.addresses = lib.mkForce [ + { + address = "fd21::1"; + prefixLength = 64; + } + ]; + networking.interfaces.eth1.ipv4.addresses = lib.mkForce [ + { + address = "192.168.0.1"; + prefixLength = 24; + } + ]; - services.unbound = { - enable = true; - enableRootTrustAnchor = false; - settings = { - server = { - interface = [ "192.168.0.1" "fd21::1" "::1" "127.0.0.1" ]; - access-control = [ "192.168.0.0/24 allow" "fd21::/64 allow" "::1 allow" "127.0.0.0/8 allow" ]; - local-data = [ - ''"example.com. IN A 192.168.0.1"'' - ''"example.com. IN AAAA fd21::1"'' - ''"tarballs.nixos.org. IN A 192.168.0.1"'' - ''"tarballs.nixos.org. IN AAAA fd21::1"'' - ]; + services.unbound = { + enable = true; + enableRootTrustAnchor = false; + settings = { + server = { + interface = [ + "192.168.0.1" + "fd21::1" + "::1" + "127.0.0.1" + ]; + access-control = [ + "192.168.0.0/24 allow" + "fd21::/64 allow" + "::1 allow" + "127.0.0.0/8 allow" + ]; + local-data = [ + ''"example.com. IN A 192.168.0.1"'' + ''"example.com. IN AAAA fd21::1"'' + ''"tarballs.nixos.org. IN A 192.168.0.1"'' + ''"tarballs.nixos.org. IN AAAA fd21::1"'' + ]; + }; + }; + }; + + services.nginx = { + enable = true; + virtualHosts."example.com" = { + root = pkgs.runCommand "testdir" { } '' + mkdir "$out" + echo hello world > "$out/index.html" + ''; }; }; }; - services.nginx = { - enable = true; - virtualHosts."example.com" = { - root = pkgs.runCommand "testdir" {} '' - mkdir "$out" - echo hello world > "$out/index.html" - ''; - }; - }; - }; - # client consumes a remote resolver - client = { lib, nodes, pkgs, ... }: { - networking.useDHCP = false; - networking.nameservers = [ - (lib.head nodes.http_dns.networking.interfaces.eth1.ipv6.addresses).address - (lib.head nodes.http_dns.networking.interfaces.eth1.ipv4.addresses).address - ]; - networking.interfaces.eth1.ipv6.addresses = [ - { address = "fd21::10"; prefixLength = 64; } - ]; - networking.interfaces.eth1.ipv4.addresses = [ - { address = "192.168.0.10"; prefixLength = 24; } - ]; + client = + { + lib, + nodes, + pkgs, + ... + }: + { + networking.useDHCP = false; + networking.nameservers = [ + (lib.head nodes.http_dns.networking.interfaces.eth1.ipv6.addresses).address + (lib.head nodes.http_dns.networking.interfaces.eth1.ipv4.addresses).address + ]; + networking.interfaces.eth1.ipv6.addresses = [ + { + address = "fd21::10"; + prefixLength = 64; + } + ]; + networking.interfaces.eth1.ipv4.addresses = [ + { + address = "192.168.0.10"; + prefixLength = 24; + } + ]; - nix.settings.extra-sandbox-paths = lib.mkForce []; - nix.settings.substituters = lib.mkForce []; - nix.settings.sandbox = lib.mkForce true; - }; + nix.settings.extra-sandbox-paths = lib.mkForce [ ]; + nix.settings.substituters = lib.mkForce [ ]; + nix.settings.sandbox = lib.mkForce true; + }; }; - testScript = { nodes, ... }: '' - http_dns.wait_for_unit("network-online.target") - http_dns.wait_for_unit("nginx") - http_dns.wait_for_open_port(80) - http_dns.wait_for_unit("unbound") - http_dns.wait_for_open_port(53) + testScript = + { nodes, ... }: + '' + http_dns.wait_for_unit("network-online.target") + http_dns.wait_for_unit("nginx") + http_dns.wait_for_open_port(80) + http_dns.wait_for_unit("unbound") + http_dns.wait_for_open_port(53) - client.start() - client.wait_for_unit('multi-user.target') - client.wait_for_unit('network-online.target') + client.start() + client.wait_for_unit('multi-user.target') + client.wait_for_unit('network-online.target') - with subtest("can fetch data from a remote server outside sandbox"): - client.succeed("nix --version >&2") - client.succeed("curl -vvv http://example.com/index.html >&2") + with subtest("can fetch data from a remote server outside sandbox"): + client.succeed("nix --version >&2") + client.succeed("curl -vvv http://example.com/index.html >&2") - with subtest("nix-build can lookup dns and fetch data"): - client.succeed(""" - nix-build ${nix-fetch} >&2 - """) - ''; + with subtest("nix-build can lookup dns and fetch data"): + client.succeed(""" + nix-build ${nix-fetch} >&2 + """) + ''; } diff --git a/tests/nixos/remote-builds-ssh-ng.nix b/tests/nixos/remote-builds-ssh-ng.nix index 3562d2d2f..726522029 100644 --- a/tests/nixos/remote-builds-ssh-ng.nix +++ b/tests/nixos/remote-builds-ssh-ng.nix @@ -1,11 +1,17 @@ -test@{ config, lib, hostPkgs, ... }: +test@{ + config, + lib, + hostPkgs, + ... +}: let pkgs = config.nodes.client.nixpkgs.pkgs; # Trivial Nix expression to build remotely. - expr = config: nr: pkgs.writeText "expr.nix" - '' + expr = + config: nr: + pkgs.writeText "expr.nix" '' let utils = builtins.storePath ${config.system.build.extraUtils}; in derivation { name = "hello-${toString nr}"; @@ -41,87 +47,94 @@ in config = { name = lib.mkDefault "remote-builds-ssh-ng"; - nodes = - { - builder = - { config, pkgs, ... }: - { - imports = [ test.config.builders.config ]; - services.openssh.enable = true; - virtualisation.writableStore = true; - nix.settings.sandbox = true; - nix.settings.substituters = lib.mkForce [ ]; - }; + nodes = { + builder = + { config, pkgs, ... }: + { + imports = [ test.config.builders.config ]; + services.openssh.enable = true; + virtualisation.writableStore = true; + nix.settings.sandbox = true; + nix.settings.substituters = lib.mkForce [ ]; + }; - client = - { config, lib, pkgs, ... }: - { - nix.settings.max-jobs = 0; # force remote building - nix.distributedBuilds = true; - nix.buildMachines = - [{ - hostName = "builder"; - sshUser = "root"; - sshKey = "/root/.ssh/id_ed25519"; - system = "i686-linux"; - maxJobs = 1; - protocol = "ssh-ng"; - }]; - virtualisation.writableStore = true; - virtualisation.additionalPaths = [ config.system.build.extraUtils ]; - nix.settings.substituters = lib.mkForce [ ]; - programs.ssh.extraConfig = "ConnectTimeout 30"; - }; - }; + client = + { + config, + lib, + pkgs, + ... + }: + { + nix.settings.max-jobs = 0; # force remote building + nix.distributedBuilds = true; + nix.buildMachines = [ + { + hostName = "builder"; + sshUser = "root"; + sshKey = "/root/.ssh/id_ed25519"; + system = "i686-linux"; + maxJobs = 1; + protocol = "ssh-ng"; + } + ]; + virtualisation.writableStore = true; + virtualisation.additionalPaths = [ config.system.build.extraUtils ]; + nix.settings.substituters = lib.mkForce [ ]; + programs.ssh.extraConfig = "ConnectTimeout 30"; + }; + }; - testScript = { nodes }: '' - # fmt: off - import subprocess + testScript = + { nodes }: + '' + # fmt: off + import subprocess - start_all() + start_all() - # Create an SSH key on the client. - subprocess.run([ - "${hostPkgs.openssh}/bin/ssh-keygen", "-t", "ed25519", "-f", "key", "-N", "" - ], capture_output=True, check=True) - client.succeed("mkdir -p -m 700 /root/.ssh") - client.copy_from_host("key", "/root/.ssh/id_ed25519") - client.succeed("chmod 600 /root/.ssh/id_ed25519") + # Create an SSH key on the client. + subprocess.run([ + "${hostPkgs.openssh}/bin/ssh-keygen", "-t", "ed25519", "-f", "key", "-N", "" + ], capture_output=True, check=True) + client.succeed("mkdir -p -m 700 /root/.ssh") + client.copy_from_host("key", "/root/.ssh/id_ed25519") + client.succeed("chmod 600 /root/.ssh/id_ed25519") - # Install the SSH key on the builder. - client.wait_for_unit("network-online.target") - builder.succeed("mkdir -p -m 700 /root/.ssh") - builder.copy_from_host("key.pub", "/root/.ssh/authorized_keys") - builder.wait_for_unit("sshd") - builder.wait_for_unit("multi-user.target") - builder.wait_for_unit("network-online.target") + # Install the SSH key on the builder. + client.wait_for_unit("network-online.target") + builder.succeed("mkdir -p -m 700 /root/.ssh") + builder.copy_from_host("key.pub", "/root/.ssh/authorized_keys") + builder.wait_for_unit("sshd") + builder.wait_for_unit("multi-user.target") + builder.wait_for_unit("network-online.target") - client.succeed(f"ssh -o StrictHostKeyChecking=no {builder.name} 'echo hello world'") + client.succeed(f"ssh -o StrictHostKeyChecking=no {builder.name} 'echo hello world'") - # Perform a build - out = client.succeed("nix-build ${expr nodes.client 1} 2> build-output") + # Perform a build + out = client.succeed("nix-build ${expr nodes.client 1} 2> build-output") - # Verify that the build was done on the builder - builder.succeed(f"test -e {out.strip()}") + # Verify that the build was done on the builder + builder.succeed(f"test -e {out.strip()}") - # Print the build log, prefix the log lines to avoid nix intercepting lines starting with @nix - buildOutput = client.succeed("sed -e 's/^/build-output:/' build-output") - print(buildOutput) + # Print the build log, prefix the log lines to avoid nix intercepting lines starting with @nix + buildOutput = client.succeed("sed -e 's/^/build-output:/' build-output") + print(buildOutput) - # Make sure that we get the expected build output - client.succeed("grep -qF Hello build-output") + # Make sure that we get the expected build output + client.succeed("grep -qF Hello build-output") - # We don't want phase reporting in the build output - client.fail("grep -qF '@nix' build-output") + # We don't want phase reporting in the build output + client.fail("grep -qF '@nix' build-output") - # Get the log file - client.succeed(f"nix-store --read-log {out.strip()} > log-output") - # Prefix the log lines to avoid nix intercepting lines starting with @nix - logOutput = client.succeed("sed -e 's/^/log-file:/' log-output") - print(logOutput) + # Get the log file + client.succeed(f"nix-store --read-log {out.strip()} > log-output") + # Prefix the log lines to avoid nix intercepting lines starting with @nix + logOutput = client.succeed("sed -e 's/^/log-file:/' log-output") + print(logOutput) - # Check that we get phase reporting in the log file - client.succeed("grep -q '@nix {\"action\":\"setPhase\",\"phase\":\"buildPhase\"}' log-output") - ''; + # Check that we get phase reporting in the log file + client.succeed("grep -q '@nix {\"action\":\"setPhase\",\"phase\":\"buildPhase\"}' log-output") + ''; }; } diff --git a/tests/nixos/remote-builds.nix b/tests/nixos/remote-builds.nix index 4fca4b938..3251984db 100644 --- a/tests/nixos/remote-builds.nix +++ b/tests/nixos/remote-builds.nix @@ -1,6 +1,11 @@ # Test Nix's remote build feature. -test@{ config, lib, hostPkgs, ... }: +test@{ + config, + lib, + hostPkgs, + ... +}: let pkgs = config.nodes.client.nixpkgs.pkgs; @@ -21,8 +26,9 @@ let }; # Trivial Nix expression to build remotely. - expr = config: nr: pkgs.writeText "expr.nix" - '' + expr = + config: nr: + pkgs.writeText "expr.nix" '' let utils = builtins.storePath ${config.system.build.extraUtils}; in derivation { name = "hello-${toString nr}"; @@ -52,107 +58,112 @@ in config = { name = lib.mkDefault "remote-builds"; - nodes = - { - builder1 = builder; - builder2 = builder; + nodes = { + builder1 = builder; + builder2 = builder; - client = - { config, lib, pkgs, ... }: - { - nix.settings.max-jobs = 0; # force remote building - nix.distributedBuilds = true; - nix.buildMachines = - [ - { - hostName = "builder1"; - sshUser = "root"; - sshKey = "/root/.ssh/id_ed25519"; - system = "i686-linux"; - maxJobs = 1; - } - { - hostName = "builder2"; - sshUser = "root"; - sshKey = "/root/.ssh/id_ed25519"; - system = "i686-linux"; - maxJobs = 1; - } - ]; - virtualisation.writableStore = true; - virtualisation.additionalPaths = [ config.system.build.extraUtils ]; - nix.settings.substituters = lib.mkForce [ ]; - programs.ssh.extraConfig = "ConnectTimeout 30"; - environment.systemPackages = [ - # `bad-shell` is used to make sure Nix works in an environment with a misbehaving shell. - # - # More realistically, a bad shell would still run the command ("echo started") - # but considering that our solution is to avoid this shell (set via $SHELL), we - # don't need to bother with a more functional mock shell. - (pkgs.writeScriptBin "bad-shell" '' - #!${pkgs.runtimeShell} - echo "Hello, I am a broken shell" - '') - ]; - }; - }; + client = + { + config, + lib, + pkgs, + ... + }: + { + nix.settings.max-jobs = 0; # force remote building + nix.distributedBuilds = true; + nix.buildMachines = [ + { + hostName = "builder1"; + sshUser = "root"; + sshKey = "/root/.ssh/id_ed25519"; + system = "i686-linux"; + maxJobs = 1; + } + { + hostName = "builder2"; + sshUser = "root"; + sshKey = "/root/.ssh/id_ed25519"; + system = "i686-linux"; + maxJobs = 1; + } + ]; + virtualisation.writableStore = true; + virtualisation.additionalPaths = [ config.system.build.extraUtils ]; + nix.settings.substituters = lib.mkForce [ ]; + programs.ssh.extraConfig = "ConnectTimeout 30"; + environment.systemPackages = [ + # `bad-shell` is used to make sure Nix works in an environment with a misbehaving shell. + # + # More realistically, a bad shell would still run the command ("echo started") + # but considering that our solution is to avoid this shell (set via $SHELL), we + # don't need to bother with a more functional mock shell. + (pkgs.writeScriptBin "bad-shell" '' + #!${pkgs.runtimeShell} + echo "Hello, I am a broken shell" + '') + ]; + }; + }; - testScript = { nodes }: '' - # fmt: off - import subprocess + testScript = + { nodes }: + '' + # fmt: off + import subprocess - start_all() + start_all() - # Create an SSH key on the client. - subprocess.run([ - "${hostPkgs.openssh}/bin/ssh-keygen", "-t", "ed25519", "-f", "key", "-N", "" - ], capture_output=True, check=True) - client.succeed("mkdir -p -m 700 /root/.ssh") - client.copy_from_host("key", "/root/.ssh/id_ed25519") - client.succeed("chmod 600 /root/.ssh/id_ed25519") + # Create an SSH key on the client. + subprocess.run([ + "${hostPkgs.openssh}/bin/ssh-keygen", "-t", "ed25519", "-f", "key", "-N", "" + ], capture_output=True, check=True) + client.succeed("mkdir -p -m 700 /root/.ssh") + client.copy_from_host("key", "/root/.ssh/id_ed25519") + client.succeed("chmod 600 /root/.ssh/id_ed25519") - # Install the SSH key on the builders. - client.wait_for_unit("network-online.target") - for builder in [builder1, builder2]: - builder.succeed("mkdir -p -m 700 /root/.ssh") - builder.copy_from_host("key.pub", "/root/.ssh/authorized_keys") - builder.wait_for_unit("sshd") - builder.wait_for_unit("network-online.target") - # Make sure the builder can handle our login correctly - builder.wait_for_unit("multi-user.target") - # Make sure there's no funny business on the client either - # (should not be necessary, but we have reason to be careful) - client.wait_for_unit("multi-user.target") - client.succeed(f""" - ssh -o StrictHostKeyChecking=no {builder.name} \ - 'echo hello world on $(hostname)' >&2 - """) + # Install the SSH key on the builders. + client.wait_for_unit("network-online.target") + for builder in [builder1, builder2]: + builder.succeed("mkdir -p -m 700 /root/.ssh") + builder.copy_from_host("key.pub", "/root/.ssh/authorized_keys") + builder.wait_for_unit("sshd") + builder.wait_for_unit("network-online.target") + # Make sure the builder can handle our login correctly + builder.wait_for_unit("multi-user.target") + # Make sure there's no funny business on the client either + # (should not be necessary, but we have reason to be careful) + client.wait_for_unit("multi-user.target") + client.succeed(f""" + ssh -o StrictHostKeyChecking=no {builder.name} \ + 'echo hello world on $(hostname)' >&2 + """) - ${lib.optionalString supportsBadShell '' - # Check that SSH uses SHELL for LocalCommand, as expected, and check that - # our test setup here is working. The next test will use this bad SHELL. - client.succeed(f"SHELL=$(which bad-shell) ssh -oLocalCommand='true' -oPermitLocalCommand=yes {builder1.name} 'echo hello world' | grep -F 'Hello, I am a broken shell'") - ''} + ${lib.optionalString supportsBadShell '' + # Check that SSH uses SHELL for LocalCommand, as expected, and check that + # our test setup here is working. The next test will use this bad SHELL. + client.succeed(f"SHELL=$(which bad-shell) ssh -oLocalCommand='true' -oPermitLocalCommand=yes {builder1.name} 'echo hello world' | grep -F 'Hello, I am a broken shell'") + ''} - # Perform a build and check that it was performed on the builder. - out = client.succeed( - "${lib.optionalString supportsBadShell "SHELL=$(which bad-shell)"} nix-build ${expr nodes.client 1} 2> build-output", - "grep -q Hello build-output" - ) - builder1.succeed(f"test -e {out}") + # Perform a build and check that it was performed on the builder. + out = client.succeed( + "${lib.optionalString supportsBadShell "SHELL=$(which bad-shell)"} nix-build ${expr nodes.client 1} 2> build-output", + "grep -q Hello build-output" + ) + builder1.succeed(f"test -e {out}") - # And a parallel build. - paths = client.succeed(r'nix-store -r $(nix-instantiate ${expr nodes.client 2})\!out $(nix-instantiate ${expr nodes.client 3})\!out') - out1, out2 = paths.split() - builder1.succeed(f"test -e {out1} -o -e {out2}") - builder2.succeed(f"test -e {out1} -o -e {out2}") + # And a parallel build. + paths = client.succeed(r'nix-store -r $(nix-instantiate ${expr nodes.client 2})\!out $(nix-instantiate ${expr nodes.client 3})\!out') + out1, out2 = paths.split() + builder1.succeed(f"test -e {out1} -o -e {out2}") + builder2.succeed(f"test -e {out1} -o -e {out2}") - # And a failing build. - client.fail("nix-build ${expr nodes.client 5}") + # And a failing build. + client.fail("nix-build ${expr nodes.client 5}") - # Test whether the build hook automatically skips unavailable builders. - builder1.block() - client.succeed("nix-build ${expr nodes.client 4}") - ''; + # Test whether the build hook automatically skips unavailable builders. + builder1.block() + client.succeed("nix-build ${expr nodes.client 4}") + ''; }; } diff --git a/tests/nixos/s3-binary-cache-store.nix b/tests/nixos/s3-binary-cache-store.nix index f8659b830..8e4808660 100644 --- a/tests/nixos/s3-binary-cache-store.nix +++ b/tests/nixos/s3-binary-cache-store.nix @@ -1,4 +1,9 @@ -{ lib, config, nixpkgs, ... }: +{ + lib, + config, + nixpkgs, + ... +}: let pkgs = config.nodes.client.nixpkgs.pkgs; @@ -12,71 +17,81 @@ let storeUrl = "s3://my-cache?endpoint=http://server:9000®ion=eu-west-1"; objectThatDoesNotExist = "s3://my-cache/foo-that-does-not-exist?endpoint=http://server:9000®ion=eu-west-1"; -in { +in +{ name = "s3-binary-cache-store"; - nodes = - { server = - { config, lib, pkgs, ... }: - { virtualisation.writableStore = true; - virtualisation.additionalPaths = [ pkgA ]; - environment.systemPackages = [ pkgs.minio-client ]; - nix.extraOptions = '' - experimental-features = nix-command - substituters = - ''; - services.minio = { - enable = true; - region = "eu-west-1"; - rootCredentialsFile = pkgs.writeText "minio-credentials-full" '' - MINIO_ROOT_USER=${accessKey} - MINIO_ROOT_PASSWORD=${secretKey} - ''; - }; - networking.firewall.allowedTCPPorts = [ 9000 ]; - }; - - client = - { config, pkgs, ... }: - { virtualisation.writableStore = true; - nix.extraOptions = '' - experimental-features = nix-command - substituters = + nodes = { + server = + { + config, + lib, + pkgs, + ... + }: + { + virtualisation.writableStore = true; + virtualisation.additionalPaths = [ pkgA ]; + environment.systemPackages = [ pkgs.minio-client ]; + nix.extraOptions = '' + experimental-features = nix-command + substituters = + ''; + services.minio = { + enable = true; + region = "eu-west-1"; + rootCredentialsFile = pkgs.writeText "minio-credentials-full" '' + MINIO_ROOT_USER=${accessKey} + MINIO_ROOT_PASSWORD=${secretKey} ''; }; - }; + networking.firewall.allowedTCPPorts = [ 9000 ]; + }; - testScript = { nodes }: '' - # fmt: off - start_all() + client = + { config, pkgs, ... }: + { + virtualisation.writableStore = true; + nix.extraOptions = '' + experimental-features = nix-command + substituters = + ''; + }; + }; - # Create a binary cache. - server.wait_for_unit("minio") - server.wait_for_unit("network-online.target") + testScript = + { nodes }: + '' + # fmt: off + start_all() - server.succeed("mc config host add minio http://localhost:9000 ${accessKey} ${secretKey} --api s3v4") - server.succeed("mc mb minio/my-cache") + # Create a binary cache. + server.wait_for_unit("minio") + server.wait_for_unit("network-online.target") - server.succeed("${env} nix copy --to '${storeUrl}' ${pkgA}") + server.succeed("mc config host add minio http://localhost:9000 ${accessKey} ${secretKey} --api s3v4") + server.succeed("mc mb minio/my-cache") - client.wait_for_unit("network-online.target") + server.succeed("${env} nix copy --to '${storeUrl}' ${pkgA}") - # Test fetchurl on s3:// URLs while we're at it. - client.succeed("${env} nix eval --impure --expr 'builtins.fetchurl { name = \"foo\"; url = \"s3://my-cache/nix-cache-info?endpoint=http://server:9000®ion=eu-west-1\"; }'") + client.wait_for_unit("network-online.target") - # Test that the format string in the error message is properly setup and won't display `%s` instead of the failed URI - msg = client.fail("${env} nix eval --impure --expr 'builtins.fetchurl { name = \"foo\"; url = \"${objectThatDoesNotExist}\"; }' 2>&1") - if "S3 object '${objectThatDoesNotExist}' does not exist" not in msg: - print(msg) # So that you can see the message that was improperly formatted - raise Exception("Error message formatting didn't work") + # Test fetchurl on s3:// URLs while we're at it. + client.succeed("${env} nix eval --impure --expr 'builtins.fetchurl { name = \"foo\"; url = \"s3://my-cache/nix-cache-info?endpoint=http://server:9000®ion=eu-west-1\"; }'") - # Copy a package from the binary cache. - client.fail("nix path-info ${pkgA}") + # Test that the format string in the error message is properly setup and won't display `%s` instead of the failed URI + msg = client.fail("${env} nix eval --impure --expr 'builtins.fetchurl { name = \"foo\"; url = \"${objectThatDoesNotExist}\"; }' 2>&1") + if "S3 object '${objectThatDoesNotExist}' does not exist" not in msg: + print(msg) # So that you can see the message that was improperly formatted + raise Exception("Error message formatting didn't work") - client.succeed("${env} nix store info --store '${storeUrl}' >&2") + # Copy a package from the binary cache. + client.fail("nix path-info ${pkgA}") - client.succeed("${env} nix copy --no-check-sigs --from '${storeUrl}' ${pkgA}") + client.succeed("${env} nix store info --store '${storeUrl}' >&2") - client.succeed("nix path-info ${pkgA}") - ''; + client.succeed("${env} nix copy --no-check-sigs --from '${storeUrl}' ${pkgA}") + + client.succeed("nix path-info ${pkgA}") + ''; } diff --git a/tests/nixos/setuid.nix b/tests/nixos/setuid.nix index 2b66320dd..dc368e383 100644 --- a/tests/nixos/setuid.nix +++ b/tests/nixos/setuid.nix @@ -1,6 +1,11 @@ # Verify that Linux builds cannot create setuid or setgid binaries. -{ lib, config, nixpkgs, ... }: +{ + lib, + config, + nixpkgs, + ... +}: let pkgs = config.nodes.machine.nixpkgs.pkgs; @@ -10,116 +15,127 @@ in name = "setuid"; nodes.machine = - { config, lib, pkgs, ... }: - { virtualisation.writableStore = true; + { + config, + lib, + pkgs, + ... + }: + { + virtualisation.writableStore = true; nix.settings.substituters = lib.mkForce [ ]; nix.nixPath = [ "nixpkgs=${lib.cleanSource pkgs.path}" ]; - virtualisation.additionalPaths = [ pkgs.stdenvNoCC pkgs.pkgsi686Linux.stdenvNoCC ]; + virtualisation.additionalPaths = [ + pkgs.stdenvNoCC + pkgs.pkgsi686Linux.stdenvNoCC + ]; }; - testScript = { nodes }: '' - # fmt: off - start_all() + testScript = + { nodes }: + '' + # fmt: off + start_all() - # Copying to /tmp should succeed. - machine.succeed(r""" - nix-build --no-sandbox -E '(with import {}; runCommand "foo" {} " - mkdir -p $out - cp ${pkgs.coreutils}/bin/id /tmp/id - ")' - """.strip()) + # Copying to /tmp should succeed. + machine.succeed(r""" + nix-build --no-sandbox -E '(with import {}; runCommand "foo" {} " + mkdir -p $out + cp ${pkgs.coreutils}/bin/id /tmp/id + ")' + """.strip()) - machine.succeed('[[ $(stat -c %a /tmp/id) = 555 ]]') + machine.succeed('[[ $(stat -c %a /tmp/id) = 555 ]]') - machine.succeed("rm /tmp/id") + machine.succeed("rm /tmp/id") - # Creating a setuid binary should fail. - machine.fail(r""" - nix-build --no-sandbox -E '(with import {}; runCommand "foo" {} " - mkdir -p $out - cp ${pkgs.coreutils}/bin/id /tmp/id - chmod 4755 /tmp/id - ")' - """.strip()) + # Creating a setuid binary should fail. + machine.fail(r""" + nix-build --no-sandbox -E '(with import {}; runCommand "foo" {} " + mkdir -p $out + cp ${pkgs.coreutils}/bin/id /tmp/id + chmod 4755 /tmp/id + ")' + """.strip()) - machine.succeed('[[ $(stat -c %a /tmp/id) = 555 ]]') + machine.succeed('[[ $(stat -c %a /tmp/id) = 555 ]]') - machine.succeed("rm /tmp/id") + machine.succeed("rm /tmp/id") - # Creating a setgid binary should fail. - machine.fail(r""" - nix-build --no-sandbox -E '(with import {}; runCommand "foo" {} " - mkdir -p $out - cp ${pkgs.coreutils}/bin/id /tmp/id - chmod 2755 /tmp/id - ")' - """.strip()) + # Creating a setgid binary should fail. + machine.fail(r""" + nix-build --no-sandbox -E '(with import {}; runCommand "foo" {} " + mkdir -p $out + cp ${pkgs.coreutils}/bin/id /tmp/id + chmod 2755 /tmp/id + ")' + """.strip()) - machine.succeed('[[ $(stat -c %a /tmp/id) = 555 ]]') + machine.succeed('[[ $(stat -c %a /tmp/id) = 555 ]]') - machine.succeed("rm /tmp/id") + machine.succeed("rm /tmp/id") - # The checks should also work on 32-bit binaries. - machine.fail(r""" - nix-build --no-sandbox -E '(with import { system = "i686-linux"; }; runCommand "foo" {} " - mkdir -p $out - cp ${pkgs.coreutils}/bin/id /tmp/id - chmod 2755 /tmp/id - ")' - """.strip()) + # The checks should also work on 32-bit binaries. + machine.fail(r""" + nix-build --no-sandbox -E '(with import { system = "i686-linux"; }; runCommand "foo" {} " + mkdir -p $out + cp ${pkgs.coreutils}/bin/id /tmp/id + chmod 2755 /tmp/id + ")' + """.strip()) - machine.succeed('[[ $(stat -c %a /tmp/id) = 555 ]]') + machine.succeed('[[ $(stat -c %a /tmp/id) = 555 ]]') - machine.succeed("rm /tmp/id") + machine.succeed("rm /tmp/id") - # The tests above use fchmodat(). Test chmod() as well. - machine.succeed(r""" - nix-build --no-sandbox -E '(with import {}; runCommand "foo" { buildInputs = [ perl ]; } " - mkdir -p $out - cp ${pkgs.coreutils}/bin/id /tmp/id - perl -e \"chmod 0666, qw(/tmp/id) or die\" - ")' - """.strip()) + # The tests above use fchmodat(). Test chmod() as well. + machine.succeed(r""" + nix-build --no-sandbox -E '(with import {}; runCommand "foo" { buildInputs = [ perl ]; } " + mkdir -p $out + cp ${pkgs.coreutils}/bin/id /tmp/id + perl -e \"chmod 0666, qw(/tmp/id) or die\" + ")' + """.strip()) - machine.succeed('[[ $(stat -c %a /tmp/id) = 666 ]]') + machine.succeed('[[ $(stat -c %a /tmp/id) = 666 ]]') - machine.succeed("rm /tmp/id") + machine.succeed("rm /tmp/id") - machine.fail(r""" - nix-build --no-sandbox -E '(with import {}; runCommand "foo" { buildInputs = [ perl ]; } " - mkdir -p $out - cp ${pkgs.coreutils}/bin/id /tmp/id - perl -e \"chmod 04755, qw(/tmp/id) or die\" - ")' - """.strip()) + machine.fail(r""" + nix-build --no-sandbox -E '(with import {}; runCommand "foo" { buildInputs = [ perl ]; } " + mkdir -p $out + cp ${pkgs.coreutils}/bin/id /tmp/id + perl -e \"chmod 04755, qw(/tmp/id) or die\" + ")' + """.strip()) - machine.succeed('[[ $(stat -c %a /tmp/id) = 555 ]]') + machine.succeed('[[ $(stat -c %a /tmp/id) = 555 ]]') - machine.succeed("rm /tmp/id") + machine.succeed("rm /tmp/id") - # And test fchmod(). - machine.succeed(r""" - nix-build --no-sandbox -E '(with import {}; runCommand "foo" { buildInputs = [ perl ]; } " - mkdir -p $out - cp ${pkgs.coreutils}/bin/id /tmp/id - perl -e \"my \\\$x; open \\\$x, qw(/tmp/id); chmod 01750, \\\$x or die\" - ")' - """.strip()) + # And test fchmod(). + machine.succeed(r""" + nix-build --no-sandbox -E '(with import {}; runCommand "foo" { buildInputs = [ perl ]; } " + mkdir -p $out + cp ${pkgs.coreutils}/bin/id /tmp/id + perl -e \"my \\\$x; open \\\$x, qw(/tmp/id); chmod 01750, \\\$x or die\" + ")' + """.strip()) - machine.succeed('[[ $(stat -c %a /tmp/id) = 1750 ]]') + machine.succeed('[[ $(stat -c %a /tmp/id) = 1750 ]]') - machine.succeed("rm /tmp/id") + machine.succeed("rm /tmp/id") - machine.fail(r""" - nix-build --no-sandbox -E '(with import {}; runCommand "foo" { buildInputs = [ perl ]; } " - mkdir -p $out - cp ${pkgs.coreutils}/bin/id /tmp/id - perl -e \"my \\\$x; open \\\$x, qw(/tmp/id); chmod 04777, \\\$x or die\" - ")' - """.strip()) + machine.fail(r""" + nix-build --no-sandbox -E '(with import {}; runCommand "foo" { buildInputs = [ perl ]; } " + mkdir -p $out + cp ${pkgs.coreutils}/bin/id /tmp/id + perl -e \"my \\\$x; open \\\$x, qw(/tmp/id); chmod 04777, \\\$x or die\" + ")' + """.strip()) - machine.succeed('[[ $(stat -c %a /tmp/id) = 555 ]]') + machine.succeed('[[ $(stat -c %a /tmp/id) = 555 ]]') - machine.succeed("rm /tmp/id") - ''; + machine.succeed("rm /tmp/id") + ''; } diff --git a/tests/nixos/sourcehut-flakes.nix b/tests/nixos/sourcehut-flakes.nix index 2f469457a..bb26b7ebb 100644 --- a/tests/nixos/sourcehut-flakes.nix +++ b/tests/nixos/sourcehut-flakes.nix @@ -1,22 +1,27 @@ -{ lib, config, hostPkgs, nixpkgs, ... }: +{ + lib, + config, + hostPkgs, + nixpkgs, + ... +}: let pkgs = config.nodes.sourcehut.nixpkgs.pkgs; # Generate a fake root CA and a fake git.sr.ht certificate. - cert = pkgs.runCommand "cert" { buildInputs = [ pkgs.openssl ]; } - '' - mkdir -p $out + cert = pkgs.runCommand "cert" { buildInputs = [ pkgs.openssl ]; } '' + mkdir -p $out - openssl genrsa -out ca.key 2048 - openssl req -new -x509 -days 36500 -key ca.key \ - -subj "/C=NL/ST=Denial/L=Springfield/O=Dis/CN=Root CA" -out $out/ca.crt + openssl genrsa -out ca.key 2048 + openssl req -new -x509 -days 36500 -key ca.key \ + -subj "/C=NL/ST=Denial/L=Springfield/O=Dis/CN=Root CA" -out $out/ca.crt - openssl req -newkey rsa:2048 -nodes -keyout $out/server.key \ - -subj "/C=CN/ST=Denial/L=Springfield/O=Dis/CN=git.sr.ht" -out server.csr - openssl x509 -req -extfile <(printf "subjectAltName=DNS:git.sr.ht") \ - -days 36500 -in server.csr -CA $out/ca.crt -CAkey ca.key -CAcreateserial -out $out/server.crt - ''; + openssl req -newkey rsa:2048 -nodes -keyout $out/server.key \ + -subj "/C=CN/ST=Denial/L=Springfield/O=Dis/CN=git.sr.ht" -out server.csr + openssl x509 -req -extfile <(printf "subjectAltName=DNS:git.sr.ht") \ + -days 36500 -in server.csr -CA $out/ca.crt -CAkey ca.key -CAcreateserial -out $out/server.crt + ''; registry = pkgs.writeTextFile { name = "registry"; @@ -41,80 +46,92 @@ let destination = "/flake-registry.json"; }; - nixpkgs-repo = pkgs.runCommand "nixpkgs-flake" { } - '' - dir=NixOS-nixpkgs-${nixpkgs.shortRev} - cp -prd ${nixpkgs} $dir + nixpkgs-repo = pkgs.runCommand "nixpkgs-flake" { } '' + dir=NixOS-nixpkgs-${nixpkgs.shortRev} + cp -prd ${nixpkgs} $dir - # Set the correct timestamp in the tarball. - find $dir -print0 | xargs -0 touch -h -t ${builtins.substring 0 12 nixpkgs.lastModifiedDate}.${builtins.substring 12 2 nixpkgs.lastModifiedDate} -- + # Set the correct timestamp in the tarball. + find $dir -print0 | xargs -0 touch -h -t ${builtins.substring 0 12 nixpkgs.lastModifiedDate}.${ + builtins.substring 12 2 nixpkgs.lastModifiedDate + } -- - mkdir -p $out/archive - tar cfz $out/archive/${nixpkgs.rev}.tar.gz $dir --hard-dereference + mkdir -p $out/archive + tar cfz $out/archive/${nixpkgs.rev}.tar.gz $dir --hard-dereference - echo 'ref: refs/heads/master' > $out/HEAD + echo 'ref: refs/heads/master' > $out/HEAD - mkdir -p $out/info - echo -e '${nixpkgs.rev}\trefs/heads/master\n${nixpkgs.rev}\trefs/tags/foo-bar' > $out/info/refs - ''; + mkdir -p $out/info + echo -e '${nixpkgs.rev}\trefs/heads/master\n${nixpkgs.rev}\trefs/tags/foo-bar' > $out/info/refs + ''; in - { - name = "sourcehut-flakes"; +{ + name = "sourcehut-flakes"; - nodes = + nodes = { + # Impersonate git.sr.ht + sourcehut = + { config, pkgs, ... }: { - # Impersonate git.sr.ht - sourcehut = - { config, pkgs, ... }: - { - networking.firewall.allowedTCPPorts = [ 80 443 ]; + networking.firewall.allowedTCPPorts = [ + 80 + 443 + ]; - services.httpd.enable = true; - services.httpd.adminAddr = "foo@example.org"; - services.httpd.extraConfig = '' - ErrorLog syslog:local6 - ''; - services.httpd.virtualHosts."git.sr.ht" = - { - forceSSL = true; - sslServerKey = "${cert}/server.key"; - sslServerCert = "${cert}/server.crt"; - servedDirs = - [ - { - urlPath = "/~NixOS/nixpkgs"; - dir = nixpkgs-repo; - } - { - urlPath = "/~NixOS/flake-registry/blob/master"; - dir = registry; - } - ]; - }; - }; - - client = - { config, lib, pkgs, nodes, ... }: - { - virtualisation.writableStore = true; - virtualisation.diskSize = 2048; - virtualisation.additionalPaths = [ pkgs.hello pkgs.fuse ]; - virtualisation.memorySize = 4096; - nix.settings.substituters = lib.mkForce [ ]; - nix.extraOptions = '' - experimental-features = nix-command flakes - flake-registry = https://git.sr.ht/~NixOS/flake-registry/blob/master/flake-registry.json - ''; - environment.systemPackages = [ pkgs.jq ]; - networking.hosts.${(builtins.head nodes.sourcehut.networking.interfaces.eth1.ipv4.addresses).address} = - [ "git.sr.ht" ]; - security.pki.certificateFiles = [ "${cert}/ca.crt" ]; - }; + services.httpd.enable = true; + services.httpd.adminAddr = "foo@example.org"; + services.httpd.extraConfig = '' + ErrorLog syslog:local6 + ''; + services.httpd.virtualHosts."git.sr.ht" = { + forceSSL = true; + sslServerKey = "${cert}/server.key"; + sslServerCert = "${cert}/server.crt"; + servedDirs = [ + { + urlPath = "/~NixOS/nixpkgs"; + dir = nixpkgs-repo; + } + { + urlPath = "/~NixOS/flake-registry/blob/master"; + dir = registry; + } + ]; + }; }; - testScript = { nodes }: '' + client = + { + config, + lib, + pkgs, + nodes, + ... + }: + { + virtualisation.writableStore = true; + virtualisation.diskSize = 2048; + virtualisation.additionalPaths = [ + pkgs.hello + pkgs.fuse + ]; + virtualisation.memorySize = 4096; + nix.settings.substituters = lib.mkForce [ ]; + nix.extraOptions = '' + experimental-features = nix-command flakes + flake-registry = https://git.sr.ht/~NixOS/flake-registry/blob/master/flake-registry.json + ''; + environment.systemPackages = [ pkgs.jq ]; + networking.hosts.${(builtins.head nodes.sourcehut.networking.interfaces.eth1.ipv4.addresses).address} = + [ "git.sr.ht" ]; + security.pki.certificateFiles = [ "${cert}/ca.crt" ]; + }; + }; + + testScript = + { nodes }: + '' # fmt: off import json import time diff --git a/tests/nixos/tarball-flakes.nix b/tests/nixos/tarball-flakes.nix index 84cf377ec..7b3638b64 100644 --- a/tests/nixos/tarball-flakes.nix +++ b/tests/nixos/tarball-flakes.nix @@ -1,94 +1,106 @@ -{ lib, config, nixpkgs, ... }: +{ + lib, + config, + nixpkgs, + ... +}: let pkgs = config.nodes.machine.nixpkgs.pkgs; - root = pkgs.runCommand "nixpkgs-flake" {} - '' - mkdir -p $out/{stable,tags} + root = pkgs.runCommand "nixpkgs-flake" { } '' + mkdir -p $out/{stable,tags} - set -x - dir=nixpkgs-${nixpkgs.shortRev} - cp -prd ${nixpkgs} $dir - # Set the correct timestamp in the tarball. - find $dir -print0 | xargs -0 touch -h -t ${builtins.substring 0 12 nixpkgs.lastModifiedDate}.${builtins.substring 12 2 nixpkgs.lastModifiedDate} -- - tar cfz $out/stable/${nixpkgs.rev}.tar.gz $dir --hard-dereference + set -x + dir=nixpkgs-${nixpkgs.shortRev} + cp -prd ${nixpkgs} $dir + # Set the correct timestamp in the tarball. + find $dir -print0 | xargs -0 touch -h -t ${builtins.substring 0 12 nixpkgs.lastModifiedDate}.${ + builtins.substring 12 2 nixpkgs.lastModifiedDate + } -- + tar cfz $out/stable/${nixpkgs.rev}.tar.gz $dir --hard-dereference - # Set the "Link" header on the redirect but not the final response to - # simulate an S3-like serving environment where the final host cannot set - # arbitrary headers. - cat >$out/tags/.htaccess <; rel=\"immutable\"" - EOF - ''; + # Set the "Link" header on the redirect but not the final response to + # simulate an S3-like serving environment where the final host cannot set + # arbitrary headers. + cat >$out/tags/.htaccess <; rel=\"immutable\"" + EOF + ''; in { name = "tarball-flakes"; - nodes = - { - machine = - { config, pkgs, ... }: - { networking.firewall.allowedTCPPorts = [ 80 ]; + nodes = { + machine = + { config, pkgs, ... }: + { + networking.firewall.allowedTCPPorts = [ 80 ]; - services.httpd.enable = true; - services.httpd.adminAddr = "foo@example.org"; - services.httpd.extraConfig = '' - ErrorLog syslog:local6 - ''; - services.httpd.virtualHosts."localhost" = - { servedDirs = - [ { urlPath = "/"; - dir = root; - } - ]; - }; - - virtualisation.writableStore = true; - virtualisation.diskSize = 2048; - virtualisation.additionalPaths = [ pkgs.hello pkgs.fuse ]; - virtualisation.memorySize = 4096; - nix.settings.substituters = lib.mkForce [ ]; - nix.extraOptions = "experimental-features = nix-command flakes"; + services.httpd.enable = true; + services.httpd.adminAddr = "foo@example.org"; + services.httpd.extraConfig = '' + ErrorLog syslog:local6 + ''; + services.httpd.virtualHosts."localhost" = { + servedDirs = [ + { + urlPath = "/"; + dir = root; + } + ]; }; - }; - testScript = { nodes }: '' - # fmt: off - import json + virtualisation.writableStore = true; + virtualisation.diskSize = 2048; + virtualisation.additionalPaths = [ + pkgs.hello + pkgs.fuse + ]; + virtualisation.memorySize = 4096; + nix.settings.substituters = lib.mkForce [ ]; + nix.extraOptions = "experimental-features = nix-command flakes"; + }; + }; - start_all() + testScript = + { nodes }: + '' + # fmt: off + import json - machine.wait_for_unit("httpd.service") + start_all() - out = machine.succeed("nix flake metadata --json http://localhost/tags/latest.tar.gz") - print(out) - info = json.loads(out) + machine.wait_for_unit("httpd.service") - # Check that we got redirected to the immutable URL. - assert info["locked"]["url"] == "http://localhost/stable/${nixpkgs.rev}.tar.gz" + out = machine.succeed("nix flake metadata --json http://localhost/tags/latest.tar.gz") + print(out) + info = json.loads(out) - # Check that we got a fingerprint for caching. - assert info["fingerprint"] + # Check that we got redirected to the immutable URL. + assert info["locked"]["url"] == "http://localhost/stable/${nixpkgs.rev}.tar.gz" - # Check that we got the rev and revCount attributes. - assert info["revision"] == "${nixpkgs.rev}" - assert info["revCount"] == 1234 + # Check that we got a fingerprint for caching. + assert info["fingerprint"] - # Check that a 0-byte HTTP 304 "Not modified" result works. - machine.succeed("nix flake metadata --refresh --json http://localhost/tags/latest.tar.gz") + # Check that we got the rev and revCount attributes. + assert info["revision"] == "${nixpkgs.rev}" + assert info["revCount"] == 1234 - # Check that fetching with rev/revCount/narHash succeeds. - machine.succeed("nix flake metadata --json http://localhost/tags/latest.tar.gz?rev=" + info["revision"]) - machine.succeed("nix flake metadata --json http://localhost/tags/latest.tar.gz?revCount=" + str(info["revCount"])) - machine.succeed("nix flake metadata --json http://localhost/tags/latest.tar.gz?narHash=" + info["locked"]["narHash"]) + # Check that a 0-byte HTTP 304 "Not modified" result works. + machine.succeed("nix flake metadata --refresh --json http://localhost/tags/latest.tar.gz") - # Check that fetching fails if we provide incorrect attributes. - machine.fail("nix flake metadata --json http://localhost/tags/latest.tar.gz?rev=493300eb13ae6fb387fbd47bf54a85915acc31c0") - machine.fail("nix flake metadata --json http://localhost/tags/latest.tar.gz?revCount=789") - machine.fail("nix flake metadata --json http://localhost/tags/latest.tar.gz?narHash=sha256-tbudgBSg+bHWHiHnlteNzN8TUvI80ygS9IULh4rklEw=") - ''; + # Check that fetching with rev/revCount/narHash succeeds. + machine.succeed("nix flake metadata --json http://localhost/tags/latest.tar.gz?rev=" + info["revision"]) + machine.succeed("nix flake metadata --json http://localhost/tags/latest.tar.gz?revCount=" + str(info["revCount"])) + machine.succeed("nix flake metadata --json http://localhost/tags/latest.tar.gz?narHash=" + info["locked"]["narHash"]) + + # Check that fetching fails if we provide incorrect attributes. + machine.fail("nix flake metadata --json http://localhost/tags/latest.tar.gz?rev=493300eb13ae6fb387fbd47bf54a85915acc31c0") + machine.fail("nix flake metadata --json http://localhost/tags/latest.tar.gz?revCount=789") + machine.fail("nix flake metadata --json http://localhost/tags/latest.tar.gz?narHash=sha256-tbudgBSg+bHWHiHnlteNzN8TUvI80ygS9IULh4rklEw=") + ''; } diff --git a/tests/nixos/user-sandboxing/default.nix b/tests/nixos/user-sandboxing/default.nix index 8a16f44e8..028efd17f 100644 --- a/tests/nixos/user-sandboxing/default.nix +++ b/tests/nixos/user-sandboxing/default.nix @@ -3,12 +3,15 @@ let pkgs = config.nodes.machine.nixpkgs.pkgs; - attacker = pkgs.runCommandWith { - name = "attacker"; - stdenv = pkgs.pkgsStatic.stdenv; - } '' - $CC -static -o $out ${./attacker.c} - ''; + attacker = + pkgs.runCommandWith + { + name = "attacker"; + stdenv = pkgs.pkgsStatic.stdenv; + } + '' + $CC -static -o $out ${./attacker.c} + ''; try-open-build-dir = pkgs.writeScript "try-open-build-dir" '' export PATH=${pkgs.coreutils}/bin:$PATH @@ -55,75 +58,88 @@ in name = "sandbox-setuid-leak"; nodes.machine = - { config, lib, pkgs, ... }: - { virtualisation.writableStore = true; + { + config, + lib, + pkgs, + ... + }: + { + virtualisation.writableStore = true; nix.settings.substituters = lib.mkForce [ ]; nix.nrBuildUsers = 1; - virtualisation.additionalPaths = [ pkgs.busybox-sandbox-shell attacker try-open-build-dir create-hello-world pkgs.socat ]; + virtualisation.additionalPaths = [ + pkgs.busybox-sandbox-shell + attacker + try-open-build-dir + create-hello-world + pkgs.socat + ]; boot.kernelPackages = pkgs.linuxPackages_latest; users.users.alice = { isNormalUser = true; }; }; - testScript = { nodes }: '' - start_all() + testScript = + { nodes }: + '' + start_all() - with subtest("A builder can't give access to its build directory"): - # Make sure that a builder can't change the permissions on its build - # directory to the point of opening it up to external users + with subtest("A builder can't give access to its build directory"): + # Make sure that a builder can't change the permissions on its build + # directory to the point of opening it up to external users - # A derivation whose builder tries to make its build directory as open - # as possible and wait for someone to hijack it - machine.succeed(r""" - nix-build -v -E ' - builtins.derivation { - name = "open-build-dir"; - system = builtins.currentSystem; - builder = "${pkgs.busybox-sandbox-shell}/bin/sh"; - args = [ (builtins.storePath "${try-open-build-dir}") ]; - }' >&2 & - """.strip()) + # A derivation whose builder tries to make its build directory as open + # as possible and wait for someone to hijack it + machine.succeed(r""" + nix-build -v -E ' + builtins.derivation { + name = "open-build-dir"; + system = builtins.currentSystem; + builder = "${pkgs.busybox-sandbox-shell}/bin/sh"; + args = [ (builtins.storePath "${try-open-build-dir}") ]; + }' >&2 & + """.strip()) - # Wait for the build to be ready - # This is OK because it runs as root, so we can access everything - machine.wait_for_file("/tmp/nix-build-open-build-dir.drv-0/build/syncPoint") + # Wait for the build to be ready + # This is OK because it runs as root, so we can access everything + machine.wait_for_file("/tmp/nix-build-open-build-dir.drv-0/build/syncPoint") - # But Alice shouldn't be able to access the build directory - machine.fail("su alice -c 'ls /tmp/nix-build-open-build-dir.drv-0/build'") - machine.fail("su alice -c 'touch /tmp/nix-build-open-build-dir.drv-0/build/bar'") - machine.fail("su alice -c 'cat /tmp/nix-build-open-build-dir.drv-0/build/foo'") + # But Alice shouldn't be able to access the build directory + machine.fail("su alice -c 'ls /tmp/nix-build-open-build-dir.drv-0/build'") + machine.fail("su alice -c 'touch /tmp/nix-build-open-build-dir.drv-0/build/bar'") + machine.fail("su alice -c 'cat /tmp/nix-build-open-build-dir.drv-0/build/foo'") - # Tell the user to finish the build - machine.succeed("echo foo > /tmp/nix-build-open-build-dir.drv-0/build/syncPoint") + # Tell the user to finish the build + machine.succeed("echo foo > /tmp/nix-build-open-build-dir.drv-0/build/syncPoint") - with subtest("Being able to execute stuff as the build user doesn't give access to the build dir"): - machine.succeed(r""" - nix-build -E ' - builtins.derivation { - name = "innocent"; - system = builtins.currentSystem; - builder = "${pkgs.busybox-sandbox-shell}/bin/sh"; - args = [ (builtins.storePath "${create-hello-world}") ]; - }' >&2 & - """.strip()) - machine.wait_for_file("/tmp/nix-build-innocent.drv-0/build/syncPoint") + with subtest("Being able to execute stuff as the build user doesn't give access to the build dir"): + machine.succeed(r""" + nix-build -E ' + builtins.derivation { + name = "innocent"; + system = builtins.currentSystem; + builder = "${pkgs.busybox-sandbox-shell}/bin/sh"; + args = [ (builtins.storePath "${create-hello-world}") ]; + }' >&2 & + """.strip()) + machine.wait_for_file("/tmp/nix-build-innocent.drv-0/build/syncPoint") - # The build ran as `nixbld1` (which is the only build user on the - # machine), but a process running as `nixbld1` outside the sandbox - # shouldn't be able to touch the build directory regardless - machine.fail("su nixbld1 --shell ${pkgs.busybox-sandbox-shell}/bin/sh -c 'ls /tmp/nix-build-innocent.drv-0/build'") - machine.fail("su nixbld1 --shell ${pkgs.busybox-sandbox-shell}/bin/sh -c 'echo pwned > /tmp/nix-build-innocent.drv-0/build/result'") + # The build ran as `nixbld1` (which is the only build user on the + # machine), but a process running as `nixbld1` outside the sandbox + # shouldn't be able to touch the build directory regardless + machine.fail("su nixbld1 --shell ${pkgs.busybox-sandbox-shell}/bin/sh -c 'ls /tmp/nix-build-innocent.drv-0/build'") + machine.fail("su nixbld1 --shell ${pkgs.busybox-sandbox-shell}/bin/sh -c 'echo pwned > /tmp/nix-build-innocent.drv-0/build/result'") - # Finish the build - machine.succeed("echo foo > /tmp/nix-build-innocent.drv-0/build/syncPoint") + # Finish the build + machine.succeed("echo foo > /tmp/nix-build-innocent.drv-0/build/syncPoint") - # Check that the build was not affected - machine.succeed(r""" - cat ./result - test "$(cat ./result)" = "hello, world" - """.strip()) - ''; + # Check that the build was not affected + machine.succeed(r""" + cat ./result + test "$(cat ./result)" = "hello, world" + """.strip()) + ''; } - diff --git a/tests/repl-completion.nix b/tests/repl-completion.nix index 3ba198a98..07406e969 100644 --- a/tests/repl-completion.nix +++ b/tests/repl-completion.nix @@ -1,40 +1,45 @@ -{ runCommand, nix, expect }: +{ + runCommand, + nix, + expect, +}: # We only use expect when necessary, e.g. for testing tab completion in nix repl. # See also tests/functional/repl.sh -runCommand "repl-completion" { - nativeBuildInputs = [ - expect - nix - ]; - expectScript = '' - # Regression https://github.com/NixOS/nix/pull/10778 - spawn nix repl --offline --extra-experimental-features nix-command - expect "nix-repl>" - send "foo = import ./does-not-exist.nix\n" - expect "nix-repl>" - send "foo.\t" - expect { - "nix-repl>" { - puts "Got another prompt. Good." +runCommand "repl-completion" + { + nativeBuildInputs = [ + expect + nix + ]; + expectScript = '' + # Regression https://github.com/NixOS/nix/pull/10778 + spawn nix repl --offline --extra-experimental-features nix-command + expect "nix-repl>" + send "foo = import ./does-not-exist.nix\n" + expect "nix-repl>" + send "foo.\t" + expect { + "nix-repl>" { + puts "Got another prompt. Good." + } + eof { + puts "Got EOF. Bad." + exit 1 + } } - eof { - puts "Got EOF. Bad." - exit 1 - } - } - exit 0 - ''; - passAsFile = [ "expectScript" ]; -} -'' - export NIX_STORE=$TMPDIR/store - export NIX_STATE_DIR=$TMPDIR/state - export HOME=$TMPDIR/home - mkdir $HOME + exit 0 + ''; + passAsFile = [ "expectScript" ]; + } + '' + export NIX_STORE=$TMPDIR/store + export NIX_STATE_DIR=$TMPDIR/state + export HOME=$TMPDIR/home + mkdir $HOME - nix-store --init - expect $expectScriptPath - touch $out -'' \ No newline at end of file + nix-store --init + expect $expectScriptPath + touch $out + '' From f629d81df094d296fbd6965d825a5085eb0affcc Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Fri, 24 Jan 2025 22:21:27 +0100 Subject: [PATCH 698/718] test: Fix shifted source positions after formatting --- ...putDependencies-multi-elem-context.err.exp | 10 +-- ...putDependencies-wrong-element-kind.err.exp | 10 +-- ...al-fail-assert-equal-attrs-names-2.err.exp | 4 +- ...eval-fail-assert-equal-attrs-names.err.exp | 4 +- ...ail-assert-equal-derivations-extra.err.exp | 18 ++--- ...eval-fail-assert-equal-derivations.err.exp | 18 ++--- ...-fail-assert-equal-function-direct.err.exp | 4 +- ...eval-fail-assert-equal-list-length.err.exp | 4 +- .../lang/eval-fail-assert-nested-bool.err.exp | 76 ++++++++---------- .../functional/lang/eval-fail-assert.err.exp | 36 ++++----- .../lang/eval-fail-attr-name-type.err.exp | 14 ++-- ...fail-attrset-merge-drops-later-rec.err.exp | 9 ++- ...al-fail-bad-string-interpolation-4.err.exp | 8 +- .../lang/eval-fail-derivation-name.err.exp | 16 ++-- .../lang/eval-fail-dup-dynamic-attrs.err.exp | 16 ++-- .../lang/eval-fail-duplicate-traces.err.exp | 52 ++++++------ ...-fail-fetchurl-baseName-attrs-name.err.exp | 4 +- ...ake-ref-to-string-negative-integer.err.exp | 18 +++-- ...-foldlStrict-strict-op-application.err.exp | 44 +++++----- .../lang/eval-fail-hashfile-missing.err.exp | 10 +-- tests/functional/lang/eval-fail-list.err.exp | 6 +- .../lang/eval-fail-missing-arg.err.exp | 13 +-- .../lang/eval-fail-mutual-recursion.err.exp | 80 +++++++++---------- .../lang/eval-fail-nested-list-items.err.exp | 10 +-- .../lang/eval-fail-not-throws.err.exp | 12 +-- .../lang/eval-fail-overflowing-add.err.exp | 10 +-- .../lang/eval-fail-overflowing-div.err.exp | 30 +++---- .../lang/eval-fail-overflowing-mul.err.exp | 20 ++--- .../lang/eval-fail-overflowing-sub.err.exp | 10 +-- .../lang/eval-fail-recursion.err.exp | 18 +++-- .../functional/lang/eval-fail-remove.err.exp | 16 ++-- .../functional/lang/eval-fail-scope-5.err.exp | 36 ++++----- .../lang/eval-fail-undeclared-arg.err.exp | 8 +- .../eval-fail-using-set-as-attr-name.err.exp | 20 ++--- .../repl/doc-comment-curried-args.expected | 6 +- .../repl/doc-comment-formals.expected | 3 +- .../repl/doc-comment-function.expected | 3 +- tests/functional/repl/doc-compact.expected | 3 +- tests/functional/repl/doc-constant.expected | 33 ++++---- tests/functional/repl/doc-floatedIn.expected | 3 +- tests/functional/repl/doc-functor.expected | 52 ++++++------ .../repl/doc-lambda-flavors.expected | 12 ++- .../functional/repl/doc-measurement.expected | 3 +- .../functional/repl/doc-unambiguous.expected | 3 +- 44 files changed, 400 insertions(+), 385 deletions(-) diff --git a/tests/functional/lang/eval-fail-addDrvOutputDependencies-multi-elem-context.err.exp b/tests/functional/lang/eval-fail-addDrvOutputDependencies-multi-elem-context.err.exp index 6828e03c8..56fbffa19 100644 --- a/tests/functional/lang/eval-fail-addDrvOutputDependencies-multi-elem-context.err.exp +++ b/tests/functional/lang/eval-fail-addDrvOutputDependencies-multi-elem-context.err.exp @@ -1,9 +1,9 @@ error: … while calling the 'addDrvOutputDependencies' builtin - at /pwd/lang/eval-fail-addDrvOutputDependencies-multi-elem-context.nix:18:4: - 17| - 18| in builtins.addDrvOutputDependencies combo-path - | ^ - 19| + at /pwd/lang/eval-fail-addDrvOutputDependencies-multi-elem-context.nix:25:1: + 24| in + 25| builtins.addDrvOutputDependencies combo-path + | ^ + 26| error: context of string '/nix/store/pg9yqs4yd85yhdm3f4i5dyaqp5jahrsz-fail.drv/nix/store/2dxd5frb715z451vbf7s8birlf3argbk-fail-2.drv' must have exactly one element, but has 2 diff --git a/tests/functional/lang/eval-fail-addDrvOutputDependencies-wrong-element-kind.err.exp b/tests/functional/lang/eval-fail-addDrvOutputDependencies-wrong-element-kind.err.exp index 72b5e6368..d8399380e 100644 --- a/tests/functional/lang/eval-fail-addDrvOutputDependencies-wrong-element-kind.err.exp +++ b/tests/functional/lang/eval-fail-addDrvOutputDependencies-wrong-element-kind.err.exp @@ -1,9 +1,9 @@ error: … while calling the 'addDrvOutputDependencies' builtin - at /pwd/lang/eval-fail-addDrvOutputDependencies-wrong-element-kind.nix:9:4: - 8| - 9| in builtins.addDrvOutputDependencies drv.outPath - | ^ - 10| + at /pwd/lang/eval-fail-addDrvOutputDependencies-wrong-element-kind.nix:13:1: + 12| in + 13| builtins.addDrvOutputDependencies drv.outPath + | ^ + 14| error: `addDrvOutputDependencies` can only act on derivations, not on a derivation output such as 'out' diff --git a/tests/functional/lang/eval-fail-assert-equal-attrs-names-2.err.exp b/tests/functional/lang/eval-fail-assert-equal-attrs-names-2.err.exp index 4b68d97c2..5912e6b8c 100644 --- a/tests/functional/lang/eval-fail-assert-equal-attrs-names-2.err.exp +++ b/tests/functional/lang/eval-fail-assert-equal-attrs-names-2.err.exp @@ -1,8 +1,8 @@ error: … while evaluating the condition of the assertion '({ a = true; } == { a = true; b = true; })' at /pwd/lang/eval-fail-assert-equal-attrs-names-2.nix:1:1: - 1| assert { a = true; } == { a = true; b = true; }; + 1| assert | ^ - 2| throw "unreachable" + 2| { error: attribute names of attribute set '{ a = true; }' differs from attribute set '{ a = true; b = true; }' diff --git a/tests/functional/lang/eval-fail-assert-equal-attrs-names.err.exp b/tests/functional/lang/eval-fail-assert-equal-attrs-names.err.exp index bc61ca63a..a93b26324 100644 --- a/tests/functional/lang/eval-fail-assert-equal-attrs-names.err.exp +++ b/tests/functional/lang/eval-fail-assert-equal-attrs-names.err.exp @@ -1,8 +1,8 @@ error: … while evaluating the condition of the assertion '({ a = true; b = true; } == { a = true; })' at /pwd/lang/eval-fail-assert-equal-attrs-names.nix:1:1: - 1| assert { a = true; b = true; } == { a = true; }; + 1| assert | ^ - 2| throw "unreachable" + 2| { error: attribute names of attribute set '{ a = true; b = true; }' differs from attribute set '{ a = true; }' diff --git a/tests/functional/lang/eval-fail-assert-equal-derivations-extra.err.exp b/tests/functional/lang/eval-fail-assert-equal-derivations-extra.err.exp index 7f4924074..9ccf5e4dc 100644 --- a/tests/functional/lang/eval-fail-assert-equal-derivations-extra.err.exp +++ b/tests/functional/lang/eval-fail-assert-equal-derivations-extra.err.exp @@ -3,23 +3,23 @@ error: at /pwd/lang/eval-fail-assert-equal-derivations-extra.nix:1:1: 1| assert | ^ - 2| { foo = { type = "derivation"; outPath = "/nix/store/0"; }; } + 2| { … while comparing attribute 'foo' … where left hand side is - at /pwd/lang/eval-fail-assert-equal-derivations-extra.nix:2:5: - 1| assert - 2| { foo = { type = "derivation"; outPath = "/nix/store/0"; }; } + at /pwd/lang/eval-fail-assert-equal-derivations-extra.nix:3:5: + 2| { + 3| foo = { | ^ - 3| == + 4| type = "derivation"; … where right hand side is - at /pwd/lang/eval-fail-assert-equal-derivations-extra.nix:4:5: - 3| == - 4| { foo = { type = "derivation"; outPath = "/nix/store/1"; devious = true; }; }; + at /pwd/lang/eval-fail-assert-equal-derivations-extra.nix:8:5: + 7| } == { + 8| foo = { | ^ - 5| throw "unreachable" + 9| type = "derivation"; … while comparing a derivation by its 'outPath' attribute diff --git a/tests/functional/lang/eval-fail-assert-equal-derivations.err.exp b/tests/functional/lang/eval-fail-assert-equal-derivations.err.exp index d7f0face0..2be1f4858 100644 --- a/tests/functional/lang/eval-fail-assert-equal-derivations.err.exp +++ b/tests/functional/lang/eval-fail-assert-equal-derivations.err.exp @@ -3,23 +3,23 @@ error: at /pwd/lang/eval-fail-assert-equal-derivations.nix:1:1: 1| assert | ^ - 2| { foo = { type = "derivation"; outPath = "/nix/store/0"; ignored = abort "not ignored"; }; } + 2| { … while comparing attribute 'foo' … where left hand side is - at /pwd/lang/eval-fail-assert-equal-derivations.nix:2:5: - 1| assert - 2| { foo = { type = "derivation"; outPath = "/nix/store/0"; ignored = abort "not ignored"; }; } + at /pwd/lang/eval-fail-assert-equal-derivations.nix:3:5: + 2| { + 3| foo = { | ^ - 3| == + 4| type = "derivation"; … where right hand side is - at /pwd/lang/eval-fail-assert-equal-derivations.nix:4:5: - 3| == - 4| { foo = { type = "derivation"; outPath = "/nix/store/1"; ignored = abort "not ignored"; }; }; + at /pwd/lang/eval-fail-assert-equal-derivations.nix:9:5: + 8| } == { + 9| foo = { | ^ - 5| throw "unreachable" + 10| type = "derivation"; … while comparing a derivation by its 'outPath' attribute diff --git a/tests/functional/lang/eval-fail-assert-equal-function-direct.err.exp b/tests/functional/lang/eval-fail-assert-equal-function-direct.err.exp index f06d79698..93c88a80c 100644 --- a/tests/functional/lang/eval-fail-assert-equal-function-direct.err.exp +++ b/tests/functional/lang/eval-fail-assert-equal-function-direct.err.exp @@ -2,8 +2,8 @@ error: … while evaluating the condition of the assertion '((x: x) == (x: x))' at /pwd/lang/eval-fail-assert-equal-function-direct.nix:3:1: 2| # This only compares a direct comparison and makes no claims about functions in nested structures. - 3| assert + 3| assert (x: x) == (x: x); | ^ - 4| (x: x) + 4| abort "unreachable" error: distinct functions and immediate comparisons of identical functions compare as unequal diff --git a/tests/functional/lang/eval-fail-assert-equal-list-length.err.exp b/tests/functional/lang/eval-fail-assert-equal-list-length.err.exp index 90108552c..e82f37875 100644 --- a/tests/functional/lang/eval-fail-assert-equal-list-length.err.exp +++ b/tests/functional/lang/eval-fail-assert-equal-list-length.err.exp @@ -1,8 +1,8 @@ error: … while evaluating the condition of the assertion '([ (1) (0) ] == [ (10) ])' at /pwd/lang/eval-fail-assert-equal-list-length.nix:1:1: - 1| assert [ 1 0 ] == [ 10 ]; + 1| assert | ^ - 2| throw "unreachable" + 2| [ error: list of size '2' is not equal to list of size '1', left hand side is '[ 1 0 ]', right hand side is '[ 10 ]' diff --git a/tests/functional/lang/eval-fail-assert-nested-bool.err.exp b/tests/functional/lang/eval-fail-assert-nested-bool.err.exp index 1debb668c..fdc081820 100644 --- a/tests/functional/lang/eval-fail-assert-nested-bool.err.exp +++ b/tests/functional/lang/eval-fail-assert-nested-bool.err.exp @@ -1,74 +1,66 @@ error: … while evaluating the condition of the assertion '({ a = { b = [ ({ c = { d = true; }; }) ]; }; } == { a = { b = [ ({ c = { d = false; }; }) ]; }; })' at /pwd/lang/eval-fail-assert-nested-bool.nix:1:1: - 1| assert + 1| assert { a.b = [ { c.d = true; } ]; } == { a.b = [ { c.d = false; } ]; }; | ^ - 2| { a.b = [ { c.d = true; } ]; } + 2| … while comparing attribute 'a' … where left hand side is - at /pwd/lang/eval-fail-assert-nested-bool.nix:2:5: - 1| assert - 2| { a.b = [ { c.d = true; } ]; } - | ^ - 3| == + at /pwd/lang/eval-fail-assert-nested-bool.nix:1:10: + 1| assert { a.b = [ { c.d = true; } ]; } == { a.b = [ { c.d = false; } ]; }; + | ^ + 2| … where right hand side is - at /pwd/lang/eval-fail-assert-nested-bool.nix:4:5: - 3| == - 4| { a.b = [ { c.d = false; } ]; }; - | ^ - 5| + at /pwd/lang/eval-fail-assert-nested-bool.nix:1:44: + 1| assert { a.b = [ { c.d = true; } ]; } == { a.b = [ { c.d = false; } ]; }; + | ^ + 2| … while comparing attribute 'b' … where left hand side is - at /pwd/lang/eval-fail-assert-nested-bool.nix:2:5: - 1| assert - 2| { a.b = [ { c.d = true; } ]; } - | ^ - 3| == + at /pwd/lang/eval-fail-assert-nested-bool.nix:1:10: + 1| assert { a.b = [ { c.d = true; } ]; } == { a.b = [ { c.d = false; } ]; }; + | ^ + 2| … where right hand side is - at /pwd/lang/eval-fail-assert-nested-bool.nix:4:5: - 3| == - 4| { a.b = [ { c.d = false; } ]; }; - | ^ - 5| + at /pwd/lang/eval-fail-assert-nested-bool.nix:1:44: + 1| assert { a.b = [ { c.d = true; } ]; } == { a.b = [ { c.d = false; } ]; }; + | ^ + 2| … while comparing list element 0 … while comparing attribute 'c' … where left hand side is - at /pwd/lang/eval-fail-assert-nested-bool.nix:2:15: - 1| assert - 2| { a.b = [ { c.d = true; } ]; } - | ^ - 3| == + at /pwd/lang/eval-fail-assert-nested-bool.nix:1:20: + 1| assert { a.b = [ { c.d = true; } ]; } == { a.b = [ { c.d = false; } ]; }; + | ^ + 2| … where right hand side is - at /pwd/lang/eval-fail-assert-nested-bool.nix:4:15: - 3| == - 4| { a.b = [ { c.d = false; } ]; }; - | ^ - 5| + at /pwd/lang/eval-fail-assert-nested-bool.nix:1:54: + 1| assert { a.b = [ { c.d = true; } ]; } == { a.b = [ { c.d = false; } ]; }; + | ^ + 2| … while comparing attribute 'd' … where left hand side is - at /pwd/lang/eval-fail-assert-nested-bool.nix:2:15: - 1| assert - 2| { a.b = [ { c.d = true; } ]; } - | ^ - 3| == + at /pwd/lang/eval-fail-assert-nested-bool.nix:1:20: + 1| assert { a.b = [ { c.d = true; } ]; } == { a.b = [ { c.d = false; } ]; }; + | ^ + 2| … where right hand side is - at /pwd/lang/eval-fail-assert-nested-bool.nix:4:15: - 3| == - 4| { a.b = [ { c.d = false; } ]; }; - | ^ - 5| + at /pwd/lang/eval-fail-assert-nested-bool.nix:1:54: + 1| assert { a.b = [ { c.d = true; } ]; } == { a.b = [ { c.d = false; } ]; }; + | ^ + 2| error: boolean 'true' is not equal to boolean 'false' diff --git a/tests/functional/lang/eval-fail-assert.err.exp b/tests/functional/lang/eval-fail-assert.err.exp index 7be9e2387..5fffe79bf 100644 --- a/tests/functional/lang/eval-fail-assert.err.exp +++ b/tests/functional/lang/eval-fail-assert.err.exp @@ -1,30 +1,30 @@ error: … while evaluating the attribute 'body' - at /pwd/lang/eval-fail-assert.nix:4:3: - 3| - 4| body = x "x"; + at /pwd/lang/eval-fail-assert.nix:7:3: + 6| + 7| body = x "x"; | ^ - 5| } + 8| } … from call site - at /pwd/lang/eval-fail-assert.nix:4:10: - 3| - 4| body = x "x"; + at /pwd/lang/eval-fail-assert.nix:7:10: + 6| + 7| body = x "x"; | ^ - 5| } + 8| } … while calling 'x' - at /pwd/lang/eval-fail-assert.nix:2:7: - 1| let { - 2| x = arg: assert arg == "y"; 123; - | ^ - 3| + at /pwd/lang/eval-fail-assert.nix:3:5: + 2| x = + 3| arg: + | ^ + 4| assert arg == "y"; … while evaluating the condition of the assertion '(arg == "y")' - at /pwd/lang/eval-fail-assert.nix:2:12: - 1| let { - 2| x = arg: assert arg == "y"; 123; - | ^ - 3| + at /pwd/lang/eval-fail-assert.nix:4:5: + 3| arg: + 4| assert arg == "y"; + | ^ + 5| 123; error: string '"x"' is not equal to string '"y"' diff --git a/tests/functional/lang/eval-fail-attr-name-type.err.exp b/tests/functional/lang/eval-fail-attr-name-type.err.exp index 6848a35ed..4ea209b13 100644 --- a/tests/functional/lang/eval-fail-attr-name-type.err.exp +++ b/tests/functional/lang/eval-fail-attr-name-type.err.exp @@ -2,20 +2,20 @@ error: … while evaluating the attribute 'puppy."${key}"' at /pwd/lang/eval-fail-attr-name-type.nix:3:5: 2| attrs = { - 3| puppy.doggy = {}; + 3| puppy.doggy = { }; | ^ 4| }; … while evaluating an attribute name - at /pwd/lang/eval-fail-attr-name-type.nix:7:17: + at /pwd/lang/eval-fail-attr-name-type.nix:7:15: 6| in - 7| attrs.puppy.${key} - | ^ + 7| attrs.puppy.${key} + | ^ 8| error: expected a string but found an integer: 1 - at /pwd/lang/eval-fail-attr-name-type.nix:7:17: + at /pwd/lang/eval-fail-attr-name-type.nix:7:15: 6| in - 7| attrs.puppy.${key} - | ^ + 7| attrs.puppy.${key} + | ^ 8| diff --git a/tests/functional/lang/eval-fail-attrset-merge-drops-later-rec.err.exp b/tests/functional/lang/eval-fail-attrset-merge-drops-later-rec.err.exp index d1cdc7b76..ba9185dce 100644 --- a/tests/functional/lang/eval-fail-attrset-merge-drops-later-rec.err.exp +++ b/tests/functional/lang/eval-fail-attrset-merge-drops-later-rec.err.exp @@ -1,5 +1,6 @@ error: undefined variable 'd' - at /pwd/lang/eval-fail-attrset-merge-drops-later-rec.nix:1:26: - 1| { a.b = 1; a = rec { c = d + 2; d = 3; }; }.c - | ^ - 2| + at /pwd/lang/eval-fail-attrset-merge-drops-later-rec.nix:4:9: + 3| a = rec { + 4| c = d + 2; + | ^ + 5| d = 3; diff --git a/tests/functional/lang/eval-fail-bad-string-interpolation-4.err.exp b/tests/functional/lang/eval-fail-bad-string-interpolation-4.err.exp index b262e814d..ea5910072 100644 --- a/tests/functional/lang/eval-fail-bad-string-interpolation-4.err.exp +++ b/tests/functional/lang/eval-fail-bad-string-interpolation-4.err.exp @@ -1,9 +1,9 @@ error: … while evaluating a path segment - at /pwd/lang/eval-fail-bad-string-interpolation-4.nix:9:3: - 8| # The error message should not be too long. - 9| ''${pkgs}'' + at /pwd/lang/eval-fail-bad-string-interpolation-4.nix:19:3: + 18| # The error message should not be too long. + 19| ''${pkgs}'' | ^ - 10| + 20| error: cannot coerce a set to a string: { a = { a = { a = { a = "ha"; b = "ha"; c = "ha"; d = "ha"; e = "ha"; f = "ha"; g = "ha"; h = "ha"; j = "ha"; }; «8 attributes elided» }; «8 attributes elided» }; «8 attributes elided» } diff --git a/tests/functional/lang/eval-fail-derivation-name.err.exp b/tests/functional/lang/eval-fail-derivation-name.err.exp index 0ef98674d..017326c34 100644 --- a/tests/functional/lang/eval-fail-derivation-name.err.exp +++ b/tests/functional/lang/eval-fail-derivation-name.err.exp @@ -1,17 +1,17 @@ error: … while evaluating the attribute 'outPath' at ::: - | value = commonAttrs // { - | outPath = builtins.getAttr outputName strict; - | ^ - | drvPath = strict.drvPath; + | value = commonAttrs // { + | outPath = builtins.getAttr outputName strict; + | ^ + | drvPath = strict.drvPath; … while calling the 'getAttr' builtin at ::: - | value = commonAttrs // { - | outPath = builtins.getAttr outputName strict; - | ^ - | drvPath = strict.drvPath; + | value = commonAttrs // { + | outPath = builtins.getAttr outputName strict; + | ^ + | drvPath = strict.drvPath; … while calling the 'derivationStrict' builtin at ::: diff --git a/tests/functional/lang/eval-fail-dup-dynamic-attrs.err.exp b/tests/functional/lang/eval-fail-dup-dynamic-attrs.err.exp index 834f9c67b..4eafe945b 100644 --- a/tests/functional/lang/eval-fail-dup-dynamic-attrs.err.exp +++ b/tests/functional/lang/eval-fail-dup-dynamic-attrs.err.exp @@ -2,13 +2,13 @@ error: … while evaluating the attribute 'set' at /pwd/lang/eval-fail-dup-dynamic-attrs.nix:2:3: 1| { - 2| set = { "${"" + "b"}" = 1; }; + 2| set = { | ^ - 3| set = { "${"b" + ""}" = 2; }; + 3| "${"" + "b"}" = 1; - error: dynamic attribute 'b' already defined at /pwd/lang/eval-fail-dup-dynamic-attrs.nix:2:11 - at /pwd/lang/eval-fail-dup-dynamic-attrs.nix:3:11: - 2| set = { "${"" + "b"}" = 1; }; - 3| set = { "${"b" + ""}" = 2; }; - | ^ - 4| } + error: dynamic attribute 'b' already defined at /pwd/lang/eval-fail-dup-dynamic-attrs.nix:3:5 + at /pwd/lang/eval-fail-dup-dynamic-attrs.nix:6:5: + 5| set = { + 6| "${"b" + ""}" = 2; + | ^ + 7| }; diff --git a/tests/functional/lang/eval-fail-duplicate-traces.err.exp b/tests/functional/lang/eval-fail-duplicate-traces.err.exp index cedaebd3b..e6ae60f3c 100644 --- a/tests/functional/lang/eval-fail-duplicate-traces.err.exp +++ b/tests/functional/lang/eval-fail-duplicate-traces.err.exp @@ -1,51 +1,51 @@ error: … from call site - at /pwd/lang/eval-fail-duplicate-traces.nix:9:3: - 8| in - 9| throwAfter 2 - | ^ - 10| + at /pwd/lang/eval-fail-duplicate-traces.nix:6:1: + 5| in + 6| throwAfter 2 + | ^ + 7| … while calling 'throwAfter' at /pwd/lang/eval-fail-duplicate-traces.nix:4:16: 3| let - 4| throwAfter = n: + 4| throwAfter = n: if n > 0 then throwAfter (n - 1) else throw "Uh oh!"; | ^ - 5| if n > 0 + 5| in … from call site - at /pwd/lang/eval-fail-duplicate-traces.nix:6:10: - 5| if n > 0 - 6| then throwAfter (n - 1) - | ^ - 7| else throw "Uh oh!"; + at /pwd/lang/eval-fail-duplicate-traces.nix:4:33: + 3| let + 4| throwAfter = n: if n > 0 then throwAfter (n - 1) else throw "Uh oh!"; + | ^ + 5| in … while calling 'throwAfter' at /pwd/lang/eval-fail-duplicate-traces.nix:4:16: 3| let - 4| throwAfter = n: + 4| throwAfter = n: if n > 0 then throwAfter (n - 1) else throw "Uh oh!"; | ^ - 5| if n > 0 + 5| in … from call site - at /pwd/lang/eval-fail-duplicate-traces.nix:6:10: - 5| if n > 0 - 6| then throwAfter (n - 1) - | ^ - 7| else throw "Uh oh!"; + at /pwd/lang/eval-fail-duplicate-traces.nix:4:33: + 3| let + 4| throwAfter = n: if n > 0 then throwAfter (n - 1) else throw "Uh oh!"; + | ^ + 5| in … while calling 'throwAfter' at /pwd/lang/eval-fail-duplicate-traces.nix:4:16: 3| let - 4| throwAfter = n: + 4| throwAfter = n: if n > 0 then throwAfter (n - 1) else throw "Uh oh!"; | ^ - 5| if n > 0 + 5| in … while calling the 'throw' builtin - at /pwd/lang/eval-fail-duplicate-traces.nix:7:10: - 6| then throwAfter (n - 1) - 7| else throw "Uh oh!"; - | ^ - 8| in + at /pwd/lang/eval-fail-duplicate-traces.nix:4:57: + 3| let + 4| throwAfter = n: if n > 0 then throwAfter (n - 1) else throw "Uh oh!"; + | ^ + 5| in error: Uh oh! diff --git a/tests/functional/lang/eval-fail-fetchurl-baseName-attrs-name.err.exp b/tests/functional/lang/eval-fail-fetchurl-baseName-attrs-name.err.exp index 30f8b6a35..2cac02f58 100644 --- a/tests/functional/lang/eval-fail-fetchurl-baseName-attrs-name.err.exp +++ b/tests/functional/lang/eval-fail-fetchurl-baseName-attrs-name.err.exp @@ -1,8 +1,8 @@ error: … while calling the 'fetchurl' builtin at /pwd/lang/eval-fail-fetchurl-baseName-attrs-name.nix:1:1: - 1| builtins.fetchurl { url = "https://example.com/foo.tar.gz"; name = "~wobble~"; } + 1| builtins.fetchurl { | ^ - 2| + 2| url = "https://example.com/foo.tar.gz"; error: invalid store path name when fetching URL 'https://example.com/foo.tar.gz': name '~wobble~' contains illegal character '~'. Please change the value for the 'name' attribute passed to 'fetchurl', so that it can create a valid store path. diff --git a/tests/functional/lang/eval-fail-flake-ref-to-string-negative-integer.err.exp b/tests/functional/lang/eval-fail-flake-ref-to-string-negative-integer.err.exp index 25c8d7eaa..2b56939c6 100644 --- a/tests/functional/lang/eval-fail-flake-ref-to-string-negative-integer.err.exp +++ b/tests/functional/lang/eval-fail-flake-ref-to-string-negative-integer.err.exp @@ -1,14 +1,16 @@ error: … while calling the 'seq' builtin - at /pwd/lang/eval-fail-flake-ref-to-string-negative-integer.nix:1:16: - 1| let n = -1; in builtins.seq n (builtins.flakeRefToString { - | ^ - 2| type = "github"; + at /pwd/lang/eval-fail-flake-ref-to-string-negative-integer.nix:4:1: + 3| in + 4| builtins.seq n ( + | ^ + 5| builtins.flakeRefToString { … while calling the 'flakeRefToString' builtin - at /pwd/lang/eval-fail-flake-ref-to-string-negative-integer.nix:1:32: - 1| let n = -1; in builtins.seq n (builtins.flakeRefToString { - | ^ - 2| type = "github"; + at /pwd/lang/eval-fail-flake-ref-to-string-negative-integer.nix:5:3: + 4| builtins.seq n ( + 5| builtins.flakeRefToString { + | ^ + 6| type = "github"; error: negative value given for flake ref attr repo: -1 diff --git a/tests/functional/lang/eval-fail-foldlStrict-strict-op-application.err.exp b/tests/functional/lang/eval-fail-foldlStrict-strict-op-application.err.exp index 4903bc82d..bb02ecdcb 100644 --- a/tests/functional/lang/eval-fail-foldlStrict-strict-op-application.err.exp +++ b/tests/functional/lang/eval-fail-foldlStrict-strict-op-application.err.exp @@ -2,36 +2,36 @@ error: … while calling the 'foldl'' builtin at /pwd/lang/eval-fail-foldlStrict-strict-op-application.nix:2:1: 1| # Tests that the result of applying op is forced even if the value is never used - 2| builtins.foldl' + 2| builtins.foldl' (_: f: f null) null [ | ^ - 3| (_: f: f null) + 3| (_: throw "Not the final value, but is still forced!") … while calling anonymous lambda - at /pwd/lang/eval-fail-foldlStrict-strict-op-application.nix:3:7: - 2| builtins.foldl' - 3| (_: f: f null) - | ^ - 4| null + at /pwd/lang/eval-fail-foldlStrict-strict-op-application.nix:2:21: + 1| # Tests that the result of applying op is forced even if the value is never used + 2| builtins.foldl' (_: f: f null) null [ + | ^ + 3| (_: throw "Not the final value, but is still forced!") … from call site - at /pwd/lang/eval-fail-foldlStrict-strict-op-application.nix:3:10: - 2| builtins.foldl' - 3| (_: f: f null) - | ^ - 4| null + at /pwd/lang/eval-fail-foldlStrict-strict-op-application.nix:2:24: + 1| # Tests that the result of applying op is forced even if the value is never used + 2| builtins.foldl' (_: f: f null) null [ + | ^ + 3| (_: throw "Not the final value, but is still forced!") … while calling anonymous lambda - at /pwd/lang/eval-fail-foldlStrict-strict-op-application.nix:5:6: - 4| null - 5| [ (_: throw "Not the final value, but is still forced!") (_: 23) ] - | ^ - 6| + at /pwd/lang/eval-fail-foldlStrict-strict-op-application.nix:3:4: + 2| builtins.foldl' (_: f: f null) null [ + 3| (_: throw "Not the final value, but is still forced!") + | ^ + 4| (_: 23) … while calling the 'throw' builtin - at /pwd/lang/eval-fail-foldlStrict-strict-op-application.nix:5:9: - 4| null - 5| [ (_: throw "Not the final value, but is still forced!") (_: 23) ] - | ^ - 6| + at /pwd/lang/eval-fail-foldlStrict-strict-op-application.nix:3:7: + 2| builtins.foldl' (_: f: f null) null [ + 3| (_: throw "Not the final value, but is still forced!") + | ^ + 4| (_: 23) error: Not the final value, but is still forced! diff --git a/tests/functional/lang/eval-fail-hashfile-missing.err.exp b/tests/functional/lang/eval-fail-hashfile-missing.err.exp index 1e4653927..0d3747a6d 100644 --- a/tests/functional/lang/eval-fail-hashfile-missing.err.exp +++ b/tests/functional/lang/eval-fail-hashfile-missing.err.exp @@ -1,10 +1,10 @@ error: … while calling the 'toString' builtin - at /pwd/lang/eval-fail-hashfile-missing.nix:4:3: - 3| in - 4| toString (builtins.concatLists (map (hash: map (builtins.hashFile hash) paths) ["md5" "sha1" "sha256" "sha512"])) - | ^ - 5| + at /pwd/lang/eval-fail-hashfile-missing.nix:7:1: + 6| in + 7| toString ( + | ^ + 8| builtins.concatLists ( … while evaluating the first argument passed to builtins.toString diff --git a/tests/functional/lang/eval-fail-list.err.exp b/tests/functional/lang/eval-fail-list.err.exp index d492f8bd2..8b21e9a37 100644 --- a/tests/functional/lang/eval-fail-list.err.exp +++ b/tests/functional/lang/eval-fail-list.err.exp @@ -1,8 +1,8 @@ error: … while evaluating one of the elements to concatenate - at /pwd/lang/eval-fail-list.nix:1:2: - 1| 8++1 - | ^ + at /pwd/lang/eval-fail-list.nix:1:3: + 1| 8 ++ 1 + | ^ 2| error: expected a list but found an integer: 8 diff --git a/tests/functional/lang/eval-fail-missing-arg.err.exp b/tests/functional/lang/eval-fail-missing-arg.err.exp index 3b162fe1b..d5a66d2c5 100644 --- a/tests/functional/lang/eval-fail-missing-arg.err.exp +++ b/tests/functional/lang/eval-fail-missing-arg.err.exp @@ -1,12 +1,13 @@ error: … from call site at /pwd/lang/eval-fail-missing-arg.nix:1:1: - 1| ({x, y, z}: x + y + z) {x = "foo"; z = "bar";} + 1| ( | ^ - 2| + 2| { error: function 'anonymous lambda' called without required argument 'y' - at /pwd/lang/eval-fail-missing-arg.nix:1:2: - 1| ({x, y, z}: x + y + z) {x = "foo"; z = "bar";} - | ^ - 2| + at /pwd/lang/eval-fail-missing-arg.nix:2:3: + 1| ( + 2| { + | ^ + 3| x, diff --git a/tests/functional/lang/eval-fail-mutual-recursion.err.exp b/tests/functional/lang/eval-fail-mutual-recursion.err.exp index c034afcd5..9d84aa43f 100644 --- a/tests/functional/lang/eval-fail-mutual-recursion.err.exp +++ b/tests/functional/lang/eval-fail-mutual-recursion.err.exp @@ -1,64 +1,64 @@ error: … from call site - at /pwd/lang/eval-fail-mutual-recursion.nix:36:3: - 35| in - 36| throwAfterA true 10 - | ^ - 37| + at /pwd/lang/eval-fail-mutual-recursion.nix:40:1: + 39| in + 40| throwAfterA true 10 + | ^ + 41| … while calling 'throwAfterA' - at /pwd/lang/eval-fail-mutual-recursion.nix:29:26: - 28| - 29| throwAfterA = recurse: n: - | ^ - 30| if n > 0 + at /pwd/lang/eval-fail-mutual-recursion.nix:32:14: + 31| throwAfterA = + 32| recurse: n: + | ^ + 33| if n > 0 then … from call site - at /pwd/lang/eval-fail-mutual-recursion.nix:31:10: - 30| if n > 0 - 31| then throwAfterA recurse (n - 1) - | ^ - 32| else if recurse + at /pwd/lang/eval-fail-mutual-recursion.nix:34:7: + 33| if n > 0 then + 34| throwAfterA recurse (n - 1) + | ^ + 35| else if recurse then (19 duplicate frames omitted) … from call site - at /pwd/lang/eval-fail-mutual-recursion.nix:33:10: - 32| else if recurse - 33| then throwAfterB true 10 - | ^ - 34| else throw "Uh oh!"; + at /pwd/lang/eval-fail-mutual-recursion.nix:36:7: + 35| else if recurse then + 36| throwAfterB true 10 + | ^ + 37| else … while calling 'throwAfterB' - at /pwd/lang/eval-fail-mutual-recursion.nix:22:26: - 21| let - 22| throwAfterB = recurse: n: - | ^ - 23| if n > 0 + at /pwd/lang/eval-fail-mutual-recursion.nix:23:14: + 22| throwAfterB = + 23| recurse: n: + | ^ + 24| if n > 0 then … from call site - at /pwd/lang/eval-fail-mutual-recursion.nix:24:10: - 23| if n > 0 - 24| then throwAfterB recurse (n - 1) - | ^ - 25| else if recurse + at /pwd/lang/eval-fail-mutual-recursion.nix:25:7: + 24| if n > 0 then + 25| throwAfterB recurse (n - 1) + | ^ + 26| else if recurse then (19 duplicate frames omitted) … from call site - at /pwd/lang/eval-fail-mutual-recursion.nix:26:10: - 25| else if recurse - 26| then throwAfterA false 10 - | ^ - 27| else throw "Uh oh!"; + at /pwd/lang/eval-fail-mutual-recursion.nix:27:7: + 26| else if recurse then + 27| throwAfterA false 10 + | ^ + 28| else (21 duplicate frames omitted) … while calling the 'throw' builtin - at /pwd/lang/eval-fail-mutual-recursion.nix:34:10: - 33| then throwAfterB true 10 - 34| else throw "Uh oh!"; - | ^ - 35| in + at /pwd/lang/eval-fail-mutual-recursion.nix:38:7: + 37| else + 38| throw "Uh oh!"; + | ^ + 39| in error: Uh oh! diff --git a/tests/functional/lang/eval-fail-nested-list-items.err.exp b/tests/functional/lang/eval-fail-nested-list-items.err.exp index 90d439061..1169b8326 100644 --- a/tests/functional/lang/eval-fail-nested-list-items.err.exp +++ b/tests/functional/lang/eval-fail-nested-list-items.err.exp @@ -1,9 +1,9 @@ error: … while evaluating a path segment - at /pwd/lang/eval-fail-nested-list-items.nix:11:6: - 10| - 11| "" + (let v = [ [ 1 2 3 4 5 6 7 8 ] [1 2 3 4]]; in builtins.deepSeq v v) - | ^ - 12| + at /pwd/lang/eval-fail-nested-list-items.nix:12:3: + 11| "" + 12| + ( + | ^ + 13| let error: cannot coerce a list to a string: [ [ 1 2 3 4 5 6 7 8 ] [ 1 «3 items elided» ] ] diff --git a/tests/functional/lang/eval-fail-not-throws.err.exp b/tests/functional/lang/eval-fail-not-throws.err.exp index fc81f7277..b49ed7b00 100644 --- a/tests/functional/lang/eval-fail-not-throws.err.exp +++ b/tests/functional/lang/eval-fail-not-throws.err.exp @@ -1,14 +1,14 @@ error: … in the argument of the not operator - at /pwd/lang/eval-fail-not-throws.nix:1:4: - 1| ! (throw "uh oh!") - | ^ + at /pwd/lang/eval-fail-not-throws.nix:1:3: + 1| !(throw "uh oh!") + | ^ 2| … while calling the 'throw' builtin - at /pwd/lang/eval-fail-not-throws.nix:1:4: - 1| ! (throw "uh oh!") - | ^ + at /pwd/lang/eval-fail-not-throws.nix:1:3: + 1| !(throw "uh oh!") + | ^ 2| error: uh oh! diff --git a/tests/functional/lang/eval-fail-overflowing-add.err.exp b/tests/functional/lang/eval-fail-overflowing-add.err.exp index 6458cf1c9..5a77e9c9d 100644 --- a/tests/functional/lang/eval-fail-overflowing-add.err.exp +++ b/tests/functional/lang/eval-fail-overflowing-add.err.exp @@ -1,6 +1,6 @@ error: integer overflow in adding 9223372036854775807 + 1 - at /pwd/lang/eval-fail-overflowing-add.nix:4:8: - 3| b = 1; - 4| in a + b - | ^ - 5| + at /pwd/lang/eval-fail-overflowing-add.nix:5:5: + 4| in + 5| a + b + | ^ + 6| diff --git a/tests/functional/lang/eval-fail-overflowing-div.err.exp b/tests/functional/lang/eval-fail-overflowing-div.err.exp index 8ce07d4d6..812c6056b 100644 --- a/tests/functional/lang/eval-fail-overflowing-div.err.exp +++ b/tests/functional/lang/eval-fail-overflowing-div.err.exp @@ -1,23 +1,23 @@ error: … while calling the 'seq' builtin - at /pwd/lang/eval-fail-overflowing-div.nix:7:4: - 6| b = -1; - 7| in builtins.seq intMin (builtins.seq b (intMin / b)) - | ^ - 8| + at /pwd/lang/eval-fail-overflowing-div.nix:8:1: + 7| in + 8| builtins.seq intMin (builtins.seq b (intMin / b)) + | ^ + 9| … while calling the 'seq' builtin - at /pwd/lang/eval-fail-overflowing-div.nix:7:25: - 6| b = -1; - 7| in builtins.seq intMin (builtins.seq b (intMin / b)) - | ^ - 8| + at /pwd/lang/eval-fail-overflowing-div.nix:8:22: + 7| in + 8| builtins.seq intMin (builtins.seq b (intMin / b)) + | ^ + 9| … while calling the 'div' builtin - at /pwd/lang/eval-fail-overflowing-div.nix:7:48: - 6| b = -1; - 7| in builtins.seq intMin (builtins.seq b (intMin / b)) - | ^ - 8| + at /pwd/lang/eval-fail-overflowing-div.nix:8:45: + 7| in + 8| builtins.seq intMin (builtins.seq b (intMin / b)) + | ^ + 9| error: integer overflow in dividing -9223372036854775808 / -1 diff --git a/tests/functional/lang/eval-fail-overflowing-mul.err.exp b/tests/functional/lang/eval-fail-overflowing-mul.err.exp index f42b39d4d..aaae4b7bd 100644 --- a/tests/functional/lang/eval-fail-overflowing-mul.err.exp +++ b/tests/functional/lang/eval-fail-overflowing-mul.err.exp @@ -1,16 +1,16 @@ error: … while calling the 'mul' builtin - at /pwd/lang/eval-fail-overflowing-mul.nix:3:10: - 2| a = 4294967297; - 3| in a * a * a - | ^ - 4| + at /pwd/lang/eval-fail-overflowing-mul.nix:4:7: + 3| in + 4| a * a * a + | ^ + 5| … while calling the 'mul' builtin - at /pwd/lang/eval-fail-overflowing-mul.nix:3:6: - 2| a = 4294967297; - 3| in a * a * a - | ^ - 4| + at /pwd/lang/eval-fail-overflowing-mul.nix:4:3: + 3| in + 4| a * a * a + | ^ + 5| error: integer overflow in multiplying 4294967297 * 4294967297 diff --git a/tests/functional/lang/eval-fail-overflowing-sub.err.exp b/tests/functional/lang/eval-fail-overflowing-sub.err.exp index 66a3a03f8..5904c8dcc 100644 --- a/tests/functional/lang/eval-fail-overflowing-sub.err.exp +++ b/tests/functional/lang/eval-fail-overflowing-sub.err.exp @@ -1,9 +1,9 @@ error: … while calling the 'sub' builtin - at /pwd/lang/eval-fail-overflowing-sub.nix:4:6: - 3| b = 2; - 4| in a - b - | ^ - 5| + at /pwd/lang/eval-fail-overflowing-sub.nix:5:3: + 4| in + 5| a - b + | ^ + 6| error: integer overflow in subtracting -9223372036854775807 - 2 diff --git a/tests/functional/lang/eval-fail-recursion.err.exp b/tests/functional/lang/eval-fail-recursion.err.exp index 19380dc65..8bfb4e12e 100644 --- a/tests/functional/lang/eval-fail-recursion.err.exp +++ b/tests/functional/lang/eval-fail-recursion.err.exp @@ -1,12 +1,14 @@ error: … in the right operand of the update (//) operator - at /pwd/lang/eval-fail-recursion.nix:1:12: - 1| let a = {} // a; in a.foo - | ^ - 2| + at /pwd/lang/eval-fail-recursion.nix:2:11: + 1| let + 2| a = { } // a; + | ^ + 3| in error: infinite recursion encountered - at /pwd/lang/eval-fail-recursion.nix:1:15: - 1| let a = {} // a; in a.foo - | ^ - 2| + at /pwd/lang/eval-fail-recursion.nix:2:14: + 1| let + 2| a = { } // a; + | ^ + 3| in diff --git a/tests/functional/lang/eval-fail-remove.err.exp b/tests/functional/lang/eval-fail-remove.err.exp index 292b3c3f3..0e087688a 100644 --- a/tests/functional/lang/eval-fail-remove.err.exp +++ b/tests/functional/lang/eval-fail-remove.err.exp @@ -1,15 +1,15 @@ error: … while evaluating the attribute 'body' - at /pwd/lang/eval-fail-remove.nix:4:3: - 3| - 4| body = (removeAttrs attrs ["x"]).x; + at /pwd/lang/eval-fail-remove.nix:7:3: + 6| + 7| body = (removeAttrs attrs [ "x" ]).x; | ^ - 5| } + 8| } error: attribute 'x' missing - at /pwd/lang/eval-fail-remove.nix:4:10: - 3| - 4| body = (removeAttrs attrs ["x"]).x; + at /pwd/lang/eval-fail-remove.nix:7:10: + 6| + 7| body = (removeAttrs attrs [ "x" ]).x; | ^ - 5| } + 8| } Did you mean y? diff --git a/tests/functional/lang/eval-fail-scope-5.err.exp b/tests/functional/lang/eval-fail-scope-5.err.exp index b0b05cad7..6edc85f4f 100644 --- a/tests/functional/lang/eval-fail-scope-5.err.exp +++ b/tests/functional/lang/eval-fail-scope-5.err.exp @@ -1,28 +1,28 @@ error: … while evaluating the attribute 'body' - at /pwd/lang/eval-fail-scope-5.nix:8:3: - 7| - 8| body = f {}; + at /pwd/lang/eval-fail-scope-5.nix:13:3: + 12| + 13| body = f { }; | ^ - 9| + 14| … from call site - at /pwd/lang/eval-fail-scope-5.nix:8:10: - 7| - 8| body = f {}; + at /pwd/lang/eval-fail-scope-5.nix:13:10: + 12| + 13| body = f { }; | ^ - 9| + 14| … while calling 'f' - at /pwd/lang/eval-fail-scope-5.nix:6:7: - 5| - 6| f = {x ? y, y ? x}: x + y; - | ^ - 7| + at /pwd/lang/eval-fail-scope-5.nix:7:5: + 6| f = + 7| { + | ^ + 8| x ? y, error: infinite recursion encountered - at /pwd/lang/eval-fail-scope-5.nix:6:12: - 5| - 6| f = {x ? y, y ? x}: x + y; - | ^ - 7| + at /pwd/lang/eval-fail-scope-5.nix:8:11: + 7| { + 8| x ? y, + | ^ + 9| y ? x, diff --git a/tests/functional/lang/eval-fail-undeclared-arg.err.exp b/tests/functional/lang/eval-fail-undeclared-arg.err.exp index 6e13a138e..353894d01 100644 --- a/tests/functional/lang/eval-fail-undeclared-arg.err.exp +++ b/tests/functional/lang/eval-fail-undeclared-arg.err.exp @@ -1,13 +1,13 @@ error: … from call site at /pwd/lang/eval-fail-undeclared-arg.nix:1:1: - 1| ({x, z}: x + z) {x = "foo"; y = "bla"; z = "bar";} + 1| ({ x, z }: x + z) { | ^ - 2| + 2| x = "foo"; error: function 'anonymous lambda' called with unexpected argument 'y' at /pwd/lang/eval-fail-undeclared-arg.nix:1:2: - 1| ({x, z}: x + z) {x = "foo"; y = "bla"; z = "bar";} + 1| ({ x, z }: x + z) { | ^ - 2| + 2| x = "foo"; Did you mean one of x or z? diff --git a/tests/functional/lang/eval-fail-using-set-as-attr-name.err.exp b/tests/functional/lang/eval-fail-using-set-as-attr-name.err.exp index 4326c9650..9a59f37f3 100644 --- a/tests/functional/lang/eval-fail-using-set-as-attr-name.err.exp +++ b/tests/functional/lang/eval-fail-using-set-as-attr-name.err.exp @@ -1,14 +1,14 @@ error: … while evaluating an attribute name - at /pwd/lang/eval-fail-using-set-as-attr-name.nix:5:10: - 4| in - 5| attr.${key} - | ^ - 6| + at /pwd/lang/eval-fail-using-set-as-attr-name.nix:7:8: + 6| in + 7| attr.${key} + | ^ + 8| error: expected a string but found a set: { } - at /pwd/lang/eval-fail-using-set-as-attr-name.nix:5:10: - 4| in - 5| attr.${key} - | ^ - 6| + at /pwd/lang/eval-fail-using-set-as-attr-name.nix:7:8: + 6| in + 7| attr.${key} + | ^ + 8| diff --git a/tests/functional/repl/doc-comment-curried-args.expected b/tests/functional/repl/doc-comment-curried-args.expected index 56607e911..d2a5bf328 100644 --- a/tests/functional/repl/doc-comment-curried-args.expected +++ b/tests/functional/repl/doc-comment-curried-args.expected @@ -6,7 +6,8 @@ Added variables. nix-repl> :doc curriedArgs Function `curriedArgs`\ - … defined at /path/to/tests/functional/repl/doc-comments.nix:48:5 + … defined at /path/to/tests/functional/repl/doc-comments.nix:87:5 + A documented function. @@ -17,7 +18,8 @@ nix-repl> "Note that users may not expect this to behave as it currently does" nix-repl> :doc x Function `curriedArgs`\ - … defined at /path/to/tests/functional/repl/doc-comments.nix:50:5 + … defined at /path/to/tests/functional/repl/doc-comments.nix:91:5 + The function returned by applying once diff --git a/tests/functional/repl/doc-comment-formals.expected b/tests/functional/repl/doc-comment-formals.expected index 1024919f4..357cf9986 100644 --- a/tests/functional/repl/doc-comment-formals.expected +++ b/tests/functional/repl/doc-comment-formals.expected @@ -9,6 +9,7 @@ nix-repl> "Note that this is not yet complete" nix-repl> :doc documentedFormals Function `documentedFormals`\ - … defined at /path/to/tests/functional/repl/doc-comments.nix:57:5 + … defined at /path/to/tests/functional/repl/doc-comments.nix:104:5 + Finds x diff --git a/tests/functional/repl/doc-comment-function.expected b/tests/functional/repl/doc-comment-function.expected index 3889c4f78..030cfc326 100644 --- a/tests/functional/repl/doc-comment-function.expected +++ b/tests/functional/repl/doc-comment-function.expected @@ -2,6 +2,7 @@ Nix Type :? for help. nix-repl> :doc import ./doc-comment-function.nix -Function defined at /path/to/tests/functional/repl/doc-comment-function.nix:2:1 +Function defined at /path/to/tests/functional/repl/doc-comment-function.nix:4:1 + A doc comment for a file that only contains a function diff --git a/tests/functional/repl/doc-compact.expected b/tests/functional/repl/doc-compact.expected index 79f1fd44f..276de2e60 100644 --- a/tests/functional/repl/doc-compact.expected +++ b/tests/functional/repl/doc-compact.expected @@ -6,6 +6,7 @@ Added variables. nix-repl> :doc compact Function `compact`\ - … defined at /path/to/tests/functional/repl/doc-comments.nix:18:20 + … defined at /path/to/tests/functional/repl/doc-comments.nix:27:5 + boom diff --git a/tests/functional/repl/doc-constant.expected b/tests/functional/repl/doc-constant.expected index 5787e04dc..a68188b25 100644 --- a/tests/functional/repl/doc-constant.expected +++ b/tests/functional/repl/doc-constant.expected @@ -10,25 +10,27 @@ error: value does not have documentation nix-repl> :doc lib.version Attribute `version` - … defined at /path/to/tests/functional/repl/doc-comments.nix:30:3 + … defined at /path/to/tests/functional/repl/doc-comments.nix:47:3 + Immovably fixed. nix-repl> :doc lib.attr.empty Attribute `empty` - … defined at /path/to/tests/functional/repl/doc-comments.nix:33:3 + … defined at /path/to/tests/functional/repl/doc-comments.nix:52:3 + Unchangeably constant. nix-repl> :doc lib.attr.undocument error: … while evaluating the attribute 'attr.undocument' - at /path/to/tests/functional/repl/doc-comments.nix:33:3: - 32| /** Unchangeably constant. */ - 33| lib.attr.empty = { }; + at /path/to/tests/functional/repl/doc-comments.nix:52:3: + 51| */ + 52| lib.attr.empty = { }; | ^ - 34| + 53| error: attribute 'undocument' missing at «string»:1:1: @@ -39,28 +41,31 @@ error: nix-repl> :doc (import ./doc-comments.nix).constant Attribute `constant` - … defined at /path/to/tests/functional/repl/doc-comments.nix:27:3 + … defined at /path/to/tests/functional/repl/doc-comments.nix:42:3 + Firmly rigid. nix-repl> :doc (import ./doc-comments.nix).lib.version Attribute `version` - … defined at /path/to/tests/functional/repl/doc-comments.nix:30:3 + … defined at /path/to/tests/functional/repl/doc-comments.nix:47:3 + Immovably fixed. nix-repl> :doc (import ./doc-comments.nix).lib.attr.empty Attribute `empty` - … defined at /path/to/tests/functional/repl/doc-comments.nix:33:3 + … defined at /path/to/tests/functional/repl/doc-comments.nix:52:3 + Unchangeably constant. nix-repl> :doc (import ./doc-comments.nix).lib.attr.undocumented Attribute `undocumented` - … defined at /path/to/tests/functional/repl/doc-comments.nix:35:3 + … defined at /path/to/tests/functional/repl/doc-comments.nix:54:3 No documentation found. @@ -97,11 +102,11 @@ error: attribute 'missing' missing nix-repl> :doc lib.attr.undocumental error: … while evaluating the attribute 'attr.undocumental' - at /path/to/tests/functional/repl/doc-comments.nix:33:3: - 32| /** Unchangeably constant. */ - 33| lib.attr.empty = { }; + at /path/to/tests/functional/repl/doc-comments.nix:52:3: + 51| */ + 52| lib.attr.empty = { }; | ^ - 34| + 53| error: attribute 'undocumental' missing at «string»:1:1: diff --git a/tests/functional/repl/doc-floatedIn.expected b/tests/functional/repl/doc-floatedIn.expected index 82bb80b95..3bf1c4071 100644 --- a/tests/functional/repl/doc-floatedIn.expected +++ b/tests/functional/repl/doc-floatedIn.expected @@ -6,6 +6,7 @@ Added variables. nix-repl> :doc floatedIn Function `floatedIn`\ - … defined at /path/to/tests/functional/repl/doc-comments.nix:16:5 + … defined at /path/to/tests/functional/repl/doc-comments.nix:21:5 + This also works. diff --git a/tests/functional/repl/doc-functor.expected b/tests/functional/repl/doc-functor.expected index 8cb2706ef..503fb8073 100644 --- a/tests/functional/repl/doc-functor.expected +++ b/tests/functional/repl/doc-functor.expected @@ -20,7 +20,7 @@ Look, it's just like a function! nix-repl> :doc recursive Function `__functor`\ - … defined at /path/to/tests/functional/repl/doc-functor.nix:77:23 + … defined at /path/to/tests/functional/repl/doc-functor.nix:82:23 This looks bad, but the docs are ok because of the eta expansion. @@ -30,27 +30,27 @@ error: … while partially calling '__functor' to retrieve documentation … while calling '__functor' - at /path/to/tests/functional/repl/doc-functor.nix:85:17: - 84| */ - 85| __functor = self: self.__functor self; + at /path/to/tests/functional/repl/doc-functor.nix:90:17: + 89| */ + 90| __functor = self: self.__functor self; | ^ - 86| }; + 91| }; … from call site - at /path/to/tests/functional/repl/doc-functor.nix:85:23: - 84| */ - 85| __functor = self: self.__functor self; + at /path/to/tests/functional/repl/doc-functor.nix:90:23: + 89| */ + 90| __functor = self: self.__functor self; | ^ - 86| }; + 91| }; (19999 duplicate frames omitted) error: stack overflow; max-call-depth exceeded - at /path/to/tests/functional/repl/doc-functor.nix:85:23: - 84| */ - 85| __functor = self: self.__functor self; + at /path/to/tests/functional/repl/doc-functor.nix:90:23: + 89| */ + 90| __functor = self: self.__functor self; | ^ - 86| }; + 91| }; nix-repl> :doc diverging error: @@ -59,18 +59,18 @@ error: (10000 duplicate frames omitted) … while calling '__functor' - at /path/to/tests/functional/repl/doc-functor.nix:97:19: - 96| f = x: { - 97| __functor = self: (f (x + 1)); - | ^ - 98| }; + at /path/to/tests/functional/repl/doc-functor.nix:103:21: + 102| f = x: { + 103| __functor = self: (f (x + 1)); + | ^ + 104| }; error: stack overflow; max-call-depth exceeded - at /path/to/tests/functional/repl/doc-functor.nix:97:26: - 96| f = x: { - 97| __functor = self: (f (x + 1)); - | ^ - 98| }; + at /path/to/tests/functional/repl/doc-functor.nix:103:28: + 102| f = x: { + 103| __functor = self: (f (x + 1)); + | ^ + 104| }; nix-repl> :doc helper Function `square`\ @@ -81,21 +81,21 @@ Compute x^2 nix-repl> :doc helper2 Function `__functor`\ - … defined at /path/to/tests/functional/repl/doc-functor.nix:45:23 + … defined at /path/to/tests/functional/repl/doc-functor.nix:46:13 This is a function that can be overridden. nix-repl> :doc lib.helper3 Function `__functor`\ - … defined at /path/to/tests/functional/repl/doc-functor.nix:45:23 + … defined at /path/to/tests/functional/repl/doc-functor.nix:46:13 This is a function that can be overridden. nix-repl> :doc helper3 Function `__functor`\ - … defined at /path/to/tests/functional/repl/doc-functor.nix:45:23 + … defined at /path/to/tests/functional/repl/doc-functor.nix:46:13 This is a function that can be overridden. diff --git a/tests/functional/repl/doc-lambda-flavors.expected b/tests/functional/repl/doc-lambda-flavors.expected index ab5c95639..437c09d2b 100644 --- a/tests/functional/repl/doc-lambda-flavors.expected +++ b/tests/functional/repl/doc-lambda-flavors.expected @@ -6,24 +6,28 @@ Added variables. nix-repl> :doc nonStrict Function `nonStrict`\ - … defined at /path/to/tests/functional/repl/doc-comments.nix:37:70 + … defined at /path/to/tests/functional/repl/doc-comments.nix:60:5 + My syntax is not strict, but I'm strict anyway. nix-repl> :doc strict Function `strict`\ - … defined at /path/to/tests/functional/repl/doc-comments.nix:38:63 + … defined at /path/to/tests/functional/repl/doc-comments.nix:65:5 + I don't have to be strict, but I am anyway. nix-repl> :doc strictPre Function `strictPre`\ - … defined at /path/to/tests/functional/repl/doc-comments.nix:40:48 + … defined at /path/to/tests/functional/repl/doc-comments.nix:71:5 + Here's one way to do this nix-repl> :doc strictPost Function `strictPost`\ - … defined at /path/to/tests/functional/repl/doc-comments.nix:41:53 + … defined at /path/to/tests/functional/repl/doc-comments.nix:76:5 + Here's another way to do this diff --git a/tests/functional/repl/doc-measurement.expected b/tests/functional/repl/doc-measurement.expected index 555cac9a2..862697613 100644 --- a/tests/functional/repl/doc-measurement.expected +++ b/tests/functional/repl/doc-measurement.expected @@ -6,6 +6,7 @@ Added variables. nix-repl> :doc measurement Function `measurement`\ - … defined at /path/to/tests/functional/repl/doc-comments.nix:13:17 + … defined at /path/to/tests/functional/repl/doc-comments.nix:15:17 + 👈 precisely this wide 👉 diff --git a/tests/functional/repl/doc-unambiguous.expected b/tests/functional/repl/doc-unambiguous.expected index 0db5505d7..32ca9aef2 100644 --- a/tests/functional/repl/doc-unambiguous.expected +++ b/tests/functional/repl/doc-unambiguous.expected @@ -6,6 +6,7 @@ Added variables. nix-repl> :doc unambiguous Function `unambiguous`\ - … defined at /path/to/tests/functional/repl/doc-comments.nix:24:5 + … defined at /path/to/tests/functional/repl/doc-comments.nix:37:5 + Very close From 791d6cf4332d62da6edd88eb5d20c9cef34c7b92 Mon Sep 17 00:00:00 2001 From: Ben Millwood Date: Thu, 10 Oct 2024 16:05:50 +0100 Subject: [PATCH 699/718] Improve "illegal path references in fixed output derivation" error The main improvement is that the new message gives an example of a path that is referenced, which should make it easier to track down. While there, I also clarified the wording, saying exactly why the paths in question were illegal. (cherry picked from commit 4e5d1b281e503641d649ddba22d49361e6295e2e) --- src/libstore/unix/build/local-derivation-goal.cc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/libstore/unix/build/local-derivation-goal.cc b/src/libstore/unix/build/local-derivation-goal.cc index 06a2f85be..5b9bc0bb0 100644 --- a/src/libstore/unix/build/local-derivation-goal.cc +++ b/src/libstore/unix/build/local-derivation-goal.cc @@ -2657,10 +2657,14 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs() wanted.to_string(HashFormat::SRI, true), got.to_string(HashFormat::SRI, true))); } - if (!newInfo0.references.empty()) + if (!newInfo0.references.empty()) { + auto numViolations = newInfo.references.size(); delayedException = std::make_exception_ptr( - BuildError("illegal path references in fixed-output derivation '%s'", - worker.store.printStorePath(drvPath))); + BuildError("fixed-output derivations must not reference store paths: '%s' references %d distinct paths, e.g. '%s'", + worker.store.printStorePath(drvPath), + numViolations, + worker.store.printStorePath(*newInfo.references.begin()))); + } return newInfo0; }, From 527e68ac3eeb4822d863ff6ac2557cc2fc3268be Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 27 Jan 2025 12:32:46 +0100 Subject: [PATCH 700/718] refactor: Extract EvalState::realiseString (cherry picked from commit 7465fbe9264e46c556b456226e8fb980fcfd7e66) --- src/libexpr-c/nix_api_value.cc | 6 +----- src/libexpr/eval.hh | 9 +++++++++ src/libexpr/primops.cc | 9 +++++++++ 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/libexpr-c/nix_api_value.cc b/src/libexpr-c/nix_api_value.cc index bae078d31..448f4a58a 100644 --- a/src/libexpr-c/nix_api_value.cc +++ b/src/libexpr-c/nix_api_value.cc @@ -613,12 +613,8 @@ nix_realised_string * nix_string_realise(nix_c_context * context, EvalState * st context->last_err_code = NIX_OK; try { auto & v = check_value_in(value); - nix::NixStringContext stringContext; - auto rawStr = state->state.coerceToString(nix::noPos, v, stringContext, "while realising a string").toOwned(); nix::StorePathSet storePaths; - auto rewrites = state->state.realiseContext(stringContext, &storePaths); - - auto s = nix::rewriteStrings(rawStr, rewrites); + auto s = state->state.realiseString(v, &storePaths, isIFD); // Convert to the C API StorePath type and convert to vector for index-based access std::vector vec; diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 84b7d823c..767578343 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -820,6 +820,15 @@ public: */ [[nodiscard]] StringMap realiseContext(const NixStringContext & context, StorePathSet * maybePaths = nullptr, bool isIFD = true); + /** + * Realise the given string with context, and return the string with outputs instead of downstream output placeholders. + * @param[in] str the string to realise + * @param[out] paths all referenced store paths will be added to this set + * @return the realised string + * @throw EvalError if the value is not a string, path or derivation (see `coerceToString`) + */ + std::string realiseString(Value & str, StorePathSet * storePathsOutMaybe, bool isIFD = true, const PosIdx pos = noPos); + /* Call the binary path filter predicate used builtins.path etc. */ bool callPathFilter( Value * filterFun, diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index a0e2753b5..e6f6f1dda 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -47,6 +47,15 @@ static inline Value * mkString(EvalState & state, const std::csub_match & match) return v; } +std::string EvalState::realiseString(Value & s, StorePathSet * storePathsOutMaybe, bool isIFD, const PosIdx pos) +{ + nix::NixStringContext stringContext; + auto rawStr = coerceToString(pos, s, stringContext, "while realising a string").toOwned(); + auto rewrites = realiseContext(stringContext, storePathsOutMaybe, isIFD); + + return nix::rewriteStrings(rawStr, rewrites); +} + StringMap EvalState::realiseContext(const NixStringContext & context, StorePathSet * maybePathsOut, bool isIFD) { std::vector drvs; From 605bd06ca4512c401573053c3605287b3275e8b8 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 27 Jan 2025 14:25:35 +0100 Subject: [PATCH 701/718] packages.default: Add meta.mainProgram (cherry picked from commit 0d7418b4feebcfb3e0e66798398d3ecf618c1e58) --- packaging/everything.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/packaging/everything.nix b/packaging/everything.nix index 2b47c31bb..0974a34df 100644 --- a/packaging/everything.nix +++ b/packaging/everything.nix @@ -93,6 +93,7 @@ let libs = throw "`nix.dev.libs` is not meant to be used; use `nix.libs` instead."; }; meta = { + mainProgram = "nix"; pkgConfigModules = [ "nix-cmd" "nix-expr" From a75cf5770280e14998097c7bbed0521b924dab91 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 27 Jan 2025 14:26:05 +0100 Subject: [PATCH 702/718] packages.nix-cli: Add meta.mainProgram (cherry picked from commit 850329dea59358db6e8ea572d769eb706715c508) --- src/nix/package.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/src/nix/package.nix b/src/nix/package.nix index 89c52c3bb..6e59adc38 100644 --- a/src/nix/package.nix +++ b/src/nix/package.nix @@ -103,6 +103,7 @@ mkMesonExecutable (finalAttrs: { ]; meta = { + mainProgram = "nix"; platforms = lib.platforms.unix ++ lib.platforms.windows; }; From 1c1f8b2343b15e88b7023adc01529d0496d92014 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 30 Jan 2025 11:27:24 +0100 Subject: [PATCH 703/718] Fix duplicate setPathDisplay() Fixes messages like 'copying /tmp/repo/tmp/repo to the store'. The PosixSourceAccessor already sets the prefix. Setting the prefix twice shouldn't be a problem, but GitRepoImpl::getAccessor() returns a wrapped accessor so it's not actually idempotent. (cherry picked from commit 102d90ebf07b1f268a3551daf5457131ae063d4a) --- src/libfetchers/git.cc | 2 -- tests/functional/fetchGit.sh | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libfetchers/git.cc b/src/libfetchers/git.cc index b411e112f..e8698709a 100644 --- a/src/libfetchers/git.cc +++ b/src/libfetchers/git.cc @@ -737,8 +737,6 @@ struct GitInputScheme : InputScheme exportIgnore, makeNotAllowedError(repoInfo.locationToArg())); - accessor->setPathDisplay(repoInfo.locationToArg()); - /* If the repo has submodules, return a mounted input accessor consisting of the accessor for the top-level repo and the accessors for the submodule workdirs. */ diff --git a/tests/functional/fetchGit.sh b/tests/functional/fetchGit.sh index 78925b5cd..f3eda54dc 100755 --- a/tests/functional/fetchGit.sh +++ b/tests/functional/fetchGit.sh @@ -37,6 +37,7 @@ nix-instantiate --eval -E "builtins.readFile ((builtins.fetchGit file://$TEST_RO # Fetch a worktree. unset _NIX_FORCE_HTTP +expectStderr 0 nix eval -vvvv --impure --raw --expr "(builtins.fetchGit file://$TEST_ROOT/worktree).outPath" | grepQuiet "copying '$TEST_ROOT/worktree/' to the store" path0=$(nix eval --impure --raw --expr "(builtins.fetchGit file://$TEST_ROOT/worktree).outPath") path0_=$(nix eval --impure --raw --expr "(builtins.fetchTree { type = \"git\"; url = file://$TEST_ROOT/worktree; }).outPath") [[ $path0 = $path0_ ]] From 28684af74b56fba5bbcfa976b5c37fe355ea88af Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 30 Jan 2025 12:41:02 +0100 Subject: [PATCH 704/718] =?UTF-8?q?GitExportIgnoreSourceAccessor:=20Don't?= =?UTF-8?q?=20show=20=C2=ABunknown=C2=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In general we should set the path display prefix on the inner accessor, so we now pass the display prefix to getAccessor(). (cherry picked from commit 3032512425a09fc58f2d658442043894e0aab256) --- src/libfetchers/git-utils.cc | 21 +++++++++++++-------- src/libfetchers/git-utils.hh | 5 ++++- src/libfetchers/git.cc | 4 +--- src/libfetchers/github.cc | 7 ++++--- src/libfetchers/tarball.cc | 12 +++++++----- 5 files changed, 29 insertions(+), 20 deletions(-) diff --git a/src/libfetchers/git-utils.cc b/src/libfetchers/git-utils.cc index 6a75daf61..a6b13fb31 100644 --- a/src/libfetchers/git-utils.cc +++ b/src/libfetchers/git-utils.cc @@ -508,7 +508,10 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this */ ref getRawAccessor(const Hash & rev); - ref getAccessor(const Hash & rev, bool exportIgnore) override; + ref getAccessor( + const Hash & rev, + bool exportIgnore, + std::string displayPrefix) override; ref getAccessor(const WorkdirInfo & wd, bool exportIgnore, MakeNotAllowedError e) override; @@ -627,7 +630,7 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this Hash treeHashToNarHash(const Hash & treeHash) override { - auto accessor = getAccessor(treeHash, false); + auto accessor = getAccessor(treeHash, false, ""); fetchers::Cache::Key cacheKey{"treeHashToNarHash", {{"treeHash", treeHash.gitRev()}}}; @@ -1194,16 +1197,18 @@ ref GitRepoImpl::getRawAccessor(const Hash & rev) return make_ref(self, rev); } -ref GitRepoImpl::getAccessor(const Hash & rev, bool exportIgnore) +ref GitRepoImpl::getAccessor( + const Hash & rev, + bool exportIgnore, + std::string displayPrefix) { auto self = ref(shared_from_this()); ref rawGitAccessor = getRawAccessor(rev); - if (exportIgnore) { + rawGitAccessor->setPathDisplay(std::move(displayPrefix)); + if (exportIgnore) return make_ref(self, rawGitAccessor, rev); - } - else { + else return rawGitAccessor; - } } ref GitRepoImpl::getAccessor(const WorkdirInfo & wd, bool exportIgnore, MakeNotAllowedError makeNotAllowedError) @@ -1236,7 +1241,7 @@ std::vector> GitRepoImpl::getSubmodules /* Read the .gitmodules files from this revision. */ CanonPath modulesFile(".gitmodules"); - auto accessor = getAccessor(rev, exportIgnore); + auto accessor = getAccessor(rev, exportIgnore, ""); if (!accessor->pathExists(modulesFile)) return {}; /* Parse it and get the revision of each submodule. */ diff --git a/src/libfetchers/git-utils.hh b/src/libfetchers/git-utils.hh index ff115143f..9677f5079 100644 --- a/src/libfetchers/git-utils.hh +++ b/src/libfetchers/git-utils.hh @@ -86,7 +86,10 @@ struct GitRepo virtual bool hasObject(const Hash & oid) = 0; - virtual ref getAccessor(const Hash & rev, bool exportIgnore) = 0; + virtual ref getAccessor( + const Hash & rev, + bool exportIgnore, + std::string displayPrefix) = 0; virtual ref getAccessor(const WorkdirInfo & wd, bool exportIgnore, MakeNotAllowedError makeNotAllowedError) = 0; diff --git a/src/libfetchers/git.cc b/src/libfetchers/git.cc index e8698709a..e40afb865 100644 --- a/src/libfetchers/git.cc +++ b/src/libfetchers/git.cc @@ -672,9 +672,7 @@ struct GitInputScheme : InputScheme verifyCommit(input, repo); bool exportIgnore = getExportIgnoreAttr(input); - auto accessor = repo->getAccessor(rev, exportIgnore); - - accessor->setPathDisplay("«" + input.to_string() + "»"); + auto accessor = repo->getAccessor(rev, exportIgnore, "«" + input.to_string() + "»"); /* If the repo has submodules, fetch them and return a mounted input accessor consisting of the accessor for the top-level diff --git a/src/libfetchers/github.cc b/src/libfetchers/github.cc index 185941988..ec469df7c 100644 --- a/src/libfetchers/github.cc +++ b/src/libfetchers/github.cc @@ -294,9 +294,10 @@ struct GitArchiveInputScheme : InputScheme #endif input.attrs.insert_or_assign("lastModified", uint64_t(tarballInfo.lastModified)); - auto accessor = getTarballCache()->getAccessor(tarballInfo.treeHash, false); - - accessor->setPathDisplay("«" + input.to_string() + "»"); + auto accessor = getTarballCache()->getAccessor( + tarballInfo.treeHash, + false, + "«" + input.to_string() + "»"); return {accessor, input}; } diff --git a/src/libfetchers/tarball.cc b/src/libfetchers/tarball.cc index 28574e7b1..699612e25 100644 --- a/src/libfetchers/tarball.cc +++ b/src/libfetchers/tarball.cc @@ -105,7 +105,8 @@ DownloadFileResult downloadFile( static DownloadTarballResult downloadTarball_( const std::string & url, - const Headers & headers) + const Headers & headers, + const std::string & displayPrefix) { Cache::Key cacheKey{"tarball", {{"url", url}}}; @@ -118,7 +119,7 @@ static DownloadTarballResult downloadTarball_( .treeHash = treeHash, .lastModified = (time_t) getIntAttr(infoAttrs, "lastModified"), .immutableUrl = maybeGetStrAttr(infoAttrs, "immutableUrl"), - .accessor = getTarballCache()->getAccessor(treeHash, false), + .accessor = getTarballCache()->getAccessor(treeHash, false, displayPrefix), }; }; @@ -371,9 +372,10 @@ struct TarballInputScheme : CurlInputScheme { auto input(_input); - auto result = downloadTarball_(getStrAttr(input.attrs, "url"), {}); - - result.accessor->setPathDisplay("«" + input.to_string() + "»"); + auto result = downloadTarball_( + getStrAttr(input.attrs, "url"), + {}, + "«" + input.to_string() + "»"); if (result.immutableUrl) { auto immutableInput = Input::fromURL(*input.settings, *result.immutableUrl); From 491aaaf116cdf36a5f97316f61066fdeb6f29e68 Mon Sep 17 00:00:00 2001 From: Illia Bobyr Date: Mon, 13 Jan 2025 18:19:16 -0800 Subject: [PATCH 705/718] nix-profile.fish: Typo NIX_SS{H => L}_CERT_FILE (cherry picked from commit 803fb83f7ffb3bd5e2e1ee3bb9ce3ea3001bec2c) # Conflicts: # scripts/nix-profile.fish.in --- scripts/nix-profile.fish.in | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/scripts/nix-profile.fish.in b/scripts/nix-profile.fish.in index 619df52b8..becc5efd0 100644 --- a/scripts/nix-profile.fish.in +++ b/scripts/nix-profile.fish.in @@ -56,4 +56,36 @@ if test -n "$HOME" && test -n "$USER" set --erase NIX_LINK end +<<<<<<< HEAD +======= +# Set $NIX_SSL_CERT_FILE so that Nixpkgs applications like curl work. +if test -n "$NIX_SSL_CERT_FILE" + : # Allow users to override the NIX_SSL_CERT_FILE +else if test -e /etc/ssl/certs/ca-certificates.crt # NixOS, Ubuntu, Debian, Gentoo, Arch + set --export NIX_SSL_CERT_FILE /etc/ssl/certs/ca-certificates.crt +else if test -e /etc/ssl/ca-bundle.pem # openSUSE Tumbleweed + set --export NIX_SSL_CERT_FILE /etc/ssl/ca-bundle.pem +else if test -e /etc/ssl/certs/ca-bundle.crt # Old NixOS + set --export NIX_SSL_CERT_FILE /etc/ssl/certs/ca-bundle.crt +else if test -e /etc/pki/tls/certs/ca-bundle.crt # Fedora, CentOS + set --export NIX_SSL_CERT_FILE /etc/pki/tls/certs/ca-bundle.crt +else if test -e "$NIX_LINK/etc/ssl/certs/ca-bundle.crt" # fall back to cacert in Nix profile + set --export NIX_SSL_CERT_FILE "$NIX_LINK/etc/ssl/certs/ca-bundle.crt" +else if test -e "$NIX_LINK/etc/ca-bundle.crt" # old cacert in Nix profile + set --export NIX_SSL_CERT_FILE "$NIX_LINK/etc/ca-bundle.crt" +end + +# Only use MANPATH if it is already set. In general `man` will just simply +# pick up `.nix-profile/share/man` because is it close to `.nix-profile/bin` +# which is in the $PATH. For more info, run `manpath -d`. +if set --query MANPATH + set --export --prepend --path MANPATH "$NIX_LINK/share/man" +end + +add_path "$NIX_LINK/bin" +set --erase NIX_LINK + +# Cleanup + +>>>>>>> 803fb83f7 (nix-profile.fish: Typo NIX_SS{H => L}_CERT_FILE) functions -e add_path From 727cf59997c33a03558dab84071767983d57d892 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 30 Jan 2025 11:47:41 +0100 Subject: [PATCH 706/718] Git fetcher: Don't pass URL query parameters for file:// URLs Git interprets them as part of the file name, so passing parameters like 'rev' breaks. Only relevant for testing (when _NIX_FORCE_HTTP is set) and local bare repos. (cherry picked from commit 9f72d5bce9205c9f45dcb0e06b9573ccca5724ac) --- src/libfetchers/git.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/libfetchers/git.cc b/src/libfetchers/git.cc index e40afb865..a1f65c0db 100644 --- a/src/libfetchers/git.cc +++ b/src/libfetchers/git.cc @@ -459,8 +459,14 @@ struct GitInputScheme : InputScheme url); } repoInfo.location = std::filesystem::absolute(url.path); - } else + } else { + if (url.scheme == "file") + /* Query parameters are meaningless for file://, but + Git interprets them as part of the file name. So get + rid of them. */ + url.query.clear(); repoInfo.location = url; + } // If this is a local directory and no ref or revision is // given, then allow the use of an unclean working tree. From 1fe33c13d94744e071c7a4d5fe6cd93f12dab40a Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 30 Jan 2025 18:23:27 +0100 Subject: [PATCH 707/718] Git fetcher: Don't use refspec : This causes Git to create a local ref named refs/head/, e.g. $ git -C ~/.cache/nix/gitv3/11irpim06vj4h6c0w8yls6kx4hvl0qd0gr1fvk47n76g6wf1s1vk ls-remote --symref . 5c4410e3b9891c05ab40d723de78c6f0be45ad30 refs/heads/5c4410e3b9891c05ab40d723de78c6f0be45ad30 7f6bde8a20de4cccc2256f088bc5af9dbe38881d refs/heads/7f6bde8a20de4cccc2256f088bc5af9dbe38881d which confuses readHead(), leading to errors like fatal: Refusing to point HEAD outside of refs/ warning: could not update cached head 'd275d93aa0bb8a004939b2f1e87f559f989453be' for 'file:///tmp/repo' (cherry picked from commit ee9fa0d3603165631e65c8e694a033c47872267a) --- src/libfetchers/git.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libfetchers/git.cc b/src/libfetchers/git.cc index a1f65c0db..758bb3653 100644 --- a/src/libfetchers/git.cc +++ b/src/libfetchers/git.cc @@ -611,16 +611,16 @@ struct GitInputScheme : InputScheme try { auto fetchRef = getAllRefsAttr(input) - ? "refs/*" + ? "refs/*:refs/*" : input.getRev() ? input.getRev()->gitRev() : ref.compare(0, 5, "refs/") == 0 - ? ref + ? fmt("%1%:%1%", ref) : ref == "HEAD" ? ref - : "refs/heads/" + ref; + : fmt("%1%:%1%", "refs/heads/" + ref); - repo->fetch(repoUrl.to_string(), fmt("%s:%s", fetchRef, fetchRef), getShallowAttr(input)); + repo->fetch(repoUrl.to_string(), fetchRef, getShallowAttr(input)); } catch (Error & e) { if (!std::filesystem::exists(localRefFile)) throw; logError(e.info()); From 8e4cd2f5370e2083b99cbc231f4a2180ab813b5a Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 30 Jan 2025 18:57:43 +0100 Subject: [PATCH 708/718] readHead(): Make sure we're returning the HEAD ref line If we previously fetched by revision, the output of "git ls-remote" won't start with the expected line like ref: refs/heads/master HEAD but will be something like 5c4410e3b9891c05ab40d723de78c6f0be45ad30 refs/heads/5c4410e3b9891c05ab40d723de78c6f0be45ad30 This then causes Nix to treat that revision as a refname, which then leads to warnings like warning: could not update cached head '5c4410e3b9891c05ab40d723de78c6f0be45ad30' for 'file:///tmp/repo' (cherry picked from commit c8b22643ba13b12f493e8b90dfa4b416bf267553) --- src/libfetchers/git.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libfetchers/git.cc b/src/libfetchers/git.cc index 758bb3653..0d423a7a3 100644 --- a/src/libfetchers/git.cc +++ b/src/libfetchers/git.cc @@ -69,7 +69,7 @@ std::optional readHead(const Path & path) std::string_view line = output; line = line.substr(0, line.find("\n")); - if (const auto parseResult = git::parseLsRemoteLine(line)) { + if (const auto parseResult = git::parseLsRemoteLine(line); parseResult && parseResult->reference == "HEAD") { switch (parseResult->kind) { case git::LsRemoteRefLine::Kind::Symbolic: debug("resolved HEAD ref '%s' for repo '%s'", parseResult->target, path); From 30435e0559ae2d6784a115b7ffea266964fcb25d Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Fri, 24 Jan 2025 16:37:09 +0100 Subject: [PATCH 709/718] pre-commit/check-merge-conflicts-2: fix use outside dev shell Note that this is just a script that is meant to run outside a derivation (but also can be called by a derivation builder). `touch $out` does not belong in it. `touch $out` worked accidentally in the derivation-based check, and also in the dev shell, but if pre-commit is invoked without the dev shell it would fail. --- maintainers/flake-module.nix | 1 - 1 file changed, 1 deletion(-) diff --git a/maintainers/flake-module.nix b/maintainers/flake-module.nix index 9b2c6dcbf..2f19072ee 100644 --- a/maintainers/flake-module.nix +++ b/maintainers/flake-module.nix @@ -35,7 +35,6 @@ echo "ERROR: found merge/patch conflicts in files" exit 1 fi - touch $out ''}"; }; clang-format = { From df8d5e61ad736653486c0d0a2fbd81d9b08f008b Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 29 Jan 2025 21:53:12 +0100 Subject: [PATCH 710/718] test: Fix shellcheck by giving git-hashing scripts shebangs This seems to be the way to do it now, even though I can't run them without setting at least one env var. I'll only fix shellcheck for now. Don't shoot the messenger. It isn't quite clear to me why the previous commit masked this problem, but I'm glad shellcheck has an effect or more effect now. --- tests/functional/git-hashing/simple.sh | 2 ++ 1 file changed, 2 insertions(+) mode change 100644 => 100755 tests/functional/git-hashing/simple.sh diff --git a/tests/functional/git-hashing/simple.sh b/tests/functional/git-hashing/simple.sh old mode 100644 new mode 100755 index f43168eb2..e02d8b297 --- a/tests/functional/git-hashing/simple.sh +++ b/tests/functional/git-hashing/simple.sh @@ -1,3 +1,5 @@ +#!/usr/bin/env bash + source common.sh repo="$TEST_ROOT/scratch" From 0531f1299c467b083638aef3656c3d88a25b86ec Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 10 Feb 2025 16:01:13 +0100 Subject: [PATCH 711/718] Resolve conflict --- scripts/nix-profile.fish.in | 34 +--------------------------------- 1 file changed, 1 insertion(+), 33 deletions(-) diff --git a/scripts/nix-profile.fish.in b/scripts/nix-profile.fish.in index becc5efd0..3a8c234ad 100644 --- a/scripts/nix-profile.fish.in +++ b/scripts/nix-profile.fish.in @@ -29,7 +29,7 @@ if test -n "$HOME" && test -n "$USER" end # Set $NIX_SSL_CERT_FILE so that Nixpkgs applications like curl work. - if test -n "$NIX_SSH_CERT_FILE" + if test -n "$NIX_SSL_CERT_FILE" : # Allow users to override the NIX_SSL_CERT_FILE else if test -e /etc/ssl/certs/ca-certificates.crt # NixOS, Ubuntu, Debian, Gentoo, Arch set --export NIX_SSL_CERT_FILE /etc/ssl/certs/ca-certificates.crt @@ -56,36 +56,4 @@ if test -n "$HOME" && test -n "$USER" set --erase NIX_LINK end -<<<<<<< HEAD -======= -# Set $NIX_SSL_CERT_FILE so that Nixpkgs applications like curl work. -if test -n "$NIX_SSL_CERT_FILE" - : # Allow users to override the NIX_SSL_CERT_FILE -else if test -e /etc/ssl/certs/ca-certificates.crt # NixOS, Ubuntu, Debian, Gentoo, Arch - set --export NIX_SSL_CERT_FILE /etc/ssl/certs/ca-certificates.crt -else if test -e /etc/ssl/ca-bundle.pem # openSUSE Tumbleweed - set --export NIX_SSL_CERT_FILE /etc/ssl/ca-bundle.pem -else if test -e /etc/ssl/certs/ca-bundle.crt # Old NixOS - set --export NIX_SSL_CERT_FILE /etc/ssl/certs/ca-bundle.crt -else if test -e /etc/pki/tls/certs/ca-bundle.crt # Fedora, CentOS - set --export NIX_SSL_CERT_FILE /etc/pki/tls/certs/ca-bundle.crt -else if test -e "$NIX_LINK/etc/ssl/certs/ca-bundle.crt" # fall back to cacert in Nix profile - set --export NIX_SSL_CERT_FILE "$NIX_LINK/etc/ssl/certs/ca-bundle.crt" -else if test -e "$NIX_LINK/etc/ca-bundle.crt" # old cacert in Nix profile - set --export NIX_SSL_CERT_FILE "$NIX_LINK/etc/ca-bundle.crt" -end - -# Only use MANPATH if it is already set. In general `man` will just simply -# pick up `.nix-profile/share/man` because is it close to `.nix-profile/bin` -# which is in the $PATH. For more info, run `manpath -d`. -if set --query MANPATH - set --export --prepend --path MANPATH "$NIX_LINK/share/man" -end - -add_path "$NIX_LINK/bin" -set --erase NIX_LINK - -# Cleanup - ->>>>>>> 803fb83f7 (nix-profile.fish: Typo NIX_SS{H => L}_CERT_FILE) functions -e add_path From 83306bb841cff73723b813905c2e7dab76c6bfcc Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 11 Feb 2025 20:36:28 +0100 Subject: [PATCH 712/718] copyPathToStore(): Preserve symlinks E.g. in a derivation attribute `foo = ./bar`, if ./bar is a symlink, we should copy the symlink to the store, not its target. This restores the behaviour of Nix <= 2.19. (cherry picked from commit 26b87e78b5dd62d9cca7c7d08a697dd2d22ae38c) --- src/libexpr/eval.cc | 2 +- tests/functional/meson.build | 1 + tests/functional/simple.sh | 2 +- tests/functional/symlinks.sh | 16 ++++++++++++++++ 4 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 tests/functional/symlinks.sh diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 19ca1a359..dee764429 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -2384,7 +2384,7 @@ StorePath EvalState::copyPathToStore(NixStringContext & context, const SourcePat : [&]() { auto dstPath = fetchToStore( *store, - path.resolveSymlinks(), + path.resolveSymlinks(SymlinkResolution::Ancestors), settings.readOnlyMode ? FetchMode::DryRun : FetchMode::Copy, path.baseName(), ContentAddressMethod::Raw::NixArchive, diff --git a/tests/functional/meson.build b/tests/functional/meson.build index 83e08c4f5..03a07bc54 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -164,6 +164,7 @@ suites = [ 'debugger.sh', 'extra-sandbox-profile.sh', 'help.sh', + 'symlinks.sh', ], 'workdir': meson.current_source_dir(), }, diff --git a/tests/functional/simple.sh b/tests/functional/simple.sh index 8afa369c2..c1f2eef41 100755 --- a/tests/functional/simple.sh +++ b/tests/functional/simple.sh @@ -15,7 +15,7 @@ echo "output path is $outPath" [[ ! -w $outPath ]] text=$(cat "$outPath/hello") -if test "$text" != "Hello World!"; then exit 1; fi +[[ "$text" = "Hello World!" ]] TODO_NixOS diff --git a/tests/functional/symlinks.sh b/tests/functional/symlinks.sh new file mode 100644 index 000000000..5eb22b3f9 --- /dev/null +++ b/tests/functional/symlinks.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +source common.sh + +# Check that when we have a derivation attribute that refers to a +# symlink, we copy the symlink, not its target. +# shellcheck disable=SC2016 +nix build --impure --no-link --expr ' + with import ./config.nix; + + mkDerivation { + name = "simple"; + builder = builtins.toFile "builder.sh" "[[ -L \"$symlink\" ]]; mkdir $out"; + symlink = ./lang/symlink-resolution/foo/overlays; + } +' From d3082284974e8028fd406909651fdec8f23f19d4 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 11 Feb 2025 22:42:36 +0100 Subject: [PATCH 713/718] Don't import a symlink This is a workaround to avoid differing evaluation results between Nix 2.19 and >= 2.20 (#12449). (cherry picked from commit 2e20a5f8220c736681752587193d36b7955f6cbc) --- packaging/components.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/components.nix b/packaging/components.nix index d1bfe83bf..07bb209cd 100644 --- a/packaging/components.nix +++ b/packaging/components.nix @@ -56,7 +56,7 @@ in nix-cli = callPackage ../src/nix/package.nix { version = fineVersion; }; - nix-functional-tests = callPackage ../src/nix-functional-tests/package.nix { + nix-functional-tests = callPackage ../tests/functional/package.nix { version = fineVersion; }; From dffcc184d7ab8a39085015181e7e693b0de5433a Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 12 Feb 2025 14:53:04 +0100 Subject: [PATCH 714/718] lockFlake(): When refetching a locked flake, use the locked ref Otherwise we may accidentally update a lock when we shouldn't. Fixes #12445. (cherry picked from commit 5c552b62fc1b45e614b86bb93c7b6ef4f14bff18) # Conflicts: # src/libflake/flake/flake.cc --- src/libflake/flake/flake.cc | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/libflake/flake/flake.cc b/src/libflake/flake/flake.cc index 06260c67a..5827668a2 100644 --- a/src/libflake/flake/flake.cc +++ b/src/libflake/flake/flake.cc @@ -554,12 +554,18 @@ LockedFlake lockFlake( /* Get the input flake, resolve 'path:./...' flakerefs relative to the parent flake. */ - auto getInputFlake = [&]() + auto getInputFlake = [&](const FlakeRef & ref) { if (auto resolvedPath = resolveRelativePath()) { +<<<<<<< HEAD return readFlake(state, *input.ref, *input.ref, *input.ref, *resolvedPath, inputPath); } else { return getFlake(state, *input.ref, useRegistries, flakeCache, inputPath); +======= + return readFlake(state, ref, ref, ref, *resolvedPath, inputAttrPath); + } else { + return getFlake(state, ref, useRegistries, flakeCache, inputAttrPath); +>>>>>>> 5c552b62f (lockFlake(): When refetching a locked flake, use the locked ref) } }; @@ -640,7 +646,7 @@ LockedFlake lockFlake( } if (mustRefetch) { - auto inputFlake = getInputFlake(); + auto inputFlake = getInputFlake(oldLock->lockedRef); nodePaths.emplace(childNode, inputFlake.path.parent()); computeLocks(inputFlake.inputs, childNode, inputPath, oldLock, followsPrefix, inputFlake.path, false); @@ -668,7 +674,7 @@ LockedFlake lockFlake( auto ref = (input2.ref && explicitCliOverrides.contains(inputPath)) ? *input2.ref : *input.ref; if (input.isFlake) { - auto inputFlake = getInputFlake(); + auto inputFlake = getInputFlake(*input.ref); auto childNode = make_ref( inputFlake.lockedRef, From 0ff190107f2de65247b8f2c2f7c7995737c72e16 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 12 Feb 2025 16:54:48 +0100 Subject: [PATCH 715/718] Resolve merge conflict --- src/libflake/flake/flake.cc | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/libflake/flake/flake.cc b/src/libflake/flake/flake.cc index 5827668a2..507bef769 100644 --- a/src/libflake/flake/flake.cc +++ b/src/libflake/flake/flake.cc @@ -557,15 +557,9 @@ LockedFlake lockFlake( auto getInputFlake = [&](const FlakeRef & ref) { if (auto resolvedPath = resolveRelativePath()) { -<<<<<<< HEAD - return readFlake(state, *input.ref, *input.ref, *input.ref, *resolvedPath, inputPath); + return readFlake(state, ref, ref, ref, *resolvedPath, inputPath); } else { - return getFlake(state, *input.ref, useRegistries, flakeCache, inputPath); -======= - return readFlake(state, ref, ref, ref, *resolvedPath, inputAttrPath); - } else { - return getFlake(state, ref, useRegistries, flakeCache, inputAttrPath); ->>>>>>> 5c552b62f (lockFlake(): When refetching a locked flake, use the locked ref) + return getFlake(state, ref, useRegistries, flakeCache, inputPath); } }; From 6c61d0ab8ccd47d52859de7af89c5abb6901a63c Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 18 Feb 2025 23:52:26 +0100 Subject: [PATCH 716/718] Formatting --- flake.nix | 59 +++++++------- packaging/hydra.nix | 184 ++++++++++++++++++++++---------------------- 2 files changed, 122 insertions(+), 121 deletions(-) diff --git a/flake.nix b/flake.nix index 74b0a9809..29111b453 100644 --- a/flake.nix +++ b/flake.nix @@ -34,7 +34,9 @@ officialRelease = true; - linux32BitSystems = [ /* "i686-linux" */ ]; + linux32BitSystems = [ + # "i686-linux" + ]; linux64BitSystems = [ "x86_64-linux" "aarch64-linux" @@ -345,7 +347,7 @@ # These attributes go right into `packages.`. "${pkgName}" = nixpkgsFor.${system}.native.nixComponents.${pkgName}; #"${pkgName}-static" = nixpkgsFor.${system}.static.nixComponents.${pkgName}; - "${pkgName}-llvm" = nixpkgsFor.${system}.llvm.nixComponents.${pkgName}; + #"${pkgName}-llvm" = nixpkgsFor.${system}.llvm.nixComponents.${pkgName}; } // lib.optionalAttrs supportsCross ( flatMapAttrs (lib.genAttrs crossSystems (_: { })) ( @@ -402,35 +404,34 @@ } ) ) - // lib.optionalAttrs (!nixpkgsFor.${system}.native.stdenv.isDarwin) ( - /* - prefixAttrs "static" ( - forAllStdenvs ( - stdenvName: - makeShell { - pkgs = nixpkgsFor.${system}.stdenvs."${stdenvName}Packages".pkgsStatic; - } + /* + // lib.optionalAttrs (!nixpkgsFor.${system}.native.stdenv.isDarwin) ( + prefixAttrs "static" ( + forAllStdenvs ( + stdenvName: + makeShell { + pkgs = nixpkgsFor.${system}.stdenvs."${stdenvName}Packages".pkgsStatic; + } + ) + ) + // prefixAttrs "llvm" ( + forAllStdenvs ( + stdenvName: + makeShell { + pkgs = nixpkgsFor.${system}.stdenvs."${stdenvName}Packages".pkgsLLVM; + } + ) + ) + // prefixAttrs "cross" ( + forAllCrossSystems ( + crossSystem: + makeShell { + pkgs = nixpkgsFor.${system}.cross.${crossSystem}; + } + ) ) ) - // - */ - prefixAttrs "llvm" ( - forAllStdenvs ( - stdenvName: - makeShell { - pkgs = nixpkgsFor.${system}.stdenvs."${stdenvName}Packages".pkgsLLVM; - } - ) - ) - // prefixAttrs "cross" ( - forAllCrossSystems ( - crossSystem: - makeShell { - pkgs = nixpkgsFor.${system}.cross.${crossSystem}; - } - ) - ) - ) + */ // { default = self.devShells.${system}.native-stdenvPackages; } diff --git a/packaging/hydra.nix b/packaging/hydra.nix index be1b69668..debd98cf2 100644 --- a/packaging/hydra.nix +++ b/packaging/hydra.nix @@ -66,62 +66,62 @@ in )) [ "i686-linux" ]; /* - buildStatic = forAllPackages ( - pkgName: - lib.genAttrs linux64BitSystems (system: nixpkgsFor.${system}.static.nixComponents.${pkgName}) - ); + buildStatic = forAllPackages ( + pkgName: + lib.genAttrs linux64BitSystems (system: nixpkgsFor.${system}.static.nixComponents.${pkgName}) + ); - buildCross = forAllPackages ( - pkgName: - # Hack to avoid non-evaling package - ( - if pkgName == "nix-functional-tests" then - lib.flip builtins.removeAttrs [ "x86_64-w64-mingw32" ] - else - lib.id - ) + buildCross = forAllPackages ( + pkgName: + # Hack to avoid non-evaling package ( - forAllCrossSystems ( - crossSystem: - lib.genAttrs [ "x86_64-linux" ] ( - system: nixpkgsFor.${system}.cross.${crossSystem}.nixComponents.${pkgName} + if pkgName == "nix-functional-tests" then + lib.flip builtins.removeAttrs [ "x86_64-w64-mingw32" ] + else + lib.id + ) + ( + forAllCrossSystems ( + crossSystem: + lib.genAttrs [ "x86_64-linux" ] ( + system: nixpkgsFor.${system}.cross.${crossSystem}.nixComponents.${pkgName} + ) ) ) - ) - ); + ); - buildNoGc = - let - components = forAllSystems ( - system: - nixpkgsFor.${system}.native.nixComponents.overrideScope ( - self: super: { - nix-expr = super.nix-expr.override { enableGC = false; }; - } - ) - ); - in - forAllPackages (pkgName: forAllSystems (system: components.${system}.${pkgName})); + buildNoGc = + let + components = forAllSystems ( + system: + nixpkgsFor.${system}.native.nixComponents.overrideScope ( + self: super: { + nix-expr = super.nix-expr.override { enableGC = false; }; + } + ) + ); + in + forAllPackages (pkgName: forAllSystems (system: components.${system}.${pkgName})); - buildNoTests = forAllSystems (system: nixpkgsFor.${system}.native.nixComponents.nix-cli); + buildNoTests = forAllSystems (system: nixpkgsFor.${system}.native.nixComponents.nix-cli); - # Toggles some settings for better coverage. Windows needs these - # library combinations, and Debian build Nix with GNU readline too. - buildReadlineNoMarkdown = - let - components = forAllSystems ( - system: - nixpkgsFor.${system}.native.nixComponents.overrideScope ( - self: super: { - nix-cmd = super.nix-cmd.override { - enableMarkdown = false; - readlineFlavor = "readline"; - }; - } - ) - ); - in - forAllPackages (pkgName: forAllSystems (system: components.${system}.${pkgName})); + # Toggles some settings for better coverage. Windows needs these + # library combinations, and Debian build Nix with GNU readline too. + buildReadlineNoMarkdown = + let + components = forAllSystems ( + system: + nixpkgsFor.${system}.native.nixComponents.overrideScope ( + self: super: { + nix-cmd = super.nix-cmd.override { + enableMarkdown = false; + readlineFlavor = "readline"; + }; + } + ) + ); + in + forAllPackages (pkgName: forAllSystems (system: components.${system}.${pkgName})); */ # Perl bindings for various platforms. @@ -135,31 +135,31 @@ in ); /* - binaryTarballCross = lib.genAttrs [ "x86_64-linux" ] ( - system: - forAllCrossSystems ( - crossSystem: - binaryTarball nixpkgsFor.${system}.cross.${crossSystem}.nix - nixpkgsFor.${system}.cross.${crossSystem} - ) - ); + binaryTarballCross = lib.genAttrs [ "x86_64-linux" ] ( + system: + forAllCrossSystems ( + crossSystem: + binaryTarball nixpkgsFor.${system}.cross.${crossSystem}.nix + nixpkgsFor.${system}.cross.${crossSystem} + ) + ); - # The first half of the installation script. This is uploaded - # to https://nixos.org/nix/install. It downloads the binary - # tarball for the user's system and calls the second half of the - # installation script. - installerScript = installScriptFor [ - # Native - self.hydraJobs.binaryTarball."x86_64-linux" - self.hydraJobs.binaryTarball."i686-linux" - self.hydraJobs.binaryTarball."aarch64-linux" - self.hydraJobs.binaryTarball."x86_64-darwin" - self.hydraJobs.binaryTarball."aarch64-darwin" - # Cross - self.hydraJobs.binaryTarballCross."x86_64-linux"."armv6l-unknown-linux-gnueabihf" - self.hydraJobs.binaryTarballCross."x86_64-linux"."armv7l-unknown-linux-gnueabihf" - self.hydraJobs.binaryTarballCross."x86_64-linux"."riscv64-unknown-linux-gnu" - ]; + # The first half of the installation script. This is uploaded + # to https://nixos.org/nix/install. It downloads the binary + # tarball for the user's system and calls the second half of the + # installation script. + installerScript = installScriptFor [ + # Native + self.hydraJobs.binaryTarball."x86_64-linux" + self.hydraJobs.binaryTarball."i686-linux" + self.hydraJobs.binaryTarball."aarch64-linux" + self.hydraJobs.binaryTarball."x86_64-darwin" + self.hydraJobs.binaryTarball."aarch64-darwin" + # Cross + self.hydraJobs.binaryTarballCross."x86_64-linux"."armv6l-unknown-linux-gnueabihf" + self.hydraJobs.binaryTarballCross."x86_64-linux"."armv7l-unknown-linux-gnueabihf" + self.hydraJobs.binaryTarballCross."x86_64-linux"."riscv64-unknown-linux-gnu" + ]; */ installerScriptForGHA = forAllSystems ( @@ -232,25 +232,25 @@ in }; /* - installTests = forAllSystems ( - system: - let - pkgs = nixpkgsFor.${system}.native; - in - pkgs.runCommand "install-tests" { - againstSelf = testNixVersions pkgs pkgs.nix; - againstCurrentLatest = - # FIXME: temporarily disable this on macOS because of #3605. - if system == "x86_64-linux" then testNixVersions pkgs pkgs.nixVersions.latest else null; - # Disabled because the latest stable version doesn't handle - # `NIX_DAEMON_SOCKET_PATH` which is required for the tests to work - # againstLatestStable = testNixVersions pkgs pkgs.nixStable; - } "touch $out" - ); + installTests = forAllSystems ( + system: + let + pkgs = nixpkgsFor.${system}.native; + in + pkgs.runCommand "install-tests" { + againstSelf = testNixVersions pkgs pkgs.nix; + againstCurrentLatest = + # FIXME: temporarily disable this on macOS because of #3605. + if system == "x86_64-linux" then testNixVersions pkgs pkgs.nixVersions.latest else null; + # Disabled because the latest stable version doesn't handle + # `NIX_DAEMON_SOCKET_PATH` which is required for the tests to work + # againstLatestStable = testNixVersions pkgs pkgs.nixStable; + } "touch $out" + ); - installerTests = import ../tests/installer { - binaryTarballs = self.hydraJobs.binaryTarball; - inherit nixpkgsFor; - }; + installerTests = import ../tests/installer { + binaryTarballs = self.hydraJobs.binaryTarball; + inherit nixpkgsFor; + }; */ } From ed4aeb48750d63ec97518a14deda377b043082fd Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 19 Feb 2025 00:24:42 +0100 Subject: [PATCH 717/718] Fix hydraJobs.tests.functional_user --- tests/functional/common/init.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/functional/common/init.sh b/tests/functional/common/init.sh index 63f732d6a..6e9bffec5 100755 --- a/tests/functional/common/init.sh +++ b/tests/functional/common/init.sh @@ -12,6 +12,7 @@ if isTestOnNixOS; then ! test -e "$test_nix_conf" cat > "$test_nix_conf" < Date: Wed, 19 Feb 2025 00:25:04 +0100 Subject: [PATCH 718/718] Fix flake-regression dependency --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ad1ee5317..86a673b37 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -75,7 +75,7 @@ jobs: ; flake_regressions: - needs: vm_tests + needs: build_x86_64-linux runs-on: UbuntuLatest32Cores128G steps: - name: Checkout nix