mirror of
https://github.com/NixOS/nix.git
synced 2025-11-26 04:00:59 +01:00
* Maintain the references graph again.
* Only build a derivation if there are no trusted output paths in the equivalence classes for that derivation's outputs. * Set the trust ID to the current user name, or use the value of the NIX_USER_ID environment variable.
This commit is contained in:
parent
75454567f7
commit
89635e16ba
14 changed files with 179 additions and 162 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
#include "build.hh"
|
#include "build.hh"
|
||||||
#include "eval.hh"
|
#include "eval.hh"
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
|
#include "misc.hh"
|
||||||
#include "nixexpr-ast.hh"
|
#include "nixexpr-ast.hh"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -144,6 +144,17 @@ static void initAndRun(int argc, char * * argv)
|
||||||
improve. */
|
improve. */
|
||||||
srand(time(0));
|
srand(time(0));
|
||||||
|
|
||||||
|
/* Set the trust ID to the user name. */
|
||||||
|
currentTrustId = getEnv("NIX_USER_ID"); /* !!! dangerous? */
|
||||||
|
if (currentTrustId == "") {
|
||||||
|
SwitchToOriginalUser sw;
|
||||||
|
uid_t uid = geteuid();
|
||||||
|
struct passwd * pw = getpwuid(uid);
|
||||||
|
if (!pw) throw Error(format("unknown user ID %1%, go away") % uid);
|
||||||
|
currentTrustId = pw->pw_name;
|
||||||
|
}
|
||||||
|
printMsg(lvlError, format("trust ID is `%1%'") % currentTrustId);
|
||||||
|
|
||||||
/* Put the arguments in a vector. */
|
/* Put the arguments in a vector. */
|
||||||
Strings args, remaining;
|
Strings args, remaining;
|
||||||
while (argc--) args.push_back(*argv++);
|
while (argc--) args.push_back(*argv++);
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ noinst_LIBRARIES = libstore.a
|
||||||
|
|
||||||
libstore_a_SOURCES = \
|
libstore_a_SOURCES = \
|
||||||
store.cc store.hh derivations.cc derivations.hh \
|
store.cc store.hh derivations.cc derivations.hh \
|
||||||
build.cc misc.cc build.hh \
|
build.cc build.hh misc.cc misc.hh \
|
||||||
globals.cc globals.hh db.cc db.hh \
|
globals.cc globals.hh db.cc db.hh \
|
||||||
references.cc references.hh pathlocks.cc pathlocks.hh \
|
references.cc references.hh pathlocks.cc pathlocks.hh \
|
||||||
gc.cc gc.hh derivations-ast.hh
|
gc.cc gc.hh derivations-ast.hh
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
#include "pathlocks.hh"
|
#include "pathlocks.hh"
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
#include "gc.hh"
|
#include "gc.hh"
|
||||||
|
#include "misc.hh"
|
||||||
|
|
||||||
|
|
||||||
/* !!! TODO derivationFromPath shouldn't be used here */
|
/* !!! TODO derivationFromPath shouldn't be used here */
|
||||||
|
|
@ -409,7 +410,8 @@ private:
|
||||||
void writeLog(int fd, const unsigned char * buf, size_t count);
|
void writeLog(int fd, const unsigned char * buf, size_t count);
|
||||||
|
|
||||||
/* Return the set of (in)valid paths. */
|
/* Return the set of (in)valid paths. */
|
||||||
PathSet checkPathValidity(bool returnValid);
|
typedef set<OutputEqClass> OutputEqClasses;
|
||||||
|
OutputEqClasses checkOutputValidity(bool returnValid);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -477,9 +479,11 @@ void DerivationGoal::haveStoreExpr()
|
||||||
for (DerivationOutputs::iterator i = drv.outputs.begin();
|
for (DerivationOutputs::iterator i = drv.outputs.begin();
|
||||||
i != drv.outputs.end(); ++i)
|
i != drv.outputs.end(); ++i)
|
||||||
addTempRoot(i->second.path);
|
addTempRoot(i->second.path);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Check what outputs paths are not already valid. */
|
/* Check for what output path equivalence classes we do not
|
||||||
PathSet invalidOutputs = checkPathValidity(false);
|
already have valid, trusted output paths. */
|
||||||
|
OutputEqClasses invalidOutputs = checkOutputValidity(false);
|
||||||
|
|
||||||
/* If they are all valid, then we're done. */
|
/* If they are all valid, then we're done. */
|
||||||
if (invalidOutputs.size() == 0) {
|
if (invalidOutputs.size() == 0) {
|
||||||
|
|
@ -487,6 +491,7 @@ void DerivationGoal::haveStoreExpr()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* We are first going to try to create the invalid output paths
|
/* We are first going to try to create the invalid output paths
|
||||||
through substitutes. If that doesn't work, we'll build
|
through substitutes. If that doesn't work, we'll build
|
||||||
them. */
|
them. */
|
||||||
|
|
@ -514,12 +519,10 @@ void DerivationGoal::outputsSubstituted()
|
||||||
|
|
||||||
nrFailed = 0;
|
nrFailed = 0;
|
||||||
|
|
||||||
#if 0
|
if (checkOutputValidity(false).size() == 0) {
|
||||||
if (checkPathValidity(false).size() == 0) {
|
|
||||||
amDone(true);
|
amDone(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Otherwise, at least one of the output paths could not be
|
/* Otherwise, at least one of the output paths could not be
|
||||||
produced using a substitute. So we have to build instead. */
|
produced using a substitute. So we have to build instead. */
|
||||||
|
|
@ -904,6 +907,9 @@ void DerivationGoal::terminateBuildHook()
|
||||||
|
|
||||||
bool DerivationGoal::prepareBuild()
|
bool DerivationGoal::prepareBuild()
|
||||||
{
|
{
|
||||||
|
/* We direct each output of the derivation to a temporary location
|
||||||
|
in the Nix store. Afterwards, we move the outputs to their
|
||||||
|
final, content-addressed location. */
|
||||||
for (DerivationOutputs::iterator i = drv.outputs.begin();
|
for (DerivationOutputs::iterator i = drv.outputs.begin();
|
||||||
i != drv.outputs.end(); ++i)
|
i != drv.outputs.end(); ++i)
|
||||||
{
|
{
|
||||||
|
|
@ -911,8 +917,20 @@ bool DerivationGoal::prepareBuild()
|
||||||
printMsg(lvlError, format("mapping output id `%1%', class `%2%' to `%3%'")
|
printMsg(lvlError, format("mapping output id `%1%', class `%2%' to `%3%'")
|
||||||
% i->first % i->second.eqClass % tmpPath);
|
% i->first % i->second.eqClass % tmpPath);
|
||||||
assert(i->second.eqClass.size() == tmpPath.size());
|
assert(i->second.eqClass.size() == tmpPath.size());
|
||||||
rewrites[hashPartOf(i->second.eqClass)] = hashPartOf(tmpPath);
|
|
||||||
|
debug(format("building path `%1%'") % tmpPath);
|
||||||
|
|
||||||
tmpOutputs[i->second.eqClass] = tmpPath;
|
tmpOutputs[i->second.eqClass] = tmpPath;
|
||||||
|
|
||||||
|
/* This is a referenceable path. Make a note of that for when
|
||||||
|
we are scanning for references in the output. */
|
||||||
|
allPaths.insert(tmpPath);
|
||||||
|
|
||||||
|
/* The environment variables and command-line arguments of the
|
||||||
|
builder refer to the output path equivalence class. Cause
|
||||||
|
those references to be rewritten to the temporary
|
||||||
|
locations. */
|
||||||
|
rewrites[hashPartOf(i->second.eqClass)] = hashPartOf(tmpPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Obtain locks on all output paths. The locks are automatically
|
/* Obtain locks on all output paths. The locks are automatically
|
||||||
|
|
@ -948,19 +966,6 @@ bool DerivationGoal::prepareBuild()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Gather information necessary for computing the closure and/or
|
|
||||||
running the build hook. */
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* The outputs are referenceable paths. */
|
|
||||||
for (DerivationOutputs::iterator i = drv.outputs.begin();
|
|
||||||
i != drv.outputs.end(); ++i)
|
|
||||||
{
|
|
||||||
debug(format("building path `%1%'") % i->second.path);
|
|
||||||
allPaths.insert(i->second.path);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Determine the full set of input paths. */
|
/* Determine the full set of input paths. */
|
||||||
|
|
||||||
/* First, the input derivations. */
|
/* First, the input derivations. */
|
||||||
|
|
@ -972,30 +977,19 @@ bool DerivationGoal::prepareBuild()
|
||||||
that are specified as inputs. */
|
that are specified as inputs. */
|
||||||
assert(isValidPath(i->first));
|
assert(isValidPath(i->first));
|
||||||
Derivation inDrv = derivationFromPath(i->first);
|
Derivation inDrv = derivationFromPath(i->first);
|
||||||
|
|
||||||
for (StringSet::iterator j = i->second.begin();
|
for (StringSet::iterator j = i->second.begin();
|
||||||
j != i->second.end(); ++j)
|
j != i->second.end(); ++j)
|
||||||
|
{
|
||||||
if (inDrv.outputs.find(*j) != inDrv.outputs.end()) {
|
OutputEqClass eqClass = findOutputEqClass(inDrv, *j);
|
||||||
|
Path input = findTrustedEqClassMember(eqClass, currentTrustId);
|
||||||
OutputEqClass eqClass = inDrv.outputs[*j].eqClass;
|
if (input == "")
|
||||||
OutputEqMembers members;
|
throw Error(format("output `%1%' of derivation `%2%' is missing!")
|
||||||
queryOutputEqMembers(noTxn, eqClass, members);
|
% *j % i->first);
|
||||||
|
|
||||||
if (members.size() == 0)
|
|
||||||
throw Error(format("output equivalence class `%1%' has no members!")
|
|
||||||
% eqClass);
|
|
||||||
|
|
||||||
Path input = members.front().path;
|
|
||||||
|
|
||||||
rewrites[hashPartOf(eqClass)] = hashPartOf(input);
|
rewrites[hashPartOf(eqClass)] = hashPartOf(input);
|
||||||
|
|
||||||
#if 0
|
computeFSClosure(input, inputPaths);
|
||||||
computeFSClosure(inDrv.outputs[*j].path, inputPaths);
|
}
|
||||||
#endif
|
|
||||||
} else
|
|
||||||
throw Error(
|
|
||||||
format("derivation `%1%' requires non-existent output `%2%' from input derivation `%3%'")
|
|
||||||
% drvPath % *j % i->first);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Second, the input sources. */
|
/* Second, the input sources. */
|
||||||
|
|
@ -1003,7 +997,7 @@ bool DerivationGoal::prepareBuild()
|
||||||
i != drv.inputSrcs.end(); ++i)
|
i != drv.inputSrcs.end(); ++i)
|
||||||
computeFSClosure(*i, inputPaths);
|
computeFSClosure(*i, inputPaths);
|
||||||
|
|
||||||
debug(format("added input paths %1%") % showPaths(inputPaths));
|
printMsg(lvlError, format("added input paths %1%") % showPaths(inputPaths)); /* !!! */
|
||||||
|
|
||||||
allPaths.insert(inputPaths.begin(), inputPaths.end());
|
allPaths.insert(inputPaths.begin(), inputPaths.end());
|
||||||
|
|
||||||
|
|
@ -1014,7 +1008,7 @@ bool DerivationGoal::prepareBuild()
|
||||||
void DerivationGoal::startBuilder()
|
void DerivationGoal::startBuilder()
|
||||||
{
|
{
|
||||||
startNest(nest, lvlInfo,
|
startNest(nest, lvlInfo,
|
||||||
format("building path(s) XXX") /* % showPaths(outputPaths(drv.outputs)) */)
|
format("building derivation `%1%'") % drvPath)
|
||||||
|
|
||||||
/* Right platform? */
|
/* Right platform? */
|
||||||
if (drv.platform != thisSystem)
|
if (drv.platform != thisSystem)
|
||||||
|
|
@ -1151,43 +1145,16 @@ void DerivationGoal::computeClosure()
|
||||||
map<Path, PathSet> allReferences;
|
map<Path, PathSet> allReferences;
|
||||||
map<Path, Hash> contentHashes;
|
map<Path, Hash> contentHashes;
|
||||||
|
|
||||||
for (OutputMap::iterator i = tmpOutputs.begin();
|
|
||||||
i != tmpOutputs.end(); ++i)
|
|
||||||
{
|
|
||||||
/* Rewrite each output to a name matching its content hash.
|
|
||||||
I.e., enforce the hash invariant: the hash part of a store
|
|
||||||
path matches the contents at that path. */
|
|
||||||
Path finalPath = addToStore(i->second, hashPartOf(i->second),
|
|
||||||
namePartOf(i->second));
|
|
||||||
printMsg(lvlError, format("produced final path `%1%'") % finalPath);
|
|
||||||
|
|
||||||
/* Register the fact that this output path is a member of some
|
|
||||||
output path equivalence class (for a certain user, at
|
|
||||||
least). This is how subsequent derivations will be able to
|
|
||||||
find it. */
|
|
||||||
Transaction txn;
|
|
||||||
createStoreTransaction(txn);
|
|
||||||
addOutputEqMember(txn, i->first, "root", finalPath);
|
|
||||||
txn.commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* Check whether the output paths were created, and grep each
|
|
||||||
output path to determine what other paths it references. Also make all
|
|
||||||
output paths read-only. */
|
|
||||||
for (DerivationOutputs::iterator i = drv.outputs.begin();
|
for (DerivationOutputs::iterator i = drv.outputs.begin();
|
||||||
i != drv.outputs.end(); ++i)
|
i != drv.outputs.end(); ++i)
|
||||||
{
|
{
|
||||||
Path path = i->second.path;
|
Path path = tmpOutputs[i->second.eqClass];
|
||||||
if (!pathExists(path)) {
|
if (!pathExists(path)) {
|
||||||
throw BuildError(
|
throw BuildError(
|
||||||
format("builder for `%1%' failed to produce output path `%2%'")
|
format("builder for `%1%' failed to produce output path `%2%'")
|
||||||
% drvPath % path);
|
% drvPath % path);
|
||||||
}
|
}
|
||||||
|
|
||||||
startNest(nest, lvlTalkative,
|
|
||||||
format("scanning for references inside `%1%'") % path);
|
|
||||||
|
|
||||||
/* Check that fixed-output derivations produced the right
|
/* Check that fixed-output derivations produced the right
|
||||||
outputs (i.e., the content hash should match the specified
|
outputs (i.e., the content hash should match the specified
|
||||||
hash). */
|
hash). */
|
||||||
|
|
@ -1225,64 +1192,50 @@ void DerivationGoal::computeClosure()
|
||||||
% path % algo % printHash(h) % printHash(h2));
|
% path % algo % printHash(h) % printHash(h2));
|
||||||
}
|
}
|
||||||
|
|
||||||
canonicalisePathMetaData(path);
|
/* For this output path, find the references to other paths
|
||||||
|
contained in it. */
|
||||||
/* For this output path, find the references to other paths contained
|
PathSet referenced;
|
||||||
in it. */
|
|
||||||
PathSet references;
|
|
||||||
if (!pathExists(path + "/nix-support/no-scan")) {
|
if (!pathExists(path + "/nix-support/no-scan")) {
|
||||||
Paths references2;
|
Paths referenced2 = filterReferences(path,
|
||||||
references2 = filterReferences(path,
|
|
||||||
Paths(allPaths.begin(), allPaths.end()));
|
Paths(allPaths.begin(), allPaths.end()));
|
||||||
references = PathSet(references2.begin(), references2.end());
|
referenced = PathSet(referenced2.begin(), referenced2.end());
|
||||||
|
|
||||||
/* For debugging, print out the referenced and
|
/* For debugging, print out the referenced and
|
||||||
unreferenced paths. */
|
unreferenced paths. */
|
||||||
for (PathSet::iterator i = inputPaths.begin();
|
PathSet unreferenced;
|
||||||
i != inputPaths.end(); ++i)
|
insert_iterator<PathSet> ins(unreferenced, unreferenced.begin());
|
||||||
{
|
set_difference(
|
||||||
PathSet::iterator j = references.find(*i);
|
inputPaths.begin(), inputPaths.end(),
|
||||||
if (j == references.end())
|
referenced.begin(), referenced.end(), ins);
|
||||||
debug(format("unreferenced input: `%1%'") % *i);
|
printMsg(lvlError, format("unreferenced inputs: %1%") % showPaths(unreferenced));
|
||||||
else
|
printMsg(lvlError, format("referenced inputs: %1%") % showPaths(referenced));
|
||||||
debug(format("referenced input: `%1%'") % *i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
allReferences[path] = references;
|
/* Rewrite each output to a name matching its content hash.
|
||||||
|
I.e., enforce the hash invariant: the hash part of a store
|
||||||
|
path matches the contents at that path.
|
||||||
|
|
||||||
/* Hash the contents of the path. The hash is stored in the
|
This also registers the final output path as valid, and
|
||||||
database so that we can verify later on whether nobody has
|
sets it references. */
|
||||||
messed with the store. !!! inefficient: it would be nice
|
Path finalPath = addToStore(path,
|
||||||
if we could combine this with filterReferences(). */
|
hashPartOf(path), namePartOf(path),
|
||||||
contentHashes[path] = hashPath(htSHA256, path);
|
referenced);
|
||||||
}
|
printMsg(lvlError, format("produced final path `%1%'") % finalPath);
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0
|
/* Register the fact that this output path is a member of some
|
||||||
/* Register each output path as valid, and register the sets of
|
output path equivalence class (for a certain user, at
|
||||||
paths referenced by each of them. This is wrapped in one
|
least). This is how subsequent derivations will be able to
|
||||||
database transaction to ensure that if we crash, either
|
find it. */
|
||||||
everything is registered or nothing is. This is for
|
|
||||||
recoverability: unregistered paths in the store can be deleted
|
|
||||||
arbitrarily, while registered paths can only be deleted by
|
|
||||||
running the garbage collector.
|
|
||||||
|
|
||||||
The reason that we do the transaction here and not on the fly
|
|
||||||
while we are scanning (above) is so that we don't hold database
|
|
||||||
locks for too long. */
|
|
||||||
Transaction txn;
|
Transaction txn;
|
||||||
createStoreTransaction(txn);
|
createStoreTransaction(txn);
|
||||||
for (DerivationOutputs::iterator i = drv.outputs.begin();
|
addOutputEqMember(txn, i->second.eqClass, currentTrustId, finalPath);
|
||||||
i != drv.outputs.end(); ++i)
|
|
||||||
{
|
|
||||||
registerValidPath(txn, i->second.path,
|
|
||||||
contentHashes[i->second.path],
|
|
||||||
allReferences[i->second.path],
|
|
||||||
drvPath);
|
|
||||||
}
|
|
||||||
txn.commit();
|
txn.commit();
|
||||||
#endif
|
|
||||||
|
/* Get rid of the temporary output. !!! optimise all this by
|
||||||
|
*moving* the temporary output to the new location and
|
||||||
|
applying rewrites in situ. */
|
||||||
|
deletePath(path);
|
||||||
|
}
|
||||||
|
|
||||||
/* It is now safe to delete the lock files, since all future
|
/* It is now safe to delete the lock files, since all future
|
||||||
lockers will see that the output paths are valid; they will not
|
lockers will see that the output paths are valid; they will not
|
||||||
|
|
@ -1363,19 +1316,21 @@ void DerivationGoal::writeLog(int fd,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PathSet DerivationGoal::checkPathValidity(bool returnValid)
|
DerivationGoal::OutputEqClasses DerivationGoal::checkOutputValidity(bool returnValid)
|
||||||
{
|
{
|
||||||
#if 0
|
OutputEqClasses result;
|
||||||
PathSet result;
|
|
||||||
for (DerivationOutputs::iterator i = drv.outputs.begin();
|
for (DerivationOutputs::iterator i = drv.outputs.begin();
|
||||||
i != drv.outputs.end(); ++i)
|
i != drv.outputs.end(); ++i)
|
||||||
if (isValidPath(i->second.path)) {
|
{
|
||||||
if (returnValid) result.insert(i->second.path);
|
Path path = findTrustedEqClassMember(i->second.eqClass, currentTrustId);
|
||||||
|
if (path != "") {
|
||||||
|
assert(isValidPath(path));
|
||||||
|
if (returnValid) result.insert(i->second.eqClass);
|
||||||
} else {
|
} else {
|
||||||
if (!returnValid) result.insert(i->second.path);
|
if (!returnValid) result.insert(i->second.eqClass);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "derivations.hh"
|
#include "derivations.hh"
|
||||||
|
|
||||||
|
|
||||||
/* Ensure that the output paths of the derivation are valid. If they
|
/* Ensure that the output paths of the derivation are valid. If they
|
||||||
are already valid, this is a no-op. Otherwise, validity can
|
are already valid, this is a no-op. Otherwise, validity can
|
||||||
be reached in two ways. First, if the output paths have
|
be reached in two ways. First, if the output paths have
|
||||||
|
|
@ -11,26 +12,10 @@
|
||||||
sub-derivations. */
|
sub-derivations. */
|
||||||
void buildDerivations(const PathSet & drvPaths);
|
void buildDerivations(const PathSet & drvPaths);
|
||||||
|
|
||||||
|
|
||||||
/* Ensure that a path is valid. If it is not currently valid, it may
|
/* Ensure that a path is valid. If it is not currently valid, it may
|
||||||
be made valid by running a substitute (if defined for the path). */
|
be made valid by running a substitute (if defined for the path). */
|
||||||
void ensurePath(const Path & storePath);
|
void ensurePath(const Path & storePath);
|
||||||
|
|
||||||
/* Read a derivation, after ensuring its existence through
|
|
||||||
ensurePath(). */
|
|
||||||
Derivation derivationFromPath(const Path & drvPath);
|
|
||||||
|
|
||||||
/* Place in `paths' the set of all store paths in the file system
|
|
||||||
closure of `storePath'; that is, all paths than can be directly or
|
|
||||||
indirectly reached from it. `paths' is not cleared. If
|
|
||||||
`flipDirection' is true, the set of paths that can reach
|
|
||||||
`storePath' is returned; that is, the closures under the `referers'
|
|
||||||
relation instead of the `references' relation is returned. */
|
|
||||||
void computeFSClosure(const Path & storePath,
|
|
||||||
PathSet & paths, bool flipDirection = false);
|
|
||||||
|
|
||||||
/* Return the path corresponding to the output identifier `id' in the
|
|
||||||
given derivation. */
|
|
||||||
Path findOutput(const Derivation & drv, string id);
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* !__BUILD_H */
|
#endif /* !__BUILD_H */
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#include "gc.hh"
|
#include "gc.hh"
|
||||||
#include "build.hh"
|
#include "build.hh"
|
||||||
#include "pathlocks.hh"
|
#include "pathlocks.hh"
|
||||||
|
#include "misc.hh"
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,8 @@ unsigned int maxBuildJobs = 1;
|
||||||
|
|
||||||
bool readOnlyMode = false;
|
bool readOnlyMode = false;
|
||||||
|
|
||||||
|
string currentTrustId;
|
||||||
|
|
||||||
|
|
||||||
static bool settingsRead = false;
|
static bool settingsRead = false;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,10 @@ extern unsigned int maxBuildJobs;
|
||||||
database. */
|
database. */
|
||||||
extern bool readOnlyMode;
|
extern bool readOnlyMode;
|
||||||
|
|
||||||
|
/* Current trust ID. !!! Of course, this shouldn't be a global
|
||||||
|
variable. */
|
||||||
|
extern string currentTrustId;
|
||||||
|
|
||||||
|
|
||||||
string querySetting(const string & name, const string & def);
|
string querySetting(const string & name, const string & def);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,13 +29,23 @@ void computeFSClosure(const Path & storePath,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Path findOutput(const Derivation & drv, string id)
|
OutputEqClass findOutputEqClass(const Derivation & drv, const string & id)
|
||||||
{
|
{
|
||||||
assert(0);
|
DerivationOutputs::const_iterator i = drv.outputs.find(id);
|
||||||
#if 0
|
if (i == drv.outputs.end())
|
||||||
for (DerivationOutputs::const_iterator i = drv.outputs.begin();
|
|
||||||
i != drv.outputs.end(); ++i)
|
|
||||||
if (i->first == id) return i->second.path;
|
|
||||||
throw Error(format("derivation has no output `%1%'") % id);
|
throw Error(format("derivation has no output `%1%'") % id);
|
||||||
#endif
|
return i->second.eqClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Path findTrustedEqClassMember(const OutputEqClass & eqClass,
|
||||||
|
const TrustId & trustId)
|
||||||
|
{
|
||||||
|
OutputEqMembers members;
|
||||||
|
queryOutputEqMembers(noTxn, eqClass, members);
|
||||||
|
|
||||||
|
for (OutputEqMembers::iterator j = members.begin(); j != members.end(); ++j)
|
||||||
|
if (j->trustId == trustId || j->trustId == "root") return j->path;
|
||||||
|
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
36
src/libstore/misc.hh
Normal file
36
src/libstore/misc.hh
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
#ifndef __MISC_H
|
||||||
|
#define __MISC_H
|
||||||
|
|
||||||
|
#include "derivations.hh"
|
||||||
|
#include "store.hh"
|
||||||
|
|
||||||
|
|
||||||
|
/* Read a derivation, after ensuring its existence through
|
||||||
|
ensurePath(). */
|
||||||
|
Derivation derivationFromPath(const Path & drvPath);
|
||||||
|
|
||||||
|
|
||||||
|
/* Place in `paths' the set of all store paths in the file system
|
||||||
|
closure of `storePath'; that is, all paths than can be directly or
|
||||||
|
indirectly reached from it. `paths' is not cleared. If
|
||||||
|
`flipDirection' is true, the set of paths that can reach
|
||||||
|
`storePath' is returned; that is, the closures under the `referers'
|
||||||
|
relation instead of the `references' relation is returned. */
|
||||||
|
void computeFSClosure(const Path & storePath,
|
||||||
|
PathSet & paths, bool flipDirection = false);
|
||||||
|
|
||||||
|
|
||||||
|
/* Return the output equivalence class denoted by `id' in the
|
||||||
|
derivation `drv'. */
|
||||||
|
OutputEqClass findOutputEqClass(const Derivation & drv,
|
||||||
|
const string & id);
|
||||||
|
|
||||||
|
|
||||||
|
/* Return any trusted path (wrt to the given trust ID) in the given
|
||||||
|
output path equivalence class, or "" if no such path currently
|
||||||
|
exists. */
|
||||||
|
Path findTrustedEqClassMember(const OutputEqClass & eqClass,
|
||||||
|
const TrustId & trustId);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* !__MISC_H */
|
||||||
|
|
@ -842,8 +842,8 @@ static Path _addToStore(const string & suffix, string dump,
|
||||||
|
|
||||||
/* If the contents had a previous hash reference, rewrite those
|
/* If the contents had a previous hash reference, rewrite those
|
||||||
references to the new hash. */
|
references to the new hash. */
|
||||||
if (!selfHash.isNull()) {
|
|
||||||
HashRewrites rewrites;
|
HashRewrites rewrites;
|
||||||
|
if (!selfHash.isNull()) {
|
||||||
rewrites[selfHash] = pathHash;
|
rewrites[selfHash] = pathHash;
|
||||||
vector<int> positions;
|
vector<int> positions;
|
||||||
dump = rewriteHashes(dump, rewrites, positions);
|
dump = rewriteHashes(dump, rewrites, positions);
|
||||||
|
|
@ -872,8 +872,15 @@ static Path _addToStore(const string & suffix, string dump,
|
||||||
|
|
||||||
canonicalisePathMetaData(dstPath);
|
canonicalisePathMetaData(dstPath);
|
||||||
|
|
||||||
|
/* Set the references for the new path. Of course, any
|
||||||
|
hash rewrites have to be applied to the references,
|
||||||
|
too. */
|
||||||
|
PathSet references2;
|
||||||
|
for (PathSet::iterator i = references.begin(); i != references.end(); ++i)
|
||||||
|
references2.insert(rewriteHashes(*i, rewrites));
|
||||||
|
|
||||||
Transaction txn(nixDB);
|
Transaction txn(nixDB);
|
||||||
registerValidPath(txn, dstPath, contentHash, references, "");
|
registerValidPath(txn, dstPath, contentHash, references2, "");
|
||||||
txn.commit();
|
txn.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -885,7 +892,7 @@ static Path _addToStore(const string & suffix, string dump,
|
||||||
|
|
||||||
|
|
||||||
Path addToStore(const Path & _srcPath, const PathHash & selfHash,
|
Path addToStore(const Path & _srcPath, const PathHash & selfHash,
|
||||||
const string & suffix)
|
const string & suffix, const PathSet & references)
|
||||||
{
|
{
|
||||||
Path srcPath(absPath(_srcPath));
|
Path srcPath(absPath(_srcPath));
|
||||||
debug(format("adding `%1%' to the store") % srcPath);
|
debug(format("adding `%1%' to the store") % srcPath);
|
||||||
|
|
@ -897,7 +904,7 @@ Path addToStore(const Path & _srcPath, const PathHash & selfHash,
|
||||||
}
|
}
|
||||||
|
|
||||||
return _addToStore(suffix == "" ? baseNameOf(srcPath) : suffix,
|
return _addToStore(suffix == "" ? baseNameOf(srcPath) : suffix,
|
||||||
sink.s, selfHash, PathSet());
|
sink.s, selfHash, references);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -226,7 +226,7 @@ string rewriteHashes(const string & s, const HashRewrites & rewrites);
|
||||||
/* Copy the contents of a path to the store and register the validity
|
/* Copy the contents of a path to the store and register the validity
|
||||||
the resulting path. The resulting path is returned. */
|
the resulting path. The resulting path is returned. */
|
||||||
Path addToStore(const Path & srcPath, const PathHash & selfHash = PathHash(),
|
Path addToStore(const Path & srcPath, const PathHash & selfHash = PathHash(),
|
||||||
const string & suffix = "");
|
const string & suffix = "", const PathSet & references = PathSet());
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* Like addToStore(), but for pre-adding the outputs of fixed-output
|
/* Like addToStore(), but for pre-adding the outputs of fixed-output
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
#include "build.hh"
|
#include "build.hh"
|
||||||
#include "gc.hh"
|
#include "gc.hh"
|
||||||
|
#include "misc.hh"
|
||||||
#include "shared.hh"
|
#include "shared.hh"
|
||||||
#include "parser.hh"
|
#include "parser.hh"
|
||||||
#include "eval.hh"
|
#include "eval.hh"
|
||||||
|
|
@ -383,7 +384,6 @@ static void queryInstSources(EvalState & state,
|
||||||
(import ./foo.nix)' = `(import ./foo.nix).bar'. */
|
(import ./foo.nix)' = `(import ./foo.nix).bar'. */
|
||||||
case srcNixExprs: {
|
case srcNixExprs: {
|
||||||
|
|
||||||
|
|
||||||
Expr e1 = parseExprFromFile(state,
|
Expr e1 = parseExprFromFile(state,
|
||||||
absPath(instSource.nixExprPath));
|
absPath(instSource.nixExprPath));
|
||||||
|
|
||||||
|
|
@ -416,7 +416,10 @@ static void queryInstSources(EvalState & state,
|
||||||
|
|
||||||
if (isDerivation(*i)) {
|
if (isDerivation(*i)) {
|
||||||
elem.setDrvPath(*i);
|
elem.setDrvPath(*i);
|
||||||
elem.setOutPath(findOutput(derivationFromPath(*i), "out"));
|
elem.setOutPath(
|
||||||
|
/* XXX check this; may not give a result */
|
||||||
|
findTrustedEqClassMember(
|
||||||
|
findOutputEqClass(derivationFromPath(*i), "out"), currentTrustId));
|
||||||
if (name.size() >= drvExtension.size() &&
|
if (name.size() >= drvExtension.size() &&
|
||||||
string(name, name.size() - drvExtension.size()) == drvExtension)
|
string(name, name.size() - drvExtension.size()) == drvExtension)
|
||||||
name = string(name, 0, name.size() - drvExtension.size());
|
name = string(name, 0, name.size() - drvExtension.size());
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
#include "build.hh"
|
#include "build.hh"
|
||||||
#include "gc.hh"
|
#include "gc.hh"
|
||||||
|
#include "misc.hh"
|
||||||
#include "archive.hh"
|
#include "archive.hh"
|
||||||
#include "shared.hh"
|
#include "shared.hh"
|
||||||
#include "dotgraph.hh"
|
#include "dotgraph.hh"
|
||||||
|
|
@ -45,7 +46,8 @@ static Path realisePath(const Path & path)
|
||||||
PathSet paths;
|
PathSet paths;
|
||||||
paths.insert(path);
|
paths.insert(path);
|
||||||
buildDerivations(paths);
|
buildDerivations(paths);
|
||||||
Path outPath = findOutput(derivationFromPath(path), "out");
|
Path outPath = findTrustedEqClassMember(
|
||||||
|
findOutputEqClass(derivationFromPath(path), "out"), currentTrustId);
|
||||||
|
|
||||||
if (gcRoot == "")
|
if (gcRoot == "")
|
||||||
printGCWarning();
|
printGCWarning();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue