aboutsummaryrefslogtreecommitdiff
path: root/src/libutil
diff options
context:
space:
mode:
authorBen Burdette <bburdette@gmail.com>2020-06-18 13:07:53 -0600
committerBen Burdette <bburdette@gmail.com>2020-06-18 13:07:53 -0600
commite6f93b94fc38d94827778bcaa64642aee5030ecd (patch)
treeaa80872b4ed72abc548a41f52ec876be76fc85a0 /src/libutil
parent2f19650768e2bbef0f7ad819c5aa3dce5084d56d (diff)
parent6c000eed80565d83d596da800ca0db92e248342e (diff)
Merge branch 'master' into caveman-LOCs
Diffstat (limited to 'src/libutil')
-rw-r--r--src/libutil/ansicolor.hh2
-rw-r--r--src/libutil/args.cc11
-rw-r--r--src/libutil/args.hh2
-rw-r--r--src/libutil/config.hh1
-rw-r--r--src/libutil/error.cc12
-rw-r--r--src/libutil/error.hh15
-rw-r--r--src/libutil/hash.cc14
-rw-r--r--src/libutil/hash.hh6
-rw-r--r--src/libutil/json.cc2
-rw-r--r--src/libutil/local.mk2
-rw-r--r--src/libutil/logging.cc32
-rw-r--r--src/libutil/logging.hh8
-rw-r--r--src/libutil/rust-ffi.cc2
-rw-r--r--src/libutil/rust-ffi.hh2
-rw-r--r--src/libutil/serialise.cc4
-rw-r--r--src/libutil/tests/hash.cc16
-rw-r--r--src/libutil/tests/logging.cc28
-rw-r--r--src/libutil/tests/pool.cc127
-rw-r--r--src/libutil/types.hh3
-rw-r--r--src/libutil/util.cc14
-rw-r--r--src/libutil/util.hh9
21 files changed, 245 insertions, 67 deletions
diff --git a/src/libutil/ansicolor.hh b/src/libutil/ansicolor.hh
index 8ae07b092..a38c2d798 100644
--- a/src/libutil/ansicolor.hh
+++ b/src/libutil/ansicolor.hh
@@ -11,5 +11,7 @@ namespace nix {
#define ANSI_GREEN "\e[32;1m"
#define ANSI_YELLOW "\e[33;1m"
#define ANSI_BLUE "\e[34;1m"
+#define ANSI_MAGENTA "\e[35m;1m"
+#define ANSI_CYAN "\e[36m;1m"
}
diff --git a/src/libutil/args.cc b/src/libutil/args.cc
index 10d6e89bb..ce6580119 100644
--- a/src/libutil/args.cc
+++ b/src/libutil/args.cc
@@ -217,10 +217,15 @@ MultiCommand::MultiCommand(const Commands & commands)
{
expectedArgs.push_back(ExpectedArg{"command", 1, true, [=](std::vector<std::string> ss) {
assert(!command);
- auto i = commands.find(ss[0]);
+ auto cmd = ss[0];
+ if (auto alias = get(deprecatedAliases, cmd)) {
+ warn("'%s' is a deprecated alias for '%s'", cmd, *alias);
+ cmd = *alias;
+ }
+ auto i = commands.find(cmd);
if (i == commands.end())
- throw UsageError("'%s' is not a recognised command", ss[0]);
- command = {ss[0], i->second()};
+ throw UsageError("'%s' is not a recognised command", cmd);
+ command = {cmd, i->second()};
}});
categories[Command::catDefault] = "Available commands";
diff --git a/src/libutil/args.hh b/src/libutil/args.hh
index 1932e6a8a..154d1e6aa 100644
--- a/src/libutil/args.hh
+++ b/src/libutil/args.hh
@@ -234,6 +234,8 @@ public:
std::map<Command::Category, std::string> categories;
+ std::map<std::string, std::string> deprecatedAliases;
+
// Selected command, if any.
std::optional<std::pair<std::string, ref<Command>>> command;
diff --git a/src/libutil/config.hh b/src/libutil/config.hh
index 5c7a70a2e..66073546e 100644
--- a/src/libutil/config.hh
+++ b/src/libutil/config.hh
@@ -1,3 +1,4 @@
+#include <cassert>
#include <map>
#include <set>
diff --git a/src/libutil/error.cc b/src/libutil/error.cc
index a713fe9db..07d9791ad 100644
--- a/src/libutil/error.cc
+++ b/src/libutil/error.cc
@@ -132,7 +132,7 @@ void printCodeLines(std::ostream &out, const string &prefix, const NixCode &nixC
{
// previous line of code.
if (nixCode.prevLineOfCode.has_value()) {
- out << std::endl
+ out << std::endl
<< fmt("%1% %|2$5d|| %3%",
prefix,
(nixCode.errPos.line - 1),
@@ -176,7 +176,7 @@ void printCodeLines(std::ostream &out, const string &prefix, const NixCode &nixC
std::ostream& operator<<(std::ostream &out, const ErrorInfo &einfo)
{
- int errwidth = 80;
+ auto errwidth = std::max<size_t>(getWindowSize().second, 20);
string prefix = "";
string levelString;
@@ -229,12 +229,10 @@ std::ostream& operator<<(std::ostream &out, const ErrorInfo &einfo)
}
}
- int ndl = prefix.length() + levelString.length() + 3 + einfo.name.length() + einfo.programName.value_or("").length();
- int dashwidth = ndl > (errwidth - 3) ? 3 : errwidth - ndl;
+ auto ndl = prefix.length() + levelString.length() + 3 + einfo.name.length() + einfo.programName.value_or("").length();
+ auto dashwidth = ndl > (errwidth - 3) ? 3 : errwidth - ndl;
- string dashes;
- for (int i = 0; i < dashwidth; ++i)
- dashes.append("-");
+ std::string dashes(dashwidth, '-');
// divider.
if (einfo.name != "")
diff --git a/src/libutil/error.hh b/src/libutil/error.hh
index bd17a47c1..8494b9412 100644
--- a/src/libutil/error.hh
+++ b/src/libutil/error.hh
@@ -4,6 +4,7 @@
#include "ref.hh"
#include "types.hh"
+#include <cstring>
#include <list>
#include <memory>
#include <map>
@@ -22,7 +23,7 @@
namespace nix {
-/*
+/*
This file defines two main structs/classes used in nix error handling.
@@ -114,7 +115,7 @@ protected:
mutable std::optional<string> what_;
const string& calcWhat() const;
-
+
public:
unsigned int status = 1; // exit status
@@ -127,9 +128,9 @@ public:
{ }
template<typename... Args>
- BaseError(const Args & ... args)
+ BaseError(const std::string & fs, const Args & ... args)
: err { .level = lvlError,
- .hint = hintfmt(args...)
+ .hint = hintfmt(fs, args...)
}
{ }
@@ -139,7 +140,11 @@ public:
}
{ }
- BaseError(ErrorInfo e)
+ BaseError(ErrorInfo && e)
+ : err(std::move(e))
+ { }
+
+ BaseError(const ErrorInfo & e)
: err(e)
{ }
diff --git a/src/libutil/hash.cc b/src/libutil/hash.cc
index 7caee1da7..460d479a3 100644
--- a/src/libutil/hash.cc
+++ b/src/libutil/hash.cc
@@ -125,7 +125,7 @@ std::string Hash::to_string(Base base, bool includeType) const
}
-Hash::Hash(const std::string & s, HashType type)
+Hash::Hash(std::string_view s, HashType type)
: type(type)
{
size_t pos = 0;
@@ -194,7 +194,7 @@ Hash::Hash(const std::string & s, HashType type)
}
else if (isSRI || size == base64Len()) {
- auto d = base64Decode(std::string(s, pos));
+ auto d = base64Decode(s.substr(pos));
if (d.size() != hashSize)
throw BadHash("invalid %s hash '%s'", isSRI ? "SRI" : "base-64", s);
assert(hashSize);
@@ -205,6 +205,16 @@ Hash::Hash(const std::string & s, HashType type)
throw BadHash("hash '%s' has wrong length for hash type '%s'", s, printHashType(type));
}
+Hash newHashAllowEmpty(std::string hashStr, HashType ht)
+{
+ if (hashStr.empty()) {
+ Hash h(ht);
+ warn("found empty hash, assuming '%s'", h.to_string(SRI, true));
+ return h;
+ } else
+ return Hash(hashStr, ht);
+}
+
union Ctx
{
diff --git a/src/libutil/hash.hh b/src/libutil/hash.hh
index ea9fca3e7..180fb7633 100644
--- a/src/libutil/hash.hh
+++ b/src/libutil/hash.hh
@@ -42,7 +42,7 @@ struct Hash
Subresource Integrity hash expression). If the 'type' argument
is htUnknown, then the hash type must be specified in the
string. */
- Hash(const std::string & s, HashType type = htUnknown);
+ Hash(std::string_view s, HashType type = htUnknown);
void init();
@@ -79,7 +79,7 @@ struct Hash
/* Return a string representation of the hash, in base-16, base-32
or base-64. By default, this is prefixed by the hash type
(e.g. "sha256:"). */
- std::string to_string(Base base = Base32, bool includeType = true) const;
+ std::string to_string(Base base, bool includeType) const;
std::string gitRev() const
{
@@ -94,6 +94,8 @@ struct Hash
}
};
+/* Helper that defaults empty hashes to the 0 hash. */
+Hash newHashAllowEmpty(std::string hashStr, HashType ht);
/* Print a hash in base-16 if it's MD5, or base-32 otherwise. */
string printHash16or32(const Hash & hash);
diff --git a/src/libutil/json.cc b/src/libutil/json.cc
index 74e37b4c4..01331947e 100644
--- a/src/libutil/json.cc
+++ b/src/libutil/json.cc
@@ -173,7 +173,7 @@ JSONObject JSONPlaceholder::object()
JSONPlaceholder::~JSONPlaceholder()
{
- assert(!first || std::uncaught_exception());
+ assert(!first || std::uncaught_exceptions());
}
}
diff --git a/src/libutil/local.mk b/src/libutil/local.mk
index 16c1fa03f..ae7eb67ad 100644
--- a/src/libutil/local.mk
+++ b/src/libutil/local.mk
@@ -7,5 +7,3 @@ libutil_DIR := $(d)
libutil_SOURCES := $(wildcard $(d)/*.cc)
libutil_LDFLAGS = $(LIBLZMA_LIBS) -lbz2 -pthread $(OPENSSL_LIBS) $(LIBBROTLI_LIBS) $(LIBARCHIVE_LIBS) $(BOOST_LDFLAGS) -lboost_context
-
-libutil_LIBS = libnixrust
diff --git a/src/libutil/logging.cc b/src/libutil/logging.cc
index 41378b0db..105fadb15 100644
--- a/src/libutil/logging.cc
+++ b/src/libutil/logging.cc
@@ -18,7 +18,7 @@ void setCurActivity(const ActivityId activityId)
curActivity = activityId;
}
-Logger * logger = makeDefaultLogger();
+Logger * logger = makeSimpleLogger(true);
void Logger::warn(const std::string & msg)
{
@@ -35,13 +35,19 @@ class SimpleLogger : public Logger
public:
bool systemd, tty;
+ bool printBuildLogs;
- SimpleLogger()
+ SimpleLogger(bool printBuildLogs)
+ : printBuildLogs(printBuildLogs)
{
systemd = getEnv("IN_SYSTEMD") == "1";
tty = isatty(STDERR_FILENO);
}
+ bool isVerbose() override {
+ return printBuildLogs;
+ }
+
void log(Verbosity lvl, const FormatOrString & fs) override
{
if (lvl > verbosity) return;
@@ -78,6 +84,18 @@ public:
if (lvl <= verbosity && !s.empty())
log(lvl, s + "...");
}
+
+ void result(ActivityId act, ResultType type, const Fields & fields) override
+ {
+ if (type == resBuildLogLine && printBuildLogs) {
+ auto lastLine = fields[0].s;
+ printError(lastLine);
+ }
+ else if (type == resPostBuildLogLine && printBuildLogs) {
+ auto lastLine = fields[0].s;
+ printError("post-build-hook: " + lastLine);
+ }
+ }
};
Verbosity verbosity = lvlInfo;
@@ -102,9 +120,9 @@ void writeToStderr(const string & s)
}
}
-Logger * makeDefaultLogger()
+Logger * makeSimpleLogger(bool printBuildLogs)
{
- return new SimpleLogger();
+ return new SimpleLogger(printBuildLogs);
}
std::atomic<uint64_t> nextId{(uint64_t) getpid() << 32};
@@ -121,6 +139,10 @@ struct JSONLogger : Logger {
JSONLogger(Logger & prevLogger) : prevLogger(prevLogger) { }
+ bool isVerbose() override {
+ return true;
+ }
+
void addFields(nlohmann::json & json, const Fields & fields)
{
if (fields.empty()) return;
@@ -251,7 +273,7 @@ bool handleJSONLogMessage(const std::string & msg,
}
} catch (std::exception & e) {
- logError({
+ logError({
.name = "Json log message",
.hint = hintfmt("bad log message from builder: %s", e.what())
});
diff --git a/src/libutil/logging.hh b/src/libutil/logging.hh
index eeb7233e9..b1583eced 100644
--- a/src/libutil/logging.hh
+++ b/src/libutil/logging.hh
@@ -18,6 +18,7 @@ typedef enum {
actSubstitute = 108,
actQueryPathInfo = 109,
actPostBuildHook = 110,
+ actBuildWaiting = 111,
} ActivityType;
typedef enum {
@@ -54,6 +55,11 @@ public:
virtual ~Logger() { }
+ virtual void stop() { };
+
+ // Whether the logger prints the whole build log
+ virtual bool isVerbose() { return false; }
+
virtual void log(Verbosity lvl, const FormatOrString & fs) = 0;
void log(const FormatOrString & fs)
@@ -140,7 +146,7 @@ struct PushActivity
extern Logger * logger;
-Logger * makeDefaultLogger();
+Logger * makeSimpleLogger(bool printBuildLogs = true);
Logger * makeJSONLogger(Logger & prevLogger);
diff --git a/src/libutil/rust-ffi.cc b/src/libutil/rust-ffi.cc
index 6f36b3192..67924568f 100644
--- a/src/libutil/rust-ffi.cc
+++ b/src/libutil/rust-ffi.cc
@@ -1,3 +1,4 @@
+#if 0
#include "logging.hh"
#include "rust-ffi.hh"
@@ -20,3 +21,4 @@ std::ostream & operator << (std::ostream & str, const String & s)
}
}
+#endif
diff --git a/src/libutil/rust-ffi.hh b/src/libutil/rust-ffi.hh
index 228e2eead..cfbaf9dec 100644
--- a/src/libutil/rust-ffi.hh
+++ b/src/libutil/rust-ffi.hh
@@ -1,4 +1,5 @@
#pragma once
+#if 0
#include "serialise.hh"
@@ -185,3 +186,4 @@ struct Result
};
}
+#endif
diff --git a/src/libutil/serialise.cc b/src/libutil/serialise.cc
index 35f7ee917..c8b71188f 100644
--- a/src/libutil/serialise.cc
+++ b/src/libutil/serialise.cc
@@ -52,10 +52,10 @@ size_t threshold = 256 * 1024 * 1024;
static void warnLargeDump()
{
- logWarning(ErrorInfo {
+ logWarning({
.name = "Large path",
.description = "dumping very large path (> 256 MiB); this may run out of memory"
- });
+ });
}
diff --git a/src/libutil/tests/hash.cc b/src/libutil/tests/hash.cc
index 7cb439817..5334b046e 100644
--- a/src/libutil/tests/hash.cc
+++ b/src/libutil/tests/hash.cc
@@ -11,28 +11,28 @@ namespace nix {
// values taken from: https://tools.ietf.org/html/rfc1321
auto s1 = "";
auto hash = hashString(HashType::htMD5, s1);
- ASSERT_EQ(hash.to_string(Base::Base16), "md5:d41d8cd98f00b204e9800998ecf8427e");
+ ASSERT_EQ(hash.to_string(Base::Base16, true), "md5:d41d8cd98f00b204e9800998ecf8427e");
}
TEST(hashString, testKnownMD5Hashes2) {
// values taken from: https://tools.ietf.org/html/rfc1321
auto s2 = "abc";
auto hash = hashString(HashType::htMD5, s2);
- ASSERT_EQ(hash.to_string(Base::Base16), "md5:900150983cd24fb0d6963f7d28e17f72");
+ ASSERT_EQ(hash.to_string(Base::Base16, true), "md5:900150983cd24fb0d6963f7d28e17f72");
}
TEST(hashString, testKnownSHA1Hashes1) {
// values taken from: https://tools.ietf.org/html/rfc3174
auto s = "abc";
auto hash = hashString(HashType::htSHA1, s);
- ASSERT_EQ(hash.to_string(Base::Base16),"sha1:a9993e364706816aba3e25717850c26c9cd0d89d");
+ ASSERT_EQ(hash.to_string(Base::Base16, true),"sha1:a9993e364706816aba3e25717850c26c9cd0d89d");
}
TEST(hashString, testKnownSHA1Hashes2) {
// values taken from: https://tools.ietf.org/html/rfc3174
auto s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
auto hash = hashString(HashType::htSHA1, s);
- ASSERT_EQ(hash.to_string(Base::Base16),"sha1:84983e441c3bd26ebaae4aa1f95129e5e54670f1");
+ ASSERT_EQ(hash.to_string(Base::Base16, true),"sha1:84983e441c3bd26ebaae4aa1f95129e5e54670f1");
}
TEST(hashString, testKnownSHA256Hashes1) {
@@ -40,7 +40,7 @@ namespace nix {
auto s = "abc";
auto hash = hashString(HashType::htSHA256, s);
- ASSERT_EQ(hash.to_string(Base::Base16),
+ ASSERT_EQ(hash.to_string(Base::Base16, true),
"sha256:ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");
}
@@ -48,7 +48,7 @@ namespace nix {
// values taken from: https://tools.ietf.org/html/rfc4634
auto s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
auto hash = hashString(HashType::htSHA256, s);
- ASSERT_EQ(hash.to_string(Base::Base16),
+ ASSERT_EQ(hash.to_string(Base::Base16, true),
"sha256:248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1");
}
@@ -56,7 +56,7 @@ namespace nix {
// values taken from: https://tools.ietf.org/html/rfc4634
auto s = "abc";
auto hash = hashString(HashType::htSHA512, s);
- ASSERT_EQ(hash.to_string(Base::Base16),
+ ASSERT_EQ(hash.to_string(Base::Base16, true),
"sha512:ddaf35a193617abacc417349ae20413112e6fa4e89a9"
"7ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd"
"454d4423643ce80e2a9ac94fa54ca49f");
@@ -67,7 +67,7 @@ namespace nix {
auto s = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu";
auto hash = hashString(HashType::htSHA512, s);
- ASSERT_EQ(hash.to_string(Base::Base16),
+ ASSERT_EQ(hash.to_string(Base::Base16, true),
"sha512:8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa1"
"7299aeadb6889018501d289e4900f7e4331b99dec4b5433a"
"c7d329eeb6dd26545e96e55b874be909");
diff --git a/src/libutil/tests/logging.cc b/src/libutil/tests/logging.cc
index fa5983f2e..8c7bb16b3 100644
--- a/src/libutil/tests/logging.cc
+++ b/src/libutil/tests/logging.cc
@@ -22,7 +22,7 @@ namespace nix {
logger->logEI(e.info());
auto str = testing::internal::GetCapturedStderr();
- ASSERT_STREQ(str.c_str(),"\x1B[31;1merror:\x1B[0m\x1B[34;1m --- TestError ------------------------------------ error-unit-test\x1B[0m\nan error for testing purposes\n");
+ ASSERT_STREQ(str.c_str(),"\x1B[31;1merror:\x1B[0m\x1B[34;1m --- TestError --- error-unit-test\x1B[0m\nan error for testing purposes\n");
}
}
@@ -42,7 +42,7 @@ namespace nix {
logger->logEI(ei);
auto str = testing::internal::GetCapturedStderr();
- ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- TestError ------------------------------------ error-unit-test\x1B[0m\n\x1B[33;1m\x1B[0minitial error\x1B[0m; subsequent error message.\n");
+ ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- TestError --- error-unit-test\x1B[0m\n\x1B[33;1m\x1B[0minitial error\x1B[0m; subsequent error message.\n");
}
}
@@ -60,7 +60,7 @@ namespace nix {
logError(e.info());
auto str = testing::internal::GetCapturedStderr();
- ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- SysError ------------------------------------- error-unit-test\x1B[0m\n\x1B[33;1m\x1B[0mstatting file\x1B[0m: \x1B[33;1mBad file descriptor\x1B[0m\n");
+ ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- SysError --- error-unit-test\x1B[0m\n\x1B[33;1m\x1B[0mstatting file\x1B[0m: \x1B[33;1mBad file descriptor\x1B[0m\n");
}
}
@@ -74,7 +74,7 @@ namespace nix {
});
auto str = testing::internal::GetCapturedStderr();
- ASSERT_STREQ(str.c_str(), "\x1B[32;1minfo:\x1B[0m\x1B[34;1m --- Info name ------------------------------------- error-unit-test\x1B[0m\nInfo description\n");
+ ASSERT_STREQ(str.c_str(), "\x1B[32;1minfo:\x1B[0m\x1B[34;1m --- Info name --- error-unit-test\x1B[0m\nInfo description\n");
}
TEST(logEI, loggingErrorOnTalkativeLevel) {
@@ -88,7 +88,7 @@ namespace nix {
});
auto str = testing::internal::GetCapturedStderr();
- ASSERT_STREQ(str.c_str(), "\x1B[32;1mtalk:\x1B[0m\x1B[34;1m --- Talkative name -------------------------------- error-unit-test\x1B[0m\nTalkative description\n");
+ ASSERT_STREQ(str.c_str(), "\x1B[32;1mtalk:\x1B[0m\x1B[34;1m --- Talkative name --- error-unit-test\x1B[0m\nTalkative description\n");
}
TEST(logEI, loggingErrorOnChattyLevel) {
@@ -102,7 +102,7 @@ namespace nix {
});
auto str = testing::internal::GetCapturedStderr();
- ASSERT_STREQ(str.c_str(), "\x1B[32;1mchat:\x1B[0m\x1B[34;1m --- Chatty name ----------------------------------- error-unit-test\x1B[0m\nTalkative description\n");
+ ASSERT_STREQ(str.c_str(), "\x1B[32;1mchat:\x1B[0m\x1B[34;1m --- Chatty name --- error-unit-test\x1B[0m\nTalkative description\n");
}
TEST(logEI, loggingErrorOnDebugLevel) {
@@ -116,7 +116,7 @@ namespace nix {
});
auto str = testing::internal::GetCapturedStderr();
- ASSERT_STREQ(str.c_str(), "\x1B[33;1mdebug:\x1B[0m\x1B[34;1m --- Debug name ----------------------------------- error-unit-test\x1B[0m\nDebug description\n");
+ ASSERT_STREQ(str.c_str(), "\x1B[33;1mdebug:\x1B[0m\x1B[34;1m --- Debug name --- error-unit-test\x1B[0m\nDebug description\n");
}
TEST(logEI, loggingErrorOnVomitLevel) {
@@ -130,7 +130,7 @@ namespace nix {
});
auto str = testing::internal::GetCapturedStderr();
- ASSERT_STREQ(str.c_str(), "\x1B[32;1mvomit:\x1B[0m\x1B[34;1m --- Vomit name ----------------------------------- error-unit-test\x1B[0m\nVomit description\n");
+ ASSERT_STREQ(str.c_str(), "\x1B[32;1mvomit:\x1B[0m\x1B[34;1m --- Vomit name --- error-unit-test\x1B[0m\nVomit description\n");
}
/* ----------------------------------------------------------------------------
@@ -147,7 +147,7 @@ namespace nix {
});
auto str = testing::internal::GetCapturedStderr();
- ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- name ----------------------------------------- error-unit-test\x1B[0m\nerror description\n");
+ ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- name --- error-unit-test\x1B[0m\nerror description\n");
}
TEST(logError, logErrorWithPreviousAndNextLinesOfCode) {
@@ -171,7 +171,7 @@ namespace nix {
auto str = testing::internal::GetCapturedStderr();
- ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- error name ----------------------------------- error-unit-test\x1B[0m\nin file: \x1B[34;1mmyfile.nix (40:13)\x1B[0m\n\nerror with code lines\n\n 39| previous line of code\n 40| this is the problem line of code\n | \x1B[31;1m^\x1B[0m\n 41| next line of code\n\nthis hint has \x1B[33;1myellow\x1B[0m templated \x1B[33;1mvalues\x1B[0m!!\n");
+ ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- error name --- error-unit-test\x1B[0m\nin file: \x1B[34;1mmyfile.nix (40:13)\x1B[0m\n\nerror with code lines\n\n 39| previous line of code\n 40| this is the problem line of code\n | \x1B[31;1m^\x1B[0m\n 41| next line of code\n\nthis hint has \x1B[33;1myellow\x1B[0m templated \x1B[33;1mvalues\x1B[0m!!\n");
}
TEST(logError, logErrorWithoutLinesOfCode) {
@@ -190,7 +190,7 @@ namespace nix {
}});
auto str = testing::internal::GetCapturedStderr();
- ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- error name ----------------------------------- error-unit-test\x1B[0m\nin file: \x1B[34;1mmyfile.nix (40:13)\x1B[0m\n\nerror without any code lines.\n\nthis hint has \x1B[33;1myellow\x1B[0m templated \x1B[33;1mvalues\x1B[0m!!\n");
+ ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- error name --- error-unit-test\x1B[0m\nin file: \x1B[34;1mmyfile.nix (40:13)\x1B[0m\n\nerror without any code lines.\n\nthis hint has \x1B[33;1myellow\x1B[0m templated \x1B[33;1mvalues\x1B[0m!!\n");
}
TEST(logError, logErrorWithOnlyHintAndName) {
@@ -206,7 +206,7 @@ namespace nix {
}});
auto str = testing::internal::GetCapturedStderr();
- ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- error name ----------------------------------- error-unit-test\x1B[0m\nin file: \x1B[34;1mmyfile.nix (40:13)\x1B[0m\n\nhint \x1B[33;1monly\x1B[0m\n");
+ ASSERT_STREQ(str.c_str(), "\x1B[31;1merror:\x1B[0m\x1B[34;1m --- error name --- error-unit-test\x1B[0m\nin file: \x1B[34;1mmyfile.nix (40:13)\x1B[0m\n\nhint \x1B[33;1monly\x1B[0m\n");
}
@@ -224,7 +224,7 @@ namespace nix {
});
auto str = testing::internal::GetCapturedStderr();
- ASSERT_STREQ(str.c_str(), "\x1B[33;1mwarning:\x1B[0m\x1B[34;1m --- name --------------------------------------- error-unit-test\x1B[0m\nerror description\n\nthere was a \x1B[33;1mwarning\x1B[0m\n");
+ ASSERT_STREQ(str.c_str(), "\x1B[33;1mwarning:\x1B[0m\x1B[34;1m --- name --- error-unit-test\x1B[0m\nerror description\n\nthere was a \x1B[33;1mwarning\x1B[0m\n");
}
TEST(logWarning, logWarningWithFileLineNumAndCode) {
@@ -249,7 +249,7 @@ namespace nix {
auto str = testing::internal::GetCapturedStderr();
- ASSERT_STREQ(str.c_str(), "\x1B[33;1mwarning:\x1B[0m\x1B[34;1m --- warning name ------------------------------- error-unit-test\x1B[0m\nin file: \x1B[34;1mmyfile.nix (40:13)\x1B[0m\n\nwarning description\n\n 40| this is the problem line of code\n | \x1B[31;1m^\x1B[0m\n\nthis hint has \x1B[33;1myellow\x1B[0m templated \x1B[33;1mvalues\x1B[0m!!\n");
+ ASSERT_STREQ(str.c_str(), "\x1B[33;1mwarning:\x1B[0m\x1B[34;1m --- warning name --- error-unit-test\x1B[0m\nin file: \x1B[34;1mmyfile.nix (40:13)\x1B[0m\n\nwarning description\n\n 40| this is the problem line of code\n | \x1B[31;1m^\x1B[0m\n\nthis hint has \x1B[33;1myellow\x1B[0m templated \x1B[33;1mvalues\x1B[0m!!\n");
}
}
diff --git a/src/libutil/tests/pool.cc b/src/libutil/tests/pool.cc
new file mode 100644
index 000000000..127e42dda
--- /dev/null
+++ b/src/libutil/tests/pool.cc
@@ -0,0 +1,127 @@
+#include "pool.hh"
+#include <gtest/gtest.h>
+
+namespace nix {
+
+ struct TestResource
+ {
+
+ TestResource() {
+ static int counter = 0;
+ num = counter++;
+ }
+
+ int dummyValue = 1;
+ bool good = true;
+ int num;
+ };
+
+ /* ----------------------------------------------------------------------------
+ * Pool
+ * --------------------------------------------------------------------------*/
+
+ TEST(Pool, freshPoolHasZeroCountAndSpecifiedCapacity) {
+ auto isGood = [](const ref<TestResource> & r) { return r->good; };
+ auto createResource = []() { return make_ref<TestResource>(); };
+
+ Pool<TestResource> pool = Pool<TestResource>((size_t)1, createResource, isGood);
+
+ ASSERT_EQ(pool.count(), 0);
+ ASSERT_EQ(pool.capacity(), 1);
+ }
+
+ TEST(Pool, freshPoolCanGetAResource) {
+ auto isGood = [](const ref<TestResource> & r) { return r->good; };
+ auto createResource = []() { return make_ref<TestResource>(); };
+
+ Pool<TestResource> pool = Pool<TestResource>((size_t)1, createResource, isGood);
+ ASSERT_EQ(pool.count(), 0);
+
+ TestResource r = *(pool.get());
+
+ ASSERT_EQ(pool.count(), 1);
+ ASSERT_EQ(pool.capacity(), 1);
+ ASSERT_EQ(r.dummyValue, 1);
+ ASSERT_EQ(r.good, true);
+ }
+
+ TEST(Pool, capacityCanBeIncremented) {
+ auto isGood = [](const ref<TestResource> & r) { return r->good; };
+ auto createResource = []() { return make_ref<TestResource>(); };
+
+ Pool<TestResource> pool = Pool<TestResource>((size_t)1, createResource, isGood);
+ ASSERT_EQ(pool.capacity(), 1);
+ pool.incCapacity();
+ ASSERT_EQ(pool.capacity(), 2);
+ }
+
+ TEST(Pool, capacityCanBeDecremented) {
+ auto isGood = [](const ref<TestResource> & r) { return r->good; };
+ auto createResource = []() { return make_ref<TestResource>(); };
+
+ Pool<TestResource> pool = Pool<TestResource>((size_t)1, createResource, isGood);
+ ASSERT_EQ(pool.capacity(), 1);
+ pool.decCapacity();
+ ASSERT_EQ(pool.capacity(), 0);
+ }
+
+ TEST(Pool, flushBadDropsOutOfScopeResources) {
+ auto isGood = [](const ref<TestResource> & r) { return false; };
+ auto createResource = []() { return make_ref<TestResource>(); };
+
+ Pool<TestResource> pool = Pool<TestResource>((size_t)1, createResource, isGood);
+
+ {
+ auto _r = pool.get();
+ ASSERT_EQ(pool.count(), 1);
+ }
+
+ pool.flushBad();
+ ASSERT_EQ(pool.count(), 0);
+ }
+
+ // Test that the resources we allocate are being reused when they are still good.
+ TEST(Pool, reuseResource) {
+ auto isGood = [](const ref<TestResource> & r) { return true; };
+ auto createResource = []() { return make_ref<TestResource>(); };
+
+ Pool<TestResource> pool = Pool<TestResource>((size_t)1, createResource, isGood);
+
+ // Compare the instance counter between the two handles. We expect them to be equal
+ // as the pool should hand out the same (still) good one again.
+ int counter = -1;
+ {
+ Pool<TestResource>::Handle h = pool.get();
+ counter = h->num;
+ } // the first handle goes out of scope
+
+ { // the second handle should contain the same resource (with the same counter value)
+ Pool<TestResource>::Handle h = pool.get();
+ ASSERT_EQ(h->num, counter);
+ }
+ }
+
+ // Test that the resources we allocate are being thrown away when they are no longer good.
+ TEST(Pool, badResourceIsNotReused) {
+ auto isGood = [](const ref<TestResource> & r) { return false; };
+ auto createResource = []() { return make_ref<TestResource>(); };
+
+ Pool<TestResource> pool = Pool<TestResource>((size_t)1, createResource, isGood);
+
+ // Compare the instance counter between the two handles. We expect them
+ // to *not* be equal as the pool should hand out a new instance after
+ // the first one was returned.
+ int counter = -1;
+ {
+ Pool<TestResource>::Handle h = pool.get();
+ counter = h->num;
+ } // the first handle goes out of scope
+
+ {
+ // the second handle should contain a different resource (with a
+ //different counter value)
+ Pool<TestResource>::Handle h = pool.get();
+ ASSERT_NE(h->num, counter);
+ }
+ }
+}
diff --git a/src/libutil/types.hh b/src/libutil/types.hh
index 89ae108f9..3af485fa0 100644
--- a/src/libutil/types.hh
+++ b/src/libutil/types.hh
@@ -1,6 +1,5 @@
#pragma once
-
#include "ref.hh"
#include <list>
@@ -25,7 +24,6 @@ typedef string Path;
typedef list<Path> Paths;
typedef set<Path> PathSet;
-
/* Helper class to run code at startup. */
template<typename T>
struct OnStartup
@@ -33,5 +31,4 @@ struct OnStartup
OnStartup(T && t) { t(); }
};
-
}
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index dcf89ff69..1268b146a 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -35,7 +35,7 @@
#endif
-extern char * * environ;
+extern char * * environ __attribute__((weak));
namespace nix {
@@ -314,7 +314,7 @@ string readFile(const Path & path)
void readFile(const Path & path, Sink & sink)
{
AutoCloseFD fd = open(path.c_str(), O_RDONLY | O_CLOEXEC);
- if (!fd)
+ if (!fd)
throw SysError("opening file '%s'", path);
drainFD(fd.get(), sink);
}
@@ -972,7 +972,7 @@ pid_t startProcess(std::function<void()> fun, const ProcessOptions & options)
{
auto wrapper = [&]() {
if (!options.allowVfork)
- logger = makeDefaultLogger();
+ logger = makeSimpleLogger();
try {
#if __linux__
if (options.dieWithParent && prctl(PR_SET_PDEATHSIG, SIGKILL) == -1)
@@ -1199,7 +1199,7 @@ void _interrupted()
/* Block user interrupts while an exception is being handled.
Throwing an exception while another exception is being handled
kills the program! */
- if (!interruptThrown && !std::uncaught_exception()) {
+ if (!interruptThrown && !std::uncaught_exceptions()) {
interruptThrown = true;
throw Interrupted("interrupted by the user");
}
@@ -1297,7 +1297,7 @@ bool statusOk(int status)
}
-bool hasPrefix(const string & s, const string & prefix)
+bool hasPrefix(std::string_view s, std::string_view prefix)
{
return s.compare(0, prefix.size(), prefix) == 0;
}
@@ -1391,7 +1391,7 @@ std::string filterANSIEscapes(const std::string & s, bool filterAll, unsigned in
static char base64Chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-string base64Encode(const string & s)
+string base64Encode(std::string_view s)
{
string res;
int data = 0, nbits = 0;
@@ -1412,7 +1412,7 @@ string base64Encode(const string & s)
}
-string base64Decode(const string & s)
+string base64Decode(std::string_view s)
{
bool init = false;
char decode[256];
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index 30b647a6a..3641daaec 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -417,7 +417,7 @@ template<class N> bool string2Float(const string & s, N & n)
/* Return true iff `s' starts with `prefix'. */
-bool hasPrefix(const string & s, const string & prefix);
+bool hasPrefix(std::string_view s, std::string_view prefix);
/* Return true iff `s' ends in `suffix'. */
@@ -456,12 +456,11 @@ std::string filterANSIEscapes(const std::string & s,
/* Base64 encoding/decoding. */
-string base64Encode(const string & s);
-string base64Decode(const string & s);
+string base64Encode(std::string_view s);
+string base64Decode(std::string_view s);
-/* Get a value for the specified key from an associate container, or a
- default value if the key doesn't exist. */
+/* Get a value for the specified key from an associate container. */
template <class T>
std::optional<typename T::mapped_type> get(const T & map, const typename T::key_type & key)
{