1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-06-28 17:51:15 +02:00

Merge branch 'path-info' into ca-drv-exotic

This commit is contained in:
John Ericson 2022-04-19 22:39:57 +00:00
commit 08b8657978
85 changed files with 1319 additions and 590 deletions

View file

@ -1,101 +0,0 @@
#include "common-eval-args.hh"
#include "shared.hh"
#include "filetransfer.hh"
#include "util.hh"
#include "eval.hh"
#include "fetchers.hh"
#include "registry.hh"
#include "flake/flakeref.hh"
#include "store-api.hh"
namespace nix {
MixEvalArgs::MixEvalArgs()
{
auto category = "Common evaluation options";
addFlag({
.longName = "arg",
.description = "Pass the value *expr* as the argument *name* to Nix functions.",
.category = category,
.labels = {"name", "expr"},
.handler = {[&](std::string name, std::string expr) { autoArgs[name] = 'E' + expr; }}
});
addFlag({
.longName = "argstr",
.description = "Pass the string *string* as the argument *name* to Nix functions.",
.category = category,
.labels = {"name", "string"},
.handler = {[&](std::string name, std::string s) { autoArgs[name] = 'S' + s; }},
});
addFlag({
.longName = "include",
.shortName = 'I',
.description = "Add *path* to the list of locations used to look up `<...>` file names.",
.category = category,
.labels = {"path"},
.handler = {[&](std::string s) { searchPath.push_back(s); }}
});
addFlag({
.longName = "impure",
.description = "Allow access to mutable paths and repositories.",
.category = category,
.handler = {[&]() {
evalSettings.pureEval = false;
}},
});
addFlag({
.longName = "override-flake",
.description = "Override the flake registries, redirecting *original-ref* to *resolved-ref*.",
.category = category,
.labels = {"original-ref", "resolved-ref"},
.handler = {[&](std::string _from, std::string _to) {
auto from = parseFlakeRef(_from, absPath("."));
auto to = parseFlakeRef(_to, absPath("."));
fetchers::Attrs extraAttrs;
if (to.subdir != "") extraAttrs["dir"] = to.subdir;
fetchers::overrideRegistry(from.input, to.input, extraAttrs);
}}
});
addFlag({
.longName = "eval-store",
.description = "The Nix store to use for evaluations.",
.category = category,
.labels = {"store-url"},
.handler = {&evalStoreUrl},
});
}
Bindings * MixEvalArgs::getAutoArgs(EvalState & state)
{
auto res = state.buildBindings(autoArgs.size());
for (auto & i : autoArgs) {
auto v = state.allocValue();
if (i.second[0] == 'E')
state.mkThunk_(*v, state.parseExprFromString(i.second.substr(1), absPath(".")));
else
v->mkString(((std::string_view) i.second).substr(1));
res.insert(state.symbols.create(i.first), v);
}
return res.finish();
}
Path lookupFileArg(EvalState & state, std::string_view s)
{
if (isUri(s)) {
return state.store->toRealPath(
fetchers::downloadTarball(
state.store, resolveUri(s), "source", false).first.storePath);
} else if (s.size() > 2 && s.at(0) == '<' && s.at(s.size() - 1) == '>') {
Path p(s.substr(1, s.size() - 2));
return state.findFile(p);
} else
return absPath(std::string(s));
}
}

View file

@ -1,27 +0,0 @@
#pragma once
#include "args.hh"
namespace nix {
class Store;
class EvalState;
class Bindings;
struct MixEvalArgs : virtual Args
{
MixEvalArgs();
Bindings * getAutoArgs(EvalState & state);
Strings searchPath;
std::optional<std::string> evalStoreUrl;
private:
std::map<std::string, std::string> autoArgs;
};
Path lookupFileArg(EvalState & state, std::string_view s);
}

View file

@ -306,9 +306,9 @@ Value * EvalCache::getRootValue()
return *value;
}
std::shared_ptr<AttrCursor> EvalCache::getRoot()
ref<AttrCursor> EvalCache::getRoot()
{
return std::make_shared<AttrCursor>(ref(shared_from_this()), std::nullopt);
return make_ref<AttrCursor>(ref(shared_from_this()), std::nullopt);
}
AttrCursor::AttrCursor(

View file

@ -33,7 +33,7 @@ public:
EvalState & state,
RootLoader rootLoader);
std::shared_ptr<AttrCursor> getRoot();
ref<AttrCursor> getRoot();
};
enum AttrType {
@ -104,6 +104,8 @@ public:
ref<AttrCursor> getAttr(std::string_view name);
/* Get an attribute along a chain of attrsets. Note that this does
not auto-call functors or functions. */
OrSuggestions<ref<AttrCursor>> findAlongAttrPath(const std::vector<Symbol> & attrPath, bool force = false);
std::string getString();

View file

@ -436,6 +436,7 @@ EvalState::EvalState(
, sBuilder(symbols.create("builder"))
, sArgs(symbols.create("args"))
, sContentAddressed(symbols.create("__contentAddressed"))
, sImpure(symbols.create("__impure"))
, sOutputHash(symbols.create("outputHash"))
, sOutputHashAlgo(symbols.create("outputHashAlgo"))
, sOutputHashMode(symbols.create("outputHashMode"))

View file

@ -78,7 +78,7 @@ public:
sSystem, sOverrides, sOutputs, sOutputName, sIgnoreNulls,
sFile, sLine, sColumn, sFunctor, sToString,
sRight, sWrong, sStructuredAttrs, sBuilder, sArgs,
sContentAddressed,
sContentAddressed, sImpure,
sOutputHash, sOutputHashAlgo, sOutputHashMode,
sRecurseForDerivations,
sDescription, sSelf, sEpsilon, sStartSet, sOperator, sKey, sPath,

View file

@ -989,9 +989,10 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
PathSet context;
bool contentAddressed = false;
bool isImpure = false;
std::optional<std::string> outputHash;
std::string outputHashAlgo;
ContentAddressMethod ingestionMethod = FileIngestionMethod::Flat;
std::optional<ContentAddressMethod> ingestionMethod;
StringSet outputs;
outputs.insert("out");
@ -1052,6 +1053,12 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
settings.requireExperimentalFeature(Xp::CaDerivations);
}
else if (i->name == state.sImpure) {
isImpure = state.forceBool(*i->value, pos);
if (isImpure)
settings.requireExperimentalFeature(Xp::ImpureDerivations);
}
/* The `args' attribute is special: it supplies the
command-line arguments to the builder. */
else if (i->name == state.sArgs) {
@ -1187,12 +1194,12 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
.errPos = posDrvName
});
std::optional<HashType> ht = parseHashTypeOpt(outputHashAlgo);
Hash h = newHashAllowEmpty(*outputHash, ht);
auto h = newHashAllowEmpty(*outputHash, parseHashTypeOpt(outputHashAlgo));
auto method = ingestionMethod.value_or(FileIngestionMethod::Flat);
// FIXME non-trivial fixed refs set
auto ca = contentAddressFromMethodHashAndRefs(
ingestionMethod,
method,
std::move(h),
{});
@ -1202,15 +1209,30 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
drv.outputs.insert_or_assign("out", dof);
}
else if (contentAddressed) {
HashType ht = parseHashType(outputHashAlgo);
else if (contentAddressed || isImpure) {
if (contentAddressed && isImpure)
throw EvalError({
.msg = hintfmt("derivation cannot be both content-addressed and impure"),
.errPos = posDrvName
});
auto ht = parseHashTypeOpt(outputHashAlgo).value_or(htSHA256);
auto method = ingestionMethod.value_or(FileIngestionMethod::Recursive);
for (auto & i : outputs) {
drv.env[i] = hashPlaceholder(i);
drv.outputs.insert_or_assign(i,
DerivationOutput::CAFloating {
.method = ingestionMethod,
.hashType = ht,
});
if (isImpure)
drv.outputs.insert_or_assign(i,
DerivationOutput::Impure {
.method = method,
.hashType = ht,
});
else
drv.outputs.insert_or_assign(i,
DerivationOutput::CAFloating {
.method = method,
.hashType = ht,
});
}
}
@ -1227,34 +1249,26 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
DerivationOutput::Deferred { });
}
// Regular, non-CA derivation should always return a single hash and not
// hash per output.
auto hashModulo = hashDerivationModulo(*state.store, drv, true);
std::visit(overloaded {
[&](const DrvHash & drvHash) {
auto & h = drvHash.hash;
switch (drvHash.kind) {
case DrvHash::Kind::Deferred:
/* Outputs already deferred, nothing to do */
break;
case DrvHash::Kind::Regular:
for (auto & [outputName, output] : drv.outputs) {
auto outPath = state.store->makeOutputPath(outputName, h, drvName);
drv.env[outputName] = state.store->printStorePath(outPath);
output = DerivationOutput::InputAddressed {
.path = std::move(outPath),
};
}
break;
}
},
[&](const CaOutputHashes &) {
// Shouldn't happen as the toplevel derivation is not CA.
assert(false);
},
},
hashModulo.raw());
auto hashModulo = hashDerivationModulo(*state.store, Derivation(drv), true);
switch (hashModulo.kind) {
case DrvHash::Kind::Regular:
for (auto & i : outputs) {
auto h = hashModulo.hashes.at(i);
auto outPath = state.store->makeOutputPath(i, h, drvName);
drv.env[i] = state.store->printStorePath(outPath);
drv.outputs.insert_or_assign(
i,
DerivationOutputInputAddressed {
.path = std::move(outPath),
});
}
break;
;
case DrvHash::Kind::Deferred:
for (auto & i : outputs) {
drv.outputs.insert_or_assign(i, DerivationOutputDeferred {});
}
}
}
/* Write the resulting term into the Nix store directory. */

View file

@ -61,6 +61,12 @@ static void prim_fetchClosure(EvalState & state, const Pos & pos, Value * * args
.errPos = pos
});
if (!parsedURL.query.empty())
throw Error({
.msg = hintfmt("'fetchClosure' does not support URL query parameters (in '%s')", *fromStoreUrl),
.errPos = pos
});
auto fromStore = openStore(parsedURL.to_string());
if (toCA) {
@ -87,7 +93,8 @@ static void prim_fetchClosure(EvalState & state, const Pos & pos, Value * * args
});
}
} else {
copyClosure(*fromStore, *state.store, RealisedPath::Set { *fromPath });
if (!state.store->isValidPath(*fromPath))
copyClosure(*fromStore, *state.store, RealisedPath::Set { *fromPath });
toPath = fromPath;
}

View file

@ -84,7 +84,8 @@ void printValueAsJSON(EvalState & state, bool strict,
.msg = hintfmt("cannot convert %1% to JSON", showType(v)),
.errPos = v.determinePos(pos)
});
throw e.addTrace(pos, hintfmt("message for the trace"));
e.addTrace(pos, hintfmt("message for the trace"));
throw e;
}
}