aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--meson.build7
-rw-r--r--src/build-remote/build-remote.cc47
-rw-r--r--src/libcmd/meson.build14
-rw-r--r--src/libexpr/flake/meson.build8
-rw-r--r--src/libexpr/meson.build37
-rw-r--r--src/libexpr/print.cc2
-rw-r--r--src/libexpr/print.hh2
-rw-r--r--src/libmain/meson.build14
-rw-r--r--src/libstore/local-store.cc9
-rw-r--r--src/libstore/meson.build30
-rw-r--r--src/libutil/fmt.hh177
-rw-r--r--src/libutil/logging.hh4
-rw-r--r--src/libutil/meson.build1
-rw-r--r--tests/functional/meson.build3
-rw-r--r--tests/unit/libutil/fmt.cc23
15 files changed, 243 insertions, 135 deletions
diff --git a/meson.build b/meson.build
index 556712c34..a4c2bbc14 100644
--- a/meson.build
+++ b/meson.build
@@ -244,13 +244,12 @@ bison = find_program('bison')
flex = find_program('flex')
# This is how Nix does generated headers...
+# other instances of header generation use a very similar command.
# FIXME(Qyriad): do we really need to use the shell for this?
+gen_header_sh = 'echo \'R"__NIX_STR(\' | cat - @INPUT@ && echo \')__NIX_STR"\''
gen_header = generator(
bash,
- arguments : [
- '-c',
- 'echo \'R"__NIX_STR(\' | cat - @INPUT@ && echo \')__NIX_STR"\'',
- ],
+ arguments : [ '-c', gen_header_sh ],
capture : true,
output : '@PLAINNAME@.gen.hh',
)
diff --git a/src/build-remote/build-remote.cc b/src/build-remote/build-remote.cc
index e2ada70cd..f7a159829 100644
--- a/src/build-remote/build-remote.cc
+++ b/src/build-remote/build-remote.cc
@@ -185,16 +185,6 @@ static int main_build_remote(int argc, char * * argv)
std::cerr << "# postpone\n";
else
{
- // build the hint template.
- std::string errorText =
- "Failed to find a machine for remote build!\n"
- "derivation: %s\nrequired (system, features): (%s, [%s])";
- errorText += "\n%s available machines:";
- errorText += "\n(systems, maxjobs, supportedFeatures, mandatoryFeatures)";
-
- for (unsigned int i = 0; i < machines.size(); ++i)
- errorText += "\n([%s], %s, [%s], [%s])";
-
// add the template values.
std::string drvstr;
if (drvPath.has_value())
@@ -202,19 +192,30 @@ static int main_build_remote(int argc, char * * argv)
else
drvstr = "<unknown>";
- auto error = HintFmt::fromFormatString(errorText);
- error
- % drvstr
- % neededSystem
- % concatStringsSep<StringSet>(", ", requiredFeatures)
- % machines.size();
-
- for (auto & m : machines)
- error
- % concatStringsSep<StringSet>(", ", m.systemTypes)
- % m.maxJobs
- % concatStringsSep<StringSet>(", ", m.supportedFeatures)
- % concatStringsSep<StringSet>(", ", m.mandatoryFeatures);
+ std::string machinesFormatted;
+
+ for (auto & m : machines) {
+ machinesFormatted += HintFmt(
+ "\n([%s], %s, [%s], [%s])",
+ concatStringsSep<StringSet>(", ", m.systemTypes),
+ m.maxJobs,
+ concatStringsSep<StringSet>(", ", m.supportedFeatures),
+ concatStringsSep<StringSet>(", ", m.mandatoryFeatures)
+ ).str();
+ }
+
+ auto error = HintFmt(
+ "Failed to find a machine for remote build!\n"
+ "derivation: %s\n"
+ "required (system, features): (%s, [%s])\n"
+ "%s available machines:\n"
+ "(systems, maxjobs, supportedFeatures, mandatoryFeatures)%s",
+ drvstr,
+ neededSystem,
+ concatStringsSep<StringSet>(", ", requiredFeatures),
+ machines.size(),
+ Uncolored(machinesFormatted)
+ );
printMsg(couldBuildLocally ? lvlChatty : lvlWarn, error.str());
diff --git a/src/libcmd/meson.build b/src/libcmd/meson.build
index e033bb1cd..c3782723b 100644
--- a/src/libcmd/meson.build
+++ b/src/libcmd/meson.build
@@ -56,3 +56,17 @@ liblixcmd = declare_dependency(
include_directories : '.',
link_with : libcmd,
)
+
+# FIXME: not using the pkg-config module because it creates way too many deps
+# while meson migration is in progress, and we want to not include boost here
+configure_file(
+ input : 'nix-cmd.pc.in',
+ output : 'nix-cmd.pc',
+ install_dir : libdir / 'pkgconfig',
+ configuration : {
+ 'prefix' : prefix,
+ 'libdir' : libdir,
+ 'includedir' : includedir,
+ 'PACKAGE_VERSION' : meson.project_version(),
+ },
+)
diff --git a/src/libexpr/flake/meson.build b/src/libexpr/flake/meson.build
new file mode 100644
index 000000000..3ecc30f4e
--- /dev/null
+++ b/src/libexpr/flake/meson.build
@@ -0,0 +1,8 @@
+libexpr_generated_headers += custom_target(
+ command : [ 'bash', '-c', 'echo \'R"__NIX_STR(\' | cat - @INPUT@ && echo \')__NIX_STR"\'' ],
+ input : 'call-flake.nix',
+ output : '@PLAINNAME@.gen.hh',
+ capture : true,
+ install : true,
+ install_dir : includedir / 'nix/flake',
+)
diff --git a/src/libexpr/meson.build b/src/libexpr/meson.build
index 2e810f4c9..7c0555f8f 100644
--- a/src/libexpr/meson.build
+++ b/src/libexpr/meson.build
@@ -49,10 +49,20 @@ meson.add_install_script(
'@0@'.format(includedir),
)
-imported_drv_to_derivation_gen = gen_header.process('imported-drv-to-derivation.nix')
-fetchurl_gen = gen_header.process('fetchurl.nix')
-derivation_gen = gen_header.process('primops/derivation.nix', preserve_path_from : meson.current_source_dir())
-call_flake_gen = gen_header.process('flake/call-flake.nix')
+libexpr_generated_headers = [
+ gen_header.process('primops/derivation.nix', preserve_path_from : meson.current_source_dir()),
+]
+foreach header : [ 'imported-drv-to-derivation.nix', 'fetchurl.nix' ]
+ libexpr_generated_headers += custom_target(
+ command : [ 'bash', '-c', 'echo \'R"__NIX_STR(\' | cat - @INPUT@ && echo \')__NIX_STR"\'' ],
+ input : header,
+ output : '@PLAINNAME@.gen.hh',
+ capture : true,
+ install : true,
+ install_dir : includedir / 'nix',
+ )
+endforeach
+subdir('flake')
libexpr_sources = files(
'attr-path.cc',
@@ -121,10 +131,7 @@ libexpr = library(
libexpr_sources,
parser_tab,
lexer_tab,
- imported_drv_to_derivation_gen,
- fetchurl_gen,
- derivation_gen,
- call_flake_gen,
+ libexpr_generated_headers,
dependencies : [
liblixutil,
liblixstore,
@@ -152,3 +159,17 @@ liblixexpr = declare_dependency(
include_directories : include_directories('.'),
link_with : libexpr,
)
+
+# FIXME: not using the pkg-config module because it creates way too many deps
+# while meson migration is in progress, and we want to not include boost here
+configure_file(
+ input : 'nix-expr.pc.in',
+ output : 'nix-expr.pc',
+ install_dir : libdir / 'pkgconfig',
+ configuration : {
+ 'prefix' : prefix,
+ 'libdir' : libdir,
+ 'includedir' : includedir,
+ 'PACKAGE_VERSION' : meson.project_version(),
+ },
+)
diff --git a/src/libexpr/print.cc b/src/libexpr/print.cc
index 19ef6f8aa..43e366d08 100644
--- a/src/libexpr/print.cc
+++ b/src/libexpr/print.cc
@@ -608,7 +608,7 @@ std::ostream & operator<<(std::ostream & output, const ValuePrinter & printer)
}
template<>
-HintFmt & HintFmt::operator%(const ValuePrinter & value)
+fmt_internal::HintFmt & fmt_internal::HintFmt::operator%(const ValuePrinter & value)
{
fmt % value;
return *this;
diff --git a/src/libexpr/print.hh b/src/libexpr/print.hh
index 7ddda81b8..94cb11ca7 100644
--- a/src/libexpr/print.hh
+++ b/src/libexpr/print.hh
@@ -86,6 +86,6 @@ std::ostream & operator<<(std::ostream & output, const ValuePrinter & printer);
* magenta.
*/
template<>
-HintFmt & HintFmt::operator%(const ValuePrinter & value);
+fmt_internal::HintFmt & fmt_internal::HintFmt::operator%(const ValuePrinter & value);
}
diff --git a/src/libmain/meson.build b/src/libmain/meson.build
index 54326c305..3f50b158d 100644
--- a/src/libmain/meson.build
+++ b/src/libmain/meson.build
@@ -31,3 +31,17 @@ liblixmain = declare_dependency(
include_directories : include_directories('.'),
link_with : libmain,
)
+
+# FIXME: not using the pkg-config module because it creates way too many deps
+# while meson migration is in progress, and we want to not include boost here
+configure_file(
+ input : 'nix-main.pc.in',
+ output : 'nix-main.pc',
+ install_dir : libdir / 'pkgconfig',
+ configuration : {
+ 'prefix' : prefix,
+ 'libdir' : libdir,
+ 'includedir' : includedir,
+ 'PACKAGE_VERSION' : meson.project_version(),
+ },
+)
diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc
index 29081244f..db3934d5e 100644
--- a/src/libstore/local-store.cc
+++ b/src/libstore/local-store.cc
@@ -548,6 +548,15 @@ void LocalStore::openDB(State & state, bool create)
sqlite3_exec(db, ("pragma main.journal_mode = " + mode + ";").c_str(), 0, 0, 0) != SQLITE_OK)
SQLiteError::throw_(db, "setting journal mode");
+ if (mode == "wal" ) {
+ /* persist the WAL files when the DB connection is closed.
+ * This allows for read-only connections without any write permissions
+ * on the state directory to succeed on a closed database. */
+ int enable = 1;
+ if (sqlite3_file_control(db, NULL, SQLITE_FCNTL_PERSIST_WAL, &enable) != SQLITE_OK)
+ SQLiteError::throw_(db, "setting persistent WAL mode");
+ }
+
/* Increase the auto-checkpoint interval to 40000 pages. This
seems enough to ensure that instantiating the NixOS system
derivation is done in a single fsync(). */
diff --git a/src/libstore/meson.build b/src/libstore/meson.build
index 33e475f70..29dbc5e70 100644
--- a/src/libstore/meson.build
+++ b/src/libstore/meson.build
@@ -1,5 +1,14 @@
-schema_sql_gen = gen_header.process('schema.sql')
-ca_specific_schema_gen = gen_header.process('ca-specific-schema.sql')
+libstore_generated_headers = []
+foreach header : [ 'schema.sql', 'ca-specific-schema.sql' ]
+ libstore_generated_headers += custom_target(
+ command : [ 'bash', '-c', 'echo \'R"__NIX_STR(\' | cat - @INPUT@ && echo \')__NIX_STR"\'' ],
+ input : header,
+ output : '@PLAINNAME@.gen.hh',
+ capture : true,
+ install : true,
+ install_dir : includedir / 'nix',
+ )
+endforeach
libstore_sources = files(
'binary-cache-store.cc',
@@ -157,8 +166,7 @@ endforeach
libstore = library(
'nixstore',
- schema_sql_gen,
- ca_specific_schema_gen,
+ libstore_generated_headers,
libstore_sources,
dependencies : [
libarchive,
@@ -186,3 +194,17 @@ liblixstore = declare_dependency(
include_directories : include_directories('.'),
link_with : libstore,
)
+
+# FIXME: not using the pkg-config module because it creates way too many deps
+# while meson migration is in progress, and we want to not include boost here
+configure_file(
+ input : 'nix-store.pc.in',
+ output : 'nix-store.pc',
+ install_dir : libdir / 'pkgconfig',
+ configuration : {
+ 'prefix' : prefix,
+ 'libdir' : libdir,
+ 'includedir' : includedir,
+ 'PACKAGE_VERSION' : meson.project_version(),
+ },
+)
diff --git a/src/libutil/fmt.hh b/src/libutil/fmt.hh
index 84a3e3e11..c68591b72 100644
--- a/src/libutil/fmt.hh
+++ b/src/libutil/fmt.hh
@@ -5,43 +5,94 @@
#include <string>
#include "ansicolor.hh"
-
namespace nix {
-namespace {
/**
- * A helper for writing `boost::format` expressions.
- *
- * These are equivalent:
+ * Values wrapped in this struct are printed in magenta.
*
- * ```
- * formatHelper(formatter, a_0, ..., a_n)
- * formatter % a_0 % ... % a_n
- * ```
+ * By default, arguments to `HintFmt` are printed in magenta. To avoid this,
+ * either wrap the argument in `Uncolored` or add a specialization of
+ * `HintFmt::operator%`.
+ */
+template<class T>
+struct Magenta
+{
+ Magenta(const T & s) : value(s) {}
+ const T & value;
+};
+
+template<class T>
+std::ostream & operator<<(std::ostream & out, const Magenta<T> & y)
+{
+ return out << ANSI_MAGENTA << y.value << ANSI_NORMAL;
+}
+
+/**
+ * Values wrapped in this class are printed without coloring.
*
- * With a single argument, `formatHelper(s)` is a no-op.
+ * By default, arguments to `HintFmt` are printed in magenta (see `Magenta`).
*/
-template<class F>
-inline void formatHelper(F & f)
-{ }
+template<class T>
+struct Uncolored
+{
+ Uncolored(const T & s) : value(s) {}
+ const T & value;
+};
-template<class F, typename T, typename... Args>
-inline void formatHelper(F & f, const T & x, const Args & ... args)
+template<class T>
+std::ostream & operator<<(std::ostream & out, const Uncolored<T> & y)
{
- // Interpolate one argument and then recurse.
- formatHelper(f % x, args...);
+ return out << ANSI_NORMAL << y.value;
}
+namespace fmt_internal {
+
/**
* Set the correct exceptions for `fmt`.
*/
-void setExceptions(boost::format & fmt)
+inline void setExceptions(boost::format & fmt)
{
fmt.exceptions(
- boost::io::all_error_bits ^
- boost::io::too_many_args_bit ^
- boost::io::too_few_args_bit);
+ boost::io::all_error_bits ^ boost::io::too_many_args_bit ^ boost::io::too_few_args_bit
+ );
}
+
+/**
+ * Helper class for `HintFmt` that supports the evil `operator%`.
+ *
+ * See: https://git.lix.systems/lix-project/lix/issues/178
+ */
+struct HintFmt
+{
+ boost::format fmt;
+
+ template<typename... Args>
+ HintFmt(boost::format && fmt, const Args &... args) : fmt(std::move(fmt))
+ {
+ setExceptions(fmt);
+ (*this % ... % args);
+ }
+
+ template<class T>
+ HintFmt & operator%(const T & value)
+ {
+ fmt % Magenta(value);
+ return *this;
+ }
+
+ template<class T>
+ HintFmt & operator%(const Uncolored<T> & value)
+ {
+ fmt % value.value;
+ return *this;
+ }
+
+ boost::format into_format()
+ {
+ return std::move(fmt);
+ }
+};
+
}
/**
@@ -77,53 +128,15 @@ inline std::string fmt(const char * s)
}
template<typename... Args>
-inline std::string fmt(const std::string & fs, const Args & ... args)
+inline std::string fmt(const std::string & fs, const Args &... args)
{
boost::format f(fs);
- setExceptions(f);
- formatHelper(f, args...);
+ fmt_internal::setExceptions(f);
+ (f % ... % args);
return f.str();
}
/**
- * Values wrapped in this struct are printed in magenta.
- *
- * By default, arguments to `HintFmt` are printed in magenta. To avoid this,
- * either wrap the argument in `Uncolored` or add a specialization of
- * `HintFmt::operator%`.
- */
-template <class T>
-struct Magenta
-{
- Magenta(const T &s) : value(s) {}
- const T & value;
-};
-
-template <class T>
-std::ostream & operator<<(std::ostream & out, const Magenta<T> & y)
-{
- return out << ANSI_WARNING << y.value << ANSI_NORMAL;
-}
-
-/**
- * Values wrapped in this class are printed without coloring.
- *
- * By default, arguments to `HintFmt` are printed in magenta (see `Magenta`).
- */
-template <class T>
-struct Uncolored
-{
- Uncolored(const T & s) : value(s) {}
- const T & value;
-};
-
-template <class T>
-std::ostream & operator<<(std::ostream & out, const Uncolored<T> & y)
-{
- return out << ANSI_NORMAL << y.value;
-}
-
-/**
* A wrapper around `boost::format` which colors interpolated arguments in
* magenta by default.
*/
@@ -137,46 +150,28 @@ public:
* Format the given string literally, without interpolating format
* placeholders.
*/
- HintFmt(const std::string & literal)
- : HintFmt("%s", Uncolored(literal))
- { }
-
- static HintFmt fromFormatString(const std::string & format) {
- return HintFmt(boost::format(format));
- }
+ HintFmt(const std::string & literal) : HintFmt("%s", Uncolored(literal)) {}
/**
* Interpolate the given arguments into the format string.
*/
template<typename... Args>
- HintFmt(const std::string & format, const Args & ... args)
+ HintFmt(const std::string & format, const Args &... args)
: HintFmt(boost::format(format), args...)
- { }
-
- HintFmt(const HintFmt & hf)
- : fmt(hf.fmt)
- { }
-
- template<typename... Args>
- HintFmt(boost::format && fmt, const Args & ... args)
- : fmt(std::move(fmt))
{
- setExceptions(fmt);
- formatHelper(*this, args...);
}
- template<class T>
- HintFmt & operator%(const T & value)
- {
- fmt % Magenta(value);
- return *this;
- }
+ HintFmt(const HintFmt & hf) : fmt(hf.fmt) {}
- template<class T>
- HintFmt & operator%(const Uncolored<T> & value)
+ template<typename... Args>
+ HintFmt(boost::format && fmt, const Args &... args)
+ : fmt(fmt_internal::HintFmt(std::move(fmt), args...).into_format())
{
- fmt % value.value;
- return *this;
+ if (this->fmt.remaining_args() != 0) {
+ throw boost::io::too_few_args(
+ this->fmt.bound_args() + this->fmt.fed_args(), this->fmt.expected_args()
+ );
+ }
}
std::string str() const
diff --git a/src/libutil/logging.hh b/src/libutil/logging.hh
index dc6f53d77..7b7f69833 100644
--- a/src/libutil/logging.hh
+++ b/src/libutil/logging.hh
@@ -230,9 +230,7 @@ extern Verbosity verbosity;
template<typename... Args>
inline void warn(const std::string & fs, const Args & ... args)
{
- boost::format f(fs);
- formatHelper(f, args...);
- logger->warn(f.str());
+ logger->warn(HintFmt(fs, args...).str());
}
#define warnOnce(haveWarned, args...) \
diff --git a/src/libutil/meson.build b/src/libutil/meson.build
index cdfda3cf5..c37e7ae68 100644
--- a/src/libutil/meson.build
+++ b/src/libutil/meson.build
@@ -36,6 +36,7 @@ libutil_headers = files(
'abstract-setting-to-json.hh',
'ansicolor.hh',
'archive.hh',
+ 'args/root.hh',
'args.hh',
'box_ptr.hh',
'callback.hh',
diff --git a/tests/functional/meson.build b/tests/functional/meson.build
index 53dc21af5..0ea0e4df5 100644
--- a/tests/functional/meson.build
+++ b/tests/functional/meson.build
@@ -176,5 +176,8 @@ foreach script : functional_tests_scripts
env : {
'MESON_BUILD_ROOT': meson.project_build_root(),
},
+ # some tests take 15+ seconds even on an otherwise idle machine, on a loaded machine
+ # this can easily drive them to failure. give them more time, 5min rather than 30sec
+ timeout : 300,
)
endforeach
diff --git a/tests/unit/libutil/fmt.cc b/tests/unit/libutil/fmt.cc
new file mode 100644
index 000000000..383a688d3
--- /dev/null
+++ b/tests/unit/libutil/fmt.cc
@@ -0,0 +1,23 @@
+#include "fmt.hh"
+#include "ansicolor.hh"
+
+#include <gtest/gtest.h>
+
+namespace nix {
+
+TEST(HintFmt, arg_count)
+{
+ // Single arg is treated as a literal string.
+ ASSERT_EQ(HintFmt("%s").str(), "%s");
+
+ // Other strings format as expected:
+ ASSERT_EQ(HintFmt("%s", 1).str(), ANSI_MAGENTA "1" ANSI_NORMAL);
+ ASSERT_EQ(HintFmt("%1%", "hello").str(), ANSI_MAGENTA "hello" ANSI_NORMAL);
+
+ // Argument counts are detected at construction.
+ ASSERT_THROW(HintFmt("%s %s", 1), boost::io::too_few_args);
+
+ ASSERT_THROW(HintFmt("%s", 1, 2), boost::io::too_many_args);
+}
+
+}