daemon: Use 'Agent' to spawn 'guix substitute --query'.
* nix/libstore/local-store.hh (RunningSubstituter): Remove. (LocalStore)[runningSubstituter]: Change to unique_ptr<Agent>. [setSubstituterEnv, didSetSubstituterEnv]: Remove. [getLineFromSubstituter, getIntLineFromSubstituter]: Take an 'Agent'. * nix/libstore/local-store.cc (LocalStore::~LocalStore): Remove reference to 'runningSubstituter'. (LocalStore::setSubstituterEnv, LocalStore::startSubstituter): Remove. (LocalStore::getLineFromSubstituter): Adjust to 'run' being an 'Agent'. (LocalStore::querySubstitutablePaths): Spawn substituter agent if needed. Adjust to 'Agent' interface. (LocalStore::querySubstitutablePathInfos): Likewise. * nix/libstore/build.cc (SubstitutionGoal::tryToRun): Remove call to 'setSubstituterEnv' and add 'setenv' call for "_NIX_OPTIONS" instead. (SubstitutionGoal::finished): Remove 'readLine' call for 'dummy'. * guix/scripts/substitute.scm (%allow-unauthenticated-substitutes?): Remove second argument to 'make-parameter'. (process-query): Call 'warn-about-missing-authentication' when (%allow-unauthenticated-substitutes?) is #t. (guix-substitute): Wrap body in 'parameterize'. Set 'guix-warning-port' too. No longer exit when 'substitute-urls' returns the empty list. No longer print newline initially. * tests/substitute.scm (test-quit): Parameterize 'current-error-port' to account for the port changes in 'guix-substitute'.master
parent
2e308238ad
commit
79c6614f58
|
@ -124,11 +124,7 @@ disabled!~%"))
|
||||||
;; purposes, and should be avoided otherwise.
|
;; purposes, and should be avoided otherwise.
|
||||||
(make-parameter
|
(make-parameter
|
||||||
(and=> (getenv "GUIX_ALLOW_UNAUTHENTICATED_SUBSTITUTES")
|
(and=> (getenv "GUIX_ALLOW_UNAUTHENTICATED_SUBSTITUTES")
|
||||||
(cut string-ci=? <> "yes"))
|
(cut string-ci=? <> "yes"))))
|
||||||
(lambda (value)
|
|
||||||
(when value
|
|
||||||
(warn-about-missing-authentication))
|
|
||||||
value)))
|
|
||||||
|
|
||||||
(define %narinfo-ttl
|
(define %narinfo-ttl
|
||||||
;; Number of seconds during which cached narinfo lookups are considered
|
;; Number of seconds during which cached narinfo lookups are considered
|
||||||
|
@ -893,6 +889,9 @@ authorized substitutes."
|
||||||
(define (valid? obj)
|
(define (valid? obj)
|
||||||
(valid-narinfo? obj acl))
|
(valid-narinfo? obj acl))
|
||||||
|
|
||||||
|
(when (%allow-unauthenticated-substitutes?)
|
||||||
|
(warn-about-missing-authentication))
|
||||||
|
|
||||||
(match (string-tokenize command)
|
(match (string-tokenize command)
|
||||||
(("have" paths ..1)
|
(("have" paths ..1)
|
||||||
;; Return the subset of PATHS available in CACHE-URLS.
|
;; Return the subset of PATHS available in CACHE-URLS.
|
||||||
|
@ -1139,68 +1138,67 @@ default value."
|
||||||
((= string->number number) (> number 0))
|
((= string->number number) (> number 0))
|
||||||
(_ #f)))
|
(_ #f)))
|
||||||
|
|
||||||
(mkdir-p %narinfo-cache-directory)
|
;; The daemon's agent code opens file descriptor 4 for us and this is where
|
||||||
(maybe-remove-expired-cache-entries %narinfo-cache-directory
|
;; stderr should go.
|
||||||
cached-narinfo-files
|
(parameterize ((current-error-port (match args
|
||||||
#:entry-expiration
|
(("--query") (fdopen 4 "wl"))
|
||||||
cached-narinfo-expiration-time
|
(_ (current-error-port)))))
|
||||||
#:cleanup-period
|
;; Redirect diagnostics to file descriptor 4 as well.
|
||||||
%narinfo-expired-cache-entry-removal-delay)
|
(guix-warning-port (current-error-port))
|
||||||
(check-acl-initialized)
|
|
||||||
|
|
||||||
;; Starting from commit 22144afa in Nix, we are allowed to bail out directly
|
(mkdir-p %narinfo-cache-directory)
|
||||||
;; when we know we cannot substitute, but we must emit a newline on stdout
|
(maybe-remove-expired-cache-entries %narinfo-cache-directory
|
||||||
;; when everything is alright.
|
cached-narinfo-files
|
||||||
(when (null? (substitute-urls))
|
#:entry-expiration
|
||||||
(exit 0))
|
cached-narinfo-expiration-time
|
||||||
|
#:cleanup-period
|
||||||
|
%narinfo-expired-cache-entry-removal-delay)
|
||||||
|
(check-acl-initialized)
|
||||||
|
|
||||||
;; Say hello (see above.)
|
;; Sanity-check SUBSTITUTE-URLS so we can provide a meaningful error
|
||||||
(newline)
|
;; message.
|
||||||
(force-output (current-output-port))
|
(for-each validate-uri (substitute-urls))
|
||||||
|
|
||||||
;; Sanity-check SUBSTITUTE-URLS so we can provide a meaningful error message.
|
;; Attempt to install the client's locale so that messages are suitably
|
||||||
(for-each validate-uri (substitute-urls))
|
;; translated. LC_CTYPE must be a UTF-8 locale; it's the case by default
|
||||||
|
;; so don't change it.
|
||||||
|
(match (or (find-daemon-option "untrusted-locale")
|
||||||
|
(find-daemon-option "locale"))
|
||||||
|
(#f #f)
|
||||||
|
(locale (false-if-exception (setlocale LC_MESSAGES locale))))
|
||||||
|
|
||||||
;; Attempt to install the client's locale so that messages are suitably
|
(catch 'system-error
|
||||||
;; translated. LC_CTYPE must be a UTF-8 locale; it's the case by default so
|
(lambda ()
|
||||||
;; don't change it.
|
(set-thread-name "guix substitute"))
|
||||||
(match (or (find-daemon-option "untrusted-locale")
|
(const #t)) ;GNU/Hurd lacks 'prctl'
|
||||||
(find-daemon-option "locale"))
|
|
||||||
(#f #f)
|
|
||||||
(locale (false-if-exception (setlocale LC_MESSAGES locale))))
|
|
||||||
|
|
||||||
(catch 'system-error
|
(with-networking
|
||||||
(lambda ()
|
(with-error-handling ; for signature errors
|
||||||
(set-thread-name "guix substitute"))
|
(match args
|
||||||
(const #t)) ;GNU/Hurd lacks 'prctl'
|
(("--query")
|
||||||
|
(let ((acl (current-acl)))
|
||||||
(with-networking
|
(let loop ((command (read-line)))
|
||||||
(with-error-handling ; for signature errors
|
(or (eof-object? command)
|
||||||
(match args
|
(begin
|
||||||
(("--query")
|
(process-query command
|
||||||
(let ((acl (current-acl)))
|
#:cache-urls (substitute-urls)
|
||||||
(let loop ((command (read-line)))
|
#:acl acl)
|
||||||
(or (eof-object? command)
|
(loop (read-line)))))))
|
||||||
(begin
|
(("--substitute" store-path destination)
|
||||||
(process-query command
|
;; Download STORE-PATH and store it as a Nar in file DESTINATION.
|
||||||
#:cache-urls (substitute-urls)
|
;; Specify the number of columns of the terminal so the progress
|
||||||
#:acl acl)
|
;; report displays nicely.
|
||||||
(loop (read-line)))))))
|
(parameterize ((current-terminal-columns (client-terminal-columns)))
|
||||||
(("--substitute" store-path destination)
|
(process-substitution store-path destination
|
||||||
;; Download STORE-PATH and add store it as a Nar in file DESTINATION.
|
#:cache-urls (substitute-urls)
|
||||||
;; Specify the number of columns of the terminal so the progress
|
#:acl (current-acl)
|
||||||
;; report displays nicely.
|
#:print-build-trace? print-build-trace?)))
|
||||||
(parameterize ((current-terminal-columns (client-terminal-columns)))
|
((or ("-V") ("--version"))
|
||||||
(process-substitution store-path destination
|
(show-version-and-exit "guix substitute"))
|
||||||
#:cache-urls (substitute-urls)
|
(("--help")
|
||||||
#:acl (current-acl)
|
(show-help))
|
||||||
#:print-build-trace? print-build-trace?)))
|
(opts
|
||||||
((or ("-V") ("--version"))
|
(leave (G_ "~a: unrecognized options~%") opts)))))))
|
||||||
(show-version-and-exit "guix substitute"))
|
|
||||||
(("--help")
|
|
||||||
(show-help))
|
|
||||||
(opts
|
|
||||||
(leave (G_ "~a: unrecognized options~%") opts))))))
|
|
||||||
|
|
||||||
;;; Local Variables:
|
;;; Local Variables:
|
||||||
;;; eval: (put 'with-timeout 'scheme-indent-function 1)
|
;;; eval: (put 'with-timeout 'scheme-indent-function 1)
|
||||||
|
|
|
@ -2986,8 +2986,6 @@ void SubstitutionGoal::tryToRun()
|
||||||
if (pathExists(destPath))
|
if (pathExists(destPath))
|
||||||
deletePath(destPath);
|
deletePath(destPath);
|
||||||
|
|
||||||
worker.store.setSubstituterEnv();
|
|
||||||
|
|
||||||
/* Fill in the arguments. */
|
/* Fill in the arguments. */
|
||||||
Strings args;
|
Strings args;
|
||||||
args.push_back("guix");
|
args.push_back("guix");
|
||||||
|
@ -2999,6 +2997,9 @@ void SubstitutionGoal::tryToRun()
|
||||||
/* Fork the substitute program. */
|
/* Fork the substitute program. */
|
||||||
pid = startProcess([&]() {
|
pid = startProcess([&]() {
|
||||||
|
|
||||||
|
/* Communicate substitute-urls & co. to 'guix substitute'. */
|
||||||
|
setenv("_NIX_OPTIONS", settings.pack().c_str(), 1);
|
||||||
|
|
||||||
commonChildInit(logPipe);
|
commonChildInit(logPipe);
|
||||||
|
|
||||||
if (dup2(outPipe.writeSide, STDOUT_FILENO) == -1)
|
if (dup2(outPipe.writeSide, STDOUT_FILENO) == -1)
|
||||||
|
@ -3041,7 +3042,6 @@ void SubstitutionGoal::finished()
|
||||||
logPipe.readSide.close();
|
logPipe.readSide.close();
|
||||||
|
|
||||||
/* Get the hash info from stdout. */
|
/* Get the hash info from stdout. */
|
||||||
string dummy = readLine(outPipe.readSide);
|
|
||||||
string expectedHashStr = statusOk(status) ? readLine(outPipe.readSide) : "";
|
string expectedHashStr = statusOk(status) ? readLine(outPipe.readSide) : "";
|
||||||
outPipe.readSide.close();
|
outPipe.readSide.close();
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,6 @@ void checkStoreNotSymlink()
|
||||||
|
|
||||||
|
|
||||||
LocalStore::LocalStore(bool reserveSpace)
|
LocalStore::LocalStore(bool reserveSpace)
|
||||||
: didSetSubstituterEnv(false)
|
|
||||||
{
|
{
|
||||||
schemaPath = settings.nixDBPath + "/schema";
|
schemaPath = settings.nixDBPath + "/schema";
|
||||||
|
|
||||||
|
@ -182,21 +181,6 @@ LocalStore::LocalStore(bool reserveSpace)
|
||||||
|
|
||||||
LocalStore::~LocalStore()
|
LocalStore::~LocalStore()
|
||||||
{
|
{
|
||||||
try {
|
|
||||||
if (runningSubstituter) {
|
|
||||||
RunningSubstituter &i = *runningSubstituter;
|
|
||||||
if (!i.disabled) {
|
|
||||||
i.to.close();
|
|
||||||
i.from.close();
|
|
||||||
i.error.close();
|
|
||||||
if (i.pid != -1)
|
|
||||||
i.pid.wait(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (...) {
|
|
||||||
ignoreException();
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (fdTempRoots != -1) {
|
if (fdTempRoots != -1) {
|
||||||
fdTempRoots.close();
|
fdTempRoots.close();
|
||||||
|
@ -796,96 +780,31 @@ Path LocalStore::queryPathFromHashPart(const string & hashPart)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void LocalStore::setSubstituterEnv()
|
|
||||||
{
|
|
||||||
if (didSetSubstituterEnv) return;
|
|
||||||
|
|
||||||
/* Pass configuration options (including those overridden with
|
|
||||||
--option) to substituters. */
|
|
||||||
setenv("_NIX_OPTIONS", settings.pack().c_str(), 1);
|
|
||||||
|
|
||||||
didSetSubstituterEnv = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void LocalStore::startSubstituter(RunningSubstituter & run)
|
|
||||||
{
|
|
||||||
if (run.disabled || run.pid != -1) return;
|
|
||||||
|
|
||||||
debug(format("starting substituter program `%1% substitute'")
|
|
||||||
% settings.guixProgram);
|
|
||||||
|
|
||||||
Pipe toPipe, fromPipe, errorPipe;
|
|
||||||
|
|
||||||
toPipe.create();
|
|
||||||
fromPipe.create();
|
|
||||||
errorPipe.create();
|
|
||||||
|
|
||||||
setSubstituterEnv();
|
|
||||||
|
|
||||||
run.pid = startProcess([&]() {
|
|
||||||
if (dup2(toPipe.readSide, STDIN_FILENO) == -1)
|
|
||||||
throw SysError("dupping stdin");
|
|
||||||
if (dup2(fromPipe.writeSide, STDOUT_FILENO) == -1)
|
|
||||||
throw SysError("dupping stdout");
|
|
||||||
if (dup2(errorPipe.writeSide, STDERR_FILENO) == -1)
|
|
||||||
throw SysError("dupping stderr");
|
|
||||||
execl(settings.guixProgram.c_str(), "guix", "substitute", "--query", NULL);
|
|
||||||
throw SysError(format("executing `%1%'") % settings.guixProgram);
|
|
||||||
});
|
|
||||||
|
|
||||||
run.to = toPipe.writeSide.borrow();
|
|
||||||
run.from = run.fromBuf.fd = fromPipe.readSide.borrow();
|
|
||||||
run.error = errorPipe.readSide.borrow();
|
|
||||||
|
|
||||||
toPipe.readSide.close();
|
|
||||||
fromPipe.writeSide.close();
|
|
||||||
errorPipe.writeSide.close();
|
|
||||||
|
|
||||||
/* The substituter may exit right away if it's disabled in any way
|
|
||||||
(e.g. copy-from-other-stores.pl will exit if no other stores
|
|
||||||
are configured). */
|
|
||||||
try {
|
|
||||||
getLineFromSubstituter(run);
|
|
||||||
} catch (EndOfFile & e) {
|
|
||||||
run.to.close();
|
|
||||||
run.from.close();
|
|
||||||
run.error.close();
|
|
||||||
run.disabled = true;
|
|
||||||
if (run.pid.wait(true) != 0) throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Read a line from the substituter's stdout, while also processing
|
/* Read a line from the substituter's stdout, while also processing
|
||||||
its stderr. */
|
its stderr. */
|
||||||
string LocalStore::getLineFromSubstituter(RunningSubstituter & run)
|
string LocalStore::getLineFromSubstituter(Agent & run)
|
||||||
{
|
{
|
||||||
string res, err;
|
string res, err;
|
||||||
|
|
||||||
/* We might have stdout data left over from the last time. */
|
|
||||||
if (run.fromBuf.hasData()) goto haveData;
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
checkInterrupt();
|
checkInterrupt();
|
||||||
|
|
||||||
fd_set fds;
|
fd_set fds;
|
||||||
FD_ZERO(&fds);
|
FD_ZERO(&fds);
|
||||||
FD_SET(run.from, &fds);
|
FD_SET(run.fromAgent.readSide, &fds);
|
||||||
FD_SET(run.error, &fds);
|
FD_SET(run.builderOut.readSide, &fds);
|
||||||
|
|
||||||
/* Wait for data to appear on the substituter's stdout or
|
/* Wait for data to appear on the substituter's stdout or
|
||||||
stderr. */
|
stderr. */
|
||||||
if (select(run.from > run.error ? run.from + 1 : run.error + 1, &fds, 0, 0, 0) == -1) {
|
if (select(std::max(run.fromAgent.readSide, run.builderOut.readSide) + 1, &fds, 0, 0, 0) == -1) {
|
||||||
if (errno == EINTR) continue;
|
if (errno == EINTR) continue;
|
||||||
throw SysError("waiting for input from the substituter");
|
throw SysError("waiting for input from the substituter");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Completely drain stderr before dealing with stdout. */
|
/* Completely drain stderr before dealing with stdout. */
|
||||||
if (FD_ISSET(run.error, &fds)) {
|
if (FD_ISSET(run.builderOut.readSide, &fds)) {
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
ssize_t n = read(run.error, (unsigned char *) buf, sizeof(buf));
|
ssize_t n = read(run.builderOut.readSide, (unsigned char *) buf, sizeof(buf));
|
||||||
if (n == -1) {
|
if (n == -1) {
|
||||||
if (errno == EINTR) continue;
|
if (errno == EINTR) continue;
|
||||||
throw SysError("reading from substituter's stderr");
|
throw SysError("reading from substituter's stderr");
|
||||||
|
@ -903,23 +822,20 @@ string LocalStore::getLineFromSubstituter(RunningSubstituter & run)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read from stdout until we get a newline or the buffer is empty. */
|
/* Read from stdout until we get a newline or the buffer is empty. */
|
||||||
else if (run.fromBuf.hasData() || FD_ISSET(run.from, &fds)) {
|
else if (FD_ISSET(run.fromAgent.readSide, &fds)) {
|
||||||
haveData:
|
unsigned char c;
|
||||||
do {
|
readFull(run.fromAgent.readSide, (unsigned char *) &c, 1);
|
||||||
unsigned char c;
|
if (c == '\n') {
|
||||||
run.fromBuf(&c, 1);
|
if (!err.empty()) printMsg(lvlError, "substitute: " + err);
|
||||||
if (c == '\n') {
|
return res;
|
||||||
if (!err.empty()) printMsg(lvlError, "substitute: " + err);
|
}
|
||||||
return res;
|
res += c;
|
||||||
}
|
|
||||||
res += c;
|
|
||||||
} while (run.fromBuf.hasData());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class T> T LocalStore::getIntLineFromSubstituter(RunningSubstituter & run)
|
template<class T> T LocalStore::getIntLineFromSubstituter(Agent & run)
|
||||||
{
|
{
|
||||||
string s = getLineFromSubstituter(run);
|
string s = getLineFromSubstituter(run);
|
||||||
T res;
|
T res;
|
||||||
|
@ -935,27 +851,26 @@ PathSet LocalStore::querySubstitutablePaths(const PathSet & paths)
|
||||||
if (!settings.useSubstitutes || paths.empty()) return res;
|
if (!settings.useSubstitutes || paths.empty()) return res;
|
||||||
|
|
||||||
if (!runningSubstituter) {
|
if (!runningSubstituter) {
|
||||||
std::unique_ptr<RunningSubstituter>fresh(new RunningSubstituter);
|
const Strings args = { "substitute", "--query" };
|
||||||
|
const std::map<string, string> env = { { "_NIX_OPTIONS", settings.pack() } };
|
||||||
|
std::unique_ptr<Agent> fresh(new Agent(settings.guixProgram, args, env));
|
||||||
runningSubstituter.swap(fresh);
|
runningSubstituter.swap(fresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
RunningSubstituter & run = *runningSubstituter;
|
Agent & run = *runningSubstituter;
|
||||||
startSubstituter(run);
|
|
||||||
|
|
||||||
if (!run.disabled) {
|
string s = "have ";
|
||||||
string s = "have ";
|
foreach (PathSet::const_iterator, j, paths)
|
||||||
foreach (PathSet::const_iterator, j, paths)
|
if (res.find(*j) == res.end()) { s += *j; s += " "; }
|
||||||
if (res.find(*j) == res.end()) { s += *j; s += " "; }
|
writeLine(run.toAgent.writeSide, s);
|
||||||
writeLine(run.to, s);
|
while (true) {
|
||||||
while (true) {
|
/* FIXME: we only read stderr when an error occurs, so
|
||||||
/* FIXME: we only read stderr when an error occurs, so
|
substituters should only write (short) messages to
|
||||||
substituters should only write (short) messages to
|
stderr when they fail. I.e. they shouldn't write debug
|
||||||
stderr when they fail. I.e. they shouldn't write debug
|
output. */
|
||||||
output. */
|
Path path = getLineFromSubstituter(run);
|
||||||
Path path = getLineFromSubstituter(run);
|
if (path == "") break;
|
||||||
if (path == "") break;
|
res.insert(path);
|
||||||
res.insert(path);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
@ -967,18 +882,18 @@ void LocalStore::querySubstitutablePathInfos(PathSet & paths, SubstitutablePathI
|
||||||
if (!settings.useSubstitutes) return;
|
if (!settings.useSubstitutes) return;
|
||||||
|
|
||||||
if (!runningSubstituter) {
|
if (!runningSubstituter) {
|
||||||
std::unique_ptr<RunningSubstituter>fresh(new RunningSubstituter);
|
const Strings args = { "substitute", "--query" };
|
||||||
|
const std::map<string, string> env = { { "_NIX_OPTIONS", settings.pack() } };
|
||||||
|
std::unique_ptr<Agent> fresh(new Agent(settings.guixProgram, args, env));
|
||||||
runningSubstituter.swap(fresh);
|
runningSubstituter.swap(fresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
RunningSubstituter & run = *runningSubstituter;
|
Agent & run = *runningSubstituter;
|
||||||
startSubstituter(run);
|
|
||||||
if (run.disabled) return;
|
|
||||||
|
|
||||||
string s = "info ";
|
string s = "info ";
|
||||||
foreach (PathSet::const_iterator, i, paths)
|
foreach (PathSet::const_iterator, i, paths)
|
||||||
if (infos.find(*i) == infos.end()) { s += *i; s += " "; }
|
if (infos.find(*i) == infos.end()) { s += *i; s += " "; }
|
||||||
writeLine(run.to, s);
|
writeLine(run.toAgent.writeSide, s);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
Path path = getLineFromSubstituter(run);
|
Path path = getLineFromSubstituter(run);
|
||||||
|
|
|
@ -38,21 +38,11 @@ struct OptimiseStats
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct RunningSubstituter
|
|
||||||
{
|
|
||||||
Pid pid;
|
|
||||||
AutoCloseFD to, from, error;
|
|
||||||
FdSource fromBuf;
|
|
||||||
bool disabled;
|
|
||||||
RunningSubstituter() : disabled(false) { };
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class LocalStore : public StoreAPI
|
class LocalStore : public StoreAPI
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
/* The currently running substituter or empty. */
|
/* The currently running substituter or empty. */
|
||||||
std::unique_ptr<RunningSubstituter> runningSubstituter;
|
std::unique_ptr<Agent> runningSubstituter;
|
||||||
|
|
||||||
Path linksDir;
|
Path linksDir;
|
||||||
|
|
||||||
|
@ -178,8 +168,6 @@ public:
|
||||||
|
|
||||||
void markContentsGood(const Path & path);
|
void markContentsGood(const Path & path);
|
||||||
|
|
||||||
void setSubstituterEnv();
|
|
||||||
|
|
||||||
void createUser(const std::string & userName, uid_t userId);
|
void createUser(const std::string & userName, uid_t userId);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -213,8 +201,6 @@ private:
|
||||||
/* Cache for pathContentsGood(). */
|
/* Cache for pathContentsGood(). */
|
||||||
std::map<Path, bool> pathContentsGoodCache;
|
std::map<Path, bool> pathContentsGoodCache;
|
||||||
|
|
||||||
bool didSetSubstituterEnv;
|
|
||||||
|
|
||||||
/* The file to which we write our temporary roots. */
|
/* The file to which we write our temporary roots. */
|
||||||
Path fnTempRoots;
|
Path fnTempRoots;
|
||||||
AutoCloseFD fdTempRoots;
|
AutoCloseFD fdTempRoots;
|
||||||
|
@ -262,11 +248,9 @@ private:
|
||||||
|
|
||||||
void removeUnusedLinks(const GCState & state);
|
void removeUnusedLinks(const GCState & state);
|
||||||
|
|
||||||
void startSubstituter(RunningSubstituter & runningSubstituter);
|
string getLineFromSubstituter(Agent & run);
|
||||||
|
|
||||||
string getLineFromSubstituter(RunningSubstituter & run);
|
template<class T> T getIntLineFromSubstituter(Agent & run);
|
||||||
|
|
||||||
template<class T> T getIntLineFromSubstituter(RunningSubstituter & run);
|
|
||||||
|
|
||||||
Path createTempDirInStore();
|
Path createTempDirInStore();
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,8 @@ it writes to GUIX-WARNING-PORT a messages that matches ERROR-RX."
|
||||||
(test-equal name
|
(test-equal name
|
||||||
'(1 #t)
|
'(1 #t)
|
||||||
(let ((error-output (open-output-string)))
|
(let ((error-output (open-output-string)))
|
||||||
(parameterize ((guix-warning-port error-output))
|
(parameterize ((current-error-port error-output)
|
||||||
|
(guix-warning-port error-output))
|
||||||
(catch 'quit
|
(catch 'quit
|
||||||
(lambda ()
|
(lambda ()
|
||||||
exp
|
exp
|
||||||
|
|
Reference in New Issue