diff options
author | John Ericson <John.Ericson@Obsidian.Systems> | 2020-06-18 18:08:02 +0000 |
---|---|---|
committer | John Ericson <John.Ericson@Obsidian.Systems> | 2020-06-18 18:08:02 +0000 |
commit | fb432b0bd2b102c42057628e0cce3039ce167810 (patch) | |
tree | ad4a4d7a79f153ef0bb2bd405bd3bde157cccd54 /src | |
parent | 74b219ef6e5e171c56c8ad7385969e0d0df09ed8 (diff) | |
parent | 639e20dc3ed9c5b28138285653912de78fe0507f (diff) |
Merge remote-tracking branch 'obsidian/fix-url-format' into add-body-to-network-errors
Diffstat (limited to 'src')
-rw-r--r-- | src/libexpr/attr-path.cc | 13 | ||||
-rw-r--r-- | src/libexpr/attr-path.hh | 2 | ||||
-rw-r--r-- | src/libexpr/eval.cc | 39 | ||||
-rw-r--r-- | src/libexpr/eval.hh | 6 | ||||
-rw-r--r-- | src/libexpr/get-drvs.cc | 2 | ||||
-rw-r--r-- | src/libexpr/primops.cc | 23 | ||||
-rw-r--r-- | src/libexpr/primops.hh | 17 | ||||
-rw-r--r-- | src/libmain/shared.cc | 20 | ||||
-rw-r--r-- | src/libstore/binary-cache-store.cc | 2 | ||||
-rw-r--r-- | src/libstore/build.cc | 6 | ||||
-rw-r--r-- | src/libstore/filetransfer.cc | 17 |
11 files changed, 102 insertions, 45 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<Symbol> parseAttrPath(EvalState & state, std::string_view s) +{ + std::vector<Symbol> res; + for (auto & a : parseAttrPath(s)) + res.push_back(state.symbols.create(a)); + return res; +} + + std::pair<Value *, Pos> 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<Value *, Pos> 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<Symbol> parseAttrPath(EvalState & state, std::string_view s); + } diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 8e71db2b8..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> store) , sOutputHash(symbols.create("outputHash")) , sOutputHashAlgo(symbols.create("outputHashAlgo")) , sOutputHashMode(symbols.create("outputHashMode")) + , sRecurseForDerivations(symbols.create("recurseForDerivations")) , repair(NoRepair) , store(store) , baseEnv(allocEnv(128)) @@ -471,14 +485,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; diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 1485dc7fe..863365259 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; @@ -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 ‘!<name>!<path>’ into a pair <path, diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc index ca9c547fa..a4937e722 100644 --- a/src/libexpr/get-drvs.cc +++ b/src/libexpr/get-drvs.cc @@ -348,7 +348,7 @@ static void getDerivations(EvalState & state, Value & vIn, should we recurse into it? => 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..2f1a41a64 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -50,20 +50,20 @@ void EvalState::realiseContext(const PathSet & context) std::vector<StorePathWithOutputs> drvs; for (auto & i : context) { - std::pair<string, string> 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); } @@ -2201,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<std::string> requiredFeature) { if (!primOps) primOps = new PrimOps; - primOps->emplace_back(name, arity, fun); + primOps->push_back({name, arity, fun, requiredFeature}); } @@ -2396,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<std::tuple<std::string, size_t, PrimOpFun>> PrimOps; + struct Info + { + std::string name; + size_t arity; + PrimOpFun primOp; + std::optional<std::string> requiredFeature; + }; + + typedef std::vector<Info> 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<std::string> requiredFeature = {}); }; /* These primops are disabled without enableNativeCode, but plugins 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> 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> 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))); } 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); } diff --git a/src/libstore/build.cc b/src/libstore/build.cc index e1d812b09..3b0efa1a5 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<Goal> GoalPtr; typedef std::weak_ptr<Goal> WeakGoalPtr; @@ -1196,8 +1196,8 @@ void DerivationGoal::haveDerivation() parsedDrv = std::make_unique<ParsedDerivation>(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"); } diff --git a/src/libstore/filetransfer.cc b/src/libstore/filetransfer.cc index fa8ad33f5..9ae682bbb 100644 --- a/src/libstore/filetransfer.cc +++ b/src/libstore/filetransfer.cc @@ -424,16 +424,13 @@ struct curlFileTransfer : public FileTransfer response = teeSink->data; auto exc = code == CURLE_ABORTED_BY_CALLBACK && _isInterrupted - ? FileTransferError(Interrupted, response, fmt("%s of '%s' was interrupted", request.verb(), request.uri)) + ? FileTransferError(Interrupted, response, "%s of '%s' was interrupted", request.verb(), request.uri) : httpStatus != 0 - ? FileTransferError(err, response, - fmt("unable to %s '%s': HTTP error %d", - request.verb(), request.uri, httpStatus) - + (code == CURLE_OK ? "" : fmt(" (curl error: %s)", curl_easy_strerror(code))) - ) - : FileTransferError(err, response, - fmt("unable to %s '%s': %s (%d)", - request.verb(), request.uri, curl_easy_strerror(code), code)); + ? FileTransferError(err, response, "unable to %s '%s': HTTP error %d%s", + request.verb(), request.uri, httpStatus, + code == CURLE_OK ? "" : fmt(" (curl error: %s)", curl_easy_strerror(code))) + : FileTransferError(err, response, "unable to %s '%s': %s (%d)", + request.verb(), request.uri, curl_easy_strerror(code), code); /* If this is a transient error, then maybe retry the download after a while. If we're writing to a @@ -689,7 +686,7 @@ struct curlFileTransfer : public FileTransfer auto s3Res = s3Helper.getObject(bucketName, key); FileTransferResult res; if (!s3Res.data) - throw FileTransferError(NotFound, nullptr, fmt("S3 object '%s' does not exist", request.uri)); + throw FileTransferError(NotFound, nullptr, "S3 object '%s' does not exist", request.uri); res.data = s3Res.data; callback(std::move(res)); #else |