forked from lix-project/lix
* Support integers and lists of strings in meta fields. This is
useful for fields like meta.maintainers, meta.priority (which can be a proper integer now) and even meta.license (if there are multiple licenses).
This commit is contained in:
parent
f2c3fc5191
commit
749dd97a54
|
@ -50,31 +50,55 @@ MetaInfo DrvInfo::queryMetaInfo(EvalState & state) const
|
||||||
Expr e = evalExpr(state, i->value);
|
Expr e = evalExpr(state, i->value);
|
||||||
string s;
|
string s;
|
||||||
PathSet context;
|
PathSet context;
|
||||||
if (matchStr(e, s, context))
|
MetaValue value;
|
||||||
meta[aterm2String(i->key)] = s;
|
int n;
|
||||||
/* For future compatibility, ignore attribute values that are
|
ATermList es;
|
||||||
not strings. */
|
if (matchStr(e, s, context)) {
|
||||||
|
value.type = MetaValue::tpString;
|
||||||
|
value.stringValue = s;
|
||||||
|
meta[aterm2String(i->key)] = value;
|
||||||
|
} else if (matchInt(e, n)) {
|
||||||
|
value.type = MetaValue::tpInt;
|
||||||
|
value.intValue = n;
|
||||||
|
meta[aterm2String(i->key)] = value;
|
||||||
|
} else if (matchList(e, es)) {
|
||||||
|
value.type = MetaValue::tpStrings;
|
||||||
|
for (ATermIterator j(es); j; ++j)
|
||||||
|
value.stringValues.push_back(evalStringNoCtx(state, *j));
|
||||||
|
meta[aterm2String(i->key)] = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return meta;
|
return meta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
string DrvInfo::queryMetaInfo(EvalState & state, const string & name) const
|
MetaValue DrvInfo::queryMetaInfo(EvalState & state, const string & name) const
|
||||||
{
|
{
|
||||||
/* !!! evaluates all meta attributes => inefficient */
|
/* !!! evaluates all meta attributes => inefficient */
|
||||||
MetaInfo meta = queryMetaInfo(state);
|
return queryMetaInfo(state)[name];
|
||||||
MetaInfo::iterator i = meta.find(name);
|
|
||||||
return i == meta.end() ? "" : i->second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DrvInfo::setMetaInfo(const MetaInfo & meta)
|
void DrvInfo::setMetaInfo(const MetaInfo & meta)
|
||||||
{
|
{
|
||||||
ATermMap metaAttrs;
|
ATermMap metaAttrs;
|
||||||
for (MetaInfo::const_iterator i = meta.begin(); i != meta.end(); ++i)
|
foreach (MetaInfo::const_iterator, i, meta) {
|
||||||
metaAttrs.set(toATerm(i->first),
|
Expr e;
|
||||||
makeAttrRHS(makeStr(i->second), makeNoPos()));
|
switch (i->second.type) {
|
||||||
|
case MetaValue::tpInt: e = makeInt(i->second.intValue); break;
|
||||||
|
case MetaValue::tpString: e = makeStr(i->second.stringValue); break;
|
||||||
|
case MetaValue::tpStrings: {
|
||||||
|
ATermList es = ATempty;
|
||||||
|
foreach (Strings::const_iterator, j, i->second.stringValues)
|
||||||
|
es = ATinsert(es, makeStr(*j));
|
||||||
|
e = makeList(ATreverse(es));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: abort();
|
||||||
|
}
|
||||||
|
metaAttrs.set(toATerm(i->first), makeAttrRHS(e, makeNoPos()));
|
||||||
|
}
|
||||||
attrs->set(toATerm("meta"), makeAttrs(metaAttrs));
|
attrs->set(toATerm("meta"), makeAttrs(metaAttrs));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,16 @@
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
|
||||||
typedef std::map<string, string> MetaInfo;
|
struct MetaValue
|
||||||
|
{
|
||||||
|
enum { tpNone, tpString, tpStrings, tpInt } type;
|
||||||
|
string stringValue;
|
||||||
|
Strings stringValues;
|
||||||
|
int intValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef std::map<string, MetaValue> MetaInfo;
|
||||||
|
|
||||||
|
|
||||||
struct DrvInfo
|
struct DrvInfo
|
||||||
|
@ -34,7 +43,7 @@ public:
|
||||||
string queryDrvPath(EvalState & state) const;
|
string queryDrvPath(EvalState & state) const;
|
||||||
string queryOutPath(EvalState & state) const;
|
string queryOutPath(EvalState & state) const;
|
||||||
MetaInfo queryMetaInfo(EvalState & state) const;
|
MetaInfo queryMetaInfo(EvalState & state) const;
|
||||||
string 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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -251,15 +251,14 @@ static string optimisticLockProfile(const Path & profile)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool createUserEnv(EvalState & state, const DrvInfos & elems,
|
static bool createUserEnv(EvalState & state, DrvInfos & elems,
|
||||||
const Path & profile, bool keepDerivations,
|
const Path & profile, bool keepDerivations,
|
||||||
const string & lockToken)
|
const string & lockToken)
|
||||||
{
|
{
|
||||||
/* 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;
|
||||||
for (DrvInfos::const_iterator i = elems.begin();
|
foreach (DrvInfos::const_iterator, i, elems)
|
||||||
i != elems.end(); ++i)
|
|
||||||
/* Call to `isDerivation' is for compatibility with Nix <= 0.7
|
/* Call to `isDerivation' is for compatibility with Nix <= 0.7
|
||||||
user environments. */
|
user environments. */
|
||||||
if (i->queryDrvPath(state) != "" &&
|
if (i->queryDrvPath(state) != "" &&
|
||||||
|
@ -277,19 +276,16 @@ static bool createUserEnv(EvalState & state, const DrvInfos & elems,
|
||||||
PathSet references;
|
PathSet references;
|
||||||
ATermList manifest = ATempty;
|
ATermList manifest = ATempty;
|
||||||
ATermList inputs = ATempty;
|
ATermList inputs = ATempty;
|
||||||
for (DrvInfos::const_iterator i = elems.begin();
|
foreach (DrvInfos::iterator, i, elems) {
|
||||||
i != elems.end(); ++i)
|
|
||||||
{
|
|
||||||
/* Create a pseudo-derivation containing the name, system,
|
/* Create a pseudo-derivation containing the name, system,
|
||||||
output path, and optionally the derivation path, as well as
|
output path, and optionally the derivation path, as well as
|
||||||
the meta attributes. */
|
the meta attributes. */
|
||||||
Path drvPath = keepDerivations ? i->queryDrvPath(state) : "";
|
Path drvPath = keepDerivations ? i->queryDrvPath(state) : "";
|
||||||
|
|
||||||
|
/* Round trip to get rid of "bad" meta values (like
|
||||||
|
functions). */
|
||||||
MetaInfo meta = i->queryMetaInfo(state);
|
MetaInfo meta = i->queryMetaInfo(state);
|
||||||
ATermList metaList = ATempty;
|
i->setMetaInfo(meta);
|
||||||
foreach (MetaInfo::iterator, j, meta)
|
|
||||||
metaList = ATinsert(metaList,
|
|
||||||
makeBind(toATerm(j->first), makeStr(j->second), makeNoPos()));
|
|
||||||
|
|
||||||
ATermList as = ATmakeList5(
|
ATermList as = ATmakeList5(
|
||||||
makeBind(toATerm("type"),
|
makeBind(toATerm("type"),
|
||||||
|
@ -300,7 +296,8 @@ static bool createUserEnv(EvalState & state, const DrvInfos & elems,
|
||||||
makeStr(i->system), makeNoPos()),
|
makeStr(i->system), makeNoPos()),
|
||||||
makeBind(toATerm("outPath"),
|
makeBind(toATerm("outPath"),
|
||||||
makeStr(i->queryOutPath(state)), makeNoPos()),
|
makeStr(i->queryOutPath(state)), makeNoPos()),
|
||||||
makeBind(toATerm("meta"), makeAttrs(metaList), makeNoPos()));
|
makeBind(toATerm("meta"),
|
||||||
|
i->attrs->get(toATerm("meta")), makeNoPos()));
|
||||||
|
|
||||||
if (drvPath != "") as = ATinsert(as,
|
if (drvPath != "") as = ATinsert(as,
|
||||||
makeBind(toATerm("drvPath"),
|
makeBind(toATerm("drvPath"),
|
||||||
|
@ -361,13 +358,23 @@ static bool createUserEnv(EvalState & state, const DrvInfos & elems,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int getPriority(EvalState & state, const DrvInfo & drv)
|
||||||
|
{
|
||||||
|
MetaValue value = drv.queryMetaInfo(state, "priority");
|
||||||
|
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,
|
||||||
const DrvInfo & drv1, const DrvInfo & drv2)
|
const DrvInfo & drv1, const DrvInfo & drv2)
|
||||||
{
|
{
|
||||||
int prio1, prio2;
|
return getPriority(state, drv2) - getPriority(state, drv1);
|
||||||
if (!string2Int(drv1.queryMetaInfo(state, "priority"), prio1)) prio1 = 0;
|
|
||||||
if (!string2Int(drv2.queryMetaInfo(state, "priority"), prio2)) prio2 = 0;
|
|
||||||
return prio2 - prio1; /* higher number = lower priority, so negate */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -594,6 +601,13 @@ static void printMissing(EvalState & state, const DrvInfos & elems)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool keep(MetaInfo & meta)
|
||||||
|
{
|
||||||
|
MetaValue value = meta["keep"];
|
||||||
|
return value.type == MetaValue::tpString && value.stringValue == "true";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void installDerivations(Globals & globals,
|
static void installDerivations(Globals & globals,
|
||||||
const Strings & args, const Path & profile)
|
const Strings & args, const Path & profile)
|
||||||
{
|
{
|
||||||
|
@ -628,7 +642,7 @@ static void installDerivations(Globals & globals,
|
||||||
MetaInfo meta = i->queryMetaInfo(globals.state);
|
MetaInfo meta = i->queryMetaInfo(globals.state);
|
||||||
if (!globals.preserveInstalled &&
|
if (!globals.preserveInstalled &&
|
||||||
newNames.find(drvName.name) != newNames.end() &&
|
newNames.find(drvName.name) != newNames.end() &&
|
||||||
meta["keep"] != "true")
|
!keep(meta))
|
||||||
printMsg(lvlInfo,
|
printMsg(lvlInfo,
|
||||||
format("replacing old `%1%'") % i->name);
|
format("replacing old `%1%'") % i->name);
|
||||||
else
|
else
|
||||||
|
@ -691,7 +705,7 @@ static void upgradeDerivations(Globals & globals,
|
||||||
DrvName drvName(i->name);
|
DrvName drvName(i->name);
|
||||||
|
|
||||||
MetaInfo meta = i->queryMetaInfo(globals.state);
|
MetaInfo meta = i->queryMetaInfo(globals.state);
|
||||||
if (meta["keep"] == "true") {
|
if (keep(meta)) {
|
||||||
newElems.push_back(*i);
|
newElems.push_back(*i);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -709,9 +723,9 @@ static void upgradeDerivations(Globals & globals,
|
||||||
if (newName.name == drvName.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 (d == 0) d = compareVersions(drvName.version, newName.version);
|
||||||
if (upgradeType == utLt && d < 0 ||
|
if ((upgradeType == utLt && d < 0) ||
|
||||||
upgradeType == utLeq && d <= 0 ||
|
(upgradeType == utLeq && d <= 0) ||
|
||||||
upgradeType == utEq && d == 0 ||
|
(upgradeType == utEq && d == 0) ||
|
||||||
upgradeType == utAlways)
|
upgradeType == utAlways)
|
||||||
{
|
{
|
||||||
int d2 = -1;
|
int d2 = -1;
|
||||||
|
@ -770,7 +784,10 @@ static void setMetaFlag(EvalState & state, DrvInfo & drv,
|
||||||
const string & name, const string & value)
|
const string & name, const string & value)
|
||||||
{
|
{
|
||||||
MetaInfo meta = drv.queryMetaInfo(state);
|
MetaInfo meta = drv.queryMetaInfo(state);
|
||||||
meta[name] = value;
|
MetaValue v;
|
||||||
|
v.type = MetaValue::tpString;
|
||||||
|
v.stringValue = value;
|
||||||
|
meta[name] = v;
|
||||||
drv.setMetaInfo(meta);
|
drv.setMetaInfo(meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1075,9 +1092,7 @@ static void opQuery(Globals & globals,
|
||||||
XMLWriter xml(true, *(xmlOutput ? &cout : &dummy));
|
XMLWriter xml(true, *(xmlOutput ? &cout : &dummy));
|
||||||
XMLOpenElement xmlRoot(xml, "items");
|
XMLOpenElement xmlRoot(xml, "items");
|
||||||
|
|
||||||
for (vector<DrvInfo>::iterator i = elems2.begin();
|
foreach (vector<DrvInfo>::iterator, i, elems2) {
|
||||||
i != elems2.end(); ++i)
|
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
/* For table output. */
|
/* For table output. */
|
||||||
|
@ -1164,7 +1179,8 @@ static void opQuery(Globals & globals,
|
||||||
|
|
||||||
if (printDescription) {
|
if (printDescription) {
|
||||||
MetaInfo meta = i->queryMetaInfo(globals.state);
|
MetaInfo meta = i->queryMetaInfo(globals.state);
|
||||||
string descr = meta["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
|
||||||
|
@ -1178,8 +1194,23 @@ static void opQuery(Globals & globals,
|
||||||
for (MetaInfo::iterator j = meta.begin(); j != meta.end(); ++j) {
|
for (MetaInfo::iterator j = meta.begin(); j != meta.end(); ++j) {
|
||||||
XMLAttrs attrs2;
|
XMLAttrs attrs2;
|
||||||
attrs2["name"] = j->first;
|
attrs2["name"] = j->first;
|
||||||
attrs2["value"] = j->second;
|
if (j->second.type == MetaValue::tpString) {
|
||||||
xml.writeEmptyElement("meta", attrs2);
|
attrs2["type"] = "string";
|
||||||
|
attrs2["value"] = j->second.stringValue;
|
||||||
|
xml.writeEmptyElement("meta", attrs2);
|
||||||
|
} else if (j->second.type == MetaValue::tpInt) {
|
||||||
|
attrs2["type"] = "int";
|
||||||
|
attrs2["value"] = (format("%1%") % j->second.intValue).str();
|
||||||
|
xml.writeEmptyElement("meta", attrs2);
|
||||||
|
} else if (j->second.type == MetaValue::tpStrings) {
|
||||||
|
attrs2["type"] = "strings";
|
||||||
|
XMLOpenElement m(xml, "meta", attrs2);
|
||||||
|
foreach (Strings::iterator, k, j->second.stringValues) {
|
||||||
|
XMLAttrs attrs3;
|
||||||
|
attrs3["value"] = *k;
|
||||||
|
xml.writeEmptyElement("string", attrs3);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1230,12 +1261,13 @@ static void switchGeneration(Globals & globals, int dstGen)
|
||||||
(dstGen >= 0 && i->number == dstGen))
|
(dstGen >= 0 && i->number == dstGen))
|
||||||
dst = *i;
|
dst = *i;
|
||||||
|
|
||||||
if (!dst)
|
if (!dst) {
|
||||||
if (dstGen == prevGen)
|
if (dstGen == prevGen)
|
||||||
throw Error(format("no generation older than the current (%1%) exists")
|
throw Error(format("no generation older than the current (%1%) exists")
|
||||||
% curGen);
|
% curGen);
|
||||||
else
|
else
|
||||||
throw Error(format("generation %1% does not exist") % dstGen);
|
throw Error(format("generation %1% does not exist") % dstGen);
|
||||||
|
}
|
||||||
|
|
||||||
printMsg(lvlInfo, format("switching from generation %1% to %2%")
|
printMsg(lvlInfo, format("switching from generation %1% to %2%")
|
||||||
% curGen % dst.number);
|
% curGen % dst.number);
|
||||||
|
|
Loading…
Reference in a new issue