style(3p/nix): Final act in the brace-wrapping saga
This last change set was generated by a full clang-tidy run (including compilation): clang-tidy -p ~/projects/nix-build/ \ -checks=-*,readability-braces-around-statements -fix src/*/*.cc Actually running clang-tidy requires some massaging to make it play nice with Nix + meson, I'll be adding a wrapper or something for that soon.
This commit is contained in:
parent
cf40d08908
commit
3908732181
84 changed files with 2601 additions and 1554 deletions
third_party
default.nix
nix
default.nix
src
build-remote
libexpr
attr-path.ccattr-set.cccommon-eval-args.cceval.ccget-drvs.ccjson-to-value.ccnames.ccnixexpr.ccprimops.ccvalue-to-json.ccvalue-to-xml.cc
libmain
libstore
binary-cache-store.ccbuild.cccrypto.ccderivations.ccdownload.ccexport-import.ccgc.ccglobals.ccglobals.hhhttp-binary-cache-store.cclegacy-ssh-store.cclocal-binary-cache-store.cclocal-fs-store.cclocal-store.ccmisc.ccnar-accessor.ccnar-info-disk-cache.ccnar-info.ccoptimise-store.ccparsed-derivations.ccpathlocks.ccprofiles.ccreferences.ccremote-fs-accessor.ccremote-store.ccsqlite.ccssh.ccstore-api.cc
libutil
archive.ccargs.cccompression.ccconfig.cchash.ccjson.ccserialise.ccthread-pool.ccutil.ccxml-writer.cc
nix-build
nix-channel
nix-collect-garbage
nix-copy-closure
nix-daemon
nix-env
nix-instantiate
nix-prefetch-url
nix-store
nix
1
third_party/default.nix
vendored
1
third_party/default.nix
vendored
|
@ -33,6 +33,7 @@ let
|
|||
cairo
|
||||
cargo
|
||||
cgit
|
||||
clang-tools
|
||||
clangStdenv
|
||||
clang_9
|
||||
cmake
|
||||
|
|
1
third_party/nix/default.nix
vendored
1
third_party/nix/default.nix
vendored
|
@ -20,6 +20,7 @@ in stdenv.mkDerivation {
|
|||
|
||||
nativeBuildInputs = with pkgs; [
|
||||
bison
|
||||
clang-tools
|
||||
meson
|
||||
ninja
|
||||
pkgconfig
|
||||
|
|
17
third_party/nix/src/build-remote/build-remote.cc
vendored
17
third_party/nix/src/build-remote/build-remote.cc
vendored
|
@ -39,10 +39,11 @@ static AutoCloseFD openSlotLock(const Machine& m, unsigned long long slot) {
|
|||
}
|
||||
|
||||
static bool allSupportedLocally(const std::set<std::string>& requiredFeatures) {
|
||||
for (auto& feature : requiredFeatures)
|
||||
for (auto& feature : requiredFeatures) {
|
||||
if (!settings.systemFeatures.get().count(feature)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -172,10 +173,11 @@ static int _main(int argc, char** argv) {
|
|||
}
|
||||
|
||||
if (!bestSlotLock) {
|
||||
if (rightType && !canBuildLocally)
|
||||
if (rightType && !canBuildLocally) {
|
||||
std::cerr << "# postpone\n";
|
||||
else
|
||||
} else {
|
||||
std::cerr << "# decline\n";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -194,8 +196,9 @@ static int _main(int argc, char** argv) {
|
|||
if (hasPrefix(bestMachine->storeUri, "ssh://")) {
|
||||
storeParams["max-connections"] = "1";
|
||||
storeParams["log-fd"] = "4";
|
||||
if (bestMachine->sshKey != "")
|
||||
if (bestMachine->sshKey != "") {
|
||||
storeParams["ssh-key"] = bestMachine->sshKey;
|
||||
}
|
||||
}
|
||||
|
||||
sshStore = openStore(bestMachine->storeUri, storeParams);
|
||||
|
@ -254,15 +257,17 @@ static int _main(int argc, char** argv) {
|
|||
|
||||
auto result = sshStore->buildDerivation(drvPath, drv);
|
||||
|
||||
if (!result.success())
|
||||
if (!result.success()) {
|
||||
throw Error("build of '%s' on '%s' failed: %s", drvPath, storeUri,
|
||||
result.errorMsg);
|
||||
}
|
||||
|
||||
PathSet missing;
|
||||
for (auto& path : outputs)
|
||||
for (auto& path : outputs) {
|
||||
if (!store->isValidPath(path)) {
|
||||
missing.insert(path);
|
||||
}
|
||||
}
|
||||
|
||||
if (!missing.empty()) {
|
||||
DLOG(INFO) << "copying outputs from '" << storeUri << "'";
|
||||
|
|
21
third_party/nix/src/libexpr/attr-path.cc
vendored
21
third_party/nix/src/libexpr/attr-path.cc
vendored
|
@ -16,16 +16,18 @@ static Strings parseAttrPath(const string& s) {
|
|||
} else if (*i == '"') {
|
||||
++i;
|
||||
while (1) {
|
||||
if (i == s.end())
|
||||
if (i == s.end()) {
|
||||
throw Error(format("missing closing quote in selection path '%1%'") %
|
||||
s);
|
||||
}
|
||||
if (*i == '"') {
|
||||
break;
|
||||
}
|
||||
cur.push_back(*i++);
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
cur.push_back(*i);
|
||||
}
|
||||
++i;
|
||||
}
|
||||
if (!cur.empty()) {
|
||||
|
@ -62,33 +64,38 @@ Value* findAlongAttrPath(EvalState& state, const string& attrPath,
|
|||
according to what is specified in the attrPath. */
|
||||
|
||||
if (apType == apAttr) {
|
||||
if (v->type != tAttrs)
|
||||
if (v->type != tAttrs) {
|
||||
throw TypeError(format("the expression selected by the selection path "
|
||||
"'%1%' should be a set but is %2%") %
|
||||
attrPath % showType(*v));
|
||||
}
|
||||
|
||||
if (attr.empty())
|
||||
if (attr.empty()) {
|
||||
throw Error(format("empty attribute name in selection path '%1%'") %
|
||||
attrPath);
|
||||
}
|
||||
|
||||
Bindings::iterator a = v->attrs->find(state.symbols.create(attr));
|
||||
if (a == v->attrs->end())
|
||||
if (a == v->attrs->end()) {
|
||||
throw Error(
|
||||
format("attribute '%1%' in selection path '%2%' not found") % attr %
|
||||
attrPath);
|
||||
}
|
||||
v = &*a->value;
|
||||
}
|
||||
|
||||
else if (apType == apIndex) {
|
||||
if (!v->isList())
|
||||
if (!v->isList()) {
|
||||
throw TypeError(format("the expression selected by the selection path "
|
||||
"'%1%' should be a list but is %2%") %
|
||||
attrPath % showType(*v));
|
||||
}
|
||||
|
||||
if (attrIndex >= v->listSize())
|
||||
if (attrIndex >= v->listSize()) {
|
||||
throw Error(
|
||||
format("list index %1% in selection path '%2%' is out of range") %
|
||||
attrIndex % attrPath);
|
||||
}
|
||||
|
||||
v = v->listElems()[attrIndex];
|
||||
}
|
||||
|
|
3
third_party/nix/src/libexpr/attr-set.cc
vendored
3
third_party/nix/src/libexpr/attr-set.cc
vendored
|
@ -10,8 +10,9 @@ namespace nix {
|
|||
capacity. The space is implicitly reserved after the Bindings
|
||||
structure. */
|
||||
Bindings* EvalState::allocBindings(size_t capacity) {
|
||||
if (capacity > std::numeric_limits<Bindings::size_t>::max())
|
||||
if (capacity > std::numeric_limits<Bindings::size_t>::max()) {
|
||||
throw Error("attribute set of size %d is too big", capacity);
|
||||
}
|
||||
return new (allocBytes(sizeof(Bindings) + sizeof(Attr) * capacity))
|
||||
Bindings((Bindings::size_t)capacity);
|
||||
}
|
||||
|
|
|
@ -36,11 +36,12 @@ Bindings* MixEvalArgs::getAutoArgs(EvalState& state) {
|
|||
Bindings* res = state.allocBindings(autoArgs.size());
|
||||
for (auto& i : autoArgs) {
|
||||
Value* v = state.allocValue();
|
||||
if (i.second[0] == 'E')
|
||||
if (i.second[0] == 'E') {
|
||||
state.mkThunk_(
|
||||
*v, state.parseExprFromString(string(i.second, 1), absPath(".")));
|
||||
else
|
||||
} else {
|
||||
mkString(*v, string(i.second, 1));
|
||||
}
|
||||
res->push_back(Attr(state.symbols.create(i.first), v));
|
||||
}
|
||||
res->sort();
|
||||
|
@ -55,8 +56,9 @@ Path lookupFileArg(EvalState& state, string s) {
|
|||
} else if (s.size() > 2 && s.at(0) == '<' && s.at(s.size() - 1) == '>') {
|
||||
Path p = s.substr(1, s.size() - 2);
|
||||
return state.findFile(p);
|
||||
} else
|
||||
} else {
|
||||
return absPath(s);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace nix
|
||||
|
|
155
third_party/nix/src/libexpr/eval.cc
vendored
155
third_party/nix/src/libexpr/eval.cc
vendored
|
@ -62,17 +62,19 @@ static void printValue(std::ostream& str, std::set<const Value*>& active,
|
|||
break;
|
||||
case tString:
|
||||
str << "\"";
|
||||
for (const char* i = v.string.s; *i; i++)
|
||||
if (*i == '\"' || *i == '\\')
|
||||
for (const char* i = v.string.s; *i; i++) {
|
||||
if (*i == '\"' || *i == '\\') {
|
||||
str << "\\" << *i;
|
||||
else if (*i == '\n')
|
||||
} else if (*i == '\n') {
|
||||
str << "\\n";
|
||||
else if (*i == '\r')
|
||||
} else if (*i == '\r') {
|
||||
str << "\\r";
|
||||
else if (*i == '\t')
|
||||
} else if (*i == '\t') {
|
||||
str << "\\t";
|
||||
else
|
||||
} else {
|
||||
str << *i;
|
||||
}
|
||||
}
|
||||
str << "\"";
|
||||
break;
|
||||
case tPath:
|
||||
|
@ -281,7 +283,9 @@ static Strings parseNixPath(const string& s) {
|
|||
if (*p == ':') {
|
||||
if (isUri(std::string(start2, s.end()))) {
|
||||
++p;
|
||||
while (p != s.end() && *p != ':') ++p;
|
||||
while (p != s.end() && *p != ':') {
|
||||
++p;
|
||||
}
|
||||
}
|
||||
res.push_back(std::string(start, p));
|
||||
if (p == s.end()) {
|
||||
|
@ -361,8 +365,9 @@ EvalState::EvalState(const Strings& _searchPath, ref<Store> store)
|
|||
for (auto& path : closure) {
|
||||
allowedPaths->insert(path);
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
allowedPaths->insert(r.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -400,9 +405,10 @@ Path EvalState::checkSourcePath(const Path& path_) {
|
|||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
if (!found) {
|
||||
throw RestrictedPathError(
|
||||
"access to path '%1%' is forbidden in restricted mode", abspath);
|
||||
}
|
||||
|
||||
/* Resolve symlinks. */
|
||||
DLOG(INFO) << "checking access to '" << abspath << "'";
|
||||
|
@ -428,12 +434,14 @@ void EvalState::checkURI(const std::string& uri) {
|
|||
prefix. Thus, the prefix https://github.co does not permit
|
||||
access to https://github.com. Note: this allows 'http://' and
|
||||
'https://' as prefixes for any http/https URI. */
|
||||
for (auto& prefix : evalSettings.allowedUris.get())
|
||||
for (auto& prefix : evalSettings.allowedUris.get()) {
|
||||
if (uri == prefix ||
|
||||
(uri.size() > prefix.size() && prefix.size() > 0 &&
|
||||
hasPrefix(uri, prefix) &&
|
||||
(prefix[prefix.size() - 1] == '/' || uri[prefix.size()] == '/')))
|
||||
(prefix[prefix.size() - 1] == '/' || uri[prefix.size()] == '/'))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the URI is a path, then check it against allowedPaths as
|
||||
well. */
|
||||
|
@ -600,9 +608,10 @@ inline Value* EvalState::lookupVar(Env* env, const ExprVar& var, bool noEval) {
|
|||
}
|
||||
return j->value;
|
||||
}
|
||||
if (!env->prevWith)
|
||||
if (!env->prevWith) {
|
||||
throwUndefinedVarError("undefined variable '%1%' at %2%", var.name,
|
||||
var.pos);
|
||||
}
|
||||
for (size_t l = env->prevWith; l; --l, env = env->up) {
|
||||
;
|
||||
}
|
||||
|
@ -622,8 +631,9 @@ Value* EvalState::allocValue() {
|
|||
}
|
||||
|
||||
Env& EvalState::allocEnv(size_t size) {
|
||||
if (size > std::numeric_limits<decltype(Env::size)>::max())
|
||||
if (size > std::numeric_limits<decltype(Env::size)>::max()) {
|
||||
throw Error("environment size %d is too big", size);
|
||||
}
|
||||
|
||||
nrEnvs++;
|
||||
nrValuesInEnvs += size;
|
||||
|
@ -669,8 +679,9 @@ void EvalState::mkPos(Value& v, Pos* pos) {
|
|||
mkInt(*allocAttr(v, sLine), pos->line);
|
||||
mkInt(*allocAttr(v, sColumn), pos->column);
|
||||
v.attrs->sort();
|
||||
} else
|
||||
} else {
|
||||
mkNull(v);
|
||||
}
|
||||
}
|
||||
|
||||
/* Create a thunk for the delayed computation of the given expression
|
||||
|
@ -823,8 +834,9 @@ void ExprAttrs::eval(EvalState& state, Env& env, Value& v) {
|
|||
if (hasOverrides && !i.second.inherited) {
|
||||
vAttr = state.allocValue();
|
||||
mkThunk(*vAttr, env2, i.second.e);
|
||||
} else
|
||||
} else {
|
||||
vAttr = i.second.e->maybeThunk(state, i.second.inherited ? env : env2);
|
||||
}
|
||||
env2.values[displ++] = vAttr;
|
||||
v.attrs->push_back(Attr(i.first, vAttr, &i.second.pos));
|
||||
}
|
||||
|
@ -850,16 +862,18 @@ void ExprAttrs::eval(EvalState& state, Env& env, Value& v) {
|
|||
if (j != attrs.end()) {
|
||||
(*newBnds)[j->second.displ] = i;
|
||||
env2.values[j->second.displ] = i.value;
|
||||
} else
|
||||
} else {
|
||||
newBnds->push_back(i);
|
||||
}
|
||||
}
|
||||
newBnds->sort();
|
||||
v.attrs = newBnds;
|
||||
}
|
||||
} else {
|
||||
for (auto& i : attrs)
|
||||
for (auto& i : attrs) {
|
||||
v.attrs->push_back(
|
||||
Attr(i.first, i.second.e->maybeThunk(state, env), &i.second.pos));
|
||||
}
|
||||
}
|
||||
|
||||
/* Dynamic attrs apply *after* rec and __overrides. */
|
||||
|
@ -873,9 +887,10 @@ void ExprAttrs::eval(EvalState& state, Env& env, Value& v) {
|
|||
state.forceStringNoCtx(nameVal);
|
||||
Symbol nameSym = state.symbols.create(nameVal.string.s);
|
||||
Bindings::iterator j = v.attrs->find(nameSym);
|
||||
if (j != v.attrs->end())
|
||||
if (j != v.attrs->end()) {
|
||||
throwEvalError("dynamic attribute '%1%' at %2% already defined at %3%",
|
||||
nameSym, i.pos, *j->pos);
|
||||
}
|
||||
|
||||
i.valueExpr->setName(nameSym);
|
||||
/* Keep sorted order so find can catch duplicates */
|
||||
|
@ -895,17 +910,19 @@ void ExprLet::eval(EvalState& state, Env& env, Value& v) {
|
|||
while the inherited attributes are evaluated in the original
|
||||
environment. */
|
||||
size_t displ = 0;
|
||||
for (auto& i : attrs->attrs)
|
||||
for (auto& i : attrs->attrs) {
|
||||
env2.values[displ++] =
|
||||
i.second.e->maybeThunk(state, i.second.inherited ? env : env2);
|
||||
}
|
||||
|
||||
body->eval(state, env2, v);
|
||||
}
|
||||
|
||||
void ExprList::eval(EvalState& state, Env& env, Value& v) {
|
||||
state.mkList(v, elems.size());
|
||||
for (size_t n = 0; n < elems.size(); ++n)
|
||||
for (size_t n = 0; n < elems.size(); ++n) {
|
||||
v.listElems()[n] = elems[n]->maybeThunk(state, env);
|
||||
}
|
||||
}
|
||||
|
||||
void ExprVar::eval(EvalState& state, Env& env, Value& v) {
|
||||
|
@ -919,10 +936,11 @@ static string showAttrPath(EvalState& state, Env& env,
|
|||
std::ostringstream out;
|
||||
bool first = true;
|
||||
for (auto& i : attrPath) {
|
||||
if (!first)
|
||||
if (!first) {
|
||||
out << '.';
|
||||
else
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
try {
|
||||
out << getName(i, state, env);
|
||||
} catch (Error& e) {
|
||||
|
@ -956,8 +974,9 @@ void ExprSelect::eval(EvalState& state, Env& env, Value& v) {
|
|||
}
|
||||
} else {
|
||||
state.forceAttrs(*vAttrs, pos);
|
||||
if ((j = vAttrs->attrs->find(name)) == vAttrs->attrs->end())
|
||||
if ((j = vAttrs->attrs->find(name)) == vAttrs->attrs->end()) {
|
||||
throwEvalError("attribute '%1%' missing, at %2%", name, pos);
|
||||
}
|
||||
}
|
||||
vAttrs = j->value;
|
||||
pos2 = j->pos;
|
||||
|
@ -969,9 +988,10 @@ void ExprSelect::eval(EvalState& state, Env& env, Value& v) {
|
|||
state.forceValue(*vAttrs, (pos2 != NULL ? *pos2 : this->pos));
|
||||
|
||||
} catch (Error& e) {
|
||||
if (pos2 && pos2->file != state.sDerivationNix)
|
||||
if (pos2 && pos2->file != state.sDerivationNix) {
|
||||
addErrorPrefix(e, "while evaluating the attribute '%1%' at %2%:\n",
|
||||
showAttrPath(state, env, attrPath), *pos2);
|
||||
}
|
||||
throw;
|
||||
}
|
||||
|
||||
|
@ -1112,9 +1132,10 @@ void EvalState::callFunction(Value& fun, Value& arg, Value& v, const Pos& pos) {
|
|||
for (auto& i : lambda.formals->formals) {
|
||||
Bindings::iterator j = arg.attrs->find(i.name);
|
||||
if (j == arg.attrs->end()) {
|
||||
if (!i.def)
|
||||
if (!i.def) {
|
||||
throwTypeError("%1% called without required argument '%2%', at %3%",
|
||||
lambda, i.name, pos);
|
||||
}
|
||||
env2.values[displ++] = i.def->maybeThunk(*this, env2);
|
||||
} else {
|
||||
attrsUsed++;
|
||||
|
@ -1127,11 +1148,13 @@ void EvalState::callFunction(Value& fun, Value& arg, Value& v, const Pos& pos) {
|
|||
if (!lambda.formals->ellipsis && attrsUsed != arg.attrs->size()) {
|
||||
/* Nope, so show the first unexpected argument to the
|
||||
user. */
|
||||
for (auto& i : *arg.attrs)
|
||||
for (auto& i : *arg.attrs) {
|
||||
if (lambda.formals->argNames.find(i.name) ==
|
||||
lambda.formals->argNames.end())
|
||||
lambda.formals->argNames.end()) {
|
||||
throwTypeError("%1% called with unexpected argument '%2%', at %3%",
|
||||
lambda, i.name, pos);
|
||||
}
|
||||
}
|
||||
abort(); // can't happen
|
||||
}
|
||||
}
|
||||
|
@ -1143,15 +1166,17 @@ void EvalState::callFunction(Value& fun, Value& arg, Value& v, const Pos& pos) {
|
|||
|
||||
/* Evaluate the body. This is conditional on showTrace, because
|
||||
catching exceptions makes this function not tail-recursive. */
|
||||
if (settings.showTrace) try {
|
||||
if (settings.showTrace) {
|
||||
try {
|
||||
lambda.body->eval(*this, env2, v);
|
||||
} catch (Error& e) {
|
||||
addErrorPrefix(e, "while evaluating %1%, called from %2%:\n", lambda,
|
||||
pos);
|
||||
throw;
|
||||
}
|
||||
else
|
||||
} else {
|
||||
fun.lambda.fun->body->eval(*this, env2, v);
|
||||
}
|
||||
}
|
||||
|
||||
// Lifted out of callFunction() because it creates a temporary that
|
||||
|
@ -1181,13 +1206,14 @@ void EvalState::autoCallFunction(Bindings& args, Value& fun, Value& res) {
|
|||
|
||||
for (auto& i : fun.lambda.fun->formals->formals) {
|
||||
Bindings::iterator j = args.find(i.name);
|
||||
if (j != args.end())
|
||||
if (j != args.end()) {
|
||||
actualArgs->attrs->push_back(*j);
|
||||
else if (!i.def)
|
||||
} else if (!i.def) {
|
||||
throwTypeError(
|
||||
"cannot auto-call a function that has an argument without a default "
|
||||
"value ('%1%')",
|
||||
i.name);
|
||||
}
|
||||
}
|
||||
|
||||
actualArgs->attrs->sort();
|
||||
|
@ -1278,10 +1304,11 @@ void ExprOpUpdate::eval(EvalState& state, Env& env, Value& v) {
|
|||
v.attrs->push_back(*j);
|
||||
++i;
|
||||
++j;
|
||||
} else if (i->name < j->name)
|
||||
} else if (i->name < j->name) {
|
||||
v.attrs->push_back(*i++);
|
||||
else
|
||||
} else {
|
||||
v.attrs->push_back(*j++);
|
||||
}
|
||||
}
|
||||
|
||||
while (i != v1.attrs->end()) {
|
||||
|
@ -1364,20 +1391,23 @@ void ExprConcatStrings::eval(EvalState& state, Env& env, Value& v) {
|
|||
firstType = tFloat;
|
||||
nf = n;
|
||||
nf += vTmp.fpoint;
|
||||
} else
|
||||
} else {
|
||||
throwEvalError("cannot add %1% to an integer, at %2%", showType(vTmp),
|
||||
pos);
|
||||
}
|
||||
} else if (firstType == tFloat) {
|
||||
if (vTmp.type == tInt) {
|
||||
nf += vTmp.integer;
|
||||
} else if (vTmp.type == tFloat) {
|
||||
nf += vTmp.fpoint;
|
||||
} else
|
||||
} else {
|
||||
throwEvalError("cannot add %1% to a float, at %2%", showType(vTmp),
|
||||
pos);
|
||||
} else
|
||||
}
|
||||
} else {
|
||||
s << state.coerceToString(pos, vTmp, context, false,
|
||||
firstType == tString);
|
||||
}
|
||||
}
|
||||
|
||||
if (firstType == tInt) {
|
||||
|
@ -1385,11 +1415,12 @@ void ExprConcatStrings::eval(EvalState& state, Env& env, Value& v) {
|
|||
} else if (firstType == tFloat) {
|
||||
mkFloat(v, nf);
|
||||
} else if (firstType == tPath) {
|
||||
if (!context.empty())
|
||||
if (!context.empty()) {
|
||||
throwEvalError(
|
||||
"a string that refers to a store path cannot be appended to a path, "
|
||||
"at %1%",
|
||||
pos);
|
||||
}
|
||||
auto path = canonPath(s.str());
|
||||
mkPath(v, path.c_str());
|
||||
} else {
|
||||
|
@ -1415,13 +1446,15 @@ void EvalState::forceValueDeep(Value& v) {
|
|||
forceValue(v);
|
||||
|
||||
if (v.type == tAttrs) {
|
||||
for (auto& i : *v.attrs) try {
|
||||
for (auto& i : *v.attrs) {
|
||||
try {
|
||||
recurse(*i.value);
|
||||
} catch (Error& e) {
|
||||
addErrorPrefix(e, "while evaluating the attribute '%1%' at %2%:\n",
|
||||
i.name, *i.pos);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
} else if (v.isList()) {
|
||||
for (size_t n = 0; n < v.listSize(); ++n) {
|
||||
recurse(*v.listElems()[n]);
|
||||
|
@ -1486,10 +1519,11 @@ string EvalState::forceString(Value& v, const Pos& pos) {
|
|||
}
|
||||
|
||||
void copyContext(const Value& v, PathSet& context) {
|
||||
if (v.string.context)
|
||||
if (v.string.context) {
|
||||
for (const char** p = v.string.context; *p; ++p) {
|
||||
context.insert(*p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string EvalState::forceString(Value& v, PathSet& context, const Pos& pos) {
|
||||
|
@ -1501,16 +1535,17 @@ string EvalState::forceString(Value& v, PathSet& context, const Pos& pos) {
|
|||
string EvalState::forceStringNoCtx(Value& v, const Pos& pos) {
|
||||
string s = forceString(v, pos);
|
||||
if (v.string.context) {
|
||||
if (pos)
|
||||
if (pos) {
|
||||
throwEvalError(
|
||||
"the string '%1%' is not allowed to refer to a store path (such as "
|
||||
"'%2%'), at %3%",
|
||||
v.string.s, v.string.context[0], pos);
|
||||
else
|
||||
} else {
|
||||
throwEvalError(
|
||||
"the string '%1%' is not allowed to refer to a store path (such as "
|
||||
"'%2%')",
|
||||
v.string.s, v.string.context[0]);
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
@ -1567,13 +1602,15 @@ string EvalState::coerceToString(const Pos& pos, Value& v, PathSet& context,
|
|||
return *maybeString;
|
||||
}
|
||||
auto i = v.attrs->find(sOutPath);
|
||||
if (i == v.attrs->end())
|
||||
if (i == v.attrs->end()) {
|
||||
throwTypeError("cannot coerce a set to a string, at %1%", pos);
|
||||
}
|
||||
return coerceToString(pos, *i->value, context, coerceMore, copyToStore);
|
||||
}
|
||||
|
||||
if (v.type == tExternal)
|
||||
if (v.type == tExternal) {
|
||||
return v.external->coerceToString(pos, context, coerceMore, copyToStore);
|
||||
}
|
||||
|
||||
if (coerceMore) {
|
||||
/* Note that `false' is represented as an empty string for
|
||||
|
@ -1601,9 +1638,10 @@ string EvalState::coerceToString(const Pos& pos, Value& v, PathSet& context,
|
|||
copyToStore);
|
||||
if (n < v.listSize() - 1
|
||||
/* !!! not quite correct */
|
||||
&&
|
||||
(!v.listElems()[n]->isList() || v.listElems()[n]->listSize() != 0))
|
||||
&& (!v.listElems()[n]->isList() ||
|
||||
v.listElems()[n]->listSize() != 0)) {
|
||||
result += " ";
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -1613,13 +1651,14 @@ string EvalState::coerceToString(const Pos& pos, Value& v, PathSet& context,
|
|||
}
|
||||
|
||||
string EvalState::copyPathToStore(PathSet& context, const Path& path) {
|
||||
if (nix::isDerivation(path))
|
||||
if (nix::isDerivation(path)) {
|
||||
throwEvalError("file names are not allowed to end in '%1%'", drvExtension);
|
||||
}
|
||||
|
||||
Path dstPath;
|
||||
if (srcToStore[path] != "")
|
||||
if (srcToStore[path] != "") {
|
||||
dstPath = srcToStore[path];
|
||||
else {
|
||||
} else {
|
||||
dstPath =
|
||||
settings.readOnlyMode
|
||||
? store
|
||||
|
@ -1638,9 +1677,10 @@ string EvalState::copyPathToStore(PathSet& context, const Path& path) {
|
|||
|
||||
Path EvalState::coerceToPath(const Pos& pos, Value& v, PathSet& context) {
|
||||
string path = coerceToString(pos, v, context, false, false);
|
||||
if (path == "" || path[0] != '/')
|
||||
if (path == "" || path[0] != '/') {
|
||||
throwEvalError("string '%1%' doesn't represent an absolute path, at %2%",
|
||||
path, pos);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
|
@ -1827,10 +1867,11 @@ void EvalState::printStats() {
|
|||
auto list = topObj.list("functions");
|
||||
for (auto& i : functionCalls) {
|
||||
auto obj = list.object();
|
||||
if (i.first->name.set())
|
||||
if (i.first->name.set()) {
|
||||
obj.attr("name", (const string&)i.first->name);
|
||||
else
|
||||
} else {
|
||||
obj.attr("name", nullptr);
|
||||
}
|
||||
if (i.first->pos) {
|
||||
obj.attr("file", (const string&)i.first->pos.file);
|
||||
obj.attr("line", i.first->pos.line);
|
||||
|
@ -1885,10 +1926,11 @@ size_t valueSize(Value& v) {
|
|||
switch (v.type) {
|
||||
case tString:
|
||||
sz += doString(v.string.s);
|
||||
if (v.string.context)
|
||||
if (v.string.context) {
|
||||
for (const char** p = v.string.context; *p; ++p) {
|
||||
sz += doString(*p);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case tPath:
|
||||
sz += doString(v.path);
|
||||
|
@ -1908,8 +1950,9 @@ size_t valueSize(Value& v) {
|
|||
if (seen.find(v.listElems()) == seen.end()) {
|
||||
seen.insert(v.listElems());
|
||||
sz += v.listSize() * sizeof(Value*);
|
||||
for (size_t n = 0; n < v.listSize(); ++n)
|
||||
for (size_t n = 0; n < v.listSize(); ++n) {
|
||||
sz += doValue(*v.listElems()[n]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case tThunk:
|
||||
|
@ -1947,11 +1990,13 @@ size_t valueSize(Value& v) {
|
|||
|
||||
size_t sz = sizeof(Env) + sizeof(Value*) * env.size;
|
||||
|
||||
if (env.type != Env::HasWithExpr)
|
||||
for (size_t i = 0; i < env.size; ++i)
|
||||
if (env.type != Env::HasWithExpr) {
|
||||
for (size_t i = 0; i < env.size; ++i) {
|
||||
if (env.values[i]) {
|
||||
sz += doValue(*env.values[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (env.up) {
|
||||
sz += doEnv(*env.up);
|
||||
|
|
26
third_party/nix/src/libexpr/get-drvs.cc
vendored
26
third_party/nix/src/libexpr/get-drvs.cc
vendored
|
@ -25,18 +25,20 @@ DrvInfo::DrvInfo(EvalState& state, ref<Store> store,
|
|||
|
||||
name = storePathToName(drvPath);
|
||||
|
||||
if (spec.second.size() > 1)
|
||||
if (spec.second.size() > 1) {
|
||||
throw Error(
|
||||
"building more than one derivation output is not supported, in '%s'",
|
||||
drvPathWithOutputs);
|
||||
}
|
||||
|
||||
outputName = spec.second.empty() ? get(drv.env, "outputName", "out")
|
||||
: *spec.second.begin();
|
||||
|
||||
auto i = drv.outputs.find(outputName);
|
||||
if (i == drv.outputs.end())
|
||||
if (i == drv.outputs.end()) {
|
||||
throw Error("derivation '%s' does not have output '%s'", drvPath,
|
||||
outputName);
|
||||
}
|
||||
|
||||
outPath = i->second.path;
|
||||
}
|
||||
|
@ -110,8 +112,9 @@ DrvInfo::Outputs DrvInfo::queryOutputs(bool onlyOutputsToInstall) {
|
|||
outputs[name] =
|
||||
state->coerceToPath(*outPath->pos, *outPath->value, context);
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
outputs["out"] = queryOutPath();
|
||||
}
|
||||
}
|
||||
if (!onlyOutputsToInstall || !attrs) {
|
||||
return outputs;
|
||||
|
@ -363,10 +366,11 @@ static void getDerivations(EvalState& state, Value& vIn,
|
|||
state.autoCallFunction(autoArgs, vIn, v);
|
||||
|
||||
/* Process the expression. */
|
||||
if (!getDerivation(state, v, pathPrefix, drvs, done, ignoreAssertionFailures))
|
||||
if (!getDerivation(state, v, pathPrefix, drvs, done,
|
||||
ignoreAssertionFailures)) {
|
||||
;
|
||||
|
||||
else if (v.type == tAttrs) {
|
||||
} else if (v.type == tAttrs) {
|
||||
/* !!! undocumented hackery to support combining channels in
|
||||
nix-env.cc. */
|
||||
bool combineChannels =
|
||||
|
@ -384,11 +388,11 @@ static void getDerivations(EvalState& state, Value& vIn,
|
|||
continue;
|
||||
}
|
||||
string pathPrefix2 = addToPath(pathPrefix, i->name);
|
||||
if (combineChannels)
|
||||
if (combineChannels) {
|
||||
getDerivations(state, *i->value, pathPrefix2, autoArgs, drvs, done,
|
||||
ignoreAssertionFailures);
|
||||
else if (getDerivation(state, *i->value, pathPrefix2, drvs, done,
|
||||
ignoreAssertionFailures)) {
|
||||
} else if (getDerivation(state, *i->value, pathPrefix2, drvs, done,
|
||||
ignoreAssertionFailures)) {
|
||||
/* If the value of this attribute is itself a set,
|
||||
should we recurse into it? => Only if it has a
|
||||
`recurseForDerivations = true' attribute. */
|
||||
|
@ -396,9 +400,10 @@ static void getDerivations(EvalState& state, Value& vIn,
|
|||
Bindings::iterator j = i->value->attrs->find(
|
||||
state.symbols.create("recurseForDerivations"));
|
||||
if (j != i->value->attrs->end() &&
|
||||
state.forceBool(*j->value, *j->pos))
|
||||
state.forceBool(*j->value, *j->pos)) {
|
||||
getDerivations(state, *i->value, pathPrefix2, autoArgs, drvs, done,
|
||||
ignoreAssertionFailures);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -408,9 +413,10 @@ static void getDerivations(EvalState& state, Value& vIn,
|
|||
for (unsigned int n = 0; n < v.listSize(); ++n) {
|
||||
string pathPrefix2 = addToPath(pathPrefix, (format("%1%") % n).str());
|
||||
if (getDerivation(state, *v.listElems()[n], pathPrefix2, drvs, done,
|
||||
ignoreAssertionFailures))
|
||||
ignoreAssertionFailures)) {
|
||||
getDerivations(state, *v.listElems()[n], pathPrefix2, autoArgs, drvs,
|
||||
done, ignoreAssertionFailures);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
40
third_party/nix/src/libexpr/json-to-value.cc
vendored
40
third_party/nix/src/libexpr/json-to-value.cc
vendored
|
@ -21,29 +21,30 @@ static string parseJSONString(const char*& s) {
|
|||
}
|
||||
if (*s == '\\') {
|
||||
s++;
|
||||
if (*s == '"')
|
||||
if (*s == '"') {
|
||||
res += '"';
|
||||
else if (*s == '\\')
|
||||
} else if (*s == '\\') {
|
||||
res += '\\';
|
||||
else if (*s == '/')
|
||||
} else if (*s == '/') {
|
||||
res += '/';
|
||||
else if (*s == '/')
|
||||
} else if (*s == '/') {
|
||||
res += '/';
|
||||
else if (*s == 'b')
|
||||
} else if (*s == 'b') {
|
||||
res += '\b';
|
||||
else if (*s == 'f')
|
||||
} else if (*s == 'f') {
|
||||
res += '\f';
|
||||
else if (*s == 'n')
|
||||
} else if (*s == 'n') {
|
||||
res += '\n';
|
||||
else if (*s == 'r')
|
||||
} else if (*s == 'r') {
|
||||
res += '\r';
|
||||
else if (*s == 't')
|
||||
} else if (*s == 't') {
|
||||
res += '\t';
|
||||
else if (*s == 'u')
|
||||
} else if (*s == 'u') {
|
||||
throw JSONParseError(
|
||||
"\\u characters in JSON strings are currently not supported");
|
||||
else
|
||||
} else {
|
||||
throw JSONParseError("invalid escaped character in JSON string");
|
||||
}
|
||||
s++;
|
||||
} else {
|
||||
res += *s++;
|
||||
|
@ -76,8 +77,9 @@ static void parseJSON(EvalState& state, const char*& s, Value& v) {
|
|||
if (*s == ']') {
|
||||
break;
|
||||
}
|
||||
if (*s != ',')
|
||||
if (*s != ',') {
|
||||
throw JSONParseError("expected ',' or ']' after JSON array element");
|
||||
}
|
||||
s++;
|
||||
}
|
||||
s++;
|
||||
|
@ -108,8 +110,9 @@ static void parseJSON(EvalState& state, const char*& s, Value& v) {
|
|||
if (*s == '}') {
|
||||
break;
|
||||
}
|
||||
if (*s != ',')
|
||||
if (*s != ',') {
|
||||
throw JSONParseError("expected ',' or '}' after JSON member");
|
||||
}
|
||||
s++;
|
||||
}
|
||||
state.mkAttrs(v, attrs.size());
|
||||
|
@ -137,10 +140,11 @@ static void parseJSON(EvalState& state, const char*& s, Value& v) {
|
|||
}
|
||||
|
||||
try {
|
||||
if (number_type == tFloat)
|
||||
if (number_type == tFloat) {
|
||||
mkFloat(v, stod(tmp_number));
|
||||
else
|
||||
} else {
|
||||
mkInt(v, stol(tmp_number));
|
||||
}
|
||||
} catch (std::invalid_argument& e) {
|
||||
throw JSONParseError("invalid JSON number");
|
||||
} catch (std::out_of_range& e) {
|
||||
|
@ -163,17 +167,19 @@ static void parseJSON(EvalState& state, const char*& s, Value& v) {
|
|||
mkNull(v);
|
||||
}
|
||||
|
||||
else
|
||||
else {
|
||||
throw JSONParseError("unrecognised JSON value");
|
||||
}
|
||||
}
|
||||
|
||||
void parseJSON(EvalState& state, const string& s_, Value& v) {
|
||||
const char* s = s_.c_str();
|
||||
parseJSON(state, s, v);
|
||||
skipWhitespace(s);
|
||||
if (*s)
|
||||
if (*s) {
|
||||
throw JSONParseError(
|
||||
format("expected end-of-string while parsing JSON value: %1%") % s);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace nix
|
||||
|
|
35
third_party/nix/src/libexpr/names.cc
vendored
35
third_party/nix/src/libexpr/names.cc
vendored
|
@ -25,9 +25,10 @@ DrvName::DrvName(const string& s) : hits(0) {
|
|||
|
||||
bool DrvName::matches(DrvName& n) {
|
||||
if (name != "*") {
|
||||
if (!regex)
|
||||
if (!regex) {
|
||||
regex = std::unique_ptr<std::regex>(
|
||||
new std::regex(name, std::regex::extended));
|
||||
}
|
||||
if (!std::regex_match(n.name, *regex)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -41,7 +42,9 @@ bool DrvName::matches(DrvName& n) {
|
|||
string nextComponent(string::const_iterator& p,
|
||||
const string::const_iterator end) {
|
||||
/* Skip any dots and dashes (component separators). */
|
||||
while (p != end && (*p == '.' || *p == '-')) ++p;
|
||||
while (p != end && (*p == '.' || *p == '-')) {
|
||||
++p;
|
||||
}
|
||||
|
||||
if (p == end) {
|
||||
return "";
|
||||
|
@ -51,10 +54,15 @@ string nextComponent(string::const_iterator& p,
|
|||
of digits. Otherwise, consume the longest sequence of
|
||||
non-digit, non-separator characters. */
|
||||
string s;
|
||||
if (isdigit(*p))
|
||||
while (p != end && isdigit(*p)) s += *p++;
|
||||
else
|
||||
while (p != end && (!isdigit(*p) && *p != '.' && *p != '-')) s += *p++;
|
||||
if (isdigit(*p)) {
|
||||
while (p != end && isdigit(*p)) {
|
||||
s += *p++;
|
||||
}
|
||||
} else {
|
||||
while (p != end && (!isdigit(*p) && *p != '.' && *p != '-')) {
|
||||
s += *p++;
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
@ -65,14 +73,14 @@ static bool componentsLT(const string& c1, const string& c2) {
|
|||
|
||||
if (c1Num && c2Num) {
|
||||
return n1 < n2;
|
||||
} else if (c1 == "" && c2Num)
|
||||
} else if (c1 == "" && c2Num) {
|
||||
return true;
|
||||
else if (c1 == "pre" && c2 != "pre")
|
||||
} else if (c1 == "pre" && c2 != "pre") {
|
||||
return true;
|
||||
else if (c2 == "pre")
|
||||
} else if (c2 == "pre") {
|
||||
return false;
|
||||
/* Assume that `2.3a' < `2.3.1'. */
|
||||
else if (c2Num) {
|
||||
/* Assume that `2.3a' < `2.3.1'. */
|
||||
} else if (c2Num) {
|
||||
return true;
|
||||
} else if (c1Num) {
|
||||
return false;
|
||||
|
@ -88,10 +96,11 @@ int compareVersions(const string& v1, const string& v2) {
|
|||
while (p1 != v1.end() || p2 != v2.end()) {
|
||||
string c1 = nextComponent(p1, v1.end());
|
||||
string c2 = nextComponent(p2, v2.end());
|
||||
if (componentsLT(c1, c2))
|
||||
if (componentsLT(c1, c2)) {
|
||||
return -1;
|
||||
else if (componentsLT(c2, c1))
|
||||
} else if (componentsLT(c2, c1)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
80
third_party/nix/src/libexpr/nixexpr.cc
vendored
80
third_party/nix/src/libexpr/nixexpr.cc
vendored
|
@ -16,37 +16,40 @@ std::ostream& operator<<(std::ostream& str, const Expr& e) {
|
|||
|
||||
static void showString(std::ostream& str, const string& s) {
|
||||
str << '"';
|
||||
for (auto c : (string)s)
|
||||
if (c == '"' || c == '\\' || c == '$')
|
||||
for (auto c : (string)s) {
|
||||
if (c == '"' || c == '\\' || c == '$') {
|
||||
str << "\\" << c;
|
||||
else if (c == '\n')
|
||||
} else if (c == '\n') {
|
||||
str << "\\n";
|
||||
else if (c == '\r')
|
||||
} else if (c == '\r') {
|
||||
str << "\\r";
|
||||
else if (c == '\t')
|
||||
} else if (c == '\t') {
|
||||
str << "\\t";
|
||||
else
|
||||
} else {
|
||||
str << c;
|
||||
}
|
||||
}
|
||||
str << '"';
|
||||
}
|
||||
|
||||
static void showId(std::ostream& str, const string& s) {
|
||||
if (s.empty())
|
||||
if (s.empty()) {
|
||||
str << "\"\"";
|
||||
else if (s == "if") // FIXME: handle other keywords
|
||||
} else if (s == "if") { // FIXME: handle other keywords
|
||||
str << '"' << s << '"';
|
||||
else {
|
||||
} else {
|
||||
char c = s[0];
|
||||
if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_')) {
|
||||
showString(str, s);
|
||||
return;
|
||||
}
|
||||
for (auto c : s)
|
||||
for (auto c : s) {
|
||||
if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
|
||||
(c >= '0' && c <= '9') || c == '_' || c == '\'' || c == '-')) {
|
||||
showString(str, s);
|
||||
return;
|
||||
}
|
||||
}
|
||||
str << s;
|
||||
}
|
||||
}
|
||||
|
@ -84,14 +87,17 @@ void ExprAttrs::show(std::ostream& str) const {
|
|||
str << "rec ";
|
||||
}
|
||||
str << "{ ";
|
||||
for (auto& i : attrs)
|
||||
if (i.second.inherited)
|
||||
for (auto& i : attrs) {
|
||||
if (i.second.inherited) {
|
||||
str << "inherit " << i.first << " "
|
||||
<< "; ";
|
||||
else
|
||||
} else {
|
||||
str << i.first << " = " << *i.second.e << "; ";
|
||||
for (auto& i : dynamicAttrs)
|
||||
}
|
||||
}
|
||||
for (auto& i : dynamicAttrs) {
|
||||
str << "\"${" << *i.nameExpr << "}\" = " << *i.valueExpr << "; ";
|
||||
}
|
||||
str << "}";
|
||||
}
|
||||
|
||||
|
@ -109,10 +115,11 @@ void ExprLambda::show(std::ostream& str) const {
|
|||
str << "{ ";
|
||||
bool first = true;
|
||||
for (auto& i : formals->formals) {
|
||||
if (first)
|
||||
if (first) {
|
||||
first = false;
|
||||
else
|
||||
} else {
|
||||
str << ", ";
|
||||
}
|
||||
str << i.name;
|
||||
if (i.def) {
|
||||
str << " ? " << *i.def;
|
||||
|
@ -137,11 +144,13 @@ void ExprLambda::show(std::ostream& str) const {
|
|||
|
||||
void ExprLet::show(std::ostream& str) const {
|
||||
str << "(let ";
|
||||
for (auto& i : attrs->attrs)
|
||||
for (auto& i : attrs->attrs) {
|
||||
if (i.second.inherited) {
|
||||
str << "inherit " << i.first << "; ";
|
||||
} else
|
||||
} else {
|
||||
str << i.first << " = " << *i.second.e << "; ";
|
||||
}
|
||||
}
|
||||
str << "in " << *body << ")";
|
||||
}
|
||||
|
||||
|
@ -163,10 +172,11 @@ void ExprConcatStrings::show(std::ostream& str) const {
|
|||
bool first = true;
|
||||
str << "(";
|
||||
for (auto& i : *es) {
|
||||
if (first)
|
||||
if (first) {
|
||||
first = false;
|
||||
else
|
||||
} else {
|
||||
str << " + ";
|
||||
}
|
||||
str << *i;
|
||||
}
|
||||
str << ")";
|
||||
|
@ -175,12 +185,13 @@ void ExprConcatStrings::show(std::ostream& str) const {
|
|||
void ExprPos::show(std::ostream& str) const { str << "__curPos"; }
|
||||
|
||||
std::ostream& operator<<(std::ostream& str, const Pos& pos) {
|
||||
if (!pos)
|
||||
if (!pos) {
|
||||
str << "undefined position";
|
||||
else
|
||||
} else {
|
||||
str << (format(ANSI_BOLD "%1%" ANSI_NORMAL ":%2%:%3%") % (string)pos.file %
|
||||
pos.line % pos.column)
|
||||
.str();
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
|
@ -188,14 +199,16 @@ string showAttrPath(const AttrPath& attrPath) {
|
|||
std::ostringstream out;
|
||||
bool first = true;
|
||||
for (auto& i : attrPath) {
|
||||
if (!first)
|
||||
if (!first) {
|
||||
out << '.';
|
||||
else
|
||||
} else {
|
||||
first = false;
|
||||
if (i.symbol.set())
|
||||
}
|
||||
if (i.symbol.set()) {
|
||||
out << i.symbol;
|
||||
else
|
||||
} else {
|
||||
out << "\"${" << *i.expr << "}\"";
|
||||
}
|
||||
}
|
||||
return out.str();
|
||||
}
|
||||
|
@ -239,9 +252,10 @@ void ExprVar::bindVars(const StaticEnv& env) {
|
|||
/* Otherwise, the variable must be obtained from the nearest
|
||||
enclosing `with'. If there is no `with', then we can issue an
|
||||
"undefined variable" error now. */
|
||||
if (withLevel == -1)
|
||||
if (withLevel == -1) {
|
||||
throw UndefinedVarError(format("undefined variable '%1%' at %2%") % name %
|
||||
pos);
|
||||
}
|
||||
|
||||
fromWith = true;
|
||||
this->level = withLevel;
|
||||
|
@ -252,18 +266,20 @@ void ExprSelect::bindVars(const StaticEnv& env) {
|
|||
if (def) {
|
||||
def->bindVars(env);
|
||||
}
|
||||
for (auto& i : attrPath)
|
||||
for (auto& i : attrPath) {
|
||||
if (!i.symbol.set()) {
|
||||
i.expr->bindVars(env);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ExprOpHasAttr::bindVars(const StaticEnv& env) {
|
||||
e->bindVars(env);
|
||||
for (auto& i : attrPath)
|
||||
for (auto& i : attrPath) {
|
||||
if (!i.symbol.set()) {
|
||||
i.expr->bindVars(env);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ExprAttrs::bindVars(const StaticEnv& env) {
|
||||
|
@ -315,10 +331,11 @@ void ExprLambda::bindVars(const StaticEnv& env) {
|
|||
newEnv.vars[i.name] = displ++;
|
||||
}
|
||||
|
||||
for (auto& i : formals->formals)
|
||||
for (auto& i : formals->formals) {
|
||||
if (i.def) {
|
||||
i.def->bindVars(newEnv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
body->bindVars(newEnv);
|
||||
|
@ -332,8 +349,9 @@ void ExprLet::bindVars(const StaticEnv& env) {
|
|||
newEnv.vars[i.first] = i.second.displ = displ++;
|
||||
}
|
||||
|
||||
for (auto& i : attrs->attrs)
|
||||
for (auto& i : attrs->attrs) {
|
||||
i.second.e->bindVars(i.second.inherited ? env : newEnv);
|
||||
}
|
||||
|
||||
body->bindVars(newEnv);
|
||||
}
|
||||
|
|
227
third_party/nix/src/libexpr/primops.cc
vendored
227
third_party/nix/src/libexpr/primops.cc
vendored
|
@ -37,8 +37,9 @@ std::pair<string, string> decodeContext(const string& s) {
|
|||
size_t index = s.find("!", 1);
|
||||
return std::pair<string, string>(string(s, index + 1),
|
||||
string(s, 1, index - 1));
|
||||
} else
|
||||
} else {
|
||||
return std::pair<string, string>(s.at(0) == '/' ? s : string(s, 1), "");
|
||||
}
|
||||
}
|
||||
|
||||
InvalidPathError::InvalidPathError(const Path& path)
|
||||
|
@ -62,9 +63,10 @@ void EvalState::realiseContext(const PathSet& context) {
|
|||
if (allowedPaths) {
|
||||
auto drv = store->derivationFromPath(decoded.first);
|
||||
DerivationOutputs::iterator i = drv.outputs.find(decoded.second);
|
||||
if (i == drv.outputs.end())
|
||||
if (i == drv.outputs.end()) {
|
||||
throw Error("derivation '%s' does not have an output named '%s'",
|
||||
decoded.first, decoded.second);
|
||||
}
|
||||
allowedPaths->insert(i->second.path);
|
||||
}
|
||||
}
|
||||
|
@ -74,10 +76,11 @@ void EvalState::realiseContext(const PathSet& context) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!evalSettings.enableImportFromDerivation)
|
||||
if (!evalSettings.enableImportFromDerivation) {
|
||||
throw EvalError(format("attempted to realize '%1%' during evaluation but "
|
||||
"'allow-import-from-derivation' is false") %
|
||||
*(drvs.begin()));
|
||||
}
|
||||
|
||||
/* For performance, prefetch all substitute info. */
|
||||
PathSet willBuild, willSubstitute, unknown;
|
||||
|
@ -178,20 +181,22 @@ void prim_importNative(EvalState& state, const Pos& pos, Value** args,
|
|||
string sym = state.forceStringNoCtx(*args[1], pos);
|
||||
|
||||
void* handle = dlopen(path.c_str(), RTLD_LAZY | RTLD_LOCAL);
|
||||
if (!handle)
|
||||
if (!handle) {
|
||||
throw EvalError(format("could not open '%1%': %2%") % path % dlerror());
|
||||
}
|
||||
|
||||
dlerror();
|
||||
ValueInitializer func = (ValueInitializer)dlsym(handle, sym.c_str());
|
||||
if (!func) {
|
||||
char* message = dlerror();
|
||||
if (message)
|
||||
if (message) {
|
||||
throw EvalError(format("could not load symbol '%1%' from '%2%': %3%") %
|
||||
sym % path % message);
|
||||
else
|
||||
} else {
|
||||
throw EvalError(format("symbol '%1%' from '%2%' resolved to NULL when a "
|
||||
"function pointer was expected") %
|
||||
sym % path);
|
||||
}
|
||||
}
|
||||
|
||||
(func)(state, v);
|
||||
|
@ -356,9 +361,10 @@ struct CompareValues {
|
|||
if (v1->type == tInt && v2->type == tFloat) {
|
||||
return v1->integer < v2->fpoint;
|
||||
}
|
||||
if (v1->type != v2->type)
|
||||
if (v1->type != v2->type) {
|
||||
throw EvalError(format("cannot compare %1% with %2%") % showType(*v1) %
|
||||
showType(*v2));
|
||||
}
|
||||
switch (v1->type) {
|
||||
case tInt:
|
||||
return v1->integer < v2->integer;
|
||||
|
@ -388,19 +394,22 @@ static void prim_genericClosure(EvalState& state, const Pos& pos, Value** args,
|
|||
/* Get the start set. */
|
||||
Bindings::iterator startSet =
|
||||
args[0]->attrs->find(state.symbols.create("startSet"));
|
||||
if (startSet == args[0]->attrs->end())
|
||||
if (startSet == args[0]->attrs->end()) {
|
||||
throw EvalError(format("attribute 'startSet' required, at %1%") % pos);
|
||||
}
|
||||
state.forceList(*startSet->value, pos);
|
||||
|
||||
ValueList workSet;
|
||||
for (unsigned int n = 0; n < startSet->value->listSize(); ++n)
|
||||
for (unsigned int n = 0; n < startSet->value->listSize(); ++n) {
|
||||
workSet.push_back(startSet->value->listElems()[n]);
|
||||
}
|
||||
|
||||
/* Get the operator. */
|
||||
Bindings::iterator op =
|
||||
args[0]->attrs->find(state.symbols.create("operator"));
|
||||
if (op == args[0]->attrs->end())
|
||||
if (op == args[0]->attrs->end()) {
|
||||
throw EvalError(format("attribute 'operator' required, at %1%") % pos);
|
||||
}
|
||||
state.forceValue(*op->value);
|
||||
|
||||
/* Construct the closure by applying the operator to element of
|
||||
|
@ -417,8 +426,9 @@ static void prim_genericClosure(EvalState& state, const Pos& pos, Value** args,
|
|||
state.forceAttrs(*e, pos);
|
||||
|
||||
Bindings::iterator key = e->attrs->find(state.symbols.create("key"));
|
||||
if (key == e->attrs->end())
|
||||
if (key == e->attrs->end()) {
|
||||
throw EvalError(format("attribute 'key' required, at %1%") % pos);
|
||||
}
|
||||
state.forceValue(*key->value);
|
||||
|
||||
if (doneKeys.find(key->value) != doneKeys.end()) {
|
||||
|
@ -551,8 +561,9 @@ static void prim_derivationStrict(EvalState& state, const Pos& pos,
|
|||
|
||||
/* Figure out the name first (for stack backtraces). */
|
||||
Bindings::iterator attr = args[0]->attrs->find(state.sName);
|
||||
if (attr == args[0]->attrs->end())
|
||||
if (attr == args[0]->attrs->end()) {
|
||||
throw EvalError(format("required attribute 'name' missing, at %1%") % pos);
|
||||
}
|
||||
string drvName;
|
||||
Pos& posDrvName(*attr->pos);
|
||||
try {
|
||||
|
@ -568,8 +579,9 @@ static void prim_derivationStrict(EvalState& state, const Pos& pos,
|
|||
std::ostringstream jsonBuf;
|
||||
std::unique_ptr<JSONObject> jsonObject;
|
||||
attr = args[0]->attrs->find(state.sStructuredAttrs);
|
||||
if (attr != args[0]->attrs->end() && state.forceBool(*attr->value, pos))
|
||||
if (attr != args[0]->attrs->end() && state.forceBool(*attr->value, pos)) {
|
||||
jsonObject = std::make_unique<JSONObject>(jsonBuf);
|
||||
}
|
||||
|
||||
/* Check whether null attributes should be ignored. */
|
||||
bool ignoreNulls = false;
|
||||
|
@ -597,37 +609,41 @@ static void prim_derivationStrict(EvalState& state, const Pos& pos,
|
|||
const string& key = i->name;
|
||||
|
||||
auto handleHashMode = [&](const std::string& s) {
|
||||
if (s == "recursive")
|
||||
if (s == "recursive") {
|
||||
outputHashRecursive = true;
|
||||
else if (s == "flat")
|
||||
} else if (s == "flat") {
|
||||
outputHashRecursive = false;
|
||||
else
|
||||
} else {
|
||||
throw EvalError(
|
||||
"invalid value '%s' for 'outputHashMode' attribute, at %s", s,
|
||||
posDrvName);
|
||||
}
|
||||
};
|
||||
|
||||
auto handleOutputs = [&](const Strings& ss) {
|
||||
outputs.clear();
|
||||
for (auto& j : ss) {
|
||||
if (outputs.find(j) != outputs.end())
|
||||
if (outputs.find(j) != outputs.end()) {
|
||||
throw EvalError(format("duplicate derivation output '%1%', at %2%") %
|
||||
j % posDrvName);
|
||||
}
|
||||
/* !!! Check whether j is a valid attribute
|
||||
name. */
|
||||
/* Derivations cannot be named ‘drv’, because
|
||||
then we'd have an attribute ‘drvPath’ in
|
||||
the resulting set. */
|
||||
if (j == "drv")
|
||||
if (j == "drv") {
|
||||
throw EvalError(
|
||||
format("invalid derivation output name 'drv', at %1%") %
|
||||
posDrvName);
|
||||
}
|
||||
outputs.insert(j);
|
||||
}
|
||||
if (outputs.empty())
|
||||
if (outputs.empty()) {
|
||||
throw EvalError(
|
||||
format("derivation cannot have an empty set of outputs, at %1%") %
|
||||
posDrvName);
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
|
@ -660,41 +676,43 @@ static void prim_derivationStrict(EvalState& state, const Pos& pos,
|
|||
auto placeholder(jsonObject->placeholder(key));
|
||||
printValueAsJSON(state, true, *i->value, placeholder, context);
|
||||
|
||||
if (i->name == state.sBuilder)
|
||||
if (i->name == state.sBuilder) {
|
||||
drv.builder = state.forceString(*i->value, context, posDrvName);
|
||||
else if (i->name == state.sSystem)
|
||||
} else if (i->name == state.sSystem) {
|
||||
drv.platform = state.forceStringNoCtx(*i->value, posDrvName);
|
||||
else if (i->name == state.sOutputHash)
|
||||
} else if (i->name == state.sOutputHash) {
|
||||
outputHash = state.forceStringNoCtx(*i->value, posDrvName);
|
||||
else if (i->name == state.sOutputHashAlgo)
|
||||
} else if (i->name == state.sOutputHashAlgo) {
|
||||
outputHashAlgo = state.forceStringNoCtx(*i->value, posDrvName);
|
||||
else if (i->name == state.sOutputHashMode)
|
||||
} else if (i->name == state.sOutputHashMode) {
|
||||
handleHashMode(state.forceStringNoCtx(*i->value, posDrvName));
|
||||
else if (i->name == state.sOutputs) {
|
||||
} else if (i->name == state.sOutputs) {
|
||||
/* Require ‘outputs’ to be a list of strings. */
|
||||
state.forceList(*i->value, posDrvName);
|
||||
Strings ss;
|
||||
for (unsigned int n = 0; n < i->value->listSize(); ++n)
|
||||
for (unsigned int n = 0; n < i->value->listSize(); ++n) {
|
||||
ss.emplace_back(state.forceStringNoCtx(*i->value->listElems()[n],
|
||||
posDrvName));
|
||||
}
|
||||
handleOutputs(ss);
|
||||
}
|
||||
|
||||
} else {
|
||||
auto s = state.coerceToString(posDrvName, *i->value, context, true);
|
||||
drv.env.emplace(key, s);
|
||||
if (i->name == state.sBuilder)
|
||||
if (i->name == state.sBuilder) {
|
||||
drv.builder = s;
|
||||
else if (i->name == state.sSystem)
|
||||
} else if (i->name == state.sSystem) {
|
||||
drv.platform = s;
|
||||
else if (i->name == state.sOutputHash)
|
||||
} else if (i->name == state.sOutputHash) {
|
||||
outputHash = s;
|
||||
else if (i->name == state.sOutputHashAlgo)
|
||||
} else if (i->name == state.sOutputHashAlgo) {
|
||||
outputHashAlgo = s;
|
||||
else if (i->name == state.sOutputHashMode)
|
||||
} else if (i->name == state.sOutputHashMode) {
|
||||
handleHashMode(s);
|
||||
else if (i->name == state.sOutputs)
|
||||
} else if (i->name == state.sOutputs) {
|
||||
handleOutputs(tokenizeString<Strings>(s));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -728,8 +746,9 @@ static void prim_derivationStrict(EvalState& state, const Pos& pos,
|
|||
state.store->computeFSClosure(string(path, 1), refs);
|
||||
for (auto& j : refs) {
|
||||
drv.inputSrcs.insert(j);
|
||||
if (isDerivation(j))
|
||||
if (isDerivation(j)) {
|
||||
drv.inputDrvs[j] = state.store->queryDerivationOutputNames(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -740,31 +759,36 @@ static void prim_derivationStrict(EvalState& state, const Pos& pos,
|
|||
}
|
||||
|
||||
/* Otherwise it's a source file. */
|
||||
else
|
||||
else {
|
||||
drv.inputSrcs.insert(path);
|
||||
}
|
||||
}
|
||||
|
||||
/* Do we have all required attributes? */
|
||||
if (drv.builder == "")
|
||||
if (drv.builder == "") {
|
||||
throw EvalError(format("required attribute 'builder' missing, at %1%") %
|
||||
posDrvName);
|
||||
if (drv.platform == "")
|
||||
}
|
||||
if (drv.platform == "") {
|
||||
throw EvalError(format("required attribute 'system' missing, at %1%") %
|
||||
posDrvName);
|
||||
}
|
||||
|
||||
/* Check whether the derivation name is valid. */
|
||||
checkStoreName(drvName);
|
||||
if (isDerivation(drvName))
|
||||
if (isDerivation(drvName)) {
|
||||
throw EvalError(
|
||||
format("derivation names are not allowed to end in '%1%', at %2%") %
|
||||
drvExtension % posDrvName);
|
||||
}
|
||||
|
||||
if (outputHash) {
|
||||
/* Handle fixed-output derivations. */
|
||||
if (outputs.size() != 1 || *(outputs.begin()) != "out")
|
||||
if (outputs.size() != 1 || *(outputs.begin()) != "out") {
|
||||
throw Error(format("multiple outputs are not supported in fixed-output "
|
||||
"derivations, at %1%") %
|
||||
posDrvName);
|
||||
}
|
||||
|
||||
HashType ht =
|
||||
outputHashAlgo.empty() ? htUnknown : parseHashType(outputHashAlgo);
|
||||
|
@ -797,7 +821,7 @@ static void prim_derivationStrict(EvalState& state, const Pos& pos,
|
|||
path. */
|
||||
Hash h = hashDerivationModulo(*state.store, drv);
|
||||
|
||||
for (auto& i : drv.outputs)
|
||||
for (auto& i : drv.outputs) {
|
||||
if (i.second.path == "") {
|
||||
Path outPath = state.store->makeOutputPath(i.first, h, drvName);
|
||||
if (!jsonObject) {
|
||||
|
@ -805,6 +829,7 @@ static void prim_derivationStrict(EvalState& state, const Pos& pos,
|
|||
}
|
||||
i.second.path = outPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Write the resulting term into the Nix store directory. */
|
||||
|
@ -868,9 +893,10 @@ static void prim_storePath(EvalState& state, const Pos& pos, Value** args,
|
|||
if (!state.store->isStorePath(path)) {
|
||||
path = canonPath(path, true);
|
||||
}
|
||||
if (!state.store->isInStore(path))
|
||||
if (!state.store->isInStore(path)) {
|
||||
throw EvalError(format("path '%1%' is not in the Nix store, at %2%") %
|
||||
path % pos);
|
||||
}
|
||||
Path path2 = state.store->toStorePath(path);
|
||||
if (!settings.readOnlyMode) {
|
||||
state.store->ensurePath(path2);
|
||||
|
@ -939,10 +965,11 @@ static void prim_readFile(EvalState& state, const Pos& pos, Value** args,
|
|||
path % e.path % pos);
|
||||
}
|
||||
string s = readFile(state.checkSourcePath(state.toRealPath(path, context)));
|
||||
if (s.find((char)0) != string::npos)
|
||||
if (s.find((char)0) != string::npos) {
|
||||
throw Error(format("the contents of the file '%1%' cannot be represented "
|
||||
"as a Nix string") %
|
||||
path);
|
||||
}
|
||||
mkString(v, s.c_str());
|
||||
}
|
||||
|
||||
|
@ -965,8 +992,9 @@ static void prim_findFile(EvalState& state, const Pos& pos, Value** args,
|
|||
}
|
||||
|
||||
i = v2.attrs->find(state.symbols.create("path"));
|
||||
if (i == v2.attrs->end())
|
||||
if (i == v2.attrs->end()) {
|
||||
throw EvalError(format("attribute 'path' missing, at %1%") % pos);
|
||||
}
|
||||
|
||||
PathSet context;
|
||||
string path = state.coerceToString(pos, *i->value, context, false, false);
|
||||
|
@ -993,8 +1021,9 @@ static void prim_hashFile(EvalState& state, const Pos& pos, Value** args,
|
|||
Value& v) {
|
||||
string type = state.forceStringNoCtx(*args[0], pos);
|
||||
HashType ht = parseHashType(type);
|
||||
if (ht == htUnknown)
|
||||
if (ht == htUnknown) {
|
||||
throw Error(format("unknown hash type '%1%', at %2%") % type % pos);
|
||||
}
|
||||
|
||||
PathSet context; // discarded
|
||||
Path p = state.coerceToPath(pos, *args[1], context);
|
||||
|
@ -1079,10 +1108,11 @@ static void prim_toFile(EvalState& state, const Pos& pos, Value** args,
|
|||
PathSet refs;
|
||||
|
||||
for (auto path : context) {
|
||||
if (path.at(0) != '/')
|
||||
if (path.at(0) != '/') {
|
||||
throw EvalError(format("in 'toFile': the file '%1%' cannot refer to "
|
||||
"derivation outputs, at %2%") %
|
||||
name % pos);
|
||||
}
|
||||
refs.insert(path);
|
||||
}
|
||||
|
||||
|
@ -1150,8 +1180,9 @@ static void addPath(EvalState& state, const Pos& pos, const string& name,
|
|||
"added from '%1%'") %
|
||||
path);
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
dstPath = expectedStorePath;
|
||||
}
|
||||
|
||||
mkString(v, dstPath, {dstPath});
|
||||
}
|
||||
|
@ -1160,15 +1191,17 @@ static void prim_filterSource(EvalState& state, const Pos& pos, Value** args,
|
|||
Value& v) {
|
||||
PathSet context;
|
||||
Path path = state.coerceToPath(pos, *args[1], context);
|
||||
if (!context.empty())
|
||||
if (!context.empty()) {
|
||||
throw EvalError(format("string '%1%' cannot refer to other paths, at %2%") %
|
||||
path % pos);
|
||||
}
|
||||
|
||||
state.forceValue(*args[0]);
|
||||
if (args[0]->type != tLambda)
|
||||
if (args[0]->type != tLambda) {
|
||||
throw TypeError(format("first argument in call to 'filterSource' is not a "
|
||||
"function but %1%, at %2%") %
|
||||
showType(*args[0]) % pos);
|
||||
}
|
||||
|
||||
addPath(state, pos, baseNameOf(path), path, args[0], true, Hash(), v);
|
||||
}
|
||||
|
@ -1187,24 +1220,26 @@ static void prim_path(EvalState& state, const Pos& pos, Value** args,
|
|||
if (n == "path") {
|
||||
PathSet context;
|
||||
path = state.coerceToPath(*attr.pos, *attr.value, context);
|
||||
if (!context.empty())
|
||||
if (!context.empty()) {
|
||||
throw EvalError(
|
||||
format("string '%1%' cannot refer to other paths, at %2%") % path %
|
||||
*attr.pos);
|
||||
} else if (attr.name == state.sName)
|
||||
}
|
||||
} else if (attr.name == state.sName) {
|
||||
name = state.forceStringNoCtx(*attr.value, *attr.pos);
|
||||
else if (n == "filter") {
|
||||
} else if (n == "filter") {
|
||||
state.forceValue(*attr.value);
|
||||
filterFun = attr.value;
|
||||
} else if (n == "recursive")
|
||||
} else if (n == "recursive") {
|
||||
recursive = state.forceBool(*attr.value, *attr.pos);
|
||||
else if (n == "sha256")
|
||||
} else if (n == "sha256") {
|
||||
expectedHash =
|
||||
Hash(state.forceStringNoCtx(*attr.value, *attr.pos), htSHA256);
|
||||
else
|
||||
} else {
|
||||
throw EvalError(
|
||||
format("unsupported argument '%1%' to 'addPath', at %2%") %
|
||||
attr.name % *attr.pos);
|
||||
}
|
||||
}
|
||||
if (path.empty()) {
|
||||
throw EvalError(format("'path' required, at %1%") % pos);
|
||||
|
@ -1229,8 +1264,9 @@ static void prim_attrNames(EvalState& state, const Pos& pos, Value** args,
|
|||
state.mkList(v, args[0]->attrs->size());
|
||||
|
||||
size_t n = 0;
|
||||
for (auto& i : *args[0]->attrs)
|
||||
for (auto& i : *args[0]->attrs) {
|
||||
mkString(*(v.listElems()[n++] = state.allocValue()), i.name);
|
||||
}
|
||||
|
||||
std::sort(v.listElems(), v.listElems() + n, [](Value* v1, Value* v2) {
|
||||
return strcmp(v1->string.s, v2->string.s) < 0;
|
||||
|
@ -1265,8 +1301,9 @@ void prim_getAttr(EvalState& state, const Pos& pos, Value** args, Value& v) {
|
|||
state.forceAttrs(*args[1], pos);
|
||||
// !!! Should we create a symbol here or just do a lookup?
|
||||
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(format("attribute '%1%' missing, at %2%") % attr % pos);
|
||||
}
|
||||
// !!! add to stack trace?
|
||||
if (state.countCalls && i->pos) {
|
||||
state.attrSelects[*i->pos]++;
|
||||
|
@ -1345,21 +1382,23 @@ static void prim_listToAttrs(EvalState& state, const Pos& pos, Value** args,
|
|||
state.forceAttrs(v2, pos);
|
||||
|
||||
Bindings::iterator j = v2.attrs->find(state.sName);
|
||||
if (j == v2.attrs->end())
|
||||
if (j == v2.attrs->end()) {
|
||||
throw TypeError(
|
||||
format(
|
||||
"'name' attribute missing in a call to 'listToAttrs', at %1%") %
|
||||
pos);
|
||||
}
|
||||
string name = state.forceStringNoCtx(*j->value, pos);
|
||||
|
||||
Symbol sym = state.symbols.create(name);
|
||||
if (seen.find(sym) == seen.end()) {
|
||||
Bindings::iterator j2 =
|
||||
v2.attrs->find(state.symbols.create(state.sValue));
|
||||
if (j2 == v2.attrs->end())
|
||||
if (j2 == v2.attrs->end()) {
|
||||
throw TypeError(format("'value' attribute missing in a call to "
|
||||
"'listToAttrs', at %1%") %
|
||||
pos);
|
||||
}
|
||||
|
||||
v.attrs->push_back(Attr(sym, j2->value, j2->pos));
|
||||
seen.insert(sym);
|
||||
|
@ -1434,8 +1473,9 @@ static void prim_catAttrs(EvalState& state, const Pos& pos, Value** args,
|
|||
static void prim_functionArgs(EvalState& state, const Pos& pos, Value** args,
|
||||
Value& v) {
|
||||
state.forceValue(*args[0]);
|
||||
if (args[0]->type != tLambda)
|
||||
if (args[0]->type != tLambda) {
|
||||
throw TypeError(format("'functionArgs' requires a function, at %1%") % pos);
|
||||
}
|
||||
|
||||
if (!args[0]->lambda.fun->matchAttrs) {
|
||||
state.mkAttrs(v, 0);
|
||||
|
@ -1443,9 +1483,10 @@ static void prim_functionArgs(EvalState& state, const Pos& pos, Value** args,
|
|||
}
|
||||
|
||||
state.mkAttrs(v, args[0]->lambda.fun->formals->formals.size());
|
||||
for (auto& i : args[0]->lambda.fun->formals->formals)
|
||||
for (auto& i : args[0]->lambda.fun->formals->formals) {
|
||||
// !!! should optimise booleans (allocate only once)
|
||||
mkBool(*state.allocAttr(v, i.name), i.def);
|
||||
}
|
||||
v.attrs->sort();
|
||||
}
|
||||
|
||||
|
@ -1479,8 +1520,9 @@ static void prim_isList(EvalState& state, const Pos& pos, Value** args,
|
|||
static void elemAt(EvalState& state, const Pos& pos, Value& list, int n,
|
||||
Value& v) {
|
||||
state.forceList(list, pos);
|
||||
if (n < 0 || (unsigned int)n >= list.listSize())
|
||||
if (n < 0 || (unsigned int)n >= list.listSize()) {
|
||||
throw Error(format("list index %1% is out of bounds, at %2%") % n % pos);
|
||||
}
|
||||
state.forceValue(*list.listElems()[n]);
|
||||
v = *list.listElems()[n];
|
||||
}
|
||||
|
@ -1503,8 +1545,9 @@ static void prim_head(EvalState& state, const Pos& pos, Value** args,
|
|||
static void prim_tail(EvalState& state, const Pos& pos, Value** args,
|
||||
Value& v) {
|
||||
state.forceList(*args[0], pos);
|
||||
if (args[0]->listSize() == 0)
|
||||
if (args[0]->listSize() == 0) {
|
||||
throw Error(format("'tail' called on an empty list, at %1%") % pos);
|
||||
}
|
||||
state.mkList(v, args[0]->listSize() - 1);
|
||||
for (unsigned int n = 0; n < v.listSize(); ++n) {
|
||||
v.listElems()[n] = args[0]->listElems()[n + 1];
|
||||
|
@ -1637,9 +1680,10 @@ static void prim_genList(EvalState& state, const Pos& pos, Value** args,
|
|||
Value& v) {
|
||||
auto len = state.forceInt(*args[1], pos);
|
||||
|
||||
if (len < 0)
|
||||
if (len < 0) {
|
||||
throw EvalError(format("cannot create list of size %1%, at %2%") % len %
|
||||
pos);
|
||||
}
|
||||
|
||||
state.mkList(v, len);
|
||||
|
||||
|
@ -1698,10 +1742,11 @@ static void prim_partition(EvalState& state, const Pos& pos, Value** args,
|
|||
state.forceValue(*vElem);
|
||||
Value res;
|
||||
state.callFunction(*args[0], *vElem, res, pos);
|
||||
if (state.forceBool(res, pos))
|
||||
if (state.forceBool(res, pos)) {
|
||||
right.push_back(vElem);
|
||||
else
|
||||
} else {
|
||||
wrong.push_back(vElem);
|
||||
}
|
||||
}
|
||||
|
||||
state.mkAttrs(v, 2);
|
||||
|
@ -1805,8 +1850,9 @@ static void prim_div(EvalState& state, const Pos& pos, Value** args, Value& v) {
|
|||
NixInt i1 = state.forceInt(*args[0], pos);
|
||||
NixInt i2 = state.forceInt(*args[1], pos);
|
||||
/* 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(format("overflow in integer division, at %1%") % pos);
|
||||
}
|
||||
mkInt(v, i1 / i2);
|
||||
}
|
||||
}
|
||||
|
@ -1859,9 +1905,10 @@ static void prim_substring(EvalState& state, const Pos& pos, Value** args,
|
|||
PathSet context;
|
||||
string s = state.coerceToString(pos, *args[2], context);
|
||||
|
||||
if (start < 0)
|
||||
if (start < 0) {
|
||||
throw EvalError(format("negative start position in 'substring', at %1%") %
|
||||
pos);
|
||||
}
|
||||
|
||||
mkString(v, (unsigned int)start >= s.size() ? "" : string(s, start, len),
|
||||
context);
|
||||
|
@ -1879,8 +1926,9 @@ static void prim_hashString(EvalState& state, const Pos& pos, Value** args,
|
|||
Value& v) {
|
||||
string type = state.forceStringNoCtx(*args[0], pos);
|
||||
HashType ht = parseHashType(type);
|
||||
if (ht == htUnknown)
|
||||
if (ht == htUnknown) {
|
||||
throw Error(format("unknown hash type '%1%', at %2%") % type % pos);
|
||||
}
|
||||
|
||||
PathSet context; // discarded
|
||||
string s = state.forceString(*args[1], context, pos);
|
||||
|
@ -1910,11 +1958,12 @@ static void prim_match(EvalState& state, const Pos& pos, Value** args,
|
|||
const size_t len = match.size() - 1;
|
||||
state.mkList(v, len);
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
if (!match[i + 1].matched)
|
||||
if (!match[i + 1].matched) {
|
||||
mkNull(*(v.listElems()[i] = state.allocValue()));
|
||||
else
|
||||
} else {
|
||||
mkString(*(v.listElems()[i] = state.allocValue()),
|
||||
match[i + 1].str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
} catch (std::regex_error& e) {
|
||||
|
@ -1969,11 +2018,12 @@ static void prim_split(EvalState& state, const Pos& pos, Value** args,
|
|||
// Start at 1, beacause the first match is the whole string.
|
||||
state.mkList(*elem, slen);
|
||||
for (size_t si = 0; si < slen; ++si) {
|
||||
if (!match[si + 1].matched)
|
||||
if (!match[si + 1].matched) {
|
||||
mkNull(*(elem->listElems()[si] = state.allocValue()));
|
||||
else
|
||||
} else {
|
||||
mkString(*(elem->listElems()[si] = state.allocValue()),
|
||||
match[si + 1].str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// Add a string for non-matched suffix characters.
|
||||
|
@ -2023,15 +2073,17 @@ static void prim_replaceStrings(EvalState& state, const Pos& pos, Value** args,
|
|||
Value& v) {
|
||||
state.forceList(*args[0], pos);
|
||||
state.forceList(*args[1], pos);
|
||||
if (args[0]->listSize() != args[1]->listSize())
|
||||
if (args[0]->listSize() != args[1]->listSize()) {
|
||||
throw EvalError(format("'from' and 'to' arguments to 'replaceStrings' have "
|
||||
"different lengths, at %1%") %
|
||||
pos);
|
||||
}
|
||||
|
||||
vector<string> from;
|
||||
from.reserve(args[0]->listSize());
|
||||
for (unsigned int n = 0; n < args[0]->listSize(); ++n)
|
||||
for (unsigned int n = 0; n < args[0]->listSize(); ++n) {
|
||||
from.push_back(state.forceString(*args[0]->listElems()[n], pos));
|
||||
}
|
||||
|
||||
vector<std::pair<string, PathSet>> to;
|
||||
to.reserve(args[1]->listSize());
|
||||
|
@ -2051,7 +2103,7 @@ static void prim_replaceStrings(EvalState& state, const Pos& pos, Value** args,
|
|||
bool found = false;
|
||||
auto i = from.begin();
|
||||
auto j = to.begin();
|
||||
for (; i != from.end(); ++i, ++j)
|
||||
for (; i != from.end(); ++i, ++j) {
|
||||
if (s.compare(p, i->size(), *i) == 0) {
|
||||
found = true;
|
||||
res += j->first;
|
||||
|
@ -2069,6 +2121,7 @@ static void prim_replaceStrings(EvalState& state, const Pos& pos, Value** args,
|
|||
j->second.clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
if (p < s.size()) {
|
||||
res += s[p];
|
||||
|
@ -2139,20 +2192,22 @@ void fetch(EvalState& state, const Pos& pos, Value** args, Value& v,
|
|||
|
||||
for (auto& attr : *args[0]->attrs) {
|
||||
string n(attr.name);
|
||||
if (n == "url")
|
||||
if (n == "url") {
|
||||
request.uri = state.forceStringNoCtx(*attr.value, *attr.pos);
|
||||
else if (n == "sha256")
|
||||
} else if (n == "sha256") {
|
||||
request.expectedHash =
|
||||
Hash(state.forceStringNoCtx(*attr.value, *attr.pos), htSHA256);
|
||||
else if (n == "name")
|
||||
} else if (n == "name") {
|
||||
request.name = state.forceStringNoCtx(*attr.value, *attr.pos);
|
||||
else
|
||||
} else {
|
||||
throw EvalError(format("unsupported argument '%1%' to '%2%', at %3%") %
|
||||
attr.name % who % attr.pos);
|
||||
}
|
||||
}
|
||||
|
||||
if (request.uri.empty())
|
||||
if (request.uri.empty()) {
|
||||
throw EvalError(format("'url' argument required, at %1%") % pos);
|
||||
}
|
||||
|
||||
} else {
|
||||
request.uri = state.forceStringNoCtx(*args[0], pos);
|
||||
|
@ -2160,9 +2215,10 @@ void fetch(EvalState& state, const Pos& pos, Value** args, Value& v,
|
|||
|
||||
state.checkURI(request.uri);
|
||||
|
||||
if (evalSettings.pureEval && !request.expectedHash)
|
||||
if (evalSettings.pureEval && !request.expectedHash) {
|
||||
throw Error("in pure evaluation mode, '%s' requires a 'sha256' argument",
|
||||
who);
|
||||
}
|
||||
|
||||
auto res = getDownloader()->downloadCached(state.store, request);
|
||||
|
||||
|
@ -2282,10 +2338,11 @@ void EvalState::createBaseEnv() {
|
|||
|
||||
// Paths
|
||||
addPrimOp("__toPath", 1, prim_toPath);
|
||||
if (evalSettings.pureEval)
|
||||
if (evalSettings.pureEval) {
|
||||
addPurityError("__storePath");
|
||||
else
|
||||
} else {
|
||||
addPrimOp("__storePath", 1, prim_storePath);
|
||||
}
|
||||
addPrimOp("__pathExists", 1, prim_pathExists);
|
||||
addPrimOp("baseNameOf", 1, prim_baseNameOf);
|
||||
addPrimOp("dirOf", 1, prim_dirOf);
|
||||
|
@ -2387,9 +2444,11 @@ void EvalState::createBaseEnv() {
|
|||
}
|
||||
addConstant("__nixPath", v);
|
||||
|
||||
if (RegisterPrimOp::primOps)
|
||||
for (auto& primOp : *RegisterPrimOp::primOps)
|
||||
if (RegisterPrimOp::primOps) {
|
||||
for (auto& primOp : *RegisterPrimOp::primOps) {
|
||||
addPrimOp(std::get<0>(primOp), std::get<1>(primOp), std::get<2>(primOp));
|
||||
}
|
||||
}
|
||||
|
||||
/* Now that we've added all primops, sort the `builtins' set,
|
||||
because attribute lookups expect it to be sorted. */
|
||||
|
|
3
third_party/nix/src/libexpr/value-to-json.cc
vendored
3
third_party/nix/src/libexpr/value-to-json.cc
vendored
|
@ -58,8 +58,9 @@ void printValueAsJSON(EvalState& state, bool strict, Value& v,
|
|||
auto placeholder(obj.placeholder(j));
|
||||
printValueAsJSON(state, strict, *a.value, placeholder, context);
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
printValueAsJSON(state, strict, *i->value, out, context);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
9
third_party/nix/src/libexpr/value-to-xml.cc
vendored
9
third_party/nix/src/libexpr/value-to-xml.cc
vendored
|
@ -94,8 +94,9 @@ static void printValueAsXML(EvalState& state, bool strict, bool location,
|
|||
if (strict) {
|
||||
state.forceValue(*a->value);
|
||||
}
|
||||
if (a->value->type == tString)
|
||||
if (a->value->type == tString) {
|
||||
xmlAttrs["drvPath"] = drvPath = a->value->string.s;
|
||||
}
|
||||
}
|
||||
|
||||
a = v.attrs->find(state.sOutPath);
|
||||
|
@ -103,8 +104,9 @@ static void printValueAsXML(EvalState& state, bool strict, bool location,
|
|||
if (strict) {
|
||||
state.forceValue(*a->value);
|
||||
}
|
||||
if (a->value->type == tString)
|
||||
if (a->value->type == tString) {
|
||||
xmlAttrs["outPath"] = a->value->string.s;
|
||||
}
|
||||
}
|
||||
|
||||
XMLOpenElement _(doc, "derivation", xmlAttrs);
|
||||
|
@ -112,8 +114,9 @@ static void printValueAsXML(EvalState& state, bool strict, bool location,
|
|||
if (drvPath != "" && drvsSeen.find(drvPath) == drvsSeen.end()) {
|
||||
drvsSeen.insert(drvPath);
|
||||
showAttrs(state, strict, location, *v.attrs, doc, context, drvsSeen);
|
||||
} else
|
||||
} else {
|
||||
doc.writeEmptyElement("repeated");
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
|
|
13
third_party/nix/src/libmain/shared.cc
vendored
13
third_party/nix/src/libmain/shared.cc
vendored
|
@ -233,7 +233,9 @@ bool LegacyArgs::processFlag(Strings::iterator& pos, Strings::iterator end) {
|
|||
return true;
|
||||
}
|
||||
bool res = parseArg(pos, end);
|
||||
if (res) ++pos;
|
||||
if (res) {
|
||||
++pos;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -244,8 +246,9 @@ bool LegacyArgs::processArgs(const Strings& args, bool finish) {
|
|||
assert(args.size() == 1);
|
||||
Strings ss(args);
|
||||
auto pos = ss.begin();
|
||||
if (!parseArg(pos, ss.end()))
|
||||
if (!parseArg(pos, ss.end())) {
|
||||
throw UsageError(format("unexpected argument '%1%'") % args.front());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -346,8 +349,9 @@ RunPager::RunPager() {
|
|||
toPager.create();
|
||||
|
||||
pid = startProcess([&]() {
|
||||
if (dup2(toPager.readSide.get(), STDIN_FILENO) == -1)
|
||||
if (dup2(toPager.readSide.get(), STDIN_FILENO) == -1) {
|
||||
throw SysError("dupping stdin");
|
||||
}
|
||||
if (!getenv("LESS")) {
|
||||
setenv("LESS", "FRSXMK", 1);
|
||||
}
|
||||
|
@ -363,8 +367,9 @@ RunPager::RunPager() {
|
|||
|
||||
pid.setKillSignal(SIGINT);
|
||||
|
||||
if (dup2(toPager.writeSide.get(), STDOUT_FILENO) == -1)
|
||||
if (dup2(toPager.writeSide.get(), STDOUT_FILENO) == -1) {
|
||||
throw SysError("dupping stdout");
|
||||
}
|
||||
}
|
||||
|
||||
RunPager::~RunPager() {
|
||||
|
|
3
third_party/nix/src/libmain/stack.cc
vendored
3
third_party/nix/src/libmain/stack.cc
vendored
|
@ -58,8 +58,9 @@ void detectStackOverflow() {
|
|||
throw Error("cannot allocate alternative stack");
|
||||
}
|
||||
stack.ss_flags = 0;
|
||||
if (sigaltstack(&stack, 0) == -1)
|
||||
if (sigaltstack(&stack, 0) == -1) {
|
||||
throw SysError("cannot set alternative stack");
|
||||
}
|
||||
|
||||
struct sigaction act;
|
||||
sigfillset(&act.sa_mask);
|
||||
|
|
|
@ -19,9 +19,10 @@
|
|||
namespace nix {
|
||||
|
||||
BinaryCacheStore::BinaryCacheStore(const Params& params) : Store(params) {
|
||||
if (secretKeyFile != "")
|
||||
if (secretKeyFile != "") {
|
||||
secretKey =
|
||||
std::unique_ptr<SecretKey>(new SecretKey(readFile(secretKeyFile)));
|
||||
}
|
||||
|
||||
StringSink sink;
|
||||
sink << narVersionMagic1;
|
||||
|
@ -44,10 +45,11 @@ void BinaryCacheStore::init() {
|
|||
auto name = line.substr(0, colon);
|
||||
auto value = trim(line.substr(colon + 1, std::string::npos));
|
||||
if (name == "StoreDir") {
|
||||
if (value != storeDir)
|
||||
if (value != storeDir) {
|
||||
throw Error(format("binary cache '%s' is for Nix stores with prefix "
|
||||
"'%s', not '%s'") %
|
||||
getUri() % value % storeDir);
|
||||
}
|
||||
} else if (name == "WantMassQuery") {
|
||||
wantMassQuery_ = value == "1";
|
||||
} else if (name == "Priority") {
|
||||
|
@ -108,9 +110,10 @@ void BinaryCacheStore::writeNarInfo(ref<NarInfo> narInfo) {
|
|||
state_->pathInfoCache.upsert(hashPart, std::shared_ptr<NarInfo>(narInfo));
|
||||
}
|
||||
|
||||
if (diskCache)
|
||||
if (diskCache) {
|
||||
diskCache->upsertNarInfo(getUri(), hashPart,
|
||||
std::shared_ptr<NarInfo>(narInfo));
|
||||
}
|
||||
}
|
||||
|
||||
void BinaryCacheStore::addToStore(const ValidPathInfo& info,
|
||||
|
@ -123,7 +126,8 @@ void BinaryCacheStore::addToStore(const ValidPathInfo& info,
|
|||
|
||||
/* Verify that all references are valid. This may do some .narinfo
|
||||
reads, but typically they'll already be cached. */
|
||||
for (auto& ref : info.references) try {
|
||||
for (auto& ref : info.references) {
|
||||
try {
|
||||
if (ref != info.path) {
|
||||
queryPathInfo(ref);
|
||||
}
|
||||
|
@ -132,6 +136,7 @@ void BinaryCacheStore::addToStore(const ValidPathInfo& info,
|
|||
"reference '%s' is not valid") %
|
||||
info.path % ref);
|
||||
}
|
||||
}
|
||||
|
||||
assert(nar->compare(0, narMagic.size(), narMagic) == 0);
|
||||
|
||||
|
@ -140,10 +145,11 @@ void BinaryCacheStore::addToStore(const ValidPathInfo& info,
|
|||
narInfo->narSize = nar->size();
|
||||
narInfo->narHash = hashString(htSHA256, *nar);
|
||||
|
||||
if (info.narHash && info.narHash != narInfo->narHash)
|
||||
if (info.narHash && info.narHash != narInfo->narHash) {
|
||||
throw Error(
|
||||
format("refusing to copy corrupted path '%1%' to binary cache") %
|
||||
info.path);
|
||||
}
|
||||
|
||||
auto accessor_ = std::dynamic_pointer_cast<RemoteFSAccessor>(accessor);
|
||||
|
||||
|
@ -203,8 +209,9 @@ void BinaryCacheStore::addToStore(const ValidPathInfo& info,
|
|||
if (repair || !fileExists(narInfo->url)) {
|
||||
stats.narWrite++;
|
||||
upsertFile(narInfo->url, *narCompressed, "application/x-nix-nar");
|
||||
} else
|
||||
} else {
|
||||
stats.narWriteAverted++;
|
||||
}
|
||||
|
||||
stats.narWriteBytes += nar->size();
|
||||
stats.narWriteCompressedBytes += narCompressed->size();
|
||||
|
@ -349,9 +356,9 @@ void BinaryCacheStore::addSignatures(const Path& storePath,
|
|||
std::shared_ptr<std::string> BinaryCacheStore::getBuildLog(const Path& path) {
|
||||
Path drvPath;
|
||||
|
||||
if (isDerivation(path))
|
||||
if (isDerivation(path)) {
|
||||
drvPath = path;
|
||||
else {
|
||||
} else {
|
||||
try {
|
||||
auto info = queryPathInfo(path);
|
||||
// FIXME: add a "Log" field to .narinfo
|
||||
|
|
576
third_party/nix/src/libstore/build.cc
vendored
576
third_party/nix/src/libstore/build.cc
vendored
File diff suppressed because it is too large
Load diff
6
third_party/nix/src/libstore/crypto.cc
vendored
6
third_party/nix/src/libstore/crypto.cc
vendored
|
@ -32,8 +32,9 @@ Key::Key(const string& s) {
|
|||
|
||||
SecretKey::SecretKey(const string& s) : Key(s) {
|
||||
#if HAVE_SODIUM
|
||||
if (key.size() != crypto_sign_SECRETKEYBYTES)
|
||||
if (key.size() != crypto_sign_SECRETKEYBYTES) {
|
||||
throw Error("secret key is not valid");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -69,8 +70,9 @@ PublicKey SecretKey::toPublicKey() const {
|
|||
|
||||
PublicKey::PublicKey(const string& s) : Key(s) {
|
||||
#if HAVE_SODIUM
|
||||
if (key.size() != crypto_sign_PUBLICKEYBYTES)
|
||||
if (key.size() != crypto_sign_PUBLICKEYBYTES) {
|
||||
throw Error("public key is not valid");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
34
third_party/nix/src/libstore/derivations.cc
vendored
34
third_party/nix/src/libstore/derivations.cc
vendored
|
@ -19,16 +19,18 @@ void DerivationOutput::parseHashInfo(bool& recursive, Hash& hash) const {
|
|||
}
|
||||
|
||||
HashType hashType = parseHashType(algo);
|
||||
if (hashType == htUnknown)
|
||||
if (hashType == htUnknown) {
|
||||
throw Error(format("unknown hash algorithm '%1%'") % algo);
|
||||
}
|
||||
|
||||
hash = Hash(this->hash, hashType);
|
||||
}
|
||||
|
||||
Path BasicDerivation::findOutput(const string& id) const {
|
||||
auto i = outputs.find(id);
|
||||
if (i == outputs.end())
|
||||
if (i == outputs.end()) {
|
||||
throw Error(format("derivation has no output '%1%'") % id);
|
||||
}
|
||||
return i->second.path;
|
||||
}
|
||||
|
||||
|
@ -57,8 +59,9 @@ Path writeDerivation(ref<Store> store, const Derivation& drv,
|
|||
static void expect(std::istream& str, const string& s) {
|
||||
char s2[s.size()];
|
||||
str.read(s2, s.size());
|
||||
if (string(s2, s.size()) != s)
|
||||
if (string(s2, s.size()) != s) {
|
||||
throw FormatError(format("expected string '%1%'") % s);
|
||||
}
|
||||
}
|
||||
|
||||
/* Read a C-style string from stream `str'. */
|
||||
|
@ -66,26 +69,30 @@ static string parseString(std::istream& str) {
|
|||
string res;
|
||||
expect(str, "\"");
|
||||
int c;
|
||||
while ((c = str.get()) != '"')
|
||||
while ((c = str.get()) != '"') {
|
||||
if (c == '\\') {
|
||||
c = str.get();
|
||||
if (c == 'n')
|
||||
if (c == 'n') {
|
||||
res += '\n';
|
||||
else if (c == 'r')
|
||||
} else if (c == 'r') {
|
||||
res += '\r';
|
||||
else if (c == 't')
|
||||
} else if (c == 't') {
|
||||
res += '\t';
|
||||
else
|
||||
} else {
|
||||
res += c;
|
||||
} else
|
||||
}
|
||||
} else {
|
||||
res += c;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static Path parsePath(std::istream& str) {
|
||||
string s = parseString(str);
|
||||
if (s.size() == 0 || s[0] != '/')
|
||||
if (s.size() == 0 || s[0] != '/') {
|
||||
throw FormatError(format("bad path '%1%' in derivation") % s);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
@ -103,8 +110,9 @@ static bool endOfList(std::istream& str) {
|
|||
|
||||
static StringSet parseStrings(std::istream& str, bool arePaths) {
|
||||
StringSet res;
|
||||
while (!endOfList(str))
|
||||
while (!endOfList(str)) {
|
||||
res.insert(arePaths ? parsePath(str) : parseString(str));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -147,7 +155,9 @@ static Derivation parseDerivation(const string& s) {
|
|||
|
||||
/* Parse the builder arguments. */
|
||||
expect(str, ",[");
|
||||
while (!endOfList(str)) drv.args.push_back(parseString(str));
|
||||
while (!endOfList(str)) {
|
||||
drv.args.push_back(parseString(str));
|
||||
}
|
||||
|
||||
/* Parse the environment variables. */
|
||||
expect(str, ",[");
|
||||
|
|
75
third_party/nix/src/libstore/download.cc
vendored
75
third_party/nix/src/libstore/download.cc
vendored
|
@ -36,11 +36,12 @@ DownloadSettings downloadSettings;
|
|||
static GlobalConfig::Register r1(&downloadSettings);
|
||||
|
||||
std::string resolveUri(const std::string& uri) {
|
||||
if (uri.compare(0, 8, "channel:") == 0)
|
||||
if (uri.compare(0, 8, "channel:") == 0) {
|
||||
return "https://nixos.org/channels/" + std::string(uri, 8) +
|
||||
"/nixexprs.tar.xz";
|
||||
else
|
||||
} else {
|
||||
return uri;
|
||||
}
|
||||
}
|
||||
|
||||
struct CurlDownloader : public Downloader {
|
||||
|
@ -92,18 +93,21 @@ struct CurlDownloader : public Downloader {
|
|||
writtenToSink += len;
|
||||
this->request.dataCallback((char*)data, len);
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
this->result.data->append((char*)data, len);
|
||||
}
|
||||
}) {
|
||||
LOG(INFO) << (request.data ? "uploading '" : "downloading '")
|
||||
<< request.uri << "'";
|
||||
|
||||
if (!request.expectedETag.empty())
|
||||
if (!request.expectedETag.empty()) {
|
||||
requestHeaders = curl_slist_append(
|
||||
requestHeaders, ("If-None-Match: " + request.expectedETag).c_str());
|
||||
if (!request.mimeType.empty())
|
||||
}
|
||||
if (!request.mimeType.empty()) {
|
||||
requestHeaders = curl_slist_append(
|
||||
requestHeaders, ("Content-Type: " + request.mimeType).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
~DownloadItem() {
|
||||
|
@ -117,10 +121,11 @@ struct CurlDownloader : public Downloader {
|
|||
curl_slist_free_all(requestHeaders);
|
||||
}
|
||||
try {
|
||||
if (!done)
|
||||
if (!done) {
|
||||
fail(DownloadError(
|
||||
Interrupted,
|
||||
format("download of '%s' was interrupted") % request.uri));
|
||||
}
|
||||
} catch (...) {
|
||||
ignoreException();
|
||||
}
|
||||
|
@ -147,8 +152,9 @@ struct CurlDownloader : public Downloader {
|
|||
size_t realSize = size * nmemb;
|
||||
result.bodySize += realSize;
|
||||
|
||||
if (!decompressionSink)
|
||||
if (!decompressionSink) {
|
||||
decompressionSink = makeDecompressionSink(encoding, finalSink);
|
||||
}
|
||||
|
||||
(*decompressionSink)((unsigned char*)contents, realSize);
|
||||
|
||||
|
@ -192,11 +198,12 @@ struct CurlDownloader : public Downloader {
|
|||
<< "shutting down on 200 HTTP response with expected ETag";
|
||||
return 0;
|
||||
}
|
||||
} else if (name == "content-encoding")
|
||||
} else if (name == "content-encoding") {
|
||||
encoding = trim(string(line, i + 1));
|
||||
else if (name == "accept-ranges" &&
|
||||
toLower(trim(std::string(line, i + 1))) == "bytes")
|
||||
} else if (name == "accept-ranges" &&
|
||||
toLower(trim(std::string(line, i + 1))) == "bytes") {
|
||||
acceptRanges = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return realSize;
|
||||
|
@ -275,10 +282,11 @@ struct CurlDownloader : public Downloader {
|
|||
curl_easy_setopt(req, CURLOPT_PIPEWAIT, 1);
|
||||
#endif
|
||||
#if LIBCURL_VERSION_NUM >= 0x072f00
|
||||
if (downloadSettings.enableHttp2)
|
||||
if (downloadSettings.enableHttp2) {
|
||||
curl_easy_setopt(req, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS);
|
||||
else
|
||||
} else {
|
||||
curl_easy_setopt(req, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
|
||||
}
|
||||
#endif
|
||||
curl_easy_setopt(req, CURLOPT_WRITEFUNCTION,
|
||||
DownloadItem::writeCallbackWrapper);
|
||||
|
@ -306,8 +314,9 @@ struct CurlDownloader : public Downloader {
|
|||
}
|
||||
|
||||
if (request.verifyTLS) {
|
||||
if (settings.caFile != "")
|
||||
if (settings.caFile != "") {
|
||||
curl_easy_setopt(req, CURLOPT_CAINFO, settings.caFile.c_str());
|
||||
}
|
||||
} else {
|
||||
curl_easy_setopt(req, CURLOPT_SSL_VERIFYPEER, 0);
|
||||
curl_easy_setopt(req, CURLOPT_SSL_VERIFYHOST, 0);
|
||||
|
@ -362,14 +371,14 @@ struct CurlDownloader : public Downloader {
|
|||
httpStatus = 304;
|
||||
}
|
||||
|
||||
if (writeException)
|
||||
if (writeException) {
|
||||
failEx(writeException);
|
||||
|
||||
else if (code == CURLE_OK &&
|
||||
(httpStatus == 200 || httpStatus == 201 || httpStatus == 204 ||
|
||||
httpStatus == 206 || httpStatus == 304 ||
|
||||
httpStatus == 226 /* FTP */ ||
|
||||
httpStatus == 0 /* other protocol */)) {
|
||||
} else if (code == CURLE_OK &&
|
||||
(httpStatus == 200 || httpStatus == 201 || httpStatus == 204 ||
|
||||
httpStatus == 206 || httpStatus == 304 ||
|
||||
httpStatus == 226 /* FTP */ ||
|
||||
httpStatus == 0 /* other protocol */)) {
|
||||
result.cached = httpStatus == 304;
|
||||
done = true;
|
||||
callback(std::move(result));
|
||||
|
@ -464,8 +473,9 @@ struct CurlDownloader : public Downloader {
|
|||
embargo =
|
||||
std::chrono::steady_clock::now() + std::chrono::milliseconds(ms);
|
||||
downloader.enqueueItem(shared_from_this());
|
||||
} else
|
||||
} else {
|
||||
fail(exc);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -548,10 +558,11 @@ struct CurlDownloader : public Downloader {
|
|||
/* Let curl do its thing. */
|
||||
int running;
|
||||
CURLMcode mc = curl_multi_perform(curlm, &running);
|
||||
if (mc != CURLM_OK)
|
||||
if (mc != CURLM_OK) {
|
||||
throw nix::Error(
|
||||
format("unexpected error from curl_multi_perform(): %s") %
|
||||
curl_multi_strerror(mc));
|
||||
}
|
||||
|
||||
/* Set the promises of any finished requests. */
|
||||
CURLMsg* msg;
|
||||
|
@ -584,9 +595,10 @@ struct CurlDownloader : public Downloader {
|
|||
: maxSleepTimeMs;
|
||||
DLOG(INFO) << "download thread waiting for " << sleepTimeMs << " ms";
|
||||
mc = curl_multi_wait(curlm, extraFDs, 1, sleepTimeMs, &numfds);
|
||||
if (mc != CURLM_OK)
|
||||
if (mc != CURLM_OK) {
|
||||
throw nix::Error(format("unexpected error from curl_multi_wait(): %s") %
|
||||
curl_multi_strerror(mc));
|
||||
}
|
||||
|
||||
nextWakeup = std::chrono::steady_clock::time_point();
|
||||
|
||||
|
@ -596,8 +608,9 @@ struct CurlDownloader : public Downloader {
|
|||
if (extraFDs[0].revents & CURL_WAIT_POLLIN) {
|
||||
char buf[1024];
|
||||
auto res = read(extraFDs[0].fd, buf, sizeof(buf));
|
||||
if (res == -1 && errno != EINTR)
|
||||
if (res == -1 && errno != EINTR) {
|
||||
throw SysError("reading curl wakeup socket");
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<DownloadItem>> incoming;
|
||||
|
@ -612,8 +625,9 @@ struct CurlDownloader : public Downloader {
|
|||
state->incoming.pop();
|
||||
} else {
|
||||
if (nextWakeup == std::chrono::steady_clock::time_point() ||
|
||||
item->embargo < nextWakeup)
|
||||
item->embargo < nextWakeup) {
|
||||
nextWakeup = item->embargo;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -643,22 +657,26 @@ struct CurlDownloader : public Downloader {
|
|||
|
||||
{
|
||||
auto state(state_.lock());
|
||||
while (!state->incoming.empty()) state->incoming.pop();
|
||||
while (!state->incoming.empty()) {
|
||||
state->incoming.pop();
|
||||
}
|
||||
state->quit = true;
|
||||
}
|
||||
}
|
||||
|
||||
void enqueueItem(std::shared_ptr<DownloadItem> item) {
|
||||
if (item->request.data && !hasPrefix(item->request.uri, "http://") &&
|
||||
!hasPrefix(item->request.uri, "https://"))
|
||||
!hasPrefix(item->request.uri, "https://")) {
|
||||
throw nix::Error("uploading to '%s' is not supported", item->request.uri);
|
||||
}
|
||||
|
||||
{
|
||||
auto state(state_.lock());
|
||||
if (state->quit)
|
||||
if (state->quit) {
|
||||
throw nix::Error(
|
||||
"cannot enqueue download request because the download thread is "
|
||||
"shutting down");
|
||||
}
|
||||
state->incoming.push(item);
|
||||
}
|
||||
writeFull(wakeupPipe.writeSide.get(), " ");
|
||||
|
@ -900,8 +918,9 @@ CachedDownloadResult Downloader::downloadCached(
|
|||
expectedETag = ss[1];
|
||||
}
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
storePath = "";
|
||||
}
|
||||
}
|
||||
|
||||
if (!skip) {
|
||||
|
|
|
@ -46,9 +46,10 @@ void Store::exportPath(const Path& path, Sink& sink) {
|
|||
filesystem corruption from spreading to other machines.
|
||||
Don't complain if the stored hash is zero (unknown). */
|
||||
Hash hash = hashAndWriteSink.currentHash();
|
||||
if (hash != info->narHash && info->narHash != Hash(info->narHash.type))
|
||||
if (hash != info->narHash && info->narHash != Hash(info->narHash.type)) {
|
||||
throw Error(format("hash of path '%1%' has changed from '%2%' to '%3%'!") %
|
||||
path % info->narHash.to_string() % hash.to_string());
|
||||
}
|
||||
|
||||
hashAndWriteSink << exportMagic << path << info->references << info->deriver
|
||||
<< 0;
|
||||
|
@ -62,17 +63,19 @@ Paths Store::importPaths(Source& source, std::shared_ptr<FSAccessor> accessor,
|
|||
if (n == 0) {
|
||||
break;
|
||||
}
|
||||
if (n != 1)
|
||||
if (n != 1) {
|
||||
throw Error(
|
||||
"input doesn't look like something created by 'nix-store --export'");
|
||||
}
|
||||
|
||||
/* Extract the NAR from the source. */
|
||||
TeeSink tee(source);
|
||||
parseDump(tee, tee.source);
|
||||
|
||||
uint32_t magic = readInt(source);
|
||||
if (magic != exportMagic)
|
||||
if (magic != exportMagic) {
|
||||
throw Error("Nix archive cannot be imported; wrong format");
|
||||
}
|
||||
|
||||
ValidPathInfo info;
|
||||
|
||||
|
|
95
third_party/nix/src/libstore/gc.cc
vendored
95
third_party/nix/src/libstore/gc.cc
vendored
|
@ -61,8 +61,9 @@ static void makeSymlink(const Path& link, const Path& target) {
|
|||
createSymlink(target, tempLink);
|
||||
|
||||
/* Atomically replace the old one. */
|
||||
if (rename(tempLink.c_str(), link.c_str()) == -1)
|
||||
if (rename(tempLink.c_str(), link.c_str()) == -1) {
|
||||
throw SysError(format("cannot rename '%1%' to '%2%'") % tempLink % link);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalStore::syncWithGC() { AutoCloseFD fdGCLock = openGCLock(ltRead); }
|
||||
|
@ -80,18 +81,21 @@ Path LocalFSStore::addPermRoot(const Path& _storePath, const Path& _gcRoot,
|
|||
Path gcRoot(canonPath(_gcRoot));
|
||||
assertStorePath(storePath);
|
||||
|
||||
if (isInStore(gcRoot))
|
||||
if (isInStore(gcRoot)) {
|
||||
throw Error(format("creating a garbage collector root (%1%) in the Nix "
|
||||
"store is forbidden "
|
||||
"(are you running nix-build inside the store?)") %
|
||||
gcRoot);
|
||||
}
|
||||
|
||||
if (indirect) {
|
||||
/* Don't clobber the link if it already exists and doesn't
|
||||
point to the Nix store. */
|
||||
if (pathExists(gcRoot) && (!isLink(gcRoot) || !isInStore(readLink(gcRoot))))
|
||||
if (pathExists(gcRoot) &&
|
||||
(!isLink(gcRoot) || !isInStore(readLink(gcRoot)))) {
|
||||
throw Error(format("cannot create symlink '%1%'; already exists") %
|
||||
gcRoot);
|
||||
}
|
||||
makeSymlink(gcRoot, storePath);
|
||||
addIndirectRoot(gcRoot);
|
||||
}
|
||||
|
@ -101,16 +105,18 @@ Path LocalFSStore::addPermRoot(const Path& _storePath, const Path& _gcRoot,
|
|||
Path rootsDir =
|
||||
canonPath((format("%1%/%2%") % stateDir % gcRootsDir).str());
|
||||
|
||||
if (string(gcRoot, 0, rootsDir.size() + 1) != rootsDir + "/")
|
||||
if (string(gcRoot, 0, rootsDir.size() + 1) != rootsDir + "/") {
|
||||
throw Error(format("path '%1%' is not a valid garbage collector root; "
|
||||
"it's not in the directory '%2%'") %
|
||||
gcRoot % rootsDir);
|
||||
}
|
||||
}
|
||||
|
||||
if (baseNameOf(gcRoot) == baseNameOf(storePath))
|
||||
if (baseNameOf(gcRoot) == baseNameOf(storePath)) {
|
||||
writeFile(gcRoot, "");
|
||||
else
|
||||
} else {
|
||||
makeSymlink(gcRoot, storePath);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check that the root can be found by the garbage collector.
|
||||
|
@ -144,10 +150,11 @@ void LocalStore::addTempRoot(const Path& path) {
|
|||
while (1) {
|
||||
AutoCloseFD fdGCLock = openGCLock(ltRead);
|
||||
|
||||
if (pathExists(fnTempRoots))
|
||||
if (pathExists(fnTempRoots)) {
|
||||
/* It *must* be stale, since there can be no two
|
||||
processes with the same pid. */
|
||||
unlink(fnTempRoots.c_str());
|
||||
}
|
||||
|
||||
state->fdTempRoots = openLockFile(fnTempRoots, true);
|
||||
|
||||
|
@ -159,8 +166,9 @@ void LocalStore::addTempRoot(const Path& path) {
|
|||
/* Check whether the garbage collector didn't get in our
|
||||
way. */
|
||||
struct stat st;
|
||||
if (fstat(state->fdTempRoots.get(), &st) == -1)
|
||||
if (fstat(state->fdTempRoots.get(), &st) == -1) {
|
||||
throw SysError(format("statting '%1%'") % fnTempRoots);
|
||||
}
|
||||
if (st.st_size == 0) {
|
||||
break;
|
||||
}
|
||||
|
@ -245,11 +253,12 @@ void LocalStore::findTempRoots(FDs& fds, Roots& tempRoots, bool censor) {
|
|||
void LocalStore::findRoots(const Path& path, unsigned char type, Roots& roots) {
|
||||
auto foundRoot = [&](const Path& path, const Path& target) {
|
||||
Path storePath = toStorePath(target);
|
||||
if (isStorePath(storePath) && isValidPath(storePath))
|
||||
if (isStorePath(storePath) && isValidPath(storePath)) {
|
||||
roots[storePath].emplace(path);
|
||||
else
|
||||
} else {
|
||||
LOG(INFO) << "skipping invalid root from '" << path << "' to '"
|
||||
<< storePath << "'";
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
|
@ -258,8 +267,9 @@ void LocalStore::findRoots(const Path& path, unsigned char type, Roots& roots) {
|
|||
}
|
||||
|
||||
if (type == DT_DIR) {
|
||||
for (auto& i : readDirectory(path))
|
||||
for (auto& i : readDirectory(path)) {
|
||||
findRoots(path + "/" + i.name, i.type, roots);
|
||||
}
|
||||
}
|
||||
|
||||
else if (type == DT_LNK) {
|
||||
|
@ -292,8 +302,9 @@ void LocalStore::findRoots(const Path& path, unsigned char type, Roots& roots) {
|
|||
|
||||
else if (type == DT_REG) {
|
||||
Path storePath = storeDir + "/" + baseNameOf(path);
|
||||
if (isStorePath(storePath) && isValidPath(storePath))
|
||||
if (isStorePath(storePath) && isValidPath(storePath)) {
|
||||
roots[storePath].emplace(path);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -395,8 +406,9 @@ void LocalStore::findRuntimeRoots(Roots& roots, bool censor) {
|
|||
}
|
||||
struct dirent* fd_ent;
|
||||
while (errno = 0, fd_ent = readdir(fdDir.get())) {
|
||||
if (fd_ent->d_name[0] != '.')
|
||||
if (fd_ent->d_name[0] != '.') {
|
||||
readProcLink(fmt("%s/%s", fdStr, fd_ent->d_name), unchecked);
|
||||
}
|
||||
}
|
||||
if (errno) {
|
||||
if (errno == ESRCH) {
|
||||
|
@ -412,8 +424,9 @@ void LocalStore::findRuntimeRoots(Roots& roots, bool censor) {
|
|||
readFile(mapFile, true), "\n");
|
||||
for (const auto& line : mapLines) {
|
||||
auto match = std::smatch{};
|
||||
if (std::regex_match(line, match, mapRegex))
|
||||
if (std::regex_match(line, match, mapRegex)) {
|
||||
unchecked[match[1]].emplace(mapFile);
|
||||
}
|
||||
}
|
||||
|
||||
auto envFile = fmt("/proc/%s/environ", ent->d_name);
|
||||
|
@ -421,8 +434,9 @@ void LocalStore::findRuntimeRoots(Roots& roots, bool censor) {
|
|||
auto env_end = std::sregex_iterator{};
|
||||
for (auto i = std::sregex_iterator{envString.begin(), envString.end(),
|
||||
storePathRegex};
|
||||
i != env_end; ++i)
|
||||
i != env_end; ++i) {
|
||||
unchecked[i->str()].emplace(envFile);
|
||||
}
|
||||
} catch (SysError& e) {
|
||||
if (errno == ENOENT || errno == EACCES || errno == ESRCH) {
|
||||
continue;
|
||||
|
@ -467,10 +481,11 @@ void LocalStore::findRuntimeRoots(Roots& roots, bool censor) {
|
|||
Path path = toStorePath(target);
|
||||
if (isStorePath(path) && isValidPath(path)) {
|
||||
DLOG(INFO) << "got additional root " << path;
|
||||
if (censor)
|
||||
if (censor) {
|
||||
roots[path].insert(censored);
|
||||
else
|
||||
} else {
|
||||
roots[path].insert(links.begin(), links.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -514,10 +529,11 @@ void LocalStore::deletePathRecursive(GCState& state, const Path& path) {
|
|||
if (isStorePath(path) && isValidPath(path)) {
|
||||
PathSet referrers;
|
||||
queryReferrers(path, referrers);
|
||||
for (auto& i : referrers)
|
||||
for (auto& i : referrers) {
|
||||
if (i != path) {
|
||||
deletePathRecursive(state, i);
|
||||
}
|
||||
}
|
||||
size = queryPathInfo(path)->narSize;
|
||||
invalidatePathChecked(path);
|
||||
}
|
||||
|
@ -546,12 +562,14 @@ void LocalStore::deletePathRecursive(GCState& state, const Path& path) {
|
|||
// if the path was not valid, need to determine the actual
|
||||
// size.
|
||||
try {
|
||||
if (chmod(realPath.c_str(), st.st_mode | S_IWUSR) == -1)
|
||||
if (chmod(realPath.c_str(), st.st_mode | S_IWUSR) == -1) {
|
||||
throw SysError(format("making '%1%' writable") % realPath);
|
||||
}
|
||||
Path tmp = trashDir + "/" + baseNameOf(path);
|
||||
if (rename(realPath.c_str(), tmp.c_str()))
|
||||
if (rename(realPath.c_str(), tmp.c_str())) {
|
||||
throw SysError(format("unable to rename '%1%' to '%2%'") % realPath %
|
||||
tmp);
|
||||
}
|
||||
state.bytesInvalidated += size;
|
||||
} catch (SysError& e) {
|
||||
if (e.errNo == ENOSPC) {
|
||||
|
@ -560,8 +578,9 @@ void LocalStore::deletePathRecursive(GCState& state, const Path& path) {
|
|||
deleteGarbage(state, realPath);
|
||||
}
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
deleteGarbage(state, realPath);
|
||||
}
|
||||
|
||||
if (state.results.bytesFreed + state.bytesInvalidated >
|
||||
state.options.maxFreed) {
|
||||
|
@ -606,9 +625,11 @@ bool LocalStore::canReachRoot(GCState& state, PathSet& visited,
|
|||
don't delete the derivation if any of the outputs are alive. */
|
||||
if (state.gcKeepDerivations && isDerivation(path)) {
|
||||
PathSet outputs = queryDerivationOutputs(path);
|
||||
for (auto& i : outputs)
|
||||
if (isValidPath(i) && queryPathInfo(i)->deriver == path)
|
||||
for (auto& i : outputs) {
|
||||
if (isValidPath(i) && queryPathInfo(i)->deriver == path) {
|
||||
incoming.insert(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If keep-outputs is set, then don't delete this path if there
|
||||
|
@ -620,12 +641,14 @@ bool LocalStore::canReachRoot(GCState& state, PathSet& visited,
|
|||
}
|
||||
}
|
||||
|
||||
for (auto& i : incoming)
|
||||
if (i != path)
|
||||
for (auto& i : incoming) {
|
||||
if (i != path) {
|
||||
if (canReachRoot(state, visited, i)) {
|
||||
state.alive.insert(path);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -701,8 +724,9 @@ void LocalStore::removeUnusedLinks(const GCState& state) {
|
|||
Path path = linksDir + "/" + name;
|
||||
|
||||
struct stat st;
|
||||
if (lstat(path.c_str(), &st) == -1)
|
||||
if (lstat(path.c_str(), &st) == -1) {
|
||||
throw SysError(format("statting '%1%'") % path);
|
||||
}
|
||||
|
||||
if (st.st_nlink != 1) {
|
||||
actualSize += st.st_size;
|
||||
|
@ -807,16 +831,18 @@ void LocalStore::collectGarbage(const GCOptions& options, GCResults& results) {
|
|||
for (auto& i : options.pathsToDelete) {
|
||||
assertStorePath(i);
|
||||
tryToDelete(state, i);
|
||||
if (state.dead.find(i) == state.dead.end())
|
||||
if (state.dead.find(i) == state.dead.end()) {
|
||||
throw Error(format("cannot delete path '%1%' since it is still alive") %
|
||||
i);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (options.maxFreed > 0) {
|
||||
if (state.shouldDelete)
|
||||
if (state.shouldDelete) {
|
||||
LOG(INFO) << "deleting garbage...";
|
||||
else
|
||||
} else {
|
||||
LOG(ERROR) << "determining live/dead paths...";
|
||||
}
|
||||
|
||||
try {
|
||||
AutoCloseDir dir(opendir(realStoreDir.c_str()));
|
||||
|
@ -839,10 +865,11 @@ void LocalStore::collectGarbage(const GCOptions& options, GCResults& results) {
|
|||
continue;
|
||||
}
|
||||
Path path = storeDir + "/" + name;
|
||||
if (isStorePath(path) && isValidPath(path))
|
||||
if (isStorePath(path) && isValidPath(path)) {
|
||||
entries.push_back(path);
|
||||
else
|
||||
} else {
|
||||
tryToDelete(state, path);
|
||||
}
|
||||
}
|
||||
|
||||
dir.reset();
|
||||
|
@ -897,8 +924,9 @@ void LocalStore::autoGC(bool sync) {
|
|||
static auto fakeFreeSpaceFile = getEnv("_NIX_TEST_FREE_SPACE_FILE", "");
|
||||
|
||||
auto getAvail = [this]() -> uint64_t {
|
||||
if (!fakeFreeSpaceFile.empty())
|
||||
if (!fakeFreeSpaceFile.empty()) {
|
||||
return std::stoll(readFile(fakeFreeSpaceFile));
|
||||
}
|
||||
|
||||
struct statvfs st;
|
||||
if (statvfs(realStoreDir.c_str(), &st)) {
|
||||
|
@ -922,8 +950,9 @@ void LocalStore::autoGC(bool sync) {
|
|||
auto now = std::chrono::steady_clock::now();
|
||||
|
||||
if (now < state->lastGCCheck +
|
||||
std::chrono::seconds(settings.minFreeCheckInterval))
|
||||
std::chrono::seconds(settings.minFreeCheckInterval)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto avail = getAvail();
|
||||
|
||||
|
|
32
third_party/nix/src/libstore/globals.cc
vendored
32
third_party/nix/src/libstore/globals.cc
vendored
|
@ -49,11 +49,12 @@ Settings::Settings()
|
|||
if (caFile == "") {
|
||||
for (auto& fn :
|
||||
{"/etc/ssl/certs/ca-certificates.crt",
|
||||
"/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt"})
|
||||
"/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt"}) {
|
||||
if (pathExists(fn)) {
|
||||
caFile = fn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Backwards compatibility. */
|
||||
|
@ -112,26 +113,28 @@ const string nixVersion = PACKAGE_VERSION;
|
|||
|
||||
template <>
|
||||
void BaseSetting<SandboxMode>::set(const std::string& str) {
|
||||
if (str == "true")
|
||||
if (str == "true") {
|
||||
value = smEnabled;
|
||||
else if (str == "relaxed")
|
||||
} else if (str == "relaxed") {
|
||||
value = smRelaxed;
|
||||
else if (str == "false")
|
||||
} else if (str == "false") {
|
||||
value = smDisabled;
|
||||
else
|
||||
} else {
|
||||
throw UsageError("option '%s' has invalid value '%s'", name, str);
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
std::string BaseSetting<SandboxMode>::to_string() {
|
||||
if (value == smEnabled)
|
||||
if (value == smEnabled) {
|
||||
return "true";
|
||||
else if (value == smRelaxed)
|
||||
} else if (value == smRelaxed) {
|
||||
return "relaxed";
|
||||
else if (value == smDisabled)
|
||||
} else if (value == smDisabled) {
|
||||
return "false";
|
||||
else
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
|
@ -160,11 +163,12 @@ void BaseSetting<SandboxMode>::convertToArg(Args& args,
|
|||
}
|
||||
|
||||
void MaxBuildJobsSetting::set(const std::string& str) {
|
||||
if (str == "auto")
|
||||
if (str == "auto") {
|
||||
value = std::max(1U, std::thread::hardware_concurrency());
|
||||
else if (!string2Int(str, value))
|
||||
} else if (!string2Int(str, value)) {
|
||||
throw UsageError(
|
||||
"configuration setting '%s' should be 'auto' or an integer", name);
|
||||
}
|
||||
}
|
||||
|
||||
void initPlugins() {
|
||||
|
@ -172,8 +176,9 @@ void initPlugins() {
|
|||
Paths pluginFiles;
|
||||
try {
|
||||
auto ents = readDirectory(pluginFile);
|
||||
for (const auto& ent : ents)
|
||||
for (const auto& ent : ents) {
|
||||
pluginFiles.emplace_back(pluginFile + "/" + ent.name);
|
||||
}
|
||||
} catch (SysError& e) {
|
||||
if (e.errNo != ENOTDIR) {
|
||||
throw;
|
||||
|
@ -184,9 +189,10 @@ void initPlugins() {
|
|||
/* handle is purposefully leaked as there may be state in the
|
||||
DSO needed by the action of the plugin. */
|
||||
void* handle = dlopen(file.c_str(), RTLD_LAZY | RTLD_LOCAL);
|
||||
if (!handle)
|
||||
if (!handle) {
|
||||
throw Error("could not dynamically open plugin file '%s': %s", file,
|
||||
dlerror());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
15
third_party/nix/src/libstore/globals.hh
vendored
15
third_party/nix/src/libstore/globals.hh
vendored
|
@ -408,17 +408,10 @@ class Settings : public Config {
|
|||
this, true, "print-missing",
|
||||
"Whether to print what paths need to be built or downloaded."};
|
||||
|
||||
Setting<std::string> preBuildHook {
|
||||
this,
|
||||
#if __APPLE__
|
||||
nixLibexecDir + "/nix/resolve-system-dependencies",
|
||||
#else
|
||||
"",
|
||||
#endif
|
||||
"pre-build-hook",
|
||||
"A program to run just before a build to set derivation-specific build "
|
||||
"settings."
|
||||
};
|
||||
Setting<std::string> preBuildHook{
|
||||
this, "", "pre-build-hook",
|
||||
"A program to run just before a build to set derivation-specific build "
|
||||
"settings."};
|
||||
|
||||
Setting<std::string> postBuildHook{
|
||||
this, "", "post-build-hook",
|
||||
|
|
|
@ -113,9 +113,10 @@ class HttpBinaryCacheStore : public BinaryCacheStore {
|
|||
try {
|
||||
getDownloader()->download(std::move(request), sink);
|
||||
} catch (DownloadError& e) {
|
||||
if (e.error == Downloader::NotFound || e.error == Downloader::Forbidden)
|
||||
if (e.error == Downloader::NotFound || e.error == Downloader::Forbidden) {
|
||||
throw NoSuchBinaryCacheFile(
|
||||
"file '%s' does not exist in binary cache '%s'", path, getUri());
|
||||
}
|
||||
maybeDisable();
|
||||
throw;
|
||||
}
|
||||
|
@ -137,8 +138,9 @@ class HttpBinaryCacheStore : public BinaryCacheStore {
|
|||
(*callbackPtr)(result.get().data);
|
||||
} catch (DownloadError& e) {
|
||||
if (e.error == Downloader::NotFound ||
|
||||
e.error == Downloader::Forbidden)
|
||||
e.error == Downloader::Forbidden) {
|
||||
return (*callbackPtr)(std::shared_ptr<std::string>());
|
||||
}
|
||||
maybeDisable();
|
||||
callbackPtr->rethrow();
|
||||
} catch (...) {
|
||||
|
@ -154,8 +156,9 @@ static RegisterStoreImplementation regStore(
|
|||
if (std::string(uri, 0, 7) != "http://" &&
|
||||
std::string(uri, 0, 8) != "https://" &&
|
||||
(getEnv("_NIX_FORCE_HTTP_BINARY_CACHE_STORE") != "1" ||
|
||||
std::string(uri, 0, 7) != "file://"))
|
||||
std::string(uri, 0, 7) != "file://")) {
|
||||
return 0;
|
||||
}
|
||||
auto store = std::make_shared<HttpBinaryCacheStore>(params, uri);
|
||||
store->init();
|
||||
return store;
|
||||
|
|
18
third_party/nix/src/libstore/legacy-ssh-store.cc
vendored
18
third_party/nix/src/libstore/legacy-ssh-store.cc
vendored
|
@ -69,12 +69,14 @@ struct LegacySSHStore : public Store {
|
|||
conn->to.flush();
|
||||
|
||||
unsigned int magic = readInt(conn->from);
|
||||
if (magic != SERVE_MAGIC_2)
|
||||
if (magic != SERVE_MAGIC_2) {
|
||||
throw Error("protocol mismatch with 'nix-store --serve' on '%s'", host);
|
||||
}
|
||||
conn->remoteVersion = readInt(conn->from);
|
||||
if (GET_PROTOCOL_MAJOR(conn->remoteVersion) != 0x200)
|
||||
if (GET_PROTOCOL_MAJOR(conn->remoteVersion) != 0x200) {
|
||||
throw Error("unsupported 'nix-store --serve' protocol version on '%s'",
|
||||
host);
|
||||
}
|
||||
|
||||
} catch (EndOfFile& e) {
|
||||
throw Error("cannot connect to '%1%'", host);
|
||||
|
@ -160,9 +162,10 @@ struct LegacySSHStore : public Store {
|
|||
conn->to.flush();
|
||||
}
|
||||
|
||||
if (readInt(conn->from) != 1)
|
||||
if (readInt(conn->from) != 1) {
|
||||
throw Error(
|
||||
"failed to add path '%s' to remote host '%s', info.path, host");
|
||||
}
|
||||
}
|
||||
|
||||
void narFromPath(const Path& path, Sink& sink) override {
|
||||
|
@ -194,10 +197,12 @@ struct LegacySSHStore : public Store {
|
|||
|
||||
conn->to << cmdBuildDerivation << drvPath << drv << settings.maxSilentTime
|
||||
<< settings.buildTimeout;
|
||||
if (GET_PROTOCOL_MINOR(conn->remoteVersion) >= 2)
|
||||
if (GET_PROTOCOL_MINOR(conn->remoteVersion) >= 2) {
|
||||
conn->to << settings.maxLogSize;
|
||||
if (GET_PROTOCOL_MINOR(conn->remoteVersion) >= 3)
|
||||
}
|
||||
if (GET_PROTOCOL_MINOR(conn->remoteVersion) >= 3) {
|
||||
conn->to << settings.buildRepeat << settings.enforceDeterminism;
|
||||
}
|
||||
|
||||
conn->to.flush();
|
||||
|
||||
|
@ -205,9 +210,10 @@ struct LegacySSHStore : public Store {
|
|||
status.status = (BuildResult::Status)readInt(conn->from);
|
||||
conn->from >> status.errorMsg;
|
||||
|
||||
if (GET_PROTOCOL_MINOR(conn->remoteVersion) >= 3)
|
||||
if (GET_PROTOCOL_MINOR(conn->remoteVersion) >= 3) {
|
||||
conn->from >> status.timesBuilt >> status.isNonDeterministic >>
|
||||
status.startTime >> status.stopTime;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
|
|
@ -26,9 +26,10 @@ class LocalBinaryCacheStore : public BinaryCacheStore {
|
|||
try {
|
||||
readFile(binaryCacheDir + "/" + path, sink);
|
||||
} catch (SysError& e) {
|
||||
if (e.errNo == ENOENT)
|
||||
if (e.errNo == ENOENT) {
|
||||
throw NoSuchBinaryCacheFile("file '%s' does not exist in binary cache",
|
||||
path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -36,8 +37,9 @@ class LocalBinaryCacheStore : public BinaryCacheStore {
|
|||
PathSet paths;
|
||||
|
||||
for (auto& entry : readDirectory(binaryCacheDir)) {
|
||||
if (entry.name.size() != 40 || !hasSuffix(entry.name, ".narinfo"))
|
||||
if (entry.name.size() != 40 || !hasSuffix(entry.name, ".narinfo")) {
|
||||
continue;
|
||||
}
|
||||
paths.insert(storeDir + "/" +
|
||||
entry.name.substr(0, entry.name.size() - 8));
|
||||
}
|
||||
|
@ -55,8 +57,9 @@ static void atomicWrite(const Path& path, const std::string& s) {
|
|||
Path tmp = path + ".tmp." + std::to_string(getpid());
|
||||
AutoDelete del(tmp, false);
|
||||
writeFile(tmp, s);
|
||||
if (rename(tmp.c_str(), path.c_str()))
|
||||
if (rename(tmp.c_str(), path.c_str())) {
|
||||
throw SysError(format("renaming '%1%' to '%2%'") % tmp % path);
|
||||
}
|
||||
del.cancel();
|
||||
}
|
||||
|
||||
|
@ -74,8 +77,9 @@ static RegisterStoreImplementation regStore(
|
|||
[](const std::string& uri,
|
||||
const Store::Params& params) -> std::shared_ptr<Store> {
|
||||
if (getEnv("_NIX_FORCE_HTTP_BINARY_CACHE_STORE") == "1" ||
|
||||
std::string(uri, 0, 7) != "file://")
|
||||
std::string(uri, 0, 7) != "file://") {
|
||||
return 0;
|
||||
}
|
||||
auto store =
|
||||
std::make_shared<LocalBinaryCacheStore>(params, std::string(uri, 7));
|
||||
store->init();
|
||||
|
|
|
@ -16,9 +16,10 @@ struct LocalStoreAccessor : public FSAccessor {
|
|||
|
||||
Path toRealPath(const Path& path) {
|
||||
Path storePath = store->toStorePath(path);
|
||||
if (!store->isValidPath(storePath))
|
||||
if (!store->isValidPath(storePath)) {
|
||||
throw InvalidPath(format("path '%1%' is not a valid store path") %
|
||||
storePath);
|
||||
}
|
||||
return store->getRealStoreDir() + std::string(path, store->storeDir.size());
|
||||
}
|
||||
|
||||
|
@ -27,13 +28,15 @@ struct LocalStoreAccessor : public FSAccessor {
|
|||
|
||||
struct stat st;
|
||||
if (lstat(realPath.c_str(), &st)) {
|
||||
if (errno == ENOENT || errno == ENOTDIR)
|
||||
if (errno == ENOENT || errno == ENOTDIR) {
|
||||
return {Type::tMissing, 0, false};
|
||||
}
|
||||
throw SysError(format("getting status of '%1%'") % path);
|
||||
}
|
||||
|
||||
if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode))
|
||||
if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode)) {
|
||||
throw Error(format("file '%1%' has unsupported type") % path);
|
||||
}
|
||||
|
||||
return {S_ISREG(st.st_mode)
|
||||
? Type::tRegular
|
||||
|
|
171
third_party/nix/src/libstore/local-store.cc
vendored
171
third_party/nix/src/libstore/local-store.cc
vendored
|
@ -73,8 +73,9 @@ LocalStore::LocalStore(const Params& params)
|
|||
for (auto& perUserDir :
|
||||
{profilesDir + "/per-user", gcRootsDir + "/per-user"}) {
|
||||
createDirs(perUserDir);
|
||||
if (chmod(perUserDir.c_str(), 0755) == -1)
|
||||
if (chmod(perUserDir.c_str(), 0755) == -1) {
|
||||
throw SysError("could not set permissions on '%s' to 755", perUserDir);
|
||||
}
|
||||
}
|
||||
|
||||
createUser(getUserName(), getuid());
|
||||
|
@ -90,18 +91,21 @@ LocalStore::LocalStore(const Params& params)
|
|||
<< "' specified in 'build-users-group' does not exist";
|
||||
} else {
|
||||
struct stat st;
|
||||
if (stat(realStoreDir.c_str(), &st))
|
||||
if (stat(realStoreDir.c_str(), &st)) {
|
||||
throw SysError(format("getting attributes of path '%1%'") %
|
||||
realStoreDir);
|
||||
}
|
||||
|
||||
if (st.st_uid != 0 || st.st_gid != gr->gr_gid ||
|
||||
(st.st_mode & ~S_IFMT) != perm) {
|
||||
if (chown(realStoreDir.c_str(), 0, gr->gr_gid) == -1)
|
||||
if (chown(realStoreDir.c_str(), 0, gr->gr_gid) == -1) {
|
||||
throw SysError(format("changing ownership of path '%1%'") %
|
||||
realStoreDir);
|
||||
if (chmod(realStoreDir.c_str(), perm) == -1)
|
||||
}
|
||||
if (chmod(realStoreDir.c_str(), perm) == -1) {
|
||||
throw SysError(format("changing permissions on path '%1%'") %
|
||||
realStoreDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -111,13 +115,15 @@ LocalStore::LocalStore(const Params& params)
|
|||
Path path = realStoreDir;
|
||||
struct stat st;
|
||||
while (path != "/") {
|
||||
if (lstat(path.c_str(), &st))
|
||||
if (lstat(path.c_str(), &st)) {
|
||||
throw SysError(format("getting status of '%1%'") % path);
|
||||
if (S_ISLNK(st.st_mode))
|
||||
}
|
||||
if (S_ISLNK(st.st_mode)) {
|
||||
throw Error(format("the path '%1%' is a symlink; "
|
||||
"this is not allowed for the Nix store and its "
|
||||
"parent directories") %
|
||||
path);
|
||||
}
|
||||
path = dirOf(path);
|
||||
}
|
||||
}
|
||||
|
@ -168,17 +174,19 @@ LocalStore::LocalStore(const Params& params)
|
|||
openDB(*state, true);
|
||||
writeFile(schemaPath, (format("%1%") % nixSchemaVersion).str());
|
||||
} else if (curSchema < nixSchemaVersion) {
|
||||
if (curSchema < 5)
|
||||
if (curSchema < 5) {
|
||||
throw Error(
|
||||
"Your Nix store has a database in Berkeley DB format,\n"
|
||||
"which is no longer supported. To convert to the new format,\n"
|
||||
"please upgrade Nix to version 0.12 first.");
|
||||
}
|
||||
|
||||
if (curSchema < 6)
|
||||
if (curSchema < 6) {
|
||||
throw Error(
|
||||
"Your Nix store has a database in flat file format,\n"
|
||||
"which is no longer supported. To convert to the new format,\n"
|
||||
"please upgrade Nix to version 1.11 first.");
|
||||
}
|
||||
|
||||
if (!lockFile(globalLock.get(), ltWrite, false)) {
|
||||
LOG(INFO) << "waiting for exclusive access to the Nix store...";
|
||||
|
@ -295,24 +303,27 @@ int LocalStore::getSchema() {
|
|||
int curSchema = 0;
|
||||
if (pathExists(schemaPath)) {
|
||||
string s = readFile(schemaPath);
|
||||
if (!string2Int(s, curSchema))
|
||||
if (!string2Int(s, curSchema)) {
|
||||
throw Error(format("'%1%' is corrupt") % schemaPath);
|
||||
}
|
||||
}
|
||||
return curSchema;
|
||||
}
|
||||
|
||||
void LocalStore::openDB(State& state, bool create) {
|
||||
if (access(dbDir.c_str(), R_OK | W_OK))
|
||||
if (access(dbDir.c_str(), R_OK | W_OK)) {
|
||||
throw SysError(format("Nix database directory '%1%' is not writable") %
|
||||
dbDir);
|
||||
}
|
||||
|
||||
/* Open the Nix database. */
|
||||
string dbPath = dbDir + "/db.sqlite";
|
||||
auto& db(state.db);
|
||||
if (sqlite3_open_v2(dbPath.c_str(), &db.db,
|
||||
SQLITE_OPEN_READWRITE | (create ? SQLITE_OPEN_CREATE : 0),
|
||||
0) != SQLITE_OK)
|
||||
0) != SQLITE_OK) {
|
||||
throw Error(format("cannot open Nix database '%1%'") % dbPath);
|
||||
}
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
/* The cygwin version of sqlite3 has a patch which calls
|
||||
|
@ -354,15 +365,17 @@ void LocalStore::openDB(State& state, bool create) {
|
|||
}
|
||||
if (prevMode != mode &&
|
||||
sqlite3_exec(db, ("pragma main.journal_mode = " + mode + ";").c_str(), 0,
|
||||
0, 0) != SQLITE_OK)
|
||||
0, 0) != SQLITE_OK) {
|
||||
throwSQLiteError(db, "setting journal mode");
|
||||
}
|
||||
|
||||
/* Increase the auto-checkpoint interval to 40000 pages. This
|
||||
seems enough to ensure that instantiating the NixOS system
|
||||
derivation is done in a single fsync(). */
|
||||
if (mode == "wal" && sqlite3_exec(db, "pragma wal_autocheckpoint = 40000;", 0,
|
||||
0, 0) != SQLITE_OK)
|
||||
0, 0) != SQLITE_OK) {
|
||||
throwSQLiteError(db, "setting autocheckpoint interval");
|
||||
}
|
||||
|
||||
/* Initialise the database schema, if necessary. */
|
||||
if (create) {
|
||||
|
@ -382,15 +395,18 @@ void LocalStore::makeStoreWritable() {
|
|||
}
|
||||
/* Check if /nix/store is on a read-only mount. */
|
||||
struct statvfs stat;
|
||||
if (statvfs(realStoreDir.c_str(), &stat) != 0)
|
||||
if (statvfs(realStoreDir.c_str(), &stat) != 0) {
|
||||
throw SysError("getting info about the Nix store mount point");
|
||||
}
|
||||
|
||||
if (stat.f_flag & ST_RDONLY) {
|
||||
if (unshare(CLONE_NEWNS) == -1)
|
||||
if (unshare(CLONE_NEWNS) == -1) {
|
||||
throw SysError("setting up a private mount namespace");
|
||||
}
|
||||
|
||||
if (mount(0, realStoreDir.c_str(), "none", MS_REMOUNT | MS_BIND, 0) == -1)
|
||||
if (mount(0, realStoreDir.c_str(), "none", MS_REMOUNT | MS_BIND, 0) == -1) {
|
||||
throw SysError(format("remounting %1% writable") % realStoreDir);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -405,8 +421,9 @@ static void canonicaliseTimestampAndPermissions(const Path& path,
|
|||
|
||||
if (mode != 0444 && mode != 0555) {
|
||||
mode = (st.st_mode & S_IFMT) | 0444 | (st.st_mode & S_IXUSR ? 0111 : 0);
|
||||
if (chmod(path.c_str(), mode) == -1)
|
||||
if (chmod(path.c_str(), mode) == -1) {
|
||||
throw SysError(format("changing mode of '%1%' to %2$o") % path % mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -417,20 +434,23 @@ static void canonicaliseTimestampAndPermissions(const Path& path,
|
|||
times[1].tv_sec = mtimeStore;
|
||||
times[1].tv_usec = 0;
|
||||
#if HAVE_LUTIMES
|
||||
if (lutimes(path.c_str(), times) == -1)
|
||||
if (lutimes(path.c_str(), times) == -1) {
|
||||
if (errno != ENOSYS ||
|
||||
(!S_ISLNK(st.st_mode) && utimes(path.c_str(), times) == -1))
|
||||
(!S_ISLNK(st.st_mode) && utimes(path.c_str(), times) == -1)) {
|
||||
#else
|
||||
if (!S_ISLNK(st.st_mode) && utimes(path.c_str(), times) == -1)
|
||||
#endif
|
||||
throw SysError(format("changing modification time of '%1%'") % path);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace nix
|
||||
}
|
||||
|
||||
void canonicaliseTimestampAndPermissions(const Path& path) {
|
||||
struct stat st;
|
||||
if (lstat(path.c_str(), &st))
|
||||
if (lstat(path.c_str(), &st)) {
|
||||
throw SysError(format("getting attributes of path '%1%'") % path);
|
||||
}
|
||||
canonicaliseTimestampAndPermissions(path, st);
|
||||
}
|
||||
|
||||
|
@ -449,25 +469,29 @@ static void canonicalisePathMetaData_(const Path& path, uid_t fromUid,
|
|||
#endif
|
||||
|
||||
struct stat st;
|
||||
if (lstat(path.c_str(), &st))
|
||||
if (lstat(path.c_str(), &st)) {
|
||||
throw SysError(format("getting attributes of path '%1%'") % path);
|
||||
}
|
||||
|
||||
/* Really make sure that the path is of a supported type. */
|
||||
if (!(S_ISREG(st.st_mode) || S_ISDIR(st.st_mode) || S_ISLNK(st.st_mode)))
|
||||
if (!(S_ISREG(st.st_mode) || S_ISDIR(st.st_mode) || S_ISLNK(st.st_mode))) {
|
||||
throw Error(format("file '%1%' has an unsupported type") % path);
|
||||
}
|
||||
|
||||
#if __linux__
|
||||
/* Remove extended attributes / ACLs. */
|
||||
ssize_t eaSize = llistxattr(path.c_str(), nullptr, 0);
|
||||
|
||||
if (eaSize < 0) {
|
||||
if (errno != ENOTSUP && errno != ENODATA)
|
||||
if (errno != ENOTSUP && errno != ENODATA) {
|
||||
throw SysError("querying extended attributes of '%s'", path);
|
||||
}
|
||||
} else if (eaSize > 0) {
|
||||
std::vector<char> eaBuf(eaSize);
|
||||
|
||||
if ((eaSize = llistxattr(path.c_str(), eaBuf.data(), eaBuf.size())) < 0)
|
||||
if ((eaSize = llistxattr(path.c_str(), eaBuf.data(), eaBuf.size())) < 0) {
|
||||
throw SysError("querying extended attributes of '%s'", path);
|
||||
}
|
||||
|
||||
for (auto& eaName : tokenizeString<Strings>(
|
||||
std::string(eaBuf.data(), eaSize), std::string("\000", 1))) {
|
||||
|
@ -476,9 +500,10 @@ static void canonicalisePathMetaData_(const Path& path, uid_t fromUid,
|
|||
if (eaName == "security.selinux") {
|
||||
continue;
|
||||
}
|
||||
if (lremovexattr(path.c_str(), eaName.c_str()) == -1)
|
||||
if (lremovexattr(path.c_str(), eaName.c_str()) == -1) {
|
||||
throw SysError("removing extended attribute '%s' from '%s'", eaName,
|
||||
path);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -491,8 +516,9 @@ static void canonicalisePathMetaData_(const Path& path, uid_t fromUid,
|
|||
(i.e. "touch $out/foo; ln $out/foo $out/bar"). */
|
||||
if (fromUid != (uid_t)-1 && st.st_uid != fromUid) {
|
||||
assert(!S_ISDIR(st.st_mode));
|
||||
if (inodesSeen.find(Inode(st.st_dev, st.st_ino)) == inodesSeen.end())
|
||||
if (inodesSeen.find(Inode(st.st_dev, st.st_ino)) == inodesSeen.end()) {
|
||||
throw BuildError(format("invalid ownership on file '%1%'") % path);
|
||||
}
|
||||
mode_t mode = st.st_mode & ~S_IFMT;
|
||||
assert(S_ISLNK(st.st_mode) ||
|
||||
(st.st_uid == geteuid() && (mode == 0444 || mode == 0555) &&
|
||||
|
@ -513,18 +539,20 @@ static void canonicalisePathMetaData_(const Path& path, uid_t fromUid,
|
|||
users group); we check for this case below. */
|
||||
if (st.st_uid != geteuid()) {
|
||||
#if HAVE_LCHOWN
|
||||
if (lchown(path.c_str(), geteuid(), getegid()) == -1)
|
||||
if (lchown(path.c_str(), geteuid(), getegid()) == -1) {
|
||||
#else
|
||||
if (!S_ISLNK(st.st_mode) && chown(path.c_str(), geteuid(), getegid()) == -1)
|
||||
#endif
|
||||
throw SysError(format("changing owner of '%1%' to %2%") % path %
|
||||
geteuid());
|
||||
}
|
||||
}
|
||||
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
DirEntries entries = readDirectory(path);
|
||||
for (auto& i : entries)
|
||||
for (auto& i : entries) {
|
||||
canonicalisePathMetaData_(path + "/" + i.name, fromUid, inodesSeen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -535,8 +563,9 @@ void canonicalisePathMetaData(const Path& path, uid_t fromUid,
|
|||
/* On platforms that don't have lchown(), the top-level path can't
|
||||
be a symlink, since we can't change its ownership. */
|
||||
struct stat st;
|
||||
if (lstat(path.c_str(), &st))
|
||||
if (lstat(path.c_str(), &st)) {
|
||||
throw SysError(format("getting attributes of path '%1%'") % path);
|
||||
}
|
||||
|
||||
if (st.st_uid != geteuid()) {
|
||||
assert(S_ISLNK(st.st_mode));
|
||||
|
@ -557,10 +586,11 @@ void LocalStore::checkDerivationOutputs(const Path& drvPath,
|
|||
|
||||
if (drv.isFixedOutput()) {
|
||||
DerivationOutputs::const_iterator out = drv.outputs.find("out");
|
||||
if (out == drv.outputs.end())
|
||||
if (out == drv.outputs.end()) {
|
||||
throw Error(
|
||||
format("derivation '%1%' does not have an output named 'out'") %
|
||||
drvPath);
|
||||
}
|
||||
|
||||
bool recursive;
|
||||
Hash h;
|
||||
|
@ -569,11 +599,12 @@ void LocalStore::checkDerivationOutputs(const Path& drvPath,
|
|||
|
||||
StringPairs::const_iterator j = drv.env.find("out");
|
||||
if (out->second.path != outPath || j == drv.env.end() ||
|
||||
j->second != outPath)
|
||||
j->second != outPath) {
|
||||
throw Error(
|
||||
format(
|
||||
"derivation '%1%' has incorrect output '%2%', should be '%3%'") %
|
||||
drvPath % out->second.path % outPath);
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
|
@ -589,21 +620,23 @@ void LocalStore::checkDerivationOutputs(const Path& drvPath,
|
|||
Path outPath = makeOutputPath(i.first, h, drvName);
|
||||
StringPairs::const_iterator j = drv.env.find(i.first);
|
||||
if (i.second.path != outPath || j == drv.env.end() ||
|
||||
j->second != outPath)
|
||||
j->second != outPath) {
|
||||
throw Error(format("derivation '%1%' has incorrect output '%2%', "
|
||||
"should be '%3%'") %
|
||||
drvPath % i.second.path % outPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t LocalStore::addValidPath(State& state, const ValidPathInfo& info,
|
||||
bool checkOutputs) {
|
||||
if (info.ca != "" && !info.isContentAddressed(*this))
|
||||
if (info.ca != "" && !info.isContentAddressed(*this)) {
|
||||
throw Error(
|
||||
"cannot add path '%s' to the Nix store because it claims to be "
|
||||
"content-addressed but isn't",
|
||||
info.path);
|
||||
}
|
||||
|
||||
state.stmtRegisterValidPath
|
||||
.use()(info.path)(info.narHash.to_string(Base16))(
|
||||
|
@ -697,8 +730,9 @@ void LocalStore::queryPathInfoUncached(
|
|||
/* Get the references. */
|
||||
auto useQueryReferences(state->stmtQueryReferences.use()(info->id));
|
||||
|
||||
while (useQueryReferences.next())
|
||||
while (useQueryReferences.next()) {
|
||||
info->references.insert(useQueryReferences.getStr(0));
|
||||
}
|
||||
|
||||
return info;
|
||||
}));
|
||||
|
@ -740,10 +774,11 @@ bool LocalStore::isValidPathUncached(const Path& path) {
|
|||
PathSet LocalStore::queryValidPaths(const PathSet& paths,
|
||||
SubstituteFlag maybeSubstitute) {
|
||||
PathSet res;
|
||||
for (auto& i : paths)
|
||||
for (auto& i : paths) {
|
||||
if (isValidPath(i)) {
|
||||
res.insert(i);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -752,7 +787,9 @@ PathSet LocalStore::queryAllValidPaths() {
|
|||
auto state(_state.lock());
|
||||
auto use(state->stmtQueryValidPaths.use());
|
||||
PathSet res;
|
||||
while (use.next()) res.insert(use.getStr(0));
|
||||
while (use.next()) {
|
||||
res.insert(use.getStr(0));
|
||||
}
|
||||
return res;
|
||||
});
|
||||
}
|
||||
|
@ -761,8 +798,9 @@ void LocalStore::queryReferrers(State& state, const Path& path,
|
|||
PathSet& referrers) {
|
||||
auto useQueryReferrers(state.stmtQueryReferrers.use()(path));
|
||||
|
||||
while (useQueryReferrers.next())
|
||||
while (useQueryReferrers.next()) {
|
||||
referrers.insert(useQueryReferrers.getStr(0));
|
||||
}
|
||||
}
|
||||
|
||||
void LocalStore::queryReferrers(const Path& path, PathSet& referrers) {
|
||||
|
@ -782,8 +820,9 @@ PathSet LocalStore::queryValidDerivers(const Path& path) {
|
|||
auto useQueryValidDerivers(state->stmtQueryValidDerivers.use()(path));
|
||||
|
||||
PathSet derivers;
|
||||
while (useQueryValidDerivers.next())
|
||||
while (useQueryValidDerivers.next()) {
|
||||
derivers.insert(useQueryValidDerivers.getStr(1));
|
||||
}
|
||||
|
||||
return derivers;
|
||||
});
|
||||
|
@ -797,8 +836,9 @@ PathSet LocalStore::queryDerivationOutputs(const Path& path) {
|
|||
queryValidPathId(*state, path)));
|
||||
|
||||
PathSet outputs;
|
||||
while (useQueryDerivationOutputs.next())
|
||||
while (useQueryDerivationOutputs.next()) {
|
||||
outputs.insert(useQueryDerivationOutputs.getStr(1));
|
||||
}
|
||||
|
||||
return outputs;
|
||||
});
|
||||
|
@ -812,8 +852,9 @@ StringSet LocalStore::queryDerivationOutputNames(const Path& path) {
|
|||
queryValidPathId(*state, path)));
|
||||
|
||||
StringSet outputNames;
|
||||
while (useQueryDerivationOutputs.next())
|
||||
while (useQueryDerivationOutputs.next()) {
|
||||
outputNames.insert(useQueryDerivationOutputs.getStr(0));
|
||||
}
|
||||
|
||||
return outputNames;
|
||||
});
|
||||
|
@ -865,11 +906,13 @@ PathSet LocalStore::querySubstitutablePaths(const PathSet& paths) {
|
|||
auto valid = sub->queryValidPaths(remaining);
|
||||
|
||||
PathSet remaining2;
|
||||
for (auto& path : remaining)
|
||||
if (valid.count(path))
|
||||
for (auto& path : remaining) {
|
||||
if (valid.count(path)) {
|
||||
res.insert(path);
|
||||
else
|
||||
} else {
|
||||
remaining2.insert(path);
|
||||
}
|
||||
}
|
||||
|
||||
std::swap(remaining, remaining2);
|
||||
}
|
||||
|
@ -935,24 +978,26 @@ void LocalStore::registerValidPaths(const ValidPathInfos& infos) {
|
|||
|
||||
for (auto& i : infos) {
|
||||
assert(i.narHash.type == htSHA256);
|
||||
if (isValidPath_(*state, i.path))
|
||||
if (isValidPath_(*state, i.path)) {
|
||||
updatePathInfo(*state, i);
|
||||
else
|
||||
} else {
|
||||
addValidPath(*state, i, false);
|
||||
}
|
||||
paths.insert(i.path);
|
||||
}
|
||||
|
||||
for (auto& i : infos) {
|
||||
auto referrer = queryValidPathId(*state, i.path);
|
||||
for (auto& j : i.references)
|
||||
for (auto& j : i.references) {
|
||||
state->stmtAddReference.use()(referrer)(queryValidPathId(*state, j))
|
||||
.exec();
|
||||
}
|
||||
}
|
||||
|
||||
/* Check that the derivation outputs are correct. We can't do
|
||||
this in addValidPath() above, because the references might
|
||||
not be valid yet. */
|
||||
for (auto& i : infos)
|
||||
for (auto& i : infos) {
|
||||
if (isDerivation(i.path)) {
|
||||
// FIXME: inefficient; we already loaded the
|
||||
// derivation in addValidPath().
|
||||
|
@ -960,6 +1005,7 @@ void LocalStore::registerValidPaths(const ValidPathInfos& infos) {
|
|||
readDerivation(realStoreDir + "/" + baseNameOf(i.path));
|
||||
checkDerivationOutputs(i.path, drv);
|
||||
}
|
||||
}
|
||||
|
||||
/* Do a topological sort of the paths. This will throw an
|
||||
error if a cycle is detected and roll back the
|
||||
|
@ -989,8 +1035,9 @@ void LocalStore::invalidatePath(State& state, const Path& path) {
|
|||
|
||||
const PublicKeys& LocalStore::getPublicKeys() {
|
||||
auto state(_state.lock());
|
||||
if (!state->publicKeys)
|
||||
if (!state->publicKeys) {
|
||||
state->publicKeys = std::make_unique<PublicKeys>(getDefaultPublicKeys());
|
||||
}
|
||||
return *state->publicKeys;
|
||||
}
|
||||
|
||||
|
@ -1039,15 +1086,17 @@ void LocalStore::addToStore(const ValidPathInfo& info, Source& source,
|
|||
|
||||
auto hashResult = hashSink.finish();
|
||||
|
||||
if (hashResult.first != info.narHash)
|
||||
if (hashResult.first != info.narHash) {
|
||||
throw Error(
|
||||
"hash mismatch importing path '%s';\n wanted: %s\n got: %s",
|
||||
info.path, info.narHash.to_string(), hashResult.first.to_string());
|
||||
}
|
||||
|
||||
if (hashResult.second != info.narSize)
|
||||
if (hashResult.second != info.narSize) {
|
||||
throw Error(
|
||||
"size mismatch importing path '%s';\n wanted: %s\n got: %s",
|
||||
info.path, info.narSize, hashResult.second);
|
||||
}
|
||||
|
||||
autoGC();
|
||||
|
||||
|
@ -1130,10 +1179,11 @@ Path LocalStore::addToStore(const string& name, const Path& _srcPath,
|
|||
method for very large paths, but `copyPath' is mainly used for
|
||||
small files. */
|
||||
StringSink sink;
|
||||
if (recursive)
|
||||
if (recursive) {
|
||||
dumpPath(srcPath, sink, filter);
|
||||
else
|
||||
} else {
|
||||
sink.s = make_ref<std::string>(readFile(srcPath));
|
||||
}
|
||||
|
||||
return addToStoreFromDump(*sink.s, name, recursive, hashAlgo, repair);
|
||||
}
|
||||
|
@ -1206,10 +1256,11 @@ void LocalStore::invalidatePathChecked(const Path& path) {
|
|||
PathSet referrers;
|
||||
queryReferrers(*state, path, referrers);
|
||||
referrers.erase(path); /* ignore self-references */
|
||||
if (!referrers.empty())
|
||||
if (!referrers.empty()) {
|
||||
throw PathInUse(
|
||||
format("cannot delete path '%1%' because it is in use by %2%") %
|
||||
path % showPaths(referrers));
|
||||
}
|
||||
invalidatePath(*state, path);
|
||||
}
|
||||
|
||||
|
@ -1238,8 +1289,9 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair) {
|
|||
|
||||
fdGCLock = -1;
|
||||
|
||||
for (auto& i : validPaths2)
|
||||
for (auto& i : validPaths2) {
|
||||
verifyPath(i, store, done, validPaths, repair, errors);
|
||||
}
|
||||
|
||||
/* Optionally, check the content hashes (slow). */
|
||||
if (checkContents) {
|
||||
|
@ -1328,13 +1380,14 @@ void LocalStore::verifyPath(const Path& path, const PathSet& store,
|
|||
bool canInvalidate = true;
|
||||
PathSet referrers;
|
||||
queryReferrers(path, referrers);
|
||||
for (auto& i : referrers)
|
||||
for (auto& i : referrers) {
|
||||
if (i != path) {
|
||||
verifyPath(i, store, done, validPaths, repair, errors);
|
||||
if (validPaths.find(i) != validPaths.end()) {
|
||||
canInvalidate = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (canInvalidate) {
|
||||
LOG(WARNING) << "path '" << path
|
||||
|
@ -1463,10 +1516,12 @@ void LocalStore::createUser(const std::string& userName, uid_t userId) {
|
|||
for (auto& dir : {fmt("%s/profiles/per-user/%s", stateDir, userName),
|
||||
fmt("%s/gcroots/per-user/%s", stateDir, userName)}) {
|
||||
createDirs(dir);
|
||||
if (chmod(dir.c_str(), 0755) == -1)
|
||||
if (chmod(dir.c_str(), 0755) == -1) {
|
||||
throw SysError("changing permissions of directory '%s'", dir);
|
||||
if (chown(dir.c_str(), userId, getgid()) == -1)
|
||||
}
|
||||
if (chown(dir.c_str(), userId, getgid()) == -1) {
|
||||
throw SysError("changing owner of directory '%s'", dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
58
third_party/nix/src/libstore/misc.cc
vendored
58
third_party/nix/src/libstore/misc.cc
vendored
|
@ -47,35 +47,44 @@ void Store::computeFSClosure(const PathSet& startPaths, PathSet& paths_,
|
|||
if (flipDirection) {
|
||||
PathSet referrers;
|
||||
queryReferrers(path, referrers);
|
||||
for (auto& ref : referrers)
|
||||
for (auto& ref : referrers) {
|
||||
if (ref != path) {
|
||||
enqueue(ref);
|
||||
}
|
||||
}
|
||||
|
||||
if (includeOutputs)
|
||||
if (includeOutputs) {
|
||||
for (auto& i : queryValidDerivers(path)) {
|
||||
enqueue(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (includeDerivers && isDerivation(path))
|
||||
for (auto& i : queryDerivationOutputs(path))
|
||||
if (isValidPath(i) && queryPathInfo(i)->deriver == path)
|
||||
if (includeDerivers && isDerivation(path)) {
|
||||
for (auto& i : queryDerivationOutputs(path)) {
|
||||
if (isValidPath(i) && queryPathInfo(i)->deriver == path) {
|
||||
enqueue(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
for (auto& ref : info->references)
|
||||
for (auto& ref : info->references) {
|
||||
if (ref != path) {
|
||||
enqueue(ref);
|
||||
}
|
||||
}
|
||||
|
||||
if (includeOutputs && isDerivation(path))
|
||||
for (auto& i : queryDerivationOutputs(path))
|
||||
if (includeOutputs && isDerivation(path)) {
|
||||
for (auto& i : queryDerivationOutputs(path)) {
|
||||
if (isValidPath(i)) {
|
||||
enqueue(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (includeDerivers && isValidPath(info->deriver))
|
||||
if (includeDerivers && isValidPath(info->deriver)) {
|
||||
enqueue(info->deriver);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -105,7 +114,9 @@ void Store::computeFSClosure(const PathSet& startPaths, PathSet& paths_,
|
|||
|
||||
{
|
||||
auto state(state_.lock());
|
||||
while (state->pending) state.wait(done);
|
||||
while (state->pending) {
|
||||
state.wait(done);
|
||||
}
|
||||
if (state->exc) {
|
||||
std::rethrow_exception(state->exc);
|
||||
}
|
||||
|
@ -154,9 +165,10 @@ void Store::queryMissing(const PathSet& targets, PathSet& willBuild_,
|
|||
state->willBuild.insert(drvPath);
|
||||
}
|
||||
|
||||
for (auto& i : drv.inputDrvs)
|
||||
for (auto& i : drv.inputDrvs) {
|
||||
pool.enqueue(
|
||||
std::bind(doPath, makeDrvPathWithOutputs(i.first, i.second)));
|
||||
}
|
||||
};
|
||||
|
||||
auto checkOutput = [&](const Path& drvPath, ref<Derivation> drv,
|
||||
|
@ -181,8 +193,9 @@ void Store::queryMissing(const PathSet& targets, PathSet& willBuild_,
|
|||
drvState->left--;
|
||||
drvState->outPaths.insert(outPath);
|
||||
if (!drvState->left) {
|
||||
for (auto& path : drvState->outPaths)
|
||||
for (auto& path : drvState->outPaths) {
|
||||
pool.enqueue(std::bind(doPath, path));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -211,20 +224,24 @@ void Store::queryMissing(const PathSet& targets, PathSet& willBuild_,
|
|||
ParsedDerivation parsedDrv(i2.first, drv);
|
||||
|
||||
PathSet invalid;
|
||||
for (auto& j : drv.outputs)
|
||||
if (wantOutput(j.first, i2.second) && !isValidPath(j.second.path))
|
||||
for (auto& j : drv.outputs) {
|
||||
if (wantOutput(j.first, i2.second) && !isValidPath(j.second.path)) {
|
||||
invalid.insert(j.second.path);
|
||||
}
|
||||
}
|
||||
if (invalid.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (settings.useSubstitutes && parsedDrv.substitutesAllowed()) {
|
||||
auto drvState = make_ref<Sync<DrvState>>(DrvState(invalid.size()));
|
||||
for (auto& output : invalid)
|
||||
for (auto& output : invalid) {
|
||||
pool.enqueue(std::bind(checkOutput, i2.first,
|
||||
make_ref<Derivation>(drv), output, drvState));
|
||||
} else
|
||||
}
|
||||
} else {
|
||||
mustBuildDrv(i2.first, drv);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (isValidPath(path)) {
|
||||
|
@ -250,8 +267,9 @@ void Store::queryMissing(const PathSet& targets, PathSet& willBuild_,
|
|||
state->narSize += info->second.narSize;
|
||||
}
|
||||
|
||||
for (auto& ref : info->second.references)
|
||||
for (auto& ref : info->second.references) {
|
||||
pool.enqueue(std::bind(doPath, ref));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -269,10 +287,11 @@ Paths Store::topoSortPaths(const PathSet& paths) {
|
|||
std::function<void(const Path& path, const Path* parent)> dfsVisit;
|
||||
|
||||
dfsVisit = [&](const Path& path, const Path* parent) {
|
||||
if (parents.find(path) != parents.end())
|
||||
if (parents.find(path) != parents.end()) {
|
||||
throw BuildError(
|
||||
format("cycle detected in the references of '%1%' from '%2%'") %
|
||||
path % *parent);
|
||||
}
|
||||
|
||||
if (visited.find(path) != visited.end()) {
|
||||
return;
|
||||
|
@ -286,12 +305,13 @@ Paths Store::topoSortPaths(const PathSet& paths) {
|
|||
} catch (InvalidPath&) {
|
||||
}
|
||||
|
||||
for (auto& i : references)
|
||||
for (auto& i : references) {
|
||||
/* Don't traverse into paths that don't exist. That can
|
||||
happen due to substitutes for non-existent paths. */
|
||||
if (i != path && paths.find(i) != paths.end()) {
|
||||
dfsVisit(i, &path);
|
||||
}
|
||||
}
|
||||
|
||||
sorted.push_front(path);
|
||||
parents.erase(path);
|
||||
|
|
25
third_party/nix/src/libstore/nar-accessor.cc
vendored
25
third_party/nix/src/libstore/nar-accessor.cc
vendored
|
@ -45,14 +45,17 @@ struct NarAccessor : public FSAccessor {
|
|||
|
||||
void createMember(const Path& path, NarMember member) {
|
||||
size_t level = std::count(path.begin(), path.end(), '/');
|
||||
while (parents.size() > level) parents.pop();
|
||||
while (parents.size() > level) {
|
||||
parents.pop();
|
||||
}
|
||||
|
||||
if (parents.empty()) {
|
||||
acc.root = std::move(member);
|
||||
parents.push(&acc.root);
|
||||
} else {
|
||||
if (parents.top()->type != FSAccessor::Type::tDirectory)
|
||||
if (parents.top()->type != FSAccessor::Type::tDirectory) {
|
||||
throw Error("NAR file missing parent directory of path '%s'", path);
|
||||
}
|
||||
auto result = parents.top()->children.emplace(baseNameOf(path),
|
||||
std::move(member));
|
||||
parents.push(&result.first->second);
|
||||
|
@ -118,8 +121,9 @@ struct NarAccessor : public FSAccessor {
|
|||
} else if (type == "symlink") {
|
||||
member.type = FSAccessor::Type::tSymlink;
|
||||
member.target = v.value("target", "");
|
||||
} else
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
json v = json::parse(listing);
|
||||
|
@ -157,8 +161,9 @@ struct NarAccessor : public FSAccessor {
|
|||
|
||||
NarMember& get(const Path& path) {
|
||||
auto result = find(path);
|
||||
if (result == nullptr)
|
||||
if (result == nullptr) {
|
||||
throw Error("NAR file does not contain path '%1%'", path);
|
||||
}
|
||||
return *result;
|
||||
}
|
||||
|
||||
|
@ -173,9 +178,10 @@ struct NarAccessor : public FSAccessor {
|
|||
StringSet readDirectory(const Path& path) override {
|
||||
auto i = get(path);
|
||||
|
||||
if (i.type != FSAccessor::Type::tDirectory)
|
||||
if (i.type != FSAccessor::Type::tDirectory) {
|
||||
throw Error(format("path '%1%' inside NAR file is not a directory") %
|
||||
path);
|
||||
}
|
||||
|
||||
StringSet res;
|
||||
for (auto& child : i.children) {
|
||||
|
@ -187,9 +193,10 @@ struct NarAccessor : public FSAccessor {
|
|||
|
||||
std::string readFile(const Path& path) override {
|
||||
auto i = get(path);
|
||||
if (i.type != FSAccessor::Type::tRegular)
|
||||
if (i.type != FSAccessor::Type::tRegular) {
|
||||
throw Error(format("path '%1%' inside NAR file is not a regular file") %
|
||||
path);
|
||||
}
|
||||
|
||||
if (getNarBytes) {
|
||||
return getNarBytes(i.start, i.size);
|
||||
|
@ -201,8 +208,9 @@ struct NarAccessor : public FSAccessor {
|
|||
|
||||
std::string readLink(const Path& path) override {
|
||||
auto i = get(path);
|
||||
if (i.type != FSAccessor::Type::tSymlink)
|
||||
if (i.type != FSAccessor::Type::tSymlink) {
|
||||
throw Error(format("path '%1%' inside NAR file is not a symlink") % path);
|
||||
}
|
||||
return i.target;
|
||||
}
|
||||
};
|
||||
|
@ -241,8 +249,9 @@ void listNar(JSONPlaceholder& res, ref<FSAccessor> accessor, const Path& path,
|
|||
if (recurse) {
|
||||
auto res3 = res2.placeholder(name);
|
||||
listNar(res3, accessor, path + "/" + name, true);
|
||||
} else
|
||||
} else {
|
||||
res2.object(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -76,8 +76,9 @@ class NarInfoDiskCacheImpl : public NarInfoDiskCache {
|
|||
|
||||
state->db = SQLite(dbPath);
|
||||
|
||||
if (sqlite3_busy_timeout(state->db, 60 * 60 * 1000) != SQLITE_OK)
|
||||
if (sqlite3_busy_timeout(state->db, 60 * 60 * 1000) != SQLITE_OK) {
|
||||
throwSQLiteError(state->db, "setting timeout");
|
||||
}
|
||||
|
||||
// We can always reproduce the cache.
|
||||
state->db.exec("pragma synchronous = off");
|
||||
|
@ -224,12 +225,15 @@ class NarInfoDiskCacheImpl : public NarInfoDiskCache {
|
|||
narInfo->fileSize = queryNAR.getInt(5);
|
||||
narInfo->narHash = Hash(queryNAR.getStr(6));
|
||||
narInfo->narSize = queryNAR.getInt(7);
|
||||
for (auto& r : tokenizeString<Strings>(queryNAR.getStr(8), " "))
|
||||
for (auto& r : tokenizeString<Strings>(queryNAR.getStr(8), " ")) {
|
||||
narInfo->references.insert(cache.storeDir + "/" + r);
|
||||
if (!queryNAR.isNull(9))
|
||||
}
|
||||
if (!queryNAR.isNull(9)) {
|
||||
narInfo->deriver = cache.storeDir + "/" + queryNAR.getStr(9);
|
||||
for (auto& sig : tokenizeString<Strings>(queryNAR.getStr(10), " "))
|
||||
}
|
||||
for (auto& sig : tokenizeString<Strings>(queryNAR.getStr(10), " ")) {
|
||||
narInfo->sigs.insert(sig);
|
||||
}
|
||||
narInfo->ca = queryNAR.getStr(11);
|
||||
|
||||
return {oValid, narInfo};
|
||||
|
|
18
third_party/nix/src/libstore/nar-info.cc
vendored
18
third_party/nix/src/libstore/nar-info.cc
vendored
|
@ -40,19 +40,19 @@ NarInfo::NarInfo(const Store& store, const std::string& s,
|
|||
corrupt();
|
||||
}
|
||||
path = value;
|
||||
} else if (name == "URL")
|
||||
} else if (name == "URL") {
|
||||
url = value;
|
||||
else if (name == "Compression")
|
||||
} else if (name == "Compression") {
|
||||
compression = value;
|
||||
else if (name == "FileHash")
|
||||
} else if (name == "FileHash") {
|
||||
fileHash = parseHashField(value);
|
||||
else if (name == "FileSize") {
|
||||
} else if (name == "FileSize") {
|
||||
if (!string2Int(value, fileSize)) {
|
||||
corrupt();
|
||||
}
|
||||
} else if (name == "NarHash")
|
||||
} else if (name == "NarHash") {
|
||||
narHash = parseHashField(value);
|
||||
else if (name == "NarSize") {
|
||||
} else if (name == "NarSize") {
|
||||
if (!string2Int(value, narSize)) {
|
||||
corrupt();
|
||||
}
|
||||
|
@ -76,11 +76,11 @@ NarInfo::NarInfo(const Store& store, const std::string& s,
|
|||
}
|
||||
deriver = p;
|
||||
}
|
||||
} else if (name == "System")
|
||||
} else if (name == "System") {
|
||||
system = value;
|
||||
else if (name == "Sig")
|
||||
} else if (name == "Sig") {
|
||||
sigs.insert(value);
|
||||
else if (name == "CA") {
|
||||
} else if (name == "CA") {
|
||||
if (!ca.empty()) {
|
||||
corrupt();
|
||||
}
|
||||
|
|
12
third_party/nix/src/libstore/optimise-store.cc
vendored
12
third_party/nix/src/libstore/optimise-store.cc
vendored
|
@ -17,10 +17,12 @@ namespace nix {
|
|||
|
||||
static void makeWritable(const Path& path) {
|
||||
struct stat st;
|
||||
if (lstat(path.c_str(), &st))
|
||||
if (lstat(path.c_str(), &st)) {
|
||||
throw SysError(format("getting attributes of path '%1%'") % path);
|
||||
if (chmod(path.c_str(), st.st_mode | S_IWUSR) == -1)
|
||||
}
|
||||
if (chmod(path.c_str(), st.st_mode | S_IWUSR) == -1) {
|
||||
throw SysError(format("changing writability of '%1%'") % path);
|
||||
}
|
||||
}
|
||||
|
||||
struct MakeReadOnly {
|
||||
|
@ -98,8 +100,9 @@ void LocalStore::optimisePath_(OptimiseStats& stats, const Path& path,
|
|||
checkInterrupt();
|
||||
|
||||
struct stat st;
|
||||
if (lstat(path.c_str(), &st))
|
||||
if (lstat(path.c_str(), &st)) {
|
||||
throw SysError(format("getting attributes of path '%1%'") % path);
|
||||
}
|
||||
|
||||
#if __APPLE__
|
||||
/* HFS/macOS has some undocumented security feature disabling hardlinking for
|
||||
|
@ -192,8 +195,9 @@ retry:
|
|||
/* Yes! We've seen a file with the same contents. Replace the
|
||||
current file with a hard link to that file. */
|
||||
struct stat stLink;
|
||||
if (lstat(linkPath.c_str(), &stLink))
|
||||
if (lstat(linkPath.c_str(), &stLink)) {
|
||||
throw SysError(format("getting attributes of path '%1%'") % linkPath);
|
||||
}
|
||||
|
||||
if (st.st_ino == stLink.st_ino) {
|
||||
DLOG(INFO) << path << " is already linked to " << linkPath;
|
||||
|
|
|
@ -20,40 +20,44 @@ std::optional<std::string> ParsedDerivation::getStringAttr(
|
|||
const std::string& name) const {
|
||||
if (structuredAttrs) {
|
||||
auto i = structuredAttrs->find(name);
|
||||
if (i == structuredAttrs->end())
|
||||
if (i == structuredAttrs->end()) {
|
||||
return {};
|
||||
else {
|
||||
if (!i->is_string())
|
||||
} else {
|
||||
if (!i->is_string()) {
|
||||
throw Error("attribute '%s' of derivation '%s' must be a string", name,
|
||||
drvPath);
|
||||
}
|
||||
return i->get<std::string>();
|
||||
}
|
||||
} else {
|
||||
auto i = drv.env.find(name);
|
||||
if (i == drv.env.end())
|
||||
if (i == drv.env.end()) {
|
||||
return {};
|
||||
else
|
||||
} else {
|
||||
return i->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ParsedDerivation::getBoolAttr(const std::string& name, bool def) const {
|
||||
if (structuredAttrs) {
|
||||
auto i = structuredAttrs->find(name);
|
||||
if (i == structuredAttrs->end())
|
||||
if (i == structuredAttrs->end()) {
|
||||
return def;
|
||||
else {
|
||||
if (!i->is_boolean())
|
||||
} else {
|
||||
if (!i->is_boolean()) {
|
||||
throw Error("attribute '%s' of derivation '%s' must be a Boolean", name,
|
||||
drvPath);
|
||||
}
|
||||
return i->get<bool>();
|
||||
}
|
||||
} else {
|
||||
auto i = drv.env.find(name);
|
||||
if (i == drv.env.end())
|
||||
if (i == drv.env.end()) {
|
||||
return def;
|
||||
else
|
||||
} else {
|
||||
return i->second == "1";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,48 +65,54 @@ std::optional<Strings> ParsedDerivation::getStringsAttr(
|
|||
const std::string& name) const {
|
||||
if (structuredAttrs) {
|
||||
auto i = structuredAttrs->find(name);
|
||||
if (i == structuredAttrs->end())
|
||||
if (i == structuredAttrs->end()) {
|
||||
return {};
|
||||
else {
|
||||
if (!i->is_array())
|
||||
} else {
|
||||
if (!i->is_array()) {
|
||||
throw Error(
|
||||
"attribute '%s' of derivation '%s' must be a list of strings", name,
|
||||
drvPath);
|
||||
}
|
||||
Strings res;
|
||||
for (auto j = i->begin(); j != i->end(); ++j) {
|
||||
if (!j->is_string())
|
||||
if (!j->is_string()) {
|
||||
throw Error(
|
||||
"attribute '%s' of derivation '%s' must be a list of strings",
|
||||
name, drvPath);
|
||||
}
|
||||
res.push_back(j->get<std::string>());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
} else {
|
||||
auto i = drv.env.find(name);
|
||||
if (i == drv.env.end())
|
||||
if (i == drv.env.end()) {
|
||||
return {};
|
||||
else
|
||||
} else {
|
||||
return tokenizeString<Strings>(i->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StringSet ParsedDerivation::getRequiredSystemFeatures() const {
|
||||
StringSet res;
|
||||
for (auto& i : getStringsAttr("requiredSystemFeatures").value_or(Strings()))
|
||||
for (auto& i : getStringsAttr("requiredSystemFeatures").value_or(Strings())) {
|
||||
res.insert(i);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool ParsedDerivation::canBuildLocally() const {
|
||||
if (drv.platform != settings.thisSystem.get() &&
|
||||
!settings.extraPlatforms.get().count(drv.platform) && !drv.isBuiltin())
|
||||
!settings.extraPlatforms.get().count(drv.platform) && !drv.isBuiltin()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto& feature : getRequiredSystemFeatures())
|
||||
for (auto& feature : getRequiredSystemFeatures()) {
|
||||
if (!settings.systemFeatures.get().count(feature)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
25
third_party/nix/src/libstore/pathlocks.cc
vendored
25
third_party/nix/src/libstore/pathlocks.cc
vendored
|
@ -18,8 +18,9 @@ AutoCloseFD openLockFile(const Path& path, bool create) {
|
|||
AutoCloseFD fd;
|
||||
|
||||
fd = open(path.c_str(), O_CLOEXEC | O_RDWR | (create ? O_CREAT : 0), 0600);
|
||||
if (!fd && (create || errno != ENOENT))
|
||||
if (!fd && (create || errno != ENOENT)) {
|
||||
throw SysError(format("opening lock file '%1%'") % path);
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
@ -37,22 +38,24 @@ void deleteLockFile(const Path& path, int fd) {
|
|||
|
||||
bool lockFile(int fd, LockType lockType, bool wait) {
|
||||
int type;
|
||||
if (lockType == ltRead)
|
||||
if (lockType == ltRead) {
|
||||
type = LOCK_SH;
|
||||
else if (lockType == ltWrite)
|
||||
} else if (lockType == ltWrite) {
|
||||
type = LOCK_EX;
|
||||
else if (lockType == ltNone)
|
||||
} else if (lockType == ltNone) {
|
||||
type = LOCK_UN;
|
||||
else
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
|
||||
if (wait) {
|
||||
while (flock(fd, type) != 0) {
|
||||
checkInterrupt();
|
||||
if (errno != EINTR)
|
||||
if (errno != EINTR) {
|
||||
throw SysError(format("acquiring/releasing lock"));
|
||||
else
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while (flock(fd, type | LOCK_NB) != 0) {
|
||||
|
@ -118,16 +121,18 @@ bool PathLocks::lockPaths(const PathSet& paths, const string& waitMsg,
|
|||
/* Check that the lock file hasn't become stale (i.e.,
|
||||
hasn't been unlinked). */
|
||||
struct stat st;
|
||||
if (fstat(fd.get(), &st) == -1)
|
||||
if (fstat(fd.get(), &st) == -1) {
|
||||
throw SysError(format("statting lock file '%1%'") % lockPath);
|
||||
if (st.st_size != 0)
|
||||
}
|
||||
if (st.st_size != 0) {
|
||||
/* This lock file has been unlinked, so we're holding
|
||||
a lock on a deleted file. This means that other
|
||||
processes may create and acquire a lock on
|
||||
`lockPath', and proceed. So we must retry. */
|
||||
DLOG(INFO) << "open lock file '" << lockPath << "' has become stale";
|
||||
else
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Use borrow so that the descriptor isn't closed. */
|
||||
|
|
23
third_party/nix/src/libstore/profiles.cc
vendored
23
third_party/nix/src/libstore/profiles.cc
vendored
|
@ -28,10 +28,11 @@ static int parseName(const string& profileName, const string& name) {
|
|||
return -1;
|
||||
}
|
||||
int n;
|
||||
if (string2Int(string(s, 0, p), n) && n >= 0)
|
||||
if (string2Int(string(s, 0, p), n) && n >= 0) {
|
||||
return n;
|
||||
else
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
Generations findGenerations(Path profile, int& curGen) {
|
||||
|
@ -47,8 +48,9 @@ Generations findGenerations(Path profile, int& curGen) {
|
|||
gen.path = profileDir + "/" + i.name;
|
||||
gen.number = n;
|
||||
struct stat st;
|
||||
if (lstat(gen.path.c_str(), &st) != 0)
|
||||
if (lstat(gen.path.c_str(), &st) != 0) {
|
||||
throw SysError(format("statting '%1%'") % gen.path);
|
||||
}
|
||||
gen.creationTime = st.st_mtime;
|
||||
gens.push_back(gen);
|
||||
}
|
||||
|
@ -105,8 +107,9 @@ Path createGeneration(ref<LocalFSStore> store, Path profile, Path outPath) {
|
|||
}
|
||||
|
||||
static void removeFile(const Path& path) {
|
||||
if (remove(path.c_str()) == -1)
|
||||
if (remove(path.c_str()) == -1) {
|
||||
throw SysError(format("cannot unlink '%1%'") % path);
|
||||
}
|
||||
}
|
||||
|
||||
void deleteGeneration(const Path& profile, unsigned int gen) {
|
||||
|
@ -134,9 +137,10 @@ void deleteGenerations(const Path& profile,
|
|||
int curGen;
|
||||
Generations gens = findGenerations(profile, curGen);
|
||||
|
||||
if (gensToDelete.find(curGen) != gensToDelete.end())
|
||||
if (gensToDelete.find(curGen) != gensToDelete.end()) {
|
||||
throw Error(format("cannot delete current generation of profile %1%'") %
|
||||
profile);
|
||||
}
|
||||
|
||||
for (auto& i : gens) {
|
||||
if (gensToDelete.find(i.number) == gensToDelete.end()) {
|
||||
|
@ -176,10 +180,11 @@ void deleteOldGenerations(const Path& profile, bool dryRun) {
|
|||
int curGen;
|
||||
Generations gens = findGenerations(profile, curGen);
|
||||
|
||||
for (auto& i : gens)
|
||||
for (auto& i : gens) {
|
||||
if (i.number != curGen) {
|
||||
deleteGeneration2(profile, i.number, dryRun);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void deleteGenerationsOlderThan(const Path& profile, time_t t, bool dryRun) {
|
||||
|
@ -190,7 +195,7 @@ void deleteGenerationsOlderThan(const Path& profile, time_t t, bool dryRun) {
|
|||
Generations gens = findGenerations(profile, curGen);
|
||||
|
||||
bool canDelete = false;
|
||||
for (auto i = gens.rbegin(); i != gens.rend(); ++i)
|
||||
for (auto i = gens.rbegin(); i != gens.rend(); ++i) {
|
||||
if (canDelete) {
|
||||
assert(i->creationTime < t);
|
||||
if (i->number != curGen) {
|
||||
|
@ -203,6 +208,7 @@ void deleteGenerationsOlderThan(const Path& profile, time_t t, bool dryRun) {
|
|||
time. */
|
||||
canDelete = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void deleteGenerationsOlderThan(const Path& profile, const string& timeSpec,
|
||||
|
@ -211,8 +217,9 @@ void deleteGenerationsOlderThan(const Path& profile, const string& timeSpec,
|
|||
string strDays = string(timeSpec, 0, timeSpec.size() - 1);
|
||||
int days;
|
||||
|
||||
if (!string2Int(strDays, days) || days < 1)
|
||||
if (!string2Int(strDays, days) || days < 1) {
|
||||
throw Error(format("invalid number of days specifier '%1%'") % timeSpec);
|
||||
}
|
||||
|
||||
time_t oldTime = curTime - days * 24 * 3600;
|
||||
|
||||
|
|
6
third_party/nix/src/libstore/references.cc
vendored
6
third_party/nix/src/libstore/references.cc
vendored
|
@ -21,20 +21,22 @@ static void search(const unsigned char* s, size_t len, StringSet& hashes,
|
|||
for (unsigned int i = 0; i < 256; ++i) {
|
||||
isBase32[i] = false;
|
||||
}
|
||||
for (unsigned int i = 0; i < base32Chars.size(); ++i)
|
||||
for (unsigned int i = 0; i < base32Chars.size(); ++i) {
|
||||
isBase32[(unsigned char)base32Chars[i]] = true;
|
||||
}
|
||||
initialised = true;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i + refLength <= len;) {
|
||||
int j;
|
||||
bool match = true;
|
||||
for (j = refLength - 1; j >= 0; --j)
|
||||
for (j = refLength - 1; j >= 0; --j) {
|
||||
if (!isBase32[(unsigned char)s[i + j]]) {
|
||||
i += j + 1;
|
||||
match = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!match) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -48,9 +48,10 @@ std::pair<ref<FSAccessor>, Path> RemoteFSAccessor::fetch(const Path& path_) {
|
|||
auto storePath = store->toStorePath(path);
|
||||
std::string restPath = std::string(path, storePath.size());
|
||||
|
||||
if (!store->isValidPath(storePath))
|
||||
if (!store->isValidPath(storePath)) {
|
||||
throw InvalidPath(format("path '%1%' is not a valid store path") %
|
||||
storePath);
|
||||
}
|
||||
|
||||
auto i = nars.find(storePath);
|
||||
if (i != nars.end()) {
|
||||
|
@ -73,8 +74,9 @@ std::pair<ref<FSAccessor>, Path> RemoteFSAccessor::fetch(const Path& path_) {
|
|||
throw SysError("opening NAR cache file '%s'", cacheFile);
|
||||
}
|
||||
|
||||
if (lseek(fd.get(), offset, SEEK_SET) != (off_t)offset)
|
||||
if (lseek(fd.get(), offset, SEEK_SET) != (off_t)offset) {
|
||||
throw SysError("seeking in '%s'", cacheFile);
|
||||
}
|
||||
|
||||
std::string buf(length, 0);
|
||||
readFull(fd.get(), (unsigned char*)buf.data(), length);
|
||||
|
|
43
third_party/nix/src/libstore/remote-store.cc
vendored
43
third_party/nix/src/libstore/remote-store.cc
vendored
|
@ -57,9 +57,10 @@ RemoteStore::RemoteStore(const Params& params)
|
|||
})) {}
|
||||
|
||||
ref<RemoteStore::Connection> RemoteStore::openConnectionWrapper() {
|
||||
if (failed)
|
||||
if (failed) {
|
||||
throw Error("opening a connection to remote store '%s' previously failed",
|
||||
getUri());
|
||||
}
|
||||
try {
|
||||
return openConnection();
|
||||
} catch (...) {
|
||||
|
@ -105,12 +106,14 @@ ref<RemoteStore::Connection> UDSRemoteStore::openConnection() {
|
|||
|
||||
struct sockaddr_un addr;
|
||||
addr.sun_family = AF_UNIX;
|
||||
if (socketPath.size() + 1 >= sizeof(addr.sun_path))
|
||||
if (socketPath.size() + 1 >= sizeof(addr.sun_path)) {
|
||||
throw Error(format("socket path '%1%' is too long") % socketPath);
|
||||
}
|
||||
strcpy(addr.sun_path, socketPath.c_str());
|
||||
|
||||
if (::connect(conn->fd.get(), (struct sockaddr*)&addr, sizeof(addr)) == -1)
|
||||
if (::connect(conn->fd.get(), (struct sockaddr*)&addr, sizeof(addr)) == -1) {
|
||||
throw SysError(format("cannot connect to daemon at '%1%'") % socketPath);
|
||||
}
|
||||
|
||||
conn->from.fd = conn->fd.get();
|
||||
conn->to.fd = conn->fd.get();
|
||||
|
@ -134,18 +137,21 @@ void RemoteStore::initConnection(Connection& conn) {
|
|||
|
||||
conn.from >> conn.daemonVersion;
|
||||
if (GET_PROTOCOL_MAJOR(conn.daemonVersion) !=
|
||||
GET_PROTOCOL_MAJOR(PROTOCOL_VERSION))
|
||||
GET_PROTOCOL_MAJOR(PROTOCOL_VERSION)) {
|
||||
throw Error("Nix daemon protocol version not supported");
|
||||
if (GET_PROTOCOL_MINOR(conn.daemonVersion) < 10)
|
||||
}
|
||||
if (GET_PROTOCOL_MINOR(conn.daemonVersion) < 10) {
|
||||
throw Error("the Nix daemon version is too old");
|
||||
}
|
||||
conn.to << PROTOCOL_VERSION;
|
||||
|
||||
if (GET_PROTOCOL_MINOR(conn.daemonVersion) >= 14) {
|
||||
int cpu = sameMachine() && settings.lockCPU ? lockToCurrentCPU() : -1;
|
||||
if (cpu != -1)
|
||||
if (cpu != -1) {
|
||||
conn.to << 1 << cpu;
|
||||
else
|
||||
} else {
|
||||
conn.to << 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (GET_PROTOCOL_MINOR(conn.daemonVersion) >= 11) {
|
||||
|
@ -249,10 +255,11 @@ PathSet RemoteStore::queryValidPaths(const PathSet& paths,
|
|||
auto conn(getConnection());
|
||||
if (GET_PROTOCOL_MINOR(conn->daemonVersion) < 12) {
|
||||
PathSet res;
|
||||
for (auto& i : paths)
|
||||
for (auto& i : paths) {
|
||||
if (isValidPath(i)) {
|
||||
res.insert(i);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
} else {
|
||||
conn->to << wopQueryValidPaths << paths;
|
||||
|
@ -344,8 +351,9 @@ void RemoteStore::queryPathInfoUncached(
|
|||
conn.processStderr();
|
||||
} catch (Error& e) {
|
||||
// Ugly backwards compatibility hack.
|
||||
if (e.msg().find("is not valid") != std::string::npos)
|
||||
if (e.msg().find("is not valid") != std::string::npos) {
|
||||
throw InvalidPath(e.what());
|
||||
}
|
||||
throw;
|
||||
}
|
||||
if (GET_PROTOCOL_MINOR(conn->daemonVersion) >= 17) {
|
||||
|
@ -456,9 +464,10 @@ void RemoteStore::addToStore(const ValidPathInfo& info, Source& source,
|
|||
Path RemoteStore::addToStore(const string& name, const Path& _srcPath,
|
||||
bool recursive, HashType hashAlgo,
|
||||
PathFilter& filter, RepairFlag repair) {
|
||||
if (repair)
|
||||
if (repair) {
|
||||
throw Error(
|
||||
"repairing is not supported when building through the Nix daemon");
|
||||
}
|
||||
|
||||
auto conn(getConnection());
|
||||
|
||||
|
@ -483,10 +492,12 @@ Path RemoteStore::addToStore(const string& name, const Path& _srcPath,
|
|||
} catch (SysError& e) {
|
||||
/* Daemon closed while we were sending the path. Probably OOM
|
||||
or I/O error. */
|
||||
if (e.errNo == EPIPE) try {
|
||||
if (e.errNo == EPIPE) {
|
||||
try {
|
||||
conn.processStderr();
|
||||
} catch (EndOfFile& e) {
|
||||
}
|
||||
}
|
||||
throw;
|
||||
}
|
||||
|
||||
|
@ -495,9 +506,10 @@ Path RemoteStore::addToStore(const string& name, const Path& _srcPath,
|
|||
|
||||
Path RemoteStore::addTextToStore(const string& name, const string& s,
|
||||
const PathSet& references, RepairFlag repair) {
|
||||
if (repair)
|
||||
if (repair) {
|
||||
throw Error(
|
||||
"repairing is not supported when building through the Nix daemon");
|
||||
}
|
||||
|
||||
auto conn(getConnection());
|
||||
conn->to << wopAddTextToStore << name << s << references;
|
||||
|
@ -511,15 +523,16 @@ void RemoteStore::buildPaths(const PathSet& drvPaths, BuildMode buildMode) {
|
|||
conn->to << wopBuildPaths;
|
||||
if (GET_PROTOCOL_MINOR(conn->daemonVersion) >= 13) {
|
||||
conn->to << drvPaths;
|
||||
if (GET_PROTOCOL_MINOR(conn->daemonVersion) >= 15)
|
||||
if (GET_PROTOCOL_MINOR(conn->daemonVersion) >= 15) {
|
||||
conn->to << buildMode;
|
||||
else
|
||||
} else
|
||||
/* Old daemons did not take a 'buildMode' parameter, so we
|
||||
need to validate it here on the client side. */
|
||||
if (buildMode != bmNormal)
|
||||
if (buildMode != bmNormal) {
|
||||
throw Error(
|
||||
"repairing or checking is not supported when building through the "
|
||||
"Nix daemon");
|
||||
}
|
||||
} else {
|
||||
/* For backwards compatibility with old daemons, strip output
|
||||
identifiers. */
|
||||
|
|
24
third_party/nix/src/libstore/sqlite.cc
vendored
24
third_party/nix/src/libstore/sqlite.cc
vendored
|
@ -31,8 +31,9 @@ namespace nix {
|
|||
SQLite::SQLite(const Path& path) {
|
||||
if (sqlite3_open_v2(path.c_str(), &db,
|
||||
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
|
||||
0) != SQLITE_OK)
|
||||
0) != SQLITE_OK) {
|
||||
throw Error(format("cannot open SQLite database '%s'") % path);
|
||||
}
|
||||
}
|
||||
|
||||
SQLite::~SQLite() {
|
||||
|
@ -47,24 +48,27 @@ SQLite::~SQLite() {
|
|||
|
||||
void SQLite::exec(const std::string& stmt) {
|
||||
retrySQLite<void>([&]() {
|
||||
if (sqlite3_exec(db, stmt.c_str(), 0, 0, 0) != SQLITE_OK)
|
||||
if (sqlite3_exec(db, stmt.c_str(), 0, 0, 0) != SQLITE_OK) {
|
||||
throwSQLiteError(db, format("executing SQLite statement '%s'") % stmt);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void SQLiteStmt::create(sqlite3* db, const string& sql) {
|
||||
checkInterrupt();
|
||||
assert(!stmt);
|
||||
if (sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, 0) != SQLITE_OK)
|
||||
if (sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, 0) != SQLITE_OK) {
|
||||
throwSQLiteError(db, fmt("creating statement '%s'", sql));
|
||||
}
|
||||
this->db = db;
|
||||
this->sql = sql;
|
||||
}
|
||||
|
||||
SQLiteStmt::~SQLiteStmt() {
|
||||
try {
|
||||
if (stmt && sqlite3_finalize(stmt) != SQLITE_OK)
|
||||
if (stmt && sqlite3_finalize(stmt) != SQLITE_OK) {
|
||||
throwSQLiteError(db, fmt("finalizing statement '%s'", sql));
|
||||
}
|
||||
} catch (...) {
|
||||
ignoreException();
|
||||
}
|
||||
|
@ -83,8 +87,9 @@ SQLiteStmt::Use& SQLiteStmt::Use::operator()(const std::string& value,
|
|||
bool notNull) {
|
||||
if (notNull) {
|
||||
if (sqlite3_bind_text(stmt, curArg++, value.c_str(), -1,
|
||||
SQLITE_TRANSIENT) != SQLITE_OK)
|
||||
SQLITE_TRANSIENT) != SQLITE_OK) {
|
||||
throwSQLiteError(stmt.db, "binding argument");
|
||||
}
|
||||
} else {
|
||||
bind();
|
||||
}
|
||||
|
@ -93,8 +98,9 @@ SQLiteStmt::Use& SQLiteStmt::Use::operator()(const std::string& value,
|
|||
|
||||
SQLiteStmt::Use& SQLiteStmt::Use::operator()(int64_t value, bool notNull) {
|
||||
if (notNull) {
|
||||
if (sqlite3_bind_int64(stmt, curArg++, value) != SQLITE_OK)
|
||||
if (sqlite3_bind_int64(stmt, curArg++, value) != SQLITE_OK) {
|
||||
throwSQLiteError(stmt.db, "binding argument");
|
||||
}
|
||||
} else {
|
||||
bind();
|
||||
}
|
||||
|
@ -113,14 +119,16 @@ int SQLiteStmt::Use::step() { return sqlite3_step(stmt); }
|
|||
void SQLiteStmt::Use::exec() {
|
||||
int r = step();
|
||||
assert(r != SQLITE_ROW);
|
||||
if (r != SQLITE_DONE)
|
||||
if (r != SQLITE_DONE) {
|
||||
throwSQLiteError(stmt.db, fmt("executing SQLite statement '%s'", stmt.sql));
|
||||
}
|
||||
}
|
||||
|
||||
bool SQLiteStmt::Use::next() {
|
||||
int r = step();
|
||||
if (r != SQLITE_DONE && r != SQLITE_ROW)
|
||||
if (r != SQLITE_DONE && r != SQLITE_ROW) {
|
||||
throwSQLiteError(stmt.db, fmt("executing SQLite query '%s'", stmt.sql));
|
||||
}
|
||||
return r == SQLITE_ROW;
|
||||
}
|
||||
|
||||
|
|
21
third_party/nix/src/libstore/ssh.cc
vendored
21
third_party/nix/src/libstore/ssh.cc
vendored
|
@ -10,13 +10,15 @@ SSHMaster::SSHMaster(const std::string& host, const std::string& keyFile,
|
|||
useMaster(useMaster && !fakeSSH),
|
||||
compress(compress),
|
||||
logFD(logFD) {
|
||||
if (host == "" || hasPrefix(host, "-"))
|
||||
if (host == "" || hasPrefix(host, "-")) {
|
||||
throw Error("invalid SSH host name '%s'", host);
|
||||
}
|
||||
}
|
||||
|
||||
void SSHMaster::addCommonSSHOpts(Strings& args) {
|
||||
for (auto& i : tokenizeString<Strings>(getEnv("NIX_SSHOPTS")))
|
||||
for (auto& i : tokenizeString<Strings>(getEnv("NIX_SSHOPTS"))) {
|
||||
args.push_back(i);
|
||||
}
|
||||
if (!keyFile.empty()) {
|
||||
args.insert(args.end(), {"-i", keyFile});
|
||||
}
|
||||
|
@ -44,12 +46,15 @@ std::unique_ptr<SSHMaster::Connection> SSHMaster::startCommand(
|
|||
close(in.writeSide.get());
|
||||
close(out.readSide.get());
|
||||
|
||||
if (dup2(in.readSide.get(), STDIN_FILENO) == -1)
|
||||
if (dup2(in.readSide.get(), STDIN_FILENO) == -1) {
|
||||
throw SysError("duping over stdin");
|
||||
if (dup2(out.writeSide.get(), STDOUT_FILENO) == -1)
|
||||
}
|
||||
if (dup2(out.writeSide.get(), STDOUT_FILENO) == -1) {
|
||||
throw SysError("duping over stdout");
|
||||
if (logFD != -1 && dup2(logFD, STDERR_FILENO) == -1)
|
||||
}
|
||||
if (logFD != -1 && dup2(logFD, STDERR_FILENO) == -1) {
|
||||
throw SysError("duping over stderr");
|
||||
}
|
||||
|
||||
Strings args;
|
||||
|
||||
|
@ -112,8 +117,9 @@ Path SSHMaster::startMaster() {
|
|||
|
||||
close(out.readSide.get());
|
||||
|
||||
if (dup2(out.writeSide.get(), STDOUT_FILENO) == -1)
|
||||
if (dup2(out.writeSide.get(), STDOUT_FILENO) == -1) {
|
||||
throw SysError("duping over stdout");
|
||||
}
|
||||
|
||||
Strings args = {"ssh", host.c_str(),
|
||||
"-M", "-N",
|
||||
|
@ -136,8 +142,9 @@ Path SSHMaster::startMaster() {
|
|||
} catch (EndOfFile& e) {
|
||||
}
|
||||
|
||||
if (reply != "started")
|
||||
if (reply != "started") {
|
||||
throw Error("failed to start SSH master connection to '%s'", host);
|
||||
}
|
||||
|
||||
return state->socketPath;
|
||||
}
|
||||
|
|
76
third_party/nix/src/libstore/store-api.cc
vendored
76
third_party/nix/src/libstore/store-api.cc
vendored
|
@ -25,18 +25,21 @@ bool Store::isStorePath(const Path& path) const {
|
|||
}
|
||||
|
||||
void Store::assertStorePath(const Path& path) const {
|
||||
if (!isStorePath(path))
|
||||
if (!isStorePath(path)) {
|
||||
throw Error(format("path '%1%' is not in the Nix store") % path);
|
||||
}
|
||||
}
|
||||
|
||||
Path Store::toStorePath(const Path& path) const {
|
||||
if (!isInStore(path))
|
||||
if (!isInStore(path)) {
|
||||
throw Error(format("path '%1%' is not in the Nix store") % path);
|
||||
}
|
||||
Path::size_type slash = path.find('/', storeDir.size() + 1);
|
||||
if (slash == Path::npos)
|
||||
if (slash == Path::npos) {
|
||||
return path;
|
||||
else
|
||||
} else {
|
||||
return Path(path, 0, slash);
|
||||
}
|
||||
}
|
||||
|
||||
Path Store::followLinksToStore(const Path& _path) const {
|
||||
|
@ -48,8 +51,9 @@ Path Store::followLinksToStore(const Path& _path) const {
|
|||
string target = readLink(path);
|
||||
path = absPath(target, dirOf(path));
|
||||
}
|
||||
if (!isInStore(path))
|
||||
if (!isInStore(path)) {
|
||||
throw Error(format("path '%1%' is not in the Nix store") % path);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
|
@ -86,17 +90,20 @@ void checkStoreName(const string& name) {
|
|||
|
||||
/* Disallow names starting with a dot for possible security
|
||||
reasons (e.g., "." and ".."). */
|
||||
if (string(name, 0, 1) == ".")
|
||||
if (string(name, 0, 1) == ".") {
|
||||
throw Error(baseError % "it is illegal to start the name with a period");
|
||||
}
|
||||
/* Disallow names longer than 211 characters. ext4’s max is 256,
|
||||
but we need extra space for the hash and .chroot extensions. */
|
||||
if (name.length() > 211)
|
||||
if (name.length() > 211) {
|
||||
throw Error(baseError % "name must be less than 212 characters");
|
||||
for (auto& i : name)
|
||||
}
|
||||
for (auto& i : name) {
|
||||
if (!((i >= 'A' && i <= 'Z') || (i >= 'a' && i <= 'z') ||
|
||||
(i >= '0' && i <= '9') || validChars.find(i) != string::npos)) {
|
||||
throw Error(baseError % (format("the '%1%' character is invalid") % i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Store paths have the following form:
|
||||
|
@ -261,9 +268,10 @@ bool Store::isValidPath(const Path& storePath) {
|
|||
|
||||
bool valid = isValidPathUncached(storePath);
|
||||
|
||||
if (diskCache && !valid)
|
||||
if (diskCache && !valid) {
|
||||
// FIXME: handle valid = true case.
|
||||
diskCache->upsertNarInfo(getUri(), hashPart, 0);
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
@ -306,8 +314,9 @@ void Store::queryPathInfo(const Path& storePath,
|
|||
auto res = state.lock()->pathInfoCache.get(hashPart);
|
||||
if (res) {
|
||||
stats.narInfoReadAverted++;
|
||||
if (!*res)
|
||||
if (!*res) {
|
||||
throw InvalidPath(format("path '%s' is not valid") % storePath);
|
||||
}
|
||||
return callback(ref<ValidPathInfo>(*res));
|
||||
}
|
||||
}
|
||||
|
@ -323,8 +332,9 @@ void Store::queryPathInfo(const Path& storePath,
|
|||
res.first == NarInfoDiskCache::oInvalid ? 0 : res.second);
|
||||
if (res.first == NarInfoDiskCache::oInvalid ||
|
||||
(res.second->path != storePath &&
|
||||
storePathToName(storePath) != ""))
|
||||
storePathToName(storePath) != "")) {
|
||||
throw InvalidPath(format("path '%s' is not valid") % storePath);
|
||||
}
|
||||
}
|
||||
return callback(ref<ValidPathInfo>(res.second));
|
||||
}
|
||||
|
@ -483,8 +493,9 @@ void Store::pathInfoToJSON(JSONPlaceholder& jsonOut, const PathSet& storePaths,
|
|||
jsonPath.attr("deriver", info->deriver);
|
||||
}
|
||||
|
||||
if (info->registrationTime)
|
||||
if (info->registrationTime) {
|
||||
jsonPath.attr("registrationTime", info->registrationTime);
|
||||
}
|
||||
|
||||
if (info->ultimate) {
|
||||
jsonPath.attr("ultimate", info->ultimate);
|
||||
|
@ -504,12 +515,15 @@ void Store::pathInfoToJSON(JSONPlaceholder& jsonOut, const PathSet& storePaths,
|
|||
if (!narInfo->url.empty()) {
|
||||
jsonPath.attr("url", narInfo->url);
|
||||
}
|
||||
if (narInfo->fileHash)
|
||||
if (narInfo->fileHash) {
|
||||
jsonPath.attr("downloadHash", narInfo->fileHash.to_string());
|
||||
if (narInfo->fileSize)
|
||||
}
|
||||
if (narInfo->fileSize) {
|
||||
jsonPath.attr("downloadSize", narInfo->fileSize);
|
||||
if (showClosureSize)
|
||||
}
|
||||
if (showClosureSize) {
|
||||
jsonPath.attr("closureDownloadSize", closureSizes.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -544,10 +558,11 @@ const Store::Stats& Store::getStats() {
|
|||
}
|
||||
|
||||
void Store::buildPaths(const PathSet& paths, BuildMode buildMode) {
|
||||
for (auto& path : paths)
|
||||
for (auto& path : paths) {
|
||||
if (isDerivation(path)) {
|
||||
unsupported("buildPaths");
|
||||
}
|
||||
}
|
||||
|
||||
if (queryValidPaths(paths).size() != paths.size()) {
|
||||
unsupported("buildPaths");
|
||||
|
@ -621,10 +636,11 @@ void copyPaths(ref<Store> srcStore, ref<Store> dstStore,
|
|||
PathSet valid = dstStore->queryValidPaths(storePaths, substitute);
|
||||
|
||||
PathSet missing;
|
||||
for (auto& path : storePaths)
|
||||
for (auto& path : storePaths) {
|
||||
if (!valid.count(path)) {
|
||||
missing.insert(path);
|
||||
}
|
||||
}
|
||||
|
||||
if (missing.empty()) {
|
||||
return;
|
||||
|
@ -729,10 +745,11 @@ string showPaths(const PathSet& paths) {
|
|||
}
|
||||
|
||||
std::string ValidPathInfo::fingerprint() const {
|
||||
if (narSize == 0 || !narHash)
|
||||
if (narSize == 0 || !narHash) {
|
||||
throw Error(format("cannot calculate fingerprint of path '%s' because its "
|
||||
"size/hash is not known") %
|
||||
path);
|
||||
}
|
||||
return "1;" + path + ";" + narHash.to_string(Base32) + ";" +
|
||||
std::to_string(narSize) + ";" + concatStringsSep(",", references);
|
||||
}
|
||||
|
@ -749,10 +766,11 @@ bool ValidPathInfo::isContentAddressed(const Store& store) const {
|
|||
|
||||
if (hasPrefix(ca, "text:")) {
|
||||
Hash hash(std::string(ca, 5));
|
||||
if (store.makeTextPath(storePathToName(path), hash, references) == path)
|
||||
if (store.makeTextPath(storePathToName(path), hash, references) == path) {
|
||||
return true;
|
||||
else
|
||||
} else {
|
||||
warn();
|
||||
}
|
||||
}
|
||||
|
||||
else if (hasPrefix(ca, "fixed:")) {
|
||||
|
@ -760,10 +778,11 @@ bool ValidPathInfo::isContentAddressed(const Store& store) const {
|
|||
Hash hash(std::string(ca, recursive ? 8 : 6));
|
||||
if (references.empty() &&
|
||||
store.makeFixedOutputPath(recursive, hash, storePathToName(path)) ==
|
||||
path)
|
||||
path) {
|
||||
return true;
|
||||
else
|
||||
} else {
|
||||
warn();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -776,10 +795,11 @@ size_t ValidPathInfo::checkSignatures(const Store& store,
|
|||
}
|
||||
|
||||
size_t good = 0;
|
||||
for (auto& sig : sigs)
|
||||
for (auto& sig : sigs) {
|
||||
if (checkSignature(publicKeys, sig)) {
|
||||
good++;
|
||||
}
|
||||
}
|
||||
return good;
|
||||
}
|
||||
|
||||
|
@ -838,16 +858,18 @@ std::pair<std::string, Store::Params> splitUriAndParams(
|
|||
std::string decoded;
|
||||
for (size_t i = 0; i < value.size();) {
|
||||
if (value[i] == '%') {
|
||||
if (i + 2 >= value.size())
|
||||
if (i + 2 >= value.size()) {
|
||||
throw Error("invalid URI parameter '%s'", value);
|
||||
}
|
||||
try {
|
||||
decoded += std::stoul(std::string(value, i + 1, 2), 0, 16);
|
||||
i += 3;
|
||||
} catch (...) {
|
||||
throw Error("invalid URI parameter '%s'", value);
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
decoded += value[i++];
|
||||
}
|
||||
}
|
||||
params[s.substr(0, e)] = decoded;
|
||||
}
|
||||
|
@ -880,9 +902,9 @@ StoreType getStoreType(const std::string& uri, const std::string& stateDir) {
|
|||
} else if (uri == "local" || hasPrefix(uri, "/")) {
|
||||
return tLocal;
|
||||
} else if (uri == "" || uri == "auto") {
|
||||
if (access(stateDir.c_str(), R_OK | W_OK) == 0)
|
||||
if (access(stateDir.c_str(), R_OK | W_OK) == 0) {
|
||||
return tLocal;
|
||||
else if (pathExists(settings.nixDaemonSocketFile)) {
|
||||
} else if (pathExists(settings.nixDaemonSocketFile)) {
|
||||
return tDaemon;
|
||||
} else {
|
||||
return tLocal;
|
||||
|
|
47
third_party/nix/src/libutil/archive.cc
vendored
47
third_party/nix/src/libutil/archive.cc
vendored
|
@ -76,9 +76,10 @@ static void dump(const Path& path, Sink& sink, PathFilter& filter) {
|
|||
if (S_ISREG(st.st_mode)) {
|
||||
sink << "type"
|
||||
<< "regular";
|
||||
if (st.st_mode & S_IXUSR)
|
||||
if (st.st_mode & S_IXUSR) {
|
||||
sink << "executable"
|
||||
<< "";
|
||||
}
|
||||
dumpContents(path, (size_t)st.st_size, sink);
|
||||
}
|
||||
|
||||
|
@ -89,7 +90,7 @@ static void dump(const Path& path, Sink& sink, PathFilter& filter) {
|
|||
/* If we're on a case-insensitive system like macOS, undo
|
||||
the case hack applied by restorePath(). */
|
||||
std::map<string, string> unhacked;
|
||||
for (auto& i : readDirectory(path))
|
||||
for (auto& i : readDirectory(path)) {
|
||||
if (archiveSettings.useCaseHack) {
|
||||
string name(i.name);
|
||||
size_t pos = i.name.find(caseHackSuffix);
|
||||
|
@ -99,14 +100,17 @@ static void dump(const Path& path, Sink& sink, PathFilter& filter) {
|
|||
|
||||
name.erase(pos);
|
||||
}
|
||||
if (unhacked.find(name) != unhacked.end())
|
||||
if (unhacked.find(name) != unhacked.end()) {
|
||||
throw Error(format("file name collision in between '%1%' and '%2%'") %
|
||||
(path + "/" + unhacked[name]) % (path + "/" + i.name));
|
||||
}
|
||||
unhacked[name] = i.name;
|
||||
} else
|
||||
} else {
|
||||
unhacked[i.name] = i.name;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& i : unhacked)
|
||||
for (auto& i : unhacked) {
|
||||
if (filter(path + "/" + i.first)) {
|
||||
sink << "entry"
|
||||
<< "("
|
||||
|
@ -114,15 +118,17 @@ static void dump(const Path& path, Sink& sink, PathFilter& filter) {
|
|||
dump(path + "/" + i.second, sink, filter);
|
||||
sink << ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (S_ISLNK(st.st_mode))
|
||||
else if (S_ISLNK(st.st_mode)) {
|
||||
sink << "type"
|
||||
<< "symlink"
|
||||
<< "target" << readLink(path);
|
||||
|
||||
else
|
||||
} else {
|
||||
throw Error(format("file '%1%' has an unsupported type") % path);
|
||||
}
|
||||
|
||||
sink << ")";
|
||||
}
|
||||
|
@ -222,8 +228,9 @@ static void parse(ParseSink& sink, Source& source, const Path& path) {
|
|||
type = tpSymlink;
|
||||
}
|
||||
|
||||
else
|
||||
else {
|
||||
throw badArchive("unknown file type " + t);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -258,8 +265,9 @@ static void parse(ParseSink& sink, Source& source, const Path& path) {
|
|||
name = readString(source);
|
||||
if (name.empty() || name == "." || name == ".." ||
|
||||
name.find('/') != string::npos ||
|
||||
name.find((char)0) != string::npos)
|
||||
name.find((char)0) != string::npos) {
|
||||
throw Error(format("NAR contains invalid file name '%1%'") % name);
|
||||
}
|
||||
if (name <= prevName) {
|
||||
throw Error("NAR directory is not sorted");
|
||||
}
|
||||
|
@ -271,16 +279,18 @@ static void parse(ParseSink& sink, Source& source, const Path& path) {
|
|||
<< name << "'";
|
||||
name += caseHackSuffix;
|
||||
name += std::to_string(++i->second);
|
||||
} else
|
||||
} else {
|
||||
names[name] = 0;
|
||||
}
|
||||
}
|
||||
} else if (s == "node") {
|
||||
if (s.empty()) {
|
||||
throw badArchive("entry name missing");
|
||||
}
|
||||
parse(sink, source, path + "/" + name);
|
||||
} else
|
||||
} else {
|
||||
throw badArchive("unknown field " + s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -289,8 +299,9 @@ static void parse(ParseSink& sink, Source& source, const Path& path) {
|
|||
sink.createSymlink(path, target);
|
||||
}
|
||||
|
||||
else
|
||||
else {
|
||||
throw badArchive("unknown field " + s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -302,8 +313,9 @@ void parseDump(ParseSink& sink, Source& source) {
|
|||
/* This generally means the integer at the start couldn't be
|
||||
decoded. Ignore and throw the exception below. */
|
||||
}
|
||||
if (version != narVersionMagic1)
|
||||
if (version != narVersionMagic1) {
|
||||
throw badArchive("input doesn't look like a Nix archive");
|
||||
}
|
||||
parse(sink, source, "");
|
||||
}
|
||||
|
||||
|
@ -313,8 +325,9 @@ struct RestoreSink : ParseSink {
|
|||
|
||||
void createDirectory(const Path& path) {
|
||||
Path p = dstPath + path;
|
||||
if (mkdir(p.c_str(), 0777) == -1)
|
||||
if (mkdir(p.c_str(), 0777) == -1) {
|
||||
throw SysError(format("creating directory '%1%'") % p);
|
||||
}
|
||||
};
|
||||
|
||||
void createRegularFile(const Path& path) {
|
||||
|
@ -330,8 +343,9 @@ struct RestoreSink : ParseSink {
|
|||
if (fstat(fd.get(), &st) == -1) {
|
||||
throw SysError("fstat");
|
||||
}
|
||||
if (fchmod(fd.get(), st.st_mode | (S_IXUSR | S_IXGRP | S_IXOTH)) == -1)
|
||||
if (fchmod(fd.get(), st.st_mode | (S_IXUSR | S_IXGRP | S_IXOTH)) == -1) {
|
||||
throw SysError("fchmod");
|
||||
}
|
||||
}
|
||||
|
||||
void preallocateContents(unsigned long long len) {
|
||||
|
@ -342,8 +356,9 @@ struct RestoreSink : ParseSink {
|
|||
filesystem doesn't support preallocation (e.g. on
|
||||
OpenSolaris). Since preallocation is just an
|
||||
optimisation, ignore it. */
|
||||
if (errno && errno != EINVAL && errno != EOPNOTSUPP && errno != ENOSYS)
|
||||
if (errno && errno != EINVAL && errno != EOPNOTSUPP && errno != ENOSYS) {
|
||||
throw SysError(format("preallocating file of %1% bytes") % len);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
20
third_party/nix/src/libutil/args.cc
vendored
20
third_party/nix/src/libutil/args.cc
vendored
|
@ -30,13 +30,14 @@ void Args::parseCmdline(const Strings& _cmdline) {
|
|||
*pos = (string) "-" + arg[1];
|
||||
auto next = pos;
|
||||
++next;
|
||||
for (unsigned int j = 2; j < arg.length(); j++)
|
||||
if (isalpha(arg[j]))
|
||||
for (unsigned int j = 2; j < arg.length(); j++) {
|
||||
if (isalpha(arg[j])) {
|
||||
cmdline.insert(next, (string) "-" + arg[j]);
|
||||
else {
|
||||
} else {
|
||||
cmdline.insert(next, string(arg, j));
|
||||
break;
|
||||
}
|
||||
}
|
||||
arg = *pos;
|
||||
}
|
||||
|
||||
|
@ -44,8 +45,9 @@ void Args::parseCmdline(const Strings& _cmdline) {
|
|||
dashDash = true;
|
||||
++pos;
|
||||
} else if (!dashDash && std::string(arg, 0, 1) == "-") {
|
||||
if (!processFlag(pos, cmdline.end()))
|
||||
if (!processFlag(pos, cmdline.end())) {
|
||||
throw UsageError(format("unrecognised flag '%1%'") % arg);
|
||||
}
|
||||
} else {
|
||||
pendingArgs.push_back(*pos++);
|
||||
if (processArgs(pendingArgs, false)) {
|
||||
|
@ -141,8 +143,9 @@ bool Args::processFlag(Strings::iterator& pos, Strings::iterator end) {
|
|||
|
||||
bool Args::processArgs(const Strings& args, bool finish) {
|
||||
if (expectedArgs.empty()) {
|
||||
if (!args.empty())
|
||||
if (!args.empty()) {
|
||||
throw UsageError(format("unexpected argument '%1%'") % args.front());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -161,8 +164,9 @@ bool Args::processArgs(const Strings& args, bool finish) {
|
|||
res = true;
|
||||
}
|
||||
|
||||
if (finish && !expectedArgs.empty() && !expectedArgs.front().optional)
|
||||
if (finish && !expectedArgs.empty() && !expectedArgs.front().optional) {
|
||||
throw UsageError("more arguments are required");
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -184,7 +188,9 @@ Strings argvToStrings(int argc, char** argv) {
|
|||
Strings args;
|
||||
argc--;
|
||||
argv++;
|
||||
while (argc--) args.push_back(*argv++);
|
||||
while (argc--) {
|
||||
args.push_back(*argv++);
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
|
|
49
third_party/nix/src/libutil/compression.cc
vendored
49
third_party/nix/src/libutil/compression.cc
vendored
|
@ -49,8 +49,9 @@ struct XzDecompressionSink : CompressionSink {
|
|||
|
||||
XzDecompressionSink(Sink& nextSink) : nextSink(nextSink) {
|
||||
lzma_ret ret = lzma_stream_decoder(&strm, UINT64_MAX, LZMA_CONCATENATED);
|
||||
if (ret != LZMA_OK)
|
||||
if (ret != LZMA_OK) {
|
||||
throw CompressionError("unable to initialise lzma decoder");
|
||||
}
|
||||
|
||||
strm.next_out = outbuf;
|
||||
strm.avail_out = sizeof(outbuf);
|
||||
|
@ -71,8 +72,9 @@ struct XzDecompressionSink : CompressionSink {
|
|||
checkInterrupt();
|
||||
|
||||
lzma_ret ret = lzma_code(&strm, data ? LZMA_RUN : LZMA_FINISH);
|
||||
if (ret != LZMA_OK && ret != LZMA_STREAM_END)
|
||||
if (ret != LZMA_OK && ret != LZMA_STREAM_END) {
|
||||
throw CompressionError("error %d while decompressing xz file", ret);
|
||||
}
|
||||
|
||||
finished = ret == LZMA_STREAM_END;
|
||||
|
||||
|
@ -93,8 +95,9 @@ struct BzipDecompressionSink : ChunkedCompressionSink {
|
|||
BzipDecompressionSink(Sink& nextSink) : nextSink(nextSink) {
|
||||
memset(&strm, 0, sizeof(strm));
|
||||
int ret = BZ2_bzDecompressInit(&strm, 0, 0);
|
||||
if (ret != BZ_OK)
|
||||
if (ret != BZ_OK) {
|
||||
throw CompressionError("unable to initialise bzip2 decoder");
|
||||
}
|
||||
|
||||
strm.next_out = (char*)outbuf;
|
||||
strm.avail_out = sizeof(outbuf);
|
||||
|
@ -117,8 +120,9 @@ struct BzipDecompressionSink : ChunkedCompressionSink {
|
|||
checkInterrupt();
|
||||
|
||||
int ret = BZ2_bzDecompress(&strm);
|
||||
if (ret != BZ_OK && ret != BZ_STREAM_END)
|
||||
if (ret != BZ_OK && ret != BZ_STREAM_END) {
|
||||
throw CompressionError("error while decompressing bzip2 file");
|
||||
}
|
||||
|
||||
finished = ret == BZ_STREAM_END;
|
||||
|
||||
|
@ -160,8 +164,9 @@ struct BrotliDecompressionSink : ChunkedCompressionSink {
|
|||
checkInterrupt();
|
||||
|
||||
if (!BrotliDecoderDecompressStream(state, &avail_in, &next_in, &avail_out,
|
||||
&next_out, nullptr))
|
||||
&next_out, nullptr)) {
|
||||
throw CompressionError("error while decompressing brotli file");
|
||||
}
|
||||
|
||||
if (avail_out < sizeof(outbuf) || avail_in == 0) {
|
||||
nextSink(outbuf, sizeof(outbuf) - avail_out);
|
||||
|
@ -184,16 +189,17 @@ ref<std::string> decompress(const std::string& method, const std::string& in) {
|
|||
|
||||
ref<CompressionSink> makeDecompressionSink(const std::string& method,
|
||||
Sink& nextSink) {
|
||||
if (method == "none" || method == "")
|
||||
if (method == "none" || method == "") {
|
||||
return make_ref<NoneSink>(nextSink);
|
||||
else if (method == "xz")
|
||||
} else if (method == "xz") {
|
||||
return make_ref<XzDecompressionSink>(nextSink);
|
||||
else if (method == "bzip2")
|
||||
} else if (method == "bzip2") {
|
||||
return make_ref<BzipDecompressionSink>(nextSink);
|
||||
else if (method == "br")
|
||||
} else if (method == "br") {
|
||||
return make_ref<BrotliDecompressionSink>(nextSink);
|
||||
else
|
||||
} else {
|
||||
throw UnknownCompressionMethod("unknown compression method '%s'", method);
|
||||
}
|
||||
}
|
||||
|
||||
struct XzCompressionSink : CompressionSink {
|
||||
|
@ -258,8 +264,9 @@ struct XzCompressionSink : CompressionSink {
|
|||
checkInterrupt();
|
||||
|
||||
lzma_ret ret = lzma_code(&strm, data ? LZMA_RUN : LZMA_FINISH);
|
||||
if (ret != LZMA_OK && ret != LZMA_STREAM_END)
|
||||
if (ret != LZMA_OK && ret != LZMA_STREAM_END) {
|
||||
throw CompressionError("error %d while compressing xz file", ret);
|
||||
}
|
||||
|
||||
finished = ret == LZMA_STREAM_END;
|
||||
|
||||
|
@ -280,8 +287,9 @@ struct BzipCompressionSink : ChunkedCompressionSink {
|
|||
BzipCompressionSink(Sink& nextSink) : nextSink(nextSink) {
|
||||
memset(&strm, 0, sizeof(strm));
|
||||
int ret = BZ2_bzCompressInit(&strm, 9, 0, 30);
|
||||
if (ret != BZ_OK)
|
||||
if (ret != BZ_OK) {
|
||||
throw CompressionError("unable to initialise bzip2 encoder");
|
||||
}
|
||||
|
||||
strm.next_out = (char*)outbuf;
|
||||
strm.avail_out = sizeof(outbuf);
|
||||
|
@ -304,8 +312,9 @@ struct BzipCompressionSink : ChunkedCompressionSink {
|
|||
checkInterrupt();
|
||||
|
||||
int ret = BZ2_bzCompress(&strm, data ? BZ_RUN : BZ_FINISH);
|
||||
if (ret != BZ_RUN_OK && ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
|
||||
if (ret != BZ_RUN_OK && ret != BZ_FINISH_OK && ret != BZ_STREAM_END) {
|
||||
throw CompressionError("error %d while compressing bzip2 file", ret);
|
||||
}
|
||||
|
||||
finished = ret == BZ_STREAM_END;
|
||||
|
||||
|
@ -349,8 +358,9 @@ struct BrotliCompressionSink : ChunkedCompressionSink {
|
|||
|
||||
if (!BrotliEncoderCompressStream(
|
||||
state, data ? BROTLI_OPERATION_PROCESS : BROTLI_OPERATION_FINISH,
|
||||
&avail_in, &next_in, &avail_out, &next_out, nullptr))
|
||||
&avail_in, &next_in, &avail_out, &next_out, nullptr)) {
|
||||
throw CompressionError("error while compressing brotli compression");
|
||||
}
|
||||
|
||||
if (avail_out < sizeof(outbuf) || avail_in == 0) {
|
||||
nextSink(outbuf, sizeof(outbuf) - avail_out);
|
||||
|
@ -365,17 +375,18 @@ struct BrotliCompressionSink : ChunkedCompressionSink {
|
|||
|
||||
ref<CompressionSink> makeCompressionSink(const std::string& method,
|
||||
Sink& nextSink, const bool parallel) {
|
||||
if (method == "none")
|
||||
if (method == "none") {
|
||||
return make_ref<NoneSink>(nextSink);
|
||||
else if (method == "xz")
|
||||
} else if (method == "xz") {
|
||||
return make_ref<XzCompressionSink>(nextSink, parallel);
|
||||
else if (method == "bzip2")
|
||||
} else if (method == "bzip2") {
|
||||
return make_ref<BzipCompressionSink>(nextSink);
|
||||
else if (method == "br")
|
||||
} else if (method == "br") {
|
||||
return make_ref<BrotliCompressionSink>(nextSink);
|
||||
else
|
||||
} else {
|
||||
throw UnknownCompressionMethod(format("unknown compression method '%s'") %
|
||||
method);
|
||||
}
|
||||
}
|
||||
|
||||
ref<std::string> compress(const std::string& method, const std::string& in,
|
||||
|
|
58
third_party/nix/src/libutil/config.cc
vendored
58
third_party/nix/src/libutil/config.cc
vendored
|
@ -21,8 +21,9 @@ bool Config::set(const std::string& name, const std::string& value) {
|
|||
|
||||
void Config::addSetting(AbstractSetting* setting) {
|
||||
_settings.emplace(setting->name, Config::SettingData(false, setting));
|
||||
for (auto& alias : setting->aliases)
|
||||
for (auto& alias : setting->aliases) {
|
||||
_settings.emplace(alias, Config::SettingData(true, setting));
|
||||
}
|
||||
|
||||
bool set = false;
|
||||
|
||||
|
@ -68,11 +69,13 @@ void AbstractConfig::reapplyUnknownSettings() {
|
|||
|
||||
void Config::getSettings(std::map<std::string, SettingInfo>& res,
|
||||
bool overridenOnly) {
|
||||
for (auto& opt : _settings)
|
||||
for (auto& opt : _settings) {
|
||||
if (!opt.second.isAlias &&
|
||||
(!overridenOnly || opt.second.setting->overriden))
|
||||
(!overridenOnly || opt.second.setting->overriden)) {
|
||||
res.emplace(opt.first, SettingInfo{opt.second.setting->to_string(),
|
||||
opt.second.setting->description});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractConfig::applyConfigFile(const Path& path) {
|
||||
|
@ -83,8 +86,9 @@ void AbstractConfig::applyConfigFile(const Path& path) {
|
|||
|
||||
while (pos < contents.size()) {
|
||||
string line;
|
||||
while (pos < contents.size() && contents[pos] != '\n')
|
||||
while (pos < contents.size() && contents[pos] != '\n') {
|
||||
line += contents[pos++];
|
||||
}
|
||||
pos++;
|
||||
|
||||
string::size_type hash = line.find('#');
|
||||
|
@ -97,23 +101,25 @@ void AbstractConfig::applyConfigFile(const Path& path) {
|
|||
continue;
|
||||
}
|
||||
|
||||
if (tokens.size() < 2)
|
||||
if (tokens.size() < 2) {
|
||||
throw UsageError("illegal configuration line '%1%' in '%2%'", line,
|
||||
path);
|
||||
}
|
||||
|
||||
auto include = false;
|
||||
auto ignoreMissing = false;
|
||||
if (tokens[0] == "include")
|
||||
if (tokens[0] == "include") {
|
||||
include = true;
|
||||
else if (tokens[0] == "!include") {
|
||||
} else if (tokens[0] == "!include") {
|
||||
include = true;
|
||||
ignoreMissing = true;
|
||||
}
|
||||
|
||||
if (include) {
|
||||
if (tokens.size() != 2)
|
||||
if (tokens.size() != 2) {
|
||||
throw UsageError("illegal configuration line '%1%' in '%2%'", line,
|
||||
path);
|
||||
}
|
||||
auto p = absPath(tokens[1], dirOf(path));
|
||||
if (pathExists(p)) {
|
||||
applyConfigFile(p);
|
||||
|
@ -123,9 +129,10 @@ void AbstractConfig::applyConfigFile(const Path& path) {
|
|||
continue;
|
||||
}
|
||||
|
||||
if (tokens[1] != "=")
|
||||
if (tokens[1] != "=") {
|
||||
throw UsageError("illegal configuration line '%1%' in '%2%'", line,
|
||||
path);
|
||||
}
|
||||
|
||||
string name = tokens[0];
|
||||
|
||||
|
@ -146,20 +153,22 @@ void Config::resetOverriden() {
|
|||
}
|
||||
|
||||
void Config::toJSON(JSONObject& out) {
|
||||
for (auto& s : _settings)
|
||||
for (auto& s : _settings) {
|
||||
if (!s.second.isAlias) {
|
||||
JSONObject out2(out.object(s.first));
|
||||
out2.attr("description", s.second.setting->description);
|
||||
JSONPlaceholder out3(out2.placeholder("value"));
|
||||
s.second.setting->toJSON(out3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Config::convertToArgs(Args& args, const std::string& category) {
|
||||
for (auto& s : _settings)
|
||||
for (auto& s : _settings) {
|
||||
if (!s.second.isAlias) {
|
||||
s.second.setting->convertToArg(args, category);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AbstractSetting::AbstractSetting(const std::string& name,
|
||||
|
@ -202,8 +211,9 @@ std::string BaseSetting<std::string>::to_string() {
|
|||
template <typename T>
|
||||
void BaseSetting<T>::set(const std::string& str) {
|
||||
static_assert(std::is_integral<T>::value, "Integer required.");
|
||||
if (!string2Int(str, value))
|
||||
if (!string2Int(str, value)) {
|
||||
throw UsageError("setting '%s' has invalid value '%s'", name, str);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -214,12 +224,13 @@ std::string BaseSetting<T>::to_string() {
|
|||
|
||||
template <>
|
||||
void BaseSetting<bool>::set(const std::string& str) {
|
||||
if (str == "true" || str == "yes" || str == "1")
|
||||
if (str == "true" || str == "yes" || str == "1") {
|
||||
value = true;
|
||||
else if (str == "false" || str == "no" || str == "0")
|
||||
} else if (str == "false" || str == "no" || str == "0") {
|
||||
value = false;
|
||||
else
|
||||
} else {
|
||||
throw UsageError("Boolean setting '%s' has invalid value '%s'", name, str);
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
|
@ -290,19 +301,22 @@ template class BaseSetting<StringSet>;
|
|||
|
||||
void PathSetting::set(const std::string& str) {
|
||||
if (str == "") {
|
||||
if (allowEmpty)
|
||||
if (allowEmpty) {
|
||||
value = "";
|
||||
else
|
||||
} else {
|
||||
throw UsageError("setting '%s' cannot be empty", name);
|
||||
} else
|
||||
}
|
||||
} else {
|
||||
value = canonPath(str);
|
||||
}
|
||||
}
|
||||
|
||||
bool GlobalConfig::set(const std::string& name, const std::string& value) {
|
||||
for (auto& config : *configRegistrations)
|
||||
for (auto& config : *configRegistrations) {
|
||||
if (config->set(name, value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
unknownSettings.emplace(name, value);
|
||||
|
||||
|
@ -311,8 +325,9 @@ bool GlobalConfig::set(const std::string& name, const std::string& value) {
|
|||
|
||||
void GlobalConfig::getSettings(std::map<std::string, SettingInfo>& res,
|
||||
bool overridenOnly) {
|
||||
for (auto& config : *configRegistrations)
|
||||
for (auto& config : *configRegistrations) {
|
||||
config->getSettings(res, overridenOnly);
|
||||
}
|
||||
}
|
||||
|
||||
void GlobalConfig::resetOverriden() {
|
||||
|
@ -328,8 +343,9 @@ void GlobalConfig::toJSON(JSONObject& out) {
|
|||
}
|
||||
|
||||
void GlobalConfig::convertToArgs(Args& args, const std::string& category) {
|
||||
for (auto& config : *configRegistrations)
|
||||
for (auto& config : *configRegistrations) {
|
||||
config->convertToArgs(args, category);
|
||||
}
|
||||
}
|
||||
|
||||
GlobalConfig globalConfig;
|
||||
|
|
64
third_party/nix/src/libutil/hash.cc
vendored
64
third_party/nix/src/libutil/hash.cc
vendored
|
@ -132,8 +132,9 @@ Hash::Hash(const std::string& s, HashType type) : type(type) {
|
|||
sep = s.find('-');
|
||||
if (sep != string::npos) {
|
||||
isSRI = true;
|
||||
} else if (type == htUnknown)
|
||||
} else if (type == htUnknown) {
|
||||
throw BadHash("hash '%s' does not include a type", s);
|
||||
}
|
||||
}
|
||||
|
||||
if (sep != string::npos) {
|
||||
|
@ -142,8 +143,9 @@ Hash::Hash(const std::string& s, HashType type) : type(type) {
|
|||
if (this->type == htUnknown) {
|
||||
throw BadHash("unknown hash type '%s'", hts);
|
||||
}
|
||||
if (type != htUnknown && type != this->type)
|
||||
if (type != htUnknown && type != this->type) {
|
||||
throw BadHash("hash '%s' should have type '%s'", s, printHashType(type));
|
||||
}
|
||||
pos = sep + 1;
|
||||
}
|
||||
|
||||
|
@ -175,10 +177,11 @@ Hash::Hash(const std::string& s, HashType type) : type(type) {
|
|||
for (unsigned int n = 0; n < size; ++n) {
|
||||
char c = s[pos + size - n - 1];
|
||||
unsigned char digit;
|
||||
for (digit = 0; digit < base32Chars.size(); ++digit) /* !!! slow */
|
||||
for (digit = 0; digit < base32Chars.size(); ++digit) { /* !!! slow */
|
||||
if (base32Chars[digit] == c) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (digit >= 32) {
|
||||
throw BadHash("invalid base-32 hash '%s'", s);
|
||||
}
|
||||
|
@ -199,15 +202,17 @@ Hash::Hash(const std::string& s, HashType type) : type(type) {
|
|||
|
||||
else if (isSRI || size == base64Len()) {
|
||||
auto d = base64Decode(std::string(s, pos));
|
||||
if (d.size() != hashSize)
|
||||
if (d.size() != hashSize) {
|
||||
throw BadHash("invalid %s hash '%s'", isSRI ? "SRI" : "base-64", s);
|
||||
}
|
||||
assert(hashSize);
|
||||
memcpy(hash, d.data(), hashSize);
|
||||
}
|
||||
|
||||
else
|
||||
else {
|
||||
throw BadHash("hash '%s' has wrong length for hash type '%s'", s,
|
||||
printHashType(type));
|
||||
}
|
||||
}
|
||||
|
||||
union Ctx {
|
||||
|
@ -218,37 +223,40 @@ union Ctx {
|
|||
};
|
||||
|
||||
static void start(HashType ht, Ctx& ctx) {
|
||||
if (ht == htMD5)
|
||||
if (ht == htMD5) {
|
||||
MD5_Init(&ctx.md5);
|
||||
else if (ht == htSHA1)
|
||||
} else if (ht == htSHA1) {
|
||||
SHA1_Init(&ctx.sha1);
|
||||
else if (ht == htSHA256)
|
||||
} else if (ht == htSHA256) {
|
||||
SHA256_Init(&ctx.sha256);
|
||||
else if (ht == htSHA512)
|
||||
} else if (ht == htSHA512) {
|
||||
SHA512_Init(&ctx.sha512);
|
||||
}
|
||||
}
|
||||
|
||||
static void update(HashType ht, Ctx& ctx, const unsigned char* bytes,
|
||||
size_t len) {
|
||||
if (ht == htMD5)
|
||||
if (ht == htMD5) {
|
||||
MD5_Update(&ctx.md5, bytes, len);
|
||||
else if (ht == htSHA1)
|
||||
} else if (ht == htSHA1) {
|
||||
SHA1_Update(&ctx.sha1, bytes, len);
|
||||
else if (ht == htSHA256)
|
||||
} else if (ht == htSHA256) {
|
||||
SHA256_Update(&ctx.sha256, bytes, len);
|
||||
else if (ht == htSHA512)
|
||||
} else if (ht == htSHA512) {
|
||||
SHA512_Update(&ctx.sha512, bytes, len);
|
||||
}
|
||||
}
|
||||
|
||||
static void finish(HashType ht, Ctx& ctx, unsigned char* hash) {
|
||||
if (ht == htMD5)
|
||||
if (ht == htMD5) {
|
||||
MD5_Final(hash, &ctx.md5);
|
||||
else if (ht == htSHA1)
|
||||
} else if (ht == htSHA1) {
|
||||
SHA1_Final(hash, &ctx.sha1);
|
||||
else if (ht == htSHA256)
|
||||
} else if (ht == htSHA256) {
|
||||
SHA256_Final(hash, &ctx.sha256);
|
||||
else if (ht == htSHA512)
|
||||
} else if (ht == htSHA512) {
|
||||
SHA512_Final(hash, &ctx.sha512);
|
||||
}
|
||||
}
|
||||
|
||||
Hash hashString(HashType ht, const string& s) {
|
||||
|
@ -331,29 +339,31 @@ Hash compressHash(const Hash& hash, unsigned int newSize) {
|
|||
}
|
||||
|
||||
HashType parseHashType(const string& s) {
|
||||
if (s == "md5")
|
||||
if (s == "md5") {
|
||||
return htMD5;
|
||||
else if (s == "sha1")
|
||||
} else if (s == "sha1") {
|
||||
return htSHA1;
|
||||
else if (s == "sha256")
|
||||
} else if (s == "sha256") {
|
||||
return htSHA256;
|
||||
else if (s == "sha512")
|
||||
} else if (s == "sha512") {
|
||||
return htSHA512;
|
||||
else
|
||||
} else {
|
||||
return htUnknown;
|
||||
}
|
||||
}
|
||||
|
||||
string printHashType(HashType ht) {
|
||||
if (ht == htMD5)
|
||||
if (ht == htMD5) {
|
||||
return "md5";
|
||||
else if (ht == htSHA1)
|
||||
} else if (ht == htSHA1) {
|
||||
return "sha1";
|
||||
else if (ht == htSHA256)
|
||||
} else if (ht == htSHA256) {
|
||||
return "sha256";
|
||||
else if (ht == htSHA512)
|
||||
} else if (ht == htSHA512) {
|
||||
return "sha512";
|
||||
else
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace nix
|
||||
|
|
21
third_party/nix/src/libutil/json.cc
vendored
21
third_party/nix/src/libutil/json.cc
vendored
|
@ -7,28 +7,31 @@ namespace nix {
|
|||
|
||||
void toJSON(std::ostream& str, const char* start, const char* end) {
|
||||
str << '"';
|
||||
for (auto i = start; i != end; i++)
|
||||
if (*i == '\"' || *i == '\\')
|
||||
for (auto i = start; i != end; i++) {
|
||||
if (*i == '\"' || *i == '\\') {
|
||||
str << '\\' << *i;
|
||||
else if (*i == '\n')
|
||||
} else if (*i == '\n') {
|
||||
str << "\\n";
|
||||
else if (*i == '\r')
|
||||
} else if (*i == '\r') {
|
||||
str << "\\r";
|
||||
else if (*i == '\t')
|
||||
} else if (*i == '\t') {
|
||||
str << "\\t";
|
||||
else if (*i >= 0 && *i < 32)
|
||||
} else if (*i >= 0 && *i < 32) {
|
||||
str << "\\u" << std::setfill('0') << std::setw(4) << std::hex
|
||||
<< (uint16_t)*i << std::dec;
|
||||
else
|
||||
} else {
|
||||
str << *i;
|
||||
}
|
||||
}
|
||||
str << '"';
|
||||
}
|
||||
|
||||
void toJSON(std::ostream& str, const char* s) {
|
||||
if (!s)
|
||||
if (!s) {
|
||||
str << "null";
|
||||
else
|
||||
} else {
|
||||
toJSON(str, s, s + strlen(s));
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
|
|
14
third_party/nix/src/libutil/serialise.cc
vendored
14
third_party/nix/src/libutil/serialise.cc
vendored
|
@ -173,7 +173,7 @@ std::unique_ptr<Source> sinkToSource(std::function<void(Sink&)> fun,
|
|||
size_t pos = 0;
|
||||
|
||||
size_t read(unsigned char* data, size_t len) override {
|
||||
if (!coro)
|
||||
if (!coro) {
|
||||
coro = coro_t::pull_type([&](coro_t::push_type& yield) {
|
||||
LambdaSink sink([&](const unsigned char* data, size_t len) {
|
||||
if (len) {
|
||||
|
@ -182,6 +182,7 @@ std::unique_ptr<Source> sinkToSource(std::function<void(Sink&)> fun,
|
|||
});
|
||||
fun(sink);
|
||||
});
|
||||
}
|
||||
|
||||
if (!*coro) {
|
||||
eof();
|
||||
|
@ -189,7 +190,9 @@ std::unique_ptr<Source> sinkToSource(std::function<void(Sink&)> fun,
|
|||
}
|
||||
|
||||
if (pos == cur.size()) {
|
||||
if (!cur.empty()) (*coro)();
|
||||
if (!cur.empty()) {
|
||||
(*coro)();
|
||||
}
|
||||
cur = coro->get();
|
||||
pos = 0;
|
||||
}
|
||||
|
@ -247,10 +250,11 @@ void readPadding(size_t len, Source& source) {
|
|||
unsigned char zero[8];
|
||||
size_t n = 8 - (len % 8);
|
||||
source(zero, n);
|
||||
for (unsigned int i = 0; i < n; i++)
|
||||
for (unsigned int i = 0; i < n; i++) {
|
||||
if (zero[i]) {
|
||||
throw SerialisationError("non-zero padding");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -284,7 +288,9 @@ template <class T>
|
|||
T readStrings(Source& source) {
|
||||
auto count = readNum<size_t>(source);
|
||||
T ss;
|
||||
while (count--) ss.insert(ss.end(), readString(source));
|
||||
while (count--) {
|
||||
ss.insert(ss.end(), readString(source));
|
||||
}
|
||||
return ss;
|
||||
}
|
||||
|
||||
|
|
6
third_party/nix/src/libutil/thread-pool.cc
vendored
6
third_party/nix/src/libutil/thread-pool.cc
vendored
|
@ -50,8 +50,9 @@ void ThreadPool::enqueue(const work_t& t) {
|
|||
state->pending.push(t);
|
||||
/* Note: process() also executes items, so count it as a worker. */
|
||||
if (state->pending.size() > state->workers.size() + 1 &&
|
||||
state->workers.size() + 1 < maxThreads)
|
||||
state->workers.size() + 1 < maxThreads) {
|
||||
state->workers.emplace_back(&ThreadPool::doWork, this, false);
|
||||
}
|
||||
work.notify_one();
|
||||
}
|
||||
|
||||
|
@ -111,8 +112,9 @@ void ThreadPool::doWork(bool mainThread) {
|
|||
std::rethrow_exception(exc);
|
||||
} catch (std::exception& e) {
|
||||
if (!dynamic_cast<Interrupted*>(&e) &&
|
||||
!dynamic_cast<ThreadPoolShutDown*>(&e))
|
||||
!dynamic_cast<ThreadPoolShutDown*>(&e)) {
|
||||
ignoreException();
|
||||
}
|
||||
} catch (...) {
|
||||
}
|
||||
}
|
||||
|
|
205
third_party/nix/src/libutil/util.cc
vendored
205
third_party/nix/src/libutil/util.cc
vendored
|
@ -60,9 +60,10 @@ std::map<std::string, std::string> getEnv() {
|
|||
for (size_t i = 0; environ[i]; ++i) {
|
||||
auto s = environ[i];
|
||||
auto eq = strchr(s, '=');
|
||||
if (!eq)
|
||||
if (!eq) {
|
||||
// invalid env, just keep going
|
||||
continue;
|
||||
}
|
||||
env.emplace(std::string(s, eq), std::string(eq + 1));
|
||||
}
|
||||
return env;
|
||||
|
@ -91,18 +92,19 @@ Path absPath(Path path, Path dir) {
|
|||
if (buf == NULL)
|
||||
#else
|
||||
char buf[PATH_MAX];
|
||||
if (!getcwd(buf, sizeof(buf)))
|
||||
if (!getcwd(buf, sizeof(buf))) {
|
||||
#endif
|
||||
throw SysError("cannot get cwd");
|
||||
dir = buf;
|
||||
#ifdef __GNU__
|
||||
free(buf);
|
||||
#endif
|
||||
}
|
||||
path = dir + "/" + path;
|
||||
dir = buf;
|
||||
#ifdef __GNU__
|
||||
free(buf);
|
||||
#endif
|
||||
}
|
||||
return canonPath(path);
|
||||
path = dir + "/" + path;
|
||||
}
|
||||
return canonPath(path);
|
||||
} // namespace nix
|
||||
|
||||
Path canonPath(const Path& path, bool resolveSymlinks) {
|
||||
assert(path != "");
|
||||
|
@ -122,7 +124,9 @@ Path canonPath(const Path& path, bool resolveSymlinks) {
|
|||
|
||||
while (1) {
|
||||
/* Skip slashes. */
|
||||
while (i != end && *i == '/') i++;
|
||||
while (i != end && *i == '/') {
|
||||
i++;
|
||||
}
|
||||
if (i == end) {
|
||||
break;
|
||||
}
|
||||
|
@ -144,14 +148,17 @@ Path canonPath(const Path& path, bool resolveSymlinks) {
|
|||
/* Normal component; copy it. */
|
||||
else {
|
||||
s += '/';
|
||||
while (i != end && *i != '/') s += *i++;
|
||||
while (i != end && *i != '/') {
|
||||
s += *i++;
|
||||
}
|
||||
|
||||
/* If s points to a symlink, resolve it and restart (since
|
||||
the symlink target might contain new symlinks). */
|
||||
if (resolveSymlinks && isLink(s)) {
|
||||
if (++followCount >= maxFollow)
|
||||
if (++followCount >= maxFollow) {
|
||||
throw Error(format("infinite symlink recursion in path '%1%'") %
|
||||
path);
|
||||
}
|
||||
temp = absPath(readLink(s), dirOf(s)) + string(i, end);
|
||||
i = temp.begin(); /* restart */
|
||||
end = temp.end();
|
||||
|
@ -182,10 +189,11 @@ string baseNameOf(const Path& path) {
|
|||
}
|
||||
|
||||
Path::size_type pos = path.rfind('/', last);
|
||||
if (pos == string::npos)
|
||||
if (pos == string::npos) {
|
||||
pos = 0;
|
||||
else
|
||||
} else {
|
||||
pos += 1;
|
||||
}
|
||||
|
||||
return string(path, pos, last - pos + 1);
|
||||
}
|
||||
|
@ -201,8 +209,9 @@ bool isDirOrInDir(const Path& path, const Path& dir) {
|
|||
|
||||
struct stat lstat(const Path& path) {
|
||||
struct stat st;
|
||||
if (lstat(path.c_str(), &st))
|
||||
if (lstat(path.c_str(), &st)) {
|
||||
throw SysError(format("getting status of '%1%'") % path);
|
||||
}
|
||||
return st;
|
||||
}
|
||||
|
||||
|
@ -213,8 +222,9 @@ bool pathExists(const Path& path) {
|
|||
if (!res) {
|
||||
return true;
|
||||
}
|
||||
if (errno != ENOENT && errno != ENOTDIR)
|
||||
if (errno != ENOENT && errno != ENOTDIR) {
|
||||
throw SysError(format("getting status of %1%") % path);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -224,13 +234,15 @@ Path readLink(const Path& path) {
|
|||
for (ssize_t bufSize = PATH_MAX / 4; true; bufSize += bufSize / 2) {
|
||||
buf.resize(bufSize);
|
||||
ssize_t rlSize = readlink(path.c_str(), buf.data(), bufSize);
|
||||
if (rlSize == -1)
|
||||
if (errno == EINVAL)
|
||||
if (rlSize == -1) {
|
||||
if (errno == EINVAL) {
|
||||
throw Error("'%1%' is not a symlink", path);
|
||||
else
|
||||
} else {
|
||||
throw SysError("reading symbolic link '%1%'", path);
|
||||
else if (rlSize < bufSize)
|
||||
}
|
||||
} else if (rlSize < bufSize) {
|
||||
return string(buf.data(), rlSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -351,9 +363,9 @@ string readLine(int fd) {
|
|||
if (errno != EINTR) {
|
||||
throw SysError("reading a line");
|
||||
}
|
||||
} else if (rd == 0)
|
||||
} else if (rd == 0) {
|
||||
throw EndOfFile("unexpected EOF reading a line");
|
||||
else {
|
||||
} else {
|
||||
if (ch == '\n') {
|
||||
return s;
|
||||
}
|
||||
|
@ -386,12 +398,14 @@ static void _deletePath(const Path& path, unsigned long long& bytesFreed) {
|
|||
/* Make the directory accessible. */
|
||||
const auto PERM_MASK = S_IRUSR | S_IWUSR | S_IXUSR;
|
||||
if ((st.st_mode & PERM_MASK) != PERM_MASK) {
|
||||
if (chmod(path.c_str(), st.st_mode | PERM_MASK) == -1)
|
||||
if (chmod(path.c_str(), st.st_mode | PERM_MASK) == -1) {
|
||||
throw SysError(format("chmod '%1%'") % path);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& i : readDirectory(path))
|
||||
for (auto& i : readDirectory(path)) {
|
||||
_deletePath(path + "/" + i.name, bytesFreed);
|
||||
}
|
||||
}
|
||||
|
||||
if (remove(path.c_str()) == -1) {
|
||||
|
@ -418,11 +432,12 @@ static Path tempName(Path tmpRoot, const Path& prefix, bool includePid,
|
|||
int& counter) {
|
||||
tmpRoot =
|
||||
canonPath(tmpRoot.empty() ? getEnv("TMPDIR", "/tmp") : tmpRoot, true);
|
||||
if (includePid)
|
||||
if (includePid) {
|
||||
return (format("%1%/%2%-%3%-%4%") % tmpRoot % prefix % getpid() % counter++)
|
||||
.str();
|
||||
else
|
||||
} else {
|
||||
return (format("%1%/%2%-%3%") % tmpRoot % prefix % counter++).str();
|
||||
}
|
||||
}
|
||||
|
||||
Path createTempDir(const Path& tmpRoot, const Path& prefix, bool includePid,
|
||||
|
@ -449,8 +464,9 @@ Path createTempDir(const Path& tmpRoot, const Path& prefix, bool includePid,
|
|||
#endif
|
||||
return tmpDir;
|
||||
}
|
||||
if (errno != EEXIST)
|
||||
if (errno != EEXIST) {
|
||||
throw SysError(format("creating directory '%1%'") % tmpDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -470,8 +486,9 @@ static Lazy<Path> getHome2([]() {
|
|||
struct passwd pwbuf;
|
||||
struct passwd* pw;
|
||||
if (getpwuid_r(geteuid(), &pwbuf, buf.data(), buf.size(), &pw) != 0 ||
|
||||
!pw || !pw->pw_dir || !pw->pw_dir[0])
|
||||
!pw || !pw->pw_dir || !pw->pw_dir[0]) {
|
||||
throw Error("cannot determine user's home directory");
|
||||
}
|
||||
homeDir = pw->pw_dir;
|
||||
}
|
||||
return homeDir;
|
||||
|
@ -521,25 +538,29 @@ Paths createDirs(const Path& path) {
|
|||
struct stat st;
|
||||
if (lstat(path.c_str(), &st) == -1) {
|
||||
created = createDirs(dirOf(path));
|
||||
if (mkdir(path.c_str(), 0777) == -1 && errno != EEXIST)
|
||||
if (mkdir(path.c_str(), 0777) == -1 && errno != EEXIST) {
|
||||
throw SysError(format("creating directory '%1%'") % path);
|
||||
}
|
||||
st = lstat(path);
|
||||
created.push_back(path);
|
||||
}
|
||||
|
||||
if (S_ISLNK(st.st_mode) && stat(path.c_str(), &st) == -1)
|
||||
if (S_ISLNK(st.st_mode) && stat(path.c_str(), &st) == -1) {
|
||||
throw SysError(format("statting symlink '%1%'") % path);
|
||||
}
|
||||
|
||||
if (!S_ISDIR(st.st_mode))
|
||||
if (!S_ISDIR(st.st_mode)) {
|
||||
throw Error(format("'%1%' is not a directory") % path);
|
||||
}
|
||||
|
||||
return created;
|
||||
}
|
||||
|
||||
void createSymlink(const Path& target, const Path& link) {
|
||||
if (symlink(target.c_str(), link.c_str()))
|
||||
if (symlink(target.c_str(), link.c_str())) {
|
||||
throw SysError(format("creating symlink from '%1%' to '%2%'") % link %
|
||||
target);
|
||||
}
|
||||
}
|
||||
|
||||
void replaceSymlink(const Path& target, const Path& link) {
|
||||
|
@ -555,8 +576,9 @@ void replaceSymlink(const Path& target, const Path& link) {
|
|||
throw;
|
||||
}
|
||||
|
||||
if (rename(tmp.c_str(), link.c_str()) != 0)
|
||||
if (rename(tmp.c_str(), link.c_str()) != 0) {
|
||||
throw SysError(format("renaming '%1%' to '%2%'") % tmp % link);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -612,15 +634,17 @@ void drainFD(int fd, Sink& sink, bool block) {
|
|||
|
||||
Finally finally([&]() {
|
||||
if (!block) {
|
||||
if (fcntl(fd, F_SETFL, saved) == -1)
|
||||
if (fcntl(fd, F_SETFL, saved) == -1) {
|
||||
throw SysError("making file descriptor blocking");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!block) {
|
||||
saved = fcntl(fd, F_GETFL);
|
||||
if (fcntl(fd, F_SETFL, saved | O_NONBLOCK) == -1)
|
||||
if (fcntl(fd, F_SETFL, saved | O_NONBLOCK) == -1) {
|
||||
throw SysError("making file descriptor non-blocking");
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<unsigned char> buf(64 * 1024);
|
||||
|
@ -634,10 +658,11 @@ void drainFD(int fd, Sink& sink, bool block) {
|
|||
if (errno != EINTR) {
|
||||
throw SysError("reading from file");
|
||||
}
|
||||
} else if (rd == 0)
|
||||
} else if (rd == 0) {
|
||||
break;
|
||||
else
|
||||
} else {
|
||||
sink(buf.data(), rd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -656,8 +681,9 @@ AutoDelete::~AutoDelete() {
|
|||
if (recursive) {
|
||||
deletePath(path);
|
||||
} else {
|
||||
if (remove(path.c_str()) == -1)
|
||||
if (remove(path.c_str()) == -1) {
|
||||
throw SysError(format("cannot unlink '%1%'") % path);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (...) {
|
||||
|
@ -700,8 +726,9 @@ int AutoCloseFD::get() const { return fd; }
|
|||
|
||||
void AutoCloseFD::close() {
|
||||
if (fd != -1) {
|
||||
if (::close(fd) == -1) /* This should never happen. */
|
||||
if (::close(fd) == -1) { /* This should never happen. */
|
||||
throw SysError(format("closing file descriptor %1%") % fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -835,8 +862,9 @@ void killUser(uid_t uid) {
|
|||
if (errno == ESRCH) {
|
||||
break;
|
||||
} /* no more processes */
|
||||
if (errno != EINTR)
|
||||
if (errno != EINTR) {
|
||||
throw SysError(format("cannot kill processes for uid '%1%'") % uid);
|
||||
}
|
||||
}
|
||||
|
||||
_exit(0);
|
||||
|
@ -844,9 +872,10 @@ void killUser(uid_t uid) {
|
|||
options);
|
||||
|
||||
int status = pid.wait();
|
||||
if (status != 0)
|
||||
if (status != 0) {
|
||||
throw Error(format("cannot kill processes for uid '%1%': %2%") % uid %
|
||||
statusToString(status));
|
||||
}
|
||||
|
||||
/* !!! We should really do some check to make sure that there are
|
||||
no processes left running under `uid', but there is no portable
|
||||
|
@ -877,8 +906,9 @@ pid_t startProcess(std::function<void()> fun, const ProcessOptions& options) {
|
|||
auto wrapper = [&]() {
|
||||
try {
|
||||
#if __linux__
|
||||
if (options.dieWithParent && prctl(PR_SET_PDEATHSIG, SIGKILL) == -1)
|
||||
if (options.dieWithParent && prctl(PR_SET_PDEATHSIG, SIGKILL) == -1) {
|
||||
throw SysError("setting death signal");
|
||||
}
|
||||
#endif
|
||||
restoreAffinity();
|
||||
fun();
|
||||
|
@ -889,10 +919,11 @@ pid_t startProcess(std::function<void()> fun, const ProcessOptions& options) {
|
|||
}
|
||||
} catch (...) {
|
||||
}
|
||||
if (options.runExitHandlers)
|
||||
if (options.runExitHandlers) {
|
||||
exit(1);
|
||||
else
|
||||
} else {
|
||||
_exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
pid_t pid = doFork(options.allowVfork, wrapper);
|
||||
|
@ -920,9 +951,10 @@ string runProgram(Path program, bool searchPath, const Strings& args,
|
|||
|
||||
auto res = runProgram(opts);
|
||||
|
||||
if (!statusOk(res.first))
|
||||
if (!statusOk(res.first)) {
|
||||
throw ExecError(res.first, fmt("program '%1%' %2%", program,
|
||||
statusToString(res.first)));
|
||||
}
|
||||
|
||||
return res.second;
|
||||
}
|
||||
|
@ -980,33 +1012,42 @@ void runProgram2(const RunOptions& options) {
|
|||
replaceEnv(*options.environment);
|
||||
}
|
||||
if (options.standardOut &&
|
||||
dup2(out.writeSide.get(), STDOUT_FILENO) == -1)
|
||||
dup2(out.writeSide.get(), STDOUT_FILENO) == -1) {
|
||||
throw SysError("dupping stdout");
|
||||
if (options.mergeStderrToStdout)
|
||||
if (dup2(STDOUT_FILENO, STDERR_FILENO) == -1)
|
||||
}
|
||||
if (options.mergeStderrToStdout) {
|
||||
if (dup2(STDOUT_FILENO, STDERR_FILENO) == -1) {
|
||||
throw SysError("cannot dup stdout into stderr");
|
||||
if (source && dup2(in.readSide.get(), STDIN_FILENO) == -1)
|
||||
}
|
||||
}
|
||||
if (source && dup2(in.readSide.get(), STDIN_FILENO) == -1) {
|
||||
throw SysError("dupping stdin");
|
||||
}
|
||||
|
||||
if (options.chdir && chdir((*options.chdir).c_str()) == -1)
|
||||
if (options.chdir && chdir((*options.chdir).c_str()) == -1) {
|
||||
throw SysError("chdir failed");
|
||||
if (options.gid && setgid(*options.gid) == -1)
|
||||
}
|
||||
if (options.gid && setgid(*options.gid) == -1) {
|
||||
throw SysError("setgid failed");
|
||||
}
|
||||
/* Drop all other groups if we're setgid. */
|
||||
if (options.gid && setgroups(0, 0) == -1)
|
||||
if (options.gid && setgroups(0, 0) == -1) {
|
||||
throw SysError("setgroups failed");
|
||||
if (options.uid && setuid(*options.uid) == -1)
|
||||
}
|
||||
if (options.uid && setuid(*options.uid) == -1) {
|
||||
throw SysError("setuid failed");
|
||||
}
|
||||
|
||||
Strings args_(options.args);
|
||||
args_.push_front(options.program);
|
||||
|
||||
restoreSignals();
|
||||
|
||||
if (options.searchPath)
|
||||
if (options.searchPath) {
|
||||
execvp(options.program.c_str(), stringsToCharPtrs(args_).data());
|
||||
else
|
||||
} else {
|
||||
execv(options.program.c_str(), stringsToCharPtrs(args_).data());
|
||||
}
|
||||
|
||||
throw SysError("executing '%1%'", options.program);
|
||||
},
|
||||
|
@ -1058,9 +1099,10 @@ void runProgram2(const RunOptions& options) {
|
|||
promise.get_future().get();
|
||||
}
|
||||
|
||||
if (status)
|
||||
if (status) {
|
||||
throw ExecError(status, fmt("program '%1%' %2%", options.program,
|
||||
statusToString(status)));
|
||||
}
|
||||
}
|
||||
|
||||
void closeMostFDs(const set<int>& exceptions) {
|
||||
|
@ -1080,17 +1122,19 @@ void closeMostFDs(const set<int>& exceptions) {
|
|||
|
||||
int maxFD = 0;
|
||||
maxFD = sysconf(_SC_OPEN_MAX);
|
||||
for (int fd = 0; fd < maxFD; ++fd)
|
||||
for (int fd = 0; fd < maxFD; ++fd) {
|
||||
if (!exceptions.count(fd)) {
|
||||
close(fd);
|
||||
} /* ignore result */
|
||||
}
|
||||
}
|
||||
|
||||
void closeOnExec(int fd) {
|
||||
int prev;
|
||||
if ((prev = fcntl(fd, F_GETFD, 0)) == -1 ||
|
||||
fcntl(fd, F_SETFD, prev | FD_CLOEXEC) == -1)
|
||||
fcntl(fd, F_SETFD, prev | FD_CLOEXEC) == -1) {
|
||||
throw SysError("setting close-on-exec flag");
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
@ -1187,9 +1231,9 @@ string replaceStrings(const std::string& s, const std::string& from,
|
|||
|
||||
string statusToString(int status) {
|
||||
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
|
||||
if (WIFEXITED(status))
|
||||
if (WIFEXITED(status)) {
|
||||
return (format("failed with exit code %1%") % WEXITSTATUS(status)).str();
|
||||
else if (WIFSIGNALED(status)) {
|
||||
} else if (WIFSIGNALED(status)) {
|
||||
int sig = WTERMSIG(status);
|
||||
#if HAVE_STRSIGNAL
|
||||
const char* description = strsignal(sig);
|
||||
|
@ -1198,10 +1242,12 @@ string statusToString(int status) {
|
|||
#else
|
||||
return (format("failed due to signal %1%") % sig).str();
|
||||
#endif
|
||||
} else
|
||||
} else {
|
||||
return "died abnormally";
|
||||
} else
|
||||
}
|
||||
} else {
|
||||
return "succeeded";
|
||||
}
|
||||
}
|
||||
|
||||
bool statusOk(int status) {
|
||||
|
@ -1227,11 +1273,13 @@ std::string toLower(const std::string& s) {
|
|||
|
||||
std::string shellEscape(const std::string& s) {
|
||||
std::string r = "'";
|
||||
for (auto& i : s)
|
||||
if (i == '\'')
|
||||
for (auto& i : s) {
|
||||
if (i == '\'') {
|
||||
r += "'\\''";
|
||||
else
|
||||
} else {
|
||||
r += i;
|
||||
}
|
||||
}
|
||||
r += '\'';
|
||||
return r;
|
||||
}
|
||||
|
@ -1259,9 +1307,13 @@ std::string filterANSIEscapes(const std::string& s, bool filterAll,
|
|||
if (i != s.end() && *i == '[') {
|
||||
e += *i++;
|
||||
// eat parameter bytes
|
||||
while (i != s.end() && *i >= 0x30 && *i <= 0x3f) e += *i++;
|
||||
while (i != s.end() && *i >= 0x30 && *i <= 0x3f) {
|
||||
e += *i++;
|
||||
}
|
||||
// eat intermediate bytes
|
||||
while (i != s.end() && *i >= 0x20 && *i <= 0x2f) e += *i++;
|
||||
while (i != s.end() && *i >= 0x20 && *i <= 0x2f) {
|
||||
e += *i++;
|
||||
}
|
||||
// eat final byte
|
||||
if (i != s.end() && *i >= 0x40 && *i <= 0x7e) {
|
||||
e += last = *i++;
|
||||
|
@ -1287,11 +1339,11 @@ std::string filterANSIEscapes(const std::string& s, bool filterAll,
|
|||
}
|
||||
}
|
||||
|
||||
else if (*i == '\r')
|
||||
else if (*i == '\r') {
|
||||
// do nothing for now
|
||||
i++;
|
||||
|
||||
else {
|
||||
} else {
|
||||
t += *i++;
|
||||
w++;
|
||||
}
|
||||
|
@ -1319,7 +1371,9 @@ string base64Encode(const string& s) {
|
|||
if (nbits) {
|
||||
res.push_back(base64Chars[data << (6 - nbits) & 0x3f]);
|
||||
}
|
||||
while (res.size() % 4) res.push_back('=');
|
||||
while (res.size() % 4) {
|
||||
res.push_back('=');
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -1395,10 +1449,10 @@ static void signalHandlerThread(sigset_t set) {
|
|||
int signal = 0;
|
||||
sigwait(&set, &signal);
|
||||
|
||||
if (signal == SIGINT || signal == SIGTERM || signal == SIGHUP)
|
||||
if (signal == SIGINT || signal == SIGTERM || signal == SIGHUP) {
|
||||
triggerInterrupt();
|
||||
|
||||
else if (signal == SIGWINCH) {
|
||||
} else if (signal == SIGWINCH) {
|
||||
updateWindowSize();
|
||||
}
|
||||
}
|
||||
|
@ -1424,8 +1478,9 @@ static sigset_t savedSignalMask;
|
|||
void startSignalHandlerThread() {
|
||||
updateWindowSize();
|
||||
|
||||
if (sigprocmask(SIG_BLOCK, nullptr, &savedSignalMask))
|
||||
if (sigprocmask(SIG_BLOCK, nullptr, &savedSignalMask)) {
|
||||
throw SysError("quering signal mask");
|
||||
}
|
||||
|
||||
sigset_t set;
|
||||
sigemptyset(&set);
|
||||
|
@ -1434,15 +1489,17 @@ void startSignalHandlerThread() {
|
|||
sigaddset(&set, SIGHUP);
|
||||
sigaddset(&set, SIGPIPE);
|
||||
sigaddset(&set, SIGWINCH);
|
||||
if (pthread_sigmask(SIG_BLOCK, &set, nullptr))
|
||||
if (pthread_sigmask(SIG_BLOCK, &set, nullptr)) {
|
||||
throw SysError("blocking signals");
|
||||
}
|
||||
|
||||
std::thread(signalHandlerThread, set).detach();
|
||||
}
|
||||
|
||||
void restoreSignals() {
|
||||
if (sigprocmask(SIG_SETMASK, &savedSignalMask, nullptr))
|
||||
if (sigprocmask(SIG_SETMASK, &savedSignalMask, nullptr)) {
|
||||
throw SysError("restoring signals");
|
||||
}
|
||||
}
|
||||
|
||||
/* RAII helper to automatically deregister a callback. */
|
||||
|
|
21
third_party/nix/src/libutil/xml-writer.cc
vendored
21
third_party/nix/src/libutil/xml-writer.cc
vendored
|
@ -16,7 +16,9 @@ void XMLWriter::close() {
|
|||
if (closed) {
|
||||
return;
|
||||
}
|
||||
while (!pendingElems.empty()) closeElement();
|
||||
while (!pendingElems.empty()) {
|
||||
closeElement();
|
||||
}
|
||||
closed = true;
|
||||
}
|
||||
|
||||
|
@ -68,20 +70,21 @@ void XMLWriter::writeAttrs(const XMLAttrs& attrs) {
|
|||
output << " " << i.first << "=\"";
|
||||
for (size_t j = 0; j < i.second.size(); ++j) {
|
||||
char c = i.second[j];
|
||||
if (c == '"')
|
||||
if (c == '"') {
|
||||
output << """;
|
||||
else if (c == '<')
|
||||
} else if (c == '<') {
|
||||
output << "<";
|
||||
else if (c == '>')
|
||||
} else if (c == '>') {
|
||||
output << ">";
|
||||
else if (c == '&')
|
||||
} else if (c == '&') {
|
||||
output << "&";
|
||||
/* Escape newlines to prevent attribute normalisation (see
|
||||
XML spec, section 3.3.3. */
|
||||
else if (c == '\n')
|
||||
/* Escape newlines to prevent attribute normalisation (see
|
||||
XML spec, section 3.3.3. */
|
||||
} else if (c == '\n') {
|
||||
output << "
";
|
||||
else
|
||||
} else {
|
||||
output << c;
|
||||
}
|
||||
}
|
||||
output << "\"";
|
||||
}
|
||||
|
|
108
third_party/nix/src/nix-build/nix-build.cc
vendored
108
third_party/nix/src/nix-build/nix-build.cc
vendored
|
@ -125,9 +125,11 @@ static void _main(int argc, char** argv) {
|
|||
line = chomp(line);
|
||||
std::smatch match;
|
||||
if (std::regex_match(line, match,
|
||||
std::regex("^#!\\s*nix-shell (.*)$")))
|
||||
for (const auto& word : shellwords(match[1].str()))
|
||||
std::regex("^#!\\s*nix-shell (.*)$"))) {
|
||||
for (const auto& word : shellwords(match[1].str())) {
|
||||
args.push_back(word);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (SysError&) {
|
||||
|
@ -145,63 +147,63 @@ static void _main(int argc, char** argv) {
|
|||
showManPage(myName);
|
||||
}
|
||||
|
||||
else if (*arg == "--version")
|
||||
else if (*arg == "--version") {
|
||||
printVersion(myName);
|
||||
|
||||
else if (*arg == "--add-drv-link" || *arg == "--indirect")
|
||||
} else if (*arg == "--add-drv-link" || *arg == "--indirect") {
|
||||
; // obsolete
|
||||
|
||||
else if (*arg == "--no-out-link" || *arg == "--no-link")
|
||||
} else if (*arg == "--no-out-link" || *arg == "--no-link") {
|
||||
outLink = (Path)tmpDir + "/result";
|
||||
|
||||
else if (*arg == "--attr" || *arg == "-A")
|
||||
} else if (*arg == "--attr" || *arg == "-A") {
|
||||
attrPaths.push_back(getArg(*arg, arg, end));
|
||||
|
||||
else if (*arg == "--drv-link")
|
||||
} else if (*arg == "--drv-link") {
|
||||
getArg(*arg, arg, end); // obsolete
|
||||
|
||||
else if (*arg == "--out-link" || *arg == "-o")
|
||||
} else if (*arg == "--out-link" || *arg == "-o") {
|
||||
outLink = getArg(*arg, arg, end);
|
||||
|
||||
else if (*arg == "--add-root")
|
||||
} else if (*arg == "--add-root") {
|
||||
gcRoot = getArg(*arg, arg, end);
|
||||
|
||||
else if (*arg == "--dry-run")
|
||||
} else if (*arg == "--dry-run") {
|
||||
dryRun = true;
|
||||
|
||||
else if (*arg == "--repair") {
|
||||
} else if (*arg == "--repair") {
|
||||
repair = Repair;
|
||||
buildMode = bmRepair;
|
||||
}
|
||||
|
||||
else if (*arg == "--run-env") // obsolete
|
||||
else if (*arg == "--run-env") { // obsolete
|
||||
runEnv = true;
|
||||
|
||||
else if (*arg == "--command" || *arg == "--run") {
|
||||
} else if (*arg == "--command" || *arg == "--run") {
|
||||
if (*arg == "--run") {
|
||||
interactive = false;
|
||||
}
|
||||
envCommand = getArg(*arg, arg, end) + "\nexit";
|
||||
}
|
||||
|
||||
else if (*arg == "--check")
|
||||
else if (*arg == "--check") {
|
||||
buildMode = bmCheck;
|
||||
|
||||
else if (*arg == "--exclude")
|
||||
} else if (*arg == "--exclude") {
|
||||
envExclude.push_back(getArg(*arg, arg, end));
|
||||
|
||||
else if (*arg == "--expr" || *arg == "-E")
|
||||
} else if (*arg == "--expr" || *arg == "-E") {
|
||||
fromArgs = true;
|
||||
|
||||
else if (*arg == "--pure")
|
||||
} else if (*arg == "--pure") {
|
||||
pure = true;
|
||||
else if (*arg == "--impure")
|
||||
} else if (*arg == "--impure") {
|
||||
pure = false;
|
||||
|
||||
else if (*arg == "--packages" || *arg == "-p")
|
||||
} else if (*arg == "--packages" || *arg == "-p") {
|
||||
packages = true;
|
||||
|
||||
else if (inShebang && *arg == "-i") {
|
||||
} else if (inShebang && *arg == "-i") {
|
||||
auto interpreter = getArg(*arg, arg, end);
|
||||
interactive = false;
|
||||
auto execArgs = "";
|
||||
|
@ -210,8 +212,9 @@ static void _main(int argc, char** argv) {
|
|||
// executes it unless it contains the string "perl" or "indir",
|
||||
// or (undocumented) argv[0] does not contain "perl". Exploit
|
||||
// the latter by doing "exec -a".
|
||||
if (std::regex_search(interpreter, std::regex("perl")))
|
||||
if (std::regex_search(interpreter, std::regex("perl"))) {
|
||||
execArgs = "-a PERL";
|
||||
}
|
||||
|
||||
std::ostringstream joined;
|
||||
for (const auto& i : savedArgs) {
|
||||
|
@ -233,17 +236,18 @@ static void _main(int argc, char** argv) {
|
|||
}
|
||||
}
|
||||
|
||||
else if (*arg == "--keep")
|
||||
else if (*arg == "--keep") {
|
||||
keepVars.insert(getArg(*arg, arg, end));
|
||||
|
||||
else if (*arg == "-")
|
||||
} else if (*arg == "-") {
|
||||
readStdin = true;
|
||||
|
||||
else if (*arg != "" && arg->at(0) == '-')
|
||||
} else if (*arg != "" && arg->at(0) == '-') {
|
||||
return false;
|
||||
|
||||
else
|
||||
} else {
|
||||
left.push_back(*arg);
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
@ -252,8 +256,9 @@ static void _main(int argc, char** argv) {
|
|||
|
||||
initPlugins();
|
||||
|
||||
if (packages && fromArgs)
|
||||
if (packages && fromArgs) {
|
||||
throw UsageError("'-p' and '-E' are mutually exclusive");
|
||||
}
|
||||
|
||||
auto store = openStore();
|
||||
|
||||
|
@ -290,22 +295,22 @@ static void _main(int argc, char** argv) {
|
|||
/* Parse the expressions. */
|
||||
std::vector<Expr*> exprs;
|
||||
|
||||
if (readStdin)
|
||||
if (readStdin) {
|
||||
exprs = {state->parseStdin()};
|
||||
else
|
||||
} else {
|
||||
for (auto i : left) {
|
||||
if (fromArgs)
|
||||
if (fromArgs) {
|
||||
exprs.push_back(state->parseExprFromString(i, absPath(".")));
|
||||
else {
|
||||
} else {
|
||||
auto absolute = i;
|
||||
try {
|
||||
absolute = canonPath(absPath(i), true);
|
||||
} catch (Error& e) {
|
||||
};
|
||||
if (store->isStorePath(absolute) &&
|
||||
std::regex_match(absolute, std::regex(".*\\.drv(!.*)?")))
|
||||
std::regex_match(absolute, std::regex(".*\\.drv(!.*)?"))) {
|
||||
drvs.push_back(DrvInfo(*state, store, absolute));
|
||||
else
|
||||
} else {
|
||||
/* If we're in a #! script, interpret filenames
|
||||
relative to the script. */
|
||||
exprs.push_back(
|
||||
|
@ -313,8 +318,10 @@ static void _main(int argc, char** argv) {
|
|||
lookupFileArg(*state, inShebang && !packages
|
||||
? absPath(i, absPath(dirOf(script)))
|
||||
: i)))));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Evaluate them into derivations. */
|
||||
if (attrPaths.empty()) {
|
||||
|
@ -342,9 +349,10 @@ static void _main(int argc, char** argv) {
|
|||
store->queryMissing(paths, willBuild, willSubstitute, unknown, downloadSize,
|
||||
narSize);
|
||||
|
||||
if (settings.printMissing)
|
||||
if (settings.printMissing) {
|
||||
printMissing(ref<Store>(store), willBuild, willSubstitute, unknown,
|
||||
downloadSize, narSize);
|
||||
}
|
||||
|
||||
if (!dryRun) {
|
||||
store->buildPaths(paths, buildMode);
|
||||
|
@ -352,8 +360,9 @@ static void _main(int argc, char** argv) {
|
|||
};
|
||||
|
||||
if (runEnv) {
|
||||
if (drvs.size() != 1)
|
||||
if (drvs.size() != 1) {
|
||||
throw UsageError("nix-shell requires a single derivation");
|
||||
}
|
||||
|
||||
auto& drvInfo = drvs.front();
|
||||
auto drv = store->derivationFromPath(drvInfo.queryDrvPath());
|
||||
|
@ -374,10 +383,11 @@ static void _main(int argc, char** argv) {
|
|||
state->eval(expr, v);
|
||||
|
||||
auto drv = getDerivation(*state, v, false);
|
||||
if (!drv)
|
||||
if (!drv) {
|
||||
throw Error(
|
||||
"the 'bashInteractive' attribute in <nixpkgs> did not evaluate "
|
||||
"to a derivation");
|
||||
}
|
||||
|
||||
pathsToBuild.insert(drv->queryDrvPath());
|
||||
|
||||
|
@ -390,13 +400,15 @@ static void _main(int argc, char** argv) {
|
|||
}
|
||||
|
||||
// Build or fetch all dependencies of the derivation.
|
||||
for (const auto& input : drv.inputDrvs)
|
||||
for (const auto& input : drv.inputDrvs) {
|
||||
if (std::all_of(envExclude.cbegin(), envExclude.cend(),
|
||||
[&](const string& exclude) {
|
||||
return !std::regex_search(input.first,
|
||||
std::regex(exclude));
|
||||
}))
|
||||
})) {
|
||||
pathsToBuild.insert(makeDrvPathWithOutputs(input.first, input.second));
|
||||
}
|
||||
}
|
||||
for (const auto& src : drv.inputSrcs) {
|
||||
pathsToBuild.insert(src);
|
||||
}
|
||||
|
@ -414,10 +426,11 @@ static void _main(int argc, char** argv) {
|
|||
|
||||
if (pure) {
|
||||
decltype(env) newEnv;
|
||||
for (auto& i : env)
|
||||
for (auto& i : env) {
|
||||
if (keepVars.count(i.first)) {
|
||||
newEnv.emplace(i);
|
||||
}
|
||||
}
|
||||
env = newEnv;
|
||||
// NixOS hack: prevent /etc/bashrc from sourcing /etc/profile.
|
||||
env["__ETC_PROFILE_SOURCED"] = "1";
|
||||
|
@ -433,15 +446,17 @@ static void _main(int argc, char** argv) {
|
|||
bool keepTmp = false;
|
||||
int fileNr = 0;
|
||||
|
||||
for (auto& var : drv.env)
|
||||
for (auto& var : drv.env) {
|
||||
if (passAsFile.count(var.first)) {
|
||||
keepTmp = true;
|
||||
string fn = ".attr-" + std::to_string(fileNr++);
|
||||
Path p = (Path)tmpDir + "/" + fn;
|
||||
writeFile(p, var.second);
|
||||
env[var.first + "Path"] = p;
|
||||
} else
|
||||
} else {
|
||||
env[var.first] = var.second;
|
||||
}
|
||||
}
|
||||
|
||||
restoreAffinity();
|
||||
|
||||
|
@ -507,16 +522,17 @@ static void _main(int argc, char** argv) {
|
|||
auto outPath = drvInfo.queryOutPath();
|
||||
|
||||
auto outputName = drvInfo.queryOutputName();
|
||||
if (outputName == "")
|
||||
if (outputName == "") {
|
||||
throw Error("derivation '%s' lacks an 'outputName' attribute", drvPath);
|
||||
}
|
||||
|
||||
pathsToBuild.insert(drvPath + "!" + outputName);
|
||||
|
||||
std::string drvPrefix;
|
||||
auto i = drvPrefixes.find(drvPath);
|
||||
if (i != drvPrefixes.end())
|
||||
if (i != drvPrefixes.end()) {
|
||||
drvPrefix = i->second;
|
||||
else {
|
||||
} else {
|
||||
drvPrefix = outLink;
|
||||
if (drvPrefixes.size()) {
|
||||
drvPrefix += fmt("-%d", drvPrefixes.size() + 1);
|
||||
|
@ -539,9 +555,11 @@ static void _main(int argc, char** argv) {
|
|||
return;
|
||||
}
|
||||
|
||||
for (auto& symlink : resultSymlinks)
|
||||
if (auto store2 = store.dynamic_pointer_cast<LocalFSStore>())
|
||||
for (auto& symlink : resultSymlinks) {
|
||||
if (auto store2 = store.dynamic_pointer_cast<LocalFSStore>()) {
|
||||
store2->addPermRoot(symlink.second, absPath(symlink.first), true);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& path : outPaths) {
|
||||
std::cout << path << '\n';
|
||||
|
|
30
third_party/nix/src/nix-channel/nix-channel.cc
vendored
30
third_party/nix/src/nix-channel/nix-channel.cc
vendored
|
@ -40,18 +40,22 @@ static void readChannels() {
|
|||
static void writeChannels() {
|
||||
auto channelsFD = AutoCloseFD{open(
|
||||
channelsList.c_str(), O_WRONLY | O_CLOEXEC | O_CREAT | O_TRUNC, 0644)};
|
||||
if (!channelsFD)
|
||||
if (!channelsFD) {
|
||||
throw SysError(format("opening '%1%' for writing") % channelsList);
|
||||
for (const auto& channel : channels)
|
||||
}
|
||||
for (const auto& channel : channels) {
|
||||
writeFull(channelsFD.get(), channel.second + " " + channel.first + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Adds a channel.
|
||||
static void addChannel(const string& url, const string& name) {
|
||||
if (!regex_search(url, std::regex("^(file|http|https)://")))
|
||||
if (!regex_search(url, std::regex("^(file|http|https)://"))) {
|
||||
throw Error(format("invalid channel URL '%1%'") % url);
|
||||
if (!regex_search(name, std::regex("^[a-zA-Z0-9_][a-zA-Z0-9_\\.-]*$")))
|
||||
}
|
||||
if (!regex_search(name, std::regex("^[a-zA-Z0-9_][a-zA-Z0-9_\\.-]*$"))) {
|
||||
throw Error(format("invalid channel identifier '%1%'") % name);
|
||||
}
|
||||
readChannels();
|
||||
channels[name] = url;
|
||||
writeChannels();
|
||||
|
@ -157,10 +161,12 @@ static void update(const StringSet& channelNames) {
|
|||
// Make the channels appear in nix-env.
|
||||
struct stat st;
|
||||
if (lstat(nixDefExpr.c_str(), &st) == 0) {
|
||||
if (S_ISLNK(st.st_mode))
|
||||
if (S_ISLNK(st.st_mode)) {
|
||||
// old-skool ~/.nix-defexpr
|
||||
if (unlink(nixDefExpr.c_str()) == -1)
|
||||
if (unlink(nixDefExpr.c_str()) == -1) {
|
||||
throw SysError(format("unlinking %1%") % nixDefExpr);
|
||||
}
|
||||
}
|
||||
} else if (errno != ENOENT) {
|
||||
throw SysError(format("getting status of %1%") % nixDefExpr);
|
||||
}
|
||||
|
@ -210,8 +216,9 @@ static int _main(int argc, char** argv) {
|
|||
case cNone:
|
||||
throw UsageError("no command specified");
|
||||
case cAdd:
|
||||
if (args.size() < 1 || args.size() > 2)
|
||||
if (args.size() < 1 || args.size() > 2) {
|
||||
throw UsageError("'--add' requires one or two arguments");
|
||||
}
|
||||
{
|
||||
auto url = args[0];
|
||||
std::string name;
|
||||
|
@ -226,8 +233,9 @@ static int _main(int argc, char** argv) {
|
|||
}
|
||||
break;
|
||||
case cRemove:
|
||||
if (args.size() != 1)
|
||||
if (args.size() != 1) {
|
||||
throw UsageError("'--remove' requires one argument");
|
||||
}
|
||||
removeChannel(args[0]);
|
||||
break;
|
||||
case cList:
|
||||
|
@ -235,15 +243,17 @@ static int _main(int argc, char** argv) {
|
|||
throw UsageError("'--list' expects no arguments");
|
||||
}
|
||||
readChannels();
|
||||
for (const auto& channel : channels)
|
||||
for (const auto& channel : channels) {
|
||||
std::cout << channel.first << ' ' << channel.second << '\n';
|
||||
}
|
||||
break;
|
||||
case cUpdate:
|
||||
update(StringSet(args.begin(), args.end()));
|
||||
break;
|
||||
case cRollback:
|
||||
if (args.size() > 1)
|
||||
if (args.size() > 1) {
|
||||
throw UsageError("'--rollback' has at most one argument");
|
||||
}
|
||||
Strings envArgs{"--profile", profile};
|
||||
if (args.size() == 1) {
|
||||
envArgs.push_back("--switch-generation");
|
||||
|
|
|
@ -42,10 +42,11 @@ void removeOldGenerations(std::string dir) {
|
|||
}
|
||||
if (link.find("link") != string::npos) {
|
||||
LOG(INFO) << "removing old generations of profile " << path;
|
||||
if (deleteOlderThan != "")
|
||||
if (deleteOlderThan != "") {
|
||||
deleteGenerationsOlderThan(path, deleteOlderThan, dryRun);
|
||||
else
|
||||
} else {
|
||||
deleteOldGenerations(path, dryRun);
|
||||
}
|
||||
}
|
||||
} else if (type == DT_DIR) {
|
||||
removeOldGenerations(path);
|
||||
|
@ -61,22 +62,23 @@ static int _main(int argc, char** argv) {
|
|||
|
||||
parseCmdLine(
|
||||
argc, argv, [&](Strings::iterator& arg, const Strings::iterator& end) {
|
||||
if (*arg == "--help")
|
||||
if (*arg == "--help") {
|
||||
showManPage("nix-collect-garbage");
|
||||
else if (*arg == "--version")
|
||||
} else if (*arg == "--version") {
|
||||
printVersion("nix-collect-garbage");
|
||||
else if (*arg == "--delete-old" || *arg == "-d")
|
||||
} else if (*arg == "--delete-old" || *arg == "-d") {
|
||||
removeOld = true;
|
||||
else if (*arg == "--delete-older-than") {
|
||||
} else if (*arg == "--delete-older-than") {
|
||||
removeOld = true;
|
||||
deleteOlderThan = getArg(*arg, arg, end);
|
||||
} else if (*arg == "--dry-run")
|
||||
} else if (*arg == "--dry-run") {
|
||||
dryRun = true;
|
||||
else if (*arg == "--max-freed") {
|
||||
} else if (*arg == "--max-freed") {
|
||||
long long maxFreed = getIntArg<long long>(*arg, arg, end, true);
|
||||
options.maxFreed = maxFreed >= 0 ? maxFreed : 0;
|
||||
} else
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
|
|
|
@ -18,32 +18,33 @@ static int _main(int argc, char** argv) {
|
|||
|
||||
parseCmdLine(
|
||||
argc, argv, [&](Strings::iterator& arg, const Strings::iterator& end) {
|
||||
if (*arg == "--help")
|
||||
if (*arg == "--help") {
|
||||
showManPage("nix-copy-closure");
|
||||
else if (*arg == "--version")
|
||||
} else if (*arg == "--version") {
|
||||
printVersion("nix-copy-closure");
|
||||
else if (*arg == "--gzip" || *arg == "--bzip2" || *arg == "--xz") {
|
||||
} else if (*arg == "--gzip" || *arg == "--bzip2" || *arg == "--xz") {
|
||||
if (*arg != "--gzip") {
|
||||
LOG(WARNING) << "'" << *arg
|
||||
<< "' is not implemented, falling back to gzip";
|
||||
}
|
||||
gzip = true;
|
||||
} else if (*arg == "--from")
|
||||
} else if (*arg == "--from") {
|
||||
toMode = false;
|
||||
else if (*arg == "--to")
|
||||
} else if (*arg == "--to") {
|
||||
toMode = true;
|
||||
else if (*arg == "--include-outputs")
|
||||
} else if (*arg == "--include-outputs") {
|
||||
includeOutputs = true;
|
||||
else if (*arg == "--show-progress")
|
||||
} else if (*arg == "--show-progress") {
|
||||
LOG(WARNING) << "'--show-progress' is not implemented";
|
||||
else if (*arg == "--dry-run")
|
||||
} else if (*arg == "--dry-run") {
|
||||
dryRun = true;
|
||||
else if (*arg == "--use-substitutes" || *arg == "-s")
|
||||
} else if (*arg == "--use-substitutes" || *arg == "-s") {
|
||||
useSubstitutes = Substitute;
|
||||
else if (sshHost.empty())
|
||||
} else if (sshHost.empty()) {
|
||||
sshHost = *arg;
|
||||
else
|
||||
} else {
|
||||
storePaths.insert(*arg);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
|
@ -58,8 +59,9 @@ static int _main(int argc, char** argv) {
|
|||
auto from = toMode ? openStore() : openStore(remoteUri);
|
||||
|
||||
PathSet storePaths2;
|
||||
for (auto& path : storePaths)
|
||||
for (auto& path : storePaths) {
|
||||
storePaths2.insert(from->followLinksToStorePath(path));
|
||||
}
|
||||
|
||||
PathSet closure;
|
||||
from->computeFSClosure(storePaths2, closure, false, includeOutputs);
|
||||
|
|
120
third_party/nix/src/nix-daemon/nix-daemon.cc
vendored
120
third_party/nix/src/nix-daemon/nix-daemon.cc
vendored
|
@ -90,8 +90,9 @@ struct TunnelLogger {
|
|||
state->canSendStderr = false;
|
||||
throw;
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
state->pendingMsgs.push_back(s);
|
||||
}
|
||||
}
|
||||
|
||||
void log(const FormatOrString& fs) {
|
||||
|
@ -253,14 +254,15 @@ static void performOp(TunnelLogger* logger, ref<Store> store, bool trusted,
|
|||
Path path = readStorePath(*store, from);
|
||||
logger->startWork();
|
||||
PathSet paths;
|
||||
if (op == wopQueryReferences)
|
||||
if (op == wopQueryReferences) {
|
||||
paths = store->queryPathInfo(path)->references;
|
||||
else if (op == wopQueryReferrers)
|
||||
} else if (op == wopQueryReferrers) {
|
||||
store->queryReferrers(path, paths);
|
||||
else if (op == wopQueryValidDerivers)
|
||||
} else if (op == wopQueryValidDerivers) {
|
||||
paths = store->queryValidDerivers(path);
|
||||
else
|
||||
} else {
|
||||
paths = store->queryDerivationOutputs(path);
|
||||
}
|
||||
logger->stopWork();
|
||||
to << paths;
|
||||
break;
|
||||
|
@ -377,10 +379,11 @@ static void performOp(TunnelLogger* logger, ref<Store> store, bool trusted,
|
|||
|
||||
/* Repairing is not atomic, so disallowed for "untrusted"
|
||||
clients. */
|
||||
if (mode == bmRepair && !trusted)
|
||||
if (mode == bmRepair && !trusted) {
|
||||
throw Error(
|
||||
"repairing is not allowed because you are not in "
|
||||
"'trusted-users'");
|
||||
}
|
||||
}
|
||||
logger->startWork();
|
||||
store->buildPaths(drvs, mode);
|
||||
|
@ -451,10 +454,11 @@ static void performOp(TunnelLogger* logger, ref<Store> store, bool trusted,
|
|||
|
||||
to << size;
|
||||
|
||||
for (auto& [target, links] : roots)
|
||||
for (auto& [target, links] : roots) {
|
||||
for (auto& link : links) {
|
||||
to << link << target;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -472,8 +476,9 @@ static void performOp(TunnelLogger* logger, ref<Store> store, bool trusted,
|
|||
GCResults results;
|
||||
|
||||
logger->startWork();
|
||||
if (options.ignoreLiveness)
|
||||
if (options.ignoreLiveness) {
|
||||
throw Error("you are not allowed to ignore liveness");
|
||||
}
|
||||
store->collectGarbage(options, results);
|
||||
logger->stopWork();
|
||||
|
||||
|
@ -522,30 +527,33 @@ static void performOp(TunnelLogger* logger, ref<Store> store, bool trusted,
|
|||
}
|
||||
Strings subs;
|
||||
auto ss = tokenizeString<Strings>(value);
|
||||
for (auto& s : ss)
|
||||
if (trusted.count(s))
|
||||
for (auto& s : ss) {
|
||||
if (trusted.count(s)) {
|
||||
subs.push_back(s);
|
||||
else
|
||||
} else {
|
||||
LOG(WARNING) << "ignoring untrusted substituter '" << s << "'";
|
||||
}
|
||||
}
|
||||
res = subs;
|
||||
return true;
|
||||
};
|
||||
|
||||
try {
|
||||
if (name == "ssh-auth-sock") // obsolete
|
||||
if (name == "ssh-auth-sock") { // obsolete
|
||||
;
|
||||
else if (trusted || name == settings.buildTimeout.name ||
|
||||
name == "connect-timeout" ||
|
||||
(name == "builders" && value == ""))
|
||||
} else if (trusted || name == settings.buildTimeout.name ||
|
||||
name == "connect-timeout" ||
|
||||
(name == "builders" && value == "")) {
|
||||
settings.set(name, value);
|
||||
else if (setSubstituters(settings.substituters))
|
||||
} else if (setSubstituters(settings.substituters)) {
|
||||
;
|
||||
else if (setSubstituters(settings.extraSubstituters))
|
||||
} else if (setSubstituters(settings.extraSubstituters)) {
|
||||
;
|
||||
else
|
||||
} else {
|
||||
LOG(WARNING) << "ignoring the user-specified setting '" << name
|
||||
<< "', because it is a "
|
||||
<< "restricted setting and you are not a trusted user";
|
||||
}
|
||||
} catch (UsageError& e) {
|
||||
LOG(WARNING) << e.what();
|
||||
}
|
||||
|
@ -562,9 +570,9 @@ static void performOp(TunnelLogger* logger, ref<Store> store, bool trusted,
|
|||
store->querySubstitutablePathInfos({path}, infos);
|
||||
logger->stopWork();
|
||||
SubstitutablePathInfos::iterator i = infos.find(path);
|
||||
if (i == infos.end())
|
||||
if (i == infos.end()) {
|
||||
to << 0;
|
||||
else {
|
||||
} else {
|
||||
to << 1 << i->second.deriver << i->second.references
|
||||
<< i->second.downloadSize << i->second.narSize;
|
||||
}
|
||||
|
@ -632,8 +640,9 @@ static void performOp(TunnelLogger* logger, ref<Store> store, bool trusted,
|
|||
bool checkContents, repair;
|
||||
from >> checkContents >> repair;
|
||||
logger->startWork();
|
||||
if (repair && !trusted)
|
||||
if (repair && !trusted) {
|
||||
throw Error("you are not privileged to repair paths");
|
||||
}
|
||||
bool errors = store->verifyStore(checkContents, (RepairFlag)repair);
|
||||
logger->stopWork();
|
||||
to << errors;
|
||||
|
@ -746,8 +755,9 @@ static void processConnection(bool trusted, const std::string& userName,
|
|||
DLOG(INFO) << opCount << " operations";
|
||||
});
|
||||
|
||||
if (GET_PROTOCOL_MINOR(clientVersion) >= 14 && readInt(from))
|
||||
if (GET_PROTOCOL_MINOR(clientVersion) >= 14 && readInt(from)) {
|
||||
setAffinityTo(readInt(from));
|
||||
}
|
||||
|
||||
readInt(from); // obsolete reserveSpace
|
||||
|
||||
|
@ -823,8 +833,9 @@ static void sigChldHandler(int sigNo) {
|
|||
// Ensure we don't modify errno of whatever we've interrupted
|
||||
auto saved_errno = errno;
|
||||
/* Reap all dead children. */
|
||||
while (waitpid(-1, 0, WNOHANG) > 0)
|
||||
while (waitpid(-1, 0, WNOHANG) > 0) {
|
||||
;
|
||||
}
|
||||
errno = saved_errno;
|
||||
}
|
||||
|
||||
|
@ -833,8 +844,9 @@ static void setSigChldAction(bool autoReap) {
|
|||
act.sa_handler = autoReap ? sigChldHandler : SIG_DFL;
|
||||
sigfillset(&act.sa_mask);
|
||||
act.sa_flags = 0;
|
||||
if (sigaction(SIGCHLD, &act, &oact))
|
||||
if (sigaction(SIGCHLD, &act, &oact)) {
|
||||
throw SysError("setting SIGCHLD handler");
|
||||
}
|
||||
}
|
||||
|
||||
bool matchUser(const string& user, const string& group, const Strings& users) {
|
||||
|
@ -846,7 +858,7 @@ bool matchUser(const string& user, const string& group, const Strings& users) {
|
|||
return true;
|
||||
}
|
||||
|
||||
for (auto& i : users)
|
||||
for (auto& i : users) {
|
||||
if (string(i, 0, 1) == "@") {
|
||||
if (group == string(i, 1)) {
|
||||
return true;
|
||||
|
@ -855,11 +867,13 @@ bool matchUser(const string& user, const string& group, const Strings& users) {
|
|||
if (!gr) {
|
||||
continue;
|
||||
}
|
||||
for (char** mem = gr->gr_mem; *mem; mem++)
|
||||
for (char** mem = gr->gr_mem; *mem; mem++) {
|
||||
if (user == string(*mem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -881,8 +895,9 @@ static PeerInfo getPeerInfo(int remote) {
|
|||
|
||||
ucred cred;
|
||||
socklen_t credLen = sizeof(cred);
|
||||
if (getsockopt(remote, SOL_SOCKET, SO_PEERCRED, &cred, &credLen) == -1)
|
||||
if (getsockopt(remote, SOL_SOCKET, SO_PEERCRED, &cred, &credLen) == -1) {
|
||||
throw SysError("getting peer credentials");
|
||||
}
|
||||
peer = {true, cred.pid, true, cred.uid, true, cred.gid};
|
||||
|
||||
#elif defined(LOCAL_PEERCRED)
|
||||
|
@ -918,8 +933,9 @@ static void daemonLoop(char** argv) {
|
|||
/* Handle socket-based activation by systemd. */
|
||||
if (getEnv("LISTEN_FDS") != "") {
|
||||
if (getEnv("LISTEN_PID") != std::to_string(getpid()) ||
|
||||
getEnv("LISTEN_FDS") != "1")
|
||||
getEnv("LISTEN_FDS") != "1") {
|
||||
throw Error("unexpected systemd environment variables");
|
||||
}
|
||||
fdSocket = SD_LISTEN_FDS_START;
|
||||
}
|
||||
|
||||
|
@ -938,14 +954,16 @@ static void daemonLoop(char** argv) {
|
|||
/* Urgh, sockaddr_un allows path names of only 108 characters.
|
||||
So chdir to the socket directory so that we can pass a
|
||||
relative path name. */
|
||||
if (chdir(dirOf(socketPath).c_str()) == -1)
|
||||
if (chdir(dirOf(socketPath).c_str()) == -1) {
|
||||
throw SysError("cannot change current directory");
|
||||
}
|
||||
Path socketPathRel = "./" + baseNameOf(socketPath);
|
||||
|
||||
struct sockaddr_un addr;
|
||||
addr.sun_family = AF_UNIX;
|
||||
if (socketPathRel.size() >= sizeof(addr.sun_path))
|
||||
if (socketPathRel.size() >= sizeof(addr.sun_path)) {
|
||||
throw Error(format("socket path '%1%' is too long") % socketPathRel);
|
||||
}
|
||||
strcpy(addr.sun_path, socketPathRel.c_str());
|
||||
|
||||
unlink(socketPath.c_str());
|
||||
|
@ -956,14 +974,17 @@ static void daemonLoop(char** argv) {
|
|||
mode_t oldMode = umask(0111);
|
||||
int res = bind(fdSocket.get(), (struct sockaddr*)&addr, sizeof(addr));
|
||||
umask(oldMode);
|
||||
if (res == -1)
|
||||
if (res == -1) {
|
||||
throw SysError(format("cannot bind to socket '%1%'") % socketPath);
|
||||
}
|
||||
|
||||
if (chdir("/") == -1) /* back to the root */
|
||||
if (chdir("/") == -1) { /* back to the root */
|
||||
throw SysError("cannot change current directory");
|
||||
}
|
||||
|
||||
if (listen(fdSocket.get(), 5) == -1)
|
||||
if (listen(fdSocket.get(), 5) == -1) {
|
||||
throw SysError(format("cannot listen on socket '%1%'") % socketPath);
|
||||
}
|
||||
}
|
||||
|
||||
closeOnExec(fdSocket.get());
|
||||
|
@ -1062,16 +1083,17 @@ static int _main(int argc, char** argv) {
|
|||
|
||||
parseCmdLine(argc, argv,
|
||||
[&](Strings::iterator& arg, const Strings::iterator& end) {
|
||||
if (*arg == "--daemon")
|
||||
if (*arg == "--daemon") {
|
||||
; /* ignored for backwards compatibility */
|
||||
else if (*arg == "--help")
|
||||
} else if (*arg == "--help") {
|
||||
showManPage("nix-daemon");
|
||||
else if (*arg == "--version")
|
||||
} else if (*arg == "--version") {
|
||||
printVersion("nix-daemon");
|
||||
else if (*arg == "--stdio")
|
||||
} else if (*arg == "--stdio") {
|
||||
stdio = true;
|
||||
else
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
|
@ -1087,20 +1109,23 @@ static int _main(int argc, char** argv) {
|
|||
}
|
||||
|
||||
auto socketDir = dirOf(socketPath);
|
||||
if (chdir(socketDir.c_str()) == -1)
|
||||
if (chdir(socketDir.c_str()) == -1) {
|
||||
throw SysError(format("changing to socket directory '%1%'") %
|
||||
socketDir);
|
||||
}
|
||||
|
||||
auto socketName = baseNameOf(socketPath);
|
||||
auto addr = sockaddr_un{};
|
||||
addr.sun_family = AF_UNIX;
|
||||
if (socketName.size() + 1 >= sizeof(addr.sun_path))
|
||||
if (socketName.size() + 1 >= sizeof(addr.sun_path)) {
|
||||
throw Error(format("socket name %1% is too long") % socketName);
|
||||
}
|
||||
strcpy(addr.sun_path, socketName.c_str());
|
||||
|
||||
if (connect(s, (struct sockaddr*)&addr, sizeof(addr)) == -1)
|
||||
if (connect(s, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
|
||||
throw SysError(format("cannot connect to daemon at %1%") %
|
||||
socketPath);
|
||||
}
|
||||
|
||||
auto nfds = (s > STDIN_FILENO ? s : STDIN_FILENO) + 1;
|
||||
while (true) {
|
||||
|
@ -1108,23 +1133,26 @@ static int _main(int argc, char** argv) {
|
|||
FD_ZERO(&fds);
|
||||
FD_SET(s, &fds);
|
||||
FD_SET(STDIN_FILENO, &fds);
|
||||
if (select(nfds, &fds, nullptr, nullptr, nullptr) == -1)
|
||||
if (select(nfds, &fds, nullptr, nullptr, nullptr) == -1) {
|
||||
throw SysError("waiting for data from client or server");
|
||||
}
|
||||
if (FD_ISSET(s, &fds)) {
|
||||
auto res = splice(s, nullptr, STDOUT_FILENO, nullptr, SSIZE_MAX,
|
||||
SPLICE_F_MOVE);
|
||||
if (res == -1)
|
||||
if (res == -1) {
|
||||
throw SysError("splicing data from daemon socket to stdout");
|
||||
else if (res == 0)
|
||||
} else if (res == 0) {
|
||||
throw EndOfFile("unexpected EOF from daemon socket");
|
||||
}
|
||||
}
|
||||
if (FD_ISSET(STDIN_FILENO, &fds)) {
|
||||
auto res = splice(STDIN_FILENO, nullptr, s, nullptr, SSIZE_MAX,
|
||||
SPLICE_F_MOVE);
|
||||
if (res == -1)
|
||||
if (res == -1) {
|
||||
throw SysError("splicing data from stdin to daemon socket");
|
||||
else if (res == 0)
|
||||
} else if (res == 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
310
third_party/nix/src/nix-env/nix-env.cc
vendored
310
third_party/nix/src/nix-env/nix-env.cc
vendored
|
@ -60,22 +60,24 @@ struct Globals {
|
|||
typedef void (*Operation)(Globals& globals, Strings opFlags, Strings opArgs);
|
||||
|
||||
static string needArg(Strings::iterator& i, Strings& args, const string& arg) {
|
||||
if (i == args.end())
|
||||
if (i == args.end()) {
|
||||
throw UsageError(format("'%1%' requires an argument") % arg);
|
||||
}
|
||||
return *i++;
|
||||
}
|
||||
|
||||
static bool parseInstallSourceOptions(Globals& globals, Strings::iterator& i,
|
||||
Strings& args, const string& arg) {
|
||||
if (arg == "--from-expression" || arg == "-E")
|
||||
if (arg == "--from-expression" || arg == "-E") {
|
||||
globals.instSource.type = srcNixExprs;
|
||||
else if (arg == "--from-profile") {
|
||||
} else if (arg == "--from-profile") {
|
||||
globals.instSource.type = srcProfile;
|
||||
globals.instSource.profile = needArg(i, args, arg);
|
||||
} else if (arg == "--attr" || arg == "-A")
|
||||
} else if (arg == "--attr" || arg == "-A") {
|
||||
globals.instSource.type = srcAttrPath;
|
||||
else
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -102,8 +104,9 @@ static void getAllExprs(EvalState& state, const Path& path, StringSet& attrs,
|
|||
Path path2 = path + "/" + i;
|
||||
|
||||
struct stat st;
|
||||
if (stat(path2.c_str(), &st) == -1)
|
||||
if (stat(path2.c_str(), &st) == -1) {
|
||||
continue; // ignore dangling symlinks in ~/.nix-defexpr
|
||||
}
|
||||
|
||||
if (isNixExpr(path2, st) &&
|
||||
(!S_ISREG(st.st_mode) || hasSuffix(path2, ".nix"))) {
|
||||
|
@ -112,8 +115,9 @@ static void getAllExprs(EvalState& state, const Path& path, StringSet& attrs,
|
|||
`-A' option. Useful if you want to stick a Nix
|
||||
expression directly in ~/.nix-defexpr. */
|
||||
string attrName = i;
|
||||
if (hasSuffix(attrName, ".nix"))
|
||||
if (hasSuffix(attrName, ".nix")) {
|
||||
attrName = string(attrName, 0, attrName.size() - 4);
|
||||
}
|
||||
if (attrs.find(attrName) != attrs.end()) {
|
||||
LOG(WARNING) << "name collision in input Nix expressions, skipping '"
|
||||
<< path2 << "'";
|
||||
|
@ -124,21 +128,24 @@ static void getAllExprs(EvalState& state, const Path& path, StringSet& attrs,
|
|||
Value& vFun = state.getBuiltin("import");
|
||||
Value& vArg(*state.allocValue());
|
||||
mkString(vArg, path2);
|
||||
if (v.attrs->size() == v.attrs->capacity())
|
||||
if (v.attrs->size() == v.attrs->capacity()) {
|
||||
throw Error(format("too many Nix expressions in directory '%1%'") %
|
||||
path);
|
||||
}
|
||||
mkApp(*state.allocAttr(v, state.symbols.create(attrName)), vFun, vArg);
|
||||
} else if (S_ISDIR(st.st_mode))
|
||||
} else if (S_ISDIR(st.st_mode)) {
|
||||
/* `path2' is a directory (with no default.nix in it);
|
||||
recurse into it. */
|
||||
getAllExprs(state, path2, attrs, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void loadSourceExpr(EvalState& state, const Path& path, Value& v) {
|
||||
struct stat st;
|
||||
if (stat(path.c_str(), &st) == -1)
|
||||
if (stat(path.c_str(), &st) == -1) {
|
||||
throw SysError(format("getting information about '%1%'") % path);
|
||||
}
|
||||
|
||||
if (isNixExpr(path, st)) {
|
||||
state.evalFile(path, v);
|
||||
|
@ -159,8 +166,9 @@ static void loadSourceExpr(EvalState& state, const Path& path, Value& v) {
|
|||
v.attrs->sort();
|
||||
}
|
||||
|
||||
else
|
||||
else {
|
||||
throw Error("path '%s' is not a directory or a Nix expression", path);
|
||||
}
|
||||
}
|
||||
|
||||
static void loadDerivations(EvalState& state, Path nixExprPath,
|
||||
|
@ -205,9 +213,11 @@ static bool isPrebuilt(EvalState& state, DrvInfo& elem) {
|
|||
|
||||
static void checkSelectorUse(DrvNames& selectors) {
|
||||
/* Check that all selectors have been used. */
|
||||
for (auto& i : selectors)
|
||||
if (i.hits == 0 && i.fullName != "*")
|
||||
for (auto& i : selectors) {
|
||||
if (i.hits == 0 && i.fullName != "*") {
|
||||
throw Error(format("selector '%1%' matches no derivations") % i.fullName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static DrvInfos filterBySelector(EvalState& state, const DrvInfos& allElems,
|
||||
|
@ -263,9 +273,10 @@ static DrvInfos filterBySelector(EvalState& state, const DrvInfos& allElems,
|
|||
if (d == 0) {
|
||||
d = comparePriorities(state, j.first, k->second.first);
|
||||
}
|
||||
if (d == 0)
|
||||
if (d == 0) {
|
||||
d = compareVersions(drvName.version,
|
||||
DrvName(k->second.first.queryName()).version);
|
||||
}
|
||||
}
|
||||
|
||||
if (d > 0) {
|
||||
|
@ -279,21 +290,23 @@ static DrvInfos filterBySelector(EvalState& state, const DrvInfos& allElems,
|
|||
|
||||
matches.clear();
|
||||
for (auto& j : newest) {
|
||||
if (multiple.find(j.second.first.queryName()) != multiple.end())
|
||||
if (multiple.find(j.second.first.queryName()) != multiple.end()) {
|
||||
LOG(WARNING) << "warning: there are multiple derivations named '"
|
||||
<< j.second.first.queryName()
|
||||
<< "'; using the first one";
|
||||
}
|
||||
matches.push_back(j.second);
|
||||
}
|
||||
}
|
||||
|
||||
/* Insert only those elements in the final list that we
|
||||
haven't inserted before. */
|
||||
for (auto& j : matches)
|
||||
for (auto& j : matches) {
|
||||
if (done.find(j.second) == done.end()) {
|
||||
done.insert(j.second);
|
||||
elems.push_back(j.first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkSelectorUse(selectors);
|
||||
|
@ -307,8 +320,9 @@ static void queryInstSources(EvalState& state, InstallSourceInfo& instSource,
|
|||
const Strings& args, DrvInfos& elems,
|
||||
bool newestOnly) {
|
||||
InstallSourceType type = instSource.type;
|
||||
if (type == srcUnknown && args.size() > 0 && isPath(args.front()))
|
||||
if (type == srcUnknown && args.size() > 0 && isPath(args.front())) {
|
||||
type = srcStorePaths;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
/* Get the available user environment elements from the
|
||||
|
@ -369,10 +383,12 @@ static void queryInstSources(EvalState& state, InstallSourceInfo& instSource,
|
|||
elem.setOutPath(
|
||||
state.store->derivationFromPath(path).findOutput("out"));
|
||||
if (name.size() >= drvExtension.size() &&
|
||||
string(name, name.size() - drvExtension.size()) == drvExtension)
|
||||
string(name, name.size() - drvExtension.size()) == drvExtension) {
|
||||
name = string(name, 0, name.size() - drvExtension.size());
|
||||
} else
|
||||
}
|
||||
} else {
|
||||
elem.setOutPath(path);
|
||||
}
|
||||
|
||||
elems.push_back(elem);
|
||||
}
|
||||
|
@ -405,10 +421,11 @@ static void printMissing(EvalState& state, DrvInfos& elems) {
|
|||
PathSet targets;
|
||||
for (auto& i : elems) {
|
||||
Path drvPath = i.queryDrvPath();
|
||||
if (drvPath != "")
|
||||
if (drvPath != "") {
|
||||
targets.insert(drvPath);
|
||||
else
|
||||
} else {
|
||||
targets.insert(i.queryOutPath());
|
||||
}
|
||||
}
|
||||
|
||||
printMissing(state.store, targets);
|
||||
|
@ -425,9 +442,11 @@ static void installDerivations(Globals& globals, const Strings& args,
|
|||
queryInstSources(*globals.state, globals.instSource, args, newElemsTmp, true);
|
||||
|
||||
/* If --prebuilt-only is given, filter out source-only packages. */
|
||||
for (auto& i : newElemsTmp)
|
||||
if (!globals.prebuiltOnly || isPrebuilt(*globals.state, i))
|
||||
for (auto& i : newElemsTmp) {
|
||||
if (!globals.prebuiltOnly || isPrebuilt(*globals.state, i)) {
|
||||
newElems.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
StringSet newNames;
|
||||
for (auto& i : newElems) {
|
||||
|
@ -454,10 +473,11 @@ static void installDerivations(Globals& globals, const Strings& args,
|
|||
for (auto& i : installedElems) {
|
||||
DrvName drvName(i.queryName());
|
||||
if (!globals.preserveInstalled &&
|
||||
newNames.find(drvName.name) != newNames.end() && !keep(i))
|
||||
newNames.find(drvName.name) != newNames.end() && !keep(i)) {
|
||||
LOG(INFO) << "replacing old '" << i.queryName() << "'";
|
||||
else
|
||||
} else {
|
||||
allElems.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& i : newElems) {
|
||||
|
@ -472,22 +492,24 @@ static void installDerivations(Globals& globals, const Strings& args,
|
|||
}
|
||||
|
||||
if (createUserEnv(*globals.state, allElems, profile,
|
||||
settings.envKeepDerivations, lockToken))
|
||||
settings.envKeepDerivations, lockToken)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void opInstall(Globals& globals, Strings opFlags, Strings opArgs) {
|
||||
for (Strings::iterator i = opFlags.begin(); i != opFlags.end();) {
|
||||
string arg = *i++;
|
||||
if (parseInstallSourceOptions(globals, i, opFlags, arg))
|
||||
if (parseInstallSourceOptions(globals, i, opFlags, arg)) {
|
||||
;
|
||||
else if (arg == "--preserve-installed" || arg == "-P")
|
||||
} else if (arg == "--preserve-installed" || arg == "-P") {
|
||||
globals.preserveInstalled = true;
|
||||
else if (arg == "--remove-all" || arg == "-r")
|
||||
} else if (arg == "--remove-all" || arg == "-r") {
|
||||
globals.removeAll = true;
|
||||
else
|
||||
} else {
|
||||
throw UsageError(format("unknown flag '%1%'") % arg);
|
||||
}
|
||||
}
|
||||
|
||||
installDerivations(globals, opArgs, globals.profile);
|
||||
|
@ -569,8 +591,9 @@ static void upgradeDerivations(Globals& globals, const Strings& args,
|
|||
LOG(INFO) << action << " '" << i.queryName() << "' to '"
|
||||
<< bestElem->queryName() << "'";
|
||||
newElems.push_back(*bestElem);
|
||||
} else
|
||||
} else {
|
||||
newElems.push_back(i);
|
||||
}
|
||||
|
||||
} catch (Error& e) {
|
||||
e.addPrefix(
|
||||
|
@ -586,8 +609,9 @@ static void upgradeDerivations(Globals& globals, const Strings& args,
|
|||
}
|
||||
|
||||
if (createUserEnv(*globals.state, newElems, globals.profile,
|
||||
settings.envKeepDerivations, lockToken))
|
||||
settings.envKeepDerivations, lockToken)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -595,18 +619,19 @@ static void opUpgrade(Globals& globals, Strings opFlags, Strings opArgs) {
|
|||
UpgradeType upgradeType = utLt;
|
||||
for (Strings::iterator i = opFlags.begin(); i != opFlags.end();) {
|
||||
string arg = *i++;
|
||||
if (parseInstallSourceOptions(globals, i, opFlags, arg))
|
||||
if (parseInstallSourceOptions(globals, i, opFlags, arg)) {
|
||||
;
|
||||
else if (arg == "--lt")
|
||||
} else if (arg == "--lt") {
|
||||
upgradeType = utLt;
|
||||
else if (arg == "--leq")
|
||||
} else if (arg == "--leq") {
|
||||
upgradeType = utLeq;
|
||||
else if (arg == "--eq")
|
||||
} else if (arg == "--eq") {
|
||||
upgradeType = utEq;
|
||||
else if (arg == "--always")
|
||||
} else if (arg == "--always") {
|
||||
upgradeType = utAlways;
|
||||
else
|
||||
} else {
|
||||
throw UsageError(format("unknown flag '%1%'") % arg);
|
||||
}
|
||||
}
|
||||
|
||||
upgradeDerivations(globals, opArgs, upgradeType);
|
||||
|
@ -620,10 +645,12 @@ static void setMetaFlag(EvalState& state, DrvInfo& drv, const string& name,
|
|||
}
|
||||
|
||||
static void opSetFlag(Globals& globals, Strings opFlags, Strings opArgs) {
|
||||
if (opFlags.size() > 0)
|
||||
if (opFlags.size() > 0) {
|
||||
throw UsageError(format("unknown flag '%1%'") % opFlags.front());
|
||||
if (opArgs.size() < 2)
|
||||
}
|
||||
if (opArgs.size() < 2) {
|
||||
throw UsageError("not enough arguments to '--set-flag'");
|
||||
}
|
||||
|
||||
Strings::iterator arg = opArgs.begin();
|
||||
string flagName = *arg++;
|
||||
|
@ -638,21 +665,23 @@ static void opSetFlag(Globals& globals, Strings opFlags, Strings opArgs) {
|
|||
/* Update all matching derivations. */
|
||||
for (auto& i : installedElems) {
|
||||
DrvName drvName(i.queryName());
|
||||
for (auto& j : selectors)
|
||||
for (auto& j : selectors) {
|
||||
if (j.matches(drvName)) {
|
||||
LOG(INFO) << "setting flag on '" << i.queryName() << "'";
|
||||
j.hits++;
|
||||
setMetaFlag(*globals.state, i, flagName, flagValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkSelectorUse(selectors);
|
||||
|
||||
/* Write the new user environment. */
|
||||
if (createUserEnv(*globals.state, installedElems, globals.profile,
|
||||
settings.envKeepDerivations, lockToken))
|
||||
settings.envKeepDerivations, lockToken)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -664,10 +693,11 @@ static void opSet(Globals& globals, Strings opFlags, Strings opArgs) {
|
|||
|
||||
for (Strings::iterator i = opFlags.begin(); i != opFlags.end();) {
|
||||
string arg = *i++;
|
||||
if (parseInstallSourceOptions(globals, i, opFlags, arg))
|
||||
if (parseInstallSourceOptions(globals, i, opFlags, arg)) {
|
||||
;
|
||||
else
|
||||
} else {
|
||||
throw UsageError(format("unknown flag '%1%'") % arg);
|
||||
}
|
||||
}
|
||||
|
||||
DrvInfos elems;
|
||||
|
@ -716,7 +746,7 @@ static void uninstallDerivations(Globals& globals, Strings& selectors,
|
|||
for (auto& i : installedElems) {
|
||||
DrvName drvName(i.queryName());
|
||||
bool found = false;
|
||||
for (auto& j : selectors)
|
||||
for (auto& j : selectors) {
|
||||
/* !!! the repeated calls to followLinksToStorePath()
|
||||
are expensive, should pre-compute them. */
|
||||
if ((isPath(j) &&
|
||||
|
@ -727,6 +757,7 @@ static void uninstallDerivations(Globals& globals, Strings& selectors,
|
|||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
newElems.push_back(i);
|
||||
}
|
||||
|
@ -737,14 +768,16 @@ static void uninstallDerivations(Globals& globals, Strings& selectors,
|
|||
}
|
||||
|
||||
if (createUserEnv(*globals.state, newElems, profile,
|
||||
settings.envKeepDerivations, lockToken))
|
||||
settings.envKeepDerivations, lockToken)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void opUninstall(Globals& globals, Strings opFlags, Strings opArgs) {
|
||||
if (opFlags.size() > 0)
|
||||
if (opFlags.size() > 0) {
|
||||
throw UsageError(format("unknown flag '%1%'") % opFlags.front());
|
||||
}
|
||||
uninstallDerivations(globals, opArgs, globals.profile);
|
||||
}
|
||||
|
||||
|
@ -769,10 +802,11 @@ void printTable(Table& table) {
|
|||
assert(i.size() == nrColumns);
|
||||
Strings::iterator j;
|
||||
size_t column;
|
||||
for (j = i.begin(), column = 0; j != i.end(); ++j, ++column)
|
||||
for (j = i.begin(), column = 0; j != i.end(); ++j, ++column) {
|
||||
if (j->size() > widths[column]) {
|
||||
widths[column] = j->size();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& i : table) {
|
||||
|
@ -782,8 +816,9 @@ void printTable(Table& table) {
|
|||
string s = *j;
|
||||
replace(s.begin(), s.end(), '\n', ' ');
|
||||
cout << s;
|
||||
if (column < nrColumns - 1)
|
||||
if (column < nrColumns - 1) {
|
||||
cout << string(widths[column] - s.size() + 2, ' ');
|
||||
}
|
||||
}
|
||||
cout << std::endl;
|
||||
}
|
||||
|
@ -818,8 +853,9 @@ static VersionDiff compareVersionAgainstSet(const DrvInfo& elem,
|
|||
version = name2.version;
|
||||
} else if (diff != cvGreater && diff != cvEqual && d > 0) {
|
||||
diff = cvLess;
|
||||
if (version == "" || compareVersions(version, name2.version) < 0)
|
||||
if (version == "" || compareVersions(version, name2.version) < 0) {
|
||||
version = name2.version;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -877,48 +913,51 @@ static void opQuery(Globals& globals, Strings opFlags, Strings opArgs) {
|
|||
|
||||
for (Strings::iterator i = opFlags.begin(); i != opFlags.end();) {
|
||||
string arg = *i++;
|
||||
if (arg == "--status" || arg == "-s")
|
||||
if (arg == "--status" || arg == "-s") {
|
||||
printStatus = true;
|
||||
else if (arg == "--no-name")
|
||||
} else if (arg == "--no-name") {
|
||||
printName = false;
|
||||
else if (arg == "--system")
|
||||
} else if (arg == "--system") {
|
||||
printSystem = true;
|
||||
else if (arg == "--description")
|
||||
} else if (arg == "--description") {
|
||||
printDescription = true;
|
||||
else if (arg == "--compare-versions" || arg == "-c")
|
||||
} else if (arg == "--compare-versions" || arg == "-c") {
|
||||
compareVersions = true;
|
||||
else if (arg == "--drv-path")
|
||||
} else if (arg == "--drv-path") {
|
||||
printDrvPath = true;
|
||||
else if (arg == "--out-path")
|
||||
} else if (arg == "--out-path") {
|
||||
printOutPath = true;
|
||||
else if (arg == "--meta")
|
||||
} else if (arg == "--meta") {
|
||||
printMeta = true;
|
||||
else if (arg == "--installed")
|
||||
} else if (arg == "--installed") {
|
||||
source = sInstalled;
|
||||
else if (arg == "--available" || arg == "-a")
|
||||
} else if (arg == "--available" || arg == "-a") {
|
||||
source = sAvailable;
|
||||
else if (arg == "--xml")
|
||||
} else if (arg == "--xml") {
|
||||
xmlOutput = true;
|
||||
else if (arg == "--json")
|
||||
} else if (arg == "--json") {
|
||||
jsonOutput = true;
|
||||
else if (arg == "--attr-path" || arg == "-P")
|
||||
} else if (arg == "--attr-path" || arg == "-P") {
|
||||
printAttrPath = true;
|
||||
else if (arg == "--attr" || arg == "-A")
|
||||
} else if (arg == "--attr" || arg == "-A") {
|
||||
attrPath = needArg(i, opFlags, arg);
|
||||
else
|
||||
} else {
|
||||
throw UsageError(format("unknown flag '%1%'") % arg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Obtain derivation information from the specified source. */
|
||||
DrvInfos availElems, installedElems;
|
||||
|
||||
if (source == sInstalled || compareVersions || printStatus)
|
||||
if (source == sInstalled || compareVersions || printStatus) {
|
||||
installedElems = queryInstalled(*globals.state, globals.profile);
|
||||
}
|
||||
|
||||
if (source == sAvailable || compareVersions)
|
||||
if (source == sAvailable || compareVersions) {
|
||||
loadDerivations(*globals.state, globals.instSource.nixExprPath,
|
||||
globals.instSource.systemFilter,
|
||||
*globals.instSource.autoArgs, attrPath, availElems);
|
||||
}
|
||||
|
||||
DrvInfos elems_ = filterBySelector(
|
||||
*globals.state, source == sInstalled ? installedElems : availElems,
|
||||
|
@ -948,13 +987,15 @@ static void opQuery(Globals& globals, Strings opFlags, Strings opArgs) {
|
|||
PathSet validPaths, substitutablePaths;
|
||||
if (printStatus || globals.prebuiltOnly) {
|
||||
PathSet paths;
|
||||
for (auto& i : elems) try {
|
||||
for (auto& i : elems) {
|
||||
try {
|
||||
paths.insert(i.queryOutPath());
|
||||
} catch (AssertionError& e) {
|
||||
DLOG(WARNING) << "skipping derivation named '" << i.queryName()
|
||||
<< "' which gives an assertion failure";
|
||||
i.setFailed();
|
||||
}
|
||||
}
|
||||
validPaths = globals.state->store->queryValidPaths(paths);
|
||||
substitutablePaths = globals.state->store->querySubstitutablePaths(paths);
|
||||
}
|
||||
|
@ -984,8 +1025,10 @@ static void opQuery(Globals& globals, Strings opFlags, Strings opArgs) {
|
|||
|
||||
if (globals.prebuiltOnly &&
|
||||
validPaths.find(i.queryOutPath()) == validPaths.end() &&
|
||||
substitutablePaths.find(i.queryOutPath()) == substitutablePaths.end())
|
||||
substitutablePaths.find(i.queryOutPath()) ==
|
||||
substitutablePaths.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* For table output. */
|
||||
Strings columns;
|
||||
|
@ -1003,15 +1046,17 @@ static void opQuery(Globals& globals, Strings opFlags, Strings opArgs) {
|
|||
attrs["installed"] = isInstalled ? "1" : "0";
|
||||
attrs["valid"] = isValid ? "1" : "0";
|
||||
attrs["substitutable"] = hasSubs ? "1" : "0";
|
||||
} else
|
||||
} else {
|
||||
columns.push_back((string)(isInstalled ? "I" : "-") +
|
||||
(isValid ? "P" : "-") + (hasSubs ? "S" : "-"));
|
||||
}
|
||||
}
|
||||
|
||||
if (xmlOutput)
|
||||
if (xmlOutput) {
|
||||
attrs["attrPath"] = i.attrPath;
|
||||
else if (printAttrPath)
|
||||
} else if (printAttrPath) {
|
||||
columns.push_back(i.attrPath);
|
||||
}
|
||||
|
||||
if (xmlOutput) {
|
||||
auto drvName = DrvName(i.queryName());
|
||||
|
@ -1055,8 +1100,9 @@ static void opQuery(Globals& globals, Strings opFlags, Strings opArgs) {
|
|||
}
|
||||
} else {
|
||||
string column = (string) "" + ch + " " + version;
|
||||
if (diff == cvGreater && tty)
|
||||
if (diff == cvGreater && tty) {
|
||||
column = ANSI_RED + column + ANSI_NORMAL;
|
||||
}
|
||||
columns.push_back(column);
|
||||
}
|
||||
}
|
||||
|
@ -1065,8 +1111,9 @@ static void opQuery(Globals& globals, Strings opFlags, Strings opArgs) {
|
|||
if (i.querySystem() != "") {
|
||||
attrs["system"] = i.querySystem();
|
||||
}
|
||||
} else if (printSystem)
|
||||
} else if (printSystem) {
|
||||
columns.push_back(i.querySystem());
|
||||
}
|
||||
|
||||
if (printDrvPath) {
|
||||
string drvPath = i.queryDrvPath();
|
||||
|
@ -1074,8 +1121,9 @@ static void opQuery(Globals& globals, Strings opFlags, Strings opArgs) {
|
|||
if (drvPath != "") {
|
||||
attrs["drvPath"] = drvPath;
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
columns.push_back(drvPath == "" ? "-" : drvPath);
|
||||
}
|
||||
}
|
||||
|
||||
if (printOutPath && !xmlOutput) {
|
||||
|
@ -1100,8 +1148,9 @@ static void opQuery(Globals& globals, Strings opFlags, Strings opArgs) {
|
|||
if (descr != "") {
|
||||
attrs["description"] = descr;
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
columns.push_back(descr);
|
||||
}
|
||||
}
|
||||
|
||||
if (xmlOutput) {
|
||||
|
@ -1171,10 +1220,12 @@ static void opQuery(Globals& globals, Strings opFlags, Strings opArgs) {
|
|||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
xml.writeEmptyElement("item", attrs);
|
||||
} else
|
||||
}
|
||||
} else {
|
||||
table.push_back(columns);
|
||||
}
|
||||
|
||||
cout.flush();
|
||||
|
||||
|
@ -1194,10 +1245,12 @@ static void opQuery(Globals& globals, Strings opFlags, Strings opArgs) {
|
|||
}
|
||||
|
||||
static void opSwitchProfile(Globals& globals, Strings opFlags, Strings opArgs) {
|
||||
if (opFlags.size() > 0)
|
||||
if (opFlags.size() > 0) {
|
||||
throw UsageError(format("unknown flag '%1%'") % opFlags.front());
|
||||
if (opArgs.size() != 1)
|
||||
}
|
||||
if (opArgs.size() != 1) {
|
||||
throw UsageError(format("exactly one argument expected"));
|
||||
}
|
||||
|
||||
Path profile = absPath(opArgs.front());
|
||||
Path profileLink = getHome() + "/.nix-profile";
|
||||
|
@ -1215,17 +1268,20 @@ static void switchGeneration(Globals& globals, int dstGen) {
|
|||
Generations gens = findGenerations(globals.profile, curGen);
|
||||
|
||||
Generation dst;
|
||||
for (auto& i : gens)
|
||||
for (auto& i : gens) {
|
||||
if ((dstGen == prevGen && i.number < curGen) ||
|
||||
(dstGen >= 0 && i.number == dstGen))
|
||||
(dstGen >= 0 && i.number == dstGen)) {
|
||||
dst = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dst) {
|
||||
if (dstGen == prevGen)
|
||||
if (dstGen == prevGen) {
|
||||
throw Error(format("no generation older than the current (%1%) exists") %
|
||||
curGen);
|
||||
else
|
||||
} else {
|
||||
throw Error(format("generation %1% does not exist") % dstGen);
|
||||
}
|
||||
}
|
||||
|
||||
LOG(INFO) << "switching from generation " << curGen << " to " << dst.number;
|
||||
|
@ -1239,21 +1295,25 @@ static void switchGeneration(Globals& globals, int dstGen) {
|
|||
|
||||
static void opSwitchGeneration(Globals& globals, Strings opFlags,
|
||||
Strings opArgs) {
|
||||
if (opFlags.size() > 0)
|
||||
if (opFlags.size() > 0) {
|
||||
throw UsageError(format("unknown flag '%1%'") % opFlags.front());
|
||||
if (opArgs.size() != 1)
|
||||
}
|
||||
if (opArgs.size() != 1) {
|
||||
throw UsageError(format("exactly one argument expected"));
|
||||
}
|
||||
|
||||
int dstGen;
|
||||
if (!string2Int(opArgs.front(), dstGen))
|
||||
if (!string2Int(opArgs.front(), dstGen)) {
|
||||
throw UsageError(format("expected a generation number"));
|
||||
}
|
||||
|
||||
switchGeneration(globals, dstGen);
|
||||
}
|
||||
|
||||
static void opRollback(Globals& globals, Strings opFlags, Strings opArgs) {
|
||||
if (opFlags.size() > 0)
|
||||
if (opFlags.size() > 0) {
|
||||
throw UsageError(format("unknown flag '%1%'") % opFlags.front());
|
||||
}
|
||||
if (opArgs.size() != 0) {
|
||||
throw UsageError(format("no arguments expected"));
|
||||
}
|
||||
|
@ -1263,8 +1323,9 @@ static void opRollback(Globals& globals, Strings opFlags, Strings opArgs) {
|
|||
|
||||
static void opListGenerations(Globals& globals, Strings opFlags,
|
||||
Strings opArgs) {
|
||||
if (opFlags.size() > 0)
|
||||
if (opFlags.size() > 0) {
|
||||
throw UsageError(format("unknown flag '%1%'") % opFlags.front());
|
||||
}
|
||||
if (opArgs.size() != 0) {
|
||||
throw UsageError(format("no arguments expected"));
|
||||
}
|
||||
|
@ -1291,29 +1352,33 @@ static void opListGenerations(Globals& globals, Strings opFlags,
|
|||
|
||||
static void opDeleteGenerations(Globals& globals, Strings opFlags,
|
||||
Strings opArgs) {
|
||||
if (opFlags.size() > 0)
|
||||
if (opFlags.size() > 0) {
|
||||
throw UsageError(format("unknown flag '%1%'") % opFlags.front());
|
||||
}
|
||||
|
||||
if (opArgs.size() == 1 && opArgs.front() == "old") {
|
||||
deleteOldGenerations(globals.profile, globals.dryRun);
|
||||
} else if (opArgs.size() == 1 && opArgs.front().find('d') != string::npos) {
|
||||
deleteGenerationsOlderThan(globals.profile, opArgs.front(), globals.dryRun);
|
||||
} else if (opArgs.size() == 1 && opArgs.front().find('+') != string::npos) {
|
||||
if (opArgs.front().size() < 2)
|
||||
if (opArgs.front().size() < 2) {
|
||||
throw Error(format("invalid number of generations ‘%1%’") %
|
||||
opArgs.front());
|
||||
}
|
||||
string str_max = string(opArgs.front(), 1, opArgs.front().size());
|
||||
int max;
|
||||
if (!string2Int(str_max, max) || max == 0)
|
||||
if (!string2Int(str_max, max) || max == 0) {
|
||||
throw Error(format("invalid number of generations to keep ‘%1%’") %
|
||||
opArgs.front());
|
||||
}
|
||||
deleteGenerationsGreaterThan(globals.profile, max, globals.dryRun);
|
||||
} else {
|
||||
std::set<unsigned int> gens;
|
||||
for (auto& i : opArgs) {
|
||||
unsigned int n;
|
||||
if (!string2Int(i, n))
|
||||
if (!string2Int(i, n)) {
|
||||
throw UsageError(format("invalid generation number '%1%'") % i);
|
||||
}
|
||||
gens.insert(n);
|
||||
}
|
||||
deleteGenerations(globals.profile, gens, globals.dryRun);
|
||||
|
@ -1343,10 +1408,11 @@ static int _main(int argc, char** argv) {
|
|||
replaceSymlink(fmt("%s/profiles/per-user/%s/channels",
|
||||
settings.nixStateDir, getUserName()),
|
||||
globals.instSource.nixExprPath + "/channels");
|
||||
if (getuid() != 0)
|
||||
if (getuid() != 0) {
|
||||
replaceSymlink(
|
||||
fmt("%s/profiles/per-user/root/channels", settings.nixStateDir),
|
||||
globals.instSource.nixExprPath + "/channels_root");
|
||||
}
|
||||
} catch (Error&) {
|
||||
}
|
||||
}
|
||||
|
@ -1364,59 +1430,62 @@ static int _main(int argc, char** argv) {
|
|||
const Strings::iterator& end) {
|
||||
Operation oldOp = op;
|
||||
|
||||
if (*arg == "--help")
|
||||
if (*arg == "--help") {
|
||||
showManPage("nix-env");
|
||||
else if (*arg == "--version")
|
||||
} else if (*arg == "--version") {
|
||||
op = opVersion;
|
||||
else if (*arg == "--install" || *arg == "-i")
|
||||
} else if (*arg == "--install" || *arg == "-i") {
|
||||
op = opInstall;
|
||||
else if (*arg ==
|
||||
"--force-name") // undocumented flag for nix-install-package
|
||||
} else if (*arg ==
|
||||
"--force-name") { // undocumented flag for nix-install-package
|
||||
globals.forceName = getArg(*arg, arg, end);
|
||||
else if (*arg == "--uninstall" || *arg == "-e")
|
||||
} else if (*arg == "--uninstall" || *arg == "-e") {
|
||||
op = opUninstall;
|
||||
else if (*arg == "--upgrade" || *arg == "-u")
|
||||
} else if (*arg == "--upgrade" || *arg == "-u") {
|
||||
op = opUpgrade;
|
||||
else if (*arg == "--set-flag")
|
||||
} else if (*arg == "--set-flag") {
|
||||
op = opSetFlag;
|
||||
else if (*arg == "--set")
|
||||
} else if (*arg == "--set") {
|
||||
op = opSet;
|
||||
else if (*arg == "--query" || *arg == "-q")
|
||||
} else if (*arg == "--query" || *arg == "-q") {
|
||||
op = opQuery;
|
||||
else if (*arg == "--profile" || *arg == "-p")
|
||||
} else if (*arg == "--profile" || *arg == "-p") {
|
||||
globals.profile = absPath(getArg(*arg, arg, end));
|
||||
else if (*arg == "--file" || *arg == "-f")
|
||||
} else if (*arg == "--file" || *arg == "-f") {
|
||||
file = getArg(*arg, arg, end);
|
||||
else if (*arg == "--switch-profile" || *arg == "-S")
|
||||
} else if (*arg == "--switch-profile" || *arg == "-S") {
|
||||
op = opSwitchProfile;
|
||||
else if (*arg == "--switch-generation" || *arg == "-G")
|
||||
} else if (*arg == "--switch-generation" || *arg == "-G") {
|
||||
op = opSwitchGeneration;
|
||||
else if (*arg == "--rollback")
|
||||
} else if (*arg == "--rollback") {
|
||||
op = opRollback;
|
||||
else if (*arg == "--list-generations")
|
||||
} else if (*arg == "--list-generations") {
|
||||
op = opListGenerations;
|
||||
else if (*arg == "--delete-generations")
|
||||
} else if (*arg == "--delete-generations") {
|
||||
op = opDeleteGenerations;
|
||||
else if (*arg == "--dry-run") {
|
||||
} else if (*arg == "--dry-run") {
|
||||
LOG(INFO) << "(dry run; not doing anything)";
|
||||
globals.dryRun = true;
|
||||
} else if (*arg == "--system-filter")
|
||||
} else if (*arg == "--system-filter") {
|
||||
globals.instSource.systemFilter = getArg(*arg, arg, end);
|
||||
else if (*arg == "--prebuilt-only" || *arg == "-b")
|
||||
} else if (*arg == "--prebuilt-only" || *arg == "-b") {
|
||||
globals.prebuiltOnly = true;
|
||||
else if (*arg == "--repair")
|
||||
} else if (*arg == "--repair") {
|
||||
repair = Repair;
|
||||
else if (*arg != "" && arg->at(0) == '-') {
|
||||
} else if (*arg != "" && arg->at(0) == '-') {
|
||||
opFlags.push_back(*arg);
|
||||
/* FIXME: hacky */
|
||||
if (*arg == "--from-profile" ||
|
||||
(op == opQuery && (*arg == "--attr" || *arg == "-A")))
|
||||
(op == opQuery && (*arg == "--attr" || *arg == "-A"))) {
|
||||
opFlags.push_back(getArg(*arg, arg, end));
|
||||
} else
|
||||
}
|
||||
} else {
|
||||
opArgs.push_back(*arg);
|
||||
}
|
||||
|
||||
if (oldOp && oldOp != op)
|
||||
if (oldOp && oldOp != op) {
|
||||
throw UsageError("only one operation may be specified");
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
@ -1435,8 +1504,9 @@ static int _main(int argc, char** argv) {
|
|||
std::shared_ptr<EvalState>(new EvalState(myArgs.searchPath, store));
|
||||
globals.state->repair = repair;
|
||||
|
||||
if (file != "")
|
||||
if (file != "") {
|
||||
globals.instSource.nixExprPath = lookupFileArg(*globals.state, file);
|
||||
}
|
||||
|
||||
globals.instSource.autoArgs = myArgs.getAutoArgs(*globals.state);
|
||||
|
||||
|
|
6
third_party/nix/src/nix-env/user-env.cc
vendored
6
third_party/nix/src/nix-env/user-env.cc
vendored
|
@ -30,10 +30,11 @@ bool createUserEnv(EvalState& state, DrvInfos& elems, const Path& profile,
|
|||
/* Build the components in the user environment, if they don't
|
||||
exist already. */
|
||||
PathSet drvsToBuild;
|
||||
for (auto& i : elems)
|
||||
for (auto& i : elems) {
|
||||
if (i.queryDrvPath() != "") {
|
||||
drvsToBuild.insert(i.queryDrvPath());
|
||||
}
|
||||
}
|
||||
|
||||
DLOG(INFO) << "building user environment dependencies";
|
||||
state.store->buildPaths(drvsToBuild, state.repair ? bmRepair : bmNormal);
|
||||
|
@ -60,8 +61,9 @@ bool createUserEnv(EvalState& state, DrvInfos& elems, const Path& profile,
|
|||
mkString(*state.allocAttr(v, state.sSystem), system);
|
||||
}
|
||||
mkString(*state.allocAttr(v, state.sOutPath), i.queryOutPath());
|
||||
if (drvPath != "")
|
||||
if (drvPath != "") {
|
||||
mkString(*state.allocAttr(v, state.sDrvPath), i.queryDrvPath());
|
||||
}
|
||||
|
||||
// Copy each output meant for installation.
|
||||
DrvInfo::Outputs outputs = i.queryOutputs(true);
|
||||
|
|
|
@ -40,15 +40,16 @@ void processExpr(EvalState& state, const Strings& attrPaths, bool parseOnly,
|
|||
PathSet context;
|
||||
if (evalOnly) {
|
||||
Value vRes;
|
||||
if (autoArgs.empty())
|
||||
if (autoArgs.empty()) {
|
||||
vRes = v;
|
||||
else
|
||||
} else {
|
||||
state.autoCallFunction(autoArgs, v, vRes);
|
||||
if (output == okXML)
|
||||
}
|
||||
if (output == okXML) {
|
||||
printValueAsXML(state, strict, location, vRes, std::cout, context);
|
||||
else if (output == okJSON)
|
||||
} else if (output == okJSON) {
|
||||
printValueAsJSON(state, strict, vRes, std::cout, context);
|
||||
else {
|
||||
} else {
|
||||
if (strict) {
|
||||
state.forceValueDeep(vRes);
|
||||
}
|
||||
|
@ -62,21 +63,23 @@ void processExpr(EvalState& state, const Strings& attrPaths, bool parseOnly,
|
|||
|
||||
/* What output do we want? */
|
||||
string outputName = i.queryOutputName();
|
||||
if (outputName == "")
|
||||
if (outputName == "") {
|
||||
throw Error(
|
||||
format("derivation '%1%' lacks an 'outputName' attribute ") %
|
||||
drvPath);
|
||||
}
|
||||
|
||||
if (gcRoot == "")
|
||||
if (gcRoot == "") {
|
||||
printGCWarning();
|
||||
else {
|
||||
} else {
|
||||
Path rootName = indirectRoot ? absPath(gcRoot) : gcRoot;
|
||||
if (++rootNr > 1) {
|
||||
rootName += "-" + std::to_string(rootNr);
|
||||
}
|
||||
auto store2 = state.store.dynamic_pointer_cast<LocalFSStore>();
|
||||
if (store2)
|
||||
if (store2) {
|
||||
drvPath = store2->addPermRoot(drvPath, rootName, indirectRoot);
|
||||
}
|
||||
}
|
||||
std::cout << format("%1%%2%\n") % drvPath %
|
||||
(outputName != "out" ? "!" + outputName : "");
|
||||
|
@ -106,44 +109,45 @@ static int _main(int argc, char** argv) {
|
|||
|
||||
MyArgs myArgs(baseNameOf(argv[0]),
|
||||
[&](Strings::iterator& arg, const Strings::iterator& end) {
|
||||
if (*arg == "--help")
|
||||
if (*arg == "--help") {
|
||||
showManPage("nix-instantiate");
|
||||
else if (*arg == "--version")
|
||||
} else if (*arg == "--version") {
|
||||
printVersion("nix-instantiate");
|
||||
else if (*arg == "-")
|
||||
} else if (*arg == "-") {
|
||||
readStdin = true;
|
||||
else if (*arg == "--expr" || *arg == "-E")
|
||||
} else if (*arg == "--expr" || *arg == "-E") {
|
||||
fromArgs = true;
|
||||
else if (*arg == "--eval" || *arg == "--eval-only")
|
||||
} else if (*arg == "--eval" || *arg == "--eval-only") {
|
||||
evalOnly = true;
|
||||
else if (*arg == "--read-write-mode")
|
||||
} else if (*arg == "--read-write-mode") {
|
||||
wantsReadWrite = true;
|
||||
else if (*arg == "--parse" || *arg == "--parse-only")
|
||||
} else if (*arg == "--parse" || *arg == "--parse-only") {
|
||||
parseOnly = evalOnly = true;
|
||||
else if (*arg == "--find-file")
|
||||
} else if (*arg == "--find-file") {
|
||||
findFile = true;
|
||||
else if (*arg == "--attr" || *arg == "-A")
|
||||
} else if (*arg == "--attr" || *arg == "-A") {
|
||||
attrPaths.push_back(getArg(*arg, arg, end));
|
||||
else if (*arg == "--add-root")
|
||||
} else if (*arg == "--add-root") {
|
||||
gcRoot = getArg(*arg, arg, end);
|
||||
else if (*arg == "--indirect")
|
||||
} else if (*arg == "--indirect") {
|
||||
indirectRoot = true;
|
||||
else if (*arg == "--xml")
|
||||
} else if (*arg == "--xml") {
|
||||
outputKind = okXML;
|
||||
else if (*arg == "--json")
|
||||
} else if (*arg == "--json") {
|
||||
outputKind = okJSON;
|
||||
else if (*arg == "--no-location")
|
||||
} else if (*arg == "--no-location") {
|
||||
xmlOutputSourceLocation = false;
|
||||
else if (*arg == "--strict")
|
||||
} else if (*arg == "--strict") {
|
||||
strict = true;
|
||||
else if (*arg == "--repair")
|
||||
} else if (*arg == "--repair") {
|
||||
repair = Repair;
|
||||
else if (*arg == "--dry-run")
|
||||
} else if (*arg == "--dry-run") {
|
||||
settings.readOnlyMode = true;
|
||||
else if (*arg != "" && arg->at(0) == '-')
|
||||
} else if (*arg != "" && arg->at(0) == '-') {
|
||||
return false;
|
||||
else
|
||||
} else {
|
||||
files.push_back(*arg);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
|
|
|
@ -40,12 +40,14 @@ string resolveMirrorUri(EvalState& state, string uri) {
|
|||
state.forceAttrs(vMirrors);
|
||||
|
||||
auto mirrorList = vMirrors.attrs->find(state.symbols.create(mirrorName));
|
||||
if (mirrorList == vMirrors.attrs->end())
|
||||
if (mirrorList == vMirrors.attrs->end()) {
|
||||
throw Error(format("unknown mirror name '%1%'") % mirrorName);
|
||||
}
|
||||
state.forceList(*mirrorList->value);
|
||||
|
||||
if (mirrorList->value->listSize() < 1)
|
||||
if (mirrorList->value->listSize() < 1) {
|
||||
throw Error(format("mirror URI '%1%' did not expand to anything") % uri);
|
||||
}
|
||||
|
||||
string mirror = state.forceString(*mirrorList->value->listElems()[0]);
|
||||
return mirror + (hasSuffix(mirror, "/") ? "" : "/") + string(s, p + 1);
|
||||
|
@ -67,28 +69,30 @@ static int _main(int argc, char** argv) {
|
|||
|
||||
MyArgs myArgs(baseNameOf(argv[0]),
|
||||
[&](Strings::iterator& arg, const Strings::iterator& end) {
|
||||
if (*arg == "--help")
|
||||
if (*arg == "--help") {
|
||||
showManPage("nix-prefetch-url");
|
||||
else if (*arg == "--version")
|
||||
} else if (*arg == "--version") {
|
||||
printVersion("nix-prefetch-url");
|
||||
else if (*arg == "--type") {
|
||||
} else if (*arg == "--type") {
|
||||
string s = getArg(*arg, arg, end);
|
||||
ht = parseHashType(s);
|
||||
if (ht == htUnknown)
|
||||
if (ht == htUnknown) {
|
||||
throw UsageError(format("unknown hash type '%1%'") % s);
|
||||
} else if (*arg == "--print-path")
|
||||
}
|
||||
} else if (*arg == "--print-path") {
|
||||
printPath = true;
|
||||
else if (*arg == "--attr" || *arg == "-A") {
|
||||
} else if (*arg == "--attr" || *arg == "-A") {
|
||||
fromExpr = true;
|
||||
attrPath = getArg(*arg, arg, end);
|
||||
} else if (*arg == "--unpack")
|
||||
} else if (*arg == "--unpack") {
|
||||
unpack = true;
|
||||
else if (*arg == "--name")
|
||||
} else if (*arg == "--name") {
|
||||
name = getArg(*arg, arg, end);
|
||||
else if (*arg != "" && arg->at(0) == '-')
|
||||
} else if (*arg != "" && arg->at(0) == '-') {
|
||||
return false;
|
||||
else
|
||||
} else {
|
||||
args.push_back(*arg);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
|
@ -123,8 +127,9 @@ static int _main(int argc, char** argv) {
|
|||
|
||||
/* Extract the URI. */
|
||||
auto attr = v.attrs->find(state->symbols.create("urls"));
|
||||
if (attr == v.attrs->end())
|
||||
if (attr == v.attrs->end()) {
|
||||
throw Error("attribute set does not contain a 'urls' attribute");
|
||||
}
|
||||
state->forceList(*attr->value);
|
||||
if (attr->value->listSize() < 1) {
|
||||
throw Error("'urls' list is empty");
|
||||
|
@ -133,10 +138,11 @@ static int _main(int argc, char** argv) {
|
|||
|
||||
/* Extract the hash mode. */
|
||||
attr = v.attrs->find(state->symbols.create("outputHashMode"));
|
||||
if (attr == v.attrs->end())
|
||||
if (attr == v.attrs->end()) {
|
||||
LOG(WARNING) << "this does not look like a fetchurl call";
|
||||
else
|
||||
} else {
|
||||
unpack = state->forceString(*attr->value) == "recursive";
|
||||
}
|
||||
|
||||
/* Extract the name. */
|
||||
if (name.empty()) {
|
||||
|
@ -151,8 +157,9 @@ static int _main(int argc, char** argv) {
|
|||
if (name.empty()) {
|
||||
name = baseNameOf(uri);
|
||||
}
|
||||
if (name.empty())
|
||||
if (name.empty()) {
|
||||
throw Error(format("cannot figure out file name for '%1%'") % uri);
|
||||
}
|
||||
|
||||
/* If an expected hash is given, the file may already exist in
|
||||
the store. */
|
||||
|
@ -161,10 +168,11 @@ static int _main(int argc, char** argv) {
|
|||
if (args.size() == 2) {
|
||||
expectedHash = Hash(args[1], ht);
|
||||
storePath = store->makeFixedOutputPath(unpack, expectedHash, name);
|
||||
if (store->isValidPath(storePath))
|
||||
if (store->isValidPath(storePath)) {
|
||||
hash = expectedHash;
|
||||
else
|
||||
} else {
|
||||
storePath.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (storePath.empty()) {
|
||||
|
@ -193,27 +201,30 @@ static int _main(int argc, char** argv) {
|
|||
LOG(INFO) << "unpacking...";
|
||||
Path unpacked = (Path)tmpDir + "/unpacked";
|
||||
createDirs(unpacked);
|
||||
if (hasSuffix(baseNameOf(uri), ".zip"))
|
||||
if (hasSuffix(baseNameOf(uri), ".zip")) {
|
||||
runProgram("unzip", true, {"-qq", tmpFile, "-d", unpacked});
|
||||
else
|
||||
} else {
|
||||
// FIXME: this requires GNU tar for decompression.
|
||||
runProgram("tar", true, {"xf", tmpFile, "-C", unpacked});
|
||||
}
|
||||
|
||||
/* If the archive unpacks to a single file/directory, then use
|
||||
that as the top-level. */
|
||||
auto entries = readDirectory(unpacked);
|
||||
if (entries.size() == 1)
|
||||
if (entries.size() == 1) {
|
||||
tmpFile = unpacked + "/" + entries[0].name;
|
||||
else
|
||||
} else {
|
||||
tmpFile = unpacked;
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: inefficient; addToStore() will also hash
|
||||
this. */
|
||||
hash = unpack ? hashPath(ht, tmpFile).first : hashFile(ht, tmpFile);
|
||||
|
||||
if (expectedHash != Hash(ht) && expectedHash != hash)
|
||||
if (expectedHash != Hash(ht) && expectedHash != hash) {
|
||||
throw Error(format("hash mismatch for '%1%'") % uri);
|
||||
}
|
||||
|
||||
/* Copy the file to the Nix store. FIXME: if RemoteStore
|
||||
implemented addToStoreFromDump() and downloadFile()
|
||||
|
|
418
third_party/nix/src/nix-store/nix-store.cc
vendored
418
third_party/nix/src/nix-store/nix-store.cc
vendored
|
@ -38,8 +38,9 @@ static std::shared_ptr<Store> store;
|
|||
|
||||
ref<LocalStore> ensureLocalStore() {
|
||||
auto store2 = std::dynamic_pointer_cast<LocalStore>(store);
|
||||
if (!store2)
|
||||
if (!store2) {
|
||||
throw Error("you don't have sufficient rights to use this command");
|
||||
}
|
||||
return ref<LocalStore>(store2);
|
||||
}
|
||||
|
||||
|
@ -48,8 +49,9 @@ static Path useDeriver(Path path) {
|
|||
return path;
|
||||
}
|
||||
Path drvPath = store->queryPathInfo(path)->deriver;
|
||||
if (drvPath == "")
|
||||
if (drvPath == "") {
|
||||
throw Error(format("deriver of path '%1%' is not known") % path);
|
||||
}
|
||||
return drvPath;
|
||||
}
|
||||
|
||||
|
@ -67,23 +69,25 @@ static PathSet realisePath(Path path, bool build = true) {
|
|||
Derivation drv = store->derivationFromPath(p.first);
|
||||
rootNr++;
|
||||
|
||||
if (p.second.empty())
|
||||
if (p.second.empty()) {
|
||||
for (auto& i : drv.outputs) {
|
||||
p.second.insert(i.first);
|
||||
}
|
||||
}
|
||||
|
||||
PathSet outputs;
|
||||
for (auto& j : p.second) {
|
||||
DerivationOutputs::iterator i = drv.outputs.find(j);
|
||||
if (i == drv.outputs.end())
|
||||
if (i == drv.outputs.end()) {
|
||||
throw Error(
|
||||
format("derivation '%1%' does not have an output named '%2%'") %
|
||||
p.first % j);
|
||||
}
|
||||
Path outPath = i->second.path;
|
||||
if (store2) {
|
||||
if (gcRoot == "")
|
||||
if (gcRoot == "") {
|
||||
printGCWarning();
|
||||
else {
|
||||
} else {
|
||||
Path rootName = gcRoot;
|
||||
if (rootNr > 1) {
|
||||
rootName += "-" + std::to_string(rootNr);
|
||||
|
@ -100,15 +104,16 @@ static PathSet realisePath(Path path, bool build = true) {
|
|||
}
|
||||
|
||||
else {
|
||||
if (build)
|
||||
if (build) {
|
||||
store->ensurePath(path);
|
||||
else if (!store->isValidPath(path))
|
||||
} else if (!store->isValidPath(path)) {
|
||||
throw Error(format("path '%1%' does not exist and cannot be created") %
|
||||
path);
|
||||
}
|
||||
if (store2) {
|
||||
if (gcRoot == "")
|
||||
if (gcRoot == "") {
|
||||
printGCWarning();
|
||||
else {
|
||||
} else {
|
||||
Path rootName = gcRoot;
|
||||
rootNr++;
|
||||
if (rootNr > 1) {
|
||||
|
@ -127,17 +132,19 @@ static void opRealise(Strings opFlags, Strings opArgs) {
|
|||
BuildMode buildMode = bmNormal;
|
||||
bool ignoreUnknown = false;
|
||||
|
||||
for (auto& i : opFlags)
|
||||
if (i == "--dry-run")
|
||||
for (auto& i : opFlags) {
|
||||
if (i == "--dry-run") {
|
||||
dryRun = true;
|
||||
else if (i == "--repair")
|
||||
} else if (i == "--repair") {
|
||||
buildMode = bmRepair;
|
||||
else if (i == "--check")
|
||||
} else if (i == "--check") {
|
||||
buildMode = bmCheck;
|
||||
else if (i == "--ignore-unknown")
|
||||
} else if (i == "--ignore-unknown") {
|
||||
ignoreUnknown = true;
|
||||
else
|
||||
} else {
|
||||
throw UsageError(format("unknown flag '%1%'") % i);
|
||||
}
|
||||
}
|
||||
|
||||
Paths paths;
|
||||
for (auto& i : opArgs) {
|
||||
|
@ -153,17 +160,19 @@ static void opRealise(Strings opFlags, Strings opArgs) {
|
|||
|
||||
if (ignoreUnknown) {
|
||||
Paths paths2;
|
||||
for (auto& i : paths)
|
||||
for (auto& i : paths) {
|
||||
if (unknown.find(i) == unknown.end()) {
|
||||
paths2.push_back(i);
|
||||
}
|
||||
}
|
||||
paths = paths2;
|
||||
unknown = PathSet();
|
||||
}
|
||||
|
||||
if (settings.printMissing)
|
||||
if (settings.printMissing) {
|
||||
printMissing(ref<Store>(store), willBuild, willSubstitute, unknown,
|
||||
downloadSize, narSize);
|
||||
}
|
||||
|
||||
if (dryRun) {
|
||||
return;
|
||||
|
@ -172,14 +181,16 @@ static void opRealise(Strings opFlags, Strings opArgs) {
|
|||
/* Build all paths at the same time to exploit parallelism. */
|
||||
store->buildPaths(PathSet(paths.begin(), paths.end()), buildMode);
|
||||
|
||||
if (!ignoreUnknown)
|
||||
if (!ignoreUnknown) {
|
||||
for (auto& i : paths) {
|
||||
PathSet paths = realisePath(i, false);
|
||||
if (!noOutput)
|
||||
if (!noOutput) {
|
||||
for (auto& j : paths) {
|
||||
cout << format("%1%\n") % j;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Add files to the Nix store and print the resulting paths. */
|
||||
|
@ -188,8 +199,9 @@ static void opAdd(Strings opFlags, Strings opArgs) {
|
|||
throw UsageError("unknown flag");
|
||||
}
|
||||
|
||||
for (auto& i : opArgs)
|
||||
for (auto& i : opArgs) {
|
||||
cout << format("%1%\n") % store->addToStore(baseNameOf(i), i);
|
||||
}
|
||||
}
|
||||
|
||||
/* Preload the output of a fixed-output derivation into the Nix
|
||||
|
@ -197,11 +209,13 @@ static void opAdd(Strings opFlags, Strings opArgs) {
|
|||
static void opAddFixed(Strings opFlags, Strings opArgs) {
|
||||
bool recursive = false;
|
||||
|
||||
for (auto& i : opFlags)
|
||||
if (i == "--recursive")
|
||||
for (auto& i : opFlags) {
|
||||
if (i == "--recursive") {
|
||||
recursive = true;
|
||||
else
|
||||
} else {
|
||||
throw UsageError(format("unknown flag '%1%'") % i);
|
||||
}
|
||||
}
|
||||
|
||||
if (opArgs.empty()) {
|
||||
throw UsageError("first argument must be hash algorithm");
|
||||
|
@ -210,23 +224,27 @@ static void opAddFixed(Strings opFlags, Strings opArgs) {
|
|||
HashType hashAlgo = parseHashType(opArgs.front());
|
||||
opArgs.pop_front();
|
||||
|
||||
for (auto& i : opArgs)
|
||||
for (auto& i : opArgs) {
|
||||
cout << format("%1%\n") %
|
||||
store->addToStore(baseNameOf(i), i, recursive, hashAlgo);
|
||||
}
|
||||
}
|
||||
|
||||
/* Hack to support caching in `nix-prefetch-url'. */
|
||||
static void opPrintFixedPath(Strings opFlags, Strings opArgs) {
|
||||
bool recursive = false;
|
||||
|
||||
for (auto i : opFlags)
|
||||
if (i == "--recursive")
|
||||
for (auto i : opFlags) {
|
||||
if (i == "--recursive") {
|
||||
recursive = true;
|
||||
else
|
||||
} else {
|
||||
throw UsageError(format("unknown flag '%1%'") % i);
|
||||
}
|
||||
}
|
||||
|
||||
if (opArgs.size() != 3)
|
||||
if (opArgs.size() != 3) {
|
||||
throw UsageError(format("'--print-fixed-path' requires three arguments"));
|
||||
}
|
||||
|
||||
Strings::iterator i = opArgs.begin();
|
||||
HashType hashAlgo = parseHashType(*i++);
|
||||
|
@ -249,8 +267,9 @@ static PathSet maybeUseOutputs(const Path& storePath, bool useOutput,
|
|||
outputs.insert(i.second.path);
|
||||
}
|
||||
return outputs;
|
||||
} else
|
||||
} else {
|
||||
return {storePath};
|
||||
}
|
||||
}
|
||||
|
||||
/* Some code to print a tree representation of a derivation dependency
|
||||
|
@ -316,50 +335,52 @@ static void opQuery(Strings opFlags, Strings opArgs) {
|
|||
|
||||
for (auto& i : opFlags) {
|
||||
QueryType prev = query;
|
||||
if (i == "--outputs")
|
||||
if (i == "--outputs") {
|
||||
query = qOutputs;
|
||||
else if (i == "--requisites" || i == "-R")
|
||||
} else if (i == "--requisites" || i == "-R") {
|
||||
query = qRequisites;
|
||||
else if (i == "--references")
|
||||
} else if (i == "--references") {
|
||||
query = qReferences;
|
||||
else if (i == "--referrers" || i == "--referers")
|
||||
} else if (i == "--referrers" || i == "--referers") {
|
||||
query = qReferrers;
|
||||
else if (i == "--referrers-closure" || i == "--referers-closure")
|
||||
} else if (i == "--referrers-closure" || i == "--referers-closure") {
|
||||
query = qReferrersClosure;
|
||||
else if (i == "--deriver" || i == "-d")
|
||||
} else if (i == "--deriver" || i == "-d") {
|
||||
query = qDeriver;
|
||||
else if (i == "--binding" || i == "-b") {
|
||||
} else if (i == "--binding" || i == "-b") {
|
||||
if (opArgs.size() == 0) {
|
||||
throw UsageError("expected binding name");
|
||||
}
|
||||
bindingName = opArgs.front();
|
||||
opArgs.pop_front();
|
||||
query = qBinding;
|
||||
} else if (i == "--hash")
|
||||
} else if (i == "--hash") {
|
||||
query = qHash;
|
||||
else if (i == "--size")
|
||||
} else if (i == "--size") {
|
||||
query = qSize;
|
||||
else if (i == "--tree")
|
||||
} else if (i == "--tree") {
|
||||
query = qTree;
|
||||
else if (i == "--graph")
|
||||
} else if (i == "--graph") {
|
||||
query = qGraph;
|
||||
else if (i == "--graphml")
|
||||
} else if (i == "--graphml") {
|
||||
query = qGraphML;
|
||||
else if (i == "--resolve")
|
||||
} else if (i == "--resolve") {
|
||||
query = qResolve;
|
||||
else if (i == "--roots")
|
||||
} else if (i == "--roots") {
|
||||
query = qRoots;
|
||||
else if (i == "--use-output" || i == "-u")
|
||||
} else if (i == "--use-output" || i == "-u") {
|
||||
useOutput = true;
|
||||
else if (i == "--force-realise" || i == "--force-realize" || i == "-f")
|
||||
} else if (i == "--force-realise" || i == "--force-realize" || i == "-f") {
|
||||
forceRealise = true;
|
||||
else if (i == "--include-outputs")
|
||||
} else if (i == "--include-outputs") {
|
||||
includeOutputs = true;
|
||||
else
|
||||
} else {
|
||||
throw UsageError(format("unknown flag '%1%'") % i);
|
||||
if (prev != qDefault && prev != query)
|
||||
}
|
||||
if (prev != qDefault && prev != query) {
|
||||
throw UsageError(format("query type '%1%' conflicts with earlier flag") %
|
||||
i);
|
||||
}
|
||||
}
|
||||
|
||||
if (query == qDefault) {
|
||||
|
@ -392,21 +413,24 @@ static void opQuery(Strings opFlags, Strings opArgs) {
|
|||
PathSet ps = maybeUseOutputs(store->followLinksToStorePath(i),
|
||||
useOutput, forceRealise);
|
||||
for (auto& j : ps) {
|
||||
if (query == qRequisites)
|
||||
if (query == qRequisites) {
|
||||
store->computeFSClosure(j, paths, false, includeOutputs);
|
||||
else if (query == qReferences) {
|
||||
} else if (query == qReferences) {
|
||||
for (auto& p : store->queryPathInfo(j)->references) {
|
||||
paths.insert(p);
|
||||
}
|
||||
} else if (query == qReferrers)
|
||||
} else if (query == qReferrers) {
|
||||
store->queryReferrers(j, paths);
|
||||
else if (query == qReferrersClosure)
|
||||
} else if (query == qReferrersClosure) {
|
||||
store->computeFSClosure(j, paths, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
Paths sorted = store->topoSortPaths(paths);
|
||||
for (Paths::reverse_iterator i = sorted.rbegin(); i != sorted.rend(); ++i)
|
||||
for (Paths::reverse_iterator i = sorted.rbegin(); i != sorted.rend();
|
||||
++i) {
|
||||
cout << format("%s\n") % *i;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -423,11 +447,12 @@ static void opQuery(Strings opFlags, Strings opArgs) {
|
|||
Path path = useDeriver(store->followLinksToStorePath(i));
|
||||
Derivation drv = store->derivationFromPath(path);
|
||||
StringPairs::iterator j = drv.env.find(bindingName);
|
||||
if (j == drv.env.end())
|
||||
if (j == drv.env.end()) {
|
||||
throw Error(
|
||||
format(
|
||||
"derivation '%1%' has no environment binding named '%2%'") %
|
||||
path % bindingName);
|
||||
}
|
||||
cout << format("%1%\n") % j->second;
|
||||
}
|
||||
break;
|
||||
|
@ -442,16 +467,18 @@ static void opQuery(Strings opFlags, Strings opArgs) {
|
|||
if (query == qHash) {
|
||||
assert(info->narHash.type == htSHA256);
|
||||
cout << fmt("%s\n", info->narHash.to_string(Base32));
|
||||
} else if (query == qSize)
|
||||
} else if (query == qSize) {
|
||||
cout << fmt("%d\n", info->narSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case qTree: {
|
||||
PathSet done;
|
||||
for (auto& i : opArgs)
|
||||
for (auto& i : opArgs) {
|
||||
printTree(store->followLinksToStorePath(i), "", "", done);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -478,8 +505,9 @@ static void opQuery(Strings opFlags, Strings opArgs) {
|
|||
}
|
||||
|
||||
case qResolve: {
|
||||
for (auto& i : opArgs)
|
||||
for (auto& i : opArgs) {
|
||||
cout << format("%1%\n") % store->followLinksToStorePath(i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -493,10 +521,13 @@ static void opQuery(Strings opFlags, Strings opArgs) {
|
|||
settings.gcKeepDerivations);
|
||||
}
|
||||
Roots roots = store->findRoots(false);
|
||||
for (auto& [target, links] : roots)
|
||||
if (referrers.find(target) != referrers.end())
|
||||
for (auto& link : links)
|
||||
for (auto& [target, links] : roots) {
|
||||
if (referrers.find(target) != referrers.end()) {
|
||||
for (auto& link : links) {
|
||||
cout << format("%1% -> %2%\n") % link % target;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -509,16 +540,18 @@ static void opPrintEnv(Strings opFlags, Strings opArgs) {
|
|||
if (!opFlags.empty()) {
|
||||
throw UsageError("unknown flag");
|
||||
}
|
||||
if (opArgs.size() != 1)
|
||||
if (opArgs.size() != 1) {
|
||||
throw UsageError("'--print-env' requires one derivation store path");
|
||||
}
|
||||
|
||||
Path drvPath = opArgs.front();
|
||||
Derivation drv = store->derivationFromPath(drvPath);
|
||||
|
||||
/* Print each environment variable in the derivation in a format
|
||||
that can be sourced by the shell. */
|
||||
for (auto& i : drv.env)
|
||||
for (auto& i : drv.env) {
|
||||
cout << format("export %1%; %1%=%2%\n") % i.first % shellEscape(i.second);
|
||||
}
|
||||
|
||||
/* Also output the arguments. This doesn't preserve whitespace in
|
||||
arguments. */
|
||||
|
@ -544,8 +577,9 @@ static void opReadLog(Strings opFlags, Strings opArgs) {
|
|||
for (auto& i : opArgs) {
|
||||
auto path = store->followLinksToStorePath(i);
|
||||
auto log = store->getBuildLog(path);
|
||||
if (!log)
|
||||
if (!log) {
|
||||
throw Error("build log of derivation '%s' is not available", path);
|
||||
}
|
||||
std::cout << *log;
|
||||
}
|
||||
}
|
||||
|
@ -558,12 +592,14 @@ static void opDumpDB(Strings opFlags, Strings opArgs) {
|
|||
for (auto& i : opArgs) {
|
||||
i = store->followLinksToStorePath(i);
|
||||
}
|
||||
for (auto& i : opArgs)
|
||||
for (auto& i : opArgs) {
|
||||
cout << store->makeValidityRegistration({i}, true, true);
|
||||
}
|
||||
} else {
|
||||
PathSet validPaths = store->queryAllValidPaths();
|
||||
for (auto& i : validPaths)
|
||||
for (auto& i : validPaths) {
|
||||
cout << store->makeValidityRegistration({i}, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -607,13 +643,15 @@ static void opRegisterValidity(Strings opFlags, Strings opArgs) {
|
|||
bool reregister = false; // !!! maybe this should be the default
|
||||
bool hashGiven = false;
|
||||
|
||||
for (auto& i : opFlags)
|
||||
if (i == "--reregister")
|
||||
for (auto& i : opFlags) {
|
||||
if (i == "--reregister") {
|
||||
reregister = true;
|
||||
else if (i == "--hash-given")
|
||||
} else if (i == "--hash-given") {
|
||||
hashGiven = true;
|
||||
else
|
||||
} else {
|
||||
throw UsageError(format("unknown flag '%1%'") % i);
|
||||
}
|
||||
}
|
||||
|
||||
if (!opArgs.empty()) {
|
||||
throw UsageError("no arguments expected");
|
||||
|
@ -625,19 +663,22 @@ static void opRegisterValidity(Strings opFlags, Strings opArgs) {
|
|||
static void opCheckValidity(Strings opFlags, Strings opArgs) {
|
||||
bool printInvalid = false;
|
||||
|
||||
for (auto& i : opFlags)
|
||||
if (i == "--print-invalid")
|
||||
for (auto& i : opFlags) {
|
||||
if (i == "--print-invalid") {
|
||||
printInvalid = true;
|
||||
else
|
||||
} else {
|
||||
throw UsageError(format("unknown flag '%1%'") % i);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& i : opArgs) {
|
||||
Path path = store->followLinksToStorePath(i);
|
||||
if (!store->isValidPath(path)) {
|
||||
if (printInvalid)
|
||||
if (printInvalid) {
|
||||
cout << format("%1%\n") % path;
|
||||
else
|
||||
} else {
|
||||
throw Error(format("path '%1%' is not valid") % path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -650,20 +691,22 @@ static void opGC(Strings opFlags, Strings opArgs) {
|
|||
GCResults results;
|
||||
|
||||
/* Do what? */
|
||||
for (auto i = opFlags.begin(); i != opFlags.end(); ++i)
|
||||
if (*i == "--print-roots")
|
||||
for (auto i = opFlags.begin(); i != opFlags.end(); ++i) {
|
||||
if (*i == "--print-roots") {
|
||||
printRoots = true;
|
||||
else if (*i == "--print-live")
|
||||
} else if (*i == "--print-live") {
|
||||
options.action = GCOptions::gcReturnLive;
|
||||
else if (*i == "--print-dead")
|
||||
} else if (*i == "--print-dead") {
|
||||
options.action = GCOptions::gcReturnDead;
|
||||
else if (*i == "--delete")
|
||||
} else if (*i == "--delete") {
|
||||
options.action = GCOptions::gcDeleteDead;
|
||||
else if (*i == "--max-freed") {
|
||||
} else if (*i == "--max-freed") {
|
||||
long long maxFreed = getIntArg<long long>(*i, i, opFlags.end(), true);
|
||||
options.maxFreed = maxFreed >= 0 ? maxFreed : 0;
|
||||
} else
|
||||
} else {
|
||||
throw UsageError(format("bad sub-operation '%1%' in GC") % *i);
|
||||
}
|
||||
}
|
||||
|
||||
if (!opArgs.empty()) {
|
||||
throw UsageError("no arguments expected");
|
||||
|
@ -673,22 +716,25 @@ static void opGC(Strings opFlags, Strings opArgs) {
|
|||
Roots roots = store->findRoots(false);
|
||||
std::set<std::pair<Path, Path>> roots2;
|
||||
// Transpose and sort the roots.
|
||||
for (auto& [target, links] : roots)
|
||||
for (auto& [target, links] : roots) {
|
||||
for (auto& link : links) {
|
||||
roots2.emplace(link, target);
|
||||
}
|
||||
for (auto& [link, target] : roots2)
|
||||
}
|
||||
for (auto& [link, target] : roots2) {
|
||||
std::cout << link << " -> " << target << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
PrintFreed freed(options.action == GCOptions::gcDeleteDead, results);
|
||||
store->collectGarbage(options, results);
|
||||
|
||||
if (options.action != GCOptions::gcDeleteDead)
|
||||
if (options.action != GCOptions::gcDeleteDead) {
|
||||
for (auto& i : results.paths) {
|
||||
cout << i << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -699,14 +745,17 @@ static void opDelete(Strings opFlags, Strings opArgs) {
|
|||
GCOptions options;
|
||||
options.action = GCOptions::gcDeleteSpecific;
|
||||
|
||||
for (auto& i : opFlags)
|
||||
if (i == "--ignore-liveness")
|
||||
for (auto& i : opFlags) {
|
||||
if (i == "--ignore-liveness") {
|
||||
options.ignoreLiveness = true;
|
||||
else
|
||||
} else {
|
||||
throw UsageError(format("unknown flag '%1%'") % i);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& i : opArgs)
|
||||
for (auto& i : opArgs) {
|
||||
options.pathsToDelete.insert(store->followLinksToStorePath(i));
|
||||
}
|
||||
|
||||
GCResults results;
|
||||
PrintFreed freed(true, results);
|
||||
|
@ -795,13 +844,15 @@ static void opVerify(Strings opFlags, Strings opArgs) {
|
|||
bool checkContents = false;
|
||||
RepairFlag repair = NoRepair;
|
||||
|
||||
for (auto& i : opFlags)
|
||||
if (i == "--check-contents")
|
||||
for (auto& i : opFlags) {
|
||||
if (i == "--check-contents") {
|
||||
checkContents = true;
|
||||
else if (i == "--repair")
|
||||
} else if (i == "--repair") {
|
||||
repair = Repair;
|
||||
else
|
||||
} else {
|
||||
throw UsageError(format("unknown flag '%1%'") % i);
|
||||
}
|
||||
}
|
||||
|
||||
if (store->verifyStore(checkContents, repair)) {
|
||||
LOG(WARNING) << "not all errors were fixed";
|
||||
|
@ -851,8 +902,9 @@ static void opRepairPath(Strings opFlags, Strings opArgs) {
|
|||
/* Optimise the disk space usage of the Nix store by hard-linking
|
||||
files with the same contents. */
|
||||
static void opOptimise(Strings opFlags, Strings opArgs) {
|
||||
if (!opArgs.empty() || !opFlags.empty())
|
||||
if (!opArgs.empty() || !opFlags.empty()) {
|
||||
throw UsageError("no arguments expected");
|
||||
}
|
||||
|
||||
store->optimiseStore();
|
||||
}
|
||||
|
@ -860,11 +912,13 @@ static void opOptimise(Strings opFlags, Strings opArgs) {
|
|||
/* Serve the nix store in a way usable by a restricted ssh user. */
|
||||
static void opServe(Strings opFlags, Strings opArgs) {
|
||||
bool writeAllowed = false;
|
||||
for (auto& i : opFlags)
|
||||
if (i == "--write")
|
||||
for (auto& i : opFlags) {
|
||||
if (i == "--write") {
|
||||
writeAllowed = true;
|
||||
else
|
||||
} else {
|
||||
throw UsageError(format("unknown flag '%1%'") % i);
|
||||
}
|
||||
}
|
||||
|
||||
if (!opArgs.empty()) {
|
||||
throw UsageError("no arguments expected");
|
||||
|
@ -889,8 +943,9 @@ static void opServe(Strings opFlags, Strings opArgs) {
|
|||
settings.useSubstitutes = false;
|
||||
settings.maxSilentTime = readInt(in);
|
||||
settings.buildTimeout = readInt(in);
|
||||
if (GET_PROTOCOL_MINOR(clientVersion) >= 2)
|
||||
if (GET_PROTOCOL_MINOR(clientVersion) >= 2) {
|
||||
settings.maxLogSize = readNum<unsigned long>(in);
|
||||
}
|
||||
if (GET_PROTOCOL_MINOR(clientVersion) >= 3) {
|
||||
settings.buildRepeat = readInt(in);
|
||||
settings.enforceDeterminism = readInt(in);
|
||||
|
@ -912,10 +967,11 @@ static void opServe(Strings opFlags, Strings opArgs) {
|
|||
bool lock = readInt(in);
|
||||
bool substitute = readInt(in);
|
||||
PathSet paths = readStorePaths<PathSet>(*store, in);
|
||||
if (lock && writeAllowed)
|
||||
if (lock && writeAllowed) {
|
||||
for (auto& path : paths) {
|
||||
store->addTempRoot(path);
|
||||
}
|
||||
}
|
||||
|
||||
/* If requested, substitute missing paths. This
|
||||
implements nix-copy-closure's --use-substitutes
|
||||
|
@ -923,21 +979,24 @@ static void opServe(Strings opFlags, Strings opArgs) {
|
|||
if (substitute && writeAllowed) {
|
||||
/* Filter out .drv files (we don't want to build anything). */
|
||||
PathSet paths2;
|
||||
for (auto& path : paths)
|
||||
for (auto& path : paths) {
|
||||
if (!isDerivation(path)) {
|
||||
paths2.insert(path);
|
||||
}
|
||||
}
|
||||
unsigned long long downloadSize, narSize;
|
||||
PathSet willBuild, willSubstitute, unknown;
|
||||
store->queryMissing(PathSet(paths2.begin(), paths2.end()), willBuild,
|
||||
willSubstitute, unknown, downloadSize, narSize);
|
||||
/* FIXME: should use ensurePath(), but it only
|
||||
does one path at a time. */
|
||||
if (!willSubstitute.empty()) try {
|
||||
if (!willSubstitute.empty()) {
|
||||
try {
|
||||
store->buildPaths(willSubstitute);
|
||||
} catch (Error& e) {
|
||||
LOG(WARNING) << e.msg();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out << store->queryValidPaths(paths);
|
||||
|
@ -954,9 +1013,10 @@ static void opServe(Strings opFlags, Strings opArgs) {
|
|||
// !!! Maybe we want compression?
|
||||
out << info->narSize // downloadSize
|
||||
<< info->narSize;
|
||||
if (GET_PROTOCOL_MINOR(clientVersion) >= 4)
|
||||
if (GET_PROTOCOL_MINOR(clientVersion) >= 4) {
|
||||
out << (info->narHash ? info->narHash.to_string() : "")
|
||||
<< info->ca << info->sigs;
|
||||
}
|
||||
} catch (InvalidPath&) {
|
||||
}
|
||||
}
|
||||
|
@ -1020,9 +1080,10 @@ static void opServe(Strings opFlags, Strings opArgs) {
|
|||
|
||||
out << status.status << status.errorMsg;
|
||||
|
||||
if (GET_PROTOCOL_MINOR(clientVersion) >= 3)
|
||||
if (GET_PROTOCOL_MINOR(clientVersion) >= 3) {
|
||||
out << status.timesBuilt << status.isNonDeterministic
|
||||
<< status.startTime << status.stopTime;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -1127,81 +1188,85 @@ static int _main(int argc, char** argv) {
|
|||
Strings opFlags, opArgs;
|
||||
Operation op = 0;
|
||||
|
||||
parseCmdLine(
|
||||
argc, argv, [&](Strings::iterator& arg, const Strings::iterator& end) {
|
||||
Operation oldOp = op;
|
||||
parseCmdLine(argc, argv,
|
||||
[&](Strings::iterator& arg, const Strings::iterator& end) {
|
||||
Operation oldOp = op;
|
||||
|
||||
if (*arg == "--help")
|
||||
showManPage("nix-store");
|
||||
else if (*arg == "--version")
|
||||
op = opVersion;
|
||||
else if (*arg == "--realise" || *arg == "--realize" || *arg == "-r")
|
||||
op = opRealise;
|
||||
else if (*arg == "--add" || *arg == "-A")
|
||||
op = opAdd;
|
||||
else if (*arg == "--add-fixed")
|
||||
op = opAddFixed;
|
||||
else if (*arg == "--print-fixed-path")
|
||||
op = opPrintFixedPath;
|
||||
else if (*arg == "--delete")
|
||||
op = opDelete;
|
||||
else if (*arg == "--query" || *arg == "-q")
|
||||
op = opQuery;
|
||||
else if (*arg == "--print-env")
|
||||
op = opPrintEnv;
|
||||
else if (*arg == "--read-log" || *arg == "-l")
|
||||
op = opReadLog;
|
||||
else if (*arg == "--dump-db")
|
||||
op = opDumpDB;
|
||||
else if (*arg == "--load-db")
|
||||
op = opLoadDB;
|
||||
else if (*arg == "--register-validity")
|
||||
op = opRegisterValidity;
|
||||
else if (*arg == "--check-validity")
|
||||
op = opCheckValidity;
|
||||
else if (*arg == "--gc")
|
||||
op = opGC;
|
||||
else if (*arg == "--dump")
|
||||
op = opDump;
|
||||
else if (*arg == "--restore")
|
||||
op = opRestore;
|
||||
else if (*arg == "--export")
|
||||
op = opExport;
|
||||
else if (*arg == "--import")
|
||||
op = opImport;
|
||||
else if (*arg == "--init")
|
||||
op = opInit;
|
||||
else if (*arg == "--verify")
|
||||
op = opVerify;
|
||||
else if (*arg == "--verify-path")
|
||||
op = opVerifyPath;
|
||||
else if (*arg == "--repair-path")
|
||||
op = opRepairPath;
|
||||
else if (*arg == "--optimise" || *arg == "--optimize")
|
||||
op = opOptimise;
|
||||
else if (*arg == "--serve")
|
||||
op = opServe;
|
||||
else if (*arg == "--generate-binary-cache-key")
|
||||
op = opGenerateBinaryCacheKey;
|
||||
else if (*arg == "--add-root")
|
||||
gcRoot = absPath(getArg(*arg, arg, end));
|
||||
else if (*arg == "--indirect")
|
||||
indirectRoot = true;
|
||||
else if (*arg == "--no-output")
|
||||
noOutput = true;
|
||||
else if (*arg != "" && arg->at(0) == '-') {
|
||||
opFlags.push_back(*arg);
|
||||
if (*arg == "--max-freed" || *arg == "--max-links" ||
|
||||
*arg == "--max-atime") /* !!! hack */
|
||||
opFlags.push_back(getArg(*arg, arg, end));
|
||||
} else
|
||||
opArgs.push_back(*arg);
|
||||
if (*arg == "--help") {
|
||||
showManPage("nix-store");
|
||||
} else if (*arg == "--version") {
|
||||
op = opVersion;
|
||||
} else if (*arg == "--realise" || *arg == "--realize" ||
|
||||
*arg == "-r") {
|
||||
op = opRealise;
|
||||
} else if (*arg == "--add" || *arg == "-A") {
|
||||
op = opAdd;
|
||||
} else if (*arg == "--add-fixed") {
|
||||
op = opAddFixed;
|
||||
} else if (*arg == "--print-fixed-path") {
|
||||
op = opPrintFixedPath;
|
||||
} else if (*arg == "--delete") {
|
||||
op = opDelete;
|
||||
} else if (*arg == "--query" || *arg == "-q") {
|
||||
op = opQuery;
|
||||
} else if (*arg == "--print-env") {
|
||||
op = opPrintEnv;
|
||||
} else if (*arg == "--read-log" || *arg == "-l") {
|
||||
op = opReadLog;
|
||||
} else if (*arg == "--dump-db") {
|
||||
op = opDumpDB;
|
||||
} else if (*arg == "--load-db") {
|
||||
op = opLoadDB;
|
||||
} else if (*arg == "--register-validity") {
|
||||
op = opRegisterValidity;
|
||||
} else if (*arg == "--check-validity") {
|
||||
op = opCheckValidity;
|
||||
} else if (*arg == "--gc") {
|
||||
op = opGC;
|
||||
} else if (*arg == "--dump") {
|
||||
op = opDump;
|
||||
} else if (*arg == "--restore") {
|
||||
op = opRestore;
|
||||
} else if (*arg == "--export") {
|
||||
op = opExport;
|
||||
} else if (*arg == "--import") {
|
||||
op = opImport;
|
||||
} else if (*arg == "--init") {
|
||||
op = opInit;
|
||||
} else if (*arg == "--verify") {
|
||||
op = opVerify;
|
||||
} else if (*arg == "--verify-path") {
|
||||
op = opVerifyPath;
|
||||
} else if (*arg == "--repair-path") {
|
||||
op = opRepairPath;
|
||||
} else if (*arg == "--optimise" || *arg == "--optimize") {
|
||||
op = opOptimise;
|
||||
} else if (*arg == "--serve") {
|
||||
op = opServe;
|
||||
} else if (*arg == "--generate-binary-cache-key") {
|
||||
op = opGenerateBinaryCacheKey;
|
||||
} else if (*arg == "--add-root") {
|
||||
gcRoot = absPath(getArg(*arg, arg, end));
|
||||
} else if (*arg == "--indirect") {
|
||||
indirectRoot = true;
|
||||
} else if (*arg == "--no-output") {
|
||||
noOutput = true;
|
||||
} else if (*arg != "" && arg->at(0) == '-') {
|
||||
opFlags.push_back(*arg);
|
||||
if (*arg == "--max-freed" || *arg == "--max-links" ||
|
||||
*arg == "--max-atime") { /* !!! hack */
|
||||
opFlags.push_back(getArg(*arg, arg, end));
|
||||
}
|
||||
} else {
|
||||
opArgs.push_back(*arg);
|
||||
}
|
||||
|
||||
if (oldOp && oldOp != op)
|
||||
throw UsageError("only one operation may be specified");
|
||||
if (oldOp && oldOp != op) {
|
||||
throw UsageError("only one operation may be specified");
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
return true;
|
||||
});
|
||||
|
||||
initPlugins();
|
||||
|
||||
|
@ -1209,8 +1274,9 @@ static int _main(int argc, char** argv) {
|
|||
throw UsageError("no operation specified");
|
||||
}
|
||||
|
||||
if (op != opDump && op != opRestore) /* !!! hack */
|
||||
if (op != opDump && op != opRestore) { /* !!! hack */
|
||||
store = openStore();
|
||||
}
|
||||
|
||||
op(opFlags, opArgs);
|
||||
|
||||
|
|
6
third_party/nix/src/nix/build.cc
vendored
6
third_party/nix/src/nix/build.cc
vendored
|
@ -47,8 +47,8 @@ struct CmdBuild : MixDryRun, InstallablesCommand {
|
|||
for (size_t i = 0; i < buildables.size(); ++i) {
|
||||
auto& b(buildables[i]);
|
||||
|
||||
if (outLink != "")
|
||||
for (auto& output : b.outputs)
|
||||
if (outLink != "") {
|
||||
for (auto& output : b.outputs) {
|
||||
if (auto store2 = store.dynamic_pointer_cast<LocalFSStore>()) {
|
||||
std::string symlink = outLink;
|
||||
if (i) {
|
||||
|
@ -59,6 +59,8 @@ struct CmdBuild : MixDryRun, InstallablesCommand {
|
|||
}
|
||||
store2->addPermRoot(output.second, absPath(symlink), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
6
third_party/nix/src/nix/cat.cc
vendored
6
third_party/nix/src/nix/cat.cc
vendored
|
@ -10,10 +10,12 @@ struct MixCat : virtual Args {
|
|||
|
||||
void cat(ref<FSAccessor> accessor) {
|
||||
auto st = accessor->stat(path);
|
||||
if (st.type == FSAccessor::Type::tMissing)
|
||||
if (st.type == FSAccessor::Type::tMissing) {
|
||||
throw Error(format("path '%1%' does not exist") % path);
|
||||
if (st.type != FSAccessor::Type::tRegular)
|
||||
}
|
||||
if (st.type != FSAccessor::Type::tRegular) {
|
||||
throw Error(format("path '%1%' is not a regular file") % path);
|
||||
}
|
||||
|
||||
std::cout << accessor->readFile(path);
|
||||
}
|
||||
|
|
32
third_party/nix/src/nix/command.cc
vendored
32
third_party/nix/src/nix/command.cc
vendored
|
@ -14,10 +14,11 @@ void Command::printHelp(const string& programName, std::ostream& out) {
|
|||
if (!exs.empty()) {
|
||||
out << "\n";
|
||||
out << "Examples:\n";
|
||||
for (auto& ex : exs)
|
||||
for (auto& ex : exs) {
|
||||
out << "\n"
|
||||
<< " " << ex.description << "\n" // FIXME: wrap
|
||||
<< " $ " << ex.command << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,8 +27,9 @@ MultiCommand::MultiCommand(const Commands& _commands) : commands(_commands) {
|
|||
"command", 1, true, [=](std::vector<std::string> ss) {
|
||||
assert(!command);
|
||||
auto i = commands.find(ss[0]);
|
||||
if (i == commands.end())
|
||||
if (i == commands.end()) {
|
||||
throw UsageError("'%s' is not a recognised command", ss[0]);
|
||||
}
|
||||
command = i->second;
|
||||
}});
|
||||
}
|
||||
|
@ -50,8 +52,9 @@ void MultiCommand::printHelp(const string& programName, std::ostream& out) {
|
|||
Table2 table;
|
||||
for (auto& command : commands) {
|
||||
auto descr = command.second->description();
|
||||
if (!descr.empty())
|
||||
if (!descr.empty()) {
|
||||
table.push_back(std::make_pair(command.second->name(), descr));
|
||||
}
|
||||
}
|
||||
printTable(out, table);
|
||||
|
||||
|
@ -72,16 +75,19 @@ bool MultiCommand::processFlag(Strings::iterator& pos, Strings::iterator end) {
|
|||
}
|
||||
|
||||
bool MultiCommand::processArgs(const Strings& args, bool finish) {
|
||||
if (command)
|
||||
if (command) {
|
||||
return command->processArgs(args, finish);
|
||||
else
|
||||
} else {
|
||||
return Args::processArgs(args, finish);
|
||||
}
|
||||
}
|
||||
|
||||
StoreCommand::StoreCommand() {}
|
||||
|
||||
ref<Store> StoreCommand::getStore() {
|
||||
if (!_store) _store = createStore();
|
||||
if (!_store) {
|
||||
_store = createStore();
|
||||
}
|
||||
return ref<Store>(_store);
|
||||
}
|
||||
|
||||
|
@ -90,17 +96,18 @@ ref<Store> StoreCommand::createStore() { return openStore(); }
|
|||
void StoreCommand::run() { run(getStore()); }
|
||||
|
||||
StorePathsCommand::StorePathsCommand(bool recursive) : recursive(recursive) {
|
||||
if (recursive)
|
||||
if (recursive) {
|
||||
mkFlag()
|
||||
.longName("no-recursive")
|
||||
.description("apply operation to specified paths only")
|
||||
.set(&this->recursive, false);
|
||||
else
|
||||
} else {
|
||||
mkFlag()
|
||||
.longName("recursive")
|
||||
.shortName('r')
|
||||
.description("apply operation to closure of the specified paths")
|
||||
.set(&this->recursive, true);
|
||||
}
|
||||
|
||||
mkFlag(0, "all", "apply operation to the entire store", &all);
|
||||
}
|
||||
|
@ -109,16 +116,18 @@ void StorePathsCommand::run(ref<Store> store) {
|
|||
Paths storePaths;
|
||||
|
||||
if (all) {
|
||||
if (installables.size())
|
||||
if (installables.size()) {
|
||||
throw UsageError("'--all' does not expect arguments");
|
||||
}
|
||||
for (auto& p : store->queryAllValidPaths()) {
|
||||
storePaths.push_back(p);
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
for (auto& p : toStorePaths(store, NoBuild, installables))
|
||||
for (auto& p : toStorePaths(store, NoBuild, installables)) {
|
||||
storePaths.push_back(p);
|
||||
}
|
||||
|
||||
if (recursive) {
|
||||
PathSet closure;
|
||||
|
@ -134,8 +143,9 @@ void StorePathsCommand::run(ref<Store> store) {
|
|||
void StorePathCommand::run(ref<Store> store) {
|
||||
auto storePaths = toStorePaths(store, NoBuild, installables);
|
||||
|
||||
if (storePaths.size() != 1)
|
||||
if (storePaths.size() != 1) {
|
||||
throw UsageError("this command requires exactly one store path");
|
||||
}
|
||||
|
||||
run(store, *storePaths.begin());
|
||||
}
|
||||
|
|
3
third_party/nix/src/nix/copy.cc
vendored
3
third_party/nix/src/nix/copy.cc
vendored
|
@ -72,8 +72,9 @@ struct CmdCopy : StorePathsCommand {
|
|||
}
|
||||
|
||||
void run(ref<Store> srcStore, Paths storePaths) override {
|
||||
if (srcUri.empty() && dstUri.empty())
|
||||
if (srcUri.empty() && dstUri.empty()) {
|
||||
throw UsageError("you must pass '--from' and/or '--to'");
|
||||
}
|
||||
|
||||
ref<Store> dstStore = dstUri.empty() ? openStore() : openStore(dstUri);
|
||||
|
||||
|
|
12
third_party/nix/src/nix/doctor.cc
vendored
12
third_party/nix/src/nix/doctor.cc
vendored
|
@ -44,9 +44,11 @@ struct CmdDoctor : StoreCommand {
|
|||
bool checkNixInPath() {
|
||||
PathSet dirs;
|
||||
|
||||
for (auto& dir : tokenizeString<Strings>(getEnv("PATH"), ":"))
|
||||
if (pathExists(dir + "/nix-env"))
|
||||
for (auto& dir : tokenizeString<Strings>(getEnv("PATH"), ":")) {
|
||||
if (pathExists(dir + "/nix-env")) {
|
||||
dirs.insert(dirOf(canonPath(dir + "/nix-env", true)));
|
||||
}
|
||||
}
|
||||
|
||||
if (dirs.size() != 1) {
|
||||
std::cout << "Warning: multiple versions of nix found in PATH."
|
||||
|
@ -73,11 +75,13 @@ struct CmdDoctor : StoreCommand {
|
|||
if (store->isStorePath(userEnv) &&
|
||||
hasSuffix(userEnv, "user-environment")) {
|
||||
while (profileDir.find("/profiles/") == std::string::npos &&
|
||||
isLink(profileDir))
|
||||
isLink(profileDir)) {
|
||||
profileDir = absPath(readLink(profileDir), dirOf(profileDir));
|
||||
}
|
||||
|
||||
if (profileDir.find("/profiles/") == std::string::npos)
|
||||
if (profileDir.find("/profiles/") == std::string::npos) {
|
||||
dirs.insert(dir);
|
||||
}
|
||||
}
|
||||
} catch (SysError&) {
|
||||
}
|
||||
|
|
6
third_party/nix/src/nix/edit.cc
vendored
6
third_party/nix/src/nix/edit.cc
vendored
|
@ -40,8 +40,9 @@ struct CmdEdit : InstallableCommand {
|
|||
DLOG(INFO) << "position is " << pos;
|
||||
|
||||
auto colon = pos.rfind(':');
|
||||
if (colon == std::string::npos)
|
||||
if (colon == std::string::npos) {
|
||||
throw Error("cannot parse meta.position attribute '%s'", pos);
|
||||
}
|
||||
|
||||
std::string filename(pos, 0, colon);
|
||||
int lineno;
|
||||
|
@ -57,8 +58,9 @@ struct CmdEdit : InstallableCommand {
|
|||
|
||||
if (editor.find("emacs") != std::string::npos ||
|
||||
editor.find("nano") != std::string::npos ||
|
||||
editor.find("vim") != std::string::npos)
|
||||
editor.find("vim") != std::string::npos) {
|
||||
args.push_back(fmt("+%d", lineno));
|
||||
}
|
||||
|
||||
args.push_back(filename);
|
||||
|
||||
|
|
3
third_party/nix/src/nix/eval.cc
vendored
3
third_party/nix/src/nix/eval.cc
vendored
|
@ -32,8 +32,9 @@ struct CmdEval : MixJSON, InstallableCommand {
|
|||
}
|
||||
|
||||
void run(ref<Store> store) override {
|
||||
if (raw && json)
|
||||
if (raw && json) {
|
||||
throw UsageError("--raw and --json are mutually exclusive");
|
||||
}
|
||||
|
||||
auto state = getEvalState();
|
||||
|
||||
|
|
27
third_party/nix/src/nix/hash.cc
vendored
27
third_party/nix/src/nix/hash.cc
vendored
|
@ -73,8 +73,9 @@ struct CmdToBase : Command {
|
|||
}
|
||||
|
||||
void run() override {
|
||||
for (auto s : args)
|
||||
for (auto s : args) {
|
||||
std::cout << fmt("%s\n", Hash(s, ht).to_string(base, base == SRI));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -94,29 +95,31 @@ static int compatNixHash(int argc, char** argv) {
|
|||
|
||||
parseCmdLine(argc, argv,
|
||||
[&](Strings::iterator& arg, const Strings::iterator& end) {
|
||||
if (*arg == "--help")
|
||||
if (*arg == "--help") {
|
||||
showManPage("nix-hash");
|
||||
else if (*arg == "--version")
|
||||
} else if (*arg == "--version") {
|
||||
printVersion("nix-hash");
|
||||
else if (*arg == "--flat")
|
||||
} else if (*arg == "--flat") {
|
||||
flat = true;
|
||||
else if (*arg == "--base32")
|
||||
} else if (*arg == "--base32") {
|
||||
base32 = true;
|
||||
else if (*arg == "--truncate")
|
||||
} else if (*arg == "--truncate") {
|
||||
truncate = true;
|
||||
else if (*arg == "--type") {
|
||||
} else if (*arg == "--type") {
|
||||
string s = getArg(*arg, arg, end);
|
||||
ht = parseHashType(s);
|
||||
if (ht == htUnknown)
|
||||
if (ht == htUnknown) {
|
||||
throw UsageError(format("unknown hash type '%1%'") % s);
|
||||
} else if (*arg == "--to-base16")
|
||||
}
|
||||
} else if (*arg == "--to-base16") {
|
||||
op = opTo16;
|
||||
else if (*arg == "--to-base32")
|
||||
} else if (*arg == "--to-base32") {
|
||||
op = opTo32;
|
||||
else if (*arg != "" && arg->at(0) == '-')
|
||||
} else if (*arg != "" && arg->at(0) == '-') {
|
||||
return false;
|
||||
else
|
||||
} else {
|
||||
ss.push_back(*arg);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
|
|
64
third_party/nix/src/nix/installables.cc
vendored
64
third_party/nix/src/nix/installables.cc
vendored
|
@ -30,10 +30,10 @@ Value* SourceExprCommand::getSourceExpr(EvalState& state) {
|
|||
|
||||
vSourceExpr = state.allocValue();
|
||||
|
||||
if (file != "")
|
||||
if (file != "") {
|
||||
state.evalFile(lookupFileArg(state, file), *vSourceExpr);
|
||||
|
||||
else {
|
||||
} else {
|
||||
/* Construct the installation source from $NIX_PATH. */
|
||||
|
||||
auto searchPath = state.getSearchPath();
|
||||
|
@ -60,14 +60,18 @@ Value* SourceExprCommand::getSourceExpr(EvalState& state) {
|
|||
state.getBuiltin("import"), *v2);
|
||||
};
|
||||
|
||||
for (auto& i : searchPath) /* Hack to handle channels. */
|
||||
for (auto& i : searchPath) { /* Hack to handle channels. */
|
||||
if (i.first.empty() && pathExists(i.second + "/manifest.nix")) {
|
||||
for (auto& j : readDirectory(i.second))
|
||||
for (auto& j : readDirectory(i.second)) {
|
||||
if (j.name != "manifest.nix" &&
|
||||
pathExists(fmt("%s/%s/default.nix", i.second, j.name)))
|
||||
pathExists(fmt("%s/%s/default.nix", i.second, j.name))) {
|
||||
addEntry(j.name);
|
||||
} else
|
||||
}
|
||||
}
|
||||
} else {
|
||||
addEntry(i.first);
|
||||
}
|
||||
}
|
||||
|
||||
vSourceExpr->attrs->sort();
|
||||
}
|
||||
|
@ -76,18 +80,20 @@ Value* SourceExprCommand::getSourceExpr(EvalState& state) {
|
|||
}
|
||||
|
||||
ref<EvalState> SourceExprCommand::getEvalState() {
|
||||
if (!evalState)
|
||||
if (!evalState) {
|
||||
evalState = std::make_shared<EvalState>(searchPath, getStore());
|
||||
}
|
||||
return ref<EvalState>(evalState);
|
||||
}
|
||||
|
||||
Buildable Installable::toBuildable() {
|
||||
auto buildables = toBuildables();
|
||||
if (buildables.size() != 1)
|
||||
if (buildables.size() != 1) {
|
||||
throw Error(
|
||||
"installable '%s' evaluates to %d derivations, where only one is "
|
||||
"expected",
|
||||
what(), buildables.size());
|
||||
}
|
||||
return std::move(buildables[0]);
|
||||
}
|
||||
|
||||
|
@ -127,9 +133,10 @@ struct InstallableValue : Installable {
|
|||
drvPaths.insert(b.drvPath);
|
||||
|
||||
auto outputName = drv.queryOutputName();
|
||||
if (outputName == "")
|
||||
if (outputName == "") {
|
||||
throw Error("derivation '%s' lacks an 'outputName' attribute",
|
||||
b.drvPath);
|
||||
}
|
||||
|
||||
b.outputs.emplace(outputName, drv.queryOutPath());
|
||||
|
||||
|
@ -140,11 +147,13 @@ struct InstallableValue : Installable {
|
|||
// merge the buildables.
|
||||
if (drvPaths.size() == 1) {
|
||||
Buildable b{*drvPaths.begin()};
|
||||
for (auto& b2 : res)
|
||||
for (auto& b2 : res) {
|
||||
b.outputs.insert(b2.outputs.begin(), b2.outputs.end());
|
||||
}
|
||||
return {b};
|
||||
} else
|
||||
} else {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -200,21 +209,23 @@ static std::vector<std::shared_ptr<Installable>> parseInstallables(
|
|||
}
|
||||
|
||||
for (auto& s : ss) {
|
||||
if (s.compare(0, 1, "(") == 0)
|
||||
if (s.compare(0, 1, "(") == 0) {
|
||||
result.push_back(std::make_shared<InstallableExpr>(cmd, s));
|
||||
|
||||
else if (s.find("/") != std::string::npos) {
|
||||
} else if (s.find("/") != std::string::npos) {
|
||||
auto path = store->toStorePath(store->followLinksToStore(s));
|
||||
|
||||
if (store->isStorePath(path))
|
||||
if (store->isStorePath(path)) {
|
||||
result.push_back(std::make_shared<InstallableStorePath>(path));
|
||||
}
|
||||
}
|
||||
|
||||
else if (s == "" || std::regex_match(s, attrPathRegex))
|
||||
else if (s == "" || std::regex_match(s, attrPathRegex)) {
|
||||
result.push_back(std::make_shared<InstallableAttrPath>(cmd, s));
|
||||
|
||||
else
|
||||
} else {
|
||||
throw UsageError("don't know what to do with argument '%s'", s);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -248,10 +259,11 @@ Buildables build(ref<Store> store, RealiseMode mode,
|
|||
}
|
||||
pathsToBuild.insert(b.drvPath + "!" +
|
||||
concatStringsSep(",", outputNames));
|
||||
} else
|
||||
} else {
|
||||
for (auto& output : b.outputs) {
|
||||
pathsToBuild.insert(output.second);
|
||||
}
|
||||
}
|
||||
buildables.push_back(std::move(b));
|
||||
}
|
||||
}
|
||||
|
@ -269,10 +281,11 @@ PathSet toStorePaths(ref<Store> store, RealiseMode mode,
|
|||
std::vector<std::shared_ptr<Installable>> installables) {
|
||||
PathSet outPaths;
|
||||
|
||||
for (auto& b : build(store, mode, installables))
|
||||
for (auto& b : build(store, mode, installables)) {
|
||||
for (auto& output : b.outputs) {
|
||||
outPaths.insert(output.second);
|
||||
}
|
||||
}
|
||||
|
||||
return outPaths;
|
||||
}
|
||||
|
@ -281,9 +294,10 @@ Path toStorePath(ref<Store> store, RealiseMode mode,
|
|||
std::shared_ptr<Installable> installable) {
|
||||
auto paths = toStorePaths(store, mode, {installable});
|
||||
|
||||
if (paths.size() != 1)
|
||||
if (paths.size() != 1) {
|
||||
throw Error("argument '%s' should evaluate to one store path",
|
||||
installable->what());
|
||||
}
|
||||
|
||||
return *paths.begin();
|
||||
}
|
||||
|
@ -293,22 +307,26 @@ PathSet toDerivations(ref<Store> store,
|
|||
bool useDeriver) {
|
||||
PathSet drvPaths;
|
||||
|
||||
for (auto& i : installables)
|
||||
for (auto& i : installables) {
|
||||
for (auto& b : i->toBuildables()) {
|
||||
if (b.drvPath.empty()) {
|
||||
if (!useDeriver)
|
||||
if (!useDeriver) {
|
||||
throw Error("argument '%s' did not evaluate to a derivation",
|
||||
i->what());
|
||||
}
|
||||
for (auto& output : b.outputs) {
|
||||
auto derivers = store->queryValidDerivers(output.second);
|
||||
if (derivers.empty())
|
||||
if (derivers.empty()) {
|
||||
throw Error("'%s' does not have a known deriver", i->what());
|
||||
}
|
||||
// FIXME: use all derivers?
|
||||
drvPaths.insert(*derivers.begin());
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
drvPaths.insert(b.drvPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return drvPaths;
|
||||
}
|
||||
|
|
12
third_party/nix/src/nix/ls.cc
vendored
12
third_party/nix/src/nix/ls.cc
vendored
|
@ -35,17 +35,20 @@ struct MixLs : virtual Args, MixJSON {
|
|||
? "lrwxrwxrwx"
|
||||
: "dr-xr-xr-x";
|
||||
std::cout << (format("%s %20d %s") % tp % st.fileSize % relPath);
|
||||
if (st.type == FSAccessor::Type::tSymlink)
|
||||
if (st.type == FSAccessor::Type::tSymlink) {
|
||||
std::cout << " -> " << accessor->readLink(curPath);
|
||||
}
|
||||
std::cout << "\n";
|
||||
if (recursive && st.type == FSAccessor::Type::tDirectory)
|
||||
if (recursive && st.type == FSAccessor::Type::tDirectory) {
|
||||
doPath(st, curPath, relPath, false);
|
||||
}
|
||||
} else {
|
||||
std::cout << relPath << "\n";
|
||||
if (recursive) {
|
||||
auto st = accessor->stat(curPath);
|
||||
if (st.type == FSAccessor::Type::tDirectory)
|
||||
if (st.type == FSAccessor::Type::tDirectory) {
|
||||
doPath(st, curPath, relPath, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -57,8 +60,9 @@ struct MixLs : virtual Args, MixJSON {
|
|||
for (auto& name : names) {
|
||||
showFile(curPath + "/" + name, relPath + "/" + name);
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
showFile(curPath, relPath);
|
||||
}
|
||||
};
|
||||
|
||||
auto st = accessor->stat(path);
|
||||
|
|
12
third_party/nix/src/nix/main.cc
vendored
12
third_party/nix/src/nix/main.cc
vendored
|
@ -44,8 +44,9 @@ static bool haveInternet() {
|
|||
}
|
||||
} else if (i->ifa_addr->sa_family == AF_INET6) {
|
||||
if (!IN6_IS_ADDR_LOOPBACK(&((sockaddr_in6*)i->ifa_addr)->sin6_addr) &&
|
||||
!IN6_IS_ADDR_LINKLOCAL(&((sockaddr_in6*)i->ifa_addr)->sin6_addr))
|
||||
!IN6_IS_ADDR_LINKLOCAL(&((sockaddr_in6*)i->ifa_addr)->sin6_addr)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,8 +73,9 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs {
|
|||
Table2 tbl;
|
||||
std::map<std::string, Config::SettingInfo> settings;
|
||||
globalConfig.getSettings(settings);
|
||||
for (const auto& s : settings)
|
||||
for (const auto& s : settings) {
|
||||
tbl.emplace_back(s.first, s.second.description);
|
||||
}
|
||||
printTable(std::cout, tbl);
|
||||
throw Exit();
|
||||
});
|
||||
|
@ -159,13 +161,15 @@ void mainWrapped(int argc, char** argv) {
|
|||
if (!settings.useSubstitutes.overriden) {
|
||||
settings.useSubstitutes = false;
|
||||
}
|
||||
if (!settings.tarballTtl.overriden)
|
||||
if (!settings.tarballTtl.overriden) {
|
||||
settings.tarballTtl = std::numeric_limits<unsigned int>::max();
|
||||
}
|
||||
if (!downloadSettings.tries.overriden) {
|
||||
downloadSettings.tries = 0;
|
||||
}
|
||||
if (!downloadSettings.connectTimeout.overriden)
|
||||
if (!downloadSettings.connectTimeout.overriden) {
|
||||
downloadSettings.connectTimeout = 1;
|
||||
}
|
||||
}
|
||||
|
||||
args.command->prepare();
|
||||
|
|
6
third_party/nix/src/nix/path-info.cc
vendored
6
third_party/nix/src/nix/path-info.cc
vendored
|
@ -75,8 +75,9 @@ struct CmdPathInfo : StorePathsCommand, MixJSON {
|
|||
|
||||
void run(ref<Store> store, Paths storePaths) override {
|
||||
size_t pathLen = 0;
|
||||
for (auto& storePath : storePaths)
|
||||
for (auto& storePath : storePaths) {
|
||||
pathLen = std::max(pathLen, storePath.size());
|
||||
}
|
||||
|
||||
if (json) {
|
||||
JSONPlaceholder jsonRoot(std::cout);
|
||||
|
@ -93,9 +94,10 @@ struct CmdPathInfo : StorePathsCommand, MixJSON {
|
|||
|
||||
std::cout << storePath;
|
||||
|
||||
if (showSize || showClosureSize || showSigs)
|
||||
if (showSize || showClosureSize || showSigs) {
|
||||
std::cout << std::string(
|
||||
std::max(0, (int)pathLen - (int)storePath.size()), ' ');
|
||||
}
|
||||
|
||||
if (showSize) {
|
||||
printSize(info->narSize);
|
||||
|
|
75
third_party/nix/src/nix/repl.cc
vendored
75
third_party/nix/src/nix/repl.cc
vendored
|
@ -181,8 +181,9 @@ static char* completionCallback(char* s, int* match) {
|
|||
static int listPossibleCallback(char* s, char*** avp) {
|
||||
auto possible = curRepl->completePrefix(s);
|
||||
|
||||
if (possible.size() > (INT_MAX / sizeof(char*)))
|
||||
if (possible.size() > (INT_MAX / sizeof(char*))) {
|
||||
throw Error("too many completions");
|
||||
}
|
||||
|
||||
int ac = 0;
|
||||
char** vp = nullptr;
|
||||
|
@ -190,7 +191,9 @@ static int listPossibleCallback(char* s, char*** avp) {
|
|||
auto check = [&](auto* p) {
|
||||
if (!p) {
|
||||
if (vp) {
|
||||
while (--ac >= 0) free(vp[ac]);
|
||||
while (--ac >= 0) {
|
||||
free(vp[ac]);
|
||||
}
|
||||
free(vp);
|
||||
}
|
||||
throw Error("allocation failure");
|
||||
|
@ -288,20 +291,24 @@ bool NixRepl::getLine(string& input, const std::string& prompt) {
|
|||
act.sa_handler = sigintHandler;
|
||||
sigfillset(&act.sa_mask);
|
||||
act.sa_flags = 0;
|
||||
if (sigaction(SIGINT, &act, &old))
|
||||
if (sigaction(SIGINT, &act, &old)) {
|
||||
throw SysError("installing handler for SIGINT");
|
||||
}
|
||||
|
||||
sigemptyset(&set);
|
||||
sigaddset(&set, SIGINT);
|
||||
if (sigprocmask(SIG_UNBLOCK, &set, &savedSignalMask))
|
||||
if (sigprocmask(SIG_UNBLOCK, &set, &savedSignalMask)) {
|
||||
throw SysError("unblocking SIGINT");
|
||||
}
|
||||
};
|
||||
auto restoreSignals = [&]() {
|
||||
if (sigprocmask(SIG_SETMASK, &savedSignalMask, nullptr))
|
||||
if (sigprocmask(SIG_SETMASK, &savedSignalMask, nullptr)) {
|
||||
throw SysError("restoring signals");
|
||||
}
|
||||
|
||||
if (sigaction(SIGINT, &old, 0))
|
||||
if (sigaction(SIGINT, &old, 0)) {
|
||||
throw SysError("restoring handler for SIGINT");
|
||||
}
|
||||
};
|
||||
|
||||
setupSignals();
|
||||
|
@ -343,8 +350,9 @@ StringSet NixRepl::completePrefix(string prefix) {
|
|||
auto dir = std::string(cur, 0, slash);
|
||||
auto prefix2 = std::string(cur, slash + 1);
|
||||
for (auto& entry : readDirectory(dir == "" ? "/" : dir)) {
|
||||
if (entry.name[0] != '.' && hasPrefix(entry.name, prefix2))
|
||||
if (entry.name[0] != '.' && hasPrefix(entry.name, prefix2)) {
|
||||
completions.insert(prev + dir + "/" + entry.name);
|
||||
}
|
||||
}
|
||||
} catch (Error&) {
|
||||
}
|
||||
|
@ -417,21 +425,25 @@ bool isVarName(const string& s) {
|
|||
if ((c >= '0' && c <= '9') || c == '-' || c == '\'') {
|
||||
return false;
|
||||
}
|
||||
for (auto& i : s)
|
||||
for (auto& i : s) {
|
||||
if (!((i >= 'a' && i <= 'z') || (i >= 'A' && i <= 'Z') ||
|
||||
(i >= '0' && i <= '9') || i == '_' || i == '-' || i == '\''))
|
||||
(i >= '0' && i <= '9') || i == '_' || i == '-' || i == '\'')) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Path NixRepl::getDerivationPath(Value& v) {
|
||||
auto drvInfo = getDerivation(state, v, false);
|
||||
if (!drvInfo)
|
||||
if (!drvInfo) {
|
||||
throw Error(
|
||||
"expression does not evaluate to a derivation, so I can't build it");
|
||||
}
|
||||
Path drvPath = drvInfo->queryDrvPath();
|
||||
if (drvPath == "" || !state.store->isValidPath(drvPath))
|
||||
if (drvPath == "" || !state.store->isValidPath(drvPath)) {
|
||||
throw Error("expression did not evaluate to a valid derivation");
|
||||
}
|
||||
return drvPath;
|
||||
}
|
||||
|
||||
|
@ -520,9 +532,10 @@ bool NixRepl::processLine(string line) {
|
|||
std::cout << std::endl
|
||||
<< "this derivation produced the following outputs:"
|
||||
<< std::endl;
|
||||
for (auto& i : drv.outputs)
|
||||
for (auto& i : drv.outputs) {
|
||||
std::cout << format(" %1% -> %2%") % i.first % i.second.path
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
} else if (command == ":i") {
|
||||
runProgram(settings.nixBinDir + "/nix-env", Strings{"-i", drvPath});
|
||||
|
@ -537,13 +550,13 @@ bool NixRepl::processLine(string line) {
|
|||
printValue(std::cout, v, 1000000000) << std::endl;
|
||||
}
|
||||
|
||||
else if (command == ":q" || command == ":quit")
|
||||
else if (command == ":q" || command == ":quit") {
|
||||
return false;
|
||||
|
||||
else if (command != "")
|
||||
} else if (command != "") {
|
||||
throw Error(format("unknown command '%1%'") % command);
|
||||
|
||||
else {
|
||||
} else {
|
||||
size_t p = line.find('=');
|
||||
string name;
|
||||
if (p != string::npos && p < line.size() && line[p + 1] != '=' &&
|
||||
|
@ -612,8 +625,9 @@ void NixRepl::addAttrsToScope(Value& attrs) {
|
|||
}
|
||||
|
||||
void NixRepl::addVarToScope(const Symbol& name, Value& v) {
|
||||
if (displ >= envSize)
|
||||
if (displ >= envSize) {
|
||||
throw Error("environment full; cannot add more variables");
|
||||
}
|
||||
staticEnv.vars[name] = displ;
|
||||
env->values[displ++] = &v;
|
||||
varNames.insert((string)name);
|
||||
|
@ -638,17 +652,19 @@ std::ostream& NixRepl::printValue(std::ostream& str, Value& v,
|
|||
|
||||
std::ostream& printStringValue(std::ostream& str, const char* string) {
|
||||
str << "\"";
|
||||
for (const char* i = string; *i; i++)
|
||||
if (*i == '\"' || *i == '\\')
|
||||
for (const char* i = string; *i; i++) {
|
||||
if (*i == '\"' || *i == '\\') {
|
||||
str << "\\" << *i;
|
||||
else if (*i == '\n')
|
||||
} else if (*i == '\n') {
|
||||
str << "\\n";
|
||||
else if (*i == '\r')
|
||||
} else if (*i == '\r') {
|
||||
str << "\\r";
|
||||
else if (*i == '\t')
|
||||
} else if (*i == '\t') {
|
||||
str << "\\t";
|
||||
else
|
||||
} else {
|
||||
str << *i;
|
||||
}
|
||||
}
|
||||
str << "\"";
|
||||
return str;
|
||||
}
|
||||
|
@ -709,19 +725,21 @@ std::ostream& NixRepl::printValue(std::ostream& str, Value& v,
|
|||
}
|
||||
|
||||
for (auto& i : sorted) {
|
||||
if (isVarName(i.first))
|
||||
if (isVarName(i.first)) {
|
||||
str << i.first;
|
||||
else
|
||||
} else {
|
||||
printStringValue(str, i.first.c_str());
|
||||
}
|
||||
str << " = ";
|
||||
if (seen.find(i.second) != seen.end())
|
||||
if (seen.find(i.second) != seen.end()) {
|
||||
str << "«repeated»";
|
||||
else
|
||||
} else {
|
||||
try {
|
||||
printValue(str, *i.second, maxDepth - 1, seen);
|
||||
} catch (AssertionError& e) {
|
||||
str << ESC_RED "«error: " << e.msg() << "»" ESC_END;
|
||||
}
|
||||
}
|
||||
str << "; ";
|
||||
}
|
||||
|
||||
|
@ -741,14 +759,15 @@ std::ostream& NixRepl::printValue(std::ostream& str, Value& v,
|
|||
str << "[ ";
|
||||
if (maxDepth > 0) {
|
||||
for (unsigned int n = 0; n < v.listSize(); ++n) {
|
||||
if (seen.find(v.listElems()[n]) != seen.end())
|
||||
if (seen.find(v.listElems()[n]) != seen.end()) {
|
||||
str << "«repeated»";
|
||||
else
|
||||
} else {
|
||||
try {
|
||||
printValue(str, *v.listElems()[n], maxDepth - 1, seen);
|
||||
} catch (AssertionError& e) {
|
||||
str << ESC_RED "«error: " << e.msg() << "»" ESC_END;
|
||||
}
|
||||
}
|
||||
str << " ";
|
||||
}
|
||||
} else {
|
||||
|
|
37
third_party/nix/src/nix/run.cc
vendored
37
third_party/nix/src/nix/run.cc
vendored
|
@ -31,8 +31,9 @@ struct CmdRun : InstallablesCommand {
|
|||
.labels({"command", "args"})
|
||||
.arity(ArityAny)
|
||||
.handler([&](std::vector<std::string> ss) {
|
||||
if (ss.empty())
|
||||
if (ss.empty()) {
|
||||
throw UsageError("--command requires at least one argument");
|
||||
}
|
||||
command = ss;
|
||||
});
|
||||
|
||||
|
@ -87,9 +88,10 @@ struct CmdRun : InstallablesCommand {
|
|||
auto accessor = store->getFSAccessor();
|
||||
|
||||
if (ignoreEnvironment) {
|
||||
if (!unset.empty())
|
||||
if (!unset.empty()) {
|
||||
throw UsageError(
|
||||
"--unset does not make sense with --ignore-environment");
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> kept;
|
||||
for (auto& var : keep) {
|
||||
|
@ -106,9 +108,10 @@ struct CmdRun : InstallablesCommand {
|
|||
}
|
||||
|
||||
} else {
|
||||
if (!keep.empty())
|
||||
if (!keep.empty()) {
|
||||
throw UsageError(
|
||||
"--keep does not make sense without --ignore-environment");
|
||||
}
|
||||
|
||||
for (auto& var : unset) {
|
||||
unsetenv(var.c_str());
|
||||
|
@ -191,17 +194,21 @@ void chrootHelper(int argc, char** argv) {
|
|||
std::string realStoreDir = argv[p++];
|
||||
std::string cmd = argv[p++];
|
||||
Strings args;
|
||||
while (p < argc) args.push_back(argv[p++]);
|
||||
while (p < argc) {
|
||||
args.push_back(argv[p++]);
|
||||
}
|
||||
|
||||
#if __linux__
|
||||
uid_t uid = getuid();
|
||||
uid_t gid = getgid();
|
||||
|
||||
if (unshare(CLONE_NEWUSER | CLONE_NEWNS) == -1)
|
||||
if (unshare(CLONE_NEWUSER | CLONE_NEWNS) == -1) {
|
||||
/* Try with just CLONE_NEWNS in case user namespaces are
|
||||
specifically disabled. */
|
||||
if (unshare(CLONE_NEWNS) == -1)
|
||||
if (unshare(CLONE_NEWNS) == -1) {
|
||||
throw SysError("setting up a private mount namespace");
|
||||
}
|
||||
}
|
||||
|
||||
/* Bind-mount realStoreDir on /nix/store. If the latter mount
|
||||
point doesn't already exists, we have to create a chroot
|
||||
|
@ -218,8 +225,9 @@ void chrootHelper(int argc, char** argv) {
|
|||
createDirs(tmpDir + storeDir);
|
||||
|
||||
if (mount(realStoreDir.c_str(), (tmpDir + storeDir).c_str(), "", MS_BIND,
|
||||
0) == -1)
|
||||
0) == -1) {
|
||||
throw SysError("mounting '%s' on '%s'", realStoreDir, storeDir);
|
||||
}
|
||||
|
||||
for (auto entry : readDirectory("/")) {
|
||||
auto src = "/" + entry.name;
|
||||
|
@ -231,10 +239,12 @@ void chrootHelper(int argc, char** argv) {
|
|||
if (pathExists(dst)) {
|
||||
continue;
|
||||
}
|
||||
if (mkdir(dst.c_str(), 0700) == -1)
|
||||
if (mkdir(dst.c_str(), 0700) == -1) {
|
||||
throw SysError("creating directory '%s'", dst);
|
||||
if (mount(src.c_str(), dst.c_str(), "", MS_BIND | MS_REC, 0) == -1)
|
||||
}
|
||||
if (mount(src.c_str(), dst.c_str(), "", MS_BIND | MS_REC, 0) == -1) {
|
||||
throw SysError("mounting '%s' on '%s'", src, dst);
|
||||
}
|
||||
}
|
||||
|
||||
char* cwd = getcwd(0, 0);
|
||||
|
@ -243,14 +253,17 @@ void chrootHelper(int argc, char** argv) {
|
|||
}
|
||||
Finally freeCwd([&]() { free(cwd); });
|
||||
|
||||
if (chroot(tmpDir.c_str()) == -1)
|
||||
if (chroot(tmpDir.c_str()) == -1) {
|
||||
throw SysError(format("chrooting into '%s'") % tmpDir);
|
||||
}
|
||||
|
||||
if (chdir(cwd) == -1)
|
||||
if (chdir(cwd) == -1) {
|
||||
throw SysError(format("chdir to '%s' in chroot") % cwd);
|
||||
}
|
||||
} else if (mount(realStoreDir.c_str(), storeDir.c_str(), "", MS_BIND, 0) ==
|
||||
-1)
|
||||
-1) {
|
||||
throw SysError("mounting '%s' on '%s'", realStoreDir, storeDir);
|
||||
}
|
||||
|
||||
writeFile("/proc/self/setgroups", "deny");
|
||||
writeFile("/proc/self/uid_map", fmt("%d %d %d", uid, uid, 1));
|
||||
|
|
6
third_party/nix/src/nix/search.cc
vendored
6
third_party/nix/src/nix/search.cc
vendored
|
@ -251,13 +251,15 @@ struct CmdSearch : SourceExprCommand, MixJSON {
|
|||
}
|
||||
|
||||
if (writeCache &&
|
||||
rename(tmpFile.c_str(), jsonCacheFileName.c_str()) == -1)
|
||||
rename(tmpFile.c_str(), jsonCacheFileName.c_str()) == -1) {
|
||||
throw SysError("cannot rename '%s' to '%s'", tmpFile,
|
||||
jsonCacheFileName);
|
||||
}
|
||||
}
|
||||
|
||||
if (results.size() == 0)
|
||||
if (results.size() == 0) {
|
||||
throw Error("no results for the given search term(s)!");
|
||||
}
|
||||
|
||||
RunPager pager;
|
||||
for (auto el : results) {
|
||||
|
|
3
third_party/nix/src/nix/show-config.cc
vendored
3
third_party/nix/src/nix/show-config.cc
vendored
|
@ -21,8 +21,9 @@ struct CmdShowConfig : Command, MixJSON {
|
|||
} else {
|
||||
std::map<std::string, Config::SettingInfo> settings;
|
||||
globalConfig.getSettings(settings);
|
||||
for (auto& s : settings)
|
||||
for (auto& s : settings) {
|
||||
std::cout << s.first + " = " + s.second.value + "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
15
third_party/nix/src/nix/sigs.cc
vendored
15
third_party/nix/src/nix/sigs.cc
vendored
|
@ -31,8 +31,9 @@ struct CmdCopySigs : StorePathsCommand {
|
|||
}
|
||||
|
||||
void run(ref<Store> store, Paths storePaths) override {
|
||||
if (substituterUris.empty())
|
||||
if (substituterUris.empty()) {
|
||||
throw UsageError("you must specify at least one substituter using '-s'");
|
||||
}
|
||||
|
||||
// FIXME: factor out commonality with MixVerify.
|
||||
std::vector<ref<Store>> substituters;
|
||||
|
@ -65,13 +66,15 @@ struct CmdCopySigs : StorePathsCommand {
|
|||
binary. */
|
||||
if (info->narHash != info2->narHash ||
|
||||
info->narSize != info2->narSize ||
|
||||
info->references != info2->references)
|
||||
info->references != info2->references) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (auto& sig : info2->sigs)
|
||||
for (auto& sig : info2->sigs) {
|
||||
if (!info->sigs.count(sig)) {
|
||||
newSigs.insert(sig);
|
||||
}
|
||||
}
|
||||
} catch (InvalidPath&) {
|
||||
}
|
||||
}
|
||||
|
@ -84,8 +87,9 @@ struct CmdCopySigs : StorePathsCommand {
|
|||
// logger->incProgress(doneLabel);
|
||||
};
|
||||
|
||||
for (auto& storePath : storePaths)
|
||||
for (auto& storePath : storePaths) {
|
||||
pool.enqueue(std::bind(doPath, storePath));
|
||||
}
|
||||
|
||||
pool.process();
|
||||
|
||||
|
@ -112,8 +116,9 @@ struct CmdSignPaths : StorePathsCommand {
|
|||
std::string description() override { return "sign the specified paths"; }
|
||||
|
||||
void run(ref<Store> store, Paths storePaths) override {
|
||||
if (secretKeyFile.empty())
|
||||
if (secretKeyFile.empty()) {
|
||||
throw UsageError("you must specify a secret key file using '-k'");
|
||||
}
|
||||
|
||||
SecretKey secretKey(readFile(secretKeyFile));
|
||||
|
||||
|
|
18
third_party/nix/src/nix/upgrade-nix.cc
vendored
18
third_party/nix/src/nix/upgrade-nix.cc
vendored
|
@ -80,8 +80,9 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand {
|
|||
LOG(INFO) << "verifying that '" << storePath << "' works...";
|
||||
auto program = storePath + "/bin/nix-env";
|
||||
auto s = runProgram(program, false, {"--version"});
|
||||
if (s.find("Nix") == std::string::npos)
|
||||
if (s.find("Nix") == std::string::npos) {
|
||||
throw Error("could not verify that '%s' works", program);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -99,15 +100,17 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand {
|
|||
Path getProfileDir(ref<Store> store) {
|
||||
Path where;
|
||||
|
||||
for (auto& dir : tokenizeString<Strings>(getEnv("PATH"), ":"))
|
||||
for (auto& dir : tokenizeString<Strings>(getEnv("PATH"), ":")) {
|
||||
if (pathExists(dir + "/nix-env")) {
|
||||
where = dir;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (where == "")
|
||||
if (where == "") {
|
||||
throw Error(
|
||||
"couldn't figure out how Nix is installed, so I can't upgrade it");
|
||||
}
|
||||
|
||||
LOG(INFO) << "found Nix in '" << where << "'";
|
||||
|
||||
|
@ -119,19 +122,22 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand {
|
|||
|
||||
// Resolve profile to /nix/var/nix/profiles/<name> link.
|
||||
while (canonPath(profileDir).find("/profiles/") == std::string::npos &&
|
||||
isLink(profileDir))
|
||||
isLink(profileDir)) {
|
||||
profileDir = readLink(profileDir);
|
||||
}
|
||||
|
||||
LOG(INFO) << "found profile '" << profileDir << "'";
|
||||
|
||||
Path userEnv = canonPath(profileDir, true);
|
||||
|
||||
if (baseNameOf(where) != "bin" || !hasSuffix(userEnv, "user-environment"))
|
||||
if (baseNameOf(where) != "bin" || !hasSuffix(userEnv, "user-environment")) {
|
||||
throw Error("directory '%s' does not appear to be part of a Nix profile",
|
||||
where);
|
||||
}
|
||||
|
||||
if (!store->isValidPath(userEnv))
|
||||
if (!store->isValidPath(userEnv)) {
|
||||
throw Error("directory '%s' is not in the Nix store", userEnv);
|
||||
}
|
||||
|
||||
return profileDir;
|
||||
}
|
||||
|
|
16
third_party/nix/src/nix/verify.cc
vendored
16
third_party/nix/src/nix/verify.cc
vendored
|
@ -94,10 +94,10 @@ struct CmdVerify : StorePathsCommand {
|
|||
if (!noTrust) {
|
||||
bool good = false;
|
||||
|
||||
if (info->ultimate && !sigsNeeded)
|
||||
if (info->ultimate && !sigsNeeded) {
|
||||
good = true;
|
||||
|
||||
else {
|
||||
} else {
|
||||
StringSet sigsSeen;
|
||||
size_t actualSigsNeeded = std::max(sigsNeeded, (size_t)1);
|
||||
size_t validSigs = 0;
|
||||
|
@ -109,13 +109,15 @@ struct CmdVerify : StorePathsCommand {
|
|||
}
|
||||
sigsSeen.insert(sig);
|
||||
if (validSigs < ValidPathInfo::maxSigs &&
|
||||
info->checkSignature(publicKeys, sig))
|
||||
info->checkSignature(publicKeys, sig)) {
|
||||
validSigs++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (info->isContentAddressed(*store))
|
||||
if (info->isContentAddressed(*store)) {
|
||||
validSigs = ValidPathInfo::maxSigs;
|
||||
}
|
||||
|
||||
doSigs(info->sigs);
|
||||
|
||||
|
@ -125,8 +127,9 @@ struct CmdVerify : StorePathsCommand {
|
|||
}
|
||||
try {
|
||||
auto info2 = store2->queryPathInfo(info->path);
|
||||
if (info2->isContentAddressed(*store))
|
||||
if (info2->isContentAddressed(*store)) {
|
||||
validSigs = ValidPathInfo::maxSigs;
|
||||
}
|
||||
doSigs(info2->sigs);
|
||||
} catch (InvalidPath&) {
|
||||
} catch (Error& e) {
|
||||
|
@ -153,8 +156,9 @@ struct CmdVerify : StorePathsCommand {
|
|||
}
|
||||
};
|
||||
|
||||
for (auto& storePath : storePaths)
|
||||
for (auto& storePath : storePaths) {
|
||||
pool.enqueue(std::bind(doPath, storePath));
|
||||
}
|
||||
|
||||
pool.process();
|
||||
|
||||
|
|
13
third_party/nix/src/nix/why-depends.cc
vendored
13
third_party/nix/src/nix/why-depends.cc
vendored
|
@ -92,14 +92,16 @@ struct CmdWhyDepends : SourceExprCommand {
|
|||
|
||||
std::map<Path, Node> graph;
|
||||
|
||||
for (auto& path : closure)
|
||||
for (auto& path : closure) {
|
||||
graph.emplace(path, Node{path, store->queryPathInfo(path)->references});
|
||||
}
|
||||
|
||||
// Transpose the graph.
|
||||
for (auto& node : graph)
|
||||
for (auto& node : graph) {
|
||||
for (auto& ref : node.second.refs) {
|
||||
graph[ref].rrefs.insert(node.first);
|
||||
}
|
||||
}
|
||||
|
||||
/* Run Dijkstra's shortest path algorithm to get the distance
|
||||
of every path in the closure to 'dependency'. */
|
||||
|
@ -146,8 +148,10 @@ struct CmdWhyDepends : SourceExprCommand {
|
|||
node.visited ? "\e[38;5;244m" : "",
|
||||
firstPad != "" ? "=> " : "", node.path);
|
||||
|
||||
if (node.path == dependencyPath && !all && packagePath != dependencyPath)
|
||||
if (node.path == dependencyPath && !all &&
|
||||
packagePath != dependencyPath) {
|
||||
throw BailOut();
|
||||
}
|
||||
|
||||
if (node.visited) {
|
||||
return;
|
||||
|
@ -216,10 +220,11 @@ struct CmdWhyDepends : SourceExprCommand {
|
|||
|
||||
for (auto& hash : hashes) {
|
||||
auto pos = target.find(hash);
|
||||
if (pos != std::string::npos)
|
||||
if (pos != std::string::npos) {
|
||||
hits[hash].emplace_back(
|
||||
fmt("%s -> %s\n", p2,
|
||||
hilite(target, pos, storePathHashLen, getColour(hash))));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue