* Synchronise terminology with the ICSE paper (e.g., slice -> closure,

fstate -> Nix expression).
* Fix src/test.cc.
This commit is contained in:
Eelco Dolstra 2003-10-07 12:27:49 +00:00
parent 563afb7fcc
commit 5d4171f7fb
15 changed files with 254 additions and 268 deletions

View File

@ -10,7 +10,7 @@ foreach my $id (@ARGV) {
die unless $id =~ /^([0-9a-z]{32})$/;
# Get all paths referenced by the normalisation of the given
# fstate expression.
# Nix expression.
system "nix --install $id";
if ($?) { die "`nix --install' failed"; }
@ -52,7 +52,7 @@ foreach my $id (@ARGV) {
# Construct a Fix expression that creates a Nix archive.
my $fixexpr =
"App(IncludeFix(\"nar/nar.fix\"), " .
"[ (\"path\", Slice([\"$path\"], [(\"$path\", \"$pathid\", [])]))" .
"[ (\"path\", Closure([\"$path\"], [(\"$path\", \"$pathid\", [])]))" .
"])";
print FIX "," unless ($first);

View File

@ -23,7 +23,7 @@ test_LDADD = libshared.a libnix.a $(LDADD)
noinst_LIBRARIES = libnix.a libshared.a
libnix_a_SOURCES = util.cc hash.cc archive.cc md5.c \
store.cc fstate.cc normalise.cc exec.cc \
store.cc expr.cc normalise.cc exec.cc \
globals.cc db.cc references.cc pathlocks.cc
libshared_a_SOURCES = shared.cc

View File

@ -51,9 +51,9 @@ string pathLabel(const FSId & id, const string & path)
}
void printSlice(const FSId & id, const FState & fs)
void printClosure(const FSId & id, const NixExpr & fs)
{
Strings workList(fs.slice.roots.begin(), fs.slice.roots.end());
Strings workList(fs.closure.roots.begin(), fs.closure.roots.end());
StringSet doneSet;
for (Strings::iterator i = workList.begin(); i != workList.end(); i++) {
@ -67,9 +67,9 @@ void printSlice(const FSId & id, const FState & fs)
if (doneSet.find(path) == doneSet.end()) {
doneSet.insert(path);
SliceElems::const_iterator elem = fs.slice.elems.find(path);
if (elem == fs.slice.elems.end())
throw Error(format("bad slice, missing path `%1%'") % path);
ClosureElems::const_iterator elem = fs.closure.elems.find(path);
if (elem == fs.closure.elems.end())
throw Error(format("bad closure, missing path `%1%'") % path);
for (StringSet::const_iterator i = elem->second.refs.begin();
i != elem->second.refs.end(); i++)
@ -99,29 +99,29 @@ void printDotGraph(const FSIds & roots)
if (doneSet.find(id) == doneSet.end()) {
doneSet.insert(id);
FState fs = parseFState(termFromId(id));
NixExpr ne = parseNixExpr(termFromId(id));
string label, colour;
if (fs.type == FState::fsDerive) {
for (FSIdSet::iterator i = fs.derive.inputs.begin();
i != fs.derive.inputs.end(); i++)
if (ne.type == NixExpr::neDerivation) {
for (FSIdSet::iterator i = ne.derivation.inputs.begin();
i != ne.derivation.inputs.end(); i++)
{
workList.push_back(*i);
cout << makeEdge(*i, id);
}
label = "derive";
label = "derivation";
colour = "#00ff00";
for (StringPairs::iterator i = fs.derive.env.begin();
i != fs.derive.env.end(); i++)
for (StringPairs::iterator i = ne.derivation.env.begin();
i != ne.derivation.env.end(); i++)
if (i->first == "name") label = i->second;
}
else if (fs.type == FState::fsSlice) {
label = "<slice>";
else if (ne.type == NixExpr::neClosure) {
label = "<closure>";
colour = "#00ffff";
printSlice(id, fs);
printClosure(id, ne);
}
else abort();

View File

@ -1,7 +1,7 @@
#ifndef __DOTGRAPH_H
#define __DOTGRAPH_H
#include "fstate.hh"
#include "expr.hh"
void printDotGraph(const FSIds & roots);

View File

@ -1,4 +1,4 @@
#include "fstate.hh"
#include "expr.hh"
#include "globals.hh"
#include "store.hh"
@ -65,23 +65,23 @@ static void parsePaths(ATermList paths, StringSet & out)
}
static void checkSlice(const Slice & slice)
static void checkClosure(const Closure & closure)
{
if (slice.elems.size() == 0)
throw Error("empty slice");
if (closure.elems.size() == 0)
throw Error("empty closure");
StringSet decl;
for (SliceElems::const_iterator i = slice.elems.begin();
i != slice.elems.end(); i++)
for (ClosureElems::const_iterator i = closure.elems.begin();
i != closure.elems.end(); i++)
decl.insert(i->first);
for (StringSet::const_iterator i = slice.roots.begin();
i != slice.roots.end(); i++)
for (StringSet::const_iterator i = closure.roots.begin();
i != closure.roots.end(); i++)
if (decl.find(*i) == decl.end())
throw Error(format("undefined root path `%1%'") % *i);
for (SliceElems::const_iterator i = slice.elems.begin();
i != slice.elems.end(); i++)
for (ClosureElems::const_iterator i = closure.elems.begin();
i != closure.elems.end(); i++)
for (StringSet::const_iterator j = i->second.refs.begin();
j != i->second.refs.end(); j++)
if (decl.find(*j) == decl.end())
@ -91,35 +91,35 @@ static void checkSlice(const Slice & slice)
}
/* Parse a slice. */
static bool parseSlice(ATerm t, Slice & slice)
/* Parse a closure. */
static bool parseClosure(ATerm t, Closure & closure)
{
ATermList roots, elems;
if (!ATmatch(t, "Slice([<list>], [<list>])", &roots, &elems))
if (!ATmatch(t, "Closure([<list>], [<list>])", &roots, &elems))
return false;
parsePaths(roots, slice.roots);
parsePaths(roots, closure.roots);
while (!ATisEmpty(elems)) {
char * s1, * s2;
ATermList refs;
ATerm t = ATgetFirst(elems);
if (!ATmatch(t, "(<str>, <str>, [<list>])", &s1, &s2, &refs))
throw badTerm("not a slice element", t);
SliceElem elem;
throw badTerm("not a closure element", t);
ClosureElem elem;
elem.id = parseHash(s2);
parsePaths(refs, elem.refs);
slice.elems[s1] = elem;
closure.elems[s1] = elem;
elems = ATgetNext(elems);
}
checkSlice(slice);
checkClosure(closure);
return true;
}
static bool parseDerive(ATerm t, Derive & derive)
static bool parseDerivation(ATerm t, Derivation & derivation)
{
ATermList outs, ins, args, bnds;
char * builder;
@ -139,8 +139,8 @@ static bool parseDerive(ATerm t, Derive & derive)
char * s1, * s2;
ATerm t = ATgetFirst(outs);
if (!ATmatch(t, "(<str>, <str>)", &s1, &s2))
throw badTerm("not a derive output", t);
derive.outputs[s1] = parseHash(s2);
throw badTerm("not a derivation output", t);
derivation.outputs[s1] = parseHash(s2);
outs = ATgetNext(outs);
}
@ -149,19 +149,19 @@ static bool parseDerive(ATerm t, Derive & derive)
ATerm t = ATgetFirst(ins);
if (!ATmatch(t, "<str>", &s))
throw badTerm("not an id", t);
derive.inputs.insert(parseHash(s));
derivation.inputs.insert(parseHash(s));
ins = ATgetNext(ins);
}
derive.builder = builder;
derive.platform = platform;
derivation.builder = builder;
derivation.platform = platform;
while (!ATisEmpty(args)) {
char * s;
ATerm arg = ATgetFirst(args);
if (!ATmatch(arg, "<str>", &s))
throw badTerm("string expected", arg);
derive.args.push_back(s);
derivation.args.push_back(s);
args = ATgetNext(args);
}
@ -170,7 +170,7 @@ static bool parseDerive(ATerm t, Derive & derive)
ATerm bnd = ATgetFirst(bnds);
if (!ATmatch(bnd, "(<str>, <str>)", &s1, &s2))
throw badTerm("tuple of strings expected", bnd);
derive.env[s1] = s2;
derivation.env[s1] = s2;
bnds = ATgetNext(bnds);
}
@ -178,15 +178,15 @@ static bool parseDerive(ATerm t, Derive & derive)
}
FState parseFState(ATerm t)
NixExpr parseNixExpr(ATerm t)
{
FState fs;
if (parseSlice(t, fs.slice))
fs.type = FState::fsSlice;
else if (parseDerive(t, fs.derive))
fs.type = FState::fsDerive;
else throw badTerm("not an fstate-expression", t);
return fs;
NixExpr ne;
if (parseClosure(t, ne.closure))
ne.type = NixExpr::neClosure;
else if (parseDerivation(t, ne.derivation))
ne.type = NixExpr::neDerivation;
else throw badTerm("not a Nix expression", t);
return ne;
}
@ -200,45 +200,45 @@ static ATermList unparsePaths(const StringSet & paths)
}
static ATerm unparseSlice(const Slice & slice)
static ATerm unparseClosure(const Closure & closure)
{
ATermList roots = unparsePaths(slice.roots);
ATermList roots = unparsePaths(closure.roots);
ATermList elems = ATempty;
for (SliceElems::const_iterator i = slice.elems.begin();
i != slice.elems.end(); i++)
for (ClosureElems::const_iterator i = closure.elems.begin();
i != closure.elems.end(); i++)
elems = ATinsert(elems,
ATmake("(<str>, <str>, <term>)",
i->first.c_str(),
((string) i->second.id).c_str(),
unparsePaths(i->second.refs)));
return ATmake("Slice(<term>, <term>)", roots, elems);
return ATmake("Closure(<term>, <term>)", roots, elems);
}
static ATerm unparseDerive(const Derive & derive)
static ATerm unparseDerivation(const Derivation & derivation)
{
ATermList outs = ATempty;
for (DeriveOutputs::const_iterator i = derive.outputs.begin();
i != derive.outputs.end(); i++)
for (DerivationOutputs::const_iterator i = derivation.outputs.begin();
i != derivation.outputs.end(); i++)
outs = ATinsert(outs,
ATmake("(<str>, <str>)",
i->first.c_str(), ((string) i->second).c_str()));
ATermList ins = ATempty;
for (FSIdSet::const_iterator i = derive.inputs.begin();
i != derive.inputs.end(); i++)
for (FSIdSet::const_iterator i = derivation.inputs.begin();
i != derivation.inputs.end(); i++)
ins = ATinsert(ins, ATmake("<str>", ((string) *i).c_str()));
ATermList args = ATempty;
for (Strings::const_iterator i = derive.args.begin();
i != derive.args.end(); i++)
for (Strings::const_iterator i = derivation.args.begin();
i != derivation.args.end(); i++)
args = ATinsert(args, ATmake("<str>", i->c_str()));
ATermList env = ATempty;
for (StringPairs::const_iterator i = derive.env.begin();
i != derive.env.end(); i++)
for (StringPairs::const_iterator i = derivation.env.begin();
i != derivation.env.end(); i++)
env = ATinsert(env,
ATmake("(<str>, <str>)",
i->first.c_str(), i->second.c_str()));
@ -246,18 +246,18 @@ static ATerm unparseDerive(const Derive & derive)
return ATmake("Derive(<term>, <term>, <str>, <str>, <term>, <term>)",
ATreverse(outs),
ATreverse(ins),
derive.platform.c_str(),
derive.builder.c_str(),
derivation.platform.c_str(),
derivation.builder.c_str(),
ATreverse(args),
ATreverse(env));
}
ATerm unparseFState(const FState & fs)
ATerm unparseNixExpr(const NixExpr & ne)
{
if (fs.type == FState::fsSlice)
return unparseSlice(fs.slice);
else if (fs.type == FState::fsDerive)
return unparseDerive(fs.derive);
if (ne.type == NixExpr::neClosure)
return unparseClosure(ne.closure);
else if (ne.type == NixExpr::neDerivation)
return unparseDerivation(ne.derivation);
else abort();
}

View File

@ -8,30 +8,30 @@ extern "C" {
#include "store.hh"
/* Abstract syntax of fstate-expressions. */
/* Abstract syntax of Nix expressions. */
typedef list<FSId> FSIds;
struct SliceElem
struct ClosureElem
{
FSId id;
StringSet refs;
};
typedef map<string, SliceElem> SliceElems;
typedef map<string, ClosureElem> ClosureElems;
struct Slice
struct Closure
{
StringSet roots;
SliceElems elems;
ClosureElems elems;
};
typedef map<string, FSId> DeriveOutputs;
typedef map<string, FSId> DerivationOutputs;
typedef map<string, string> StringPairs;
struct Derive
struct Derivation
{
DeriveOutputs outputs;
DerivationOutputs outputs;
FSIdSet inputs;
string platform;
string builder;
@ -39,11 +39,11 @@ struct Derive
StringPairs env;
};
struct FState
struct NixExpr
{
enum { fsSlice, fsDerive } type;
Slice slice;
Derive derive;
enum { neClosure, neDerivation } type;
Closure closure;
Derivation derivation;
};
@ -63,11 +63,11 @@ ATerm termFromId(const FSId & id);
/* Write an aterm to the Nix store directory, and return its hash. */
FSId writeTerm(ATerm t, const string & suffix, FSId id = FSId());
/* Parse an fstate-expression. */
FState parseFState(ATerm t);
/* Parse a Nix expression. */
NixExpr parseNixExpr(ATerm t);
/* Parse an fstate-expression. */
ATerm unparseFState(const FState & fs);
/* Parse a Nix expression. */
ATerm unparseNixExpr(const NixExpr & ne);
#endif /* !__FSTATE_H */

View File

@ -121,47 +121,47 @@ static Expr substExprMany(ATermList formals, ATermList args, Expr body)
}
static Strings fstatePathsCached(EvalState & state, const FSId & id)
static Strings nixExprPathsCached(EvalState & state, const FSId & id)
{
PkgPaths::iterator i = state.pkgPaths.find(id);
if (i != state.pkgPaths.end())
return i->second;
else {
Strings paths = fstatePaths(id);
Strings paths = nixExprPaths(id);
state.pkgPaths[id] = paths;
return paths;
}
}
static Hash hashPackage(EvalState & state, FState fs)
static Hash hashPackage(EvalState & state, NixExpr ne)
{
if (fs.type == FState::fsDerive) {
if (ne.type == NixExpr::neDerivation) {
FSIdSet inputs2;
for (FSIdSet::iterator i = fs.derive.inputs.begin();
i != fs.derive.inputs.end(); i++)
for (FSIdSet::iterator i = ne.derivation.inputs.begin();
i != ne.derivation.inputs.end(); i++)
{
PkgHashes::iterator j = state.pkgHashes.find(*i);
if (j == state.pkgHashes.end())
throw Error(format("unknown package id %1%") % (string) *i);
inputs2.insert(j->second);
}
fs.derive.inputs = inputs2;
ne.derivation.inputs = inputs2;
}
return hashTerm(unparseFState(fs));
return hashTerm(unparseNixExpr(ne));
}
static string processBinding(EvalState & state, Expr e, FState & fs)
static string processBinding(EvalState & state, Expr e, NixExpr & ne)
{
char * s1;
if (ATmatch(e, "FSId(<str>)", &s1)) {
FSId id = parseHash(s1);
Strings paths = fstatePathsCached(state, id);
Strings paths = nixExprPathsCached(state, id);
if (paths.size() != 1) abort();
string path = *(paths.begin());
fs.derive.inputs.insert(id);
ne.derivation.inputs.insert(id);
return path;
}
@ -178,7 +178,7 @@ static string processBinding(EvalState & state, Expr e, FState & fs)
bool first = true;
while (!ATisEmpty(l)) {
if (!first) s = s + " "; else first = false;
s += processBinding(state, evalExpr(state, ATgetFirst(l)), fs);
s += processBinding(state, evalExpr(state, ATgetFirst(l)), ne);
l = ATgetNext(l);
}
return s;
@ -204,7 +204,7 @@ static Expr evalExpr2(EvalState & state, Expr e)
return e;
try {
Hash pkgHash = hashPackage(state, parseFState(e));
Hash pkgHash = hashPackage(state, parseNixExpr(e));
FSId pkgId = writeTerm(e, "");
state.pkgHashes[pkgId] = pkgHash;
return ATmake("FSId(<str>)", ((string) pkgId).c_str());
@ -265,15 +265,15 @@ static Expr evalExpr2(EvalState & state, Expr e)
FSId id;
addToStore(srcPath, dstPath, id, true);
SliceElem elem;
ClosureElem elem;
elem.id = id;
FState fs;
fs.type = FState::fsSlice;
fs.slice.roots.insert(dstPath);
fs.slice.elems[dstPath] = elem;
NixExpr ne;
ne.type = NixExpr::neClosure;
ne.closure.roots.insert(dstPath);
ne.closure.elems[dstPath] = elem;
Hash pkgHash = hashPackage(state, fs);
FSId pkgId = writeTerm(unparseFState(fs), "");
Hash pkgHash = hashPackage(state, ne);
FSId pkgId = writeTerm(unparseNixExpr(ne), "");
state.pkgHashes[pkgId] = pkgHash;
msg(lvlChatty, format("copied `%1%' -> %2%")
@ -282,7 +282,7 @@ static Expr evalExpr2(EvalState & state, Expr e)
return ATmake("FSId(<str>)", ((string) pkgId).c_str());
}
/* Packages are transformed into Derive fstate expressions. */
/* Packages are transformed into Nix derivation expressions. */
if (ATmatch(e, "Package([<list>])", &bnds)) {
/* Evaluate the bindings and put them in a map. */
@ -296,10 +296,11 @@ static Expr evalExpr2(EvalState & state, Expr e)
bnds = ATgetNext(bnds);
}
/* Gather information for building the Derive expression. */
FState fs;
fs.type = FState::fsDerive;
fs.derive.platform = SYSTEM;
/* Gather information for building the derivation
expression. */
NixExpr ne;
ne.type = NixExpr::neDerivation;
ne.derivation.platform = SYSTEM;
string name;
FSId outId;
bool outIdGiven = false;
@ -318,16 +319,16 @@ static Expr evalExpr2(EvalState & state, Expr e)
while (!ATisEmpty(args)) {
Expr arg = evalExpr(state, ATgetFirst(args));
fs.derive.args.push_back(processBinding(state, arg, fs));
ne.derivation.args.push_back(processBinding(state, arg, ne));
args = ATgetNext(args);
}
}
else {
string s = processBinding(state, value, fs);
fs.derive.env[key] = s;
string s = processBinding(state, value, ne);
ne.derivation.env[key] = s;
if (key == "build") fs.derive.builder = s;
if (key == "build") ne.derivation.builder = s;
if (key == "name") name = s;
if (key == "id") {
outId = parseHash(s);
@ -339,25 +340,25 @@ static Expr evalExpr2(EvalState & state, Expr e)
ATmake("(<str>, <term>)", key.c_str(), value));
}
if (fs.derive.builder == "")
if (ne.derivation.builder == "")
throw badTerm("no builder specified", e);
if (name == "")
throw badTerm("no package name specified", e);
/* Hash the fstate-expression with no outputs to produce a
/* Hash the Nix expression with no outputs to produce a
unique but deterministic path name for this package. */
if (!outIdGiven) outId = hashPackage(state, fs);
if (!outIdGiven) outId = hashPackage(state, ne);
string outPath =
canonPath(nixStore + "/" + ((string) outId).c_str() + "-" + name);
fs.derive.env["out"] = outPath;
fs.derive.outputs[outPath] = outId;
ne.derivation.env["out"] = outPath;
ne.derivation.outputs[outPath] = outId;
/* Write the resulting term into the Nix store directory. */
Hash pkgHash = outIdGiven
? hashString((string) outId + outPath)
: hashPackage(state, fs);
FSId pkgId = writeTerm(unparseFState(fs), "-d-" + name);
: hashPackage(state, ne);
FSId pkgId = writeTerm(unparseNixExpr(ne), "-d-" + name);
state.pkgHashes[pkgId] = pkgHash;
msg(lvlChatty, format("instantiated `%1%' -> %2%")

View File

@ -29,7 +29,7 @@ extern TableId dbId2Paths;
/* dbSuccessors :: FSId -> FSId
Each pair $(id_1, id_2)$ in this mapping records the fact that a
successor of an fstate expression stored in a file with identifier
successor of a Nix expression stored in a file with identifier
$id_1$ is stored in a file with identifier $id_2$.
Note that a term $y$ is successor of $x$ iff there exists a
@ -41,15 +41,14 @@ extern TableId dbSuccessors;
/* dbSubstitutes :: FSId -> [FSId]
Each pair $(id, [ids])$ tells Nix that it can realise any of the
fstate expressions referenced by the identifiers in $ids$ to
Nix expressions referenced by the identifiers in $ids$ to
generate a path with identifier $id$.
The main purpose of this is for distributed caching of derivates.
One system can compute a derivate with hash $h$ and put it on a
website (as a Nix archive), for instance, and then another system
can register a substitute for that derivate. The substitute in
this case might be an fstate expression that fetches the Nix
archive.
this case might be a Nix expression that fetches the Nix archive.
*/
extern TableId dbSubstitutes;

View File

@ -2,7 +2,7 @@ nix [OPTIONS...] [ARGUMENTS...]
Operations:
--install / -i: realise an fstate
--install / -i: realise a Nix expression
--delete / -d: delete paths from the Nix store
--add / -A: copy a path to the Nix store
--query / -q: query information
@ -25,7 +25,7 @@ Source selection for --install, --dump:
Query flags:
--list / -l: query the output paths (roots) of an fstate (default)
--list / -l: query the output paths (roots) of a Nix expression (default)
--requisites / -r: print all paths necessary to realise expression
--generators / -g: find expressions producing a subset of given ids
--expansion / -e: print a path containing id

View File

@ -37,8 +37,7 @@ static FSId argToId(const string & arg)
}
/* Realise (or install) paths from the given Nix fstate
expressions. */
/* Realise (or install) paths from the given Nix expressions. */
static void opInstall(Strings opFlags, Strings opArgs)
{
if (!opFlags.empty()) throw UsageError("unknown flag");
@ -46,8 +45,8 @@ static void opInstall(Strings opFlags, Strings opArgs)
for (Strings::iterator it = opArgs.begin();
it != opArgs.end(); it++)
{
FSId id = normaliseFState(argToId(*it));
realiseSlice(id);
FSId id = normaliseNixExpr(argToId(*it));
realiseClosure(id);
cout << format("%1%\n") % (string) id;
}
}
@ -83,7 +82,7 @@ static void opAdd(Strings opFlags, Strings opArgs)
FSId maybeNormalise(const FSId & id, bool normalise)
{
return normalise ? normaliseFState(id) : id;
return normalise ? normaliseNixExpr(id) : id;
}
@ -115,7 +114,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
for (Strings::iterator i = opArgs.begin();
i != opArgs.end(); i++)
{
Strings paths2 = fstatePaths(
Strings paths2 = nixExprPaths(
maybeNormalise(argToId(*i), normalise));
paths.insert(paths2.begin(), paths2.end());
}
@ -130,7 +129,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
for (Strings::iterator i = opArgs.begin();
i != opArgs.end(); i++)
{
Strings paths2 = fstateRequisites(
Strings paths2 = nixExprRequisites(
maybeNormalise(argToId(*i), normalise),
includeExprs, includeSuccessors);
paths.insert(paths2.begin(), paths2.end());

View File

@ -26,40 +26,41 @@ static FSId useSuccessor(const FSId & id)
}
Strings pathsFromOutputs(const DeriveOutputs & ps)
Strings pathsFromOutputs(const DerivationOutputs & ps)
{
Strings ss;
for (DeriveOutputs::const_iterator i = ps.begin();
for (DerivationOutputs::const_iterator i = ps.begin();
i != ps.end(); i++)
ss.push_back(i->first);
return ss;
}
FSId normaliseFState(FSId id, FSIdSet pending)
FSId normaliseNixExpr(FSId id, FSIdSet pending)
{
Nest nest(lvlTalkative, format("normalising fstate %1%") % (string) id);
Nest nest(lvlTalkative,
format("normalising nix expression %1%") % (string) id);
/* Try to substitute $id$ by any known successors in order to
speed up the rewrite process. */
id = useSuccessor(id);
/* Get the fstate expression. */
FState fs = parseFState(termFromId(id));
/* Get the Nix expression. */
NixExpr ne = parseNixExpr(termFromId(id));
/* If this is a normal form (i.e., a slice) we are done. */
if (fs.type == FState::fsSlice) return id;
if (fs.type != FState::fsDerive) abort();
/* If this is a normal form (i.e., a closure) we are done. */
if (ne.type == NixExpr::neClosure) return id;
if (ne.type != NixExpr::neDerivation) abort();
/* Otherwise, it's a derive expression, and we have to build it to
/* Otherwise, it's a derivation expression, and we have to build it to
determine its normal form. */
/* Some variables. */
/* Input paths, with their slice elements. */
SliceElems inSlices;
/* Input paths, with their closure elements. */
ClosureElems inClosures;
/* Referencable paths (i.e., input and output paths). */
StringSet allPaths;
@ -68,13 +69,13 @@ FSId normaliseFState(FSId id, FSIdSet pending)
Environment env;
/* The result. */
FState nfFS;
nfFS.type = FState::fsSlice;
NixExpr nf;
nf.type = NixExpr::neClosure;
/* Parse the outputs. */
for (DeriveOutputs::iterator i = fs.derive.outputs.begin();
i != fs.derive.outputs.end(); i++)
for (DerivationOutputs::iterator i = ne.derivation.outputs.begin();
i != ne.derivation.outputs.end(); i++)
{
debug(format("building %1% in `%2%'") % (string) i->second % i->first);
allPaths.insert(i->first);
@ -82,7 +83,7 @@ FSId normaliseFState(FSId id, FSIdSet pending)
/* Obtain locks on all output paths. The locks are automatically
released when we exit this function or Nix crashes. */
PathLocks outputLocks(pathsFromOutputs(fs.derive.outputs));
PathLocks outputLocks(pathsFromOutputs(ne.derivation.outputs));
/* Now check again whether there is a successor. This is because
another process may have started building in parallel. After
@ -95,33 +96,33 @@ FSId normaliseFState(FSId id, FSIdSet pending)
{
FSId id2 = useSuccessor(id);
if (id2 != id) {
FState fs = parseFState(termFromId(id2));
NixExpr ne = parseNixExpr(termFromId(id2));
debug(format("skipping build of %1%, someone beat us to it")
% (string) id);
if (fs.type != FState::fsSlice) abort();
if (ne.type != NixExpr::neClosure) abort();
return id2;
}
}
/* Right platform? */
if (fs.derive.platform != thisSystem)
if (ne.derivation.platform != thisSystem)
throw Error(format("a `%1%' is required, but I am a `%2%'")
% fs.derive.platform % thisSystem);
% ne.derivation.platform % thisSystem);
/* Realise inputs (and remember all input paths). */
for (FSIdSet::iterator i = fs.derive.inputs.begin();
i != fs.derive.inputs.end(); i++)
for (FSIdSet::iterator i = ne.derivation.inputs.begin();
i != ne.derivation.inputs.end(); i++)
{
FSId nf = normaliseFState(*i, pending);
realiseSlice(nf, pending);
FSId nf = normaliseNixExpr(*i, pending);
realiseClosure(nf, pending);
/* !!! nf should be a root of the garbage collector while we
are building */
FState fs = parseFState(termFromId(nf));
if (fs.type != FState::fsSlice) abort();
for (SliceElems::iterator j = fs.slice.elems.begin();
j != fs.slice.elems.end(); j++)
NixExpr ne = parseNixExpr(termFromId(nf));
if (ne.type != NixExpr::neClosure) abort();
for (ClosureElems::iterator j = ne.closure.elems.begin();
j != ne.closure.elems.end(); j++)
{
inSlices[j->first] = j->second;
inClosures[j->first] = j->second;
allPaths.insert(j->first);
}
}
@ -140,15 +141,15 @@ FSId normaliseFState(FSId id, FSIdSet pending)
env["HOME"] = "/homeless-shelter";
/* Build the environment. */
for (StringPairs::iterator i = fs.derive.env.begin();
i != fs.derive.env.end(); i++)
for (StringPairs::iterator i = ne.derivation.env.begin();
i != ne.derivation.env.end(); i++)
env[i->first] = i->second;
/* We can skip running the builder if we can expand all output
paths from their ids. */
bool fastBuild = true;
for (DeriveOutputs::iterator i = fs.derive.outputs.begin();
i != fs.derive.outputs.end(); i++)
for (DerivationOutputs::iterator i = ne.derivation.outputs.begin();
i != ne.derivation.outputs.end(); i++)
{
try {
expandId(i->second, i->first, "/", pending);
@ -164,8 +165,8 @@ FSId normaliseFState(FSId id, FSIdSet pending)
/* If any of the outputs already exist but are not registered,
delete them. */
for (DeriveOutputs::iterator i = fs.derive.outputs.begin();
i != fs.derive.outputs.end(); i++)
for (DerivationOutputs::iterator i = ne.derivation.outputs.begin();
i != ne.derivation.outputs.end(); i++)
{
string path = i->first;
FSId id;
@ -179,7 +180,7 @@ FSId normaliseFState(FSId id, FSIdSet pending)
/* Run the builder. */
msg(lvlChatty, format("building..."));
runProgram(fs.derive.builder, fs.derive.args, env);
runProgram(ne.derivation.builder, ne.derivation.args, env);
msg(lvlChatty, format("build completed"));
} else
@ -189,13 +190,13 @@ FSId normaliseFState(FSId id, FSIdSet pending)
output path to determine what other paths it references. Also make all
output paths read-only. */
StringSet usedPaths;
for (DeriveOutputs::iterator i = fs.derive.outputs.begin();
i != fs.derive.outputs.end(); i++)
for (DerivationOutputs::iterator i = ne.derivation.outputs.begin();
i != ne.derivation.outputs.end(); i++)
{
string path = i->first;
if (!pathExists(path))
throw Error(format("path `%1%' does not exist") % path);
nfFS.slice.roots.insert(path);
nf.closure.roots.insert(path);
makePathReadOnly(path);
@ -204,28 +205,28 @@ FSId normaliseFState(FSId id, FSIdSet pending)
Strings refPaths = filterReferences(path,
Strings(allPaths.begin(), allPaths.end()));
/* Construct a slice element for this output path. */
SliceElem elem;
/* Construct a closure element for this output path. */
ClosureElem elem;
elem.id = i->second;
/* For each path referenced by this output path, add its id to the
slice element and add the id to the `usedPaths' set (so that the
elements referenced by *its* slice are added below). */
closure element and add the id to the `usedPaths' set (so that the
elements referenced by *its* closure are added below). */
for (Strings::iterator j = refPaths.begin();
j != refPaths.end(); j++)
{
string path = *j;
elem.refs.insert(path);
if (inSlices.find(path) != inSlices.end())
if (inClosures.find(path) != inClosures.end())
usedPaths.insert(path);
else if (fs.derive.outputs.find(path) == fs.derive.outputs.end())
else if (ne.derivation.outputs.find(path) == ne.derivation.outputs.end())
abort();
}
nfFS.slice.elems[path] = elem;
nf.closure.elems[path] = elem;
}
/* Close the slice. That is, for any referenced path, add the paths
/* Close the closure. That is, for any referenced path, add the paths
referenced by it. */
StringSet donePaths;
@ -237,10 +238,10 @@ FSId normaliseFState(FSId id, FSIdSet pending)
if (donePaths.find(path) != donePaths.end()) continue;
donePaths.insert(path);
SliceElems::iterator j = inSlices.find(path);
if (j == inSlices.end()) abort();
ClosureElems::iterator j = inClosures.find(path);
if (j == inClosures.end()) abort();
nfFS.slice.elems[path] = j->second;
nf.closure.elems[path] = j->second;
for (StringSet::iterator k = j->second.refs.begin();
k != j->second.refs.end(); k++)
@ -248,8 +249,8 @@ FSId normaliseFState(FSId id, FSIdSet pending)
}
/* For debugging, print out the referenced and unreferenced paths. */
for (SliceElems::iterator i = inSlices.begin();
i != inSlices.end(); i++)
for (ClosureElems::iterator i = inClosures.begin();
i != inClosures.end(); i++)
{
StringSet::iterator j = donePaths.find(i->first);
if (j == donePaths.end())
@ -260,9 +261,9 @@ FSId normaliseFState(FSId id, FSIdSet pending)
/* Write the normal form. This does not have to occur in the
transaction below because writing terms is idem-potent. */
ATerm nf = unparseFState(nfFS);
msg(lvlVomit, format("normal form: %1%") % printTerm(nf));
FSId idNF = writeTerm(nf, "-s-" + (string) id);
ATerm nfTerm = unparseNixExpr(nf);
msg(lvlVomit, format("normal form: %1%") % printTerm(nfTerm));
FSId idNF = writeTerm(nfTerm, "-s-" + (string) id);
/* Register each outpat path, and register the normal form. This
is wrapped in one database transaction to ensure that if we
@ -271,8 +272,8 @@ FSId normaliseFState(FSId id, FSIdSet pending)
deleted arbitrarily, while registered paths can only be deleted
by running the garbage collector. */
Transaction txn(nixDB);
for (DeriveOutputs::iterator i = fs.derive.outputs.begin();
i != fs.derive.outputs.end(); i++)
for (DerivationOutputs::iterator i = ne.derivation.outputs.begin();
i != ne.derivation.outputs.end(); i++)
registerPath(txn, i->first, i->second);
registerSuccessor(txn, id, idNF);
txn.commit();
@ -281,36 +282,36 @@ FSId normaliseFState(FSId id, FSIdSet pending)
}
void realiseSlice(const FSId & id, FSIdSet pending)
void realiseClosure(const FSId & id, FSIdSet pending)
{
Nest nest(lvlDebug,
format("realising slice %1%") % (string) id);
format("realising closure %1%") % (string) id);
FState fs = parseFState(termFromId(id));
if (fs.type != FState::fsSlice)
throw Error(format("expected slice in %1%") % (string) id);
NixExpr ne = parseNixExpr(termFromId(id));
if (ne.type != NixExpr::neClosure)
throw Error(format("expected closure in %1%") % (string) id);
for (SliceElems::const_iterator i = fs.slice.elems.begin();
i != fs.slice.elems.end(); i++)
for (ClosureElems::const_iterator i = ne.closure.elems.begin();
i != ne.closure.elems.end(); i++)
expandId(i->second.id, i->first, "/", pending);
}
Strings fstatePaths(const FSId & id)
Strings nixExprPaths(const FSId & id)
{
Strings paths;
FState fs = parseFState(termFromId(id));
NixExpr ne = parseNixExpr(termFromId(id));
if (fs.type == FState::fsSlice) {
for (StringSet::const_iterator i = fs.slice.roots.begin();
i != fs.slice.roots.end(); i++)
if (ne.type == NixExpr::neClosure) {
for (StringSet::const_iterator i = ne.closure.roots.begin();
i != ne.closure.roots.end(); i++)
paths.push_back(*i);
}
else if (fs.type == FState::fsDerive) {
for (DeriveOutputs::iterator i = fs.derive.outputs.begin();
i != fs.derive.outputs.end(); i++)
else if (ne.type == NixExpr::neDerivation) {
for (DerivationOutputs::iterator i = ne.derivation.outputs.begin();
i != ne.derivation.outputs.end(); i++)
paths.push_back(i->first);
}
@ -320,24 +321,24 @@ Strings fstatePaths(const FSId & id)
}
static void fstateRequisitesSet(const FSId & id,
static void nixExprRequisitesSet(const FSId & id,
bool includeExprs, bool includeSuccessors, StringSet & paths,
FSIdSet & doneSet)
{
if (doneSet.find(id) != doneSet.end()) return;
doneSet.insert(id);
FState fs = parseFState(termFromId(id));
NixExpr ne = parseNixExpr(termFromId(id));
if (fs.type == FState::fsSlice)
for (SliceElems::iterator i = fs.slice.elems.begin();
i != fs.slice.elems.end(); i++)
if (ne.type == NixExpr::neClosure)
for (ClosureElems::iterator i = ne.closure.elems.begin();
i != ne.closure.elems.end(); i++)
paths.insert(i->first);
else if (fs.type == FState::fsDerive)
for (FSIdSet::iterator i = fs.derive.inputs.begin();
i != fs.derive.inputs.end(); i++)
fstateRequisitesSet(*i,
else if (ne.type == NixExpr::neDerivation)
for (FSIdSet::iterator i = ne.derivation.inputs.begin();
i != ne.derivation.inputs.end(); i++)
nixExprRequisitesSet(*i,
includeExprs, includeSuccessors, paths, doneSet);
else abort();
@ -348,17 +349,17 @@ static void fstateRequisitesSet(const FSId & id,
string idSucc;
if (includeSuccessors &&
nixDB.queryString(noTxn, dbSuccessors, id, idSucc))
fstateRequisitesSet(parseHash(idSucc),
nixExprRequisitesSet(parseHash(idSucc),
includeExprs, includeSuccessors, paths, doneSet);
}
Strings fstateRequisites(const FSId & id,
Strings nixExprRequisites(const FSId & id,
bool includeExprs, bool includeSuccessors)
{
StringSet paths;
FSIdSet doneSet;
fstateRequisitesSet(id, includeExprs, includeSuccessors, paths, doneSet);
nixExprRequisitesSet(id, includeExprs, includeSuccessors, paths, doneSet);
return Strings(paths.begin(), paths.end());
}
@ -381,19 +382,19 @@ FSIds findGenerators(const FSIds & _ids)
if (!nixDB.queryString(noTxn, dbSuccessors, *i, s)) continue;
FSId id = parseHash(s);
FState fs;
NixExpr ne;
try {
/* !!! should substitutes be used? */
fs = parseFState(termFromId(id));
ne = parseNixExpr(termFromId(id));
} catch (...) { /* !!! only catch parse errors */
continue;
}
if (fs.type != FState::fsSlice) continue;
if (ne.type != NixExpr::neClosure) continue;
bool okay = true;
for (SliceElems::const_iterator i = fs.slice.elems.begin();
i != fs.slice.elems.end(); i++)
for (ClosureElems::const_iterator i = ne.closure.elems.begin();
i != ne.closure.elems.end(); i++)
if (ids.find(i->second.id) == ids.end()) {
okay = false;
break;

View File

@ -1,30 +1,29 @@
#ifndef __NORMALISE_H
#define __NORMALISE_H
#include "fstate.hh"
#include "expr.hh"
/* Normalise an fstate-expression, that is, return an equivalent
slice. (For the meaning of `pending', see expandId()). */
FSId normaliseFState(FSId id, FSIdSet pending = FSIdSet());
/* Normalise a Nix expression, that is, return an equivalent
closure. (For the meaning of `pending', see expandId()). */
FSId normaliseNixExpr(FSId id, FSIdSet pending = FSIdSet());
/* Realise a Slice in the file system. */
void realiseSlice(const FSId & id, FSIdSet pending = FSIdSet());
/* Realise a Closure in the file system. */
void realiseClosure(const FSId & id, FSIdSet pending = FSIdSet());
/* Get the list of root (output) paths of the given
fstate-expression. */
Strings fstatePaths(const FSId & id);
/* Get the list of root (output) paths of the given Nix expression. */
Strings nixExprPaths(const FSId & id);
/* Get the list of paths that are required to realise the given
expression. For a derive expression, this is the union of
requisites of the inputs; for a slice expression, it is the path of
each element in the slice. If `includeExprs' is true, include the
requisites of the inputs; for a closure expression, it is the path of
each element in the closure. If `includeExprs' is true, include the
paths of the Nix expressions themselves. If `includeSuccessors' is
true, include the requisites of successors. */
Strings fstateRequisites(const FSId & id,
Strings nixExprRequisites(const FSId & id,
bool includeExprs, bool includeSuccessors);
/* Return the list of the ids of all known fstate-expressions whose
/* Return the list of the ids of all known Nix expressions whose
output ids are completely contained in `ids'. */
FSIds findGenerators(const FSIds & ids);

View File

@ -246,7 +246,7 @@ string expandId(const FSId & id, const string & target,
debug(format("trying substitute %1%") % (string) subId);
realiseSlice(normaliseFState(subId, pending), pending);
realiseClosure(normaliseNixExpr(subId, pending), pending);
return expandId(id, target, prefix, pending);
}

View File

@ -2,7 +2,7 @@
echo "builder 2"
mkdir $out || exit 1
/bin/mkdir $out || exit 1
cd $out || exit 1
echo "Hallo Wereld" > bla
echo $builder >> bla

View File

@ -13,23 +13,10 @@
void realise(FSId id)
{
Nest nest(lvlDebug, format("TEST: realising %1%") % (string) id);
realiseSlice(normaliseFState(id));
realiseClosure(normaliseNixExpr(id));
}
#if 0
void realiseFail(FState fs)
{
try {
realiseFState(fs);
abort();
} catch (Error e) {
cout << "error (expected): " << e.what() << endl;
}
}
#endif
struct MySink : DumpSink
{
virtual void operator () (const unsigned char * data, unsigned int len)
@ -115,8 +102,8 @@ void runTests()
addToStore("./test-builder-1.sh", builder1fn, builder1id);
ATerm fs1 = ATmake(
"Slice([<str>], [(<str>, <str>, [])])",
((string) builder1id).c_str(),
"Closure([<str>], [(<str>, <str>, [])])",
builder1fn.c_str(),
builder1fn.c_str(),
((string) builder1id).c_str());
FSId fs1id = writeTerm(fs1, "");
@ -125,8 +112,8 @@ void runTests()
realise(fs1id);
ATerm fs2 = ATmake(
"Slice([<str>], [(<str>, <str>, [])])",
((string) builder1id).c_str(),
"Closure([<str>], [(<str>, <str>, [])])",
(builder1fn + "_bla").c_str(),
(builder1fn + "_bla").c_str(),
((string) builder1id).c_str());
FSId fs2id = writeTerm(fs2, "");
@ -137,12 +124,12 @@ void runTests()
string out1id = hashString("foo"); /* !!! bad */
string out1fn = nixStore + "/" + (string) out1id + "-hello.txt";
ATerm fs3 = ATmake(
"Derive([(<str>, <str>)], [<str>], <str>, <str>, [(\"out\", <str>)])",
"Derive([(<str>, <str>)], [<str>], <str>, <str>, [], [(\"out\", <str>)])",
out1fn.c_str(),
((string) out1id).c_str(),
((string) fs1id).c_str(),
((string) builder1fn).c_str(),
thisSystem.c_str(),
((string) builder1fn).c_str(),
out1fn.c_str());
debug(printTerm(fs3));
FSId fs3id = writeTerm(fs3, "");
@ -156,8 +143,8 @@ void runTests()
addToStore("./test-builder-2.sh", builder4fn, builder4id);
ATerm fs4 = ATmake(
"Slice([<str>], [(<str>, <str>, [])])",
((string) builder4id).c_str(),
"Closure([<str>], [(<str>, <str>, [])])",
builder4fn.c_str(),
builder4fn.c_str(),
((string) builder4id).c_str());
FSId fs4id = writeTerm(fs4, "");
@ -167,12 +154,12 @@ void runTests()
string out5id = hashString("bar"); /* !!! bad */
string out5fn = nixStore + "/" + (string) out5id + "-hello2";
ATerm fs5 = ATmake(
"Derive([(<str>, <str>)], [<str>], <str>, <str>, [(\"out\", <str>), (\"builder\", <str>)])",
"Derive([(<str>, <str>)], [<str>], <str>, <str>, [], [(\"out\", <str>), (\"builder\", <str>)])",
out5fn.c_str(),
((string) out5id).c_str(),
((string) fs4id).c_str(),
((string) builder4fn).c_str(),
thisSystem.c_str(),
((string) builder4fn).c_str(),
out5fn.c_str(),
((string) builder4fn).c_str());
debug(printTerm(fs5));