diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libexpr/lexer.l | 8 | ||||
-rw-r--r-- | src/libexpr/primops.cc | 9 | ||||
-rw-r--r-- | src/libexpr/value.hh | 2 | ||||
-rw-r--r-- | src/libstore/binary-cache-store.cc | 2 | ||||
-rw-r--r-- | src/libstore/local-store.cc | 2 | ||||
-rw-r--r-- | src/libstore/s3-binary-cache-store.cc | 75 | ||||
-rw-r--r-- | src/libstore/store-api.cc | 2 | ||||
-rw-r--r-- | src/libutil/compression.cc | 12 | ||||
-rw-r--r-- | src/libutil/serialise.cc | 15 | ||||
-rw-r--r-- | src/libutil/serialise.hh | 6 | ||||
-rwxr-xr-x | src/nix-build/nix-build.cc | 1 | ||||
-rw-r--r-- | src/nix/installables.cc | 2 | ||||
-rw-r--r-- | src/nix/run.cc | 26 |
13 files changed, 99 insertions, 63 deletions
diff --git a/src/libexpr/lexer.l b/src/libexpr/lexer.l index 29ca327c1e4e..a052447d3dce 100644 --- a/src/libexpr/lexer.l +++ b/src/libexpr/lexer.l @@ -12,6 +12,8 @@ %{ +#include <boost/lexical_cast.hpp> + #include "nixexpr.hh" #include "parser-tab.hh" @@ -124,9 +126,11 @@ or { return OR_KW; } {ID} { yylval->id = strdup(yytext); return ID; } {INT} { errno = 0; - yylval->n = strtol(yytext, 0, 10); - if (errno != 0) + try { + yylval->n = boost::lexical_cast<int64_t>(yytext); + } catch (const boost::bad_lexical_cast &) { throw ParseError(format("invalid integer '%1%'") % yytext); + } return INT; } {FLOAT} { errno = 0; diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 8ace6db4d11d..6f82c6c404f2 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -1680,6 +1680,8 @@ static void prim_concatMap(EvalState & state, const Pos & pos, Value * * args, V static void prim_add(EvalState & state, const Pos & pos, Value * * args, Value & v) { + state.forceValue(*args[0], pos); + state.forceValue(*args[1], pos); if (args[0]->type == tFloat || args[1]->type == tFloat) mkFloat(v, state.forceFloat(*args[0], pos) + state.forceFloat(*args[1], pos)); else @@ -1689,6 +1691,8 @@ static void prim_add(EvalState & state, const Pos & pos, Value * * args, Value & static void prim_sub(EvalState & state, const Pos & pos, Value * * args, Value & v) { + state.forceValue(*args[0], pos); + state.forceValue(*args[1], pos); if (args[0]->type == tFloat || args[1]->type == tFloat) mkFloat(v, state.forceFloat(*args[0], pos) - state.forceFloat(*args[1], pos)); else @@ -1698,6 +1702,8 @@ static void prim_sub(EvalState & state, const Pos & pos, Value * * args, Value & static void prim_mul(EvalState & state, const Pos & pos, Value * * args, Value & v) { + state.forceValue(*args[0], pos); + state.forceValue(*args[1], pos); if (args[0]->type == tFloat || args[1]->type == tFloat) mkFloat(v, state.forceFloat(*args[0], pos) * state.forceFloat(*args[1], pos)); else @@ -1707,6 +1713,9 @@ static void prim_mul(EvalState & state, const Pos & pos, Value * * args, Value & static void prim_div(EvalState & state, const Pos & pos, Value * * args, Value & v) { + state.forceValue(*args[0], pos); + state.forceValue(*args[1], pos); + NixFloat f2 = state.forceFloat(*args[1], pos); if (f2 == 0) throw EvalError(format("division by zero, at %1%") % pos); diff --git a/src/libexpr/value.hh b/src/libexpr/value.hh index 809772f7c084..e1ec87d3b84c 100644 --- a/src/libexpr/value.hh +++ b/src/libexpr/value.hh @@ -43,7 +43,7 @@ class XMLWriter; class JSONPlaceholder; -typedef long NixInt; +typedef int64_t NixInt; typedef double NixFloat; /* External values must descend from ExternalValueBase, so that diff --git a/src/libstore/binary-cache-store.cc b/src/libstore/binary-cache-store.cc index 9c75c85993f9..4527ee6ba660 100644 --- a/src/libstore/binary-cache-store.cc +++ b/src/libstore/binary-cache-store.cc @@ -232,7 +232,7 @@ void BinaryCacheStore::narFromPath(const Path & storePath, Sink & sink) throw SubstituteGone(e.what()); } - decompressor->flush(); + decompressor->finish(); stats.narRead++; //stats.narReadCompressedBytes += nar->size(); // FIXME diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 3b2ba65f3b46..c91dbf241bcf 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -450,7 +450,7 @@ static void canonicalisePathMetaData_(const Path & path, uid_t fromUid, InodesSe ssize_t eaSize = llistxattr(path.c_str(), nullptr, 0); if (eaSize < 0) { - if (errno != ENOTSUP) + if (errno != ENOTSUP && errno != ENODATA) throw SysError("querying extended attributes of '%s'", path); } else if (eaSize > 0) { std::vector<char> eaBuf(eaSize); diff --git a/src/libstore/s3-binary-cache-store.cc b/src/libstore/s3-binary-cache-store.cc index 6d95c1fa8c65..7711388f05a9 100644 --- a/src/libstore/s3-binary-cache-store.cc +++ b/src/libstore/s3-binary-cache-store.cc @@ -275,6 +275,9 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore return true; } + std::shared_ptr<TransferManager> transferManager; + std::once_flag transferManagerCreated; + void uploadFile(const std::string & path, const std::string & data, const std::string & mimeType, const std::string & contentEncoding) @@ -286,48 +289,28 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore static std::shared_ptr<Aws::Utils::Threading::PooledThreadExecutor> executor = std::make_shared<Aws::Utils::Threading::PooledThreadExecutor>(maxThreads); - TransferManagerConfiguration transferConfig(executor.get()); - - transferConfig.s3Client = s3Helper.client; - transferConfig.bufferSize = bufferSize; - - transferConfig.uploadProgressCallback = - [&](const TransferManager *transferManager, - const std::shared_ptr<const TransferHandle> - &transferHandle) { - //FIXME: find a way to properly abort the multipart upload. - checkInterrupt(); - debug("upload progress ('%s'): '%d' of '%d' bytes", - path, - transferHandle->GetBytesTransferred(), - transferHandle->GetBytesTotalSize()); - }; + std::call_once(transferManagerCreated, [&]() { - transferConfig.transferStatusUpdatedCallback = - [&](const TransferManager *, - const std::shared_ptr<const TransferHandle> - &transferHandle) { - switch (transferHandle->GetStatus()) { - case TransferStatus::COMPLETED: - printTalkative("upload of '%s' completed", path); - stats.put++; - stats.putBytes += data.size(); - break; - case TransferStatus::IN_PROGRESS: - break; - case TransferStatus::FAILED: - throw Error("AWS error: failed to upload 's3://%s/%s'", - bucketName, path); - break; - default: - throw Error("AWS error: transfer status of 's3://%s/%s' " - "in unexpected state", - bucketName, path); - }; - }; + TransferManagerConfiguration transferConfig(executor.get()); + + transferConfig.s3Client = s3Helper.client; + transferConfig.bufferSize = bufferSize; - std::shared_ptr<TransferManager> transferManager = - TransferManager::Create(transferConfig); + transferConfig.uploadProgressCallback = + [&](const TransferManager *transferManager, + const std::shared_ptr<const TransferHandle> + &transferHandle) + { + //FIXME: find a way to properly abort the multipart upload. + //checkInterrupt(); + debug("upload progress ('%s'): '%d' of '%d' bytes", + path, + transferHandle->GetBytesTransferred(), + transferHandle->GetBytesTotalSize()); + }; + + transferManager = TransferManager::Create(transferConfig); + }); auto now1 = std::chrono::steady_clock::now(); @@ -339,6 +322,16 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore transferHandle->WaitUntilFinished(); + if (transferHandle->GetStatus() == TransferStatus::FAILED) + throw Error("AWS error: failed to upload 's3://%s/%s': %s", + bucketName, path, transferHandle->GetLastError().GetMessage()); + + if (transferHandle->GetStatus() != TransferStatus::COMPLETED) + throw Error("AWS error: transfer status of 's3://%s/%s' in unexpected state", + bucketName, path); + + printTalkative("upload of '%s' completed", path); + auto now2 = std::chrono::steady_clock::now(); auto duration = @@ -349,6 +342,8 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore bucketName % path % data.size() % duration); stats.putTimeMs += duration; + stats.putBytes += data.size(); + stats.put++; } void upsertFile(const std::string & path, const std::string & data, diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index 7a4a5f5eb85d..1f42097fccfb 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -609,6 +609,8 @@ void copyStorePath(ref<Store> srcStore, ref<Store> dstStore, act.progress(total, info->narSize); }); srcStore->narFromPath({storePath}, wrapperSink); + }, [&]() { + throw EndOfFile("NAR for '%s' fetched from '%s' is incomplete", storePath, srcStore->getUri()); }); dstStore->addToStore(*info, *source, repair, checkSigs); diff --git a/src/libutil/compression.cc b/src/libutil/compression.cc index 53b62f62a76f..204c63cd26fc 100644 --- a/src/libutil/compression.cc +++ b/src/libutil/compression.cc @@ -15,12 +15,10 @@ namespace nix { -static const size_t bufSize = 32 * 1024; - // Don't feed brotli too much at once. struct ChunkedCompressionSink : CompressionSink { - uint8_t outbuf[BUFSIZ]; + uint8_t outbuf[32 * 1024]; void write(const unsigned char * data, size_t len) override { @@ -124,7 +122,7 @@ struct BzipDecompressionSink : ChunkedCompressionSink write(nullptr, 0); } - void writeInternal(const unsigned char * data, size_t len) + void writeInternal(const unsigned char * data, size_t len) override { assert(len <= std::numeric_limits<decltype(strm.avail_in)>::max()); @@ -173,7 +171,7 @@ struct BrotliDecompressionSink : ChunkedCompressionSink writeInternal(nullptr, 0); } - void writeInternal(const unsigned char * data, size_t len) + void writeInternal(const unsigned char * data, size_t len) override { const uint8_t * next_in = data; size_t avail_in = len; @@ -330,7 +328,7 @@ struct BzipCompressionSink : ChunkedCompressionSink writeInternal(nullptr, 0); } - void writeInternal(const unsigned char * data, size_t len) + void writeInternal(const unsigned char * data, size_t len) override { assert(len <= std::numeric_limits<decltype(strm.avail_in)>::max()); @@ -380,7 +378,7 @@ struct BrotliCompressionSink : ChunkedCompressionSink writeInternal(nullptr, 0); } - void writeInternal(const unsigned char * data, size_t len) + void writeInternal(const unsigned char * data, size_t len) override { const uint8_t * next_in = data; size_t avail_in = len; diff --git a/src/libutil/serialise.cc b/src/libutil/serialise.cc index b2c49d911b34..17448f70efb6 100644 --- a/src/libutil/serialise.cc +++ b/src/libutil/serialise.cc @@ -161,16 +161,20 @@ size_t StringSource::read(unsigned char * data, size_t len) #error Coroutines are broken in this version of Boost! #endif -std::unique_ptr<Source> sinkToSource(std::function<void(Sink &)> fun) +std::unique_ptr<Source> sinkToSource( + std::function<void(Sink &)> fun, + std::function<void()> eof) { struct SinkToSource : Source { typedef boost::coroutines2::coroutine<std::string> coro_t; + std::function<void()> eof; coro_t::pull_type coro; - SinkToSource(std::function<void(Sink &)> fun) - : coro([&](coro_t::push_type & yield) { + SinkToSource(std::function<void(Sink &)> fun, std::function<void()> eof) + : eof(eof) + , coro([&](coro_t::push_type & yield) { LambdaSink sink([&](const unsigned char * data, size_t len) { if (len) yield(std::string((const char *) data, len)); }); @@ -184,8 +188,7 @@ std::unique_ptr<Source> sinkToSource(std::function<void(Sink &)> fun) size_t read(unsigned char * data, size_t len) override { - if (!coro) - throw EndOfFile("coroutine has finished"); + if (!coro) { eof(); abort(); } if (pos == cur.size()) { if (!cur.empty()) coro(); @@ -201,7 +204,7 @@ std::unique_ptr<Source> sinkToSource(std::function<void(Sink &)> fun) } }; - return std::make_unique<SinkToSource>(fun); + return std::make_unique<SinkToSource>(fun, eof); } diff --git a/src/libutil/serialise.hh b/src/libutil/serialise.hh index 14b62fdb6774..4b6ad5da5b9c 100644 --- a/src/libutil/serialise.hh +++ b/src/libutil/serialise.hh @@ -214,7 +214,11 @@ struct LambdaSource : Source /* Convert a function that feeds data into a Sink into a Source. The Source executes the function as a coroutine. */ -std::unique_ptr<Source> sinkToSource(std::function<void(Sink &)> fun); +std::unique_ptr<Source> sinkToSource( + std::function<void(Sink &)> fun, + std::function<void()> eof = []() { + throw EndOfFile("coroutine has finished"); + }); void writePadding(size_t len, Sink & sink); diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc index 34f1cba9ddac..21a0756a2007 100755 --- a/src/nix-build/nix-build.cc +++ b/src/nix-build/nix-build.cc @@ -419,7 +419,6 @@ void mainWrapped(int argc, char * * argv) R"s([ -n "$PS1" ] && PS1='\n\[\033[1;32m\][nix-shell:\w]\$\[\033[0m\] '; )s" "if [ \"$(type -t runHook)\" = function ]; then runHook shellHook; fi; " "unset NIX_ENFORCE_PURITY; " - "unset NIX_INDENT_MAKE; " "shopt -u nullglob; " "unset TZ; %4%" "%5%", diff --git a/src/nix/installables.cc b/src/nix/installables.cc index 0be992b03c5a..0c1ad3ab3db0 100644 --- a/src/nix/installables.cc +++ b/src/nix/installables.cc @@ -96,7 +96,7 @@ struct InstallableStorePath : Installable Buildables toBuildables() override { - return {{"", {{"out", storePath}}}}; + return {{isDerivation(storePath) ? storePath : "", {{"out", storePath}}}}; } }; diff --git a/src/nix/run.cc b/src/nix/run.cc index d04e106e037b..35b763345872 100644 --- a/src/nix/run.cc +++ b/src/nix/run.cc @@ -7,11 +7,14 @@ #include "finally.hh" #include "fs-accessor.hh" #include "progress-bar.hh" +#include "affinity.hh" #if __linux__ #include <sys/mount.h> #endif +#include <queue> + using namespace nix; std::string chrootHelperName = "__run_in_chroot"; @@ -121,10 +124,27 @@ struct CmdRun : InstallablesCommand unsetenv(var.c_str()); } + std::unordered_set<Path> done; + std::queue<Path> todo; + for (auto & path : outPaths) todo.push(path); + auto unixPath = tokenizeString<Strings>(getEnv("PATH"), ":"); - for (auto & path : outPaths) - if (accessor->stat(path + "/bin").type != FSAccessor::tMissing) + + while (!todo.empty()) { + Path path = todo.front(); + todo.pop(); + if (!done.insert(path).second) continue; + + if (true) unixPath.push_front(path + "/bin"); + + auto propPath = path + "/nix-support/propagated-user-env-packages"; + if (accessor->stat(propPath).type == FSAccessor::tRegular) { + for (auto & p : tokenizeString<Paths>(readFile(propPath))) + todo.push(p); + } + } + setenv("PATH", concatStringsSep(":", unixPath).c_str(), 1); std::string cmd = *command.begin(); @@ -135,6 +155,8 @@ struct CmdRun : InstallablesCommand restoreSignals(); + restoreAffinity(); + /* If this is a diverted store (i.e. its "logical" location (typically /nix/store) differs from its "physical" location (e.g. /home/eelco/nix/store), then run the command in a |