Merge remote-tracking branch 'obsidian/fix-url-format' into add-body-to-network-errors

This commit is contained in:
John Ericson 2020-06-18 18:08:02 +00:00
commit fb432b0bd2
17 changed files with 111 additions and 54 deletions

View file

@ -70,7 +70,7 @@ path just built.</para>
<screen> <screen>
$ nix-build ./deterministic.nix -A stable $ nix-build ./deterministic.nix -A stable
these derivations will be built: this derivation will be built:
/nix/store/z98fasz2jqy9gs0xbvdj939p27jwda38-stable.drv /nix/store/z98fasz2jqy9gs0xbvdj939p27jwda38-stable.drv
building '/nix/store/z98fasz2jqy9gs0xbvdj939p27jwda38-stable.drv'... building '/nix/store/z98fasz2jqy9gs0xbvdj939p27jwda38-stable.drv'...
/nix/store/yyxlzw3vqaas7wfp04g0b1xg51f2czgq-stable /nix/store/yyxlzw3vqaas7wfp04g0b1xg51f2czgq-stable
@ -85,7 +85,7 @@ checking outputs of '/nix/store/z98fasz2jqy9gs0xbvdj939p27jwda38-stable.drv'...
<screen> <screen>
$ nix-build ./deterministic.nix -A unstable $ nix-build ./deterministic.nix -A unstable
these derivations will be built: this derivation will be built:
/nix/store/cgl13lbj1w368r5z8gywipl1ifli7dhk-unstable.drv /nix/store/cgl13lbj1w368r5z8gywipl1ifli7dhk-unstable.drv
building '/nix/store/cgl13lbj1w368r5z8gywipl1ifli7dhk-unstable.drv'... building '/nix/store/cgl13lbj1w368r5z8gywipl1ifli7dhk-unstable.drv'...
/nix/store/krpqk0l9ib0ibi1d2w52z293zw455cap-unstable /nix/store/krpqk0l9ib0ibi1d2w52z293zw455cap-unstable
@ -193,7 +193,7 @@ repeat = 1
An example output of this configuration: An example output of this configuration:
<screen> <screen>
$ nix-build ./test.nix -A unstable $ nix-build ./test.nix -A unstable
these derivations will be built: this derivation will be built:
/nix/store/ch6llwpr2h8c3jmnf3f2ghkhx59aa97f-unstable.drv /nix/store/ch6llwpr2h8c3jmnf3f2ghkhx59aa97f-unstable.drv
building '/nix/store/ch6llwpr2h8c3jmnf3f2ghkhx59aa97f-unstable.drv' (round 1/2)... building '/nix/store/ch6llwpr2h8c3jmnf3f2ghkhx59aa97f-unstable.drv' (round 1/2)...
building '/nix/store/ch6llwpr2h8c3jmnf3f2ghkhx59aa97f-unstable.drv' (round 2/2)... building '/nix/store/ch6llwpr2h8c3jmnf3f2ghkhx59aa97f-unstable.drv' (round 2/2)...

View file

@ -122,7 +122,7 @@ post-build-hook = /etc/nix/upload-to-cache.sh
<screen> <screen>
$ nix-build -E '(import &lt;nixpkgs&gt; {}).writeText "example" (builtins.toString builtins.currentTime)' $ nix-build -E '(import &lt;nixpkgs&gt; {}).writeText "example" (builtins.toString builtins.currentTime)'
these derivations will be built: this derivation will be built:
/nix/store/s4pnfbkalzy5qz57qs6yybna8wylkig6-example.drv /nix/store/s4pnfbkalzy5qz57qs6yybna8wylkig6-example.drv
building '/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'... running post-build-hook '/home/grahamc/projects/github.com/NixOS/nix/post-hook.sh'...

View file

@ -516,7 +516,7 @@ source:
$ nix-env -f '&lt;nixpkgs>' -iA hello --dry-run $ nix-env -f '&lt;nixpkgs>' -iA hello --dry-run
(dry run; not doing anything) (dry run; not doing anything)
installing hello-2.10 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 /nix/store/wkhdf9jinag5750mqlax6z2zbwhqb76n-hello-2.10
<replaceable>...</replaceable></screen> <replaceable>...</replaceable></screen>

View file

@ -39,7 +39,7 @@ bundle.</para>
<step><para>Set the environment variable and install Nix</para> <step><para>Set the environment variable and install Nix</para>
<screen> <screen>
$ export NIX_SSL_CERT_FILE=/etc/ssl/my-certificate-bundle.crt $ export NIX_SSL_CERT_FILE=/etc/ssl/my-certificate-bundle.crt
$ sh &lt;(curl https://nixos.org/nix/install) $ sh &lt;(curl -L https://nixos.org/nix/install)
</screen></step> </screen></step>
<step><para>In the shell profile and rc files (for example, <step><para>In the shell profile and rc files (for example,

View file

@ -12,7 +12,7 @@
</para> </para>
<screen> <screen>
$ sh &lt;(curl https://nixos.org/nix/install) $ sh &lt;(curl -L https://nixos.org/nix/install)
</screen> </screen>
<para> <para>
@ -39,7 +39,7 @@
To explicitly select a single-user installation on your system: To explicitly select a single-user installation on your system:
<screen> <screen>
sh &lt;(curl https://nixos.org/nix/install) --no-daemon sh &lt;(curl -L https://nixos.org/nix/install) --no-daemon
</screen> </screen>
</para> </para>

View file

@ -15,7 +15,7 @@ to subsequent chapters.</para>
<step><para>Install single-user Nix by running the following: <step><para>Install single-user Nix by running the following:
<screen> <screen>
$ bash &lt;(curl https://nixos.org/nix/install) $ bash &lt;(curl -L https://nixos.org/nix/install)
</screen> </screen>
This will install Nix in <filename>/nix</filename>. The install script This will install Nix in <filename>/nix</filename>. The install script

View file

@ -6,11 +6,11 @@
namespace nix { namespace nix {
static Strings parseAttrPath(const string & s) static Strings parseAttrPath(std::string_view s)
{ {
Strings res; Strings res;
string cur; string cur;
string::const_iterator i = s.begin(); auto i = s.begin();
while (i != s.end()) { while (i != s.end()) {
if (*i == '.') { if (*i == '.') {
res.push_back(cur); 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, std::pair<Value *, Pos> findAlongAttrPath(EvalState & state, const string & attrPath,
Bindings & autoArgs, Value & vIn) Bindings & autoArgs, Value & vIn)
{ {

View file

@ -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. */ /* Heuristic to find the filename and lineno or a nix value. */
Pos findDerivationFilename(EvalState & state, Value & v, std::string what); Pos findDerivationFilename(EvalState & state, Value & v, std::string what);
std::vector<Symbol> parseAttrPath(EvalState & state, std::string_view s);
} }

View file

@ -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 tInt: return "an integer";
case tBool: return "a boolean"; case tBool: return "a Boolean";
case tString: return v.string.context ? "a string with context" : "a string"; case tString: return "a string";
case tPath: return "a path"; case tPath: return "a path";
case tNull: return "null"; case tNull: return "null";
case tAttrs: return "a set"; case tAttrs: return "a set";
@ -175,14 +175,27 @@ string showType(const Value & v)
case tApp: return "a function application"; case tApp: return "a function application";
case tLambda: return "a function"; case tLambda: return "a function";
case tBlackhole: return "a black hole"; 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: case tPrimOp:
return fmt("the built-in function '%s'", string(v.primOp->name)); return fmt("the built-in function '%s'", string(v.primOp->name));
case tPrimOpApp: case tPrimOpApp:
return fmt("the partially applied built-in function '%s'", string(getPrimOp(v)->primOp->name)); return fmt("the partially applied built-in function '%s'", string(getPrimOp(v)->primOp->name));
case tExternal: return v.external->showType(); 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")) , sOutputHash(symbols.create("outputHash"))
, sOutputHashAlgo(symbols.create("outputHashAlgo")) , sOutputHashAlgo(symbols.create("outputHashAlgo"))
, sOutputHashMode(symbols.create("outputHashMode")) , sOutputHashMode(symbols.create("outputHashMode"))
, sRecurseForDerivations(symbols.create("recurseForDerivations"))
, repair(NoRepair) , repair(NoRepair)
, store(store) , store(store)
, baseEnv(allocEnv(128)) , baseEnv(allocEnv(128))
@ -471,14 +485,21 @@ Value * EvalState::addConstant(const string & name, Value & v)
Value * EvalState::addPrimOp(const string & name, Value * EvalState::addPrimOp(const string & name,
size_t arity, PrimOpFun primOp) 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) { if (arity == 0) {
auto vPrimOp = allocValue();
vPrimOp->type = tPrimOp;
vPrimOp->primOp = new PrimOp(primOp, 1, sym);
Value v; Value v;
primOp(*this, noPos, nullptr, v); mkApp(v, *vPrimOp, *vPrimOp);
return addConstant(name, v); return addConstant(name, v);
} }
Value * v = allocValue(); Value * v = allocValue();
string name2 = string(name, 0, 2) == "__" ? string(name, 2) : name;
Symbol sym = symbols.create(name2);
v->type = tPrimOp; v->type = tPrimOp;
v->primOp = new PrimOp(primOp, arity, sym); v->primOp = new PrimOp(primOp, arity, sym);
staticBaseEnv.vars[symbols.create(name)] = baseEnvDispl; staticBaseEnv.vars[symbols.create(name)] = baseEnvDispl;

View file

@ -18,7 +18,7 @@ namespace nix {
class Store; class Store;
class EvalState; class EvalState;
struct StorePath; class StorePath;
enum RepairFlag : bool; enum RepairFlag : bool;
@ -74,7 +74,8 @@ public:
sSystem, sOverrides, sOutputs, sOutputName, sIgnoreNulls, sSystem, sOverrides, sOutputs, sOutputName, sIgnoreNulls,
sFile, sLine, sColumn, sFunctor, sToString, sFile, sLine, sColumn, sFunctor, sToString,
sRight, sWrong, sStructuredAttrs, sBuilder, sArgs, sRight, sWrong, sStructuredAttrs, sBuilder, sArgs,
sOutputHash, sOutputHashAlgo, sOutputHashMode; sOutputHash, sOutputHashAlgo, sOutputHashMode,
sRecurseForDerivations;
Symbol sDerivationNix; Symbol sDerivationNix;
/* If set, force copying files to the Nix store even if they /* 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'. */ /* Return a string representing the type of the value `v'. */
string showType(ValueType type);
string showType(const Value & v); string showType(const Value & v);
/* Decode a context string !<name>!<path> into a pair <path, /* Decode a context string !<name>!<path> into a pair <path,

View file

@ -348,7 +348,7 @@ static void getDerivations(EvalState & state, Value & vIn,
should we recurse into it? => Only if it has a should we recurse into it? => Only if it has a
`recurseForDerivations = true' attribute. */ `recurseForDerivations = true' attribute. */
if (i->value->type == tAttrs) { 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)) if (j != i->value->attrs->end() && state.forceBool(*j->value, *j->pos))
getDerivations(state, *i->value, pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures); getDerivations(state, *i->value, pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures);
} }

View file

@ -50,20 +50,20 @@ void EvalState::realiseContext(const PathSet & context)
std::vector<StorePathWithOutputs> drvs; std::vector<StorePathWithOutputs> drvs;
for (auto & i : context) { for (auto & i : context) {
std::pair<string, string> decoded = decodeContext(i); auto [ctxS, outputName] = decodeContext(i);
auto ctx = store->parseStorePath(decoded.first); auto ctx = store->parseStorePath(ctxS);
if (!store->isValidPath(ctx)) if (!store->isValidPath(ctx))
throw InvalidPathError(store->printStorePath(ctx)); throw InvalidPathError(store->printStorePath(ctx));
if (!decoded.second.empty() && ctx.isDerivation()) { if (!outputName.empty() && ctx.isDerivation()) {
drvs.push_back(StorePathWithOutputs{ctx, {decoded.second}}); drvs.push_back(StorePathWithOutputs{ctx, {outputName}});
/* Add the output of this derivation to the allowed /* Add the output of this derivation to the allowed
paths. */ paths. */
if (allowedPaths) { if (allowedPaths) {
auto drv = store->derivationFromPath(store->parseStorePath(decoded.first)); auto drv = store->derivationFromPath(ctx);
DerivationOutputs::iterator i = drv.outputs.find(decoded.second); DerivationOutputs::iterator i = drv.outputs.find(outputName);
if (i == drv.outputs.end()) 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)); allowedPaths->insert(store->printStorePath(i->second.path));
} }
} }
@ -79,6 +79,7 @@ void EvalState::realiseContext(const PathSet & context)
StorePathSet willBuild, willSubstitute, unknown; StorePathSet willBuild, willSubstitute, unknown;
unsigned long long downloadSize, narSize; unsigned long long downloadSize, narSize;
store->queryMissing(drvs, willBuild, willSubstitute, unknown, downloadSize, narSize); store->queryMissing(drvs, willBuild, willSubstitute, unknown, downloadSize, narSize);
store->buildPaths(drvs); store->buildPaths(drvs);
} }
@ -2201,10 +2202,11 @@ static void prim_splitVersion(EvalState & state, const Pos & pos, Value * * args
RegisterPrimOp::PrimOps * RegisterPrimOp::primOps; 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; 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) if (RegisterPrimOp::primOps)
for (auto & primOp : *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, /* Now that we've added all primops, sort the `builtins' set,
because attribute lookups expect it to be sorted. */ because attribute lookups expect it to be sorted. */

View file

@ -7,12 +7,25 @@ namespace nix {
struct RegisterPrimOp 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; static PrimOps * primOps;
/* You can register a constant by passing an arity of 0. fun /* You can register a constant by passing an arity of 0. fun
will get called during EvalState initialization, so there will get called during EvalState initialization, so there
may be primops not yet added and builtins is not yet sorted. */ 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 /* These primops are disabled without enableNativeCode, but plugins

View file

@ -48,7 +48,10 @@ void printMissing(ref<Store> store, const StorePathSet & willBuild,
unsigned long long downloadSize, unsigned long long narSize, Verbosity lvl) unsigned long long downloadSize, unsigned long long narSize, Verbosity lvl)
{ {
if (!willBuild.empty()) { 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); auto sorted = store->topoSortPaths(willBuild);
reverse(sorted.begin(), sorted.end()); reverse(sorted.begin(), sorted.end());
for (auto & i : sorted) for (auto & i : sorted)
@ -56,9 +59,18 @@ void printMissing(ref<Store> store, const StorePathSet & willBuild,
} }
if (!willSubstitute.empty()) { if (!willSubstitute.empty()) {
printMsg(lvl, fmt("these paths will be fetched (%.2f MiB download, %.2f MiB unpacked):", const float downloadSizeMiB = downloadSize / (1024.f * 1024.f);
downloadSize / (1024.0 * 1024.0), const float narSizeMiB = narSize / (1024.f * 1024.f);
narSize / (1024.0 * 1024.0))); 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) for (auto & i : willSubstitute)
printMsg(lvl, fmt(" %s", store->printStorePath(i))); printMsg(lvl, fmt(" %s", store->printStorePath(i)));
} }

View file

@ -388,8 +388,6 @@ void BinaryCacheStore::addSignatures(const StorePath & storePath, const StringSe
narInfo->sigs.insert(sigs.begin(), sigs.end()); narInfo->sigs.insert(sigs.begin(), sigs.end());
auto narInfoFile = narInfoFileFor(narInfo->path);
writeNarInfo(narInfo); writeNarInfo(narInfo);
} }

View file

@ -86,7 +86,7 @@ struct HookInstance;
/* A pointer to a goal. */ /* A pointer to a goal. */
class Goal; struct Goal;
class DerivationGoal; class DerivationGoal;
typedef std::shared_ptr<Goal> GoalPtr; typedef std::shared_ptr<Goal> GoalPtr;
typedef std::weak_ptr<Goal> WeakGoalPtr; typedef std::weak_ptr<Goal> WeakGoalPtr;
@ -1196,8 +1196,8 @@ void DerivationGoal::haveDerivation()
parsedDrv = std::make_unique<ParsedDerivation>(drvPath, *drv); parsedDrv = std::make_unique<ParsedDerivation>(drvPath, *drv);
if (parsedDrv->contentAddressed()) { if (parsedDrv->contentAddressed()) {
settings.requireExperimentalFeature("content-addressed-paths"); settings.requireExperimentalFeature("ca-derivations");
throw Error("content-addressed-paths isn't implemented yet"); throw Error("ca-derivations isn't implemented yet");
} }

View file

@ -424,16 +424,13 @@ struct curlFileTransfer : public FileTransfer
response = teeSink->data; response = teeSink->data;
auto exc = auto exc =
code == CURLE_ABORTED_BY_CALLBACK && _isInterrupted 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 : httpStatus != 0
? FileTransferError(err, response, ? FileTransferError(err, response, "unable to %s '%s': HTTP error %d%s",
fmt("unable to %s '%s': HTTP error %d", request.verb(), request.uri, httpStatus,
request.verb(), request.uri, httpStatus) code == CURLE_OK ? "" : fmt(" (curl error: %s)", curl_easy_strerror(code)))
+ (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);
: FileTransferError(err, response,
fmt("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 /* If this is a transient error, then maybe retry the
download after a while. If we're writing to a download after a while. If we're writing to a
@ -689,7 +686,7 @@ struct curlFileTransfer : public FileTransfer
auto s3Res = s3Helper.getObject(bucketName, key); auto s3Res = s3Helper.getObject(bucketName, key);
FileTransferResult res; FileTransferResult res;
if (!s3Res.data) 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; res.data = s3Res.data;
callback(std::move(res)); callback(std::move(res));
#else #else