forked from lix-project/lix
Merge pull request #4467 from edolstra/error-formatting
Improve error formatting
This commit is contained in:
commit
488a826842
|
@ -176,13 +176,14 @@ static int main_build_remote(int argc, char * * argv)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// build the hint template.
|
// build the hint template.
|
||||||
string hintstring = "derivation: %s\nrequired (system, features): (%s, %s)";
|
string errorText =
|
||||||
hintstring += "\n%s available machines:";
|
"Failed to find a machine for remote build!\n"
|
||||||
hintstring += "\n(systems, maxjobs, supportedFeatures, mandatoryFeatures)";
|
"derivation: %s\nrequired (system, features): (%s, %s)";
|
||||||
|
errorText += "\n%s available machines:";
|
||||||
|
errorText += "\n(systems, maxjobs, supportedFeatures, mandatoryFeatures)";
|
||||||
|
|
||||||
for (unsigned int i = 0; i < machines.size(); ++i) {
|
for (unsigned int i = 0; i < machines.size(); ++i)
|
||||||
hintstring += "\n(%s, %s, %s, %s)";
|
errorText += "\n(%s, %s, %s, %s)";
|
||||||
}
|
|
||||||
|
|
||||||
// add the template values.
|
// add the template values.
|
||||||
string drvstr;
|
string drvstr;
|
||||||
|
@ -191,25 +192,21 @@ static int main_build_remote(int argc, char * * argv)
|
||||||
else
|
else
|
||||||
drvstr = "<unknown>";
|
drvstr = "<unknown>";
|
||||||
|
|
||||||
auto hint = hintformat(hintstring);
|
auto error = hintformat(errorText);
|
||||||
hint
|
error
|
||||||
% drvstr
|
% drvstr
|
||||||
% neededSystem
|
% neededSystem
|
||||||
% concatStringsSep<StringSet>(", ", requiredFeatures)
|
% concatStringsSep<StringSet>(", ", requiredFeatures)
|
||||||
% machines.size();
|
% machines.size();
|
||||||
|
|
||||||
for (auto & m : machines) {
|
for (auto & m : machines)
|
||||||
hint % concatStringsSep<vector<string>>(", ", m.systemTypes)
|
error
|
||||||
% m.maxJobs
|
% concatStringsSep<vector<string>>(", ", m.systemTypes)
|
||||||
% concatStringsSep<StringSet>(", ", m.supportedFeatures)
|
% m.maxJobs
|
||||||
% concatStringsSep<StringSet>(", ", m.mandatoryFeatures);
|
% concatStringsSep<StringSet>(", ", m.supportedFeatures)
|
||||||
}
|
% concatStringsSep<StringSet>(", ", m.mandatoryFeatures);
|
||||||
|
|
||||||
logErrorInfo(canBuildLocally ? lvlChatty : lvlWarn, {
|
printMsg(canBuildLocally ? lvlChatty : lvlWarn, error);
|
||||||
.name = "Remote build",
|
|
||||||
.description = "Failed to find a machine for remote build!",
|
|
||||||
.hint = hint
|
|
||||||
});
|
|
||||||
|
|
||||||
std::cerr << "# decline\n";
|
std::cerr << "# decline\n";
|
||||||
}
|
}
|
||||||
|
@ -234,12 +231,9 @@ static int main_build_remote(int argc, char * * argv)
|
||||||
|
|
||||||
} catch (std::exception & e) {
|
} catch (std::exception & e) {
|
||||||
auto msg = chomp(drainFD(5, false));
|
auto msg = chomp(drainFD(5, false));
|
||||||
logError({
|
printError("cannot build on '%s': %s%s",
|
||||||
.name = "Remote build",
|
bestMachine->storeUri, e.what(),
|
||||||
.hint = hintfmt("cannot build on '%s': %s%s",
|
msg.empty() ? "" : ": " + msg);
|
||||||
bestMachine->storeUri, e.what(),
|
|
||||||
(msg.empty() ? "" : ": " + msg))
|
|
||||||
});
|
|
||||||
bestMachine->enabled = false;
|
bestMachine->enabled = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,7 +77,7 @@ public:
|
||||||
auto a = get(name);
|
auto a = get(name);
|
||||||
if (!a)
|
if (!a)
|
||||||
throw Error({
|
throw Error({
|
||||||
.hint = hintfmt("attribute '%s' missing", name),
|
.msg = hintfmt("attribute '%s' missing", name),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ namespace nix {
|
||||||
LocalNoInlineNoReturn(void throwEvalError(const Pos & pos, const char * s))
|
LocalNoInlineNoReturn(void throwEvalError(const Pos & pos, const char * s))
|
||||||
{
|
{
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt(s),
|
.msg = hintfmt(s),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ LocalNoInlineNoReturn(void throwTypeError(const char * s, const Value & v))
|
||||||
LocalNoInlineNoReturn(void throwTypeError(const Pos & pos, const char * s, const Value & v))
|
LocalNoInlineNoReturn(void throwTypeError(const Pos & pos, const char * s, const Value & v))
|
||||||
{
|
{
|
||||||
throw TypeError({
|
throw TypeError({
|
||||||
.hint = hintfmt(s, showType(v)),
|
.msg = hintfmt(s, showType(v)),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -622,7 +622,7 @@ LocalNoInlineNoReturn(void throwEvalError(const char * s, const string & s2))
|
||||||
LocalNoInlineNoReturn(void throwEvalError(const Pos & pos, const char * s, const string & s2))
|
LocalNoInlineNoReturn(void throwEvalError(const Pos & pos, const char * s, const string & s2))
|
||||||
{
|
{
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt(s, s2),
|
.msg = hintfmt(s, s2),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -635,7 +635,7 @@ LocalNoInlineNoReturn(void throwEvalError(const char * s, const string & s2, con
|
||||||
LocalNoInlineNoReturn(void throwEvalError(const Pos & pos, const char * s, const string & s2, const string & s3))
|
LocalNoInlineNoReturn(void throwEvalError(const Pos & pos, const char * s, const string & s2, const string & s3))
|
||||||
{
|
{
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt(s, s2, s3),
|
.msg = hintfmt(s, s2, s3),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -644,7 +644,7 @@ LocalNoInlineNoReturn(void throwEvalError(const Pos & p1, const char * s, const
|
||||||
{
|
{
|
||||||
// p1 is where the error occurred; p2 is a position mentioned in the message.
|
// p1 is where the error occurred; p2 is a position mentioned in the message.
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt(s, sym, p2),
|
.msg = hintfmt(s, sym, p2),
|
||||||
.errPos = p1
|
.errPos = p1
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -652,7 +652,7 @@ LocalNoInlineNoReturn(void throwEvalError(const Pos & p1, const char * s, const
|
||||||
LocalNoInlineNoReturn(void throwTypeError(const Pos & pos, const char * s))
|
LocalNoInlineNoReturn(void throwTypeError(const Pos & pos, const char * s))
|
||||||
{
|
{
|
||||||
throw TypeError({
|
throw TypeError({
|
||||||
.hint = hintfmt(s),
|
.msg = hintfmt(s),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -660,7 +660,7 @@ LocalNoInlineNoReturn(void throwTypeError(const Pos & pos, const char * s))
|
||||||
LocalNoInlineNoReturn(void throwTypeError(const Pos & pos, const char * s, const ExprLambda & fun, const Symbol & s2))
|
LocalNoInlineNoReturn(void throwTypeError(const Pos & pos, const char * s, const ExprLambda & fun, const Symbol & s2))
|
||||||
{
|
{
|
||||||
throw TypeError({
|
throw TypeError({
|
||||||
.hint = hintfmt(s, fun.showNamePos(), s2),
|
.msg = hintfmt(s, fun.showNamePos(), s2),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -668,7 +668,7 @@ LocalNoInlineNoReturn(void throwTypeError(const Pos & pos, const char * s, const
|
||||||
LocalNoInlineNoReturn(void throwAssertionError(const Pos & pos, const char * s, const string & s1))
|
LocalNoInlineNoReturn(void throwAssertionError(const Pos & pos, const char * s, const string & s1))
|
||||||
{
|
{
|
||||||
throw AssertionError({
|
throw AssertionError({
|
||||||
.hint = hintfmt(s, s1),
|
.msg = hintfmt(s, s1),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -676,7 +676,7 @@ LocalNoInlineNoReturn(void throwAssertionError(const Pos & pos, const char * s,
|
||||||
LocalNoInlineNoReturn(void throwUndefinedVarError(const Pos & pos, const char * s, const string & s1))
|
LocalNoInlineNoReturn(void throwUndefinedVarError(const Pos & pos, const char * s, const string & s1))
|
||||||
{
|
{
|
||||||
throw UndefinedVarError({
|
throw UndefinedVarError({
|
||||||
.hint = hintfmt(s, s1),
|
.msg = hintfmt(s, s1),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -684,7 +684,7 @@ LocalNoInlineNoReturn(void throwUndefinedVarError(const Pos & pos, const char *
|
||||||
LocalNoInlineNoReturn(void throwMissingArgumentError(const Pos & pos, const char * s, const string & s1))
|
LocalNoInlineNoReturn(void throwMissingArgumentError(const Pos & pos, const char * s, const string & s1))
|
||||||
{
|
{
|
||||||
throw MissingArgumentError({
|
throw MissingArgumentError({
|
||||||
.hint = hintfmt(s, s1),
|
.msg = hintfmt(s, s1),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -2057,7 +2057,7 @@ void EvalState::printStats()
|
||||||
string ExternalValueBase::coerceToString(const Pos & pos, PathSet & context, bool copyMore, bool copyToStore) const
|
string ExternalValueBase::coerceToString(const Pos & pos, PathSet & context, bool copyMore, bool copyToStore) const
|
||||||
{
|
{
|
||||||
throw TypeError({
|
throw TypeError({
|
||||||
.hint = hintfmt("cannot coerce %1% to a string", showType()),
|
.msg = hintfmt("cannot coerce %1% to a string", showType()),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -284,7 +284,7 @@ void ExprVar::bindVars(const StaticEnv & env)
|
||||||
"undefined variable" error now. */
|
"undefined variable" error now. */
|
||||||
if (withLevel == -1)
|
if (withLevel == -1)
|
||||||
throw UndefinedVarError({
|
throw UndefinedVarError({
|
||||||
.hint = hintfmt("undefined variable '%1%'", name),
|
.msg = hintfmt("undefined variable '%1%'", name),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
fromWith = true;
|
fromWith = true;
|
||||||
|
|
|
@ -239,7 +239,7 @@ struct ExprLambda : Expr
|
||||||
{
|
{
|
||||||
if (!arg.empty() && formals && formals->argNames.find(arg) != formals->argNames.end())
|
if (!arg.empty() && formals && formals->argNames.find(arg) != formals->argNames.end())
|
||||||
throw ParseError({
|
throw ParseError({
|
||||||
.hint = hintfmt("duplicate formal function argument '%1%'", arg),
|
.msg = hintfmt("duplicate formal function argument '%1%'", arg),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -32,7 +32,7 @@ namespace nix {
|
||||||
Path basePath;
|
Path basePath;
|
||||||
Symbol file;
|
Symbol file;
|
||||||
FileOrigin origin;
|
FileOrigin origin;
|
||||||
ErrorInfo error;
|
std::optional<ErrorInfo> error;
|
||||||
Symbol sLetBody;
|
Symbol sLetBody;
|
||||||
ParseData(EvalState & state)
|
ParseData(EvalState & state)
|
||||||
: state(state)
|
: state(state)
|
||||||
|
@ -66,8 +66,8 @@ namespace nix {
|
||||||
static void dupAttr(const AttrPath & attrPath, const Pos & pos, const Pos & prevPos)
|
static void dupAttr(const AttrPath & attrPath, const Pos & pos, const Pos & prevPos)
|
||||||
{
|
{
|
||||||
throw ParseError({
|
throw ParseError({
|
||||||
.hint = hintfmt("attribute '%1%' already defined at %2%",
|
.msg = hintfmt("attribute '%1%' already defined at %2%",
|
||||||
showAttrPath(attrPath), prevPos),
|
showAttrPath(attrPath), prevPos),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ static void dupAttr(const AttrPath & attrPath, const Pos & pos, const Pos & prev
|
||||||
static void dupAttr(Symbol attr, const Pos & pos, const Pos & prevPos)
|
static void dupAttr(Symbol attr, const Pos & pos, const Pos & prevPos)
|
||||||
{
|
{
|
||||||
throw ParseError({
|
throw ParseError({
|
||||||
.hint = hintfmt("attribute '%1%' already defined at %2%", attr, prevPos),
|
.msg = hintfmt("attribute '%1%' already defined at %2%", attr, prevPos),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -146,7 +146,7 @@ static void addFormal(const Pos & pos, Formals * formals, const Formal & formal)
|
||||||
{
|
{
|
||||||
if (!formals->argNames.insert(formal.name).second)
|
if (!formals->argNames.insert(formal.name).second)
|
||||||
throw ParseError({
|
throw ParseError({
|
||||||
.hint = hintfmt("duplicate formal function argument '%1%'",
|
.msg = hintfmt("duplicate formal function argument '%1%'",
|
||||||
formal.name),
|
formal.name),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
|
@ -258,7 +258,7 @@ static inline Pos makeCurPos(const YYLTYPE & loc, ParseData * data)
|
||||||
void yyerror(YYLTYPE * loc, yyscan_t scanner, ParseData * data, const char * error)
|
void yyerror(YYLTYPE * loc, yyscan_t scanner, ParseData * data, const char * error)
|
||||||
{
|
{
|
||||||
data->error = {
|
data->error = {
|
||||||
.hint = hintfmt(error),
|
.msg = hintfmt(error),
|
||||||
.errPos = makeCurPos(*loc, data)
|
.errPos = makeCurPos(*loc, data)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -338,7 +338,7 @@ expr_function
|
||||||
| LET binds IN expr_function
|
| LET binds IN expr_function
|
||||||
{ if (!$2->dynamicAttrs.empty())
|
{ if (!$2->dynamicAttrs.empty())
|
||||||
throw ParseError({
|
throw ParseError({
|
||||||
.hint = hintfmt("dynamic attributes not allowed in let"),
|
.msg = hintfmt("dynamic attributes not allowed in let"),
|
||||||
.errPos = CUR_POS
|
.errPos = CUR_POS
|
||||||
});
|
});
|
||||||
$$ = new ExprLet($2, $4);
|
$$ = new ExprLet($2, $4);
|
||||||
|
@ -418,7 +418,7 @@ expr_simple
|
||||||
static bool noURLLiterals = settings.isExperimentalFeatureEnabled("no-url-literals");
|
static bool noURLLiterals = settings.isExperimentalFeatureEnabled("no-url-literals");
|
||||||
if (noURLLiterals)
|
if (noURLLiterals)
|
||||||
throw ParseError({
|
throw ParseError({
|
||||||
.hint = hintfmt("URL literals are disabled"),
|
.msg = hintfmt("URL literals are disabled"),
|
||||||
.errPos = CUR_POS
|
.errPos = CUR_POS
|
||||||
});
|
});
|
||||||
$$ = new ExprString(data->symbols.create($1));
|
$$ = new ExprString(data->symbols.create($1));
|
||||||
|
@ -491,7 +491,7 @@ attrs
|
||||||
delete str;
|
delete str;
|
||||||
} else
|
} else
|
||||||
throw ParseError({
|
throw ParseError({
|
||||||
.hint = hintfmt("dynamic attributes not allowed in inherit"),
|
.msg = hintfmt("dynamic attributes not allowed in inherit"),
|
||||||
.errPos = makeCurPos(@2, data)
|
.errPos = makeCurPos(@2, data)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -576,7 +576,7 @@ Expr * EvalState::parse(const char * text, FileOrigin origin,
|
||||||
ParseData data(*this);
|
ParseData data(*this);
|
||||||
data.origin = origin;
|
data.origin = origin;
|
||||||
switch (origin) {
|
switch (origin) {
|
||||||
case foFile:
|
case foFile:
|
||||||
data.file = data.symbols.create(path);
|
data.file = data.symbols.create(path);
|
||||||
break;
|
break;
|
||||||
case foStdin:
|
case foStdin:
|
||||||
|
@ -593,7 +593,7 @@ Expr * EvalState::parse(const char * text, FileOrigin origin,
|
||||||
int res = yyparse(scanner, &data);
|
int res = yyparse(scanner, &data);
|
||||||
yylex_destroy(scanner);
|
yylex_destroy(scanner);
|
||||||
|
|
||||||
if (res) throw ParseError(data.error);
|
if (res) throw ParseError(data.error.value());
|
||||||
|
|
||||||
data.result->bindVars(staticEnv);
|
data.result->bindVars(staticEnv);
|
||||||
|
|
||||||
|
@ -703,7 +703,7 @@ Path EvalState::findFile(SearchPath & searchPath, const string & path, const Pos
|
||||||
return corepkgsPrefix + path.substr(4);
|
return corepkgsPrefix + path.substr(4);
|
||||||
|
|
||||||
throw ThrownError({
|
throw ThrownError({
|
||||||
.hint = hintfmt(evalSettings.pureEval
|
.msg = hintfmt(evalSettings.pureEval
|
||||||
? "cannot look up '<%s>' in pure evaluation mode (use '--impure' to override)"
|
? "cannot look up '<%s>' in pure evaluation mode (use '--impure' to override)"
|
||||||
: "file '%s' was not found in the Nix search path (add it using $NIX_PATH or -I)",
|
: "file '%s' was not found in the Nix search path (add it using $NIX_PATH or -I)",
|
||||||
path),
|
path),
|
||||||
|
@ -725,8 +725,7 @@ std::pair<bool, std::string> EvalState::resolveSearchPathElem(const SearchPathEl
|
||||||
store, resolveUri(elem.second), "source", false).first.storePath) };
|
store, resolveUri(elem.second), "source", false).first.storePath) };
|
||||||
} catch (FileTransferError & e) {
|
} catch (FileTransferError & e) {
|
||||||
logWarning({
|
logWarning({
|
||||||
.name = "Entry download",
|
.msg = hintfmt("Nix search path entry '%1%' cannot be downloaded, ignoring", elem.second)
|
||||||
.hint = hintfmt("Nix search path entry '%1%' cannot be downloaded, ignoring", elem.second)
|
|
||||||
});
|
});
|
||||||
res = { false, "" };
|
res = { false, "" };
|
||||||
}
|
}
|
||||||
|
@ -736,8 +735,7 @@ std::pair<bool, std::string> EvalState::resolveSearchPathElem(const SearchPathEl
|
||||||
res = { true, path };
|
res = { true, path };
|
||||||
else {
|
else {
|
||||||
logWarning({
|
logWarning({
|
||||||
.name = "Entry not found",
|
.msg = hintfmt("warning: Nix search path entry '%1%' does not exist, ignoring", elem.second)
|
||||||
.hint = hintfmt("warning: Nix search path entry '%1%' does not exist, ignoring", elem.second)
|
|
||||||
});
|
});
|
||||||
res = { false, "" };
|
res = { false, "" };
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,7 +115,7 @@ static void import(EvalState & state, const Pos & pos, Value & vPath, Value * vS
|
||||||
state.realiseContext(context);
|
state.realiseContext(context);
|
||||||
} catch (InvalidPathError & e) {
|
} catch (InvalidPathError & e) {
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("cannot import '%1%', since path '%2%' is not valid", path, e.path),
|
.msg = hintfmt("cannot import '%1%', since path '%2%' is not valid", path, e.path),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -282,7 +282,7 @@ void prim_importNative(EvalState & state, const Pos & pos, Value * * args, Value
|
||||||
state.realiseContext(context);
|
state.realiseContext(context);
|
||||||
} catch (InvalidPathError & e) {
|
} catch (InvalidPathError & e) {
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt(
|
.msg = hintfmt(
|
||||||
"cannot import '%1%', since path '%2%' is not valid",
|
"cannot import '%1%', since path '%2%' is not valid",
|
||||||
path, e.path),
|
path, e.path),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
|
@ -322,7 +322,7 @@ void prim_exec(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
auto count = args[0]->listSize();
|
auto count = args[0]->listSize();
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("at least one argument to 'exec' required"),
|
.msg = hintfmt("at least one argument to 'exec' required"),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -336,7 +336,7 @@ void prim_exec(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
state.realiseContext(context);
|
state.realiseContext(context);
|
||||||
} catch (InvalidPathError & e) {
|
} catch (InvalidPathError & e) {
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("cannot execute '%1%', since path '%2%' is not valid",
|
.msg = hintfmt("cannot execute '%1%', since path '%2%' is not valid",
|
||||||
program, e.path),
|
program, e.path),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
|
@ -551,7 +551,7 @@ static void prim_genericClosure(EvalState & state, const Pos & pos, Value * * ar
|
||||||
args[0]->attrs->find(state.symbols.create("startSet"));
|
args[0]->attrs->find(state.symbols.create("startSet"));
|
||||||
if (startSet == args[0]->attrs->end())
|
if (startSet == args[0]->attrs->end())
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("attribute 'startSet' required"),
|
.msg = hintfmt("attribute 'startSet' required"),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
state.forceList(*startSet->value, pos);
|
state.forceList(*startSet->value, pos);
|
||||||
|
@ -565,7 +565,7 @@ static void prim_genericClosure(EvalState & state, const Pos & pos, Value * * ar
|
||||||
args[0]->attrs->find(state.symbols.create("operator"));
|
args[0]->attrs->find(state.symbols.create("operator"));
|
||||||
if (op == args[0]->attrs->end())
|
if (op == args[0]->attrs->end())
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("attribute 'operator' required"),
|
.msg = hintfmt("attribute 'operator' required"),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
state.forceValue(*op->value, pos);
|
state.forceValue(*op->value, pos);
|
||||||
|
@ -587,7 +587,7 @@ static void prim_genericClosure(EvalState & state, const Pos & pos, Value * * ar
|
||||||
e->attrs->find(state.symbols.create("key"));
|
e->attrs->find(state.symbols.create("key"));
|
||||||
if (key == e->attrs->end())
|
if (key == e->attrs->end())
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("attribute 'key' required"),
|
.msg = hintfmt("attribute 'key' required"),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
state.forceValue(*key->value, pos);
|
state.forceValue(*key->value, pos);
|
||||||
|
@ -810,7 +810,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
|
||||||
Bindings::iterator attr = args[0]->attrs->find(state.sName);
|
Bindings::iterator attr = args[0]->attrs->find(state.sName);
|
||||||
if (attr == args[0]->attrs->end())
|
if (attr == args[0]->attrs->end())
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("required attribute 'name' missing"),
|
.msg = hintfmt("required attribute 'name' missing"),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
string drvName;
|
string drvName;
|
||||||
|
@ -859,7 +859,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
|
||||||
else if (s == "flat") ingestionMethod = FileIngestionMethod::Flat;
|
else if (s == "flat") ingestionMethod = FileIngestionMethod::Flat;
|
||||||
else
|
else
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("invalid value '%s' for 'outputHashMode' attribute", s),
|
.msg = hintfmt("invalid value '%s' for 'outputHashMode' attribute", s),
|
||||||
.errPos = posDrvName
|
.errPos = posDrvName
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -869,7 +869,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
|
||||||
for (auto & j : ss) {
|
for (auto & j : ss) {
|
||||||
if (outputs.find(j) != outputs.end())
|
if (outputs.find(j) != outputs.end())
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("duplicate derivation output '%1%'", j),
|
.msg = hintfmt("duplicate derivation output '%1%'", j),
|
||||||
.errPos = posDrvName
|
.errPos = posDrvName
|
||||||
});
|
});
|
||||||
/* !!! Check whether j is a valid attribute
|
/* !!! Check whether j is a valid attribute
|
||||||
|
@ -879,14 +879,14 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
|
||||||
the resulting set. */
|
the resulting set. */
|
||||||
if (j == "drv")
|
if (j == "drv")
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("invalid derivation output name 'drv'" ),
|
.msg = hintfmt("invalid derivation output name 'drv'" ),
|
||||||
.errPos = posDrvName
|
.errPos = posDrvName
|
||||||
});
|
});
|
||||||
outputs.insert(j);
|
outputs.insert(j);
|
||||||
}
|
}
|
||||||
if (outputs.empty())
|
if (outputs.empty())
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("derivation cannot have an empty set of outputs"),
|
.msg = hintfmt("derivation cannot have an empty set of outputs"),
|
||||||
.errPos = posDrvName
|
.errPos = posDrvName
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -1007,20 +1007,20 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
|
||||||
/* Do we have all required attributes? */
|
/* Do we have all required attributes? */
|
||||||
if (drv.builder == "")
|
if (drv.builder == "")
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("required attribute 'builder' missing"),
|
.msg = hintfmt("required attribute 'builder' missing"),
|
||||||
.errPos = posDrvName
|
.errPos = posDrvName
|
||||||
});
|
});
|
||||||
|
|
||||||
if (drv.platform == "")
|
if (drv.platform == "")
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("required attribute 'system' missing"),
|
.msg = hintfmt("required attribute 'system' missing"),
|
||||||
.errPos = posDrvName
|
.errPos = posDrvName
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Check whether the derivation name is valid. */
|
/* Check whether the derivation name is valid. */
|
||||||
if (isDerivation(drvName))
|
if (isDerivation(drvName))
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("derivation names are not allowed to end in '%s'", drvExtension),
|
.msg = hintfmt("derivation names are not allowed to end in '%s'", drvExtension),
|
||||||
.errPos = posDrvName
|
.errPos = posDrvName
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1031,7 +1031,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
|
||||||
already content addressed. */
|
already content addressed. */
|
||||||
if (outputs.size() != 1 || *(outputs.begin()) != "out")
|
if (outputs.size() != 1 || *(outputs.begin()) != "out")
|
||||||
throw Error({
|
throw Error({
|
||||||
.hint = hintfmt("multiple outputs are not supported in fixed-output derivations"),
|
.msg = hintfmt("multiple outputs are not supported in fixed-output derivations"),
|
||||||
.errPos = posDrvName
|
.errPos = posDrvName
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1211,7 +1211,7 @@ static void prim_storePath(EvalState & state, const Pos & pos, Value * * args, V
|
||||||
if (!state.store->isStorePath(path)) path = canonPath(path, true);
|
if (!state.store->isStorePath(path)) path = canonPath(path, true);
|
||||||
if (!state.store->isInStore(path))
|
if (!state.store->isInStore(path))
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("path '%1%' is not in the Nix store", path),
|
.msg = hintfmt("path '%1%' is not in the Nix store", path),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
auto path2 = state.store->toStorePath(path).first;
|
auto path2 = state.store->toStorePath(path).first;
|
||||||
|
@ -1247,7 +1247,7 @@ static void prim_pathExists(EvalState & state, const Pos & pos, Value * * args,
|
||||||
state.realiseContext(context);
|
state.realiseContext(context);
|
||||||
} catch (InvalidPathError & e) {
|
} catch (InvalidPathError & e) {
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt(
|
.msg = hintfmt(
|
||||||
"cannot check the existence of '%1%', since path '%2%' is not valid",
|
"cannot check the existence of '%1%', since path '%2%' is not valid",
|
||||||
path, e.path),
|
path, e.path),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
|
@ -1324,7 +1324,7 @@ static void prim_readFile(EvalState & state, const Pos & pos, Value * * args, Va
|
||||||
state.realiseContext(context);
|
state.realiseContext(context);
|
||||||
} catch (InvalidPathError & e) {
|
} catch (InvalidPathError & e) {
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("cannot read '%1%', since path '%2%' is not valid", path, e.path),
|
.msg = hintfmt("cannot read '%1%', since path '%2%' is not valid", path, e.path),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1363,7 +1363,7 @@ static void prim_findFile(EvalState & state, const Pos & pos, Value * * args, Va
|
||||||
i = v2.attrs->find(state.symbols.create("path"));
|
i = v2.attrs->find(state.symbols.create("path"));
|
||||||
if (i == v2.attrs->end())
|
if (i == v2.attrs->end())
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("attribute 'path' missing"),
|
.msg = hintfmt("attribute 'path' missing"),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1374,7 +1374,7 @@ static void prim_findFile(EvalState & state, const Pos & pos, Value * * args, Va
|
||||||
state.realiseContext(context);
|
state.realiseContext(context);
|
||||||
} catch (InvalidPathError & e) {
|
} catch (InvalidPathError & e) {
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("cannot find '%1%', since path '%2%' is not valid", path, e.path),
|
.msg = hintfmt("cannot find '%1%', since path '%2%' is not valid", path, e.path),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1400,7 +1400,7 @@ static void prim_hashFile(EvalState & state, const Pos & pos, Value * * args, Va
|
||||||
std::optional<HashType> ht = parseHashType(type);
|
std::optional<HashType> ht = parseHashType(type);
|
||||||
if (!ht)
|
if (!ht)
|
||||||
throw Error({
|
throw Error({
|
||||||
.hint = hintfmt("unknown hash type '%1%'", type),
|
.msg = hintfmt("unknown hash type '%1%'", type),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1430,7 +1430,7 @@ static void prim_readDir(EvalState & state, const Pos & pos, Value * * args, Val
|
||||||
state.realiseContext(ctx);
|
state.realiseContext(ctx);
|
||||||
} catch (InvalidPathError & e) {
|
} catch (InvalidPathError & e) {
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("cannot read '%1%', since path '%2%' is not valid", path, e.path),
|
.msg = hintfmt("cannot read '%1%', since path '%2%' is not valid", path, e.path),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1650,7 +1650,7 @@ static void prim_toFile(EvalState & state, const Pos & pos, Value * * args, Valu
|
||||||
for (auto path : context) {
|
for (auto path : context) {
|
||||||
if (path.at(0) != '/')
|
if (path.at(0) != '/')
|
||||||
throw EvalError( {
|
throw EvalError( {
|
||||||
.hint = hintfmt(
|
.msg = hintfmt(
|
||||||
"in 'toFile': the file named '%1%' must not contain a reference "
|
"in 'toFile': the file named '%1%' must not contain a reference "
|
||||||
"to a derivation but contains (%2%)",
|
"to a derivation but contains (%2%)",
|
||||||
name, path),
|
name, path),
|
||||||
|
@ -1801,14 +1801,14 @@ static void prim_filterSource(EvalState & state, const Pos & pos, Value * * args
|
||||||
Path path = state.coerceToPath(pos, *args[1], context);
|
Path path = state.coerceToPath(pos, *args[1], context);
|
||||||
if (!context.empty())
|
if (!context.empty())
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("string '%1%' cannot refer to other paths", path),
|
.msg = hintfmt("string '%1%' cannot refer to other paths", path),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
|
|
||||||
state.forceValue(*args[0], pos);
|
state.forceValue(*args[0], pos);
|
||||||
if (args[0]->type() != nFunction)
|
if (args[0]->type() != nFunction)
|
||||||
throw TypeError({
|
throw TypeError({
|
||||||
.hint = hintfmt(
|
.msg = hintfmt(
|
||||||
"first argument in call to 'filterSource' is not a function but %1%",
|
"first argument in call to 'filterSource' is not a function but %1%",
|
||||||
showType(*args[0])),
|
showType(*args[0])),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
|
@ -1875,7 +1875,7 @@ static void prim_path(EvalState & state, const Pos & pos, Value * * args, Value
|
||||||
path = state.coerceToPath(*attr.pos, *attr.value, context);
|
path = state.coerceToPath(*attr.pos, *attr.value, context);
|
||||||
if (!context.empty())
|
if (!context.empty())
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("string '%1%' cannot refer to other paths", path),
|
.msg = hintfmt("string '%1%' cannot refer to other paths", path),
|
||||||
.errPos = *attr.pos
|
.errPos = *attr.pos
|
||||||
});
|
});
|
||||||
} else if (attr.name == state.sName)
|
} else if (attr.name == state.sName)
|
||||||
|
@ -1889,13 +1889,13 @@ static void prim_path(EvalState & state, const Pos & pos, Value * * args, Value
|
||||||
expectedHash = newHashAllowEmpty(state.forceStringNoCtx(*attr.value, *attr.pos), htSHA256);
|
expectedHash = newHashAllowEmpty(state.forceStringNoCtx(*attr.value, *attr.pos), htSHA256);
|
||||||
else
|
else
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("unsupported argument '%1%' to 'addPath'", attr.name),
|
.msg = hintfmt("unsupported argument '%1%' to 'addPath'", attr.name),
|
||||||
.errPos = *attr.pos
|
.errPos = *attr.pos
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (path.empty())
|
if (path.empty())
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("'path' required"),
|
.msg = hintfmt("'path' required"),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
if (name.empty())
|
if (name.empty())
|
||||||
|
@ -2010,7 +2010,7 @@ void prim_getAttr(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
Bindings::iterator i = args[1]->attrs->find(state.symbols.create(attr));
|
Bindings::iterator i = args[1]->attrs->find(state.symbols.create(attr));
|
||||||
if (i == args[1]->attrs->end())
|
if (i == args[1]->attrs->end())
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("attribute '%1%' missing", attr),
|
.msg = hintfmt("attribute '%1%' missing", attr),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
// !!! add to stack trace?
|
// !!! add to stack trace?
|
||||||
|
@ -2142,7 +2142,7 @@ static void prim_listToAttrs(EvalState & state, const Pos & pos, Value * * args,
|
||||||
Bindings::iterator j = v2.attrs->find(state.sName);
|
Bindings::iterator j = v2.attrs->find(state.sName);
|
||||||
if (j == v2.attrs->end())
|
if (j == v2.attrs->end())
|
||||||
throw TypeError({
|
throw TypeError({
|
||||||
.hint = hintfmt("'name' attribute missing in a call to 'listToAttrs'"),
|
.msg = hintfmt("'name' attribute missing in a call to 'listToAttrs'"),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
string name = state.forceStringNoCtx(*j->value, pos);
|
string name = state.forceStringNoCtx(*j->value, pos);
|
||||||
|
@ -2152,7 +2152,7 @@ static void prim_listToAttrs(EvalState & state, const Pos & pos, Value * * args,
|
||||||
Bindings::iterator j2 = v2.attrs->find(state.symbols.create(state.sValue));
|
Bindings::iterator j2 = v2.attrs->find(state.symbols.create(state.sValue));
|
||||||
if (j2 == v2.attrs->end())
|
if (j2 == v2.attrs->end())
|
||||||
throw TypeError({
|
throw TypeError({
|
||||||
.hint = hintfmt("'value' attribute missing in a call to 'listToAttrs'"),
|
.msg = hintfmt("'value' attribute missing in a call to 'listToAttrs'"),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
v.attrs->push_back(Attr(sym, j2->value, j2->pos));
|
v.attrs->push_back(Attr(sym, j2->value, j2->pos));
|
||||||
|
@ -2258,7 +2258,7 @@ static void prim_functionArgs(EvalState & state, const Pos & pos, Value * * args
|
||||||
}
|
}
|
||||||
if (!args[0]->isLambda())
|
if (!args[0]->isLambda())
|
||||||
throw TypeError({
|
throw TypeError({
|
||||||
.hint = hintfmt("'functionArgs' requires a function"),
|
.msg = hintfmt("'functionArgs' requires a function"),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2352,7 +2352,7 @@ static void elemAt(EvalState & state, const Pos & pos, Value & list, int n, Valu
|
||||||
state.forceList(list, pos);
|
state.forceList(list, pos);
|
||||||
if (n < 0 || (unsigned int) n >= list.listSize())
|
if (n < 0 || (unsigned int) n >= list.listSize())
|
||||||
throw Error({
|
throw Error({
|
||||||
.hint = hintfmt("list index %1% is out of bounds", n),
|
.msg = hintfmt("list index %1% is out of bounds", n),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
state.forceValue(*list.listElems()[n], pos);
|
state.forceValue(*list.listElems()[n], pos);
|
||||||
|
@ -2400,7 +2400,7 @@ static void prim_tail(EvalState & state, const Pos & pos, Value * * args, Value
|
||||||
state.forceList(*args[0], pos);
|
state.forceList(*args[0], pos);
|
||||||
if (args[0]->listSize() == 0)
|
if (args[0]->listSize() == 0)
|
||||||
throw Error({
|
throw Error({
|
||||||
.hint = hintfmt("'tail' called on an empty list"),
|
.msg = hintfmt("'tail' called on an empty list"),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2639,7 +2639,7 @@ static void prim_genList(EvalState & state, const Pos & pos, Value * * args, Val
|
||||||
|
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("cannot create list of size %1%", len),
|
.msg = hintfmt("cannot create list of size %1%", len),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2890,7 +2890,7 @@ static void prim_div(EvalState & state, const Pos & pos, Value * * args, Value &
|
||||||
NixFloat f2 = state.forceFloat(*args[1], pos);
|
NixFloat f2 = state.forceFloat(*args[1], pos);
|
||||||
if (f2 == 0)
|
if (f2 == 0)
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("division by zero"),
|
.msg = hintfmt("division by zero"),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2902,7 +2902,7 @@ static void prim_div(EvalState & state, const Pos & pos, Value * * args, Value &
|
||||||
/* Avoid division overflow as it might raise SIGFPE. */
|
/* Avoid division overflow as it might raise SIGFPE. */
|
||||||
if (i1 == std::numeric_limits<NixInt>::min() && i2 == -1)
|
if (i1 == std::numeric_limits<NixInt>::min() && i2 == -1)
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("overflow in integer division"),
|
.msg = hintfmt("overflow in integer division"),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -3033,7 +3033,7 @@ static void prim_substring(EvalState & state, const Pos & pos, Value * * args, V
|
||||||
|
|
||||||
if (start < 0)
|
if (start < 0)
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("negative start position in 'substring'"),
|
.msg = hintfmt("negative start position in 'substring'"),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -3084,7 +3084,7 @@ static void prim_hashString(EvalState & state, const Pos & pos, Value * * args,
|
||||||
std::optional<HashType> ht = parseHashType(type);
|
std::optional<HashType> ht = parseHashType(type);
|
||||||
if (!ht)
|
if (!ht)
|
||||||
throw Error({
|
throw Error({
|
||||||
.hint = hintfmt("unknown hash type '%1%'", type),
|
.msg = hintfmt("unknown hash type '%1%'", type),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -3148,12 +3148,12 @@ void prim_match(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
if (e.code() == std::regex_constants::error_space) {
|
if (e.code() == std::regex_constants::error_space) {
|
||||||
// limit is _GLIBCXX_REGEX_STATE_LIMIT for libstdc++
|
// limit is _GLIBCXX_REGEX_STATE_LIMIT for libstdc++
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("memory limit exceeded by regular expression '%s'", re),
|
.msg = hintfmt("memory limit exceeded by regular expression '%s'", re),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("invalid regular expression '%s'", re),
|
.msg = hintfmt("invalid regular expression '%s'", re),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -3256,12 +3256,12 @@ static void prim_split(EvalState & state, const Pos & pos, Value * * args, Value
|
||||||
if (e.code() == std::regex_constants::error_space) {
|
if (e.code() == std::regex_constants::error_space) {
|
||||||
// limit is _GLIBCXX_REGEX_STATE_LIMIT for libstdc++
|
// limit is _GLIBCXX_REGEX_STATE_LIMIT for libstdc++
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("memory limit exceeded by regular expression '%s'", re),
|
.msg = hintfmt("memory limit exceeded by regular expression '%s'", re),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("invalid regular expression '%s'", re),
|
.msg = hintfmt("invalid regular expression '%s'", re),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -3341,7 +3341,7 @@ static void prim_replaceStrings(EvalState & state, const Pos & pos, Value * * ar
|
||||||
state.forceList(*args[1], pos);
|
state.forceList(*args[1], pos);
|
||||||
if (args[0]->listSize() != args[1]->listSize())
|
if (args[0]->listSize() != args[1]->listSize())
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("'from' and 'to' arguments to 'replaceStrings' have different lengths"),
|
.msg = hintfmt("'from' and 'to' arguments to 'replaceStrings' have different lengths"),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -147,7 +147,7 @@ static void prim_appendContext(EvalState & state, const Pos & pos, Value * * arg
|
||||||
for (auto & i : *args[1]->attrs) {
|
for (auto & i : *args[1]->attrs) {
|
||||||
if (!state.store->isStorePath(i.name))
|
if (!state.store->isStorePath(i.name))
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("Context key '%s' is not a store path", i.name),
|
.msg = hintfmt("Context key '%s' is not a store path", i.name),
|
||||||
.errPos = *i.pos
|
.errPos = *i.pos
|
||||||
});
|
});
|
||||||
if (!settings.readOnlyMode)
|
if (!settings.readOnlyMode)
|
||||||
|
@ -164,7 +164,7 @@ static void prim_appendContext(EvalState & state, const Pos & pos, Value * * arg
|
||||||
if (state.forceBool(*iter->value, *iter->pos)) {
|
if (state.forceBool(*iter->value, *iter->pos)) {
|
||||||
if (!isDerivation(i.name)) {
|
if (!isDerivation(i.name)) {
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("Tried to add all-outputs context of %s, which is not a derivation, to a string", i.name),
|
.msg = hintfmt("Tried to add all-outputs context of %s, which is not a derivation, to a string", i.name),
|
||||||
.errPos = *i.pos
|
.errPos = *i.pos
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -177,7 +177,7 @@ static void prim_appendContext(EvalState & state, const Pos & pos, Value * * arg
|
||||||
state.forceList(*iter->value, *iter->pos);
|
state.forceList(*iter->value, *iter->pos);
|
||||||
if (iter->value->listSize() && !isDerivation(i.name)) {
|
if (iter->value->listSize() && !isDerivation(i.name)) {
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("Tried to add derivation output context of %s, which is not a derivation, to a string", i.name),
|
.msg = hintfmt("Tried to add derivation output context of %s, which is not a derivation, to a string", i.name),
|
||||||
.errPos = *i.pos
|
.errPos = *i.pos
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,14 +38,14 @@ static void prim_fetchMercurial(EvalState & state, const Pos & pos, Value * * ar
|
||||||
name = state.forceStringNoCtx(*attr.value, *attr.pos);
|
name = state.forceStringNoCtx(*attr.value, *attr.pos);
|
||||||
else
|
else
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("unsupported argument '%s' to 'fetchMercurial'", attr.name),
|
.msg = hintfmt("unsupported argument '%s' to 'fetchMercurial'", attr.name),
|
||||||
.errPos = *attr.pos
|
.errPos = *attr.pos
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (url.empty())
|
if (url.empty())
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("'url' argument required"),
|
.msg = hintfmt("'url' argument required"),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -115,7 +115,7 @@ static void fetchTree(
|
||||||
|
|
||||||
if (!attrs.count("type"))
|
if (!attrs.count("type"))
|
||||||
throw Error({
|
throw Error({
|
||||||
.hint = hintfmt("attribute 'type' is missing in call to 'fetchTree'"),
|
.msg = hintfmt("attribute 'type' is missing in call to 'fetchTree'"),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -177,14 +177,14 @@ static void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v,
|
||||||
name = state.forceStringNoCtx(*attr.value, *attr.pos);
|
name = state.forceStringNoCtx(*attr.value, *attr.pos);
|
||||||
else
|
else
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("unsupported argument '%s' to '%s'", attr.name, who),
|
.msg = hintfmt("unsupported argument '%s' to '%s'", attr.name, who),
|
||||||
.errPos = *attr.pos
|
.errPos = *attr.pos
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!url)
|
if (!url)
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("'url' argument required"),
|
.msg = hintfmt("'url' argument required"),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
} else
|
} else
|
||||||
|
|
|
@ -82,7 +82,7 @@ static void prim_fromTOML(EvalState & state, const Pos & pos, Value * * args, Va
|
||||||
visit(v, parser(tomlStream).parse());
|
visit(v, parser(tomlStream).parse());
|
||||||
} catch (std::runtime_error & e) {
|
} catch (std::runtime_error & e) {
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.hint = hintfmt("while parsing a TOML string: %s", e.what()),
|
.msg = hintfmt("while parsing a TOML string: %s", e.what()),
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,8 +87,8 @@ void handleDiffHook(
|
||||||
printError(chomp(diffRes.second));
|
printError(chomp(diffRes.second));
|
||||||
} catch (Error & error) {
|
} catch (Error & error) {
|
||||||
ErrorInfo ei = error.info();
|
ErrorInfo ei = error.info();
|
||||||
ei.hint = hintfmt("diff hook execution failed: %s",
|
// FIXME: wrap errors.
|
||||||
(error.info().hint.has_value() ? error.info().hint->str() : ""));
|
ei.msg = hintfmt("diff hook execution failed: %s", ei.msg.str());
|
||||||
logError(ei);
|
logError(ei);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -439,12 +439,9 @@ void DerivationGoal::repairClosure()
|
||||||
/* Check each path (slow!). */
|
/* Check each path (slow!). */
|
||||||
for (auto & i : outputClosure) {
|
for (auto & i : outputClosure) {
|
||||||
if (worker.pathContentsGood(i)) continue;
|
if (worker.pathContentsGood(i)) continue;
|
||||||
logError({
|
printError(
|
||||||
.name = "Corrupt path in closure",
|
"found corrupted or missing path '%s' in the output closure of '%s'",
|
||||||
.hint = hintfmt(
|
worker.store.printStorePath(i), worker.store.printStorePath(drvPath));
|
||||||
"found corrupted or missing path '%s' in the output closure of '%s'",
|
|
||||||
worker.store.printStorePath(i), worker.store.printStorePath(drvPath))
|
|
||||||
});
|
|
||||||
auto drvPath2 = outputsToDrv.find(i);
|
auto drvPath2 = outputsToDrv.find(i);
|
||||||
if (drvPath2 == outputsToDrv.end())
|
if (drvPath2 == outputsToDrv.end())
|
||||||
addWaitee(upcast_goal(worker.makeSubstitutionGoal(i, Repair)));
|
addWaitee(upcast_goal(worker.makeSubstitutionGoal(i, Repair)));
|
||||||
|
@ -893,9 +890,12 @@ void DerivationGoal::buildDone()
|
||||||
statusToString(status));
|
statusToString(status));
|
||||||
|
|
||||||
if (!logger->isVerbose() && !logTail.empty()) {
|
if (!logger->isVerbose() && !logTail.empty()) {
|
||||||
msg += (format("; last %d log lines:") % logTail.size()).str();
|
msg += fmt(";\nlast %d log lines:\n", logTail.size());
|
||||||
for (auto & line : logTail)
|
for (auto & line : logTail) {
|
||||||
msg += "\n " + line;
|
msg += "> ";
|
||||||
|
msg += line;
|
||||||
|
msg += "\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (diskFull)
|
if (diskFull)
|
||||||
|
@ -1071,12 +1071,9 @@ HookReply DerivationGoal::tryBuildHook()
|
||||||
|
|
||||||
} catch (SysError & e) {
|
} catch (SysError & e) {
|
||||||
if (e.errNo == EPIPE) {
|
if (e.errNo == EPIPE) {
|
||||||
logError({
|
printError(
|
||||||
.name = "Build hook died",
|
"build hook died unexpectedly: %s",
|
||||||
.hint = hintfmt(
|
chomp(drainFD(worker.hook->fromHook.readSide.get())));
|
||||||
"build hook died unexpectedly: %s",
|
|
||||||
chomp(drainFD(worker.hook->fromHook.readSide.get())))
|
|
||||||
});
|
|
||||||
worker.hook = 0;
|
worker.hook = 0;
|
||||||
return rpDecline;
|
return rpDecline;
|
||||||
} else
|
} else
|
||||||
|
@ -3088,10 +3085,7 @@ void DerivationGoal::registerOutputs()
|
||||||
auto rewriteOutput = [&]() {
|
auto rewriteOutput = [&]() {
|
||||||
/* Apply hash rewriting if necessary. */
|
/* Apply hash rewriting if necessary. */
|
||||||
if (!outputRewrites.empty()) {
|
if (!outputRewrites.empty()) {
|
||||||
logWarning({
|
warn("rewriting hashes in '%1%'; cross fingers", actualPath);
|
||||||
.name = "Rewriting hashes",
|
|
||||||
.hint = hintfmt("rewriting hashes in '%1%'; cross fingers", actualPath),
|
|
||||||
});
|
|
||||||
|
|
||||||
/* FIXME: this is in-memory. */
|
/* FIXME: this is in-memory. */
|
||||||
StringSink sink;
|
StringSink sink;
|
||||||
|
@ -3385,10 +3379,7 @@ void DerivationGoal::registerOutputs()
|
||||||
if (settings.enforceDeterminism)
|
if (settings.enforceDeterminism)
|
||||||
throw NotDeterministic(hint);
|
throw NotDeterministic(hint);
|
||||||
|
|
||||||
logError({
|
printError(hint);
|
||||||
.name = "Output determinism error",
|
|
||||||
.hint = hint
|
|
||||||
});
|
|
||||||
|
|
||||||
curRound = nrRounds; // we know enough, bail out early
|
curRound = nrRounds; // we know enough, bail out early
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,11 +144,8 @@ void SubstitutionGoal::tryNext()
|
||||||
only after we've downloaded the path. */
|
only after we've downloaded the path. */
|
||||||
if (!sub->isTrusted && worker.store.pathInfoIsTrusted(*info))
|
if (!sub->isTrusted && worker.store.pathInfoIsTrusted(*info))
|
||||||
{
|
{
|
||||||
logWarning({
|
warn("substituter '%s' does not have a valid signature for path '%s'",
|
||||||
.name = "Invalid path signature",
|
sub->getUri(), worker.store.printStorePath(storePath));
|
||||||
.hint = hintfmt("substituter '%s' does not have a valid signature for path '%s'",
|
|
||||||
sub->getUri(), worker.store.printStorePath(storePath))
|
|
||||||
});
|
|
||||||
tryNext();
|
tryNext();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -456,10 +456,7 @@ bool Worker::pathContentsGood(const StorePath & path)
|
||||||
}
|
}
|
||||||
pathContentsGoodCache.insert_or_assign(path, res);
|
pathContentsGoodCache.insert_or_assign(path, res);
|
||||||
if (!res)
|
if (!res)
|
||||||
logError({
|
printError("path '%s' is corrupted or missing!", store.printStorePath(path));
|
||||||
.name = "Corrupted path",
|
|
||||||
.hint = hintfmt("path '%s' is corrupted or missing!", store.printStorePath(path))
|
|
||||||
});
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,10 +22,7 @@ static void createLinks(State & state, const Path & srcDir, const Path & dstDir,
|
||||||
srcFiles = readDirectory(srcDir);
|
srcFiles = readDirectory(srcDir);
|
||||||
} catch (SysError & e) {
|
} catch (SysError & e) {
|
||||||
if (e.errNo == ENOTDIR) {
|
if (e.errNo == ENOTDIR) {
|
||||||
logWarning({
|
warn("not including '%s' in the user environment because it's not a directory", srcDir);
|
||||||
.name = "Create links - directory",
|
|
||||||
.hint = hintfmt("not including '%s' in the user environment because it's not a directory", srcDir)
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw;
|
throw;
|
||||||
|
@ -44,10 +41,7 @@ static void createLinks(State & state, const Path & srcDir, const Path & dstDir,
|
||||||
throw SysError("getting status of '%1%'", srcFile);
|
throw SysError("getting status of '%1%'", srcFile);
|
||||||
} catch (SysError & e) {
|
} catch (SysError & e) {
|
||||||
if (e.errNo == ENOENT || e.errNo == ENOTDIR) {
|
if (e.errNo == ENOENT || e.errNo == ENOTDIR) {
|
||||||
logWarning({
|
warn("skipping dangling symlink '%s'", dstFile);
|
||||||
.name = "Create links - skipping symlink",
|
|
||||||
.hint = hintfmt("skipping dangling symlink '%s'", dstFile)
|
|
||||||
});
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
throw;
|
throw;
|
||||||
|
|
|
@ -639,11 +639,7 @@ struct curlFileTransfer : public FileTransfer
|
||||||
workerThreadMain();
|
workerThreadMain();
|
||||||
} catch (nix::Interrupted & e) {
|
} catch (nix::Interrupted & e) {
|
||||||
} catch (std::exception & e) {
|
} catch (std::exception & e) {
|
||||||
logError({
|
printError("unexpected error in download thread: %s", e.what());
|
||||||
.name = "File transfer",
|
|
||||||
.hint = hintfmt("unexpected error in download thread: %s",
|
|
||||||
e.what())
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -859,11 +855,10 @@ FileTransferError::FileTransferError(FileTransfer::Error error, std::shared_ptr<
|
||||||
// FIXME: Due to https://github.com/NixOS/nix/issues/3841 we don't know how
|
// FIXME: Due to https://github.com/NixOS/nix/issues/3841 we don't know how
|
||||||
// to print different messages for different verbosity levels. For now
|
// to print different messages for different verbosity levels. For now
|
||||||
// we add some heuristics for detecting when we want to show the response.
|
// we add some heuristics for detecting when we want to show the response.
|
||||||
if (response && (response->size() < 1024 || response->find("<html>") != string::npos)) {
|
if (response && (response->size() < 1024 || response->find("<html>") != string::npos))
|
||||||
err.hint = hintfmt("%1%\n\nresponse body:\n\n%2%", normaltxt(hf.str()), *response);
|
err.msg = hintfmt("%1%\n\nresponse body:\n\n%2%", normaltxt(hf.str()), *response);
|
||||||
} else {
|
else
|
||||||
err.hint = hf;
|
err.msg = hf;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isUri(const string & s)
|
bool isUri(const string & s)
|
||||||
|
|
|
@ -150,12 +150,7 @@ LocalStore::LocalStore(const Params & params)
|
||||||
|
|
||||||
struct group * gr = getgrnam(settings.buildUsersGroup.get().c_str());
|
struct group * gr = getgrnam(settings.buildUsersGroup.get().c_str());
|
||||||
if (!gr)
|
if (!gr)
|
||||||
logError({
|
printError("warning: the group '%1%' specified in 'build-users-group' does not exist", settings.buildUsersGroup);
|
||||||
.name = "'build-users-group' not found",
|
|
||||||
.hint = hintfmt(
|
|
||||||
"warning: the group '%1%' specified in 'build-users-group' does not exist",
|
|
||||||
settings.buildUsersGroup)
|
|
||||||
});
|
|
||||||
else {
|
else {
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (stat(realStoreDir.c_str(), &st))
|
if (stat(realStoreDir.c_str(), &st))
|
||||||
|
@ -1406,12 +1401,8 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair)
|
||||||
Path linkPath = linksDir + "/" + link.name;
|
Path linkPath = linksDir + "/" + link.name;
|
||||||
string hash = hashPath(htSHA256, linkPath).first.to_string(Base32, false);
|
string hash = hashPath(htSHA256, linkPath).first.to_string(Base32, false);
|
||||||
if (hash != link.name) {
|
if (hash != link.name) {
|
||||||
logError({
|
printError("link '%s' was modified! expected hash '%s', got '%s'",
|
||||||
.name = "Invalid hash",
|
linkPath, link.name, hash);
|
||||||
.hint = hintfmt(
|
|
||||||
"link '%s' was modified! expected hash '%s', got '%s'",
|
|
||||||
linkPath, link.name, hash)
|
|
||||||
});
|
|
||||||
if (repair) {
|
if (repair) {
|
||||||
if (unlink(linkPath.c_str()) == 0)
|
if (unlink(linkPath.c_str()) == 0)
|
||||||
printInfo("removed link '%s'", linkPath);
|
printInfo("removed link '%s'", linkPath);
|
||||||
|
@ -1444,11 +1435,8 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair)
|
||||||
auto current = hashSink->finish();
|
auto current = hashSink->finish();
|
||||||
|
|
||||||
if (info->narHash != nullHash && info->narHash != current.first) {
|
if (info->narHash != nullHash && info->narHash != current.first) {
|
||||||
logError({
|
printError("path '%s' was modified! expected hash '%s', got '%s'",
|
||||||
.name = "Invalid hash - path modified",
|
printStorePath(i), info->narHash.to_string(Base32, true), current.first.to_string(Base32, true));
|
||||||
.hint = hintfmt("path '%s' was modified! expected hash '%s', got '%s'",
|
|
||||||
printStorePath(i), info->narHash.to_string(Base32, true), current.first.to_string(Base32, true))
|
|
||||||
});
|
|
||||||
if (repair) repairPath(i); else errors = true;
|
if (repair) repairPath(i); else errors = true;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
@ -1499,10 +1487,7 @@ void LocalStore::verifyPath(const Path & pathS, const StringSet & store,
|
||||||
if (!done.insert(pathS).second) return;
|
if (!done.insert(pathS).second) return;
|
||||||
|
|
||||||
if (!isStorePath(pathS)) {
|
if (!isStorePath(pathS)) {
|
||||||
logError({
|
printError("path '%s' is not in the Nix store", pathS);
|
||||||
.name = "Nix path not found",
|
|
||||||
.hint = hintfmt("path '%s' is not in the Nix store", pathS)
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1525,10 +1510,7 @@ void LocalStore::verifyPath(const Path & pathS, const StringSet & store,
|
||||||
auto state(_state.lock());
|
auto state(_state.lock());
|
||||||
invalidatePath(*state, path);
|
invalidatePath(*state, path);
|
||||||
} else {
|
} else {
|
||||||
logError({
|
printError("path '%s' disappeared, but it still has valid referrers!", pathS);
|
||||||
.name = "Missing path with referrers",
|
|
||||||
.hint = hintfmt("path '%s' disappeared, but it still has valid referrers!", pathS)
|
|
||||||
});
|
|
||||||
if (repair)
|
if (repair)
|
||||||
try {
|
try {
|
||||||
repairPath(path);
|
repairPath(path);
|
||||||
|
|
|
@ -126,16 +126,13 @@ void LocalStore::optimisePath_(Activity * act, OptimiseStats & stats,
|
||||||
NixOS (example: $fontconfig/var/cache being modified). Skip
|
NixOS (example: $fontconfig/var/cache being modified). Skip
|
||||||
those files. FIXME: check the modification time. */
|
those files. FIXME: check the modification time. */
|
||||||
if (S_ISREG(st.st_mode) && (st.st_mode & S_IWUSR)) {
|
if (S_ISREG(st.st_mode) && (st.st_mode & S_IWUSR)) {
|
||||||
logWarning({
|
warn("skipping suspicious writable file '%1%'", path);
|
||||||
.name = "Suspicious file",
|
|
||||||
.hint = hintfmt("skipping suspicious writable file '%1%'", path)
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This can still happen on top-level files. */
|
/* This can still happen on top-level files. */
|
||||||
if (st.st_nlink > 1 && inodeHash.count(st.st_ino)) {
|
if (st.st_nlink > 1 && inodeHash.count(st.st_ino)) {
|
||||||
debug(format("'%1%' is already linked, with %2% other file(s)") % path % (st.st_nlink - 2));
|
debug("'%s' is already linked, with %d other file(s)", path, st.st_nlink - 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,10 +188,7 @@ void LocalStore::optimisePath_(Activity * act, OptimiseStats & stats,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (st.st_size != stLink.st_size) {
|
if (st.st_size != stLink.st_size) {
|
||||||
logWarning({
|
warn("removing corrupted link '%s'", linkPath);
|
||||||
.name = "Corrupted link",
|
|
||||||
.hint = hintfmt("removing corrupted link '%1%'", linkPath)
|
|
||||||
});
|
|
||||||
unlink(linkPath.c_str());
|
unlink(linkPath.c_str());
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
@ -229,10 +223,7 @@ void LocalStore::optimisePath_(Activity * act, OptimiseStats & stats,
|
||||||
/* Atomically replace the old file with the new hard link. */
|
/* Atomically replace the old file with the new hard link. */
|
||||||
if (rename(tempLink.c_str(), path.c_str()) == -1) {
|
if (rename(tempLink.c_str(), path.c_str()) == -1) {
|
||||||
if (unlink(tempLink.c_str()) == -1)
|
if (unlink(tempLink.c_str()) == -1)
|
||||||
logError({
|
printError("unable to unlink '%1%'", tempLink);
|
||||||
.name = "Unlink error",
|
|
||||||
.hint = hintfmt("unable to unlink '%1%'", tempLink)
|
|
||||||
});
|
|
||||||
if (errno == EMLINK) {
|
if (errno == EMLINK) {
|
||||||
/* Some filesystems generate too many links on the rename,
|
/* Some filesystems generate too many links on the rename,
|
||||||
rather than on the original link. (Probably it
|
rather than on the original link. (Probably it
|
||||||
|
|
|
@ -211,7 +211,7 @@ void handleSQLiteBusy(const SQLiteBusy & e)
|
||||||
lastWarned = now;
|
lastWarned = now;
|
||||||
logWarning({
|
logWarning({
|
||||||
.name = "Sqlite busy",
|
.name = "Sqlite busy",
|
||||||
.hint = hintfmt(e.what())
|
.msg = hintfmt(e.what())
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,9 +43,9 @@ string showErrPos(const ErrPos & errPos)
|
||||||
{
|
{
|
||||||
if (errPos.line > 0) {
|
if (errPos.line > 0) {
|
||||||
if (errPos.column > 0) {
|
if (errPos.column > 0) {
|
||||||
return fmt("(%1%:%2%)", errPos.line, errPos.column);
|
return fmt("%d:%d", errPos.line, errPos.column);
|
||||||
} else {
|
} else {
|
||||||
return fmt("(%1%)", errPos.line);
|
return fmt("%d", errPos.line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -180,24 +180,20 @@ void printCodeLines(std::ostream & out,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void printAtPos(const string & prefix, const ErrPos & pos, std::ostream & out)
|
void printAtPos(const ErrPos & pos, std::ostream & out)
|
||||||
{
|
{
|
||||||
if (pos)
|
if (pos) {
|
||||||
{
|
|
||||||
switch (pos.origin) {
|
switch (pos.origin) {
|
||||||
case foFile: {
|
case foFile: {
|
||||||
out << prefix << ANSI_BLUE << "at: " << ANSI_YELLOW << showErrPos(pos) <<
|
out << fmt(ANSI_BLUE "at " ANSI_YELLOW "%s:%s" ANSI_NORMAL ":", pos.file, showErrPos(pos));
|
||||||
ANSI_BLUE << " in file: " << ANSI_NORMAL << pos.file;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case foString: {
|
case foString: {
|
||||||
out << prefix << ANSI_BLUE << "at: " << ANSI_YELLOW << showErrPos(pos) <<
|
out << fmt(ANSI_BLUE "at " ANSI_YELLOW "«string»:%s" ANSI_NORMAL ":", showErrPos(pos));
|
||||||
ANSI_BLUE << " from string" << ANSI_NORMAL;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case foStdin: {
|
case foStdin: {
|
||||||
out << prefix << ANSI_BLUE << "at: " << ANSI_YELLOW << showErrPos(pos) <<
|
out << fmt(ANSI_BLUE "at " ANSI_YELLOW "«stdin»:%s" ANSI_NORMAL ":", showErrPos(pos));
|
||||||
ANSI_BLUE << " from stdin" << ANSI_NORMAL;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -206,168 +202,108 @@ void printAtPos(const string & prefix, const ErrPos & pos, std::ostream & out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string indent(std::string_view indentFirst, std::string_view indentRest, std::string_view s)
|
||||||
|
{
|
||||||
|
std::string res;
|
||||||
|
bool first = true;
|
||||||
|
|
||||||
|
while (!s.empty()) {
|
||||||
|
auto end = s.find('\n');
|
||||||
|
if (!first) res += "\n";
|
||||||
|
res += chomp(std::string(first ? indentFirst : indentRest) + std::string(s.substr(0, end)));
|
||||||
|
first = false;
|
||||||
|
if (end == s.npos) break;
|
||||||
|
s = s.substr(end + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
std::ostream & showErrorInfo(std::ostream & out, const ErrorInfo & einfo, bool showTrace)
|
std::ostream & showErrorInfo(std::ostream & out, const ErrorInfo & einfo, bool showTrace)
|
||||||
{
|
{
|
||||||
auto errwidth = std::max<size_t>(getWindowSize().second, 20);
|
std::string prefix;
|
||||||
string prefix = "";
|
|
||||||
|
|
||||||
string levelString;
|
|
||||||
switch (einfo.level) {
|
switch (einfo.level) {
|
||||||
case Verbosity::lvlError: {
|
case Verbosity::lvlError: {
|
||||||
levelString = ANSI_RED;
|
prefix = ANSI_RED "error";
|
||||||
levelString += "error:";
|
break;
|
||||||
levelString += ANSI_NORMAL;
|
}
|
||||||
|
case Verbosity::lvlNotice: {
|
||||||
|
prefix = ANSI_RED "note";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Verbosity::lvlWarn: {
|
case Verbosity::lvlWarn: {
|
||||||
levelString = ANSI_YELLOW;
|
prefix = ANSI_YELLOW "warning";
|
||||||
levelString += "warning:";
|
|
||||||
levelString += ANSI_NORMAL;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Verbosity::lvlInfo: {
|
case Verbosity::lvlInfo: {
|
||||||
levelString = ANSI_GREEN;
|
prefix = ANSI_GREEN "info";
|
||||||
levelString += "info:";
|
|
||||||
levelString += ANSI_NORMAL;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Verbosity::lvlTalkative: {
|
case Verbosity::lvlTalkative: {
|
||||||
levelString = ANSI_GREEN;
|
prefix = ANSI_GREEN "talk";
|
||||||
levelString += "talk:";
|
|
||||||
levelString += ANSI_NORMAL;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Verbosity::lvlChatty: {
|
case Verbosity::lvlChatty: {
|
||||||
levelString = ANSI_GREEN;
|
prefix = ANSI_GREEN "chat";
|
||||||
levelString += "chat:";
|
|
||||||
levelString += ANSI_NORMAL;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Verbosity::lvlVomit: {
|
case Verbosity::lvlVomit: {
|
||||||
levelString = ANSI_GREEN;
|
prefix = ANSI_GREEN "vomit";
|
||||||
levelString += "vomit:";
|
|
||||||
levelString += ANSI_NORMAL;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Verbosity::lvlDebug: {
|
case Verbosity::lvlDebug: {
|
||||||
levelString = ANSI_YELLOW;
|
prefix = ANSI_YELLOW "debug";
|
||||||
levelString += "debug:";
|
|
||||||
levelString += ANSI_NORMAL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
levelString = fmt("invalid error level: %1%", einfo.level);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ndl = prefix.length()
|
// FIXME: show the program name as part of the trace?
|
||||||
+ filterANSIEscapes(levelString, true).length()
|
if (einfo.programName && einfo.programName != ErrorInfo::programName)
|
||||||
+ 7
|
prefix += fmt(" [%s]:" ANSI_NORMAL " ", einfo.programName.value_or(""));
|
||||||
+ einfo.name.length()
|
|
||||||
+ einfo.programName.value_or("").length();
|
|
||||||
auto dashwidth = std::max<int>(errwidth - ndl, 3);
|
|
||||||
|
|
||||||
std::string dashes(dashwidth, '-');
|
|
||||||
|
|
||||||
// divider.
|
|
||||||
if (einfo.name != "")
|
|
||||||
out << fmt("%1%%2%" ANSI_BLUE " --- %3% %4% %5%" ANSI_NORMAL,
|
|
||||||
prefix,
|
|
||||||
levelString,
|
|
||||||
einfo.name,
|
|
||||||
dashes,
|
|
||||||
einfo.programName.value_or(""));
|
|
||||||
else
|
else
|
||||||
out << fmt("%1%%2%" ANSI_BLUE " -----%3% %4%" ANSI_NORMAL,
|
prefix += ":" ANSI_NORMAL " ";
|
||||||
prefix,
|
|
||||||
levelString,
|
|
||||||
dashes,
|
|
||||||
einfo.programName.value_or(""));
|
|
||||||
|
|
||||||
bool nl = false; // intersperse newline between sections.
|
std::ostringstream oss;
|
||||||
if (einfo.errPos.has_value() && (*einfo.errPos)) {
|
oss << einfo.msg << "\n";
|
||||||
out << prefix << std::endl;
|
|
||||||
printAtPos(prefix, *einfo.errPos, out);
|
|
||||||
nl = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// description
|
if (einfo.errPos.has_value() && *einfo.errPos) {
|
||||||
if (einfo.description != "") {
|
oss << "\n";
|
||||||
if (nl)
|
printAtPos(*einfo.errPos, oss);
|
||||||
out << std::endl << prefix;
|
|
||||||
out << std::endl << prefix << einfo.description;
|
|
||||||
nl = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (einfo.errPos.has_value() && (*einfo.errPos)) {
|
|
||||||
auto loc = getCodeLines(*einfo.errPos);
|
auto loc = getCodeLines(*einfo.errPos);
|
||||||
|
|
||||||
// lines of code.
|
// lines of code.
|
||||||
if (loc.has_value()) {
|
if (loc.has_value()) {
|
||||||
if (nl)
|
oss << "\n";
|
||||||
out << std::endl << prefix;
|
printCodeLines(oss, "", *einfo.errPos, *loc);
|
||||||
printCodeLines(out, prefix, *einfo.errPos, *loc);
|
oss << "\n";
|
||||||
nl = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// hint
|
|
||||||
if (einfo.hint.has_value()) {
|
|
||||||
if (nl)
|
|
||||||
out << std::endl << prefix;
|
|
||||||
out << std::endl << prefix << *einfo.hint;
|
|
||||||
nl = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// traces
|
// traces
|
||||||
if (showTrace && !einfo.traces.empty())
|
if (showTrace && !einfo.traces.empty()) {
|
||||||
{
|
for (auto iter = einfo.traces.rbegin(); iter != einfo.traces.rend(); ++iter) {
|
||||||
const string tracetitle(" show-trace ");
|
oss << "\n" << "… " << iter->hint.str() << "\n";
|
||||||
|
|
||||||
int fill = errwidth - tracetitle.length();
|
|
||||||
int lw = 0;
|
|
||||||
int rw = 0;
|
|
||||||
const int min_dashes = 3;
|
|
||||||
if (fill > min_dashes * 2) {
|
|
||||||
if (fill % 2 != 0) {
|
|
||||||
lw = fill / 2;
|
|
||||||
rw = lw + 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lw = rw = fill / 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
lw = rw = min_dashes;
|
|
||||||
|
|
||||||
if (nl)
|
|
||||||
out << std::endl << prefix;
|
|
||||||
|
|
||||||
out << ANSI_BLUE << std::string(lw, '-') << tracetitle << std::string(rw, '-') << ANSI_NORMAL;
|
|
||||||
|
|
||||||
for (auto iter = einfo.traces.rbegin(); iter != einfo.traces.rend(); ++iter)
|
|
||||||
{
|
|
||||||
out << std::endl << prefix;
|
|
||||||
out << ANSI_BLUE << "trace: " << ANSI_NORMAL << iter->hint.str();
|
|
||||||
|
|
||||||
if (iter->pos.has_value() && (*iter->pos)) {
|
if (iter->pos.has_value() && (*iter->pos)) {
|
||||||
auto pos = iter->pos.value();
|
auto pos = iter->pos.value();
|
||||||
out << std::endl << prefix;
|
oss << "\n";
|
||||||
printAtPos(prefix, pos, out);
|
printAtPos(pos, oss);
|
||||||
|
|
||||||
auto loc = getCodeLines(pos);
|
auto loc = getCodeLines(pos);
|
||||||
if (loc.has_value())
|
if (loc.has_value()) {
|
||||||
{
|
oss << "\n";
|
||||||
out << std::endl << prefix;
|
printCodeLines(oss, "", pos, *loc);
|
||||||
printCodeLines(out, prefix, pos, *loc);
|
oss << "\n";
|
||||||
out << std::endl << prefix;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out << indent(prefix, std::string(filterANSIEscapes(prefix, true).size(), ' '), chomp(oss.str()));
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,9 +107,8 @@ struct Trace {
|
||||||
|
|
||||||
struct ErrorInfo {
|
struct ErrorInfo {
|
||||||
Verbosity level;
|
Verbosity level;
|
||||||
string name;
|
string name; // FIXME: rename
|
||||||
string description; // FIXME: remove? it seems to be barely used
|
hintformat msg;
|
||||||
std::optional<hintformat> hint;
|
|
||||||
std::optional<ErrPos> errPos;
|
std::optional<ErrPos> errPos;
|
||||||
std::list<Trace> traces;
|
std::list<Trace> traces;
|
||||||
|
|
||||||
|
@ -133,23 +132,17 @@ public:
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
BaseError(unsigned int status, const Args & ... args)
|
BaseError(unsigned int status, const Args & ... args)
|
||||||
: err {.level = lvlError,
|
: err { .level = lvlError, .msg = hintfmt(args...) }
|
||||||
.hint = hintfmt(args...)
|
|
||||||
}
|
|
||||||
, status(status)
|
, status(status)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
BaseError(const std::string & fs, const Args & ... args)
|
BaseError(const std::string & fs, const Args & ... args)
|
||||||
: err {.level = lvlError,
|
: err { .level = lvlError, .msg = hintfmt(fs, args...) }
|
||||||
.hint = hintfmt(fs, args...)
|
|
||||||
}
|
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
BaseError(hintformat hint)
|
BaseError(hintformat hint)
|
||||||
: err {.level = lvlError,
|
: err { .level = lvlError, .msg = hint }
|
||||||
.hint = hint
|
|
||||||
}
|
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
BaseError(ErrorInfo && e)
|
BaseError(ErrorInfo && e)
|
||||||
|
@ -206,7 +199,7 @@ public:
|
||||||
{
|
{
|
||||||
errNo = errno;
|
errNo = errno;
|
||||||
auto hf = hintfmt(args...);
|
auto hf = hintfmt(args...);
|
||||||
err.hint = hintfmt("%1%: %2%", normaltxt(hf.str()), strerror(errNo));
|
err.msg = hintfmt("%1%: %2%", normaltxt(hf.str()), strerror(errNo));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual const char* sname() const override { return "SysError"; }
|
virtual const char* sname() const override { return "SysError"; }
|
||||||
|
|
|
@ -184,7 +184,7 @@ struct JSONLogger : Logger {
|
||||||
json["action"] = "msg";
|
json["action"] = "msg";
|
||||||
json["level"] = ei.level;
|
json["level"] = ei.level;
|
||||||
json["msg"] = oss.str();
|
json["msg"] = oss.str();
|
||||||
json["raw_msg"] = ei.hint->str();
|
json["raw_msg"] = ei.msg.str();
|
||||||
|
|
||||||
if (ei.errPos.has_value() && (*ei.errPos)) {
|
if (ei.errPos.has_value() && (*ei.errPos)) {
|
||||||
json["line"] = ei.errPos->line;
|
json["line"] = ei.errPos->line;
|
||||||
|
@ -305,10 +305,7 @@ bool handleJSONLogMessage(const std::string & msg,
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (std::exception & e) {
|
} catch (std::exception & e) {
|
||||||
logError({
|
printError("bad JSON log message from builder: %s", e.what());
|
||||||
.name = "JSON log message",
|
|
||||||
.hint = hintfmt("bad log message from builder: %s", e.what())
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -52,10 +52,7 @@ size_t threshold = 256 * 1024 * 1024;
|
||||||
|
|
||||||
static void warnLargeDump()
|
static void warnLargeDump()
|
||||||
{
|
{
|
||||||
logWarning({
|
warn("dumping very large path (> 256 MiB); this may run out of memory");
|
||||||
.name = "Large path",
|
|
||||||
.description = "dumping very large path (> 256 MiB); this may run out of memory"
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -306,8 +303,7 @@ Sink & operator << (Sink & sink, const Error & ex)
|
||||||
<< "Error"
|
<< "Error"
|
||||||
<< info.level
|
<< info.level
|
||||||
<< info.name
|
<< info.name
|
||||||
<< info.description
|
<< info.msg.str()
|
||||||
<< (info.hint ? info.hint->str() : "")
|
|
||||||
<< 0 // FIXME: info.errPos
|
<< 0 // FIXME: info.errPos
|
||||||
<< info.traces.size();
|
<< info.traces.size();
|
||||||
for (auto & trace : info.traces) {
|
for (auto & trace : info.traces) {
|
||||||
|
@ -374,12 +370,14 @@ Error readError(Source & source)
|
||||||
{
|
{
|
||||||
auto type = readString(source);
|
auto type = readString(source);
|
||||||
assert(type == "Error");
|
assert(type == "Error");
|
||||||
ErrorInfo info;
|
auto level = (Verbosity) readInt(source);
|
||||||
info.level = (Verbosity) readInt(source);
|
auto name = readString(source);
|
||||||
info.name = readString(source);
|
auto msg = readString(source);
|
||||||
info.description = readString(source);
|
ErrorInfo info {
|
||||||
auto hint = readString(source);
|
.level = level,
|
||||||
if (hint != "") info.hint = hintformat(std::move(format("%s") % hint));
|
.name = name,
|
||||||
|
.msg = hintformat(std::move(format("%s") % msg)),
|
||||||
|
};
|
||||||
auto havePos = readNum<size_t>(source);
|
auto havePos = readNum<size_t>(source);
|
||||||
assert(havePos == 0);
|
assert(havePos == 0);
|
||||||
auto nrTraces = readNum<size_t>(source);
|
auto nrTraces = readNum<size_t>(source);
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#if 0
|
||||||
|
|
||||||
#include "logging.hh"
|
#include "logging.hh"
|
||||||
#include "nixexpr.hh"
|
#include "nixexpr.hh"
|
||||||
#include "util.hh"
|
#include "util.hh"
|
||||||
|
@ -41,8 +43,7 @@ namespace nix {
|
||||||
|
|
||||||
makeJSONLogger(*logger)->logEI({
|
makeJSONLogger(*logger)->logEI({
|
||||||
.name = "error name",
|
.name = "error name",
|
||||||
.description = "error without any code lines.",
|
.msg = hintfmt("this hint has %1% templated %2%!!",
|
||||||
.hint = hintfmt("this hint has %1% templated %2%!!",
|
|
||||||
"yellow",
|
"yellow",
|
||||||
"values"),
|
"values"),
|
||||||
.errPos = Pos(foFile, problem_file, 02, 13)
|
.errPos = Pos(foFile, problem_file, 02, 13)
|
||||||
|
@ -62,7 +63,7 @@ namespace nix {
|
||||||
throw TestError(e.info());
|
throw TestError(e.info());
|
||||||
} catch (Error &e) {
|
} catch (Error &e) {
|
||||||
ErrorInfo ei = e.info();
|
ErrorInfo ei = e.info();
|
||||||
ei.hint = hintfmt("%s; subsequent error message.", normaltxt(e.info().hint ? e.info().hint->str() : ""));
|
ei.msg = hintfmt("%s; subsequent error message.", normaltxt(e.info().msg.str()));
|
||||||
|
|
||||||
testing::internal::CaptureStderr();
|
testing::internal::CaptureStderr();
|
||||||
logger->logEI(ei);
|
logger->logEI(ei);
|
||||||
|
@ -95,7 +96,6 @@ namespace nix {
|
||||||
|
|
||||||
logger->logEI({ .level = lvlInfo,
|
logger->logEI({ .level = lvlInfo,
|
||||||
.name = "Info name",
|
.name = "Info name",
|
||||||
.description = "Info description",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
auto str = testing::internal::GetCapturedStderr();
|
auto str = testing::internal::GetCapturedStderr();
|
||||||
|
@ -109,7 +109,6 @@ namespace nix {
|
||||||
|
|
||||||
logger->logEI({ .level = lvlTalkative,
|
logger->logEI({ .level = lvlTalkative,
|
||||||
.name = "Talkative name",
|
.name = "Talkative name",
|
||||||
.description = "Talkative description",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
auto str = testing::internal::GetCapturedStderr();
|
auto str = testing::internal::GetCapturedStderr();
|
||||||
|
@ -123,7 +122,6 @@ namespace nix {
|
||||||
|
|
||||||
logger->logEI({ .level = lvlChatty,
|
logger->logEI({ .level = lvlChatty,
|
||||||
.name = "Chatty name",
|
.name = "Chatty name",
|
||||||
.description = "Talkative description",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
auto str = testing::internal::GetCapturedStderr();
|
auto str = testing::internal::GetCapturedStderr();
|
||||||
|
@ -137,7 +135,6 @@ namespace nix {
|
||||||
|
|
||||||
logger->logEI({ .level = lvlDebug,
|
logger->logEI({ .level = lvlDebug,
|
||||||
.name = "Debug name",
|
.name = "Debug name",
|
||||||
.description = "Debug description",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
auto str = testing::internal::GetCapturedStderr();
|
auto str = testing::internal::GetCapturedStderr();
|
||||||
|
@ -151,7 +148,6 @@ namespace nix {
|
||||||
|
|
||||||
logger->logEI({ .level = lvlVomit,
|
logger->logEI({ .level = lvlVomit,
|
||||||
.name = "Vomit name",
|
.name = "Vomit name",
|
||||||
.description = "Vomit description",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
auto str = testing::internal::GetCapturedStderr();
|
auto str = testing::internal::GetCapturedStderr();
|
||||||
|
@ -167,7 +163,6 @@ namespace nix {
|
||||||
|
|
||||||
logError({
|
logError({
|
||||||
.name = "name",
|
.name = "name",
|
||||||
.description = "error description",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
auto str = testing::internal::GetCapturedStderr();
|
auto str = testing::internal::GetCapturedStderr();
|
||||||
|
@ -182,8 +177,7 @@ namespace nix {
|
||||||
|
|
||||||
logError({
|
logError({
|
||||||
.name = "error name",
|
.name = "error name",
|
||||||
.description = "error with code lines",
|
.msg = hintfmt("this hint has %1% templated %2%!!",
|
||||||
.hint = hintfmt("this hint has %1% templated %2%!!",
|
|
||||||
"yellow",
|
"yellow",
|
||||||
"values"),
|
"values"),
|
||||||
.errPos = Pos(foString, problem_file, 02, 13),
|
.errPos = Pos(foString, problem_file, 02, 13),
|
||||||
|
@ -200,8 +194,7 @@ namespace nix {
|
||||||
|
|
||||||
logError({
|
logError({
|
||||||
.name = "error name",
|
.name = "error name",
|
||||||
.description = "error without any code lines.",
|
.msg = hintfmt("this hint has %1% templated %2%!!",
|
||||||
.hint = hintfmt("this hint has %1% templated %2%!!",
|
|
||||||
"yellow",
|
"yellow",
|
||||||
"values"),
|
"values"),
|
||||||
.errPos = Pos(foFile, problem_file, 02, 13)
|
.errPos = Pos(foFile, problem_file, 02, 13)
|
||||||
|
@ -216,7 +209,7 @@ namespace nix {
|
||||||
|
|
||||||
logError({
|
logError({
|
||||||
.name = "error name",
|
.name = "error name",
|
||||||
.hint = hintfmt("hint %1%", "only"),
|
.msg = hintfmt("hint %1%", "only"),
|
||||||
});
|
});
|
||||||
|
|
||||||
auto str = testing::internal::GetCapturedStderr();
|
auto str = testing::internal::GetCapturedStderr();
|
||||||
|
@ -233,8 +226,7 @@ namespace nix {
|
||||||
|
|
||||||
logWarning({
|
logWarning({
|
||||||
.name = "name",
|
.name = "name",
|
||||||
.description = "warning description",
|
.msg = hintfmt("there was a %1%", "warning"),
|
||||||
.hint = hintfmt("there was a %1%", "warning"),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
auto str = testing::internal::GetCapturedStderr();
|
auto str = testing::internal::GetCapturedStderr();
|
||||||
|
@ -250,8 +242,7 @@ namespace nix {
|
||||||
|
|
||||||
logWarning({
|
logWarning({
|
||||||
.name = "warning name",
|
.name = "warning name",
|
||||||
.description = "warning description",
|
.msg = hintfmt("this hint has %1% templated %2%!!",
|
||||||
.hint = hintfmt("this hint has %1% templated %2%!!",
|
|
||||||
"yellow",
|
"yellow",
|
||||||
"values"),
|
"values"),
|
||||||
.errPos = Pos(foStdin, problem_file, 2, 13),
|
.errPos = Pos(foStdin, problem_file, 2, 13),
|
||||||
|
@ -274,8 +265,7 @@ namespace nix {
|
||||||
|
|
||||||
auto e = AssertionError(ErrorInfo {
|
auto e = AssertionError(ErrorInfo {
|
||||||
.name = "wat",
|
.name = "wat",
|
||||||
.description = "show-traces",
|
.msg = hintfmt("it has been %1% days since our last error", "zero"),
|
||||||
.hint = hintfmt("it has been %1% days since our last error", "zero"),
|
|
||||||
.errPos = Pos(foString, problem_file, 2, 13),
|
.errPos = Pos(foString, problem_file, 2, 13),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -301,8 +291,7 @@ namespace nix {
|
||||||
|
|
||||||
auto e = AssertionError(ErrorInfo {
|
auto e = AssertionError(ErrorInfo {
|
||||||
.name = "wat",
|
.name = "wat",
|
||||||
.description = "hide traces",
|
.msg = hintfmt("it has been %1% days since our last error", "zero"),
|
||||||
.hint = hintfmt("it has been %1% days since our last error", "zero"),
|
|
||||||
.errPos = Pos(foString, problem_file, 2, 13),
|
.errPos = Pos(foString, problem_file, 2, 13),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -377,3 +366,5 @@ namespace nix {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -1249,7 +1249,7 @@ template StringSet tokenizeString(std::string_view s, const string & separators)
|
||||||
template vector<string> tokenizeString(std::string_view s, const string & separators);
|
template vector<string> tokenizeString(std::string_view s, const string & separators);
|
||||||
|
|
||||||
|
|
||||||
string chomp(const string & s)
|
string chomp(std::string_view s)
|
||||||
{
|
{
|
||||||
size_t i = s.find_last_not_of(" \n\r\t");
|
size_t i = s.find_last_not_of(" \n\r\t");
|
||||||
return i == string::npos ? "" : string(s, 0, i + 1);
|
return i == string::npos ? "" : string(s, 0, i + 1);
|
||||||
|
|
|
@ -373,8 +373,9 @@ template<class C> Strings quoteStrings(const C & c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Remove trailing whitespace from a string. */
|
/* Remove trailing whitespace from a string. FIXME: return
|
||||||
string chomp(const string & s);
|
std::string_view. */
|
||||||
|
string chomp(std::string_view s);
|
||||||
|
|
||||||
|
|
||||||
/* Remove whitespace from the start and end of a string. */
|
/* Remove whitespace from the start and end of a string. */
|
||||||
|
|
|
@ -369,11 +369,8 @@ static void main_nix_build(int argc, char * * argv)
|
||||||
shell = drv->queryOutPath() + "/bin/bash";
|
shell = drv->queryOutPath() + "/bin/bash";
|
||||||
|
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
logWarning({
|
logError(e.info());
|
||||||
.name = "bashInteractive",
|
notice("will use bash from your environment");
|
||||||
.hint = hintfmt("%s; will use bash from your environment",
|
|
||||||
(e.info().hint ? e.info().hint->str() : ""))
|
|
||||||
});
|
|
||||||
shell = "bash";
|
shell = "bash";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,10 +124,7 @@ static void getAllExprs(EvalState & state,
|
||||||
if (hasSuffix(attrName, ".nix"))
|
if (hasSuffix(attrName, ".nix"))
|
||||||
attrName = string(attrName, 0, attrName.size() - 4);
|
attrName = string(attrName, 0, attrName.size() - 4);
|
||||||
if (!attrs.insert(attrName).second) {
|
if (!attrs.insert(attrName).second) {
|
||||||
logError({
|
printError("warning: name collision in input Nix expressions, skipping '%1%'", path2);
|
||||||
.name = "Name collision",
|
|
||||||
.hint = hintfmt("warning: name collision in input Nix expressions, skipping '%1%'", path2)
|
|
||||||
});
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* Load the expression on demand. */
|
/* Load the expression on demand. */
|
||||||
|
@ -876,11 +873,7 @@ static void queryJSON(Globals & globals, vector<DrvInfo> & elems)
|
||||||
auto placeholder = metaObj.placeholder(j);
|
auto placeholder = metaObj.placeholder(j);
|
||||||
Value * v = i.queryMeta(j);
|
Value * v = i.queryMeta(j);
|
||||||
if (!v) {
|
if (!v) {
|
||||||
logError({
|
printError("derivation '%s' has invalid meta attribute '%s'", i.queryName(), j);
|
||||||
.name = "Invalid meta attribute",
|
|
||||||
.hint = hintfmt("derivation '%s' has invalid meta attribute '%s'",
|
|
||||||
i.queryName(), j)
|
|
||||||
});
|
|
||||||
placeholder.write(nullptr);
|
placeholder.write(nullptr);
|
||||||
} else {
|
} else {
|
||||||
PathSet context;
|
PathSet context;
|
||||||
|
@ -1131,12 +1124,9 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
|
||||||
attrs2["name"] = j;
|
attrs2["name"] = j;
|
||||||
Value * v = i.queryMeta(j);
|
Value * v = i.queryMeta(j);
|
||||||
if (!v)
|
if (!v)
|
||||||
logError({
|
printError(
|
||||||
.name = "Invalid meta attribute",
|
"derivation '%s' has invalid meta attribute '%s'",
|
||||||
.hint = hintfmt(
|
i.queryName(), j);
|
||||||
"derivation '%s' has invalid meta attribute '%s'",
|
|
||||||
i.queryName(), j)
|
|
||||||
});
|
|
||||||
else {
|
else {
|
||||||
if (v->type() == nString) {
|
if (v->type() == nString) {
|
||||||
attrs2["type"] = "string";
|
attrs2["type"] = "string";
|
||||||
|
|
|
@ -708,10 +708,7 @@ static void opVerify(Strings opFlags, Strings opArgs)
|
||||||
else throw UsageError("unknown flag '%1%'", i);
|
else throw UsageError("unknown flag '%1%'", i);
|
||||||
|
|
||||||
if (store->verifyStore(checkContents, repair)) {
|
if (store->verifyStore(checkContents, repair)) {
|
||||||
logWarning({
|
warn("not all store errors were fixed");
|
||||||
.name = "Store consistency",
|
|
||||||
.description = "not all errors were fixed"
|
|
||||||
});
|
|
||||||
throw Exit(1);
|
throw Exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -733,14 +730,10 @@ static void opVerifyPath(Strings opFlags, Strings opArgs)
|
||||||
store->narFromPath(path, sink);
|
store->narFromPath(path, sink);
|
||||||
auto current = sink.finish();
|
auto current = sink.finish();
|
||||||
if (current.first != info->narHash) {
|
if (current.first != info->narHash) {
|
||||||
logError({
|
printError("path '%s' was modified! expected hash '%s', got '%s'",
|
||||||
.name = "Hash mismatch",
|
store->printStorePath(path),
|
||||||
.hint = hintfmt(
|
info->narHash.to_string(Base32, true),
|
||||||
"path '%s' was modified! expected hash '%s', got '%s'",
|
current.first.to_string(Base32, true));
|
||||||
store->printStorePath(path),
|
|
||||||
info->narHash.to_string(Base32, true),
|
|
||||||
current.first.to_string(Base32, true))
|
|
||||||
});
|
|
||||||
status = 1;
|
status = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -258,8 +258,8 @@ static void daemonLoop()
|
||||||
return;
|
return;
|
||||||
} catch (Error & error) {
|
} catch (Error & error) {
|
||||||
ErrorInfo ei = error.info();
|
ErrorInfo ei = error.info();
|
||||||
ei.hint = std::optional(hintfmt("error processing connection: %1%",
|
// FIXME: add to trace?
|
||||||
(error.info().hint.has_value() ? error.info().hint->str() : "")));
|
ei.msg = hintfmt("error processing connection: %1%", ei.msg.str());
|
||||||
logError(ei);
|
logError(ei);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,10 +61,7 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand
|
||||||
|
|
||||||
if (dryRun) {
|
if (dryRun) {
|
||||||
stopProgressBar();
|
stopProgressBar();
|
||||||
logWarning({
|
warn("would upgrade to version %s", version);
|
||||||
.name = "Version update",
|
|
||||||
.hint = hintfmt("would upgrade to version %s", version)
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -101,14 +101,10 @@ struct CmdVerify : StorePathsCommand
|
||||||
if (hash.first != info->narHash) {
|
if (hash.first != info->narHash) {
|
||||||
corrupted++;
|
corrupted++;
|
||||||
act2.result(resCorruptedPath, store->printStorePath(info->path));
|
act2.result(resCorruptedPath, store->printStorePath(info->path));
|
||||||
logError({
|
printError("path '%s' was modified! expected hash '%s', got '%s'",
|
||||||
.name = "Hash error - path modified",
|
store->printStorePath(info->path),
|
||||||
.hint = hintfmt(
|
info->narHash.to_string(Base32, true),
|
||||||
"path '%s' was modified! expected hash '%s', got '%s'",
|
hash.first.to_string(Base32, true));
|
||||||
store->printStorePath(info->path),
|
|
||||||
info->narHash.to_string(Base32, true),
|
|
||||||
hash.first.to_string(Base32, true))
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,12 +152,7 @@ struct CmdVerify : StorePathsCommand
|
||||||
if (!good) {
|
if (!good) {
|
||||||
untrusted++;
|
untrusted++;
|
||||||
act2.result(resUntrustedPath, store->printStorePath(info->path));
|
act2.result(resUntrustedPath, store->printStorePath(info->path));
|
||||||
logError({
|
printError("path '%s' is untrusted", store->printStorePath(info->path));
|
||||||
.name = "Untrusted path",
|
|
||||||
.hint = hintfmt("path '%s' is untrusted",
|
|
||||||
store->printStorePath(info->path))
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,18 +39,12 @@ std::set<std::string> runResolver(const Path & filename)
|
||||||
throw SysError("statting '%s'", filename);
|
throw SysError("statting '%s'", filename);
|
||||||
|
|
||||||
if (!S_ISREG(st.st_mode)) {
|
if (!S_ISREG(st.st_mode)) {
|
||||||
logError({
|
printError("file '%s' is not a regular MACH binary", filename);
|
||||||
.name = "Regular MACH file",
|
|
||||||
.hint = hintfmt("file '%s' is not a regular file", filename)
|
|
||||||
});
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (st.st_size < sizeof(mach_header_64)) {
|
if (st.st_size < sizeof(mach_header_64)) {
|
||||||
logError({
|
printError("file '%s' is too short for a MACH binary", filename);
|
||||||
.name = "File too short",
|
|
||||||
.hint = hintfmt("file '%s' is too short for a MACH binary", filename)
|
|
||||||
});
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,19 +66,13 @@ std::set<std::string> runResolver(const Path & filename)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mach64_offset == 0) {
|
if (mach64_offset == 0) {
|
||||||
logError({
|
printError("could not find any mach64 blobs in file '%1%', continuing...", filename);
|
||||||
.name = "No mach64 blobs",
|
|
||||||
.hint = hintfmt("Could not find any mach64 blobs in file '%1%', continuing...", filename)
|
|
||||||
});
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
} else if (magic == MH_MAGIC_64 || magic == MH_CIGAM_64) {
|
} else if (magic == MH_MAGIC_64 || magic == MH_CIGAM_64) {
|
||||||
mach64_offset = 0;
|
mach64_offset = 0;
|
||||||
} else {
|
} else {
|
||||||
logError({
|
printError("Object file has unknown magic number '%1%', skipping it...", magic);
|
||||||
.name = "Magic number",
|
|
||||||
.hint = hintfmt("Object file has unknown magic number '%1%', skipping it...", magic)
|
|
||||||
});
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,10 +17,10 @@ nix-env -q --foo 2>&1 | grep "unknown flag"
|
||||||
|
|
||||||
# Eval Errors.
|
# Eval Errors.
|
||||||
eval_arg_res=$(nix-instantiate --eval -E 'let a = {} // a; in a.foo' 2>&1 || true)
|
eval_arg_res=$(nix-instantiate --eval -E 'let a = {} // a; in a.foo' 2>&1 || true)
|
||||||
echo $eval_arg_res | grep "at: (1:15) from string"
|
echo $eval_arg_res | grep "at «string»:1:15:"
|
||||||
echo $eval_arg_res | grep "infinite recursion encountered"
|
echo $eval_arg_res | grep "infinite recursion encountered"
|
||||||
|
|
||||||
eval_stdin_res=$(echo 'let a = {} // a; in a.foo' | nix-instantiate --eval -E - 2>&1 || true)
|
eval_stdin_res=$(echo 'let a = {} // a; in a.foo' | nix-instantiate --eval -E - 2>&1 || true)
|
||||||
echo $eval_stdin_res | grep "at: (1:15) from stdin"
|
echo $eval_stdin_res | grep "at «stdin»:1:15:"
|
||||||
echo $eval_stdin_res | grep "infinite recursion encountered"
|
echo $eval_stdin_res | grep "infinite recursion encountered"
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue