Generalise meta attributes
This commit is contained in:
parent
990126cde0
commit
0f24400d90
|
@ -2,116 +2,155 @@
|
||||||
#include "util.hh"
|
#include "util.hh"
|
||||||
#include "eval-inline.hh"
|
#include "eval-inline.hh"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
|
||||||
string DrvInfo::queryDrvPath(EvalState & state) const
|
string DrvInfo::queryDrvPath()
|
||||||
{
|
{
|
||||||
if (drvPath == "" && attrs) {
|
if (drvPath == "" && attrs) {
|
||||||
Bindings::iterator i = attrs->find(state.sDrvPath);
|
Bindings::iterator i = attrs->find(state->sDrvPath);
|
||||||
PathSet context;
|
PathSet context;
|
||||||
(string &) drvPath = i != attrs->end() ? state.coerceToPath(*i->value, context) : "";
|
drvPath = i != attrs->end() ? state->coerceToPath(*i->value, context) : "";
|
||||||
}
|
}
|
||||||
return drvPath;
|
return drvPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
string DrvInfo::queryOutPath(EvalState & state) const
|
string DrvInfo::queryOutPath()
|
||||||
{
|
{
|
||||||
if (outPath == "" && attrs) {
|
if (outPath == "" && attrs) {
|
||||||
Bindings::iterator i = attrs->find(state.sOutPath);
|
Bindings::iterator i = attrs->find(state->sOutPath);
|
||||||
PathSet context;
|
PathSet context;
|
||||||
(string &) outPath = i != attrs->end() ? state.coerceToPath(*i->value, context) : "";
|
outPath = i != attrs->end() ? state->coerceToPath(*i->value, context) : "";
|
||||||
}
|
}
|
||||||
return outPath;
|
return outPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DrvInfo::Outputs DrvInfo::queryOutputs(EvalState & state)
|
DrvInfo::Outputs DrvInfo::queryOutputs()
|
||||||
{
|
{
|
||||||
if (outputs.empty()) {
|
if (outputs.empty()) {
|
||||||
/* Get the ‘outputs’ list. */
|
/* Get the ‘outputs’ list. */
|
||||||
Bindings::iterator i = attrs->find(state.sOutputs);
|
Bindings::iterator i;
|
||||||
|
if (attrs && (i = attrs->find(state->sOutputs)) != attrs->end()) {
|
||||||
if (i == attrs->end())
|
state->forceList(*i->value);
|
||||||
outputs["out"] = queryOutPath(state);
|
|
||||||
else {
|
|
||||||
state.forceList(*i->value);
|
|
||||||
|
|
||||||
/* For each output... */
|
/* For each output... */
|
||||||
for (unsigned int j = 0; j < i->value->list.length; ++j) {
|
for (unsigned int j = 0; j < i->value->list.length; ++j) {
|
||||||
/* Evaluate the corresponding set. */
|
/* Evaluate the corresponding set. */
|
||||||
string name = state.forceStringNoCtx(*i->value->list.elems[j]);
|
string name = state->forceStringNoCtx(*i->value->list.elems[j]);
|
||||||
Bindings::iterator out = attrs->find(state.symbols.create(name));
|
Bindings::iterator out = attrs->find(state->symbols.create(name));
|
||||||
if (out == attrs->end()) continue; // FIXME: throw error?
|
if (out == attrs->end()) continue; // FIXME: throw error?
|
||||||
state.forceAttrs(*out->value);
|
state->forceAttrs(*out->value);
|
||||||
|
|
||||||
/* And evaluate its ‘outPath’ attribute. */
|
/* And evaluate its ‘outPath’ attribute. */
|
||||||
Bindings::iterator outPath = out->value->attrs->find(state.sOutPath);
|
Bindings::iterator outPath = out->value->attrs->find(state->sOutPath);
|
||||||
if (outPath == out->value->attrs->end()) continue; // FIXME: throw error?
|
if (outPath == out->value->attrs->end()) continue; // FIXME: throw error?
|
||||||
PathSet context;
|
PathSet context;
|
||||||
outputs[name] = state.coerceToPath(*outPath->value, context);
|
outputs[name] = state->coerceToPath(*outPath->value, context);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else
|
||||||
|
outputs["out"] = queryOutPath();
|
||||||
}
|
}
|
||||||
return outputs;
|
return outputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
string DrvInfo::queryOutputName(EvalState & state) const
|
string DrvInfo::queryOutputName()
|
||||||
{
|
{
|
||||||
if (outputName == "" && attrs) {
|
if (outputName == "" && attrs) {
|
||||||
Bindings::iterator i = attrs->find(state.sOutputName);
|
Bindings::iterator i = attrs->find(state->sOutputName);
|
||||||
(string &) outputName = i != attrs->end() ? state.forceStringNoCtx(*i->value) : "";
|
outputName = i != attrs->end() ? state->forceStringNoCtx(*i->value) : "";
|
||||||
}
|
}
|
||||||
return outputName;
|
return outputName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MetaInfo DrvInfo::queryMetaInfo(EvalState & state) const
|
Bindings * DrvInfo::getMeta()
|
||||||
{
|
{
|
||||||
if (metaInfoRead) return meta;
|
if (meta) return meta;
|
||||||
|
if (!attrs) return 0;
|
||||||
(bool &) metaInfoRead = true;
|
Bindings::iterator a = attrs->find(state->sMeta);
|
||||||
|
if (a == attrs->end()) return 0;
|
||||||
Bindings::iterator a = attrs->find(state.sMeta);
|
state->forceAttrs(*a->value);
|
||||||
if (a == attrs->end()) return meta; /* fine, empty meta information */
|
meta = a->value->attrs;
|
||||||
|
|
||||||
state.forceAttrs(*a->value);
|
|
||||||
|
|
||||||
foreach (Bindings::iterator, i, *a->value->attrs) {
|
|
||||||
MetaValue value;
|
|
||||||
state.forceValue(*i->value);
|
|
||||||
if (i->value->type == tString) {
|
|
||||||
value.type = MetaValue::tpString;
|
|
||||||
value.stringValue = i->value->string.s;
|
|
||||||
} else if (i->value->type == tInt) {
|
|
||||||
value.type = MetaValue::tpInt;
|
|
||||||
value.intValue = i->value->integer;
|
|
||||||
} else if (i->value->type == tList) {
|
|
||||||
value.type = MetaValue::tpStrings;
|
|
||||||
for (unsigned int j = 0; j < i->value->list.length; ++j)
|
|
||||||
value.stringValues.push_back(state.forceStringNoCtx(*i->value->list.elems[j]));
|
|
||||||
} else continue;
|
|
||||||
((MetaInfo &) meta)[i->name] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return meta;
|
return meta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MetaValue DrvInfo::queryMetaInfo(EvalState & state, const string & name) const
|
StringSet DrvInfo::queryMetaNames()
|
||||||
{
|
{
|
||||||
/* !!! evaluates all meta attributes => inefficient */
|
StringSet res;
|
||||||
return queryMetaInfo(state)[name];
|
if (!getMeta()) return res;
|
||||||
|
foreach (Bindings::iterator, i, *meta)
|
||||||
|
res.insert(i->name);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DrvInfo::setMetaInfo(const MetaInfo & meta)
|
Value * DrvInfo::queryMeta(const string & name)
|
||||||
{
|
{
|
||||||
metaInfoRead = true;
|
if (!getMeta()) return 0;
|
||||||
this->meta = meta;
|
Bindings::iterator a = meta->find(state->symbols.create(name));
|
||||||
|
if (a == meta->end()) return 0;
|
||||||
|
state->forceValue(*a->value);
|
||||||
|
return a->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string DrvInfo::queryMetaString(const string & name)
|
||||||
|
{
|
||||||
|
Value * v = queryMeta(name);
|
||||||
|
if (!v || v->type != tString) return "";
|
||||||
|
return v->string.s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int DrvInfo::queryMetaInt(const string & name, int def)
|
||||||
|
{
|
||||||
|
Value * v = queryMeta(name);
|
||||||
|
if (!v) return def;
|
||||||
|
if (v->type == tInt) return v->integer;
|
||||||
|
if (v->type == tString) {
|
||||||
|
/* Backwards compatibility with before we had support for
|
||||||
|
integer meta fields. */
|
||||||
|
int n;
|
||||||
|
if (string2Int(v->string.s, n)) return n;
|
||||||
|
}
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool DrvInfo::queryMetaBool(const string & name, bool def)
|
||||||
|
{
|
||||||
|
Value * v = queryMeta(name);
|
||||||
|
if (!v) return def;
|
||||||
|
if (v->type == tBool) return v->boolean;
|
||||||
|
if (v->type == tString) {
|
||||||
|
/* Backwards compatibility with before we had support for
|
||||||
|
Boolean meta fields. */
|
||||||
|
if (strcmp(v->string.s, "true") == 0) return true;
|
||||||
|
if (strcmp(v->string.s, "false") == 0) return false;
|
||||||
|
}
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DrvInfo::setMeta(const string & name, Value * v)
|
||||||
|
{
|
||||||
|
getMeta();
|
||||||
|
Bindings * old = meta;
|
||||||
|
meta = new Bindings();
|
||||||
|
Symbol sym = state->symbols.create(name);
|
||||||
|
if (old)
|
||||||
|
foreach (Bindings::iterator, i, *old)
|
||||||
|
if (i->name != sym)
|
||||||
|
meta->push_back(*i);
|
||||||
|
if (v) meta->push_back(Attr(sym, v));
|
||||||
|
meta->sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -136,22 +175,18 @@ static bool getDerivation(EvalState & state, Value & v,
|
||||||
if (done.find(v.attrs) != done.end()) return false;
|
if (done.find(v.attrs) != done.end()) return false;
|
||||||
done.insert(v.attrs);
|
done.insert(v.attrs);
|
||||||
|
|
||||||
DrvInfo drv;
|
|
||||||
|
|
||||||
Bindings::iterator i = v.attrs->find(state.sName);
|
Bindings::iterator i = v.attrs->find(state.sName);
|
||||||
/* !!! We really would like to have a decent back trace here. */
|
/* !!! We really would like to have a decent back trace here. */
|
||||||
if (i == v.attrs->end()) throw TypeError("derivation name missing");
|
if (i == v.attrs->end()) throw TypeError("derivation name missing");
|
||||||
drv.name = state.forceStringNoCtx(*i->value);
|
|
||||||
|
|
||||||
Bindings::iterator i2 = v.attrs->find(state.sSystem);
|
Bindings::iterator i2 = v.attrs->find(state.sSystem);
|
||||||
if (i2 == v.attrs->end())
|
|
||||||
drv.system = "unknown";
|
|
||||||
else
|
|
||||||
drv.system = state.forceStringNoCtx(*i2->value);
|
|
||||||
|
|
||||||
drv.attrs = v.attrs;
|
DrvInfo drv(
|
||||||
|
state,
|
||||||
drv.attrPath = attrPath;
|
state.forceStringNoCtx(*i->value),
|
||||||
|
attrPath,
|
||||||
|
i2 == v.attrs->end() ? "unknown" : state.forceStringNoCtx(*i2->value),
|
||||||
|
v.attrs);
|
||||||
|
|
||||||
drvs.push_back(drv);
|
drvs.push_back(drv);
|
||||||
return false;
|
return false;
|
||||||
|
@ -190,8 +225,6 @@ static void getDerivations(EvalState & state, Value & vIn,
|
||||||
state.autoCallFunction(autoArgs, vIn, v);
|
state.autoCallFunction(autoArgs, vIn, v);
|
||||||
|
|
||||||
/* Process the expression. */
|
/* Process the expression. */
|
||||||
DrvInfo drv;
|
|
||||||
|
|
||||||
if (!getDerivation(state, v, pathPrefix, drvs, done, ignoreAssertionFailures)) ;
|
if (!getDerivation(state, v, pathPrefix, drvs, done, ignoreAssertionFailures)) ;
|
||||||
|
|
||||||
else if (v.type == tAttrs) {
|
else if (v.type == tAttrs) {
|
||||||
|
|
|
@ -11,50 +11,50 @@
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
|
||||||
struct MetaValue
|
|
||||||
{
|
|
||||||
enum { tpNone, tpString, tpStrings, tpInt } type;
|
|
||||||
string stringValue;
|
|
||||||
Strings stringValues;
|
|
||||||
int intValue;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
typedef std::map<string, MetaValue> MetaInfo;
|
|
||||||
|
|
||||||
|
|
||||||
struct DrvInfo
|
struct DrvInfo
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef std::map<string, Path> Outputs;
|
typedef std::map<string, Path> Outputs;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
EvalState * state;
|
||||||
|
|
||||||
string drvPath;
|
string drvPath;
|
||||||
string outPath;
|
string outPath;
|
||||||
string outputName;
|
string outputName;
|
||||||
Outputs outputs;
|
Outputs outputs;
|
||||||
|
|
||||||
bool metaInfoRead;
|
|
||||||
MetaInfo meta;
|
|
||||||
|
|
||||||
bool failed; // set if we get an AssertionError
|
bool failed; // set if we get an AssertionError
|
||||||
|
|
||||||
|
Bindings * attrs, * meta;
|
||||||
|
|
||||||
|
Bindings * getMeta();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
string name;
|
string name;
|
||||||
string attrPath; /* path towards the derivation */
|
string attrPath; /* path towards the derivation */
|
||||||
string system;
|
string system;
|
||||||
|
|
||||||
/* !!! make this private */
|
DrvInfo(EvalState & state) : state(&state), failed(false), attrs(0), meta(0) { };
|
||||||
Bindings * attrs;
|
DrvInfo(EvalState & state, const string & name, const string & attrPath, const string & system, Bindings * attrs)
|
||||||
|
: state(&state), failed(false), attrs(attrs), meta(0), name(name), attrPath(attrPath), system(system) { };
|
||||||
|
|
||||||
DrvInfo() : metaInfoRead(false), failed(false), attrs(0) { };
|
string queryDrvPath();
|
||||||
|
string queryOutPath();
|
||||||
|
string queryOutputName();
|
||||||
|
Outputs queryOutputs();
|
||||||
|
|
||||||
string queryDrvPath(EvalState & state) const;
|
StringSet queryMetaNames();
|
||||||
string queryOutPath(EvalState & state) const;
|
Value * queryMeta(const string & name);
|
||||||
string queryOutputName(EvalState & state) const;
|
string queryMetaString(const string & name);
|
||||||
Outputs queryOutputs(EvalState & state);
|
int queryMetaInt(const string & name, int def);
|
||||||
|
bool queryMetaBool(const string & name, bool def);
|
||||||
|
void setMeta(const string & name, Value * v);
|
||||||
|
|
||||||
|
/*
|
||||||
MetaInfo queryMetaInfo(EvalState & state) const;
|
MetaInfo queryMetaInfo(EvalState & state) const;
|
||||||
MetaValue queryMetaInfo(EvalState & state, const string & name) const;
|
MetaValue queryMetaInfo(EvalState & state, const string & name) const;
|
||||||
|
*/
|
||||||
|
|
||||||
void setDrvPath(const string & s)
|
void setDrvPath(const string & s)
|
||||||
{
|
{
|
||||||
|
@ -66,8 +66,6 @@ public:
|
||||||
outPath = s;
|
outPath = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setMetaInfo(const MetaInfo & meta);
|
|
||||||
|
|
||||||
void setFailed() { failed = true; };
|
void setFailed() { failed = true; };
|
||||||
bool hasFailed() { return failed; };
|
bool hasFailed() { return failed; };
|
||||||
};
|
};
|
||||||
|
|
|
@ -210,21 +210,13 @@ static Path getDefNixExprPath()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int getPriority(EvalState & state, const DrvInfo & drv)
|
static int getPriority(EvalState & state, DrvInfo & drv)
|
||||||
{
|
{
|
||||||
MetaValue value = drv.queryMetaInfo(state, "priority");
|
return drv.queryMetaInt("priority", 0);
|
||||||
int prio = 0;
|
|
||||||
if (value.type == MetaValue::tpInt) prio = value.intValue;
|
|
||||||
else if (value.type == MetaValue::tpString)
|
|
||||||
/* Backwards compatibility. Priorities used to be strings
|
|
||||||
before we had support for integer meta field. */
|
|
||||||
string2Int(value.stringValue, prio);
|
|
||||||
return prio;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int comparePriorities(EvalState & state,
|
static int comparePriorities(EvalState & state, DrvInfo & drv1, DrvInfo & drv2)
|
||||||
const DrvInfo & drv1, const DrvInfo & drv2)
|
|
||||||
{
|
{
|
||||||
return getPriority(state, drv2) - getPriority(state, drv1);
|
return getPriority(state, drv2) - getPriority(state, drv1);
|
||||||
}
|
}
|
||||||
|
@ -232,9 +224,9 @@ static int comparePriorities(EvalState & state,
|
||||||
|
|
||||||
// FIXME: this function is rather slow since it checks a single path
|
// FIXME: this function is rather slow since it checks a single path
|
||||||
// at a time.
|
// at a time.
|
||||||
static bool isPrebuilt(EvalState & state, const DrvInfo & elem)
|
static bool isPrebuilt(EvalState & state, DrvInfo & elem)
|
||||||
{
|
{
|
||||||
Path path = elem.queryOutPath(state);
|
Path path = elem.queryOutPath();
|
||||||
if (store->isValidPath(path)) return true;
|
if (store->isValidPath(path)) return true;
|
||||||
PathSet ps = store->querySubstitutablePaths(singleton<PathSet>(path));
|
PathSet ps = store->querySubstitutablePaths(singleton<PathSet>(path));
|
||||||
return ps.find(path) != ps.end();
|
return ps.find(path) != ps.end();
|
||||||
|
@ -296,7 +288,8 @@ static DrvInfos filterBySelector(EvalState & state, const DrvInfos & allElems,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d > 0) {
|
if (d > 0) {
|
||||||
newest[drvName.name] = *j;
|
newest.erase(drvName.name);
|
||||||
|
newest.insert(Newest::value_type(drvName.name, *j));
|
||||||
multiple.erase(j->first.name);
|
multiple.erase(j->first.name);
|
||||||
} else if (d == 0) {
|
} else if (d == 0) {
|
||||||
multiple.insert(j->first.name);
|
multiple.insert(j->first.name);
|
||||||
|
@ -392,18 +385,16 @@ static void queryInstSources(EvalState & state,
|
||||||
derivations). */
|
derivations). */
|
||||||
case srcStorePaths: {
|
case srcStorePaths: {
|
||||||
|
|
||||||
for (Strings::const_iterator i = args.begin();
|
foreach (Strings::const_iterator, i, args) {
|
||||||
i != args.end(); ++i)
|
|
||||||
{
|
|
||||||
Path path = followLinksToStorePath(*i);
|
Path path = followLinksToStorePath(*i);
|
||||||
|
|
||||||
DrvInfo elem;
|
|
||||||
elem.attrs = new Bindings;
|
|
||||||
string name = baseNameOf(path);
|
string name = baseNameOf(path);
|
||||||
string::size_type dash = name.find('-');
|
string::size_type dash = name.find('-');
|
||||||
if (dash != string::npos)
|
if (dash != string::npos)
|
||||||
name = string(name, dash + 1);
|
name = string(name, dash + 1);
|
||||||
|
|
||||||
|
DrvInfo elem(state, name, "", "", 0);
|
||||||
|
|
||||||
if (isDerivation(path)) {
|
if (isDerivation(path)) {
|
||||||
elem.setDrvPath(path);
|
elem.setDrvPath(path);
|
||||||
elem.setOutPath(findOutput(derivationFromPath(*store, path), "out"));
|
elem.setOutPath(findOutput(derivationFromPath(*store, path), "out"));
|
||||||
|
@ -413,8 +404,6 @@ static void queryInstSources(EvalState & state,
|
||||||
}
|
}
|
||||||
else elem.setOutPath(path);
|
else elem.setOutPath(path);
|
||||||
|
|
||||||
elem.name = name;
|
|
||||||
|
|
||||||
elems.push_back(elem);
|
elems.push_back(elem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -444,25 +433,24 @@ static void queryInstSources(EvalState & state,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void printMissing(EvalState & state, const DrvInfos & elems)
|
static void printMissing(EvalState & state, DrvInfos & elems)
|
||||||
{
|
{
|
||||||
PathSet targets;
|
PathSet targets;
|
||||||
foreach (DrvInfos::const_iterator, i, elems) {
|
foreach (DrvInfos::iterator, i, elems) {
|
||||||
Path drvPath = i->queryDrvPath(state);
|
Path drvPath = i->queryDrvPath();
|
||||||
if (drvPath != "")
|
if (drvPath != "")
|
||||||
targets.insert(drvPath);
|
targets.insert(drvPath);
|
||||||
else
|
else
|
||||||
targets.insert(i->queryOutPath(state));
|
targets.insert(i->queryOutPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
printMissing(*store, targets);
|
printMissing(*store, targets);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool keep(MetaInfo & meta)
|
static bool keep(DrvInfo & drv)
|
||||||
{
|
{
|
||||||
MetaValue value = meta["keep"];
|
return drv.queryMetaBool("keep", false);
|
||||||
return value.type == MetaValue::tpString && value.stringValue == "true";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -504,10 +492,9 @@ static void installDerivations(Globals & globals,
|
||||||
|
|
||||||
foreach (DrvInfos::iterator, i, installedElems) {
|
foreach (DrvInfos::iterator, i, installedElems) {
|
||||||
DrvName drvName(i->name);
|
DrvName drvName(i->name);
|
||||||
MetaInfo meta = i->queryMetaInfo(globals.state);
|
|
||||||
if (!globals.preserveInstalled &&
|
if (!globals.preserveInstalled &&
|
||||||
newNames.find(drvName.name) != newNames.end() &&
|
newNames.find(drvName.name) != newNames.end() &&
|
||||||
!keep(meta))
|
!keep(*i))
|
||||||
printMsg(lvlInfo, format("replacing old `%1%'") % i->name);
|
printMsg(lvlInfo, format("replacing old `%1%'") % i->name);
|
||||||
else
|
else
|
||||||
allElems.push_back(*i);
|
allElems.push_back(*i);
|
||||||
|
@ -573,8 +560,7 @@ static void upgradeDerivations(Globals & globals,
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
MetaInfo meta = i->queryMetaInfo(globals.state);
|
if (keep(*i)) {
|
||||||
if (keep(meta)) {
|
|
||||||
newElems.push_back(*i);
|
newElems.push_back(*i);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -611,8 +597,8 @@ static void upgradeDerivations(Globals & globals,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bestElem != availElems.end() &&
|
if (bestElem != availElems.end() &&
|
||||||
i->queryOutPath(globals.state) !=
|
i->queryOutPath() !=
|
||||||
bestElem->queryOutPath(globals.state))
|
bestElem->queryOutPath())
|
||||||
{
|
{
|
||||||
printMsg(lvlInfo,
|
printMsg(lvlInfo,
|
||||||
format("upgrading `%1%' to `%2%'")
|
format("upgrading `%1%' to `%2%'")
|
||||||
|
@ -657,12 +643,9 @@ static void opUpgrade(Globals & globals,
|
||||||
static void setMetaFlag(EvalState & state, DrvInfo & drv,
|
static void setMetaFlag(EvalState & state, DrvInfo & drv,
|
||||||
const string & name, const string & value)
|
const string & name, const string & value)
|
||||||
{
|
{
|
||||||
MetaInfo meta = drv.queryMetaInfo(state);
|
Value * v = state.allocValue();
|
||||||
MetaValue v;
|
mkString(*v, value.c_str());
|
||||||
v.type = MetaValue::tpString;
|
drv.setMeta(name, v);
|
||||||
v.stringValue = value;
|
|
||||||
meta[name] = v;
|
|
||||||
drv.setMetaInfo(meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -689,8 +672,7 @@ static void opSetFlag(Globals & globals,
|
||||||
DrvName drvName(i->name);
|
DrvName drvName(i->name);
|
||||||
foreach (DrvNames::iterator, j, selectors)
|
foreach (DrvNames::iterator, j, selectors)
|
||||||
if (j->matches(drvName)) {
|
if (j->matches(drvName)) {
|
||||||
printMsg(lvlInfo,
|
printMsg(lvlInfo, format("setting flag on `%1%'") % i->name);
|
||||||
format("setting flag on `%1%'") % i->name);
|
|
||||||
setMetaFlag(globals.state, *i, flagName, flagValue);
|
setMetaFlag(globals.state, *i, flagName, flagValue);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -720,20 +702,20 @@ static void opSet(Globals & globals,
|
||||||
|
|
||||||
DrvInfo & drv(elems.front());
|
DrvInfo & drv(elems.front());
|
||||||
|
|
||||||
if (drv.queryDrvPath(globals.state) != "") {
|
if (drv.queryDrvPath() != "") {
|
||||||
PathSet paths = singleton<PathSet>(drv.queryDrvPath(globals.state));
|
PathSet paths = singleton<PathSet>(drv.queryDrvPath());
|
||||||
printMissing(*store, paths);
|
printMissing(*store, paths);
|
||||||
if (globals.dryRun) return;
|
if (globals.dryRun) return;
|
||||||
store->buildPaths(paths, globals.state.repair);
|
store->buildPaths(paths, globals.state.repair);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
printMissing(*store, singleton<PathSet>(drv.queryOutPath(globals.state)));
|
printMissing(*store, singleton<PathSet>(drv.queryOutPath()));
|
||||||
if (globals.dryRun) return;
|
if (globals.dryRun) return;
|
||||||
store->ensurePath(drv.queryOutPath(globals.state));
|
store->ensurePath(drv.queryOutPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
debug(format("switching to new user environment"));
|
debug(format("switching to new user environment"));
|
||||||
Path generation = createGeneration(globals.profile, drv.queryOutPath(globals.state));
|
Path generation = createGeneration(globals.profile, drv.queryOutPath());
|
||||||
switchLink(globals.profile, generation);
|
switchLink(globals.profile, generation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -753,7 +735,7 @@ static void uninstallDerivations(Globals & globals, Strings & selectors,
|
||||||
foreach (Strings::iterator, j, selectors)
|
foreach (Strings::iterator, j, selectors)
|
||||||
/* !!! the repeated calls to followLinksToStorePath()
|
/* !!! the repeated calls to followLinksToStorePath()
|
||||||
are expensive, should pre-compute them. */
|
are expensive, should pre-compute them. */
|
||||||
if ((isPath(*j) && i->queryOutPath(globals.state) == followLinksToStorePath(*j))
|
if ((isPath(*j) && i->queryOutPath() == followLinksToStorePath(*j))
|
||||||
|| DrvName(*j).matches(drvName))
|
|| DrvName(*j).matches(drvName))
|
||||||
{
|
{
|
||||||
printMsg(lvlInfo, format("uninstalling `%1%'") % i->name);
|
printMsg(lvlInfo, format("uninstalling `%1%'") % i->name);
|
||||||
|
@ -887,18 +869,12 @@ static void queryJSON(Globals & globals, vector<DrvInfo> & elems)
|
||||||
|
|
||||||
pkgObj.attr("meta");
|
pkgObj.attr("meta");
|
||||||
JSONObject metaObj(cout);
|
JSONObject metaObj(cout);
|
||||||
MetaInfo meta = i->queryMetaInfo(globals.state);
|
StringSet metaNames = i->queryMetaNames();
|
||||||
foreach (MetaInfo::iterator, j, meta) {
|
foreach (StringSet::iterator, j, metaNames) {
|
||||||
metaObj.attr(j->first);
|
metaObj.attr(*j);
|
||||||
if (j->second.type == MetaValue::tpString) {
|
Value * v = i->queryMeta(*j);
|
||||||
escapeJSON(cout, j->second.stringValue);
|
PathSet context;
|
||||||
} else if (j->second.type == MetaValue::tpInt) {
|
printValueAsJSON(globals.state, true, *v, cout, context);
|
||||||
cout << j->second.intValue;
|
|
||||||
} else if (j->second.type == MetaValue::tpStrings) {
|
|
||||||
JSONList l(cout);
|
|
||||||
foreach (Strings::iterator, k, j->second.stringValues)
|
|
||||||
l.elem(*k);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -983,7 +959,7 @@ static void opQuery(Globals & globals,
|
||||||
if (printStatus) {
|
if (printStatus) {
|
||||||
for (DrvInfos::iterator i = installedElems.begin();
|
for (DrvInfos::iterator i = installedElems.begin();
|
||||||
i != installedElems.end(); ++i)
|
i != installedElems.end(); ++i)
|
||||||
installed.insert(i->queryOutPath(globals.state));
|
installed.insert(i->queryOutPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -993,7 +969,7 @@ static void opQuery(Globals & globals,
|
||||||
PathSet paths;
|
PathSet paths;
|
||||||
foreach (vector<DrvInfo>::iterator, i, elems)
|
foreach (vector<DrvInfo>::iterator, i, elems)
|
||||||
try {
|
try {
|
||||||
paths.insert(i->queryOutPath(globals.state));
|
paths.insert(i->queryOutPath());
|
||||||
} catch (AssertionError & e) {
|
} 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);
|
||||||
i->setFailed();
|
i->setFailed();
|
||||||
|
@ -1021,8 +997,8 @@ static void opQuery(Globals & globals,
|
||||||
startNest(nest, lvlDebug, format("outputting query result `%1%'") % i->attrPath);
|
startNest(nest, lvlDebug, format("outputting query result `%1%'") % i->attrPath);
|
||||||
|
|
||||||
if (globals.prebuiltOnly &&
|
if (globals.prebuiltOnly &&
|
||||||
validPaths.find(i->queryOutPath(globals.state)) == validPaths.end() &&
|
validPaths.find(i->queryOutPath()) == validPaths.end() &&
|
||||||
substitutablePaths.find(i->queryOutPath(globals.state)) == substitutablePaths.end())
|
substitutablePaths.find(i->queryOutPath()) == substitutablePaths.end())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* For table output. */
|
/* For table output. */
|
||||||
|
@ -1032,7 +1008,7 @@ static void opQuery(Globals & globals,
|
||||||
XMLAttrs attrs;
|
XMLAttrs attrs;
|
||||||
|
|
||||||
if (printStatus) {
|
if (printStatus) {
|
||||||
Path outPath = i->queryOutPath(globals.state);
|
Path outPath = i->queryOutPath();
|
||||||
bool hasSubs = substitutablePaths.find(outPath) != substitutablePaths.end();
|
bool hasSubs = substitutablePaths.find(outPath) != substitutablePaths.end();
|
||||||
bool isInstalled = installed.find(outPath) != installed.end();
|
bool isInstalled = installed.find(outPath) != installed.end();
|
||||||
bool isValid = validPaths.find(outPath) != validPaths.end();
|
bool isValid = validPaths.find(outPath) != validPaths.end();
|
||||||
|
@ -1093,7 +1069,7 @@ static void opQuery(Globals & globals,
|
||||||
columns.push_back(i->system);
|
columns.push_back(i->system);
|
||||||
|
|
||||||
if (printDrvPath) {
|
if (printDrvPath) {
|
||||||
string drvPath = i->queryDrvPath(globals.state);
|
string drvPath = i->queryDrvPath();
|
||||||
if (xmlOutput) {
|
if (xmlOutput) {
|
||||||
if (drvPath != "") attrs["drvPath"] = drvPath;
|
if (drvPath != "") attrs["drvPath"] = drvPath;
|
||||||
} else
|
} else
|
||||||
|
@ -1101,7 +1077,7 @@ static void opQuery(Globals & globals,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (printOutPath && !xmlOutput) {
|
if (printOutPath && !xmlOutput) {
|
||||||
DrvInfo::Outputs outputs = i->queryOutputs(globals.state);
|
DrvInfo::Outputs outputs = i->queryOutputs();
|
||||||
string s;
|
string s;
|
||||||
foreach (DrvInfo::Outputs::iterator, j, outputs) {
|
foreach (DrvInfo::Outputs::iterator, j, outputs) {
|
||||||
if (!s.empty()) s += ';';
|
if (!s.empty()) s += ';';
|
||||||
|
@ -1112,9 +1088,7 @@ static void opQuery(Globals & globals,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (printDescription) {
|
if (printDescription) {
|
||||||
MetaInfo meta = i->queryMetaInfo(globals.state);
|
string descr = i->queryMetaString("description");
|
||||||
MetaValue value = meta["description"];
|
|
||||||
string descr = value.type == MetaValue::tpString ? value.stringValue : "";
|
|
||||||
if (xmlOutput) {
|
if (xmlOutput) {
|
||||||
if (descr != "") attrs["description"] = descr;
|
if (descr != "") attrs["description"] = descr;
|
||||||
} else
|
} else
|
||||||
|
@ -1125,7 +1099,7 @@ static void opQuery(Globals & globals,
|
||||||
if (printOutPath || printMeta) {
|
if (printOutPath || printMeta) {
|
||||||
XMLOpenElement item(xml, "item", attrs);
|
XMLOpenElement item(xml, "item", attrs);
|
||||||
if (printOutPath) {
|
if (printOutPath) {
|
||||||
DrvInfo::Outputs outputs = i->queryOutputs(globals.state);
|
DrvInfo::Outputs outputs = i->queryOutputs();
|
||||||
foreach (DrvInfo::Outputs::iterator, j, outputs) {
|
foreach (DrvInfo::Outputs::iterator, j, outputs) {
|
||||||
XMLAttrs attrs2;
|
XMLAttrs attrs2;
|
||||||
attrs2["name"] = j->first;
|
attrs2["name"] = j->first;
|
||||||
|
@ -1134,24 +1108,30 @@ static void opQuery(Globals & globals,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (printMeta) {
|
if (printMeta) {
|
||||||
MetaInfo meta = i->queryMetaInfo(globals.state);
|
StringSet metaNames = i->queryMetaNames();
|
||||||
foreach (MetaInfo::iterator, j, meta) {
|
foreach (StringSet::iterator, j, metaNames) {
|
||||||
XMLAttrs attrs2;
|
XMLAttrs attrs2;
|
||||||
attrs2["name"] = j->first;
|
attrs2["name"] = *j;
|
||||||
if (j->second.type == MetaValue::tpString) {
|
Value & v(*i->queryMeta(*j));
|
||||||
|
if (v.type == tString) {
|
||||||
attrs2["type"] = "string";
|
attrs2["type"] = "string";
|
||||||
attrs2["value"] = j->second.stringValue;
|
attrs2["value"] = v.string.s;
|
||||||
xml.writeEmptyElement("meta", attrs2);
|
xml.writeEmptyElement("meta", attrs2);
|
||||||
} else if (j->second.type == MetaValue::tpInt) {
|
} else if (v.type == tInt) {
|
||||||
attrs2["type"] = "int";
|
attrs2["type"] = "int";
|
||||||
attrs2["value"] = (format("%1%") % j->second.intValue).str();
|
attrs2["value"] = (format("%1%") % v.integer).str();
|
||||||
xml.writeEmptyElement("meta", attrs2);
|
xml.writeEmptyElement("meta", attrs2);
|
||||||
} else if (j->second.type == MetaValue::tpStrings) {
|
} else if (v.type == tBool) {
|
||||||
|
attrs2["type"] = "bool";
|
||||||
|
attrs2["value"] = v.boolean ? "true" : "false";
|
||||||
|
xml.writeEmptyElement("meta", attrs2);
|
||||||
|
} else if (v.type == tList) {
|
||||||
attrs2["type"] = "strings";
|
attrs2["type"] = "strings";
|
||||||
XMLOpenElement m(xml, "meta", attrs2);
|
XMLOpenElement m(xml, "meta", attrs2);
|
||||||
foreach (Strings::iterator, k, j->second.stringValues) {
|
for (unsigned int j = 0; j < v.list.length; ++j) {
|
||||||
|
string s = globals.state.forceStringNoCtx(*v.list.elems[j]);
|
||||||
XMLAttrs attrs3;
|
XMLAttrs attrs3;
|
||||||
attrs3["value"] = *k;
|
attrs3["value"] = s;
|
||||||
xml.writeEmptyElement("string", attrs3);
|
xml.writeEmptyElement("string", attrs3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1166,6 +1146,9 @@ static void opQuery(Globals & globals,
|
||||||
|
|
||||||
} catch (AssertionError & e) {
|
} 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);
|
||||||
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
#include "shared.hh"
|
#include "shared.hh"
|
||||||
#include "eval.hh"
|
#include "eval.hh"
|
||||||
|
#include "eval-inline.hh"
|
||||||
#include "profiles.hh"
|
#include "profiles.hh"
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,9 +33,9 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
|
||||||
/* Build the components in the user environment, if they don't
|
/* Build the components in the user environment, if they don't
|
||||||
exist already. */
|
exist already. */
|
||||||
PathSet drvsToBuild;
|
PathSet drvsToBuild;
|
||||||
foreach (DrvInfos::const_iterator, i, elems)
|
foreach (DrvInfos::iterator, i, elems)
|
||||||
if (i->queryDrvPath(state) != "")
|
if (i->queryDrvPath() != "")
|
||||||
drvsToBuild.insert(i->queryDrvPath(state));
|
drvsToBuild.insert(i->queryDrvPath());
|
||||||
|
|
||||||
debug(format("building user environment dependencies"));
|
debug(format("building user environment dependencies"));
|
||||||
store->buildPaths(drvsToBuild, state.repair);
|
store->buildPaths(drvsToBuild, state.repair);
|
||||||
|
@ -48,7 +49,7 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
|
||||||
/* Create a pseudo-derivation containing the name, system,
|
/* Create a pseudo-derivation containing the name, system,
|
||||||
output paths, and optionally the derivation path, as well
|
output paths, and optionally the derivation path, as well
|
||||||
as the meta attributes. */
|
as the meta attributes. */
|
||||||
Path drvPath = keepDerivations ? i->queryDrvPath(state) : "";
|
Path drvPath = keepDerivations ? i->queryDrvPath() : "";
|
||||||
|
|
||||||
Value & v(*state.allocValue());
|
Value & v(*state.allocValue());
|
||||||
manifest.list.elems[n++] = &v;
|
manifest.list.elems[n++] = &v;
|
||||||
|
@ -58,12 +59,12 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
|
||||||
mkString(*state.allocAttr(v, state.sName), i->name);
|
mkString(*state.allocAttr(v, state.sName), i->name);
|
||||||
if (!i->system.empty())
|
if (!i->system.empty())
|
||||||
mkString(*state.allocAttr(v, state.sSystem), i->system);
|
mkString(*state.allocAttr(v, state.sSystem), i->system);
|
||||||
mkString(*state.allocAttr(v, state.sOutPath), i->queryOutPath(state));
|
mkString(*state.allocAttr(v, state.sOutPath), i->queryOutPath());
|
||||||
if (drvPath != "")
|
if (drvPath != "")
|
||||||
mkString(*state.allocAttr(v, state.sDrvPath), i->queryDrvPath(state));
|
mkString(*state.allocAttr(v, state.sDrvPath), i->queryDrvPath());
|
||||||
|
|
||||||
// Copy each output.
|
// Copy each output.
|
||||||
DrvInfo::Outputs outputs = i->queryOutputs(state);
|
DrvInfo::Outputs outputs = i->queryOutputs();
|
||||||
Value & vOutputs = *state.allocAttr(v, state.sOutputs);
|
Value & vOutputs = *state.allocAttr(v, state.sOutputs);
|
||||||
state.mkList(vOutputs, outputs.size());
|
state.mkList(vOutputs, outputs.size());
|
||||||
unsigned int m = 0;
|
unsigned int m = 0;
|
||||||
|
@ -84,28 +85,12 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
|
||||||
// Copy the meta attributes.
|
// Copy the meta attributes.
|
||||||
Value & vMeta = *state.allocAttr(v, state.sMeta);
|
Value & vMeta = *state.allocAttr(v, state.sMeta);
|
||||||
state.mkAttrs(vMeta, 16);
|
state.mkAttrs(vMeta, 16);
|
||||||
|
StringSet metaNames = i->queryMetaNames();
|
||||||
MetaInfo meta = i->queryMetaInfo(state);
|
foreach (StringSet::iterator, j, metaNames) {
|
||||||
|
Value * v = i->queryMeta(*j);
|
||||||
foreach (MetaInfo::const_iterator, j, meta) {
|
state.strictForceValue(*v); // FIXME
|
||||||
Value & v2(*state.allocAttr(vMeta, state.symbols.create(j->first)));
|
vMeta.attrs->push_back(Attr(state.symbols.create(*j), v));
|
||||||
switch (j->second.type) {
|
|
||||||
case MetaValue::tpInt: mkInt(v2, j->second.intValue); break;
|
|
||||||
case MetaValue::tpString: mkString(v2, j->second.stringValue); break;
|
|
||||||
case MetaValue::tpStrings: {
|
|
||||||
state.mkList(v2, j->second.stringValues.size());
|
|
||||||
unsigned int m = 0;
|
|
||||||
foreach (Strings::const_iterator, k, j->second.stringValues) {
|
|
||||||
v2.list.elems[m] = state.allocValue();
|
|
||||||
mkString(*v2.list.elems[m++], *k);
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: abort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vMeta.attrs->sort();
|
|
||||||
v.attrs->sort();
|
v.attrs->sort();
|
||||||
|
|
||||||
if (drvPath != "") references.insert(drvPath);
|
if (drvPath != "") references.insert(drvPath);
|
||||||
|
@ -133,13 +118,14 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
|
||||||
|
|
||||||
/* Evaluate it. */
|
/* Evaluate it. */
|
||||||
debug("evaluating user environment builder");
|
debug("evaluating user environment builder");
|
||||||
DrvInfo topLevelDrv;
|
state.forceValue(topLevel);
|
||||||
if (!getDerivation(state, topLevel, topLevelDrv, false))
|
PathSet context;
|
||||||
abort();
|
Path topLevelDrv = state.coerceToPath(*topLevel.attrs->find(state.sDrvPath)->value, context);
|
||||||
|
Path topLevelOut = state.coerceToPath(*topLevel.attrs->find(state.sOutPath)->value, context);
|
||||||
|
|
||||||
/* Realise the resulting store expression. */
|
/* Realise the resulting store expression. */
|
||||||
debug("building user environment");
|
debug("building user environment");
|
||||||
store->buildPaths(singleton<PathSet>(topLevelDrv.queryDrvPath(state)), state.repair);
|
store->buildPaths(singleton<PathSet>(topLevelDrv), state.repair);
|
||||||
|
|
||||||
/* Switch the current user environment to the output path. */
|
/* Switch the current user environment to the output path. */
|
||||||
PathLocks lock;
|
PathLocks lock;
|
||||||
|
@ -152,7 +138,7 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
|
||||||
}
|
}
|
||||||
|
|
||||||
debug(format("switching to new user environment"));
|
debug(format("switching to new user environment"));
|
||||||
Path generation = createGeneration(profile, topLevelDrv.queryOutPath(state));
|
Path generation = createGeneration(profile, topLevelOut);
|
||||||
switchLink(profile, generation);
|
switchLink(profile, generation);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -63,10 +63,10 @@ void processExpr(EvalState & state, const Strings & attrPaths,
|
||||||
DrvInfos drvs;
|
DrvInfos drvs;
|
||||||
getDerivations(state, v, "", autoArgs, drvs, false);
|
getDerivations(state, v, "", autoArgs, drvs, false);
|
||||||
foreach (DrvInfos::iterator, i, drvs) {
|
foreach (DrvInfos::iterator, i, drvs) {
|
||||||
Path drvPath = i->queryDrvPath(state);
|
Path drvPath = i->queryDrvPath();
|
||||||
|
|
||||||
/* What output do we want? */
|
/* What output do we want? */
|
||||||
string outputName = i->queryOutputName(state);
|
string outputName = i->queryOutputName();
|
||||||
if (outputName == "")
|
if (outputName == "")
|
||||||
throw Error(format("derivation `%1%' lacks an `outputName' attribute ") % drvPath);
|
throw Error(format("derivation `%1%' lacks an `outputName' attribute ") % drvPath);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue