* Fixed a serious bug in the computation of slices. Sometimes the slices
would not be properly closed under the path reference relation.
This commit is contained in:
parent
1472cc4825
commit
ed0db2e0d8
1 changed files with 61 additions and 20 deletions
|
@ -69,7 +69,7 @@ FSId normaliseFState(FSId id, FSIdSet pending)
|
||||||
ElemMap inMap;
|
ElemMap inMap;
|
||||||
|
|
||||||
/* Referencable paths (i.e., input and output paths). */
|
/* Referencable paths (i.e., input and output paths). */
|
||||||
Strings refPaths;
|
Strings allPaths;
|
||||||
|
|
||||||
/* The environment to be passed to the builder. */
|
/* The environment to be passed to the builder. */
|
||||||
Environment env;
|
Environment env;
|
||||||
|
@ -81,7 +81,7 @@ FSId normaliseFState(FSId id, FSIdSet pending)
|
||||||
{
|
{
|
||||||
debug(format("building %1% in `%2%'") % (string) i->second % i->first);
|
debug(format("building %1% in `%2%'") % (string) i->second % i->first);
|
||||||
outPaths[i->first] = i->second;
|
outPaths[i->first] = i->second;
|
||||||
refPaths.push_back(i->first);
|
allPaths.push_back(i->first);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Obtain locks on all output paths. The locks are automatically
|
/* Obtain locks on all output paths. The locks are automatically
|
||||||
|
@ -127,7 +127,7 @@ FSId normaliseFState(FSId id, FSIdSet pending)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ElemMap::iterator i = inMap.begin(); i != inMap.end(); i++)
|
for (ElemMap::iterator i = inMap.begin(); i != inMap.end(); i++)
|
||||||
refPaths.push_back(i->second.path);
|
allPaths.push_back(i->second.path);
|
||||||
|
|
||||||
/* Most shells initialise PATH to some default (/bin:/usr/bin:...) when
|
/* Most shells initialise PATH to some default (/bin:/usr/bin:...) when
|
||||||
PATH is not set. We don't want this, so we fill it in with some dummy
|
PATH is not set. We don't want this, so we fill it in with some dummy
|
||||||
|
@ -182,7 +182,7 @@ FSId normaliseFState(FSId id, FSIdSet pending)
|
||||||
|
|
||||||
/* Check whether the output paths were created, and grep each
|
/* Check whether the output paths were created, and grep each
|
||||||
output path to determine what other paths it references. */
|
output path to determine what other paths it references. */
|
||||||
FSIdSet used;
|
StringSet usedPaths;
|
||||||
for (OutPaths::iterator i = outPaths.begin();
|
for (OutPaths::iterator i = outPaths.begin();
|
||||||
i != outPaths.end(); i++)
|
i != outPaths.end(); i++)
|
||||||
{
|
{
|
||||||
|
@ -191,41 +191,82 @@ FSId normaliseFState(FSId id, FSIdSet pending)
|
||||||
throw Error(format("path `%1%' does not exist") % path);
|
throw Error(format("path `%1%' does not exist") % path);
|
||||||
fs.slice.roots.push_back(i->second);
|
fs.slice.roots.push_back(i->second);
|
||||||
|
|
||||||
Strings refs = filterReferences(path, refPaths);
|
/* For this output path, find the references to other paths contained
|
||||||
|
in it. */
|
||||||
|
Strings refPaths = filterReferences(path, allPaths);
|
||||||
|
|
||||||
|
/* Construct a slice element for this output path. */
|
||||||
SliceElem elem;
|
SliceElem elem;
|
||||||
elem.path = path;
|
elem.path = path;
|
||||||
elem.id = i->second;
|
elem.id = i->second;
|
||||||
|
|
||||||
for (Strings::iterator j = refs.begin(); j != refs.end(); j++) {
|
/* For each path referenced by this output path, add its id to the
|
||||||
|
slice element and add the id to the `used' set (so that the
|
||||||
|
elements referenced by *its* slice are added below). */
|
||||||
|
for (Strings::iterator j = refPaths.begin();
|
||||||
|
j != refPaths.end(); j++)
|
||||||
|
{
|
||||||
|
string path = *j;
|
||||||
ElemMap::iterator k;
|
ElemMap::iterator k;
|
||||||
OutPaths::iterator l;
|
OutPaths::iterator l;
|
||||||
if ((k = inMap.find(*j)) != inMap.end()) {
|
|
||||||
|
/* Is it an input path? */
|
||||||
|
if ((k = inMap.find(path)) != inMap.end()) {
|
||||||
elem.refs.push_back(k->second.id);
|
elem.refs.push_back(k->second.id);
|
||||||
used.insert(k->second.id);
|
usedPaths.insert(k->second.path);
|
||||||
for (FSIds::iterator m = k->second.refs.begin();
|
}
|
||||||
m != k->second.refs.end(); m++)
|
|
||||||
used.insert(*m);
|
/* Or an output path? */
|
||||||
} else if ((l = outPaths.find(*j)) != outPaths.end()) {
|
else if ((l = outPaths.find(path)) != outPaths.end())
|
||||||
elem.refs.push_back(l->second);
|
elem.refs.push_back(l->second);
|
||||||
used.insert(l->second);
|
|
||||||
} else
|
/* Can't happen. */
|
||||||
throw Error(format("unknown referenced path `%1%'") % *j);
|
else abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.slice.elems.push_back(elem);
|
fs.slice.elems.push_back(elem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Close the slice. That is, for any referenced path, add the paths
|
||||||
|
referenced by it. */
|
||||||
|
FSIdSet donePaths;
|
||||||
|
|
||||||
|
while (!usedPaths.empty()) {
|
||||||
|
StringSet::iterator i = usedPaths.begin();
|
||||||
|
string path = *i;
|
||||||
|
usedPaths.erase(i);
|
||||||
|
|
||||||
|
ElemMap::iterator j = inMap.find(path);
|
||||||
|
if (j == inMap.end()) abort();
|
||||||
|
|
||||||
|
donePaths.insert(j->second.id);
|
||||||
|
|
||||||
|
fs.slice.elems.push_back(j->second);
|
||||||
|
|
||||||
|
for (FSIds::iterator k = j->second.refs.begin();
|
||||||
|
k != j->second.refs.end(); k++)
|
||||||
|
if (donePaths.find(*k) == donePaths.end()) {
|
||||||
|
/* !!! performance */
|
||||||
|
bool found = false;
|
||||||
|
for (ElemMap::iterator l = inMap.begin();
|
||||||
|
l != inMap.end(); l++)
|
||||||
|
if (l->second.id == *k) {
|
||||||
|
usedPaths.insert(l->first);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
if (!found) abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For debugging, print out the referenced and unreferenced paths. */
|
||||||
for (ElemMap::iterator i = inMap.begin();
|
for (ElemMap::iterator i = inMap.begin();
|
||||||
i != inMap.end(); i++)
|
i != inMap.end(); i++)
|
||||||
{
|
{
|
||||||
FSIdSet::iterator j = used.find(i->second.id);
|
FSIdSet::iterator j = donePaths.find(i->second.id);
|
||||||
if (j == used.end())
|
if (j == donePaths.end())
|
||||||
debug(format("NOT referenced: `%1%'") % i->second.path);
|
debug(format("NOT referenced: `%1%'") % i->second.path);
|
||||||
else {
|
else
|
||||||
debug(format("referenced: `%1%'") % i->second.path);
|
debug(format("referenced: `%1%'") % i->second.path);
|
||||||
fs.slice.elems.push_back(i->second);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write the normal form. This does not have to occur in the
|
/* Write the normal form. This does not have to occur in the
|
||||||
|
|
Loading…
Reference in a new issue