From 6ee03b8444e1838b9985a9fd4f0f46947e958b3b Mon Sep 17 00:00:00 2001 From: zimbatm Date: Wed, 3 Jun 2020 12:38:23 +0200 Subject: [PATCH 01/62] libutils/hash: remove default encoding This will make it easier to reason about the hash encoding and switch to SRI everywhere where possible. --- perl/lib/Nix/Store.xs | 4 ++-- src/libexpr/primops/fetchTree.cc | 4 ++-- src/libfetchers/fetchers.cc | 4 ++-- src/libfetchers/tarball.cc | 6 +++--- src/libstore/build.cc | 2 +- src/libstore/export-import.cc | 2 +- src/libstore/local-store.cc | 10 +++++----- src/libstore/nar-info-disk-cache.cc | 4 ++-- src/libstore/nar-info.cc | 4 ++-- src/libstore/optimise-store.cc | 2 +- src/libstore/store-api.cc | 12 ++++++------ src/libutil/hash.hh | 2 +- src/libutil/tests/hash.cc | 16 ++++++++-------- src/nix-store/nix-store.cc | 6 +++--- src/nix/verify.cc | 2 +- 15 files changed, 40 insertions(+), 40 deletions(-) diff --git a/perl/lib/Nix/Store.xs b/perl/lib/Nix/Store.xs index 890310b3e..945ed49c7 100644 --- a/perl/lib/Nix/Store.xs +++ b/perl/lib/Nix/Store.xs @@ -80,7 +80,7 @@ SV * queryReferences(char * path) SV * queryPathHash(char * path) PPCODE: try { - auto s = store()->queryPathInfo(store()->parseStorePath(path))->narHash.to_string(); + auto s = store()->queryPathInfo(store()->parseStorePath(path))->narHash.to_string(Base32, true); XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0))); } catch (Error & e) { croak("%s", e.what()); @@ -106,7 +106,7 @@ SV * queryPathInfo(char * path, int base32) XPUSHs(&PL_sv_undef); else XPUSHs(sv_2mortal(newSVpv(store()->printStorePath(*info->deriver).c_str(), 0))); - auto s = info->narHash.to_string(base32 ? Base32 : Base16); + auto s = info->narHash.to_string(base32 ? Base32 : Base16, true); XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0))); mXPUSHi(info->registrationTime); mXPUSHi(info->narSize); diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc index c5a0d9886..b90408798 100644 --- a/src/libexpr/primops/fetchTree.cc +++ b/src/libexpr/primops/fetchTree.cc @@ -23,7 +23,7 @@ void emitTreeAttrs( assert(tree.info.narHash); mkString(*state.allocAttr(v, state.symbols.create("narHash")), - tree.info.narHash.to_string(SRI)); + tree.info.narHash.to_string(SRI, true)); if (input->getRev()) { mkString(*state.allocAttr(v, state.symbols.create("rev")), input->getRev()->gitRev()); @@ -140,7 +140,7 @@ static void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v, : hashFile(htSHA256, path); if (hash != *expectedHash) throw Error((unsigned int) 102, "hash mismatch in file downloaded from '%s':\n wanted: %s\n got: %s", - *url, expectedHash->to_string(), hash.to_string()); + *url, expectedHash->to_string(Base32, true), hash.to_string(Base32, true)); } if (state.allowedPaths) diff --git a/src/libfetchers/fetchers.cc b/src/libfetchers/fetchers.cc index 94ac30e38..ca555114d 100644 --- a/src/libfetchers/fetchers.cc +++ b/src/libfetchers/fetchers.cc @@ -47,7 +47,7 @@ Attrs Input::toAttrs() const { auto attrs = toAttrsInternal(); if (narHash) - attrs.emplace("narHash", narHash->to_string(SRI)); + attrs.emplace("narHash", narHash->to_string(SRI, true)); attrs.emplace("type", type()); return attrs; } @@ -67,7 +67,7 @@ std::pair> Input::fetchTree(ref store) if (narHash && narHash != input->narHash) throw Error("NAR hash mismatch in input '%s' (%s), expected '%s', got '%s'", - to_string(), tree.actualPath, narHash->to_string(SRI), input->narHash->to_string(SRI)); + to_string(), tree.actualPath, narHash->to_string(SRI, true), input->narHash->to_string(SRI, true)); return {std::move(tree), input}; } diff --git a/src/libfetchers/tarball.cc b/src/libfetchers/tarball.cc index b6e57379b..1b0eba18a 100644 --- a/src/libfetchers/tarball.cc +++ b/src/libfetchers/tarball.cc @@ -196,9 +196,9 @@ struct TarballInput : Input // NAR hashes are preferred over file hashes since tar/zip files // don't have a canonical representation. if (narHash) - url2.query.insert_or_assign("narHash", narHash->to_string(SRI)); + url2.query.insert_or_assign("narHash", narHash->to_string(SRI, true)); else if (hash) - url2.query.insert_or_assign("hash", hash->to_string(SRI)); + url2.query.insert_or_assign("hash", hash->to_string(SRI, true)); return url2; } @@ -207,7 +207,7 @@ struct TarballInput : Input Attrs attrs; attrs.emplace("url", url.to_string()); if (hash) - attrs.emplace("hash", hash->to_string(SRI)); + attrs.emplace("hash", hash->to_string(SRI, true)); return attrs; } diff --git a/src/libstore/build.cc b/src/libstore/build.cc index f5c132a83..9582a9007 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -3718,7 +3718,7 @@ void DerivationGoal::registerOutputs() worker.hashMismatch = true; delayedException = std::make_exception_ptr( BuildError("hash mismatch in fixed-output derivation '%s':\n wanted: %s\n got: %s", - worker.store.printStorePath(dest), h.to_string(SRI), h2.to_string(SRI))); + worker.store.printStorePath(dest), h.to_string(SRI, true), h2.to_string(SRI, true))); Path actualDest = worker.store.Store::toRealPath(dest); diff --git a/src/libstore/export-import.cc b/src/libstore/export-import.cc index f0d01a240..54471d4a3 100644 --- a/src/libstore/export-import.cc +++ b/src/libstore/export-import.cc @@ -57,7 +57,7 @@ void Store::exportPath(const StorePath & path, Sink & sink) Hash hash = hashAndWriteSink.currentHash(); if (hash != info->narHash && info->narHash != Hash(info->narHash.type)) throw Error("hash of path '%s' has changed from '%s' to '%s'!", - printStorePath(path), info->narHash.to_string(), hash.to_string()); + printStorePath(path), info->narHash.to_string(Base32, true), hash.to_string(Base32, true)); hashAndWriteSink << exportMagic diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 80851b591..1c3795eb1 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -580,7 +580,7 @@ uint64_t LocalStore::addValidPath(State & state, state.stmtRegisterValidPath.use() (printStorePath(info.path)) - (info.narHash.to_string(Base16)) + (info.narHash.to_string(Base16, true)) (info.registrationTime == 0 ? time(0) : info.registrationTime) (info.deriver ? printStorePath(*info.deriver) : "", (bool) info.deriver) (info.narSize, info.narSize != 0) @@ -680,7 +680,7 @@ void LocalStore::updatePathInfo(State & state, const ValidPathInfo & info) { state.stmtUpdatePathInfo.use() (info.narSize, info.narSize != 0) - (info.narHash.to_string(Base16)) + (info.narHash.to_string(Base16, true)) (info.ultimate ? 1 : 0, info.ultimate) (concatStringsSep(" ", info.sigs), !info.sigs.empty()) (info.ca, !info.ca.empty()) @@ -1022,7 +1022,7 @@ void LocalStore::addToStore(const ValidPathInfo & info, Source & source, if (hashResult.first != info.narHash) throw Error("hash mismatch importing path '%s';\n wanted: %s\n got: %s", - printStorePath(info.path), info.narHash.to_string(), hashResult.first.to_string()); + printStorePath(info.path), info.narHash.to_string(Base32, true), hashResult.first.to_string(Base32, true)); if (hashResult.second != info.narSize) throw Error("size mismatch importing path '%s';\n wanted: %s\n got: %s", @@ -1155,7 +1155,7 @@ StorePath LocalStore::addTextToStore(const string & name, const string & s, info.narHash = narHash; info.narSize = sink.s->size(); info.references = cloneStorePathSet(references); - info.ca = "text:" + hash.to_string(); + info.ca = "text:" + hash.to_string(Base32, true); registerValidPath(info); } @@ -1273,7 +1273,7 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair) if (info->narHash != nullHash && info->narHash != current.first) { printError("path '%s' was modified! expected hash '%s', got '%s'", - printStorePath(i), info->narHash.to_string(), current.first.to_string()); + printStorePath(i), info->narHash.to_string(Base32, true), current.first.to_string(Base32, true)); if (repair) repairPath(i); else errors = true; } else { diff --git a/src/libstore/nar-info-disk-cache.cc b/src/libstore/nar-info-disk-cache.cc index 442541330..e8cf1d177 100644 --- a/src/libstore/nar-info-disk-cache.cc +++ b/src/libstore/nar-info-disk-cache.cc @@ -230,9 +230,9 @@ public: (std::string(info->path.name())) (narInfo ? narInfo->url : "", narInfo != 0) (narInfo ? narInfo->compression : "", narInfo != 0) - (narInfo && narInfo->fileHash ? narInfo->fileHash.to_string() : "", narInfo && narInfo->fileHash) + (narInfo && narInfo->fileHash ? narInfo->fileHash.to_string(Base32, true) : "", narInfo && narInfo->fileHash) (narInfo ? narInfo->fileSize : 0, narInfo != 0 && narInfo->fileSize) - (info->narHash.to_string()) + (info->narHash.to_string(Base32, true)) (info->narSize) (concatStringsSep(" ", info->shortRefs())) (info->deriver ? std::string(info->deriver->to_string()) : "", (bool) info->deriver) diff --git a/src/libstore/nar-info.cc b/src/libstore/nar-info.cc index 1375094b5..6b16be08a 100644 --- a/src/libstore/nar-info.cc +++ b/src/libstore/nar-info.cc @@ -87,10 +87,10 @@ std::string NarInfo::to_string(const Store & store) const assert(compression != ""); res += "Compression: " + compression + "\n"; assert(fileHash.type == htSHA256); - res += "FileHash: " + fileHash.to_string(Base32) + "\n"; + res += "FileHash: " + fileHash.to_string(Base32, true) + "\n"; res += "FileSize: " + std::to_string(fileSize) + "\n"; assert(narHash.type == htSHA256); - res += "NarHash: " + narHash.to_string(Base32) + "\n"; + res += "NarHash: " + narHash.to_string(Base32, true) + "\n"; res += "NarSize: " + std::to_string(narSize) + "\n"; res += "References: " + concatStringsSep(" ", shortRefs()) + "\n"; diff --git a/src/libstore/optimise-store.cc b/src/libstore/optimise-store.cc index 8ac382e9d..3f4b72b9c 100644 --- a/src/libstore/optimise-store.cc +++ b/src/libstore/optimise-store.cc @@ -150,7 +150,7 @@ void LocalStore::optimisePath_(Activity * act, OptimiseStats & stats, contents of the symlink (i.e. the result of readlink()), not the contents of the target (which may not even exist). */ Hash hash = hashPath(htSHA256, path).first; - debug(format("'%1%' has hash '%2%'") % path % hash.to_string()); + debug(format("'%1%' has hash '%2%'") % path % hash.to_string(Base32, true)); /* Check if this is a known hash. */ Path linkPath = linksDir + "/" + hash.to_string(Base32, false); diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index 095363d0c..0645fca84 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -142,7 +142,7 @@ StorePath Store::makeStorePath(const string & type, const Hash & hash, std::string_view name) const { /* e.g., "source:sha256:1abc...:/nix/store:foo.tar.gz" */ - string s = type + ":" + hash.to_string(Base16) + ":" + storeDir + ":" + std::string(name); + string s = type + ":" + hash.to_string(Base16, true) + ":" + storeDir + ":" + std::string(name); auto h = compressHash(hashString(htSHA256, s), 20); return StorePath::make(h.hash, name); } @@ -186,7 +186,7 @@ StorePath Store::makeFixedOutputPath( hashString(htSHA256, "fixed:out:" + (recursive == FileIngestionMethod::Recursive ? (string) "r:" : "") - + hash.to_string(Base16) + ":"), + + hash.to_string(Base16, true) + ":"), name); } } @@ -461,7 +461,7 @@ void Store::pathInfoToJSON(JSONPlaceholder & jsonOut, const StorePathSet & store auto info = queryPathInfo(storePath); jsonPath - .attr("narHash", info->narHash.to_string(hashBase)) + .attr("narHash", info->narHash.to_string(hashBase, true)) .attr("narSize", info->narSize); { @@ -504,7 +504,7 @@ void Store::pathInfoToJSON(JSONPlaceholder & jsonOut, const StorePathSet & store if (!narInfo->url.empty()) jsonPath.attr("url", narInfo->url); if (narInfo->fileHash) - jsonPath.attr("downloadHash", narInfo->fileHash.to_string()); + jsonPath.attr("downloadHash", narInfo->fileHash.to_string(Base32, true)); if (narInfo->fileSize) jsonPath.attr("downloadSize", narInfo->fileSize); if (showClosureSize) @@ -760,7 +760,7 @@ std::string ValidPathInfo::fingerprint(const Store & store) const store.printStorePath(path)); return "1;" + store.printStorePath(path) + ";" - + narHash.to_string(Base32) + ";" + + narHash.to_string(Base32, true) + ";" + std::to_string(narSize) + ";" + concatStringsSep(",", store.printStorePathSet(references)); } @@ -836,7 +836,7 @@ std::string makeFixedOutputCA(FileIngestionMethod recursive, const Hash & hash) { return "fixed:" + (recursive == FileIngestionMethod::Recursive ? (std::string) "r:" : "") - + hash.to_string(); + + hash.to_string(Base32, true); } diff --git a/src/libutil/hash.hh b/src/libutil/hash.hh index ea9fca3e7..4ff13f6b2 100644 --- a/src/libutil/hash.hh +++ b/src/libutil/hash.hh @@ -79,7 +79,7 @@ struct Hash /* Return a string representation of the hash, in base-16, base-32 or base-64. By default, this is prefixed by the hash type (e.g. "sha256:"). */ - std::string to_string(Base base = Base32, bool includeType = true) const; + std::string to_string(Base base, bool includeType) const; std::string gitRev() const { diff --git a/src/libutil/tests/hash.cc b/src/libutil/tests/hash.cc index 7cb439817..5334b046e 100644 --- a/src/libutil/tests/hash.cc +++ b/src/libutil/tests/hash.cc @@ -11,28 +11,28 @@ namespace nix { // values taken from: https://tools.ietf.org/html/rfc1321 auto s1 = ""; auto hash = hashString(HashType::htMD5, s1); - ASSERT_EQ(hash.to_string(Base::Base16), "md5:d41d8cd98f00b204e9800998ecf8427e"); + ASSERT_EQ(hash.to_string(Base::Base16, true), "md5:d41d8cd98f00b204e9800998ecf8427e"); } TEST(hashString, testKnownMD5Hashes2) { // values taken from: https://tools.ietf.org/html/rfc1321 auto s2 = "abc"; auto hash = hashString(HashType::htMD5, s2); - ASSERT_EQ(hash.to_string(Base::Base16), "md5:900150983cd24fb0d6963f7d28e17f72"); + ASSERT_EQ(hash.to_string(Base::Base16, true), "md5:900150983cd24fb0d6963f7d28e17f72"); } TEST(hashString, testKnownSHA1Hashes1) { // values taken from: https://tools.ietf.org/html/rfc3174 auto s = "abc"; auto hash = hashString(HashType::htSHA1, s); - ASSERT_EQ(hash.to_string(Base::Base16),"sha1:a9993e364706816aba3e25717850c26c9cd0d89d"); + ASSERT_EQ(hash.to_string(Base::Base16, true),"sha1:a9993e364706816aba3e25717850c26c9cd0d89d"); } TEST(hashString, testKnownSHA1Hashes2) { // values taken from: https://tools.ietf.org/html/rfc3174 auto s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; auto hash = hashString(HashType::htSHA1, s); - ASSERT_EQ(hash.to_string(Base::Base16),"sha1:84983e441c3bd26ebaae4aa1f95129e5e54670f1"); + ASSERT_EQ(hash.to_string(Base::Base16, true),"sha1:84983e441c3bd26ebaae4aa1f95129e5e54670f1"); } TEST(hashString, testKnownSHA256Hashes1) { @@ -40,7 +40,7 @@ namespace nix { auto s = "abc"; auto hash = hashString(HashType::htSHA256, s); - ASSERT_EQ(hash.to_string(Base::Base16), + ASSERT_EQ(hash.to_string(Base::Base16, true), "sha256:ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"); } @@ -48,7 +48,7 @@ namespace nix { // values taken from: https://tools.ietf.org/html/rfc4634 auto s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; auto hash = hashString(HashType::htSHA256, s); - ASSERT_EQ(hash.to_string(Base::Base16), + ASSERT_EQ(hash.to_string(Base::Base16, true), "sha256:248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"); } @@ -56,7 +56,7 @@ namespace nix { // values taken from: https://tools.ietf.org/html/rfc4634 auto s = "abc"; auto hash = hashString(HashType::htSHA512, s); - ASSERT_EQ(hash.to_string(Base::Base16), + ASSERT_EQ(hash.to_string(Base::Base16, true), "sha512:ddaf35a193617abacc417349ae20413112e6fa4e89a9" "7ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd" "454d4423643ce80e2a9ac94fa54ca49f"); @@ -67,7 +67,7 @@ namespace nix { auto s = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"; auto hash = hashString(HashType::htSHA512, s); - ASSERT_EQ(hash.to_string(Base::Base16), + ASSERT_EQ(hash.to_string(Base::Base16, true), "sha512:8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa1" "7299aeadb6889018501d289e4900f7e4331b99dec4b5433a" "c7d329eeb6dd26545e96e55b874be909"); diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc index 3a3060ad8..9491a0c26 100644 --- a/src/nix-store/nix-store.cc +++ b/src/nix-store/nix-store.cc @@ -373,7 +373,7 @@ static void opQuery(Strings opFlags, Strings opArgs) auto info = store->queryPathInfo(j); if (query == qHash) { assert(info->narHash.type == htSHA256); - cout << fmt("%s\n", info->narHash.to_string(Base32)); + cout << fmt("%s\n", info->narHash.to_string(Base32, true)); } else if (query == qSize) cout << fmt("%d\n", info->narSize); } @@ -728,7 +728,7 @@ static void opVerifyPath(Strings opFlags, Strings opArgs) if (current.first != info->narHash) { printError( "path '%s' was modified! expected hash '%s', got '%s'", - store->printStorePath(path), info->narHash.to_string(), current.first.to_string()); + store->printStorePath(path), info->narHash.to_string(Base32, true), current.first.to_string(Base32, true)); status = 1; } } @@ -856,7 +856,7 @@ static void opServe(Strings opFlags, Strings opArgs) out << info->narSize // downloadSize << info->narSize; if (GET_PROTOCOL_MINOR(clientVersion) >= 4) - out << (info->narHash ? info->narHash.to_string() : "") << info->ca << info->sigs; + out << (info->narHash ? info->narHash.to_string(Base32, true) : "") << info->ca << info->sigs; } catch (InvalidPath &) { } } diff --git a/src/nix/verify.cc b/src/nix/verify.cc index cf1fa6a99..287dad101 100644 --- a/src/nix/verify.cc +++ b/src/nix/verify.cc @@ -101,7 +101,7 @@ struct CmdVerify : StorePathsCommand act2.result(resCorruptedPath, store->printStorePath(info->path)); printError( "path '%s' was modified! expected hash '%s', got '%s'", - store->printStorePath(info->path), info->narHash.to_string(), hash.first.to_string()); + store->printStorePath(info->path), info->narHash.to_string(Base32, true), hash.first.to_string(Base32, true)); } } From 132d6f2c2419891b92870c61c599a5e6aa97c865 Mon Sep 17 00:00:00 2001 From: Carlo Nucera Date: Wed, 3 Jun 2020 16:08:32 -0400 Subject: [PATCH 02/62] Clarify the description of StorePath construction --- src/libstore/store-api.cc | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index 095363d0c..e5492ce34 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -69,7 +69,7 @@ string storePathToHash(const Path & path) /* Store paths have the following form: - /- + = /- where @@ -93,11 +93,14 @@ string storePathToHash(const Path & path) = one of: "text:::..." for plain text files written to the store using - addTextToStore(); ... are the references of the - path. - "source" + addTextToStore(); ... are the store paths referenced + by this path, in the form described by + "source:::...::self" for paths copied to the store using addToStore() when recursive - = true and hashAlgo = "sha256" + = true and hashAlgo = "sha256". Just like in the text case, we + can have the store paths referenced by the path. + Additionally, we can have an optional :self label to denote self + reference. "output:" for either the outputs created by derivations, OR paths copied to the store using addToStore() with recursive != true or @@ -125,6 +128,12 @@ string storePathToHash(const Path & path) the contents of the path (or expected contents of the path for fixed-output derivations) + Note that since an output derivation has always type output, while + something added by addToStore can have type output or source depending + on the hash, this means that the same input can be hashed differently + if added to the store via addToStore or via a derivation, in the sha256 + recursive case. + It would have been nicer to handle fixed-output derivations under "source", e.g. have something like "source:", but we're stuck with this for now... From 61e3d598b67290ca66f34fcac7b7373f506240da Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 4 Jun 2020 10:57:40 +0200 Subject: [PATCH 03/62] Rename 'nix dev-shell' to 'nix develop' Fixes #3648. --- src/nix/{dev-shell.cc => develop.cc} | 14 +++++++------- src/nix/local.mk | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) rename src/nix/{dev-shell.cc => develop.cc} (96%) diff --git a/src/nix/dev-shell.cc b/src/nix/develop.cc similarity index 96% rename from src/nix/dev-shell.cc rename to src/nix/develop.cc index d300f6a23..3045d7dc3 100644 --- a/src/nix/dev-shell.cc +++ b/src/nix/develop.cc @@ -110,7 +110,7 @@ StorePath getDerivationEnvironment(ref store, const StorePath & drvPath) auto builder = baseNameOf(drv.builder); if (builder != "bash") - throw Error("'nix dev-shell' only works on derivations that use 'bash' as their builder"); + throw Error("'nix develop' only works on derivations that use 'bash' as their builder"); auto getEnvShPath = store->addTextToStore("get-env.sh", getEnvSh, {}); @@ -231,11 +231,11 @@ struct Common : InstallableCommand, MixProfile } }; -struct CmdDevShell : Common, MixEnvironment +struct CmdDevelop : Common, MixEnvironment { std::vector command; - CmdDevShell() + CmdDevelop() { addFlag({ .longName = "command", @@ -259,15 +259,15 @@ struct CmdDevShell : Common, MixEnvironment return { Example{ "To get the build environment of GNU hello:", - "nix dev-shell nixpkgs.hello" + "nix develop nixpkgs.hello" }, Example{ "To store the build environment in a profile:", - "nix dev-shell --profile /tmp/my-shell nixpkgs.hello" + "nix develop --profile /tmp/my-shell nixpkgs.hello" }, Example{ "To use a build environment previously recorded in a profile:", - "nix dev-shell /tmp/my-shell" + "nix develop /tmp/my-shell" }, }; } @@ -341,4 +341,4 @@ struct CmdPrintDevEnv : Common }; static auto r1 = registerCommand("print-dev-env"); -static auto r2 = registerCommand("dev-shell"); +static auto r2 = registerCommand("develop"); diff --git a/src/nix/local.mk b/src/nix/local.mk index 8c0eed19e..43b7754e3 100644 --- a/src/nix/local.mk +++ b/src/nix/local.mk @@ -28,4 +28,4 @@ $(eval $(call install-symlink, $(bindir)/nix, $(libexecdir)/nix/build-remote)) src/nix-env/user-env.cc: src/nix-env/buildenv.nix.gen.hh -src/nix/dev-shell.cc: src/nix/get-env.sh.gen.hh +src/nix/develop.cc: src/nix/get-env.sh.gen.hh From 0f44b60e6dc999697bf9f2a4b3652a0551016598 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 4 Jun 2020 11:14:19 +0200 Subject: [PATCH 04/62] Make 'nix dev-shell' a deprecated alias for 'nix develop' --- src/libutil/args.cc | 11 ++++++++--- src/libutil/args.hh | 2 ++ src/libutil/util.hh | 3 +-- src/nix/main.cc | 2 ++ 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/libutil/args.cc b/src/libutil/args.cc index f829415d1..afeaf4cea 100644 --- a/src/libutil/args.cc +++ b/src/libutil/args.cc @@ -217,10 +217,15 @@ MultiCommand::MultiCommand(const Commands & commands) { expectedArgs.push_back(ExpectedArg{"command", 1, true, [=](std::vector ss) { assert(!command); - auto i = commands.find(ss[0]); + auto cmd = ss[0]; + if (auto alias = get(deprecatedAliases, cmd)) { + warn("'%s' is a deprecated alias for '%s'", cmd, *alias); + cmd = *alias; + } + auto i = commands.find(cmd); if (i == commands.end()) - throw UsageError("'%s' is not a recognised command", ss[0]); - command = {ss[0], i->second()}; + throw UsageError("'%s' is not a recognised command", cmd); + command = {cmd, i->second()}; }}); categories[Command::catDefault] = "Available commands"; diff --git a/src/libutil/args.hh b/src/libutil/args.hh index 1932e6a8a..154d1e6aa 100644 --- a/src/libutil/args.hh +++ b/src/libutil/args.hh @@ -234,6 +234,8 @@ public: std::map categories; + std::map deprecatedAliases; + // Selected command, if any. std::optional>> command; diff --git a/src/libutil/util.hh b/src/libutil/util.hh index a63ee05b3..4b117f9bc 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -459,8 +459,7 @@ string base64Encode(const string & s); string base64Decode(const string & s); -/* Get a value for the specified key from an associate container, or a - default value if the key doesn't exist. */ +/* Get a value for the specified key from an associate container. */ template std::optional get(const T & map, const typename T::key_type & key) { diff --git a/src/nix/main.cc b/src/nix/main.cc index ef301580a..1120ba5ef 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -110,6 +110,8 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs .description = "consider all previously downloaded files out-of-date", .handler = {[&]() { refresh = true; }}, }); + + deprecatedAliases.insert({"dev-shell", "develop"}); } void printFlags(std::ostream & out) override From 2299ef705c2d69add371ee4ccca04de9f2628853 Mon Sep 17 00:00:00 2001 From: Matthew Bauer Date: Wed, 3 Jun 2020 15:18:46 -0500 Subject: [PATCH 05/62] Add error message when FileIngestionMethod is out of bounds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bool coerces anything >0 to true, but in the future we may have other file ingestion methods. This shows a better error message when the “recursive” byte isn’t 1. --- src/libstore/daemon.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libstore/daemon.cc b/src/libstore/daemon.cc index f1afdff69..5cff170dd 100644 --- a/src/libstore/daemon.cc +++ b/src/libstore/daemon.cc @@ -358,8 +358,10 @@ static void performOp(TunnelLogger * logger, ref store, std::string s, baseName; FileIngestionMethod method; { - bool fixed, recursive; + bool fixed; uint8_t recursive; from >> baseName >> fixed /* obsolete */ >> recursive >> s; + if (recursive > (uint8_t) FileIngestionMethod::Recursive) + throw Error("unsupported FileIngestionMethod with value of %i; you may need to upgrade nix-daemon", recursive); method = FileIngestionMethod { recursive }; /* Compatibility hack. */ if (!fixed) { From efc5e45e95734cdade04ad6231c5185a298357d0 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Thu, 4 Jun 2020 21:05:41 +0000 Subject: [PATCH 06/62] Add `src/libutil/tests/libutil-tests` to `.gitignore` I gather this comes from the new unit tests. --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index ad5684123..983026570 100644 --- a/.gitignore +++ b/.gitignore @@ -49,6 +49,9 @@ perl/Makefile.config # /src/libstore/ *.gen.* +# /src/libutil/ +/src/libutil/tests/libutil-tests + /src/nix/nix # /src/nix-env/ From 39e84c35d0b8bf5b49f45736febd9f506e3ee4ae Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 5 Jun 2020 10:45:05 +0200 Subject: [PATCH 07/62] Fix log-prefix of `nix build -L` Alternative fix to #3661. The cause was that 'name' is a std::string_view into a temporary which could get overwritten. --- src/nix/progress-bar.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nix/progress-bar.cc b/src/nix/progress-bar.cc index 8e7ba95a3..c67701098 100644 --- a/src/nix/progress-bar.cc +++ b/src/nix/progress-bar.cc @@ -154,7 +154,7 @@ public: state->activitiesByType[type].its.emplace(act, i); if (type == actBuild) { - auto name = storePathToName(getS(fields, 0)); + std::string name(storePathToName(getS(fields, 0))); if (hasSuffix(name, ".drv")) name = name.substr(0, name.size() - 4); i->s = fmt("building " ANSI_BOLD "%s" ANSI_NORMAL, name); From 170e86dff5724264e0d3d25b9af1bd42df6aec74 Mon Sep 17 00:00:00 2001 From: regnat Date: Fri, 5 Jun 2020 17:01:02 +0200 Subject: [PATCH 08/62] Make the logger customisable Add a new `--log-format` cli argument to change the format of the logs. The possible values are - raw (the default one for old-style commands) - bar (the default one for new-style commands) - bar-with-logs (equivalent to `--print-build-logs`) - internal-json (the internal machine-readable json format) --- src/libmain/common-args.cc | 9 ++++++++ src/libmain/loggers.cc | 47 ++++++++++++++++++++++++++++++++++++++ src/libmain/loggers.hh | 19 +++++++++++++++ src/libutil/logging.cc | 4 ++-- src/libutil/logging.hh | 4 +++- src/libutil/util.cc | 2 +- src/nix-build/nix-build.cc | 4 ++++ src/nix-env/nix-env.cc | 2 ++ src/nix-store/nix-store.cc | 2 ++ src/nix/main.cc | 11 +++++---- src/nix/progress-bar.cc | 14 ++++++++---- src/nix/progress-bar.hh | 2 ++ 12 files changed, 107 insertions(+), 13 deletions(-) create mode 100644 src/libmain/loggers.cc create mode 100644 src/libmain/loggers.hh diff --git a/src/libmain/common-args.cc b/src/libmain/common-args.cc index 51e199ea5..a0cccceb4 100644 --- a/src/libmain/common-args.cc +++ b/src/libmain/common-args.cc @@ -1,5 +1,6 @@ #include "common-args.hh" #include "globals.hh" +#include "loggers.hh" namespace nix { @@ -38,6 +39,14 @@ MixCommonArgs::MixCommonArgs(const string & programName) }}, }); + addFlag({ + .longName = "log-format", + .description = "Format of the logs. One of \"raw\", \"internal-json\", \"bar\" " + "or \"bar-with-logs\".", + .labels = {"format"}, + .handler = {[](std::string format) { setLogFormat(format); }}, + }); + addFlag({ .longName = "max-jobs", .shortName = 'j', diff --git a/src/libmain/loggers.cc b/src/libmain/loggers.cc new file mode 100644 index 000000000..d3d5b104b --- /dev/null +++ b/src/libmain/loggers.cc @@ -0,0 +1,47 @@ +#include "loggers.hh" +#include "../nix/progress-bar.hh" + +namespace nix { + +LogFormat defaultLogFormat = LogFormat::raw; + +LogFormat parseLogFormat(const string &logFormatStr) { + if (logFormatStr == "raw") + return LogFormat::raw; + else if (logFormatStr == "internal-json") + return LogFormat::internalJson; + else if (logFormatStr == "bar") + return LogFormat::bar; + else if (logFormatStr == "bar-with-logs") + return LogFormat::barWithLogs; + throw Error(format("option 'log-format' has an invalid value '%s'") % + logFormatStr); +} + +Logger *makeDefaultLogger() { + switch (defaultLogFormat) { + case LogFormat::raw: + return makeSimpleLogger(); + case LogFormat::internalJson: + return makeJSONLogger(*makeSimpleLogger()); + case LogFormat::bar: + return makeProgressBar(); + case LogFormat::barWithLogs: + return makeProgressBar(true); + } +} + +void setLogFormat(const string &logFormatStr) { + setLogFormat(parseLogFormat(logFormatStr)); +} + +void setLogFormat(const LogFormat &logFormat) { + defaultLogFormat = logFormat; + createDefaultLogger(); +} + +void createDefaultLogger() { + logger = makeDefaultLogger(); +} + +} diff --git a/src/libmain/loggers.hh b/src/libmain/loggers.hh new file mode 100644 index 000000000..f50cbb682 --- /dev/null +++ b/src/libmain/loggers.hh @@ -0,0 +1,19 @@ +#pragma once + +#include "types.hh" + +namespace nix { + +enum class LogFormat { + raw, + internalJson, + bar, + barWithLogs, +}; + +void setLogFormat(const string &logFormatStr); +void setLogFormat(const LogFormat &logFormat); + +void createDefaultLogger(); + +} diff --git a/src/libutil/logging.cc b/src/libutil/logging.cc index 3cc4ef8f1..6aec16e58 100644 --- a/src/libutil/logging.cc +++ b/src/libutil/logging.cc @@ -18,7 +18,7 @@ void setCurActivity(const ActivityId activityId) curActivity = activityId; } -Logger * logger = makeDefaultLogger(); +Logger * logger = makeSimpleLogger(); void Logger::warn(const std::string & msg) { @@ -94,7 +94,7 @@ void writeToStderr(const string & s) } } -Logger * makeDefaultLogger() +Logger * makeSimpleLogger() { return new SimpleLogger(); } diff --git a/src/libutil/logging.hh b/src/libutil/logging.hh index 18c24d508..e319790fc 100644 --- a/src/libutil/logging.hh +++ b/src/libutil/logging.hh @@ -63,6 +63,8 @@ public: virtual ~Logger() { } + virtual void stop() { }; + virtual void log(Verbosity lvl, const FormatOrString & fs) = 0; void log(const FormatOrString & fs) @@ -141,7 +143,7 @@ struct PushActivity extern Logger * logger; -Logger * makeDefaultLogger(); +Logger * makeSimpleLogger(); Logger * makeJSONLogger(Logger & prevLogger); diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 71db92d77..e0a99152b 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -989,7 +989,7 @@ pid_t startProcess(std::function fun, const ProcessOptions & options) { auto wrapper = [&]() { if (!options.allowVfork) - logger = makeDefaultLogger(); + logger = makeSimpleLogger(); try { #if __linux__ if (options.dieWithParent && prctl(PR_SET_PDEATHSIG, SIGKILL) == -1) diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc index 0a058a31b..8649de5e9 100755 --- a/src/nix-build/nix-build.cc +++ b/src/nix-build/nix-build.cc @@ -472,6 +472,8 @@ static void _main(int argc, char * * argv) restoreSignals(); + logger->stop(); + execvp(shell->c_str(), argPtrs.data()); throw SysError("executing shell '%s'", *shell); @@ -521,6 +523,8 @@ static void _main(int argc, char * * argv) if (auto store2 = store.dynamic_pointer_cast()) store2->addPermRoot(store->parseStorePath(symlink.second), absPath(symlink.first), true); + logger->stop(); + for (auto & path : outPaths) std::cout << path << '\n'; } diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index d62febaff..f7b04eb2b 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -1446,6 +1446,8 @@ static int _main(int argc, char * * argv) globals.state->printStats(); + logger->stop(); + return 0; } } diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc index 3a3060ad8..708591b14 100644 --- a/src/nix-store/nix-store.cc +++ b/src/nix-store/nix-store.cc @@ -1098,6 +1098,8 @@ static int _main(int argc, char * * argv) op(opFlags, opArgs); + logger->stop(); + return 0; } } diff --git a/src/nix/main.cc b/src/nix/main.cc index 1120ba5ef..203901168 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -10,6 +10,7 @@ #include "progress-bar.hh" #include "filetransfer.hh" #include "finally.hh" +#include "loggers.hh" #include #include @@ -90,7 +91,7 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs .longName = "print-build-logs", .shortName = 'L', .description = "print full build logs on stderr", - .handler = {&printBuildLogs, true}, + .handler = {[&]() {setLogFormat(LogFormat::barWithLogs); }}, }); addFlag({ @@ -165,6 +166,10 @@ void mainWrapped(int argc, char * * argv) verbosity = lvlWarn; settings.verboseBuild = false; + setLogFormat("bar"); + + Finally f([] { logger->stop(); }); + NixArgs args; args.parseCmdline(argvToStrings(argc, argv)); @@ -178,10 +183,6 @@ void mainWrapped(int argc, char * * argv) && args.command->first != "upgrade-nix") settings.requireExperimentalFeature("nix-command"); - Finally f([]() { stopProgressBar(); }); - - startProgressBar(args.printBuildLogs); - if (args.useNet && !haveInternet()) { warn("you don't have Internet access; disabling some network-dependent features"); args.useNet = false; diff --git a/src/nix/progress-bar.cc b/src/nix/progress-bar.cc index c67701098..828541bfe 100644 --- a/src/nix/progress-bar.cc +++ b/src/nix/progress-bar.cc @@ -106,7 +106,7 @@ public: updateThread.join(); } - void stop() + void stop() override { auto state(state_.lock()); if (!state->active) return; @@ -457,11 +457,17 @@ public: } }; +Logger *makeProgressBar(bool printBuildLogs) +{ + return new ProgressBar( + printBuildLogs, + isatty(STDERR_FILENO) && getEnv("TERM").value_or("dumb") != "dumb" + ); +} + void startProgressBar(bool printBuildLogs) { - logger = new ProgressBar( - printBuildLogs, - isatty(STDERR_FILENO) && getEnv("TERM").value_or("dumb") != "dumb"); + logger = makeProgressBar(printBuildLogs); } void stopProgressBar() diff --git a/src/nix/progress-bar.hh b/src/nix/progress-bar.hh index 4d61175c2..60d0a2076 100644 --- a/src/nix/progress-bar.hh +++ b/src/nix/progress-bar.hh @@ -4,6 +4,8 @@ namespace nix { +Logger* makeProgressBar(bool printBuildLogs = false); + void startProgressBar(bool printBuildLogs = false); void stopProgressBar(); From 2c4de6af1033367168320f43b0f04062bdac9234 Mon Sep 17 00:00:00 2001 From: zimbatm Date: Thu, 26 Sep 2019 16:55:51 +0000 Subject: [PATCH 09/62] add documentation --- doc/manual/command-ref/opt-common-syn.xml | 6 ++++- doc/manual/command-ref/opt-common.xml | 31 +++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/doc/manual/command-ref/opt-common-syn.xml b/doc/manual/command-ref/opt-common-syn.xml index b610b54b9..2660e3bb1 100644 --- a/doc/manual/command-ref/opt-common-syn.xml +++ b/doc/manual/command-ref/opt-common-syn.xml @@ -1,5 +1,5 @@ - + @@ -11,6 +11,10 @@ + + + format + diff --git a/doc/manual/command-ref/opt-common.xml b/doc/manual/command-ref/opt-common.xml index 0383bfaed..a68eef1d0 100644 --- a/doc/manual/command-ref/opt-common.xml +++ b/doc/manual/command-ref/opt-common.xml @@ -92,6 +92,37 @@ + format + + + + This option can be used to change the output of the log format, with + format being one of: + + + + raw + This is the raw format, as outputted by nix-build. + + + internal-json + Outputs the logs in a structured manner. NOTE: the json schema is not guarantees to be stable between releases. + + + bar + Only display a progress bar during the builds. + + + bar-with-logs + Display the raw logs, with the progress bar at the bottom. + + + + + + + + / By default, output written by builders to standard From 4983401440e1c46d6c576bc36ac86169bd296f9f Mon Sep 17 00:00:00 2001 From: regnat Date: Fri, 5 Jun 2020 18:20:11 +0200 Subject: [PATCH 10/62] Unify the printing of the logs between bar-with-logs and raw Make the printing of the build logs systematically go through the logger, and replicate the behavior of `no-build-output` by having two different loggers (one that prints the build logs and one that doesn't) --- src/libmain/loggers.cc | 6 +++++- src/libmain/loggers.hh | 1 + src/libmain/shared.cc | 3 ++- src/libstore/build.cc | 17 ++++------------- src/libutil/logging.cc | 30 ++++++++++++++++++++++++++---- src/libutil/logging.hh | 5 ++++- src/nix/progress-bar.cc | 4 ++++ 7 files changed, 46 insertions(+), 20 deletions(-) diff --git a/src/libmain/loggers.cc b/src/libmain/loggers.cc index d3d5b104b..b81096931 100644 --- a/src/libmain/loggers.cc +++ b/src/libmain/loggers.cc @@ -8,6 +8,8 @@ LogFormat defaultLogFormat = LogFormat::raw; LogFormat parseLogFormat(const string &logFormatStr) { if (logFormatStr == "raw") return LogFormat::raw; + else if (logFormatStr == "raw-with-logs") + return LogFormat::rawWithLogs; else if (logFormatStr == "internal-json") return LogFormat::internalJson; else if (logFormatStr == "bar") @@ -21,7 +23,9 @@ LogFormat parseLogFormat(const string &logFormatStr) { Logger *makeDefaultLogger() { switch (defaultLogFormat) { case LogFormat::raw: - return makeSimpleLogger(); + return makeSimpleLogger(false); + case LogFormat::rawWithLogs: + return makeSimpleLogger(true); case LogFormat::internalJson: return makeJSONLogger(*makeSimpleLogger()); case LogFormat::bar: diff --git a/src/libmain/loggers.hh b/src/libmain/loggers.hh index f50cbb682..f9ba5ee5e 100644 --- a/src/libmain/loggers.hh +++ b/src/libmain/loggers.hh @@ -6,6 +6,7 @@ namespace nix { enum class LogFormat { raw, + rawWithLogs, internalJson, bar, barWithLogs, diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc index 70d1f0186..3bbb5cf93 100644 --- a/src/libmain/shared.cc +++ b/src/libmain/shared.cc @@ -2,6 +2,7 @@ #include "shared.hh" #include "store-api.hh" #include "util.hh" +#include "loggers.hh" #include #include @@ -169,7 +170,7 @@ LegacyArgs::LegacyArgs(const std::string & programName, .longName = "no-build-output", .shortName = 'Q', .description = "do not show build output", - .handler = {&settings.verboseBuild, false}, + .handler = {[&]() {setLogFormat(LogFormat::raw); }}, }); addFlag({ diff --git a/src/libstore/build.cc b/src/libstore/build.cc index f5c132a83..2d022093c 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -1642,7 +1642,7 @@ void DerivationGoal::buildDone() worker.store.printStorePath(drvPath), statusToString(status)); - if (!settings.verboseBuild && !logTail.empty()) { + if (!logger->isVerbose() && !logTail.empty()) { msg += (format("; last %d log lines:") % logTail.size()).str(); for (auto & line : logTail) msg += "\n " + line; @@ -1691,11 +1691,7 @@ void DerivationGoal::buildDone() } void flushLine() { - if (settings.verboseBuild) { - printError("post-build-hook: " + currentLine); - } else { - act.result(resPostBuildLogLine, currentLine); - } + act.result(resPostBuildLogLine, currentLine); currentLine.clear(); } @@ -4155,13 +4151,8 @@ void DerivationGoal::flushLine() ; else { - if (settings.verboseBuild && - (settings.printRepeatedBuilds || curRound == 1)) - printError(currentLogLine); - else { - logTail.push_back(currentLogLine); - if (logTail.size() > settings.logLines) logTail.pop_front(); - } + logTail.push_back(currentLogLine); + if (logTail.size() > settings.logLines) logTail.pop_front(); act->result(resBuildLogLine, currentLogLine); } diff --git a/src/libutil/logging.cc b/src/libutil/logging.cc index 6aec16e58..15cbc1589 100644 --- a/src/libutil/logging.cc +++ b/src/libutil/logging.cc @@ -18,7 +18,7 @@ void setCurActivity(const ActivityId activityId) curActivity = activityId; } -Logger * logger = makeSimpleLogger(); +Logger * logger = makeSimpleLogger(true); void Logger::warn(const std::string & msg) { @@ -35,13 +35,19 @@ class SimpleLogger : public Logger public: bool systemd, tty; + bool printBuildLogs; - SimpleLogger() + SimpleLogger(bool printBuildLogs) + : printBuildLogs(printBuildLogs) { systemd = getEnv("IN_SYSTEMD") == "1"; tty = isatty(STDERR_FILENO); } + bool isVerbose() override { + return printBuildLogs; + } + void log(Verbosity lvl, const FormatOrString & fs) override { if (lvl > verbosity) return; @@ -70,6 +76,18 @@ public: if (lvl <= verbosity && !s.empty()) log(lvl, s + "..."); } + + void result(ActivityId act, ResultType type, const Fields & fields) override + { + if (type == resBuildLogLine && printBuildLogs) { + auto lastLine = fields[0].s; + printError(lastLine); + } + else if (type == resPostBuildLogLine && printBuildLogs) { + auto lastLine = fields[0].s; + printError("post-build-hook: " + lastLine); + } + } }; Verbosity verbosity = lvlInfo; @@ -94,9 +112,9 @@ void writeToStderr(const string & s) } } -Logger * makeSimpleLogger() +Logger * makeSimpleLogger(bool printBuildLogs) { - return new SimpleLogger(); + return new SimpleLogger(printBuildLogs); } std::atomic nextId{(uint64_t) getpid() << 32}; @@ -114,6 +132,10 @@ struct JSONLogger : Logger JSONLogger(Logger & prevLogger) : prevLogger(prevLogger) { } + bool isVerbose() override { + return true; + } + void addFields(nlohmann::json & json, const Fields & fields) { if (fields.empty()) return; diff --git a/src/libutil/logging.hh b/src/libutil/logging.hh index e319790fc..e3d91e01f 100644 --- a/src/libutil/logging.hh +++ b/src/libutil/logging.hh @@ -65,6 +65,9 @@ public: virtual void stop() { }; + // Whether the logger prints the whole build log + virtual bool isVerbose() { return false; } + virtual void log(Verbosity lvl, const FormatOrString & fs) = 0; void log(const FormatOrString & fs) @@ -143,7 +146,7 @@ struct PushActivity extern Logger * logger; -Logger * makeSimpleLogger(); +Logger * makeSimpleLogger(bool printBuildLogs = true); Logger * makeJSONLogger(Logger & prevLogger); diff --git a/src/nix/progress-bar.cc b/src/nix/progress-bar.cc index 828541bfe..c9ba89714 100644 --- a/src/nix/progress-bar.cc +++ b/src/nix/progress-bar.cc @@ -119,6 +119,10 @@ public: quitCV.notify_one(); } + bool isVerbose() override { + return printBuildLogs; + } + void log(Verbosity lvl, const FormatOrString & fs) override { auto state(state_.lock()); From f6ac888d3e1897f37a8accb9c46ebdf4fc2ca204 Mon Sep 17 00:00:00 2001 From: regnat Date: Mon, 8 Jun 2020 10:01:14 +0200 Subject: [PATCH 11/62] Actually test nix-env with a remote store The `remote-store` test loads the `user-env` one to test nix-env when using the daemon, but actually does it incorrectly because every test starts (in `common.sh`) by resetting the value of `NIX_REMOTE`, meaning that the `user-env` test will never use the daemon. Fix this by setting `NIX_REMOTE_` before sourcing `user-env.sh` in the `remote-store` test, so that `NIX_REMOTE` is correctly set inside the test --- tests/remote-store.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/remote-store.sh b/tests/remote-store.sh index 77437658e..4cc73465a 100644 --- a/tests/remote-store.sh +++ b/tests/remote-store.sh @@ -4,7 +4,7 @@ clearStore startDaemon -storeCleared=1 $SHELL ./user-envs.sh +storeCleared=1 NIX_REMOTE_=$NIX_REMOTE $SHELL ./user-envs.sh nix-store --dump-db > $TEST_ROOT/d1 NIX_REMOTE= nix-store --dump-db > $TEST_ROOT/d2 From c27f92698bbbb99df3c4403db6590276318940a0 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 8 Jun 2020 13:24:01 +0200 Subject: [PATCH 12/62] Style fixes --- src/libmain/common-args.cc | 4 ++-- src/libmain/loggers.cc | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/libmain/common-args.cc b/src/libmain/common-args.cc index a0cccceb4..051668e53 100644 --- a/src/libmain/common-args.cc +++ b/src/libmain/common-args.cc @@ -41,8 +41,8 @@ MixCommonArgs::MixCommonArgs(const string & programName) addFlag({ .longName = "log-format", - .description = "Format of the logs. One of \"raw\", \"internal-json\", \"bar\" " - "or \"bar-with-logs\".", + .description = "format of log output; \"raw\", \"internal-json\", \"bar\" " + "or \"bar-with-logs\"", .labels = {"format"}, .handler = {[](std::string format) { setLogFormat(format); }}, }); diff --git a/src/libmain/loggers.cc b/src/libmain/loggers.cc index b81096931..ee3836382 100644 --- a/src/libmain/loggers.cc +++ b/src/libmain/loggers.cc @@ -16,8 +16,7 @@ LogFormat parseLogFormat(const string &logFormatStr) { return LogFormat::bar; else if (logFormatStr == "bar-with-logs") return LogFormat::barWithLogs; - throw Error(format("option 'log-format' has an invalid value '%s'") % - logFormatStr); + throw Error("option 'log-format' has an invalid value '%s'", logFormatStr); } Logger *makeDefaultLogger() { From 801112de1af8e519e29e1e1c678f97de45a8c49d Mon Sep 17 00:00:00 2001 From: regnat Date: Mon, 8 Jun 2020 17:16:52 +0200 Subject: [PATCH 13/62] Move progress-bar.cc to libmain Needed so that we can include it as a logger in loggers.cc without adding a dependency on nix This also requires moving names.hh to libutil to prevent a circular dependency between libmain and libexpr --- src/libmain/loggers.cc | 2 +- src/{nix => libmain}/progress-bar.cc | 0 src/{nix => libmain}/progress-bar.hh | 0 src/{libexpr => libutil}/names.cc | 0 src/{libexpr => libutil}/names.hh | 0 src/nix-prefetch-url/nix-prefetch-url.cc | 2 +- 6 files changed, 2 insertions(+), 2 deletions(-) rename src/{nix => libmain}/progress-bar.cc (100%) rename src/{nix => libmain}/progress-bar.hh (100%) rename src/{libexpr => libutil}/names.cc (100%) rename src/{libexpr => libutil}/names.hh (100%) diff --git a/src/libmain/loggers.cc b/src/libmain/loggers.cc index ee3836382..41f0b35fb 100644 --- a/src/libmain/loggers.cc +++ b/src/libmain/loggers.cc @@ -1,5 +1,5 @@ #include "loggers.hh" -#include "../nix/progress-bar.hh" +#include "progress-bar.hh" namespace nix { diff --git a/src/nix/progress-bar.cc b/src/libmain/progress-bar.cc similarity index 100% rename from src/nix/progress-bar.cc rename to src/libmain/progress-bar.cc diff --git a/src/nix/progress-bar.hh b/src/libmain/progress-bar.hh similarity index 100% rename from src/nix/progress-bar.hh rename to src/libmain/progress-bar.hh diff --git a/src/libexpr/names.cc b/src/libutil/names.cc similarity index 100% rename from src/libexpr/names.cc rename to src/libutil/names.cc diff --git a/src/libexpr/names.hh b/src/libutil/names.hh similarity index 100% rename from src/libexpr/names.hh rename to src/libutil/names.hh diff --git a/src/nix-prefetch-url/nix-prefetch-url.cc b/src/nix-prefetch-url/nix-prefetch-url.cc index 5a686c8cd..b645bdc1b 100644 --- a/src/nix-prefetch-url/nix-prefetch-url.cc +++ b/src/nix-prefetch-url/nix-prefetch-url.cc @@ -8,7 +8,7 @@ #include "attr-path.hh" #include "finally.hh" #include "../nix/legacy.hh" -#include "../nix/progress-bar.hh" +#include "progress-bar.hh" #include "tarfile.hh" #include From 762273f1fd48b2b2f2bbedca65abfd4c07b5af05 Mon Sep 17 00:00:00 2001 From: Matthew Bauer Date: Tue, 9 Jun 2020 01:23:37 -0500 Subject: [PATCH 14/62] Allow empty hash in derivations follow up of https://github.com/NixOS/nix/pull/3544 This allows hash="" so that it can be used for debugging purposes. For instance, this gives you an error message like: warning: found empty hash, assuming you wanted 'sha256:0000000000000000000000000000000000000000000000000000' hash mismatch in fixed-output derivation '/nix/store/asx6qw1r1xk6iak6y6jph4n58h4hdmbm-nix': wanted: sha256:0000000000000000000000000000000000000000000000000000 got: sha256:0fpfhipl9v1mfzw2ffmxiyyzqwlkvww22bh9wcy4qrfslb4jm429 --- src/libexpr/primops.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index d458ab272..de04fd2be 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -719,7 +719,13 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * * throw Error(format("multiple outputs are not supported in fixed-output derivations, at %1%") % posDrvName); HashType ht = outputHashAlgo.empty() ? htUnknown : parseHashType(outputHashAlgo); - Hash h(*outputHash, ht); + + Hash h; + if (outputHash->empty()) { + h = Hash(ht); + printError("warning: found empty hash, assuming you wanted '%s'", h.to_string()); + } else + h = Hash(*outputHash, ht); auto outPath = state.store->makeFixedOutputPath(ingestionMethod, h, drvName); if (!jsonObject) drv.env["out"] = state.store->printStorePath(outPath); From 19aa892f2064d437d32a3c12758d6a623b7ae8e5 Mon Sep 17 00:00:00 2001 From: Matthew Bauer Date: Tue, 9 Jun 2020 11:10:54 -0500 Subject: [PATCH 15/62] Support empty hash in fetchers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fetchTarball, fetchTree, and fetchGit all have *optional* hash attrs. This means that we need to be careful with what we allow to avoid accidentally making these defaults. When ‘hash = ""’ we assume the empty hash is wanted. --- src/libexpr/primops.cc | 11 ++++++++--- src/libexpr/primops/fetchTree.cc | 11 ++++++++--- src/libfetchers/fetchers.cc | 11 ++++++++--- src/libfetchers/tarball.cc | 11 ++++++++--- 4 files changed, 32 insertions(+), 12 deletions(-) diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index de04fd2be..df3d4a459 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -1131,9 +1131,14 @@ static void prim_path(EvalState & state, const Pos & pos, Value * * args, Value filterFun = attr.value; } else if (n == "recursive") method = FileIngestionMethod { state.forceBool(*attr.value, *attr.pos) }; - else if (n == "sha256") - expectedHash = Hash(state.forceStringNoCtx(*attr.value, *attr.pos), htSHA256); - else + else if (n == "sha256") { + auto hashStr = state.forceStringNoCtx(*attr.value, *attr.pos); + if (hashStr == "") { + expectedHash = Hash(htSHA256); + printError("warning: found empty hash, assuming you wanted '%s'", expectedHash.to_string()); + } else + expectedHash = Hash(hashStr, htSHA256); + } else throw EvalError(format("unsupported argument '%1%' to 'addPath', at %2%") % attr.name % *attr.pos); } if (path.empty()) diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc index c5a0d9886..745f65adf 100644 --- a/src/libexpr/primops/fetchTree.cc +++ b/src/libexpr/primops/fetchTree.cc @@ -102,9 +102,14 @@ static void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v, string n(attr.name); if (n == "url") url = state.forceStringNoCtx(*attr.value, *attr.pos); - else if (n == "sha256") - expectedHash = Hash(state.forceStringNoCtx(*attr.value, *attr.pos), htSHA256); - else if (n == "name") + else if (n == "sha256") { + auto hashStr = state.forceStringNoCtx(*attr.value, *attr.pos); + if (hashStr == "") { + expectedHash = Hash(htSHA256); + printError("warning: found empty hash, assuming you wanted '%s'", expectedHash->to_string()); + } else + expectedHash = Hash(hashStr, htSHA256); + } else if (n == "name") name = state.forceStringNoCtx(*attr.value, *attr.pos); else throw EvalError("unsupported argument '%s' to '%s', at %s", diff --git a/src/libfetchers/fetchers.cc b/src/libfetchers/fetchers.cc index 94ac30e38..988a8dc69 100644 --- a/src/libfetchers/fetchers.cc +++ b/src/libfetchers/fetchers.cc @@ -34,9 +34,14 @@ std::unique_ptr inputFromAttrs(const Attrs & attrs) for (auto & inputScheme : *inputSchemes) { auto res = inputScheme->inputFromAttrs(attrs2); if (res) { - if (auto narHash = maybeGetStrAttr(attrs, "narHash")) - // FIXME: require SRI hash. - res->narHash = Hash(*narHash); + if (auto narHash = maybeGetStrAttr(attrs, "narHash")) { + if (narHash->empty()) { + res->narHash = Hash(htUnknown); + printError("warning: found empty hash, assuming you wanted '%s'", res->narHash->to_string()); + } else + // FIXME: require SRI hash. + res->narHash = Hash(*narHash); + } return res; } } diff --git a/src/libfetchers/tarball.cc b/src/libfetchers/tarball.cc index b6e57379b..e4dafec0b 100644 --- a/src/libfetchers/tarball.cc +++ b/src/libfetchers/tarball.cc @@ -263,9 +263,14 @@ struct TarballInputScheme : InputScheme throw Error("unsupported tarball input attribute '%s'", name); auto input = std::make_unique(parseURL(getStrAttr(attrs, "url"))); - if (auto hash = maybeGetStrAttr(attrs, "hash")) - // FIXME: require SRI hash. - input->hash = Hash(*hash); + if (auto hash = maybeGetStrAttr(attrs, "hash")) { + if (hash->empty()) { + input->hash = Hash(htUnknown); + printError("warning: found empty hash, assuming you wanted '%s'", input->hash->to_string()); + } else + // FIXME: require SRI hash. + input->hash = Hash(*hash); + } return input; } From b2c8061b44b01a39d953d75db30e39bd8f300021 Mon Sep 17 00:00:00 2001 From: Matthew Bauer Date: Tue, 9 Jun 2020 16:53:53 -0500 Subject: [PATCH 16/62] Disable extra-platforms = i686-linux on wsl1 (#3676) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit WSL1 doesn’t support i686-linux emulation, see https://github.com/microsoft/wsl/issues/2468 --- 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 da95fd3ae..2fbcafff8 100644 --- a/src/libstore/globals.hh +++ b/src/libstore/globals.hh @@ -271,7 +271,7 @@ public: "listed in 'trusted-public-keys'."}; Setting extraPlatforms{this, - std::string{SYSTEM} == "x86_64-linux" ? StringSet{"i686-linux"} : StringSet{}, + std::string{SYSTEM} == "x86_64-linux" && !isWSL1() ? StringSet{"i686-linux"} : StringSet{}, "extra-platforms", "Additional platforms that can be built on the local system. " "These may be supported natively (e.g. armv7 on some aarch64 CPUs " From 7eca8a16eaf74bc15a816e24005a65e5480d2a79 Mon Sep 17 00:00:00 2001 From: Matthew Bauer Date: Tue, 9 Jun 2020 23:35:38 -0500 Subject: [PATCH 17/62] Prelink static libraries into an object file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This combines the *.o into a big .o producing one translation unit. This preserve our unused static initializers, as specified in the C++ standard: If no variable or function is odr-used from a given translation unit, the non-local variables defined in that translation unit may never be initialized (this models the behavior of an on-demand dynamic library). Note that this is very similar to how the --whole-archive flag works. One advantage of this is that users of the final .a library don’t have to worry about specifying --whole-archive, or that we have unused static initializers at all! --- mk/libraries.mk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mk/libraries.mk b/mk/libraries.mk index 307e29b9d..e6ef2e3ec 100644 --- a/mk/libraries.mk +++ b/mk/libraries.mk @@ -125,7 +125,8 @@ define build-library $(1)_PATH := $$(_d)/$$($(1)_NAME).a $$($(1)_PATH): $$($(1)_OBJS) | $$(_d)/ - $(trace-ar) $(AR) crs $$@ $$? + $(trace-ld) $(LD) -Ur -o $$(_d)/$$($(1)_NAME).o $$? + $(trace-ar) $(AR) crs $$@ $$(_d)/$$($(1)_NAME).o $(1)_LDFLAGS_USE += $$($(1)_PATH) $$($(1)_LDFLAGS) From 4750d98bbd7c233e993b1ed66dd5573e6bdf543c Mon Sep 17 00:00:00 2001 From: Tobias Pflug Date: Mon, 8 Jun 2020 17:39:46 +0200 Subject: [PATCH 18/62] Add tests for pool.hh --- src/libutil/tests/pool.cc | 127 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 src/libutil/tests/pool.cc diff --git a/src/libutil/tests/pool.cc b/src/libutil/tests/pool.cc new file mode 100644 index 000000000..127e42dda --- /dev/null +++ b/src/libutil/tests/pool.cc @@ -0,0 +1,127 @@ +#include "pool.hh" +#include + +namespace nix { + + struct TestResource + { + + TestResource() { + static int counter = 0; + num = counter++; + } + + int dummyValue = 1; + bool good = true; + int num; + }; + + /* ---------------------------------------------------------------------------- + * Pool + * --------------------------------------------------------------------------*/ + + TEST(Pool, freshPoolHasZeroCountAndSpecifiedCapacity) { + auto isGood = [](const ref & r) { return r->good; }; + auto createResource = []() { return make_ref(); }; + + Pool pool = Pool((size_t)1, createResource, isGood); + + ASSERT_EQ(pool.count(), 0); + ASSERT_EQ(pool.capacity(), 1); + } + + TEST(Pool, freshPoolCanGetAResource) { + auto isGood = [](const ref & r) { return r->good; }; + auto createResource = []() { return make_ref(); }; + + Pool pool = Pool((size_t)1, createResource, isGood); + ASSERT_EQ(pool.count(), 0); + + TestResource r = *(pool.get()); + + ASSERT_EQ(pool.count(), 1); + ASSERT_EQ(pool.capacity(), 1); + ASSERT_EQ(r.dummyValue, 1); + ASSERT_EQ(r.good, true); + } + + TEST(Pool, capacityCanBeIncremented) { + auto isGood = [](const ref & r) { return r->good; }; + auto createResource = []() { return make_ref(); }; + + Pool pool = Pool((size_t)1, createResource, isGood); + ASSERT_EQ(pool.capacity(), 1); + pool.incCapacity(); + ASSERT_EQ(pool.capacity(), 2); + } + + TEST(Pool, capacityCanBeDecremented) { + auto isGood = [](const ref & r) { return r->good; }; + auto createResource = []() { return make_ref(); }; + + Pool pool = Pool((size_t)1, createResource, isGood); + ASSERT_EQ(pool.capacity(), 1); + pool.decCapacity(); + ASSERT_EQ(pool.capacity(), 0); + } + + TEST(Pool, flushBadDropsOutOfScopeResources) { + auto isGood = [](const ref & r) { return false; }; + auto createResource = []() { return make_ref(); }; + + Pool pool = Pool((size_t)1, createResource, isGood); + + { + auto _r = pool.get(); + ASSERT_EQ(pool.count(), 1); + } + + pool.flushBad(); + ASSERT_EQ(pool.count(), 0); + } + + // Test that the resources we allocate are being reused when they are still good. + TEST(Pool, reuseResource) { + auto isGood = [](const ref & r) { return true; }; + auto createResource = []() { return make_ref(); }; + + Pool pool = Pool((size_t)1, createResource, isGood); + + // Compare the instance counter between the two handles. We expect them to be equal + // as the pool should hand out the same (still) good one again. + int counter = -1; + { + Pool::Handle h = pool.get(); + counter = h->num; + } // the first handle goes out of scope + + { // the second handle should contain the same resource (with the same counter value) + Pool::Handle h = pool.get(); + ASSERT_EQ(h->num, counter); + } + } + + // Test that the resources we allocate are being thrown away when they are no longer good. + TEST(Pool, badResourceIsNotReused) { + auto isGood = [](const ref & r) { return false; }; + auto createResource = []() { return make_ref(); }; + + Pool pool = Pool((size_t)1, createResource, isGood); + + // Compare the instance counter between the two handles. We expect them + // to *not* be equal as the pool should hand out a new instance after + // the first one was returned. + int counter = -1; + { + Pool::Handle h = pool.get(); + counter = h->num; + } // the first handle goes out of scope + + { + // the second handle should contain a different resource (with a + //different counter value) + Pool::Handle h = pool.get(); + ASSERT_NE(h->num, counter); + } + } +} From 8bd892117a324c22803366b872bfe7ed783b34eb Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 11 Jun 2020 15:39:08 +0200 Subject: [PATCH 19/62] Style fixes --- src/libmain/loggers.cc | 8 ++++---- src/libmain/loggers.hh | 4 ++-- src/libmain/progress-bar.cc | 2 +- src/libmain/progress-bar.hh | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/libmain/loggers.cc b/src/libmain/loggers.cc index 41f0b35fb..350f90266 100644 --- a/src/libmain/loggers.cc +++ b/src/libmain/loggers.cc @@ -5,7 +5,7 @@ namespace nix { LogFormat defaultLogFormat = LogFormat::raw; -LogFormat parseLogFormat(const string &logFormatStr) { +LogFormat parseLogFormat(const std::string & logFormatStr) { if (logFormatStr == "raw") return LogFormat::raw; else if (logFormatStr == "raw-with-logs") @@ -19,7 +19,7 @@ LogFormat parseLogFormat(const string &logFormatStr) { throw Error("option 'log-format' has an invalid value '%s'", logFormatStr); } -Logger *makeDefaultLogger() { +Logger * makeDefaultLogger() { switch (defaultLogFormat) { case LogFormat::raw: return makeSimpleLogger(false); @@ -34,11 +34,11 @@ Logger *makeDefaultLogger() { } } -void setLogFormat(const string &logFormatStr) { +void setLogFormat(const std::string & logFormatStr) { setLogFormat(parseLogFormat(logFormatStr)); } -void setLogFormat(const LogFormat &logFormat) { +void setLogFormat(const LogFormat & logFormat) { defaultLogFormat = logFormat; createDefaultLogger(); } diff --git a/src/libmain/loggers.hh b/src/libmain/loggers.hh index f9ba5ee5e..cada03110 100644 --- a/src/libmain/loggers.hh +++ b/src/libmain/loggers.hh @@ -12,8 +12,8 @@ enum class LogFormat { barWithLogs, }; -void setLogFormat(const string &logFormatStr); -void setLogFormat(const LogFormat &logFormat); +void setLogFormat(const std::string & logFormatStr); +void setLogFormat(const LogFormat & logFormat); void createDefaultLogger(); diff --git a/src/libmain/progress-bar.cc b/src/libmain/progress-bar.cc index c9ba89714..b287de8a3 100644 --- a/src/libmain/progress-bar.cc +++ b/src/libmain/progress-bar.cc @@ -461,7 +461,7 @@ public: } }; -Logger *makeProgressBar(bool printBuildLogs) +Logger * makeProgressBar(bool printBuildLogs) { return new ProgressBar( printBuildLogs, diff --git a/src/libmain/progress-bar.hh b/src/libmain/progress-bar.hh index 60d0a2076..7f0dafecf 100644 --- a/src/libmain/progress-bar.hh +++ b/src/libmain/progress-bar.hh @@ -4,7 +4,7 @@ namespace nix { -Logger* makeProgressBar(bool printBuildLogs = false); +Logger * makeProgressBar(bool printBuildLogs = false); void startProgressBar(bool printBuildLogs = false); From 95eb0640620f0704b4ded6ed6c7509024c00273e Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 11 Jun 2020 15:39:30 +0200 Subject: [PATCH 20/62] Shut up warning --- src/libmain/loggers.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libmain/loggers.cc b/src/libmain/loggers.cc index 350f90266..c44bb6408 100644 --- a/src/libmain/loggers.cc +++ b/src/libmain/loggers.cc @@ -31,6 +31,8 @@ Logger * makeDefaultLogger() { return makeProgressBar(); case LogFormat::barWithLogs: return makeProgressBar(true); + default: + abort(); } } From dd9bb11d0d38139bb32411170403171c4c92f8cf Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 11 Jun 2020 15:42:18 +0200 Subject: [PATCH 21/62] Move names.{cc,hh} to libstore --- src/{libutil => libstore}/names.cc | 0 src/{libutil => libstore}/names.hh | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/{libutil => libstore}/names.cc (100%) rename src/{libutil => libstore}/names.hh (100%) diff --git a/src/libutil/names.cc b/src/libstore/names.cc similarity index 100% rename from src/libutil/names.cc rename to src/libstore/names.cc diff --git a/src/libutil/names.hh b/src/libstore/names.hh similarity index 100% rename from src/libutil/names.hh rename to src/libstore/names.hh From 045b07200c77bf1fe19c0a986aafb531e7e1ba54 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 12 Jun 2020 12:46:33 +0200 Subject: [PATCH 22/62] Remove Store::queryDerivationOutputNames() This function was used in only one place, where it could easily be replaced by readDerivation() since it's not performance-critical. (This function appears to have been modelled after queryDerivationOutputs(), which exists only to make the garbage collector faster.) --- src/libexpr/primops.cc | 2 +- src/libstore/build.cc | 3 --- src/libstore/daemon.cc | 3 +-- src/libstore/derivations.cc | 9 +++++++++ src/libstore/derivations.hh | 2 ++ src/libstore/local-store.cc | 17 ----------------- src/libstore/local-store.hh | 2 -- src/libstore/remote-store.cc | 9 --------- src/libstore/remote-store.hh | 2 -- src/libstore/store-api.hh | 4 ---- src/libstore/worker-protocol.hh | 2 +- 11 files changed, 14 insertions(+), 41 deletions(-) diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index d458ab272..9efb8eae5 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -688,7 +688,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * * for (auto & j : refs) { drv.inputSrcs.insert(j.clone()); if (j.isDerivation()) - drv.inputDrvs[j.clone()] = state.store->queryDerivationOutputNames(j); + drv.inputDrvs[j.clone()] = readDerivation(*state.store, state.store->toRealPath(j)).outputNames(); } } diff --git a/src/libstore/build.cc b/src/libstore/build.cc index bdf03ff94..3ab6220e3 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -2723,9 +2723,6 @@ struct RestrictedStore : public LocalFSStore StorePathSet queryDerivationOutputs(const StorePath & path) override { throw Error("queryDerivationOutputs"); } - StringSet queryDerivationOutputNames(const StorePath & path) override - { throw Error("queryDerivationOutputNames"); } - std::optional queryPathFromHashPart(const std::string & hashPart) override { throw Error("queryPathFromHashPart"); } diff --git a/src/libstore/daemon.cc b/src/libstore/daemon.cc index 5cff170dd..dc2015579 100644 --- a/src/libstore/daemon.cc +++ b/src/libstore/daemon.cc @@ -329,8 +329,7 @@ static void performOp(TunnelLogger * logger, ref store, case wopQueryDerivationOutputNames: { auto path = store->parseStorePath(readString(from)); logger->startWork(); - StringSet names; - names = store->queryDerivationOutputNames(path); + auto names = readDerivation(*store, store->toRealPath(path)).outputNames(); logger->stopWork(); to << names; break; diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc index c68e7b16b..6de91ec97 100644 --- a/src/libstore/derivations.cc +++ b/src/libstore/derivations.cc @@ -410,6 +410,15 @@ StorePathSet BasicDerivation::outputPaths() const } +StringSet BasicDerivation::outputNames() const +{ + StringSet names; + for (auto & i : outputs) + names.insert(i.first); + return names; +} + + Source & readDerivation(Source & in, const Store & store, BasicDerivation & drv) { drv.outputs.clear(); diff --git a/src/libstore/derivations.hh b/src/libstore/derivations.hh index b1224b93b..88aed66bf 100644 --- a/src/libstore/derivations.hh +++ b/src/libstore/derivations.hh @@ -58,6 +58,8 @@ struct BasicDerivation /* Return the output paths of a derivation. */ StorePathSet outputPaths() const; + /* Return the output names of a derivation. */ + StringSet outputNames() const; }; struct Derivation : BasicDerivation diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 1c3795eb1..e379db426 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -785,23 +785,6 @@ StorePathSet LocalStore::queryDerivationOutputs(const StorePath & path) } -StringSet LocalStore::queryDerivationOutputNames(const StorePath & path) -{ - return retrySQLite([&]() { - auto state(_state.lock()); - - auto useQueryDerivationOutputs(state->stmtQueryDerivationOutputs.use() - (queryValidPathId(*state, path))); - - StringSet outputNames; - while (useQueryDerivationOutputs.next()) - outputNames.insert(useQueryDerivationOutputs.getStr(0)); - - return outputNames; - }); -} - - std::optional LocalStore::queryPathFromHashPart(const std::string & hashPart) { if (hashPart.size() != storePathHashLen) throw Error("invalid hash part"); diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh index c1e75390c..e17cc45ae 100644 --- a/src/libstore/local-store.hh +++ b/src/libstore/local-store.hh @@ -135,8 +135,6 @@ public: StorePathSet queryDerivationOutputs(const StorePath & path) override; - StringSet queryDerivationOutputNames(const StorePath & path) override; - std::optional queryPathFromHashPart(const std::string & hashPart) override; StorePathSet querySubstitutablePaths(const StorePathSet & paths) override; diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index 5c36693e6..735f59a91 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -418,15 +418,6 @@ StorePathSet RemoteStore::queryDerivationOutputs(const StorePath & path) } -PathSet RemoteStore::queryDerivationOutputNames(const StorePath & path) -{ - auto conn(getConnection()); - conn->to << wopQueryDerivationOutputNames << printStorePath(path); - conn.processStderr(); - return readStrings(conn->from); -} - - std::optional RemoteStore::queryPathFromHashPart(const std::string & hashPart) { auto conn(getConnection()); diff --git a/src/libstore/remote-store.hh b/src/libstore/remote-store.hh index 3c86b4524..80c8e9f11 100644 --- a/src/libstore/remote-store.hh +++ b/src/libstore/remote-store.hh @@ -51,8 +51,6 @@ public: StorePathSet queryDerivationOutputs(const StorePath & path) override; - StringSet queryDerivationOutputNames(const StorePath & path) override; - std::optional queryPathFromHashPart(const std::string & hashPart) override; StorePathSet querySubstitutablePaths(const StorePathSet & paths) override; diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh index b1e25fc7d..5ba17e0bc 100644 --- a/src/libstore/store-api.hh +++ b/src/libstore/store-api.hh @@ -430,10 +430,6 @@ public: virtual StorePathSet queryDerivationOutputs(const StorePath & path) { unsupported("queryDerivationOutputs"); } - /* Query the output names of the derivation denoted by `path'. */ - virtual StringSet queryDerivationOutputNames(const StorePath & path) - { unsupported("queryDerivationOutputNames"); } - /* Query the full store path given the hash part of a valid store path, or empty if the path doesn't exist. */ virtual std::optional queryPathFromHashPart(const std::string & hashPart) = 0; diff --git a/src/libstore/worker-protocol.hh b/src/libstore/worker-protocol.hh index 857d54d99..ac42457fc 100644 --- a/src/libstore/worker-protocol.hh +++ b/src/libstore/worker-protocol.hh @@ -36,7 +36,7 @@ typedef enum { wopClearFailedPaths = 25, wopQueryPathInfo = 26, wopImportPaths = 27, // obsolete - wopQueryDerivationOutputNames = 28, + wopQueryDerivationOutputNames = 28, // obsolete wopQueryPathFromHashPart = 29, wopQuerySubstitutablePathInfos = 30, wopQueryValidPaths = 31, From 9f736dd89d064718a378703a9557de56fdd1a734 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 12 Jun 2020 13:04:52 +0200 Subject: [PATCH 23/62] Add Store::readDerivation() convenience function --- src/build-remote/build-remote.cc | 2 +- src/libexpr/primops.cc | 2 +- src/libstore/daemon.cc | 2 +- src/libstore/derivations.cc | 8 +++++++- src/libstore/local-store.cc | 5 ++--- src/libstore/store-api.hh | 3 +++ src/nix/show-derivation.cc | 6 ++---- 7 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/build-remote/build-remote.cc b/src/build-remote/build-remote.cc index 00340b787..d2ea6c956 100644 --- a/src/build-remote/build-remote.cc +++ b/src/build-remote/build-remote.cc @@ -241,7 +241,7 @@ connected: uploadLock = -1; - BasicDerivation drv(readDerivation(*store, store->realStoreDir + "/" + std::string(drvPath->to_string()))); + auto drv = store->readDerivation(*drvPath); drv.inputSrcs = store->parseStorePathSet(inputs); auto result = sshStore->buildDerivation(*drvPath, drv); diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 9efb8eae5..3a27527a0 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -688,7 +688,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * * for (auto & j : refs) { drv.inputSrcs.insert(j.clone()); if (j.isDerivation()) - drv.inputDrvs[j.clone()] = readDerivation(*state.store, state.store->toRealPath(j)).outputNames(); + drv.inputDrvs[j.clone()] = state.store->readDerivation(j).outputNames(); } } diff --git a/src/libstore/daemon.cc b/src/libstore/daemon.cc index dc2015579..877c70a03 100644 --- a/src/libstore/daemon.cc +++ b/src/libstore/daemon.cc @@ -329,7 +329,7 @@ static void performOp(TunnelLogger * logger, ref store, case wopQueryDerivationOutputNames: { auto path = store->parseStorePath(readString(from)); logger->startWork(); - auto names = readDerivation(*store, store->toRealPath(path)).outputNames(); + auto names = store->readDerivation(path).outputNames(); logger->stopWork(); to << names; break; diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc index 6de91ec97..e268c65ff 100644 --- a/src/libstore/derivations.cc +++ b/src/libstore/derivations.cc @@ -204,6 +204,12 @@ Derivation readDerivation(const Store & store, const Path & drvPath) Derivation Store::derivationFromPath(const StorePath & drvPath) { ensurePath(drvPath); + return readDerivation(drvPath); +} + + +Derivation Store::readDerivation(const StorePath & drvPath) +{ auto accessor = getFSAccessor(); try { return parseDerivation(*this, accessor->readFile(printStorePath(drvPath))); @@ -378,7 +384,7 @@ Hash hashDerivationModulo(Store & store, const Derivation & drv, bool maskOutput if (h == drvHashes.end()) { assert(store.isValidPath(i.first)); h = drvHashes.insert_or_assign(i.first.clone(), hashDerivationModulo(store, - readDerivation(store, store.toRealPath(i.first)), false)).first; + store.readDerivation(i.first), false)).first; } inputs2.insert_or_assign(h->second.to_string(Base16, false), i.second); } diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index e379db426..c2c45b4c2 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -595,7 +595,7 @@ uint64_t LocalStore::addValidPath(State & state, efficiently query whether a path is an output of some derivation. */ if (info.path.isDerivation()) { - auto drv = readDerivation(*this, realStoreDir + "/" + std::string(info.path.to_string())); + auto drv = readDerivation(info.path); /* Verify that the output paths in the derivation are correct (i.e., follow the scheme for computing output paths from @@ -911,8 +911,7 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos) for (auto & i : infos) if (i.path.isDerivation()) { // FIXME: inefficient; we already loaded the derivation in addValidPath(). - checkDerivationOutputs(i.path, - readDerivation(*this, realStoreDir + "/" + std::string(i.path.to_string()))); + checkDerivationOutputs(i.path, readDerivation(i.path)); } /* Do a topological sort of the paths. This will throw an diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh index 5ba17e0bc..5ef506326 100644 --- a/src/libstore/store-api.hh +++ b/src/libstore/store-api.hh @@ -583,6 +583,9 @@ public: ensurePath(). */ Derivation derivationFromPath(const StorePath & drvPath); + /* Read a derivation (which must already be valid). */ + Derivation readDerivation(const StorePath & drvPath); + /* Place in `out' the set of all store paths in the file system closure of `storePath'; that is, all paths than can be directly or indirectly reached from it. `out' is not cleared. If diff --git a/src/nix/show-derivation.cc b/src/nix/show-derivation.cc index 22c569f3c..2d31894c2 100644 --- a/src/nix/show-derivation.cc +++ b/src/nix/show-derivation.cc @@ -61,11 +61,9 @@ struct CmdShowDerivation : InstallablesCommand for (auto & drvPath : drvPaths) { if (!drvPath.isDerivation()) continue; - auto drvPathS = store->printStorePath(drvPath); + auto drvObj(jsonRoot.object(store->printStorePath(drvPath))); - auto drvObj(jsonRoot.object(drvPathS)); - - auto drv = readDerivation(*store, drvPathS); + auto drv = store->readDerivation(drvPath); { auto outputsObj(drvObj.object("outputs")); From b260c9ee0325d7a4c78d91e47bd6e2afbde16e28 Mon Sep 17 00:00:00 2001 From: Matthew Bauer Date: Fri, 12 Jun 2020 10:09:42 -0500 Subject: [PATCH 24/62] Add newHashAllowEmpty helper function This replaces the copy&paste with a helper function in hash.hh. --- src/libexpr/primops.cc | 18 ++++-------------- src/libexpr/primops/fetchTree.cc | 11 +++-------- src/libfetchers/fetchers.cc | 11 +++-------- src/libfetchers/tarball.cc | 10 ++-------- src/libutil/hash.cc | 10 ++++++++++ src/libutil/hash.hh | 2 ++ 6 files changed, 24 insertions(+), 38 deletions(-) diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index df3d4a459..083c7d398 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -720,12 +720,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * * HashType ht = outputHashAlgo.empty() ? htUnknown : parseHashType(outputHashAlgo); - Hash h; - if (outputHash->empty()) { - h = Hash(ht); - printError("warning: found empty hash, assuming you wanted '%s'", h.to_string()); - } else - h = Hash(*outputHash, ht); + Hash h = newHashAllowEmpty(*outputHash, ht); auto outPath = state.store->makeFixedOutputPath(ingestionMethod, h, drvName); if (!jsonObject) drv.env["out"] = state.store->printStorePath(outPath); @@ -1131,14 +1126,9 @@ static void prim_path(EvalState & state, const Pos & pos, Value * * args, Value filterFun = attr.value; } else if (n == "recursive") method = FileIngestionMethod { state.forceBool(*attr.value, *attr.pos) }; - else if (n == "sha256") { - auto hashStr = state.forceStringNoCtx(*attr.value, *attr.pos); - if (hashStr == "") { - expectedHash = Hash(htSHA256); - printError("warning: found empty hash, assuming you wanted '%s'", expectedHash.to_string()); - } else - expectedHash = Hash(hashStr, htSHA256); - } else + else if (n == "sha256") + expectedHash = newHashAllowEmpty(state.forceStringNoCtx(*attr.value, *attr.pos), htSHA256); + else throw EvalError(format("unsupported argument '%1%' to 'addPath', at %2%") % attr.name % *attr.pos); } if (path.empty()) diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc index 745f65adf..1464aa8b4 100644 --- a/src/libexpr/primops/fetchTree.cc +++ b/src/libexpr/primops/fetchTree.cc @@ -102,14 +102,9 @@ static void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v, string n(attr.name); if (n == "url") url = state.forceStringNoCtx(*attr.value, *attr.pos); - else if (n == "sha256") { - auto hashStr = state.forceStringNoCtx(*attr.value, *attr.pos); - if (hashStr == "") { - expectedHash = Hash(htSHA256); - printError("warning: found empty hash, assuming you wanted '%s'", expectedHash->to_string()); - } else - expectedHash = Hash(hashStr, htSHA256); - } else if (n == "name") + else if (n == "sha256") + expectedHash = newHashAllowEmpty(state.forceStringNoCtx(*attr.value, *attr.pos), htSHA256); + else if (n == "name") name = state.forceStringNoCtx(*attr.value, *attr.pos); else throw EvalError("unsupported argument '%s' to '%s', at %s", diff --git a/src/libfetchers/fetchers.cc b/src/libfetchers/fetchers.cc index 988a8dc69..91b897e62 100644 --- a/src/libfetchers/fetchers.cc +++ b/src/libfetchers/fetchers.cc @@ -34,14 +34,9 @@ std::unique_ptr inputFromAttrs(const Attrs & attrs) for (auto & inputScheme : *inputSchemes) { auto res = inputScheme->inputFromAttrs(attrs2); if (res) { - if (auto narHash = maybeGetStrAttr(attrs, "narHash")) { - if (narHash->empty()) { - res->narHash = Hash(htUnknown); - printError("warning: found empty hash, assuming you wanted '%s'", res->narHash->to_string()); - } else - // FIXME: require SRI hash. - res->narHash = Hash(*narHash); - } + if (auto narHash = maybeGetStrAttr(attrs, "narHash")) + // FIXME: require SRI hash. + res->narHash = newHashAllowEmpty(*narHash, htUnknown); return res; } } diff --git a/src/libfetchers/tarball.cc b/src/libfetchers/tarball.cc index e4dafec0b..937f86bc6 100644 --- a/src/libfetchers/tarball.cc +++ b/src/libfetchers/tarball.cc @@ -263,14 +263,8 @@ struct TarballInputScheme : InputScheme throw Error("unsupported tarball input attribute '%s'", name); auto input = std::make_unique(parseURL(getStrAttr(attrs, "url"))); - if (auto hash = maybeGetStrAttr(attrs, "hash")) { - if (hash->empty()) { - input->hash = Hash(htUnknown); - printError("warning: found empty hash, assuming you wanted '%s'", input->hash->to_string()); - } else - // FIXME: require SRI hash. - input->hash = Hash(*hash); - } + if (auto hash = maybeGetStrAttr(attrs, "hash")) + input->hash = newHashAllowEmpty(*hash, htUnknown); return input; } diff --git a/src/libutil/hash.cc b/src/libutil/hash.cc index 7caee1da7..2c8085e42 100644 --- a/src/libutil/hash.cc +++ b/src/libutil/hash.cc @@ -205,6 +205,16 @@ Hash::Hash(const std::string & s, HashType type) throw BadHash("hash '%s' has wrong length for hash type '%s'", s, printHashType(type)); } +Hash newHashAllowEmpty(std::string hashStr, HashType ht) +{ + if (hashStr.empty()) + { + Hash h(ht); + warn("found empty hash, assuming you wanted '%s'", h.to_string()); + } else + return Hash(hashStr, ht); +} + union Ctx { diff --git a/src/libutil/hash.hh b/src/libutil/hash.hh index ea9fca3e7..449cb1b86 100644 --- a/src/libutil/hash.hh +++ b/src/libutil/hash.hh @@ -94,6 +94,8 @@ struct Hash } }; +/* Helper that defaults empty hashes to the 0 hash. */ +Hash newHashAllowEmpty(std::string hashStr, HashType ht); /* Print a hash in base-16 if it's MD5, or base-32 otherwise. */ string printHash16or32(const Hash & hash); From ea0d29d99a400c328fa0ca05ba5e639351673ebc Mon Sep 17 00:00:00 2001 From: Matthew Bauer Date: Fri, 12 Jun 2020 10:18:27 -0500 Subject: [PATCH 25/62] Provide base argument to to_string --- src/libutil/hash.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libutil/hash.cc b/src/libutil/hash.cc index 2c8085e42..3f6d4c0c9 100644 --- a/src/libutil/hash.cc +++ b/src/libutil/hash.cc @@ -210,7 +210,7 @@ Hash newHashAllowEmpty(std::string hashStr, HashType ht) if (hashStr.empty()) { Hash h(ht); - warn("found empty hash, assuming you wanted '%s'", h.to_string()); + warn("found empty hash, assuming you wanted '%s'", h.to_string(SRI)); } else return Hash(hashStr, ht); } From 2853ba4ab26c254d564aee9e75fe8f9f664b94fc Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 12 Jun 2020 19:00:48 +0200 Subject: [PATCH 26/62] Fix build --- src/libutil/hash.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libutil/hash.cc b/src/libutil/hash.cc index 3f6d4c0c9..c935f05eb 100644 --- a/src/libutil/hash.cc +++ b/src/libutil/hash.cc @@ -207,10 +207,10 @@ Hash::Hash(const std::string & s, HashType type) Hash newHashAllowEmpty(std::string hashStr, HashType ht) { - if (hashStr.empty()) - { + if (hashStr.empty()) { Hash h(ht); - warn("found empty hash, assuming you wanted '%s'", h.to_string(SRI)); + warn("found empty hash, assuming '%s'", h.to_string(SRI, true)); + return h; } else return Hash(hashStr, ht); } From f6f01416b71f239c0d9594f5c6201dfd208fe8c4 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Fri, 12 Jun 2020 21:12:36 +0000 Subject: [PATCH 27/62] Use `std::string_view` in a few more places --- src/libfetchers/github.cc | 2 +- src/libstore/store-api.cc | 4 ++-- src/libutil/hash.cc | 4 ++-- src/libutil/hash.hh | 2 +- src/libutil/util.cc | 6 +++--- src/libutil/util.hh | 6 +++--- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/libfetchers/github.cc b/src/libfetchers/github.cc index 8675a5a66..0bee1d6b3 100644 --- a/src/libfetchers/github.cc +++ b/src/libfetchers/github.cc @@ -76,7 +76,7 @@ struct GitHubInput : Input readFile( store->toRealPath( downloadFile(store, url, "source", false).storePath))); - rev = Hash(json["sha"], htSHA1); + rev = Hash(std::string { json["sha"] }, htSHA1); debug("HEAD revision for '%s' is %s", url, rev->gitRev()); } diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index 0645fca84..f6901bf42 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -779,7 +779,7 @@ bool ValidPathInfo::isContentAddressed(const Store & store) const }; if (hasPrefix(ca, "text:")) { - Hash hash(std::string(ca, 5)); + Hash hash(ca.substr(5)); if (store.makeTextPath(path.name(), hash, references) == path) return true; else @@ -788,7 +788,7 @@ bool ValidPathInfo::isContentAddressed(const Store & store) const else if (hasPrefix(ca, "fixed:")) { FileIngestionMethod recursive { ca.compare(6, 2, "r:") == 0 }; - Hash hash(std::string(ca, recursive == FileIngestionMethod::Recursive ? 8 : 6)); + Hash hash(ca.substr(recursive == FileIngestionMethod::Recursive ? 8 : 6)); auto refs = cloneStorePathSet(references); bool hasSelfReference = false; if (refs.count(path)) { diff --git a/src/libutil/hash.cc b/src/libutil/hash.cc index c935f05eb..460d479a3 100644 --- a/src/libutil/hash.cc +++ b/src/libutil/hash.cc @@ -125,7 +125,7 @@ std::string Hash::to_string(Base base, bool includeType) const } -Hash::Hash(const std::string & s, HashType type) +Hash::Hash(std::string_view s, HashType type) : type(type) { size_t pos = 0; @@ -194,7 +194,7 @@ Hash::Hash(const std::string & s, HashType type) } else if (isSRI || size == base64Len()) { - auto d = base64Decode(std::string(s, pos)); + auto d = base64Decode(s.substr(pos)); if (d.size() != hashSize) throw BadHash("invalid %s hash '%s'", isSRI ? "SRI" : "base-64", s); assert(hashSize); diff --git a/src/libutil/hash.hh b/src/libutil/hash.hh index 5080539b2..180fb7633 100644 --- a/src/libutil/hash.hh +++ b/src/libutil/hash.hh @@ -42,7 +42,7 @@ struct Hash Subresource Integrity hash expression). If the 'type' argument is htUnknown, then the hash type must be specified in the string. */ - Hash(const std::string & s, HashType type = htUnknown); + Hash(std::string_view s, HashType type = htUnknown); void init(); diff --git a/src/libutil/util.cc b/src/libutil/util.cc index e0a99152b..b66447e08 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -1314,7 +1314,7 @@ bool statusOk(int status) } -bool hasPrefix(const string & s, const string & prefix) +bool hasPrefix(std::string_view s, std::string_view prefix) { return s.compare(0, prefix.size(), prefix) == 0; } @@ -1408,7 +1408,7 @@ std::string filterANSIEscapes(const std::string & s, bool filterAll, unsigned in static char base64Chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -string base64Encode(const string & s) +string base64Encode(std::string_view s) { string res; int data = 0, nbits = 0; @@ -1429,7 +1429,7 @@ string base64Encode(const string & s) } -string base64Decode(const string & s) +string base64Decode(std::string_view s) { bool init = false; char decode[256]; diff --git a/src/libutil/util.hh b/src/libutil/util.hh index 4b117f9bc..c95232317 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -416,7 +416,7 @@ template bool string2Float(const string & s, N & n) /* Return true iff `s' starts with `prefix'. */ -bool hasPrefix(const string & s, const string & prefix); +bool hasPrefix(std::string_view s, std::string_view prefix); /* Return true iff `s' ends in `suffix'. */ @@ -455,8 +455,8 @@ std::string filterANSIEscapes(const std::string & s, /* Base64 encoding/decoding. */ -string base64Encode(const string & s); -string base64Decode(const string & s); +string base64Encode(std::string_view s); +string base64Decode(std::string_view s); /* Get a value for the specified key from an associate container. */ From 340d0b055afb02ec7292d6cd9dd1661640158210 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 3 Jun 2020 14:57:24 +0200 Subject: [PATCH 28/62] upload-release.pl: Fix nix-fallback-paths.nix generation --- maintainers/upload-release.pl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/maintainers/upload-release.pl b/maintainers/upload-release.pl index cb584d427..baefe0f12 100755 --- a/maintainers/upload-release.pl +++ b/maintainers/upload-release.pl @@ -142,8 +142,12 @@ $oldName =~ s/"//g; sub getStorePath { my ($jobName) = @_; my $buildInfo = decode_json(fetch("$evalUrl/job/$jobName", 'application/json')); - die unless $buildInfo->{buildproducts}->{1}->{type} eq "nix-build"; - return $buildInfo->{buildproducts}->{1}->{path}; + for my $product (values %{$buildInfo->{buildproducts}}) { + next unless $product->{type} eq "nix-build"; + next if $product->{path} =~ /[a-z]+$/; + return $product->{path}; + } + die; } write_file("$nixpkgsDir/nixos/modules/installer/tools/nix-fallback-paths.nix", From fd64e4fb96f814440dc337ce664cdbd22e0eabb2 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 15 Jun 2020 13:50:33 +0200 Subject: [PATCH 29/62] Disambiguate BaseError(Args) constructor This means that 'throw Error({ ... ErrorInfo ... })' now works. --- src/libexpr/eval.cc | 9 ++++----- src/libutil/types.hh | 3 --- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 7bf25ea17..75e6a23a1 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -506,11 +506,10 @@ LocalNoInlineNoReturn(void throwEvalError(const char * s, const string & s2)) LocalNoInlineNoReturn(void throwEvalError(const Pos & pos, const char * s, const string & s2)) { - throw EvalError( - ErrorInfo { - .hint = hintfmt(s, s2), - .nixCode = NixCode { .errPos = pos } - }); + throw EvalError({ + .hint = hintfmt(s, s2), + .nixCode = NixCode { .errPos = pos } + }); } LocalNoInlineNoReturn(void throwEvalError(const char * s, const string & s2, const string & s3)) diff --git a/src/libutil/types.hh b/src/libutil/types.hh index 89ae108f9..3af485fa0 100644 --- a/src/libutil/types.hh +++ b/src/libutil/types.hh @@ -1,6 +1,5 @@ #pragma once - #include "ref.hh" #include @@ -25,7 +24,6 @@ typedef string Path; typedef list Paths; typedef set PathSet; - /* Helper class to run code at startup. */ template struct OnStartup @@ -33,5 +31,4 @@ struct OnStartup OnStartup(T && t) { t(); } }; - } From 1fb762d11fadc659ef41b79eaddddcce5fbbc192 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 15 Jun 2020 14:06:58 +0200 Subject: [PATCH 30/62] Get rid of explicit ErrorInfo constructors --- src/libexpr/attr-set.hh | 9 +- src/libexpr/eval-inline.hh | 18 +- src/libexpr/eval.cc | 65 ++-- src/libexpr/nixexpr.cc | 9 +- src/libexpr/nixexpr.hh | 9 +- src/libexpr/parser.y | 86 +++-- src/libexpr/primops.cc | 442 ++++++++++++-------------- src/libexpr/primops/context.cc | 27 +- src/libexpr/primops/fetchGit.cc | 18 +- src/libexpr/primops/fetchMercurial.cc | 18 +- src/libexpr/primops/fetchTree.cc | 28 +- src/libexpr/primops/fromTOML.cc | 9 +- src/libstore/builtins/buildenv.cc | 14 +- src/libstore/gc.cc | 11 +- src/libstore/sqlite.cc | 8 +- src/libutil/error.hh | 14 +- src/libutil/serialise.cc | 4 +- src/nix-build/nix-build.cc | 11 +- src/nix/upgrade-nix.cc | 7 +- 19 files changed, 360 insertions(+), 447 deletions(-) diff --git a/src/libexpr/attr-set.hh b/src/libexpr/attr-set.hh index f5651891f..c601d09c2 100644 --- a/src/libexpr/attr-set.hh +++ b/src/libexpr/attr-set.hh @@ -76,11 +76,10 @@ public: { auto a = get(name); if (!a) - throw Error( - ErrorInfo { - .hint = hintfmt("attribute '%s' missing", name), - .nixCode = NixCode { .errPos = pos } - }); + throw Error({ + .hint = hintfmt("attribute '%s' missing", name), + .nixCode = NixCode { .errPos = pos } + }); return *a; } diff --git a/src/libexpr/eval-inline.hh b/src/libexpr/eval-inline.hh index eee49e02e..3d544c903 100644 --- a/src/libexpr/eval-inline.hh +++ b/src/libexpr/eval-inline.hh @@ -9,11 +9,10 @@ namespace nix { LocalNoInlineNoReturn(void throwEvalError(const Pos & pos, const char * s)) { - throw EvalError( - ErrorInfo { - .hint = hintfmt(s), - .nixCode = NixCode { .errPos = pos } - }); + throw EvalError({ + .hint = hintfmt(s), + .nixCode = NixCode { .errPos = pos } + }); } LocalNoInlineNoReturn(void throwTypeError(const char * s, const Value & v)) @@ -24,11 +23,10 @@ LocalNoInlineNoReturn(void throwTypeError(const char * s, const Value & v)) LocalNoInlineNoReturn(void throwTypeError(const Pos & pos, const char * s, const Value & v)) { - throw TypeError( - ErrorInfo { - .hint = hintfmt(s, showType(v)), - .nixCode = NixCode { .errPos = pos } - }); + throw TypeError({ + .hint = hintfmt(s, showType(v)), + .nixCode = NixCode { .errPos = pos } + }); } diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 75e6a23a1..8e71db2b8 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -519,30 +519,27 @@ LocalNoInlineNoReturn(void throwEvalError(const char * s, const string & s2, con LocalNoInlineNoReturn(void throwEvalError(const Pos & pos, const char * s, const string & s2, const string & s3)) { - throw EvalError( - ErrorInfo { - .hint = hintfmt(s, s2, s3), - .nixCode = NixCode { .errPos = pos } - }); + throw EvalError({ + .hint = hintfmt(s, s2, s3), + .nixCode = NixCode { .errPos = pos } + }); } LocalNoInlineNoReturn(void throwEvalError(const Pos & p1, const char * s, const Symbol & sym, const Pos & p2)) { // p1 is where the error occurred; p2 is a position mentioned in the message. - throw EvalError( - ErrorInfo { - .hint = hintfmt(s, sym, p2), - .nixCode = NixCode { .errPos = p1 } - }); + throw EvalError({ + .hint = hintfmt(s, sym, p2), + .nixCode = NixCode { .errPos = p1 } + }); } LocalNoInlineNoReturn(void throwTypeError(const Pos & pos, const char * s)) { - throw TypeError( - ErrorInfo { - .hint = hintfmt(s), - .nixCode = NixCode { .errPos = pos } - }); + throw TypeError({ + .hint = hintfmt(s), + .nixCode = NixCode { .errPos = pos } + }); } LocalNoInlineNoReturn(void throwTypeError(const char * s, const string & s1)) @@ -552,29 +549,26 @@ LocalNoInlineNoReturn(void throwTypeError(const char * s, const string & s1)) LocalNoInlineNoReturn(void throwTypeError(const Pos & pos, const char * s, const ExprLambda & fun, const Symbol & s2)) { - throw TypeError( - ErrorInfo { - .hint = hintfmt(s, fun.showNamePos(), s2), - .nixCode = NixCode { .errPos = pos } - }); + throw TypeError({ + .hint = hintfmt(s, fun.showNamePos(), s2), + .nixCode = NixCode { .errPos = pos } + }); } LocalNoInlineNoReturn(void throwAssertionError(const Pos & pos, const char * s, const string & s1)) { - throw AssertionError( - ErrorInfo { - .hint = hintfmt(s, s1), - .nixCode = NixCode { .errPos = pos } - }); + throw AssertionError({ + .hint = hintfmt(s, s1), + .nixCode = NixCode { .errPos = pos } + }); } LocalNoInlineNoReturn(void throwUndefinedVarError(const Pos & pos, const char * s, const string & s1)) { - throw UndefinedVarError( - ErrorInfo { - .hint = hintfmt(s, s1), - .nixCode = NixCode { .errPos = pos } - }); + throw UndefinedVarError({ + .hint = hintfmt(s, s1), + .nixCode = NixCode { .errPos = pos } + }); } LocalNoInline(void addErrorPrefix(Error & e, const char * s, const string & s2)) @@ -1593,7 +1587,7 @@ string EvalState::forceStringNoCtx(Value & v, const Pos & pos) string s = forceString(v, pos); if (v.string.context) { if (pos) - throwEvalError(pos, "the string '%1%' is not allowed to refer to a store path (such as '%2%')", + throwEvalError(pos, "the string '%1%' is not allowed to refer to a store path (such as '%2%')", v.string.s, v.string.context[0]); else throwEvalError("the string '%1%' is not allowed to refer to a store path (such as '%2%')", @@ -1919,11 +1913,10 @@ void EvalState::printStats() string ExternalValueBase::coerceToString(const Pos & pos, PathSet & context, bool copyMore, bool copyToStore) const { - throw TypeError( - ErrorInfo { - .hint = hintfmt("cannot coerce %1% to a string", showType()), - .nixCode = NixCode { .errPos = pos } - }); + throw TypeError({ + .hint = hintfmt("cannot coerce %1% to a string", showType()), + .nixCode = NixCode { .errPos = pos } + }); } diff --git a/src/libexpr/nixexpr.cc b/src/libexpr/nixexpr.cc index 91a508305..5b2dd9751 100644 --- a/src/libexpr/nixexpr.cc +++ b/src/libexpr/nixexpr.cc @@ -268,11 +268,10 @@ void ExprVar::bindVars(const StaticEnv & env) enclosing `with'. If there is no `with', then we can issue an "undefined variable" error now. */ if (withLevel == -1) - throw UndefinedVarError( - ErrorInfo { - .hint = hintfmt("undefined variable '%1%'", name), - .nixCode = NixCode { .errPos = pos } - }); + throw UndefinedVarError({ + .hint = hintfmt("undefined variable '%1%'", name), + .nixCode = NixCode { .errPos = pos } + }); fromWith = true; this->level = withLevel; } diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh index 47d0e85ec..ec6fd3190 100644 --- a/src/libexpr/nixexpr.hh +++ b/src/libexpr/nixexpr.hh @@ -236,11 +236,10 @@ struct ExprLambda : Expr : pos(pos), arg(arg), matchAttrs(matchAttrs), formals(formals), body(body) { if (!arg.empty() && formals && formals->argNames.find(arg) != formals->argNames.end()) - throw ParseError( - ErrorInfo { - .hint = hintfmt("duplicate formal function argument '%1%'", arg), - .nixCode = NixCode { .errPos = pos } - }); + throw ParseError({ + .hint = hintfmt("duplicate formal function argument '%1%'", arg), + .nixCode = NixCode { .errPos = pos } + }); }; void setName(Symbol & name); string showNamePos() const; diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index 0417a3c21..a1188dec0 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -64,23 +64,20 @@ namespace nix { static void dupAttr(const AttrPath & attrPath, const Pos & pos, const Pos & prevPos) { - throw ParseError( - ErrorInfo { - .hint = hintfmt("attribute '%1%' already defined at %2%", - showAttrPath(attrPath), prevPos), - .nixCode = NixCode { .errPos = pos }, - }); + throw ParseError({ + .hint = hintfmt("attribute '%1%' already defined at %2%", + showAttrPath(attrPath), prevPos), + .nixCode = NixCode { .errPos = pos }, + }); } static void dupAttr(Symbol attr, const Pos & pos, const Pos & prevPos) { - throw ParseError( - ErrorInfo { - .hint = hintfmt("attribute '%1%' already defined at %2%", - attr, prevPos), - .nixCode = NixCode { .errPos = pos }, - }); + throw ParseError({ + .hint = hintfmt("attribute '%1%' already defined at %2%", attr, prevPos), + .nixCode = NixCode { .errPos = pos }, + }); } @@ -148,12 +145,11 @@ static void addAttr(ExprAttrs * attrs, AttrPath & attrPath, static void addFormal(const Pos & pos, Formals * formals, const Formal & formal) { if (!formals->argNames.insert(formal.name).second) - throw ParseError( - ErrorInfo { - .hint = hintfmt("duplicate formal function argument '%1%'", - formal.name), - .nixCode = NixCode { .errPos = pos }, - }); + throw ParseError({ + .hint = hintfmt("duplicate formal function argument '%1%'", + formal.name), + .nixCode = NixCode { .errPos = pos }, + }); formals->formals.push_front(formal); } @@ -261,10 +257,10 @@ static inline Pos makeCurPos(const YYLTYPE & loc, ParseData * data) void yyerror(YYLTYPE * loc, yyscan_t scanner, ParseData * data, const char * error) { - data->error = ErrorInfo { + data->error = { .hint = hintfmt(error), .nixCode = NixCode { .errPos = makeCurPos(*loc, data) } - }; + }; } @@ -341,11 +337,10 @@ expr_function { $$ = new ExprWith(CUR_POS, $2, $4); } | LET binds IN expr_function { if (!$2->dynamicAttrs.empty()) - throw ParseError( - ErrorInfo { - .hint = hintfmt("dynamic attributes not allowed in let"), - .nixCode = NixCode { .errPos = CUR_POS }, - }); + throw ParseError({ + .hint = hintfmt("dynamic attributes not allowed in let"), + .nixCode = NixCode { .errPos = CUR_POS }, + }); $$ = new ExprLet($2, $4); } | expr_if @@ -422,11 +417,10 @@ expr_simple | URI { static bool noURLLiterals = settings.isExperimentalFeatureEnabled("no-url-literals"); if (noURLLiterals) - throw ParseError( - ErrorInfo { - .hint = hintfmt("URL literals are disabled"), - .nixCode = NixCode { .errPos = CUR_POS } - }); + throw ParseError({ + .hint = hintfmt("URL literals are disabled"), + .nixCode = NixCode { .errPos = CUR_POS } + }); $$ = new ExprString(data->symbols.create($1)); } | '(' expr ')' { $$ = $2; } @@ -496,11 +490,10 @@ attrs $$->push_back(AttrName(str->s)); delete str; } else - throw ParseError( - ErrorInfo { - .hint = hintfmt("dynamic attributes not allowed in inherit"), - .nixCode = NixCode { .errPos = makeCurPos(@2, data) }, - }); + throw ParseError({ + .hint = hintfmt("dynamic attributes not allowed in inherit"), + .nixCode = NixCode { .errPos = makeCurPos(@2, data) }, + }); } | { $$ = new AttrPath; } ; @@ -695,11 +688,10 @@ Path EvalState::findFile(SearchPath & searchPath, const string & path, const Pos Path res = r.second + suffix; if (pathExists(res)) return canonPath(res); } - throw ThrownError( - ErrorInfo { - .hint = hintfmt("file '%1%' was not found in the Nix search path (add it using $NIX_PATH or -I)", path), - .nixCode = NixCode { .errPos = pos } - }); + throw ThrownError({ + .hint = hintfmt("file '%1%' was not found in the Nix search path (add it using $NIX_PATH or -I)", path), + .nixCode = NixCode { .errPos = pos } + }); } @@ -715,10 +707,9 @@ std::pair EvalState::resolveSearchPathElem(const SearchPathEl res = { true, store->toRealPath(fetchers::downloadTarball( store, resolveUri(elem.second), "source", false).storePath) }; } catch (FileTransferError & e) { - logWarning( - ErrorInfo { - .name = "Entry download", - .hint = hintfmt("Nix search path entry '%1%' cannot be downloaded, ignoring", elem.second) + logWarning({ + .name = "Entry download", + .hint = hintfmt("Nix search path entry '%1%' cannot be downloaded, ignoring", elem.second) }); res = { false, "" }; } @@ -727,10 +718,9 @@ std::pair EvalState::resolveSearchPathElem(const SearchPathEl if (pathExists(path)) res = { true, path }; else { - logWarning( - ErrorInfo { - .name = "Entry not found", - .hint = hintfmt("warning: Nix search path entry '%1%' does not exist, ignoring", elem.second) + logWarning({ + .name = "Entry not found", + .hint = hintfmt("warning: Nix search path entry '%1%' does not exist, ignoring", elem.second) }); res = { false, "" }; } diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 23ab7dec6..62e5163c9 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -93,12 +93,10 @@ static void prim_scopedImport(EvalState & state, const Pos & pos, Value * * args try { state.realiseContext(context); } catch (InvalidPathError & e) { - throw EvalError( - ErrorInfo { - .hint = hintfmt("cannot import '%1%', since path '%2%' is not valid", - path, e.path), - .nixCode = NixCode { .errPos = pos } - }); + throw EvalError({ + .hint = hintfmt("cannot import '%1%', since path '%2%' is not valid", path, e.path), + .nixCode = NixCode { .errPos = pos } + }); } Path realPath = state.checkSourcePath(state.toRealPath(path, context)); @@ -174,13 +172,12 @@ void prim_importNative(EvalState & state, const Pos & pos, Value * * args, Value try { state.realiseContext(context); } catch (InvalidPathError & e) { - throw EvalError( - ErrorInfo { - .hint = hintfmt( - "cannot import '%1%', since path '%2%' is not valid", - path, e.path), - .nixCode = NixCode { .errPos = pos } - }); + throw EvalError({ + .hint = hintfmt( + "cannot import '%1%', since path '%2%' is not valid", + path, e.path), + .nixCode = NixCode { .errPos = pos } + }); } path = state.checkSourcePath(path); @@ -215,11 +212,10 @@ void prim_exec(EvalState & state, const Pos & pos, Value * * args, Value & v) auto elems = args[0]->listElems(); auto count = args[0]->listSize(); if (count == 0) { - throw EvalError( - ErrorInfo { - .hint = hintfmt("at least one argument to 'exec' required"), - .nixCode = NixCode { .errPos = pos } - }); + throw EvalError({ + .hint = hintfmt("at least one argument to 'exec' required"), + .nixCode = NixCode { .errPos = pos } + }); } PathSet context; auto program = state.coerceToString(pos, *elems[0], context, false, false); @@ -230,12 +226,12 @@ void prim_exec(EvalState & state, const Pos & pos, Value * * args, Value & v) try { state.realiseContext(context); } catch (InvalidPathError & e) { - throw EvalError( - ErrorInfo { - .hint = hintfmt("cannot execute '%1%', since path '%2%' is not valid", - program, e.path), - .nixCode = NixCode { .errPos = pos } - });} + throw EvalError({ + .hint = hintfmt("cannot execute '%1%', since path '%2%' is not valid", + program, e.path), + .nixCode = NixCode { .errPos = pos } + }); + } auto output = runProgram(program, true, commandArgs); Expr * parsed; @@ -386,11 +382,10 @@ static void prim_genericClosure(EvalState & state, const Pos & pos, Value * * ar Bindings::iterator startSet = args[0]->attrs->find(state.symbols.create("startSet")); if (startSet == args[0]->attrs->end()) - throw EvalError( - ErrorInfo { - .hint = hintfmt("attribute 'startSet' required"), - .nixCode = NixCode { .errPos = pos } - }); + throw EvalError({ + .hint = hintfmt("attribute 'startSet' required"), + .nixCode = NixCode { .errPos = pos } + }); state.forceList(*startSet->value, pos); ValueList workSet; @@ -401,11 +396,10 @@ static void prim_genericClosure(EvalState & state, const Pos & pos, Value * * ar Bindings::iterator op = args[0]->attrs->find(state.symbols.create("operator")); if (op == args[0]->attrs->end()) - throw EvalError( - ErrorInfo { - .hint = hintfmt("attribute 'operator' required"), - .nixCode = NixCode { .errPos = pos } - }); + throw EvalError({ + .hint = hintfmt("attribute 'operator' required"), + .nixCode = NixCode { .errPos = pos } + }); state.forceValue(*op->value, pos); /* Construct the closure by applying the operator to element of @@ -424,11 +418,10 @@ static void prim_genericClosure(EvalState & state, const Pos & pos, Value * * ar Bindings::iterator key = e->attrs->find(state.symbols.create("key")); if (key == e->attrs->end()) - throw EvalError( - ErrorInfo { - .hint = hintfmt("attribute 'key' required"), - .nixCode = NixCode { .errPos = pos } - }); + throw EvalError({ + .hint = hintfmt("attribute 'key' required"), + .nixCode = NixCode { .errPos = pos } + }); state.forceValue(*key->value, pos); if (!doneKeys.insert(key->value).second) continue; @@ -560,11 +553,10 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * * /* Figure out the name first (for stack backtraces). */ Bindings::iterator attr = args[0]->attrs->find(state.sName); if (attr == args[0]->attrs->end()) - throw EvalError( - ErrorInfo { - .hint = hintfmt("required attribute 'name' missing"), - .nixCode = NixCode { .errPos = pos } - }); + throw EvalError({ + .hint = hintfmt("required attribute 'name' missing"), + .nixCode = NixCode { .errPos = pos } + }); string drvName; Pos & posDrvName(*attr->pos); try { @@ -607,42 +599,38 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * * auto handleHashMode = [&](const std::string & s) { if (s == "recursive") ingestionMethod = FileIngestionMethod::Recursive; else if (s == "flat") ingestionMethod = FileIngestionMethod::Flat; - else - throw EvalError( - ErrorInfo { - .hint = hintfmt("invalid value '%s' for 'outputHashMode' attribute", s), - .nixCode = NixCode { .errPos = posDrvName } - }); + else + throw EvalError({ + .hint = hintfmt("invalid value '%s' for 'outputHashMode' attribute", s), + .nixCode = NixCode { .errPos = posDrvName } + }); }; auto handleOutputs = [&](const Strings & ss) { outputs.clear(); for (auto & j : ss) { if (outputs.find(j) != outputs.end()) - throw EvalError( - ErrorInfo { - .hint = hintfmt("duplicate derivation output '%1%'", j), - .nixCode = NixCode { .errPos = posDrvName } - }); + throw EvalError({ + .hint = hintfmt("duplicate derivation output '%1%'", j), + .nixCode = NixCode { .errPos = posDrvName } + }); /* !!! Check whether j is a valid attribute name. */ /* Derivations cannot be named ‘drv’, because then we'd have an attribute ‘drvPath’ in the resulting set. */ if (j == "drv") - throw EvalError( - ErrorInfo { - .hint = hintfmt("invalid derivation output name 'drv'" ), - .nixCode = NixCode { .errPos = posDrvName } - }); + throw EvalError({ + .hint = hintfmt("invalid derivation output name 'drv'" ), + .nixCode = NixCode { .errPos = posDrvName } + }); outputs.insert(j); } if (outputs.empty()) - throw EvalError( - ErrorInfo { - .hint = hintfmt("derivation cannot have an empty set of outputs"), - .nixCode = NixCode { .errPos = posDrvName } - }); + throw EvalError({ + .hint = hintfmt("derivation cannot have an empty set of outputs"), + .nixCode = NixCode { .errPos = posDrvName } + }); }; try { @@ -754,35 +742,31 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * * /* Do we have all required attributes? */ if (drv.builder == "") - throw EvalError( - ErrorInfo { - .hint = hintfmt("required attribute 'builder' missing"), - .nixCode = NixCode { .errPos = posDrvName } - }); + throw EvalError({ + .hint = hintfmt("required attribute 'builder' missing"), + .nixCode = NixCode { .errPos = posDrvName } + }); if (drv.platform == "") - throw EvalError( - ErrorInfo { - .hint = hintfmt("required attribute 'system' missing"), - .nixCode = NixCode { .errPos = posDrvName } - }); + throw EvalError({ + .hint = hintfmt("required attribute 'system' missing"), + .nixCode = NixCode { .errPos = posDrvName } + }); /* Check whether the derivation name is valid. */ if (isDerivation(drvName)) - throw EvalError( - ErrorInfo { - .hint = hintfmt("derivation names are not allowed to end in '%s'", drvExtension), - .nixCode = NixCode { .errPos = posDrvName } - }); + throw EvalError({ + .hint = hintfmt("derivation names are not allowed to end in '%s'", drvExtension), + .nixCode = NixCode { .errPos = posDrvName } + }); if (outputHash) { /* Handle fixed-output derivations. */ if (outputs.size() != 1 || *(outputs.begin()) != "out") - throw Error( - ErrorInfo { - .hint = hintfmt("multiple outputs are not supported in fixed-output derivations"), - .nixCode = NixCode { .errPos = posDrvName } - }); + throw Error({ + .hint = hintfmt("multiple outputs are not supported in fixed-output derivations"), + .nixCode = NixCode { .errPos = posDrvName } + }); HashType ht = outputHashAlgo.empty() ? htUnknown : parseHashType(outputHashAlgo); @@ -887,11 +871,10 @@ static void prim_storePath(EvalState & state, const Pos & pos, Value * * args, V e.g. nix-push does the right thing. */ if (!state.store->isStorePath(path)) path = canonPath(path, true); if (!state.store->isInStore(path)) - throw EvalError( - ErrorInfo { - .hint = hintfmt("path '%1%' is not in the Nix store", path), - .nixCode = NixCode { .errPos = pos } - }); + throw EvalError({ + .hint = hintfmt("path '%1%' is not in the Nix store", path), + .nixCode = NixCode { .errPos = pos } + }); Path path2 = state.store->toStorePath(path); if (!settings.readOnlyMode) state.store->ensurePath(state.store->parseStorePath(path2)); @@ -907,13 +890,12 @@ static void prim_pathExists(EvalState & state, const Pos & pos, Value * * args, try { state.realiseContext(context); } catch (InvalidPathError & e) { - throw EvalError( - ErrorInfo { - .hint = hintfmt( - "cannot check the existence of '%1%', since path '%2%' is not valid", - path, e.path), - .nixCode = NixCode { .errPos = pos } - }); + throw EvalError({ + .hint = hintfmt( + "cannot check the existence of '%1%', since path '%2%' is not valid", + path, e.path), + .nixCode = NixCode { .errPos = pos } + }); } try { @@ -956,13 +938,11 @@ static void prim_readFile(EvalState & state, const Pos & pos, Value * * args, Va try { state.realiseContext(context); } catch (InvalidPathError & e) { - throw EvalError( - ErrorInfo { - .hint = hintfmt("cannot read '%1%', since path '%2%' is not valid" - , path, e.path), - .nixCode = NixCode { .errPos = pos } - }); - } + throw EvalError({ + .hint = hintfmt("cannot read '%1%', since path '%2%' is not valid", path, e.path), + .nixCode = NixCode { .errPos = pos } + }); + } string s = readFile(state.checkSourcePath(state.toRealPath(path, context))); if (s.find((char) 0) != string::npos) throw Error("the contents of the file '%1%' cannot be represented as a Nix string", path); @@ -989,11 +969,10 @@ static void prim_findFile(EvalState & state, const Pos & pos, Value * * args, Va i = v2.attrs->find(state.symbols.create("path")); if (i == v2.attrs->end()) - throw EvalError( - ErrorInfo { - .hint = hintfmt("attribute 'path' missing"), - .nixCode = NixCode { .errPos = pos } - }); + throw EvalError({ + .hint = hintfmt("attribute 'path' missing"), + .nixCode = NixCode { .errPos = pos } + }); PathSet context; string path = state.coerceToString(pos, *i->value, context, false, false); @@ -1001,12 +980,10 @@ static void prim_findFile(EvalState & state, const Pos & pos, Value * * args, Va try { state.realiseContext(context); } catch (InvalidPathError & e) { - throw EvalError( - ErrorInfo { - .hint = hintfmt("cannot find '%1%', since path '%2%' is not valid", - path, e.path), - .nixCode = NixCode { .errPos = pos } - }); + throw EvalError({ + .hint = hintfmt("cannot find '%1%', since path '%2%' is not valid", path, e.path), + .nixCode = NixCode { .errPos = pos } + }); } searchPath.emplace_back(prefix, path); @@ -1023,11 +1000,10 @@ static void prim_hashFile(EvalState & state, const Pos & pos, Value * * args, Va string type = state.forceStringNoCtx(*args[0], pos); HashType ht = parseHashType(type); if (ht == htUnknown) - throw Error( - ErrorInfo { - .hint = hintfmt("unknown hash type '%1%'", type), - .nixCode = NixCode { .errPos = pos } - }); + throw Error({ + .hint = hintfmt("unknown hash type '%1%'", type), + .nixCode = NixCode { .errPos = pos } + }); PathSet context; // discarded Path p = state.coerceToPath(pos, *args[1], context); @@ -1043,12 +1019,10 @@ static void prim_readDir(EvalState & state, const Pos & pos, Value * * args, Val try { state.realiseContext(ctx); } catch (InvalidPathError & e) { - throw EvalError( - ErrorInfo { - .hint = hintfmt("cannot read '%1%', since path '%2%' is not valid", - path, e.path), - .nixCode = NixCode { .errPos = pos } - }); + throw EvalError({ + .hint = hintfmt("cannot read '%1%', since path '%2%' is not valid", path, e.path), + .nixCode = NixCode { .errPos = pos } + }); } DirEntries entries = readDirectory(state.checkSourcePath(path)); @@ -1118,15 +1092,13 @@ static void prim_toFile(EvalState & state, const Pos & pos, Value * * args, Valu for (auto path : context) { if (path.at(0) != '/') - throw EvalError( - ErrorInfo { - .hint = hintfmt( - "in 'toFile': the file named '%1%' must not contain a reference " - "to a derivation but contains (%2%)", - name, - path), - .nixCode = NixCode { .errPos = pos } - }); + throw EvalError( { + .hint = hintfmt( + "in 'toFile': the file named '%1%' must not contain a reference " + "to a derivation but contains (%2%)", + name, path), + .nixCode = NixCode { .errPos = pos } + }); refs.insert(state.store->parseStorePath(path)); } @@ -1194,21 +1166,19 @@ static void prim_filterSource(EvalState & state, const Pos & pos, Value * * args PathSet context; Path path = state.coerceToPath(pos, *args[1], context); if (!context.empty()) - throw EvalError( - ErrorInfo { - .hint = hintfmt("string '%1%' cannot refer to other paths", path), - .nixCode = NixCode { .errPos = pos } - }); + throw EvalError({ + .hint = hintfmt("string '%1%' cannot refer to other paths", path), + .nixCode = NixCode { .errPos = pos } + }); state.forceValue(*args[0], pos); if (args[0]->type != tLambda) - throw TypeError( - ErrorInfo { - .hint = hintfmt( - "first argument in call to 'filterSource' is not a function but %1%", - showType(*args[0])), - .nixCode = NixCode { .errPos = pos } - }); + throw TypeError({ + .hint = hintfmt( + "first argument in call to 'filterSource' is not a function but %1%", + showType(*args[0])), + .nixCode = NixCode { .errPos = pos } + }); addPath(state, pos, std::string(baseNameOf(path)), path, args[0], FileIngestionMethod::Recursive, Hash(), v); } @@ -1228,12 +1198,10 @@ static void prim_path(EvalState & state, const Pos & pos, Value * * args, Value PathSet context; path = state.coerceToPath(*attr.pos, *attr.value, context); if (!context.empty()) - throw EvalError( - ErrorInfo { - .hint = hintfmt("string '%1%' cannot refer to other paths", - path), - .nixCode = NixCode { .errPos = *attr.pos } - }); + throw EvalError({ + .hint = hintfmt("string '%1%' cannot refer to other paths", path), + .nixCode = NixCode { .errPos = *attr.pos } + }); } else if (attr.name == state.sName) name = state.forceStringNoCtx(*attr.value, *attr.pos); else if (n == "filter") { @@ -1244,19 +1212,16 @@ static void prim_path(EvalState & state, const Pos & pos, Value * * args, Value else if (n == "sha256") expectedHash = newHashAllowEmpty(state.forceStringNoCtx(*attr.value, *attr.pos), htSHA256); else - throw EvalError( - ErrorInfo { - .hint = hintfmt("unsupported argument '%1%' to 'addPath'", - attr.name), - .nixCode = NixCode { .errPos = *attr.pos } - }); + throw EvalError({ + .hint = hintfmt("unsupported argument '%1%' to 'addPath'", attr.name), + .nixCode = NixCode { .errPos = *attr.pos } + }); } if (path.empty()) - throw EvalError( - ErrorInfo { - .hint = hintfmt("'path' required"), - .nixCode = NixCode { .errPos = pos } - }); + throw EvalError({ + .hint = hintfmt("'path' required"), + .nixCode = NixCode { .errPos = pos } + }); if (name.empty()) name = baseNameOf(path); @@ -1314,11 +1279,10 @@ void prim_getAttr(EvalState & state, const Pos & pos, Value * * args, Value & v) // !!! Should we create a symbol here or just do a lookup? Bindings::iterator i = args[1]->attrs->find(state.symbols.create(attr)); if (i == args[1]->attrs->end()) - throw EvalError( - ErrorInfo { - .hint = hintfmt("attribute '%1%' missing", attr), - .nixCode = NixCode { .errPos = pos } - }); + throw EvalError({ + .hint = hintfmt("attribute '%1%' missing", attr), + .nixCode = NixCode { .errPos = pos } + }); // !!! add to stack trace? if (state.countCalls && i->pos) state.attrSelects[*i->pos]++; state.forceValue(*i->value, pos); @@ -1398,22 +1362,20 @@ static void prim_listToAttrs(EvalState & state, const Pos & pos, Value * * args, Bindings::iterator j = v2.attrs->find(state.sName); if (j == v2.attrs->end()) - throw TypeError( - ErrorInfo { - .hint = hintfmt("'name' attribute missing in a call to 'listToAttrs'"), - .nixCode = NixCode { .errPos = pos } - }); + throw TypeError({ + .hint = hintfmt("'name' attribute missing in a call to 'listToAttrs'"), + .nixCode = NixCode { .errPos = pos } + }); string name = state.forceStringNoCtx(*j->value, pos); Symbol sym = state.symbols.create(name); if (seen.insert(sym).second) { Bindings::iterator j2 = v2.attrs->find(state.symbols.create(state.sValue)); if (j2 == v2.attrs->end()) - throw TypeError( - ErrorInfo { - .hint = hintfmt("'value' attribute missing in a call to 'listToAttrs'"), - .nixCode = NixCode { .errPos = pos } - }); + throw TypeError({ + .hint = hintfmt("'value' attribute missing in a call to 'listToAttrs'"), + .nixCode = NixCode { .errPos = pos } + }); v.attrs->push_back(Attr(sym, j2->value, j2->pos)); } } @@ -1486,11 +1448,10 @@ static void prim_functionArgs(EvalState & state, const Pos & pos, Value * * args { state.forceValue(*args[0], pos); if (args[0]->type != tLambda) - throw TypeError( - ErrorInfo { - .hint = hintfmt("'functionArgs' requires a function"), - .nixCode = NixCode { .errPos = pos } - }); + throw TypeError({ + .hint = hintfmt("'functionArgs' requires a function"), + .nixCode = NixCode { .errPos = pos } + }); if (!args[0]->lambda.fun->matchAttrs) { state.mkAttrs(v, 0); @@ -1543,11 +1504,10 @@ static void elemAt(EvalState & state, const Pos & pos, Value & list, int n, Valu { state.forceList(list, pos); if (n < 0 || (unsigned int) n >= list.listSize()) - throw Error( - ErrorInfo { - .hint = hintfmt("list index %1% is out of bounds", n), - .nixCode = NixCode { .errPos = pos } - }); + throw Error({ + .hint = hintfmt("list index %1% is out of bounds", n), + .nixCode = NixCode { .errPos = pos } + }); state.forceValue(*list.listElems()[n], pos); v = *list.listElems()[n]; } @@ -1574,11 +1534,10 @@ static void prim_tail(EvalState & state, const Pos & pos, Value * * args, Value { state.forceList(*args[0], pos); if (args[0]->listSize() == 0) - throw Error( - ErrorInfo { - .hint = hintfmt("'tail' called on an empty list"), - .nixCode = NixCode { .errPos = pos } - }); + throw Error({ + .hint = hintfmt("'tail' called on an empty list"), + .nixCode = NixCode { .errPos = pos } + }); state.mkList(v, args[0]->listSize() - 1); for (unsigned int n = 0; n < v.listSize(); ++n) @@ -1720,12 +1679,10 @@ static void prim_genList(EvalState & state, const Pos & pos, Value * * args, Val auto len = state.forceInt(*args[1], pos); if (len < 0) - throw EvalError( - ErrorInfo { - .hint = hintfmt("cannot create list of size %1%", len), - .nixCode = NixCode { .errPos = pos } - }); - + throw EvalError({ + .hint = hintfmt("cannot create list of size %1%", len), + .nixCode = NixCode { .errPos = pos } + }); state.mkList(v, len); @@ -1883,12 +1840,11 @@ static void prim_div(EvalState & state, const Pos & pos, Value * * args, Value & state.forceValue(*args[1], pos); NixFloat f2 = state.forceFloat(*args[1], pos); - if (f2 == 0) - throw EvalError( - ErrorInfo { - .hint = hintfmt("division by zero"), - .nixCode = NixCode { .errPos = pos } - }); + if (f2 == 0) + throw EvalError({ + .hint = hintfmt("division by zero"), + .nixCode = NixCode { .errPos = pos } + }); if (args[0]->type == tFloat || args[1]->type == tFloat) { mkFloat(v, state.forceFloat(*args[0], pos) / state.forceFloat(*args[1], pos)); @@ -1897,11 +1853,10 @@ static void prim_div(EvalState & state, const Pos & pos, Value * * args, Value & NixInt i2 = state.forceInt(*args[1], pos); /* Avoid division overflow as it might raise SIGFPE. */ if (i1 == std::numeric_limits::min() && i2 == -1) - throw EvalError( - ErrorInfo { - .hint = hintfmt("overflow in integer division"), - .nixCode = NixCode { .errPos = pos } - }); + throw EvalError({ + .hint = hintfmt("overflow in integer division"), + .nixCode = NixCode { .errPos = pos } + }); mkInt(v, i1 / i2); } @@ -1958,12 +1913,11 @@ static void prim_substring(EvalState & state, const Pos & pos, Value * * args, V PathSet context; string s = state.coerceToString(pos, *args[2], context); - if (start < 0) - throw EvalError( - ErrorInfo { - .hint = hintfmt("negative start position in 'substring'"), - .nixCode = NixCode { .errPos = pos } - }); + if (start < 0) + throw EvalError({ + .hint = hintfmt("negative start position in 'substring'"), + .nixCode = NixCode { .errPos = pos } + }); mkString(v, (unsigned int) start >= s.size() ? "" : string(s, start, len), context); } @@ -1983,11 +1937,10 @@ static void prim_hashString(EvalState & state, const Pos & pos, Value * * args, string type = state.forceStringNoCtx(*args[0], pos); HashType ht = parseHashType(type); if (ht == htUnknown) - throw Error( - ErrorInfo { - .hint = hintfmt("unknown hash type '%1%'", type), - .nixCode = NixCode { .errPos = pos } - }); + throw Error({ + .hint = hintfmt("unknown hash type '%1%'", type), + .nixCode = NixCode { .errPos = pos } + }); PathSet context; // discarded string s = state.forceString(*args[1], context, pos); @@ -2030,17 +1983,15 @@ void prim_match(EvalState & state, const Pos & pos, Value * * args, Value & v) } catch (std::regex_error &e) { if (e.code() == std::regex_constants::error_space) { // limit is _GLIBCXX_REGEX_STATE_LIMIT for libstdc++ - throw EvalError( - ErrorInfo { - .hint = hintfmt("memory limit exceeded by regular expression '%s'", re), - .nixCode = NixCode { .errPos = pos } - }); + throw EvalError({ + .hint = hintfmt("memory limit exceeded by regular expression '%s'", re), + .nixCode = NixCode { .errPos = pos } + }); } else { - throw EvalError( - ErrorInfo { - .hint = hintfmt("invalid regular expression '%s'", re), - .nixCode = NixCode { .errPos = pos } - }); + throw EvalError({ + .hint = hintfmt("invalid regular expression '%s'", re), + .nixCode = NixCode { .errPos = pos } + }); } } } @@ -2105,17 +2056,15 @@ static void prim_split(EvalState & state, const Pos & pos, Value * * args, Value } catch (std::regex_error &e) { if (e.code() == std::regex_constants::error_space) { // limit is _GLIBCXX_REGEX_STATE_LIMIT for libstdc++ - throw EvalError( - ErrorInfo { - .hint = hintfmt("memory limit exceeded by regular expression '%s'", re), - .nixCode = NixCode { .errPos = pos } - }); + throw EvalError({ + .hint = hintfmt("memory limit exceeded by regular expression '%s'", re), + .nixCode = NixCode { .errPos = pos } + }); } else { - throw EvalError( - ErrorInfo { - .hint = hintfmt("invalid regular expression '%s'", re), - .nixCode = NixCode { .errPos = pos } - }); + throw EvalError({ + .hint = hintfmt("invalid regular expression '%s'", re), + .nixCode = NixCode { .errPos = pos } + }); } } } @@ -2146,11 +2095,10 @@ static void prim_replaceStrings(EvalState & state, const Pos & pos, Value * * ar state.forceList(*args[0], pos); state.forceList(*args[1], pos); if (args[0]->listSize() != args[1]->listSize()) - throw EvalError( - ErrorInfo { - .hint = hintfmt("'from' and 'to' arguments to 'replaceStrings' have different lengths"), - .nixCode = NixCode { .errPos = pos } - }); + throw EvalError({ + .hint = hintfmt("'from' and 'to' arguments to 'replaceStrings' have different lengths"), + .nixCode = NixCode { .errPos = pos } + }); vector from; from.reserve(args[0]->listSize()); diff --git a/src/libexpr/primops/context.cc b/src/libexpr/primops/context.cc index 7f895fc01..efa2e9576 100644 --- a/src/libexpr/primops/context.cc +++ b/src/libexpr/primops/context.cc @@ -146,11 +146,10 @@ static void prim_appendContext(EvalState & state, const Pos & pos, Value * * arg auto sAllOutputs = state.symbols.create("allOutputs"); for (auto & i : *args[1]->attrs) { if (!state.store->isStorePath(i.name)) - throw EvalError( - ErrorInfo { - .hint = hintfmt("Context key '%s' is not a store path", i.name), - .nixCode = NixCode { .errPos = *i.pos } - }); + throw EvalError({ + .hint = hintfmt("Context key '%s' is not a store path", i.name), + .nixCode = NixCode { .errPos = *i.pos } + }); if (!settings.readOnlyMode) state.store->ensurePath(state.store->parseStorePath(i.name)); state.forceAttrs(*i.value, *i.pos); @@ -164,11 +163,10 @@ static void prim_appendContext(EvalState & state, const Pos & pos, Value * * arg if (iter != i.value->attrs->end()) { if (state.forceBool(*iter->value, *iter->pos)) { if (!isDerivation(i.name)) { - throw EvalError( - ErrorInfo { - .hint = hintfmt("Tried to add all-outputs context of %s, which is not a derivation, to a string", i.name), - .nixCode = NixCode { .errPos = *i.pos } - }); + throw EvalError({ + .hint = hintfmt("Tried to add all-outputs context of %s, which is not a derivation, to a string", i.name), + .nixCode = NixCode { .errPos = *i.pos } + }); } context.insert("=" + string(i.name)); } @@ -178,11 +176,10 @@ static void prim_appendContext(EvalState & state, const Pos & pos, Value * * arg if (iter != i.value->attrs->end()) { state.forceList(*iter->value, *iter->pos); if (iter->value->listSize() && !isDerivation(i.name)) { - throw EvalError( - ErrorInfo { - .hint = hintfmt("Tried to add derivation output context of %s, which is not a derivation, to a string", i.name), - .nixCode = NixCode { .errPos = *i.pos } - }); + throw EvalError({ + .hint = hintfmt("Tried to add derivation output context of %s, which is not a derivation, to a string", i.name), + .nixCode = NixCode { .errPos = *i.pos } + }); } for (unsigned int n = 0; n < iter->value->listSize(); ++n) { auto name = state.forceStringNoCtx(*iter->value->listElems()[n], *iter->pos); diff --git a/src/libexpr/primops/fetchGit.cc b/src/libexpr/primops/fetchGit.cc index 52826b56c..dd7229a3d 100644 --- a/src/libexpr/primops/fetchGit.cc +++ b/src/libexpr/primops/fetchGit.cc @@ -35,19 +35,17 @@ static void prim_fetchGit(EvalState & state, const Pos & pos, Value * * args, Va else if (n == "submodules") fetchSubmodules = state.forceBool(*attr.value, *attr.pos); else - throw EvalError( - ErrorInfo { - .hint = hintfmt("unsupported argument '%s' to 'fetchGit'", attr.name), - .nixCode = NixCode { .errPos = *attr.pos } - }); + throw EvalError({ + .hint = hintfmt("unsupported argument '%s' to 'fetchGit'", attr.name), + .nixCode = NixCode { .errPos = *attr.pos } + }); } if (url.empty()) - throw EvalError( - ErrorInfo { - .hint = hintfmt("'url' argument required"), - .nixCode = NixCode { .errPos = pos } - }); + throw EvalError({ + .hint = hintfmt("'url' argument required"), + .nixCode = NixCode { .errPos = pos } + }); } else url = state.coerceToString(pos, *args[0], context, false, false); diff --git a/src/libexpr/primops/fetchMercurial.cc b/src/libexpr/primops/fetchMercurial.cc index bb008ba6b..9bace8f89 100644 --- a/src/libexpr/primops/fetchMercurial.cc +++ b/src/libexpr/primops/fetchMercurial.cc @@ -38,19 +38,17 @@ static void prim_fetchMercurial(EvalState & state, const Pos & pos, Value * * ar else if (n == "name") name = state.forceStringNoCtx(*attr.value, *attr.pos); else - throw EvalError( - ErrorInfo { - .hint = hintfmt("unsupported argument '%s' to 'fetchMercurial'", attr.name), - .nixCode = NixCode { .errPos = *attr.pos } - }); + throw EvalError({ + .hint = hintfmt("unsupported argument '%s' to 'fetchMercurial'", attr.name), + .nixCode = NixCode { .errPos = *attr.pos } + }); } if (url.empty()) - throw EvalError( - ErrorInfo { - .hint = hintfmt("'url' argument required"), - .nixCode = NixCode { .errPos = pos } - }); + throw EvalError({ + .hint = hintfmt("'url' argument required"), + .nixCode = NixCode { .errPos = pos } + }); } else url = state.coerceToString(pos, *args[0], context, false, false); diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc index 62bc4f433..9be93710a 100644 --- a/src/libexpr/primops/fetchTree.cc +++ b/src/libexpr/primops/fetchTree.cc @@ -66,11 +66,10 @@ static void prim_fetchTree(EvalState & state, const Pos & pos, Value * * args, V } if (!attrs.count("type")) - throw Error( - ErrorInfo { - .hint = hintfmt("attribute 'type' is missing in call to 'fetchTree'"), - .nixCode = NixCode { .errPos = pos } - }); + throw Error({ + .hint = hintfmt("attribute 'type' is missing in call to 'fetchTree'"), + .nixCode = NixCode { .errPos = pos } + }); input = fetchers::inputFromAttrs(attrs); } else @@ -111,20 +110,17 @@ static void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v, else if (n == "name") name = state.forceStringNoCtx(*attr.value, *attr.pos); else - throw EvalError( - ErrorInfo { - .hint = hintfmt("unsupported argument '%s' to '%s'", - attr.name, who), - .nixCode = NixCode { .errPos = *attr.pos } - }); + throw EvalError({ + .hint = hintfmt("unsupported argument '%s' to '%s'", attr.name, who), + .nixCode = NixCode { .errPos = *attr.pos } + }); } if (!url) - throw EvalError( - ErrorInfo { - .hint = hintfmt("'url' argument required"), - .nixCode = NixCode { .errPos = pos } - }); + throw EvalError({ + .hint = hintfmt("'url' argument required"), + .nixCode = NixCode { .errPos = pos } + }); } else url = state.forceStringNoCtx(*args[0], pos); diff --git a/src/libexpr/primops/fromTOML.cc b/src/libexpr/primops/fromTOML.cc index 948069401..7615d1379 100644 --- a/src/libexpr/primops/fromTOML.cc +++ b/src/libexpr/primops/fromTOML.cc @@ -81,11 +81,10 @@ static void prim_fromTOML(EvalState & state, const Pos & pos, Value * * args, Va try { visit(v, parser(tomlStream).parse()); } catch (std::runtime_error & e) { - throw EvalError( - ErrorInfo { - .hint = hintfmt("while parsing a TOML string: %s", e.what()), - .nixCode = NixCode { .errPos = pos } - }); + throw EvalError({ + .hint = hintfmt("while parsing a TOML string: %s", e.what()), + .nixCode = NixCode { .errPos = pos } + }); } } diff --git a/src/libstore/builtins/buildenv.cc b/src/libstore/builtins/buildenv.cc index 6c493ed77..802fb87bc 100644 --- a/src/libstore/builtins/buildenv.cc +++ b/src/libstore/builtins/buildenv.cc @@ -22,10 +22,9 @@ static void createLinks(State & state, const Path & srcDir, const Path & dstDir, srcFiles = readDirectory(srcDir); } catch (SysError & e) { if (e.errNo == ENOTDIR) { - logWarning( - ErrorInfo { - .name = "Create links - directory", - .hint = hintfmt("not including '%s' in the user environment because it's not a directory", srcDir) + logWarning({ + .name = "Create links - directory", + .hint = hintfmt("not including '%s' in the user environment because it's not a directory", srcDir) }); return; } @@ -45,10 +44,9 @@ static void createLinks(State & state, const Path & srcDir, const Path & dstDir, throw SysError("getting status of '%1%'", srcFile); } catch (SysError & e) { if (e.errNo == ENOENT || e.errNo == ENOTDIR) { - logWarning( - ErrorInfo { - .name = "Create links - skipping symlink", - .hint = hintfmt("skipping dangling symlink '%s'", dstFile) + logWarning({ + .name = "Create links - skipping symlink", + .hint = hintfmt("skipping dangling symlink '%s'", dstFile) }); continue; } diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index 92f9328c3..04e3849f7 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -129,12 +129,11 @@ Path LocalFSStore::addPermRoot(const StorePath & storePath, if (settings.checkRootReachability) { auto roots = findRoots(false); if (roots[storePath.clone()].count(gcRoot) == 0) - logWarning( - ErrorInfo { - .name = "GC root", - .hint = hintfmt("warning: '%1%' is not in a directory where the garbage collector looks for roots; " - "therefore, '%2%' might be removed by the garbage collector", - gcRoot, printStorePath(storePath)) + logWarning({ + .name = "GC root", + .hint = hintfmt("warning: '%1%' is not in a directory where the garbage collector looks for roots; " + "therefore, '%2%' might be removed by the garbage collector", + gcRoot, printStorePath(storePath)) }); } diff --git a/src/libstore/sqlite.cc b/src/libstore/sqlite.cc index 16cdb6619..76c822c4e 100644 --- a/src/libstore/sqlite.cc +++ b/src/libstore/sqlite.cc @@ -204,10 +204,10 @@ void handleSQLiteBusy(const SQLiteBusy & e) if (now > lastWarned + 10) { lastWarned = now; - logWarning( - ErrorInfo { .name = "Sqlite busy", - .hint = hintfmt(e.what()) - }); + logWarning({ + .name = "Sqlite busy", + .hint = hintfmt(e.what()) + }); } /* Sleep for a while since retrying the transaction right away diff --git a/src/libutil/error.hh b/src/libutil/error.hh index 8a48fa105..2ba3a3b33 100644 --- a/src/libutil/error.hh +++ b/src/libutil/error.hh @@ -22,7 +22,7 @@ namespace nix { -/* +/* This file defines two main structs/classes used in nix error handling. @@ -106,7 +106,7 @@ protected: mutable std::optional what_; const string& calcWhat() const; - + public: unsigned int status = 1; // exit status @@ -119,9 +119,9 @@ public: { } template - BaseError(const Args & ... args) + BaseError(const std::string & fs, const Args & ... args) : err { .level = lvlError, - .hint = hintfmt(args...) + .hint = hintfmt(fs, args...) } { } @@ -131,7 +131,11 @@ public: } { } - BaseError(ErrorInfo e) + BaseError(ErrorInfo && e) + : err(std::move(e)) + { } + + BaseError(const ErrorInfo & e) : err(e) { } diff --git a/src/libutil/serialise.cc b/src/libutil/serialise.cc index 35f7ee917..c8b71188f 100644 --- a/src/libutil/serialise.cc +++ b/src/libutil/serialise.cc @@ -52,10 +52,10 @@ size_t threshold = 256 * 1024 * 1024; static void warnLargeDump() { - logWarning(ErrorInfo { + logWarning({ .name = "Large path", .description = "dumping very large path (> 256 MiB); this may run out of memory" - }); + }); } diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc index 591fff999..da6f005a3 100755 --- a/src/nix-build/nix-build.cc +++ b/src/nix-build/nix-build.cc @@ -368,12 +368,11 @@ static void _main(int argc, char * * argv) shell = drv->queryOutPath() + "/bin/bash"; } catch (Error & e) { - logWarning( - ErrorInfo { - .name = "bashInteractive", - .hint = hintfmt("%s; will use bash from your environment", - (e.info().hint ? e.info().hint->str() : "")) - }); + logWarning({ + .name = "bashInteractive", + .hint = hintfmt("%s; will use bash from your environment", + (e.info().hint ? e.info().hint->str() : "")) + }); shell = "bash"; } } diff --git a/src/nix/upgrade-nix.cc b/src/nix/upgrade-nix.cc index fdf94e5a3..a880bdae0 100644 --- a/src/nix/upgrade-nix.cc +++ b/src/nix/upgrade-nix.cc @@ -68,10 +68,9 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand if (dryRun) { stopProgressBar(); - logWarning( - ErrorInfo { - .name = "Version update", - .hint = hintfmt("would upgrade to version %s", version) + logWarning({ + .name = "Version update", + .hint = hintfmt("would upgrade to version %s", version) }); return; } From e14e62fddde3b00ee82a8da29725f571ad8ecee1 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 15 Jun 2020 14:12:39 +0200 Subject: [PATCH 31/62] Remove trailing whitespace --- src/build-remote/build-remote.cc | 2 +- src/libexpr/attr-path.cc | 4 +-- src/libexpr/lexer.l | 1 - src/libexpr/nixexpr.cc | 2 +- src/libmain/progress-bar.cc | 2 +- src/libstore/daemon.cc | 2 +- src/libstore/filetransfer.cc | 4 +-- src/libstore/local-store.cc | 10 +++---- src/libstore/optimise-store.cc | 6 ++-- src/libstore/store-api.cc | 2 +- src/libutil/error.cc | 2 +- src/libutil/logging.cc | 2 +- src/libutil/util.cc | 2 +- src/nix-daemon/nix-daemon.cc | 30 +++++++++---------- src/nix-env/nix-env.cc | 8 ++--- src/nix-store/nix-store.cc | 4 +-- src/nix/verify.cc | 6 ++-- .../resolve-system-dependencies.cc | 8 ++--- 18 files changed, 48 insertions(+), 49 deletions(-) diff --git a/src/build-remote/build-remote.cc b/src/build-remote/build-remote.cc index 49b35a4e9..e07117496 100644 --- a/src/build-remote/build-remote.cc +++ b/src/build-remote/build-remote.cc @@ -200,7 +200,7 @@ static int _main(int argc, char * * argv) } catch (std::exception & e) { auto msg = chomp(drainFD(5, false)); - logError({ + logError({ .name = "Remote build", .hint = hintfmt("cannot build on '%s': %s%s", bestMachine->storeUri, e.what(), diff --git a/src/libexpr/attr-path.cc b/src/libexpr/attr-path.cc index 9a9531a3f..8980bc09d 100644 --- a/src/libexpr/attr-path.cc +++ b/src/libexpr/attr-path.cc @@ -62,7 +62,7 @@ std::pair findAlongAttrPath(EvalState & state, const string & attr throw TypeError( "the expression selected by the selection path '%1%' should be a set but is %2%", attrPath, - showType(*v)); + showType(*v)); if (attr.empty()) throw Error("empty attribute name in selection path '%1%'", attrPath); @@ -79,7 +79,7 @@ std::pair findAlongAttrPath(EvalState & state, const string & attr throw TypeError( "the expression selected by the selection path '%1%' should be a list but is %2%", attrPath, - showType(*v)); + showType(*v)); if (attrIndex >= v->listSize()) throw AttrPathNotFound("list index %1% in selection path '%2%' is out of range", attrIndex, attrPath); diff --git a/src/libexpr/lexer.l b/src/libexpr/lexer.l index 85376a08f..f6e83926b 100644 --- a/src/libexpr/lexer.l +++ b/src/libexpr/lexer.l @@ -219,4 +219,3 @@ or { return OR_KW; } } %% - diff --git a/src/libexpr/nixexpr.cc b/src/libexpr/nixexpr.cc index 5b2dd9751..b4b65883d 100644 --- a/src/libexpr/nixexpr.cc +++ b/src/libexpr/nixexpr.cc @@ -267,7 +267,7 @@ void ExprVar::bindVars(const StaticEnv & env) /* Otherwise, the variable must be obtained from the nearest enclosing `with'. If there is no `with', then we can issue an "undefined variable" error now. */ - if (withLevel == -1) + if (withLevel == -1) throw UndefinedVarError({ .hint = hintfmt("undefined variable '%1%'", name), .nixCode = NixCode { .errPos = pos } diff --git a/src/libmain/progress-bar.cc b/src/libmain/progress-bar.cc index 20d9915a0..8d0421c2f 100644 --- a/src/libmain/progress-bar.cc +++ b/src/libmain/progress-bar.cc @@ -133,7 +133,7 @@ public: { auto state(state_.lock()); - std::stringstream oss; + std::stringstream oss; oss << ei; log(*state, ei.level, oss.str()); diff --git a/src/libstore/daemon.cc b/src/libstore/daemon.cc index 172cfe3cb..620722516 100644 --- a/src/libstore/daemon.cc +++ b/src/libstore/daemon.cc @@ -77,7 +77,7 @@ struct TunnelLogger : public Logger { if (ei.level > verbosity) return; - std::stringstream oss; + std::stringstream oss; oss << ei; StringSink buf; diff --git a/src/libstore/filetransfer.cc b/src/libstore/filetransfer.cc index 6ca3393ab..601cb858a 100644 --- a/src/libstore/filetransfer.cc +++ b/src/libstore/filetransfer.cc @@ -599,9 +599,9 @@ struct curlFileTransfer : public FileTransfer workerThreadMain(); } catch (nix::Interrupted & e) { } catch (std::exception & e) { - logError({ + logError({ .name = "File transfer", - .hint = hintfmt("unexpected error in download thread: %s", + .hint = hintfmt("unexpected error in download thread: %s", e.what()) }); } diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 5521b8633..f5c5bd9b7 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -87,7 +87,7 @@ LocalStore::LocalStore(const Params & params) struct group * gr = getgrnam(settings.buildUsersGroup.get().c_str()); if (!gr) - logError({ + logError({ .name = "'build-users-group' not found", .hint = hintfmt( "warning: the group '%1%' specified in 'build-users-group' does not exist", @@ -1223,7 +1223,7 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair) Path linkPath = linksDir + "/" + link.name; string hash = hashPath(htSHA256, linkPath).first.to_string(Base32, false); if (hash != link.name) { - logError({ + logError({ .name = "Invalid hash", .hint = hintfmt( "link '%s' was modified! expected hash '%s', got '%s'", @@ -1261,7 +1261,7 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair) auto current = hashSink->finish(); if (info->narHash != nullHash && info->narHash != current.first) { - logError({ + logError({ .name = "Invalid hash - path modified", .hint = hintfmt("path '%s' was modified! expected hash '%s', got '%s'", printStorePath(i), info->narHash.to_string(Base32, true), current.first.to_string(Base32, true)) @@ -1316,7 +1316,7 @@ void LocalStore::verifyPath(const Path & pathS, const StringSet & store, if (!done.insert(pathS).second) return; if (!isStorePath(pathS)) { - logError({ + logError({ .name = "Nix path not found", .hint = hintfmt("path '%s' is not in the Nix store", pathS) }); @@ -1342,7 +1342,7 @@ void LocalStore::verifyPath(const Path & pathS, const StringSet & store, auto state(_state.lock()); invalidatePath(*state, path); } else { - logError({ + logError({ .name = "Missing path with referrers", .hint = hintfmt("path '%s' disappeared, but it still has valid referrers!", pathS) }); diff --git a/src/libstore/optimise-store.cc b/src/libstore/optimise-store.cc index d760d110c..b2b2412a3 100644 --- a/src/libstore/optimise-store.cc +++ b/src/libstore/optimise-store.cc @@ -130,7 +130,7 @@ void LocalStore::optimisePath_(Activity * act, OptimiseStats & stats, NixOS (example: $fontconfig/var/cache being modified). Skip those files. FIXME: check the modification time. */ if (S_ISREG(st.st_mode) && (st.st_mode & S_IWUSR)) { - logWarning({ + logWarning({ .name = "Suspicious file", .hint = hintfmt("skipping suspicious writable file '%1%'", path) }); @@ -197,7 +197,7 @@ void LocalStore::optimisePath_(Activity * act, OptimiseStats & stats, } if (st.st_size != stLink.st_size) { - logWarning({ + logWarning({ .name = "Corrupted link", .hint = hintfmt("removing corrupted link '%1%'", linkPath) }); @@ -235,7 +235,7 @@ void LocalStore::optimisePath_(Activity * act, OptimiseStats & stats, /* Atomically replace the old file with the new hard link. */ if (rename(tempLink.c_str(), path.c_str()) == -1) { if (unlink(tempLink.c_str()) == -1) - logError({ + logError({ .name = "Unlink error", .hint = hintfmt("unable to unlink '%1%'", tempLink) }); diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index 464261010..e23a9ca50 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -777,7 +777,7 @@ bool ValidPathInfo::isContentAddressed(const Store & store) const auto warn = [&]() { logWarning( ErrorInfo{ - .name = "Path not content-addressed", + .name = "Path not content-addressed", .hint = hintfmt("path '%s' claims to be content-addressed but isn't", store.printStorePath(path)) }); }; diff --git a/src/libutil/error.cc b/src/libutil/error.cc index 1fcb8111c..cb5fe70bf 100644 --- a/src/libutil/error.cc +++ b/src/libutil/error.cc @@ -61,7 +61,7 @@ void printCodeLines(std::ostream &out, const string &prefix, const NixCode &nixC { // previous line of code. if (nixCode.prevLineOfCode.has_value()) { - out << std::endl + out << std::endl << fmt("%1% %|2$5d|| %3%", prefix, (nixCode.errPos.line - 1), diff --git a/src/libutil/logging.cc b/src/libutil/logging.cc index 108dc3bd1..105fadb15 100644 --- a/src/libutil/logging.cc +++ b/src/libutil/logging.cc @@ -273,7 +273,7 @@ bool handleJSONLogMessage(const std::string & msg, } } catch (std::exception & e) { - logError({ + logError({ .name = "Json log message", .hint = hintfmt("bad log message from builder: %s", e.what()) }); diff --git a/src/libutil/util.cc b/src/libutil/util.cc index a2281237b..667dd2edb 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -314,7 +314,7 @@ string readFile(const Path & path) void readFile(const Path & path, Sink & sink) { AutoCloseFD fd = open(path.c_str(), O_RDONLY | O_CLOEXEC); - if (!fd) + if (!fd) throw SysError("opening file '%s'", path); drainFD(fd.get(), sink); } diff --git a/src/nix-daemon/nix-daemon.cc b/src/nix-daemon/nix-daemon.cc index 582c78d14..bcb86cbce 100644 --- a/src/nix-daemon/nix-daemon.cc +++ b/src/nix-daemon/nix-daemon.cc @@ -36,7 +36,7 @@ using namespace nix::daemon; #define SPLICE_F_MOVE 0 static ssize_t splice(int fd_in, void *off_in, int fd_out, void *off_out, size_t len, unsigned int flags) { - // We ignore most parameters, we just have them for conformance with the linux syscall + // We ignore most parameters, we just have them for conformance with the linux syscall std::vector buf(8192); auto read_count = read(fd_in, buf.data(), buf.size()); if (read_count == -1) @@ -57,7 +57,7 @@ static void sigChldHandler(int sigNo) { // Ensure we don't modify errno of whatever we've interrupted auto saved_errno = errno; - // Reap all dead children. + // Reap all dead children. while (waitpid(-1, 0, WNOHANG) > 0) ; errno = saved_errno; } @@ -106,7 +106,7 @@ struct PeerInfo }; -// Get the identity of the caller, if possible. +// Get the identity of the caller, if possible. static PeerInfo getPeerInfo(int remote) { PeerInfo peer = { false, 0, false, 0, false, 0 }; @@ -154,12 +154,12 @@ static void daemonLoop(char * * argv) if (chdir("/") == -1) throw SysError("cannot change current directory"); - // Get rid of children automatically; don't let them become zombies. + // Get rid of children automatically; don't let them become zombies. setSigChldAction(true); AutoCloseFD fdSocket; - // Handle socket-based activation by systemd. + // Handle socket-based activation by systemd. auto listenFds = getEnv("LISTEN_FDS"); if (listenFds) { if (getEnv("LISTEN_PID") != std::to_string(getpid()) || listenFds != "1") @@ -168,17 +168,17 @@ static void daemonLoop(char * * argv) closeOnExec(fdSocket.get()); } - // Otherwise, create and bind to a Unix domain socket. + // Otherwise, create and bind to a Unix domain socket. else { createDirs(dirOf(settings.nixDaemonSocketFile)); fdSocket = createUnixDomainSocket(settings.nixDaemonSocketFile, 0666); } - // Loop accepting connections. + // Loop accepting connections. while (1) { try { - // Accept a connection. + // Accept a connection. struct sockaddr_un remoteAddr; socklen_t remoteAddrLen = sizeof(remoteAddr); @@ -214,7 +214,7 @@ static void daemonLoop(char * * argv) % (peer.pidKnown ? std::to_string(peer.pid) : "") % (peer.uidKnown ? user : "")); - // Fork a child to handle the connection. + // Fork a child to handle the connection. ProcessOptions options; options.errorPrefix = "unexpected Nix daemon error: "; options.dieWithParent = false; @@ -223,20 +223,20 @@ static void daemonLoop(char * * argv) startProcess([&]() { fdSocket = -1; - // Background the daemon. + // Background the daemon. if (setsid() == -1) throw SysError("creating a new session"); - // Restore normal handling of SIGCHLD. + // Restore normal handling of SIGCHLD. setSigChldAction(false); - // For debugging, stuff the pid into argv[1]. + // For debugging, stuff the pid into argv[1]. if (peer.pidKnown && argv[1]) { string processName = std::to_string(peer.pid); strncpy(argv[1], processName.c_str(), strlen(argv[1])); } - // Handle the connection. + // Handle the connection. FdSource from(remote.get()); FdSink to(remote.get()); processConnection(openUncachedStore(), from, to, trusted, NotRecursive, user, peer.uid); @@ -263,7 +263,7 @@ static int _main(int argc, char * * argv) parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) { if (*arg == "--daemon") - ; // ignored for backwards compatibility + ; // ignored for backwards compatibility else if (*arg == "--help") showManPage("nix-daemon"); else if (*arg == "--version") @@ -278,7 +278,7 @@ static int _main(int argc, char * * argv) if (stdio) { if (getStoreType() == tDaemon) { - // Forward on this connection to the real daemon + // Forward on this connection to the real daemon auto socketPath = settings.nixDaemonSocketFile; auto s = socket(PF_UNIX, SOCK_STREAM, 0); if (s == -1) diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index 7ab5ba500..2c27d97f5 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -123,7 +123,7 @@ static void getAllExprs(EvalState & state, if (hasSuffix(attrName, ".nix")) attrName = string(attrName, 0, attrName.size() - 4); if (!attrs.insert(attrName).second) { - logError({ + logError({ .name = "Name collision", .hint = hintfmt("warning: name collision in input Nix expressions, skipping '%1%'", path2) }); @@ -874,7 +874,7 @@ static void queryJSON(Globals & globals, vector & elems) auto placeholder = metaObj.placeholder(j); Value * v = i.queryMeta(j); if (!v) { - logError({ + logError({ .name = "Invalid meta attribute", .hint = hintfmt("derivation '%s' has invalid meta attribute '%s'", i.queryName(), j) @@ -1128,8 +1128,8 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs) XMLAttrs attrs2; attrs2["name"] = j; Value * v = i.queryMeta(j); - if (!v) - logError({ + if (!v) + logError({ .name = "Invalid meta attribute", .hint = hintfmt( "derivation '%s' has invalid meta attribute '%s'", diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc index dea53b52f..6d2139526 100644 --- a/src/nix-store/nix-store.cc +++ b/src/nix-store/nix-store.cc @@ -704,7 +704,7 @@ static void opVerify(Strings opFlags, Strings opArgs) else throw UsageError("unknown flag '%1%'", i); if (store->verifyStore(checkContents, repair)) { - logWarning({ + logWarning({ .name = "Store consistency", .description = "not all errors were fixed" }); @@ -729,7 +729,7 @@ static void opVerifyPath(Strings opFlags, Strings opArgs) store->narFromPath(path, sink); auto current = sink.finish(); if (current.first != info->narHash) { - logError({ + logError({ .name = "Hash mismatch", .hint = hintfmt( "path '%s' was modified! expected hash '%s', got '%s'", diff --git a/src/nix/verify.cc b/src/nix/verify.cc index 246b4b480..001401ac2 100644 --- a/src/nix/verify.cc +++ b/src/nix/verify.cc @@ -99,12 +99,12 @@ struct CmdVerify : StorePathsCommand if (hash.first != info->narHash) { corrupted++; act2.result(resCorruptedPath, store->printStorePath(info->path)); - logError({ + logError({ .name = "Hash error - path modified", .hint = hintfmt( "path '%s' was modified! expected hash '%s', got '%s'", store->printStorePath(info->path), - info->narHash.to_string(Base32, true), + info->narHash.to_string(Base32, true), hash.first.to_string(Base32, true)) }); } @@ -154,7 +154,7 @@ struct CmdVerify : StorePathsCommand if (!good) { untrusted++; act2.result(resUntrustedPath, store->printStorePath(info->path)); - logError({ + logError({ .name = "Untrusted path", .hint = hintfmt("path '%s' is untrusted", store->printStorePath(info->path)) diff --git a/src/resolve-system-dependencies/resolve-system-dependencies.cc b/src/resolve-system-dependencies/resolve-system-dependencies.cc index 82feacb3d..434ad80a6 100644 --- a/src/resolve-system-dependencies/resolve-system-dependencies.cc +++ b/src/resolve-system-dependencies/resolve-system-dependencies.cc @@ -39,7 +39,7 @@ std::set runResolver(const Path & filename) throw SysError("statting '%s'", filename); if (!S_ISREG(st.st_mode)) { - logError({ + logError({ .name = "Regular MACH file", .hint = hintfmt("file '%s' is not a regular file", filename) }); @@ -47,7 +47,7 @@ std::set runResolver(const Path & filename) } if (st.st_size < sizeof(mach_header_64)) { - logError({ + logError({ .name = "File too short", .hint = hintfmt("file '%s' is too short for a MACH binary", filename) }); @@ -72,7 +72,7 @@ std::set runResolver(const Path & filename) } } if (mach64_offset == 0) { - logError({ + logError({ .name = "No mach64 blobs", .hint = hintfmt("Could not find any mach64 blobs in file '%1%', continuing...", filename) }); @@ -81,7 +81,7 @@ std::set runResolver(const Path & filename) } else if (magic == MH_MAGIC_64 || magic == MH_CIGAM_64) { mach64_offset = 0; } else { - logError({ + logError({ .name = "Magic number", .hint = hintfmt("Object file has unknown magic number '%1%', skipping it...", magic) }); From 5ed5d7acbd00298df7b4e3a638d731143084da2e Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 15 Jun 2020 16:03:29 +0200 Subject: [PATCH 32/62] Improve "waiting for locks" messages These are now shown in the progress bar. Closes #3577. --- src/libmain/progress-bar.cc | 2 +- src/libstore/build.cc | 22 +++++++++++++++++++--- src/libutil/logging.hh | 1 + 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/libmain/progress-bar.cc b/src/libmain/progress-bar.cc index 8d0421c2f..6dfc3a4d3 100644 --- a/src/libmain/progress-bar.cc +++ b/src/libmain/progress-bar.cc @@ -156,7 +156,7 @@ public: { auto state(state_.lock()); - if (lvl <= verbosity && !s.empty()) + if (lvl <= verbosity && !s.empty() && type != actBuildWaiting) log(*state, lvl, s + "..."); state->activities.emplace_back(ActInfo()); diff --git a/src/libstore/build.cc b/src/libstore/build.cc index de393e837..2eb78591b 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -869,6 +869,9 @@ private: std::unique_ptr act; + /* Activity that denotes waiting for a lock. */ + std::unique_ptr actLock; + std::map builderActivities; /* The remote machine on which we're building. */ @@ -1439,10 +1442,15 @@ void DerivationGoal::tryToBuild() lockFiles.insert(worker.store.Store::toRealPath(outPath)); if (!outputLocks.lockPaths(lockFiles, "", false)) { + if (!actLock) + actLock = std::make_unique(*logger, lvlWarn, actBuildWaiting, + fmt("waiting for lock on %s", yellowtxt(showPaths(lockFiles)))); worker.waitForAWhile(shared_from_this()); return; } + actLock.reset(); + /* Now check again whether the outputs are valid. This is because another process may have started building in parallel. After it has finished and released the locks, we can (and should) @@ -1481,6 +1489,7 @@ void DerivationGoal::tryToBuild() case rpAccept: /* Yes, it has started doing so. Wait until we get EOF from the hook. */ + actLock.reset(); result.startTime = time(0); // inexact state = &DerivationGoal::buildDone; started(); @@ -1488,6 +1497,9 @@ void DerivationGoal::tryToBuild() case rpPostpone: /* Not now; wait until at least one child finishes or the wake-up timeout expires. */ + if (!actLock) + actLock = std::make_unique(*logger, lvlWarn, actBuildWaiting, + fmt("waiting for a machine to build '%s'", yellowtxt(worker.store.printStorePath(drvPath)))); worker.waitForAWhile(shared_from_this()); outputLocks.unlock(); return; @@ -1497,6 +1509,8 @@ void DerivationGoal::tryToBuild() } } + actLock.reset(); + /* Make sure that we are allowed to start a build. If this derivation prefers to be done locally, do it even if maxBuildJobs is 0. */ @@ -1524,7 +1538,9 @@ void DerivationGoal::tryLocalBuild() { uid. */ buildUser->kill(); } else { - debug("waiting for build users"); + if (!actLock) + actLock = std::make_unique(*logger, lvlWarn, actBuildWaiting, + fmt("waiting for UID to build '%s'", yellowtxt(worker.store.printStorePath(drvPath)))); worker.waitForAWhile(shared_from_this()); return; } @@ -1535,6 +1551,8 @@ void DerivationGoal::tryLocalBuild() { #endif } + actLock.reset(); + try { /* Okay, we have to build. */ @@ -4863,8 +4881,6 @@ void Worker::waitForInput() up after a few seconds at most. */ if (!waitingForAWhile.empty()) { useTimeout = true; - if (lastWokenUp == steady_time_point::min()) - printInfo("waiting for locks, build slots or build users..."); if (lastWokenUp == steady_time_point::min() || lastWokenUp > before) lastWokenUp = before; timeout = std::max(1L, (long) std::chrono::duration_cast( diff --git a/src/libutil/logging.hh b/src/libutil/logging.hh index b99b246c3..b1583eced 100644 --- a/src/libutil/logging.hh +++ b/src/libutil/logging.hh @@ -18,6 +18,7 @@ typedef enum { actSubstitute = 108, actQueryPathInfo = 109, actPostBuildHook = 110, + actBuildWaiting = 111, } ActivityType; typedef enum { From ccfa6b3eee9f5e613152a4b373f67ff05696adf8 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 15 Jun 2020 16:12:27 +0200 Subject: [PATCH 33/62] Give better error message about <...> in pure eval mode --- src/libexpr/parser.y | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index a1188dec0..a639be64e 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -689,7 +689,10 @@ Path EvalState::findFile(SearchPath & searchPath, const string & path, const Pos if (pathExists(res)) return canonPath(res); } throw ThrownError({ - .hint = hintfmt("file '%1%' was not found in the Nix search path (add it using $NIX_PATH or -I)", path), + .hint = hintfmt(evalSettings.pureEval + ? "cannot look up '<%s>' in pure evaluation mode (use '--impure' to override)" + : "file '%s' was not found in the Nix search path (add it using $NIX_PATH or -I)", + path), .nixCode = NixCode { .errPos = pos } }); } From 31707735b699db6dfd78e8bb8e655c3d5e6e0ba5 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 15 Jun 2020 16:47:21 +0200 Subject: [PATCH 34/62] Remove unnecessary amDone() overrides --- src/libstore/build.cc | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 2eb78591b..2a34cfbb7 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -187,7 +187,7 @@ public: protected: - virtual void amDone(ExitCode result); + void amDone(ExitCode result); }; @@ -1009,11 +1009,6 @@ private: void repairClosure(); - void amDone(ExitCode result) override - { - Goal::amDone(result); - } - void started(); void done(BuildResult::Status status, const string & msg = ""); @@ -4335,11 +4330,6 @@ public: void handleEOF(int fd) override; StorePath getStorePath() { return storePath.clone(); } - - void amDone(ExitCode result) override - { - Goal::amDone(result); - } }; From 4e995bc8a66e5486be83c935bd939726ac39cab3 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 15 Jun 2020 18:01:05 +0200 Subject: [PATCH 35/62] Always hide the progress bar on exit --- src/libmain/progress-bar.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/libmain/progress-bar.cc b/src/libmain/progress-bar.cc index 6dfc3a4d3..95a9187de 100644 --- a/src/libmain/progress-bar.cc +++ b/src/libmain/progress-bar.cc @@ -111,10 +111,7 @@ public: auto state(state_.lock()); if (!state->active) return; state->active = false; - std::string status = getStatus(*state); writeToStderr("\r\e[K"); - if (status != "") - writeToStderr("[" + status + "]\n"); updateCV.notify_one(); quitCV.notify_one(); } From f20bb983cab168bd9fe4f4ad560a64aeb4b19f07 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 15 Jun 2020 18:16:03 +0200 Subject: [PATCH 36/62] Cleanup --- src/libutil/error.cc | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/libutil/error.cc b/src/libutil/error.cc index cb5fe70bf..da11d1ffd 100644 --- a/src/libutil/error.cc +++ b/src/libutil/error.cc @@ -105,7 +105,7 @@ void printCodeLines(std::ostream &out, const string &prefix, const NixCode &nixC std::ostream& operator<<(std::ostream &out, const ErrorInfo &einfo) { - int errwidth = 80; + size_t errwidth = 80; string prefix = ""; string levelString; @@ -158,12 +158,10 @@ std::ostream& operator<<(std::ostream &out, const ErrorInfo &einfo) } } - int ndl = prefix.length() + levelString.length() + 3 + einfo.name.length() + einfo.programName.value_or("").length(); - int dashwidth = ndl > (errwidth - 3) ? 3 : errwidth - ndl; + auto ndl = prefix.length() + levelString.length() + 3 + einfo.name.length() + einfo.programName.value_or("").length(); + auto dashwidth = ndl > (errwidth - 3) ? 3 : errwidth - ndl; - string dashes; - for (int i = 0; i < dashwidth; ++i) - dashes.append("-"); + std::string dashes(dashwidth, '-'); // divider. if (einfo.name != "") From 8b099812eab7ccad9ebc6906450b637044de9369 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 15 Jun 2020 18:18:02 +0200 Subject: [PATCH 37/62] Respect terminal width printing error messages --- src/libutil/error.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libutil/error.cc b/src/libutil/error.cc index da11d1ffd..0fad9ae42 100644 --- a/src/libutil/error.cc +++ b/src/libutil/error.cc @@ -105,7 +105,7 @@ void printCodeLines(std::ostream &out, const string &prefix, const NixCode &nixC std::ostream& operator<<(std::ostream &out, const ErrorInfo &einfo) { - size_t errwidth = 80; + auto errwidth = std::max(getWindowSize().second, 20); string prefix = ""; string levelString; From 24a3208247c248956c5815554804da1bf9763ece Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 15 Jun 2020 18:20:05 +0200 Subject: [PATCH 38/62] Include only the base name of the program in error messages --- src/libmain/shared.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc index 0f2c189a6..dc6d5e413 100644 --- a/src/libmain/shared.cc +++ b/src/libmain/shared.cc @@ -290,7 +290,7 @@ int handleExceptions(const string & programName, std::function fun) { ReceiveInterrupts receiveInterrupts; // FIXME: need better place for this - ErrorInfo::programName = programName; + ErrorInfo::programName = baseNameOf(programName); string error = ANSI_RED "error:" ANSI_NORMAL " "; try { From a588b6b19d93fe80deb8518562b7a483fd4c50bc Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 15 Jun 2020 19:25:35 +0200 Subject: [PATCH 39/62] Print only one error message if a build fails E.g. instead of error: --- BuildError ----------------------------------------------- nix builder for '/nix/store/03nk0a3n8h2948k4lqfgnnmym7knkcma-foo.drv' failed with exit code 1 error: --- Error ---------------------------------------------------- nix build of '/nix/store/03nk0a3n8h2948k4lqfgnnmym7knkcma-foo.drv' failed we now get error: --- Error ---------------------------------------------------- nix builder for '/nix/store/03nk0a3n8h2948k4lqfgnnmym7knkcma-foo.drv' failed with exit code 1 --- src/libstore/build.cc | 138 ++++++++++++++++++++---------------------- 1 file changed, 67 insertions(+), 71 deletions(-) diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 2a34cfbb7..8ad2ca4f3 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -104,13 +104,10 @@ typedef std::map WeakGoalMap; -class Goal : public std::enable_shared_from_this +struct Goal : public std::enable_shared_from_this { -public: typedef enum {ecBusy, ecSuccess, ecFailed, ecNoSubstituters, ecIncompleteClosure} ExitCode; -protected: - /* Backlink to the worker. */ Worker & worker; @@ -138,6 +135,9 @@ protected: /* Whether the goal is finished. */ ExitCode exitCode; + /* Exception containing an error message, if any. */ + std::optional ex; + Goal(Worker & worker) : worker(worker) { nrFailed = nrNoSubstituters = nrIncompleteClosure = 0; @@ -149,7 +149,6 @@ protected: trace("goal destroyed"); } -public: virtual void work() = 0; void addWaitee(GoalPtr waitee); @@ -173,21 +172,14 @@ public: return name; } - ExitCode getExitCode() - { - return exitCode; - } - /* Callback in case of a timeout. It should wake up its waiters, get rid of any running child processes that are being monitored by the worker (important!), etc. */ - virtual void timedOut() = 0; + virtual void timedOut(Error && ex) = 0; virtual string key() = 0; -protected: - - void amDone(ExitCode result); + void amDone(ExitCode result, std::optional ex = {}); }; @@ -392,8 +384,7 @@ void Goal::waiteeDone(GoalPtr waitee, ExitCode result) assert(waitees.find(waitee) != waitees.end()); waitees.erase(waitee); - trace(format("waitee '%1%' done; %2% left") % - waitee->name % waitees.size()); + trace(fmt("waitee '%s' done; %d left", waitee->name, waitees.size())); if (result == ecFailed || result == ecNoSubstituters || result == ecIncompleteClosure) ++nrFailed; @@ -418,12 +409,20 @@ void Goal::waiteeDone(GoalPtr waitee, ExitCode result) } -void Goal::amDone(ExitCode result) +void Goal::amDone(ExitCode result, std::optional ex) { trace("done"); assert(exitCode == ecBusy); assert(result == ecSuccess || result == ecFailed || result == ecNoSubstituters || result == ecIncompleteClosure); exitCode = result; + + if (ex) { + if (!waiters.empty()) + logError(ex->info()); + else + this->ex = std::move(*ex); + } + for (auto & i : waiters) { GoalPtr goal = i.lock(); if (goal) goal->waiteeDone(shared_from_this(), result); @@ -910,7 +909,7 @@ public: /* Whether we need to perform hash rewriting if there are valid output paths. */ bool needsHashRewrite(); - void timedOut() override; + void timedOut(Error && ex) override; string key() override { @@ -1011,7 +1010,9 @@ private: void started(); - void done(BuildResult::Status status, const string & msg = ""); + void done( + BuildResult::Status status, + std::optional ex = {}); StorePathSet exportReferences(const StorePathSet & storePaths); }; @@ -1105,10 +1106,10 @@ void DerivationGoal::killChild() } -void DerivationGoal::timedOut() +void DerivationGoal::timedOut(Error && ex) { killChild(); - done(BuildResult::TimedOut); + done(BuildResult::TimedOut, ex); } @@ -1156,11 +1157,7 @@ void DerivationGoal::loadDerivation() trace("loading derivation"); if (nrFailed != 0) { - logError({ - .name = "missing derivation during build", - .hint = hintfmt("cannot build missing derivation '%s'", worker.store.printStorePath(drvPath)) - }); - done(BuildResult::MiscFailure); + done(BuildResult::MiscFailure, Error("cannot build missing derivation '%s'", worker.store.printStorePath(drvPath))); return; } @@ -1349,13 +1346,9 @@ void DerivationGoal::inputsRealised() if (nrFailed != 0) { if (!useDerivation) throw Error("some dependencies of '%s' are missing", worker.store.printStorePath(drvPath)); - logError({ - .name = "Dependencies could not be built", - .hint = hintfmt( - "cannot build derivation '%s': %s dependencies couldn't be built", - worker.store.printStorePath(drvPath), nrFailed) - }); - done(BuildResult::DependencyFailed); + done(BuildResult::DependencyFailed, Error( + "%s dependencies of derivation '%s' failed to build", + nrFailed, worker.store.printStorePath(drvPath))); return; } @@ -1554,11 +1547,10 @@ void DerivationGoal::tryLocalBuild() { startBuilder(); } catch (BuildError & e) { - logError(e.info()); outputLocks.unlock(); buildUser.reset(); worker.permanentFailure = true; - done(BuildResult::InputRejected, e.msg()); + done(BuildResult::InputRejected, e); return; } @@ -1670,7 +1662,7 @@ void DerivationGoal::buildDone() } auto msg = fmt("builder for '%s' %s", - worker.store.printStorePath(drvPath), + yellowtxt(worker.store.printStorePath(drvPath)), statusToString(status)); if (!logger->isVerbose() && !logTail.empty()) { @@ -1771,8 +1763,6 @@ void DerivationGoal::buildDone() outputLocks.unlock(); } catch (BuildError & e) { - logError(e.info()); - outputLocks.unlock(); BuildResult::Status st = BuildResult::MiscFailure; @@ -1791,7 +1781,7 @@ void DerivationGoal::buildDone() BuildResult::PermanentFailure; } - done(st, e.msg()); + done(st, e); return; } @@ -3881,7 +3871,6 @@ void DerivationGoal::registerOutputs() .hint = hint }); - curRound = nrRounds; // we know enough, bail out early } } @@ -4145,14 +4134,11 @@ void DerivationGoal::handleChildOutput(int fd, const string & data) { logSize += data.size(); if (settings.maxLogSize && logSize > settings.maxLogSize) { - logError({ - .name = "Max log size exceeded", - .hint = hintfmt( - "%1% killed after writing more than %2% bytes of log output", - getName(), settings.maxLogSize) - }); killChild(); - done(BuildResult::LogLimitExceeded); + done( + BuildResult::LogLimitExceeded, + Error("%s killed after writing more than %d bytes of log output", + getName(), settings.maxLogSize)); return; } @@ -4233,11 +4219,12 @@ void DerivationGoal::addHashRewrite(const StorePath & path) } -void DerivationGoal::done(BuildResult::Status status, const string & msg) +void DerivationGoal::done(BuildResult::Status status, std::optional ex) { result.status = status; - result.errorMsg = msg; - amDone(result.success() ? ecSuccess : ecFailed); + if (ex) + result.errorMsg = ex->what(); + amDone(result.success() ? ecSuccess : ecFailed, ex); if (result.status == BuildResult::TimedOut) worker.timedOut = true; if (result.status == BuildResult::PermanentFailure) @@ -4306,7 +4293,7 @@ public: SubstitutionGoal(StorePath && storePath, Worker & worker, RepairFlag repair = NoRepair); ~SubstitutionGoal(); - void timedOut() override { abort(); }; + void timedOut(Error && ex) override { abort(); }; string key() override { @@ -4693,7 +4680,7 @@ void Worker::removeGoal(GoalPtr goal) topGoals.erase(goal); /* If a top-level goal failed, then kill all other goals (unless keepGoing was set). */ - if (goal->getExitCode() == Goal::ecFailed && !settings.keepGoing) + if (goal->exitCode == Goal::ecFailed && !settings.keepGoing) topGoals.clear(); } @@ -4935,32 +4922,24 @@ void Worker::waitForInput() } } - if (goal->getExitCode() == Goal::ecBusy && + if (goal->exitCode == Goal::ecBusy && 0 != settings.maxSilentTime && j->respectTimeouts && after - j->lastOutput >= std::chrono::seconds(settings.maxSilentTime)) { - logError({ - .name = "Silent build timeout", - .hint = hintfmt( + goal->timedOut(Error( "%1% timed out after %2% seconds of silence", - goal->getName(), settings.maxSilentTime) - }); - goal->timedOut(); + goal->getName(), settings.maxSilentTime)); } - else if (goal->getExitCode() == Goal::ecBusy && + else if (goal->exitCode == Goal::ecBusy && 0 != settings.buildTimeout && j->respectTimeouts && after - j->timeStarted >= std::chrono::seconds(settings.buildTimeout)) { - logError({ - .name = "Build timeout", - .hint = hintfmt( + goal->timedOut(Error( "%1% timed out after %2% seconds", - goal->getName(), settings.buildTimeout) - }); - goal->timedOut(); + goal->getName(), settings.buildTimeout)); } } @@ -5066,16 +5045,28 @@ void LocalStore::buildPaths(const std::vector & drvPaths, worker.run(goals); StorePathSet failed; + std::optional ex; for (auto & i : goals) { - if (i->getExitCode() != Goal::ecSuccess) { + if (i->ex) { + if (ex) + logError(i->ex->info()); + else + ex = i->ex; + } + if (i->exitCode != Goal::ecSuccess) { DerivationGoal * i2 = dynamic_cast(i.get()); if (i2) failed.insert(i2->getDrvPath()); else failed.insert(dynamic_cast(i.get())->getStorePath()); } } - if (!failed.empty()) + if (failed.size() == 1 && ex) { + ex->status = worker.exitStatus(); + throw *ex; + } else if (!failed.empty()) { + if (ex) logError(ex->info()); throw Error(worker.exitStatus(), "build of %s failed", showPaths(failed)); + } } BuildResult LocalStore::buildDerivation(const StorePath & drvPath, const BasicDerivation & drv, @@ -5111,8 +5102,13 @@ void LocalStore::ensurePath(const StorePath & path) worker.run(goals); - if (goal->getExitCode() != Goal::ecSuccess) - throw Error(worker.exitStatus(), "path '%s' does not exist and cannot be created", printStorePath(path)); + if (goal->exitCode != Goal::ecSuccess) { + if (goal->ex) { + goal->ex->status = worker.exitStatus(); + throw *goal->ex; + } else + throw Error(worker.exitStatus(), "path '%s' does not exist and cannot be created", printStorePath(path)); + } } @@ -5124,7 +5120,7 @@ void LocalStore::repairPath(const StorePath & path) worker.run(goals); - if (goal->getExitCode() != Goal::ecSuccess) { + if (goal->exitCode != Goal::ecSuccess) { /* Since substituting the path didn't work, if we have a valid deriver, then rebuild the deriver. */ auto info = queryPathInfo(path); From 7e7e3b71f33bfe4899d2cf735bf5e7a25bab11fd Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 15 Jun 2020 23:35:07 +0000 Subject: [PATCH 40/62] Add mising #include for strerror --- src/libutil/error.hh | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libutil/error.hh b/src/libutil/error.hh index 2ba3a3b33..1e6102ce1 100644 --- a/src/libutil/error.hh +++ b/src/libutil/error.hh @@ -4,6 +4,7 @@ #include "ref.hh" #include "types.hh" +#include #include #include #include From cd8214c39870cc37d10c439978c8cffc69db41e0 Mon Sep 17 00:00:00 2001 From: Tobias Pflug Date: Tue, 16 Jun 2020 09:44:19 +0200 Subject: [PATCH 41/62] Fix logging unit tests --- src/libutil/tests/logging.cc | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/libutil/tests/logging.cc b/src/libutil/tests/logging.cc index fbdc91253..4cb54995b 100644 --- a/src/libutil/tests/logging.cc +++ b/src/libutil/tests/logging.cc @@ -22,7 +22,7 @@ namespace nix { logger->logEI(e.info()); auto str = testing::internal::GetCapturedStderr(); - ASSERT_STREQ(str.c_str(),"\x1B[31;1merror:\x1B[0m\x1B[34;1m --- TestError ------------------------------------ error-unit-test\x1B[0m\nan error for testing purposes\n"); + ASSERT_STREQ(str.c_str(),"\x1B[31;1merror:\x1B[0m\x1B[34;1m --- TestError --- error-unit-test\x1B[0m\nan error for testing purposes\n"); } } @@ -42,7 +42,7 @@ namespace nix { logger->logEI(ei); auto str = testing::internal::GetCapturedStderr(); - ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- TestError ------------------------------------ error-unit-test\x1B[0m\n\x1B[33;1m\x1B[0minitial error\x1B[0m; subsequent error message.\n"); + ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- TestError --- error-unit-test\x1B[0m\n\x1B[33;1m\x1B[0minitial error\x1B[0m; subsequent error message.\n"); } } @@ -60,7 +60,7 @@ namespace nix { logError(e.info()); auto str = testing::internal::GetCapturedStderr(); - ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- SysError ------------------------------------- error-unit-test\x1B[0m\n\x1B[33;1m\x1B[0mstatting file\x1B[0m: \x1B[33;1mBad file descriptor\x1B[0m\n"); + ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- SysError --- error-unit-test\x1B[0m\n\x1B[33;1m\x1B[0mstatting file\x1B[0m: \x1B[33;1mBad file descriptor\x1B[0m\n"); } } @@ -74,7 +74,7 @@ namespace nix { }); auto str = testing::internal::GetCapturedStderr(); - ASSERT_STREQ(str.c_str(), "\x1B[32;1minfo:\x1B[0m\x1B[34;1m --- Info name ------------------------------------- error-unit-test\x1B[0m\nInfo description\n"); + ASSERT_STREQ(str.c_str(), "\x1B[32;1minfo:\x1B[0m\x1B[34;1m --- Info name --- error-unit-test\x1B[0m\nInfo description\n"); } TEST(logEI, loggingErrorOnTalkativeLevel) { @@ -88,7 +88,7 @@ namespace nix { }); auto str = testing::internal::GetCapturedStderr(); - ASSERT_STREQ(str.c_str(), "\x1B[32;1mtalk:\x1B[0m\x1B[34;1m --- Talkative name -------------------------------- error-unit-test\x1B[0m\nTalkative description\n"); + ASSERT_STREQ(str.c_str(), "\x1B[32;1mtalk:\x1B[0m\x1B[34;1m --- Talkative name --- error-unit-test\x1B[0m\nTalkative description\n"); } TEST(logEI, loggingErrorOnChattyLevel) { @@ -102,7 +102,7 @@ namespace nix { }); auto str = testing::internal::GetCapturedStderr(); - ASSERT_STREQ(str.c_str(), "\x1B[32;1mchat:\x1B[0m\x1B[34;1m --- Chatty name ----------------------------------- error-unit-test\x1B[0m\nTalkative description\n"); + ASSERT_STREQ(str.c_str(), "\x1B[32;1mchat:\x1B[0m\x1B[34;1m --- Chatty name --- error-unit-test\x1B[0m\nTalkative description\n"); } TEST(logEI, loggingErrorOnDebugLevel) { @@ -116,7 +116,7 @@ namespace nix { }); auto str = testing::internal::GetCapturedStderr(); - ASSERT_STREQ(str.c_str(), "\x1B[33;1mdebug:\x1B[0m\x1B[34;1m --- Debug name ----------------------------------- error-unit-test\x1B[0m\nDebug description\n"); + ASSERT_STREQ(str.c_str(), "\x1B[33;1mdebug:\x1B[0m\x1B[34;1m --- Debug name --- error-unit-test\x1B[0m\nDebug description\n"); } TEST(logEI, loggingErrorOnVomitLevel) { @@ -130,7 +130,7 @@ namespace nix { }); auto str = testing::internal::GetCapturedStderr(); - ASSERT_STREQ(str.c_str(), "\x1B[32;1mvomit:\x1B[0m\x1B[34;1m --- Vomit name ----------------------------------- error-unit-test\x1B[0m\nVomit description\n"); + ASSERT_STREQ(str.c_str(), "\x1B[32;1mvomit:\x1B[0m\x1B[34;1m --- Vomit name --- error-unit-test\x1B[0m\nVomit description\n"); } /* ---------------------------------------------------------------------------- @@ -147,7 +147,7 @@ namespace nix { }); auto str = testing::internal::GetCapturedStderr(); - ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- name ----------------------------------------- error-unit-test\x1B[0m\nerror description\n"); + ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- name --- error-unit-test\x1B[0m\nerror description\n"); } TEST(logError, logErrorWithPreviousAndNextLinesOfCode) { @@ -171,7 +171,7 @@ namespace nix { auto str = testing::internal::GetCapturedStderr(); - ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- error name ----------------------------------- error-unit-test\x1B[0m\nin file: \x1B[34;1mmyfile.nix (40:13)\x1B[0m\n\nerror with code lines\n\n 39| previous line of code\n 40| this is the problem line of code\n | \x1B[31;1m^\x1B[0m\n 41| next line of code\n\nthis hint has \x1B[33;1myellow\x1B[0m templated \x1B[33;1mvalues\x1B[0m!!\n"); + ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- error name --- error-unit-test\x1B[0m\nin file: \x1B[34;1mmyfile.nix (40:13)\x1B[0m\n\nerror with code lines\n\n 39| previous line of code\n 40| this is the problem line of code\n | \x1B[31;1m^\x1B[0m\n 41| next line of code\n\nthis hint has \x1B[33;1myellow\x1B[0m templated \x1B[33;1mvalues\x1B[0m!!\n"); } TEST(logError, logErrorWithoutLinesOfCode) { @@ -190,7 +190,7 @@ namespace nix { }}); auto str = testing::internal::GetCapturedStderr(); - ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- error name ----------------------------------- error-unit-test\x1B[0m\nin file: \x1B[34;1mmyfile.nix (40:13)\x1B[0m\n\nerror without any code lines.\n\nthis hint has \x1B[33;1myellow\x1B[0m templated \x1B[33;1mvalues\x1B[0m!!\n"); + ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- error name --- error-unit-test\x1B[0m\nin file: \x1B[34;1mmyfile.nix (40:13)\x1B[0m\n\nerror without any code lines.\n\nthis hint has \x1B[33;1myellow\x1B[0m templated \x1B[33;1mvalues\x1B[0m!!\n"); } TEST(logError, logErrorWithOnlyHintAndName) { @@ -206,7 +206,7 @@ namespace nix { }}); auto str = testing::internal::GetCapturedStderr(); - ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- error name ----------------------------------- error-unit-test\x1B[0m\nin file: \x1B[34;1mmyfile.nix (40:13)\x1B[0m\n\nhint \x1B[33;1monly\x1B[0m\n"); + ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- error name --- error-unit-test\x1B[0m\nin file: \x1B[34;1mmyfile.nix (40:13)\x1B[0m\n\nhint \x1B[33;1monly\x1B[0m\n"); } @@ -224,7 +224,7 @@ namespace nix { }); auto str = testing::internal::GetCapturedStderr(); - ASSERT_STREQ(str.c_str(), "\x1B[33;1mwarning:\x1B[0m\x1B[34;1m --- name --------------------------------------- error-unit-test\x1B[0m\nerror description\n\nthere was a \x1B[33;1mwarning\x1B[0m\n"); + ASSERT_STREQ(str.c_str(), "\x1B[33;1mwarning:\x1B[0m\x1B[34;1m --- name --- error-unit-test\x1B[0m\nerror description\n\nthere was a \x1B[33;1mwarning\x1B[0m\n"); } TEST(logWarning, logWarningWithFileLineNumAndCode) { @@ -249,7 +249,7 @@ namespace nix { auto str = testing::internal::GetCapturedStderr(); - ASSERT_STREQ(str.c_str(), "\x1B[33;1mwarning:\x1B[0m\x1B[34;1m --- warning name ------------------------------- error-unit-test\x1B[0m\nin file: \x1B[34;1mmyfile.nix (40:13)\x1B[0m\n\nwarning description\n\n 40| this is the problem line of code\n | \x1B[31;1m^\x1B[0m\n\nthis hint has \x1B[33;1myellow\x1B[0m templated \x1B[33;1mvalues\x1B[0m!!\n"); + ASSERT_STREQ(str.c_str(), "\x1B[33;1mwarning:\x1B[0m\x1B[34;1m --- warning name --- error-unit-test\x1B[0m\nin file: \x1B[34;1mmyfile.nix (40:13)\x1B[0m\n\nwarning description\n\n 40| this is the problem line of code\n | \x1B[31;1m^\x1B[0m\n\nthis hint has \x1B[33;1myellow\x1B[0m templated \x1B[33;1mvalues\x1B[0m!!\n"); } } From 72e17290d457a8e911f126d21b74c315b034189d Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 16 Jun 2020 11:51:34 +0200 Subject: [PATCH 42/62] Fix FTP support Fixes #3618. --- src/libstore/filetransfer.cc | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/libstore/filetransfer.cc b/src/libstore/filetransfer.cc index 601cb858a..c954ace7f 100644 --- a/src/libstore/filetransfer.cc +++ b/src/libstore/filetransfer.cc @@ -72,6 +72,17 @@ struct curlFileTransfer : public FileTransfer curl_off_t writtenToSink = 0; + /* Get the HTTP status code, or 0 for other protocols. */ + long getHTTPStatus() + { + long httpStatus = 0; + long protocol = 0; + curl_easy_getinfo(req, CURLINFO_PROTOCOL, &protocol); + if (protocol == CURLPROTO_HTTP || protocol == CURLPROTO_HTTPS) + curl_easy_getinfo(req, CURLINFO_RESPONSE_CODE, &httpStatus); + return httpStatus; + } + TransferItem(curlFileTransfer & fileTransfer, const FileTransferRequest & request, Callback && callback) @@ -83,8 +94,7 @@ struct curlFileTransfer : public FileTransfer , callback(std::move(callback)) , finalSink([this](const unsigned char * data, size_t len) { if (this->request.dataCallback) { - long httpStatus = 0; - curl_easy_getinfo(req, CURLINFO_RESPONSE_CODE, &httpStatus); + auto httpStatus = getHTTPStatus(); /* Only write data to the sink if this is a successful response. */ @@ -316,8 +326,7 @@ struct curlFileTransfer : public FileTransfer void finish(CURLcode code) { - long httpStatus = 0; - curl_easy_getinfo(req, CURLINFO_RESPONSE_CODE, &httpStatus); + auto httpStatus = getHTTPStatus(); char * effectiveUriCStr; curl_easy_getinfo(req, CURLINFO_EFFECTIVE_URL, &effectiveUriCStr); @@ -344,7 +353,7 @@ struct curlFileTransfer : public FileTransfer failEx(writeException); else if (code == CURLE_OK && - (httpStatus == 200 || httpStatus == 201 || httpStatus == 204 || httpStatus == 206 || httpStatus == 304 || httpStatus == 226 /* FTP */ || httpStatus == 0 /* other protocol */)) + (httpStatus == 200 || httpStatus == 201 || httpStatus == 204 || httpStatus == 206 || httpStatus == 304 || httpStatus == 0 /* other protocol */)) { result.cached = httpStatus == 304; act.progress(result.bodySize, result.bodySize); From 759947bf72c134592f0ce23d385e48095bd0a301 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 16 Jun 2020 14:16:39 +0200 Subject: [PATCH 43/62] StorePath: Rewrite in C++ On nix-env -qa -f '', this reduces maximum RSS by 20970 KiB and runtime by 0.8%. This is mostly because we're not parsing the hash part as a hash anymore (just validating that it consists of base-32 characters). Also, replace storePathToHash() by StorePath::hashPart(). --- Makefile | 1 - src/libexpr/local.mk | 2 +- src/libfetchers/local.mk | 2 +- src/libstore/binary-cache-store.cc | 6 +- src/libstore/local-store.cc | 10 ++-- src/libstore/local.mk | 2 +- src/libstore/nar-info-disk-cache.cc | 6 +- src/libstore/nar-info.cc | 4 +- src/libstore/path.cc | 70 +++++++++++------------ src/libstore/path.hh | 72 +++++++++++++++--------- src/libstore/remote-fs-accessor.cc | 2 +- src/libstore/store-api.cc | 14 +---- src/libstore/store-api.hh | 4 -- src/libutil/local.mk | 2 - src/libutil/rust-ffi.cc | 2 + src/libutil/rust-ffi.hh | 2 + src/nix/local.mk | 2 +- src/nix/make-content-addressable.cc | 4 +- src/nix/verify.cc | 2 +- src/nix/why-depends.cc | 10 ++-- src/resolve-system-dependencies/local.mk | 2 +- 21 files changed, 110 insertions(+), 111 deletions(-) diff --git a/Makefile b/Makefile index 0ba011e2a..332e6e971 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,6 @@ makefiles = \ mk/precompiled-headers.mk \ local.mk \ - nix-rust/local.mk \ src/libutil/local.mk \ src/libutil/tests/local.mk \ src/libstore/local.mk \ diff --git a/src/libexpr/local.mk b/src/libexpr/local.mk index 917e8a1c7..9ed39e745 100644 --- a/src/libexpr/local.mk +++ b/src/libexpr/local.mk @@ -8,7 +8,7 @@ libexpr_SOURCES := $(wildcard $(d)/*.cc) $(wildcard $(d)/primops/*.cc) $(d)/lexe libexpr_CXXFLAGS += -I src/libutil -I src/libstore -I src/libfetchers -I src/libmain -I src/libexpr -libexpr_LIBS = libutil libstore libfetchers libnixrust +libexpr_LIBS = libutil libstore libfetchers libexpr_LDFLAGS = ifneq ($(OS), FreeBSD) diff --git a/src/libfetchers/local.mk b/src/libfetchers/local.mk index d7143d8a6..cfd705e22 100644 --- a/src/libfetchers/local.mk +++ b/src/libfetchers/local.mk @@ -8,4 +8,4 @@ libfetchers_SOURCES := $(wildcard $(d)/*.cc) libfetchers_CXXFLAGS += -I src/libutil -I src/libstore -libfetchers_LIBS = libutil libstore libnixrust +libfetchers_LIBS = libutil libstore diff --git a/src/libstore/binary-cache-store.cc b/src/libstore/binary-cache-store.cc index 649331495..1037b2e28 100644 --- a/src/libstore/binary-cache-store.cc +++ b/src/libstore/binary-cache-store.cc @@ -93,7 +93,7 @@ std::shared_ptr BinaryCacheStore::getFile(const std::string & path) std::string BinaryCacheStore::narInfoFileFor(const StorePath & storePath) { - return storePathToHash(printStorePath(storePath)) + ".narinfo"; + return std::string(storePath.hashPart()) + ".narinfo"; } void BinaryCacheStore::writeNarInfo(ref narInfo) @@ -102,7 +102,7 @@ void BinaryCacheStore::writeNarInfo(ref narInfo) upsertFile(narInfoFile, narInfo->to_string(*this), "text/x-nix-narinfo"); - auto hashPart = storePathToHash(printStorePath(narInfo->path)); + std::string hashPart(narInfo->path.hashPart()); { auto state_(state.lock()); @@ -164,7 +164,7 @@ void BinaryCacheStore::addToStore(const ValidPathInfo & info, Source & narSource } } - upsertFile(storePathToHash(printStorePath(info.path)) + ".ls", jsonOut.str(), "application/json"); + upsertFile(std::string(info.path.to_string()) + ".ls", jsonOut.str(), "application/json"); } /* Compress the NAR. */ diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index f5c5bd9b7..e3b718e88 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -619,7 +619,7 @@ uint64_t LocalStore::addValidPath(State & state, { auto state_(Store::state.lock()); - state_->pathInfoCache.upsert(storePathToHash(printStorePath(info.path)), + state_->pathInfoCache.upsert(std::string(info.path.hashPart()), PathInfoCacheValue{ .value = std::make_shared(info) }); } @@ -791,7 +791,7 @@ StorePathSet LocalStore::queryDerivationOutputs(const StorePath & path) std::optional LocalStore::queryPathFromHashPart(const std::string & hashPart) { - if (hashPart.size() != storePathHashLen) throw Error("invalid hash part"); + if (hashPart.size() != StorePath::HashLen) throw Error("invalid hash part"); Path prefix = storeDir + "/" + hashPart; @@ -942,7 +942,7 @@ void LocalStore::invalidatePath(State & state, const StorePath & path) { auto state_(Store::state.lock()); - state_->pathInfoCache.erase(storePathToHash(printStorePath(path))); + state_->pathInfoCache.erase(std::string(path.hashPart())); } } @@ -994,7 +994,7 @@ void LocalStore::addToStore(const ValidPathInfo & info, Source & source, if (info.ca == "" || !info.references.count(info.path)) hashSink = std::make_unique(htSHA256); else - hashSink = std::make_unique(htSHA256, storePathToHash(printStorePath(info.path))); + hashSink = std::make_unique(htSHA256, std::string(info.path.hashPart())); LambdaSource wrapperSource([&](unsigned char * data, size_t len) -> size_t { size_t n = source.read(data, len); @@ -1255,7 +1255,7 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair) if (info->ca == "" || !info->references.count(info->path)) hashSink = std::make_unique(info->narHash.type); else - hashSink = std::make_unique(info->narHash.type, storePathToHash(printStorePath(info->path))); + hashSink = std::make_unique(info->narHash.type, std::string(info->path.hashPart())); dumpPath(Store::toRealPath(i), *hashSink); auto current = hashSink->finish(); diff --git a/src/libstore/local.mk b/src/libstore/local.mk index 91acef368..aec4ed493 100644 --- a/src/libstore/local.mk +++ b/src/libstore/local.mk @@ -6,7 +6,7 @@ libstore_DIR := $(d) libstore_SOURCES := $(wildcard $(d)/*.cc $(d)/builtins/*.cc) -libstore_LIBS = libutil libnixrust +libstore_LIBS = libutil libstore_LDFLAGS = $(SQLITE3_LIBS) -lbz2 $(LIBCURL_LIBS) $(SODIUM_LIBS) -pthread ifneq ($(OS), FreeBSD) diff --git a/src/libstore/nar-info-disk-cache.cc b/src/libstore/nar-info-disk-cache.cc index e8cf1d177..552970248 100644 --- a/src/libstore/nar-info-disk-cache.cc +++ b/src/libstore/nar-info-disk-cache.cc @@ -189,7 +189,7 @@ public: return {oInvalid, 0}; auto namePart = queryNAR.getStr(1); - auto narInfo = make_ref(StorePath::fromBaseName(hashPart + "-" + namePart)); + auto narInfo = make_ref(StorePath(hashPart + "-" + namePart)); narInfo->url = queryNAR.getStr(2); narInfo->compression = queryNAR.getStr(3); if (!queryNAR.isNull(4)) @@ -198,9 +198,9 @@ public: narInfo->narHash = Hash(queryNAR.getStr(6)); narInfo->narSize = queryNAR.getInt(7); for (auto & r : tokenizeString(queryNAR.getStr(8), " ")) - narInfo->references.insert(StorePath::fromBaseName(r)); + narInfo->references.insert(StorePath(r)); if (!queryNAR.isNull(9)) - narInfo->deriver = StorePath::fromBaseName(queryNAR.getStr(9)); + narInfo->deriver = StorePath(queryNAR.getStr(9)); for (auto & sig : tokenizeString(queryNAR.getStr(10), " ")) narInfo->sigs.insert(sig); narInfo->ca = queryNAR.getStr(11); diff --git a/src/libstore/nar-info.cc b/src/libstore/nar-info.cc index 232284723..d7fc30e91 100644 --- a/src/libstore/nar-info.cc +++ b/src/libstore/nar-info.cc @@ -56,11 +56,11 @@ NarInfo::NarInfo(const Store & store, const std::string & s, const std::string & auto refs = tokenizeString(value, " "); if (!references.empty()) corrupt(); for (auto & r : refs) - references.insert(StorePath::fromBaseName(r)); + references.insert(StorePath(r)); } else if (name == "Deriver") { if (value != "unknown-deriver") - deriver = StorePath::fromBaseName(value); + deriver = StorePath(value); } else if (name == "System") system = value; diff --git a/src/libstore/path.cc b/src/libstore/path.cc index 9a28aa96a..bb2089ea4 100644 --- a/src/libstore/path.cc +++ b/src/libstore/path.cc @@ -2,38 +2,38 @@ namespace nix { -extern "C" { - rust::Result ffi_StorePath_new(rust::StringSlice path, rust::StringSlice storeDir); - rust::Result ffi_StorePath_new2(unsigned char hash[20], rust::StringSlice storeDir); - rust::Result ffi_StorePath_fromBaseName(rust::StringSlice baseName); - rust::String ffi_StorePath_to_string(const StorePath & _this); - StorePath ffi_StorePath_clone(const StorePath & _this); - rust::StringSlice ffi_StorePath_name(const StorePath & _this); +MakeError(BadStorePath, Error); + +static void checkName(std::string_view path, std::string_view name) +{ + if (name.empty()) + throw BadStorePath("store path '%s' has an empty name", path); + if (name.size() > 211) + throw BadStorePath("store path '%s' has a name longer than 211 characters", path); + for (auto c : name) + if (!((c >= '0' && c <= '9') + || (c >= 'a' && c <= 'z') + || (c >= 'A' && c <= 'Z') + || c == '+' || c == '-' || c == '.' || c == '_' || c == '?' || c == '=')) + throw BadStorePath("store path '%s' contains illegal character '%s'", path, c); } -StorePath StorePath::make(std::string_view path, std::string_view storeDir) +StorePath::StorePath(std::string_view _baseName) + : baseName(_baseName) { - return ffi_StorePath_new((rust::StringSlice) path, (rust::StringSlice) storeDir).unwrap(); + if (baseName.size() < HashLen + 1) + throw BadStorePath("'%s' is too short to be a valid store path", baseName); + for (auto c : hashPart()) + if (c == 'e' || c == 'o' || c == 'u' || c == 't' + || !((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z'))) + throw BadStorePath("store path '%s' contains illegal base-32 character '%s'", baseName, c); + checkName(baseName, name()); } -StorePath StorePath::make(unsigned char hash[20], std::string_view name) +StorePath::StorePath(const Hash & hash, std::string_view _name) + : baseName((hash.to_string(Base32, false) + "-").append(std::string(_name))) { - return ffi_StorePath_new2(hash, (rust::StringSlice) name).unwrap(); -} - -StorePath StorePath::fromBaseName(std::string_view baseName) -{ - return ffi_StorePath_fromBaseName((rust::StringSlice) baseName).unwrap(); -} - -rust::String StorePath::to_string() const -{ - return ffi_StorePath_to_string(*this); -} - -StorePath StorePath::clone() const -{ - return ffi_StorePath_clone(*this); + checkName(baseName, name()); } bool StorePath::isDerivation() const @@ -41,18 +41,14 @@ bool StorePath::isDerivation() const return hasSuffix(name(), drvExtension); } -std::string_view StorePath::name() const -{ - return ffi_StorePath_name(*this); -} - -StorePath StorePath::dummy( - StorePath::make( - (unsigned char *) "xxxxxxxxxxxxxxxxxxxx", "x")); +StorePath StorePath::dummy("ffffffffffffffffffffffffffffffff-x"); StorePath Store::parseStorePath(std::string_view path) const { - return StorePath::make(path, storeDir); + auto p = canonPath(std::string(path)); + if (dirOf(p) != storeDir) + throw BadStorePath("path '%s' is not in the Nix store", p); + return StorePath(baseNameOf(p)); } std::optional Store::maybeParseStorePath(std::string_view path) const @@ -78,9 +74,7 @@ StorePathSet Store::parseStorePathSet(const PathSet & paths) const std::string Store::printStorePath(const StorePath & path) const { - auto s = storeDir + "/"; - s += (std::string_view) path.to_string(); - return s; + return (storeDir + "/").append(path.to_string()); } PathSet Store::printStorePathSet(const StorePathSet & paths) const diff --git a/src/libstore/path.hh b/src/libstore/path.hh index 5122e7422..85c3d8e53 100644 --- a/src/libstore/path.hh +++ b/src/libstore/path.hh @@ -1,59 +1,78 @@ #pragma once -#include "rust-ffi.hh" +#include "types.hh" namespace nix { -/* See path.rs. */ -struct StorePath; - class Store; +struct Hash; -extern "C" { - void ffi_StorePath_drop(void *); - bool ffi_StorePath_less_than(const StorePath & a, const StorePath & b); - bool ffi_StorePath_eq(const StorePath & a, const StorePath & b); - unsigned char * ffi_StorePath_hash_data(const StorePath & p); -} - -struct StorePath : rust::Value<3 * sizeof(void *) + 24, ffi_StorePath_drop> +class StorePath { + std::string baseName; + + StorePath(const StorePath & path) + : baseName(path.baseName) + { } + +public: + + /* Size of the hash part of store paths, in base-32 characters. */ + constexpr static size_t HashLen = 32; // i.e. 160 bits + StorePath() = delete; - static StorePath make(std::string_view path, std::string_view storeDir); + StorePath(std::string_view baseName); - static StorePath make(unsigned char hash[20], std::string_view name); + StorePath(const Hash & hash, std::string_view name); - static StorePath fromBaseName(std::string_view baseName); + StorePath(StorePath && path) + : baseName(std::move(path.baseName)) + { } - rust::String to_string() const; + StorePath & operator = (StorePath && path) + { + baseName = std::move(path.baseName); + return *this; + } + + std::string_view to_string() const + { + return baseName; + } bool operator < (const StorePath & other) const { - return ffi_StorePath_less_than(*this, other); + return baseName < other.baseName; } bool operator == (const StorePath & other) const { - return ffi_StorePath_eq(*this, other); + return baseName == other.baseName; } bool operator != (const StorePath & other) const { - return !(*this == other); + return baseName != other.baseName; } - StorePath clone() const; + StorePath clone() const + { + return StorePath(*this); + } /* Check whether a file name ends with the extension for derivations. */ bool isDerivation() const; - std::string_view name() const; - - unsigned char * hashData() const + std::string_view name() const { - return ffi_StorePath_hash_data(*this); + return std::string_view(baseName).substr(HashLen + 1); + } + + std::string_view hashPart() const + { + return std::string_view(baseName).substr(0, HashLen); } static StorePath dummy; @@ -67,9 +86,6 @@ StorePathSet storePathsToSet(const StorePaths & paths); StorePathSet singleton(const StorePath & path); -/* Size of the hash part of store paths, in base-32 characters. */ -const size_t storePathHashLen = 32; // i.e. 160 bits - /* Extension of derivations in the Nix store. */ const std::string drvExtension = ".drv"; @@ -107,7 +123,7 @@ namespace std { template<> struct hash { std::size_t operator()(const nix::StorePath & path) const noexcept { - return * (std::size_t *) path.hashData(); + return * (std::size_t *) path.to_string().data(); } }; diff --git a/src/libstore/remote-fs-accessor.cc b/src/libstore/remote-fs-accessor.cc index 9277a8e6b..bd698d781 100644 --- a/src/libstore/remote-fs-accessor.cc +++ b/src/libstore/remote-fs-accessor.cc @@ -19,7 +19,7 @@ RemoteFSAccessor::RemoteFSAccessor(ref store, const Path & cacheDir) Path RemoteFSAccessor::makeCacheFile(const Path & storePath, const std::string & ext) { assert(cacheDir != ""); - return fmt("%s/%s.%s", cacheDir, storePathToHash(storePath), ext); + return fmt("%s/%s.%s", cacheDir, store->parseStorePath(storePath).hashPart(), ext); } void RemoteFSAccessor::addToCache(const Path & storePath, const std::string & nar, diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index e23a9ca50..42e26c427 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -59,14 +59,6 @@ StorePathWithOutputs Store::followLinksToStorePathWithOutputs(std::string_view p } -string storePathToHash(const Path & path) -{ - auto base = baseNameOf(path); - assert(base.size() >= storePathHashLen); - return string(base, 0, storePathHashLen); -} - - /* Store paths have the following form: /- @@ -144,7 +136,7 @@ StorePath Store::makeStorePath(const string & type, /* e.g., "source:sha256:1abc...:/nix/store:foo.tar.gz" */ string s = type + ":" + hash.to_string(Base16, true) + ":" + storeDir + ":" + std::string(name); auto h = compressHash(hashString(htSHA256, s), 20); - return StorePath::make(h.hash, name); + return StorePath(h, name); } @@ -243,7 +235,7 @@ bool Store::PathInfoCacheValue::isKnownNow() bool Store::isValidPath(const StorePath & storePath) { - auto hashPart = storePathToHash(printStorePath(storePath)); + std::string hashPart(storePath.hashPart()); { auto state_(state.lock()); @@ -311,7 +303,7 @@ void Store::queryPathInfo(const StorePath & storePath, std::string hashPart; try { - hashPart = storePathToHash(printStorePath(storePath)); + hashPart = storePath.hashPart(); { auto res = state.lock()->pathInfoCache.get(hashPart); diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh index 5ef506326..251fc4638 100644 --- a/src/libstore/store-api.hh +++ b/src/libstore/store-api.hh @@ -731,10 +731,6 @@ public: }; -/* Extract the hash part of the given store path. */ -string storePathToHash(const Path & path); - - /* Copy a path from one store to another. */ void copyStorePath(ref srcStore, ref dstStore, const StorePath & storePath, RepairFlag repair = NoRepair, CheckSigsFlag checkSigs = CheckSigs); diff --git a/src/libutil/local.mk b/src/libutil/local.mk index 16c1fa03f..ae7eb67ad 100644 --- a/src/libutil/local.mk +++ b/src/libutil/local.mk @@ -7,5 +7,3 @@ libutil_DIR := $(d) libutil_SOURCES := $(wildcard $(d)/*.cc) libutil_LDFLAGS = $(LIBLZMA_LIBS) -lbz2 -pthread $(OPENSSL_LIBS) $(LIBBROTLI_LIBS) $(LIBARCHIVE_LIBS) $(BOOST_LDFLAGS) -lboost_context - -libutil_LIBS = libnixrust diff --git a/src/libutil/rust-ffi.cc b/src/libutil/rust-ffi.cc index 6f36b3192..67924568f 100644 --- a/src/libutil/rust-ffi.cc +++ b/src/libutil/rust-ffi.cc @@ -1,3 +1,4 @@ +#if 0 #include "logging.hh" #include "rust-ffi.hh" @@ -20,3 +21,4 @@ std::ostream & operator << (std::ostream & str, const String & s) } } +#endif diff --git a/src/libutil/rust-ffi.hh b/src/libutil/rust-ffi.hh index 228e2eead..cfbaf9dec 100644 --- a/src/libutil/rust-ffi.hh +++ b/src/libutil/rust-ffi.hh @@ -1,4 +1,5 @@ #pragma once +#if 0 #include "serialise.hh" @@ -185,3 +186,4 @@ struct Result }; } +#endif diff --git a/src/nix/local.mk b/src/nix/local.mk index 43b7754e3..b057b7cc6 100644 --- a/src/nix/local.mk +++ b/src/nix/local.mk @@ -17,7 +17,7 @@ nix_SOURCES := \ nix_CXXFLAGS += -I src/libutil -I src/libstore -I src/libfetchers -I src/libexpr -I src/libmain -nix_LIBS = libexpr libmain libfetchers libstore libutil libnixrust +nix_LIBS = libexpr libmain libfetchers libstore libutil nix_LDFLAGS = -pthread $(SODIUM_LIBS) $(EDITLINE_LIBS) $(BOOST_LDFLAGS) -lboost_context -lboost_thread -lboost_system diff --git a/src/nix/make-content-addressable.cc b/src/nix/make-content-addressable.cc index 719ea4fd1..1211dad7b 100644 --- a/src/nix/make-content-addressable.cc +++ b/src/nix/make-content-addressable.cc @@ -48,7 +48,7 @@ struct CmdMakeContentAddressable : StorePathsCommand, MixJSON for (auto & path : paths) { auto pathS = store->printStorePath(path); auto oldInfo = store->queryPathInfo(path); - auto oldHashPart = storePathToHash(pathS); + std::string oldHashPart(path.hashPart()); StringSink sink; store->narFromPath(path, sink); @@ -88,7 +88,7 @@ struct CmdMakeContentAddressable : StorePathsCommand, MixJSON printInfo("rewrote '%s' to '%s'", pathS, store->printStorePath(info.path)); auto source = sinkToSource([&](Sink & nextSink) { - RewritingSink rsink2(oldHashPart, storePathToHash(store->printStorePath(info.path)), nextSink); + RewritingSink rsink2(oldHashPart, std::string(info.path.hashPart()), nextSink); rsink2((unsigned char *) sink.s->data(), sink.s->size()); rsink2.flush(); }); diff --git a/src/nix/verify.cc b/src/nix/verify.cc index 001401ac2..ab83637dc 100644 --- a/src/nix/verify.cc +++ b/src/nix/verify.cc @@ -90,7 +90,7 @@ struct CmdVerify : StorePathsCommand if (info->ca == "") hashSink = std::make_unique(info->narHash.type); else - hashSink = std::make_unique(info->narHash.type, storePathToHash(store->printStorePath(info->path))); + hashSink = std::make_unique(info->narHash.type, std::string(info->path.hashPart())); store->narFromPath(info->path, *hashSink); diff --git a/src/nix/why-depends.cc b/src/nix/why-depends.cc index 6057beedb..a4ee2d971 100644 --- a/src/nix/why-depends.cc +++ b/src/nix/why-depends.cc @@ -76,7 +76,7 @@ struct CmdWhyDepends : SourceExprCommand auto packagePath = toStorePath(store, Build, package); auto dependency = parseInstallable(*this, store, _dependency, false); auto dependencyPath = toStorePath(store, NoBuild, dependency); - auto dependencyPathHash = storePathToHash(store->printStorePath(dependencyPath)); + auto dependencyPathHash = dependencyPath.hashPart(); StorePathSet closure; store->computeFSClosure({packagePath}, closure, false, false); @@ -175,7 +175,7 @@ struct CmdWhyDepends : SourceExprCommand auto & node2 = graph.at(ref); if (node2.dist == inf) continue; refs.emplace(node2.dist, &node2); - hashes.insert(storePathToHash(store->printStorePath(node2.path))); + hashes.insert(std::string(node2.path.hashPart())); } /* For each reference, find the files and symlinks that @@ -211,7 +211,7 @@ struct CmdWhyDepends : SourceExprCommand p2, hilite(filterPrintable( std::string(contents, pos2, pos - pos2 + hash.size() + margin)), - pos - pos2, storePathHashLen, + pos - pos2, StorePath::HashLen, getColour(hash)))); } } @@ -224,7 +224,7 @@ struct CmdWhyDepends : SourceExprCommand auto pos = target.find(hash); if (pos != std::string::npos) hits[hash].emplace_back(fmt("%s -> %s\n", p2, - hilite(target, pos, storePathHashLen, getColour(hash)))); + hilite(target, pos, StorePath::HashLen, getColour(hash)))); } } }; @@ -235,7 +235,7 @@ struct CmdWhyDepends : SourceExprCommand RunPager pager; for (auto & ref : refs) { - auto hash = storePathToHash(store->printStorePath(ref.second->path)); + std::string hash(ref.second->path.hashPart()); bool last = all ? ref == *refs.rbegin() : true; diff --git a/src/resolve-system-dependencies/local.mk b/src/resolve-system-dependencies/local.mk index f0e82e023..054ae01cb 100644 --- a/src/resolve-system-dependencies/local.mk +++ b/src/resolve-system-dependencies/local.mk @@ -8,6 +8,6 @@ resolve-system-dependencies_INSTALL_DIR := $(libexecdir)/nix resolve-system-dependencies_CXXFLAGS += -I src/libutil -I src/libstore -I src/libmain -resolve-system-dependencies_LIBS := libstore libmain libutil libnixrust +resolve-system-dependencies_LIBS := libstore libmain libutil resolve-system-dependencies_SOURCES := $(d)/resolve-system-dependencies.cc From cc83a86276726699e5e856d26b5e24ce24f5cf34 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 16 Jun 2020 14:33:03 +0200 Subject: [PATCH 44/62] release.nix: Remove vendoredCrates --- release-common.nix | 1 - release.nix | 63 ---------------------------------------------- 2 files changed, 64 deletions(-) diff --git a/release-common.nix b/release-common.nix index 7e7de005d..4316c3c23 100644 --- a/release-common.nix +++ b/release-common.nix @@ -50,7 +50,6 @@ rec { libarchive boost nlohmann_json - rustc cargo # Tests git diff --git a/release.nix b/release.nix index 2a320e1c3..fbf9e4721 100644 --- a/release.nix +++ b/release.nix @@ -12,64 +12,8 @@ let builtins.readFile ./.version + (if officialRelease then "" else "pre${toString nix.revCount}_${nix.shortRev}"); - # Create a "vendor" directory that contains the crates listed in - # Cargo.lock. This allows Nix to be built without network access. - vendoredCrates' = - let - lockFile = builtins.fromTOML (builtins.readFile nix-rust/Cargo.lock); - - files = map (pkg: import { - url = "https://crates.io/api/v1/crates/${pkg.name}/${pkg.version}/download"; - sha256 = lockFile.metadata."checksum ${pkg.name} ${pkg.version} (registry+https://github.com/rust-lang/crates.io-index)"; - }) (builtins.filter (pkg: pkg.source or "" == "registry+https://github.com/rust-lang/crates.io-index") lockFile.package); - - in pkgs.runCommand "cargo-vendor-dir" {} - '' - mkdir -p $out/vendor - - cat > $out/vendor/config < "$dir/.cargo-checksum.json" - - # Clean up some cruft from the winapi crates. FIXME: find - # a way to remove winapi* from our dependencies. - if [[ $dir =~ /winapi ]]; then - find $dir -name "*.a" -print0 | xargs -0 rm -f -- - fi - - mv "$dir" $out/vendor/ - - rm -rf $out/vendor/tmp - '') files)} - ''; - jobs = rec { - vendoredCrates = - with pkgs; - runCommand "vendored-crates" {} - '' - mkdir -p $out/nix-support - name=nix-vendored-crates-${version} - fn=$out/$name.tar.xz - tar cvfJ $fn -C ${vendoredCrates'} vendor \ - --owner=0 --group=0 --mode=u+rw,uga+r \ - --transform "s,vendor,$name," - echo "file crates-tarball $fn" >> $out/nix-support/hydra-build-products - ''; - build = pkgs.lib.genAttrs systems (system: let pkgs = import nixpkgs { inherit system; }; in @@ -101,8 +45,6 @@ let patchelf --set-rpath $out/lib:${stdenv.cc.cc.lib}/lib $out/lib/libboost_thread.so.* ''} - ln -sfn ${vendoredCrates'}/vendor/ nix-rust/vendor - (cd perl; autoreconf --install --force --verbose) ''; @@ -247,11 +189,6 @@ let src = nix; - preConfigure = - '' - ln -sfn ${vendoredCrates'}/vendor/ nix-rust/vendor - ''; - enableParallelBuilding = true; buildInputs = buildDeps ++ propagatedDeps; From fbf90bd693f09e6ce6e0725563c7996cba4da896 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Tue, 16 Jun 2020 14:19:49 +0000 Subject: [PATCH 45/62] Add another missing #include --- src/libutil/config.hh | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libutil/config.hh b/src/libutil/config.hh index 5c7a70a2e..66073546e 100644 --- a/src/libutil/config.hh +++ b/src/libutil/config.hh @@ -1,3 +1,4 @@ +#include #include #include From 29542865cee37ab22efe1bd142900b69f6c59f0d Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 16 Jun 2020 22:20:18 +0200 Subject: [PATCH 46/62] Remove StorePath::clone() and related functions --- src/libexpr/primops.cc | 12 +-- src/libstore/binary-cache-store.cc | 6 +- src/libstore/build.cc | 110 ++++++++++++++-------------- src/libstore/daemon.cc | 8 +- src/libstore/derivations.cc | 42 ++++------- src/libstore/derivations.hh | 8 -- src/libstore/export-import.cc | 2 +- src/libstore/gc.cc | 24 +++--- src/libstore/legacy-ssh-store.cc | 2 +- src/libstore/local-fs-store.cc | 4 +- src/libstore/local-store.cc | 24 +++--- src/libstore/misc.cc | 36 ++++----- src/libstore/nar-info.cc | 2 +- src/libstore/parsed-derivations.cc | 4 +- src/libstore/parsed-derivations.hh | 2 +- src/libstore/path.cc | 23 ------ src/libstore/path.hh | 36 --------- src/libstore/remote-store.cc | 10 +-- src/libstore/store-api.cc | 21 +----- src/libstore/store-api.hh | 3 +- src/nix-build/nix-build.cc | 8 +- src/nix-env/nix-env.cc | 12 ++- src/nix-env/user-env.cc | 2 +- src/nix-store/dotgraph.cc | 4 +- src/nix-store/graphml.cc | 4 +- src/nix-store/nix-store.cc | 36 ++++----- src/nix/command.cc | 10 +-- src/nix/copy.cc | 2 +- src/nix/develop.cc | 6 +- src/nix/installables.cc | 22 +++--- src/nix/make-content-addressable.cc | 6 +- src/nix/path-info.cc | 2 +- src/nix/run.cc | 6 +- src/nix/why-depends.cc | 6 +- 34 files changed, 201 insertions(+), 304 deletions(-) diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 62e5163c9..907f15246 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -55,7 +55,7 @@ void EvalState::realiseContext(const PathSet & context) if (!store->isValidPath(ctx)) throw InvalidPathError(store->printStorePath(ctx)); if (!decoded.second.empty() && ctx.isDerivation()) { - drvs.push_back(StorePathWithOutputs{ctx.clone(), {decoded.second}}); + drvs.push_back(StorePathWithOutputs{ctx, {decoded.second}}); /* Add the output of this derivation to the allowed paths. */ @@ -723,9 +723,9 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * * StorePathSet refs; state.store->computeFSClosure(state.store->parseStorePath(std::string_view(path).substr(1)), refs); for (auto & j : refs) { - drv.inputSrcs.insert(j.clone()); + drv.inputSrcs.insert(j); if (j.isDerivation()) - drv.inputDrvs[j.clone()] = state.store->readDerivation(j).outputNames(); + drv.inputDrvs[j] = state.store->readDerivation(j).outputNames(); } } @@ -792,7 +792,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * * for (auto & i : outputs) { if (!jsonObject) drv.env[i] = ""; drv.outputs.insert_or_assign(i, - DerivationOutput(StorePath::dummy.clone(), "", "")); + DerivationOutput { StorePath::dummy, "", "" }); } Hash h = hashDerivationModulo(*state.store, Derivation(drv), true); @@ -801,7 +801,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * * auto outPath = state.store->makeOutputPath(i, h, drvName); if (!jsonObject) drv.env[i] = state.store->printStorePath(outPath); drv.outputs.insert_or_assign(i, - DerivationOutput(std::move(outPath), "", "")); + DerivationOutput { std::move(outPath), "", "" }); } } @@ -814,7 +814,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * * /* Optimisation, but required in read-only mode! because in that case we don't actually write store derivations, so we can't read them later. */ - drvHashes.insert_or_assign(drvPath.clone(), + drvHashes.insert_or_assign(drvPath, hashDerivationModulo(*state.store, Derivation(drv), false)); state.mkAttrs(v, 1 + drv.outputs.size()); diff --git a/src/libstore/binary-cache-store.cc b/src/libstore/binary-cache-store.cc index 1037b2e28..f8eff508c 100644 --- a/src/libstore/binary-cache-store.cc +++ b/src/libstore/binary-cache-store.cc @@ -360,7 +360,7 @@ StorePath BinaryCacheStore::addTextToStore(const string & name, const string & s const StorePathSet & references, RepairFlag repair) { ValidPathInfo info(computeStorePathForText(name, s, references)); - info.references = cloneStorePathSet(references); + info.references = references; if (repair || !isValidPath(info.path)) { StringSink sink; @@ -395,14 +395,14 @@ void BinaryCacheStore::addSignatures(const StorePath & storePath, const StringSe std::shared_ptr BinaryCacheStore::getBuildLog(const StorePath & path) { - auto drvPath = path.clone(); + auto drvPath = path; if (!path.isDerivation()) { try { auto info = queryPathInfo(path); // FIXME: add a "Log" field to .narinfo if (!info->deriver) return nullptr; - drvPath = info->deriver->clone(); + drvPath = *info->deriver; } catch (InvalidPath &) { return nullptr; } diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 8ad2ca4f3..53a0958aa 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -295,7 +295,7 @@ public: /* Make a goal (with caching). */ GoalPtr makeDerivationGoal(const StorePath & drvPath, const StringSet & wantedOutputs, BuildMode buildMode = bmNormal); - std::shared_ptr makeBasicDerivationGoal(StorePath && drvPath, + std::shared_ptr makeBasicDerivationGoal(const StorePath & drvPath, const BasicDerivation & drv, BuildMode buildMode = bmNormal); GoalPtr makeSubstitutionGoal(const StorePath & storePath, RepairFlag repair = NoRepair); @@ -347,7 +347,7 @@ public: contents. */ bool pathContentsGood(const StorePath & path); - void markContentsGood(StorePath && path); + void markContentsGood(const StorePath & path); void updateProgress() { @@ -900,9 +900,9 @@ private: friend struct RestrictedStore; public: - DerivationGoal(StorePath && drvPath, const StringSet & wantedOutputs, + DerivationGoal(const StorePath & drvPath, const StringSet & wantedOutputs, Worker & worker, BuildMode buildMode = bmNormal); - DerivationGoal(StorePath && drvPath, const BasicDerivation & drv, + DerivationGoal(const StorePath & drvPath, const BasicDerivation & drv, Worker & worker, BuildMode buildMode = bmNormal); ~DerivationGoal(); @@ -924,7 +924,7 @@ public: StorePath getDrvPath() { - return drvPath.clone(); + return drvPath; } /* Add wanted outputs to an already existing derivation goal. */ @@ -1021,11 +1021,11 @@ private: const Path DerivationGoal::homeDir = "/homeless-shelter"; -DerivationGoal::DerivationGoal(StorePath && drvPath, const StringSet & wantedOutputs, +DerivationGoal::DerivationGoal(const StorePath & drvPath, const StringSet & wantedOutputs, Worker & worker, BuildMode buildMode) : Goal(worker) , useDerivation(true) - , drvPath(std::move(drvPath)) + , drvPath(drvPath) , wantedOutputs(wantedOutputs) , buildMode(buildMode) { @@ -1038,11 +1038,11 @@ DerivationGoal::DerivationGoal(StorePath && drvPath, const StringSet & wantedOut } -DerivationGoal::DerivationGoal(StorePath && drvPath, const BasicDerivation & drv, +DerivationGoal::DerivationGoal(const StorePath & drvPath, const BasicDerivation & drv, Worker & worker, BuildMode buildMode) : Goal(worker) , useDerivation(false) - , drvPath(std::move(drvPath)) + , drvPath(drvPath) , buildMode(buildMode) { this->drv = std::make_unique(BasicDerivation(drv)); @@ -1193,7 +1193,7 @@ void DerivationGoal::haveDerivation() return; } - parsedDrv = std::make_unique(drvPath.clone(), *drv); + parsedDrv = std::make_unique(drvPath, *drv); /* We are first going to try to create the invalid output paths through substitutes. If that doesn't work, we'll build @@ -1301,7 +1301,7 @@ void DerivationGoal::repairClosure() if (i.isDerivation()) { Derivation drv = worker.store.derivationFromPath(i); for (auto & j : drv.outputs) - outputsToDrv.insert_or_assign(j.second.path.clone(), i.clone()); + outputsToDrv.insert_or_assign(j.second.path, i); } /* Check each path (slow!). */ @@ -1454,7 +1454,7 @@ void DerivationGoal::tryToBuild() return; } - missingPaths = cloneStorePathSet(drv->outputPaths()); + missingPaths = drv->outputPaths(); if (buildMode != bmCheck) for (auto & i : validPaths) missingPaths.erase(i); @@ -1901,14 +1901,14 @@ StorePathSet DerivationGoal::exportReferences(const StorePathSet & storePaths) if (!inputPaths.count(storePath)) throw BuildError("cannot export references of path '%s' because it is not in the input closure of the derivation", worker.store.printStorePath(storePath)); - worker.store.computeFSClosure(singleton(storePath), paths); + worker.store.computeFSClosure({storePath}, paths); } /* If there are derivations in the graph, then include their outputs as well. This is useful if you want to do things like passing all build-time dependencies of some path to a derivation that builds a NixOS DVD image. */ - auto paths2 = cloneStorePathSet(paths); + auto paths2 = paths; for (auto & j : paths2) { if (j.isDerivation()) { @@ -2037,7 +2037,7 @@ void DerivationGoal::startBuilder() /* Write closure info to . */ writeFile(tmpDir + "/" + fileName, worker.store.makeValidityRegistration( - exportReferences(singleton(storePath)), false, false)); + exportReferences({storePath}), false, false)); } } @@ -2222,7 +2222,7 @@ void DerivationGoal::startBuilder() for (auto & i : missingPaths) if (worker.store.isValidPath(i) && pathExists(worker.store.printStorePath(i))) { addHashRewrite(i); - redirectedBadOutputs.insert(i.clone()); + redirectedBadOutputs.insert(i); } } @@ -2717,8 +2717,8 @@ struct RestrictedStore : public LocalFSStore StorePathSet queryAllValidPaths() override { StorePathSet paths; - for (auto & p : goal.inputPaths) paths.insert(p.clone()); - for (auto & p : goal.addedPaths) paths.insert(p.clone()); + for (auto & p : goal.inputPaths) paths.insert(p); + for (auto & p : goal.addedPaths) paths.insert(p); return paths; } @@ -2806,7 +2806,7 @@ struct RestrictedStore : public LocalFSStore auto drv = derivationFromPath(path.path); for (auto & output : drv.outputs) if (wantOutput(output.first, path.outputs)) - newPaths.insert(output.second.path.clone()); + newPaths.insert(output.second.path); } else if (!goal.isAllowed(path.path)) throw InvalidPath("cannot build unknown path '%s' in recursive Nix", printStorePath(path.path)); } @@ -2851,7 +2851,7 @@ struct RestrictedStore : public LocalFSStore if (goal.isAllowed(path.path)) allowed.emplace_back(path); else - unknown.insert(path.path.clone()); + unknown.insert(path.path); } next->queryMissing(allowed, willBuild, willSubstitute, @@ -2946,7 +2946,7 @@ void DerivationGoal::addDependency(const StorePath & path) { if (isAllowed(path)) return; - addedPaths.insert(path.clone()); + addedPaths.insert(path); /* If we're doing a sandbox build, then we have to make the path appear in the sandbox. */ @@ -3568,7 +3568,7 @@ StorePathSet parseReferenceSpecifiers(Store & store, const BasicDerivation & drv if (store.isStorePath(i)) result.insert(store.parseStorePath(i)); else if (drv.outputs.count(i)) - result.insert(drv.outputs.find(i)->second.path.clone()); + result.insert(drv.outputs.find(i)->second.path); else throw BuildError("derivation contains an illegal reference specifier '%s'", i); } return result; @@ -3626,9 +3626,9 @@ void DerivationGoal::registerOutputs() output paths, and any paths that have been built via recursive Nix calls. */ StorePathSet referenceablePaths; - for (auto & p : inputPaths) referenceablePaths.insert(p.clone()); - for (auto & i : drv->outputs) referenceablePaths.insert(i.second.path.clone()); - for (auto & p : addedPaths) referenceablePaths.insert(p.clone()); + for (auto & p : inputPaths) referenceablePaths.insert(p); + for (auto & i : drv->outputs) referenceablePaths.insert(i.second.path); + for (auto & p : addedPaths) referenceablePaths.insert(p); /* Check whether the output paths were created, and grep each output path to determine what other paths it references. Also make all @@ -3827,7 +3827,7 @@ void DerivationGoal::registerOutputs() info.narHash = hash.first; info.narSize = hash.second; info.references = std::move(references); - info.deriver = drvPath.clone(); + info.deriver = drvPath; info.ultimate = true; info.ca = ca; worker.store.signPathInfo(info); @@ -3942,23 +3942,23 @@ void DerivationGoal::checkOutputs(const std::map & outputs) uint64_t closureSize = 0; StorePathSet pathsDone; std::queue pathsLeft; - pathsLeft.push(path.clone()); + pathsLeft.push(path); while (!pathsLeft.empty()) { - auto path = pathsLeft.front().clone(); + auto path = pathsLeft.front(); pathsLeft.pop(); - if (!pathsDone.insert(path.clone()).second) continue; + if (!pathsDone.insert(path).second) continue; auto i = outputsByPath.find(worker.store.printStorePath(path)); if (i != outputsByPath.end()) { closureSize += i->second.narSize; for (auto & ref : i->second.references) - pathsLeft.push(ref.clone()); + pathsLeft.push(ref); } else { auto info = worker.store.queryPathInfo(path); closureSize += info->narSize; for (auto & ref : info->references) - pathsLeft.push(ref.clone()); + pathsLeft.push(ref); } } @@ -3985,8 +3985,8 @@ void DerivationGoal::checkOutputs(const std::map & outputs) auto spec = parseReferenceSpecifiers(worker.store, *drv, *value); auto used = recursive - ? cloneStorePathSet(getClosure(info.path).first) - : cloneStorePathSet(info.references); + ? getClosure(info.path).first + : info.references; if (recursive && checks.ignoreSelfRefs) used.erase(info.path); @@ -3996,10 +3996,10 @@ void DerivationGoal::checkOutputs(const std::map & outputs) for (auto & i : used) if (allowed) { if (!spec.count(i)) - badPaths.insert(i.clone()); + badPaths.insert(i); } else { if (spec.count(i)) - badPaths.insert(i.clone()); + badPaths.insert(i); } if (!badPaths.empty()) { @@ -4199,7 +4199,7 @@ StorePathSet DerivationGoal::checkPathValidity(bool returnValid, bool checkHash) bool good = worker.store.isValidPath(i.second.path) && (!checkHash || worker.pathContentsGood(i.second.path)); - if (good == returnValid) result.insert(i.second.path.clone()); + if (good == returnValid) result.insert(i.second.path); } return result; } @@ -4215,7 +4215,7 @@ void DerivationGoal::addHashRewrite(const StorePath & path) deletePath(worker.store.printStorePath(p)); inputRewrites[h1] = h2; outputRewrites[h2] = h1; - redirectedOutputs.insert_or_assign(path.clone(), std::move(p)); + redirectedOutputs.insert_or_assign(path, std::move(p)); } @@ -4290,7 +4290,7 @@ private: GoalState state; public: - SubstitutionGoal(StorePath && storePath, Worker & worker, RepairFlag repair = NoRepair); + SubstitutionGoal(const StorePath & storePath, Worker & worker, RepairFlag repair = NoRepair); ~SubstitutionGoal(); void timedOut(Error && ex) override { abort(); }; @@ -4316,13 +4316,13 @@ public: void handleChildOutput(int fd, const string & data) override; void handleEOF(int fd) override; - StorePath getStorePath() { return storePath.clone(); } + StorePath getStorePath() { return storePath; } }; -SubstitutionGoal::SubstitutionGoal(StorePath && storePath, Worker & worker, RepairFlag repair) +SubstitutionGoal::SubstitutionGoal(const StorePath & storePath, Worker & worker, RepairFlag repair) : Goal(worker) - , storePath(std::move(storePath)) + , storePath(storePath) , repair(repair) { state = &SubstitutionGoal::init; @@ -4556,7 +4556,7 @@ void SubstitutionGoal::finished() return; } - worker.markContentsGood(storePath.clone()); + worker.markContentsGood(storePath); printMsg(lvlChatty, "substitution of path '%s' succeeded", worker.store.printStorePath(storePath)); @@ -4626,10 +4626,10 @@ Worker::~Worker() GoalPtr Worker::makeDerivationGoal(const StorePath & path, const StringSet & wantedOutputs, BuildMode buildMode) { - GoalPtr goal = derivationGoals[path.clone()].lock(); // FIXME + GoalPtr goal = derivationGoals[path].lock(); // FIXME if (!goal) { - goal = std::make_shared(path.clone(), wantedOutputs, *this, buildMode); - derivationGoals.insert_or_assign(path.clone(), goal); + goal = std::make_shared(path, wantedOutputs, *this, buildMode); + derivationGoals.insert_or_assign(path, goal); wakeUp(goal); } else (dynamic_cast(goal.get()))->addWantedOutputs(wantedOutputs); @@ -4637,10 +4637,10 @@ GoalPtr Worker::makeDerivationGoal(const StorePath & path, } -std::shared_ptr Worker::makeBasicDerivationGoal(StorePath && drvPath, +std::shared_ptr Worker::makeBasicDerivationGoal(const StorePath & drvPath, const BasicDerivation & drv, BuildMode buildMode) { - auto goal = std::make_shared(std::move(drvPath), drv, *this, buildMode); + auto goal = std::make_shared(drvPath, drv, *this, buildMode); wakeUp(goal); return goal; } @@ -4648,10 +4648,10 @@ std::shared_ptr Worker::makeBasicDerivationGoal(StorePath && drv GoalPtr Worker::makeSubstitutionGoal(const StorePath & path, RepairFlag repair) { - GoalPtr goal = substitutionGoals[path.clone()].lock(); // FIXME + GoalPtr goal = substitutionGoals[path].lock(); // FIXME if (!goal) { - goal = std::make_shared(path.clone(), *this, repair); - substitutionGoals.insert_or_assign(path.clone(), goal); + goal = std::make_shared(path, *this, repair); + substitutionGoals.insert_or_assign(path, goal); wakeUp(goal); } return goal; @@ -4996,7 +4996,7 @@ bool Worker::pathContentsGood(const StorePath & path) Hash nullHash(htSHA256); res = info->narHash == nullHash || info->narHash == current.first; } - pathContentsGoodCache.insert_or_assign(path.clone(), res); + pathContentsGoodCache.insert_or_assign(path, res); if (!res) logError({ .name = "Corrupted path", @@ -5006,9 +5006,9 @@ bool Worker::pathContentsGood(const StorePath & path) } -void Worker::markContentsGood(StorePath && path) +void Worker::markContentsGood(const StorePath & path) { - pathContentsGoodCache.insert_or_assign(std::move(path), true); + pathContentsGoodCache.insert_or_assign(path, true); } @@ -5073,7 +5073,7 @@ BuildResult LocalStore::buildDerivation(const StorePath & drvPath, const BasicDe BuildMode buildMode) { Worker worker(*this); - auto goal = worker.makeBasicDerivationGoal(drvPath.clone(), drv, buildMode); + auto goal = worker.makeBasicDerivationGoal(drvPath, drv, buildMode); BuildResult result; @@ -5094,7 +5094,7 @@ void LocalStore::ensurePath(const StorePath & path) /* If the path is already valid, we're done. */ if (isValidPath(path)) return; - primeCache(*this, {StorePathWithOutputs(path)}); + primeCache(*this, {{path}}); Worker worker(*this); GoalPtr goal = worker.makeSubstitutionGoal(path); diff --git a/src/libstore/daemon.cc b/src/libstore/daemon.cc index 620722516..e370e278c 100644 --- a/src/libstore/daemon.cc +++ b/src/libstore/daemon.cc @@ -293,7 +293,7 @@ static void performOp(TunnelLogger * logger, ref store, auto path = store->parseStorePath(readString(from)); logger->startWork(); StorePathSet paths; // FIXME - paths.insert(path.clone()); + paths.insert(path); auto res = store->querySubstitutablePaths(paths); logger->stopWork(); to << (res.count(path) != 0); @@ -327,7 +327,7 @@ static void performOp(TunnelLogger * logger, ref store, StorePathSet paths; if (op == wopQueryReferences) for (auto & i : store->queryPathInfo(path)->references) - paths.insert(i.clone()); + paths.insert(i); else if (op == wopQueryReferrers) store->queryReferrers(path, paths); else if (op == wopQueryValidDerivers) @@ -593,9 +593,7 @@ static void performOp(TunnelLogger * logger, ref store, auto path = store->parseStorePath(readString(from)); logger->startWork(); SubstitutablePathInfos infos; - StorePathSet paths; - paths.insert(path.clone()); // FIXME - store->querySubstitutablePathInfos(paths, infos); + store->querySubstitutablePathInfos({path}, infos); logger->stopWork(); auto i = infos.find(path); if (i == infos.end()) diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc index 915e02eed..b95f7bfdc 100644 --- a/src/libstore/derivations.cc +++ b/src/libstore/derivations.cc @@ -27,28 +27,6 @@ void DerivationOutput::parseHashInfo(FileIngestionMethod & recursive, Hash & has } -BasicDerivation::BasicDerivation(const BasicDerivation & other) - : platform(other.platform) - , builder(other.builder) - , args(other.args) - , env(other.env) -{ - for (auto & i : other.outputs) - outputs.insert_or_assign(i.first, - DerivationOutput(i.second.path.clone(), std::string(i.second.hashAlgo), std::string(i.second.hash))); - for (auto & i : other.inputSrcs) - inputSrcs.insert(i.clone()); -} - - -Derivation::Derivation(const Derivation & other) - : BasicDerivation(other) -{ - for (auto & i : other.inputDrvs) - inputDrvs.insert_or_assign(i.first.clone(), i.second); -} - - const StorePath & BasicDerivation::findOutput(const string & id) const { auto i = outputs.find(id); @@ -67,9 +45,9 @@ bool BasicDerivation::isBuiltin() const StorePath writeDerivation(ref store, const Derivation & drv, std::string_view name, RepairFlag repair) { - auto references = cloneStorePathSet(drv.inputSrcs); + auto references = drv.inputSrcs; for (auto & i : drv.inputDrvs) - references.insert(i.first.clone()); + references.insert(i.first); /* Note that the outputs of a derivation are *not* references (that can be missing (of course) and should not necessarily be held during a garbage collection). */ @@ -155,7 +133,11 @@ static Derivation parseDerivation(const Store & store, const string & s) expect(str, ","); auto hashAlgo = parseString(str); expect(str, ","); auto hash = parseString(str); expect(str, ")"); - drv.outputs.emplace(id, DerivationOutput(std::move(path), std::move(hashAlgo), std::move(hash))); + drv.outputs.emplace(id, DerivationOutput { + .path = std::move(path), + .hashAlgo = std::move(hashAlgo), + .hash = std::move(hash) + }); } /* Parse the list of input derivations. */ @@ -383,7 +365,7 @@ Hash hashDerivationModulo(Store & store, const Derivation & drv, bool maskOutput auto h = drvHashes.find(i.first); if (h == drvHashes.end()) { assert(store.isValidPath(i.first)); - h = drvHashes.insert_or_assign(i.first.clone(), hashDerivationModulo(store, + h = drvHashes.insert_or_assign(i.first, hashDerivationModulo(store, store.readDerivation(i.first), false)).first; } inputs2.insert_or_assign(h->second.to_string(Base16, false), i.second); @@ -411,7 +393,7 @@ StorePathSet BasicDerivation::outputPaths() const { StorePathSet paths; for (auto & i : outputs) - paths.insert(i.second.path.clone()); + paths.insert(i.second.path); return paths; } @@ -434,7 +416,11 @@ Source & readDerivation(Source & in, const Store & store, BasicDerivation & drv) auto path = store.parseStorePath(readString(in)); auto hashAlgo = readString(in); auto hash = readString(in); - drv.outputs.emplace(name, DerivationOutput(std::move(path), std::move(hashAlgo), std::move(hash))); + drv.outputs.emplace(name, DerivationOutput { + .path = std::move(path), + .hashAlgo = std::move(hashAlgo), + .hash = std::move(hash) + }); } drv.inputSrcs = readStorePaths(store, in); diff --git a/src/libstore/derivations.hh b/src/libstore/derivations.hh index 88aed66bf..d349c6d4d 100644 --- a/src/libstore/derivations.hh +++ b/src/libstore/derivations.hh @@ -17,11 +17,6 @@ struct DerivationOutput StorePath path; std::string hashAlgo; /* hash used for expected hash computation */ std::string hash; /* expected hash, may be null */ - DerivationOutput(StorePath && path, std::string && hashAlgo, std::string && hash) - : path(std::move(path)) - , hashAlgo(std::move(hashAlgo)) - , hash(std::move(hash)) - { } void parseHashInfo(FileIngestionMethod & recursive, Hash & hash) const; }; @@ -43,7 +38,6 @@ struct BasicDerivation StringPairs env; BasicDerivation() { } - explicit BasicDerivation(const BasicDerivation & other); virtual ~BasicDerivation() { }; /* Return the path corresponding to the output identifier `id' in @@ -71,8 +65,6 @@ struct Derivation : BasicDerivation std::map * actualInputs = nullptr) const; Derivation() { } - Derivation(Derivation && other) = default; - explicit Derivation(const Derivation & other); }; diff --git a/src/libstore/export-import.cc b/src/libstore/export-import.cc index 54471d4a3..cb9da027d 100644 --- a/src/libstore/export-import.cc +++ b/src/libstore/export-import.cc @@ -105,7 +105,7 @@ StorePaths Store::importPaths(Source & source, std::shared_ptr acces auto source = StringSource { *tee.source.data }; addToStore(info, source, NoRepair, checkSigs, accessor); - res.push_back(info.path.clone()); + res.push_back(info.path); } return res; diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index 04e3849f7..57fb20845 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -128,7 +128,7 @@ Path LocalFSStore::addPermRoot(const StorePath & storePath, gcroots directory. */ if (settings.checkRootReachability) { auto roots = findRoots(false); - if (roots[storePath.clone()].count(gcRoot) == 0) + if (roots[storePath].count(gcRoot) == 0) logWarning({ .name = "GC root", .hint = hintfmt("warning: '%1%' is not in a directory where the garbage collector looks for roots; " @@ -478,9 +478,9 @@ void LocalStore::findRuntimeRoots(Roots & roots, bool censor) if (!isValidPath(path)) continue; debug("got additional root '%1%'", pathS); if (censor) - roots[path.clone()].insert(censored); + roots[path].insert(censored); else - roots[path.clone()].insert(links.begin(), links.end()); + roots[path].insert(links.begin(), links.end()); } } @@ -592,11 +592,11 @@ bool LocalStore::canReachRoot(GCState & state, StorePathSet & visited, const Sto if (state.roots.count(path)) { debug("cannot delete '%1%' because it's a root", printStorePath(path)); - state.alive.insert(path.clone()); + state.alive.insert(path); return true; } - visited.insert(path.clone()); + visited.insert(path); if (!isValidPath(path)) return false; @@ -610,7 +610,7 @@ bool LocalStore::canReachRoot(GCState & state, StorePathSet & visited, const Sto if (state.gcKeepDerivations && path.isDerivation()) { for (auto & i : queryDerivationOutputs(path)) if (isValidPath(i) && queryPathInfo(i)->deriver == path) - incoming.insert(i.clone()); + incoming.insert(i); } /* If keep-outputs is set, then don't delete this path if there @@ -618,13 +618,13 @@ bool LocalStore::canReachRoot(GCState & state, StorePathSet & visited, const Sto if (state.gcKeepOutputs) { auto derivers = queryValidDerivers(path); for (auto & i : derivers) - incoming.insert(i.clone()); + incoming.insert(i); } for (auto & i : incoming) if (i != path) if (canReachRoot(state, visited, i)) { - state.alive.insert(path.clone()); + state.alive.insert(path); return true; } @@ -668,7 +668,7 @@ void LocalStore::tryToDelete(GCState & state, const Path & path) ‘nix-store --delete’ doesn't have the unexpected effect of recursing into derivations and outputs. */ for (auto & i : visited) - state.dead.insert(i.clone()); + state.dead.insert(i); if (state.shouldDelete) deletePathRecursive(state, path); } @@ -754,7 +754,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) if (!options.ignoreLiveness) findRootsNoTemp(rootMap, true); - for (auto & i : rootMap) state.roots.insert(i.first.clone()); + for (auto & i : rootMap) state.roots.insert(i.first); /* Read the temporary roots. This acquires read locks on all per-process temporary root files. So after this point no paths @@ -763,8 +763,8 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) Roots tempRoots; findTempRoots(fds, tempRoots, true); for (auto & root : tempRoots) { - state.tempRoots.insert(root.first.clone()); - state.roots.insert(root.first.clone()); + state.tempRoots.insert(root.first); + state.roots.insert(root.first); } /* After this point the set of roots or temporary roots cannot diff --git a/src/libstore/legacy-ssh-store.cc b/src/libstore/legacy-ssh-store.cc index af20d389b..45c70fad6 100644 --- a/src/libstore/legacy-ssh-store.cc +++ b/src/libstore/legacy-ssh-store.cc @@ -256,7 +256,7 @@ struct LegacySSHStore : public Store conn->to.flush(); for (auto & i : readStorePaths(*this, conn->from)) - out.insert(i.clone()); + out.insert(i); } StorePathSet queryValidPaths(const StorePathSet & paths, diff --git a/src/libstore/local-fs-store.cc b/src/libstore/local-fs-store.cc index 2d564a0d7..dd96d2578 100644 --- a/src/libstore/local-fs-store.cc +++ b/src/libstore/local-fs-store.cc @@ -90,13 +90,13 @@ const string LocalFSStore::drvsLogDir = "drvs"; std::shared_ptr LocalFSStore::getBuildLog(const StorePath & path_) { - auto path = path_.clone(); + auto path = path_; if (!path.isDerivation()) { try { auto info = queryPathInfo(path); if (!info->deriver) return nullptr; - path = info->deriver->clone(); + path = *info->deriver; } catch (InvalidPath &) { return nullptr; } diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index e3b718e88..0df4374b9 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -631,7 +631,7 @@ void LocalStore::queryPathInfoUncached(const StorePath & path, Callback> callback) noexcept { try { - auto info = std::make_shared(path.clone()); + auto info = std::make_shared(path); callback(retrySQLite>([&]() { auto state(_state.lock()); @@ -721,7 +721,7 @@ StorePathSet LocalStore::queryValidPaths(const StorePathSet & paths, SubstituteF { StorePathSet res; for (auto & i : paths) - if (isValidPath(i)) res.insert(i.clone()); + if (isValidPath(i)) res.insert(i); return res; } @@ -816,7 +816,7 @@ StorePathSet LocalStore::querySubstitutablePaths(const StorePathSet & paths) StorePathSet remaining; for (auto & i : paths) - remaining.insert(i.clone()); + remaining.insert(i); StorePathSet res; @@ -830,9 +830,9 @@ StorePathSet LocalStore::querySubstitutablePaths(const StorePathSet & paths) StorePathSet remaining2; for (auto & path : remaining) if (valid.count(path)) - res.insert(path.clone()); + res.insert(path); else - remaining2.insert(path.clone()); + remaining2.insert(path); std::swap(remaining, remaining2); } @@ -854,9 +854,9 @@ void LocalStore::querySubstitutablePathInfos(const StorePathSet & paths, auto info = sub->queryPathInfo(path); auto narInfo = std::dynamic_pointer_cast( std::shared_ptr(info)); - infos.insert_or_assign(path.clone(), SubstitutablePathInfo{ - info->deriver ? info->deriver->clone() : std::optional(), - cloneStorePathSet(info->references), + infos.insert_or_assign(path, SubstitutablePathInfo{ + info->deriver, + info->references, narInfo ? narInfo->fileSize : 0, info->narSize}); } catch (InvalidPath &) { @@ -900,7 +900,7 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos) updatePathInfo(*state, i); else addValidPath(*state, i, false); - paths.insert(i.path.clone()); + paths.insert(i.path); } for (auto & i : infos) { @@ -1074,7 +1074,7 @@ StorePath LocalStore::addToStoreFromDump(const string & dump, const string & nam optimisePath(realPath); // FIXME: combine with hashPath() - ValidPathInfo info(dstPath.clone()); + ValidPathInfo info(dstPath); info.narHash = hash.first; info.narSize = hash.second; info.ca = makeFixedOutputCA(method, h); @@ -1137,10 +1137,10 @@ StorePath LocalStore::addTextToStore(const string & name, const string & s, optimisePath(realPath); - ValidPathInfo info(dstPath.clone()); + ValidPathInfo info(dstPath); info.narHash = narHash; info.narSize = sink.s->size(); - info.references = cloneStorePathSet(references); + info.references = references; info.ca = "text:" + hash.to_string(Base32, true); registerValidPath(info); } diff --git a/src/libstore/misc.cc b/src/libstore/misc.cc index 9c47fe524..e68edb38c 100644 --- a/src/libstore/misc.cc +++ b/src/libstore/misc.cc @@ -103,7 +103,7 @@ void Store::computeFSClosure(const StorePath & startPath, StorePathSet & paths_, bool flipDirection, bool includeOutputs, bool includeDerivers) { StorePathSet paths; - paths.insert(startPath.clone()); + paths.insert(startPath); computeFSClosure(paths, paths_, flipDirection, includeOutputs, includeDerivers); } @@ -141,11 +141,11 @@ void Store::queryMissing(const std::vector & targets, auto mustBuildDrv = [&](const StorePath & drvPath, const Derivation & drv) { { auto state(state_.lock()); - state->willBuild.insert(drvPath.clone()); + state->willBuild.insert(drvPath); } for (auto & i : drv.inputDrvs) - pool.enqueue(std::bind(doPath, StorePathWithOutputs(i.first, i.second))); + pool.enqueue(std::bind(doPath, StorePathWithOutputs { i.first, i.second })); }; auto checkOutput = [&]( @@ -157,9 +157,7 @@ void Store::queryMissing(const std::vector & targets, auto outPath = parseStorePath(outPathS); SubstitutablePathInfos infos; - StorePathSet paths; // FIXME - paths.insert(outPath.clone()); - querySubstitutablePathInfos(paths, infos); + querySubstitutablePathInfos({outPath}, infos); if (infos.empty()) { drvState_->lock()->done = true; @@ -170,10 +168,10 @@ void Store::queryMissing(const std::vector & targets, if (drvState->done) return; assert(drvState->left); drvState->left--; - drvState->outPaths.insert(outPath.clone()); + drvState->outPaths.insert(outPath); if (!drvState->left) { for (auto & path : drvState->outPaths) - pool.enqueue(std::bind(doPath, StorePathWithOutputs(path.clone()))); + pool.enqueue(std::bind(doPath, StorePathWithOutputs { path } )); } } } @@ -190,12 +188,12 @@ void Store::queryMissing(const std::vector & targets, if (!isValidPath(path.path)) { // FIXME: we could try to substitute the derivation. auto state(state_.lock()); - state->unknown.insert(path.path.clone()); + state->unknown.insert(path.path); return; } auto drv = make_ref(derivationFromPath(path.path)); - ParsedDerivation parsedDrv(path.path.clone(), *drv); + ParsedDerivation parsedDrv(StorePath(path.path), *drv); PathSet invalid; for (auto & j : drv->outputs) @@ -216,13 +214,11 @@ void Store::queryMissing(const std::vector & targets, if (isValidPath(path.path)) return; SubstitutablePathInfos infos; - StorePathSet paths; // FIXME - paths.insert(path.path.clone()); - querySubstitutablePathInfos(paths, infos); + querySubstitutablePathInfos({path.path}, infos); if (infos.empty()) { auto state(state_.lock()); - state->unknown.insert(path.path.clone()); + state->unknown.insert(path.path); return; } @@ -231,13 +227,13 @@ void Store::queryMissing(const std::vector & targets, { auto state(state_.lock()); - state->willSubstitute.insert(path.path.clone()); + state->willSubstitute.insert(path.path); state->downloadSize += info->second.downloadSize; state->narSize += info->second.narSize; } for (auto & ref : info->second.references) - pool.enqueue(std::bind(doPath, StorePathWithOutputs(ref))); + pool.enqueue(std::bind(doPath, StorePathWithOutputs { ref })); } }; @@ -260,12 +256,12 @@ StorePaths Store::topoSortPaths(const StorePathSet & paths) throw BuildError("cycle detected in the references of '%s' from '%s'", printStorePath(path), printStorePath(*parent)); - if (!visited.insert(path.clone()).second) return; - parents.insert(path.clone()); + if (!visited.insert(path).second) return; + parents.insert(path); StorePathSet references; try { - references = cloneStorePathSet(queryPathInfo(path)->references); + references = queryPathInfo(path)->references; } catch (InvalidPath &) { } @@ -275,7 +271,7 @@ StorePaths Store::topoSortPaths(const StorePathSet & paths) if (i != path && paths.count(i)) dfsVisit(i, &path); - sorted.push_back(path.clone()); + sorted.push_back(path); parents.erase(path); }; diff --git a/src/libstore/nar-info.cc b/src/libstore/nar-info.cc index d7fc30e91..bb4448c90 100644 --- a/src/libstore/nar-info.cc +++ b/src/libstore/nar-info.cc @@ -4,7 +4,7 @@ namespace nix { NarInfo::NarInfo(const Store & store, const std::string & s, const std::string & whence) - : ValidPathInfo(StorePath::dummy.clone()) // FIXME: hack + : ValidPathInfo(StorePath(StorePath::dummy)) // FIXME: hack { auto corrupt = [&]() { throw Error("NAR info file '%1%' is corrupt", whence); diff --git a/src/libstore/parsed-derivations.cc b/src/libstore/parsed-derivations.cc index 45c033c66..24f848e46 100644 --- a/src/libstore/parsed-derivations.cc +++ b/src/libstore/parsed-derivations.cc @@ -4,8 +4,8 @@ namespace nix { -ParsedDerivation::ParsedDerivation(StorePath && drvPath, BasicDerivation & drv) - : drvPath(std::move(drvPath)), drv(drv) +ParsedDerivation::ParsedDerivation(const StorePath & drvPath, BasicDerivation & drv) + : drvPath(drvPath), drv(drv) { /* Parse the __json attribute, if any. */ auto jsonAttr = drv.env.find("__json"); diff --git a/src/libstore/parsed-derivations.hh b/src/libstore/parsed-derivations.hh index f4df5dd54..7621342d7 100644 --- a/src/libstore/parsed-derivations.hh +++ b/src/libstore/parsed-derivations.hh @@ -12,7 +12,7 @@ class ParsedDerivation public: - ParsedDerivation(StorePath && drvPath, BasicDerivation & drv); + ParsedDerivation(const StorePath & drvPath, BasicDerivation & drv); ~ParsedDerivation(); diff --git a/src/libstore/path.cc b/src/libstore/path.cc index bb2089ea4..b3d8ce95c 100644 --- a/src/libstore/path.cc +++ b/src/libstore/path.cc @@ -84,29 +84,6 @@ PathSet Store::printStorePathSet(const StorePathSet & paths) const return res; } -StorePathSet cloneStorePathSet(const StorePathSet & paths) -{ - StorePathSet res; - for (auto & p : paths) - res.insert(p.clone()); - return res; -} - -StorePathSet storePathsToSet(const StorePaths & paths) -{ - StorePathSet res; - for (auto & p : paths) - res.insert(p.clone()); - return res; -} - -StorePathSet singleton(const StorePath & path) -{ - StorePathSet res; - res.insert(path.clone()); - return res; -} - std::pair parsePathWithOutputs(std::string_view s) { size_t n = s.find("!"); diff --git a/src/libstore/path.hh b/src/libstore/path.hh index 85c3d8e53..aaebd3ec3 100644 --- a/src/libstore/path.hh +++ b/src/libstore/path.hh @@ -11,10 +11,6 @@ class StorePath { std::string baseName; - StorePath(const StorePath & path) - : baseName(path.baseName) - { } - public: /* Size of the hash part of store paths, in base-32 characters. */ @@ -26,16 +22,6 @@ public: StorePath(const Hash & hash, std::string_view name); - StorePath(StorePath && path) - : baseName(std::move(path.baseName)) - { } - - StorePath & operator = (StorePath && path) - { - baseName = std::move(path.baseName); - return *this; - } - std::string_view to_string() const { return baseName; @@ -56,11 +42,6 @@ public: return baseName != other.baseName; } - StorePath clone() const - { - return StorePath(*this); - } - /* Check whether a file name ends with the extension for derivations. */ bool isDerivation() const; @@ -81,11 +62,6 @@ public: typedef std::set StorePathSet; typedef std::vector StorePaths; -StorePathSet cloneStorePathSet(const StorePathSet & paths); -StorePathSet storePathsToSet(const StorePaths & paths); - -StorePathSet singleton(const StorePath & path); - /* Extension of derivations in the Nix store. */ const std::string drvExtension = ".drv"; @@ -99,18 +75,6 @@ struct StorePathWithOutputs StorePath path; std::set outputs; - StorePathWithOutputs(const StorePath & path, const std::set & outputs = {}) - : path(path.clone()), outputs(outputs) - { } - - StorePathWithOutputs(StorePath && path, std::set && outputs) - : path(std::move(path)), outputs(std::move(outputs)) - { } - - StorePathWithOutputs(const StorePathWithOutputs & other) - : path(other.path.clone()), outputs(other.outputs) - { } - std::string to_string(const Store & store) const; }; diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index 99fee8150..fc5ab5865 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -268,7 +268,7 @@ StorePathSet RemoteStore::queryValidPaths(const StorePathSet & paths, Substitute if (GET_PROTOCOL_MINOR(conn->daemonVersion) < 12) { StorePathSet res; for (auto & i : paths) - if (isValidPath(i)) res.insert(i.clone()); + if (isValidPath(i)) res.insert(i); return res; } else { conn->to << wopQueryValidPaths; @@ -296,7 +296,7 @@ StorePathSet RemoteStore::querySubstitutablePaths(const StorePathSet & paths) for (auto & i : paths) { conn->to << wopHasSubstitutes << printStorePath(i); conn.processStderr(); - if (readInt(conn->from)) res.insert(i.clone()); + if (readInt(conn->from)) res.insert(i); } return res; } else { @@ -329,7 +329,7 @@ void RemoteStore::querySubstitutablePathInfos(const StorePathSet & paths, info.references = readStorePaths(*this, conn->from); info.downloadSize = readLongLong(conn->from); info.narSize = readLongLong(conn->from); - infos.insert_or_assign(i.clone(), std::move(info)); + infos.insert_or_assign(i, std::move(info)); } } else { @@ -372,7 +372,7 @@ void RemoteStore::queryPathInfoUncached(const StorePath & path, bool valid; conn->from >> valid; if (!valid) throw InvalidPath("path '%s' is not valid", printStorePath(path)); } - info = std::make_shared(path.clone()); + info = std::make_shared(StorePath(path)); auto deriver = readString(conn->from); if (deriver != "") info->deriver = parseStorePath(deriver); info->narHash = Hash(readString(conn->from), htSHA256); @@ -396,7 +396,7 @@ void RemoteStore::queryReferrers(const StorePath & path, conn->to << wopQueryReferrers << printStorePath(path); conn.processStderr(); for (auto & i : readStorePaths(*this, conn->from)) - referrers.insert(i.clone()); + referrers.insert(i); } diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index 42e26c427..aae227bae 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -55,7 +55,7 @@ StorePath Store::followLinksToStorePath(std::string_view path) const StorePathWithOutputs Store::followLinksToStorePathWithOutputs(std::string_view path) const { auto [path2, outputs] = nix::parsePathWithOutputs(path); - return StorePathWithOutputs(followLinksToStorePath(path2), std::move(outputs)); + return StorePathWithOutputs { followLinksToStorePath(path2), std::move(outputs) }; } @@ -545,7 +545,7 @@ void Store::buildPaths(const std::vector & paths, BuildMod for (auto & path : paths) { if (path.path.isDerivation()) unsupported("buildPaths"); - paths2.insert(path.path.clone()); + paths2.insert(path.path); } if (queryValidPaths(paths2).size() != paths2.size()) @@ -685,21 +685,6 @@ void copyClosure(ref srcStore, ref dstStore, } -ValidPathInfo::ValidPathInfo(const ValidPathInfo & other) - : path(other.path.clone()) - , deriver(other.deriver ? other.deriver->clone(): std::optional{}) - , narHash(other.narHash) - , references(cloneStorePathSet(other.references)) - , registrationTime(other.registrationTime) - , narSize(other.narSize) - , id(other.id) - , ultimate(other.ultimate) - , sigs(other.sigs) - , ca(other.ca) -{ -} - - std::optional decodeValidPathInfo(const Store & store, std::istream & str, bool hashGiven) { std::string path; @@ -785,7 +770,7 @@ bool ValidPathInfo::isContentAddressed(const Store & store) const else if (hasPrefix(ca, "fixed:")) { FileIngestionMethod recursive { ca.compare(6, 2, "r:") == 0 }; Hash hash(ca.substr(recursive == FileIngestionMethod::Recursive ? 8 : 6)); - auto refs = cloneStorePathSet(references); + auto refs = references; bool hasSelfReference = false; if (refs.count(path)) { hasSelfReference = true; diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh index 251fc4638..6f4dd959c 100644 --- a/src/libstore/store-api.hh +++ b/src/libstore/store-api.hh @@ -189,8 +189,9 @@ struct ValidPathInfo Strings shortRefs() const; + ValidPathInfo(const StorePath & path) : path(path) { } + ValidPathInfo(StorePath && path) : path(std::move(path)) { } - explicit ValidPathInfo(const ValidPathInfo & other); virtual ~ValidPathInfo() { } }; diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc index da6f005a3..a224d635d 100755 --- a/src/nix-build/nix-build.cc +++ b/src/nix-build/nix-build.cc @@ -363,7 +363,7 @@ static void _main(int argc, char * * argv) if (!drv) throw Error("the 'bashInteractive' attribute in did not evaluate to a derivation"); - pathsToBuild.emplace_back(store->parseStorePath(drv->queryDrvPath())); + pathsToBuild.push_back({store->parseStorePath(drv->queryDrvPath())}); shell = drv->queryOutPath() + "/bin/bash"; @@ -381,9 +381,9 @@ static void _main(int argc, char * * argv) for (const auto & input : drv.inputDrvs) if (std::all_of(envExclude.cbegin(), envExclude.cend(), [&](const string & exclude) { return !std::regex_search(store->printStorePath(input.first), std::regex(exclude)); })) - pathsToBuild.emplace_back(input.first, input.second); + pathsToBuild.push_back({input.first, input.second}); for (const auto & src : drv.inputSrcs) - pathsToBuild.emplace_back(src); + pathsToBuild.push_back({src}); buildPaths(pathsToBuild); @@ -499,7 +499,7 @@ static void _main(int argc, char * * argv) if (outputName == "") throw Error("derivation '%s' lacks an 'outputName' attribute", drvPath); - pathsToBuild.emplace_back(store->parseStorePath(drvPath), StringSet{outputName}); + pathsToBuild.push_back({store->parseStorePath(drvPath), {outputName}}); std::string drvPrefix; auto i = drvPrefixes.find(drvPath); diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index 2c27d97f5..8b0692035 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -212,9 +212,7 @@ static bool isPrebuilt(EvalState & state, DrvInfo & elem) { auto path = state.store->parseStorePath(elem.queryOutPath()); if (state.store->isValidPath(path)) return true; - StorePathSet paths; - paths.insert(path.clone()); // FIXME: why doesn't StorePathSet{path.clone()} work? - return state.store->querySubstitutablePaths(paths).count(path); + return state.store->querySubstitutablePaths({path}).count(path); } @@ -425,9 +423,9 @@ static void printMissing(EvalState & state, DrvInfos & elems) for (auto & i : elems) { Path drvPath = i.queryDrvPath(); if (drvPath != "") - targets.emplace_back(state.store->parseStorePath(drvPath)); + targets.push_back({state.store->parseStorePath(drvPath)}); else - targets.emplace_back(state.store->parseStorePath(i.queryOutPath())); + targets.push_back({state.store->parseStorePath(i.queryOutPath())}); } printMissing(state.store, targets); @@ -697,13 +695,13 @@ static void opSet(Globals & globals, Strings opFlags, Strings opArgs) drv.setName(globals.forceName); if (drv.queryDrvPath() != "") { - std::vector paths{globals.state->store->parseStorePath(drv.queryDrvPath())}; + std::vector paths{{globals.state->store->parseStorePath(drv.queryDrvPath())}}; printMissing(globals.state->store, paths); if (globals.dryRun) return; globals.state->store->buildPaths(paths, globals.state->repair ? bmRepair : bmNormal); } else { printMissing(globals.state->store, - {globals.state->store->parseStorePath(drv.queryOutPath())}); + {{globals.state->store->parseStorePath(drv.queryOutPath())}}); if (globals.dryRun) return; globals.state->store->ensurePath(globals.state->store->parseStorePath(drv.queryOutPath())); } diff --git a/src/nix-env/user-env.cc b/src/nix-env/user-env.cc index f804b77a0..8e7f09e12 100644 --- a/src/nix-env/user-env.cc +++ b/src/nix-env/user-env.cc @@ -134,7 +134,7 @@ bool createUserEnv(EvalState & state, DrvInfos & elems, /* Realise the resulting store expression. */ debug("building user environment"); std::vector topLevelDrvs; - topLevelDrvs.push_back(StorePathWithOutputs{topLevelDrv.clone()}); + topLevelDrvs.push_back({topLevelDrv}); state.store->buildPaths(topLevelDrvs, state.repair ? bmRepair : bmNormal); /* Switch the current user environment to the output path. */ diff --git a/src/nix-store/dotgraph.cc b/src/nix-store/dotgraph.cc index 667d917f5..8b699f39b 100644 --- a/src/nix-store/dotgraph.cc +++ b/src/nix-store/dotgraph.cc @@ -54,13 +54,13 @@ void printDotGraph(ref store, StorePathSet && roots) while (!workList.empty()) { auto path = std::move(workList.extract(workList.begin()).value()); - if (!doneSet.insert(path.clone()).second) continue; + if (!doneSet.insert(path).second) continue; cout << makeNode(std::string(path.to_string()), path.name(), "#ff0000"); for (auto & p : store->queryPathInfo(path)->references) { if (p != path) { - workList.insert(p.clone()); + workList.insert(p); cout << makeEdge(std::string(p.to_string()), std::string(path.to_string())); } } diff --git a/src/nix-store/graphml.cc b/src/nix-store/graphml.cc index 347708851..8ca5c9c8d 100644 --- a/src/nix-store/graphml.cc +++ b/src/nix-store/graphml.cc @@ -65,7 +65,7 @@ void printGraphML(ref store, StorePathSet && roots) while (!workList.empty()) { auto path = std::move(workList.extract(workList.begin()).value()); - ret = doneSet.insert(path.clone()); + ret = doneSet.insert(path); if (ret.second == false) continue; auto info = store->queryPathInfo(path); @@ -73,7 +73,7 @@ void printGraphML(ref store, StorePathSet && roots) for (auto & p : info->references) { if (p != path) { - workList.insert(p.clone()); + workList.insert(p); cout << makeEdge(path.to_string(), p.to_string()); } } diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc index 6d2139526..5c5afd5ec 100644 --- a/src/nix-store/nix-store.cc +++ b/src/nix-store/nix-store.cc @@ -49,11 +49,11 @@ ref ensureLocalStore() static StorePath useDeriver(const StorePath & path) { - if (path.isDerivation()) return path.clone(); + if (path.isDerivation()) return path; auto info = store->queryPathInfo(path); if (!info->deriver) throw Error("deriver of path '%s' is not known", store->printStorePath(path)); - return info->deriver->clone(); + return *info->deriver; } @@ -214,15 +214,15 @@ static void opPrintFixedPath(Strings opFlags, Strings opArgs) static StorePathSet maybeUseOutputs(const StorePath & storePath, bool useOutput, bool forceRealise) { - if (forceRealise) realisePath(storePath); + if (forceRealise) realisePath({storePath}); if (useOutput && storePath.isDerivation()) { auto drv = store->derivationFromPath(storePath); StorePathSet outputs; for (auto & i : drv.outputs) - outputs.insert(i.second.path.clone()); + outputs.insert(i.second.path); return outputs; } - else return singleton(storePath.clone()); + else return {storePath}; } @@ -232,7 +232,7 @@ static StorePathSet maybeUseOutputs(const StorePath & storePath, bool useOutput, static void printTree(const StorePath & path, const string & firstPad, const string & tailPad, StorePathSet & done) { - if (!done.insert(path.clone()).second) { + if (!done.insert(path).second) { cout << fmt("%s%s [...]\n", firstPad, store->printStorePath(path)); return; } @@ -310,7 +310,7 @@ static void opQuery(Strings opFlags, Strings opArgs) case qOutputs: { for (auto & i : opArgs) { auto i2 = store->followLinksToStorePath(i); - if (forceRealise) realisePath(i2); + if (forceRealise) realisePath({i2}); Derivation drv = store->derivationFromPath(i2); for (auto & j : drv.outputs) cout << fmt("%1%\n", store->printStorePath(j.second.path)); @@ -329,13 +329,13 @@ static void opQuery(Strings opFlags, Strings opArgs) if (query == qRequisites) store->computeFSClosure(j, paths, false, includeOutputs); else if (query == qReferences) { for (auto & p : store->queryPathInfo(j)->references) - paths.insert(p.clone()); + paths.insert(p); } else if (query == qReferrers) { StorePathSet tmp; store->queryReferrers(j, tmp); for (auto & i : tmp) - paths.insert(i.clone()); + paths.insert(i); } else if (query == qReferrersClosure) store->computeFSClosure(j, paths, true); } @@ -391,7 +391,7 @@ static void opQuery(Strings opFlags, Strings opArgs) StorePathSet roots; for (auto & i : opArgs) for (auto & j : maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise)) - roots.insert(j.clone()); + roots.insert(j); printDotGraph(ref(store), std::move(roots)); break; } @@ -400,7 +400,7 @@ static void opQuery(Strings opFlags, Strings opArgs) StorePathSet roots; for (auto & i : opArgs) for (auto & j : maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise)) - roots.insert(j.clone()); + roots.insert(j); printGraphML(ref(store), std::move(roots)); break; } @@ -415,7 +415,7 @@ static void opQuery(Strings opFlags, Strings opArgs) StorePathSet args; for (auto & i : opArgs) for (auto & p : maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise)) - args.insert(p.clone()); + args.insert(p); StorePathSet referrers; store->computeFSClosure( @@ -482,10 +482,10 @@ static void opDumpDB(Strings opFlags, Strings opArgs) if (!opFlags.empty()) throw UsageError("unknown flag"); if (!opArgs.empty()) { for (auto & i : opArgs) - cout << store->makeValidityRegistration(singleton(store->followLinksToStorePath(i)), true, true); + cout << store->makeValidityRegistration({store->followLinksToStorePath(i)}, true, true); } else { for (auto & i : store->queryAllValidPaths()) - cout << store->makeValidityRegistration(singleton(i), true, true); + cout << store->makeValidityRegistration({i}, true, true); } } @@ -586,7 +586,7 @@ static void opGC(Strings opFlags, Strings opArgs) // Transpose and sort the roots. for (auto & [target, links] : roots) for (auto & link : links) - roots2.emplace(link, target.clone()); + roots2.emplace(link, target); for (auto & [link, target] : roots2) std::cout << link << " -> " << store->printStorePath(target) << "\n"; } @@ -830,7 +830,7 @@ static void opServe(Strings opFlags, Strings opArgs) std::vector paths2; for (auto & path : paths) if (!path.isDerivation()) - paths2.emplace_back(path.clone()); + paths2.push_back({path}); unsigned long long downloadSize, narSize; StorePathSet willBuild, willSubstitute, unknown; store->queryMissing(paths2, @@ -840,7 +840,7 @@ static void opServe(Strings opFlags, Strings opArgs) if (!willSubstitute.empty()) try { std::vector subs; - for (auto & p : willSubstitute) subs.emplace_back(p.clone()); + for (auto & p : willSubstitute) subs.push_back({p}); store->buildPaths(subs); } catch (Error & e) { logWarning(e.info()); @@ -895,7 +895,7 @@ static void opServe(Strings opFlags, Strings opArgs) std::vector paths; for (auto & s : readStrings(in)) - paths.emplace_back(store->parsePathWithOutputs(s)); + paths.push_back(store->parsePathWithOutputs(s)); getBuildSettings(); diff --git a/src/nix/command.cc b/src/nix/command.cc index 71b027719..d62626c26 100644 --- a/src/nix/command.cc +++ b/src/nix/command.cc @@ -59,19 +59,19 @@ void StorePathsCommand::run(ref store) if (installables.size()) throw UsageError("'--all' does not expect arguments"); for (auto & p : store->queryAllValidPaths()) - storePaths.push_back(p.clone()); + storePaths.push_back(p); } else { for (auto & p : toStorePaths(store, realiseMode, installables)) - storePaths.push_back(p.clone()); + storePaths.push_back(p); if (recursive) { StorePathSet closure; - store->computeFSClosure(storePathsToSet(storePaths), closure, false, false); + store->computeFSClosure(StorePathSet(storePaths.begin(), storePaths.end()), closure, false, false); storePaths.clear(); for (auto & p : closure) - storePaths.push_back(p.clone()); + storePaths.push_back(p); } } @@ -133,7 +133,7 @@ void MixProfile::updateProfile(const Buildables & buildables) for (auto & output : buildable.outputs) { if (result) throw Error("'--profile' requires that the arguments produce a single store path, but there are multiple"); - result = output.second.clone(); + result = output.second; } } diff --git a/src/nix/copy.cc b/src/nix/copy.cc index c7c38709d..64099f476 100644 --- a/src/nix/copy.cc +++ b/src/nix/copy.cc @@ -94,7 +94,7 @@ struct CmdCopy : StorePathsCommand ref dstStore = dstUri.empty() ? openStore() : openStore(dstUri); - copyPaths(srcStore, dstStore, storePathsToSet(storePaths), + copyPaths(srcStore, dstStore, StorePathSet(storePaths.begin(), storePaths.end()), NoRepair, checkSigs, substitute); } }; diff --git a/src/nix/develop.cc b/src/nix/develop.cc index 3045d7dc3..05a9b9cd9 100644 --- a/src/nix/develop.cc +++ b/src/nix/develop.cc @@ -135,12 +135,12 @@ StorePath getDerivationEnvironment(ref store, const StorePath & drvPath) drv.inputSrcs.insert(std::move(getEnvShPath)); Hash h = hashDerivationModulo(*store, drv, true); auto shellOutPath = store->makeOutputPath("out", h, drvName); - drv.outputs.insert_or_assign("out", DerivationOutput(shellOutPath.clone(), "", "")); + drv.outputs.insert_or_assign("out", DerivationOutput { shellOutPath, "", "" }); drv.env["out"] = store->printStorePath(shellOutPath); auto shellDrvPath2 = writeDerivation(store, drv, drvName); /* Build the derivation. */ - store->buildPaths({shellDrvPath2}); + store->buildPaths({{shellDrvPath2}}); assert(store->isValidPath(shellOutPath)); @@ -205,7 +205,7 @@ struct Common : InstallableCommand, MixProfile { auto path = installable->getStorePath(); if (path && hasSuffix(path->to_string(), "-env")) - return path->clone(); + return *path; else { auto drvs = toDerivations(store, {installable}); diff --git a/src/nix/installables.cc b/src/nix/installables.cc index 937d69206..708a0dc88 100644 --- a/src/nix/installables.cc +++ b/src/nix/installables.cc @@ -102,9 +102,9 @@ struct InstallableStorePath : Installable Buildables toBuildables() override { std::map outputs; - outputs.insert_or_assign("out", storePath.clone()); + outputs.insert_or_assign("out", storePath); Buildable b{ - .drvPath = storePath.isDerivation() ? storePath.clone() : std::optional(), + .drvPath = storePath.isDerivation() ? storePath : std::optional(), .outputs = std::move(outputs) }; Buildables bs; @@ -114,7 +114,7 @@ struct InstallableStorePath : Installable std::optional getStorePath() override { - return storePath.clone(); + return storePath; } }; @@ -141,7 +141,7 @@ struct InstallableValue : Installable for (auto & drv : drvs) { Buildable b{.drvPath = state->store->parseStorePath(drv.queryDrvPath())}; - drvPaths.insert(b.drvPath->clone()); + drvPaths.insert(*b.drvPath); auto outputName = drv.queryOutputName(); if (outputName == "") @@ -155,10 +155,10 @@ struct InstallableValue : Installable // Hack to recognize .all: if all drvs have the same drvPath, // merge the buildables. if (drvPaths.size() == 1) { - Buildable b{.drvPath = drvPaths.begin()->clone()}; + Buildable b{.drvPath = *drvPaths.begin()}; for (auto & b2 : res) for (auto & output : b2.outputs) - b.outputs.insert_or_assign(output.first, output.second.clone()); + b.outputs.insert_or_assign(output.first, output.second); Buildables bs; bs.push_back(std::move(b)); return bs; @@ -273,7 +273,7 @@ Buildables build(ref store, RealiseMode mode, pathsToBuild.push_back({*b.drvPath, outputNames}); } else for (auto & output : b.outputs) - pathsToBuild.push_back({output.second.clone()}); + pathsToBuild.push_back({output.second}); buildables.push_back(std::move(b)); } } @@ -293,7 +293,7 @@ StorePathSet toStorePaths(ref store, RealiseMode mode, for (auto & b : build(store, mode, installables)) for (auto & output : b.outputs) - outPaths.insert(output.second.clone()); + outPaths.insert(output.second); return outPaths; } @@ -306,7 +306,7 @@ StorePath toStorePath(ref store, RealiseMode mode, if (paths.size() != 1) throw Error("argument '%s' should evaluate to one store path", installable->what()); - return paths.begin()->clone(); + return *paths.begin(); } StorePathSet toDerivations(ref store, @@ -324,10 +324,10 @@ StorePathSet toDerivations(ref store, if (derivers.empty()) throw Error("'%s' does not have a known deriver", i->what()); // FIXME: use all derivers? - drvPaths.insert(derivers.begin()->clone()); + drvPaths.insert(*derivers.begin()); } } else - drvPaths.insert(b.drvPath->clone()); + drvPaths.insert(*b.drvPath); } return drvPaths; diff --git a/src/nix/make-content-addressable.cc b/src/nix/make-content-addressable.cc index 1211dad7b..0ebb8f13b 100644 --- a/src/nix/make-content-addressable.cc +++ b/src/nix/make-content-addressable.cc @@ -36,7 +36,7 @@ struct CmdMakeContentAddressable : StorePathsCommand, MixJSON void run(ref store, StorePaths storePaths) override { - auto paths = store->topoSortPaths(storePathsToSet(storePaths)); + auto paths = store->topoSortPaths(StorePathSet(storePaths.begin(), storePaths.end())); std::reverse(paths.begin(), paths.end()); @@ -62,7 +62,7 @@ struct CmdMakeContentAddressable : StorePathsCommand, MixJSON hasSelfReference = true; else { auto i = remappings.find(ref); - auto replacement = i != remappings.end() ? i->second.clone() : ref.clone(); + auto replacement = i != remappings.end() ? i->second : ref; // FIXME: warn about unremapped paths? if (replacement != ref) rewrites.insert_or_assign(store->printStorePath(ref), store->printStorePath(replacement)); @@ -79,7 +79,7 @@ struct CmdMakeContentAddressable : StorePathsCommand, MixJSON ValidPathInfo info(store->makeFixedOutputPath(FileIngestionMethod::Recursive, narHash, path.name(), references, hasSelfReference)); info.references = std::move(references); - if (hasSelfReference) info.references.insert(info.path.clone()); + if (hasSelfReference) info.references.insert(info.path); info.narHash = narHash; info.narSize = sink.s->size(); info.ca = makeFixedOutputCA(FileIngestionMethod::Recursive, info.narHash); diff --git a/src/nix/path-info.cc b/src/nix/path-info.cc index 88d7fffd4..fb7bacc4c 100644 --- a/src/nix/path-info.cc +++ b/src/nix/path-info.cc @@ -90,7 +90,7 @@ struct CmdPathInfo : StorePathsCommand, MixJSON JSONPlaceholder jsonRoot(std::cout); store->pathInfoToJSON(jsonRoot, // FIXME: preserve order? - storePathsToSet(storePaths), + StorePathSet(storePaths.begin(), storePaths.end()), true, showClosureSize, SRI, AllowInvalid); } diff --git a/src/nix/run.cc b/src/nix/run.cc index c9b69aec7..321ee1d11 100644 --- a/src/nix/run.cc +++ b/src/nix/run.cc @@ -111,16 +111,16 @@ struct CmdShell : InstallablesCommand, RunCommon, MixEnvironment std::unordered_set done; std::queue todo; - for (auto & path : outPaths) todo.push(path.clone()); + for (auto & path : outPaths) todo.push(path); setEnviron(); auto unixPath = tokenizeString(getEnv("PATH").value_or(""), ":"); while (!todo.empty()) { - auto path = todo.front().clone(); + auto path = todo.front(); todo.pop(); - if (!done.insert(path.clone()).second) continue; + if (!done.insert(path).second) continue; if (true) unixPath.push_front(store->printStorePath(path) + "/bin"); diff --git a/src/nix/why-depends.cc b/src/nix/why-depends.cc index a4ee2d971..167c974ee 100644 --- a/src/nix/why-depends.cc +++ b/src/nix/why-depends.cc @@ -106,16 +106,16 @@ struct CmdWhyDepends : SourceExprCommand std::map graph; for (auto & path : closure) - graph.emplace(path.clone(), Node { .path = path.clone(), .refs = cloneStorePathSet(store->queryPathInfo(path)->references) }); + graph.emplace(path, Node { .path = path, .refs = store->queryPathInfo(path)->references }); // Transpose the graph. for (auto & node : graph) for (auto & ref : node.second.refs) - graph.find(ref)->second.rrefs.insert(node.first.clone()); + graph.find(ref)->second.rrefs.insert(node.first); /* Run Dijkstra's shortest path algorithm to get the distance of every path in the closure to 'dependency'. */ - graph.emplace(dependencyPath.clone(), Node { .path = dependencyPath.clone(), .dist = 0 }); + graph.emplace(dependencyPath, Node { .path = dependencyPath, .dist = 0 }); std::priority_queue queue; From c9d06558b6cfb30cb6ad7d872ec1046434645b3b Mon Sep 17 00:00:00 2001 From: p01arst0rm Date: Wed, 17 Jun 2020 03:15:47 +0100 Subject: [PATCH 47/62] replaced uncaught_exception with uncaught_exceptions --- src/libstore/remote-store.cc | 2 +- src/libutil/json.cc | 2 +- src/libutil/util.cc | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index fc5ab5865..f5f2ab7fd 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -228,7 +228,7 @@ struct ConnectionHandle ~ConnectionHandle() { - if (!daemonException && std::uncaught_exception()) { + if (!daemonException && std::uncaught_exceptions()) { handle.markBad(); debug("closing daemon connection because of an exception"); } diff --git a/src/libutil/json.cc b/src/libutil/json.cc index 74e37b4c4..01331947e 100644 --- a/src/libutil/json.cc +++ b/src/libutil/json.cc @@ -173,7 +173,7 @@ JSONObject JSONPlaceholder::object() JSONPlaceholder::~JSONPlaceholder() { - assert(!first || std::uncaught_exception()); + assert(!first || std::uncaught_exceptions()); } } diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 667dd2edb..6ca9013a4 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -1199,7 +1199,7 @@ void _interrupted() /* Block user interrupts while an exception is being handled. Throwing an exception while another exception is being handled kills the program! */ - if (!interruptThrown && !std::uncaught_exception()) { + if (!interruptThrown && !std::uncaught_exceptions()) { interruptThrown = true; throw Interrupted("interrupted by the user"); } From e9970a34e8841faaecd39ba18e0913101beca592 Mon Sep 17 00:00:00 2001 From: p01arst0rm Date: Wed, 17 Jun 2020 03:19:15 +0100 Subject: [PATCH 48/62] appended ' __attribute__((weak)); ' to 'extern char * * environ ' --- src/libutil/util.cc | 2 +- src/nix-build/nix-build.cc | 2 +- src/nix/command.cc | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 667dd2edb..85246ced6 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -35,7 +35,7 @@ #endif -extern char * * environ; +extern char * * environ __attribute__((weak)); namespace nix { diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc index a224d635d..f77de56ea 100755 --- a/src/nix-build/nix-build.cc +++ b/src/nix-build/nix-build.cc @@ -21,7 +21,7 @@ using namespace nix; using namespace std::string_literals; -extern char * * environ; +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 diff --git a/src/nix/command.cc b/src/nix/command.cc index d62626c26..3651a9e9c 100644 --- a/src/nix/command.cc +++ b/src/nix/command.cc @@ -4,7 +4,7 @@ #include "nixexpr.hh" #include "profiles.hh" -extern char * * environ; +extern char * * environ __attribute__((weak)); namespace nix { From 9ce994d45eab1f89c2e3d485d7486a10fa219479 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 17 Jun 2020 10:02:33 +0200 Subject: [PATCH 49/62] Remove rustfmt --- shell.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell.nix b/shell.nix index e3b422c7c..17aaa05ed 100644 --- a/shell.nix +++ b/shell.nix @@ -7,7 +7,7 @@ with import ./release-common.nix { inherit pkgs; }; (if useClang then clangStdenv else stdenv).mkDerivation { name = "nix"; - buildInputs = buildDeps ++ propagatedDeps ++ perlDeps ++ [ pkgs.rustfmt ]; + buildInputs = buildDeps ++ propagatedDeps ++ perlDeps; inherit configureFlags; From da8aac6ce8a73a7c9dc6d3cdfa27ab074f0bc976 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Wed, 17 Jun 2020 13:41:25 +0800 Subject: [PATCH 50/62] Mention number of derivations to be build/fetched in output Also correct grammar for the case of a single derivation. --- doc/manual/advanced-topics/diff-hook.xml | 6 +++--- .../advanced-topics/post-build-hook.xml | 2 +- doc/manual/command-ref/nix-env.xml | 2 +- src/libmain/shared.cc | 20 +++++++++++++++---- 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/doc/manual/advanced-topics/diff-hook.xml b/doc/manual/advanced-topics/diff-hook.xml index fb4bf819f..f01ab71b3 100644 --- a/doc/manual/advanced-topics/diff-hook.xml +++ b/doc/manual/advanced-topics/diff-hook.xml @@ -70,7 +70,7 @@ path just built. $ nix-build ./deterministic.nix -A stable -these derivations will be built: +this derivation will be built: /nix/store/z98fasz2jqy9gs0xbvdj939p27jwda38-stable.drv building '/nix/store/z98fasz2jqy9gs0xbvdj939p27jwda38-stable.drv'... /nix/store/yyxlzw3vqaas7wfp04g0b1xg51f2czgq-stable @@ -85,7 +85,7 @@ checking outputs of '/nix/store/z98fasz2jqy9gs0xbvdj939p27jwda38-stable.drv'... $ nix-build ./deterministic.nix -A unstable -these derivations will be built: +this derivation will be built: /nix/store/cgl13lbj1w368r5z8gywipl1ifli7dhk-unstable.drv building '/nix/store/cgl13lbj1w368r5z8gywipl1ifli7dhk-unstable.drv'... /nix/store/krpqk0l9ib0ibi1d2w52z293zw455cap-unstable @@ -193,7 +193,7 @@ repeat = 1 An example output of this configuration: $ nix-build ./test.nix -A unstable -these derivations will be built: +this derivation will be built: /nix/store/ch6llwpr2h8c3jmnf3f2ghkhx59aa97f-unstable.drv building '/nix/store/ch6llwpr2h8c3jmnf3f2ghkhx59aa97f-unstable.drv' (round 1/2)... building '/nix/store/ch6llwpr2h8c3jmnf3f2ghkhx59aa97f-unstable.drv' (round 2/2)... diff --git a/doc/manual/advanced-topics/post-build-hook.xml b/doc/manual/advanced-topics/post-build-hook.xml index acfe9e3cc..6cc286ee1 100644 --- a/doc/manual/advanced-topics/post-build-hook.xml +++ b/doc/manual/advanced-topics/post-build-hook.xml @@ -122,7 +122,7 @@ post-build-hook = /etc/nix/upload-to-cache.sh $ nix-build -E '(import <nixpkgs> {}).writeText "example" (builtins.toString builtins.currentTime)' -these derivations will be built: +this derivation will be built: /nix/store/s4pnfbkalzy5qz57qs6yybna8wylkig6-example.drv building '/nix/store/s4pnfbkalzy5qz57qs6yybna8wylkig6-example.drv'... running post-build-hook '/home/grahamc/projects/github.com/NixOS/nix/post-hook.sh'... diff --git a/doc/manual/command-ref/nix-env.xml b/doc/manual/command-ref/nix-env.xml index 2b95b6819..55f25d959 100644 --- a/doc/manual/command-ref/nix-env.xml +++ b/doc/manual/command-ref/nix-env.xml @@ -516,7 +516,7 @@ source: $ nix-env -f '<nixpkgs>' -iA hello --dry-run (dry run; not doing anything) installing ‘hello-2.10’ -these paths will be fetched (0.04 MiB download, 0.19 MiB unpacked): +this path will be fetched (0.04 MiB download, 0.19 MiB unpacked): /nix/store/wkhdf9jinag5750mqlax6z2zbwhqb76n-hello-2.10 ... diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc index dc6d5e413..1cb422967 100644 --- a/src/libmain/shared.cc +++ b/src/libmain/shared.cc @@ -48,7 +48,10 @@ void printMissing(ref store, const StorePathSet & willBuild, unsigned long long downloadSize, unsigned long long narSize, Verbosity lvl) { if (!willBuild.empty()) { - printMsg(lvl, "these derivations will be built:"); + if (willBuild.size() == 1) + printMsg(lvl, fmt("this derivation will be built:")); + else + printMsg(lvl, fmt("these %d derivations will be built:", willBuild.size())); auto sorted = store->topoSortPaths(willBuild); reverse(sorted.begin(), sorted.end()); for (auto & i : sorted) @@ -56,9 +59,18 @@ void printMissing(ref store, const StorePathSet & willBuild, } if (!willSubstitute.empty()) { - printMsg(lvl, fmt("these paths will be fetched (%.2f MiB download, %.2f MiB unpacked):", - downloadSize / (1024.0 * 1024.0), - narSize / (1024.0 * 1024.0))); + const float downloadSizeMiB = downloadSize / (1024.f * 1024.f); + const float narSizeMiB = narSize / (1024.f * 1024.f); + if (willSubstitute.size() == 1) { + printMsg(lvl, fmt("this path will be fetched (%.2f MiB download, %.2f MiB unpacked):", + downloadSizeMiB, + narSizeMiB)); + } else { + printMsg(lvl, fmt("these %d paths will be fetched (%.2f MiB download, %.2f MiB unpacked):", + willSubstitute.size(), + downloadSizeMiB, + narSizeMiB)); + } for (auto & i : willSubstitute) printMsg(lvl, fmt(" %s", store->printStorePath(i))); } From 56d75bf4fcb06da1a577c6e381f4afef57f30243 Mon Sep 17 00:00:00 2001 From: regnat Date: Wed, 17 Jun 2020 15:39:10 +0200 Subject: [PATCH 51/62] Reserve the `__contentAddressed` derivation parameter Not implementing anything here, just throwing an error if a derivation sets `__contentAddressed = true` without `--experimental-features content-addressed-paths` (and also with it as there's nothing implemented yet) --- src/libstore/build.cc | 11 +++++++++++ src/libstore/parsed-derivations.cc | 5 +++++ src/libstore/parsed-derivations.hh | 2 ++ 3 files changed, 18 insertions(+) diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 53a0958aa..9b72175c7 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -809,6 +809,9 @@ private: /* Whether this is a fixed-output derivation. */ bool fixedOutput; + /* Whether this is a content adressed derivation */ + bool contentAddressed = false; + /* Whether to run the build in a private network namespace. */ bool privateNetwork = false; @@ -1195,6 +1198,14 @@ void DerivationGoal::haveDerivation() parsedDrv = std::make_unique(drvPath, *drv); + contentAddressed = parsedDrv->contentAddressed(); + + if (this->contentAddressed) { + settings.requireExperimentalFeature("content-addressed-paths"); + throw Error("content-addressed-paths isn't implemented yet"); + } + + /* We are first going to try to create the invalid output paths through substitutes. If that doesn't work, we'll build them. */ diff --git a/src/libstore/parsed-derivations.cc b/src/libstore/parsed-derivations.cc index 24f848e46..c7797b730 100644 --- a/src/libstore/parsed-derivations.cc +++ b/src/libstore/parsed-derivations.cc @@ -117,4 +117,9 @@ bool ParsedDerivation::substitutesAllowed() const return getBoolAttr("allowSubstitutes", true); } +bool ParsedDerivation::contentAddressed() const +{ + return getBoolAttr("__contentAddressed", false); +} + } diff --git a/src/libstore/parsed-derivations.hh b/src/libstore/parsed-derivations.hh index 7621342d7..d24d1eb4f 100644 --- a/src/libstore/parsed-derivations.hh +++ b/src/libstore/parsed-derivations.hh @@ -34,6 +34,8 @@ public: bool willBuildLocally() const; bool substitutesAllowed() const; + + bool contentAddressed() const; }; } From 6403508f5a2fcf073b2a0d4e5fcf5f5ebb890384 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Wed, 17 Jun 2020 15:13:00 +0000 Subject: [PATCH 52/62] Use `ansicolor.hh` in `nix repl` rather than duplicates --- src/libutil/ansicolor.hh | 2 ++ src/nix/repl.cc | 33 +++++++++++++-------------------- 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/src/libutil/ansicolor.hh b/src/libutil/ansicolor.hh index 8ae07b092..a38c2d798 100644 --- a/src/libutil/ansicolor.hh +++ b/src/libutil/ansicolor.hh @@ -11,5 +11,7 @@ namespace nix { #define ANSI_GREEN "\e[32;1m" #define ANSI_YELLOW "\e[33;1m" #define ANSI_BLUE "\e[34;1m" +#define ANSI_MAGENTA "\e[35m;1m" +#define ANSI_CYAN "\e[36m;1m" } diff --git a/src/nix/repl.cc b/src/nix/repl.cc index 4bcaaeebf..617d49614 100644 --- a/src/nix/repl.cc +++ b/src/nix/repl.cc @@ -19,6 +19,7 @@ extern "C" { } #endif +#include "ansicolor.hh" #include "shared.hh" #include "eval.hh" #include "eval-inline.hh" @@ -37,14 +38,6 @@ extern "C" { namespace nix { -#define ESC_RED "\033[31m" -#define ESC_GRE "\033[32m" -#define ESC_YEL "\033[33m" -#define ESC_BLU "\033[34;1m" -#define ESC_MAG "\033[35m" -#define ESC_CYA "\033[36m" -#define ESC_END "\033[0m" - struct NixRepl : gc { string curDir; @@ -645,25 +638,25 @@ std::ostream & NixRepl::printValue(std::ostream & str, Value & v, unsigned int m switch (v.type) { case tInt: - str << ESC_CYA << v.integer << ESC_END; + str << ANSI_CYAN << v.integer << ANSI_NORMAL; break; case tBool: - str << ESC_CYA << (v.boolean ? "true" : "false") << ESC_END; + str << ANSI_CYAN << (v.boolean ? "true" : "false") << ANSI_NORMAL; break; case tString: - str << ESC_YEL; + str << ANSI_YELLOW; printStringValue(str, v.string.s); - str << ESC_END; + str << ANSI_NORMAL; break; case tPath: - str << ESC_GRE << v.path << ESC_END; // !!! escaping? + str << ANSI_GREEN << v.path << ANSI_NORMAL; // !!! escaping? break; case tNull: - str << ESC_CYA "null" ESC_END; + str << ANSI_CYAN "null" ANSI_NORMAL; break; case tAttrs: { @@ -699,7 +692,7 @@ std::ostream & NixRepl::printValue(std::ostream & str, Value & v, unsigned int m try { printValue(str, *i.second, maxDepth - 1, seen); } catch (AssertionError & e) { - str << ESC_RED "«error: " << e.msg() << "»" ESC_END; + str << ANSI_RED "«error: " << e.msg() << "»" ANSI_NORMAL; } str << "; "; } @@ -725,7 +718,7 @@ std::ostream & NixRepl::printValue(std::ostream & str, Value & v, unsigned int m try { printValue(str, *v.listElems()[n], maxDepth - 1, seen); } catch (AssertionError & e) { - str << ESC_RED "«error: " << e.msg() << "»" ESC_END; + str << ANSI_RED "«error: " << e.msg() << "»" ANSI_NORMAL; } str << " "; } @@ -737,16 +730,16 @@ std::ostream & NixRepl::printValue(std::ostream & str, Value & v, unsigned int m case tLambda: { std::ostringstream s; s << v.lambda.fun->pos; - str << ESC_BLU "«lambda @ " << filterANSIEscapes(s.str()) << "»" ESC_END; + str << ANSI_BLUE "«lambda @ " << filterANSIEscapes(s.str()) << "»" ANSI_NORMAL; break; } case tPrimOp: - str << ESC_MAG "«primop»" ESC_END; + str << ANSI_MAGENTA "«primop»" ANSI_NORMAL; break; case tPrimOpApp: - str << ESC_BLU "«primop-app»" ESC_END; + str << ANSI_BLUE "«primop-app»" ANSI_NORMAL; break; case tFloat: @@ -754,7 +747,7 @@ std::ostream & NixRepl::printValue(std::ostream & str, Value & v, unsigned int m break; default: - str << ESC_RED "«unknown»" ESC_END; + str << ANSI_RED "«unknown»" ANSI_NORMAL; break; } From 079c6e87deb100bf21f35150736f9662557e698e Mon Sep 17 00:00:00 2001 From: Carlo Nucera Date: Wed, 17 Jun 2020 11:16:16 -0400 Subject: [PATCH 53/62] Make successful states coherent The successful states used in these two places in the code were slightly different. Should they be the same list? --- src/libstore/filetransfer.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/libstore/filetransfer.cc b/src/libstore/filetransfer.cc index c954ace7f..081960912 100644 --- a/src/libstore/filetransfer.cc +++ b/src/libstore/filetransfer.cc @@ -72,6 +72,8 @@ struct curlFileTransfer : public FileTransfer curl_off_t writtenToSink = 0; + inline static const std::set successfulStatuses; + /* Get the HTTP status code, or 0 for other protocols. */ long getHTTPStatus() { @@ -98,7 +100,7 @@ struct curlFileTransfer : public FileTransfer /* Only write data to the sink if this is a successful response. */ - if (httpStatus == 0 || httpStatus == 200 || httpStatus == 201 || httpStatus == 206) { + if (successfulStatuses.find(httpStatus) != successfulStatuses.end()) { writtenToSink += len; this->request.dataCallback((char *) data, len); } @@ -352,8 +354,7 @@ struct curlFileTransfer : public FileTransfer if (writeException) failEx(writeException); - else if (code == CURLE_OK && - (httpStatus == 200 || httpStatus == 201 || httpStatus == 204 || httpStatus == 206 || httpStatus == 304 || httpStatus == 0 /* other protocol */)) + else if (code == CURLE_OK && successfulStatuses.find(httpStatus) != successfulStatuses.end()) { result.cached = httpStatus == 304; act.progress(result.bodySize, result.bodySize); From 480b54e1c6a200a2d4a39c1fa24fa195db12953f Mon Sep 17 00:00:00 2001 From: regnat Date: Wed, 17 Jun 2020 17:36:33 +0200 Subject: [PATCH 54/62] fixup! Reserve the `__contentAddressed` derivation parameter --- src/libstore/build.cc | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 9b72175c7..e1d812b09 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -809,9 +809,6 @@ private: /* Whether this is a fixed-output derivation. */ bool fixedOutput; - /* Whether this is a content adressed derivation */ - bool contentAddressed = false; - /* Whether to run the build in a private network namespace. */ bool privateNetwork = false; @@ -1198,9 +1195,7 @@ void DerivationGoal::haveDerivation() parsedDrv = std::make_unique(drvPath, *drv); - contentAddressed = parsedDrv->contentAddressed(); - - if (this->contentAddressed) { + if (parsedDrv->contentAddressed()) { settings.requireExperimentalFeature("content-addressed-paths"); throw Error("content-addressed-paths isn't implemented yet"); } From 4930cb48a258b0a69a8669602964e3956592ae5c Mon Sep 17 00:00:00 2001 From: Carlo Nucera Date: Wed, 17 Jun 2020 12:58:59 -0400 Subject: [PATCH 55/62] Include review comments --- src/libstore/filetransfer.cc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/libstore/filetransfer.cc b/src/libstore/filetransfer.cc index 081960912..531b85af8 100644 --- a/src/libstore/filetransfer.cc +++ b/src/libstore/filetransfer.cc @@ -72,8 +72,7 @@ struct curlFileTransfer : public FileTransfer curl_off_t writtenToSink = 0; - inline static const std::set successfulStatuses; - + inline static const std::set successfulStatuses {200, 201, 204, 206, 304, 0 /* other protocol */}; /* Get the HTTP status code, or 0 for other protocols. */ long getHTTPStatus() { @@ -100,7 +99,7 @@ struct curlFileTransfer : public FileTransfer /* Only write data to the sink if this is a successful response. */ - if (successfulStatuses.find(httpStatus) != successfulStatuses.end()) { + if (successfulStatuses.count(httpStatus)) { writtenToSink += len; this->request.dataCallback((char *) data, len); } @@ -354,7 +353,7 @@ struct curlFileTransfer : public FileTransfer if (writeException) failEx(writeException); - else if (code == CURLE_OK && successfulStatuses.find(httpStatus) != successfulStatuses.end()) + else if (code == CURLE_OK && successfulStatuses.count(httpStatus)) { result.cached = httpStatus == 304; act.progress(result.bodySize, result.bodySize); From f767bedfac66bff297499f68b234ac63b02c8f62 Mon Sep 17 00:00:00 2001 From: Matthew Bauer Date: Wed, 17 Jun 2020 13:26:37 -0400 Subject: [PATCH 56/62] Replace struct StorePath with class StorePath also a similar case with struct Goal --- src/libexpr/eval.hh | 2 +- src/libstore/build.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 1485dc7fe..064b1a623 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -18,7 +18,7 @@ namespace nix { class Store; class EvalState; -struct StorePath; +class StorePath; enum RepairFlag : bool; diff --git a/src/libstore/build.cc b/src/libstore/build.cc index e1d812b09..3afebfcf4 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -86,7 +86,7 @@ struct HookInstance; /* A pointer to a goal. */ -class Goal; +struct Goal; class DerivationGoal; typedef std::shared_ptr GoalPtr; typedef std::weak_ptr WeakGoalPtr; From 22d7d36703df637980d0dcbe3ad030114662840e Mon Sep 17 00:00:00 2001 From: Matthew Bauer Date: Wed, 17 Jun 2020 13:27:10 -0400 Subject: [PATCH 57/62] Remove unused narInfoFile in binary-cache-store --- src/libstore/binary-cache-store.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/libstore/binary-cache-store.cc b/src/libstore/binary-cache-store.cc index f8eff508c..9f52ddafa 100644 --- a/src/libstore/binary-cache-store.cc +++ b/src/libstore/binary-cache-store.cc @@ -388,8 +388,6 @@ void BinaryCacheStore::addSignatures(const StorePath & storePath, const StringSe narInfo->sigs.insert(sigs.begin(), sigs.end()); - auto narInfoFile = narInfoFileFor(narInfo->path); - writeNarInfo(narInfo); } From 4fef2ba7e4f344eec32cdf02821d32036fbbc21b Mon Sep 17 00:00:00 2001 From: regnat Date: Thu, 18 Jun 2020 09:25:55 +0200 Subject: [PATCH 58/62] Rename content-addressed-paths into ca-derivations See --- src/libstore/build.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 3afebfcf4..3b0efa1a5 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -1196,8 +1196,8 @@ void DerivationGoal::haveDerivation() parsedDrv = std::make_unique(drvPath, *drv); if (parsedDrv->contentAddressed()) { - settings.requireExperimentalFeature("content-addressed-paths"); - throw Error("content-addressed-paths isn't implemented yet"); + settings.requireExperimentalFeature("ca-derivations"); + throw Error("ca-derivations isn't implemented yet"); } From 9069759767cf1821578be8006cda52ee53ecd427 Mon Sep 17 00:00:00 2001 From: Samir Talwar Date: Thu, 18 Jun 2020 10:29:24 +0200 Subject: [PATCH 59/62] Instruct the user to follow redirects when installing Nix. Nix installation now requires following redirects using `curl -L`. This is currently represented on the [Nix download page][] but not in the manual. This change updates the manual to reflect this. Using `curl` without the `-L` flag results in an empty body, making installation a no-op. [Nix download page]: https://nixos.org/download.html --- doc/manual/installation/env-variables.xml | 2 +- doc/manual/installation/installing-binary.xml | 4 ++-- doc/manual/introduction/quick-start.xml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/manual/installation/env-variables.xml b/doc/manual/installation/env-variables.xml index e2b8fc867..cc52f5b4a 100644 --- a/doc/manual/installation/env-variables.xml +++ b/doc/manual/installation/env-variables.xml @@ -39,7 +39,7 @@ bundle. Set the environment variable and install Nix $ export NIX_SSL_CERT_FILE=/etc/ssl/my-certificate-bundle.crt -$ sh <(curl https://nixos.org/nix/install) +$ sh <(curl -L https://nixos.org/nix/install) In the shell profile and rc files (for example, diff --git a/doc/manual/installation/installing-binary.xml b/doc/manual/installation/installing-binary.xml index 8d548f0ea..d25c46b85 100644 --- a/doc/manual/installation/installing-binary.xml +++ b/doc/manual/installation/installing-binary.xml @@ -12,7 +12,7 @@ - $ sh <(curl https://nixos.org/nix/install) + $ sh <(curl -L https://nixos.org/nix/install) @@ -39,7 +39,7 @@ To explicitly select a single-user installation on your system: - sh <(curl https://nixos.org/nix/install) --no-daemon + sh <(curl -L https://nixos.org/nix/install) --no-daemon diff --git a/doc/manual/introduction/quick-start.xml b/doc/manual/introduction/quick-start.xml index 1ce6c8d50..1992c14ed 100644 --- a/doc/manual/introduction/quick-start.xml +++ b/doc/manual/introduction/quick-start.xml @@ -15,7 +15,7 @@ to subsequent chapters. Install single-user Nix by running the following: -$ bash <(curl https://nixos.org/nix/install) +$ bash <(curl -L https://nixos.org/nix/install) This will install Nix in /nix. The install script From 7083d33efee2b4782c52dc04d90f7c08e96b79d1 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 29 Nov 2018 16:28:43 +0100 Subject: [PATCH 60/62] Make constant primops lazy (cherry picked from commit aa0e2a2e70a3519a9dcb9b1da000a13c01aa6cc1) --- src/libexpr/eval.cc | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 8e71db2b8..66f03fe1a 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -471,14 +471,21 @@ Value * EvalState::addConstant(const string & name, Value & v) Value * EvalState::addPrimOp(const string & name, size_t arity, PrimOpFun primOp) { + auto name2 = string(name, 0, 2) == "__" ? string(name, 2) : name; + Symbol sym = symbols.create(name2); + + /* Hack to make constants lazy: turn them into a application of + the primop to a dummy value. */ if (arity == 0) { + auto vPrimOp = allocValue(); + vPrimOp->type = tPrimOp; + vPrimOp->primOp = new PrimOp(primOp, 1, sym); Value v; - primOp(*this, noPos, nullptr, v); + mkApp(v, *vPrimOp, *vPrimOp); return addConstant(name, v); } + Value * v = allocValue(); - string name2 = string(name, 0, 2) == "__" ? string(name, 2) : name; - Symbol sym = symbols.create(name2); v->type = tPrimOp; v->primOp = new PrimOp(primOp, arity, sym); staticBaseEnv.vars[symbols.create(name)] = baseEnvDispl; From 2a61bbf77fd1b4bd518912b4923265b91a8f9d67 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 18 Jun 2020 13:44:40 +0200 Subject: [PATCH 61/62] Some backports from the flakes branch --- src/libexpr/attr-path.cc | 13 +++++++++++-- src/libexpr/attr-path.hh | 2 ++ src/libexpr/eval.cc | 26 ++++++++++++++++++++------ src/libexpr/eval.hh | 4 +++- src/libexpr/get-drvs.cc | 2 +- src/libexpr/primops.cc | 15 ++++++++------- 6 files changed, 45 insertions(+), 17 deletions(-) diff --git a/src/libexpr/attr-path.cc b/src/libexpr/attr-path.cc index 8980bc09d..2e2a17b14 100644 --- a/src/libexpr/attr-path.cc +++ b/src/libexpr/attr-path.cc @@ -6,11 +6,11 @@ namespace nix { -static Strings parseAttrPath(const string & s) +static Strings parseAttrPath(std::string_view s) { Strings res; string cur; - string::const_iterator i = s.begin(); + auto i = s.begin(); while (i != s.end()) { if (*i == '.') { res.push_back(cur); @@ -32,6 +32,15 @@ static Strings parseAttrPath(const string & s) } +std::vector parseAttrPath(EvalState & state, std::string_view s) +{ + std::vector res; + for (auto & a : parseAttrPath(s)) + res.push_back(state.symbols.create(a)); + return res; +} + + std::pair findAlongAttrPath(EvalState & state, const string & attrPath, Bindings & autoArgs, Value & vIn) { diff --git a/src/libexpr/attr-path.hh b/src/libexpr/attr-path.hh index fce160da7..d9d74ab2d 100644 --- a/src/libexpr/attr-path.hh +++ b/src/libexpr/attr-path.hh @@ -16,4 +16,6 @@ std::pair findAlongAttrPath(EvalState & state, const string & attr /* Heuristic to find the filename and lineno or a nix value. */ Pos findDerivationFilename(EvalState & state, Value & v, std::string what); +std::vector parseAttrPath(EvalState & state, std::string_view s); + } diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 66f03fe1a..b90a64357 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -161,12 +161,12 @@ const Value *getPrimOp(const Value &v) { } -string showType(const Value & v) +string showType(ValueType type) { - switch (v.type) { + switch (type) { case tInt: return "an integer"; - case tBool: return "a boolean"; - case tString: return v.string.context ? "a string with context" : "a string"; + case tBool: return "a Boolean"; + case tString: return "a string"; case tPath: return "a path"; case tNull: return "null"; case tAttrs: return "a set"; @@ -175,14 +175,27 @@ string showType(const Value & v) case tApp: return "a function application"; case tLambda: return "a function"; case tBlackhole: return "a black hole"; + case tPrimOp: return "a built-in function"; + case tPrimOpApp: return "a partially applied built-in function"; + case tExternal: return "an external value"; + case tFloat: return "a float"; + } + abort(); +} + + +string showType(const Value & v) +{ + switch (v.type) { + case tString: return v.string.context ? "a string with context" : "a string"; case tPrimOp: return fmt("the built-in function '%s'", string(v.primOp->name)); case tPrimOpApp: return fmt("the partially applied built-in function '%s'", string(getPrimOp(v)->primOp->name)); case tExternal: return v.external->showType(); - case tFloat: return "a float"; + default: + return showType(v.type); } - abort(); } @@ -323,6 +336,7 @@ EvalState::EvalState(const Strings & _searchPath, ref store) , sOutputHash(symbols.create("outputHash")) , sOutputHashAlgo(symbols.create("outputHashAlgo")) , sOutputHashMode(symbols.create("outputHashMode")) + , sRecurseForDerivations(symbols.create("recurseForDerivations")) , repair(NoRepair) , store(store) , baseEnv(allocEnv(128)) diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 064b1a623..863365259 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -74,7 +74,8 @@ public: sSystem, sOverrides, sOutputs, sOutputName, sIgnoreNulls, sFile, sLine, sColumn, sFunctor, sToString, sRight, sWrong, sStructuredAttrs, sBuilder, sArgs, - sOutputHash, sOutputHashAlgo, sOutputHashMode; + sOutputHash, sOutputHashAlgo, sOutputHashMode, + sRecurseForDerivations; Symbol sDerivationNix; /* If set, force copying files to the Nix store even if they @@ -324,6 +325,7 @@ private: /* Return a string representing the type of the value `v'. */ +string showType(ValueType type); string showType(const Value & v); /* Decode a context string ‘!!’ into a pair Only if it has a `recurseForDerivations = true' attribute. */ if (i->value->type == tAttrs) { - Bindings::iterator j = i->value->attrs->find(state.symbols.create("recurseForDerivations")); + Bindings::iterator j = i->value->attrs->find(state.sRecurseForDerivations); if (j != i->value->attrs->end() && state.forceBool(*j->value, *j->pos)) getDerivations(state, *i->value, pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures); } diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 907f15246..bb1926282 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -50,20 +50,20 @@ void EvalState::realiseContext(const PathSet & context) std::vector drvs; for (auto & i : context) { - std::pair decoded = decodeContext(i); - auto ctx = store->parseStorePath(decoded.first); + auto [ctxS, outputName] = decodeContext(i); + auto ctx = store->parseStorePath(ctxS); if (!store->isValidPath(ctx)) throw InvalidPathError(store->printStorePath(ctx)); - if (!decoded.second.empty() && ctx.isDerivation()) { - drvs.push_back(StorePathWithOutputs{ctx, {decoded.second}}); + if (!outputName.empty() && ctx.isDerivation()) { + drvs.push_back(StorePathWithOutputs{ctx, {outputName}}); /* Add the output of this derivation to the allowed paths. */ if (allowedPaths) { - auto drv = store->derivationFromPath(store->parseStorePath(decoded.first)); - DerivationOutputs::iterator i = drv.outputs.find(decoded.second); + auto drv = store->derivationFromPath(ctx); + DerivationOutputs::iterator i = drv.outputs.find(outputName); if (i == drv.outputs.end()) - throw Error("derivation '%s' does not have an output named '%s'", decoded.first, decoded.second); + throw Error("derivation '%s' does not have an output named '%s'", ctxS, outputName); allowedPaths->insert(store->printStorePath(i->second.path)); } } @@ -79,6 +79,7 @@ void EvalState::realiseContext(const PathSet & context) StorePathSet willBuild, willSubstitute, unknown; unsigned long long downloadSize, narSize; store->queryMissing(drvs, willBuild, willSubstitute, unknown, downloadSize, narSize); + store->buildPaths(drvs); } From 5771c8bbf29325c24e55c75743194612228f4e07 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 17 Jun 2020 16:54:32 +0200 Subject: [PATCH 62/62] Don't provide 'getFlake' if the 'flakes' feature is not enabled (cherry picked from commit 0a1d3c1dd311f94e9d1f56e1aa7fe1ab34314ec1) --- src/libexpr/primops.cc | 8 +++++--- src/libexpr/primops.hh | 17 +++++++++++++++-- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index bb1926282..2f1a41a64 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -2202,10 +2202,11 @@ static void prim_splitVersion(EvalState & state, const Pos & pos, Value * * args RegisterPrimOp::PrimOps * RegisterPrimOp::primOps; -RegisterPrimOp::RegisterPrimOp(std::string name, size_t arity, PrimOpFun fun) +RegisterPrimOp::RegisterPrimOp(std::string name, size_t arity, PrimOpFun fun, + std::optional requiredFeature) { if (!primOps) primOps = new PrimOps; - primOps->emplace_back(name, arity, fun); + primOps->push_back({name, arity, fun, requiredFeature}); } @@ -2397,7 +2398,8 @@ void EvalState::createBaseEnv() if (RegisterPrimOp::primOps) for (auto & primOp : *RegisterPrimOp::primOps) - addPrimOp(std::get<0>(primOp), std::get<1>(primOp), std::get<2>(primOp)); + if (!primOp.requiredFeature || settings.isExperimentalFeatureEnabled(*primOp.requiredFeature)) + addPrimOp(primOp.name, primOp.arity, primOp.primOp); /* Now that we've added all primops, sort the `builtins' set, because attribute lookups expect it to be sorted. */ diff --git a/src/libexpr/primops.hh b/src/libexpr/primops.hh index 05d0792ef..75c460ecf 100644 --- a/src/libexpr/primops.hh +++ b/src/libexpr/primops.hh @@ -7,12 +7,25 @@ namespace nix { struct RegisterPrimOp { - typedef std::vector> PrimOps; + struct Info + { + std::string name; + size_t arity; + PrimOpFun primOp; + std::optional requiredFeature; + }; + + typedef std::vector PrimOps; static PrimOps * primOps; + /* You can register a constant by passing an arity of 0. fun will get called during EvalState initialization, so there may be primops not yet added and builtins is not yet sorted. */ - RegisterPrimOp(std::string name, size_t arity, PrimOpFun fun); + RegisterPrimOp( + std::string name, + size_t arity, + PrimOpFun fun, + std::optional requiredFeature = {}); }; /* These primops are disabled without enableNativeCode, but plugins