Refactor settings processing
Put all Nix configuration flags in a Settings object.
This commit is contained in:
parent
d50d7a2874
commit
97421eb5ec
19 changed files with 596 additions and 552 deletions
|
@ -19,7 +19,7 @@ void doInit()
|
|||
{
|
||||
if (!store) {
|
||||
try {
|
||||
setDefaultsFromEnvironment();
|
||||
settings.processEnvironment();
|
||||
store = openStore();
|
||||
} catch (Error & e) {
|
||||
croak(e.what());
|
||||
|
|
|
@ -179,7 +179,7 @@ EvalState::EvalState()
|
|||
searchPathInsertionPoint = searchPath.end();
|
||||
Strings paths = tokenizeString(getEnv("NIX_PATH", ""), ":");
|
||||
foreach (Strings::iterator, i, paths) addToSearchPath(*i);
|
||||
addToSearchPath("nix=" + nixDataDir + "/nix/corepkgs");
|
||||
addToSearchPath("nix=" + settings.nixDataDir + "/nix/corepkgs");
|
||||
searchPathInsertionPoint = searchPath.begin();
|
||||
|
||||
createBaseEnv();
|
||||
|
@ -1058,7 +1058,7 @@ string EvalState::coerceToString(Value & v, PathSet & context,
|
|||
if (srcToStore[path] != "")
|
||||
dstPath = srcToStore[path];
|
||||
else {
|
||||
dstPath = readOnlyMode
|
||||
dstPath = settings.readOnlyMode
|
||||
? computeStorePathForPath(path).first
|
||||
: store->addToStore(path);
|
||||
srcToStore[path] = dstPath;
|
||||
|
|
|
@ -623,7 +623,7 @@ static void prim_toFile(EvalState & state, Value * * args, Value & v)
|
|||
refs.insert(path);
|
||||
}
|
||||
|
||||
Path storePath = readOnlyMode
|
||||
Path storePath = settings.readOnlyMode
|
||||
? computeStorePathForText(name, contents, refs)
|
||||
: store->addTextToStore(name, contents, refs);
|
||||
|
||||
|
@ -687,7 +687,7 @@ static void prim_filterSource(EvalState & state, Value * * args, Value & v)
|
|||
|
||||
FilterFromExpr filter(state, *args[0]);
|
||||
|
||||
Path dstPath = readOnlyMode
|
||||
Path dstPath = settings.readOnlyMode
|
||||
? computeStorePathForPath(path, true, htSHA256, filter).first
|
||||
: store->addToStore(path, true, htSHA256, filter);
|
||||
|
||||
|
@ -1079,7 +1079,7 @@ void EvalState::createBaseEnv()
|
|||
mkInt(v, time(0));
|
||||
addConstant("__currentTime", v);
|
||||
|
||||
mkString(v, thisSystem.c_str());
|
||||
mkString(v, settings.thisSystem.c_str());
|
||||
addConstant("__currentSystem", v);
|
||||
|
||||
// Miscellaneous
|
||||
|
|
|
@ -74,7 +74,7 @@ void printMissing(StoreAPI & store, const PathSet & paths)
|
|||
|
||||
if (!unknown.empty()) {
|
||||
printMsg(lvlInfo, format("don't know how to build these paths%1%:")
|
||||
% (readOnlyMode ? " (may be caused by read-only store access)" : ""));
|
||||
% (settings.readOnlyMode ? " (may be caused by read-only store access)" : ""));
|
||||
foreach (PathSet::iterator, i, unknown)
|
||||
printMsg(lvlInfo, format(" %1%") % *i);
|
||||
}
|
||||
|
@ -93,11 +93,20 @@ static void setLogType(string lt)
|
|||
static bool showTrace = false;
|
||||
|
||||
|
||||
string getArg(const string & opt,
|
||||
Strings::iterator & i, const Strings::iterator & end)
|
||||
{
|
||||
++i;
|
||||
if (i == end) throw UsageError(format("`%1%' requires an argument") % opt);
|
||||
return *i;
|
||||
}
|
||||
|
||||
/* Initialize and reorder arguments, then call the actual argument
|
||||
processor. */
|
||||
static void initAndRun(int argc, char * * argv)
|
||||
{
|
||||
setDefaultsFromEnvironment();
|
||||
settings.processEnvironment();
|
||||
settings.loadConfFile();
|
||||
|
||||
/* Catch SIGINT. */
|
||||
struct sigaction act;
|
||||
|
@ -156,20 +165,19 @@ static void initAndRun(int argc, char * * argv)
|
|||
remaining.clear();
|
||||
|
||||
/* Process default options. */
|
||||
int verbosityDelta = 0;
|
||||
int verbosityDelta = lvlInfo;
|
||||
for (Strings::iterator i = args.begin(); i != args.end(); ++i) {
|
||||
string arg = *i;
|
||||
if (arg == "--verbose" || arg == "-v") verbosityDelta++;
|
||||
else if (arg == "--quiet") verbosityDelta--;
|
||||
else if (arg == "--log-type") {
|
||||
++i;
|
||||
if (i == args.end()) throw UsageError("`--log-type' requires an argument");
|
||||
setLogType(*i);
|
||||
string s = getArg(arg, i, args.end());
|
||||
setLogType(s);
|
||||
}
|
||||
else if (arg == "--no-build-output" || arg == "-Q")
|
||||
buildVerbosity = lvlVomit;
|
||||
settings.buildVerbosity = lvlVomit;
|
||||
else if (arg == "--print-build-trace")
|
||||
printBuildTrace = true;
|
||||
settings.printBuildTrace = true;
|
||||
else if (arg == "--help") {
|
||||
printHelp();
|
||||
return;
|
||||
|
@ -179,23 +187,23 @@ static void initAndRun(int argc, char * * argv)
|
|||
return;
|
||||
}
|
||||
else if (arg == "--keep-failed" || arg == "-K")
|
||||
keepFailed = true;
|
||||
settings.keepFailed = true;
|
||||
else if (arg == "--keep-going" || arg == "-k")
|
||||
keepGoing = true;
|
||||
settings.keepGoing = true;
|
||||
else if (arg == "--fallback")
|
||||
tryFallback = true;
|
||||
settings.tryFallback = true;
|
||||
else if (arg == "--max-jobs" || arg == "-j")
|
||||
maxBuildJobs = getIntArg<unsigned int>(arg, i, args.end());
|
||||
settings.set("build-max-jobs", getArg(arg, i, args.end()));
|
||||
else if (arg == "--cores")
|
||||
buildCores = getIntArg<unsigned int>(arg, i, args.end());
|
||||
settings.set("build-cores", getArg(arg, i, args.end()));
|
||||
else if (arg == "--readonly-mode")
|
||||
readOnlyMode = true;
|
||||
settings.readOnlyMode = true;
|
||||
else if (arg == "--max-silent-time")
|
||||
maxSilentTime = getIntArg<unsigned int>(arg, i, args.end());
|
||||
settings.set("build-max-silent-time", getArg(arg, i, args.end()));
|
||||
else if (arg == "--timeout")
|
||||
buildTimeout = getIntArg<unsigned int>(arg, i, args.end());
|
||||
settings.set("build-timeout", getArg(arg, i, args.end()));
|
||||
else if (arg == "--no-build-hook")
|
||||
useBuildHook = false;
|
||||
settings.useBuildHook = false;
|
||||
else if (arg == "--show-trace")
|
||||
showTrace = true;
|
||||
else if (arg == "--option") {
|
||||
|
@ -203,14 +211,15 @@ static void initAndRun(int argc, char * * argv)
|
|||
string name = *i;
|
||||
++i; if (i == args.end()) throw UsageError("`--option' requires two arguments");
|
||||
string value = *i;
|
||||
overrideSetting(name, tokenizeString(value));
|
||||
settings.set(name, value);
|
||||
}
|
||||
else remaining.push_back(arg);
|
||||
}
|
||||
|
||||
verbosityDelta += queryIntSetting("verbosity", lvlInfo);
|
||||
verbosity = (Verbosity) (verbosityDelta < 0 ? 0 : verbosityDelta);
|
||||
|
||||
settings.update();
|
||||
|
||||
run(remaining);
|
||||
|
||||
/* Close the Nix database. */
|
||||
|
|
|
@ -229,8 +229,6 @@ private:
|
|||
|
||||
public:
|
||||
|
||||
bool cacheFailure;
|
||||
|
||||
/* Set if at least one derivation had a BuildError (i.e. permanent
|
||||
failure). */
|
||||
bool permanentFailure;
|
||||
|
@ -314,7 +312,7 @@ void Goal::waiteeDone(GoalPtr waitee, ExitCode result)
|
|||
|
||||
if (result == ecNoSubstituters) ++nrNoSubstituters;
|
||||
|
||||
if (waitees.empty() || (result == ecFailed && !keepGoing)) {
|
||||
if (waitees.empty() || (result == ecFailed && !settings.keepGoing)) {
|
||||
|
||||
/* If we failed and keepGoing is not set, we remove all
|
||||
remaining waitees. */
|
||||
|
@ -466,14 +464,13 @@ void UserLock::acquire()
|
|||
{
|
||||
assert(uid == 0);
|
||||
|
||||
string buildUsersGroup = querySetting("build-users-group", "");
|
||||
assert(buildUsersGroup != "");
|
||||
assert(settings.buildUsersGroup != "");
|
||||
|
||||
/* Get the members of the build-users-group. */
|
||||
struct group * gr = getgrnam(buildUsersGroup.c_str());
|
||||
struct group * gr = getgrnam(settings.buildUsersGroup.c_str());
|
||||
if (!gr)
|
||||
throw Error(format("the group `%1%' specified in `build-users-group' does not exist")
|
||||
% buildUsersGroup);
|
||||
% settings.buildUsersGroup);
|
||||
gid = gr->gr_gid;
|
||||
|
||||
/* Copy the result of getgrnam. */
|
||||
|
@ -485,7 +482,7 @@ void UserLock::acquire()
|
|||
|
||||
if (users.empty())
|
||||
throw Error(format("the build users group `%1%' has no members")
|
||||
% buildUsersGroup);
|
||||
% settings.buildUsersGroup);
|
||||
|
||||
/* Find a user account that isn't currently in use for another
|
||||
build. */
|
||||
|
@ -495,11 +492,11 @@ void UserLock::acquire()
|
|||
struct passwd * pw = getpwnam(i->c_str());
|
||||
if (!pw)
|
||||
throw Error(format("the user `%1%' in the group `%2%' does not exist")
|
||||
% *i % buildUsersGroup);
|
||||
% *i % settings.buildUsersGroup);
|
||||
|
||||
createDirs(nixStateDir + "/userpool");
|
||||
createDirs(settings.nixStateDir + "/userpool");
|
||||
|
||||
fnUserLock = (format("%1%/userpool/%2%") % nixStateDir % pw->pw_uid).str();
|
||||
fnUserLock = (format("%1%/userpool/%2%") % settings.nixStateDir % pw->pw_uid).str();
|
||||
|
||||
if (lockedPaths.find(fnUserLock) != lockedPaths.end())
|
||||
/* We already have a lock on this one. */
|
||||
|
@ -519,7 +516,7 @@ void UserLock::acquire()
|
|||
/* Sanity check... */
|
||||
if (uid == getuid() || uid == geteuid())
|
||||
throw Error(format("the Nix user should not be a member of `%1%'")
|
||||
% buildUsersGroup);
|
||||
% settings.buildUsersGroup);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -527,7 +524,7 @@ void UserLock::acquire()
|
|||
|
||||
throw Error(format("all build users are currently in use; "
|
||||
"consider creating additional users and adding them to the `%1%' group")
|
||||
% buildUsersGroup);
|
||||
% settings.buildUsersGroup);
|
||||
}
|
||||
|
||||
|
||||
|
@ -546,7 +543,7 @@ static void runSetuidHelper(const string & command,
|
|||
const string & arg)
|
||||
{
|
||||
Path program = getEnv("NIX_SETUID_HELPER",
|
||||
nixLibexecDir + "/nix-setuid-helper");
|
||||
settings.nixLibexecDir + "/nix-setuid-helper");
|
||||
|
||||
/* Fork. */
|
||||
Pid pid;
|
||||
|
@ -601,12 +598,6 @@ bool amPrivileged()
|
|||
}
|
||||
|
||||
|
||||
bool haveBuildUsers()
|
||||
{
|
||||
return querySetting("build-users-group", "") != "";
|
||||
}
|
||||
|
||||
|
||||
void getOwnership(const Path & path)
|
||||
{
|
||||
runSetuidHelper("get-ownership", path);
|
||||
|
@ -622,7 +613,7 @@ void deletePathWrapped(const Path & path,
|
|||
} catch (SysError & e) {
|
||||
/* If this failed due to a permission error, then try it with
|
||||
the setuid helper. */
|
||||
if (haveBuildUsers() && !amPrivileged()) {
|
||||
if (settings.buildUsersGroup != "" && !amPrivileged()) {
|
||||
getOwnership(path);
|
||||
deletePath(path, bytesFreed, blocksFreed);
|
||||
} else
|
||||
|
@ -701,9 +692,9 @@ HookInstance::HookInstance()
|
|||
throw SysError("dupping builder's stdout/stderr");
|
||||
|
||||
/* XXX: Pass `buildTimeout' to the hook? */
|
||||
execl(buildHook.c_str(), buildHook.c_str(), thisSystem.c_str(),
|
||||
(format("%1%") % maxSilentTime).str().c_str(),
|
||||
(format("%1%") % printBuildTrace).str().c_str(),
|
||||
execl(buildHook.c_str(), buildHook.c_str(), settings.thisSystem.c_str(),
|
||||
(format("%1%") % settings.maxSilentTime).str().c_str(),
|
||||
(format("%1%") % settings.printBuildTrace).str().c_str(),
|
||||
NULL);
|
||||
|
||||
throw SysError(format("executing `%1%'") % buildHook);
|
||||
|
@ -943,7 +934,7 @@ void DerivationGoal::init()
|
|||
{
|
||||
trace("init");
|
||||
|
||||
if (readOnlyMode)
|
||||
if (settings.readOnlyMode)
|
||||
throw Error(format("cannot build derivation `%1%' - no write access to the Nix store") % drvPath);
|
||||
|
||||
/* The first thing to do is to make sure that the derivation
|
||||
|
@ -995,7 +986,7 @@ void DerivationGoal::haveDerivation()
|
|||
/* We are first going to try to create the invalid output paths
|
||||
through substitutes. If that doesn't work, we'll build
|
||||
them. */
|
||||
if (queryBoolSetting("build-use-substitutes", true))
|
||||
if (settings.useSubstitutes)
|
||||
foreach (PathSet::iterator, i, invalidOutputs)
|
||||
addWaitee(worker.makeSubstitutionGoal(*i));
|
||||
|
||||
|
@ -1010,7 +1001,7 @@ void DerivationGoal::outputsSubstituted()
|
|||
{
|
||||
trace("all outputs substituted (maybe)");
|
||||
|
||||
if (nrFailed > 0 && nrFailed > nrNoSubstituters && !tryFallback)
|
||||
if (nrFailed > 0 && nrFailed > nrNoSubstituters && !settings.tryFallback)
|
||||
throw Error(format("some substitutes for the outputs of derivation `%1%' failed; try `--fallback'") % drvPath);
|
||||
|
||||
nrFailed = nrNoSubstituters = 0;
|
||||
|
@ -1109,9 +1100,9 @@ PathSet outputPaths(const DerivationOutputs & outputs)
|
|||
|
||||
static bool canBuildLocally(const string & platform)
|
||||
{
|
||||
return platform == thisSystem
|
||||
return platform == settings.thisSystem
|
||||
#ifdef CAN_DO_LINUX32_BUILDS
|
||||
|| (platform == "i686-linux" && thisSystem == "x86_64-linux")
|
||||
|| (platform == "i686-linux" && settings.thisSystem == "x86_64-linux")
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
@ -1213,7 +1204,7 @@ void DerivationGoal::tryToBuild()
|
|||
derivation prefers to be done locally, do it even if
|
||||
maxBuildJobs is 0. */
|
||||
unsigned int curBuilds = worker.getNrLocalBuilds();
|
||||
if (curBuilds >= maxBuildJobs && !(preferLocalBuild && curBuilds == 0)) {
|
||||
if (curBuilds >= settings.maxBuildJobs && !(preferLocalBuild && curBuilds == 0)) {
|
||||
worker.waitForBuildSlot(shared_from_this());
|
||||
outputLocks.unlock();
|
||||
return;
|
||||
|
@ -1228,7 +1219,7 @@ void DerivationGoal::tryToBuild()
|
|||
printMsg(lvlError, e.msg());
|
||||
outputLocks.unlock();
|
||||
buildUser.release();
|
||||
if (printBuildTrace)
|
||||
if (settings.printBuildTrace)
|
||||
printMsg(lvlError, format("@ build-failed %1% %2% %3% %4%")
|
||||
% drvPath % drv.outputs["out"].path % 0 % e.msg());
|
||||
worker.permanentFailure = true;
|
||||
|
@ -1360,7 +1351,7 @@ void DerivationGoal::buildDone()
|
|||
bool hookError = hook &&
|
||||
(!WIFEXITED(status) || WEXITSTATUS(status) != 100);
|
||||
|
||||
if (printBuildTrace) {
|
||||
if (settings.printBuildTrace) {
|
||||
if (hook && hookError)
|
||||
printMsg(lvlError, format("@ hook-failed %1% %2% %3% %4%")
|
||||
% drvPath % drv.outputs["out"].path % status % e.msg());
|
||||
|
@ -1376,7 +1367,7 @@ void DerivationGoal::buildDone()
|
|||
able to access the network). Hook errors (like
|
||||
communication problems with the remote machine) shouldn't
|
||||
be cached either. */
|
||||
if (worker.cacheFailure && !hookError && !fixedOutput)
|
||||
if (settings.cacheFailure && !hookError && !fixedOutput)
|
||||
foreach (DerivationOutputs::iterator, i, drv.outputs)
|
||||
worker.store.registerFailedPath(i->second.path);
|
||||
|
||||
|
@ -1388,7 +1379,7 @@ void DerivationGoal::buildDone()
|
|||
/* Release the build user, if applicable. */
|
||||
buildUser.release();
|
||||
|
||||
if (printBuildTrace) {
|
||||
if (settings.printBuildTrace) {
|
||||
printMsg(lvlError, format("@ build-succeeded %1% %2%")
|
||||
% drvPath % drv.outputs["out"].path);
|
||||
}
|
||||
|
@ -1399,7 +1390,7 @@ void DerivationGoal::buildDone()
|
|||
|
||||
HookReply DerivationGoal::tryBuildHook()
|
||||
{
|
||||
if (!useBuildHook || getEnv("NIX_BUILD_HOOK") == "") return rpDecline;
|
||||
if (!settings.useBuildHook || getEnv("NIX_BUILD_HOOK") == "") return rpDecline;
|
||||
|
||||
if (!worker.hook)
|
||||
worker.hook = boost::shared_ptr<HookInstance>(new HookInstance);
|
||||
|
@ -1412,7 +1403,7 @@ HookReply DerivationGoal::tryBuildHook()
|
|||
|
||||
/* Send the request to the hook. */
|
||||
writeLine(worker.hook->toHook.writeSide, (format("%1% %2% %3% %4%")
|
||||
% (worker.getNrLocalBuilds() < maxBuildJobs ? "1" : "0")
|
||||
% (worker.getNrLocalBuilds() < settings.maxBuildJobs ? "1" : "0")
|
||||
% drv.platform % drvPath % concatStringsSep(",", features)).str());
|
||||
|
||||
/* Read the first line of input, which should be a word indicating
|
||||
|
@ -1471,7 +1462,7 @@ HookReply DerivationGoal::tryBuildHook()
|
|||
fds.insert(hook->builderOut.readSide);
|
||||
worker.childStarted(shared_from_this(), hook->pid, fds, false, false);
|
||||
|
||||
if (printBuildTrace)
|
||||
if (settings.printBuildTrace)
|
||||
printMsg(lvlError, format("@ build-started %1% %2% %3% %4%")
|
||||
% drvPath % drv.outputs["out"].path % drv.platform % logFile);
|
||||
|
||||
|
@ -1502,7 +1493,7 @@ void DerivationGoal::startBuilder()
|
|||
if (!canBuildLocally(drv.platform))
|
||||
throw Error(
|
||||
format("a `%1%' is required to build `%3%', but I am a `%2%'")
|
||||
% drv.platform % thisSystem % drvPath);
|
||||
% drv.platform % settings.thisSystem % drvPath);
|
||||
|
||||
/* Construct the environment passed to the builder. */
|
||||
|
||||
|
@ -1523,10 +1514,10 @@ void DerivationGoal::startBuilder()
|
|||
shouldn't care, but this is useful for purity checking (e.g.,
|
||||
the compiler or linker might only want to accept paths to files
|
||||
in the store or in the build directory). */
|
||||
env["NIX_STORE"] = nixStore;
|
||||
env["NIX_STORE"] = settings.nixStore;
|
||||
|
||||
/* The maximum number of cores to utilize for parallel building. */
|
||||
env["NIX_BUILD_CORES"] = (format("%d") % buildCores).str();
|
||||
env["NIX_BUILD_CORES"] = (format("%d") % settings.buildCores).str();
|
||||
|
||||
/* Add all bindings specified in the derivation. */
|
||||
foreach (StringPairs::iterator, i, drv.env)
|
||||
|
@ -1618,7 +1609,7 @@ void DerivationGoal::startBuilder()
|
|||
|
||||
/* If `build-users-group' is not empty, then we have to build as
|
||||
one of the members of that group. */
|
||||
if (haveBuildUsers()) {
|
||||
if (settings.buildUsersGroup != "") {
|
||||
buildUser.acquire();
|
||||
assert(buildUser.getUID() != 0);
|
||||
assert(buildUser.getGID() != 0);
|
||||
|
@ -1640,15 +1631,15 @@ void DerivationGoal::startBuilder()
|
|||
the builder can create its output but not mess with the
|
||||
outputs of other processes). */
|
||||
struct stat st;
|
||||
if (stat(nixStore.c_str(), &st) == -1)
|
||||
throw SysError(format("cannot stat `%1%'") % nixStore);
|
||||
if (stat(settings.nixStore.c_str(), &st) == -1)
|
||||
throw SysError(format("cannot stat `%1%'") % settings.nixStore);
|
||||
if (!(st.st_mode & S_ISVTX) ||
|
||||
((st.st_mode & S_IRWXG) != S_IRWXG) ||
|
||||
(st.st_gid != buildUser.getGID()))
|
||||
throw Error(format(
|
||||
"builder does not have write permission to `%2%'; "
|
||||
"try `chgrp %1% %2%; chmod 1775 %2%'")
|
||||
% buildUser.getGID() % nixStore);
|
||||
% buildUser.getGID() % settings.nixStore);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1657,7 +1648,7 @@ void DerivationGoal::startBuilder()
|
|||
functions like fetchurl (which needs a proper /etc/resolv.conf)
|
||||
work properly. Purity checking for fixed-output derivations
|
||||
is somewhat pointless anyway. */
|
||||
useChroot = queryBoolSetting("build-use-chroot", false);
|
||||
useChroot = settings.useChroot;
|
||||
|
||||
if (fixedOutput) useChroot = false;
|
||||
|
||||
|
@ -1707,16 +1698,8 @@ void DerivationGoal::startBuilder()
|
|||
writeFile(chrootRootDir + "/etc/hosts", "127.0.0.1 localhost\n");
|
||||
|
||||
/* Bind-mount a user-configurable set of directories from the
|
||||
host file system. The `/dev/pts' directory must be mounted
|
||||
separately so that newly-created pseudo-terminals show
|
||||
up. */
|
||||
Paths defaultDirs;
|
||||
defaultDirs.push_back("/dev");
|
||||
defaultDirs.push_back("/dev/pts");
|
||||
|
||||
Paths dirsInChroot_ = querySetting("build-chroot-dirs", defaultDirs);
|
||||
dirsInChroot.insert(dirsInChroot_.begin(), dirsInChroot_.end());
|
||||
|
||||
host file system. */
|
||||
dirsInChroot = settings.dirsInChroot;
|
||||
dirsInChroot.insert(tmpDir);
|
||||
|
||||
/* Make the closure of the inputs available in the chroot,
|
||||
|
@ -1726,8 +1709,8 @@ void DerivationGoal::startBuilder()
|
|||
can be bind-mounted). !!! As an extra security
|
||||
precaution, make the fake Nix store only writable by the
|
||||
build user. */
|
||||
createDirs(chrootRootDir + nixStore);
|
||||
chmod(chrootRootDir + nixStore, 01777);
|
||||
createDirs(chrootRootDir + settings.nixStore);
|
||||
chmod(chrootRootDir + settings.nixStore, 01777);
|
||||
|
||||
foreach (PathSet::iterator, i, inputPaths) {
|
||||
struct stat st;
|
||||
|
@ -1827,7 +1810,7 @@ void DerivationGoal::startBuilder()
|
|||
worker.childStarted(shared_from_this(), pid,
|
||||
singleton<set<int> >(builderOut.readSide), true, true);
|
||||
|
||||
if (printBuildTrace) {
|
||||
if (settings.printBuildTrace) {
|
||||
printMsg(lvlError, format("@ build-started %1% %2% %3% %4%")
|
||||
% drvPath % drv.outputs["out"].path % drv.platform % logFile);
|
||||
}
|
||||
|
@ -1907,16 +1890,14 @@ void DerivationGoal::initChild()
|
|||
#ifdef CAN_DO_LINUX32_BUILDS
|
||||
/* Change the personality to 32-bit if we're doing an
|
||||
i686-linux build on an x86_64-linux machine. */
|
||||
if (drv.platform == "i686-linux" && thisSystem == "x86_64-linux") {
|
||||
if (drv.platform == "i686-linux" && settings.thisSystem == "x86_64-linux") {
|
||||
if (personality(0x0008 | 0x8000000 /* == PER_LINUX32_3GB */) == -1)
|
||||
throw SysError("cannot set i686-linux personality");
|
||||
}
|
||||
|
||||
/* Impersonate a Linux 2.6 machine to get some determinism in
|
||||
builds that depend on the kernel version. */
|
||||
if ((drv.platform == "i686-linux" || drv.platform == "x86_64-linux") &&
|
||||
queryBoolSetting("build-impersonate-linux-26", true))
|
||||
{
|
||||
if ((drv.platform == "i686-linux" || drv.platform == "x86_64-linux") && settings.impersonateLinux26) {
|
||||
int cur = personality(0xffffffff);
|
||||
if (cur != -1) personality(cur | 0x0020000 /* == UNAME26 */);
|
||||
}
|
||||
|
@ -1958,7 +1939,7 @@ void DerivationGoal::initChild()
|
|||
|
||||
} else {
|
||||
/* Let the setuid helper take care of it. */
|
||||
program = nixLibexecDir + "/nix-setuid-helper";
|
||||
program = settings.nixLibexecDir + "/nix-setuid-helper";
|
||||
args.push_back(program.c_str());
|
||||
args.push_back("run-builder");
|
||||
user = buildUser.getUser().c_str();
|
||||
|
@ -2126,13 +2107,13 @@ string drvsLogDir = "drvs";
|
|||
|
||||
Path DerivationGoal::openLogFile()
|
||||
{
|
||||
if (!queryBoolSetting("build-keep-log", true)) return "";
|
||||
if (!settings.keepLog) return "";
|
||||
|
||||
/* Create a log file. */
|
||||
Path dir = (format("%1%/%2%") % nixLogDir % drvsLogDir).str();
|
||||
Path dir = (format("%1%/%2%") % settings.nixLogDir % drvsLogDir).str();
|
||||
createDirs(dir);
|
||||
|
||||
if (queryBoolSetting("build-compress-log", true)) {
|
||||
if (settings.compressLog) {
|
||||
|
||||
Path logFileName = (format("%1%/%2%.bz2") % dir % baseNameOf(drvPath)).str();
|
||||
AutoCloseFD fd = open(logFileName.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0666);
|
||||
|
@ -2179,7 +2160,7 @@ void DerivationGoal::closeLogFile()
|
|||
void DerivationGoal::deleteTmpDir(bool force)
|
||||
{
|
||||
if (tmpDir != "") {
|
||||
if (keepFailed && !force) {
|
||||
if (settings.keepFailed && !force) {
|
||||
printMsg(lvlError,
|
||||
format("builder for `%1%' failed; keeping build directory `%2%'")
|
||||
% drvPath % tmpDir);
|
||||
|
@ -2199,7 +2180,7 @@ void DerivationGoal::handleChildOutput(int fd, const string & data)
|
|||
if ((hook && fd == hook->builderOut.readSide) ||
|
||||
(!hook && fd == builderOut.readSide))
|
||||
{
|
||||
if (verbosity >= buildVerbosity)
|
||||
if (verbosity >= settings.buildVerbosity)
|
||||
writeToStderr((unsigned char *) data.data(), data.size());
|
||||
if (bzLogFile) {
|
||||
int err;
|
||||
|
@ -2235,13 +2216,13 @@ PathSet DerivationGoal::checkPathValidity(bool returnValid)
|
|||
|
||||
bool DerivationGoal::pathFailed(const Path & path)
|
||||
{
|
||||
if (!worker.cacheFailure) return false;
|
||||
if (!settings.cacheFailure) return false;
|
||||
|
||||
if (!worker.store.hasPathFailed(path)) return false;
|
||||
|
||||
printMsg(lvlError, format("builder for `%1%' failed previously (cached)") % path);
|
||||
|
||||
if (printBuildTrace)
|
||||
if (settings.printBuildTrace)
|
||||
printMsg(lvlError, format("@ build-failed %1% %2% cached") % drvPath % path);
|
||||
|
||||
worker.permanentFailure = true;
|
||||
|
@ -2362,10 +2343,10 @@ void SubstitutionGoal::init()
|
|||
return;
|
||||
}
|
||||
|
||||
if (readOnlyMode)
|
||||
if (settings.readOnlyMode)
|
||||
throw Error(format("cannot substitute path `%1%' - no write access to the Nix store") % storePath);
|
||||
|
||||
subs = substituters;
|
||||
subs = settings.substituters;
|
||||
|
||||
tryNext();
|
||||
}
|
||||
|
@ -2437,7 +2418,7 @@ void SubstitutionGoal::tryToRun()
|
|||
is maxBuildJobs == 0 (no local builds allowed), we still allow
|
||||
a substituter to run. This is because substitutions cannot be
|
||||
distributed to another machine via the build hook. */
|
||||
if (worker.getNrLocalBuilds() >= (maxBuildJobs == 0 ? 1 : maxBuildJobs)) {
|
||||
if (worker.getNrLocalBuilds() >= (settings.maxBuildJobs == 0 ? 1 : settings.maxBuildJobs)) {
|
||||
worker.waitForBuildSlot(shared_from_this());
|
||||
return;
|
||||
}
|
||||
|
@ -2496,7 +2477,7 @@ void SubstitutionGoal::tryToRun()
|
|||
|
||||
/* Pass configuration options (including those overriden
|
||||
with --option) to the substituter. */
|
||||
setenv("_NIX_OPTIONS", packSettings().c_str(), 1);
|
||||
setenv("_NIX_OPTIONS", settings.pack().c_str(), 1);
|
||||
|
||||
/* Fill in the arguments. */
|
||||
Strings args;
|
||||
|
@ -2525,7 +2506,7 @@ void SubstitutionGoal::tryToRun()
|
|||
|
||||
state = &SubstitutionGoal::finished;
|
||||
|
||||
if (printBuildTrace) {
|
||||
if (settings.printBuildTrace) {
|
||||
printMsg(lvlError, format("@ substituter-started %1% %2%")
|
||||
% storePath % sub);
|
||||
}
|
||||
|
@ -2583,7 +2564,7 @@ void SubstitutionGoal::finished()
|
|||
|
||||
printMsg(lvlInfo, e.msg());
|
||||
|
||||
if (printBuildTrace) {
|
||||
if (settings.printBuildTrace) {
|
||||
printMsg(lvlError, format("@ substituter-failed %1% %2% %3%")
|
||||
% storePath % status % e.msg());
|
||||
}
|
||||
|
@ -2611,7 +2592,7 @@ void SubstitutionGoal::finished()
|
|||
printMsg(lvlChatty,
|
||||
format("substitution of path `%1%' succeeded") % storePath);
|
||||
|
||||
if (printBuildTrace) {
|
||||
if (settings.printBuildTrace) {
|
||||
printMsg(lvlError, format("@ substituter-succeeded %1%") % storePath);
|
||||
}
|
||||
|
||||
|
@ -2622,7 +2603,7 @@ void SubstitutionGoal::finished()
|
|||
void SubstitutionGoal::handleChildOutput(int fd, const string & data)
|
||||
{
|
||||
assert(fd == logPipe.readSide);
|
||||
if (verbosity >= buildVerbosity)
|
||||
if (verbosity >= settings.buildVerbosity)
|
||||
writeToStderr((unsigned char *) data.data(), data.size());
|
||||
/* Don't write substitution output to a log file for now. We
|
||||
probably should, though. */
|
||||
|
@ -2650,7 +2631,6 @@ Worker::Worker(LocalStore & store)
|
|||
working = true;
|
||||
nrLocalBuilds = 0;
|
||||
lastWokenUp = 0;
|
||||
cacheFailure = queryBoolSetting("build-cache-failure", false);
|
||||
permanentFailure = false;
|
||||
}
|
||||
|
||||
|
@ -2715,7 +2695,7 @@ void Worker::removeGoal(GoalPtr goal)
|
|||
topGoals.erase(goal);
|
||||
/* If a top-level goal failed, then kill all other goals
|
||||
(unless keepGoing was set). */
|
||||
if (goal->getExitCode() == Goal::ecFailed && !keepGoing)
|
||||
if (goal->getExitCode() == Goal::ecFailed && !settings.keepGoing)
|
||||
topGoals.clear();
|
||||
}
|
||||
|
||||
|
@ -2787,7 +2767,7 @@ void Worker::childTerminated(pid_t pid, bool wakeSleepers)
|
|||
void Worker::waitForBuildSlot(GoalPtr goal)
|
||||
{
|
||||
debug("wait for build slot");
|
||||
if (getNrLocalBuilds() < maxBuildJobs)
|
||||
if (getNrLocalBuilds() < settings.maxBuildJobs)
|
||||
wakeUp(goal); /* we can do it right away */
|
||||
else
|
||||
wantingToBuild.insert(goal);
|
||||
|
@ -2836,7 +2816,7 @@ void Worker::run(const Goals & _topGoals)
|
|||
if (!children.empty() || !waitingForAWhile.empty())
|
||||
waitForInput();
|
||||
else {
|
||||
if (awake.empty() && maxBuildJobs == 0) throw Error(
|
||||
if (awake.empty() && settings.maxBuildJobs == 0) throw Error(
|
||||
"unable to start any build; either increase `--max-jobs' "
|
||||
"or enable distributed builds");
|
||||
assert(!awake.empty());
|
||||
|
@ -2846,9 +2826,9 @@ void Worker::run(const Goals & _topGoals)
|
|||
/* If --keep-going is not set, it's possible that the main goal
|
||||
exited while some of its subgoals were still active. But if
|
||||
--keep-going *is* set, then they must all be finished now. */
|
||||
assert(!keepGoing || awake.empty());
|
||||
assert(!keepGoing || wantingToBuild.empty());
|
||||
assert(!keepGoing || children.empty());
|
||||
assert(!settings.keepGoing || awake.empty());
|
||||
assert(!settings.keepGoing || wantingToBuild.empty());
|
||||
assert(!settings.keepGoing || children.empty());
|
||||
}
|
||||
|
||||
|
||||
|
@ -2868,15 +2848,15 @@ void Worker::waitForInput()
|
|||
time_t before = time(0);
|
||||
|
||||
/* If a global timeout has been set, sleep until it's done. */
|
||||
if (buildTimeout != 0) {
|
||||
if (settings.buildTimeout != 0) {
|
||||
useTimeout = true;
|
||||
if (lastWait == 0 || lastWait > before) lastWait = before;
|
||||
timeout.tv_sec = std::max((time_t) 0, lastWait + buildTimeout - before);
|
||||
timeout.tv_sec = std::max((time_t) 0, lastWait + settings.buildTimeout - before);
|
||||
}
|
||||
|
||||
/* If we're monitoring for silence on stdout/stderr, sleep until
|
||||
the first deadline for any child. */
|
||||
if (maxSilentTime != 0) {
|
||||
if (settings.maxSilentTime != 0) {
|
||||
time_t oldest = 0;
|
||||
foreach (Children::iterator, i, children) {
|
||||
if (i->second.monitorForSilence) {
|
||||
|
@ -2885,7 +2865,7 @@ void Worker::waitForInput()
|
|||
}
|
||||
}
|
||||
if (oldest) {
|
||||
time_t silenceTimeout = std::max((time_t) 0, oldest + maxSilentTime - before);
|
||||
time_t silenceTimeout = std::max((time_t) 0, oldest + settings.maxSilentTime - before);
|
||||
timeout.tv_sec = useTimeout
|
||||
? std::min(silenceTimeout, timeout.tv_sec)
|
||||
: silenceTimeout;
|
||||
|
@ -2896,14 +2876,12 @@ void Worker::waitForInput()
|
|||
|
||||
/* If we are polling goals that are waiting for a lock, then wake
|
||||
up after a few seconds at most. */
|
||||
int wakeUpInterval = queryIntSetting("build-poll-interval", 5);
|
||||
|
||||
if (!waitingForAWhile.empty()) {
|
||||
useTimeout = true;
|
||||
if (lastWokenUp == 0)
|
||||
printMsg(lvlError, "waiting for locks or build slots...");
|
||||
if (lastWokenUp == 0 || lastWokenUp > before) lastWokenUp = before;
|
||||
timeout.tv_sec = std::max((time_t) 0, lastWokenUp + wakeUpInterval - before);
|
||||
timeout.tv_sec = std::max((time_t) 0, lastWokenUp + settings.pollInterval - before);
|
||||
} else lastWokenUp = 0;
|
||||
|
||||
using namespace std;
|
||||
|
@ -2969,27 +2947,27 @@ void Worker::waitForInput()
|
|||
}
|
||||
}
|
||||
|
||||
if (maxSilentTime != 0 &&
|
||||
if (settings.maxSilentTime != 0 &&
|
||||
j->second.monitorForSilence &&
|
||||
after - j->second.lastOutput >= (time_t) maxSilentTime)
|
||||
after - j->second.lastOutput >= (time_t) settings.maxSilentTime)
|
||||
{
|
||||
printMsg(lvlError,
|
||||
format("%1% timed out after %2% seconds of silence")
|
||||
% goal->getName() % maxSilentTime);
|
||||
% goal->getName() % settings.maxSilentTime);
|
||||
goal->cancel();
|
||||
}
|
||||
|
||||
if (buildTimeout != 0 &&
|
||||
after - before >= (time_t) buildTimeout)
|
||||
if (settings.buildTimeout != 0 &&
|
||||
after - before >= (time_t) settings.buildTimeout)
|
||||
{
|
||||
printMsg(lvlError,
|
||||
format("%1% timed out after %2% seconds of activity")
|
||||
% goal->getName() % buildTimeout);
|
||||
% goal->getName() % settings.buildTimeout);
|
||||
goal->cancel();
|
||||
}
|
||||
}
|
||||
|
||||
if (!waitingForAWhile.empty() && lastWokenUp + wakeUpInterval <= after) {
|
||||
if (!waitingForAWhile.empty() && lastWokenUp + settings.pollInterval <= after) {
|
||||
lastWokenUp = after;
|
||||
foreach (WeakGoals::iterator, i, waitingForAWhile) {
|
||||
GoalPtr goal = i->lock();
|
||||
|
|
|
@ -12,7 +12,7 @@ void DerivationOutput::parseHashInfo(bool & recursive, HashType & hashType, Hash
|
|||
{
|
||||
recursive = false;
|
||||
string algo = hashAlgo;
|
||||
|
||||
|
||||
if (string(algo, 0, 2) == "r:") {
|
||||
recursive = true;
|
||||
algo = string(algo, 2);
|
||||
|
@ -21,7 +21,7 @@ void DerivationOutput::parseHashInfo(bool & recursive, HashType & hashType, Hash
|
|||
hashType = parseHashType(algo);
|
||||
if (hashType == htUnknown)
|
||||
throw Error(format("unknown hash algorithm `%1%'") % algo);
|
||||
|
||||
|
||||
hash = parseHash(hashType, this->hash);
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,7 @@ Path writeDerivation(StoreAPI & store,
|
|||
held during a garbage collection). */
|
||||
string suffix = name + drvExtension;
|
||||
string contents = unparseDerivation(drv);
|
||||
return readOnlyMode
|
||||
return settings.readOnlyMode
|
||||
? computeStorePathForText(suffix, contents, references)
|
||||
: store.addTextToStore(suffix, contents, references);
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ static Path parsePath(std::istream & str)
|
|||
throw Error(format("bad path `%1%' in derivation") % s);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static StringSet parseStrings(std::istream & str, bool arePaths)
|
||||
{
|
||||
|
@ -60,7 +60,7 @@ static StringSet parseStrings(std::istream & str, bool arePaths)
|
|||
res.insert(arePaths ? parsePath(str) : parseString(str));
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Derivation parseDerivation(const string & s)
|
||||
{
|
||||
|
@ -106,7 +106,7 @@ Derivation parseDerivation(const string & s)
|
|||
expect(str, ")");
|
||||
drv.env[name] = value;
|
||||
}
|
||||
|
||||
|
||||
expect(str, ")");
|
||||
return drv;
|
||||
}
|
||||
|
@ -165,7 +165,7 @@ string unparseDerivation(const Derivation & drv)
|
|||
|
||||
s += "],";
|
||||
printStrings(s, drv.inputSrcs.begin(), drv.inputSrcs.end());
|
||||
|
||||
|
||||
s += ','; printString(s, drv.platform);
|
||||
s += ','; printString(s, drv.builder);
|
||||
s += ','; printStrings(s, drv.args.begin(), drv.args.end());
|
||||
|
@ -178,9 +178,9 @@ string unparseDerivation(const Derivation & drv)
|
|||
s += ','; printString(s, i->second);
|
||||
s += ')';
|
||||
}
|
||||
|
||||
|
||||
s += "])";
|
||||
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
@ -190,7 +190,7 @@ bool isDerivation(const string & fileName)
|
|||
return hasSuffix(fileName, drvExtension);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool isFixedOutputDrv(const Derivation & drv)
|
||||
{
|
||||
return drv.outputs.size() == 1 &&
|
||||
|
@ -247,7 +247,7 @@ Hash hashDerivationModulo(StoreAPI & store, Derivation drv)
|
|||
inputs2[printHash(h)] = i->second;
|
||||
}
|
||||
drv.inputDrvs = inputs2;
|
||||
|
||||
|
||||
return hashString(htSHA256, unparseDerivation(drv));
|
||||
}
|
||||
|
||||
|
|
|
@ -34,10 +34,10 @@ static const int defaultGcLevel = 1000;
|
|||
int LocalStore::openGCLock(LockType lockType)
|
||||
{
|
||||
Path fnGCLock = (format("%1%/%2%")
|
||||
% nixStateDir % gcLockName).str();
|
||||
|
||||
% settings.nixStateDir % gcLockName).str();
|
||||
|
||||
debug(format("acquiring global GC lock `%1%'") % fnGCLock);
|
||||
|
||||
|
||||
AutoCloseFD fdGCLock = open(fnGCLock.c_str(), O_RDWR | O_CREAT, 0600);
|
||||
if (fdGCLock == -1)
|
||||
throw SysError(format("opening global GC lock `%1%'") % fnGCLock);
|
||||
|
@ -51,7 +51,7 @@ int LocalStore::openGCLock(LockType lockType)
|
|||
/* !!! Restrict read permission on the GC root. Otherwise any
|
||||
process that can open the file for reading can DoS the
|
||||
collector. */
|
||||
|
||||
|
||||
return fdGCLock.borrow();
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,7 @@ void LocalStore::addIndirectRoot(const Path & path)
|
|||
{
|
||||
string hash = printHash32(hashString(htSHA1, path));
|
||||
Path realRoot = canonPath((format("%1%/%2%/auto/%3%")
|
||||
% nixStateDir % gcRootsDir % hash).str());
|
||||
% settings.nixStateDir % gcRootsDir % hash).str());
|
||||
createSymlink(realRoot, path);
|
||||
}
|
||||
|
||||
|
@ -113,15 +113,15 @@ Path addPermRoot(StoreAPI & store, const Path & _storePath,
|
|||
|
||||
else {
|
||||
if (!allowOutsideRootsDir) {
|
||||
Path rootsDir = canonPath((format("%1%/%2%") % nixStateDir % gcRootsDir).str());
|
||||
|
||||
Path rootsDir = canonPath((format("%1%/%2%") % settings.nixStateDir % gcRootsDir).str());
|
||||
|
||||
if (string(gcRoot, 0, rootsDir.size() + 1) != rootsDir + "/")
|
||||
throw Error(format(
|
||||
"path `%1%' is not a valid garbage collector root; "
|
||||
"it's not in the directory `%2%'")
|
||||
% gcRoot % rootsDir);
|
||||
}
|
||||
|
||||
|
||||
createSymlink(gcRoot, storePath);
|
||||
}
|
||||
|
||||
|
@ -130,10 +130,10 @@ Path addPermRoot(StoreAPI & store, const Path & _storePath,
|
|||
Instead of reading all the roots, it would be more efficient to
|
||||
check if the root is in a directory in or linked from the
|
||||
gcroots directory. */
|
||||
if (queryBoolSetting("gc-check-reachability", false)) {
|
||||
if (settings.checkRootReachability) {
|
||||
Roots roots = store.findRoots();
|
||||
if (roots.find(gcRoot) == roots.end())
|
||||
printMsg(lvlError,
|
||||
printMsg(lvlError,
|
||||
format(
|
||||
"warning: `%1%' is not in a directory where the garbage collector looks for roots; "
|
||||
"therefore, `%2%' might be removed by the garbage collector")
|
||||
|
@ -144,7 +144,7 @@ Path addPermRoot(StoreAPI & store, const Path & _storePath,
|
|||
progress. This prevents the set of permanent roots from
|
||||
increasing while a GC is in progress. */
|
||||
store.syncWithGC();
|
||||
|
||||
|
||||
return gcRoot;
|
||||
}
|
||||
|
||||
|
@ -160,23 +160,23 @@ void LocalStore::addTempRoot(const Path & path)
|
|||
if (fdTempRoots == -1) {
|
||||
|
||||
while (1) {
|
||||
Path dir = (format("%1%/%2%") % nixStateDir % tempRootsDir).str();
|
||||
Path dir = (format("%1%/%2%") % settings.nixStateDir % tempRootsDir).str();
|
||||
createDirs(dir);
|
||||
|
||||
|
||||
fnTempRoots = (format("%1%/%2%")
|
||||
% dir % getpid()).str();
|
||||
|
||||
AutoCloseFD fdGCLock = openGCLock(ltRead);
|
||||
|
||||
|
||||
if (pathExists(fnTempRoots))
|
||||
/* It *must* be stale, since there can be no two
|
||||
processes with the same pid. */
|
||||
unlink(fnTempRoots.c_str());
|
||||
|
||||
fdTempRoots = openLockFile(fnTempRoots, true);
|
||||
fdTempRoots = openLockFile(fnTempRoots, true);
|
||||
|
||||
fdGCLock.close();
|
||||
|
||||
|
||||
debug(format("acquiring read lock on `%1%'") % fnTempRoots);
|
||||
lockFile(fdTempRoots, ltRead, true);
|
||||
|
||||
|
@ -186,7 +186,7 @@ void LocalStore::addTempRoot(const Path & path)
|
|||
if (fstat(fdTempRoots, &st) == -1)
|
||||
throw SysError(format("statting `%1%'") % fnTempRoots);
|
||||
if (st.st_size == 0) break;
|
||||
|
||||
|
||||
/* The garbage collector deleted this file before we could
|
||||
get a lock. (It won't delete the file after we get a
|
||||
lock.) Try again. */
|
||||
|
@ -218,7 +218,7 @@ void removeTempRoots()
|
|||
|
||||
|
||||
/* Automatically clean up the temporary roots file when we exit. */
|
||||
struct RemoveTempRoots
|
||||
struct RemoveTempRoots
|
||||
{
|
||||
~RemoveTempRoots()
|
||||
{
|
||||
|
@ -238,10 +238,10 @@ static void readTempRoots(PathSet & tempRoots, FDs & fds)
|
|||
/* Read the `temproots' directory for per-process temporary root
|
||||
files. */
|
||||
Strings tempRootFiles = readDirectory(
|
||||
(format("%1%/%2%") % nixStateDir % tempRootsDir).str());
|
||||
(format("%1%/%2%") % settings.nixStateDir % tempRootsDir).str());
|
||||
|
||||
foreach (Strings::iterator, i, tempRootFiles) {
|
||||
Path path = (format("%1%/%2%/%3%") % nixStateDir % tempRootsDir % *i).str();
|
||||
Path path = (format("%1%/%2%/%3%") % settings.nixStateDir % tempRootsDir % *i).str();
|
||||
|
||||
debug(format("reading temporary root file `%1%'") % path);
|
||||
FDPtr fd(new AutoCloseFD(open(path.c_str(), O_RDWR, 0666)));
|
||||
|
@ -295,7 +295,7 @@ static void findRoots(StoreAPI & store, const Path & path,
|
|||
bool recurseSymlinks, bool deleteStale, Roots & roots)
|
||||
{
|
||||
try {
|
||||
|
||||
|
||||
struct stat st;
|
||||
if (lstat(path.c_str(), &st) == -1)
|
||||
throw SysError(format("statting `%1%'") % path);
|
||||
|
@ -315,7 +315,7 @@ static void findRoots(StoreAPI & store, const Path & path,
|
|||
debug(format("found root `%1%' in `%2%'")
|
||||
% target % path);
|
||||
Path storePath = toStorePath(target);
|
||||
if (store.isValidPath(storePath))
|
||||
if (store.isValidPath(storePath))
|
||||
roots[path] = storePath;
|
||||
else
|
||||
printMsg(lvlInfo, format("skipping invalid root from `%1%' to `%2%'")
|
||||
|
@ -350,7 +350,7 @@ static void findRoots(StoreAPI & store, const Path & path,
|
|||
static Roots findRoots(StoreAPI & store, bool deleteStale)
|
||||
{
|
||||
Roots roots;
|
||||
Path rootsDir = canonPath((format("%1%/%2%") % nixStateDir % gcRootsDir).str());
|
||||
Path rootsDir = canonPath((format("%1%/%2%") % settings.nixStateDir % gcRootsDir).str());
|
||||
findRoots(store, rootsDir, true, deleteStale, roots);
|
||||
return roots;
|
||||
}
|
||||
|
@ -365,16 +365,16 @@ Roots LocalStore::findRoots()
|
|||
static void addAdditionalRoots(StoreAPI & store, PathSet & roots)
|
||||
{
|
||||
Path rootFinder = getEnv("NIX_ROOT_FINDER",
|
||||
nixLibexecDir + "/nix/find-runtime-roots.pl");
|
||||
settings.nixLibexecDir + "/nix/find-runtime-roots.pl");
|
||||
|
||||
if (rootFinder.empty()) return;
|
||||
|
||||
|
||||
debug(format("executing `%1%' to find additional roots") % rootFinder);
|
||||
|
||||
string result = runProgram(rootFinder);
|
||||
|
||||
Strings paths = tokenizeString(result, "\n");
|
||||
|
||||
|
||||
foreach (Strings::iterator, i, paths) {
|
||||
if (isInStore(*i)) {
|
||||
Path path = toStorePath(*i);
|
||||
|
@ -557,7 +557,7 @@ bool LocalStore::tryToDelete(GCState & state, const Path & path)
|
|||
|
||||
} else
|
||||
printMsg(lvlTalkative, format("would delete `%1%'") % path);
|
||||
|
||||
|
||||
state.deleted.insert(path);
|
||||
if (state.options.action != GCOptions::gcReturnLive)
|
||||
state.results.paths.insert(path);
|
||||
|
@ -605,10 +605,10 @@ void LocalStore::removeUnusedLinks()
|
|||
void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
|
||||
{
|
||||
GCState state(results);
|
||||
state.options = options;
|
||||
|
||||
state.gcKeepOutputs = queryBoolSetting("gc-keep-outputs", false);
|
||||
state.gcKeepDerivations = queryBoolSetting("gc-keep-derivations", true);
|
||||
state.options = options;
|
||||
|
||||
state.gcKeepOutputs = settings.gcKeepOutputs;
|
||||
state.gcKeepDerivations = settings.gcKeepDerivations;
|
||||
|
||||
/* Using `--ignore-liveness' with `--delete' can have unintended
|
||||
consequences if `gc-keep-outputs' or `gc-keep-derivations' are
|
||||
|
@ -618,7 +618,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
|
|||
state.gcKeepOutputs = false;
|
||||
state.gcKeepDerivations = false;
|
||||
}
|
||||
|
||||
|
||||
/* Acquire the global GC root. This prevents
|
||||
a) New roots from being added.
|
||||
b) Processes from creating new temporary root files. */
|
||||
|
@ -659,18 +659,18 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
|
|||
if (!tryToDelete(state, *i))
|
||||
throw Error(format("cannot delete path `%1%' since it is still alive") % *i);
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
|
||||
if (shouldDelete(state.options.action))
|
||||
printMsg(lvlError, format("deleting garbage..."));
|
||||
else
|
||||
printMsg(lvlError, format("determining live/dead paths..."));
|
||||
|
||||
|
||||
try {
|
||||
|
||||
AutoCloseDir dir = opendir(nixStore.c_str());
|
||||
if (!dir) throw SysError(format("opening directory `%1%'") % nixStore);
|
||||
AutoCloseDir dir = opendir(settings.nixStore.c_str());
|
||||
if (!dir) throw SysError(format("opening directory `%1%'") % settings.nixStore);
|
||||
|
||||
/* Read the store and immediately delete all paths that
|
||||
aren't valid. When using --max-freed etc., deleting
|
||||
|
@ -684,14 +684,14 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
|
|||
checkInterrupt();
|
||||
string name = dirent->d_name;
|
||||
if (name == "." || name == "..") continue;
|
||||
Path path = nixStore + "/" + name;
|
||||
Path path = settings.nixStore + "/" + name;
|
||||
if (isValidPath(path))
|
||||
entries.push_back(path);
|
||||
else
|
||||
tryToDelete(state, path);
|
||||
}
|
||||
|
||||
dir.close();
|
||||
dir.close();
|
||||
|
||||
/* Now delete the unreachable valid paths. Randomise the
|
||||
order in which we delete entries to make the collector
|
||||
|
|
|
@ -10,38 +10,63 @@
|
|||
namespace nix {
|
||||
|
||||
|
||||
string nixStore = "/UNINIT";
|
||||
string nixDataDir = "/UNINIT";
|
||||
string nixLogDir = "/UNINIT";
|
||||
string nixStateDir = "/UNINIT";
|
||||
string nixDBPath = "/UNINIT";
|
||||
string nixConfDir = "/UNINIT";
|
||||
string nixLibexecDir = "/UNINIT";
|
||||
string nixBinDir = "/UNINIT";
|
||||
|
||||
bool keepFailed = false;
|
||||
bool keepGoing = false;
|
||||
bool tryFallback = false;
|
||||
Verbosity buildVerbosity = lvlError;
|
||||
unsigned int maxBuildJobs = 1;
|
||||
unsigned int buildCores = 1;
|
||||
bool readOnlyMode = false;
|
||||
string thisSystem = "unset";
|
||||
time_t maxSilentTime = 0;
|
||||
time_t buildTimeout = 0;
|
||||
Paths substituters;
|
||||
bool useBuildHook = true;
|
||||
bool printBuildTrace = false;
|
||||
Settings settings;
|
||||
|
||||
|
||||
static bool settingsRead = false;
|
||||
Settings::Settings()
|
||||
{
|
||||
keepFailed = false;
|
||||
keepGoing = false;
|
||||
tryFallback = false;
|
||||
buildVerbosity = lvlError;
|
||||
maxBuildJobs = 1;
|
||||
buildCores = 1;
|
||||
readOnlyMode = false;
|
||||
thisSystem = SYSTEM;
|
||||
maxSilentTime = 0;
|
||||
buildTimeout = 0;
|
||||
useBuildHook = true;
|
||||
printBuildTrace = false;
|
||||
reservedSize = 1024 * 1024;
|
||||
fsyncMetadata = true;
|
||||
useSQLiteWAL = true;
|
||||
syncBeforeRegistering = false;
|
||||
useSubstitutes = true;
|
||||
useChroot = false;
|
||||
dirsInChroot.insert("/dev");
|
||||
dirsInChroot.insert("/dev/pts");
|
||||
impersonateLinux26 = false;
|
||||
keepLog = true;
|
||||
compressLog = true;
|
||||
cacheFailure = false;
|
||||
pollInterval = 5;
|
||||
checkRootReachability = false;
|
||||
gcKeepOutputs = false;
|
||||
gcKeepDerivations = true;
|
||||
autoOptimiseStore = true;
|
||||
envKeepDerivations = false;
|
||||
}
|
||||
|
||||
typedef std::map<string, Strings> Settings;
|
||||
|
||||
static Settings settings;
|
||||
void Settings::processEnvironment()
|
||||
{
|
||||
nixStore = canonPath(getEnv("NIX_STORE_DIR", getEnv("NIX_STORE", NIX_STORE_DIR)));
|
||||
nixDataDir = canonPath(getEnv("NIX_DATA_DIR", NIX_DATA_DIR));
|
||||
nixLogDir = canonPath(getEnv("NIX_LOG_DIR", NIX_LOG_DIR));
|
||||
nixStateDir = canonPath(getEnv("NIX_STATE_DIR", NIX_STATE_DIR));
|
||||
nixDBPath = getEnv("NIX_DB_DIR", nixStateDir + "/db");
|
||||
nixConfDir = canonPath(getEnv("NIX_CONF_DIR", NIX_CONF_DIR));
|
||||
nixLibexecDir = canonPath(getEnv("NIX_LIBEXEC_DIR", NIX_LIBEXEC_DIR));
|
||||
nixBinDir = canonPath(getEnv("NIX_BIN_DIR", NIX_BIN_DIR));
|
||||
|
||||
/* Overriden settings. */
|
||||
Settings settingsCmdline;
|
||||
string subs = getEnv("NIX_SUBSTITUTERS", "default");
|
||||
if (subs == "default") {
|
||||
substituters.push_back(nixLibexecDir + "/nix/substituters/copy-from-other-stores.pl");
|
||||
substituters.push_back(nixLibexecDir + "/nix/substituters/download-using-manifests.pl");
|
||||
substituters.push_back(nixLibexecDir + "/nix/substituters/download-from-binary-cache.pl");
|
||||
} else
|
||||
substituters = tokenizeString(subs, ":");
|
||||
}
|
||||
|
||||
|
||||
string & at(Strings & ss, unsigned int n)
|
||||
|
@ -52,7 +77,7 @@ string & at(Strings & ss, unsigned int n)
|
|||
}
|
||||
|
||||
|
||||
static void readSettings()
|
||||
void Settings::loadConfFile()
|
||||
{
|
||||
Path settingsFile = (format("%1%/%2%") % nixConfDir % "nix.conf").str();
|
||||
if (!pathExists(settingsFile)) return;
|
||||
|
@ -80,104 +105,88 @@ static void readSettings()
|
|||
|
||||
Strings::iterator i = tokens.begin();
|
||||
advance(i, 2);
|
||||
settings[name] = Strings(i, tokens.end());
|
||||
settings[name] = concatStringsSep(" ", Strings(i, tokens.end())); // FIXME: slow
|
||||
};
|
||||
|
||||
settings.insert(settingsCmdline.begin(), settingsCmdline.end());
|
||||
|
||||
settingsRead = true;
|
||||
}
|
||||
|
||||
|
||||
Strings querySetting(const string & name, const Strings & def)
|
||||
void Settings::set(const string & name, const string & value)
|
||||
{
|
||||
if (!settingsRead) readSettings();
|
||||
Settings::iterator i = settings.find(name);
|
||||
return i == settings.end() ? def : i->second;
|
||||
settings[name] = value;
|
||||
}
|
||||
|
||||
|
||||
string querySetting(const string & name, const string & def)
|
||||
void Settings::update()
|
||||
{
|
||||
Strings defs;
|
||||
defs.push_back(def);
|
||||
|
||||
Strings value = querySetting(name, defs);
|
||||
if (value.size() != 1)
|
||||
throw Error(format("configuration option `%1%' should not be a list") % name);
|
||||
|
||||
return value.front();
|
||||
get(thisSystem, "system");
|
||||
get(maxBuildJobs, "build-max-jobs");
|
||||
get(buildCores, "build-cores");
|
||||
get(maxSilentTime, "build-max-silent-time");
|
||||
get(buildTimeout, "build-timeout");
|
||||
get(reservedSize, "gc-reserved-space");
|
||||
get(fsyncMetadata, "fsync-metadata");
|
||||
get(useSQLiteWAL, "use-sqlite-wal");
|
||||
get(syncBeforeRegistering, "sync-before-registering");
|
||||
get(useSubstitutes, "build-use-substitutes");
|
||||
get(buildUsersGroup, "build-users-group");
|
||||
get(useChroot, "build-use-chroot");
|
||||
get(dirsInChroot, "build-chroot-dirs");
|
||||
get(impersonateLinux26, "build-impersonate-linux-26");
|
||||
get(keepLog, "build-keep-log");
|
||||
get(compressLog, "build-compress-log");
|
||||
get(cacheFailure, "build-cache-failure");
|
||||
get(pollInterval, "build-poll-interval");
|
||||
get(checkRootReachability, "gc-check-reachability");
|
||||
get(gcKeepOutputs, "gc-keep-outputs");
|
||||
get(gcKeepDerivations, "gc-keep-derivations");
|
||||
get(autoOptimiseStore, "auto-optimise-store");
|
||||
get(envKeepDerivations, "env-keep-derivations");
|
||||
}
|
||||
|
||||
|
||||
bool queryBoolSetting(const string & name, bool def)
|
||||
void Settings::get(string & res, const string & name)
|
||||
{
|
||||
string v = querySetting(name, def ? "true" : "false");
|
||||
if (v == "true") return true;
|
||||
else if (v == "false") return false;
|
||||
SettingsMap::iterator i = settings.find(name);
|
||||
if (i == settings.end()) return;
|
||||
res = i->second;
|
||||
}
|
||||
|
||||
|
||||
void Settings::get(bool & res, const string & name)
|
||||
{
|
||||
SettingsMap::iterator i = settings.find(name);
|
||||
if (i == settings.end()) return;
|
||||
if (i->second == "true") res = true;
|
||||
else if (i->second == "false") res = false;
|
||||
else throw Error(format("configuration option `%1%' should be either `true' or `false', not `%2%'")
|
||||
% name % v);
|
||||
% name % i->second);
|
||||
}
|
||||
|
||||
|
||||
unsigned int queryIntSetting(const string & name, unsigned int def)
|
||||
void Settings::get(PathSet & res, const string & name)
|
||||
{
|
||||
int n;
|
||||
if (!string2Int(querySetting(name, int2String(def)), n) || n < 0)
|
||||
SettingsMap::iterator i = settings.find(name);
|
||||
if (i == settings.end()) return;
|
||||
res.clear();
|
||||
Strings ss = tokenizeString(i->second);
|
||||
res.insert(ss.begin(), ss.end());
|
||||
}
|
||||
|
||||
|
||||
template<class N> void Settings::get(N & res, const string & name)
|
||||
{
|
||||
SettingsMap::iterator i = settings.find(name);
|
||||
if (i == settings.end()) return;
|
||||
if (!string2Int(i->second, res))
|
||||
throw Error(format("configuration setting `%1%' should have an integer value") % name);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
void overrideSetting(const string & name, const Strings & value)
|
||||
{
|
||||
if (settingsRead) settings[name] = value;
|
||||
settingsCmdline[name] = value;
|
||||
}
|
||||
|
||||
|
||||
void reloadSettings()
|
||||
{
|
||||
settingsRead = false;
|
||||
settings.clear();
|
||||
}
|
||||
|
||||
|
||||
void setDefaultsFromEnvironment()
|
||||
{
|
||||
/* Setup Nix paths. */
|
||||
nixStore = canonPath(getEnv("NIX_STORE_DIR", getEnv("NIX_STORE", NIX_STORE_DIR)));
|
||||
nixDataDir = canonPath(getEnv("NIX_DATA_DIR", NIX_DATA_DIR));
|
||||
nixLogDir = canonPath(getEnv("NIX_LOG_DIR", NIX_LOG_DIR));
|
||||
nixStateDir = canonPath(getEnv("NIX_STATE_DIR", NIX_STATE_DIR));
|
||||
nixDBPath = getEnv("NIX_DB_DIR", nixStateDir + "/db");
|
||||
nixConfDir = canonPath(getEnv("NIX_CONF_DIR", NIX_CONF_DIR));
|
||||
nixLibexecDir = canonPath(getEnv("NIX_LIBEXEC_DIR", NIX_LIBEXEC_DIR));
|
||||
nixBinDir = canonPath(getEnv("NIX_BIN_DIR", NIX_BIN_DIR));
|
||||
|
||||
string subs = getEnv("NIX_SUBSTITUTERS", "default");
|
||||
if (subs == "default") {
|
||||
substituters.push_back(nixLibexecDir + "/nix/substituters/copy-from-other-stores.pl");
|
||||
substituters.push_back(nixLibexecDir + "/nix/substituters/download-using-manifests.pl");
|
||||
substituters.push_back(nixLibexecDir + "/nix/substituters/download-from-binary-cache.pl");
|
||||
} else
|
||||
substituters = tokenizeString(subs, ":");
|
||||
|
||||
/* Get some settings from the configuration file. */
|
||||
thisSystem = querySetting("system", SYSTEM);
|
||||
maxBuildJobs = queryIntSetting("build-max-jobs", 1);
|
||||
buildCores = queryIntSetting("build-cores", 1);
|
||||
maxSilentTime = queryIntSetting("build-max-silent-time", 0);
|
||||
buildTimeout = queryIntSetting("build-timeout", 0);
|
||||
}
|
||||
|
||||
|
||||
string packSettings()
|
||||
string Settings::pack()
|
||||
{
|
||||
string s;
|
||||
if (!settingsRead) readSettings();
|
||||
foreach (Settings::iterator, i, settings) {
|
||||
s += i->first; s += '='; s += concatStringsSep(" ", i->second); s += '\n';
|
||||
foreach (SettingsMap::iterator, i, settings) {
|
||||
s += i->first; s += '='; s += i->second; s += '\n';
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
|
|
@ -2,120 +2,189 @@
|
|||
|
||||
#include "types.hh"
|
||||
|
||||
#include <map>
|
||||
|
||||
|
||||
namespace nix {
|
||||
|
||||
|
||||
/* Path names. */
|
||||
struct Settings {
|
||||
|
||||
/* nixStore is the directory where we generally store atomic and
|
||||
derived files. */
|
||||
extern string nixStore;
|
||||
Settings();
|
||||
|
||||
extern string nixDataDir; /* !!! fix */
|
||||
void processEnvironment();
|
||||
|
||||
/* nixLogDir is the directory where we log various operations. */
|
||||
extern string nixLogDir;
|
||||
void loadConfFile();
|
||||
|
||||
/* nixStateDir is the directory where state is stored. */
|
||||
extern string nixStateDir;
|
||||
void set(const string & name, const string & value);
|
||||
|
||||
/* nixDBPath is the path name of our Berkeley DB environment. */
|
||||
extern string nixDBPath;
|
||||
void update();
|
||||
|
||||
/* nixConfDir is the directory where configuration files are
|
||||
stored. */
|
||||
extern string nixConfDir;
|
||||
string pack();
|
||||
|
||||
/* nixLibexecDir is the directory where internal helper programs are
|
||||
stored. */
|
||||
extern string nixLibexecDir;
|
||||
/* The directory where we store sources and derived files. */
|
||||
Path nixStore;
|
||||
|
||||
/* nixBinDir is the directory where the main programs are stored. */
|
||||
extern string nixBinDir;
|
||||
Path nixDataDir; /* !!! fix */
|
||||
|
||||
/* The directory where we log various operations. */
|
||||
Path nixLogDir;
|
||||
|
||||
/* The directory where state is stored. */
|
||||
Path nixStateDir;
|
||||
|
||||
/* The directory where we keep the SQLite database. */
|
||||
Path nixDBPath;
|
||||
|
||||
/* The directory where configuration files are stored. */
|
||||
Path nixConfDir;
|
||||
|
||||
/* The directory where internal helper programs are stored. */
|
||||
Path nixLibexecDir;
|
||||
|
||||
/* The directory where the main programs are stored. */
|
||||
Path nixBinDir;
|
||||
|
||||
/* Whether to keep temporary directories of failed builds. */
|
||||
bool keepFailed;
|
||||
|
||||
/* Whether to keep building subgoals when a sibling (another
|
||||
subgoal of the same goal) fails. */
|
||||
bool keepGoing;
|
||||
|
||||
/* Whether, if we cannot realise the known closure corresponding
|
||||
to a derivation, we should try to normalise the derivation
|
||||
instead. */
|
||||
bool tryFallback;
|
||||
|
||||
/* Verbosity level for build output. */
|
||||
Verbosity buildVerbosity;
|
||||
|
||||
/* Maximum number of parallel build jobs. 0 means unlimited. */
|
||||
unsigned int maxBuildJobs;
|
||||
|
||||
/* Number of CPU cores to utilize in parallel within a build,
|
||||
i.e. by passing this number to Make via '-j'. 0 means that the
|
||||
number of actual CPU cores on the local host ought to be
|
||||
auto-detected. */
|
||||
unsigned int buildCores;
|
||||
|
||||
/* Read-only mode. Don't copy stuff to the store, don't change
|
||||
the database. */
|
||||
bool readOnlyMode;
|
||||
|
||||
/* The canonical system name, as returned by config.guess. */
|
||||
string thisSystem;
|
||||
|
||||
/* The maximum time in seconds that a builer can go without
|
||||
producing any output on stdout/stderr before it is killed. 0
|
||||
means infinity. */
|
||||
time_t maxSilentTime;
|
||||
|
||||
/* The maximum duration in seconds that a builder can run. 0
|
||||
means infinity. */
|
||||
time_t buildTimeout;
|
||||
|
||||
/* The substituters. There are programs that can somehow realise
|
||||
a store path without building, e.g., by downloading it or
|
||||
copying it from a CD. */
|
||||
Paths substituters;
|
||||
|
||||
/* Whether to use build hooks (for distributed builds). Sometimes
|
||||
users want to disable this from the command-line. */
|
||||
bool useBuildHook;
|
||||
|
||||
/* Whether buildDerivations() should print out lines on stderr in
|
||||
a fixed format to allow its progress to be monitored. Each
|
||||
line starts with a "@". The following are defined:
|
||||
|
||||
@ build-started <drvpath> <outpath> <system> <logfile>
|
||||
@ build-failed <drvpath> <outpath> <exitcode> <error text>
|
||||
@ build-succeeded <drvpath> <outpath>
|
||||
@ substituter-started <outpath> <substituter>
|
||||
@ substituter-failed <outpath> <exitcode> <error text>
|
||||
@ substituter-succeeded <outpath>
|
||||
|
||||
Best combined with --no-build-output, otherwise stderr might
|
||||
conceivably contain lines in this format printed by the
|
||||
builders. */
|
||||
bool printBuildTrace;
|
||||
|
||||
/* Amount of reserved space for the garbage collector
|
||||
(/nix/var/nix/db/reserved). */
|
||||
off_t reservedSize;
|
||||
|
||||
/* Whether SQLite should use fsync. */
|
||||
bool fsyncMetadata;
|
||||
|
||||
/* Whether SQLite should use WAL mode. */
|
||||
bool useSQLiteWAL;
|
||||
|
||||
/* Whether to call sync() before registering a path as valid. */
|
||||
bool syncBeforeRegistering;
|
||||
|
||||
/* Whether to use substitutes. */
|
||||
bool useSubstitutes;
|
||||
|
||||
/* The Unix group that contains the build users. */
|
||||
string buildUsersGroup;
|
||||
|
||||
/* Whether to build in chroot. */
|
||||
bool useChroot;
|
||||
|
||||
/* The directories from the host filesystem to be included in the
|
||||
chroot. */
|
||||
PathSet dirsInChroot;
|
||||
|
||||
/* Whether to impersonate a Linux 2.6 machine on newer kernels. */
|
||||
bool impersonateLinux26;
|
||||
|
||||
/* Whether to store build logs. */
|
||||
bool keepLog;
|
||||
|
||||
/* Whether to compress logs. */
|
||||
bool compressLog;
|
||||
|
||||
/* Whether to cache build failures. */
|
||||
bool cacheFailure;
|
||||
|
||||
/* How often (in seconds) to poll for locks. */
|
||||
unsigned int pollInterval;
|
||||
|
||||
/* Whether to check if new GC roots can in fact be found by the
|
||||
garbage collector. */
|
||||
bool checkRootReachability;
|
||||
|
||||
/* Whether the garbage collector should keep outputs of live
|
||||
derivations. */
|
||||
bool gcKeepOutputs;
|
||||
|
||||
/* Whether the garbage collector should keep derivers of live
|
||||
paths. */
|
||||
bool gcKeepDerivations;
|
||||
|
||||
/* Whether to automatically replace files with identical contents
|
||||
with hard links. */
|
||||
bool autoOptimiseStore;
|
||||
|
||||
/* Whether to add derivations as a dependency of user environments
|
||||
(to prevent them from being GCed). */
|
||||
bool envKeepDerivations;
|
||||
|
||||
private:
|
||||
typedef std::map<string, string> SettingsMap;
|
||||
|
||||
SettingsMap settings;
|
||||
|
||||
void get(string & res, const string & name);
|
||||
void get(bool & res, const string & name);
|
||||
void get(PathSet & res, const string & name);
|
||||
template<class N> void get(N & res, const string & name);
|
||||
};
|
||||
|
||||
|
||||
/* Misc. global flags. */
|
||||
|
||||
/* Whether to keep temporary directories of failed builds. */
|
||||
extern bool keepFailed;
|
||||
|
||||
/* Whether to keep building subgoals when a sibling (another subgoal
|
||||
of the same goal) fails. */
|
||||
extern bool keepGoing;
|
||||
|
||||
/* Whether, if we cannot realise the known closure corresponding to a
|
||||
derivation, we should try to normalise the derivation instead. */
|
||||
extern bool tryFallback;
|
||||
|
||||
/* Verbosity level for build output. */
|
||||
extern Verbosity buildVerbosity;
|
||||
|
||||
/* Maximum number of parallel build jobs. 0 means unlimited. */
|
||||
extern unsigned int maxBuildJobs;
|
||||
|
||||
/* Number of CPU cores to utilize in parallel within a build, i.e. by passing
|
||||
this number to Make via '-j'. 0 means that the number of actual CPU cores on
|
||||
the local host ought to be auto-detected. */
|
||||
extern unsigned int buildCores;
|
||||
|
||||
/* Read-only mode. Don't copy stuff to the store, don't change the
|
||||
database. */
|
||||
extern bool readOnlyMode;
|
||||
|
||||
/* The canonical system name, as returned by config.guess. */
|
||||
extern string thisSystem;
|
||||
|
||||
/* The maximum time in seconds that a builer can go without producing
|
||||
any output on stdout/stderr before it is killed. 0 means
|
||||
infinity. */
|
||||
extern time_t maxSilentTime;
|
||||
|
||||
/* The maximum duration in seconds that a builder can run. 0 means
|
||||
infinity. */
|
||||
extern time_t buildTimeout;
|
||||
|
||||
/* The substituters. There are programs that can somehow realise a
|
||||
store path without building, e.g., by downloading it or copying it
|
||||
from a CD. */
|
||||
extern Paths substituters;
|
||||
|
||||
/* Whether to use build hooks (for distributed builds). Sometimes
|
||||
users want to disable this from the command-line. */
|
||||
extern bool useBuildHook;
|
||||
|
||||
/* Whether buildDerivations() should print out lines on stderr in a
|
||||
fixed format to allow its progress to be monitored. Each line
|
||||
starts with a "@". The following are defined:
|
||||
|
||||
@ build-started <drvpath> <outpath> <system> <logfile>
|
||||
@ build-failed <drvpath> <outpath> <exitcode> <error text>
|
||||
@ build-succeeded <drvpath> <outpath>
|
||||
@ substituter-started <outpath> <substituter>
|
||||
@ substituter-failed <outpath> <exitcode> <error text>
|
||||
@ substituter-succeeded <outpath>
|
||||
|
||||
Best combined with --no-build-output, otherwise stderr might
|
||||
conceivably contain lines in this format printed by the builders.
|
||||
*/
|
||||
extern bool printBuildTrace;
|
||||
|
||||
|
||||
Strings querySetting(const string & name, const Strings & def);
|
||||
|
||||
string querySetting(const string & name, const string & def);
|
||||
|
||||
bool queryBoolSetting(const string & name, bool def);
|
||||
|
||||
unsigned int queryIntSetting(const string & name, unsigned int def);
|
||||
|
||||
void overrideSetting(const string & name, const Strings & value);
|
||||
|
||||
void reloadSettings();
|
||||
|
||||
void setDefaultsFromEnvironment();
|
||||
|
||||
string packSettings();
|
||||
// FIXME: don't use a global variable.
|
||||
extern Settings settings;
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -181,7 +181,7 @@ struct SQLiteTxn
|
|||
void checkStoreNotSymlink()
|
||||
{
|
||||
if (getEnv("NIX_IGNORE_SYMLINK_STORE") == "1") return;
|
||||
Path path = nixStore;
|
||||
Path path = settings.nixStore;
|
||||
struct stat st;
|
||||
while (path != "/") {
|
||||
if (lstat(path.c_str(), &st))
|
||||
|
@ -198,21 +198,21 @@ void checkStoreNotSymlink()
|
|||
|
||||
LocalStore::LocalStore(bool reserveSpace)
|
||||
{
|
||||
schemaPath = nixDBPath + "/schema";
|
||||
schemaPath = settings.nixDBPath + "/schema";
|
||||
|
||||
if (readOnlyMode) {
|
||||
if (settings.readOnlyMode) {
|
||||
openDB(false);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Create missing state directories if they don't already exist. */
|
||||
createDirs(nixStore);
|
||||
createDirs(linksDir = nixStore + "/.links");
|
||||
Path profilesDir = nixStateDir + "/profiles";
|
||||
createDirs(nixStateDir + "/profiles");
|
||||
createDirs(nixStateDir + "/temproots");
|
||||
createDirs(nixDBPath);
|
||||
Path gcRootsDir = nixStateDir + "/gcroots";
|
||||
createDirs(settings.nixStore);
|
||||
createDirs(linksDir = settings.nixStore + "/.links");
|
||||
Path profilesDir = settings.nixStateDir + "/profiles";
|
||||
createDirs(settings.nixStateDir + "/profiles");
|
||||
createDirs(settings.nixStateDir + "/temproots");
|
||||
createDirs(settings.nixDBPath);
|
||||
Path gcRootsDir = settings.nixStateDir + "/gcroots";
|
||||
if (!pathExists(gcRootsDir)) {
|
||||
createDirs(gcRootsDir);
|
||||
if (symlink(profilesDir.c_str(), (gcRootsDir + "/profiles").c_str()) == -1)
|
||||
|
@ -226,13 +226,12 @@ LocalStore::LocalStore(bool reserveSpace)
|
|||
needed, we reserve some dummy space that we can free just
|
||||
before doing a garbage collection. */
|
||||
try {
|
||||
Path reservedPath = nixDBPath + "/reserved";
|
||||
Path reservedPath = settings.nixDBPath + "/reserved";
|
||||
if (reserveSpace) {
|
||||
int reservedSize = queryIntSetting("gc-reserved-space", 1024 * 1024);
|
||||
struct stat st;
|
||||
if (stat(reservedPath.c_str(), &st) == -1 ||
|
||||
st.st_size != reservedSize)
|
||||
writeFile(reservedPath, string(reservedSize, 'X'));
|
||||
st.st_size != settings.reservedSize)
|
||||
writeFile(reservedPath, string(settings.reservedSize, 'X'));
|
||||
}
|
||||
else
|
||||
deletePath(reservedPath);
|
||||
|
@ -242,11 +241,11 @@ LocalStore::LocalStore(bool reserveSpace)
|
|||
/* Acquire the big fat lock in shared mode to make sure that no
|
||||
schema upgrade is in progress. */
|
||||
try {
|
||||
Path globalLockPath = nixDBPath + "/big-lock";
|
||||
Path globalLockPath = settings.nixDBPath + "/big-lock";
|
||||
globalLock = openLockFile(globalLockPath.c_str(), true);
|
||||
} catch (SysError & e) {
|
||||
if (e.errNo != EACCES) throw;
|
||||
readOnlyMode = true;
|
||||
settings.readOnlyMode = true;
|
||||
openDB(false);
|
||||
return;
|
||||
}
|
||||
|
@ -325,7 +324,7 @@ int LocalStore::getSchema()
|
|||
void LocalStore::openDB(bool create)
|
||||
{
|
||||
/* Open the Nix database. */
|
||||
if (sqlite3_open_v2((nixDBPath + "/db.sqlite").c_str(), &db.db,
|
||||
if (sqlite3_open_v2((settings.nixDBPath + "/db.sqlite").c_str(), &db.db,
|
||||
SQLITE_OPEN_READWRITE | (create ? SQLITE_OPEN_CREATE : 0), 0) != SQLITE_OK)
|
||||
throw Error("cannot open SQLite database");
|
||||
|
||||
|
@ -342,13 +341,13 @@ void LocalStore::openDB(bool create)
|
|||
should be safe enough. If the user asks for it, don't sync at
|
||||
all. This can cause database corruption if the system
|
||||
crashes. */
|
||||
string syncMode = queryBoolSetting("fsync-metadata", true) ? "normal" : "off";
|
||||
string syncMode = settings.fsyncMetadata ? "normal" : "off";
|
||||
if (sqlite3_exec(db, ("pragma synchronous = " + syncMode + ";").c_str(), 0, 0, 0) != SQLITE_OK)
|
||||
throwSQLiteError(db, "setting synchronous mode");
|
||||
|
||||
/* Set the SQLite journal mode. WAL mode is fastest, so it's the
|
||||
default. */
|
||||
string mode = queryBoolSetting("use-sqlite-wal", true) ? "wal" : "truncate";
|
||||
string mode = settings.useSQLiteWAL ? "wal" : "truncate";
|
||||
string prevMode;
|
||||
{
|
||||
SQLiteStmt stmt;
|
||||
|
@ -890,7 +889,7 @@ Path LocalStore::queryPathFromHashPart(const string & hashPart)
|
|||
|
||||
SQLiteTxn txn(db);
|
||||
|
||||
Path prefix = nixStore + "/" + hashPart;
|
||||
Path prefix = settings.nixStore + "/" + hashPart;
|
||||
|
||||
SQLiteStmtUse use(stmtQueryPathFromHashPart);
|
||||
stmtQueryPathFromHashPart.bind(prefix);
|
||||
|
@ -933,7 +932,7 @@ void LocalStore::startSubstituter(const Path & substituter, RunningSubstituter &
|
|||
|
||||
/* Pass configuration options (including those overriden
|
||||
with --option) to the substituter. */
|
||||
setenv("_NIX_OPTIONS", packSettings().c_str(), 1);
|
||||
setenv("_NIX_OPTIONS", settings.pack().c_str(), 1);
|
||||
|
||||
fromPipe.readSide.close();
|
||||
toPipe.writeSide.close();
|
||||
|
@ -969,7 +968,7 @@ template<class T> T getIntLine(int fd)
|
|||
PathSet LocalStore::querySubstitutablePaths(const PathSet & paths)
|
||||
{
|
||||
PathSet res;
|
||||
foreach (Paths::iterator, i, substituters) {
|
||||
foreach (Paths::iterator, i, settings.substituters) {
|
||||
if (res.size() == paths.size()) break;
|
||||
RunningSubstituter & run(runningSubstituters[*i]);
|
||||
startSubstituter(*i, run);
|
||||
|
@ -1023,7 +1022,7 @@ void LocalStore::querySubstitutablePathInfos(const PathSet & paths,
|
|||
SubstitutablePathInfos & infos)
|
||||
{
|
||||
PathSet todo = paths;
|
||||
foreach (Paths::iterator, i, substituters) {
|
||||
foreach (Paths::iterator, i, settings.substituters) {
|
||||
if (todo.empty()) break;
|
||||
querySubstitutablePathInfos(*i, todo, infos);
|
||||
}
|
||||
|
@ -1046,11 +1045,10 @@ void LocalStore::registerValidPath(const ValidPathInfo & info)
|
|||
|
||||
void LocalStore::registerValidPaths(const ValidPathInfos & infos)
|
||||
{
|
||||
/* sqlite will fsync by default, but the new valid paths may not be fsync-ed.
|
||||
/* SQLite will fsync by default, but the new valid paths may not be fsync-ed.
|
||||
* So some may want to fsync them before registering the validity, at the
|
||||
* expense of some speed of the path registering operation. */
|
||||
if (queryBoolSetting("sync-before-registering", false))
|
||||
sync();
|
||||
if (settings.syncBeforeRegistering) sync();
|
||||
|
||||
while (1) {
|
||||
try {
|
||||
|
@ -1294,7 +1292,7 @@ void LocalStore::exportPath(const Path & path, bool sign,
|
|||
Path hashFile = tmpDir + "/hash";
|
||||
writeFile(hashFile, printHash(hash));
|
||||
|
||||
Path secretKey = nixConfDir + "/signing-key.sec";
|
||||
Path secretKey = settings.nixConfDir + "/signing-key.sec";
|
||||
checkSecrecy(secretKey);
|
||||
|
||||
Strings args;
|
||||
|
@ -1340,7 +1338,7 @@ Path LocalStore::createTempDirInStore()
|
|||
/* There is a slight possibility that `tmpDir' gets deleted by
|
||||
the GC between createTempDir() and addTempRoot(), so repeat
|
||||
until `tmpDir' exists. */
|
||||
tmpDir = createTempDir(nixStore);
|
||||
tmpDir = createTempDir(settings.nixStore);
|
||||
addTempRoot(tmpDir);
|
||||
} while (!pathExists(tmpDir));
|
||||
return tmpDir;
|
||||
|
@ -1392,7 +1390,7 @@ Path LocalStore::importPath(bool requireSignature, Source & source)
|
|||
args.push_back("rsautl");
|
||||
args.push_back("-verify");
|
||||
args.push_back("-inkey");
|
||||
args.push_back(nixConfDir + "/signing-key.pub");
|
||||
args.push_back(settings.nixConfDir + "/signing-key.pub");
|
||||
args.push_back("-pubin");
|
||||
args.push_back("-in");
|
||||
args.push_back(sigFile);
|
||||
|
@ -1501,7 +1499,7 @@ void LocalStore::verifyStore(bool checkContents)
|
|||
/* Acquire the global GC lock to prevent a garbage collection. */
|
||||
AutoCloseFD fdGCLock = openGCLock(ltWrite);
|
||||
|
||||
Paths entries = readDirectory(nixStore);
|
||||
Paths entries = readDirectory(settings.nixStore);
|
||||
PathSet store(entries.begin(), entries.end());
|
||||
|
||||
/* Check whether all valid paths actually exist. */
|
||||
|
@ -1611,9 +1609,9 @@ void LocalStore::verifyPath(const Path & path, const PathSet & store,
|
|||
PathSet LocalStore::queryValidPathsOld()
|
||||
{
|
||||
PathSet paths;
|
||||
Strings entries = readDirectory(nixDBPath + "/info");
|
||||
Strings entries = readDirectory(settings.nixDBPath + "/info");
|
||||
foreach (Strings::iterator, i, entries)
|
||||
if (i->at(0) != '.') paths.insert(nixStore + "/" + *i);
|
||||
if (i->at(0) != '.') paths.insert(settings.nixStore + "/" + *i);
|
||||
return paths;
|
||||
}
|
||||
|
||||
|
@ -1625,7 +1623,7 @@ ValidPathInfo LocalStore::queryPathInfoOld(const Path & path)
|
|||
|
||||
/* Read the info file. */
|
||||
string baseName = baseNameOf(path);
|
||||
Path infoFile = (format("%1%/info/%2%") % nixDBPath % baseName).str();
|
||||
Path infoFile = (format("%1%/info/%2%") % settings.nixDBPath % baseName).str();
|
||||
if (!pathExists(infoFile))
|
||||
throw Error(format("path `%1%' is not valid") % path);
|
||||
string info = readFile(infoFile);
|
||||
|
|
|
@ -75,7 +75,7 @@ struct SQLiteStmt
|
|||
void bind64(long long value);
|
||||
void bind();
|
||||
};
|
||||
|
||||
|
||||
|
||||
class LocalStore : public StoreAPI
|
||||
{
|
||||
|
@ -84,7 +84,7 @@ private:
|
|||
RunningSubstituters runningSubstituters;
|
||||
|
||||
Path linksDir;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
/* Initialise the local store, upgrading the schema if
|
||||
|
@ -92,15 +92,15 @@ public:
|
|||
LocalStore(bool reserveSpace = true);
|
||||
|
||||
~LocalStore();
|
||||
|
||||
|
||||
/* Implementations of abstract store API methods. */
|
||||
|
||||
|
||||
bool isValidPath(const Path & path);
|
||||
|
||||
PathSet queryValidPaths(const PathSet & paths);
|
||||
|
||||
|
||||
PathSet queryAllValidPaths();
|
||||
|
||||
|
||||
ValidPathInfo queryPathInfo(const Path & path);
|
||||
|
||||
Hash queryPathHash(const Path & path);
|
||||
|
@ -120,17 +120,17 @@ public:
|
|||
PathSet queryDerivationOutputs(const Path & path);
|
||||
|
||||
StringSet queryDerivationOutputNames(const Path & path);
|
||||
|
||||
|
||||
Path queryPathFromHashPart(const string & hashPart);
|
||||
|
||||
|
||||
PathSet querySubstitutablePaths(const PathSet & paths);
|
||||
|
||||
void querySubstitutablePathInfos(const Path & substituter,
|
||||
PathSet & paths, SubstitutablePathInfos & infos);
|
||||
|
||||
|
||||
void querySubstitutablePathInfos(const PathSet & paths,
|
||||
SubstitutablePathInfos & infos);
|
||||
|
||||
|
||||
Path addToStore(const Path & srcPath,
|
||||
bool recursive = true, HashType hashAlgo = htSHA256,
|
||||
PathFilter & filter = defaultPathFilter);
|
||||
|
@ -149,7 +149,7 @@ public:
|
|||
Sink & sink);
|
||||
|
||||
Paths importPaths(bool requireSignature, Source & source);
|
||||
|
||||
|
||||
void buildPaths(const PathSet & paths);
|
||||
|
||||
void ensurePath(const Path & path);
|
||||
|
@ -157,7 +157,7 @@ public:
|
|||
void addTempRoot(const Path & path);
|
||||
|
||||
void addIndirectRoot(const Path & path);
|
||||
|
||||
|
||||
void syncWithGC();
|
||||
|
||||
Roots findRoots();
|
||||
|
@ -170,7 +170,7 @@ public:
|
|||
|
||||
/* Optimise a single store path. */
|
||||
void optimisePath(const Path & path);
|
||||
|
||||
|
||||
/* Check the integrity of the Nix store. */
|
||||
void verifyStore(bool checkContents);
|
||||
|
||||
|
@ -229,18 +229,18 @@ private:
|
|||
unsigned long long queryValidPathId(const Path & path);
|
||||
|
||||
unsigned long long addValidPath(const ValidPathInfo & info, bool checkOutputs = true);
|
||||
|
||||
|
||||
void addReference(unsigned long long referrer, unsigned long long reference);
|
||||
|
||||
|
||||
void appendReferrer(const Path & from, const Path & to, bool lock);
|
||||
|
||||
|
||||
void rewriteReferrers(const Path & path, bool purge, PathSet referrers);
|
||||
|
||||
void invalidatePath(const Path & path);
|
||||
|
||||
/* Delete a path from the Nix store. */
|
||||
void invalidatePathChecked(const Path & path);
|
||||
|
||||
|
||||
void verifyPath(const Path & path, const PathSet & store,
|
||||
PathSet & done, PathSet & validPaths);
|
||||
|
||||
|
@ -253,14 +253,14 @@ private:
|
|||
struct GCState;
|
||||
|
||||
void deleteGarbage(GCState & state, const Path & path);
|
||||
|
||||
|
||||
bool tryToDelete(GCState & state, const Path & path);
|
||||
|
||||
|
||||
bool isActiveTempFile(const GCState & state,
|
||||
const Path & path, const string & suffix);
|
||||
|
||||
|
||||
int openGCLock(LockType lockType);
|
||||
|
||||
|
||||
void removeUnusedLinks();
|
||||
|
||||
void startSubstituter(const Path & substituter,
|
||||
|
@ -269,7 +269,7 @@ private:
|
|||
Path createTempDirInStore();
|
||||
|
||||
Path importPath(bool requireSignature, Source & source);
|
||||
|
||||
|
||||
void checkDerivationOutputs(const Path & drvPath, const Derivation & drv);
|
||||
|
||||
void optimisePath_(OptimiseStats & stats, const Path & path);
|
||||
|
@ -290,9 +290,6 @@ void canonicalisePathMetaData(const Path & path, bool recurse);
|
|||
|
||||
MakeError(PathInUse, Error);
|
||||
|
||||
/* Whether we are in build users mode. */
|
||||
bool haveBuildUsers();
|
||||
|
||||
/* Whether we are root. */
|
||||
bool amPrivileged();
|
||||
|
||||
|
@ -305,5 +302,5 @@ void deletePathWrapped(const Path & path,
|
|||
unsigned long long & bytesFreed, unsigned long long & blocksFreed);
|
||||
|
||||
void deletePathWrapped(const Path & path);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -52,10 +52,8 @@ void queryMissing(StoreAPI & store, const PathSet & targets,
|
|||
unsigned long long & downloadSize, unsigned long long & narSize)
|
||||
{
|
||||
downloadSize = narSize = 0;
|
||||
|
||||
PathSet todo(targets.begin(), targets.end()), done;
|
||||
|
||||
bool useSubstitutes = queryBoolSetting("build-use-substitutes", true);
|
||||
PathSet todo(targets.begin(), targets.end()), done;
|
||||
|
||||
/* Getting substitute info has high latency when using the binary
|
||||
cache substituter. Thus it's essential to do substitute
|
||||
|
@ -77,7 +75,7 @@ void queryMissing(StoreAPI & store, const PathSet & targets,
|
|||
*/
|
||||
|
||||
while (!todo.empty()) {
|
||||
|
||||
|
||||
PathSet query, todoDrv, todoNonDrv;
|
||||
|
||||
foreach (PathSet::iterator, i, todo) {
|
||||
|
@ -96,9 +94,9 @@ void queryMissing(StoreAPI & store, const PathSet & targets,
|
|||
foreach (DerivationOutputs::iterator, j, drv.outputs)
|
||||
if (!store.isValidPath(j->second.path)) invalid.insert(j->second.path);
|
||||
if (invalid.empty()) continue;
|
||||
|
||||
|
||||
todoDrv.insert(*i);
|
||||
if (useSubstitutes) query.insert(invalid.begin(), invalid.end());
|
||||
if (settings.useSubstitutes) query.insert(invalid.begin(), invalid.end());
|
||||
}
|
||||
|
||||
else {
|
||||
|
@ -109,7 +107,7 @@ void queryMissing(StoreAPI & store, const PathSet & targets,
|
|||
}
|
||||
|
||||
todo.clear();
|
||||
|
||||
|
||||
SubstitutablePathInfos infos;
|
||||
store.querySubstitutablePathInfos(query, infos);
|
||||
|
||||
|
@ -118,7 +116,7 @@ void queryMissing(StoreAPI & store, const PathSet & targets,
|
|||
Derivation drv = derivationFromPath(store, *i);
|
||||
|
||||
bool mustBuild = false;
|
||||
if (useSubstitutes) {
|
||||
if (settings.useSubstitutes) {
|
||||
foreach (DerivationOutputs::iterator, j, drv.outputs)
|
||||
if (!store.isValidPath(j->second.path) &&
|
||||
infos.find(j->second.path) == infos.end())
|
||||
|
@ -135,7 +133,7 @@ void queryMissing(StoreAPI & store, const PathSet & targets,
|
|||
foreach (DerivationOutputs::iterator, i, drv.outputs)
|
||||
todoNonDrv.insert(i->second.path);
|
||||
}
|
||||
|
||||
|
||||
foreach (PathSet::iterator, i, todoNonDrv) {
|
||||
done.insert(*i);
|
||||
SubstitutablePathInfos::iterator info = infos.find(*i);
|
||||
|
@ -150,22 +148,22 @@ void queryMissing(StoreAPI & store, const PathSet & targets,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void dfsVisit(StoreAPI & store, const PathSet & paths,
|
||||
const Path & path, PathSet & visited, Paths & sorted,
|
||||
PathSet & parents)
|
||||
{
|
||||
if (parents.find(path) != parents.end())
|
||||
throw BuildError(format("cycle detected in the references of `%1%'") % path);
|
||||
|
||||
|
||||
if (visited.find(path) != visited.end()) return;
|
||||
visited.insert(path);
|
||||
parents.insert(path);
|
||||
|
||||
|
||||
PathSet references;
|
||||
if (store.isValidPath(path))
|
||||
store.queryReferences(path, references);
|
||||
|
||||
|
||||
foreach (PathSet::iterator, i, references)
|
||||
/* Don't traverse into paths that don't exist. That can
|
||||
happen due to substitutes for non-existent paths. */
|
||||
|
|
|
@ -17,7 +17,7 @@ static void makeWritable(const Path & path)
|
|||
{
|
||||
struct stat st;
|
||||
if (lstat(path.c_str(), &st))
|
||||
throw SysError(format("getting attributes of path `%1%'") % path);
|
||||
throw SysError(format("getting attributes of path `%1%'") % path);
|
||||
if (S_ISDIR(st.st_mode) || S_ISREG(st.st_mode)) makeMutable(path);
|
||||
if (chmod(path.c_str(), st.st_mode | S_IWUSR) == -1)
|
||||
throw SysError(format("changing writability of `%1%'") % path);
|
||||
|
@ -53,15 +53,15 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path)
|
|||
{
|
||||
struct stat st;
|
||||
if (lstat(path.c_str(), &st))
|
||||
throw SysError(format("getting attributes of path `%1%'") % path);
|
||||
throw SysError(format("getting attributes of path `%1%'") % path);
|
||||
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
Strings names = readDirectory(path);
|
||||
foreach (Strings::iterator, i, names)
|
||||
optimisePath_(stats, path + "/" + *i);
|
||||
foreach (Strings::iterator, i, names)
|
||||
optimisePath_(stats, path + "/" + *i);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* We can hard link regular files and maybe symlinks. */
|
||||
if (!S_ISREG(st.st_mode)
|
||||
#if CAN_LINK_SYMLINK
|
||||
|
@ -69,7 +69,7 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path)
|
|||
&& !S_ISLNK(st.st_mode)
|
||||
#endif
|
||||
) return;
|
||||
|
||||
|
||||
/* Sometimes SNAFUs can cause files in the Nix store to be
|
||||
modified, in particular when running programs as root under
|
||||
NixOS (example: $fontconfig/var/cache being modified). Skip
|
||||
|
@ -110,25 +110,25 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path)
|
|||
current file with a hard link to that file. */
|
||||
struct stat stLink;
|
||||
if (lstat(linkPath.c_str(), &stLink))
|
||||
throw SysError(format("getting attributes of path `%1%'") % linkPath);
|
||||
|
||||
throw SysError(format("getting attributes of path `%1%'") % linkPath);
|
||||
|
||||
stats.sameContents++;
|
||||
if (st.st_ino == stLink.st_ino) {
|
||||
printMsg(lvlDebug, format("`%1%' is already linked to `%2%'") % path % linkPath);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
printMsg(lvlTalkative, format("linking `%1%' to `%2%'") % path % linkPath);
|
||||
|
||||
Path tempLink = (format("%1%/.tmp-link-%2%-%3%")
|
||||
% nixStore % getpid() % rand()).str();
|
||||
% settings.nixStore % getpid() % rand()).str();
|
||||
|
||||
/* Make the containing directory writable, but only if it's not
|
||||
the store itself (we don't want or need to mess with its
|
||||
permissions). */
|
||||
bool mustToggle = !isStorePath(path);
|
||||
if (mustToggle) makeWritable(dirOf(path));
|
||||
|
||||
|
||||
/* When we're done, make the directory read-only again and reset
|
||||
its timestamp back to 0. */
|
||||
MakeReadOnly makeReadOnly(mustToggle ? dirOf(path) : "");
|
||||
|
@ -192,10 +192,8 @@ void LocalStore::optimiseStore(OptimiseStats & stats)
|
|||
|
||||
void LocalStore::optimisePath(const Path & path)
|
||||
{
|
||||
if (queryBoolSetting("auto-optimise-store", true)) {
|
||||
OptimiseStats stats;
|
||||
optimisePath_(stats, path);
|
||||
}
|
||||
OptimiseStats stats;
|
||||
if (settings.autoOptimiseStore) optimisePath_(stats, path);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ void RemoteStore::forkSlave()
|
|||
/* Start the worker. */
|
||||
Path worker = getEnv("NIX_WORKER");
|
||||
if (worker == "")
|
||||
worker = nixBinDir + "/nix-worker";
|
||||
worker = settings.nixBinDir + "/nix-worker";
|
||||
|
||||
child = fork();
|
||||
|
||||
|
@ -142,7 +142,7 @@ void RemoteStore::connectToDaemon()
|
|||
if (fdSocket == -1)
|
||||
throw SysError("cannot create Unix domain socket");
|
||||
|
||||
string socketPath = nixStateDir + DEFAULT_SOCKET_PATH;
|
||||
string socketPath = settings.nixStateDir + DEFAULT_SOCKET_PATH;
|
||||
|
||||
/* Urgh, sockaddr_un allows path names of only 108 characters. So
|
||||
chdir to the socket directory so that we can pass a relative
|
||||
|
@ -184,23 +184,23 @@ RemoteStore::~RemoteStore()
|
|||
void RemoteStore::setOptions()
|
||||
{
|
||||
writeInt(wopSetOptions, to);
|
||||
writeInt(keepFailed, to);
|
||||
writeInt(keepGoing, to);
|
||||
writeInt(tryFallback, to);
|
||||
writeInt(settings.keepFailed, to);
|
||||
writeInt(settings.keepGoing, to);
|
||||
writeInt(settings.tryFallback, to);
|
||||
writeInt(verbosity, to);
|
||||
writeInt(maxBuildJobs, to);
|
||||
writeInt(maxSilentTime, to);
|
||||
writeInt(settings.maxBuildJobs, to);
|
||||
writeInt(settings.maxSilentTime, to);
|
||||
if (GET_PROTOCOL_MINOR(daemonVersion) >= 2)
|
||||
writeInt(useBuildHook, to);
|
||||
writeInt(settings.useBuildHook, to);
|
||||
if (GET_PROTOCOL_MINOR(daemonVersion) >= 4) {
|
||||
writeInt(buildVerbosity, to);
|
||||
writeInt(settings.buildVerbosity, to);
|
||||
writeInt(logType, to);
|
||||
writeInt(printBuildTrace, to);
|
||||
writeInt(settings.printBuildTrace, to);
|
||||
}
|
||||
if (GET_PROTOCOL_MINOR(daemonVersion) >= 6)
|
||||
writeInt(buildCores, to);
|
||||
writeInt(settings.buildCores, to);
|
||||
if (GET_PROTOCOL_MINOR(daemonVersion) >= 10)
|
||||
writeInt(queryBoolSetting("build-use-substitutes", true), to);
|
||||
writeInt(settings.useSubstitutes, to);
|
||||
|
||||
processStderr();
|
||||
}
|
||||
|
|
|
@ -19,16 +19,16 @@ GCOptions::GCOptions()
|
|||
bool isInStore(const Path & path)
|
||||
{
|
||||
return path[0] == '/'
|
||||
&& string(path, 0, nixStore.size()) == nixStore
|
||||
&& path.size() >= nixStore.size() + 2
|
||||
&& path[nixStore.size()] == '/';
|
||||
&& string(path, 0, settings.nixStore.size()) == settings.nixStore
|
||||
&& path.size() >= settings.nixStore.size() + 2
|
||||
&& path[settings.nixStore.size()] == '/';
|
||||
}
|
||||
|
||||
|
||||
bool isStorePath(const Path & path)
|
||||
{
|
||||
return isInStore(path)
|
||||
&& path.find('/', nixStore.size() + 1) == Path::npos;
|
||||
&& path.find('/', settings.nixStore.size() + 1) == Path::npos;
|
||||
}
|
||||
|
||||
|
||||
|
@ -43,7 +43,7 @@ Path toStorePath(const Path & path)
|
|||
{
|
||||
if (!isInStore(path))
|
||||
throw Error(format("path `%1%' is not in the Nix store") % path);
|
||||
Path::size_type slash = path.find('/', nixStore.size() + 1);
|
||||
Path::size_type slash = path.find('/', settings.nixStore.size() + 1);
|
||||
if (slash == Path::npos)
|
||||
return path;
|
||||
else
|
||||
|
@ -74,7 +74,7 @@ Path followLinksToStorePath(const Path & path)
|
|||
string storePathToName(const Path & path)
|
||||
{
|
||||
assertStorePath(path);
|
||||
return string(path, nixStore.size() + 34);
|
||||
return string(path, settings.nixStore.size() + 34);
|
||||
}
|
||||
|
||||
|
||||
|
@ -173,11 +173,11 @@ Path makeStorePath(const string & type,
|
|||
{
|
||||
/* e.g., "source:sha256:1abc...:/nix/store:foo.tar.gz" */
|
||||
string s = type + ":sha256:" + printHash(hash) + ":"
|
||||
+ nixStore + ":" + name;
|
||||
+ settings.nixStore + ":" + name;
|
||||
|
||||
checkStoreName(name);
|
||||
|
||||
return nixStore + "/"
|
||||
return settings.nixStore + "/"
|
||||
+ printHash32(compressHash(hashString(htSHA256, s), 20))
|
||||
+ "-" + name;
|
||||
}
|
||||
|
|
|
@ -55,7 +55,6 @@ struct Globals
|
|||
EvalState state;
|
||||
bool dryRun;
|
||||
bool preserveInstalled;
|
||||
bool keepDerivations;
|
||||
string forceName;
|
||||
bool prebuiltOnly;
|
||||
};
|
||||
|
@ -266,8 +265,8 @@ static DrvInfos filterBySelector(EvalState & state, const DrvInfos & allElems,
|
|||
|
||||
if (k != newest.end()) {
|
||||
d = j->first.system == k->second.first.system ? 0 :
|
||||
j->first.system == thisSystem ? 1 :
|
||||
k->second.first.system == thisSystem ? -1 : 0;
|
||||
j->first.system == settings.thisSystem ? 1 :
|
||||
k->second.first.system == settings.thisSystem ? -1 : 0;
|
||||
if (d == 0)
|
||||
d = comparePriorities(state, j->first, k->second.first);
|
||||
if (d == 0)
|
||||
|
@ -498,7 +497,7 @@ static void installDerivations(Globals & globals,
|
|||
if (globals.dryRun) return;
|
||||
|
||||
if (createUserEnv(globals.state, allElems,
|
||||
profile, globals.keepDerivations, lockToken)) break;
|
||||
profile, settings.envKeepDerivations, lockToken)) break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -605,7 +604,7 @@ static void upgradeDerivations(Globals & globals,
|
|||
if (globals.dryRun) return;
|
||||
|
||||
if (createUserEnv(globals.state, newElems,
|
||||
globals.profile, globals.keepDerivations, lockToken)) break;
|
||||
globals.profile, settings.envKeepDerivations, lockToken)) break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -672,7 +671,7 @@ static void opSetFlag(Globals & globals,
|
|||
|
||||
/* Write the new user environment. */
|
||||
if (createUserEnv(globals.state, installedElems,
|
||||
globals.profile, globals.keepDerivations, lockToken)) break;
|
||||
globals.profile, settings.envKeepDerivations, lockToken)) break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -740,7 +739,7 @@ static void uninstallDerivations(Globals & globals, Strings & selectors,
|
|||
if (globals.dryRun) return;
|
||||
|
||||
if (createUserEnv(globals.state, newElems,
|
||||
profile, globals.keepDerivations, lockToken)) break;
|
||||
profile, settings.envKeepDerivations, lockToken)) break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -869,7 +868,7 @@ static void opQuery(Globals & globals,
|
|||
|
||||
enum { sInstalled, sAvailable } source = sInstalled;
|
||||
|
||||
readOnlyMode = true; /* makes evaluation a bit faster */
|
||||
settings.readOnlyMode = true; /* makes evaluation a bit faster */
|
||||
|
||||
for (Strings::iterator i = args.begin(); i != args.end(); ) {
|
||||
string arg = *i++;
|
||||
|
@ -1262,9 +1261,6 @@ void run(Strings args)
|
|||
globals.preserveInstalled = false;
|
||||
globals.prebuiltOnly = false;
|
||||
|
||||
globals.keepDerivations =
|
||||
queryBoolSetting("env-keep-derivations", false);
|
||||
|
||||
for (Strings::iterator i = args.begin(); i != args.end(); ) {
|
||||
string arg = *i++;
|
||||
|
||||
|
@ -1331,7 +1327,7 @@ void run(Strings args)
|
|||
Path profileLink = getHomeDir() + "/.nix-profile";
|
||||
globals.profile = pathExists(profileLink)
|
||||
? absPath(readLink(profileLink), dirOf(profileLink))
|
||||
: canonPath(nixStateDir + "/profiles/default");
|
||||
: canonPath(settings.nixStateDir + "/profiles/default");
|
||||
}
|
||||
|
||||
store = openStore();
|
||||
|
|
|
@ -94,11 +94,11 @@ void run(Strings args)
|
|||
if (arg == "-")
|
||||
readStdin = true;
|
||||
else if (arg == "--eval-only") {
|
||||
readOnlyMode = true;
|
||||
settings.readOnlyMode = true;
|
||||
evalOnly = true;
|
||||
}
|
||||
else if (arg == "--parse-only") {
|
||||
readOnlyMode = true;
|
||||
settings.readOnlyMode = true;
|
||||
parseOnly = evalOnly = true;
|
||||
}
|
||||
else if (arg == "--find-file")
|
||||
|
|
|
@ -47,7 +47,7 @@ LocalStore & ensureLocalStore()
|
|||
|
||||
|
||||
static Path useDeriver(Path path)
|
||||
{
|
||||
{
|
||||
if (!isDerivation(path)) {
|
||||
path = store->queryDeriver(path);
|
||||
if (path == "")
|
||||
|
@ -89,18 +89,18 @@ static PathSet realisePath(const Path & path)
|
|||
static void opRealise(Strings opFlags, Strings opArgs)
|
||||
{
|
||||
bool dryRun = false;
|
||||
|
||||
|
||||
foreach (Strings::iterator, i, opFlags)
|
||||
if (*i == "--dry-run") dryRun = true;
|
||||
else throw UsageError(format("unknown flag `%1%'") % *i);
|
||||
|
||||
foreach (Strings::iterator, i, opArgs)
|
||||
*i = followLinksToStorePath(*i);
|
||||
|
||||
|
||||
printMissing(*store, PathSet(opArgs.begin(), opArgs.end()));
|
||||
|
||||
|
||||
if (dryRun) return;
|
||||
|
||||
|
||||
/* Build all paths at the same time to exploit parallelism. */
|
||||
PathSet paths(opArgs.begin(), opArgs.end());
|
||||
store->buildPaths(paths);
|
||||
|
@ -128,7 +128,7 @@ static void opAdd(Strings opFlags, Strings opArgs)
|
|||
static void opAddFixed(Strings opFlags, Strings opArgs)
|
||||
{
|
||||
bool recursive = false;
|
||||
|
||||
|
||||
for (Strings::iterator i = opFlags.begin();
|
||||
i != opFlags.end(); ++i)
|
||||
if (*i == "--recursive") recursive = true;
|
||||
|
@ -136,7 +136,7 @@ static void opAddFixed(Strings opFlags, Strings opArgs)
|
|||
|
||||
if (opArgs.empty())
|
||||
throw UsageError("first argument must be hash algorithm");
|
||||
|
||||
|
||||
HashType hashAlgo = parseHashType(opArgs.front());
|
||||
opArgs.pop_front();
|
||||
|
||||
|
@ -149,7 +149,7 @@ static void opAddFixed(Strings opFlags, Strings opArgs)
|
|||
static void opPrintFixedPath(Strings opFlags, Strings opArgs)
|
||||
{
|
||||
bool recursive = false;
|
||||
|
||||
|
||||
for (Strings::iterator i = opFlags.begin();
|
||||
i != opFlags.end(); ++i)
|
||||
if (*i == "--recursive") recursive = true;
|
||||
|
@ -157,7 +157,7 @@ static void opPrintFixedPath(Strings opFlags, Strings opArgs)
|
|||
|
||||
if (opArgs.size() != 3)
|
||||
throw UsageError(format("`--print-fixed-path' requires three arguments"));
|
||||
|
||||
|
||||
Strings::iterator i = opArgs.begin();
|
||||
HashType hashAlgo = parseHashType(*i++);
|
||||
string hash = *i++;
|
||||
|
@ -205,12 +205,12 @@ static void printTree(const Path & path,
|
|||
|
||||
PathSet references;
|
||||
store->queryReferences(path, references);
|
||||
|
||||
#if 0
|
||||
|
||||
#if 0
|
||||
for (PathSet::iterator i = drv.inputSrcs.begin();
|
||||
i != drv.inputSrcs.end(); ++i)
|
||||
cout << format("%1%%2%\n") % (tailPad + treeConn) % *i;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Topologically sort under the relation A < B iff A \in
|
||||
closure(B). That is, if derivation A is an (possibly indirect)
|
||||
|
@ -266,7 +266,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
|
|||
else throw UsageError(format("unknown flag `%1%'") % *i);
|
||||
|
||||
switch (query) {
|
||||
|
||||
|
||||
case qOutputs: {
|
||||
foreach (Strings::iterator, i, opArgs) {
|
||||
*i = followLinksToStorePath(*i);
|
||||
|
@ -293,7 +293,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
|
|||
}
|
||||
}
|
||||
Paths sorted = topoSortPaths(*store, paths);
|
||||
for (Paths::reverse_iterator i = sorted.rbegin();
|
||||
for (Paths::reverse_iterator i = sorted.rbegin();
|
||||
i != sorted.rend(); ++i)
|
||||
cout << format("%s\n") % *i;
|
||||
break;
|
||||
|
@ -328,7 +328,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
|
|||
if (query == qHash) {
|
||||
assert(info.hash.type == htSHA256);
|
||||
cout << format("sha256:%1%\n") % printHash32(info.hash);
|
||||
} else if (query == qSize)
|
||||
} else if (query == qSize)
|
||||
cout << format("%1%\n") % info.narSize;
|
||||
}
|
||||
}
|
||||
|
@ -340,7 +340,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
|
|||
printTree(followLinksToStorePath(*i), "", "", done);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case qGraph: {
|
||||
PathSet roots;
|
||||
foreach (Strings::iterator, i, opArgs) {
|
||||
|
@ -366,7 +366,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
|
|||
cout << format("%1%\n") % followLinksToStorePath(*i);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case qRoots: {
|
||||
PathSet referrers;
|
||||
foreach (Strings::iterator, i, opArgs) {
|
||||
|
@ -380,7 +380,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
|
|||
cout << format("%1%\n") % i->first;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
@ -426,9 +426,9 @@ static void opReadLog(Strings opFlags, Strings opArgs)
|
|||
|
||||
foreach (Strings::iterator, i, opArgs) {
|
||||
Path path = useDeriver(followLinksToStorePath(*i));
|
||||
|
||||
|
||||
Path logPath = (format("%1%/%2%/%3%") %
|
||||
nixLogDir % drvsLogDir % baseNameOf(path)).str();
|
||||
settings.nixLogDir % drvsLogDir % baseNameOf(path)).str();
|
||||
Path logBz2Path = logPath + ".bz2";
|
||||
|
||||
if (pathExists(logPath)) {
|
||||
|
@ -454,7 +454,7 @@ static void opReadLog(Strings opFlags, Strings opArgs)
|
|||
} while (err != BZ_STREAM_END);
|
||||
BZ2_bzReadClose(&err, bz);
|
||||
}
|
||||
|
||||
|
||||
else throw Error(format("build log of derivation `%1%' is not available") % path);
|
||||
}
|
||||
}
|
||||
|
@ -474,7 +474,7 @@ static void opDumpDB(Strings opFlags, Strings opArgs)
|
|||
static void registerValidity(bool reregister, bool hashGiven, bool canonicalise)
|
||||
{
|
||||
ValidPathInfos infos;
|
||||
|
||||
|
||||
while (1) {
|
||||
ValidPathInfo info = decodeValidPathInfo(cin, hashGiven);
|
||||
if (info.path == "") break;
|
||||
|
@ -508,7 +508,7 @@ static void opRegisterValidity(Strings opFlags, Strings opArgs)
|
|||
{
|
||||
bool reregister = false; // !!! maybe this should be the default
|
||||
bool hashGiven = false;
|
||||
|
||||
|
||||
for (Strings::iterator i = opFlags.begin();
|
||||
i != opFlags.end(); ++i)
|
||||
if (*i == "--reregister") reregister = true;
|
||||
|
@ -524,7 +524,7 @@ static void opRegisterValidity(Strings opFlags, Strings opArgs)
|
|||
static void opCheckValidity(Strings opFlags, Strings opArgs)
|
||||
{
|
||||
bool printInvalid = false;
|
||||
|
||||
|
||||
for (Strings::iterator i = opFlags.begin();
|
||||
i != opFlags.end(); ++i)
|
||||
if (*i == "--print-invalid") printInvalid = true;
|
||||
|
@ -551,13 +551,13 @@ static string showBytes(unsigned long long bytes, unsigned long long blocks)
|
|||
}
|
||||
|
||||
|
||||
struct PrintFreed
|
||||
struct PrintFreed
|
||||
{
|
||||
bool show;
|
||||
const GCResults & results;
|
||||
PrintFreed(bool show, const GCResults & results)
|
||||
: show(show), results(results) { }
|
||||
~PrintFreed()
|
||||
~PrintFreed()
|
||||
{
|
||||
if (show)
|
||||
cout << format("%1% store paths deleted, %2% freed\n")
|
||||
|
@ -572,9 +572,9 @@ static void opGC(Strings opFlags, Strings opArgs)
|
|||
bool printRoots = false;
|
||||
GCOptions options;
|
||||
options.action = GCOptions::gcDeleteDead;
|
||||
|
||||
|
||||
GCResults results;
|
||||
|
||||
|
||||
/* Do what? */
|
||||
foreach (Strings::iterator, i, opFlags)
|
||||
if (*i == "--print-roots") printRoots = true;
|
||||
|
@ -613,14 +613,14 @@ static void opDelete(Strings opFlags, Strings opArgs)
|
|||
{
|
||||
GCOptions options;
|
||||
options.action = GCOptions::gcDeleteSpecific;
|
||||
|
||||
|
||||
foreach (Strings::iterator, i, opFlags)
|
||||
if (*i == "--ignore-liveness") options.ignoreLiveness = true;
|
||||
else throw UsageError(format("unknown flag `%1%'") % *i);
|
||||
|
||||
foreach (Strings::iterator, i, opArgs)
|
||||
options.pathsToDelete.insert(followLinksToStorePath(*i));
|
||||
|
||||
|
||||
GCResults results;
|
||||
PrintFreed freed(true, results);
|
||||
store->collectGarbage(options, results);
|
||||
|
@ -671,9 +671,9 @@ static void opImport(Strings opFlags, Strings opArgs)
|
|||
foreach (Strings::iterator, i, opFlags)
|
||||
if (*i == "--require-signature") requireSignature = true;
|
||||
else throw UsageError(format("unknown flag `%1%'") % *i);
|
||||
|
||||
|
||||
if (!opArgs.empty()) throw UsageError("no arguments expected");
|
||||
|
||||
|
||||
FdSource source(STDIN_FILENO);
|
||||
Paths paths = store->importPaths(requireSignature, source);
|
||||
|
||||
|
@ -700,12 +700,12 @@ static void opVerify(Strings opFlags, Strings opArgs)
|
|||
throw UsageError("no arguments expected");
|
||||
|
||||
bool checkContents = false;
|
||||
|
||||
|
||||
for (Strings::iterator i = opFlags.begin();
|
||||
i != opFlags.end(); ++i)
|
||||
if (*i == "--check-contents") checkContents = true;
|
||||
else throw UsageError(format("unknown flag `%1%'") % *i);
|
||||
|
||||
|
||||
ensureLocalStore().verifyStore(checkContents);
|
||||
}
|
||||
|
||||
|
@ -844,7 +844,7 @@ void run(Strings args)
|
|||
}
|
||||
else if (arg == "--indirect")
|
||||
indirectRoot = true;
|
||||
else if (arg[0] == '-') {
|
||||
else if (arg[0] == '-') {
|
||||
opFlags.push_back(arg);
|
||||
if (arg == "--max-freed" || arg == "--max-links" || arg == "--max-atime") { /* !!! hack */
|
||||
if (i != args.end()) opFlags.push_back(*i++);
|
||||
|
|
|
@ -527,27 +527,23 @@ static void performOp(unsigned int clientVersion,
|
|||
}
|
||||
|
||||
case wopSetOptions: {
|
||||
keepFailed = readInt(from) != 0;
|
||||
keepGoing = readInt(from) != 0;
|
||||
tryFallback = readInt(from) != 0;
|
||||
settings.keepFailed = readInt(from) != 0;
|
||||
settings.keepGoing = readInt(from) != 0;
|
||||
settings.tryFallback = readInt(from) != 0;
|
||||
verbosity = (Verbosity) readInt(from);
|
||||
maxBuildJobs = readInt(from);
|
||||
maxSilentTime = readInt(from);
|
||||
settings.maxBuildJobs = readInt(from);
|
||||
settings.maxSilentTime = readInt(from);
|
||||
if (GET_PROTOCOL_MINOR(clientVersion) >= 2)
|
||||
useBuildHook = readInt(from) != 0;
|
||||
settings.useBuildHook = readInt(from) != 0;
|
||||
if (GET_PROTOCOL_MINOR(clientVersion) >= 4) {
|
||||
buildVerbosity = (Verbosity) readInt(from);
|
||||
settings.buildVerbosity = (Verbosity) readInt(from);
|
||||
logType = (LogType) readInt(from);
|
||||
printBuildTrace = readInt(from) != 0;
|
||||
settings.printBuildTrace = readInt(from) != 0;
|
||||
}
|
||||
if (GET_PROTOCOL_MINOR(clientVersion) >= 6)
|
||||
buildCores = readInt(from);
|
||||
if (GET_PROTOCOL_MINOR(clientVersion) >= 10) {
|
||||
int x = readInt(from);
|
||||
Strings ss;
|
||||
ss.push_back(x == 0 ? "false" : "true");
|
||||
overrideSetting("build-use-substitutes", ss);
|
||||
}
|
||||
settings.buildCores = readInt(from);
|
||||
if (GET_PROTOCOL_MINOR(clientVersion) >= 10)
|
||||
settings.useSubstitutes = readInt(from) != 0;
|
||||
startWork();
|
||||
stopWork();
|
||||
break;
|
||||
|
@ -768,7 +764,7 @@ static void daemonLoop()
|
|||
if (fdSocket == -1)
|
||||
throw SysError("cannot create Unix domain socket");
|
||||
|
||||
string socketPath = nixStateDir + DEFAULT_SOCKET_PATH;
|
||||
string socketPath = settings.nixStateDir + DEFAULT_SOCKET_PATH;
|
||||
|
||||
createDirs(dirOf(socketPath));
|
||||
|
||||
|
@ -867,10 +863,6 @@ static void daemonLoop()
|
|||
strncpy(argvSaved[1], processName.c_str(), strlen(argvSaved[1]));
|
||||
}
|
||||
|
||||
/* Since the daemon can be long-running, the
|
||||
settings may have changed. So force a reload. */
|
||||
reloadSettings();
|
||||
|
||||
/* Handle the connection. */
|
||||
from.fd = remote;
|
||||
to.fd = remote;
|
||||
|
|
Loading…
Reference in a new issue