2003-11-18 13:22:29 +02:00
|
|
|
#include "storeexpr.hh"
|
2003-06-16 16:33:38 +03:00
|
|
|
#include "globals.hh"
|
2003-07-07 10:43:58 +03:00
|
|
|
#include "store.hh"
|
2003-06-16 16:33:38 +03:00
|
|
|
|
2004-10-29 14:22:49 +03:00
|
|
|
#include "storeexpr-ast.hh"
|
|
|
|
#include "storeexpr-ast.cc"
|
|
|
|
|
2003-06-16 16:33:38 +03:00
|
|
|
|
2003-06-27 16:55:12 +03:00
|
|
|
Hash hashTerm(ATerm t)
|
2003-06-16 16:33:38 +03:00
|
|
|
{
|
2005-01-13 19:39:26 +02:00
|
|
|
return hashString(atPrint(t), htMD5);
|
2003-06-16 16:33:38 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-08 18:06:59 +03:00
|
|
|
Path writeTerm(ATerm t, const string & suffix)
|
2003-07-04 15:18:06 +03:00
|
|
|
{
|
2005-01-14 15:51:38 +02:00
|
|
|
char * s = ATwriteToString(t);
|
|
|
|
if (!s) throw Error("cannot print aterm");
|
|
|
|
return addTextToStore(suffix + ".store", string(s));
|
2003-07-04 15:18:06 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-08 18:06:59 +03:00
|
|
|
static void parsePaths(ATermList paths, PathSet & out)
|
2003-07-15 19:28:54 +03:00
|
|
|
{
|
2003-11-16 20:31:29 +02:00
|
|
|
for (ATermIterator i(paths); i; ++i) {
|
2004-10-29 14:22:49 +03:00
|
|
|
if (ATgetType(*i) != AT_APPL)
|
|
|
|
throw badTerm("not a path", *i);
|
|
|
|
string s = aterm2String(*i);
|
|
|
|
if (s.size() == 0 || s[0] != '/')
|
2003-11-16 20:31:29 +02:00
|
|
|
throw badTerm("not a path", *i);
|
2003-08-20 17:11:40 +03:00
|
|
|
out.insert(s);
|
2003-07-15 19:28:54 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-07 15:27:49 +03:00
|
|
|
static void checkClosure(const Closure & closure)
|
2003-07-20 22:29:38 +03:00
|
|
|
{
|
2003-10-07 15:27:49 +03:00
|
|
|
if (closure.elems.size() == 0)
|
|
|
|
throw Error("empty closure");
|
2003-07-20 22:29:38 +03:00
|
|
|
|
2003-10-08 18:06:59 +03:00
|
|
|
PathSet decl;
|
2003-10-07 15:27:49 +03:00
|
|
|
for (ClosureElems::const_iterator i = closure.elems.begin();
|
|
|
|
i != closure.elems.end(); i++)
|
2003-08-20 17:11:40 +03:00
|
|
|
decl.insert(i->first);
|
2003-07-20 22:29:38 +03:00
|
|
|
|
2003-10-08 18:06:59 +03:00
|
|
|
for (PathSet::const_iterator i = closure.roots.begin();
|
2003-10-07 15:27:49 +03:00
|
|
|
i != closure.roots.end(); i++)
|
2003-07-20 22:29:38 +03:00
|
|
|
if (decl.find(*i) == decl.end())
|
* Change the abstract syntax of slices. It used to be that ids were used as
keys to reference slice elements, e.g.,
Slice(["1ef7..."], [("/nix/store/1ef7...-foo", "1ef7", ["8c99..."]), ...])
This was wrong, since ids represent contents, not locations. Therefore we
now have:
Slice(["/nix/store/1ef7..."], [("/nix/store/1ef7...-foo", "1ef7", ["/nix/store/8c99-..."]), ...])
* Fix a bug in the computation of slice closures that could cause slice
elements to be duplicated.
2003-08-20 15:39:56 +03:00
|
|
|
throw Error(format("undefined root path `%1%'") % *i);
|
2003-07-20 22:29:38 +03:00
|
|
|
|
2003-10-07 15:27:49 +03:00
|
|
|
for (ClosureElems::const_iterator i = closure.elems.begin();
|
|
|
|
i != closure.elems.end(); i++)
|
2003-10-08 18:06:59 +03:00
|
|
|
for (PathSet::const_iterator j = i->second.refs.begin();
|
2003-08-20 17:11:40 +03:00
|
|
|
j != i->second.refs.end(); j++)
|
2003-07-20 22:29:38 +03:00
|
|
|
if (decl.find(*j) == decl.end())
|
* Change the abstract syntax of slices. It used to be that ids were used as
keys to reference slice elements, e.g.,
Slice(["1ef7..."], [("/nix/store/1ef7...-foo", "1ef7", ["8c99..."]), ...])
This was wrong, since ids represent contents, not locations. Therefore we
now have:
Slice(["/nix/store/1ef7..."], [("/nix/store/1ef7...-foo", "1ef7", ["/nix/store/8c99-..."]), ...])
* Fix a bug in the computation of slice closures that could cause slice
elements to be duplicated.
2003-08-20 15:39:56 +03:00
|
|
|
throw Error(
|
|
|
|
format("undefined path `%1%' referenced by `%2%'")
|
2003-08-20 17:11:40 +03:00
|
|
|
% *j % i->first);
|
2003-07-20 22:29:38 +03:00
|
|
|
}
|
2003-07-16 23:33:29 +03:00
|
|
|
|
|
|
|
|
2003-10-07 15:27:49 +03:00
|
|
|
/* Parse a closure. */
|
|
|
|
static bool parseClosure(ATerm t, Closure & closure)
|
2003-07-15 19:28:54 +03:00
|
|
|
{
|
|
|
|
ATermList roots, elems;
|
2003-11-16 19:46:31 +02:00
|
|
|
|
2004-10-29 14:22:49 +03:00
|
|
|
if (!matchClosure(t, roots, elems))
|
2003-07-20 22:29:38 +03:00
|
|
|
return false;
|
2003-07-15 19:28:54 +03:00
|
|
|
|
2003-10-07 15:27:49 +03:00
|
|
|
parsePaths(roots, closure.roots);
|
2003-07-15 19:28:54 +03:00
|
|
|
|
2003-11-16 20:31:29 +02:00
|
|
|
for (ATermIterator i(elems); i; ++i) {
|
2004-10-29 14:22:49 +03:00
|
|
|
ATerm path;
|
2003-07-15 19:28:54 +03:00
|
|
|
ATermList refs;
|
2004-10-29 14:22:49 +03:00
|
|
|
if (!matchClosureElem(*i, path, refs))
|
2003-11-16 20:31:29 +02:00
|
|
|
throw badTerm("not a closure element", *i);
|
2003-10-07 15:27:49 +03:00
|
|
|
ClosureElem elem;
|
* Change the abstract syntax of slices. It used to be that ids were used as
keys to reference slice elements, e.g.,
Slice(["1ef7..."], [("/nix/store/1ef7...-foo", "1ef7", ["8c99..."]), ...])
This was wrong, since ids represent contents, not locations. Therefore we
now have:
Slice(["/nix/store/1ef7..."], [("/nix/store/1ef7...-foo", "1ef7", ["/nix/store/8c99-..."]), ...])
* Fix a bug in the computation of slice closures that could cause slice
elements to be duplicated.
2003-08-20 15:39:56 +03:00
|
|
|
parsePaths(refs, elem.refs);
|
2004-10-29 14:22:49 +03:00
|
|
|
closure.elems[aterm2String(path)] = elem;
|
2003-07-15 19:28:54 +03:00
|
|
|
}
|
|
|
|
|
2003-10-07 15:27:49 +03:00
|
|
|
checkClosure(closure);
|
2003-07-20 22:29:38 +03:00
|
|
|
return true;
|
2003-07-15 19:28:54 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-07 15:27:49 +03:00
|
|
|
static bool parseDerivation(ATerm t, Derivation & derivation)
|
2003-07-16 00:24:05 +03:00
|
|
|
{
|
2003-08-15 15:32:37 +03:00
|
|
|
ATermList outs, ins, args, bnds;
|
2004-10-29 14:22:49 +03:00
|
|
|
ATerm builder, platform;
|
2003-11-16 19:46:31 +02:00
|
|
|
|
2004-10-29 14:22:49 +03:00
|
|
|
if (!matchDerive(t, outs, ins, platform, builder, args, bnds))
|
2003-11-16 19:46:31 +02:00
|
|
|
return false;
|
2003-07-15 19:28:54 +03:00
|
|
|
|
2003-10-08 18:06:59 +03:00
|
|
|
parsePaths(outs, derivation.outputs);
|
|
|
|
parsePaths(ins, derivation.inputs);
|
2003-07-15 19:28:54 +03:00
|
|
|
|
2004-10-29 14:22:49 +03:00
|
|
|
derivation.builder = aterm2String(builder);
|
|
|
|
derivation.platform = aterm2String(platform);
|
2003-07-20 22:29:38 +03:00
|
|
|
|
2003-11-16 20:31:29 +02:00
|
|
|
for (ATermIterator i(args); i; ++i) {
|
2004-10-29 14:22:49 +03:00
|
|
|
if (ATgetType(*i) != AT_APPL)
|
2003-11-16 20:31:29 +02:00
|
|
|
throw badTerm("string expected", *i);
|
2004-10-29 14:22:49 +03:00
|
|
|
derivation.args.push_back(aterm2String(*i));
|
2003-08-15 15:32:37 +03:00
|
|
|
}
|
|
|
|
|
2003-11-16 20:31:29 +02:00
|
|
|
for (ATermIterator i(bnds); i; ++i) {
|
2004-10-29 14:22:49 +03:00
|
|
|
ATerm s1, s2;
|
|
|
|
if (!matchEnvBinding(*i, s1, s2))
|
2003-11-16 20:31:29 +02:00
|
|
|
throw badTerm("tuple of strings expected", *i);
|
2004-10-29 14:22:49 +03:00
|
|
|
derivation.env[aterm2String(s1)] = aterm2String(s2);
|
2003-07-15 19:28:54 +03:00
|
|
|
}
|
|
|
|
|
2003-07-20 22:29:38 +03:00
|
|
|
return true;
|
2003-07-15 19:28:54 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-11-18 13:22:29 +02:00
|
|
|
StoreExpr parseStoreExpr(ATerm t)
|
2003-07-16 14:05:59 +03:00
|
|
|
{
|
2003-11-18 13:22:29 +02:00
|
|
|
StoreExpr ne;
|
2003-10-07 15:27:49 +03:00
|
|
|
if (parseClosure(t, ne.closure))
|
2003-11-18 13:22:29 +02:00
|
|
|
ne.type = StoreExpr::neClosure;
|
2003-10-07 15:27:49 +03:00
|
|
|
else if (parseDerivation(t, ne.derivation))
|
2003-11-18 13:22:29 +02:00
|
|
|
ne.type = StoreExpr::neDerivation;
|
|
|
|
else throw badTerm("not a store expression", t);
|
2003-10-07 15:27:49 +03:00
|
|
|
return ne;
|
2003-07-16 14:05:59 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-08 18:06:59 +03:00
|
|
|
static ATermList unparsePaths(const PathSet & paths)
|
2003-07-16 00:24:05 +03:00
|
|
|
{
|
2003-07-20 22:29:38 +03:00
|
|
|
ATermList l = ATempty;
|
2003-10-08 18:06:59 +03:00
|
|
|
for (PathSet::const_iterator i = paths.begin();
|
* Change the abstract syntax of slices. It used to be that ids were used as
keys to reference slice elements, e.g.,
Slice(["1ef7..."], [("/nix/store/1ef7...-foo", "1ef7", ["8c99..."]), ...])
This was wrong, since ids represent contents, not locations. Therefore we
now have:
Slice(["/nix/store/1ef7..."], [("/nix/store/1ef7...-foo", "1ef7", ["/nix/store/8c99-..."]), ...])
* Fix a bug in the computation of slice closures that could cause slice
elements to be duplicated.
2003-08-20 15:39:56 +03:00
|
|
|
i != paths.end(); i++)
|
2004-11-03 20:12:03 +02:00
|
|
|
l = ATinsert(l, toATerm(*i));
|
2003-07-20 22:29:38 +03:00
|
|
|
return ATreverse(l);
|
2003-07-16 00:24:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-07 15:27:49 +03:00
|
|
|
static ATerm unparseClosure(const Closure & closure)
|
2003-07-15 19:28:54 +03:00
|
|
|
{
|
2003-10-07 15:27:49 +03:00
|
|
|
ATermList roots = unparsePaths(closure.roots);
|
2003-07-20 22:29:38 +03:00
|
|
|
|
|
|
|
ATermList elems = ATempty;
|
2003-10-07 15:27:49 +03:00
|
|
|
for (ClosureElems::const_iterator i = closure.elems.begin();
|
|
|
|
i != closure.elems.end(); i++)
|
2003-07-20 22:29:38 +03:00
|
|
|
elems = ATinsert(elems,
|
2004-10-29 14:22:49 +03:00
|
|
|
makeClosureElem(
|
2004-11-03 20:12:03 +02:00
|
|
|
toATerm(i->first),
|
2003-08-20 17:11:40 +03:00
|
|
|
unparsePaths(i->second.refs)));
|
2003-07-15 19:28:54 +03:00
|
|
|
|
2004-10-29 14:22:49 +03:00
|
|
|
return makeClosure(roots, elems);
|
2003-07-15 19:28:54 +03:00
|
|
|
}
|
2003-07-16 01:28:27 +03:00
|
|
|
|
|
|
|
|
2003-10-07 15:27:49 +03:00
|
|
|
static ATerm unparseDerivation(const Derivation & derivation)
|
2003-07-16 01:28:27 +03:00
|
|
|
{
|
2003-08-15 15:32:37 +03:00
|
|
|
ATermList args = ATempty;
|
2003-10-07 15:27:49 +03:00
|
|
|
for (Strings::const_iterator i = derivation.args.begin();
|
|
|
|
i != derivation.args.end(); i++)
|
2004-11-03 20:12:03 +02:00
|
|
|
args = ATinsert(args, toATerm(*i));
|
2003-08-15 15:32:37 +03:00
|
|
|
|
2003-07-20 22:29:38 +03:00
|
|
|
ATermList env = ATempty;
|
2003-10-07 15:27:49 +03:00
|
|
|
for (StringPairs::const_iterator i = derivation.env.begin();
|
|
|
|
i != derivation.env.end(); i++)
|
2003-07-20 22:29:38 +03:00
|
|
|
env = ATinsert(env,
|
2004-10-29 14:22:49 +03:00
|
|
|
makeEnvBinding(
|
2004-11-03 20:12:03 +02:00
|
|
|
toATerm(i->first),
|
|
|
|
toATerm(i->second)));
|
2003-07-16 01:28:27 +03:00
|
|
|
|
2004-10-29 14:22:49 +03:00
|
|
|
return makeDerive(
|
2003-10-08 18:06:59 +03:00
|
|
|
unparsePaths(derivation.outputs),
|
|
|
|
unparsePaths(derivation.inputs),
|
2004-11-03 20:12:03 +02:00
|
|
|
toATerm(derivation.platform),
|
|
|
|
toATerm(derivation.builder),
|
2003-08-15 15:32:37 +03:00
|
|
|
ATreverse(args),
|
2003-07-20 22:29:38 +03:00
|
|
|
ATreverse(env));
|
2003-07-16 01:28:27 +03:00
|
|
|
}
|
2003-07-16 14:05:59 +03:00
|
|
|
|
|
|
|
|
2003-11-18 13:22:29 +02:00
|
|
|
ATerm unparseStoreExpr(const StoreExpr & ne)
|
2003-07-16 14:05:59 +03:00
|
|
|
{
|
2003-11-18 13:22:29 +02:00
|
|
|
if (ne.type == StoreExpr::neClosure)
|
2003-10-07 15:27:49 +03:00
|
|
|
return unparseClosure(ne.closure);
|
2003-11-18 13:22:29 +02:00
|
|
|
else if (ne.type == StoreExpr::neDerivation)
|
2003-10-07 15:27:49 +03:00
|
|
|
return unparseDerivation(ne.derivation);
|
2003-07-20 22:29:38 +03:00
|
|
|
else abort();
|
2003-07-16 14:05:59 +03:00
|
|
|
}
|