1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-07-02 21:51:50 +02:00

* Sync with the trunk.

This commit is contained in:
Eelco Dolstra 2011-12-16 23:33:01 +00:00
commit 194d21f9f6
45 changed files with 928 additions and 682 deletions

View file

@ -44,4 +44,15 @@ bool parseSearchPathArg(const string & arg, Strings::iterator & i,
}
Path lookupFileArg(EvalState & state, string s)
{
if (s.size() > 2 && s.at(0) == '<' && s.at(s.size() - 1) == '>') {
Path p = state.findFile(s.substr(1, s.size() - 2));
if (p == "") throw Error(format("file `%1%' was not found in the Nix search path (add it using $NIX_PATH or -I)") % p);
return p;
} else
return absPath(s);
}
}

View file

@ -14,6 +14,8 @@ bool parseOptionArg(const string & arg, Strings::iterator & i,
bool parseSearchPathArg(const string & arg, Strings::iterator & i,
const Strings::iterator & argsEnd, EvalState & state);
Path lookupFileArg(EvalState & state, string s);
}

View file

@ -363,9 +363,8 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v)
foreach (PathSet::iterator, j, refs) {
drv.inputSrcs.insert(*j);
if (isDerivation(*j))
drv.inputDrvs[*j] = store -> queryDerivationOutputNames(*j);
drv.inputDrvs[*j] = store->queryDerivationOutputNames(*j);
}
explicitlyPassed = true;
} else if (path.at(0) == '!') {
size_t index;
@ -387,7 +386,7 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v)
debug(format("derivation uses `%1%'") % path);
if (!useDrvAsSrc && isDerivation(path))
if (explicitlyPassed)
drv.inputDrvs[path] = store -> queryDerivationOutputNames(path);
drv.inputDrvs[path] = store->queryDerivationOutputNames(path);
else if (drv.inputDrvs.find(path) == drv.inputDrvs.end())
drv.inputDrvs[path] = singleton<StringSet>(output);
else
@ -416,17 +415,7 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v)
HashType ht = parseHashType(outputHashAlgo);
if (ht == htUnknown)
throw EvalError(format("unknown hash algorithm `%1%'") % outputHashAlgo);
Hash h(ht);
if (outputHash.size() == h.hashSize * 2)
/* hexadecimal representation */
h = parseHash(ht, outputHash);
else if (outputHash.size() == hashLength32(h))
/* base-32 representation */
h = parseHash32(ht, outputHash);
else
throw Error(format("hash `%1%' has wrong length for hash type `%2%'")
% outputHash % outputHashAlgo);
string s = outputHash;
Hash h = parseHash16or32(ht, outputHash);
outputHash = printHash(h);
if (outputHashRecursive) outputHashAlgo = "r:" + outputHashAlgo;

View file

@ -7,13 +7,6 @@ libmain_la_LIBADD = ../libstore/libstore.la @BDW_GC_LIBS@
pkginclude_HEADERS = shared.hh
AM_CXXFLAGS = \
-DNIX_STORE_DIR=\"$(storedir)\" \
-DNIX_DATA_DIR=\"$(datadir)\" \
-DNIX_STATE_DIR=\"$(localstatedir)/nix\" \
-DNIX_LOG_DIR=\"$(localstatedir)/log/nix\" \
-DNIX_CONF_DIR=\"$(sysconfdir)/nix\" \
-DNIX_LIBEXEC_DIR=\"$(libexecdir)\" \
-DNIX_BIN_DIR=\"$(bindir)\" \
-DNIX_VERSION=\"$(VERSION)\" \
-I$(srcdir)/.. -I$(srcdir)/../libutil \
-I$(srcdir)/../libstore

View file

@ -65,7 +65,7 @@ void printMissing(StoreAPI & store, const PathSet & paths)
}
if (!willSubstitute.empty()) {
printMsg(lvlInfo, format("these paths will be downloaded/copied (%.2f MiB download, %.2f MiB unpacked):")
printMsg(lvlInfo, format("these paths will be fetched (%.2f MiB download, %.2f MiB unpacked):")
% (downloadSize / (1024.0 * 1024.0))
% (narSize / (1024.0 * 1024.0)));
foreach (PathSet::iterator, i, willSubstitute)
@ -90,23 +90,6 @@ static void setLogType(string lt)
}
static void closeStore()
{
try {
throw;
} catch (std::exception & e) {
printMsg(lvlError,
format("FATAL: unexpected exception (closing store and aborting): %1%") % e.what());
}
try {
store.reset((StoreAPI *) 0);
} catch (...) {
ignoreException();
}
abort();
}
RemoveTempRoots::~RemoveTempRoots()
{
removeTempRoots();
@ -120,30 +103,8 @@ static bool showTrace = false;
processor. */
static void initAndRun(int argc, char * * argv)
{
/* 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");
} 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);
setDefaultsFromEnvironment();
/* Catch SIGINT. */
struct sigaction act;
act.sa_handler = sigintHandler;
@ -260,12 +221,6 @@ static void initAndRun(int argc, char * * argv)
exit. */
RemoveTempRoots removeTempRoots __attribute__((unused));
/* Make sure that the database gets closed properly, even if
terminate() is called (which happens sometimes due to bugs in
destructor/exceptions interaction, but that needn't preclude a
clean shutdown of the database). */
std::set_terminate(closeStore);
run(remaining);
/* Close the Nix database. */

View file

@ -15,7 +15,16 @@ libstore_la_LIBADD = ../libutil/libutil.la ../boost/format/libformat.la ${aterm_
EXTRA_DIST = schema.sql
AM_CXXFLAGS = -Wall \
${sqlite_include} -I$(srcdir)/.. -I$(srcdir)/../libutil
${sqlite_include} -I$(srcdir)/.. -I$(srcdir)/../libutil \
-DNIX_STORE_DIR=\"$(storedir)\" \
-DNIX_DATA_DIR=\"$(datadir)\" \
-DNIX_STATE_DIR=\"$(localstatedir)/nix\" \
-DNIX_LOG_DIR=\"$(localstatedir)/log/nix\" \
-DNIX_CONF_DIR=\"$(sysconfdir)/nix\" \
-DNIX_LIBEXEC_DIR=\"$(libexecdir)\" \
-DNIX_BIN_DIR=\"$(bindir)\" \
-I$(srcdir)/.. -I$(srcdir)/../libutil \
-I$(srcdir)/../libstore
local-store.lo: schema.sql.hh

View file

@ -1650,6 +1650,9 @@ void DerivationGoal::startBuilder()
(format("nixbld:!:%1%:\n")
% (buildUser.enabled() ? buildUser.getGID() : getgid())).str());
/* Create /etc/hosts with localhost entry. */
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
@ -2199,9 +2202,7 @@ void SubstitutionGoal::tryNext()
if (subs.size() == 0) {
/* None left. Terminate this goal and let someone else deal
with it. */
printMsg(lvlError,
format("path `%1%' is required, but there is no substituter that can build it")
% storePath);
debug(format("path `%1%' is required, but there is no substituter that can build it") % storePath);
amDone(ecFailed);
return;
}
@ -2232,8 +2233,7 @@ void SubstitutionGoal::referencesValid()
trace("all references realised");
if (nrFailed > 0) {
printMsg(lvlError,
format("some references of path `%1%' could not be realised") % storePath);
debug(format("some references of path `%1%' could not be realised") % storePath);
amDone(ecFailed);
return;
}
@ -2286,9 +2286,7 @@ void SubstitutionGoal::tryToRun()
return;
}
printMsg(lvlInfo,
format("substituting path `%1%' using substituter `%2%'")
% storePath % sub);
printMsg(lvlInfo, format("fetching path `%1%'...") % storePath);
logPipe.create();
@ -2364,19 +2362,15 @@ void SubstitutionGoal::finished()
try {
if (!statusOk(status))
throw SubstError(format("builder for `%1%' %2%")
throw SubstError(format("fetching path `%1%' %2%")
% storePath % statusToString(status));
if (!pathExists(storePath))
throw SubstError(
format("substitute did not produce path `%1%'")
% storePath);
throw SubstError(format("substitute did not produce path `%1%'") % storePath);
} catch (SubstError & e) {
printMsg(lvlInfo,
format("substitution of path `%1%' using substituter `%2%' failed: %3%")
% storePath % sub % e.msg());
printMsg(lvlInfo, e.msg());
if (printBuildTrace) {
printMsg(lvlError, format("@ substituter-failed %1% %2% %3%")

View file

@ -1,3 +1,5 @@
#include "config.h"
#include "globals.hh"
#include "util.hh"
@ -138,5 +140,33 @@ void reloadSettings()
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");
} 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);
}
}

View file

@ -114,7 +114,9 @@ void overrideSetting(const string & name, const Strings & value);
void reloadSettings();
void setDefaultsFromEnvironment();
}

View file

@ -327,10 +327,9 @@ void LocalStore::openDB(bool create)
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, but doesn't
seem entirely stable at the moment (Oct. 2010). Thus, use
truncate mode by default. */
string mode = queryBoolSetting("use-sqlite-wal", false) ? "wal" : "truncate";
/* Set the SQLite journal mode. WAL mode is fastest, so it's the
default. */
string mode = queryBoolSetting("use-sqlite-wal", true) ? "wal" : "truncate";
string prevMode;
{
SQLiteStmt stmt;
@ -367,7 +366,7 @@ void LocalStore::openDB(bool create)
stmtRegisterValidPath.create(db,
"insert into ValidPaths (path, hash, registrationTime, deriver, narSize) values (?, ?, ?, ?, ?);");
stmtUpdatePathInfo.create(db,
"update ValidPaths set narSize = ? where path = ?;");
"update ValidPaths set narSize = ?, hash = ? where path = ?;");
stmtAddReference.create(db,
"insert or replace into Refs (referrer, reference) values (?, ?);");
stmtQueryPathInfo.create(db,
@ -684,7 +683,7 @@ ValidPathInfo LocalStore::queryPathInfo(const Path & path)
}
/* Update path info in the database. Currently only updated the
/* Update path info in the database. Currently only updates the
narSize field. */
void LocalStore::updatePathInfo(const ValidPathInfo & info)
{
@ -693,6 +692,7 @@ void LocalStore::updatePathInfo(const ValidPathInfo & info)
stmtUpdatePathInfo.bind64(info.narSize);
else
stmtUpdatePathInfo.bind(); // null
stmtUpdatePathInfo.bind("sha256:" + printHash(info.hash));
stmtUpdatePathInfo.bind(info.path);
if (sqlite3_step(stmtUpdatePathInfo) != SQLITE_DONE)
throwSQLiteError(db, format("updating info of path `%1%' in database") % info.path);
@ -1125,16 +1125,14 @@ struct HashAndWriteSink : Sink
HashAndWriteSink(Sink & writeSink) : writeSink(writeSink), hashSink(htSHA256)
{
}
virtual void operator ()
(const unsigned char * data, unsigned int len)
virtual void operator () (const unsigned char * data, size_t len)
{
writeSink(data, len);
hashSink(data, len);
}
Hash currentHash()
{
HashSink hashSinkClone(hashSink);
return hashSinkClone.finish().first;
return hashSink.currentHash().first;
}
};
@ -1180,7 +1178,7 @@ void LocalStore::exportPath(const Path & path, bool sign,
PathSet references;
queryReferences(path, references);
writeStringSet(references, hashAndWriteSink);
writeStrings(references, hashAndWriteSink);
Path deriver = queryDeriver(path);
writeString(deriver, hashAndWriteSink);
@ -1223,11 +1221,11 @@ struct HashAndReadSource : Source
{
hashing = true;
}
virtual void operator ()
(unsigned char * data, unsigned int len)
size_t read(unsigned char * data, size_t len)
{
readSource(data, len);
if (hashing) hashSink(data, len);
size_t n = readSource.read(data, len);
if (hashing) hashSink(data, n);
return n;
}
};
@ -1267,7 +1265,7 @@ Path LocalStore::importPath(bool requireSignature, Source & source)
Path dstPath = readStorePath(hashAndReadSource);
PathSet references = readStorePaths(hashAndReadSource);
PathSet references = readStorePaths<PathSet>(hashAndReadSource);
Path deriver = readString(hashAndReadSource);
if (deriver != "") assertStorePath(deriver);
@ -1278,7 +1276,7 @@ Path LocalStore::importPath(bool requireSignature, Source & source)
bool haveSignature = readInt(hashAndReadSource) == 1;
if (requireSignature && !haveSignature)
throw Error("imported archive lacks a signature");
throw Error(format("imported archive of `%1%' lacks a signature") % dstPath);
if (haveSignature) {
string signature = readString(hashAndReadSource);
@ -1354,6 +1352,19 @@ Path LocalStore::importPath(bool requireSignature, Source & source)
}
Paths LocalStore::importPaths(bool requireSignature, Source & source)
{
Paths res;
while (true) {
unsigned long long n = readLongLong(source);
if (n == 0) break;
if (n != 1) throw Error("input doesn't look like something created by `nix-store --export'");
res.push_back(importPath(requireSignature, source));
}
return res;
}
void LocalStore::deleteFromStore(const Path & path, unsigned long long & bytesFreed,
unsigned long long & blocksFreed)
{
@ -1369,7 +1380,7 @@ void LocalStore::deleteFromStore(const Path & path, unsigned long long & bytesFr
PathSet referrers; queryReferrers(path, referrers);
referrers.erase(path); /* ignore self-references */
if (!referrers.empty())
throw PathInUse(format("cannot delete path `%1%' because it is in use by `%2%'")
throw PathInUse(format("cannot delete path `%1%' because it is in use by %2%")
% path % showPaths(referrers));
invalidatePath(path);
}
@ -1409,6 +1420,8 @@ void LocalStore::verifyStore(bool checkContents)
if (checkContents) {
printMsg(lvlInfo, "checking hashes...");
Hash nullHash(htSHA256);
foreach (PathSet::iterator, i, validPaths) {
try {
ValidPathInfo info = queryPathInfo(*i);
@ -1417,17 +1430,30 @@ void LocalStore::verifyStore(bool checkContents)
printMsg(lvlTalkative, format("checking contents of `%1%'") % *i);
HashResult current = hashPath(info.hash.type, *i);
if (current.first != info.hash) {
if (info.hash != nullHash && info.hash != current.first) {
printMsg(lvlError, format("path `%1%' was modified! "
"expected hash `%2%', got `%3%'")
% *i % printHash(info.hash) % printHash(current.first));
} else {
bool update = false;
/* Fill in missing hashes. */
if (info.hash == nullHash) {
printMsg(lvlError, format("fixing missing hash on `%1%'") % *i);
info.hash = current.first;
update = true;
}
/* Fill in missing narSize fields (from old stores). */
if (info.narSize == 0) {
printMsg(lvlError, format("updating size field on `%1%' to %2%") % *i % current.second);
info.narSize = current.second;
updatePathInfo(info);
update = true;
}
if (update) updatePathInfo(info);
}
} catch (Error & e) {

View file

@ -148,7 +148,7 @@ public:
void exportPath(const Path & path, bool sign,
Sink & sink);
Path importPath(bool requireSignature, Source & source);
Paths importPaths(bool requireSignature, Source & source);
void buildDerivations(const PathSet & drvPaths);
@ -261,6 +261,8 @@ private:
Path createTempDirInStore();
Path importPath(bool requireSignature, Source & source);
void checkDerivationOutputs(const Path & drvPath, const Derivation & drv);
};

View file

@ -57,11 +57,11 @@ struct RefScanSink : Sink
RefScanSink() : hashSink(htSHA256) { }
void operator () (const unsigned char * data, unsigned int len);
void operator () (const unsigned char * data, size_t len);
};
void RefScanSink::operator () (const unsigned char * data, unsigned int len)
void RefScanSink::operator () (const unsigned char * data, size_t len)
{
hashSink(data, len);

View file

@ -27,13 +27,15 @@ Path readStorePath(Source & from)
}
PathSet readStorePaths(Source & from)
template<class T> T readStorePaths(Source & from)
{
PathSet paths = readStringSet(from);
foreach (PathSet::iterator, i, paths) assertStorePath(*i);
T paths = readStrings<T>(from);
foreach (typename T::iterator, i, paths) assertStorePath(*i);
return paths;
}
template PathSet readStorePaths(Source & from);
RemoteStore::RemoteStore()
{
@ -65,6 +67,7 @@ void RemoteStore::openConnection()
/* Send the magic greeting, check for the reply. */
try {
writeInt(WORKER_MAGIC_1, to);
to.flush();
unsigned int magic = readInt(from);
if (magic != WORKER_MAGIC_2) throw Error("protocol mismatch");
@ -166,6 +169,7 @@ void RemoteStore::connectToDaemon()
RemoteStore::~RemoteStore()
{
try {
to.flush();
fdSocket.close();
if (child != -1)
child.wait(true);
@ -213,7 +217,7 @@ PathSet RemoteStore::queryValidPaths()
openConnection();
writeInt(wopQueryValidPaths, to);
processStderr();
return readStorePaths(from);
return readStorePaths<PathSet>(from);
}
@ -240,7 +244,7 @@ bool RemoteStore::querySubstitutablePathInfo(const Path & path,
if (reply == 0) return false;
info.deriver = readString(from);
if (info.deriver != "") assertStorePath(info.deriver);
info.references = readStorePaths(from);
info.references = readStorePaths<PathSet>(from);
info.downloadSize = readLongLong(from);
info.narSize = GET_PROTOCOL_MINOR(daemonVersion) >= 7 ? readLongLong(from) : 0;
return true;
@ -258,7 +262,7 @@ ValidPathInfo RemoteStore::queryPathInfo(const Path & path)
info.deriver = readString(from);
if (info.deriver != "") assertStorePath(info.deriver);
info.hash = parseHash(htSHA256, readString(from));
info.references = readStorePaths(from);
info.references = readStorePaths<PathSet>(from);
info.registrationTime = readInt(from);
info.narSize = readLongLong(from);
return info;
@ -283,7 +287,7 @@ void RemoteStore::queryReferences(const Path & path,
writeInt(wopQueryReferences, to);
writeString(path, to);
processStderr();
PathSet references2 = readStorePaths(from);
PathSet references2 = readStorePaths<PathSet>(from);
references.insert(references2.begin(), references2.end());
}
@ -295,7 +299,7 @@ void RemoteStore::queryReferrers(const Path & path,
writeInt(wopQueryReferrers, to);
writeString(path, to);
processStderr();
PathSet referrers2 = readStorePaths(from);
PathSet referrers2 = readStorePaths<PathSet>(from);
referrers.insert(referrers2.begin(), referrers2.end());
}
@ -318,7 +322,7 @@ PathSet RemoteStore::queryDerivationOutputs(const Path & path)
writeInt(wopQueryDerivationOutputs, to);
writeString(path, to);
processStderr();
return readStorePaths(from);
return readStorePaths<PathSet>(from);
}
@ -338,7 +342,7 @@ Path RemoteStore::addToStore(const Path & _srcPath,
openConnection();
Path srcPath(absPath(_srcPath));
writeInt(wopAddToStore, to);
writeString(baseNameOf(srcPath), to);
/* backwards compatibility hack */
@ -358,7 +362,7 @@ Path RemoteStore::addTextToStore(const string & name, const string & s,
writeInt(wopAddTextToStore, to);
writeString(name, to);
writeString(s, to);
writeStringSet(references, to);
writeStrings(references, to);
processStderr();
return readStorePath(from);
@ -377,14 +381,14 @@ void RemoteStore::exportPath(const Path & path, bool sign,
}
Path RemoteStore::importPath(bool requireSignature, Source & source)
Paths RemoteStore::importPaths(bool requireSignature, Source & source)
{
openConnection();
writeInt(wopImportPath, to);
writeInt(wopImportPaths, to);
/* We ignore requireSignature, since the worker forces it to true
anyway. */
anyway. */
processStderr(0, &source);
return readStorePath(from);
return readStorePaths<Paths>(from);
}
@ -392,7 +396,7 @@ void RemoteStore::buildDerivations(const PathSet & drvPaths)
{
openConnection();
writeInt(wopBuildDerivations, to);
writeStringSet(drvPaths, to);
writeStrings(drvPaths, to);
processStderr();
readInt(from);
}
@ -459,7 +463,7 @@ void RemoteStore::collectGarbage(const GCOptions & options, GCResults & results)
writeInt(wopCollectGarbage, to);
writeInt(options.action, to);
writeStringSet(options.pathsToDelete, to);
writeStrings(options.pathsToDelete, to);
writeInt(options.ignoreLiveness, to);
writeLongLong(options.maxFreed, to);
writeInt(options.maxLinks, to);
@ -471,7 +475,7 @@ void RemoteStore::collectGarbage(const GCOptions & options, GCResults & results)
processStderr();
results.paths = readStringSet(from);
results.paths = readStrings<PathSet>(from);
results.bytesFreed = readLongLong(from);
results.blocksFreed = readLongLong(from);
}
@ -482,7 +486,7 @@ PathSet RemoteStore::queryFailedPaths()
openConnection();
writeInt(wopQueryFailedPaths, to);
processStderr();
return readStorePaths(from);
return readStorePaths<PathSet>(from);
}
@ -490,7 +494,7 @@ void RemoteStore::clearFailedPaths(const PathSet & paths)
{
openConnection();
writeInt(wopClearFailedPaths, to);
writeStringSet(paths, to);
writeStrings(paths, to);
processStderr();
readInt(from);
}
@ -498,6 +502,7 @@ void RemoteStore::clearFailedPaths(const PathSet & paths)
void RemoteStore::processStderr(Sink * sink, Source * source)
{
to.flush();
unsigned int msg;
while ((msg = readInt(from)) == STDERR_NEXT
|| msg == STDERR_READ || msg == STDERR_WRITE) {
@ -508,11 +513,11 @@ void RemoteStore::processStderr(Sink * sink, Source * source)
}
else if (msg == STDERR_READ) {
if (!source) throw Error("no source");
unsigned int len = readInt(from);
size_t len = readInt(from);
unsigned char * buf = new unsigned char[len];
AutoDeleteArray<unsigned char> d(buf);
(*source)(buf, len);
writeString(string((const char *) buf, len), to);
writeString(buf, source->read(buf, len), to);
to.flush();
}
else {
string s = readString(from);

View file

@ -58,7 +58,7 @@ public:
void exportPath(const Path & path, bool sign,
Sink & sink);
Path importPath(bool requireSignature, Source & source);
Paths importPaths(bool requireSignature, Source & source);
void buildDerivations(const PathSet & drvPaths);

View file

@ -298,6 +298,17 @@ string showPaths(const PathSet & paths)
}
void exportPaths(StoreAPI & store, const Paths & paths,
bool sign, Sink & sink)
{
foreach (Paths::const_iterator, i, paths) {
writeInt(1, sink);
store.exportPath(*i, sign, sink);
}
writeInt(0, sink);
}
}

View file

@ -154,9 +154,7 @@ public:
/* Copy the contents of a path to the store and register the
validity the resulting path. The resulting path is returned.
If `fixed' is true, then the output of a fixed-output
derivation is pre-loaded into the Nix store. The function
object `filter' can be used to exclude files (see
The function object `filter' can be used to exclude files (see
libutil/archive.hh). */
virtual Path addToStore(const Path & srcPath,
bool recursive = true, HashType hashAlgo = htSHA256,
@ -174,9 +172,9 @@ public:
virtual void exportPath(const Path & path, bool sign,
Sink & sink) = 0;
/* Import a NAR dump created by exportPath() into the Nix
store. */
virtual Path importPath(bool requireSignature, Source & source) = 0;
/* Import a sequence of NAR dumps created by exportPaths() into
the Nix store. */
virtual Paths importPaths(bool requireSignature, Source & source) = 0;
/* Ensure that the output paths of the derivation are valid. If
they are already valid, this is a no-op. Otherwise, validity
@ -345,6 +343,12 @@ ValidPathInfo decodeValidPathInfo(std::istream & str,
bool hashGiven = false);
/* Export multiple paths in the format expected by nix-store
--import. */
void exportPaths(StoreAPI & store, const Paths & paths,
bool sign, Sink & sink);
}

View file

@ -8,7 +8,7 @@ namespace nix {
#define WORKER_MAGIC_1 0x6e697863
#define WORKER_MAGIC_2 0x6478696f
#define PROTOCOL_VERSION 0x108
#define PROTOCOL_VERSION 0x109
#define GET_PROTOCOL_MAJOR(x) ((x) & 0xff00)
#define GET_PROTOCOL_MINOR(x) ((x) & 0x00ff)
@ -29,7 +29,6 @@ typedef enum {
wopSyncWithGC = 13,
wopFindRoots = 14,
wopExportPath = 16,
wopImportPath = 17,
wopQueryDeriver = 18,
wopSetOptions = 19,
wopCollectGarbage = 20,
@ -39,7 +38,8 @@ typedef enum {
wopQueryFailedPaths = 24,
wopClearFailedPaths = 25,
wopQueryPathInfo = 26,
wopQueryDerivationOutputNames = 27,
wopImportPaths = 27,
wopQueryDerivationOutputNames = 28,
} WorkerOp;
@ -59,7 +59,7 @@ typedef enum {
Path readStorePath(Source & from);
PathSet readStorePaths(Source & from);
template<class T> T readStorePaths(Source & from);
}

View file

@ -204,6 +204,22 @@ Hash parseHash32(HashType ht, const string & s)
}
Hash parseHash16or32(HashType ht, const string & s)
{
Hash hash(ht);
if (s.size() == hash.hashSize * 2)
/* hexadecimal representation */
hash = parseHash(ht, s);
else if (s.size() == hashLength32(hash))
/* base-32 representation */
hash = parseHash32(ht, s);
else
throw Error(format("hash `%1%' has wrong length for hash type `%2%'")
% s % printHashType(ht));
return hash;
}
bool isHash(const string & s)
{
if (s.length() != 32) return false;
@ -290,21 +306,13 @@ HashSink::HashSink(HashType ht) : ht(ht)
start(ht, *ctx);
}
HashSink::HashSink(const HashSink & h)
{
ht = h.ht;
bytes = h.bytes;
ctx = new Ctx;
*ctx = *h.ctx;
}
HashSink::~HashSink()
{
bufPos = 0;
delete ctx;
}
void HashSink::operator ()
(const unsigned char * data, unsigned int len)
void HashSink::write(const unsigned char * data, size_t len)
{
bytes += len;
update(ht, *ctx, data, len);
@ -312,11 +320,21 @@ void HashSink::operator ()
HashResult HashSink::finish()
{
flush();
Hash hash(ht);
nix::finish(ht, *ctx, hash.hash);
return HashResult(hash, bytes);
}
HashResult HashSink::currentHash()
{
flush();
Ctx ctx2 = *ctx;
Hash hash(ht);
nix::finish(ht, ctx2, hash.hash);
return HashResult(hash, bytes);
}
HashResult hashPath(
HashType ht, const Path & path, PathFilter & filter)

View file

@ -58,6 +58,9 @@ string printHash32(const Hash & hash);
/* Parse a base-32 representation of a hash code. */
Hash parseHash32(HashType ht, const string & s);
/* Parse a base-16 or base-32 representation of a hash code. */
Hash parseHash16or32(HashType ht, const string & s);
/* Verify that the given string is a valid hash code. */
bool isHash(const string & s);
@ -88,7 +91,7 @@ string printHashType(HashType ht);
union Ctx;
class HashSink : public Sink
class HashSink : public BufferedSink
{
private:
HashType ht;
@ -99,8 +102,9 @@ public:
HashSink(HashType ht);
HashSink(const HashSink & h);
~HashSink();
virtual void operator () (const unsigned char * data, unsigned int len);
void write(const unsigned char * data, size_t len);
HashResult finish();
HashResult currentHash();
};

View file

@ -2,24 +2,117 @@
#include "util.hh"
#include <cstring>
#include <cerrno>
namespace nix {
void FdSink::operator () (const unsigned char * data, unsigned int len)
BufferedSink::~BufferedSink()
{
/* We can't call flush() here, because C++ for some insane reason
doesn't allow you to call virtual methods from a destructor. */
assert(!bufPos);
if (buffer) delete[] buffer;
}
void BufferedSink::operator () (const unsigned char * data, size_t len)
{
if (!buffer) buffer = new unsigned char[bufSize];
while (len) {
/* Optimisation: bypass the buffer if the data exceeds the
buffer size. */
if (bufPos + len >= bufSize) {
flush();
write(data, len);
break;
}
/* Otherwise, copy the bytes to the buffer. Flush the buffer
when it's full. */
size_t n = bufPos + len > bufSize ? bufSize - bufPos : len;
memcpy(buffer + bufPos, data, n);
data += n; bufPos += n; len -= n;
if (bufPos == bufSize) flush();
}
}
void BufferedSink::flush()
{
if (bufPos == 0) return;
size_t n = bufPos;
bufPos = 0; // don't trigger the assert() in ~BufferedSink()
write(buffer, n);
}
FdSink::~FdSink()
{
try { flush(); } catch (...) { ignoreException(); }
}
void FdSink::write(const unsigned char * data, size_t len)
{
writeFull(fd, data, len);
}
void FdSource::operator () (unsigned char * data, unsigned int len)
void Source::operator () (unsigned char * data, size_t len)
{
readFull(fd, data, len);
while (len) {
size_t n = read(data, len);
data += n; len -= n;
}
}
void writePadding(unsigned int len, Sink & sink)
BufferedSource::~BufferedSource()
{
if (buffer) delete[] buffer;
}
size_t BufferedSource::read(unsigned char * data, size_t len)
{
if (!buffer) buffer = new unsigned char[bufSize];
if (!bufPosIn) bufPosIn = readUnbuffered(buffer, bufSize);
/* Copy out the data in the buffer. */
size_t n = len > bufPosIn - bufPosOut ? bufPosIn - bufPosOut : len;
memcpy(data, buffer + bufPosOut, n);
bufPosOut += n;
if (bufPosIn == bufPosOut) bufPosIn = bufPosOut = 0;
return n;
}
size_t FdSource::readUnbuffered(unsigned char * data, size_t len)
{
ssize_t n;
do {
checkInterrupt();
n = ::read(fd, (char *) data, bufSize);
} while (n == -1 && errno == EINTR);
if (n == -1) throw SysError("reading from file");
if (n == 0) throw EndOfFile("unexpected end-of-file");
return n;
}
size_t StringSource::read(unsigned char * data, size_t len)
{
if (pos == s.size()) throw EndOfFile("end of string reached");
size_t n = s.copy((char *) data, len, pos);
pos += n;
return n;
}
void writePadding(size_t len, Sink & sink)
{
if (len % 8) {
unsigned char zero[8];
@ -56,28 +149,36 @@ void writeLongLong(unsigned long long n, Sink & sink)
}
void writeString(const string & s, Sink & sink)
void writeString(const unsigned char * buf, size_t len, Sink & sink)
{
unsigned int len = s.length();
writeInt(len, sink);
sink((const unsigned char *) s.c_str(), len);
sink(buf, len);
writePadding(len, sink);
}
void writeStringSet(const StringSet & ss, Sink & sink)
void writeString(const string & s, Sink & sink)
{
writeInt(ss.size(), sink);
for (StringSet::iterator i = ss.begin(); i != ss.end(); ++i)
writeString(*i, sink);
writeString((const unsigned char *) s.c_str(), s.size(), sink);
}
void readPadding(unsigned int len, Source & source)
template<class T> void writeStrings(const T & ss, Sink & sink)
{
writeInt(ss.size(), sink);
foreach (typename T::const_iterator, i, ss)
writeString(*i, sink);
}
template void writeStrings(const Paths & ss, Sink & sink);
template void writeStrings(const PathSet & ss, Sink & sink);
void readPadding(size_t len, Source & source)
{
if (len % 8) {
unsigned char zero[8];
unsigned int n = 8 - (len % 8);
size_t n = 8 - (len % 8);
source(zero, n);
for (unsigned int i = 0; i < n; i++)
if (zero[i]) throw SerialisationError("non-zero padding");
@ -115,9 +216,19 @@ unsigned long long readLongLong(Source & source)
}
size_t readString(unsigned char * buf, size_t max, Source & source)
{
size_t len = readInt(source);
if (len > max) throw Error("string is too long");
source(buf, len);
readPadding(len, source);
return len;
}
string readString(Source & source)
{
unsigned int len = readInt(source);
size_t len = readInt(source);
unsigned char * buf = new unsigned char[len];
AutoDeleteArray<unsigned char> d(buf);
source(buf, len);
@ -126,14 +237,17 @@ string readString(Source & source)
}
StringSet readStringSet(Source & source)
template<class T> T readStrings(Source & source)
{
unsigned int count = readInt(source);
StringSet ss;
T ss;
while (count--)
ss.insert(readString(source));
ss.insert(ss.end(), readString(source));
return ss;
}
template Paths readStrings(Source & source);
template PathSet readStrings(Source & source);
}

View file

@ -11,7 +11,25 @@ namespace nix {
struct Sink
{
virtual ~Sink() { }
virtual void operator () (const unsigned char * data, unsigned int len) = 0;
virtual void operator () (const unsigned char * data, size_t len) = 0;
};
/* A buffered abstract sink. */
struct BufferedSink : Sink
{
size_t bufSize, bufPos;
unsigned char * buffer;
BufferedSink(size_t bufSize = 32 * 1024)
: bufSize(bufSize), bufPos(0), buffer(0) { }
~BufferedSink();
void operator () (const unsigned char * data, size_t len);
void flush();
virtual void write(const unsigned char * data, size_t len) = 0;
};
@ -20,49 +38,55 @@ struct Source
{
virtual ~Source() { }
/* The callee should store exactly *len bytes in the buffer
pointed to by data. It should block if that much data is not
yet available, or throw an error if it is not going to be
available. */
virtual void operator () (unsigned char * data, unsigned int len) = 0;
/* Store exactly len bytes in the buffer pointed to by data.
It blocks until all the requested data is available, or throws
an error if it is not going to be available. */
void operator () (unsigned char * data, size_t len);
/* Store up to len in the buffer pointed to by data, and
return the number of bytes stored. If blocks until at least
one byte is available. */
virtual size_t read(unsigned char * data, size_t len) = 0;
};
/* A buffered abstract source. */
struct BufferedSource : Source
{
size_t bufSize, bufPosIn, bufPosOut;
unsigned char * buffer;
BufferedSource(size_t bufSize = 32 * 1024)
: bufSize(bufSize), bufPosIn(0), bufPosOut(0), buffer(0) { }
~BufferedSource();
size_t read(unsigned char * data, size_t len);
/* Underlying read call, to be overriden. */
virtual size_t readUnbuffered(unsigned char * data, size_t len) = 0;
};
/* A sink that writes data to a file descriptor. */
struct FdSink : Sink
struct FdSink : BufferedSink
{
int fd;
FdSink()
{
fd = -1;
}
FdSink() : fd(-1) { }
FdSink(int fd) : fd(fd) { }
~FdSink();
FdSink(int fd)
{
this->fd = fd;
}
void operator () (const unsigned char * data, unsigned int len);
void write(const unsigned char * data, size_t len);
};
/* A source that reads data from a file descriptor. */
struct FdSource : Source
struct FdSource : BufferedSource
{
int fd;
FdSource()
{
fd = -1;
}
FdSource(int fd)
{
this->fd = fd;
}
void operator () (unsigned char * data, unsigned int len);
FdSource() : fd(-1) { }
FdSource(int fd) : fd(fd) { }
size_t readUnbuffered(unsigned char * data, size_t len);
};
@ -70,7 +94,7 @@ struct FdSource : Source
struct StringSink : Sink
{
string s;
virtual void operator () (const unsigned char * data, unsigned int len)
void operator () (const unsigned char * data, size_t len)
{
s.append((const char *) data, len);
}
@ -81,29 +105,25 @@ struct StringSink : Sink
struct StringSource : Source
{
const string & s;
unsigned int pos;
size_t pos;
StringSource(const string & _s) : s(_s), pos(0) { }
virtual void operator () (unsigned char * data, unsigned int len)
{
s.copy((char *) data, len, pos);
pos += len;
if (pos > s.size())
throw Error("end of string reached");
}
size_t read(unsigned char * data, size_t len);
};
void writePadding(unsigned int len, Sink & sink);
void writePadding(size_t len, Sink & sink);
void writeInt(unsigned int n, Sink & sink);
void writeLongLong(unsigned long long n, Sink & sink);
void writeString(const unsigned char * buf, size_t len, Sink & sink);
void writeString(const string & s, Sink & sink);
void writeStringSet(const StringSet & ss, Sink & sink);
template<class T> void writeStrings(const T & ss, Sink & sink);
void readPadding(unsigned int len, Source & source);
void readPadding(size_t len, Source & source);
unsigned int readInt(Source & source);
unsigned long long readLongLong(Source & source);
size_t readString(unsigned char * buf, size_t max, Source & source);
string readString(Source & source);
StringSet readStringSet(Source & source);
template<class T> T readStrings(Source & source);
MakeError(SerialisationError, Error)

View file

@ -1270,7 +1270,7 @@ void run(Strings args)
else if (arg == "--profile" || arg == "-p")
globals.profile = absPath(needArg(i, args, arg));
else if (arg == "--file" || arg == "-f")
globals.instSource.nixExprPath = absPath(needArg(i, args, arg));
globals.instSource.nixExprPath = lookupFileArg(globals.state, needArg(i, args, arg));
else if (arg == "--switch-profile" || arg == "-S")
op = opSwitchProfile;
else if (arg == "--switch-generation" || arg == "-G")

View file

@ -43,7 +43,7 @@ void run(Strings args)
}
if (op == opHash) {
for (Strings::iterator i = ss.begin(); i != ss.end(); ++i) {
foreach (Strings::iterator, i, ss) {
Hash h = flat ? hashFile(ht, *i) : hashPath(ht, *i).first;
if (truncate && h.hashSize > 20) h = compressHash(h, 20);
std::cout << format("%1%\n") %
@ -52,8 +52,8 @@ void run(Strings args)
}
else {
for (Strings::iterator i = ss.begin(); i != ss.end(); ++i) {
Hash h = op == opTo16 ? parseHash32(ht, *i) : parseHash(ht, *i);
foreach (Strings::iterator, i, ss) {
Hash h = parseHash16or32(ht, *i);
std::cout << format("%1%\n") %
(op == opTo16 ? printHash(h) : printHash32(h));
}

View file

@ -138,8 +138,7 @@ void run(Strings args)
}
foreach (Strings::iterator, i, files) {
Path path = absPath(*i);
Expr * e = state.parseExprFromFile(path);
Expr * e = state.parseExprFromFile(lookupFileArg(state, *i));
processExpr(state, attrPaths, parseOnly, strict, autoArgs,
evalOnly, xmlOutput, xmlOutputSourceLocation, e);
}

View file

@ -133,14 +133,6 @@ static void opAddFixed(Strings opFlags, Strings opArgs)
}
static Hash parseHash16or32(HashType ht, const string & s)
{
return s.size() == Hash(ht).hashSize * 2
? parseHash(ht, s)
: parseHash32(ht, s);
}
/* Hack to support caching in `nix-prefetch-url'. */
static void opPrintFixedPath(Strings opFlags, Strings opArgs)
{
@ -594,11 +586,7 @@ static void opExport(Strings opFlags, Strings opArgs)
else throw UsageError(format("unknown flag `%1%'") % *i);
FdSink sink(STDOUT_FILENO);
for (Strings::iterator i = opArgs.begin(); i != opArgs.end(); ++i) {
writeInt(1, sink);
store->exportPath(*i, sign, sink);
}
writeInt(0, sink);
exportPaths(*store, opArgs, sign, sink);
}
@ -612,12 +600,10 @@ static void opImport(Strings opFlags, Strings opArgs)
if (!opArgs.empty()) throw UsageError("no arguments expected");
FdSource source(STDIN_FILENO);
while (true) {
unsigned long long n = readLongLong(source);
if (n == 0) break;
if (n != 1) throw Error("input doesn't look like something created by `nix-store --export'");
cout << format("%1%\n") % store->importPath(requireSignature, source) << std::flush;
}
Paths paths = store->importPaths(requireSignature, source);
foreach (Paths::iterator, i, paths)
cout << format("%1%\n") % *i << std::flush;
}

View file

@ -56,7 +56,8 @@ static void tunnelStderr(const unsigned char * buf, size_t count)
if (canSendStderr && myPid == getpid()) {
try {
writeInt(STDERR_NEXT, to);
writeString(string((char *) buf, count), to);
writeString(buf, count, to);
to.flush();
} catch (...) {
/* Write failed; that means that the other side is
gone. */
@ -200,26 +201,20 @@ static void stopWork(bool success = true, const string & msg = "", unsigned int
struct TunnelSink : Sink
{
Sink & to;
TunnelSink(Sink & to) : to(to)
{
}
virtual void operator ()
(const unsigned char * data, unsigned int len)
TunnelSink(Sink & to) : to(to) { }
virtual void operator () (const unsigned char * data, size_t len)
{
writeInt(STDERR_WRITE, to);
writeString(string((const char *) data, len), to);
writeString(data, len, to);
}
};
struct TunnelSource : Source
struct TunnelSource : BufferedSource
{
Source & from;
TunnelSource(Source & from) : from(from)
{
}
virtual void operator ()
(unsigned char * data, unsigned int len)
TunnelSource(Source & from) : from(from) { }
size_t readUnbuffered(unsigned char * data, size_t len)
{
/* Careful: we're going to receive data from the client now,
so we have to disable the SIGPOLL handler. */
@ -228,11 +223,12 @@ struct TunnelSource : Source
writeInt(STDERR_READ, to);
writeInt(len, to);
string s = readString(from);
if (s.size() != len) throw Error("not enough data");
memcpy(data, (const unsigned char *) s.c_str(), len);
to.flush();
size_t n = readString(data, len, from);
startWork();
if (n == 0) throw EndOfFile("unexpected end-of-file");
return n;
}
};
@ -241,11 +237,14 @@ struct TunnelSource : Source
the contents of the file to `s'. Otherwise barf. */
struct RetrieveRegularNARSink : ParseSink
{
bool regular;
string s;
RetrieveRegularNARSink() : regular(true) { }
void createDirectory(const Path & path)
{
throw Error("regular file expected");
regular = false;
}
void receiveContents(unsigned char * data, unsigned int len)
@ -255,7 +254,7 @@ struct RetrieveRegularNARSink : ParseSink
void createSymlink(const Path & path, const string & target)
{
throw Error("regular file expected");
regular = false;
}
};
@ -266,10 +265,11 @@ struct SavingSourceAdapter : Source
Source & orig;
string s;
SavingSourceAdapter(Source & orig) : orig(orig) { }
void operator () (unsigned char * data, unsigned int len)
size_t read(unsigned char * data, size_t len)
{
orig(data, len);
s.append((const char *) data, len);
size_t n = orig.read(data, len);
s.append((const char *) data, n);
return n;
}
};
@ -327,7 +327,7 @@ static void performOp(unsigned int clientVersion,
store->queryReferrers(path, paths);
else paths = store->queryDerivationOutputs(path);
stopWork();
writeStringSet(paths, to);
writeStrings(paths, to);
break;
}
@ -371,11 +371,11 @@ static void performOp(unsigned int clientVersion,
addToStoreFromDump(). */
ParseSink sink; /* null sink; just parse the NAR */
parseDump(sink, savedNAR);
} else {
} else
parseDump(savedRegular, from);
}
startWork();
if (!savedRegular.regular) throw Error("regular file expected");
Path path = dynamic_cast<LocalStore *>(store.get())
->addToStoreFromDump(recursive ? savedNAR.s : savedRegular.s, baseName, recursive, hashAlgo);
stopWork();
@ -387,7 +387,7 @@ static void performOp(unsigned int clientVersion,
case wopAddTextToStore: {
string suffix = readString(from);
string s = readString(from);
PathSet refs = readStorePaths(from);
PathSet refs = readStorePaths<PathSet>(from);
startWork();
Path path = store->addTextToStore(suffix, s, refs);
stopWork();
@ -406,17 +406,17 @@ static void performOp(unsigned int clientVersion,
break;
}
case wopImportPath: {
case wopImportPaths: {
startWork();
TunnelSource source(from);
Path path = store->importPath(true, source);
Paths paths = store->importPaths(true, source);
stopWork();
writeString(path, to);
writeStrings(paths, to);
break;
}
case wopBuildDerivations: {
PathSet drvs = readStorePaths(from);
PathSet drvs = readStorePaths<PathSet>(from);
startWork();
store->buildDerivations(drvs);
stopWork();
@ -474,7 +474,7 @@ static void performOp(unsigned int clientVersion,
case wopCollectGarbage: {
GCOptions options;
options.action = (GCOptions::GCAction) readInt(from);
options.pathsToDelete = readStorePaths(from);
options.pathsToDelete = readStorePaths<PathSet>(from);
options.ignoreLiveness = readInt(from);
options.maxFreed = readLongLong(from);
options.maxLinks = readInt(from);
@ -492,7 +492,7 @@ static void performOp(unsigned int clientVersion,
store->collectGarbage(options, results);
stopWork();
writeStringSet(results.paths, to);
writeStrings(results.paths, to);
writeLongLong(results.bytesFreed, to);
writeLongLong(results.blocksFreed, to);
@ -530,7 +530,7 @@ static void performOp(unsigned int clientVersion,
writeInt(res ? 1 : 0, to);
if (res) {
writeString(info.deriver, to);
writeStringSet(info.references, to);
writeStrings(info.references, to);
writeLongLong(info.downloadSize, to);
if (GET_PROTOCOL_MINOR(clientVersion) >= 7)
writeLongLong(info.narSize, to);
@ -542,7 +542,7 @@ static void performOp(unsigned int clientVersion,
startWork();
PathSet paths = store->queryValidPaths();
stopWork();
writeStringSet(paths, to);
writeStrings(paths, to);
break;
}
@ -550,12 +550,12 @@ static void performOp(unsigned int clientVersion,
startWork();
PathSet paths = store->queryFailedPaths();
stopWork();
writeStringSet(paths, to);
writeStrings(paths, to);
break;
}
case wopClearFailedPaths: {
PathSet paths = readStringSet(from);
PathSet paths = readStrings<PathSet>(from);
startWork();
store->clearFailedPaths(paths);
stopWork();
@ -570,7 +570,7 @@ static void performOp(unsigned int clientVersion,
stopWork();
writeString(info.deriver, to);
writeString(printHash(info.hash), to);
writeStringSet(info.references, to);
writeStrings(info.references, to);
writeInt(info.registrationTime, to);
writeLongLong(info.narSize, to);
break;
@ -603,8 +603,8 @@ static void processConnection()
unsigned int magic = readInt(from);
if (magic != WORKER_MAGIC_1) throw Error("protocol mismatch");
writeInt(WORKER_MAGIC_2, to);
writeInt(PROTOCOL_VERSION, to);
to.flush();
unsigned int clientVersion = readInt(from);
/* Send startup error messages to the client. */
@ -626,9 +626,11 @@ static void processConnection()
store = boost::shared_ptr<StoreAPI>(new LocalStore());
stopWork();
to.flush();
} catch (Error & e) {
stopWork(false, e.msg());
to.flush();
return;
}
@ -648,9 +650,19 @@ static void processConnection()
try {
performOp(clientVersion, from, to, op);
} catch (Error & e) {
/* If we're not in a state were we can send replies, then
something went wrong processing the input of the
client. This can happen especially if I/O errors occur
during addTextToStore() / importPath(). If that
happens, just send the error message and exit. */
bool errorAllowed = canSendStderr;
if (!errorAllowed) printMsg(lvlError, format("error processing client input: %1%") % e.msg());
stopWork(false, e.msg(), GET_PROTOCOL_MINOR(clientVersion) >= 8 ? e.status : 0);
if (!errorAllowed) break;
}
to.flush();
assert(!canSendStderr);
};