mirror of
https://github.com/NixOS/nix
synced 2025-07-04 23:51:47 +02:00
* Refactorings.
This commit is contained in:
parent
ab350eafd2
commit
6f1a0f948d
14 changed files with 635 additions and 605 deletions
265
src/normalise.cc
Normal file
265
src/normalise.cc
Normal file
|
@ -0,0 +1,265 @@
|
|||
#include <map>
|
||||
|
||||
#include "normalise.hh"
|
||||
#include "references.hh"
|
||||
#include "db.hh"
|
||||
#include "exec.hh"
|
||||
#include "globals.hh"
|
||||
|
||||
|
||||
void registerSuccessor(const FSId & id1, const FSId & id2)
|
||||
{
|
||||
setDB(nixDB, dbSuccessors, id1, id2);
|
||||
}
|
||||
|
||||
|
||||
static FSId storeSuccessor(const FSId & id1, ATerm sc)
|
||||
{
|
||||
FSId id2 = writeTerm(sc, "-s-" + (string) id1);
|
||||
registerSuccessor(id1, id2);
|
||||
return id2;
|
||||
}
|
||||
|
||||
|
||||
typedef set<FSId> FSIdSet;
|
||||
|
||||
|
||||
Slice normaliseFState(FSId id)
|
||||
{
|
||||
debug(format("normalising fstate %1%") % (string) id);
|
||||
Nest nest(true);
|
||||
|
||||
/* Try to substitute $id$ by any known successors in order to
|
||||
speed up the rewrite process. */
|
||||
string idSucc;
|
||||
while (queryDB(nixDB, dbSuccessors, id, idSucc)) {
|
||||
debug(format("successor %1% -> %2%") % (string) id % idSucc);
|
||||
id = parseHash(idSucc);
|
||||
}
|
||||
|
||||
/* Get the fstate expression. */
|
||||
FState fs = parseFState(termFromId(id));
|
||||
|
||||
/* It this is a normal form (i.e., a slice) we are done. */
|
||||
if (fs.type == FState::fsSlice) return fs.slice;
|
||||
|
||||
/* Otherwise, it's a derivation. */
|
||||
|
||||
/* Right platform? */
|
||||
if (fs.derive.platform != thisSystem)
|
||||
throw Error(format("a `%1%' is required, but I am a `%2%'")
|
||||
% fs.derive.platform % thisSystem);
|
||||
|
||||
/* Realise inputs (and remember all input paths). */
|
||||
typedef map<string, SliceElem> ElemMap;
|
||||
|
||||
ElemMap inMap;
|
||||
|
||||
for (FSIds::iterator i = fs.derive.inputs.begin();
|
||||
i != fs.derive.inputs.end(); i++) {
|
||||
Slice slice = normaliseFState(*i);
|
||||
realiseSlice(slice);
|
||||
|
||||
for (SliceElems::iterator j = slice.elems.begin();
|
||||
j != slice.elems.end(); j++)
|
||||
inMap[j->path] = *j;
|
||||
}
|
||||
|
||||
Strings inPaths;
|
||||
for (ElemMap::iterator i = inMap.begin(); i != inMap.end(); i++)
|
||||
inPaths.push_back(i->second.path);
|
||||
|
||||
/* Build the environment. */
|
||||
Environment env;
|
||||
for (StringPairs::iterator i = fs.derive.env.begin();
|
||||
i != fs.derive.env.end(); i++)
|
||||
env[i->first] = i->second;
|
||||
|
||||
/* Parse the outputs. */
|
||||
typedef map<string, FSId> OutPaths;
|
||||
OutPaths outPaths;
|
||||
for (DeriveOutputs::iterator i = fs.derive.outputs.begin();
|
||||
i != fs.derive.outputs.end(); i++)
|
||||
{
|
||||
debug(format("building %1% in %2%") % (string) i->second % i->first);
|
||||
outPaths[i->first] = i->second;
|
||||
inPaths.push_back(i->first);
|
||||
}
|
||||
|
||||
/* We can skip running the builder if we can expand all output
|
||||
paths from their ids. */
|
||||
bool fastBuild = false;
|
||||
#if 0
|
||||
for (OutPaths::iterator i = outPaths.begin();
|
||||
i != outPaths.end(); i++)
|
||||
{
|
||||
try {
|
||||
expandId(i->second, i->first);
|
||||
} catch (...) {
|
||||
fastBuild = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!fastBuild) {
|
||||
|
||||
/* Check that none of the outputs exist. */
|
||||
for (OutPaths::iterator i = outPaths.begin();
|
||||
i != outPaths.end(); i++)
|
||||
if (pathExists(i->first))
|
||||
throw Error(format("path `%1%' exists") % i->first);
|
||||
|
||||
/* Run the builder. */
|
||||
debug(format("building..."));
|
||||
runProgram(fs.derive.builder, env);
|
||||
debug(format("build completed"));
|
||||
|
||||
} else
|
||||
debug(format("skipping build"));
|
||||
|
||||
/* Check whether the output paths were created, and register each
|
||||
one. */
|
||||
FSIdSet used;
|
||||
for (OutPaths::iterator i = outPaths.begin();
|
||||
i != outPaths.end(); i++)
|
||||
{
|
||||
string path = i->first;
|
||||
if (!pathExists(path))
|
||||
throw Error(format("path `%1%' does not exist") % path);
|
||||
registerPath(path, i->second);
|
||||
fs.slice.roots.push_back(i->second);
|
||||
|
||||
Strings refs = filterReferences(path, inPaths);
|
||||
|
||||
SliceElem elem;
|
||||
elem.path = path;
|
||||
elem.id = i->second;
|
||||
|
||||
for (Strings::iterator j = refs.begin(); j != refs.end(); j++) {
|
||||
ElemMap::iterator k;
|
||||
OutPaths::iterator l;
|
||||
if ((k = inMap.find(*j)) != inMap.end()) {
|
||||
elem.refs.push_back(k->second.id);
|
||||
used.insert(k->second.id);
|
||||
for (FSIds::iterator m = k->second.refs.begin();
|
||||
m != k->second.refs.end(); m++)
|
||||
used.insert(*m);
|
||||
} else if ((l = outPaths.find(*j)) != outPaths.end()) {
|
||||
elem.refs.push_back(l->second);
|
||||
used.insert(l->second);
|
||||
} else
|
||||
throw Error(format("unknown referenced path `%1%'") % *j);
|
||||
}
|
||||
|
||||
fs.slice.elems.push_back(elem);
|
||||
}
|
||||
|
||||
for (ElemMap::iterator i = inMap.begin();
|
||||
i != inMap.end(); i++)
|
||||
{
|
||||
FSIdSet::iterator j = used.find(i->second.id);
|
||||
if (j == used.end())
|
||||
debug(format("NOT referenced: `%1%'") % i->second.path);
|
||||
else {
|
||||
debug(format("referenced: `%1%'") % i->second.path);
|
||||
fs.slice.elems.push_back(i->second);
|
||||
}
|
||||
}
|
||||
|
||||
fs.type = FState::fsSlice;
|
||||
ATerm nf = unparseFState(fs);
|
||||
debug(format("normal form: %1%") % printTerm(nf));
|
||||
storeSuccessor(id, nf);
|
||||
|
||||
return fs.slice;
|
||||
}
|
||||
|
||||
|
||||
void realiseSlice(const Slice & slice)
|
||||
{
|
||||
debug(format("realising slice"));
|
||||
Nest nest(true);
|
||||
|
||||
/* Perhaps all paths already contain the right id? */
|
||||
|
||||
bool missing = false;
|
||||
for (SliceElems::const_iterator i = slice.elems.begin();
|
||||
i != slice.elems.end(); i++)
|
||||
{
|
||||
SliceElem elem = *i;
|
||||
string id;
|
||||
if (!queryDB(nixDB, dbPath2Id, elem.path, id)) {
|
||||
if (pathExists(elem.path))
|
||||
throw Error(format("path `%1%' obstructed") % elem.path);
|
||||
missing = true;
|
||||
break;
|
||||
}
|
||||
if (parseHash(id) != elem.id)
|
||||
throw Error(format("path `%1%' obstructed") % elem.path);
|
||||
}
|
||||
|
||||
if (!missing) {
|
||||
debug(format("already installed"));
|
||||
return;
|
||||
}
|
||||
|
||||
/* For each element, expand its id at its path. */
|
||||
for (SliceElems::const_iterator i = slice.elems.begin();
|
||||
i != slice.elems.end(); i++)
|
||||
{
|
||||
SliceElem elem = *i;
|
||||
debug(format("expanding %1% in %2%") % (string) elem.id % elem.path);
|
||||
expandId(elem.id, elem.path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Strings fstatePaths(const FSId & id, bool normalise)
|
||||
{
|
||||
Strings paths;
|
||||
|
||||
FState fs;
|
||||
|
||||
if (normalise) {
|
||||
fs.slice = normaliseFState(id);
|
||||
fs.type = FState::fsSlice;
|
||||
} else
|
||||
fs = parseFState(termFromId(id));
|
||||
|
||||
if (fs.type == FState::fsSlice) {
|
||||
/* !!! fix complexity */
|
||||
for (FSIds::const_iterator i = fs.slice.roots.begin();
|
||||
i != fs.slice.roots.end(); i++)
|
||||
for (SliceElems::const_iterator j = fs.slice.elems.begin();
|
||||
j != fs.slice.elems.end(); j++)
|
||||
if (*i == j->id) paths.push_back(j->path);
|
||||
}
|
||||
|
||||
else if (fs.type == FState::fsDerive) {
|
||||
for (DeriveOutputs::iterator i = fs.derive.outputs.begin();
|
||||
i != fs.derive.outputs.end(); i++)
|
||||
paths.push_back(i->first);
|
||||
}
|
||||
|
||||
else abort();
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
|
||||
StringSet fstateRefs(const FSId & id)
|
||||
{
|
||||
StringSet paths;
|
||||
Slice slice = normaliseFState(id);
|
||||
for (SliceElems::const_iterator i = slice.elems.begin();
|
||||
i != slice.elems.end(); i++)
|
||||
paths.insert(i->path);
|
||||
return paths;
|
||||
}
|
||||
|
||||
|
||||
void findGenerators(const FSIds & ids)
|
||||
{
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue