* 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:
Eelco Dolstra 2003-08-20 11:30:45 +00:00
parent 1472cc4825
commit ed0db2e0d8

View file

@ -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