aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/download-via-ssh/download-via-ssh.cc27
-rw-r--r--src/libexpr/attr-path.cc11
-rw-r--r--src/libexpr/eval-inline.hh4
-rw-r--r--src/libexpr/eval.cc171
-rw-r--r--src/libexpr/get-drvs.cc38
-rw-r--r--src/libexpr/json-to-value.cc2
-rw-r--r--src/libexpr/local.mk2
-rw-r--r--src/libexpr/names.cc4
-rw-r--r--src/libexpr/nixexpr.cc92
-rw-r--r--src/libexpr/parser.y20
-rw-r--r--src/libexpr/primops.cc262
-rw-r--r--src/libexpr/value-to-json.cc34
-rw-r--r--src/libexpr/value-to-xml.cc46
-rw-r--r--src/libexpr/value.hh29
-rw-r--r--src/libmain/shared.cc18
-rw-r--r--src/libstore/build.cc664
-rw-r--r--src/libstore/builtins.cc24
-rw-r--r--src/libstore/builtins.hh9
-rw-r--r--src/libstore/derivations.cc81
-rw-r--r--src/libstore/derivations.hh18
-rw-r--r--src/libstore/download.cc (renamed from src/libexpr/download.cc)0
-rw-r--r--src/libstore/download.hh (renamed from src/libexpr/download.hh)0
-rw-r--r--src/libstore/gc.cc43
-rw-r--r--src/libstore/globals.cc16
-rw-r--r--src/libstore/local-store.cc164
-rw-r--r--src/libstore/local-store.hh3
-rw-r--r--src/libstore/local.mk2
-rw-r--r--src/libstore/misc.cc86
-rw-r--r--src/libstore/misc.hh4
-rw-r--r--src/libstore/optimise-store.cc14
-rw-r--r--src/libstore/pathlocks.cc27
-rw-r--r--src/libstore/references.cc20
-rw-r--r--src/libstore/remote-store.cc190
-rw-r--r--src/libstore/remote-store.hh3
-rw-r--r--src/libstore/store-api.cc48
-rw-r--r--src/libstore/store-api.hh32
-rw-r--r--src/libutil/archive.cc37
-rw-r--r--src/libutil/serialise.cc67
-rw-r--r--src/libutil/serialise.hh43
-rw-r--r--src/libutil/util.cc20
-rw-r--r--src/libutil/util.hh10
-rw-r--r--src/libutil/xml-writer.cc8
-rw-r--r--src/nix-collect-garbage/nix-collect-garbage.cc7
-rw-r--r--src/nix-daemon/nix-daemon.cc102
-rw-r--r--src/nix-env/nix-env.cc276
-rw-r--r--src/nix-env/user-env.cc46
-rw-r--r--src/nix-instantiate/nix-instantiate.cc16
-rw-r--r--src/nix-store/nix-store.cc361
-rw-r--r--src/nix-store/serve-protocol.hh3
49 files changed, 1761 insertions, 1443 deletions
diff --git a/src/download-via-ssh/download-via-ssh.cc b/src/download-via-ssh/download-via-ssh.cc
index f71cf5650..ed551ac46 100644
--- a/src/download-via-ssh/download-via-ssh.cc
+++ b/src/download-via-ssh/download-via-ssh.cc
@@ -43,8 +43,7 @@ static std::pair<FdSink, FdSource> connect(const string & conn)
static void substitute(std::pair<FdSink, FdSource> & pipes, Path storePath, Path destPath)
{
- writeInt(cmdDumpStorePath, pipes.first);
- writeString(storePath, pipes.first);
+ pipes.first << cmdDumpStorePath << storePath;
pipes.first.flush();
restorePath(destPath, pipes.second);
std::cout << std::endl;
@@ -58,17 +57,17 @@ static void query(std::pair<FdSink, FdSource> & pipes)
string cmd = tokenized.front();
tokenized.pop_front();
if (cmd == "have") {
- writeInt(cmdQueryValidPaths, pipes.first);
- writeInt(0, pipes.first); // don't lock
- writeInt(0, pipes.first); // don't substitute
- writeStrings(tokenized, pipes.first);
+ pipes.first
+ << cmdQueryValidPaths
+ << 0 // don't lock
+ << 0 // don't substitute
+ << tokenized;
pipes.first.flush();
PathSet paths = readStrings<PathSet>(pipes.second);
- foreach (PathSet::iterator, i, paths)
- std::cout << *i << std::endl;
+ for (auto & i : paths)
+ std::cout << i << std::endl;
} else if (cmd == "info") {
- writeInt(cmdQueryPathInfos, pipes.first);
- writeStrings(tokenized, pipes.first);
+ pipes.first << cmdQueryPathInfos << tokenized;
pipes.first.flush();
while (1) {
Path path = readString(pipes.second);
@@ -80,8 +79,8 @@ static void query(std::pair<FdSink, FdSource> & pipes)
std::cout << deriver << std::endl;
PathSet references = readStorePaths<PathSet>(pipes.second);
std::cout << references.size() << std::endl;
- foreach (PathSet::iterator, i, references)
- std::cout << *i << std::endl;
+ for (auto & i : references)
+ std::cout << i << std::endl;
std::cout << readLongLong(pipes.second) << std::endl;
std::cout << readLongLong(pipes.second) << std::endl;
}
@@ -116,13 +115,13 @@ int main(int argc, char * * argv)
std::pair<FdSink, FdSource> pipes = connect(host);
/* Exchange the greeting */
- writeInt(SERVE_MAGIC_1, pipes.first);
+ pipes.first << SERVE_MAGIC_1;
pipes.first.flush();
unsigned int magic = readInt(pipes.second);
if (magic != SERVE_MAGIC_2)
throw Error("protocol mismatch");
readInt(pipes.second); // Server version, unused for now
- writeInt(SERVE_PROTOCOL_VERSION, pipes.first);
+ pipes.first << SERVE_PROTOCOL_VERSION;
pipes.first.flush();
string arg = argv[1];
diff --git a/src/libexpr/attr-path.cc b/src/libexpr/attr-path.cc
index fdd61a5fd..55379f94b 100644
--- a/src/libexpr/attr-path.cc
+++ b/src/libexpr/attr-path.cc
@@ -42,11 +42,10 @@ Value * findAlongAttrPath(EvalState & state, const string & attrPath,
Value * v = &vIn;
- foreach (Strings::iterator, i, tokens) {
+ for (auto & attr : tokens) {
- /* Is *i an index (integer) or a normal attribute name? */
+ /* Is i an index (integer) or a normal attribute name? */
enum { apAttr, apIndex } apType = apAttr;
- string attr = *i;
unsigned int attrIndex;
if (string2Int(attr, attrIndex)) apType = apIndex;
@@ -77,15 +76,15 @@ Value * findAlongAttrPath(EvalState & state, const string & attrPath,
else if (apType == apIndex) {
- if (v->type != tList)
+ 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->list.length)
+ if (attrIndex >= v->listSize())
throw Error(format("list index %1% in selection path ‘%2%’ is out of range") % attrIndex % attrPath);
- v = v->list.elems[attrIndex];
+ v = v->listElems()[attrIndex];
}
}
diff --git a/src/libexpr/eval-inline.hh b/src/libexpr/eval-inline.hh
index c275f7ba8..178e06c80 100644
--- a/src/libexpr/eval-inline.hh
+++ b/src/libexpr/eval-inline.hh
@@ -66,7 +66,7 @@ inline void EvalState::forceAttrs(Value & v, const Pos & pos)
inline void EvalState::forceList(Value & v)
{
forceValue(v);
- if (v.type != tList)
+ if (!v.isList())
throwTypeError("value is %1% while a list was expected", v);
}
@@ -74,7 +74,7 @@ inline void EvalState::forceList(Value & v)
inline void EvalState::forceList(Value & v, const Pos & pos)
{
forceValue(v);
- if (v.type != tList)
+ if (!v.isList())
throwTypeError("value is %1% while a list was expected, at %2%", v, pos);
}
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index eab38c9da..044256112 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -57,6 +57,8 @@ static void * allocBytes(size_t n)
static void printValue(std::ostream & str, std::set<const Value *> & active, const Value & v)
{
+ checkInterrupt();
+
if (active.find(&v) != active.end()) {
str << "<CYCLE>";
return;
@@ -90,8 +92,8 @@ static void printValue(std::ostream & str, std::set<const Value *> & active, con
str << "{ ";
typedef std::map<string, Value *> Sorted;
Sorted sorted;
- foreach (Bindings::iterator, i, *v.attrs)
- sorted[i->name] = i->value;
+ for (auto & i : *v.attrs)
+ sorted[i.name] = i.value;
for (auto & i : sorted) {
str << i.first << " = ";
printValue(str, active, *i.second);
@@ -100,10 +102,12 @@ static void printValue(std::ostream & str, std::set<const Value *> & active, con
str << "}";
break;
}
- case tList:
+ case tList1:
+ case tList2:
+ case tListN:
str << "[ ";
- for (unsigned int n = 0; n < v.list.length; ++n) {
- printValue(str, active, *v.list.elems[n]);
+ for (unsigned int n = 0; n < v.listSize(); ++n) {
+ printValue(str, active, *v.listElems()[n]);
str << " ";
}
str << "]";
@@ -149,7 +153,7 @@ string showType(const Value & v)
case tPath: return "a path";
case tNull: return "null";
case tAttrs: return "a set";
- case tList: return "a list";
+ case tList1: case tList2: case tListN: return "a list";
case tThunk: return "a thunk";
case tApp: return "a function application";
case tLambda: return "a function";
@@ -434,8 +438,8 @@ void mkString(Value & v, const string & s, const PathSet & context)
unsigned int n = 0;
v.string.context = (const char * *)
allocBytes((context.size() + 1) * sizeof(char *));
- foreach (PathSet::const_iterator, i, context)
- v.string.context[n++] = dupString(i->c_str());
+ for (auto & i : context)
+ v.string.context[n++] = dupString(i.c_str());
v.string.context[n] = 0;
}
}
@@ -497,13 +501,19 @@ Env & EvalState::allocEnv(unsigned int size)
}
-void EvalState::mkList(Value & v, unsigned int length)
+void EvalState::mkList(Value & v, unsigned int size)
{
clearValue(v);
- v.type = tList;
- v.list.length = length;
- v.list.elems = length ? (Value * *) allocBytes(length * sizeof(Value *)) : 0;
- nrListElems += length;
+ if (size == 1)
+ v.type = tList1;
+ else if (size == 2)
+ v.type = tList2;
+ else {
+ v.type = tListN;
+ v.bigList.size = size;
+ v.bigList.elems = size ? (Value * *) allocBytes(size * sizeof(Value *)) : 0;
+ }
+ nrListElems += size;
}
@@ -691,15 +701,15 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
environment, while the inherited attributes are evaluated
in the original environment. */
unsigned int displ = 0;
- foreach (AttrDefs::iterator, i, attrs) {
+ for (auto & i : attrs) {
Value * vAttr;
- if (hasOverrides && !i->second.inherited) {
+ if (hasOverrides && !i.second.inherited) {
vAttr = state.allocValue();
- mkThunk(*vAttr, env2, i->second.e);
+ mkThunk(*vAttr, env2, i.second.e);
} else
- vAttr = i->second.e->maybeThunk(state, i->second.inherited ? env : env2);
+ 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));
+ v.attrs->push_back(Attr(i.first, vAttr, &i.second.pos));
}
/* If the rec contains an attribute called `__overrides', then
@@ -730,13 +740,13 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
}
else
- foreach (AttrDefs::iterator, i, attrs)
- v.attrs->push_back(Attr(i->first, i->second.e->maybeThunk(state, env), &i->second.pos));
+ 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. */
- foreach (DynamicAttrDefs::iterator, i, dynamicAttrs) {
+ for (auto & i : dynamicAttrs) {
Value nameVal;
- i->nameExpr->eval(state, *dynamicEnv, nameVal);
+ i.nameExpr->eval(state, *dynamicEnv, nameVal);
state.forceValue(nameVal);
if (nameVal.type == tNull)
continue;
@@ -744,11 +754,11 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
Symbol nameSym = state.symbols.create(nameVal.string.s);
Bindings::iterator j = v.attrs->find(nameSym);
if (j != v.attrs->end())
- throwEvalError("dynamic attribute ‘%1%’ at %2% already defined at %3%", nameSym, i->pos, *j->pos);
+ throwEvalError("dynamic attribute ‘%1%’ at %2% already defined at %3%", nameSym, i.pos, *j->pos);
- i->valueExpr->setName(nameSym);
+ i.valueExpr->setName(nameSym);
/* Keep sorted order so find can catch duplicates */
- v.attrs->push_back(Attr(nameSym, i->valueExpr->maybeThunk(state, *dynamicEnv), &i->pos));
+ v.attrs->push_back(Attr(nameSym, i.valueExpr->maybeThunk(state, *dynamicEnv), &i.pos));
v.attrs->sort(); // FIXME: inefficient
}
}
@@ -765,8 +775,8 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v)
while the inherited attributes are evaluated in the original
environment. */
unsigned int displ = 0;
- foreach (ExprAttrs::AttrDefs::iterator, i, attrs->attrs)
- env2.values[displ++] = i->second.e->maybeThunk(state, i->second.inherited ? env : env2);
+ for (auto & i : attrs->attrs)
+ env2.values[displ++] = i.second.e->maybeThunk(state, i.second.inherited ? env : env2);
body->eval(state, env2, v);
}
@@ -775,8 +785,8 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v)
void ExprList::eval(EvalState & state, Env & env, Value & v)
{
state.mkList(v, elems.size());
- for (unsigned int n = 0; n < v.list.length; ++n)
- v.list.elems[n] = elems[n]->maybeThunk(state, env);
+ for (unsigned int n = 0; n < elems.size(); ++n)
+ v.listElems()[n] = elems[n]->maybeThunk(state, env);
}
@@ -817,10 +827,10 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
try {
- foreach (AttrPath::const_iterator, i, attrPath) {
+ for (auto & i : attrPath) {
nrLookups++;
Bindings::iterator j;
- Symbol name = getName(*i, state, env);
+ Symbol name = getName(i, state, env);
if (def) {
state.forceValue(*vAttrs);
if (vAttrs->type != tAttrs ||
@@ -859,10 +869,10 @@ void ExprOpHasAttr::eval(EvalState & state, Env & env, Value & v)
e->eval(state, env, vTmp);
- foreach (AttrPath::const_iterator, i, attrPath) {
+ for (auto & i : attrPath) {
state.forceValue(*vAttrs);
Bindings::iterator j;
- Symbol name = getName(*i, state, env);
+ Symbol name = getName(i, state, env);
if (vAttrs->type != tAttrs ||
(j = vAttrs->attrs->find(name)) == vAttrs->attrs->end())
{
@@ -975,12 +985,12 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v, const Pos & po
there is no matching actual argument but the formal
argument has a default, use the default. */
unsigned int attrsUsed = 0;
- foreach (Formals::Formals_::iterator, i, lambda.formals->formals) {
- Bindings::iterator j = arg.attrs->find(i->name);
+ for (auto & i : lambda.formals->formals) {
+ Bindings::iterator j = arg.attrs->find(i.name);
if (j == arg.attrs->end()) {
- if (!i->def) throwTypeError("%1% called without required argument ‘%2%’, at %3%",
- lambda, i->name, pos);
- env2.values[displ++] = i->def->maybeThunk(*this, env2);
+ 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++;
env2.values[displ++] = j->value;
@@ -992,9 +1002,9 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v, const Pos & po
if (!lambda.formals->ellipsis && attrsUsed != arg.attrs->size()) {
/* Nope, so show the first unexpected argument to the
user. */
- foreach (Bindings::iterator, i, *arg.attrs)
- if (lambda.formals->argNames.find(i->name) == lambda.formals->argNames.end())
- throwTypeError("%1% called with unexpected argument ‘%2%’, at %3%", lambda, i->name, pos);
+ for (auto & i : *arg.attrs)
+ if (lambda.formals->argNames.find(i.name) == lambda.formals->argNames.end())
+ throwTypeError("%1% called with unexpected argument ‘%2%’, at %3%", lambda, i.name, pos);
abort(); // can't happen
}
}
@@ -1036,12 +1046,12 @@ void EvalState::autoCallFunction(Bindings & args, Value & fun, Value & res)
Value * actualArgs = allocValue();
mkAttrs(*actualArgs, fun.lambda.fun->formals->formals.size());
- foreach (Formals::Formals_::iterator, i, fun.lambda.fun->formals->formals) {
- Bindings::iterator j = args.find(i->name);
+ for (auto & i : fun.lambda.fun->formals->formals) {
+ Bindings::iterator j = args.find(i.name);
if (j != args.end())
actualArgs->attrs->push_back(*j);
- else if (!i->def)
- throwTypeError("cannot auto-call a function that has an argument without a default value (‘%1%’)", i->name);
+ else if (!i.def)
+ throwTypeError("cannot auto-call a function that has an argument without a default value (‘%1%’)", i.name);
}
actualArgs->attrs->sort();
@@ -1169,20 +1179,21 @@ void EvalState::concatLists(Value & v, unsigned int nrLists, Value * * lists, co
unsigned int len = 0;
for (unsigned int n = 0; n < nrLists; ++n) {
forceList(*lists[n], pos);
- unsigned int l = lists[n]->list.length;
+ unsigned int l = lists[n]->listSize();
len += l;
if (l) nonEmpty = lists[n];
}
- if (nonEmpty && len == nonEmpty->list.length) {
+ if (nonEmpty && len == nonEmpty->listSize()) {
v = *nonEmpty;
return;
}
mkList(v, len);
+ auto out = v.listElems();
for (unsigned int n = 0, pos = 0; n < nrLists; ++n) {
- unsigned int l = lists[n]->list.length;
- memcpy(v.list.elems + pos, lists[n]->list.elems, l * sizeof(Value *));
+ unsigned int l = lists[n]->listSize();
+ memcpy(out + pos, lists[n]->listElems(), l * sizeof(Value *));
pos += l;
}
}
@@ -1197,9 +1208,9 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v)
bool first = !forceString;
ValueType firstType = tString;
- foreach (vector<Expr *>::iterator, i, *es) {
+ for (auto & i : *es) {
Value vTmp;
- (*i)->eval(state, env, vTmp);
+ i->eval(state, env, vTmp);
/* If the first element is a path, then the result will also
be a path, we don't copy anything (yet - that's done later,
@@ -1258,9 +1269,9 @@ void EvalState::forceValueDeep(Value & v)
}
}
- else if (v.type == tList) {
- for (unsigned int n = 0; n < v.list.length; ++n)
- recurse(*v.list.elems[n]);
+ else if (v.isList()) {
+ for (unsigned int n = 0; n < v.listSize(); ++n)
+ recurse(*v.listElems()[n]);
}
};
@@ -1384,14 +1395,14 @@ string EvalState::coerceToString(const Pos & pos, Value & v, PathSet & context,
if (v.type == tInt) return int2String(v.integer);
if (v.type == tNull) return "";
- if (v.type == tList) {
+ if (v.isList()) {
string result;
- for (unsigned int n = 0; n < v.list.length; ++n) {
- result += coerceToString(pos, *v.list.elems[n],
+ for (unsigned int n = 0; n < v.listSize(); ++n) {
+ result += coerceToString(pos, *v.listElems()[n],
context, coerceMore, copyToStore);
- if (n < v.list.length - 1
+ if (n < v.listSize() - 1
/* !!! not quite correct */
- && (v.list.elems[n]->type != tList || v.list.elems[n]->list.length != 0))
+ && (!v.listElems()[n]->isList() || v.listElems()[n]->listSize() != 0))
result += " ";
}
return result;
@@ -1462,10 +1473,12 @@ bool EvalState::eqValues(Value & v1, Value & v2)
case tNull:
return true;
- case tList:
- if (v1.list.length != v2.list.length) return false;
- for (unsigned int n = 0; n < v1.list.length; ++n)
- if (!eqValues(*v1.list.elems[n], *v2.list.elems[n])) return false;
+ case tList1:
+ case tList2:
+ case tListN:
+ if (v1.listSize() != v2.listSize()) return false;
+ for (unsigned int n = 0; n < v1.listSize(); ++n)
+ if (!eqValues(*v1.listElems()[n], *v2.listElems()[n])) return false;
return true;
case tAttrs: {
@@ -1551,25 +1564,25 @@ void EvalState::printStats()
printMsg(v, format("calls to %1% primops:") % primOpCalls.size());
typedef std::multimap<unsigned int, Symbol> PrimOpCalls_;
PrimOpCalls_ primOpCalls_;
- foreach (PrimOpCalls::iterator, i, primOpCalls)
- primOpCalls_.insert(std::pair<unsigned int, Symbol>(i->second, i->first));
- foreach_reverse (PrimOpCalls_::reverse_iterator, i, primOpCalls_)
+ for (auto & i : primOpCalls)
+ primOpCalls_.insert(std::pair<unsigned int, Symbol>(i.second, i.first));
+ for (auto i = primOpCalls_.rbegin(); i != primOpCalls_.rend(); ++i)
printMsg(v, format("%1$10d %2%") % i->first % i->second);
printMsg(v, format("calls to %1% functions:") % functionCalls.size());
typedef std::multimap<unsigned int, ExprLambda *> FunctionCalls_;
FunctionCalls_ functionCalls_;
- foreach (FunctionCalls::iterator, i, functionCalls)
- functionCalls_.insert(std::pair<unsigned int, ExprLambda *>(i->second, i->first));
- foreach_reverse (FunctionCalls_::reverse_iterator, i, functionCalls_)
+ for (auto & i : functionCalls)
+ functionCalls_.insert(std::pair<unsigned int, ExprLambda *>(i.second, i.first));
+ for (auto i = functionCalls_.rbegin(); i != functionCalls_.rend(); ++i)
printMsg(v, format("%1$10d %2%") % i->first % i->second->showNamePos());
printMsg(v, format("evaluations of %1% attributes:") % attrSelects.size());
typedef std::multimap<unsigned int, Pos> AttrSelects_;
AttrSelects_ attrSelects_;
- foreach (AttrSelects::iterator, i, attrSelects)
- attrSelects_.insert(std::pair<unsigned int, Pos>(i->second, i->first));
- foreach_reverse (AttrSelects_::reverse_iterator, i, attrSelects_)
+ for (auto & i : attrSelects)
+ attrSelects_.insert(std::pair<unsigned int, Pos>(i.second, i.first));
+ for (auto i = attrSelects_.rbegin(); i != attrSelects_.rend(); ++i)
printMsg(v, format("%1$10d %2%") % i->first % i->second);
}
@@ -1613,12 +1626,14 @@ size_t valueSize(Value & v)
sz += doValue(*i.value);
}
break;
- case tList:
- if (seen.find(v.list.elems) == seen.end()) {
- seen.insert(v.list.elems);
- sz += v.list.length * sizeof(Value *);
- for (unsigned int n = 0; n < v.list.length; ++n)
- sz += doValue(*v.list.elems[n]);
+ case tList1:
+ case tList2:
+ case tListN:
+ if (seen.find(v.listElems()) == seen.end()) {
+ seen.insert(v.listElems());
+ sz += v.listSize() * sizeof(Value *);
+ for (unsigned int n = 0; n < v.listSize(); ++n)
+ sz += doValue(*v.listElems()[n]);
}
break;
case tThunk:
diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc
index 1c9fa02a3..1002ee628 100644
--- a/src/libexpr/get-drvs.cc
+++ b/src/libexpr/get-drvs.cc
@@ -39,9 +39,9 @@ DrvInfo::Outputs DrvInfo::queryOutputs()
state->forceList(*i->value, *i->pos);
/* For each output... */
- for (unsigned int j = 0; j < i->value->list.length; ++j) {
+ for (unsigned int j = 0; j < i->value->listSize(); ++j) {
/* Evaluate the corresponding set. */
- string name = state->forceStringNoCtx(*i->value->list.elems[j], *i->pos);
+ string name = state->forceStringNoCtx(*i->value->listElems()[j], *i->pos);
Bindings::iterator out = attrs->find(state->symbols.create(name));
if (out == attrs->end()) continue; // FIXME: throw error?
state->forceAttrs(*out->value);
@@ -85,8 +85,8 @@ StringSet DrvInfo::queryMetaNames()
{
StringSet res;
if (!getMeta()) return res;
- foreach (Bindings::iterator, i, *meta)
- res.insert(i->name);
+ for (auto & i : *meta)
+ res.insert(i.name);
return res;
}
@@ -94,16 +94,16 @@ StringSet DrvInfo::queryMetaNames()
bool DrvInfo::checkMeta(Value & v)
{
state->forceValue(v);
- if (v.type == tList) {
- for (unsigned int n = 0; n < v.list.length; ++n)
- if (!checkMeta(*v.list.elems[n])) return false;
+ if (v.isList()) {
+ for (unsigned int n = 0; n < v.listSize(); ++n)
+ if (!checkMeta(*v.listElems()[n])) return false;
return true;
}
else if (v.type == tAttrs) {
Bindings::iterator i = v.attrs->find(state->sOutPath);
if (i != v.attrs->end()) return false;
- foreach (Bindings::iterator, i, *v.attrs)
- if (!checkMeta(*i->value)) return false;
+ for (auto & i : *v.attrs)
+ if (!checkMeta(*i.value)) return false;
return true;
}
else return v.type == tInt || v.type == tBool || v.type == tString;
@@ -255,13 +255,13 @@ static void getDerivations(EvalState & state, Value & vIn,
precedence). */
typedef std::map<string, Symbol> SortedSymbols;
SortedSymbols attrs;
- foreach (Bindings::iterator, i, *v.attrs)
- attrs.insert(std::pair<string, Symbol>(i->name, i->name));
+ for (auto & i : *v.attrs)
+ attrs.insert(std::pair<string, Symbol>(i.name, i.name));
- foreach (SortedSymbols::iterator, i, attrs) {
- startNest(nest, lvlDebug, format("evaluating attribute ‘%1%’") % i->first);
- string pathPrefix2 = addToPath(pathPrefix, i->first);
- Value & v2(*v.attrs->find(i->second)->value);
+ for (auto & i : attrs) {
+ startNest(nest, lvlDebug, format("evaluating attribute ‘%1%’") % i.first);
+ string pathPrefix2 = addToPath(pathPrefix, i.first);
+ Value & v2(*v.attrs->find(i.second)->value);
if (combineChannels)
getDerivations(state, v2, pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures);
else if (getDerivation(state, v2, pathPrefix2, drvs, done, ignoreAssertionFailures)) {
@@ -277,13 +277,13 @@ static void getDerivations(EvalState & state, Value & vIn,
}
}
- else if (v.type == tList) {
- for (unsigned int n = 0; n < v.list.length; ++n) {
+ else if (v.isList()) {
+ for (unsigned int n = 0; n < v.listSize(); ++n) {
startNest(nest, lvlDebug,
format("evaluating list element"));
string pathPrefix2 = addToPath(pathPrefix, (format("%1%") % n).str());
- if (getDerivation(state, *v.list.elems[n], pathPrefix2, drvs, done, ignoreAssertionFailures))
- getDerivations(state, *v.list.elems[n], pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures);
+ if (getDerivation(state, *v.listElems()[n], pathPrefix2, drvs, done, ignoreAssertionFailures))
+ getDerivations(state, *v.listElems()[n], pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures);
}
}
diff --git a/src/libexpr/json-to-value.cc b/src/libexpr/json-to-value.cc
index 1892b0bac..0898b5609 100644
--- a/src/libexpr/json-to-value.cc
+++ b/src/libexpr/json-to-value.cc
@@ -73,7 +73,7 @@ static void parseJSON(EvalState & state, const char * & s, Value & v)
s++;
state.mkList(v, values.size());
for (size_t n = 0; n < values.size(); ++n)
- v.list.elems[n] = values[n];
+ v.listElems()[n] = values[n];
}
else if (*s == '{') {
diff --git a/src/libexpr/local.mk b/src/libexpr/local.mk
index 35e84980a..4c1f4de19 100644
--- a/src/libexpr/local.mk
+++ b/src/libexpr/local.mk
@@ -8,7 +8,7 @@ libexpr_SOURCES := $(wildcard $(d)/*.cc) $(d)/lexer-tab.cc $(d)/parser-tab.cc
libexpr_LIBS = libutil libstore libformat
-libexpr_LDFLAGS = -ldl -lcurl
+libexpr_LDFLAGS = -ldl
# The dependency on libgc must be propagated (i.e. meaning that
# programs/libraries that use libexpr must explicitly pass -lgc),
diff --git a/src/libexpr/names.cc b/src/libexpr/names.cc
index cda5aa195..7bca9b655 100644
--- a/src/libexpr/names.cc
+++ b/src/libexpr/names.cc
@@ -98,8 +98,8 @@ int compareVersions(const string & v1, const string & v2)
DrvNames drvNamesFromArgs(const Strings & opArgs)
{
DrvNames result;
- foreach (Strings::const_iterator, i, opArgs)
- result.push_back(DrvName(*i));
+ for (auto & i : opArgs)
+ result.push_back(DrvName(i));
return result;
}
diff --git a/src/libexpr/nixexpr.cc b/src/libexpr/nixexpr.cc
index 43f3161f8..35db52a13 100644
--- a/src/libexpr/nixexpr.cc
+++ b/src/libexpr/nixexpr.cc
@@ -97,21 +97,21 @@ void ExprAttrs::show(std::ostream & str)
{
if (recursive) str << "rec ";
str << "{ ";
- foreach (AttrDefs::iterator, i, attrs)
- if (i->second.inherited)
- str << "inherit " << i->first << " " << "; ";
+ for (auto & i : attrs)
+ if (i.second.inherited)
+ str << "inherit " << i.first << " " << "; ";
else
- str << i->first << " = " << *i->second.e << "; ";
- foreach (DynamicAttrDefs::iterator, i, dynamicAttrs)
- str << "\"${" << *i->nameExpr << "}\" = " << *i->valueExpr << "; ";
+ str << i.first << " = " << *i.second.e << "; ";
+ for (auto & i : dynamicAttrs)
+ str << "\"${" << *i.nameExpr << "}\" = " << *i.valueExpr << "; ";
str << "}";
}
void ExprList::show(std::ostream & str)
{
str << "[ ";
- foreach (vector<Expr *>::iterator, i, elems)
- str << "(" << **i << ") ";
+ for (auto & i : elems)
+ str << "(" << *i << ") ";
str << "]";
}
@@ -121,10 +121,10 @@ void ExprLambda::show(std::ostream & str)
if (matchAttrs) {
str << "{ ";
bool first = true;
- foreach (Formals::Formals_::iterator, i, formals->formals) {
+ for (auto & i : formals->formals) {
if (first) first = false; else str << ", ";
- str << i->name;
- if (i->def) str << " ? " << *i->def;
+ str << i.name;
+ if (i.def) str << " ? " << *i.def;
}
if (formals->ellipsis) {
if (!first) str << ", ";
@@ -140,12 +140,12 @@ void ExprLambda::show(std::ostream & str)
void ExprLet::show(std::ostream & str)
{
str << "(let ";
- foreach (ExprAttrs::AttrDefs::iterator, i, attrs->attrs)
- if (i->second.inherited) {
- str << "inherit " << i->first << "; ";
+ for (auto & i : attrs->attrs)
+ if (i.second.inherited) {
+ str << "inherit " << i.first << "; ";
}
else
- str << i->first << " = " << *i->second.e << "; ";
+ str << i.first << " = " << *i.second.e << "; ";
str << "in " << *body << ")";
}
@@ -173,9 +173,9 @@ void ExprConcatStrings::show(std::ostream & str)
{
bool first = true;
str << "(";
- foreach (vector<Expr *>::iterator, i, *es) {
+ for (auto & i : *es) {
if (first) first = false; else str << " + ";
- str << **i;
+ str << *i;
}
str << ")";
}
@@ -267,17 +267,17 @@ void ExprSelect::bindVars(const StaticEnv & env)
{
e->bindVars(env);
if (def) def->bindVars(env);
- foreach (AttrPath::iterator, i, attrPath)
- if (!i->symbol.set())
- i->expr->bindVars(env);
+ for (auto & i : attrPath)
+ if (!i.symbol.set())
+ i.expr->bindVars(env);
}
void ExprOpHasAttr::bindVars(const StaticEnv & env)
{
e->bindVars(env);
- foreach (AttrPath::iterator, i, attrPath)
- if (!i->symbol.set())
- i->expr->bindVars(env);
+ for (auto & i : attrPath)
+ if (!i.symbol.set())
+ i.expr->bindVars(env);
}
void ExprAttrs::bindVars(const StaticEnv & env)
@@ -289,27 +289,27 @@ void ExprAttrs::bindVars(const StaticEnv & env)
dynamicEnv = &newEnv;
unsigned int displ = 0;
- foreach (AttrDefs::iterator, i, attrs)
- newEnv.vars[i->first] = i->second.displ = displ++;
+ for (auto & i : attrs)
+ newEnv.vars[i.first] = i.second.displ = displ++;
- foreach (AttrDefs::iterator, i, attrs)
- i->second.e->bindVars(i->second.inherited ? env : newEnv);
+ for (auto & i : attrs)
+ i.second.e->bindVars(i.second.inherited ? env : newEnv);
}
else
- foreach (AttrDefs::iterator, i, attrs)
- i->second.e->bindVars(env);
+ for (auto & i : attrs)
+ i.second.e->bindVars(env);
- foreach (DynamicAttrDefs::iterator, i, dynamicAttrs) {
- i->nameExpr->bindVars(*dynamicEnv);
- i->valueExpr->bindVars(*dynamicEnv);
+ for (auto & i : dynamicAttrs) {
+ i.nameExpr->bindVars(*dynamicEnv);
+ i.valueExpr->bindVars(*dynamicEnv);
}
}
void ExprList::bindVars(const StaticEnv & env)
{
- foreach (vector<Expr *>::iterator, i, elems)
- (*i)->bindVars(env);
+ for (auto & i : elems)
+ i->bindVars(env);
}
void ExprLambda::bindVars(const StaticEnv & env)
@@ -321,11 +321,11 @@ void ExprLambda::bindVars(const StaticEnv & env)
if (!arg.empty()) newEnv.vars[arg] = displ++;
if (matchAttrs) {
- foreach (Formals::Formals_::iterator, i, formals->formals)
- newEnv.vars[i->name] = displ++;
+ for (auto & i : formals->formals)
+ newEnv.vars[i.name] = displ++;
- foreach (Formals::Formals_::iterator, i, formals->formals)
- if (i->def) i->def->bindVars(newEnv);
+ for (auto & i : formals->formals)
+ if (i.def) i.def->bindVars(newEnv);
}
body->bindVars(newEnv);
@@ -336,11 +336,11 @@ void ExprLet::bindVars(const StaticEnv & env)
StaticEnv newEnv(false, &env);
unsigned int displ = 0;
- foreach (ExprAttrs::AttrDefs::iterator, i, attrs->attrs)
- newEnv.vars[i->first] = i->second.displ = displ++;
+ for (auto & i : attrs->attrs)
+ newEnv.vars[i.first] = i.second.displ = displ++;
- foreach (ExprAttrs::AttrDefs::iterator, i, attrs->attrs)
- i->second.e->bindVars(i->second.inherited ? env : newEnv);
+ for (auto & i : attrs->attrs)
+ i.second.e->bindVars(i.second.inherited ? env : newEnv);
body->bindVars(newEnv);
}
@@ -384,8 +384,8 @@ void ExprOpNot::bindVars(const StaticEnv & env)
void ExprConcatStrings::bindVars(const StaticEnv & env)
{
- foreach (vector<Expr *>::iterator, i, *es)
- (*i)->bindVars(env);
+ for (auto & i : *es)
+ i->bindVars(env);
}
void ExprPos::bindVars(const StaticEnv & env)
@@ -419,8 +419,8 @@ string ExprLambda::showNamePos() const
size_t SymbolTable::totalSize() const
{
size_t n = 0;
- foreach (Symbols::const_iterator, i, symbols)
- n += i->size();
+ for (auto & i : symbols)
+ n += i.size();
return n;
}
diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y
index 1f830b7e3..d34882f36 100644
--- a/src/libexpr/parser.y
+++ b/src/libexpr/parser.y
@@ -136,8 +136,8 @@ static Expr * stripIndentation(const Pos & pos, SymbolTable & symbols, vector<Ex
bool atStartOfLine = true; /* = seen only whitespace in the current line */
unsigned int minIndent = 1000000;
unsigned int curIndent = 0;
- foreach (vector<Expr *>::iterator, i, es) {
- ExprIndStr * e = dynamic_cast<ExprIndStr *>(*i);
+ for (auto & i : es) {
+ ExprIndStr * e = dynamic_cast<ExprIndStr *>(i);
if (!e) {
/* Anti-quotations end the current start-of-line whitespace. */
if (atStartOfLine) {
@@ -419,20 +419,20 @@ binds
: binds attrpath '=' expr ';' { $$ = $1; addAttr($$, *$2, $4, makeCurPos(@2, data)); }
| binds INHERIT attrs ';'
{ $$ = $1;
- foreach (AttrPath::iterator, i, *$3) {
- if ($$->attrs.find(i->symbol) != $$->attrs.end())
- dupAttr(i->symbol, makeCurPos(@3, data), $$->attrs[i->symbol].pos);
+ for (auto & i : *$3) {
+ if ($$->attrs.find(i.symbol) != $$->attrs.end())
+ dupAttr(i.symbol, makeCurPos(@3, data), $$->attrs[i.symbol].pos);
Pos pos = makeCurPos(@3, data);
- $$->attrs[i->symbol] = ExprAttrs::AttrDef(new ExprVar(CUR_POS, i->symbol), pos, true);
+ $$->attrs[i.symbol] = ExprAttrs::AttrDef(new ExprVar(CUR_POS, i.symbol), pos, true);
}
}
| binds INHERIT '(' expr ')' attrs ';'
{ $$ = $1;
/* !!! Should ensure sharing of the expression in $4. */
- foreach (AttrPath::iterator, i, *$6) {
- if ($$->attrs.find(i->symbol) != $$->attrs.end())
- dupAttr(i->symbol, makeCurPos(@6, data), $$->attrs[i->symbol].pos);
- $$->attrs[i->symbol] = ExprAttrs::AttrDef(new ExprSelect(CUR_POS, $4, i->symbol), makeCurPos(@6, data));
+ for (auto & i : *$6) {
+ if ($$->attrs.find(i.symbol) != $$->attrs.end())
+ dupAttr(i.symbol, makeCurPos(@6, data), $$->attrs[i.symbol].pos);
+ $$->attrs[i.symbol] = ExprAttrs::AttrDef(new ExprSelect(CUR_POS, $4, i.symbol), makeCurPos(@6, data));
}
}
| { $$ = new ExprAttrs; }
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index 355b81adf..7a4aad3cd 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -86,9 +86,11 @@ static void prim_scopedImport(EvalState & state, const Pos & pos, Value * * args
if (isStorePath(path) && store->isValidPath(path) && isDerivation(path)) {
Derivation drv = readDerivation(path);
Value & w = *state.allocValue();
- state.mkAttrs(w, 2 + drv.outputs.size());
+ state.mkAttrs(w, 3 + drv.outputs.size());
Value * v2 = state.allocAttr(w, state.sDrvPath);
mkString(*v2, path, singleton<PathSet>("=" + path));
+ v2 = state.allocAttr(w, state.sName);
+ mkString(*v2, drv.env["name"]);
Value * outputsVal =
state.allocAttr(w, state.symbols.create("outputs"));
state.mkList(*outputsVal, drv.outputs.size());
@@ -98,8 +100,8 @@ static void prim_scopedImport(EvalState & state, const Pos & pos, Value * * args
v2 = state.allocAttr(w, state.symbols.create(o.first));
mkString(*v2, o.second.path,
singleton<PathSet>("!" + o.first + "!" + path));
- outputsVal->list.elems[outputs_index] = state.allocValue();
- mkString(*(outputsVal->list.elems[outputs_index++]), o.first);
+ outputsVal->listElems()[outputs_index] = state.allocValue();
+ mkString(*(outputsVal->listElems()[outputs_index++]), o.first);
}
w.attrs->sort();
Value fun;
@@ -186,7 +188,7 @@ static void prim_typeOf(EvalState & state, const Pos & pos, Value * * args, Valu
case tPath: t = "path"; break;
case tNull: t = "null"; break;
case tAttrs: t = "set"; break;
- case tList: t = "list"; break;
+ case tList1: case tList2: case tListN: t = "list"; break;
case tLambda:
case tPrimOp:
case tPrimOpApp:
@@ -282,8 +284,8 @@ static void prim_genericClosure(EvalState & state, const Pos & pos, Value * * ar
state.forceList(*startSet->value, pos);
ValueList workSet;
- for (unsigned int n = 0; n < startSet->value->list.length; ++n)
- workSet.push_back(startSet->value->list.elems[n]);
+ for (unsigned int n = 0; n < startSet->value->listSize(); ++n)
+ workSet.push_back(startSet->value->listElems()[n]);
/* Get the operator. */
Bindings::iterator op =
@@ -321,17 +323,17 @@ static void prim_genericClosure(EvalState & state, const Pos & pos, Value * * ar
state.forceList(call, pos);
/* Add the values returned by the operator to the work set. */
- for (unsigned int n = 0; n < call.list.length; ++n) {
- state.forceValue(*call.list.elems[n]);
- workSet.push_back(call.list.elems[n]);
+ for (unsigned int n = 0; n < call.listSize(); ++n) {
+ state.forceValue(*call.listElems()[n]);
+ workSet.push_back(call.listElems()[n]);
}
}
/* Create the result list. */
state.mkList(v, res.size());
unsigned int n = 0;
- foreach (ValueList::iterator, i, res)
- v.list.elems[n++] = *i;
+ for (auto & i : res)
+ v.listElems()[n++] = i;
}
@@ -477,24 +479,24 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
StringSet outputs;
outputs.insert("out");
- foreach (Bindings::iterator, i, *args[0]->attrs) {
- if (i->name == state.sIgnoreNulls) continue;
- string key = i->name;
+ for (auto & i : *args[0]->attrs) {
+ if (i.name == state.sIgnoreNulls) continue;
+ string key = i.name;
startNest(nest, lvlVomit, format("processing attribute ‘%1%’") % key);
try {
if (ignoreNulls) {
- state.forceValue(*i->value);
- if (i->value->type == tNull) continue;
+ state.forceValue(*i.value);
+ if (i.value->type == tNull) continue;
}
/* The `args' attribute is special: it supplies the
command-line arguments to the builder. */
if (key == "args") {
- state.forceList(*i->value, pos);
- for (unsigned int n = 0; n < i->value->list.length; ++n) {
- string s = state.coerceToString(posDrvName, *i->value->list.elems[n], context, true);
+ state.forceList(*i.value, pos);
+ for (unsigned int n = 0; n < i.value->listSize(); ++n) {
+ string s = state.coerceToString(posDrvName, *i.value->listElems()[n], context, true);
drv.args.push_back(s);
}
}
@@ -502,11 +504,11 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
/* All other attributes are passed to the builder through
the environment. */
else {
- string s = state.coerceToString(posDrvName, *i->value, context, true);
+ string s = state.coerceToString(posDrvName, *i.value, context, true);
drv.env[key] = s;
if (key == "builder") drv.builder = s;
- else if (i->name == state.sSystem) drv.platform = s;
- else if (i->name == state.sName) {
+ else if (i.name == state.sSystem) drv.platform = s;
+ else if (i.name == state.sName) {
drvName = s;
printMsg(lvlVomit, format("derivation name is ‘%1%’") % drvName);
}
@@ -520,17 +522,17 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
else if (key == "outputs") {
Strings tmp = tokenizeString<Strings>(s);
outputs.clear();
- foreach (Strings::iterator, j, tmp) {
- if (outputs.find(*j) != outputs.end())
- throw EvalError(format("duplicate derivation output ‘%1%’, at %2%") % *j % posDrvName);
- /* !!! Check whether *j is a valid attribute
+ for (auto & j : tmp) {
+ 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);
+ outputs.insert(j);
}
if (outputs.empty())
throw EvalError(format("derivation cannot have an empty set of outputs, at %1%") % posDrvName);
@@ -547,8 +549,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
/* Everything in the context of the strings in the derivation
attributes should be added as dependencies of the resulting
derivation. */
- foreach (PathSet::iterator, i, context) {
- Path path = *i;
+ for (auto & path : context) {
/* Paths marked with `=' denote that the path of a derivation
is explicitly passed to the builder. Since that allows the
@@ -560,10 +561,10 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
if (path.at(0) == '=') {
/* !!! This doesn't work if readOnlyMode is set. */
PathSet refs; computeFSClosure(*store, string(path, 1), refs);
- foreach (PathSet::iterator, j, refs) {
- drv.inputSrcs.insert(*j);
- if (isDerivation(*j))
- drv.inputDrvs[*j] = store->queryDerivationOutputNames(*j);
+ for (auto & j : refs) {
+ drv.inputSrcs.insert(j);
+ if (isDerivation(j))
+ drv.inputDrvs[j] = store->queryDerivationOutputNames(j);
}
}
@@ -622,20 +623,20 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
are empty, and the corresponding environment variables have
an empty value. This ensures that changes in the set of
output names do get reflected in the hash. */
- foreach (StringSet::iterator, i, outputs) {
- drv.env[*i] = "";
- drv.outputs[*i] = DerivationOutput("", "", "");
+ for (auto & i : outputs) {
+ drv.env[i] = "";
+ drv.outputs[i] = DerivationOutput("", "", "");
}
/* Use the masked derivation expression to compute the output
path. */
Hash h = hashDerivationModulo(*store, drv);
- foreach (DerivationOutputs::iterator, i, drv.outputs)
- if (i->second.path == "") {
- Path outPath = makeOutputPath(i->first, h, drvName);
- drv.env[i->first] = outPath;
- i->second.path = outPath;
+ for (auto & i : drv.outputs)
+ if (i.second.path == "") {
+ Path outPath = makeOutputPath(i.first, h, drvName);
+ drv.env[i.first] = outPath;
+ i.second.path = outPath;
}
}
@@ -652,9 +653,9 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
state.mkAttrs(v, 1 + drv.outputs.size());
mkString(*state.allocAttr(v, state.sDrvPath), drvPath, singleton<PathSet>("=" + drvPath));
- foreach (DerivationOutputs::iterator, i, drv.outputs) {
- mkString(*state.allocAttr(v, state.symbols.create(i->first)),
- i->second.path, singleton<PathSet>("!" + i->first + "!" + drvPath));
+ for (auto & i : drv.outputs) {
+ mkString(*state.allocAttr(v, state.symbols.create(i.first)),
+ i.second.path, singleton<PathSet>("!" + i.first + "!" + drvPath));
}
v.attrs->sort();
}
@@ -765,8 +766,8 @@ static void prim_findFile(EvalState & state, const Pos & pos, Value * * args, Va
SearchPath searchPath;
PathSet context;
- for (unsigned int n = 0; n < args[0]->list.length; ++n) {
- Value & v2(*args[0]->list.elems[n]);
+ for (unsigned int n = 0; n < args[0]->listSize(); ++n) {
+ Value & v2(*args[0]->listElems()[n]);
state.forceAttrs(v2, pos);
string prefix;
@@ -871,11 +872,14 @@ static void prim_toFile(EvalState & state, const Pos & pos, Value * * args, Valu
PathSet refs;
- foreach (PathSet::iterator, i, context) {
- Path path = *i;
+ for (auto path : context) {
if (path.at(0) == '=') path = string(path, 1);
- if (isDerivation(path))
- throw EvalError(format("in ‘toFile’: the file ‘%1%’ cannot refer to derivation outputs, at %2%") % name % pos);
+ if (isDerivation(path)) {
+ /* See prim_unsafeDiscardOutputDependency. */
+ if (path.at(0) != '~')
+ throw EvalError(format("in ‘toFile’: the file ‘%1%’ cannot refer to derivation outputs, at %2%") % name % pos);
+ path = string(path, 1);
+ }
refs.insert(path);
}
@@ -968,9 +972,9 @@ static void prim_attrNames(EvalState & state, const Pos & pos, Value * * args, V
unsigned int n = 0;
for (auto & i : *args[0]->attrs)
- mkString(*(v.list.elems[n++] = state.allocValue()), i.name);
+ mkString(*(v.listElems()[n++] = state.allocValue()), i.name);
- std::sort(v.list.elems, v.list.elems + n,
+ std::sort(v.listElems(), v.listElems() + n,
[](Value * v1, Value * v2) { return strcmp(v1->string.s, v2->string.s) < 0; });
}
@@ -985,13 +989,13 @@ static void prim_attrValues(EvalState & state, const Pos & pos, Value * * args,
unsigned int n = 0;
for (auto & i : *args[0]->attrs)
- v.list.elems[n++] = (Value *) &i;
+ v.listElems()[n++] = (Value *) &i;
- std::sort(v.list.elems, v.list.elems + n,
+ std::sort(v.listElems(), v.listElems() + n,
[](Value * v1, Value * v2) { return (string) ((Attr *) v1)->name < (string) ((Attr *) v2)->name; });
for (unsigned int i = 0; i < n; ++i)
- v.list.elems[i] = ((Attr *) v.list.elems[i])->value;
+ v.listElems()[i] = ((Attr *) v.listElems()[i])->value;
}
@@ -1048,18 +1052,18 @@ static void prim_removeAttrs(EvalState & state, const Pos & pos, Value * * args,
/* Get the attribute names to be removed. */
std::set<Symbol> names;
- for (unsigned int i = 0; i < args[1]->list.length; ++i) {
- state.forceStringNoCtx(*args[1]->list.elems[i], pos);
- names.insert(state.symbols.create(args[1]->list.elems[i]->string.s));
+ for (unsigned int i = 0; i < args[1]->listSize(); ++i) {
+ state.forceStringNoCtx(*args[1]->listElems()[i], pos);
+ names.insert(state.symbols.create(args[1]->listElems()[i]->string.s));
}
/* Copy all attributes not in that set. Note that we don't need
to sort v.attrs because it's a subset of an already sorted
vector. */
state.mkAttrs(v, args[0]->attrs->size());
- foreach (Bindings::iterator, i, *args[0]->attrs) {
- if (names.find(i->name) == names.end())
- v.attrs->push_back(*i);
+ for (auto & i : *args[0]->attrs) {
+ if (names.find(i.name) == names.end())
+ v.attrs->push_back(i);
}
}
@@ -1073,12 +1077,12 @@ static void prim_listToAttrs(EvalState & state, const Pos & pos, Value * * args,
{
state.forceList(*args[0], pos);
- state.mkAttrs(v, args[0]->list.length);
+ state.mkAttrs(v, args[0]->listSize());
std::set<Symbol> seen;
- for (unsigned int i = 0; i < args[0]->list.length; ++i) {
- Value & v2(*args[0]->list.elems[i]);
+ for (unsigned int i = 0; i < args[0]->listSize(); ++i) {
+ Value & v2(*args[0]->listElems()[i]);
state.forceAttrs(v2, pos);
Bindings::iterator j = v2.attrs->find(state.sName);
@@ -1111,8 +1115,8 @@ static void prim_intersectAttrs(EvalState & state, const Pos & pos, Value * * ar
state.mkAttrs(v, std::min(args[0]->attrs->size(), args[1]->attrs->size()));
- foreach (Bindings::iterator, i, *args[0]->attrs) {
- Bindings::iterator j = args[1]->attrs->find(i->name);
+ for (auto & i : *args[0]->attrs) {
+ Bindings::iterator j = args[1]->attrs->find(i.name);
if (j != args[1]->attrs->end())
v.attrs->push_back(*j);
}
@@ -1131,11 +1135,11 @@ static void prim_catAttrs(EvalState & state, const Pos & pos, Value * * args, Va
Symbol attrName = state.symbols.create(state.forceStringNoCtx(*args[0], pos));
state.forceList(*args[1], pos);
- Value * res[args[1]->list.length];
+ Value * res[args[1]->listSize()];
unsigned int found = 0;
- for (unsigned int n = 0; n < args[1]->list.length; ++n) {
- Value & v2(*args[1]->list.elems[n]);
+ for (unsigned int n = 0; n < args[1]->listSize(); ++n) {
+ Value & v2(*args[1]->listElems()[n]);
state.forceAttrs(v2, pos);
Bindings::iterator i = v2.attrs->find(attrName);
if (i != v2.attrs->end())
@@ -1144,7 +1148,7 @@ static void prim_catAttrs(EvalState & state, const Pos & pos, Value * * args, Va
state.mkList(v, found);
for (unsigned int n = 0; n < found; ++n)
- v.list.elems[n] = res[n];
+ v.listElems()[n] = res[n];
}
@@ -1173,9 +1177,9 @@ static void prim_functionArgs(EvalState & state, const Pos & pos, Value * * args
}
state.mkAttrs(v, args[0]->lambda.fun->formals->formals.size());
- foreach (Formals::Formals_::iterator, 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);
+ mkBool(*state.allocAttr(v, i.name), i.def);
v.attrs->sort();
}
@@ -1189,17 +1193,17 @@ static void prim_functionArgs(EvalState & state, const Pos & pos, Value * * args
static void prim_isList(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
state.forceValue(*args[0]);
- mkBool(v, args[0]->type == tList);
+ mkBool(v, args[0]->isList());
}
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.list.length)
+ 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.list.elems[n]);
- v = *list.list.elems[n];
+ state.forceValue(*list.listElems()[n]);
+ v = *list.listElems()[n];
}
@@ -1223,11 +1227,11 @@ static void prim_head(EvalState & state, const Pos & pos, Value * * args, Value
static void prim_tail(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
state.forceList(*args[0], pos);
- if (args[0]->list.length == 0)
+ if (args[0]->listSize() == 0)
throw Error(format("‘tail’ called on an empty list, at %1%") % pos);
- state.mkList(v, args[0]->list.length - 1);
- for (unsigned int n = 0; n < v.list.length; ++n)
- v.list.elems[n] = args[0]->list.elems[n + 1];
+ state.mkList(v, args[0]->listSize() - 1);
+ for (unsigned int n = 0; n < v.listSize(); ++n)
+ v.listElems()[n] = args[0]->listElems()[n + 1];
}
@@ -1237,11 +1241,11 @@ static void prim_map(EvalState & state, const Pos & pos, Value * * args, Value &
state.forceFunction(*args[0], pos);
state.forceList(*args[1], pos);
- state.mkList(v, args[1]->list.length);
+ state.mkList(v, args[1]->listSize());
- for (unsigned int n = 0; n < v.list.length; ++n)
- mkApp(*(v.list.elems[n] = state.allocValue()),
- *args[0], *args[1]->list.elems[n]);
+ for (unsigned int n = 0; n < v.listSize(); ++n)
+ mkApp(*(v.listElems()[n] = state.allocValue()),
+ *args[0], *args[1]->listElems()[n]);
}
@@ -1254,15 +1258,15 @@ static void prim_filter(EvalState & state, const Pos & pos, Value * * args, Valu
state.forceList(*args[1], pos);
// FIXME: putting this on the stack is risky.
- Value * vs[args[1]->list.length];
+ Value * vs[args[1]->listSize()];
unsigned int k = 0;
bool same = true;
- for (unsigned int n = 0; n < args[1]->list.length; ++n) {
+ for (unsigned int n = 0; n < args[1]->listSize(); ++n) {
Value res;
- state.callFunction(*args[0], *args[1]->list.elems[n], res, noPos);
+ state.callFunction(*args[0], *args[1]->listElems()[n], res, noPos);
if (state.forceBool(res))
- vs[k++] = args[1]->list.elems[n];
+ vs[k++] = args[1]->listElems()[n];
else
same = false;
}
@@ -1271,7 +1275,7 @@ static void prim_filter(EvalState & state, const Pos & pos, Value * * args, Valu
v = *args[1];
else {
state.mkList(v, k);
- for (unsigned int n = 0; n < k; ++n) v.list.elems[n] = vs[n];
+ for (unsigned int n = 0; n < k; ++n) v.listElems()[n] = vs[n];
}
}
@@ -1281,8 +1285,8 @@ static void prim_elem(EvalState & state, const Pos & pos, Value * * args, Value
{
bool res = false;
state.forceList(*args[1], pos);
- for (unsigned int n = 0; n < args[1]->list.length; ++n)
- if (state.eqValues(*args[0], *args[1]->list.elems[n])) {
+ for (unsigned int n = 0; n < args[1]->listSize(); ++n)
+ if (state.eqValues(*args[0], *args[1]->listElems()[n])) {
res = true;
break;
}
@@ -1294,7 +1298,7 @@ static void prim_elem(EvalState & state, const Pos & pos, Value * * args, Value
static void prim_concatLists(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
state.forceList(*args[0], pos);
- state.concatLists(v, args[0]->list.length, args[0]->list.elems, pos);
+ state.concatLists(v, args[0]->listSize(), args[0]->listElems(), pos);
}
@@ -1302,7 +1306,61 @@ static void prim_concatLists(EvalState & state, const Pos & pos, Value * * args,
static void prim_length(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
state.forceList(*args[0], pos);
- mkInt(v, args[0]->list.length);
+ mkInt(v, args[0]->listSize());
+}
+
+
+/* Reduce a list by applying a binary operator, from left to
+ right. The operator is applied strictly. */
+static void prim_foldlStrict(EvalState & state, const Pos & pos, Value * * args, Value & v)
+{
+ state.forceFunction(*args[0], pos);
+ state.forceList(*args[2], pos);
+
+ Value * vCur = args[1];
+
+ if (args[2]->listSize())
+ for (unsigned int n = 0; n < args[2]->listSize(); ++n) {
+ Value vTmp;
+ state.callFunction(*args[0], *vCur, vTmp, pos);
+ vCur = n == args[2]->listSize() - 1 ? &v : state.allocValue();
+ state.callFunction(vTmp, *args[2]->listElems()[n], *vCur, pos);
+ }
+ else
+ v = *vCur;
+
+ state.forceValue(v);
+}
+
+
+static void anyOrAll(bool any, EvalState & state, const Pos & pos, Value * * args, Value & v)
+{
+ state.forceFunction(*args[0], pos);
+ state.forceList(*args[1], pos);
+
+ Value vTmp;
+ for (unsigned int n = 0; n < args[1]->listSize(); ++n) {
+ state.callFunction(*args[0], *args[1]->listElems()[n], vTmp, pos);
+ bool res = state.forceBool(vTmp);
+ if (res == any) {
+ mkBool(v, any);
+ return;
+ }
+ }
+
+ mkBool(v, !any);
+}
+
+
+static void prim_any(EvalState & state, const Pos & pos, Value * * args, Value & v)
+{
+ anyOrAll(true, state, pos, args, v);
+}
+
+
+static void prim_all(EvalState & state, const Pos & pos, Value * * args, Value & v)
+{
+ anyOrAll(false, state, pos, args, v);
}
@@ -1407,11 +1465,8 @@ static void prim_unsafeDiscardOutputDependency(EvalState & state, const Pos & po
string s = state.coerceToString(pos, *args[0], context);
PathSet context2;
- foreach (PathSet::iterator, i, context) {
- Path p = *i;
- if (p.at(0) == '=') p = "~" + string(p, 1);
- context2.insert(p);
- }
+ for (auto & p : context)
+ context2.insert(p.at(0) == '=' ? "~" + string(p, 1) : p);
mkString(v, s, context2);
}
@@ -1452,9 +1507,9 @@ static void prim_match(EvalState & state, const Pos & pos, Value * * args, Value
for (unsigned int n = 0; n < len; ++n) {
auto i = subs.find(n);
if (i == subs.end())
- mkNull(*(v.list.elems[n] = state.allocValue()));
+ mkNull(*(v.listElems()[n] = state.allocValue()));
else
- mkString(*(v.list.elems[n] = state.allocValue()), i->second);
+ mkString(*(v.listElems()[n] = state.allocValue()), i->second);
}
}
@@ -1646,6 +1701,9 @@ void EvalState::createBaseEnv()
addPrimOp("__elem", 2, prim_elem);
addPrimOp("__concatLists", 1, prim_concatLists);
addPrimOp("__length", 1, prim_length);
+ addPrimOp("__foldl'", 3, prim_foldlStrict);
+ addPrimOp("__any", 2, prim_any);
+ addPrimOp("__all", 2, prim_all);
// Integer arithmetic
addPrimOp("__add", 2, prim_add);
@@ -1685,7 +1743,7 @@ void EvalState::createBaseEnv()
mkList(v, searchPath.size());
int n = 0;
for (auto & i : searchPath) {
- v2 = v.list.elems[n++] = allocValue();
+ v2 = v.listElems()[n++] = allocValue();
mkAttrs(*v2, 2);
mkString(*allocAttr(*v2, symbols.create("path")), i.second);
mkString(*allocAttr(*v2, symbols.create("prefix")), i.first);
diff --git a/src/libexpr/value-to-json.cc b/src/libexpr/value-to-json.cc
index cdb713418..b0cf85e21 100644
--- a/src/libexpr/value-to-json.cc
+++ b/src/libexpr/value-to-json.cc
@@ -12,14 +12,14 @@ namespace nix {
void escapeJSON(std::ostream & str, const string & s)
{
str << "\"";
- foreach (string::const_iterator, i, s)
- if (*i == '\"' || *i == '\\') str << "\\" << *i;
- else if (*i == '\n') str << "\\n";
- else if (*i == '\r') str << "\\r";
- else if (*i == '\t') str << "\\t";
- else if (*i >= 0 && *i < 32)
- str << "\\u" << std::setfill('0') << std::setw(4) << std::hex << (uint16_t) *i << std::dec;
- else str << *i;
+ for (auto & i : s)
+ if (i == '\"' || i == '\\') str << "\\" << i;
+ else if (i == '\n') str << "\\n";
+ else if (i == '\r') str << "\\r";
+ else if (i == '\t') str << "\\t";
+ else if (i >= 0 && i < 32)
+ str << "\\u" << std::setfill('0') << std::setw(4) << std::hex << (uint16_t) i << std::dec;
+ else str << i;
str << "\"";
}
@@ -59,11 +59,11 @@ void printValueAsJSON(EvalState & state, bool strict,
if (i == v.attrs->end()) {
JSONObject json(str);
StringSet names;
- foreach (Bindings::iterator, i, *v.attrs)
- names.insert(i->name);
- foreach (StringSet::iterator, i, names) {
- Attr & a(*v.attrs->find(state.symbols.create(*i)));
- json.attr(*i);
+ for (auto & j : *v.attrs)
+ names.insert(j.name);
+ for (auto & j : names) {
+ Attr & a(*v.attrs->find(state.symbols.create(j)));
+ json.attr(j);
printValueAsJSON(state, strict, *a.value, str, context);
}
} else
@@ -71,16 +71,16 @@ void printValueAsJSON(EvalState & state, bool strict,
break;
}
- case tList: {
+ case tList1: case tList2: case tListN: {
JSONList json(str);
- for (unsigned int n = 0; n < v.list.length; ++n) {
+ for (unsigned int n = 0; n < v.listSize(); ++n) {
json.elem();
- printValueAsJSON(state, strict, *v.list.elems[n], str, context);
+ printValueAsJSON(state, strict, *v.listElems()[n], str, context);
}
break;
}
- case tExternal:
+ case tExternal:
v.external->printValueAsJSON(state, strict, str, context);
break;
diff --git a/src/libexpr/value-to-xml.cc b/src/libexpr/value-to-xml.cc
index bbbb7039b..cb52ce1e6 100644
--- a/src/libexpr/value-to-xml.cc
+++ b/src/libexpr/value-to-xml.cc
@@ -8,7 +8,7 @@
namespace nix {
-
+
static XMLAttrs singletonAttrs(const string & name, const string & value)
{
XMLAttrs attrs;
@@ -33,17 +33,17 @@ static void showAttrs(EvalState & state, bool strict, bool location,
Bindings & attrs, XMLWriter & doc, PathSet & context, PathSet & drvsSeen)
{
StringSet names;
-
- foreach (Bindings::iterator, i, attrs)
- names.insert(i->name);
-
- foreach (StringSet::iterator, i, names) {
- Attr & a(*attrs.find(state.symbols.create(*i)));
-
+
+ for (auto & i : attrs)
+ names.insert(i.name);
+
+ for (auto & i : names) {
+ Attr & a(*attrs.find(state.symbols.create(i)));
+
XMLAttrs xmlAttrs;
- xmlAttrs["name"] = *i;
+ xmlAttrs["name"] = i;
if (location && a.pos != &noPos) posToXML(xmlAttrs, *a.pos);
-
+
XMLOpenElement _(doc, "attr", xmlAttrs);
printValueAsXML(state, strict, location,
*a.value, doc, context, drvsSeen);
@@ -57,7 +57,7 @@ static void printValueAsXML(EvalState & state, bool strict, bool location,
checkInterrupt();
if (strict) state.forceValue(v);
-
+
switch (v.type) {
case tInt:
@@ -85,7 +85,7 @@ static void printValueAsXML(EvalState & state, bool strict, bool location,
case tAttrs:
if (state.isDerivation(v)) {
XMLAttrs xmlAttrs;
-
+
Bindings::iterator a = v.attrs->find(state.symbols.create("derivation"));
Path drvPath;
@@ -95,7 +95,7 @@ static void printValueAsXML(EvalState & state, bool strict, bool location,
if (a->value->type == tString)
xmlAttrs["drvPath"] = drvPath = a->value->string.s;
}
-
+
a = v.attrs->find(state.sOutPath);
if (a != v.attrs->end()) {
if (strict) state.forceValue(*a->value);
@@ -116,13 +116,13 @@ static void printValueAsXML(EvalState & state, bool strict, bool location,
XMLOpenElement _(doc, "attrs");
showAttrs(state, strict, location, *v.attrs, doc, context, drvsSeen);
}
-
+
break;
- case tList: {
+ case tList1: case tList2: case tListN: {
XMLOpenElement _(doc, "list");
- for (unsigned int n = 0; n < v.list.length; ++n)
- printValueAsXML(state, strict, location, *v.list.elems[n], doc, context, drvsSeen);
+ for (unsigned int n = 0; n < v.listSize(); ++n)
+ printValueAsXML(state, strict, location, *v.listElems()[n], doc, context, drvsSeen);
break;
}
@@ -130,17 +130,17 @@ static void printValueAsXML(EvalState & state, bool strict, bool location,
XMLAttrs xmlAttrs;
if (location) posToXML(xmlAttrs, v.lambda.fun->pos);
XMLOpenElement _(doc, "function", xmlAttrs);
-
+
if (v.lambda.fun->matchAttrs) {
XMLAttrs attrs;
if (!v.lambda.fun->arg.empty()) attrs["name"] = v.lambda.fun->arg;
if (v.lambda.fun->formals->ellipsis) attrs["ellipsis"] = "1";
XMLOpenElement _(doc, "attrspat", attrs);
- foreach (Formals::Formals_::iterator, i, v.lambda.fun->formals->formals)
- doc.writeEmptyElement("attr", singletonAttrs("name", i->name));
+ for (auto & i : v.lambda.fun->formals->formals)
+ doc.writeEmptyElement("attr", singletonAttrs("name", i.name));
} else
doc.writeEmptyElement("varpat", singletonAttrs("name", v.lambda.fun->arg));
-
+
break;
}
@@ -166,9 +166,9 @@ void printValueAsXML(EvalState & state, bool strict, bool location,
{
XMLWriter doc(true, out);
XMLOpenElement root(doc, "expr");
- PathSet drvsSeen;
+ PathSet drvsSeen;
printValueAsXML(state, strict, location, v, doc, context, drvsSeen);
}
-
+
}
diff --git a/src/libexpr/value.hh b/src/libexpr/value.hh
index c06b5a6d1..e6d1502cb 100644
--- a/src/libexpr/value.hh
+++ b/src/libexpr/value.hh
@@ -12,7 +12,9 @@ typedef enum {
tPath,
tNull,
tAttrs,
- tList,
+ tList1,
+ tList2,
+ tListN,
tThunk,
tApp,
tLambda,
@@ -119,9 +121,10 @@ struct Value
const char * path;
Bindings * attrs;
struct {
- unsigned int length;
+ unsigned int size;
Value * * elems;
- } list;
+ } bigList;
+ Value * smallList[2];
struct {
Env * env;
Expr * expr;
@@ -139,6 +142,26 @@ struct Value
} primOpApp;
ExternalValueBase * external;
};
+
+ bool isList() const
+ {
+ return type == tList1 || type == tList2 || type == tListN;
+ }
+
+ Value * * listElems()
+ {
+ return type == tList1 || type == tList2 ? smallList : bigList.elems;
+ }
+
+ const Value * const * listElems() const
+ {
+ return type == tList1 || type == tList2 ? smallList : bigList.elems;
+ }
+
+ unsigned int listSize() const
+ {
+ return type == tList1 ? 1 : type == tList2 ? 2 : bigList.size;
+ }
};
diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc
index f300fbf1b..a6e8f352a 100644
--- a/src/libmain/shared.cc
+++ b/src/libmain/shared.cc
@@ -90,6 +90,7 @@ static void setLogType(string lt)
if (lt == "pretty") logType = ltPretty;
else if (lt == "escapes") logType = ltEscapes;
else if (lt == "flat") logType = ltFlat;
+ else if (lt == "systemd") logType = ltSystemd;
else throw UsageError("unknown log type");
}
@@ -116,6 +117,9 @@ void initNix()
std::ios::sync_with_stdio(false);
+ if (getEnv("IN_SYSTEMD") == "1")
+ logType = ltSystemd;
+
settings.processEnvironment();
settings.loadConfFile();
@@ -239,6 +243,20 @@ void parseCmdLine(int argc, char * * argv,
void printVersion(const string & programName)
{
std::cout << format("%1% (Nix) %2%") % programName % nixVersion << std::endl;
+ if (verbosity > lvlInfo) {
+ Strings cfg;
+#if HAVE_BOEHMGC
+ cfg.push_back("gc");
+#endif
+#if HAVE_SODIUM
+ cfg.push_back("signed-caches");
+#endif
+ std::cout << "Features: " << concatStringsSep(", ", cfg) << "\n";
+ std::cout << "Configuration file: " << settings.nixConfDir + "/nix.conf" << "\n";
+ std::cout << "Store directory: " << settings.nixStore << "\n";
+ std::cout << "State directory: " << settings.nixStateDir << "\n";
+ std::cout << "Database directory: " << settings.nixDBPath << "\n";
+ }
throw Exit();
}
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index 8c4412f11..e7696e44e 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -8,6 +8,7 @@
#include "util.hh"
#include "archive.hh"
#include "affinity.hh"
+#include "builtins.hh"
#include <map>
#include <sstream>
@@ -94,6 +95,7 @@ struct HookInstance;
/* A pointer to a goal. */
class Goal;
+class DerivationGoal;
typedef std::shared_ptr<Goal> GoalPtr;
typedef std::weak_ptr<Goal> WeakGoalPtr;
@@ -184,10 +186,10 @@ public:
return exitCode;
}
- /* Cancel the goal. It should wake up its waiters, get rid of any
- running child processes that are being monitored by the worker
- (important!), etc. */
- virtual void cancel(bool timeout) = 0;
+ /* Callback in case of a timeout. It should wake up its waiters,
+ get rid of any running child processes that are being monitored
+ by the worker (important!), etc. */
+ virtual void timedOut() = 0;
virtual string key() = 0;
@@ -275,6 +277,8 @@ public:
/* Make a goal (with caching). */
GoalPtr makeDerivationGoal(const Path & drvPath, const StringSet & wantedOutputs, BuildMode buildMode = bmNormal);
+ std::shared_ptr<DerivationGoal> makeBasicDerivationGoal(const Path & drvPath,
+ const BasicDerivation & drv, BuildMode buildMode = bmNormal);
GoalPtr makeSubstitutionGoal(const Path & storePath, bool repair = false);
/* Remove a dead goal. */
@@ -330,8 +334,8 @@ void addToWeakGoals(WeakGoals & goals, GoalPtr p)
{
// FIXME: necessary?
// FIXME: O(n)
- foreach (WeakGoals::iterator, i, goals)
- if (i->lock() == p) return;
+ for (auto & i : goals)
+ if (i.lock() == p) return;
goals.push_back(p);
}
@@ -361,11 +365,10 @@ void Goal::waiteeDone(GoalPtr waitee, ExitCode result)
/* If we failed and keepGoing is not set, we remove all
remaining waitees. */
- foreach (Goals::iterator, i, waitees) {
- GoalPtr goal = *i;
+ for (auto & goal : waitees) {
WeakGoals waiters2;
- foreach (WeakGoals::iterator, j, goal->waiters)
- if (j->lock() != shared_from_this()) waiters2.push_back(*j);
+ for (auto & j : goal->waiters)
+ if (j.lock() != shared_from_this()) waiters2.push_back(j);
goal->waiters = waiters2;
}
waitees.clear();
@@ -381,8 +384,8 @@ void Goal::amDone(ExitCode result)
assert(exitCode == ecBusy);
assert(result == ecSuccess || result == ecFailed || result == ecNoSubstituters || result == ecIncompleteClosure);
exitCode = result;
- foreach (WeakGoals::iterator, i, waiters) {
- GoalPtr goal = i->lock();
+ for (auto & i : waiters) {
+ GoalPtr goal = i.lock();
if (goal) goal->waiteeDone(shared_from_this(), result);
}
waiters.clear();
@@ -508,13 +511,13 @@ void UserLock::acquire()
/* Find a user account that isn't currently in use for another
build. */
- foreach (Strings::iterator, i, users) {
- debug(format("trying user ‘%1%’") % *i);
+ for (auto & i : users) {
+ debug(format("trying user ‘%1%’") % i);
- struct passwd * pw = getpwnam(i->c_str());
+ struct passwd * pw = getpwnam(i.c_str());
if (!pw)
throw Error(format("the user ‘%1%’ in the group ‘%2%’ does not exist")
- % *i % settings.buildUsersGroup);
+ % i % settings.buildUsersGroup);
createDirs(settings.nixStateDir + "/userpool");
@@ -532,7 +535,7 @@ void UserLock::acquire()
if (lockFile(fd, ltWrite, false)) {
fdUserLock = fd.borrow();
lockedPaths.insert(fnUserLock);
- user = *i;
+ user = i;
uid = pw->pw_uid;
/* Sanity check... */
@@ -540,6 +543,7 @@ void UserLock::acquire()
throw Error(format("the Nix user should not be a member of ‘%1%’")
% settings.buildUsersGroup);
+#if __linux__
/* Get the list of supplementary groups of this build user. This
is usually either empty or contains a group such as "kvm". */
supplementaryGIDs.resize(10);
@@ -550,6 +554,7 @@ void UserLock::acquire()
throw Error(format("failed to get list of supplementary groups for ‘%1%’") % pw->pw_name);
supplementaryGIDs.resize(ngroups);
+#endif
return;
}
@@ -668,12 +673,12 @@ typedef map<string, string> HashRewrites;
string rewriteHashes(string s, const HashRewrites & rewrites)
{
- foreach (HashRewrites::const_iterator, i, rewrites) {
- assert(i->first.size() == i->second.size());
+ for (auto & i : rewrites) {
+ assert(i.first.size() == i.second.size());
size_t j = 0;
- while ((j = s.find(i->first, j)) != string::npos) {
+ while ((j = s.find(i.first, j)) != string::npos) {
debug(format("rewriting @ %1%") % j);
- s.replace(j, i->second.size(), i->second);
+ s.replace(j, i.second.size(), i.second);
}
}
return s;
@@ -690,6 +695,9 @@ class SubstitutionGoal;
class DerivationGoal : public Goal
{
private:
+ /* Whether to use an on-disk .drv file. */
+ bool useDerivation;
+
/* The path of the derivation. */
Path drvPath;
@@ -698,14 +706,14 @@ private:
StringSet wantedOutputs;
/* Whether additional wanted outputs have been added. */
- bool needRestart;
+ bool needRestart = false;
/* Whether to retry substituting the outputs after building the
inputs. */
- bool retrySubstitution;
+ bool retrySubstitution = false;
/* The derivation stored at drvPath. */
- Derivation drv;
+ std::unique_ptr<BasicDerivation> drv;
/* The remainder is state held during the build. */
@@ -736,8 +744,8 @@ private:
Path tmpDir;
/* File descriptor for the log file. */
- FILE * fLogFile;
- BZFILE * bzLogFile;
+ FILE * fLogFile = 0;
+ BZFILE * bzLogFile = 0;
AutoCloseFD fdLogFile;
/* Number of bytes received from the builder's stdout/stderr. */
@@ -750,7 +758,7 @@ private:
std::shared_ptr<HookInstance> hook;
/* Whether we're currently doing a chroot build. */
- bool useChroot;
+ bool useChroot = false;
Path chrootRootDir;
@@ -789,11 +797,16 @@ private:
outputs to allow hard links between outputs. */
InodesSeen inodesSeen;
+ BuildResult result;
+
public:
- DerivationGoal(const Path & drvPath, const StringSet & wantedOutputs, Worker & worker, BuildMode buildMode = bmNormal);
+ DerivationGoal(const Path & drvPath, const StringSet & wantedOutputs,
+ Worker & worker, BuildMode buildMode = bmNormal);
+ DerivationGoal(const Path & drvPath, const BasicDerivation & drv,
+ Worker & worker, BuildMode buildMode = bmNormal);
~DerivationGoal();
- void cancel(bool timeout);
+ void timedOut() override;
string key()
{
@@ -814,9 +827,12 @@ public:
/* Add wanted outputs to an already existing derivation goal. */
void addWantedOutputs(const StringSet & outputs);
+ BuildResult getResult() { return result; }
+
private:
/* The states. */
- void init();
+ void getDerivation();
+ void loadDerivation();
void haveDerivation();
void outputsSubstituted();
void closureRepaired();
@@ -864,26 +880,39 @@ private:
Path addHashRewrite(const Path & path);
void repairClosure();
+
+ void done(BuildResult::Status status, const string & msg = "");
};
-DerivationGoal::DerivationGoal(const Path & drvPath, const StringSet & wantedOutputs, Worker & worker, BuildMode buildMode)
+DerivationGoal::DerivationGoal(const Path & drvPath, const StringSet & wantedOutputs,
+ Worker & worker, BuildMode buildMode)
: Goal(worker)
+ , useDerivation(true)
+ , drvPath(drvPath)
, wantedOutputs(wantedOutputs)
- , needRestart(false)
- , retrySubstitution(false)
- , fLogFile(0)
- , bzLogFile(0)
- , useChroot(false)
, buildMode(buildMode)
{
- this->drvPath = drvPath;
- state = &DerivationGoal::init;
+ state = &DerivationGoal::getDerivation;
name = (format("building of ‘%1%’") % drvPath).str();
trace("created");
}
+DerivationGoal::DerivationGoal(const Path & drvPath, const BasicDerivation & drv,
+ Worker & worker, BuildMode buildMode)
+ : Goal(worker)
+ , useDerivation(false)
+ , drvPath(drvPath)
+ , buildMode(buildMode)
+{
+ this->drv = std::unique_ptr<BasicDerivation>(new BasicDerivation(drv));
+ state = &DerivationGoal::haveDerivation;
+ name = (format("building of %1%") % showPaths(outputPaths(drv))).str();
+ trace("created");
+}
+
+
DerivationGoal::~DerivationGoal()
{
/* Careful: we should never ever throw an exception from a
@@ -919,12 +948,12 @@ void DerivationGoal::killChild()
}
-void DerivationGoal::cancel(bool timeout)
+void DerivationGoal::timedOut()
{
- if (settings.printBuildTrace && timeout)
+ if (settings.printBuildTrace)
printMsg(lvlError, format("@ build-failed %1% - timeout") % drvPath);
killChild();
- amDone(ecFailed);
+ done(BuildResult::TimedOut);
}
@@ -943,42 +972,39 @@ void DerivationGoal::addWantedOutputs(const StringSet & outputs)
wantedOutputs.clear();
needRestart = true;
} else
- foreach (StringSet::const_iterator, i, outputs)
- if (wantedOutputs.find(*i) == wantedOutputs.end()) {
- wantedOutputs.insert(*i);
+ for (auto & i : outputs)
+ if (wantedOutputs.find(i) == wantedOutputs.end()) {
+ wantedOutputs.insert(i);
needRestart = true;
}
}
-void DerivationGoal::init()
+void DerivationGoal::getDerivation()
{
trace("init");
- if (settings.readOnlyMode)
- throw Error(format("cannot build derivation ‘%1%’ - no write access to the Nix store") % drvPath);
-
/* The first thing to do is to make sure that the derivation
exists. If it doesn't, it may be created through a
substitute. */
if (buildMode == bmNormal && worker.store.isValidPath(drvPath)) {
- haveDerivation();
+ loadDerivation();
return;
}
addWaitee(worker.makeSubstitutionGoal(drvPath));
- state = &DerivationGoal::haveDerivation;
+ state = &DerivationGoal::loadDerivation;
}
-void DerivationGoal::haveDerivation()
+void DerivationGoal::loadDerivation()
{
trace("loading derivation");
if (nrFailed != 0) {
printMsg(lvlError, format("cannot build missing derivation ‘%1%’") % drvPath);
- amDone(ecFailed);
+ done(BuildResult::MiscFailure);
return;
}
@@ -990,31 +1016,39 @@ void DerivationGoal::haveDerivation()
assert(worker.store.isValidPath(drvPath));
/* Get the derivation. */
- drv = derivationFromPath(worker.store, drvPath);
+ drv = std::unique_ptr<BasicDerivation>(new Derivation(derivationFromPath(worker.store, drvPath)));
+
+ haveDerivation();
+}
+
- foreach (DerivationOutputs::iterator, i, drv.outputs)
- worker.store.addTempRoot(i->second.path);
+void DerivationGoal::haveDerivation()
+{
+ trace("have derivation");
+
+ for (auto & i : drv->outputs)
+ worker.store.addTempRoot(i.second.path);
/* Check what outputs paths are not already valid. */
PathSet invalidOutputs = checkPathValidity(false, buildMode == bmRepair);
/* If they are all valid, then we're done. */
if (invalidOutputs.size() == 0 && buildMode == bmNormal) {
- amDone(ecSuccess);
+ done(BuildResult::AlreadyValid);
return;
}
/* Check whether any output previously failed to build. If so,
don't bother. */
- foreach (PathSet::iterator, i, invalidOutputs)
- if (pathFailed(*i)) return;
+ for (auto & i : invalidOutputs)
+ if (pathFailed(i)) return;
/* We are first going to try to create the invalid output paths
through substitutes. If that doesn't work, we'll build
them. */
- if (settings.useSubstitutes && substitutesAllowed(drv))
- foreach (PathSet::iterator, i, invalidOutputs)
- addWaitee(worker.makeSubstitutionGoal(*i, buildMode == bmRepair));
+ if (settings.useSubstitutes && substitutesAllowed(*drv))
+ for (auto & i : invalidOutputs)
+ addWaitee(worker.makeSubstitutionGoal(i, buildMode == bmRepair));
if (waitees.empty()) /* to prevent hang (no wake-up event) */
outputsSubstituted();
@@ -1045,7 +1079,7 @@ void DerivationGoal::outputsSubstituted()
unsigned int nrInvalid = checkPathValidity(false, buildMode == bmRepair).size();
if (buildMode == bmNormal && nrInvalid == 0) {
- amDone(ecSuccess);
+ done(BuildResult::Substituted);
return;
}
if (buildMode == bmRepair && nrInvalid == 0) {
@@ -1063,11 +1097,17 @@ void DerivationGoal::outputsSubstituted()
wantedOutputs = PathSet();
/* The inputs must be built before we can build this goal. */
- foreach (DerivationInputs::iterator, i, drv.inputDrvs)
- addWaitee(worker.makeDerivationGoal(i->first, i->second, buildMode == bmRepair ? bmRepair : bmNormal));
+ if (useDerivation)
+ for (auto & i : dynamic_cast<Derivation *>(drv.get())->inputDrvs)
+ addWaitee(worker.makeDerivationGoal(i.first, i.second, buildMode == bmRepair ? bmRepair : bmNormal));
- foreach (PathSet::iterator, i, drv.inputSrcs)
- addWaitee(worker.makeSubstitutionGoal(*i));
+ for (auto & i : drv->inputSrcs) {
+ if (worker.store.isValidPath(i)) continue;
+ if (!settings.useSubstitutes)
+ throw Error(format("dependency of ‘%1%’ of ‘%2%’ does not exist, and substitution is disabled")
+ % i % drvPath);
+ addWaitee(worker.makeSubstitutionGoal(i));
+ }
if (waitees.empty()) /* to prevent hang (no wake-up event) */
inputsRealised();
@@ -1085,40 +1125,40 @@ void DerivationGoal::repairClosure()
/* Get the output closure. */
PathSet outputClosure;
- foreach (DerivationOutputs::iterator, i, drv.outputs)
- computeFSClosure(worker.store, i->second.path, outputClosure);
+ for (auto & i : drv->outputs)
+ computeFSClosure(worker.store, i.second.path, outputClosure);
/* Filter out our own outputs (which we have already checked). */
- foreach (DerivationOutputs::iterator, i, drv.outputs)
- outputClosure.erase(i->second.path);
+ for (auto & i : drv->outputs)
+ outputClosure.erase(i.second.path);
/* Get all dependencies of this derivation so that we know which
derivation is responsible for which path in the output
closure. */
PathSet inputClosure;
- computeFSClosure(worker.store, drvPath, inputClosure);
+ if (useDerivation) computeFSClosure(worker.store, drvPath, inputClosure);
std::map<Path, Path> outputsToDrv;
- foreach (PathSet::iterator, i, inputClosure)
- if (isDerivation(*i)) {
- Derivation drv = derivationFromPath(worker.store, *i);
- foreach (DerivationOutputs::iterator, j, drv.outputs)
- outputsToDrv[j->second.path] = *i;
+ for (auto & i : inputClosure)
+ if (isDerivation(i)) {
+ Derivation drv = derivationFromPath(worker.store, i);
+ for (auto & j : drv.outputs)
+ outputsToDrv[j.second.path] = i;
}
/* Check each path (slow!). */
PathSet broken;
- foreach (PathSet::iterator, i, outputClosure) {
- if (worker.store.pathContentsGood(*i)) continue;
- printMsg(lvlError, format("found corrupted or missing path ‘%1%’ in the output closure of ‘%2%’") % *i % drvPath);
- Path drvPath2 = outputsToDrv[*i];
+ for (auto & i : outputClosure) {
+ if (worker.store.pathContentsGood(i)) continue;
+ printMsg(lvlError, format("found corrupted or missing path ‘%1%’ in the output closure of ‘%2%’") % i % drvPath);
+ Path drvPath2 = outputsToDrv[i];
if (drvPath2 == "")
- addWaitee(worker.makeSubstitutionGoal(*i, true));
+ addWaitee(worker.makeSubstitutionGoal(i, true));
else
addWaitee(worker.makeDerivationGoal(drvPath2, PathSet(), bmRepair));
}
if (waitees.empty()) {
- amDone(ecSuccess);
+ done(BuildResult::AlreadyValid);
return;
}
@@ -1131,7 +1171,7 @@ void DerivationGoal::closureRepaired()
trace("closure repaired");
if (nrFailed > 0)
throw Error(format("some paths in the output closure of derivation ‘%1%’ could not be repaired") % drvPath);
- amDone(ecSuccess);
+ done(BuildResult::AlreadyValid);
}
@@ -1140,10 +1180,12 @@ void DerivationGoal::inputsRealised()
trace("all inputs realised");
if (nrFailed != 0) {
+ if (!useDerivation)
+ throw Error(format("some dependencies of ‘%1%’ are missing") % drvPath);
printMsg(lvlError,
format("cannot build derivation ‘%1%’: %2% dependencies couldn't be built")
% drvPath % nrFailed);
- amDone(ecFailed);
+ done(BuildResult::DependencyFailed);
return;
}
@@ -1156,32 +1198,33 @@ void DerivationGoal::inputsRealised()
running the build hook. */
/* The outputs are referenceable paths. */
- foreach (DerivationOutputs::iterator, i, drv.outputs) {
- debug(format("building path ‘%1%’") % i->second.path);
- allPaths.insert(i->second.path);
+ for (auto & i : drv->outputs) {
+ debug(format("building path ‘%1%’") % i.second.path);
+ allPaths.insert(i.second.path);
}
/* Determine the full set of input paths. */
/* First, the input derivations. */
- foreach (DerivationInputs::iterator, i, drv.inputDrvs) {
- /* Add the relevant output closures of the input derivation
- `*i' as input paths. Only add the closures of output paths
- that are specified as inputs. */
- assert(worker.store.isValidPath(i->first));
- Derivation inDrv = derivationFromPath(worker.store, i->first);
- foreach (StringSet::iterator, j, i->second)
- if (inDrv.outputs.find(*j) != inDrv.outputs.end())
- computeFSClosure(worker.store, inDrv.outputs[*j].path, inputPaths);
- else
- throw Error(
- format("derivation ‘%1%’ requires non-existent output ‘%2%’ from input derivation ‘%3%’")
- % drvPath % *j % i->first);
- }
+ if (useDerivation)
+ for (auto & i : dynamic_cast<Derivation *>(drv.get())->inputDrvs) {
+ /* Add the relevant output closures of the input derivation
+ `i' as input paths. Only add the closures of output paths
+ that are specified as inputs. */
+ assert(worker.store.isValidPath(i.first));
+ Derivation inDrv = derivationFromPath(worker.store, i.first);
+ for (auto & j : i.second)
+ if (inDrv.outputs.find(j) != inDrv.outputs.end())
+ computeFSClosure(worker.store, inDrv.outputs[j].path, inputPaths);
+ else
+ throw Error(
+ format("derivation ‘%1%’ requires non-existent output ‘%2%’ from input derivation ‘%3%’")
+ % drvPath % j % i.first);
+ }
/* Second, the input sources. */
- foreach (PathSet::iterator, i, drv.inputSrcs)
- computeFSClosure(worker.store, *i, inputPaths);
+ for (auto & i : drv->inputSrcs)
+ computeFSClosure(worker.store, i, inputPaths);
debug(format("added input paths %1%") % showPaths(inputPaths));
@@ -1189,8 +1232,8 @@ void DerivationGoal::inputsRealised()
/* Is this a fixed-output derivation? */
fixedOutput = true;
- foreach (DerivationOutputs::iterator, i, drv.outputs)
- if (i->second.hash == "") fixedOutput = false;
+ for (auto & i : drv->outputs)
+ if (i.second.hash == "") fixedOutput = false;
/* Okay, try to build. Note that here we don't wait for a build
slot to become available, since we don't need one if there is a
@@ -1217,18 +1260,24 @@ static string get(const StringPairs & map, const string & key, const string & de
}
-bool willBuildLocally(const Derivation & drv)
+bool willBuildLocally(const BasicDerivation & drv)
{
return get(drv.env, "preferLocalBuild") == "1" && canBuildLocally(drv.platform);
}
-bool substitutesAllowed(const Derivation & drv)
+bool substitutesAllowed(const BasicDerivation & drv)
{
return get(drv.env, "allowSubstitutes", "1") == "1";
}
+static bool isBuiltin(const BasicDerivation & drv)
+{
+ return string(drv.builder, 0, 8) == "builtin:";
+}
+
+
void DerivationGoal::tryToBuild()
{
trace("trying to build");
@@ -1238,10 +1287,10 @@ void DerivationGoal::tryToBuild()
(It can't happen between here and the lockPaths() call below
because we're not allowing multi-threading.) If so, put this
goal to sleep until another goal finishes, then try again. */
- foreach (DerivationOutputs::iterator, i, drv.outputs)
- if (pathIsLockedByMe(i->second.path)) {
+ for (auto & i : drv->outputs)
+ if (pathIsLockedByMe(i.second.path)) {
debug(format("putting derivation ‘%1%’ to sleep because ‘%2%’ is locked by another goal")
- % drvPath % i->second.path);
+ % drvPath % i.second.path);
worker.waitForAnyGoal(shared_from_this());
return;
}
@@ -1251,7 +1300,7 @@ void DerivationGoal::tryToBuild()
can't acquire the lock, then continue; hopefully some other
goal can start a build, and if not, the main loop will sleep a
few seconds and then retry this goal. */
- if (!outputLocks.lockPaths(outputPaths(drv), "", false)) {
+ if (!outputLocks.lockPaths(outputPaths(*drv), "", false)) {
worker.waitForAWhile(shared_from_this());
return;
}
@@ -1264,22 +1313,22 @@ void DerivationGoal::tryToBuild()
now hold the locks on the output paths, no other process can
build this derivation, so no further checks are necessary. */
validPaths = checkPathValidity(true, buildMode == bmRepair);
- assert(buildMode != bmCheck || validPaths.size() == drv.outputs.size());
- if (buildMode != bmCheck && validPaths.size() == drv.outputs.size()) {
+ assert(buildMode != bmCheck || validPaths.size() == drv->outputs.size());
+ if (buildMode != bmCheck && validPaths.size() == drv->outputs.size()) {
debug(format("skipping build of derivation ‘%1%’, someone beat us to it") % drvPath);
outputLocks.setDeletion(true);
- amDone(ecSuccess);
+ done(BuildResult::AlreadyValid);
return;
}
- missingPaths = outputPaths(drv);
+ missingPaths = outputPaths(*drv);
if (buildMode != bmCheck)
- foreach (PathSet::iterator, i, validPaths) missingPaths.erase(*i);
+ for (auto & i : validPaths) missingPaths.erase(i);
/* If any of the outputs already exist but are not valid, delete
them. */
- foreach (DerivationOutputs::iterator, i, drv.outputs) {
- Path path = i->second.path;
+ for (auto & i : drv->outputs) {
+ Path path = i.second.path;
if (worker.store.isValidPath(path)) continue;
if (!pathExists(path)) continue;
debug(format("removing invalid path ‘%1%’") % path);
@@ -1289,13 +1338,13 @@ void DerivationGoal::tryToBuild()
/* Check again whether any output previously failed to build,
because some other process may have tried and failed before we
acquired the lock. */
- foreach (DerivationOutputs::iterator, i, drv.outputs)
- if (pathFailed(i->second.path)) return;
+ for (auto & i : drv->outputs)
+ if (pathFailed(i.second.path)) return;
/* Don't do a remote build if the derivation has the attribute
`preferLocalBuild' set. Also, check and repair modes are only
supported for local builds. */
- bool buildLocally = buildMode != bmNormal || willBuildLocally(drv);
+ bool buildLocally = buildMode != bmNormal || willBuildLocally(*drv);
/* Is the build hook willing to accept this job? */
if (!buildLocally) {
@@ -1340,7 +1389,7 @@ void DerivationGoal::tryToBuild()
printMsg(lvlError, format("@ build-failed %1% - %2% %3%")
% drvPath % 0 % e.msg());
worker.permanentFailure = true;
- amDone(ecFailed);
+ done(BuildResult::InputRejected, e.msg());
return;
}
@@ -1436,9 +1485,9 @@ void DerivationGoal::buildDone()
/* Move paths out of the chroot for easier debugging of
build failures. */
if (useChroot && buildMode == bmNormal)
- foreach (PathSet::iterator, i, missingPaths)
- if (pathExists(chrootRootDir + *i))
- rename((chrootRootDir + *i).c_str(), i->c_str());
+ for (auto & i : missingPaths)
+ if (pathExists(chrootRootDir + i))
+ rename((chrootRootDir + i).c_str(), i.c_str());
if (diskFull)
printMsg(lvlError, "note: build failure may have been caused by lack of free disk space");
@@ -1452,13 +1501,13 @@ void DerivationGoal::buildDone()
registerOutputs();
if (buildMode == bmCheck) {
- amDone(ecSuccess);
+ done(BuildResult::Built);
return;
}
/* Delete unused redirected outputs (when doing hash rewriting). */
- foreach (RedirectedOutputs::iterator, i, redirectedOutputs)
- if (pathExists(i->second)) deletePath(i->second);
+ for (auto & i : redirectedOutputs)
+ if (pathExists(i.second)) deletePath(i.second);
/* Delete the chroot (if we were using one). */
autoDelChroot.reset(); /* this runs the destructor */
@@ -1478,10 +1527,12 @@ void DerivationGoal::buildDone()
outputLocks.unlock();
buildUser.release();
+ BuildResult::Status st = BuildResult::MiscFailure;
+
if (hook && WIFEXITED(status) && WEXITSTATUS(status) == 101) {
if (settings.printBuildTrace)
printMsg(lvlError, format("@ build-failed %1% - timeout") % drvPath);
- worker.timedOut = true;
+ st = BuildResult::TimedOut;
}
else if (hook && (!WIFEXITED(status) || WEXITSTATUS(status) != 100)) {
@@ -1494,7 +1545,11 @@ void DerivationGoal::buildDone()
if (settings.printBuildTrace)
printMsg(lvlError, format("@ build-failed %1% - %2% %3%")
% drvPath % 1 % e.msg());
- worker.permanentFailure = !fixedOutput && !diskFull;
+
+ st =
+ statusOk(status) ? BuildResult::OutputRejected :
+ fixedOutput || diskFull ? BuildResult::TransientFailure :
+ BuildResult::PermanentFailure;
/* Register the outputs of this build as "failed" so we
won't try to build them again (negative caching).
@@ -1504,11 +1559,11 @@ void DerivationGoal::buildDone()
Hook errors (like communication problems with the
remote machine) shouldn't be cached either. */
if (settings.cacheFailure && !fixedOutput && !diskFull)
- foreach (DerivationOutputs::iterator, i, drv.outputs)
- worker.store.registerFailedPath(i->second.path);
+ for (auto & i : drv->outputs)
+ worker.store.registerFailedPath(i.second.path);
}
- amDone(ecFailed);
+ done(st, e.msg());
return;
}
@@ -1518,27 +1573,27 @@ void DerivationGoal::buildDone()
if (settings.printBuildTrace)
printMsg(lvlError, format("@ build-succeeded %1% -") % drvPath);
- amDone(ecSuccess);
+ done(BuildResult::Built);
}
HookReply DerivationGoal::tryBuildHook()
{
- if (!settings.useBuildHook || getEnv("NIX_BUILD_HOOK") == "") return rpDecline;
+ if (!settings.useBuildHook || getEnv("NIX_BUILD_HOOK") == "" || !useDerivation) return rpDecline;
if (!worker.hook)
- worker.hook = std::shared_ptr<HookInstance>(new HookInstance);
+ worker.hook = std::make_shared<HookInstance>();
/* Tell the hook about system features (beyond the system type)
required from the build machine. (The hook could parse the
drv file itself, but this is easier.) */
- Strings features = tokenizeString<Strings>(get(drv.env, "requiredSystemFeatures"));
- foreach (Strings::iterator, i, features) checkStoreName(*i); /* !!! abuse */
+ Strings features = tokenizeString<Strings>(get(drv->env, "requiredSystemFeatures"));
+ for (auto & i : features) checkStoreName(i); /* !!! abuse */
/* Send the request to the hook. */
writeLine(worker.hook->toHook.writeSide, (format("%1% %2% %3% %4%")
% (worker.getNrLocalBuilds() < settings.maxBuildJobs ? "1" : "0")
- % drv.platform % drvPath % concatStringsSep(",", features)).str());
+ % drv->platform % drvPath % concatStringsSep(",", features)).str());
/* Read the first line of input, which should be a word indicating
whether the hook wishes to perform the build. */
@@ -1575,13 +1630,13 @@ HookReply DerivationGoal::tryBuildHook()
computeFSClosure(worker.store, drvPath, allInputs);
string s;
- foreach (PathSet::iterator, i, allInputs) { s += *i; s += ' '; }
+ for (auto & i : allInputs) { s += i; s += ' '; }
writeLine(hook->toHook.writeSide, s);
/* Tell the hooks the missing outputs that have to be copied back
from the remote system. */
s = "";
- foreach (PathSet::iterator, i, missingPaths) { s += *i; s += ' '; }
+ for (auto & i : missingPaths) { s += i; s += ' '; }
writeLine(hook->toHook.writeSide, s);
hook->toHook.writeSide.close();
@@ -1596,7 +1651,7 @@ HookReply DerivationGoal::tryBuildHook()
if (settings.printBuildTrace)
printMsg(lvlError, format("@ build-started %1% - %2% %3%")
- % drvPath % drv.platform % logFile);
+ % drvPath % drv->platform % logFile);
return rpAccept;
}
@@ -1624,12 +1679,12 @@ void DerivationGoal::startBuilder()
"building path(s) %1%") % showPaths(missingPaths));
/* Right platform? */
- if (!canBuildLocally(drv.platform)) {
+ if (!canBuildLocally(drv->platform)) {
if (settings.printBuildTrace)
- printMsg(lvlError, format("@ unsupported-platform %1% %2%") % drvPath % drv.platform);
+ printMsg(lvlError, format("@ unsupported-platform %1% %2%") % drvPath % drv->platform);
throw Error(
format("a ‘%1%’ is required to build ‘%3%’, but I am a ‘%2%’")
- % drv.platform % settings.thisSystem % drvPath);
+ % drv->platform % settings.thisSystem % drvPath);
}
/* Construct the environment passed to the builder. */
@@ -1666,9 +1721,9 @@ void DerivationGoal::startBuilder()
attribute. Those are passed as file names pointing to
temporary files containing the contents. */
PathSet filesToChown;
- StringSet passAsFile = tokenizeString<StringSet>(get(drv.env, "passAsFile"));
+ StringSet passAsFile = tokenizeString<StringSet>(get(drv->env, "passAsFile"));
int fileNr = 0;
- for (auto & i : drv.env) {
+ for (auto & i : drv->env) {
if (passAsFile.find(i.first) == passAsFile.end()) {
env[i.first] = i.second;
} else {
@@ -1708,8 +1763,8 @@ void DerivationGoal::startBuilder()
fixed-output derivations is by definition pure (since we
already know the cryptographic hash of the output). */
if (fixedOutput) {
- Strings varNames = tokenizeString<Strings>(get(drv.env, "impureEnvVars"));
- foreach (Strings::iterator, i, varNames) env[*i] = getEnv(*i);
+ Strings varNames = tokenizeString<Strings>(get(drv->env, "impureEnvVars"));
+ for (auto & i : varNames) env[i] = getEnv(i);
}
/* The `exportReferencesGraph' feature allows the references graph
@@ -1719,7 +1774,7 @@ void DerivationGoal::startBuilder()
temporary build directory. The text files have the format used
by `nix-store --register-validity'. However, the deriver
fields are left empty. */
- string s = get(drv.env, "exportReferencesGraph");
+ string s = get(drv->env, "exportReferencesGraph");
Strings ss = tokenizeString<Strings>(s);
if (ss.size() % 2 != 0)
throw BuildError(format("odd number of tokens in ‘exportReferencesGraph’: ‘%1%’") % s);
@@ -1745,11 +1800,11 @@ void DerivationGoal::startBuilder()
computeFSClosure(worker.store, storePath, paths);
paths2 = paths;
- foreach (PathSet::iterator, j, paths2) {
- if (isDerivation(*j)) {
- Derivation drv = derivationFromPath(worker.store, *j);
- foreach (DerivationOutputs::iterator, k, drv.outputs)
- computeFSClosure(worker.store, k->second.path, paths);
+ for (auto & j : paths2) {
+ if (isDerivation(j)) {
+ Derivation drv = derivationFromPath(worker.store, j);
+ for (auto & k : drv.outputs)
+ computeFSClosure(worker.store, k.second.path, paths);
}
}
@@ -1789,14 +1844,14 @@ void DerivationGoal::startBuilder()
if (x != "true" && x != "false" && x != "relaxed")
throw Error("option ‘build-use-chroot’ must be set to one of ‘true’, ‘false’ or ‘relaxed’");
if (x == "true") {
- if (get(drv.env, "__noChroot") == "1")
+ if (get(drv->env, "__noChroot") == "1")
throw Error(format("derivation ‘%1%’ has ‘__noChroot’ set, but that's not allowed when ‘build-use-chroot’ is ‘true’") % drvPath);
useChroot = true;
}
else if (x == "false")
useChroot = false;
else if (x == "relaxed")
- useChroot = !fixedOutput && get(drv.env, "__noChroot") != "1";
+ useChroot = !fixedOutput && get(drv->env, "__noChroot") != "1";
}
if (useChroot) {
@@ -1834,7 +1889,7 @@ void DerivationGoal::startBuilder()
PathSet allowedPaths = tokenizeString<StringSet>(allowed);
/* This works like the above, except on a per-derivation level */
- Strings impurePaths = tokenizeString<Strings>(get(drv.env, "__impureHostDeps"));
+ Strings impurePaths = tokenizeString<Strings>(get(drv->env, "__impureHostDeps"));
for (auto & i : impurePaths) {
bool found = false;
@@ -1865,7 +1920,7 @@ void DerivationGoal::startBuilder()
if (pathExists(chrootRootDir)) deletePath(chrootRootDir);
/* Clean up the chroot directory automatically. */
- autoDelChroot = std::shared_ptr<AutoDelete>(new AutoDelete(chrootRootDir));
+ autoDelChroot = std::make_shared<AutoDelete>(chrootRootDir);
printMsg(lvlChatty, format("setting up chroot environment in ‘%1%’") % chrootRootDir);
@@ -1918,28 +1973,28 @@ void DerivationGoal::startBuilder()
if (chown(chrootStoreDir.c_str(), 0, buildUser.getGID()) == -1)
throw SysError(format("cannot change ownership of ‘%1%’") % chrootStoreDir);
- foreach (PathSet::iterator, i, inputPaths) {
+ for (auto & i : inputPaths) {
struct stat st;
- if (lstat(i->c_str(), &st))
- throw SysError(format("getting attributes of path ‘%1%’") % *i);
+ if (lstat(i.c_str(), &st))
+ throw SysError(format("getting attributes of path ‘%1%’") % i);
if (S_ISDIR(st.st_mode))
- dirsInChroot[*i] = *i;
+ dirsInChroot[i] = i;
else {
- Path p = chrootRootDir + *i;
- if (link(i->c_str(), p.c_str()) == -1) {
+ Path p = chrootRootDir + i;
+ if (link(i.c_str(), p.c_str()) == -1) {
/* Hard-linking fails if we exceed the maximum
link count on a file (e.g. 32000 of ext3),
which is quite possible after a `nix-store
--optimise'. */
if (errno != EMLINK)
- throw SysError(format("linking ‘%1%’ to ‘%2%’") % p % *i);
+ throw SysError(format("linking ‘%1%’ to ‘%2%’") % p % i);
StringSink sink;
- dumpPath(*i, sink);
+ dumpPath(i, sink);
StringSource source(sink.s);
restorePath(p, source);
}
- regularInputPaths.insert(*i);
+ regularInputPaths.insert(i);
}
}
@@ -1948,8 +2003,8 @@ void DerivationGoal::startBuilder()
(typically the dependencies of /bin/sh). Throw them
out. */
if (buildMode != bmNormal)
- foreach (DerivationOutputs::iterator, i, drv.outputs)
- dirsInChroot.erase(i->second.path);
+ for (auto & i : drv->outputs)
+ dirsInChroot.erase(i.second.path);
#elif SANDBOX_ENABLED
/* We don't really have any parent prep work to do (yet?)
@@ -1974,16 +2029,16 @@ void DerivationGoal::startBuilder()
contents of the new outputs to replace the dummy strings
with the actual hashes. */
if (validPaths.size() > 0)
- foreach (PathSet::iterator, i, validPaths)
- addHashRewrite(*i);
+ for (auto & i : validPaths)
+ addHashRewrite(i);
/* If we're repairing, then we don't want to delete the
corrupt outputs in advance. So rewrite them as well. */
if (buildMode == bmRepair)
- foreach (PathSet::iterator, i, missingPaths)
- if (worker.store.isValidPath(*i) && pathExists(*i)) {
- addHashRewrite(*i);
- redirectedBadOutputs.insert(*i);
+ for (auto & i : missingPaths)
+ if (worker.store.isValidPath(i) && pathExists(i)) {
+ addHashRewrite(i);
+ redirectedBadOutputs.insert(i);
}
}
@@ -2025,7 +2080,7 @@ void DerivationGoal::startBuilder()
}
/* Run the builder. */
- printMsg(lvlChatty, format("executing builder ‘%1%’") % drv.builder);
+ printMsg(lvlChatty, format("executing builder ‘%1%’") % drv->builder);
/* Create the log file. */
Path logFile = openLogFile();
@@ -2093,7 +2148,7 @@ void DerivationGoal::startBuilder()
#endif
{
ProcessOptions options;
- options.allowVfork = !buildUser.enabled();
+ options.allowVfork = !buildUser.enabled() && !isBuiltin(*drv);
pid = startProcess([&]() {
runChild();
}, options);
@@ -2111,7 +2166,7 @@ void DerivationGoal::startBuilder()
if (settings.printBuildTrace) {
printMsg(lvlError, format("@ build-started %1% - %2% %3%")
- % drvPath % drv.platform % logFile);
+ % drvPath % drv->platform % logFile);
}
}
@@ -2157,8 +2212,8 @@ void DerivationGoal::runChild()
local to the namespace, though, so setting MS_PRIVATE
does not affect the outside world. */
Strings mounts = tokenizeString<Strings>(readFile("/proc/self/mountinfo", true), "\n");
- foreach (Strings::iterator, i, mounts) {
- vector<string> fields = tokenizeString<vector<string> >(*i, " ");
+ for (auto & i : mounts) {
+ vector<string> fields = tokenizeString<vector<string> >(i, " ");
string fs = decodeOctalEscaped(fields.at(4));
if (mount(0, fs.c_str(), 0, MS_PRIVATE, 0) == -1)
throw SysError(format("unable to make filesystem ‘%1%’ private") % fs);
@@ -2206,10 +2261,10 @@ void DerivationGoal::runChild()
/* Bind-mount all the directories from the "host"
filesystem that we want in the chroot
environment. */
- foreach (DirsInChroot::iterator, i, dirsInChroot) {
+ for (auto & i : dirsInChroot) {
struct stat st;
- Path source = i->second;
- Path target = chrootRootDir + i->first;
+ Path source = i.second;
+ Path target = chrootRootDir + i.first;
if (source == "/proc") continue; // backwards compatibility
debug(format("bind mounting ‘%1%’ to ‘%2%’") % source % target);
if (stat(source.c_str(), &st) == -1)
@@ -2285,7 +2340,7 @@ void DerivationGoal::runChild()
i686-linux build on an x86_64-linux machine. */
struct utsname utsbuf;
uname(&utsbuf);
- if (drv.platform == "i686-linux" &&
+ if (drv->platform == "i686-linux" &&
(settings.thisSystem == "x86_64-linux" ||
(!strcmp(utsbuf.sysname, "Linux") && !strcmp(utsbuf.machine, "x86_64")))) {
if (personality(PER_LINUX32) == -1)
@@ -2294,7 +2349,7 @@ void DerivationGoal::runChild()
/* Impersonate a Linux 2.6 machine to get some determinism in
builds that depend on the kernel version. */
- if ((drv.platform == "i686-linux" || drv.platform == "x86_64-linux") && settings.impersonateLinux26) {
+ if ((drv->platform == "i686-linux" || drv->platform == "x86_64-linux") && settings.impersonateLinux26) {
int cur = personality(0xffffffff);
if (cur != -1) personality(cur | 0x0020000 /* == UNAME26 */);
}
@@ -2307,8 +2362,8 @@ void DerivationGoal::runChild()
/* Fill in the environment. */
Strings envStrs;
- foreach (Environment::const_iterator, i, env)
- envStrs.push_back(rewriteHashes(i->first + "=" + i->second, rewritesToTmp));
+ for (auto & i : env)
+ envStrs.push_back(rewriteHashes(i.first + "=" + i.second, rewritesToTmp));
/* If we are running in `build-users' mode, then switch to the
user we allocated above. Make sure that we drop all root
@@ -2319,7 +2374,8 @@ void DerivationGoal::runChild()
if (buildUser.enabled()) {
/* Preserve supplementary groups of the build user, to allow
admins to specify groups such as "kvm". */
- if (setgroups(buildUser.getSupplementaryGIDs().size(),
+ if (!buildUser.getSupplementaryGIDs().empty() &&
+ setgroups(buildUser.getSupplementaryGIDs().size(),
buildUser.getSupplementaryGIDs().data()) == -1)
throw SysError("cannot set supplementary groups of build user");
@@ -2340,7 +2396,9 @@ void DerivationGoal::runChild()
const char *builder = "invalid";
string sandboxProfile;
- if (useChroot && SANDBOX_ENABLED) {
+ if (isBuiltin(*drv))
+ ;
+ else if (useChroot && SANDBOX_ENABLED) {
/* Lots and lots and lots of file functions freak out if they can't stat their full ancestry */
PathSet ancestry;
@@ -2367,7 +2425,6 @@ void DerivationGoal::runChild()
for (auto & i : inputPaths)
dirsInChroot[i] = i;
-
/* TODO: we should factor out the policy cleanly, so we don't have to repeat the constants every time... */
sandboxProfile += "(version 1)\n";
@@ -2449,15 +2506,15 @@ void DerivationGoal::runChild()
args.push_back("sandbox-exec");
args.push_back("-p");
args.push_back(sandboxProfile);
- args.push_back(drv.builder);
+ args.push_back(drv->builder);
} else {
- builder = drv.builder.c_str();
- string builderBasename = baseNameOf(drv.builder);
+ builder = drv->builder.c_str();
+ string builderBasename = baseNameOf(drv->builder);
args.push_back(builderBasename);
}
- foreach (Strings::iterator, i, drv.args)
- args.push_back(rewriteHashes(*i, rewritesToTmp));
+ for (auto & i : drv->args)
+ args.push_back(rewriteHashes(i, rewritesToTmp));
restoreSIGPIPE();
@@ -2471,9 +2528,23 @@ void DerivationGoal::runChild()
}
/* Execute the program. This should not return. */
+ if (isBuiltin(*drv)) {
+ try {
+ logType = ltFlat;
+ if (drv->builder == "builtin:fetchurl")
+ builtinFetchurl(*drv);
+ else
+ throw Error(format("unsupported builtin function ‘%1%’") % string(drv->builder, 8));
+ _exit(0);
+ } catch (std::exception & e) {
+ writeFull(STDERR_FILENO, "error: " + string(e.what()) + "\n");
+ _exit(1);
+ }
+ }
+
execve(builder, stringsToCharPtrs(args).data(), stringsToCharPtrs(envStrs).data());
- throw SysError(format("executing ‘%1%’") % drv.builder);
+ throw SysError(format("executing ‘%1%’") % drv->builder);
} catch (std::exception & e) {
writeFull(STDERR_FILENO, "while setting up the build environment: " + string(e.what()) + "\n");
@@ -2485,18 +2556,17 @@ void DerivationGoal::runChild()
/* Parse a list of reference specifiers. Each element must either be
a store path, or the symbolic name of the output of the derivation
(such as `out'). */
-PathSet parseReferenceSpecifiers(const Derivation & drv, string attr)
+PathSet parseReferenceSpecifiers(const BasicDerivation & drv, string attr)
{
PathSet result;
Paths paths = tokenizeString<Paths>(attr);
- foreach (Strings::iterator, i, paths) {
- if (isStorePath(*i))
- result.insert(*i);
- else if (drv.outputs.find(*i) != drv.outputs.end())
- result.insert(drv.outputs.find(*i)->second.path);
+ for (auto & i : paths) {
+ if (isStorePath(i))
+ result.insert(i);
+ else if (drv.outputs.find(i) != drv.outputs.end())
+ result.insert(drv.outputs.find(i)->second.path);
else throw BuildError(
- format("derivation contains an illegal reference specifier ‘%1%’")
- % *i);
+ format("derivation contains an illegal reference specifier ‘%1%’") % i);
}
return result;
}
@@ -2509,8 +2579,8 @@ void DerivationGoal::registerOutputs()
to do anything here. */
if (hook) {
bool allValid = true;
- foreach (DerivationOutputs::iterator, i, drv.outputs)
- if (!worker.store.isValidPath(i->second.path)) allValid = false;
+ for (auto & i : drv->outputs)
+ if (!worker.store.isValidPath(i.second.path)) allValid = false;
if (allValid) return;
}
@@ -2519,8 +2589,8 @@ void DerivationGoal::registerOutputs()
/* Check whether the output paths were created, and grep each
output path to determine what other paths it references. Also make all
output paths read-only. */
- foreach (DerivationOutputs::iterator, i, drv.outputs) {
- Path path = i->second.path;
+ for (auto & i : drv->outputs) {
+ Path path = i.second.path;
if (missingPaths.find(path) == missingPaths.end()) continue;
Path actualPath = path;
@@ -2591,10 +2661,10 @@ void DerivationGoal::registerOutputs()
/* Check that fixed-output derivations produced the right
outputs (i.e., the content hash should match the specified
hash). */
- if (i->second.hash != "") {
+ if (i.second.hash != "") {
bool recursive; HashType ht; Hash h;
- i->second.parseHashInfo(recursive, ht, h);
+ i.second.parseHashInfo(recursive, ht, h);
if (!recursive) {
/* The output path should be a regular file without
@@ -2609,7 +2679,7 @@ void DerivationGoal::registerOutputs()
if (h != h2)
throw BuildError(
format("output path ‘%1%’ should have %2% hash ‘%3%’, instead has ‘%4%’")
- % path % i->second.hashAlgo % printHash16or32(h) % printHash16or32(h2));
+ % path % i.second.hashAlgo % printHash16or32(h) % printHash16or32(h2));
}
/* Get rid of all weird permissions. This also checks that
@@ -2633,19 +2703,19 @@ void DerivationGoal::registerOutputs()
/* For debugging, print out the referenced and unreferenced
paths. */
- foreach (PathSet::iterator, i, inputPaths) {
- PathSet::iterator j = references.find(*i);
+ for (auto & i : inputPaths) {
+ PathSet::iterator j = references.find(i);
if (j == references.end())
- debug(format("unreferenced input: ‘%1%’") % *i);
+ debug(format("unreferenced input: ‘%1%’") % i);
else
- debug(format("referenced input: ‘%1%’") % *i);
+ debug(format("referenced input: ‘%1%’") % i);
}
/* Enforce `allowedReferences' and friends. */
auto checkRefs = [&](const string & attrName, bool allowed, bool recursive) {
- if (drv.env.find(attrName) == drv.env.end()) return;
+ if (drv->env.find(attrName) == drv->env.end()) return;
- PathSet spec = parseReferenceSpecifiers(drv, get(drv.env, attrName));
+ PathSet spec = parseReferenceSpecifiers(*drv, get(drv->env, attrName));
PathSet used;
if (recursive) {
@@ -2779,7 +2849,7 @@ void DerivationGoal::handleChildOutput(int fd, const string & data)
printMsg(lvlError,
format("%1% killed after writing more than %2% bytes of log output")
% getName() % settings.maxLogSize);
- cancel(true); // not really a timeout, but close enough
+ timedOut(); // not really a timeout, but close enough
return;
}
if (verbosity >= settings.buildVerbosity)
@@ -2806,12 +2876,12 @@ void DerivationGoal::handleEOF(int fd)
PathSet DerivationGoal::checkPathValidity(bool returnValid, bool checkHash)
{
PathSet result;
- foreach (DerivationOutputs::iterator, i, drv.outputs) {
- if (!wantOutput(i->first, wantedOutputs)) continue;
+ for (auto & i : drv->outputs) {
+ if (!wantOutput(i.first, wantedOutputs)) continue;
bool good =
- worker.store.isValidPath(i->second.path) &&
- (!checkHash || worker.store.pathContentsGood(i->second.path));
- if (good == returnValid) result.insert(i->second.path);
+ worker.store.isValidPath(i.second.path) &&
+ (!checkHash || worker.store.pathContentsGood(i.second.path));
+ if (good == returnValid) result.insert(i.second.path);
}
return result;
}
@@ -2828,8 +2898,7 @@ bool DerivationGoal::pathFailed(const Path & path)
if (settings.printBuildTrace)
printMsg(lvlError, format("@ build-failed %1% - cached") % drvPath);
- worker.permanentFailure = true;
- amDone(ecFailed);
+ done(BuildResult::CachedFailure);
return true;
}
@@ -2849,6 +2918,18 @@ Path DerivationGoal::addHashRewrite(const Path & path)
}
+void DerivationGoal::done(BuildResult::Status status, const string & msg)
+{
+ result.status = status;
+ result.errorMsg = msg;
+ amDone(result.success() ? ecSuccess : ecFailed);
+ if (result.status == BuildResult::TimedOut)
+ worker.timedOut = true;
+ if (result.status == BuildResult::PermanentFailure || result.status == BuildResult::CachedFailure)
+ worker.permanentFailure = true;
+}
+
+
//////////////////////////////////////////////////////////////////////
@@ -2898,7 +2979,7 @@ public:
SubstitutionGoal(const Path & storePath, Worker & worker, bool repair = false);
~SubstitutionGoal();
- void cancel(bool timeout);
+ void timedOut();
string key()
{
@@ -2943,9 +3024,9 @@ SubstitutionGoal::~SubstitutionGoal()
}
-void SubstitutionGoal::cancel(bool timeout)
+void SubstitutionGoal::timedOut()
{
- if (settings.printBuildTrace && timeout)
+ if (settings.printBuildTrace)
printMsg(lvlError, format("@ substituter-failed %1% timeout") % storePath);
if (pid != -1) {
pid_t savedPid = pid;
@@ -3011,9 +3092,9 @@ void SubstitutionGoal::tryNext()
/* To maintain the closure invariant, we first have to realise the
paths referenced by this one. */
- foreach (PathSet::iterator, i, info.references)
- if (*i != storePath) /* ignore self-references */
- addWaitee(worker.makeSubstitutionGoal(*i));
+ for (auto & i : info.references)
+ if (i != storePath) /* ignore self-references */
+ addWaitee(worker.makeSubstitutionGoal(i));
if (waitees.empty()) /* to prevent hang (no wake-up event) */
referencesValid();
@@ -3032,9 +3113,9 @@ void SubstitutionGoal::referencesValid()
return;
}
- foreach (PathSet::iterator, i, info.references)
- if (*i != storePath) /* ignore self-references */
- assert(worker.store.isValidPath(*i));
+ for (auto & i : info.references)
+ if (i != storePath) /* ignore self-references */
+ assert(worker.store.isValidPath(i));
state = &SubstitutionGoal::tryToRun;
worker.wakeUp(shared_from_this());
@@ -3066,7 +3147,7 @@ void SubstitutionGoal::tryToRun()
}
/* Acquire a lock on the output path. */
- outputLock = std::shared_ptr<PathLocks>(new PathLocks);
+ outputLock = std::make_shared<PathLocks>();
if (!outputLock->lockPaths(singleton<PathSet>(storePath), "", false)) {
worker.waitForAWhile(shared_from_this());
return;
@@ -3266,11 +3347,12 @@ Worker::~Worker()
}
-GoalPtr Worker::makeDerivationGoal(const Path & path, const StringSet & wantedOutputs, BuildMode buildMode)
+GoalPtr Worker::makeDerivationGoal(const Path & path,
+ const StringSet & wantedOutputs, BuildMode buildMode)
{
GoalPtr goal = derivationGoals[path].lock();
if (!goal) {
- goal = GoalPtr(new DerivationGoal(path, wantedOutputs, *this, buildMode));
+ goal = std::make_shared<DerivationGoal>(path, wantedOutputs, *this, buildMode);
derivationGoals[path] = goal;
wakeUp(goal);
} else
@@ -3279,11 +3361,20 @@ GoalPtr Worker::makeDerivationGoal(const Path & path, const StringSet & wantedOu
}
+std::shared_ptr<DerivationGoal> Worker::makeBasicDerivationGoal(const Path & drvPath,
+ const BasicDerivation & drv, BuildMode buildMode)
+{
+ auto goal = std::make_shared<DerivationGoal>(drvPath, drv, *this, buildMode);
+ wakeUp(goal);
+ return goal;
+}
+
+
GoalPtr Worker::makeSubstitutionGoal(const Path & path, bool repair)
{
GoalPtr goal = substitutionGoals[path].lock();
if (!goal) {
- goal = GoalPtr(new SubstitutionGoal(path, *this, repair));
+ goal = std::make_shared<SubstitutionGoal>(path, *this, repair);
substitutionGoals[path] = goal;
wakeUp(goal);
}
@@ -3318,8 +3409,8 @@ void Worker::removeGoal(GoalPtr goal)
}
/* Wake up goals waiting for any goal to finish. */
- foreach (WeakGoals::iterator, i, waitingForAnyGoal) {
- GoalPtr goal = i->lock();
+ for (auto & i : waitingForAnyGoal) {
+ GoalPtr goal = i.lock();
if (goal) wakeUp(goal);
}
@@ -3372,8 +3463,8 @@ void Worker::childTerminated(pid_t pid, bool wakeSleepers)
if (wakeSleepers) {
/* Wake up goals waiting for a build slot. */
- foreach (WeakGoals::iterator, i, wantingToBuild) {
- GoalPtr goal = i->lock();
+ for (auto & i : wantingToBuild) {
+ GoalPtr goal = i.lock();
if (goal) wakeUp(goal);
}
@@ -3408,7 +3499,7 @@ void Worker::waitForAWhile(GoalPtr goal)
void Worker::run(const Goals & _topGoals)
{
- foreach (Goals::iterator, i, _topGoals) topGoals.insert(*i);
+ for (auto & i : _topGoals) topGoals.insert(i);
startNest(nest, lvlDebug, format("entered goal loop"));
@@ -3474,12 +3565,12 @@ void Worker::waitForInput()
deadline for any child. */
assert(sizeof(time_t) >= sizeof(long));
time_t nearest = LONG_MAX; // nearest deadline
- foreach (Children::iterator, i, children) {
- if (!i->second.respectTimeouts) continue;
+ for (auto & i : children) {
+ if (!i.second.respectTimeouts) continue;
if (settings.maxSilentTime != 0)
- nearest = std::min(nearest, i->second.lastOutput + settings.maxSilentTime);
+ nearest = std::min(nearest, i.second.lastOutput + settings.maxSilentTime);
if (settings.buildTimeout != 0)
- nearest = std::min(nearest, i->second.timeStarted + settings.buildTimeout);
+ nearest = std::min(nearest, i.second.timeStarted + settings.buildTimeout);
}
if (nearest != LONG_MAX) {
timeout.tv_sec = std::max((time_t) 1, nearest - before);
@@ -3504,10 +3595,10 @@ void Worker::waitForInput()
fd_set fds;
FD_ZERO(&fds);
int fdMax = 0;
- foreach (Children::iterator, i, children) {
- foreach (set<int>::iterator, j, i->second.fds) {
- FD_SET(*j, &fds);
- if (*j >= fdMax) fdMax = *j + 1;
+ for (auto & i : children) {
+ for (auto & j : i.second.fds) {
+ FD_SET(j, &fds);
+ if (j >= fdMax) fdMax = j + 1;
}
}
@@ -3523,36 +3614,36 @@ void Worker::waitForInput()
/* Since goals may be canceled from inside the loop below (causing
them go be erased from the `children' map), we have to be
careful that we don't keep iterators alive across calls to
- cancel(). */
+ timedOut(). */
set<pid_t> pids;
- foreach (Children::iterator, i, children) pids.insert(i->first);
+ for (auto & i : children) pids.insert(i.first);
- foreach (set<pid_t>::iterator, i, pids) {
+ for (auto & i : pids) {
checkInterrupt();
- Children::iterator j = children.find(*i);
+ Children::iterator j = children.find(i);
if (j == children.end()) continue; // child destroyed
GoalPtr goal = j->second.goal.lock();
assert(goal);
set<int> fds2(j->second.fds);
- foreach (set<int>::iterator, k, fds2) {
- if (FD_ISSET(*k, &fds)) {
+ for (auto & k : fds2) {
+ if (FD_ISSET(k, &fds)) {
unsigned char buffer[4096];
- ssize_t rd = read(*k, buffer, sizeof(buffer));
+ ssize_t rd = read(k, buffer, sizeof(buffer));
if (rd == -1) {
if (errno != EINTR)
throw SysError(format("reading from %1%")
% goal->getName());
} else if (rd == 0) {
debug(format("%1%: got EOF") % goal->getName());
- goal->handleEOF(*k);
- j->second.fds.erase(*k);
+ goal->handleEOF(k);
+ j->second.fds.erase(k);
} else {
printMsg(lvlVomit, format("%1%: read %2% bytes")
% goal->getName() % rd);
string data((char *) buffer, rd);
j->second.lastOutput = after;
- goal->handleChildOutput(*k, data);
+ goal->handleChildOutput(k, data);
}
}
}
@@ -3565,8 +3656,7 @@ void Worker::waitForInput()
printMsg(lvlError,
format("%1% timed out after %2% seconds of silence")
% goal->getName() % settings.maxSilentTime);
- goal->cancel(true);
- timedOut = true;
+ goal->timedOut();
}
else if (goal->getExitCode() == Goal::ecBusy &&
@@ -3577,15 +3667,14 @@ void Worker::waitForInput()
printMsg(lvlError,
format("%1% timed out after %2% seconds")
% goal->getName() % settings.buildTimeout);
- goal->cancel(true);
- timedOut = true;
+ goal->timedOut();
}
}
if (!waitingForAWhile.empty() && lastWokenUp + settings.pollInterval <= after) {
lastWokenUp = after;
- foreach (WeakGoals::iterator, i, waitingForAWhile) {
- GoalPtr goal = i->lock();
+ for (auto & i : waitingForAWhile) {
+ GoalPtr goal = i.lock();
if (goal) wakeUp(goal);
}
waitingForAWhile.clear();
@@ -3604,28 +3693,27 @@ unsigned int Worker::exitStatus()
void LocalStore::buildPaths(const PathSet & drvPaths, BuildMode buildMode)
{
- startNest(nest, lvlDebug,
- format("building %1%") % showPaths(drvPaths));
+ startNest(nest, lvlDebug, format("building %1%") % showPaths(drvPaths));
Worker worker(*this);
Goals goals;
- foreach (PathSet::const_iterator, i, drvPaths) {
- DrvPathWithOutputs i2 = parseDrvPathWithOutputs(*i);
+ for (auto & i : drvPaths) {
+ DrvPathWithOutputs i2 = parseDrvPathWithOutputs(i);
if (isDerivation(i2.first))
goals.insert(worker.makeDerivationGoal(i2.first, i2.second, buildMode));
else
- goals.insert(worker.makeSubstitutionGoal(*i, buildMode));
+ goals.insert(worker.makeSubstitutionGoal(i, buildMode));
}
worker.run(goals);
PathSet failed;
- foreach (Goals::iterator, i, goals)
- if ((*i)->getExitCode() == Goal::ecFailed) {
- DerivationGoal * i2 = dynamic_cast<DerivationGoal *>(i->get());
+ for (auto & i : goals)
+ if (i->getExitCode() == Goal::ecFailed) {
+ DerivationGoal * i2 = dynamic_cast<DerivationGoal *>(i.get());
if (i2) failed.insert(i2->getDrvPath());
- else failed.insert(dynamic_cast<SubstitutionGoal *>(i->get())->getStorePath());
+ else failed.insert(dynamic_cast<SubstitutionGoal *>(i.get())->getStorePath());
}
if (!failed.empty())
@@ -3633,6 +3721,28 @@ void LocalStore::buildPaths(const PathSet & drvPaths, BuildMode buildMode)
}
+BuildResult LocalStore::buildDerivation(const Path & drvPath, const BasicDerivation & drv,
+ BuildMode buildMode)
+{
+ startNest(nest, lvlDebug, format("building %1%") % showPaths({drvPath}));
+
+ Worker worker(*this);
+ auto goal = worker.makeBasicDerivationGoal(drvPath, drv, buildMode);
+
+ BuildResult result;
+
+ try {
+ worker.run(Goals{goal});
+ result = goal->getResult();
+ } catch (Error & e) {
+ result.status = BuildResult::MiscFailure;
+ result.errorMsg = e.msg();
+ }
+
+ return result;
+}
+
+
void LocalStore::ensurePath(const Path & path)
{
/* If the path is already valid, we're done. */
diff --git a/src/libstore/builtins.cc b/src/libstore/builtins.cc
new file mode 100644
index 000000000..97d6cb943
--- /dev/null
+++ b/src/libstore/builtins.cc
@@ -0,0 +1,24 @@
+#include "builtins.hh"
+#include "download.hh"
+
+namespace nix {
+
+void builtinFetchurl(const BasicDerivation & drv)
+{
+ auto url = drv.env.find("url");
+ if (url == drv.env.end()) throw Error("attribute ‘url’ missing");
+ printMsg(lvlInfo, format("downloading ‘%1%’...") % url->second);
+ auto data = downloadFile(url->second); // FIXME: show progress
+
+ auto out = drv.env.find("out");
+ if (out == drv.env.end()) throw Error("attribute ‘url’ missing");
+ writeFile(out->second, data.data);
+
+ auto executable = drv.env.find("out");
+ if (executable != drv.env.end() && executable->second == "1") {
+ if (chmod(out->second.c_str(), 0755) == -1)
+ throw SysError(format("making ‘%1%’ executable") % out->second);
+ }
+}
+
+}
diff --git a/src/libstore/builtins.hh b/src/libstore/builtins.hh
new file mode 100644
index 000000000..4b2431aa0
--- /dev/null
+++ b/src/libstore/builtins.hh
@@ -0,0 +1,9 @@
+#pragma once
+
+#include "derivations.hh"
+
+namespace nix {
+
+void builtinFetchurl(const BasicDerivation & drv);
+
+}
diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc
index fbc1d99f3..7959d5bfc 100644
--- a/src/libstore/derivations.cc
+++ b/src/libstore/derivations.cc
@@ -3,6 +3,7 @@
#include "globals.hh"
#include "util.hh"
#include "misc.hh"
+#include "worker-protocol.hh"
namespace nix {
@@ -31,8 +32,8 @@ Path writeDerivation(StoreAPI & store,
{
PathSet references;
references.insert(drv.inputSrcs.begin(), drv.inputSrcs.end());
- foreach (DerivationInputs::const_iterator, i, drv.inputDrvs)
- references.insert(i->first);
+ for (auto & i : drv.inputDrvs)
+ references.insert(i.first);
/* Note that the outputs of a derivation are *not* references
(that can be missing (of course) and should not necessarily be
held during a garbage collection). */
@@ -155,21 +156,21 @@ string unparseDerivation(const Derivation & drv)
s += "Derive([";
bool first = true;
- foreach (DerivationOutputs::const_iterator, i, drv.outputs) {
+ for (auto & i : drv.outputs) {
if (first) first = false; else s += ',';
- s += '('; printString(s, i->first);
- s += ','; printString(s, i->second.path);
- s += ','; printString(s, i->second.hashAlgo);
- s += ','; printString(s, i->second.hash);
+ s += '('; printString(s, i.first);
+ s += ','; printString(s, i.second.path);
+ s += ','; printString(s, i.second.hashAlgo);
+ s += ','; printString(s, i.second.hash);
s += ')';
}
s += "],[";
first = true;
- foreach (DerivationInputs::const_iterator, i, drv.inputDrvs) {
+ for (auto & i : drv.inputDrvs) {
if (first) first = false; else s += ',';
- s += '('; printString(s, i->first);
- s += ','; printStrings(s, i->second.begin(), i->second.end());
+ s += '('; printString(s, i.first);
+ s += ','; printStrings(s, i.second.begin(), i.second.end());
s += ')';
}
@@ -182,10 +183,10 @@ string unparseDerivation(const Derivation & drv)
s += ",[";
first = true;
- foreach (StringPairs::const_iterator, i, drv.env) {
+ for (auto & i : drv.env) {
if (first) first = false; else s += ',';
- s += '('; printString(s, i->first);
- s += ','; printString(s, i->second);
+ s += '('; printString(s, i.first);
+ s += ','; printString(s, i.second);
s += ')';
}
@@ -246,15 +247,15 @@ Hash hashDerivationModulo(StoreAPI & store, Derivation drv)
/* For other derivations, replace the inputs paths with recursive
calls to this function.*/
DerivationInputs inputs2;
- foreach (DerivationInputs::const_iterator, i, drv.inputDrvs) {
- Hash h = drvHashes[i->first];
+ for (auto & i : drv.inputDrvs) {
+ Hash h = drvHashes[i.first];
if (h.type == htUnknown) {
- assert(store.isValidPath(i->first));
- Derivation drv2 = readDerivation(i->first);
+ assert(store.isValidPath(i.first));
+ Derivation drv2 = readDerivation(i.first);
h = hashDerivationModulo(store, drv2);
- drvHashes[i->first] = h;
+ drvHashes[i.first] = h;
}
- inputs2[printHash(h)] = i->second;
+ inputs2[printHash(h)] = i.second;
}
drv.inputDrvs = inputs2;
@@ -285,7 +286,7 @@ bool wantOutput(const string & output, const std::set<string> & wanted)
}
-PathSet outputPaths(const Derivation & drv)
+PathSet outputPaths(const BasicDerivation & drv)
{
PathSet paths;
for (auto & i : drv.outputs)
@@ -294,4 +295,44 @@ PathSet outputPaths(const Derivation & drv)
}
+Source & operator >> (Source & in, BasicDerivation & drv)
+{
+ drv.outputs.clear();
+ auto nr = readInt(in);
+ for (unsigned int n = 0; n < nr; n++) {
+ auto name = readString(in);
+ DerivationOutput o;
+ in >> o.path >> o.hashAlgo >> o.hash;
+ assertStorePath(o.path);
+ drv.outputs[name] = o;
+ }
+
+ drv.inputSrcs = readStorePaths<PathSet>(in);
+ in >> drv.platform >> drv.builder;
+ drv.args = readStrings<Strings>(in);
+
+ nr = readInt(in);
+ for (unsigned int n = 0; n < nr; n++) {
+ auto key = readString(in);
+ auto value = readString(in);
+ drv.env[key] = value;
+ }
+
+ return in;
+}
+
+
+Sink & operator << (Sink & out, const BasicDerivation & drv)
+{
+ out << drv.outputs.size();
+ for (auto & i : drv.outputs)
+ out << i.first << i.second.path << i.second.hashAlgo << i.second.hash;
+ out << drv.inputSrcs << drv.platform << drv.builder << drv.args;
+ out << drv.env.size();
+ for (auto & i : drv.env)
+ out << i.first << i.second;
+ return out;
+}
+
+
}
diff --git a/src/libstore/derivations.hh b/src/libstore/derivations.hh
index 8d5e4d05d..f0842045f 100644
--- a/src/libstore/derivations.hh
+++ b/src/libstore/derivations.hh
@@ -40,15 +40,21 @@ typedef std::map<Path, StringSet> DerivationInputs;
typedef std::map<string, string> StringPairs;
-struct Derivation
+struct BasicDerivation
{
DerivationOutputs outputs; /* keyed on symbolic IDs */
- DerivationInputs inputDrvs; /* inputs that are sub-derivations */
PathSet inputSrcs; /* inputs that are sources */
string platform;
Path builder;
Strings args;
StringPairs env;
+
+ virtual ~BasicDerivation() { };
+};
+
+struct Derivation : BasicDerivation
+{
+ DerivationInputs inputDrvs; /* inputs that are sub-derivations */
};
@@ -89,6 +95,12 @@ Path makeDrvPathWithOutputs(const Path & drvPath, const std::set<string> & outpu
bool wantOutput(const string & output, const std::set<string> & wanted);
-PathSet outputPaths(const Derivation & drv);
+PathSet outputPaths(const BasicDerivation & drv);
+
+struct Source;
+struct Sink;
+
+Source & operator >> (Source & in, BasicDerivation & drv);
+Sink & operator << (Sink & out, const BasicDerivation & drv);
}
diff --git a/src/libexpr/download.cc b/src/libstore/download.cc
index 9bf3e13aa..9bf3e13aa 100644
--- a/src/libexpr/download.cc
+++ b/src/libstore/download.cc
diff --git a/src/libexpr/download.hh b/src/libstore/download.hh
index 28c9117e4..28c9117e4 100644
--- a/src/libexpr/download.hh
+++ b/src/libstore/download.hh
diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc
index 8d7da67f5..998a7516a 100644
--- a/src/libstore/gc.cc
+++ b/src/libstore/gc.cc
@@ -350,15 +350,14 @@ static void addAdditionalRoots(StoreAPI & store, PathSet & roots)
StringSet paths = tokenizeString<StringSet>(result, "\n");
- foreach (StringSet::iterator, i, paths) {
- if (isInStore(*i)) {
- Path path = toStorePath(*i);
+ for (auto & i : paths)
+ if (isInStore(i)) {
+ Path path = toStorePath(i);
if (roots.find(path) == roots.end() && store.isValidPath(path)) {
debug(format("got additional root ‘%1%’") % path);
roots.insert(path);
}
}
- }
}
@@ -408,8 +407,8 @@ void LocalStore::deletePathRecursive(GCState & state, const Path & path)
if (isValidPath(path)) {
PathSet referrers;
queryReferrers(path, referrers);
- foreach (PathSet::iterator, i, referrers)
- if (*i != path) deletePathRecursive(state, *i);
+ for (auto & i : referrers)
+ if (i != path) deletePathRecursive(state, i);
size = queryPathInfo(path).narSize;
invalidatePathChecked(path);
}
@@ -487,22 +486,22 @@ bool LocalStore::canReachRoot(GCState & state, PathSet & visited, const Path & p
don't delete the derivation if any of the outputs are alive. */
if (state.gcKeepDerivations && isDerivation(path)) {
PathSet outputs = queryDerivationOutputs(path);
- foreach (PathSet::iterator, i, outputs)
- if (isValidPath(*i) && queryDeriver(*i) == path)
- incoming.insert(*i);
+ for (auto & i : outputs)
+ if (isValidPath(i) && queryDeriver(i) == path)
+ incoming.insert(i);
}
/* If gc-keep-outputs is set, then don't delete this path if there
are derivers of this path that are not garbage. */
if (state.gcKeepOutputs) {
PathSet derivers = queryValidDerivers(path);
- foreach (PathSet::iterator, i, derivers)
- incoming.insert(*i);
+ for (auto & i : derivers)
+ incoming.insert(i);
}
- foreach (PathSet::iterator, i, incoming)
- if (*i != path)
- if (canReachRoot(state, visited, *i)) {
+ for (auto & i : incoming)
+ if (i != path)
+ if (canReachRoot(state, visited, i)) {
state.alive.insert(path);
return true;
}
@@ -622,7 +621,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
printMsg(lvlError, format("finding garbage collector roots..."));
Roots rootMap = options.ignoreLiveness ? Roots() : findRoots();
- foreach (Roots::iterator, i, rootMap) state.roots.insert(i->second);
+ for (auto & i : rootMap) state.roots.insert(i.second);
/* Add additional roots returned by the program specified by the
NIX_ROOT_FINDER environment variable. This is typically used
@@ -659,11 +658,11 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
if (options.action == GCOptions::gcDeleteSpecific) {
- foreach (PathSet::iterator, i, options.pathsToDelete) {
- assertStorePath(*i);
- tryToDelete(state, *i);
- if (state.dead.find(*i) == state.dead.end())
- throw Error(format("cannot delete path ‘%1%’ since it is still alive") % *i);
+ for (auto & i : options.pathsToDelete) {
+ assertStorePath(i);
+ tryToDelete(state, i);
+ 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) {
@@ -707,8 +706,8 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
vector<Path> entries_(entries.begin(), entries.end());
random_shuffle(entries_.begin(), entries_.end());
- foreach (vector<Path>::iterator, i, entries_)
- tryToDelete(state, *i);
+ for (auto & i : entries_)
+ tryToDelete(state, i);
} catch (GCLimitReached & e) {
}
diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc
index 50374f782..73f848943 100644
--- a/src/libstore/globals.cc
+++ b/src/libstore/globals.cc
@@ -248,12 +248,12 @@ template<class N> void Settings::_get(N & res, const string & name)
string Settings::pack()
{
string s;
- foreach (SettingsMap::iterator, i, settings) {
- if (i->first.find('\n') != string::npos ||
- i->first.find('=') != string::npos ||
- i->second.find('\n') != string::npos)
+ for (auto & i : settings) {
+ if (i.first.find('\n') != string::npos ||
+ i.first.find('=') != string::npos ||
+ i.second.find('\n') != string::npos)
throw Error("illegal option name/value");
- s += i->first; s += '='; s += i->second; s += '\n';
+ s += i.first; s += '='; s += i.second; s += '\n';
}
return s;
}
@@ -261,11 +261,11 @@ string Settings::pack()
void Settings::unpack(const string & pack) {
Strings lines = tokenizeString<Strings>(pack, "\n");
- foreach (Strings::iterator, i, lines) {
- string::size_type eq = i->find('=');
+ for (auto & i : lines) {
+ string::size_type eq = i.find('=');
if (eq == string::npos)
throw Error("illegal option name/value");
- set(i->substr(0, eq), i->substr(eq + 1));
+ set(i.substr(0, eq), i.substr(eq + 1));
}
}
diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc
index 074c3394f..978bca28d 100644
--- a/src/libstore/local-store.cc
+++ b/src/libstore/local-store.cc
@@ -367,13 +367,13 @@ LocalStore::LocalStore(bool reserveSpace)
LocalStore::~LocalStore()
{
try {
- foreach (RunningSubstituters::iterator, i, runningSubstituters) {
- if (i->second.disabled) continue;
- i->second.to.close();
- i->second.from.close();
- i->second.error.close();
- if (i->second.pid != -1)
- i->second.pid.wait(true);
+ for (auto & i : runningSubstituters) {
+ if (i.second.disabled) continue;
+ i.second.to.close();
+ i.second.from.close();
+ i.second.error.close();
+ if (i.second.pid != -1)
+ i.second.pid.wait(true);
}
} catch (...) {
ignoreException();
@@ -671,19 +671,19 @@ void LocalStore::checkDerivationOutputs(const Path & drvPath, const Derivation &
else {
Derivation drvCopy(drv);
- foreach (DerivationOutputs::iterator, i, drvCopy.outputs) {
- i->second.path = "";
- drvCopy.env[i->first] = "";
+ for (auto & i : drvCopy.outputs) {
+ i.second.path = "";
+ drvCopy.env[i.first] = "";
}
Hash h = hashDerivationModulo(*this, drvCopy);
- foreach (DerivationOutputs::const_iterator, i, drv.outputs) {
- 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)
+ for (auto & i : drv.outputs) {
+ 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)
throw Error(format("derivation ‘%1%’ has incorrect output ‘%2%’, should be ‘%3%’")
- % drvPath % i->second.path % outPath);
+ % drvPath % i.second.path % outPath);
}
}
}
@@ -721,11 +721,11 @@ unsigned long long LocalStore::addValidPath(const ValidPathInfo & info, bool che
registration above is undone. */
if (checkOutputs) checkDerivationOutputs(info.path, drv);
- foreach (DerivationOutputs::iterator, i, drv.outputs) {
+ for (auto & i : drv.outputs) {
SQLiteStmtUse use(stmtAddDerivationOutput);
stmtAddDerivationOutput.bind(id);
- stmtAddDerivationOutput.bind(i->first);
- stmtAddDerivationOutput.bind(i->second.path);
+ stmtAddDerivationOutput.bind(i.first);
+ stmtAddDerivationOutput.bind(i.second.path);
if (sqlite3_step(stmtAddDerivationOutput) != SQLITE_DONE)
throwSQLiteError(db, format("adding derivation output for ‘%1%’ in database") % info.path);
}
@@ -796,11 +796,11 @@ void LocalStore::clearFailedPaths(const PathSet & paths)
retry_sqlite {
SQLiteTxn txn(db);
- foreach (PathSet::const_iterator, i, paths) {
+ for (auto & i : paths) {
SQLiteStmtUse use(stmtClearFailedPath);
- stmtClearFailedPath.bind(*i);
+ stmtClearFailedPath.bind(i);
if (sqlite3_step(stmtClearFailedPath) != SQLITE_DONE)
- throwSQLiteError(db, format("clearing failed path ‘%1%’ in database") % *i);
+ throwSQLiteError(db, format("clearing failed path ‘%1%’ in database") % i);
}
txn.commit();
@@ -923,8 +923,8 @@ PathSet LocalStore::queryValidPaths(const PathSet & paths)
{
retry_sqlite {
PathSet res;
- foreach (PathSet::const_iterator, i, paths)
- if (isValidPath_(*i)) res.insert(*i);
+ for (auto & i : paths)
+ if (isValidPath_(i)) res.insert(i);
return res;
} end_retry_sqlite;
}
@@ -1212,14 +1212,14 @@ template<class T> T LocalStore::getIntLineFromSubstituter(RunningSubstituter & r
PathSet LocalStore::querySubstitutablePaths(const PathSet & paths)
{
PathSet res;
- foreach (Paths::iterator, i, settings.substituters) {
+ for (auto & i : settings.substituters) {
if (res.size() == paths.size()) break;
- RunningSubstituter & run(runningSubstituters[*i]);
- startSubstituter(*i, run);
+ RunningSubstituter & run(runningSubstituters[i]);
+ startSubstituter(i, run);
if (run.disabled) continue;
string s = "have ";
- foreach (PathSet::const_iterator, j, paths)
- if (res.find(*j) == res.end()) { s += *j; s += " "; }
+ for (auto & j : paths)
+ if (res.find(j) == res.end()) { s += j; s += " "; }
writeLine(run.to, s);
while (true) {
/* FIXME: we only read stderr when an error occurs, so
@@ -1243,8 +1243,8 @@ void LocalStore::querySubstitutablePathInfos(const Path & substituter,
if (run.disabled) return;
string s = "info ";
- foreach (PathSet::const_iterator, i, paths)
- if (infos.find(*i) == infos.end()) { s += *i; s += " "; }
+ for (auto & i : paths)
+ if (infos.find(i) == infos.end()) { s += i; s += " "; }
writeLine(run.to, s);
while (true) {
@@ -1272,9 +1272,9 @@ void LocalStore::querySubstitutablePathInfos(const PathSet & paths,
SubstitutablePathInfos & infos)
{
PathSet todo = paths;
- foreach (Paths::iterator, i, settings.substituters) {
+ for (auto & i : settings.substituters) {
if (todo.empty()) break;
- querySubstitutablePathInfos(*i, todo, infos);
+ querySubstitutablePathInfos(i, todo, infos);
}
}
@@ -1304,30 +1304,30 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos)
SQLiteTxn txn(db);
PathSet paths;
- foreach (ValidPathInfos::const_iterator, i, infos) {
- assert(i->hash.type == htSHA256);
- if (isValidPath_(i->path))
- updatePathInfo(*i);
+ for (auto & i : infos) {
+ assert(i.hash.type == htSHA256);
+ if (isValidPath_(i.path))
+ updatePathInfo(i);
else
- addValidPath(*i, false);
- paths.insert(i->path);
+ addValidPath(i, false);
+ paths.insert(i.path);
}
- foreach (ValidPathInfos::const_iterator, i, infos) {
- unsigned long long referrer = queryValidPathId(i->path);
- foreach (PathSet::iterator, j, i->references)
- addReference(referrer, queryValidPathId(*j));
+ for (auto & i : infos) {
+ unsigned long long referrer = queryValidPathId(i.path);
+ for (auto & j : i.references)
+ addReference(referrer, queryValidPathId(j));
}
/* Check that the derivation outputs are correct. We can't do
this in addValidPath() above, because the references might
not be valid yet. */
- foreach (ValidPathInfos::const_iterator, i, infos)
- if (isDerivation(i->path)) {
+ for (auto & i : infos)
+ if (isDerivation(i.path)) {
// FIXME: inefficient; we already loaded the
// derivation in addValidPath().
- Derivation drv = readDerivation(i->path);
- checkDerivationOutputs(i->path, drv);
+ Derivation drv = readDerivation(i.path);
+ checkDerivationOutputs(i.path, drv);
}
/* Do a topological sort of the paths. This will throw an
@@ -1510,7 +1510,7 @@ void LocalStore::exportPath(const Path & path, bool sign,
{
assertStorePath(path);
- printMsg(lvlInfo, format("exporting path ‘%1%’") % path);
+ printMsg(lvlTalkative, format("exporting path ‘%1%’") % path);
if (!isValidPath(path))
throw Error(format("path ‘%1%’ is not valid") % path);
@@ -1528,22 +1528,14 @@ void LocalStore::exportPath(const Path & path, bool sign,
throw Error(format("hash of path ‘%1%’ has changed from ‘%2%’ to ‘%3%’!") % path
% printHash(storedHash) % printHash(hash));
- writeInt(EXPORT_MAGIC, hashAndWriteSink);
-
- writeString(path, hashAndWriteSink);
-
PathSet references;
queryReferences(path, references);
- writeStrings(references, hashAndWriteSink);
- Path deriver = queryDeriver(path);
- writeString(deriver, hashAndWriteSink);
+ hashAndWriteSink << EXPORT_MAGIC << path << references << queryDeriver(path);
if (sign) {
Hash hash = hashAndWriteSink.currentHash();
- writeInt(1, hashAndWriteSink);
-
Path tmpDir = createTempDir();
AutoDelete delTmp(tmpDir);
Path hashFile = tmpDir + "/hash";
@@ -1561,10 +1553,10 @@ void LocalStore::exportPath(const Path & path, bool sign,
args.push_back(hashFile);
string signature = runProgram(OPENSSL_PATH, true, args);
- writeString(signature, hashAndWriteSink);
+ hashAndWriteSink << 1 << signature;
} else
- writeInt(0, hashAndWriteSink);
+ hashAndWriteSink << 0;
}
@@ -1621,6 +1613,8 @@ Path LocalStore::importPath(bool requireSignature, Source & source)
Path dstPath = readStorePath(hashAndReadSource);
+ printMsg(lvlTalkative, format("importing path ‘%1%’") % dstPath);
+
PathSet references = readStorePaths<PathSet>(hashAndReadSource);
Path deriver = readString(hashAndReadSource);
@@ -1761,8 +1755,8 @@ bool LocalStore::verifyStore(bool checkContents, bool repair)
PathSet validPaths2 = queryAllValidPaths(), validPaths, done;
- foreach (PathSet::iterator, i, validPaths2)
- verifyPath(*i, store, done, validPaths, repair, errors);
+ for (auto & i : validPaths2)
+ verifyPath(i, store, done, validPaths, repair, errors);
/* Release the GC lock so that checking content hashes (which can
take ages) doesn't block the GC or builds. */
@@ -1774,33 +1768,33 @@ bool LocalStore::verifyStore(bool checkContents, bool repair)
Hash nullHash(htSHA256);
- foreach (PathSet::iterator, i, validPaths) {
+ for (auto & i : validPaths) {
try {
- ValidPathInfo info = queryPathInfo(*i);
+ ValidPathInfo info = queryPathInfo(i);
/* Check the content hash (optionally - slow). */
- printMsg(lvlTalkative, format("checking contents of ‘%1%’") % *i);
- HashResult current = hashPath(info.hash.type, *i);
+ printMsg(lvlTalkative, format("checking contents of ‘%1%’") % i);
+ HashResult current = hashPath(info.hash.type, i);
if (info.hash != nullHash && info.hash != current.first) {
printMsg(lvlError, format("path ‘%1%’ was modified! "
"expected hash ‘%2%’, got ‘%3%’")
- % *i % printHash(info.hash) % printHash(current.first));
- if (repair) repairPath(*i); else errors = true;
+ % i % printHash(info.hash) % printHash(current.first));
+ if (repair) repairPath(i); else errors = true;
} else {
bool update = false;
/* Fill in missing hashes. */
if (info.hash == nullHash) {
- printMsg(lvlError, format("fixing missing hash on ‘%1%’") % *i);
+ printMsg(lvlError, format("fixing missing hash on ‘%1%’") % i);
info.hash = current.first;
update = true;
}
/* Fill in missing narSize fields (from old stores). */
if (info.narSize == 0) {
- printMsg(lvlError, format("updating size field on ‘%1%’ to %2%") % *i % current.second);
+ printMsg(lvlError, format("updating size field on ‘%1%’ to %2%") % i % current.second);
info.narSize = current.second;
update = true;
}
@@ -1812,7 +1806,7 @@ bool LocalStore::verifyStore(bool checkContents, bool repair)
} catch (Error & e) {
/* It's possible that the path got GC'ed, so ignore
errors on invalid paths. */
- if (isValidPath(*i))
+ if (isValidPath(i))
printMsg(lvlError, format("error: %1%") % e.msg());
else
printMsg(lvlError, format("warning: %1%") % e.msg());
@@ -1844,10 +1838,10 @@ void LocalStore::verifyPath(const Path & path, const PathSet & store,
first, then we can invalidate this path as well. */
bool canInvalidate = true;
PathSet referrers; queryReferrers(path, referrers);
- foreach (PathSet::iterator, i, referrers)
- if (*i != path) {
- verifyPath(*i, store, done, validPaths, repair, errors);
- if (validPaths.find(*i) != validPaths.end())
+ for (auto & i : referrers)
+ if (i != path) {
+ verifyPath(i, store, done, validPaths, repair, errors);
+ if (validPaths.find(i) != validPaths.end())
canInvalidate = false;
}
@@ -1925,12 +1919,12 @@ ValidPathInfo LocalStore::queryPathInfoOld(const Path & path)
/* Parse it. */
Strings lines = tokenizeString<Strings>(info, "\n");
- foreach (Strings::iterator, i, lines) {
- string::size_type p = i->find(':');
+ for (auto & i : lines) {
+ string::size_type p = i.find(':');
if (p == string::npos)
- throw Error(format("corrupt line in ‘%1%’: %2%") % infoFile % *i);
- string name(*i, 0, p);
- string value(*i, p + 2);
+ throw Error(format("corrupt line in ‘%1%’: %2%") % infoFile % i);
+ string name(i, 0, p);
+ string value(i, p + 2);
if (name == "References") {
Strings refs = tokenizeString<Strings>(value, " ");
res.references = PathSet(refs.begin(), refs.end());
@@ -1960,18 +1954,18 @@ void LocalStore::upgradeStore6()
SQLiteTxn txn(db);
- foreach (PathSet::iterator, i, validPaths) {
- addValidPath(queryPathInfoOld(*i), false);
+ for (auto & i : validPaths) {
+ addValidPath(queryPathInfoOld(i), false);
std::cerr << ".";
}
std::cerr << "|";
- foreach (PathSet::iterator, i, validPaths) {
- ValidPathInfo info = queryPathInfoOld(*i);
- unsigned long long referrer = queryValidPathId(*i);
- foreach (PathSet::iterator, j, info.references)
- addReference(referrer, queryValidPathId(*j));
+ for (auto & i : validPaths) {
+ ValidPathInfo info = queryPathInfoOld(i);
+ unsigned long long referrer = queryValidPathId(i);
+ for (auto & j : info.references)
+ addReference(referrer, queryValidPathId(j));
std::cerr << ".";
}
diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh
index 819f59327..105f3592c 100644
--- a/src/libstore/local-store.hh
+++ b/src/libstore/local-store.hh
@@ -151,6 +151,9 @@ public:
void buildPaths(const PathSet & paths, BuildMode buildMode);
+ BuildResult buildDerivation(const Path & drvPath, const BasicDerivation & drv,
+ BuildMode buildMode) override;
+
void ensurePath(const Path & path);
void addTempRoot(const Path & path);
diff --git a/src/libstore/local.mk b/src/libstore/local.mk
index 771c06753..bf5c256c9 100644
--- a/src/libstore/local.mk
+++ b/src/libstore/local.mk
@@ -8,7 +8,7 @@ libstore_SOURCES := $(wildcard $(d)/*.cc)
libstore_LIBS = libutil libformat
-libstore_LDFLAGS = -lsqlite3 -lbz2
+libstore_LDFLAGS = -lsqlite3 -lbz2 -lcurl
ifeq ($(OS), SunOS)
libstore_LDFLAGS += -lsocket
diff --git a/src/libstore/misc.cc b/src/libstore/misc.cc
index 736434ca4..61a976c02 100644
--- a/src/libstore/misc.cc
+++ b/src/libstore/misc.cc
@@ -28,15 +28,15 @@ void computeFSClosure(StoreAPI & store, const Path & path,
if (includeOutputs) {
PathSet derivers = store.queryValidDerivers(path);
- foreach (PathSet::iterator, i, derivers)
- edges.insert(*i);
+ for (auto & i : derivers)
+ edges.insert(i);
}
if (includeDerivers && isDerivation(path)) {
PathSet outputs = store.queryDerivationOutputs(path);
- foreach (PathSet::iterator, i, outputs)
- if (store.isValidPath(*i) && store.queryDeriver(*i) == path)
- edges.insert(*i);
+ for (auto & i : outputs)
+ if (store.isValidPath(i) && store.queryDeriver(i) == path)
+ edges.insert(i);
}
} else {
@@ -44,8 +44,8 @@ void computeFSClosure(StoreAPI & store, const Path & path,
if (includeOutputs && isDerivation(path)) {
PathSet outputs = store.queryDerivationOutputs(path);
- foreach (PathSet::iterator, i, outputs)
- if (store.isValidPath(*i)) edges.insert(*i);
+ for (auto & i : outputs)
+ if (store.isValidPath(i)) edges.insert(i);
}
if (includeDerivers) {
@@ -54,15 +54,15 @@ void computeFSClosure(StoreAPI & store, const Path & path,
}
}
- foreach (PathSet::iterator, i, edges)
- computeFSClosure(store, *i, paths, flipDirection, includeOutputs, includeDerivers);
+ for (auto & i : edges)
+ computeFSClosure(store, i, paths, flipDirection, includeOutputs, includeDerivers);
}
Path findOutput(const Derivation & drv, string id)
{
- foreach (DerivationOutputs::const_iterator, i, drv.outputs)
- if (i->first == id) return i->second.path;
+ for (auto & i : drv.outputs)
+ if (i.first == id) return i.second.path;
throw Error(format("derivation has no output ‘%1%’") % id);
}
@@ -98,36 +98,36 @@ void queryMissing(StoreAPI & store, const PathSet & targets,
PathSet query, todoDrv, todoNonDrv;
- foreach (PathSet::iterator, i, todo) {
- if (done.find(*i) != done.end()) continue;
- done.insert(*i);
+ for (auto & i : todo) {
+ if (done.find(i) != done.end()) continue;
+ done.insert(i);
- DrvPathWithOutputs i2 = parseDrvPathWithOutputs(*i);
+ DrvPathWithOutputs i2 = parseDrvPathWithOutputs(i);
if (isDerivation(i2.first)) {
if (!store.isValidPath(i2.first)) {
// FIXME: we could try to substitute p.
- unknown.insert(*i);
+ unknown.insert(i);
continue;
}
Derivation drv = derivationFromPath(store, i2.first);
PathSet invalid;
- foreach (DerivationOutputs::iterator, j, drv.outputs)
- if (wantOutput(j->first, i2.second)
- && !store.isValidPath(j->second.path))
- invalid.insert(j->second.path);
+ for (auto & j : drv.outputs)
+ if (wantOutput(j.first, i2.second)
+ && !store.isValidPath(j.second.path))
+ invalid.insert(j.second.path);
if (invalid.empty()) continue;
- todoDrv.insert(*i);
+ todoDrv.insert(i);
if (settings.useSubstitutes && substitutesAllowed(drv))
query.insert(invalid.begin(), invalid.end());
}
else {
- if (store.isValidPath(*i)) continue;
- query.insert(*i);
- todoNonDrv.insert(*i);
+ if (store.isValidPath(i)) continue;
+ query.insert(i);
+ todoNonDrv.insert(i);
}
}
@@ -136,8 +136,8 @@ void queryMissing(StoreAPI & store, const PathSet & targets,
SubstitutablePathInfos infos;
store.querySubstitutablePathInfos(query, infos);
- foreach (PathSet::iterator, i, todoDrv) {
- DrvPathWithOutputs i2 = parseDrvPathWithOutputs(*i);
+ for (auto & i : todoDrv) {
+ DrvPathWithOutputs i2 = parseDrvPathWithOutputs(i);
// FIXME: cache this
Derivation drv = derivationFromPath(store, i2.first);
@@ -145,13 +145,13 @@ void queryMissing(StoreAPI & store, const PathSet & targets,
PathSet outputs;
bool mustBuild = false;
if (settings.useSubstitutes && substitutesAllowed(drv)) {
- foreach (DerivationOutputs::iterator, j, drv.outputs) {
- if (!wantOutput(j->first, i2.second)) continue;
- if (!store.isValidPath(j->second.path)) {
- if (infos.find(j->second.path) == infos.end())
+ for (auto & j : drv.outputs) {
+ if (!wantOutput(j.first, i2.second)) continue;
+ if (!store.isValidPath(j.second.path)) {
+ if (infos.find(j.second.path) == infos.end())
mustBuild = true;
else
- outputs.insert(j->second.path);
+ outputs.insert(j.second.path);
}
}
} else
@@ -160,22 +160,22 @@ void queryMissing(StoreAPI & store, const PathSet & targets,
if (mustBuild) {
willBuild.insert(i2.first);
todo.insert(drv.inputSrcs.begin(), drv.inputSrcs.end());
- foreach (DerivationInputs::iterator, j, drv.inputDrvs)
- todo.insert(makeDrvPathWithOutputs(j->first, j->second));
+ for (auto & j : drv.inputDrvs)
+ todo.insert(makeDrvPathWithOutputs(j.first, j.second));
} else
todoNonDrv.insert(outputs.begin(), outputs.end());
}
- foreach (PathSet::iterator, i, todoNonDrv) {
- done.insert(*i);
- SubstitutablePathInfos::iterator info = infos.find(*i);
+ for (auto & i : todoNonDrv) {
+ done.insert(i);
+ SubstitutablePathInfos::iterator info = infos.find(i);
if (info != infos.end()) {
- willSubstitute.insert(*i);
+ willSubstitute.insert(i);
downloadSize += info->second.downloadSize;
narSize += info->second.narSize;
todo.insert(info->second.references.begin(), info->second.references.end());
} else
- unknown.insert(*i);
+ unknown.insert(i);
}
}
}
@@ -196,11 +196,11 @@ static void dfsVisit(StoreAPI & store, const PathSet & paths,
if (store.isValidPath(path))
store.queryReferences(path, references);
- foreach (PathSet::iterator, 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(store, paths, *i, visited, sorted, parents);
+ if (i != path && paths.find(i) != paths.end())
+ dfsVisit(store, paths, i, visited, sorted, parents);
sorted.push_front(path);
parents.erase(path);
@@ -211,8 +211,8 @@ Paths topoSortPaths(StoreAPI & store, const PathSet & paths)
{
Paths sorted;
PathSet visited, parents;
- foreach (PathSet::const_iterator, i, paths)
- dfsVisit(store, paths, *i, visited, sorted, parents);
+ for (auto & i : paths)
+ dfsVisit(store, paths, i, visited, sorted, parents);
return sorted;
}
diff --git a/src/libstore/misc.hh b/src/libstore/misc.hh
index d3e31d51f..495c52875 100644
--- a/src/libstore/misc.hh
+++ b/src/libstore/misc.hh
@@ -32,9 +32,9 @@ void queryMissing(StoreAPI & store, const PathSet & targets,
PathSet & willBuild, PathSet & willSubstitute, PathSet & unknown,
unsigned long long & downloadSize, unsigned long long & narSize);
-bool willBuildLocally(const Derivation & drv);
+bool willBuildLocally(const BasicDerivation & drv);
-bool substitutesAllowed(const Derivation & drv);
+bool substitutesAllowed(const BasicDerivation & drv);
}
diff --git a/src/libstore/optimise-store.cc b/src/libstore/optimise-store.cc
index 55c252b9b..6f6696179 100644
--- a/src/libstore/optimise-store.cc
+++ b/src/libstore/optimise-store.cc
@@ -99,8 +99,8 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
if (S_ISDIR(st.st_mode)) {
Strings names = readDirectoryIgnoringInodes(path, inodeHash);
- foreach (Strings::iterator, i, names)
- optimisePath_(stats, path + "/" + *i, inodeHash);
+ for (auto & i : names)
+ optimisePath_(stats, path + "/" + i, inodeHash);
return;
}
@@ -218,11 +218,11 @@ void LocalStore::optimiseStore(OptimiseStats & stats)
PathSet paths = queryAllValidPaths();
InodeHash inodeHash = loadInodeHash();
- foreach (PathSet::iterator, i, paths) {
- addTempRoot(*i);
- if (!isValidPath(*i)) continue; /* path was GC'ed, probably */
- startNest(nest, lvlChatty, format("hashing files in ‘%1%’") % *i);
- optimisePath_(stats, *i, inodeHash);
+ for (auto & i : paths) {
+ addTempRoot(i);
+ if (!isValidPath(i)) continue; /* path was GC'ed, probably */
+ startNest(nest, lvlChatty, format("hashing files in ‘%1%’") % i);
+ optimisePath_(stats, i, inodeHash);
}
}
diff --git a/src/libstore/pathlocks.cc b/src/libstore/pathlocks.cc
index 9db37e8f9..1c87034f8 100644
--- a/src/libstore/pathlocks.cc
+++ b/src/libstore/pathlocks.cc
@@ -60,7 +60,7 @@ bool lockFile(int fd, LockType lockType, bool wait)
while (fcntl(fd, F_SETLK, &lock) != 0) {
checkInterrupt();
if (errno == EACCES || errno == EAGAIN) return false;
- if (errno != EINTR)
+ if (errno != EINTR)
throw SysError(format("acquiring/releasing lock"));
}
}
@@ -94,7 +94,7 @@ bool PathLocks::lockPaths(const PathSet & _paths,
const string & waitMsg, bool wait)
{
assert(fds.empty());
-
+
/* Note that `fds' is built incrementally so that the destructor
will only release those locks that we have already acquired. */
@@ -102,11 +102,10 @@ bool PathLocks::lockPaths(const PathSet & _paths,
the same order, thus preventing deadlocks. */
Paths paths(_paths.begin(), _paths.end());
paths.sort();
-
+
/* Acquire the lock for each path. */
- foreach (Paths::iterator, i, paths) {
+ for (auto & path : paths) {
checkInterrupt();
- Path path = *i;
Path lockPath = path + ".lock";
debug(format("locking path ‘%1%’") % path);
@@ -115,11 +114,11 @@ bool PathLocks::lockPaths(const PathSet & _paths,
throw Error("deadlock: trying to re-acquire self-held lock");
AutoCloseFD fd;
-
+
while (1) {
/* Open/create the lock file. */
- fd = openLockFile(lockPath, true);
+ fd = openLockFile(lockPath, true);
/* Acquire an exclusive lock. */
if (!lockFile(fd, ltWrite, false)) {
@@ -168,15 +167,15 @@ PathLocks::~PathLocks()
void PathLocks::unlock()
{
- foreach (list<FDPair>::iterator, i, fds) {
- if (deletePaths) deleteLockFile(i->second, i->first);
+ for (auto & i : fds) {
+ if (deletePaths) deleteLockFile(i.second, i.first);
- lockedPaths.erase(i->second);
- if (close(i->first) == -1)
+ lockedPaths.erase(i.second);
+ if (close(i.first) == -1)
printMsg(lvlError,
- format("error (ignored): cannot close lock file on ‘%1%’") % i->second);
+ format("error (ignored): cannot close lock file on ‘%1%’") % i.second);
- debug(format("lock released on ‘%1%’") % i->second);
+ debug(format("lock released on ‘%1%’") % i.second);
}
fds.clear();
@@ -195,5 +194,5 @@ bool pathIsLockedByMe(const Path & path)
return lockedPaths.find(lockPath) != lockedPaths.end();
}
-
+
}
diff --git a/src/libstore/references.cc b/src/libstore/references.cc
index 521244a31..33eab5a24 100644
--- a/src/libstore/references.cc
+++ b/src/libstore/references.cc
@@ -13,7 +13,7 @@ namespace nix {
static unsigned int refLength = 32; /* characters */
-static void search(const unsigned char * s, unsigned int len,
+static void search(const unsigned char * s, unsigned int len,
StringSet & hashes, StringSet & seen)
{
static bool initialised = false;
@@ -24,7 +24,7 @@ static void search(const unsigned char * s, unsigned int len,
isBase32[(unsigned char) base32Chars[i]] = true;
initialised = true;
}
-
+
for (unsigned int i = 0; i + refLength <= len; ) {
int j;
bool match = true;
@@ -56,7 +56,7 @@ struct RefScanSink : Sink
string tail;
RefScanSink() : hashSink(htSHA256) { }
-
+
void operator () (const unsigned char * data, size_t len);
};
@@ -89,17 +89,17 @@ PathSet scanForReferences(const string & path,
/* For efficiency (and a higher hit rate), just search for the
hash part of the file name. (This assumes that all references
have the form `HASH-bla'). */
- foreach (PathSet::const_iterator, i, refs) {
- string baseName = baseNameOf(*i);
+ for (auto & i : refs) {
+ string baseName = baseNameOf(i);
string::size_type pos = baseName.find('-');
if (pos == string::npos)
- throw Error(format("bad reference ‘%1%’") % *i);
+ throw Error(format("bad reference ‘%1%’") % i);
string s = string(baseName, 0, pos);
assert(s.size() == refLength);
assert(backMap.find(s) == backMap.end());
// parseHash(htSHA256, s);
sink.hashes.insert(s);
- backMap[s] = *i;
+ backMap[s] = i;
}
/* Look for the hashes in the NAR dump of the path. */
@@ -107,14 +107,14 @@ PathSet scanForReferences(const string & path,
/* Map the hashes found back to their store paths. */
PathSet found;
- foreach (StringSet::iterator, i, sink.seen) {
+ for (auto & i : sink.seen) {
std::map<string, Path>::iterator j;
- if ((j = backMap.find(*i)) == backMap.end()) abort();
+ if ((j = backMap.find(i)) == backMap.end()) abort();
found.insert(j->second);
}
hash = sink.hashSink.finish();
-
+
return found;
}
diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc
index ab87d9d8b..fdb0975ac 100644
--- a/src/libstore/remote-store.cc
+++ b/src/libstore/remote-store.cc
@@ -31,7 +31,7 @@ Path readStorePath(Source & from)
template<class T> T readStorePaths(Source & from)
{
T paths = readStrings<T>(from);
- foreach (typename T::iterator, i, paths) assertStorePath(*i);
+ for (auto & i : paths) assertStorePath(i);
return paths;
}
@@ -63,7 +63,7 @@ void RemoteStore::openConnection(bool reserveSpace)
/* Send the magic greeting, check for the reply. */
try {
- writeInt(WORKER_MAGIC_1, to);
+ to << WORKER_MAGIC_1;
to.flush();
unsigned int magic = readInt(from);
if (magic != WORKER_MAGIC_2) throw Error("protocol mismatch");
@@ -71,19 +71,18 @@ void RemoteStore::openConnection(bool reserveSpace)
daemonVersion = readInt(from);
if (GET_PROTOCOL_MAJOR(daemonVersion) != GET_PROTOCOL_MAJOR(PROTOCOL_VERSION))
throw Error("Nix daemon protocol version not supported");
- writeInt(PROTOCOL_VERSION, to);
+ to << PROTOCOL_VERSION;
if (GET_PROTOCOL_MINOR(daemonVersion) >= 14) {
int cpu = settings.lockCPU ? lockToCurrentCPU() : -1;
- if (cpu != -1) {
- writeInt(1, to);
- writeInt(cpu, to);
- } else
- writeInt(0, to);
+ if (cpu != -1)
+ to << 1 << cpu;
+ else
+ to << 0;
}
if (GET_PROTOCOL_MINOR(daemonVersion) >= 11)
- writeInt(reserveSpace, to);
+ to << reserveSpace;
processStderr();
}
@@ -141,35 +140,31 @@ RemoteStore::~RemoteStore()
void RemoteStore::setOptions()
{
- writeInt(wopSetOptions, to);
-
- writeInt(settings.keepFailed, to);
- writeInt(settings.keepGoing, to);
- writeInt(settings.tryFallback, to);
- writeInt(verbosity, to);
- writeInt(settings.maxBuildJobs, to);
- writeInt(settings.maxSilentTime, to);
+ to << wopSetOptions
+ << settings.keepFailed
+ << settings.keepGoing
+ << settings.tryFallback
+ << verbosity
+ << settings.maxBuildJobs
+ << settings.maxSilentTime;
if (GET_PROTOCOL_MINOR(daemonVersion) >= 2)
- writeInt(settings.useBuildHook, to);
- if (GET_PROTOCOL_MINOR(daemonVersion) >= 4) {
- writeInt(settings.buildVerbosity, to);
- writeInt(logType, to);
- writeInt(settings.printBuildTrace, to);
- }
+ to << settings.useBuildHook;
+ if (GET_PROTOCOL_MINOR(daemonVersion) >= 4)
+ to << settings.buildVerbosity
+ << logType
+ << settings.printBuildTrace;
if (GET_PROTOCOL_MINOR(daemonVersion) >= 6)
- writeInt(settings.buildCores, to);
+ to << settings.buildCores;
if (GET_PROTOCOL_MINOR(daemonVersion) >= 10)
- writeInt(settings.useSubstitutes, to);
+ to << settings.useSubstitutes;
if (GET_PROTOCOL_MINOR(daemonVersion) >= 12) {
Settings::SettingsMap overrides = settings.getOverrides();
if (overrides["ssh-auth-sock"] == "")
overrides["ssh-auth-sock"] = getEnv("SSH_AUTH_SOCK");
- writeInt(overrides.size(), to);
- foreach (Settings::SettingsMap::iterator, i, overrides) {
- writeString(i->first, to);
- writeString(i->second, to);
- }
+ to << overrides.size();
+ for (auto & i : overrides)
+ to << i.first << i.second;
}
processStderr();
@@ -179,8 +174,7 @@ void RemoteStore::setOptions()
bool RemoteStore::isValidPath(const Path & path)
{
openConnection();
- writeInt(wopIsValidPath, to);
- writeString(path, to);
+ to << wopIsValidPath << path;
processStderr();
unsigned int reply = readInt(from);
return reply != 0;
@@ -192,12 +186,11 @@ PathSet RemoteStore::queryValidPaths(const PathSet & paths)
openConnection();
if (GET_PROTOCOL_MINOR(daemonVersion) < 12) {
PathSet res;
- foreach (PathSet::const_iterator, i, paths)
- if (isValidPath(*i)) res.insert(*i);
+ for (auto & i : paths)
+ if (isValidPath(i)) res.insert(i);
return res;
} else {
- writeInt(wopQueryValidPaths, to);
- writeStrings(paths, to);
+ to << wopQueryValidPaths << paths;
processStderr();
return readStorePaths<PathSet>(from);
}
@@ -207,7 +200,7 @@ PathSet RemoteStore::queryValidPaths(const PathSet & paths)
PathSet RemoteStore::queryAllValidPaths()
{
openConnection();
- writeInt(wopQueryAllValidPaths, to);
+ to << wopQueryAllValidPaths;
processStderr();
return readStorePaths<PathSet>(from);
}
@@ -218,16 +211,14 @@ PathSet RemoteStore::querySubstitutablePaths(const PathSet & paths)
openConnection();
if (GET_PROTOCOL_MINOR(daemonVersion) < 12) {
PathSet res;
- foreach (PathSet::const_iterator, i, paths) {
- writeInt(wopHasSubstitutes, to);
- writeString(*i, to);
+ for (auto & i : paths) {
+ to << wopHasSubstitutes << i;
processStderr();
- if (readInt(from)) res.insert(*i);
+ if (readInt(from)) res.insert(i);
}
return res;
} else {
- writeInt(wopQuerySubstitutablePaths, to);
- writeStrings(paths, to);
+ to << wopQuerySubstitutablePaths << paths;
processStderr();
return readStorePaths<PathSet>(from);
}
@@ -245,10 +236,9 @@ void RemoteStore::querySubstitutablePathInfos(const PathSet & paths,
if (GET_PROTOCOL_MINOR(daemonVersion) < 12) {
- foreach (PathSet::const_iterator, i, paths) {
+ for (auto & i : paths) {
SubstitutablePathInfo info;
- writeInt(wopQuerySubstitutablePathInfo, to);
- writeString(*i, to);
+ to << wopQuerySubstitutablePathInfo << i;
processStderr();
unsigned int reply = readInt(from);
if (reply == 0) continue;
@@ -257,13 +247,12 @@ void RemoteStore::querySubstitutablePathInfos(const PathSet & paths,
info.references = readStorePaths<PathSet>(from);
info.downloadSize = readLongLong(from);
info.narSize = GET_PROTOCOL_MINOR(daemonVersion) >= 7 ? readLongLong(from) : 0;
- infos[*i] = info;
+ infos[i] = info;
}
} else {
- writeInt(wopQuerySubstitutablePathInfos, to);
- writeStrings(paths, to);
+ to << wopQuerySubstitutablePathInfos << paths;
processStderr();
unsigned int count = readInt(from);
for (unsigned int n = 0; n < count; n++) {
@@ -283,8 +272,7 @@ void RemoteStore::querySubstitutablePathInfos(const PathSet & paths,
ValidPathInfo RemoteStore::queryPathInfo(const Path & path)
{
openConnection();
- writeInt(wopQueryPathInfo, to);
- writeString(path, to);
+ to << wopQueryPathInfo << path;
processStderr();
ValidPathInfo info;
info.path = path;
@@ -301,8 +289,7 @@ ValidPathInfo RemoteStore::queryPathInfo(const Path & path)
Hash RemoteStore::queryPathHash(const Path & path)
{
openConnection();
- writeInt(wopQueryPathHash, to);
- writeString(path, to);
+ to << wopQueryPathHash << path;
processStderr();
string hash = readString(from);
return parseHash(htSHA256, hash);
@@ -313,8 +300,7 @@ void RemoteStore::queryReferences(const Path & path,
PathSet & references)
{
openConnection();
- writeInt(wopQueryReferences, to);
- writeString(path, to);
+ to << wopQueryReferences << path;
processStderr();
PathSet references2 = readStorePaths<PathSet>(from);
references.insert(references2.begin(), references2.end());
@@ -325,8 +311,7 @@ void RemoteStore::queryReferrers(const Path & path,
PathSet & referrers)
{
openConnection();
- writeInt(wopQueryReferrers, to);
- writeString(path, to);
+ to << wopQueryReferrers << path;
processStderr();
PathSet referrers2 = readStorePaths<PathSet>(from);
referrers.insert(referrers2.begin(), referrers2.end());
@@ -336,8 +321,7 @@ void RemoteStore::queryReferrers(const Path & path,
Path RemoteStore::queryDeriver(const Path & path)
{
openConnection();
- writeInt(wopQueryDeriver, to);
- writeString(path, to);
+ to << wopQueryDeriver << path;
processStderr();
Path drvPath = readString(from);
if (drvPath != "") assertStorePath(drvPath);
@@ -348,8 +332,7 @@ Path RemoteStore::queryDeriver(const Path & path)
PathSet RemoteStore::queryValidDerivers(const Path & path)
{
openConnection();
- writeInt(wopQueryValidDerivers, to);
- writeString(path, to);
+ to << wopQueryValidDerivers << path;
processStderr();
return readStorePaths<PathSet>(from);
}
@@ -358,8 +341,7 @@ PathSet RemoteStore::queryValidDerivers(const Path & path)
PathSet RemoteStore::queryDerivationOutputs(const Path & path)
{
openConnection();
- writeInt(wopQueryDerivationOutputs, to);
- writeString(path, to);
+ to << wopQueryDerivationOutputs << path;
processStderr();
return readStorePaths<PathSet>(from);
}
@@ -368,8 +350,7 @@ PathSet RemoteStore::queryDerivationOutputs(const Path & path)
PathSet RemoteStore::queryDerivationOutputNames(const Path & path)
{
openConnection();
- writeInt(wopQueryDerivationOutputNames, to);
- writeString(path, to);
+ to << wopQueryDerivationOutputNames << path;
processStderr();
return readStrings<PathSet>(from);
}
@@ -378,8 +359,7 @@ PathSet RemoteStore::queryDerivationOutputNames(const Path & path)
Path RemoteStore::queryPathFromHashPart(const string & hashPart)
{
openConnection();
- writeInt(wopQueryPathFromHashPart, to);
- writeString(hashPart, to);
+ to << wopQueryPathFromHashPart << hashPart;
processStderr();
Path path = readString(from);
if (!path.empty()) assertStorePath(path);
@@ -396,12 +376,10 @@ Path RemoteStore::addToStore(const string & name, const Path & _srcPath,
Path srcPath(absPath(_srcPath));
- writeInt(wopAddToStore, to);
- writeString(name, to);
- /* backwards compatibility hack */
- writeInt((hashAlgo == htSHA256 && recursive) ? 0 : 1, to);
- writeInt(recursive ? 1 : 0, to);
- writeString(printHashType(hashAlgo), to);
+ to << wopAddToStore << name
+ << ((hashAlgo == htSHA256 && recursive) ? 0 : 1) /* backwards compatibility hack */
+ << (recursive ? 1 : 0)
+ << printHashType(hashAlgo);
try {
to.written = 0;
@@ -429,10 +407,7 @@ Path RemoteStore::addTextToStore(const string & name, const string & s,
if (repair) throw Error("repairing is not supported when building through the Nix daemon");
openConnection();
- writeInt(wopAddTextToStore, to);
- writeString(name, to);
- writeString(s, to);
- writeStrings(references, to);
+ to << wopAddTextToStore << name << s << references;
processStderr();
return readStorePath(from);
@@ -443,9 +418,7 @@ void RemoteStore::exportPath(const Path & path, bool sign,
Sink & sink)
{
openConnection();
- writeInt(wopExportPath, to);
- writeString(path, to);
- writeInt(sign ? 1 : 0, to);
+ to << wopExportPath << path << (sign ? 1 : 0);
processStderr(&sink); /* sink receives the actual data */
readInt(from);
}
@@ -454,7 +427,7 @@ void RemoteStore::exportPath(const Path & path, bool sign,
Paths RemoteStore::importPaths(bool requireSignature, Source & source)
{
openConnection();
- writeInt(wopImportPaths, to);
+ to << wopImportPaths;
/* We ignore requireSignature, since the worker forces it to true
anyway. */
processStderr(0, &source);
@@ -466,27 +439,33 @@ void RemoteStore::buildPaths(const PathSet & drvPaths, BuildMode buildMode)
{
if (buildMode != bmNormal) throw Error("repairing or checking is not supported when building through the Nix daemon");
openConnection();
- writeInt(wopBuildPaths, to);
+ to << wopBuildPaths;
if (GET_PROTOCOL_MINOR(daemonVersion) >= 13)
- writeStrings(drvPaths, to);
+ to << drvPaths;
else {
/* For backwards compatibility with old daemons, strip output
identifiers. */
PathSet drvPaths2;
- foreach (PathSet::const_iterator, i, drvPaths)
- drvPaths2.insert(string(*i, 0, i->find('!')));
- writeStrings(drvPaths2, to);
+ for (auto & i : drvPaths)
+ drvPaths2.insert(string(i, 0, i.find('!')));
+ to << drvPaths2;
}
processStderr();
readInt(from);
}
+BuildResult RemoteStore::buildDerivation(const Path & drvPath, const BasicDerivation & drv,
+ BuildMode buildMode)
+{
+ throw Error("not implemented");
+}
+
+
void RemoteStore::ensurePath(const Path & path)
{
openConnection();
- writeInt(wopEnsurePath, to);
- writeString(path, to);
+ to << wopEnsurePath << path;
processStderr();
readInt(from);
}
@@ -495,8 +474,7 @@ void RemoteStore::ensurePath(const Path & path)
void RemoteStore::addTempRoot(const Path & path)
{
openConnection();
- writeInt(wopAddTempRoot, to);
- writeString(path, to);
+ to << wopAddTempRoot << path;
processStderr();
readInt(from);
}
@@ -505,8 +483,7 @@ void RemoteStore::addTempRoot(const Path & path)
void RemoteStore::addIndirectRoot(const Path & path)
{
openConnection();
- writeInt(wopAddIndirectRoot, to);
- writeString(path, to);
+ to << wopAddIndirectRoot << path;
processStderr();
readInt(from);
}
@@ -515,7 +492,7 @@ void RemoteStore::addIndirectRoot(const Path & path)
void RemoteStore::syncWithGC()
{
openConnection();
- writeInt(wopSyncWithGC, to);
+ to << wopSyncWithGC;
processStderr();
readInt(from);
}
@@ -524,7 +501,7 @@ void RemoteStore::syncWithGC()
Roots RemoteStore::findRoots()
{
openConnection();
- writeInt(wopFindRoots, to);
+ to << wopFindRoots;
processStderr();
unsigned int count = readInt(from);
Roots result;
@@ -541,17 +518,11 @@ void RemoteStore::collectGarbage(const GCOptions & options, GCResults & results)
{
openConnection(false);
- writeInt(wopCollectGarbage, to);
- writeInt(options.action, to);
- writeStrings(options.pathsToDelete, to);
- writeInt(options.ignoreLiveness, to);
- writeLongLong(options.maxFreed, to);
- writeInt(0, to);
- if (GET_PROTOCOL_MINOR(daemonVersion) >= 5) {
+ to << wopCollectGarbage << options.action << options.pathsToDelete << options.ignoreLiveness
+ << options.maxFreed << 0;
+ if (GET_PROTOCOL_MINOR(daemonVersion) >= 5)
/* removed options */
- writeInt(0, to);
- writeInt(0, to);
- }
+ to << 0 << 0;
processStderr();
@@ -564,7 +535,7 @@ void RemoteStore::collectGarbage(const GCOptions & options, GCResults & results)
PathSet RemoteStore::queryFailedPaths()
{
openConnection();
- writeInt(wopQueryFailedPaths, to);
+ to << wopQueryFailedPaths;
processStderr();
return readStorePaths<PathSet>(from);
}
@@ -573,8 +544,7 @@ PathSet RemoteStore::queryFailedPaths()
void RemoteStore::clearFailedPaths(const PathSet & paths)
{
openConnection();
- writeInt(wopClearFailedPaths, to);
- writeStrings(paths, to);
+ to << wopClearFailedPaths << paths;
processStderr();
readInt(from);
}
@@ -582,7 +552,7 @@ void RemoteStore::clearFailedPaths(const PathSet & paths)
void RemoteStore::optimiseStore()
{
openConnection();
- writeInt(wopOptimiseStore, to);
+ to << wopOptimiseStore;
processStderr();
readInt(from);
}
@@ -590,9 +560,7 @@ void RemoteStore::optimiseStore()
bool RemoteStore::verifyStore(bool checkContents, bool repair)
{
openConnection();
- writeInt(wopVerifyStore, to);
- writeInt(checkContents, to);
- writeInt(repair, to);
+ to << wopVerifyStore << checkContents << repair;
processStderr();
return readInt(from) != 0;
}
diff --git a/src/libstore/remote-store.hh b/src/libstore/remote-store.hh
index 030120db4..09e250386 100644
--- a/src/libstore/remote-store.hh
+++ b/src/libstore/remote-store.hh
@@ -67,6 +67,9 @@ public:
void buildPaths(const PathSet & paths, BuildMode buildMode);
+ BuildResult buildDerivation(const Path & drvPath, const BasicDerivation & drv,
+ BuildMode buildMode) override;
+
void ensurePath(const Path & path);
void addTempRoot(const Path & path);
diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc
index d3cbd1e7d..bb0bc0933 100644
--- a/src/libstore/store-api.cc
+++ b/src/libstore/store-api.cc
@@ -82,14 +82,14 @@ void checkStoreName(const string & name)
reasons (e.g., "." and ".."). */
if (string(name, 0, 1) == ".")
throw Error(format("illegal name: ‘%1%’") % name);
- foreach (string::const_iterator, i, name)
- if (!((*i >= 'A' && *i <= 'Z') ||
- (*i >= 'a' && *i <= 'z') ||
- (*i >= '0' && *i <= '9') ||
- validChars.find(*i) != string::npos))
+ for (auto & i : name)
+ if (!((i >= 'A' && i <= 'Z') ||
+ (i >= 'a' && i <= 'z') ||
+ (i >= '0' && i <= '9') ||
+ validChars.find(i) != string::npos))
{
throw Error(format("invalid character ‘%1%’ in name ‘%2%’")
- % *i % name);
+ % i % name);
}
}
@@ -101,22 +101,22 @@ void checkStoreName(const string & name)
where
<store> = the location of the Nix store, usually /nix/store
-
+
<name> = a human readable name for the path, typically obtained
from the name attribute of the derivation, or the name of the
source file from which the store path is created. For derivation
outputs other than the default "out" output, the string "-<id>"
is suffixed to <name>.
-
+
<h> = base-32 representation of the first 160 bits of a SHA-256
hash of <s>; the hash part of the store name
-
+
<s> = the string "<type>:sha256:<h2>:<store>:<name>";
note that it includes the location of the store as well as the
name to make sure that changes to either of those are reflected
in the hash (e.g. you won't get /nix/store/<h>-name1 and
/nix/store/<h>-name2 with equal hash parts).
-
+
<type> = one of:
"text:<r1>:<r2>:...<rN>"
for plain text files written to the store using
@@ -219,9 +219,9 @@ Path computeStorePathForText(const string & name, const string & s,
hacky, but we can't put them in `s' since that would be
ambiguous. */
string type = "text";
- foreach (PathSet::const_iterator, i, references) {
+ for (auto & i : references) {
type += ":";
- type += *i;
+ type += i;
}
return makeStorePath(type, hash, name);
}
@@ -234,11 +234,11 @@ string StoreAPI::makeValidityRegistration(const PathSet & paths,
bool showDerivers, bool showHash)
{
string s = "";
-
- foreach (PathSet::iterator, i, paths) {
- s += *i + "\n";
- ValidPathInfo info = queryPathInfo(*i);
+ for (auto & i : paths) {
+ s += i + "\n";
+
+ ValidPathInfo info = queryPathInfo(i);
if (showHash) {
s += printHash(info.hash) + "\n";
@@ -250,8 +250,8 @@ string StoreAPI::makeValidityRegistration(const PathSet & paths,
s += (format("%1%\n") % info.references.size()).str();
- foreach (PathSet::iterator, j, info.references)
- s += *j + "\n";
+ for (auto & j : info.references)
+ s += j + "\n";
}
return s;
@@ -286,9 +286,9 @@ ValidPathInfo decodeValidPathInfo(std::istream & str, bool hashGiven)
string showPaths(const PathSet & paths)
{
string s;
- foreach (PathSet::const_iterator, i, paths) {
+ for (auto & i : paths) {
if (s.size() != 0) s += ", ";
- s += "‘" + *i + "’";
+ s += "‘" + i + "’";
}
return s;
}
@@ -297,11 +297,11 @@ string showPaths(const PathSet & paths)
void exportPaths(StoreAPI & store, const Paths & paths,
bool sign, Sink & sink)
{
- foreach (Paths::const_iterator, i, paths) {
- writeInt(1, sink);
- store.exportPath(*i, sign, sink);
+ for (auto & i : paths) {
+ sink << 1;
+ store.exportPath(i, sign, sink);
}
- writeInt(0, sink);
+ sink << 0;
}
diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh
index 3764f3e54..d04a040bb 100644
--- a/src/libstore/store-api.hh
+++ b/src/libstore/store-api.hh
@@ -100,6 +100,32 @@ typedef list<ValidPathInfo> ValidPathInfos;
enum BuildMode { bmNormal, bmRepair, bmCheck };
+struct BuildResult
+{
+ enum Status {
+ Built = 0,
+ Substituted,
+ AlreadyValid,
+ PermanentFailure,
+ InputRejected,
+ OutputRejected,
+ TransientFailure, // possibly transient
+ CachedFailure,
+ TimedOut,
+ MiscFailure,
+ DependencyFailed
+ } status = MiscFailure;
+ std::string errorMsg;
+ //time_t startTime = 0, stopTime = 0;
+ bool success() {
+ return status == Built || status == Substituted || status == AlreadyValid;
+ }
+};
+
+
+struct BasicDerivation;
+
+
class StoreAPI
{
public:
@@ -194,6 +220,12 @@ public:
not derivations, substitute them. */
virtual void buildPaths(const PathSet & paths, BuildMode buildMode = bmNormal) = 0;
+ /* Build a single non-materialized derivation (i.e. not from an
+ on-disk .drv file). Note that ‘drvPath’ is only used for
+ informational purposes. */
+ virtual BuildResult buildDerivation(const Path & drvPath, const BasicDerivation & drv,
+ BuildMode buildMode = bmNormal) = 0;
+
/* Ensure that a path is valid. If it is not currently valid, it
may be made valid by running a substitute (if defined for the
path). */
diff --git a/src/libutil/archive.cc b/src/libutil/archive.cc
index 9e16e04ae..0187f062b 100644
--- a/src/libutil/archive.cc
+++ b/src/libutil/archive.cc
@@ -39,8 +39,7 @@ PathFilter defaultPathFilter;
static void dumpContents(const Path & path, size_t size,
Sink & sink)
{
- writeString("contents", sink);
- writeLongLong(size, sink);
+ sink << "contents" << size;
AutoCloseFD fd = open(path.c_str(), O_RDONLY);
if (fd == -1) throw SysError(format("opening file ‘%1%’") % path);
@@ -65,21 +64,17 @@ static void dump(const Path & path, Sink & sink, PathFilter & filter)
if (lstat(path.c_str(), &st))
throw SysError(format("getting attributes of path ‘%1%’") % path);
- writeString("(", sink);
+ sink << "(";
if (S_ISREG(st.st_mode)) {
- writeString("type", sink);
- writeString("regular", sink);
- if (st.st_mode & S_IXUSR) {
- writeString("executable", sink);
- writeString("", sink);
- }
+ sink << "type" << "regular";
+ if (st.st_mode & S_IXUSR)
+ sink << "executable" << "";
dumpContents(path, (size_t) st.st_size, sink);
}
else if (S_ISDIR(st.st_mode)) {
- writeString("type", sink);
- writeString("directory", sink);
+ sink << "type" << "directory";
/* If we're on a case-insensitive system like Mac OS X, undo
the case hack applied by restorePath(). */
@@ -101,32 +96,24 @@ static void dump(const Path & path, Sink & sink, PathFilter & filter)
for (auto & i : unhacked)
if (filter(path + "/" + i.first)) {
- writeString("entry", sink);
- writeString("(", sink);
- writeString("name", sink);
- writeString(i.first, sink);
- writeString("node", sink);
+ sink << "entry" << "(" << "name" << i.first << "node";
dump(path + "/" + i.second, sink, filter);
- writeString(")", sink);
+ sink << ")";
}
}
- else if (S_ISLNK(st.st_mode)) {
- writeString("type", sink);
- writeString("symlink", sink);
- writeString("target", sink);
- writeString(readLink(path), sink);
- }
+ else if (S_ISLNK(st.st_mode))
+ sink << "type" << "symlink" << "target" << readLink(path);
else throw Error(format("file ‘%1%’ has an unsupported type") % path);
- writeString(")", sink);
+ sink << ")";
}
void dumpPath(const Path & path, Sink & sink, PathFilter & filter)
{
- writeString(archiveVersion1, sink);
+ sink << archiveVersion1;
dump(path, sink, filter);
}
diff --git a/src/libutil/serialise.cc b/src/libutil/serialise.cc
index 924175075..f8e9d00c1 100644
--- a/src/libutil/serialise.cc
+++ b/src/libutil/serialise.cc
@@ -16,11 +16,11 @@ BufferedSink::~BufferedSink()
delete[] buffer;
}
-
+
void BufferedSink::operator () (const unsigned char * data, size_t len)
{
if (!buffer) buffer = new unsigned char[bufSize];
-
+
while (len) {
/* Optimisation: bypass the buffer if the data exceeds the
buffer size. */
@@ -96,7 +96,7 @@ size_t BufferedSource::read(unsigned char * data, size_t len)
if (!buffer) buffer = new unsigned char[bufSize];
if (!bufPosIn) bufPosIn = readUnbuffered(buffer, bufSize);
-
+
/* Copy out the data in the buffer. */
size_t n = len > bufPosIn - bufPosOut ? bufPosIn - bufPosOut : len;
memcpy(data, buffer + bufPosOut, n);
@@ -144,56 +144,39 @@ void writePadding(size_t len, Sink & sink)
}
-void writeInt(unsigned int n, Sink & sink)
-{
- unsigned char buf[8];
- memset(buf, 0, sizeof(buf));
- buf[0] = n & 0xff;
- buf[1] = (n >> 8) & 0xff;
- buf[2] = (n >> 16) & 0xff;
- buf[3] = (n >> 24) & 0xff;
- sink(buf, sizeof(buf));
-}
-
-
-void writeLongLong(unsigned long long n, Sink & sink)
-{
- unsigned char buf[8];
- buf[0] = n & 0xff;
- buf[1] = (n >> 8) & 0xff;
- buf[2] = (n >> 16) & 0xff;
- buf[3] = (n >> 24) & 0xff;
- buf[4] = (n >> 32) & 0xff;
- buf[5] = (n >> 40) & 0xff;
- buf[6] = (n >> 48) & 0xff;
- buf[7] = (n >> 56) & 0xff;
- sink(buf, sizeof(buf));
-}
-
-
void writeString(const unsigned char * buf, size_t len, Sink & sink)
{
- writeInt(len, sink);
+ sink << len;
sink(buf, len);
writePadding(len, sink);
}
-void writeString(const string & s, Sink & sink)
+Sink & operator << (Sink & sink, const string & s)
{
writeString((const unsigned char *) s.data(), s.size(), sink);
+ return sink;
}
template<class T> void writeStrings(const T & ss, Sink & sink)
{
- writeInt(ss.size(), sink);
- foreach (typename T::const_iterator, i, ss)
- writeString(*i, sink);
+ sink << ss.size();
+ for (auto & i : ss)
+ sink << i;
+}
+
+Sink & operator << (Sink & sink, const Strings & s)
+{
+ writeStrings(s, sink);
+ return sink;
}
-template void writeStrings(const Paths & ss, Sink & sink);
-template void writeStrings(const PathSet & ss, Sink & sink);
+Sink & operator << (Sink & sink, const StringSet & s)
+{
+ writeStrings(s, sink);
+ return sink;
+}
void readPadding(size_t len, Source & source)
@@ -247,7 +230,7 @@ size_t readString(unsigned char * buf, size_t max, Source & source)
return len;
}
-
+
string readString(Source & source)
{
size_t len = readInt(source);
@@ -258,7 +241,13 @@ string readString(Source & source)
return string((char *) buf, len);
}
-
+Source & operator >> (Source & in, string & s)
+{
+ s = readString(in);
+ return in;
+}
+
+
template<class T> T readStrings(Source & source)
{
unsigned int count = readInt(source);
diff --git a/src/libutil/serialise.hh b/src/libutil/serialise.hh
index 6a6f028aa..97ac3e912 100644
--- a/src/libutil/serialise.hh
+++ b/src/libutil/serialise.hh
@@ -1,13 +1,14 @@
#pragma once
#include "types.hh"
+#include "util.hh"
namespace nix {
/* Abstract destination of binary data. */
-struct Sink
+struct Sink
{
virtual ~Sink() { }
virtual void operator () (const unsigned char * data, size_t len) = 0;
@@ -25,9 +26,9 @@ struct BufferedSink : Sink
~BufferedSink();
void operator () (const unsigned char * data, size_t len);
-
+
void flush();
-
+
virtual void write(const unsigned char * data, size_t len) = 0;
};
@@ -36,7 +37,7 @@ struct BufferedSink : Sink
struct Source
{
virtual ~Source() { }
-
+
/* Store exactly ‘len’ bytes in the buffer pointed to by ‘data’.
It blocks until all the requested data is available, or throws
an error if it is not going to be available. */
@@ -58,9 +59,9 @@ struct BufferedSource : Source
BufferedSource(size_t bufSize = 32 * 1024)
: bufSize(bufSize), bufPosIn(0), bufPosOut(0), buffer(0) { }
~BufferedSource();
-
+
size_t read(unsigned char * data, size_t len);
-
+
/* Underlying read call, to be overridden. */
virtual size_t readUnbuffered(unsigned char * data, size_t len) = 0;
@@ -78,7 +79,7 @@ struct FdSink : BufferedSink
FdSink() : fd(-1), warn(false), written(0) { }
FdSink(int fd) : fd(fd), warn(false), written(0) { }
~FdSink();
-
+
void write(const unsigned char * data, size_t len);
};
@@ -107,16 +108,32 @@ struct StringSource : Source
const string & s;
size_t pos;
StringSource(const string & _s) : s(_s), pos(0) { }
- size_t read(unsigned char * data, size_t len);
+ size_t read(unsigned char * data, size_t len);
};
void writePadding(size_t len, Sink & sink);
-void writeInt(unsigned int n, Sink & sink);
-void writeLongLong(unsigned long long n, Sink & sink);
void writeString(const unsigned char * buf, size_t len, Sink & sink);
-void writeString(const string & s, Sink & sink);
-template<class T> void writeStrings(const T & ss, Sink & sink);
+
+inline Sink & operator << (Sink & sink, uint64_t n)
+{
+ unsigned char buf[8];
+ buf[0] = n & 0xff;
+ buf[1] = (n >> 8) & 0xff;
+ buf[2] = (n >> 16) & 0xff;
+ buf[3] = (n >> 24) & 0xff;
+ buf[4] = (n >> 32) & 0xff;
+ buf[5] = (n >> 40) & 0xff;
+ buf[6] = (n >> 48) & 0xff;
+ buf[7] = (n >> 56) & 0xff;
+ sink(buf, sizeof(buf));
+ return sink;
+}
+
+Sink & operator << (Sink & sink, const string & s);
+Sink & operator << (Sink & sink, const Strings & s);
+Sink & operator << (Sink & sink, const StringSet & s);
+
void readPadding(size_t len, Source & source);
unsigned int readInt(Source & source);
@@ -125,6 +142,8 @@ size_t readString(unsigned char * buf, size_t max, Source & source);
string readString(Source & source);
template<class T> T readStrings(Source & source);
+Source & operator >> (Source & in, string & s);
+
MakeError(SerialisationError, Error)
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index 596b79e10..7959b76f8 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -477,12 +477,24 @@ void printMsg_(Verbosity level, const FormatOrString & fs)
{
checkInterrupt();
if (level > verbosity) return;
+
string prefix;
if (logType == ltPretty)
for (int i = 0; i < nestingLevel; i++)
prefix += "| ";
else if (logType == ltEscapes && level != lvlInfo)
prefix = "\033[" + escVerbosity(level) + "s";
+ else if (logType == ltSystemd) {
+ char c;
+ switch (level) {
+ case lvlError: c = '3'; break;
+ case lvlInfo: c = '5'; break;
+ case lvlTalkative: case lvlChatty: c = '6'; break;
+ default: c = '7';
+ }
+ prefix = string("<") + c + ">";
+ }
+
string s = (format("%1%%2%\n") % prefix % fs.s).str();
if (!isatty(STDERR_FILENO)) s = filterANSIEscapes(s);
writeToStderr(s);
@@ -1060,9 +1072,9 @@ template vector<string> tokenizeString(const string & s, const string & separato
string concatStringsSep(const string & sep, const Strings & ss)
{
string s;
- foreach (Strings::const_iterator, i, ss) {
+ for (auto & i : ss) {
if (s.size() != 0) s += sep;
- s += *i;
+ s += i;
}
return s;
}
@@ -1071,9 +1083,9 @@ string concatStringsSep(const string & sep, const Strings & ss)
string concatStringsSep(const string & sep, const StringSet & ss)
{
string s;
- foreach (StringSet::const_iterator, i, ss) {
+ for (auto & i : ss) {
if (s.size() != 0) s += sep;
- s += *i;
+ s += i;
}
return s;
}
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index 187e05ece..b2fb59d6f 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -15,13 +15,6 @@
namespace nix {
-#define foreach(it_type, it, collection) \
- for (it_type it = (collection).begin(); it != (collection).end(); ++it)
-
-#define foreach_reverse(it_type, it, collection) \
- for (it_type it = (collection).rbegin(); it != (collection).rend(); ++it)
-
-
/* Return an environment variable. */
string getEnv(const string & key, const string & def = "");
@@ -129,7 +122,8 @@ T singleton(const A & a)
typedef enum {
ltPretty, /* nice, nested output */
ltEscapes, /* nesting indicated using escape codes (for log2xml) */
- ltFlat /* no nesting */
+ ltFlat, /* no nesting */
+ ltSystemd, /* use systemd severity prefixes */
} LogType;
extern LogType logType;
diff --git a/src/libutil/xml-writer.cc b/src/libutil/xml-writer.cc
index 01794001b..98bd058d1 100644
--- a/src/libutil/xml-writer.cc
+++ b/src/libutil/xml-writer.cc
@@ -73,10 +73,10 @@ void XMLWriter::writeEmptyElement(const string & name,
void XMLWriter::writeAttrs(const XMLAttrs & attrs)
{
- for (XMLAttrs::const_iterator i = attrs.begin(); i != attrs.end(); ++i) {
- output << " " << i->first << "=\"";
- for (unsigned int j = 0; j < i->second.size(); ++j) {
- char c = i->second[j];
+ for (auto & i : attrs) {
+ output << " " << i.first << "=\"";
+ for (unsigned int j = 0; j < i.second.size(); ++j) {
+ char c = i.second[j];
if (c == '"') output << "&quot;";
else if (c == '<') output << "&lt;";
else if (c == '>') output << "&gt;";
diff --git a/src/nix-collect-garbage/nix-collect-garbage.cc b/src/nix-collect-garbage/nix-collect-garbage.cc
index c8dc9099c..253c0b537 100644
--- a/src/nix-collect-garbage/nix-collect-garbage.cc
+++ b/src/nix-collect-garbage/nix-collect-garbage.cc
@@ -28,7 +28,12 @@ void removeOldGenerations(std::string dir)
auto type = i.type == DT_UNKNOWN ? getFileType(path) : i.type;
if (type == DT_LNK && canWrite) {
- auto link = readLink(path);
+ std::string link;
+ try {
+ link = readLink(path);
+ } catch (SysError & e) {
+ if (e.errNo == ENOENT) continue;
+ }
if (link.find("link") != string::npos) {
printMsg(lvlInfo, format("removing old generations of profile %1%") % path);
if (deleteOlderThan != "")
diff --git a/src/nix-daemon/nix-daemon.cc b/src/nix-daemon/nix-daemon.cc
index ad8b0d133..199d3288f 100644
--- a/src/nix-daemon/nix-daemon.cc
+++ b/src/nix-daemon/nix-daemon.cc
@@ -43,7 +43,7 @@ static void tunnelStderr(const unsigned char * buf, size_t count)
{
if (canSendStderr) {
try {
- writeInt(STDERR_NEXT, to);
+ to << STDERR_NEXT;
writeString(buf, count, to);
to.flush();
} catch (...) {
@@ -72,11 +72,10 @@ static void stopWork(bool success = true, const string & msg = "", unsigned int
canSendStderr = false;
if (success)
- writeInt(STDERR_LAST, to);
+ to << STDERR_LAST;
else {
- writeInt(STDERR_ERROR, to);
- writeString(msg, to);
- if (status != 0) writeInt(status, to);
+ to << STDERR_ERROR << msg;
+ if (status != 0) to << status;
}
}
@@ -87,7 +86,7 @@ struct TunnelSink : Sink
TunnelSink(Sink & to) : to(to) { }
virtual void operator () (const unsigned char * data, size_t len)
{
- writeInt(STDERR_WRITE, to);
+ to << STDERR_WRITE;
writeString(data, len, to);
}
};
@@ -99,8 +98,7 @@ struct TunnelSource : BufferedSource
TunnelSource(Source & from) : from(from) { }
size_t readUnbuffered(unsigned char * data, size_t len)
{
- writeInt(STDERR_READ, to);
- writeInt(len, to);
+ to << STDERR_READ << len;
to.flush();
size_t n = readString(data, len, from);
if (n == 0) throw EndOfFile("unexpected end-of-file");
@@ -166,7 +164,7 @@ static void performOp(bool trusted, unsigned int clientVersion,
assertStorePath(path);
bool result = store->isValidPath(path);
stopWork();
- writeInt(result, to);
+ to << result;
break;
}
@@ -175,7 +173,7 @@ static void performOp(bool trusted, unsigned int clientVersion,
startWork();
PathSet res = store->queryValidPaths(paths);
stopWork();
- writeStrings(res, to);
+ to << res;
break;
}
@@ -184,7 +182,7 @@ static void performOp(bool trusted, unsigned int clientVersion,
startWork();
PathSet res = store->querySubstitutablePaths(singleton<PathSet>(path));
stopWork();
- writeInt(res.find(path) != res.end(), to);
+ to << (res.find(path) != res.end());
break;
}
@@ -193,7 +191,7 @@ static void performOp(bool trusted, unsigned int clientVersion,
startWork();
PathSet res = store->querySubstitutablePaths(paths);
stopWork();
- writeStrings(res, to);
+ to << res;
break;
}
@@ -202,7 +200,7 @@ static void performOp(bool trusted, unsigned int clientVersion,
startWork();
Hash hash = store->queryPathHash(path);
stopWork();
- writeString(printHash(hash), to);
+ to << printHash(hash);
break;
}
@@ -221,7 +219,7 @@ static void performOp(bool trusted, unsigned int clientVersion,
paths = store->queryValidDerivers(path);
else paths = store->queryDerivationOutputs(path);
stopWork();
- writeStrings(paths, to);
+ to << paths;
break;
}
@@ -231,7 +229,7 @@ static void performOp(bool trusted, unsigned int clientVersion,
StringSet names;
names = store->queryDerivationOutputNames(path);
stopWork();
- writeStrings(names, to);
+ to << names;
break;
}
@@ -240,7 +238,7 @@ static void performOp(bool trusted, unsigned int clientVersion,
startWork();
Path deriver = store->queryDeriver(path);
stopWork();
- writeString(deriver, to);
+ to << deriver;
break;
}
@@ -249,7 +247,7 @@ static void performOp(bool trusted, unsigned int clientVersion,
startWork();
Path path = store->queryPathFromHashPart(hashPart);
stopWork();
- writeString(path, to);
+ to << path;
break;
}
@@ -283,7 +281,7 @@ static void performOp(bool trusted, unsigned int clientVersion,
->addToStoreFromDump(recursive ? savedNAR.s : savedRegular.s, baseName, recursive, hashAlgo);
stopWork();
- writeString(path, to);
+ to << path;
break;
}
@@ -294,7 +292,7 @@ static void performOp(bool trusted, unsigned int clientVersion,
startWork();
Path path = store->addTextToStore(suffix, s, refs);
stopWork();
- writeString(path, to);
+ to << path;
break;
}
@@ -305,7 +303,7 @@ static void performOp(bool trusted, unsigned int clientVersion,
TunnelSink sink(to);
store->exportPath(path, sign, sink);
stopWork();
- writeInt(1, to);
+ to << 1;
break;
}
@@ -314,7 +312,7 @@ static void performOp(bool trusted, unsigned int clientVersion,
TunnelSource source(from);
Paths paths = store->importPaths(!trusted, source);
stopWork();
- writeStrings(paths, to);
+ to << paths;
break;
}
@@ -323,7 +321,7 @@ static void performOp(bool trusted, unsigned int clientVersion,
startWork();
store->buildPaths(drvs);
stopWork();
- writeInt(1, to);
+ to << 1;
break;
}
@@ -332,7 +330,7 @@ static void performOp(bool trusted, unsigned int clientVersion,
startWork();
store->ensurePath(path);
stopWork();
- writeInt(1, to);
+ to << 1;
break;
}
@@ -341,7 +339,7 @@ static void performOp(bool trusted, unsigned int clientVersion,
startWork();
store->addTempRoot(path);
stopWork();
- writeInt(1, to);
+ to << 1;
break;
}
@@ -350,7 +348,7 @@ static void performOp(bool trusted, unsigned int clientVersion,
startWork();
store->addIndirectRoot(path);
stopWork();
- writeInt(1, to);
+ to << 1;
break;
}
@@ -358,7 +356,7 @@ static void performOp(bool trusted, unsigned int clientVersion,
startWork();
store->syncWithGC();
stopWork();
- writeInt(1, to);
+ to << 1;
break;
}
@@ -366,11 +364,9 @@ static void performOp(bool trusted, unsigned int clientVersion,
startWork();
Roots roots = store->findRoots();
stopWork();
- writeInt(roots.size(), to);
- for (Roots::iterator i = roots.begin(); i != roots.end(); ++i) {
- writeString(i->first, to);
- writeString(i->second, to);
- }
+ to << roots.size();
+ for (auto & i : roots)
+ to << i.first << i.second;
break;
}
@@ -395,9 +391,7 @@ static void performOp(bool trusted, unsigned int clientVersion,
store->collectGarbage(options, results);
stopWork();
- writeStrings(results.paths, to);
- writeLongLong(results.bytesFreed, to);
- writeLongLong(0, to); // obsolete
+ to << results.paths << results.bytesFreed << 0 /* obsolete */;
break;
}
@@ -445,14 +439,11 @@ static void performOp(bool trusted, unsigned int clientVersion,
stopWork();
SubstitutablePathInfos::iterator i = infos.find(path);
if (i == infos.end())
- writeInt(0, to);
+ to << 0;
else {
- writeInt(1, to);
- writeString(i->second.deriver, to);
- writeStrings(i->second.references, to);
- writeLongLong(i->second.downloadSize, to);
+ to << 1 << i->second.deriver << i->second.references << i->second.downloadSize;
if (GET_PROTOCOL_MINOR(clientVersion) >= 7)
- writeLongLong(i->second.narSize, to);
+ to << i->second.narSize;
}
break;
}
@@ -463,13 +454,10 @@ static void performOp(bool trusted, unsigned int clientVersion,
SubstitutablePathInfos infos;
store->querySubstitutablePathInfos(paths, infos);
stopWork();
- writeInt(infos.size(), to);
- foreach (SubstitutablePathInfos::iterator, i, infos) {
- writeString(i->first, to);
- writeString(i->second.deriver, to);
- writeStrings(i->second.references, to);
- writeLongLong(i->second.downloadSize, to);
- writeLongLong(i->second.narSize, to);
+ to << infos.size();
+ for (auto & i : infos) {
+ to << i.first << i.second.deriver << i.second.references
+ << i.second.downloadSize << i.second.narSize;
}
break;
}
@@ -478,7 +466,7 @@ static void performOp(bool trusted, unsigned int clientVersion,
startWork();
PathSet paths = store->queryAllValidPaths();
stopWork();
- writeStrings(paths, to);
+ to << paths;
break;
}
@@ -486,7 +474,7 @@ static void performOp(bool trusted, unsigned int clientVersion,
startWork();
PathSet paths = store->queryFailedPaths();
stopWork();
- writeStrings(paths, to);
+ to << paths;
break;
}
@@ -495,7 +483,7 @@ static void performOp(bool trusted, unsigned int clientVersion,
startWork();
store->clearFailedPaths(paths);
stopWork();
- writeInt(1, to);
+ to << 1;
break;
}
@@ -504,11 +492,8 @@ static void performOp(bool trusted, unsigned int clientVersion,
startWork();
ValidPathInfo info = store->queryPathInfo(path);
stopWork();
- writeString(info.deriver, to);
- writeString(printHash(info.hash), to);
- writeStrings(info.references, to);
- writeInt(info.registrationTime, to);
- writeLongLong(info.narSize, to);
+ to << info.deriver << printHash(info.hash) << info.references
+ << info.registrationTime << info.narSize;
break;
}
@@ -516,7 +501,7 @@ static void performOp(bool trusted, unsigned int clientVersion,
startWork();
store->optimiseStore();
stopWork();
- writeInt(1, to);
+ to << 1;
break;
case wopVerifyStore: {
@@ -527,7 +512,7 @@ static void performOp(bool trusted, unsigned int clientVersion,
throw Error("you are not privileged to repair paths");
bool errors = store->verifyStore(checkContents, repair);
stopWork();
- writeInt(errors, to);
+ to << errors;
break;
}
@@ -547,8 +532,7 @@ static void processConnection(bool trusted)
/* Exchange the greeting. */
unsigned int magic = readInt(from);
if (magic != WORKER_MAGIC_1) throw Error("protocol mismatch");
- writeInt(WORKER_MAGIC_2, to);
- writeInt(PROTOCOL_VERSION, to);
+ to << WORKER_MAGIC_2 << PROTOCOL_VERSION;
to.flush();
unsigned int clientVersion = readInt(from);
diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc
index 3f82345ce..97a2bbdb7 100644
--- a/src/nix-env/nix-env.cc
+++ b/src/nix-env/nix-env.cc
@@ -232,9 +232,9 @@ static bool isPrebuilt(EvalState & state, DrvInfo & elem)
static void checkSelectorUse(DrvNames & selectors)
{
/* Check that all selectors have been used. */
- foreach (DrvNames::iterator, i, selectors)
- if (i->hits == 0 && i->fullName != "*")
- throw Error(format("selector ‘%1%’ matches no derivations") % i->fullName);
+ for (auto & i : selectors)
+ if (i.hits == 0 && i.fullName != "*")
+ throw Error(format("selector ‘%1%’ matches no derivations") % i.fullName);
}
@@ -248,7 +248,7 @@ static DrvInfos filterBySelector(EvalState & state, const DrvInfos & allElems,
DrvInfos elems;
set<unsigned int> done;
- foreach (DrvNames::iterator, i, selectors) {
+ for (auto & i : selectors) {
typedef list<std::pair<DrvInfo, unsigned int> > Matches;
Matches matches;
unsigned int n = 0;
@@ -256,8 +256,8 @@ static DrvInfos filterBySelector(EvalState & state, const DrvInfos & allElems,
j != allElems.end(); ++j, ++n)
{
DrvName drvName(j->name);
- if (i->matches(drvName)) {
- i->hits++;
+ if (i.matches(drvName)) {
+ i.hits++;
matches.push_back(std::pair<DrvInfo, unsigned int>(*j, n));
}
}
@@ -276,47 +276,47 @@ static DrvInfos filterBySelector(EvalState & state, const DrvInfos & allElems,
Newest newest;
StringSet multiple;
- for (Matches::iterator j = matches.begin(); j != matches.end(); ++j) {
- DrvName drvName(j->first.name);
+ for (auto & j : matches) {
+ DrvName drvName(j.first.name);
int d = 1;
Newest::iterator k = newest.find(drvName.name);
if (k != newest.end()) {
- d = j->first.system == k->second.first.system ? 0 :
- j->first.system == settings.thisSystem ? 1 :
+ d = j.first.system == k->second.first.system ? 0 :
+ j.first.system == settings.thisSystem ? 1 :
k->second.first.system == settings.thisSystem ? -1 : 0;
if (d == 0)
- d = comparePriorities(state, j->first, k->second.first);
+ d = comparePriorities(state, j.first, k->second.first);
if (d == 0)
d = compareVersions(drvName.version, DrvName(k->second.first.name).version);
}
if (d > 0) {
newest.erase(drvName.name);
- newest.insert(Newest::value_type(drvName.name, *j));
- multiple.erase(j->first.name);
+ newest.insert(Newest::value_type(drvName.name, j));
+ multiple.erase(j.first.name);
} else if (d == 0) {
- multiple.insert(j->first.name);
+ multiple.insert(j.first.name);
}
}
matches.clear();
- for (Newest::iterator j = newest.begin(); j != newest.end(); ++j) {
- if (multiple.find(j->second.first.name) != multiple.end())
+ for (auto & j : newest) {
+ if (multiple.find(j.second.first.name) != multiple.end())
printMsg(lvlInfo,
format("warning: there are multiple derivations named ‘%1%’; using the first one")
- % j->second.first.name);
- matches.push_back(j->second);
+ % j.second.first.name);
+ matches.push_back(j.second);
}
}
/* Insert only those elements in the final list that we
haven't inserted before. */
- for (Matches::iterator j = matches.begin(); j != matches.end(); ++j)
- if (done.find(j->second) == done.end()) {
- done.insert(j->second);
- elems.push_back(j->first);
+ for (auto & j : matches)
+ if (done.find(j.second) == done.end()) {
+ done.insert(j.second);
+ elems.push_back(j.first);
}
}
@@ -370,8 +370,8 @@ static void queryInstSources(EvalState & state,
Value vArg;
loadSourceExpr(state, instSource.nixExprPath, vArg);
- foreach (Strings::const_iterator, i, args) {
- Expr * eFun = state.parseExprFromString(*i, absPath("."));
+ for (auto & i : args) {
+ Expr * eFun = state.parseExprFromString(i, absPath("."));
Value vFun, vTmp;
state.eval(eFun, vFun);
mkApp(vTmp, vFun, vArg);
@@ -386,8 +386,8 @@ static void queryInstSources(EvalState & state,
derivations). */
case srcStorePaths: {
- foreach (Strings::const_iterator, i, args) {
- Path path = followLinksToStorePath(*i);
+ for (auto & i : args) {
+ Path path = followLinksToStorePath(i);
string name = baseNameOf(path);
string::size_type dash = name.find('-');
@@ -424,8 +424,8 @@ static void queryInstSources(EvalState & state,
case srcAttrPath: {
Value vRoot;
loadSourceExpr(state, instSource.nixExprPath, vRoot);
- foreach (Strings::const_iterator, i, args) {
- Value & v(*findAlongAttrPath(state, *i, *instSource.autoArgs, vRoot));
+ for (auto & i : args) {
+ Value & v(*findAlongAttrPath(state, i, *instSource.autoArgs, vRoot));
getDerivations(state, v, "", *instSource.autoArgs, elems, true);
}
break;
@@ -437,12 +437,12 @@ static void queryInstSources(EvalState & state,
static void printMissing(EvalState & state, DrvInfos & elems)
{
PathSet targets;
- foreach (DrvInfos::iterator, i, elems) {
- Path drvPath = i->queryDrvPath();
+ for (auto & i : elems) {
+ Path drvPath = i.queryDrvPath();
if (drvPath != "")
targets.insert(drvPath);
else
- targets.insert(i->queryOutPath());
+ targets.insert(i.queryOutPath());
}
printMissing(*store, targets);
@@ -465,19 +465,19 @@ static void installDerivations(Globals & globals,
queryInstSources(*globals.state, globals.instSource, args, newElemsTmp, true);
/* If --prebuilt-only is given, filter out source-only packages. */
- foreach (DrvInfos::iterator, i, newElemsTmp)
- if (!globals.prebuiltOnly || isPrebuilt(*globals.state, *i))
- newElems.push_back(*i);
+ for (auto & i : newElemsTmp)
+ if (!globals.prebuiltOnly || isPrebuilt(*globals.state, i))
+ newElems.push_back(i);
StringSet newNames;
- for (DrvInfos::iterator i = newElems.begin(); i != newElems.end(); ++i) {
+ for (auto & i : newElems) {
/* `forceName' is a hack to get package names right in some
one-click installs, namely those where the name used in the
path is not the one we want (e.g., `java-front' versus
`java-front-0.9pre15899'). */
if (globals.forceName != "")
- i->name = globals.forceName;
- newNames.insert(DrvName(i->name).name);
+ i.name = globals.forceName;
+ newNames.insert(DrvName(i.name).name);
}
@@ -491,18 +491,18 @@ static void installDerivations(Globals & globals,
if (!globals.removeAll) {
DrvInfos installedElems = queryInstalled(*globals.state, profile);
- foreach (DrvInfos::iterator, i, installedElems) {
- DrvName drvName(i->name);
+ for (auto & i : installedElems) {
+ DrvName drvName(i.name);
if (!globals.preserveInstalled &&
newNames.find(drvName.name) != newNames.end() &&
- !keep(*i))
- printMsg(lvlInfo, format("replacing old ‘%1%’") % i->name);
+ !keep(i))
+ printMsg(lvlInfo, format("replacing old ‘%1%’") % i.name);
else
- allElems.push_back(*i);
+ allElems.push_back(i);
}
- foreach (DrvInfos::iterator, i, newElems)
- printMsg(lvlInfo, format("installing ‘%1%’") % i->name);
+ for (auto & i : newElems)
+ printMsg(lvlInfo, format("installing ‘%1%’") % i.name);
}
printMissing(*globals.state, newElems);
@@ -555,13 +555,13 @@ static void upgradeDerivations(Globals & globals,
/* Go through all installed derivations. */
DrvInfos newElems;
- foreach (DrvInfos::iterator, i, installedElems) {
- DrvName drvName(i->name);
+ for (auto & i : installedElems) {
+ DrvName drvName(i.name);
try {
- if (keep(*i)) {
- newElems.push_back(*i);
+ if (keep(i)) {
+ newElems.push_back(i);
continue;
}
@@ -573,10 +573,10 @@ static void upgradeDerivations(Globals & globals,
take the one with the highest version. */
DrvInfos::iterator bestElem = availElems.end();
DrvName bestName;
- foreach (DrvInfos::iterator, j, availElems) {
+ for (auto j = availElems.begin(); j != availElems.end(); ++j) {
DrvName newName(j->name);
if (newName.name == drvName.name) {
- int d = comparePriorities(*globals.state, *i, *j);
+ int d = comparePriorities(*globals.state, i, *j);
if (d == 0) d = compareVersions(drvName.version, newName.version);
if ((upgradeType == utLt && d < 0) ||
(upgradeType == utLeq && d <= 0) ||
@@ -597,17 +597,17 @@ static void upgradeDerivations(Globals & globals,
}
if (bestElem != availElems.end() &&
- i->queryOutPath() !=
+ i.queryOutPath() !=
bestElem->queryOutPath())
{
printMsg(lvlInfo,
format("upgrading ‘%1%’ to ‘%2%’")
- % i->name % bestElem->name);
+ % i.name % bestElem->name);
newElems.push_back(*bestElem);
- } else newElems.push_back(*i);
+ } else newElems.push_back(i);
} catch (Error & e) {
- e.addPrefix(format("while trying to find an upgrade for ‘%1%’:\n") % i->name);
+ e.addPrefix(format("while trying to find an upgrade for ‘%1%’:\n") % i.name);
throw;
}
}
@@ -666,13 +666,13 @@ static void opSetFlag(Globals & globals, Strings opFlags, Strings opArgs)
DrvInfos installedElems = queryInstalled(*globals.state, globals.profile);
/* Update all matching derivations. */
- foreach (DrvInfos::iterator, i, installedElems) {
- DrvName drvName(i->name);
- foreach (DrvNames::iterator, j, selectors)
- if (j->matches(drvName)) {
- printMsg(lvlInfo, format("setting flag on ‘%1%’") % i->name);
- j->hits++;
- setMetaFlag(*globals.state, *i, flagName, flagValue);
+ for (auto & i : installedElems) {
+ DrvName drvName(i.name);
+ for (auto & j : selectors)
+ if (j.matches(drvName)) {
+ printMsg(lvlInfo, format("setting flag on ‘%1%’") % i.name);
+ j.hits++;
+ setMetaFlag(*globals.state, i, flagName, flagValue);
break;
}
}
@@ -732,20 +732,20 @@ static void uninstallDerivations(Globals & globals, Strings & selectors,
DrvInfos installedElems = queryInstalled(*globals.state, profile);
DrvInfos newElems;
- foreach (DrvInfos::iterator, i, installedElems) {
- DrvName drvName(i->name);
+ for (auto & i : installedElems) {
+ DrvName drvName(i.name);
bool found = false;
- foreach (Strings::iterator, j, selectors)
+ for (auto & j : selectors)
/* !!! the repeated calls to followLinksToStorePath()
are expensive, should pre-compute them. */
- if ((isPath(*j) && i->queryOutPath() == followLinksToStorePath(*j))
- || DrvName(*j).matches(drvName))
+ if ((isPath(j) && i.queryOutPath() == followLinksToStorePath(j))
+ || DrvName(j).matches(drvName))
{
- printMsg(lvlInfo, format("uninstalling ‘%1%’") % i->name);
+ printMsg(lvlInfo, format("uninstalling ‘%1%’") % i.name);
found = true;
break;
}
- if (!found) newElems.push_back(*i);
+ if (!found) newElems.push_back(i);
}
if (globals.dryRun) return;
@@ -788,18 +788,18 @@ void printTable(Table & table)
vector<unsigned int> widths;
widths.resize(nrColumns);
- foreach (Table::iterator, i, table) {
- assert(i->size() == nrColumns);
+ for (auto & i : table) {
+ assert(i.size() == nrColumns);
Strings::iterator j;
unsigned int 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();
}
- foreach (Table::iterator, i, table) {
+ for (auto & i : table) {
Strings::iterator j;
unsigned int column;
- for (j = i->begin(), column = 0; j != i->end(); ++j, ++column) {
+ for (j = i.begin(), column = 0; j != i.end(); ++j, ++column) {
string s = *j;
replace(s.begin(), s.end(), '\n', ' ');
cout << s;
@@ -828,8 +828,8 @@ static VersionDiff compareVersionAgainstSet(
VersionDiff diff = cvUnavail;
version = "?";
- for (DrvInfos::const_iterator i = elems.begin(); i != elems.end(); ++i) {
- DrvName name2(i->name);
+ for (auto & i : elems) {
+ DrvName name2(i.name);
if (name.name == name2.name) {
int d = compareVersions(name.version, name2.version);
if (d < 0) {
@@ -855,21 +855,21 @@ static VersionDiff compareVersionAgainstSet(
static void queryJSON(Globals & globals, vector<DrvInfo> & elems)
{
JSONObject topObj(cout);
- foreach (vector<DrvInfo>::iterator, i, elems) {
- topObj.attr(i->attrPath);
+ for (auto & i : elems) {
+ topObj.attr(i.attrPath);
JSONObject pkgObj(cout);
- pkgObj.attr("name", i->name);
- pkgObj.attr("system", i->system);
+ pkgObj.attr("name", i.name);
+ pkgObj.attr("system", i.system);
pkgObj.attr("meta");
JSONObject metaObj(cout);
- StringSet metaNames = i->queryMetaNames();
- foreach (StringSet::iterator, j, metaNames) {
- metaObj.attr(*j);
- Value * v = i->queryMeta(*j);
+ StringSet metaNames = i.queryMetaNames();
+ for (auto & j : metaNames) {
+ metaObj.attr(j);
+ Value * v = i.queryMeta(j);
if (!v) {
- printMsg(lvlError, format("derivation ‘%1%’ has invalid meta attribute ‘%2%’") % i->name % *j);
+ printMsg(lvlError, format("derivation ‘%1%’ has invalid meta attribute ‘%2%’") % i.name % j);
cout << "null";
} else {
PathSet context;
@@ -944,8 +944,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
/* Sort them by name. */
/* !!! */
vector<DrvInfo> elems;
- for (DrvInfos::iterator i = elems_.begin(); i != elems_.end(); ++i)
- elems.push_back(*i);
+ for (auto & i : elems_) elems.push_back(i);
sort(elems.begin(), elems.end(), cmpElemByName);
@@ -954,9 +953,8 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
PathSet installed; /* installed paths */
if (printStatus) {
- for (DrvInfos::iterator i = installedElems.begin();
- i != installedElems.end(); ++i)
- installed.insert(i->queryOutPath());
+ for (auto & i : installedElems)
+ installed.insert(i.queryOutPath());
}
@@ -964,12 +962,12 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
PathSet validPaths, substitutablePaths;
if (printStatus || globals.prebuiltOnly) {
PathSet paths;
- foreach (vector<DrvInfo>::iterator, i, elems)
+ for (auto & i : elems)
try {
- paths.insert(i->queryOutPath());
+ paths.insert(i.queryOutPath());
} catch (AssertionError & e) {
- printMsg(lvlTalkative, format("skipping derivation named ‘%1%’ which gives an assertion failure") % i->name);
- i->setFailed();
+ printMsg(lvlTalkative, format("skipping derivation named ‘%1%’ which gives an assertion failure") % i.name);
+ i.setFailed();
}
validPaths = store->queryValidPaths(paths);
substitutablePaths = store->querySubstitutablePaths(paths);
@@ -990,15 +988,15 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
XMLWriter xml(true, *(xmlOutput ? &cout : &dummy));
XMLOpenElement xmlRoot(xml, "items");
- foreach (vector<DrvInfo>::iterator, i, elems) {
+ for (auto & i : elems) {
try {
- if (i->hasFailed()) continue;
+ if (i.hasFailed()) continue;
- startNest(nest, lvlDebug, format("outputting query result ‘%1%’") % i->attrPath);
+ startNest(nest, lvlDebug, format("outputting query result ‘%1%’") % i.attrPath);
if (globals.prebuiltOnly &&
- validPaths.find(i->queryOutPath()) == validPaths.end() &&
- substitutablePaths.find(i->queryOutPath()) == substitutablePaths.end())
+ validPaths.find(i.queryOutPath()) == validPaths.end() &&
+ substitutablePaths.find(i.queryOutPath()) == substitutablePaths.end())
continue;
/* For table output. */
@@ -1008,7 +1006,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
XMLAttrs attrs;
if (printStatus) {
- Path outPath = i->queryOutPath();
+ Path outPath = i.queryOutPath();
bool hasSubs = substitutablePaths.find(outPath) != substitutablePaths.end();
bool isInstalled = installed.find(outPath) != installed.end();
bool isValid = validPaths.find(outPath) != validPaths.end();
@@ -1024,14 +1022,14 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
}
if (xmlOutput)
- attrs["attrPath"] = i->attrPath;
+ attrs["attrPath"] = i.attrPath;
else if (printAttrPath)
- columns.push_back(i->attrPath);
+ columns.push_back(i.attrPath);
if (xmlOutput)
- attrs["name"] = i->name;
+ attrs["name"] = i.name;
else if (printName)
- columns.push_back(i->name);
+ columns.push_back(i.name);
if (compareVersions) {
/* Compare this element against the versions of the
@@ -1039,7 +1037,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
elements, or the set of installed elements. !!!
This is O(N * M), should be O(N * lg M). */
string version;
- VersionDiff diff = compareVersionAgainstSet(*i, otherElems, version);
+ VersionDiff diff = compareVersionAgainstSet(i, otherElems, version);
char ch;
switch (diff) {
@@ -1064,13 +1062,13 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
}
if (xmlOutput) {
- if (i->system != "") attrs["system"] = i->system;
+ if (i.system != "") attrs["system"] = i.system;
}
else if (printSystem)
- columns.push_back(i->system);
+ columns.push_back(i.system);
if (printDrvPath) {
- string drvPath = i->queryDrvPath();
+ string drvPath = i.queryDrvPath();
if (xmlOutput) {
if (drvPath != "") attrs["drvPath"] = drvPath;
} else
@@ -1078,18 +1076,18 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
}
if (printOutPath && !xmlOutput) {
- DrvInfo::Outputs outputs = i->queryOutputs();
+ DrvInfo::Outputs outputs = i.queryOutputs();
string s;
- foreach (DrvInfo::Outputs::iterator, j, outputs) {
+ for (auto & j : outputs) {
if (!s.empty()) s += ';';
- if (j->first != "out") { s += j->first; s += "="; }
- s += j->second;
+ if (j.first != "out") { s += j.first; s += "="; }
+ s += j.second;
}
columns.push_back(s);
}
if (printDescription) {
- string descr = i->queryMetaString("description");
+ string descr = i.queryMetaString("description");
if (xmlOutput) {
if (descr != "") attrs["description"] = descr;
} else
@@ -1100,22 +1098,22 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
if (printOutPath || printMeta) {
XMLOpenElement item(xml, "item", attrs);
if (printOutPath) {
- DrvInfo::Outputs outputs = i->queryOutputs();
- foreach (DrvInfo::Outputs::iterator, j, outputs) {
+ DrvInfo::Outputs outputs = i.queryOutputs();
+ for (auto & j : outputs) {
XMLAttrs attrs2;
- attrs2["name"] = j->first;
- attrs2["path"] = j->second;
+ attrs2["name"] = j.first;
+ attrs2["path"] = j.second;
xml.writeEmptyElement("output", attrs2);
}
}
if (printMeta) {
- StringSet metaNames = i->queryMetaNames();
- foreach (StringSet::iterator, j, metaNames) {
+ StringSet metaNames = i.queryMetaNames();
+ for (auto & j : metaNames) {
XMLAttrs attrs2;
- attrs2["name"] = *j;
- Value * v = i->queryMeta(*j);
+ attrs2["name"] = j;
+ Value * v = i.queryMeta(j);
if (!v)
- printMsg(lvlError, format("derivation ‘%1%’ has invalid meta attribute ‘%2%’") % i->name % *j);
+ printMsg(lvlError, format("derivation ‘%1%’ has invalid meta attribute ‘%2%’") % i.name % j);
else {
if (v->type == tString) {
attrs2["type"] = "string";
@@ -1129,13 +1127,13 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
attrs2["type"] = "bool";
attrs2["value"] = v->boolean ? "true" : "false";
xml.writeEmptyElement("meta", attrs2);
- } else if (v->type == tList) {
+ } else if (v->isList()) {
attrs2["type"] = "strings";
XMLOpenElement m(xml, "meta", attrs2);
- for (unsigned int j = 0; j < v->list.length; ++j) {
- if (v->list.elems[j]->type != tString) continue;
+ for (unsigned int j = 0; j < v->listSize(); ++j) {
+ if (v->listElems()[j]->type != tString) continue;
XMLAttrs attrs3;
- attrs3["value"] = v->list.elems[j]->string.s;
+ attrs3["value"] = v->listElems()[j]->string.s;
xml.writeEmptyElement("string", attrs3);
}
}
@@ -1150,9 +1148,9 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
cout.flush();
} catch (AssertionError & e) {
- printMsg(lvlTalkative, format("skipping derivation named ‘%1%’ which gives an assertion failure") % i->name);
+ printMsg(lvlTalkative, format("skipping derivation named ‘%1%’ which gives an assertion failure") % i.name);
} catch (Error & e) {
- e.addPrefix(format("while querying the derivation named ‘%1%’:\n") % i->name);
+ e.addPrefix(format("while querying the derivation named ‘%1%’:\n") % i.name);
throw;
}
}
@@ -1187,10 +1185,10 @@ static void switchGeneration(Globals & globals, int dstGen)
Generations gens = findGenerations(globals.profile, curGen);
Generation dst;
- for (Generations::iterator i = gens.begin(); i != gens.end(); ++i)
- if ((dstGen == prevGen && i->number < curGen) ||
- (dstGen >= 0 && i->number == dstGen))
- dst = *i;
+ for (auto & i : gens)
+ if ((dstGen == prevGen && i.number < curGen) ||
+ (dstGen >= 0 && i.number == dstGen))
+ dst = i;
if (!dst) {
if (dstGen == prevGen)
@@ -1250,14 +1248,14 @@ static void opListGenerations(Globals & globals, Strings opFlags, Strings opArgs
RunPager pager;
- for (Generations::iterator i = gens.begin(); i != gens.end(); ++i) {
+ for (auto & i : gens) {
tm t;
- if (!localtime_r(&i->creationTime, &t)) throw Error("cannot convert time");
+ if (!localtime_r(&i.creationTime, &t)) throw Error("cannot convert time");
cout << format("%|4| %|4|-%|02|-%|02| %|02|:%|02|:%|02| %||\n")
- % i->number
+ % i.number
% (t.tm_year + 1900) % (t.tm_mon + 1) % t.tm_mday
% t.tm_hour % t.tm_min % t.tm_sec
- % (i->number == curGen ? "(current)" : "");
+ % (i.number == curGen ? "(current)" : "");
}
}
@@ -1284,6 +1282,12 @@ static void opDeleteGenerations(Globals & globals, Strings opFlags, Strings opAr
}
+static void opVersion(Globals & globals, Strings opFlags, Strings opArgs)
+{
+ printVersion("nix-env");
+}
+
+
int main(int argc, char * * argv)
{
return handleExceptions(argv[0], [&]() {
@@ -1313,7 +1317,7 @@ int main(int argc, char * * argv)
if (*arg == "--help")
showManPage("nix-env");
else if (*arg == "--version")
- printVersion("nix-env");
+ op = opVersion;
else if (*arg == "--install" || *arg == "-i")
op = opInstall;
else if (parseAutoArgs(arg, end, autoArgs_))
diff --git a/src/nix-env/user-env.cc b/src/nix-env/user-env.cc
index 3bc31b9ea..9a20b9433 100644
--- a/src/nix-env/user-env.cc
+++ b/src/nix-env/user-env.cc
@@ -33,9 +33,9 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
/* Build the components in the user environment, if they don't
exist already. */
PathSet drvsToBuild;
- foreach (DrvInfos::iterator, i, elems)
- if (i->queryDrvPath() != "")
- drvsToBuild.insert(i->queryDrvPath());
+ for (auto & i : elems)
+ if (i.queryDrvPath() != "")
+ drvsToBuild.insert(i.queryDrvPath());
debug(format("building user environment dependencies"));
store->buildPaths(drvsToBuild, state.repair ? bmRepair : bmNormal);
@@ -45,51 +45,51 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
Value manifest;
state.mkList(manifest, elems.size());
unsigned int n = 0;
- foreach (DrvInfos::iterator, i, elems) {
+ for (auto & i : elems) {
/* Create a pseudo-derivation containing the name, system,
output paths, and optionally the derivation path, as well
as the meta attributes. */
- Path drvPath = keepDerivations ? i->queryDrvPath() : "";
+ Path drvPath = keepDerivations ? i.queryDrvPath() : "";
Value & v(*state.allocValue());
- manifest.list.elems[n++] = &v;
+ manifest.listElems()[n++] = &v;
state.mkAttrs(v, 16);
mkString(*state.allocAttr(v, state.sType), "derivation");
- mkString(*state.allocAttr(v, state.sName), i->name);
- if (!i->system.empty())
- mkString(*state.allocAttr(v, state.sSystem), i->system);
- mkString(*state.allocAttr(v, state.sOutPath), i->queryOutPath());
+ mkString(*state.allocAttr(v, state.sName), i.name);
+ if (!i.system.empty())
+ mkString(*state.allocAttr(v, state.sSystem), i.system);
+ mkString(*state.allocAttr(v, state.sOutPath), i.queryOutPath());
if (drvPath != "")
- mkString(*state.allocAttr(v, state.sDrvPath), i->queryDrvPath());
+ mkString(*state.allocAttr(v, state.sDrvPath), i.queryDrvPath());
// Copy each output.
- DrvInfo::Outputs outputs = i->queryOutputs();
+ DrvInfo::Outputs outputs = i.queryOutputs();
Value & vOutputs = *state.allocAttr(v, state.sOutputs);
state.mkList(vOutputs, outputs.size());
unsigned int m = 0;
- foreach (DrvInfo::Outputs::iterator, j, outputs) {
- mkString(*(vOutputs.list.elems[m++] = state.allocValue()), j->first);
- Value & vOutputs = *state.allocAttr(v, state.symbols.create(j->first));
+ for (auto & j : outputs) {
+ mkString(*(vOutputs.listElems()[m++] = state.allocValue()), j.first);
+ Value & vOutputs = *state.allocAttr(v, state.symbols.create(j.first));
state.mkAttrs(vOutputs, 2);
- mkString(*state.allocAttr(vOutputs, state.sOutPath), j->second);
+ mkString(*state.allocAttr(vOutputs, state.sOutPath), j.second);
/* This is only necessary when installing store paths, e.g.,
`nix-env -i /nix/store/abcd...-foo'. */
- store->addTempRoot(j->second);
- store->ensurePath(j->second);
+ store->addTempRoot(j.second);
+ store->ensurePath(j.second);
- references.insert(j->second);
+ references.insert(j.second);
}
// Copy the meta attributes.
Value & vMeta = *state.allocAttr(v, state.sMeta);
state.mkAttrs(vMeta, 16);
- StringSet metaNames = i->queryMetaNames();
- foreach (StringSet::iterator, j, metaNames) {
- Value * v = i->queryMeta(*j);
+ StringSet metaNames = i.queryMetaNames();
+ for (auto & j : metaNames) {
+ Value * v = i.queryMeta(j);
if (!v) continue;
- vMeta.attrs->push_back(Attr(state.symbols.create(*j), v));
+ vMeta.attrs->push_back(Attr(state.symbols.create(j), v));
}
vMeta.attrs->sort();
v.attrs->sort();
diff --git a/src/nix-instantiate/nix-instantiate.cc b/src/nix-instantiate/nix-instantiate.cc
index bea04180e..b6845197e 100644
--- a/src/nix-instantiate/nix-instantiate.cc
+++ b/src/nix-instantiate/nix-instantiate.cc
@@ -45,8 +45,8 @@ void processExpr(EvalState & state, const Strings & attrPaths,
Value vRoot;
state.eval(e, vRoot);
- foreach (Strings::const_iterator, i, attrPaths) {
- Value & v(*findAlongAttrPath(state, *i, autoArgs, vRoot));
+ for (auto & i : attrPaths) {
+ Value & v(*findAlongAttrPath(state, i, autoArgs, vRoot));
state.forceValue(v);
PathSet context;
@@ -67,11 +67,11 @@ void processExpr(EvalState & state, const Strings & attrPaths,
} else {
DrvInfos drvs;
getDerivations(state, v, "", autoArgs, drvs, false);
- foreach (DrvInfos::iterator, i, drvs) {
- Path drvPath = i->queryDrvPath();
+ for (auto & i : drvs) {
+ Path drvPath = i.queryDrvPath();
/* What output do we want? */
- string outputName = i->queryOutputName();
+ string outputName = i.queryOutputName();
if (outputName == "")
throw Error(format("derivation ‘%1%’ lacks an ‘outputName’ attribute ") % drvPath);
@@ -168,9 +168,9 @@ int main(int argc, char * * argv)
if (attrPaths.empty()) attrPaths.push_back("");
if (findFile) {
- foreach (Strings::iterator, i, files) {
- Path p = state.findFile(*i);
- if (p == "") throw Error(format("unable to find ‘%1%’") % *i);
+ for (auto & i : files) {
+ Path p = state.findFile(i);
+ if (p == "") throw Error(format("unable to find ‘%1%’") % i);
std::cout << p << std::endl;
}
return;
diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc
index 23b97ca9e..d541b7b7d 100644
--- a/src/nix-store/nix-store.cc
+++ b/src/nix-store/nix-store.cc
@@ -69,13 +69,13 @@ static PathSet realisePath(Path path, bool build = true)
rootNr++;
if (p.second.empty())
- foreach (DerivationOutputs::iterator, i, drv.outputs) p.second.insert(i->first);
+ for (auto & i : drv.outputs) p.second.insert(i.first);
PathSet outputs;
- foreach (StringSet::iterator, j, p.second) {
- DerivationOutputs::iterator i = drv.outputs.find(*j);
+ for (auto & j : p.second) {
+ DerivationOutputs::iterator i = drv.outputs.find(j);
if (i == drv.outputs.end())
- throw Error(format("derivation ‘%1%’ does not have an output named ‘%2%’") % p.first % *j);
+ throw Error(format("derivation ‘%1%’ does not have an output named ‘%2%’") % p.first % j);
Path outPath = i->second.path;
if (gcRoot == "")
printGCWarning();
@@ -113,16 +113,16 @@ static void opRealise(Strings opFlags, Strings opArgs)
BuildMode buildMode = bmNormal;
bool ignoreUnknown = false;
- foreach (Strings::iterator, i, opFlags)
- if (*i == "--dry-run") dryRun = true;
- else if (*i == "--repair") buildMode = bmRepair;
- else if (*i == "--check") buildMode = bmCheck;
- else if (*i == "--ignore-unknown") ignoreUnknown = true;
- else throw UsageError(format("unknown flag ‘%1%’") % *i);
+ for (auto & i : opFlags)
+ if (i == "--dry-run") dryRun = true;
+ else if (i == "--repair") buildMode = bmRepair;
+ else if (i == "--check") buildMode = bmCheck;
+ else if (i == "--ignore-unknown") ignoreUnknown = true;
+ else throw UsageError(format("unknown flag ‘%1%’") % i);
Paths paths;
- foreach (Strings::iterator, i, opArgs) {
- DrvPathWithOutputs p = parseDrvPathWithOutputs(*i);
+ for (auto & i : opArgs) {
+ DrvPathWithOutputs p = parseDrvPathWithOutputs(i);
paths.push_back(makeDrvPathWithOutputs(followLinksToStorePath(p.first), p.second));
}
@@ -133,8 +133,8 @@ static void opRealise(Strings opFlags, Strings opArgs)
if (ignoreUnknown) {
Paths paths2;
- foreach (Paths::iterator, i, paths)
- if (unknown.find(*i) == unknown.end()) paths2.push_back(*i);
+ for (auto & i : paths)
+ if (unknown.find(i) == unknown.end()) paths2.push_back(i);
paths = paths2;
unknown = PathSet();
}
@@ -148,11 +148,11 @@ static void opRealise(Strings opFlags, Strings opArgs)
store->buildPaths(PathSet(paths.begin(), paths.end()), buildMode);
if (!ignoreUnknown)
- foreach (Paths::iterator, i, paths) {
- PathSet paths = realisePath(*i, false);
+ for (auto & i : paths) {
+ PathSet paths = realisePath(i, false);
if (!noOutput)
- foreach (PathSet::iterator, j, paths)
- cout << format("%1%\n") % *j;
+ for (auto & j : paths)
+ cout << format("%1%\n") % j;
}
}
@@ -173,10 +173,9 @@ static void opAddFixed(Strings opFlags, Strings opArgs)
{
bool recursive = false;
- for (Strings::iterator i = opFlags.begin();
- i != opFlags.end(); ++i)
- if (*i == "--recursive") recursive = true;
- else throw UsageError(format("unknown flag ‘%1%’") % *i);
+ for (auto & i : opFlags)
+ if (i == "--recursive") recursive = true;
+ else throw UsageError(format("unknown flag ‘%1%’") % i);
if (opArgs.empty())
throw UsageError("first argument must be hash algorithm");
@@ -194,10 +193,9 @@ static void opPrintFixedPath(Strings opFlags, Strings opArgs)
{
bool recursive = false;
- for (Strings::iterator i = opFlags.begin();
- i != opFlags.end(); ++i)
- if (*i == "--recursive") recursive = true;
- else throw UsageError(format("unknown flag ‘%1%’") % *i);
+ for (auto i : opFlags)
+ if (i == "--recursive") recursive = true;
+ else throw UsageError(format("unknown flag ‘%1%’") % i);
if (opArgs.size() != 3)
throw UsageError(format("‘--print-fixed-path’ requires three arguments"));
@@ -219,8 +217,8 @@ static PathSet maybeUseOutputs(const Path & storePath, bool useOutput, bool forc
if (useOutput && isDerivation(storePath)) {
Derivation drv = derivationFromPath(*store, storePath);
PathSet outputs;
- foreach (DerivationOutputs::iterator, i, drv.outputs)
- outputs.insert(i->second.path);
+ for (auto & i : drv.outputs)
+ outputs.insert(i.second.path);
return outputs;
}
else return singleton<PathSet>(storePath);
@@ -257,8 +255,8 @@ static void printTree(const Path & path,
Paths sorted = topoSortPaths(*store, references);
reverse(sorted.begin(), sorted.end());
- foreach (Paths::iterator, i, sorted) {
- Paths::iterator j = i; ++j;
+ for (auto i = sorted.begin(); i != sorted.end(); ++i) {
+ auto j = i; ++j;
printTree(*i, tailPad + treeConn,
j == sorted.end() ? tailPad + treeNull : tailPad + treeLine,
done);
@@ -279,34 +277,34 @@ static void opQuery(Strings opFlags, Strings opArgs)
bool forceRealise = false;
string bindingName;
- foreach (Strings::iterator, i, opFlags) {
+ for (auto & i : opFlags) {
QueryType prev = query;
- if (*i == "--outputs") query = qOutputs;
- else if (*i == "--requisites" || *i == "-R") query = qRequisites;
- else if (*i == "--references") query = qReferences;
- else if (*i == "--referrers" || *i == "--referers") query = qReferrers;
- else if (*i == "--referrers-closure" || *i == "--referers-closure") query = qReferrersClosure;
- else if (*i == "--deriver" || *i == "-d") query = qDeriver;
- else if (*i == "--binding" || *i == "-b") {
+ if (i == "--outputs") query = qOutputs;
+ else if (i == "--requisites" || i == "-R") query = qRequisites;
+ else if (i == "--references") query = qReferences;
+ else if (i == "--referrers" || i == "--referers") query = qReferrers;
+ else if (i == "--referrers-closure" || i == "--referers-closure") query = qReferrersClosure;
+ else if (i == "--deriver" || i == "-d") query = qDeriver;
+ 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") query = qHash;
- else if (*i == "--size") query = qSize;
- else if (*i == "--tree") query = qTree;
- else if (*i == "--graph") query = qGraph;
- else if (*i == "--xml") query = qXml;
- else if (*i == "--resolve") query = qResolve;
- else if (*i == "--roots") query = qRoots;
- else if (*i == "--use-output" || *i == "-u") useOutput = true;
- else if (*i == "--force-realise" || *i == "--force-realize" || *i == "-f") forceRealise = true;
- else if (*i == "--include-outputs") includeOutputs = true;
- else throw UsageError(format("unknown flag ‘%1%’") % *i);
+ else if (i == "--hash") query = qHash;
+ else if (i == "--size") query = qSize;
+ else if (i == "--tree") query = qTree;
+ else if (i == "--graph") query = qGraph;
+ else if (i == "--xml") query = qXml;
+ else if (i == "--resolve") query = qResolve;
+ else if (i == "--roots") query = qRoots;
+ else if (i == "--use-output" || i == "-u") useOutput = true;
+ else if (i == "--force-realise" || i == "--force-realize" || i == "-f") forceRealise = true;
+ else if (i == "--include-outputs") includeOutputs = true;
+ else throw UsageError(format("unknown flag ‘%1%’") % i);
if (prev != qDefault && prev != query)
- throw UsageError(format("query type ‘%1%’ conflicts with earlier flag") % *i);
+ throw UsageError(format("query type ‘%1%’ conflicts with earlier flag") % i);
}
if (query == qDefault) query = qOutputs;
@@ -316,12 +314,12 @@ static void opQuery(Strings opFlags, Strings opArgs)
switch (query) {
case qOutputs: {
- foreach (Strings::iterator, i, opArgs) {
- *i = followLinksToStorePath(*i);
- if (forceRealise) realisePath(*i);
- Derivation drv = derivationFromPath(*store, *i);
- foreach (DerivationOutputs::iterator, j, drv.outputs)
- cout << format("%1%\n") % j->second.path;
+ for (auto & i : opArgs) {
+ i = followLinksToStorePath(i);
+ if (forceRealise) realisePath(i);
+ Derivation drv = derivationFromPath(*store, i);
+ for (auto & j : drv.outputs)
+ cout << format("%1%\n") % j.second.path;
}
break;
}
@@ -331,13 +329,13 @@ static void opQuery(Strings opFlags, Strings opArgs)
case qReferrers:
case qReferrersClosure: {
PathSet paths;
- foreach (Strings::iterator, i, opArgs) {
- PathSet ps = maybeUseOutputs(followLinksToStorePath(*i), useOutput, forceRealise);
- foreach (PathSet::iterator, j, ps) {
- if (query == qRequisites) computeFSClosure(*store, *j, paths, false, includeOutputs);
- else if (query == qReferences) store->queryReferences(*j, paths);
- else if (query == qReferrers) store->queryReferrers(*j, paths);
- else if (query == qReferrersClosure) computeFSClosure(*store, *j, paths, true);
+ for (auto & i : opArgs) {
+ PathSet ps = maybeUseOutputs(followLinksToStorePath(i), useOutput, forceRealise);
+ for (auto & j : ps) {
+ if (query == qRequisites) computeFSClosure(*store, j, paths, false, includeOutputs);
+ else if (query == qReferences) store->queryReferences(j, paths);
+ else if (query == qReferrers) store->queryReferrers(j, paths);
+ else if (query == qReferrersClosure) computeFSClosure(*store, j, paths, true);
}
}
Paths sorted = topoSortPaths(*store, paths);
@@ -348,16 +346,16 @@ static void opQuery(Strings opFlags, Strings opArgs)
}
case qDeriver:
- foreach (Strings::iterator, i, opArgs) {
- Path deriver = store->queryDeriver(followLinksToStorePath(*i));
+ for (auto & i : opArgs) {
+ Path deriver = store->queryDeriver(followLinksToStorePath(i));
cout << format("%1%\n") %
(deriver == "" ? "unknown-deriver" : deriver);
}
break;
case qBinding:
- foreach (Strings::iterator, i, opArgs) {
- Path path = useDeriver(followLinksToStorePath(*i));
+ for (auto & i : opArgs) {
+ Path path = useDeriver(followLinksToStorePath(i));
Derivation drv = derivationFromPath(*store, path);
StringPairs::iterator j = drv.env.find(bindingName);
if (j == drv.env.end())
@@ -369,10 +367,10 @@ static void opQuery(Strings opFlags, Strings opArgs)
case qHash:
case qSize:
- foreach (Strings::iterator, i, opArgs) {
- PathSet paths = maybeUseOutputs(followLinksToStorePath(*i), useOutput, forceRealise);
- foreach (PathSet::iterator, j, paths) {
- ValidPathInfo info = store->queryPathInfo(*j);
+ for (auto & i : opArgs) {
+ PathSet paths = maybeUseOutputs(followLinksToStorePath(i), useOutput, forceRealise);
+ for (auto & j : paths) {
+ ValidPathInfo info = store->queryPathInfo(j);
if (query == qHash) {
assert(info.hash.type == htSHA256);
cout << format("sha256:%1%\n") % printHash32(info.hash);
@@ -384,15 +382,15 @@ static void opQuery(Strings opFlags, Strings opArgs)
case qTree: {
PathSet done;
- foreach (Strings::iterator, i, opArgs)
- printTree(followLinksToStorePath(*i), "", "", done);
+ for (auto & i : opArgs)
+ printTree(followLinksToStorePath(i), "", "", done);
break;
}
case qGraph: {
PathSet roots;
- foreach (Strings::iterator, i, opArgs) {
- PathSet paths = maybeUseOutputs(followLinksToStorePath(*i), useOutput, forceRealise);
+ for (auto & i : opArgs) {
+ PathSet paths = maybeUseOutputs(followLinksToStorePath(i), useOutput, forceRealise);
roots.insert(paths.begin(), paths.end());
}
printDotGraph(roots);
@@ -401,8 +399,8 @@ static void opQuery(Strings opFlags, Strings opArgs)
case qXml: {
PathSet roots;
- foreach (Strings::iterator, i, opArgs) {
- PathSet paths = maybeUseOutputs(followLinksToStorePath(*i), useOutput, forceRealise);
+ for (auto & i : opArgs) {
+ PathSet paths = maybeUseOutputs(followLinksToStorePath(i), useOutput, forceRealise);
roots.insert(paths.begin(), paths.end());
}
printXmlGraph(roots);
@@ -410,23 +408,23 @@ static void opQuery(Strings opFlags, Strings opArgs)
}
case qResolve: {
- foreach (Strings::iterator, i, opArgs)
- cout << format("%1%\n") % followLinksToStorePath(*i);
+ for (auto & i : opArgs)
+ cout << format("%1%\n") % followLinksToStorePath(i);
break;
}
case qRoots: {
PathSet referrers;
- foreach (Strings::iterator, i, opArgs) {
- PathSet paths = maybeUseOutputs(followLinksToStorePath(*i), useOutput, forceRealise);
- foreach (PathSet::iterator, j, paths)
- computeFSClosure(*store, *j, referrers, true,
+ for (auto & i : opArgs) {
+ PathSet paths = maybeUseOutputs(followLinksToStorePath(i), useOutput, forceRealise);
+ for (auto & j : paths)
+ computeFSClosure(*store, j, referrers, true,
settings.gcKeepOutputs, settings.gcKeepDerivations);
}
Roots roots = store->findRoots();
- foreach (Roots::iterator, i, roots)
- if (referrers.find(i->second) != referrers.end())
- cout << format("%1%\n") % i->first;
+ for (auto & i : roots)
+ if (referrers.find(i.second) != referrers.end())
+ cout << format("%1%\n") % i.first;
break;
}
@@ -439,8 +437,8 @@ static void opQuery(Strings opFlags, Strings opArgs)
static string shellEscape(const string & s)
{
string r;
- foreach (string::const_iterator, i, s)
- if (*i == '\'') r += "'\\''"; else r += *i;
+ for (auto & i : s)
+ if (i == '\'') r += "'\\''"; else r += i;
return r;
}
@@ -455,15 +453,17 @@ static void opPrintEnv(Strings opFlags, Strings opArgs)
/* Print each environment variable in the derivation in a format
that can be sourced by the shell. */
- foreach (StringPairs::iterator, i, drv.env)
- cout << format("export %1%; %1%='%2%'\n") % i->first % shellEscape(i->second);
+ 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. */
cout << "export _args; _args='";
- foreach (Strings::iterator, i, drv.args) {
- if (i != drv.args.begin()) cout << ' ';
- cout << shellEscape(*i);
+ bool first = true;
+ for (auto & i : drv.args) {
+ if (!first) cout << ' ';
+ first = false;
+ cout << shellEscape(i);
}
cout << "'\n";
}
@@ -475,8 +475,8 @@ static void opReadLog(Strings opFlags, Strings opArgs)
RunPager pager;
- foreach (Strings::iterator, i, opArgs) {
- Path path = useDeriver(followLinksToStorePath(*i));
+ for (auto & i : opArgs) {
+ Path path = useDeriver(followLinksToStorePath(i));
string baseName = baseNameOf(path);
bool found = false;
@@ -547,8 +547,8 @@ static void opDumpDB(Strings opFlags, Strings opArgs)
if (!opArgs.empty())
throw UsageError("no arguments expected");
PathSet validPaths = store->queryAllValidPaths();
- foreach (PathSet::iterator, i, validPaths)
- cout << store->makeValidityRegistration(singleton<PathSet>(*i), true, true);
+ for (auto & i : validPaths)
+ cout << store->makeValidityRegistration(singleton<PathSet>(i), true, true);
}
@@ -590,11 +590,10 @@ static void opRegisterValidity(Strings opFlags, Strings opArgs)
bool reregister = false; // !!! maybe this should be the default
bool hashGiven = false;
- for (Strings::iterator i = opFlags.begin();
- i != opFlags.end(); ++i)
- if (*i == "--reregister") reregister = true;
- else if (*i == "--hash-given") hashGiven = true;
- else throw UsageError(format("unknown flag ‘%1%’") % *i);
+ for (auto & i : opFlags)
+ if (i == "--reregister") reregister = true;
+ else if (i == "--hash-given") hashGiven = true;
+ else throw UsageError(format("unknown flag ‘%1%’") % i);
if (!opArgs.empty()) throw UsageError("no arguments expected");
@@ -606,15 +605,12 @@ static void opCheckValidity(Strings opFlags, Strings opArgs)
{
bool printInvalid = false;
- for (Strings::iterator i = opFlags.begin();
- i != opFlags.end(); ++i)
- if (*i == "--print-invalid") printInvalid = true;
- else throw UsageError(format("unknown flag ‘%1%’") % *i);
+ for (auto & i : opFlags)
+ if (i == "--print-invalid") printInvalid = true;
+ else throw UsageError(format("unknown flag ‘%1%’") % i);
- for (Strings::iterator i = opArgs.begin();
- i != opArgs.end(); ++i)
- {
- Path path = followLinksToStorePath(*i);
+ for (auto & i : opArgs) {
+ Path path = followLinksToStorePath(i);
if (!store->isValidPath(path)) {
if (printInvalid)
cout << format("%1%\n") % path;
@@ -634,7 +630,7 @@ static void opGC(Strings opFlags, Strings opArgs)
GCResults results;
/* Do what? */
- foreach (Strings::iterator, i, opFlags)
+ for (auto i = opFlags.begin(); i != opFlags.end(); ++i)
if (*i == "--print-roots") printRoots = true;
else if (*i == "--print-live") options.action = GCOptions::gcReturnLive;
else if (*i == "--print-dead") options.action = GCOptions::gcReturnDead;
@@ -649,8 +645,8 @@ static void opGC(Strings opFlags, Strings opArgs)
if (printRoots) {
Roots roots = store->findRoots();
- foreach (Roots::iterator, i, roots)
- cout << i->first << " -> " << i->second << std::endl;
+ for (auto & i : roots)
+ cout << i.first << " -> " << i.second << std::endl;
}
else {
@@ -658,8 +654,8 @@ static void opGC(Strings opFlags, Strings opArgs)
store->collectGarbage(options, results);
if (options.action != GCOptions::gcDeleteDead)
- foreach (PathSet::iterator, i, results.paths)
- cout << *i << std::endl;
+ for (auto & i : results.paths)
+ cout << i << std::endl;
}
}
@@ -672,12 +668,12 @@ static void opDelete(Strings opFlags, Strings opArgs)
GCOptions options;
options.action = GCOptions::gcDeleteSpecific;
- foreach (Strings::iterator, i, opFlags)
- if (*i == "--ignore-liveness") options.ignoreLiveness = true;
- else throw UsageError(format("unknown flag ‘%1%’") % *i);
+ for (auto & i : opFlags)
+ if (i == "--ignore-liveness") options.ignoreLiveness = true;
+ else throw UsageError(format("unknown flag ‘%1%’") % i);
- foreach (Strings::iterator, i, opArgs)
- options.pathsToDelete.insert(followLinksToStorePath(*i));
+ for (auto & i : opArgs)
+ options.pathsToDelete.insert(followLinksToStorePath(i));
GCResults results;
PrintFreed freed(true, results);
@@ -713,10 +709,9 @@ static void opRestore(Strings opFlags, Strings opArgs)
static void opExport(Strings opFlags, Strings opArgs)
{
bool sign = false;
- for (Strings::iterator i = opFlags.begin();
- i != opFlags.end(); ++i)
- if (*i == "--sign") sign = true;
- else throw UsageError(format("unknown flag ‘%1%’") % *i);
+ for (auto & i : opFlags)
+ if (i == "--sign") sign = true;
+ else throw UsageError(format("unknown flag ‘%1%’") % i);
FdSink sink(STDOUT_FILENO);
Paths sorted = topoSortPaths(*store, PathSet(opArgs.begin(), opArgs.end()));
@@ -728,17 +723,17 @@ static void opExport(Strings opFlags, Strings opArgs)
static void opImport(Strings opFlags, Strings opArgs)
{
bool requireSignature = false;
- foreach (Strings::iterator, i, opFlags)
- if (*i == "--require-signature") requireSignature = true;
- else throw UsageError(format("unknown flag ‘%1%’") % *i);
+ for (auto & i : opFlags)
+ if (i == "--require-signature") requireSignature = true;
+ else throw UsageError(format("unknown flag ‘%1%’") % i);
if (!opArgs.empty()) throw UsageError("no arguments expected");
FdSource source(STDIN_FILENO);
Paths paths = store->importPaths(requireSignature, source);
- foreach (Paths::iterator, i, paths)
- cout << format("%1%\n") % *i << std::flush;
+ for (auto & i : paths)
+ cout << format("%1%\n") % i << std::flush;
}
@@ -762,11 +757,10 @@ static void opVerify(Strings opFlags, Strings opArgs)
bool checkContents = false;
bool repair = false;
- for (Strings::iterator i = opFlags.begin();
- i != opFlags.end(); ++i)
- if (*i == "--check-contents") checkContents = true;
- else if (*i == "--repair") repair = true;
- else throw UsageError(format("unknown flag ‘%1%’") % *i);
+ for (auto & i : opFlags)
+ if (i == "--check-contents") checkContents = true;
+ else if (i == "--repair") repair = true;
+ else throw UsageError(format("unknown flag ‘%1%’") % i);
if (store->verifyStore(checkContents, repair)) {
printMsg(lvlError, "warning: not all errors were fixed");
@@ -783,8 +777,8 @@ static void opVerifyPath(Strings opFlags, Strings opArgs)
int status = 0;
- foreach (Strings::iterator, i, opArgs) {
- Path path = followLinksToStorePath(*i);
+ for (auto & i : opArgs) {
+ Path path = followLinksToStorePath(i);
printMsg(lvlTalkative, format("checking path ‘%1%’...") % path);
ValidPathInfo info = store->queryPathInfo(path);
HashResult current = hashPath(info.hash.type, path);
@@ -807,8 +801,8 @@ static void opRepairPath(Strings opFlags, Strings opArgs)
if (!opFlags.empty())
throw UsageError("no flags expected");
- foreach (Strings::iterator, i, opArgs) {
- Path path = followLinksToStorePath(*i);
+ for (auto & i : opArgs) {
+ Path path = followLinksToStorePath(i);
ensureLocalStore().repairPath(path);
}
}
@@ -828,8 +822,8 @@ static void opQueryFailedPaths(Strings opFlags, Strings opArgs)
if (!opArgs.empty() || !opFlags.empty())
throw UsageError("no arguments expected");
PathSet failed = store->queryFailedPaths();
- foreach (PathSet::iterator, i, failed)
- cout << format("%1%\n") % *i;
+ for (auto & i : failed)
+ cout << format("%1%\n") % i;
}
@@ -845,9 +839,9 @@ static void opClearFailedPaths(Strings opFlags, Strings opArgs)
static void opServe(Strings opFlags, Strings opArgs)
{
bool writeAllowed = false;
- foreach (Strings::iterator, i, opFlags)
- if (*i == "--write") writeAllowed = true;
- else throw UsageError(format("unknown flag ‘%1%’") % *i);
+ for (auto & i : opFlags)
+ if (i == "--write") writeAllowed = true;
+ else throw UsageError(format("unknown flag ‘%1%’") % i);
if (!opArgs.empty()) throw UsageError("no arguments expected");
@@ -857,11 +851,20 @@ static void opServe(Strings opFlags, Strings opArgs)
/* Exchange the greeting. */
unsigned int magic = readInt(in);
if (magic != SERVE_MAGIC_1) throw Error("protocol mismatch");
- writeInt(SERVE_MAGIC_2, out);
- writeInt(SERVE_PROTOCOL_VERSION, out);
+ out << SERVE_MAGIC_2 << SERVE_PROTOCOL_VERSION;
out.flush();
readInt(in); // Client version, unused for now
+ auto getBuildSettings = [&]() {
+ // FIXME: changing options here doesn't work if we're
+ // building through the daemon.
+ verbosity = lvlError;
+ settings.keepLog = false;
+ settings.useSubstitutes = false;
+ settings.maxSilentTime = readInt(in);
+ settings.buildTimeout = readInt(in);
+ };
+
while (true) {
ServeCommand cmd;
try {
@@ -902,25 +905,23 @@ static void opServe(Strings opFlags, Strings opArgs)
}
}
- writeStrings(store->queryValidPaths(paths), out);
+ out << store->queryValidPaths(paths);
break;
}
case cmdQueryPathInfos: {
PathSet paths = readStorePaths<PathSet>(in);
// !!! Maybe we want a queryPathInfos?
- foreach (PathSet::iterator, i, paths) {
- if (!store->isValidPath(*i))
+ for (auto & i : paths) {
+ if (!store->isValidPath(i))
continue;
- ValidPathInfo info = store->queryPathInfo(*i);
- writeString(info.path, out);
- writeString(info.deriver, out);
- writeStrings(info.references, out);
+ ValidPathInfo info = store->queryPathInfo(i);
+ out << info.path << info.deriver << info.references;
// !!! Maybe we want compression?
- writeLongLong(info.narSize, out); // downloadSize
- writeLongLong(info.narSize, out);
+ out << info.narSize // downloadSize
+ << info.narSize;
}
- writeString("", out);
+ out << "";
break;
}
@@ -931,7 +932,7 @@ static void opServe(Strings opFlags, Strings opArgs)
case cmdImportPaths: {
if (!writeAllowed) throw Error("importing paths is not allowed");
store->importPaths(false, in);
- writeInt(1, out); // indicate success
+ out << 1; // indicate success
break;
}
@@ -943,39 +944,49 @@ static void opServe(Strings opFlags, Strings opArgs)
break;
}
- case cmdBuildPaths: {
+ case cmdBuildPaths: { /* Used by build-remote.pl. */
- /* Used by build-remote.pl. */
if (!writeAllowed) throw Error("building paths is not allowed");
PathSet paths = readStorePaths<PathSet>(in);
- // FIXME: changing options here doesn't work if we're
- // building through the daemon.
- verbosity = lvlError;
- settings.keepLog = false;
- settings.useSubstitutes = false;
- settings.maxSilentTime = readInt(in);
- settings.buildTimeout = readInt(in);
+ getBuildSettings();
try {
MonitorFdHup monitor(in.fd);
store->buildPaths(paths);
- writeInt(0, out);
+ out << 0;
} catch (Error & e) {
assert(e.status);
- writeInt(e.status, out);
- writeString(e.msg(), out);
+ out << e.status << e.msg();
}
break;
}
+ case cmdBuildDerivation: { /* Used by hydra-queue-runner. */
+
+ if (!writeAllowed) throw Error("building paths is not allowed");
+
+ Path drvPath = readStorePath(in); // informational only
+ BasicDerivation drv;
+ in >> drv;
+
+ getBuildSettings();
+
+ MonitorFdHup monitor(in.fd);
+ auto status = store->buildDerivation(drvPath, drv);
+
+ out << status.status << status.errorMsg;
+
+ break;
+ }
+
case cmdQueryClosure: {
bool includeOutputs = readInt(in);
PathSet paths = readStorePaths<PathSet>(in);
PathSet closure;
for (auto & i : paths)
computeFSClosure(*store, i, closure, false, includeOutputs);
- writeStrings(closure, out);
+ out << closure;
break;
}
@@ -990,8 +1001,8 @@ static void opServe(Strings opFlags, Strings opArgs)
static void opGenerateBinaryCacheKey(Strings opFlags, Strings opArgs)
{
- foreach (Strings::iterator, i, opFlags)
- throw UsageError(format("unknown flag ‘%1%’") % *i);
+ for (auto & i : opFlags)
+ throw UsageError(format("unknown flag ‘%1%’") % i);
if (opArgs.size() != 3) throw UsageError("three arguments expected");
auto i = opArgs.begin();
@@ -1016,6 +1027,12 @@ static void opGenerateBinaryCacheKey(Strings opFlags, Strings opArgs)
}
+static void opVersion(Strings opFlags, Strings opArgs)
+{
+ printVersion("nix-store");
+}
+
+
/* Scan the arguments; find the operation, set global flags, put all
other flags in a list, and put all other arguments in another
list. */
@@ -1033,7 +1050,7 @@ int main(int argc, char * * argv)
if (*arg == "--help")
showManPage("nix-store");
else if (*arg == "--version")
- printVersion("nix-store");
+ op = opVersion;
else if (*arg == "--realise" || *arg == "--realize" || *arg == "-r")
op = opRealise;
else if (*arg == "--add" || *arg == "-A")
diff --git a/src/nix-store/serve-protocol.hh b/src/nix-store/serve-protocol.hh
index 741b622be..f7f151d46 100644
--- a/src/nix-store/serve-protocol.hh
+++ b/src/nix-store/serve-protocol.hh
@@ -5,7 +5,7 @@ namespace nix {
#define SERVE_MAGIC_1 0x390c9deb
#define SERVE_MAGIC_2 0x5452eecb
-#define SERVE_PROTOCOL_VERSION 0x200
+#define SERVE_PROTOCOL_VERSION 0x201
#define GET_PROTOCOL_MAJOR(x) ((x) & 0xff00)
#define GET_PROTOCOL_MINOR(x) ((x) & 0x00ff)
@@ -17,6 +17,7 @@ typedef enum {
cmdExportPaths = 5,
cmdBuildPaths = 6,
cmdQueryClosure = 7,
+ cmdBuildDerivation = 8,
} ServeCommand;
}