From e433d4af4cf78c88dc0cb3e8139e835470b72fd3 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Sun, 22 Mar 2020 23:43:07 -0400 Subject: Extend Rust FFI Do idiomatic C++ copy and move constructors for a few things, so wrapping structs' defaults can work. --- nix-rust/src/c.rs | 7 +++++++ src/libstore/derivations.hh | 3 +++ src/libstore/nar-info.cc | 2 +- src/libstore/path.hh | 14 ++++++++++++++ src/libstore/store-api.cc | 15 --------------- src/libstore/store-api.hh | 5 +++-- src/libutil/hash.hh | 6 ++++++ src/libutil/rust-ffi.hh | 32 +++++++++++++++++++++++++++++--- 8 files changed, 63 insertions(+), 21 deletions(-) diff --git a/nix-rust/src/c.rs b/nix-rust/src/c.rs index c1358545f..dc2f8ddf5 100644 --- a/nix-rust/src/c.rs +++ b/nix-rust/src/c.rs @@ -64,6 +64,13 @@ pub extern "C" fn ffi_StorePath_clone(self_: &StorePath) -> StorePath { self_.clone() } +#[no_mangle] +pub extern "C" fn ffi_StorePath_clone_to(self_: &StorePath, other: *mut StorePath) { + unsafe { + core::ptr::write(other, self_.clone()); + } +} + #[no_mangle] pub extern "C" fn ffi_StorePath_name(self_: &StorePath) -> &str { self_.name.name() diff --git a/src/libstore/derivations.hh b/src/libstore/derivations.hh index 7222d25e5..f010318ce 100644 --- a/src/libstore/derivations.hh +++ b/src/libstore/derivations.hh @@ -22,6 +22,9 @@ struct DerivationOutput , hashAlgo(std::move(hashAlgo)) , hash(std::move(hash)) { } + DerivationOutput(const DerivationOutput &) = default; + DerivationOutput(DerivationOutput &&) = default; + DerivationOutput & operator = (const DerivationOutput &) = default; void parseHashInfo(bool & recursive, Hash & hash) const; }; diff --git a/src/libstore/nar-info.cc b/src/libstore/nar-info.cc index 1375094b5..87b1b656b 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::dummy) // FIXME: hack { auto corrupt = [&]() { throw Error(format("NAR info file '%1%' is corrupt") % whence); diff --git a/src/libstore/path.hh b/src/libstore/path.hh index c90bb1fff..186976855 100644 --- a/src/libstore/path.hh +++ b/src/libstore/path.hh @@ -13,6 +13,7 @@ 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); + void ffi_StorePath_clone_to(const StorePath & _other, StorePath & _this); unsigned char * ffi_StorePath_hash_data(const StorePath & p); } @@ -43,6 +44,19 @@ struct StorePath : rust::Value<3 * sizeof(void *) + 24, ffi_StorePath_drop> return !(*this == other); } + StorePath(StorePath && that) = default; + + StorePath(const StorePath & that) + { + ffi_StorePath_clone_to(that, *this); + } + + void operator = (const StorePath & that) + { + (rust::Value<3 * sizeof(void *) + 24, ffi_StorePath_drop>::operator = (that)); + ffi_StorePath_clone_to(that, *this); + } + StorePath clone() const; /* Check whether a file name ends with the extension for diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index b9e894a9a..261afed49 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -687,21 +687,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; diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh index 0fa59be6a..0237d0b04 100644 --- a/src/libstore/store-api.hh +++ b/src/libstore/store-api.hh @@ -189,8 +189,9 @@ struct ValidPathInfo Strings shortRefs() const; - ValidPathInfo(StorePath && path) : path(std::move(path)) { } - explicit ValidPathInfo(const ValidPathInfo & other); + ValidPathInfo(StorePath && path) : path(std::move(path)) { }; + ValidPathInfo(const StorePath & path) : path(path) { }; + ValidPathInfo(const ValidPathInfo & other) = default; virtual ~ValidPathInfo() { } }; diff --git a/src/libutil/hash.hh b/src/libutil/hash.hh index ea9fca3e7..294555a09 100644 --- a/src/libutil/hash.hh +++ b/src/libutil/hash.hh @@ -44,6 +44,12 @@ struct Hash string. */ Hash(const std::string & s, HashType type = htUnknown); + Hash(const Hash &) = default; + + Hash(Hash &&) = default; + + Hash & operator = (const Hash &) = default; + void init(); /* Check whether a hash is set. */ diff --git a/src/libutil/rust-ffi.hh b/src/libutil/rust-ffi.hh index 228e2eead..584dcf110 100644 --- a/src/libutil/rust-ffi.hh +++ b/src/libutil/rust-ffi.hh @@ -30,7 +30,10 @@ protected: // Must not be called directly. Value() - { } + { + // Precaution, in case this is used improperly + evacuate(); + } Value(Value && other) : raw(other.raw) @@ -38,6 +41,19 @@ protected: other.evacuate(); } + // Not all Rust types are Clone / Copy, but our base Value class needs to + // have a copy constructor so that ones which do implement Copy/Clone + // can be copied/cloned. + Value(const Value & other) + : raw(other.raw) + { + } + void operator =(const Value & other) + { + if (!isEvacuated()) + drop(this); + } + void operator =(Value && other) { if (!isEvacuated()) @@ -76,6 +92,16 @@ struct Vec : Value<3 * sizeof(void *), drop> { return ((const T * *) &this->raw)[0]; } + +protected: + + // Must not be called directly. + Vec(); + + Vec(Vec && other) = default; + + // Delete until we know how to do this properly. + Vec(const Vec & other) = delete; }; /* A Rust slice. */ @@ -144,7 +170,7 @@ struct Result std::exception_ptr * exc; }; - Result() : tag(Uninit) { }; // FIXME: remove + Result() = delete; Result(const Result &) = delete; @@ -171,7 +197,7 @@ struct Result } /* Rethrow the wrapped exception or return the wrapped value. */ - T unwrap() + T unwrap() && { if (tag == Ok) { tag = Uninit; -- cgit v1.2.3 From 832bd534dc0ab36fd8267f62b67ab1db1498d2b4 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Sun, 22 Mar 2020 23:43:07 -0400 Subject: Store parsed hashes in `DerivationOutput` It's best to detect invalid data as soon as possible, with data types that make storing it impossible. --- src/libexpr/primops.cc | 10 ++--- src/libstore/build.cc | 19 ++++----- src/libstore/derivations.cc | 99 ++++++++++++++++++++++++++++++--------------- src/libstore/derivations.hh | 21 +++++++--- src/libstore/local-store.cc | 10 +++-- src/libstore/store-api.cc | 23 ++++++++--- src/libstore/store-api.hh | 3 ++ src/nix/show-derivation.cc | 6 +-- 8 files changed, 128 insertions(+), 63 deletions(-) diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 7d45733f4..df0ef4e4e 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -724,9 +724,9 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * * auto outPath = state.store->makeFixedOutputPath(outputHashRecursive, h, drvName); if (!jsonObject) drv.env["out"] = state.store->printStorePath(outPath); - drv.outputs.insert_or_assign("out", DerivationOutput(std::move(outPath), - (static_cast(outputHashRecursive) ? "r:" : "") + printHashType(h.type), - h.to_string(Base16, false))); + drv.outputs.insert_or_assign("out", DerivationOutput( + std::move(outPath), + FileSystemHash(outputHashRecursive, std::move(h)))); } else { @@ -739,7 +739,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.clone(), std::optional())); } Hash h = hashDerivationModulo(*state.store, Derivation(drv), true); @@ -748,7 +748,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), std::optional())); } } diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 224633106..c2605cb39 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -3647,10 +3647,7 @@ void DerivationGoal::registerOutputs() if (fixedOutput) { - FileIngestionMethod recursive; Hash h; - i.second.parseHashInfo(recursive, h); - - if (!static_cast(recursive)) { + if (i.second.hash->method == FileIngestionMethod::Flat) { /* The output path should be a regular file without execute permission. */ if (!S_ISREG(st.st_mode) || (st.st_mode & S_IXUSR) != 0) throw BuildError( @@ -3659,18 +3656,22 @@ void DerivationGoal::registerOutputs() /* Check the hash. In hash mode, move the path produced by the derivation to its content-addressed location. */ - Hash h2 = static_cast(recursive) ? hashPath(h.type, actualPath).first : hashFile(h.type, actualPath); + Hash h2 = i.second.hash->method == FileIngestionMethod::Recursive + ? hashPath(i.second.hash->hash.type, actualPath).first + : hashFile(i.second.hash->hash.type, actualPath); - auto dest = worker.store.makeFixedOutputPath(recursive, h2, i.second.path.name()); + auto dest = worker.store.makeFixedOutputPath(i.second.hash->method, h2, i.second.path.name()); - if (h != h2) { + if (i.second.hash->hash != h2) { /* Throw an error after registering the path as valid. */ 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), + i.second.hash->hash.to_string(SRI), + h2.to_string(SRI))); Path actualDest = worker.store.Store::toRealPath(dest); @@ -3690,7 +3691,7 @@ void DerivationGoal::registerOutputs() else assert(worker.store.parseStorePath(path) == dest); - ca = makeFixedOutputCA(recursive, h2); + ca = makeFixedOutputCA(i.second.hash->method, h2); } /* Get rid of all weird permissions. This also checks that diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc index 5934c1912..3f5efe8a6 100644 --- a/src/libstore/derivations.cc +++ b/src/libstore/derivations.cc @@ -8,22 +8,8 @@ namespace nix { - -void DerivationOutput::parseHashInfo(FileIngestionMethod & recursive, Hash & hash) const -{ - recursive = FileIngestionMethod::Flat; - string algo = hashAlgo; - - if (string(algo, 0, 2) == "r:") { - recursive = FileIngestionMethod::Recursive; - algo = string(algo, 2); - } - - HashType hashType = parseHashType(algo); - if (hashType == htUnknown) - throw Error("unknown hash algorithm '%s'", algo); - - hash = Hash(this->hash, hashType); +std::string FileSystemHash::printMethodAlgo() const { + return makeFileIngestionPrefix(method) + printHashType(hash.type); } @@ -35,7 +21,7 @@ BasicDerivation::BasicDerivation(const BasicDerivation & other) { 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))); + DerivationOutput(i.second.path.clone(), std::optional(i.second.hash))); for (auto & i : other.inputSrcs) inputSrcs.insert(i.clone()); } @@ -142,6 +128,33 @@ static StringSet parseStrings(std::istream & str, bool arePaths) } +static DerivationOutput parseDerivationOutput(const Store & store, istringstream_nocopy & str) +{ + expect(str, ","); auto path = store.parseStorePath(parsePath(str)); + expect(str, ","); auto hashAlgo = parseString(str); + expect(str, ","); const auto hash = parseString(str); + expect(str, ")"); + + auto method = FileIngestionMethod::Flat; + std::optional fsh; + if (hashAlgo != "") { + if (string(hashAlgo, 0, 2) == "r:") { + method = FileIngestionMethod::Recursive; + hashAlgo = string(hashAlgo, 2); + } + const HashType hashType = parseHashType(hashAlgo); + if (hashType == htUnknown) + throw Error("unknown hash hashAlgorithm '%s'", hashAlgo); + fsh = FileSystemHash { + std::move(method), + Hash(hash, hashType), + }; + } + + return DerivationOutput(std::move(path), std::move(fsh)); +} + + static Derivation parseDerivation(const Store & store, const string & s) { Derivation drv; @@ -151,11 +164,7 @@ static Derivation parseDerivation(const Store & store, const string & s) /* Parse the list of outputs. */ while (!endOfList(str)) { expect(str, "("); std::string id = parseString(str); - expect(str, ","); auto path = store.parseStorePath(parsePath(str)); - 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, parseDerivationOutput(store, str)); } /* Parse the list of input derivations. */ @@ -275,8 +284,9 @@ string Derivation::unparse(const Store & store, bool maskOutputs, if (first) first = false; else s += ','; s += '('; printUnquotedString(s, i.first); s += ','; printUnquotedString(s, maskOutputs ? "" : store.printStorePath(i.second.path)); - s += ','; printUnquotedString(s, i.second.hashAlgo); - s += ','; printUnquotedString(s, i.second.hash); + s += ','; printUnquotedString(s, i.second.hash ? i.second.hash->printMethodAlgo() : ""); + s += ','; printUnquotedString(s, + i.second.hash ? i.second.hash->hash.to_string(Base16, false) : ""); s += ')'; } @@ -332,7 +342,7 @@ bool BasicDerivation::isFixedOutput() const { return outputs.size() == 1 && outputs.begin()->first == "out" && - outputs.begin()->second.hash != ""; + outputs.begin()->second.hash; } @@ -365,8 +375,8 @@ Hash hashDerivationModulo(Store & store, const Derivation & drv, bool maskOutput if (drv.isFixedOutput()) { DerivationOutputs::const_iterator i = drv.outputs.begin(); return hashString(htSHA256, "fixed:out:" - + i->second.hashAlgo + ":" - + i->second.hash + ":" + + i->second.hash->printMethodAlgo() + ":" + + i->second.hash->hash.to_string(Base16, false) + ":" + store.printStorePath(i->second.path)); } @@ -409,6 +419,30 @@ StorePathSet BasicDerivation::outputPaths() const return paths; } +static DerivationOutput readDerivationOutput(Source & in, const Store & store) +{ + auto path = store.parseStorePath(readString(in)); + auto hashAlgo = readString(in); + const auto hash = readString(in); + + auto method = FileIngestionMethod::Flat; + std::optional fsh; + if (hashAlgo != "") { + if (string(hashAlgo, 0, 2) == "r:") { + method = FileIngestionMethod::Recursive; + hashAlgo = string(hashAlgo, 2); + } + HashType hashType = parseHashType(hashAlgo); + if (hashType == htUnknown) + throw Error("unknown hash hashAlgorithm '%s'", hashAlgo); + fsh = FileSystemHash { + std::move(method), + Hash(hash, hashType), + }; + } + + return DerivationOutput(std::move(path), std::move(fsh)); +} Source & readDerivation(Source & in, const Store & store, BasicDerivation & drv) { @@ -416,10 +450,8 @@ Source & readDerivation(Source & in, const Store & store, BasicDerivation & drv) auto nr = readNum(in); for (size_t n = 0; n < nr; n++) { auto name = readString(in); - 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))); + auto output = readDerivationOutput(in, store); + drv.outputs.emplace(name, output); } drv.inputSrcs = readStorePaths(store, in); @@ -441,7 +473,10 @@ void writeDerivation(Sink & out, const Store & store, const BasicDerivation & dr { out << drv.outputs.size(); for (auto & i : drv.outputs) - out << i.first << store.printStorePath(i.second.path) << i.second.hashAlgo << i.second.hash; + out << i.first + << store.printStorePath(i.second.path) + << i.second.hash->printMethodAlgo() + << i.second.hash->hash.to_string(Base16, false); writeStorePaths(store, out, drv.inputSrcs); out << drv.platform << drv.builder << drv.args; out << drv.env.size(); diff --git a/src/libstore/derivations.hh b/src/libstore/derivations.hh index ea517a78c..320adc7c9 100644 --- a/src/libstore/derivations.hh +++ b/src/libstore/derivations.hh @@ -12,20 +12,31 @@ namespace nix { /* Abstract syntax of derivations. */ +/// Pair of a hash, and how the file system was ingested +struct FileSystemHash { + FileIngestionMethod method; + Hash hash; + FileSystemHash(FileIngestionMethod method, Hash hash) + : method(std::move(method)) + , hash(std::move(hash)) + { } + FileSystemHash(const FileSystemHash &) = default; + FileSystemHash(FileSystemHash &&) = default; + FileSystemHash & operator = (const FileSystemHash &) = default; + std::string printMethodAlgo() const; +}; + 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) + std::optional hash; /* hash used for expected hash computation */ + DerivationOutput(StorePath && path, std::optional && hash) : path(std::move(path)) - , hashAlgo(std::move(hashAlgo)) , hash(std::move(hash)) { } DerivationOutput(const DerivationOutput &) = default; DerivationOutput(DerivationOutput &&) = default; DerivationOutput & operator = (const DerivationOutput &) = default; - void parseHashInfo(FileIngestionMethod & recursive, Hash & hash) const; }; typedef std::map DerivationOutputs; diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 746f81beb..82a9eb43c 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -557,10 +557,12 @@ void LocalStore::checkDerivationOutputs(const StorePath & drvPath, const Derivat if (out == drv.outputs.end()) throw Error("derivation '%s' does not have an output named 'out'", printStorePath(drvPath)); - FileIngestionMethod recursive; Hash h; - out->second.parseHashInfo(recursive, h); - - check(makeFixedOutputPath(recursive, h, drvName), out->second.path, "out"); + check( + makeFixedOutputPath( + out->second.hash->method, + out->second.hash->hash, + drvName), + out->second.path, "out"); } else { diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index 359a9a768..d4772e04e 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -171,18 +171,18 @@ static std::string makeType( StorePath Store::makeFixedOutputPath( - FileIngestionMethod recursive, + FileIngestionMethod method, const Hash & hash, std::string_view name, const StorePathSet & references, bool hasSelfReference) const { - if (hash.type == htSHA256 && recursive == FileIngestionMethod::Recursive) { + if (hash.type == htSHA256 && method == FileIngestionMethod::Recursive) { return makeStorePath(makeType(*this, "source", references, hasSelfReference), hash, name); } else { assert(references.empty()); return makeStorePath("output:out", hashString(htSHA256, - "fixed:out:" + (static_cast(recursive) ? (string) "r:" : "") + + "fixed:out:" + makeFileIngestionPrefix(method) + hash.to_string(Base16) + ":"), name); } } @@ -811,9 +811,22 @@ Strings ValidPathInfo::shortRefs() const } -std::string makeFixedOutputCA(FileIngestionMethod recursive, const Hash & hash) +std::string makeFileIngestionPrefix(const FileIngestionMethod m) { + switch (m) { + case FileIngestionMethod::Flat: + return ""; + case FileIngestionMethod::Recursive: + return "r:"; + default: + throw Error("impossible, caught both cases"); + } +} + +std::string makeFixedOutputCA(FileIngestionMethod method, const Hash & hash) { - return "fixed:" + (static_cast(recursive) ? (std::string) "r:" : "") + hash.to_string(); + return "fixed:" + + makeFileIngestionPrefix(method) + + hash.to_string(); } diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh index a4fdad8c4..ef15e60ec 100644 --- a/src/libstore/store-api.hh +++ b/src/libstore/store-api.hh @@ -847,6 +847,9 @@ std::optional decodeValidPathInfo( std::istream & str, bool hashGiven = false); +/* Compute the prefix to the hash algorithm which indicates how the files were + ingested. */ +std::string makeFileIngestionPrefix(const FileIngestionMethod m); /* Compute the content-addressability assertion (ValidPathInfo::ca) for paths created by makeFixedOutputPath() / addToStore(). */ diff --git a/src/nix/show-derivation.cc b/src/nix/show-derivation.cc index 0ede7b468..b2ec71dbb 100644 --- a/src/nix/show-derivation.cc +++ b/src/nix/show-derivation.cc @@ -69,9 +69,9 @@ struct CmdShowDerivation : InstallablesCommand for (auto & output : drv.outputs) { auto outputObj(outputsObj.object(output.first)); outputObj.attr("path", store->printStorePath(output.second.path)); - if (output.second.hash != "") { - outputObj.attr("hashAlgo", output.second.hashAlgo); - outputObj.attr("hash", output.second.hash); + if (output.second.hash) { + outputObj.attr("hashAlgo", output.second.hash->printMethodAlgo()); + outputObj.attr("hash", output.second.hash->hash.to_string(Base16, false)); } } } -- cgit v1.2.3 From c2f33edd1f30f5c7c54780636104bdef318d65db Mon Sep 17 00:00:00 2001 From: Carlo Nucera Date: Tue, 26 May 2020 11:43:18 -0400 Subject: Update src/libutil/rust-ffi.hh Co-authored-by: Cole Helbling --- src/libutil/rust-ffi.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libutil/rust-ffi.hh b/src/libutil/rust-ffi.hh index 584dcf110..8b61b6d00 100644 --- a/src/libutil/rust-ffi.hh +++ b/src/libutil/rust-ffi.hh @@ -42,7 +42,7 @@ protected: } // Not all Rust types are Clone / Copy, but our base Value class needs to - // have a copy constructor so that ones which do implement Copy/Clone + // have a copy constructor so that types which do implement Copy/Clone // can be copied/cloned. Value(const Value & other) : raw(other.raw) -- cgit v1.2.3 From f3f520c14ca0316f9e6333fbe939a277e5d78d1b Mon Sep 17 00:00:00 2001 From: Carlo Nucera Date: Tue, 26 May 2020 12:51:28 -0400 Subject: Change syntax for CI --- src/nix/dev-shell.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/nix/dev-shell.cc b/src/nix/dev-shell.cc index 092ff8b10..337d7750e 100644 --- a/src/nix/dev-shell.cc +++ b/src/nix/dev-shell.cc @@ -136,8 +136,7 @@ StorePath getDerivationEnvironment(ref store, const StorePath & drvPath) Hash h = hashDerivationModulo(*store, drv, true); auto shellOutPath = store->makeOutputPath("out", h, drvName); drv.outputs.insert_or_assign("out", DerivationOutput(shellOutPath.clone(), FileSystemHash { - .method = FileIngestionMethod::Flat, - .hash = Hash { } + FileIngestionMethod::Flat, Hash { } })); drv.env["out"] = store->printStorePath(shellOutPath); auto shellDrvPath2 = writeDerivation(store, drv, drvName); -- cgit v1.2.3 From a7b82fd006606dad591f8da88907e79b4c87b1f7 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Thu, 4 Jun 2020 21:04:20 +0000 Subject: Remove file which shouldn't be committed --- src/libutil/tests/libutil-tests | Bin 9399624 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100755 src/libutil/tests/libutil-tests diff --git a/src/libutil/tests/libutil-tests b/src/libutil/tests/libutil-tests deleted file mode 100755 index ae871b466..000000000 Binary files a/src/libutil/tests/libutil-tests and /dev/null differ -- cgit v1.2.3 From cd6dbf951a0ea903d0e9f2671fb127ae419e5ed2 Mon Sep 17 00:00:00 2001 From: Tobias Pflug Date: Mon, 8 Jun 2020 11:34:37 +0200 Subject: Add compression unit tests --- src/libutil/tests/compression.cc | 78 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 src/libutil/tests/compression.cc diff --git a/src/libutil/tests/compression.cc b/src/libutil/tests/compression.cc new file mode 100644 index 000000000..5b7a2c5b9 --- /dev/null +++ b/src/libutil/tests/compression.cc @@ -0,0 +1,78 @@ +#include "compression.hh" +#include + +namespace nix { + + /* ---------------------------------------------------------------------------- + * compress / decompress + * --------------------------------------------------------------------------*/ + + TEST(compress, compressWithUnknownMethod) { + ASSERT_THROW(compress("invalid-method", "something-to-compress"), UnknownCompressionMethod); + } + + TEST(compress, noneMethodDoesNothingToTheInput) { + ref o = compress("none", "this-is-a-test"); + + ASSERT_EQ(*o, "this-is-a-test"); + } + + TEST(decompress, decompressXzCompressed) { + auto method = "xz"; + auto str = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; + ref o = decompress(method, *compress(method, str)); + + ASSERT_EQ(*o, str); + } + + TEST(decompress, decompressBzip2Compressed) { + auto method = "bzip2"; + auto str = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; + ref o = decompress(method, *compress(method, str)); + + ASSERT_EQ(*o, str); + } + + TEST(decompress, decompressBrCompressed) { + auto method = "br"; + auto str = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; + ref o = decompress(method, *compress(method, str)); + + ASSERT_EQ(*o, str); + } + + TEST(decompress, decompressInvalidInputThrowsCompressionError) { + auto method = "bzip2"; + auto str = "this is a string that does not qualify as valid bzip2 data"; + + ASSERT_THROW(decompress(method, str), CompressionError); + } + + /* ---------------------------------------------------------------------------- + * compression sinks + * --------------------------------------------------------------------------*/ + + TEST(makeCompressionSink, noneSinkDoesNothingToInput) { + StringSink strSink; + auto inputString = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; + auto sink = makeCompressionSink("none", strSink); + (*sink)(inputString); + sink->finish(); + + ASSERT_STREQ((*strSink.s).c_str(), inputString); + } + + TEST(makeCompressionSink, compressAndDecompress) { + StringSink strSink; + auto inputString = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; + auto decompressionSink = makeDecompressionSink("bzip2", strSink); + auto sink = makeCompressionSink("bzip2", *decompressionSink); + + (*sink)(inputString); + sink->finish(); + decompressionSink->finish(); + + ASSERT_STREQ((*strSink.s).c_str(), inputString); + } + +} -- cgit v1.2.3 From da8aac6ce8a73a7c9dc6d3cdfa27ab074f0bc976 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Wed, 17 Jun 2020 13:41:25 +0800 Subject: 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 +++--- doc/manual/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))); } -- cgit v1.2.3 From 079c6e87deb100bf21f35150736f9662557e698e Mon Sep 17 00:00:00 2001 From: Carlo Nucera Date: Wed, 17 Jun 2020 11:16:16 -0400 Subject: 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); -- cgit v1.2.3 From 4930cb48a258b0a69a8669602964e3956592ae5c Mon Sep 17 00:00:00 2001 From: Carlo Nucera Date: Wed, 17 Jun 2020 12:58:59 -0400 Subject: 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); -- cgit v1.2.3 From f767bedfac66bff297499f68b234ac63b02c8f62 Mon Sep 17 00:00:00 2001 From: Matthew Bauer Date: Wed, 17 Jun 2020 13:26:37 -0400 Subject: 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; -- cgit v1.2.3 From 22d7d36703df637980d0dcbe3ad030114662840e Mon Sep 17 00:00:00 2001 From: Matthew Bauer Date: Wed, 17 Jun 2020 13:27:10 -0400 Subject: 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); } -- cgit v1.2.3 From 4fef2ba7e4f344eec32cdf02821d32036fbbc21b Mon Sep 17 00:00:00 2001 From: regnat Date: Thu, 18 Jun 2020 09:25:55 +0200 Subject: 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"); } -- cgit v1.2.3 From 9069759767cf1821578be8006cda52ee53ecd427 Mon Sep 17 00:00:00 2001 From: Samir Talwar Date: Thu, 18 Jun 2020 10:29:24 +0200 Subject: 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 -- cgit v1.2.3 From 7083d33efee2b4782c52dc04d90f7c08e96b79d1 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 29 Nov 2018 16:28:43 +0100 Subject: 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; -- cgit v1.2.3 From 2a61bbf77fd1b4bd518912b4923265b91a8f9d67 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 18 Jun 2020 13:44:40 +0200 Subject: 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); } -- cgit v1.2.3 From 5771c8bbf29325c24e55c75743194612228f4e07 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 17 Jun 2020 16:54:32 +0200 Subject: 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 -- cgit v1.2.3 From 237d88c97e1f08f8c1513261ac5fea847d5917ff Mon Sep 17 00:00:00 2001 From: John Ericson Date: Fri, 19 Jun 2020 14:47:10 +0000 Subject: FileSystemHash -> DerivationOutputHash --- src/libexpr/primops.cc | 6 +++--- src/libstore/derivations.cc | 10 +++++----- src/libstore/derivations.hh | 12 ++++++------ src/nix/develop.cc | 2 +- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 8288dd6a1..175fccf39 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -776,7 +776,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * * if (!jsonObject) drv.env["out"] = state.store->printStorePath(outPath); drv.outputs.insert_or_assign("out", DerivationOutput { .path = std::move(outPath), - .hash = FileSystemHash { ingestionMethod, std::move(h) }, + .hash = DerivationOutputHash { ingestionMethod, std::move(h) }, }); } @@ -792,7 +792,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * * drv.outputs.insert_or_assign(i, DerivationOutput { .path = StorePath::dummy, - .hash = std::optional {}, + .hash = std::optional {}, }); } @@ -804,7 +804,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * * drv.outputs.insert_or_assign(i, DerivationOutput { .path = std::move(outPath), - .hash = std::optional(), + .hash = std::optional(), }); } } diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc index 826b336e0..51a01feac 100644 --- a/src/libstore/derivations.cc +++ b/src/libstore/derivations.cc @@ -8,7 +8,7 @@ namespace nix { -std::string FileSystemHash::printMethodAlgo() const { +std::string DerivationOutputHash::printMethodAlgo() const { return makeFileIngestionPrefix(method) + printHashType(hash.type); } @@ -113,7 +113,7 @@ static DerivationOutput parseDerivationOutput(const Store & store, istringstream expect(str, ","); const auto hash = parseString(str); expect(str, ")"); - std::optional fsh; + std::optional fsh; if (hashAlgo != "") { auto method = FileIngestionMethod::Flat; if (string(hashAlgo, 0, 2) == "r:") { @@ -123,7 +123,7 @@ static DerivationOutput parseDerivationOutput(const Store & store, istringstream const HashType hashType = parseHashType(hashAlgo); if (hashType == htUnknown) throw Error("unknown hash hashAlgorithm '%s'", hashAlgo); - fsh = FileSystemHash { + fsh = DerivationOutputHash { std::move(method), Hash(hash, hashType), }; @@ -413,7 +413,7 @@ static DerivationOutput readDerivationOutput(Source & in, const Store & store) auto hashAlgo = readString(in); const auto hash = readString(in); - std::optional fsh; + std::optional fsh; if (hashAlgo != "") { auto method = FileIngestionMethod::Flat; if (string(hashAlgo, 0, 2) == "r:") { @@ -423,7 +423,7 @@ static DerivationOutput readDerivationOutput(Source & in, const Store & store) const HashType hashType = parseHashType(hashAlgo); if (hashType == htUnknown) throw Error("unknown hash hashAlgorithm '%s'", hashAlgo); - fsh = FileSystemHash { + fsh = DerivationOutputHash { std::move(method), Hash(hash, hashType), }; diff --git a/src/libstore/derivations.hh b/src/libstore/derivations.hh index 3b4eb7ec4..f3eff2748 100644 --- a/src/libstore/derivations.hh +++ b/src/libstore/derivations.hh @@ -13,23 +13,23 @@ namespace nix { /* Abstract syntax of derivations. */ /// Pair of a hash, and how the file system was ingested -struct FileSystemHash { +struct DerivationOutputHash { FileIngestionMethod method; Hash hash; - FileSystemHash(FileIngestionMethod method, Hash hash) + DerivationOutputHash(FileIngestionMethod method, Hash hash) : method(std::move(method)) , hash(std::move(hash)) { } - FileSystemHash(const FileSystemHash &) = default; - FileSystemHash(FileSystemHash &&) = default; - FileSystemHash & operator = (const FileSystemHash &) = default; + DerivationOutputHash(const DerivationOutputHash &) = default; + DerivationOutputHash(DerivationOutputHash &&) = default; + DerivationOutputHash & operator = (const DerivationOutputHash &) = default; std::string printMethodAlgo() const; }; struct DerivationOutput { StorePath path; - std::optional hash; /* hash used for expected hash computation */ + std::optional hash; /* hash used for expected hash computation */ void parseHashInfo(FileIngestionMethod & recursive, Hash & hash) const; }; diff --git a/src/nix/develop.cc b/src/nix/develop.cc index 8abb710c2..0845c65fa 100644 --- a/src/nix/develop.cc +++ b/src/nix/develop.cc @@ -137,7 +137,7 @@ StorePath getDerivationEnvironment(ref store, const StorePath & drvPath) auto shellOutPath = store->makeOutputPath("out", h, drvName); drv.outputs.insert_or_assign("out", DerivationOutput { .path = shellOutPath, - .hash = FileSystemHash { + .hash = DerivationOutputHash { FileIngestionMethod::Flat, Hash { } }, }); -- cgit v1.2.3 From 145d88cb2a160871968285fb1898732090f4e14c Mon Sep 17 00:00:00 2001 From: John Ericson Date: Fri, 19 Jun 2020 14:58:30 +0000 Subject: Use designated initializers for `DerivationOutputHash` --- src/libexpr/primops.cc | 5 ++++- src/libstore/derivations.cc | 8 ++++---- src/libstore/derivations.hh | 3 --- src/nix/develop.cc | 3 ++- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 175fccf39..bf3c17997 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -776,7 +776,10 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * * if (!jsonObject) drv.env["out"] = state.store->printStorePath(outPath); drv.outputs.insert_or_assign("out", DerivationOutput { .path = std::move(outPath), - .hash = DerivationOutputHash { ingestionMethod, std::move(h) }, + .hash = DerivationOutputHash { + .method = ingestionMethod, + .hash = std::move(h), + }, }); } diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc index 51a01feac..528b7ccea 100644 --- a/src/libstore/derivations.cc +++ b/src/libstore/derivations.cc @@ -124,8 +124,8 @@ static DerivationOutput parseDerivationOutput(const Store & store, istringstream if (hashType == htUnknown) throw Error("unknown hash hashAlgorithm '%s'", hashAlgo); fsh = DerivationOutputHash { - std::move(method), - Hash(hash, hashType), + .method = std::move(method), + .hash = Hash(hash, hashType), }; } @@ -424,8 +424,8 @@ static DerivationOutput readDerivationOutput(Source & in, const Store & store) if (hashType == htUnknown) throw Error("unknown hash hashAlgorithm '%s'", hashAlgo); fsh = DerivationOutputHash { - std::move(method), - Hash(hash, hashType), + .method = std::move(method), + .hash = Hash(hash, hashType), }; } diff --git a/src/libstore/derivations.hh b/src/libstore/derivations.hh index f3eff2748..292861065 100644 --- a/src/libstore/derivations.hh +++ b/src/libstore/derivations.hh @@ -20,9 +20,6 @@ struct DerivationOutputHash { : method(std::move(method)) , hash(std::move(hash)) { } - DerivationOutputHash(const DerivationOutputHash &) = default; - DerivationOutputHash(DerivationOutputHash &&) = default; - DerivationOutputHash & operator = (const DerivationOutputHash &) = default; std::string printMethodAlgo() const; }; diff --git a/src/nix/develop.cc b/src/nix/develop.cc index 0845c65fa..8b85caf82 100644 --- a/src/nix/develop.cc +++ b/src/nix/develop.cc @@ -138,7 +138,8 @@ StorePath getDerivationEnvironment(ref store, const StorePath & drvPath) drv.outputs.insert_or_assign("out", DerivationOutput { .path = shellOutPath, .hash = DerivationOutputHash { - FileIngestionMethod::Flat, Hash { } + .method = FileIngestionMethod::Flat, + .hash = Hash { }, }, }); drv.env["out"] = store->printStorePath(shellOutPath); -- cgit v1.2.3 From b90cac3bad41715c2fefc9d725630d0abb9af725 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Fri, 19 Jun 2020 15:00:38 +0000 Subject: Remove uneeded `= default` for Hash --- src/libutil/hash.hh | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/libutil/hash.hh b/src/libutil/hash.hh index 92e10ee6e..180fb7633 100644 --- a/src/libutil/hash.hh +++ b/src/libutil/hash.hh @@ -44,12 +44,6 @@ struct Hash string. */ Hash(std::string_view s, HashType type = htUnknown); - Hash(const Hash &) = default; - - Hash(Hash &&) = default; - - Hash & operator = (const Hash &) = default; - void init(); /* Check whether a hash is set. */ -- cgit v1.2.3 From fb39a5e00c03c8fb3b893263e1d2b151c3ba11aa Mon Sep 17 00:00:00 2001 From: John Ericson Date: Fri, 19 Jun 2020 15:11:11 +0000 Subject: Remove unneeded constructor for `DerivationOutputHash` --- src/libstore/derivations.hh | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/libstore/derivations.hh b/src/libstore/derivations.hh index 292861065..7b677ca49 100644 --- a/src/libstore/derivations.hh +++ b/src/libstore/derivations.hh @@ -16,10 +16,6 @@ namespace nix { struct DerivationOutputHash { FileIngestionMethod method; Hash hash; - DerivationOutputHash(FileIngestionMethod method, Hash hash) - : method(std::move(method)) - , hash(std::move(hash)) - { } std::string printMethodAlgo() const; }; -- cgit v1.2.3