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

View file

@ -23,7 +23,7 @@ test_LDADD = libshared.a libnix.a $(LDADD)
noinst_LIBRARIES = libnix.a libshared.a noinst_LIBRARIES = libnix.a libshared.a
libnix_a_SOURCES = util.cc hash.cc archive.cc md5.c \ 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 globals.cc db.cc references.cc pathlocks.cc
libshared_a_SOURCES = shared.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; StringSet doneSet;
for (Strings::iterator i = workList.begin(); i != workList.end(); i++) { 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()) { if (doneSet.find(path) == doneSet.end()) {
doneSet.insert(path); doneSet.insert(path);
SliceElems::const_iterator elem = fs.slice.elems.find(path); ClosureElems::const_iterator elem = fs.closure.elems.find(path);
if (elem == fs.slice.elems.end()) if (elem == fs.closure.elems.end())
throw Error(format("bad slice, missing path `%1%'") % path); throw Error(format("bad closure, missing path `%1%'") % path);
for (StringSet::const_iterator i = elem->second.refs.begin(); for (StringSet::const_iterator i = elem->second.refs.begin();
i != elem->second.refs.end(); i++) i != elem->second.refs.end(); i++)
@ -99,29 +99,29 @@ void printDotGraph(const FSIds & roots)
if (doneSet.find(id) == doneSet.end()) { if (doneSet.find(id) == doneSet.end()) {
doneSet.insert(id); doneSet.insert(id);
FState fs = parseFState(termFromId(id)); NixExpr ne = parseNixExpr(termFromId(id));
string label, colour; string label, colour;
if (fs.type == FState::fsDerive) { if (ne.type == NixExpr::neDerivation) {
for (FSIdSet::iterator i = fs.derive.inputs.begin(); for (FSIdSet::iterator i = ne.derivation.inputs.begin();
i != fs.derive.inputs.end(); i++) i != ne.derivation.inputs.end(); i++)
{ {
workList.push_back(*i); workList.push_back(*i);
cout << makeEdge(*i, id); cout << makeEdge(*i, id);
} }
label = "derive"; label = "derivation";
colour = "#00ff00"; colour = "#00ff00";
for (StringPairs::iterator i = fs.derive.env.begin(); for (StringPairs::iterator i = ne.derivation.env.begin();
i != fs.derive.env.end(); i++) i != ne.derivation.env.end(); i++)
if (i->first == "name") label = i->second; if (i->first == "name") label = i->second;
} }
else if (fs.type == FState::fsSlice) { else if (ne.type == NixExpr::neClosure) {
label = "<slice>"; label = "<closure>";
colour = "#00ffff"; colour = "#00ffff";
printSlice(id, fs); printClosure(id, ne);
} }
else abort(); else abort();

View file

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

View file

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

View file

@ -8,30 +8,30 @@ extern "C" {
#include "store.hh" #include "store.hh"
/* Abstract syntax of fstate-expressions. */ /* Abstract syntax of Nix expressions. */
typedef list<FSId> FSIds; typedef list<FSId> FSIds;
struct SliceElem struct ClosureElem
{ {
FSId id; FSId id;
StringSet refs; StringSet refs;
}; };
typedef map<string, SliceElem> SliceElems; typedef map<string, ClosureElem> ClosureElems;
struct Slice struct Closure
{ {
StringSet roots; StringSet roots;
SliceElems elems; ClosureElems elems;
}; };
typedef map<string, FSId> DeriveOutputs; typedef map<string, FSId> DerivationOutputs;
typedef map<string, string> StringPairs; typedef map<string, string> StringPairs;
struct Derive struct Derivation
{ {
DeriveOutputs outputs; DerivationOutputs outputs;
FSIdSet inputs; FSIdSet inputs;
string platform; string platform;
string builder; string builder;
@ -39,11 +39,11 @@ struct Derive
StringPairs env; StringPairs env;
}; };
struct FState struct NixExpr
{ {
enum { fsSlice, fsDerive } type; enum { neClosure, neDerivation } type;
Slice slice; Closure closure;
Derive derive; Derivation derivation;
}; };
@ -63,11 +63,11 @@ ATerm termFromId(const FSId & id);
/* Write an aterm to the Nix store directory, and return its hash. */ /* Write an aterm to the Nix store directory, and return its hash. */
FSId writeTerm(ATerm t, const string & suffix, FSId id = FSId()); FSId writeTerm(ATerm t, const string & suffix, FSId id = FSId());
/* Parse an fstate-expression. */ /* Parse a Nix expression. */
FState parseFState(ATerm t); NixExpr parseNixExpr(ATerm t);
/* Parse an fstate-expression. */ /* Parse a Nix expression. */
ATerm unparseFState(const FState & fs); ATerm unparseNixExpr(const NixExpr & ne);
#endif /* !__FSTATE_H */ #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); PkgPaths::iterator i = state.pkgPaths.find(id);
if (i != state.pkgPaths.end()) if (i != state.pkgPaths.end())
return i->second; return i->second;
else { else {
Strings paths = fstatePaths(id); Strings paths = nixExprPaths(id);
state.pkgPaths[id] = paths; state.pkgPaths[id] = paths;
return 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; FSIdSet inputs2;
for (FSIdSet::iterator i = fs.derive.inputs.begin(); for (FSIdSet::iterator i = ne.derivation.inputs.begin();
i != fs.derive.inputs.end(); i++) i != ne.derivation.inputs.end(); i++)
{ {
PkgHashes::iterator j = state.pkgHashes.find(*i); PkgHashes::iterator j = state.pkgHashes.find(*i);
if (j == state.pkgHashes.end()) if (j == state.pkgHashes.end())
throw Error(format("unknown package id %1%") % (string) *i); throw Error(format("unknown package id %1%") % (string) *i);
inputs2.insert(j->second); 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; char * s1;
if (ATmatch(e, "FSId(<str>)", &s1)) { if (ATmatch(e, "FSId(<str>)", &s1)) {
FSId id = parseHash(s1); FSId id = parseHash(s1);
Strings paths = fstatePathsCached(state, id); Strings paths = nixExprPathsCached(state, id);
if (paths.size() != 1) abort(); if (paths.size() != 1) abort();
string path = *(paths.begin()); string path = *(paths.begin());
fs.derive.inputs.insert(id); ne.derivation.inputs.insert(id);
return path; return path;
} }
@ -178,7 +178,7 @@ static string processBinding(EvalState & state, Expr e, FState & fs)
bool first = true; bool first = true;
while (!ATisEmpty(l)) { while (!ATisEmpty(l)) {
if (!first) s = s + " "; else first = false; 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); l = ATgetNext(l);
} }
return s; return s;
@ -204,7 +204,7 @@ static Expr evalExpr2(EvalState & state, Expr e)
return e; return e;
try { try {
Hash pkgHash = hashPackage(state, parseFState(e)); Hash pkgHash = hashPackage(state, parseNixExpr(e));
FSId pkgId = writeTerm(e, ""); FSId pkgId = writeTerm(e, "");
state.pkgHashes[pkgId] = pkgHash; state.pkgHashes[pkgId] = pkgHash;
return ATmake("FSId(<str>)", ((string) pkgId).c_str()); return ATmake("FSId(<str>)", ((string) pkgId).c_str());
@ -265,15 +265,15 @@ static Expr evalExpr2(EvalState & state, Expr e)
FSId id; FSId id;
addToStore(srcPath, dstPath, id, true); addToStore(srcPath, dstPath, id, true);
SliceElem elem; ClosureElem elem;
elem.id = id; elem.id = id;
FState fs; NixExpr ne;
fs.type = FState::fsSlice; ne.type = NixExpr::neClosure;
fs.slice.roots.insert(dstPath); ne.closure.roots.insert(dstPath);
fs.slice.elems[dstPath] = elem; ne.closure.elems[dstPath] = elem;
Hash pkgHash = hashPackage(state, fs); Hash pkgHash = hashPackage(state, ne);
FSId pkgId = writeTerm(unparseFState(fs), ""); FSId pkgId = writeTerm(unparseNixExpr(ne), "");
state.pkgHashes[pkgId] = pkgHash; state.pkgHashes[pkgId] = pkgHash;
msg(lvlChatty, format("copied `%1%' -> %2%") 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()); 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)) { if (ATmatch(e, "Package([<list>])", &bnds)) {
/* Evaluate the bindings and put them in a map. */ /* Evaluate the bindings and put them in a map. */
@ -296,10 +296,11 @@ static Expr evalExpr2(EvalState & state, Expr e)
bnds = ATgetNext(bnds); bnds = ATgetNext(bnds);
} }
/* Gather information for building the Derive expression. */ /* Gather information for building the derivation
FState fs; expression. */
fs.type = FState::fsDerive; NixExpr ne;
fs.derive.platform = SYSTEM; ne.type = NixExpr::neDerivation;
ne.derivation.platform = SYSTEM;
string name; string name;
FSId outId; FSId outId;
bool outIdGiven = false; bool outIdGiven = false;
@ -318,16 +319,16 @@ static Expr evalExpr2(EvalState & state, Expr e)
while (!ATisEmpty(args)) { while (!ATisEmpty(args)) {
Expr arg = evalExpr(state, ATgetFirst(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); args = ATgetNext(args);
} }
} }
else { else {
string s = processBinding(state, value, fs); string s = processBinding(state, value, ne);
fs.derive.env[key] = s; 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 == "name") name = s;
if (key == "id") { if (key == "id") {
outId = parseHash(s); outId = parseHash(s);
@ -339,25 +340,25 @@ static Expr evalExpr2(EvalState & state, Expr e)
ATmake("(<str>, <term>)", key.c_str(), value)); ATmake("(<str>, <term>)", key.c_str(), value));
} }
if (fs.derive.builder == "") if (ne.derivation.builder == "")
throw badTerm("no builder specified", e); throw badTerm("no builder specified", e);
if (name == "") if (name == "")
throw badTerm("no package name specified", e); 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. */ unique but deterministic path name for this package. */
if (!outIdGiven) outId = hashPackage(state, fs); if (!outIdGiven) outId = hashPackage(state, ne);
string outPath = string outPath =
canonPath(nixStore + "/" + ((string) outId).c_str() + "-" + name); canonPath(nixStore + "/" + ((string) outId).c_str() + "-" + name);
fs.derive.env["out"] = outPath; ne.derivation.env["out"] = outPath;
fs.derive.outputs[outPath] = outId; ne.derivation.outputs[outPath] = outId;
/* Write the resulting term into the Nix store directory. */ /* Write the resulting term into the Nix store directory. */
Hash pkgHash = outIdGiven Hash pkgHash = outIdGiven
? hashString((string) outId + outPath) ? hashString((string) outId + outPath)
: hashPackage(state, fs); : hashPackage(state, ne);
FSId pkgId = writeTerm(unparseFState(fs), "-d-" + name); FSId pkgId = writeTerm(unparseNixExpr(ne), "-d-" + name);
state.pkgHashes[pkgId] = pkgHash; state.pkgHashes[pkgId] = pkgHash;
msg(lvlChatty, format("instantiated `%1%' -> %2%") msg(lvlChatty, format("instantiated `%1%' -> %2%")

View file

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

View file

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

View file

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

View file

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

View file

@ -13,23 +13,10 @@
void realise(FSId id) void realise(FSId id)
{ {
Nest nest(lvlDebug, format("TEST: realising %1%") % (string) 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 struct MySink : DumpSink
{ {
virtual void operator () (const unsigned char * data, unsigned int len) virtual void operator () (const unsigned char * data, unsigned int len)
@ -115,8 +102,8 @@ void runTests()
addToStore("./test-builder-1.sh", builder1fn, builder1id); addToStore("./test-builder-1.sh", builder1fn, builder1id);
ATerm fs1 = ATmake( ATerm fs1 = ATmake(
"Slice([<str>], [(<str>, <str>, [])])", "Closure([<str>], [(<str>, <str>, [])])",
((string) builder1id).c_str(), builder1fn.c_str(),
builder1fn.c_str(), builder1fn.c_str(),
((string) builder1id).c_str()); ((string) builder1id).c_str());
FSId fs1id = writeTerm(fs1, ""); FSId fs1id = writeTerm(fs1, "");
@ -125,8 +112,8 @@ void runTests()
realise(fs1id); realise(fs1id);
ATerm fs2 = ATmake( ATerm fs2 = ATmake(
"Slice([<str>], [(<str>, <str>, [])])", "Closure([<str>], [(<str>, <str>, [])])",
((string) builder1id).c_str(), (builder1fn + "_bla").c_str(),
(builder1fn + "_bla").c_str(), (builder1fn + "_bla").c_str(),
((string) builder1id).c_str()); ((string) builder1id).c_str());
FSId fs2id = writeTerm(fs2, ""); FSId fs2id = writeTerm(fs2, "");
@ -137,12 +124,12 @@ void runTests()
string out1id = hashString("foo"); /* !!! bad */ string out1id = hashString("foo"); /* !!! bad */
string out1fn = nixStore + "/" + (string) out1id + "-hello.txt"; string out1fn = nixStore + "/" + (string) out1id + "-hello.txt";
ATerm fs3 = ATmake( ATerm fs3 = ATmake(
"Derive([(<str>, <str>)], [<str>], <str>, <str>, [(\"out\", <str>)])", "Derive([(<str>, <str>)], [<str>], <str>, <str>, [], [(\"out\", <str>)])",
out1fn.c_str(), out1fn.c_str(),
((string) out1id).c_str(), ((string) out1id).c_str(),
((string) fs1id).c_str(), ((string) fs1id).c_str(),
((string) builder1fn).c_str(),
thisSystem.c_str(), thisSystem.c_str(),
((string) builder1fn).c_str(),
out1fn.c_str()); out1fn.c_str());
debug(printTerm(fs3)); debug(printTerm(fs3));
FSId fs3id = writeTerm(fs3, ""); FSId fs3id = writeTerm(fs3, "");
@ -156,8 +143,8 @@ void runTests()
addToStore("./test-builder-2.sh", builder4fn, builder4id); addToStore("./test-builder-2.sh", builder4fn, builder4id);
ATerm fs4 = ATmake( ATerm fs4 = ATmake(
"Slice([<str>], [(<str>, <str>, [])])", "Closure([<str>], [(<str>, <str>, [])])",
((string) builder4id).c_str(), builder4fn.c_str(),
builder4fn.c_str(), builder4fn.c_str(),
((string) builder4id).c_str()); ((string) builder4id).c_str());
FSId fs4id = writeTerm(fs4, ""); FSId fs4id = writeTerm(fs4, "");
@ -167,12 +154,12 @@ void runTests()
string out5id = hashString("bar"); /* !!! bad */ string out5id = hashString("bar"); /* !!! bad */
string out5fn = nixStore + "/" + (string) out5id + "-hello2"; string out5fn = nixStore + "/" + (string) out5id + "-hello2";
ATerm fs5 = ATmake( 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(), out5fn.c_str(),
((string) out5id).c_str(), ((string) out5id).c_str(),
((string) fs4id).c_str(), ((string) fs4id).c_str(),
((string) builder4fn).c_str(),
thisSystem.c_str(), thisSystem.c_str(),
((string) builder4fn).c_str(),
out5fn.c_str(), out5fn.c_str(),
((string) builder4fn).c_str()); ((string) builder4fn).c_str());
debug(printTerm(fs5)); debug(printTerm(fs5));