From 3af52f845fe2ceb448416ac7b9f48925673c594e Mon Sep 17 00:00:00 2001 From: Congcong Kuo Date: Mon, 21 Jul 2025 11:02:40 +0800 Subject: [PATCH] =?UTF-8?q?daemon:=20Bump=20to=20C++20=20and=20use=20?= =?UTF-8?q?=E2=80=98std::format=E2=80=99=20instead=20of=20=E2=80=98boost::?= =?UTF-8?q?format=E2=80=99.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * nix/boost: This directory and all files inside it are removed. * nix/libstore/build.cc (Goal::trace): Use ‘std::string’ instead of ‘const format &’. (DerivationGoal::startBuilder, ...): Use ‘std::format’ or ‘std::vformat’ instead of ‘boost::format’. * nix/libstore/builtins.cc (builtinDownload): Same. * nix/libstore/derivations.cc (DerivationOutput::parseHashInfo, ...): Same. * nix/libstore/gc.cc (LocalStore::openGCLock, ...): Same. * nix/libstore/globals.cc (Settings::_get): Same. * nix/libstore/local-store.cc: (checkStoreNotSymlink, ...): Same. * nix/libstore/misc.cc (dfsVisit, showBytes): Same * nix/libstore/optimise-store.cc (makeWritable, ...): Same. * nix/libstore/pathlocks.cc (openLockFile, ...): Same. * nix/libstore/references.cc (search, scanForReferences): Same. * nix/libstore/sqlite.hh (throwSQLiteError): Use ‘std::string’ instead of ‘const format &’. * nix/libstore/sqlite.cc (throwSQLiteError): Use ‘std::string’ instead of ‘const format &’. * nix/libstore/store-api.cc (assertStorePath, ...): Use ‘std::format’ instead of ‘boost::format’. * nix/libutil/affinity.cc (setAffinityTo): Same. * nix/libutil/archive.cc (dumpContents, ...): Same. * nix/libutil/hash.cc (parseHash, parseHash32, parseHash16or32, hashFile): Same. * nix/libutil/hash.hh (parseHash, parseHash32, parseHash16or32, isHash): Same. * nix/libutil/serialise.cc : Add ‘’ header file. * nix/libutil/spawn.cc (addPhaseAfter, ...): Use ‘std::format’ instead of ‘boost::format’. * nix/libutil/types.hh (FormatOrString): Removed. (BaseError, BaseError::addPrefix, SysError, MakeError): Use ‘std::string or std::string_view’ instead of ‘FormatOrString’. * nix/libutil/util.hh (Nest::open, printMsg_, warnOnce, expect): Same. * nix/libutil/util.cc (BaseError::BaseError, ...): Same. (writeToStderr, _interrupted): Use std::uncaught_exceptions() instead of std::uncaught_exception() * nix/nix-daemon/nix-daemon.cc (performOp, ...): Same. * nix/nix-daemon/guix-daemon.cc (string_to_bool, ...): Same. * nix/local.mk: Remove ‘libformat.a’ from ‘noinst_LIBRARIES’, remove ‘libformat_a_SOURCES’ and ‘libformat_headers’, remove ‘libformat_a_CPPFLAGS’ from ‘libutil_a_CPPFLAGS’ and ‘guix_daemon_LDADD’, update ‘AM_CXXFLAGS’ to ‘-std=c++20’. Signed-off-by: Ludovic Courtès --- nix/boost/assert.hpp | 38 -- nix/boost/format.hpp | 64 -- nix/boost/format/exceptions.hpp | 96 --- nix/boost/format/feed_args.hpp | 247 -------- nix/boost/format/format_class.hpp | 135 ----- nix/boost/format/format_fwd.hpp | 49 -- nix/boost/format/format_implementation.cc | 256 -------- nix/boost/format/free_funcs.cc | 71 --- nix/boost/format/group.hpp | 680 ---------------------- nix/boost/format/internals.hpp | 167 ------ nix/boost/format/internals_fwd.hpp | 65 --- nix/boost/format/macros_default.hpp | 48 -- nix/boost/format/parsing.cc | 454 --------------- nix/boost/throw_exception.hpp | 47 -- nix/libstore/build.cc | 433 +++++++------- nix/libstore/builtins.cc | 3 +- nix/libstore/builtins.hh | 1 - nix/libstore/derivations.cc | 9 +- nix/libstore/gc.cc | 139 +++-- nix/libstore/globals.cc | 8 +- nix/libstore/local-store.cc | 162 +++--- nix/libstore/misc.cc | 17 +- nix/libstore/optimise-store.cc | 61 +- nix/libstore/pathlocks.cc | 20 +- nix/libstore/references.cc | 8 +- nix/libstore/sqlite.cc | 9 +- nix/libstore/sqlite.hh | 3 +- nix/libstore/store-api.cc | 15 +- nix/libutil/affinity.cc | 6 +- nix/libutil/archive.cc | 15 +- nix/libutil/hash.cc | 27 +- nix/libutil/hash.hh | 8 +- nix/libutil/serialise.cc | 2 +- nix/libutil/spawn.cc | 59 +- nix/libutil/types.hh | 21 +- nix/libutil/util.cc | 162 +++--- nix/libutil/util.hh | 11 +- nix/local.mk | 34 +- nix/nix-daemon/guix-daemon.cc | 47 +- nix/nix-daemon/nix-daemon.cc | 25 +- 40 files changed, 645 insertions(+), 3077 deletions(-) delete mode 100644 nix/boost/assert.hpp delete mode 100644 nix/boost/format.hpp delete mode 100644 nix/boost/format/exceptions.hpp delete mode 100644 nix/boost/format/feed_args.hpp delete mode 100644 nix/boost/format/format_class.hpp delete mode 100644 nix/boost/format/format_fwd.hpp delete mode 100644 nix/boost/format/format_implementation.cc delete mode 100644 nix/boost/format/free_funcs.cc delete mode 100644 nix/boost/format/group.hpp delete mode 100644 nix/boost/format/internals.hpp delete mode 100644 nix/boost/format/internals_fwd.hpp delete mode 100644 nix/boost/format/macros_default.hpp delete mode 100644 nix/boost/format/parsing.cc delete mode 100644 nix/boost/throw_exception.hpp diff --git a/nix/boost/assert.hpp b/nix/boost/assert.hpp deleted file mode 100644 index 754ebb954bce0b0e7474681f38d871d74eb18323..0000000000000000000000000000000000000000 --- a/nix/boost/assert.hpp +++ /dev/null @@ -1,38 +0,0 @@ -// -// boost/assert.hpp - BOOST_ASSERT(expr) -// -// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -// Note: There are no include guards. This is intentional. -// -// See http://www.boost.org/libs/utility/assert.html for documentation. -// - -#undef BOOST_ASSERT - -#if defined(BOOST_DISABLE_ASSERTS) - -# define BOOST_ASSERT(expr) ((void)0) - -#elif defined(BOOST_ENABLE_ASSERT_HANDLER) - -#include - -namespace boost -{ - -void assertion_failed(char const * expr, char const * function, char const * file, long line); // user defined - -} // namespace boost - -#define BOOST_ASSERT(expr) ((expr)? ((void)0): ::boost::assertion_failed(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__)) - -#else -# include -# define BOOST_ASSERT(expr) assert(expr) -#endif diff --git a/nix/boost/format.hpp b/nix/boost/format.hpp deleted file mode 100644 index f965f0f33e9a0713563313efda9eafcc1983d96c..0000000000000000000000000000000000000000 --- a/nix/boost/format.hpp +++ /dev/null @@ -1,64 +0,0 @@ -// -*- C++ -*- -// Boost general library 'format' --------------------------- -// See http://www.boost.org for updates, documentation, and revision history. - -// (C) Samuel Krempp 2001 -// krempp@crans.ens-cachan.fr -// Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. - -// ideas taken from Rüdiger Loos's format class -// and Karl Nelson's ofstream - -// ---------------------------------------------------------------------------- -// format.hpp : primary header -// ---------------------------------------------------------------------------- - -#ifndef BOOST_FORMAT_HPP -#define BOOST_FORMAT_HPP - -#include -#include -#include -#include - -#if HAVE_LOCALE -#include -#else -#define BOOST_NO_STD_LOCALE -#define BOOST_NO_LOCALE_ISIDIGIT -#include -#endif - -#include - - -// **** Forward declarations ---------------------------------- -#include // basic_format, and other frontends -#include // misc forward declarations for internal use - - -// **** Auxiliary structs (stream_format_state , and format_item ) -#include - -// **** Format class interface -------------------------------- -#include - -// **** Exceptions ----------------------------------------------- -#include - -// **** Implementation ------------------------------------------- -//#include // member functions - -#include // class for grouping arguments - -#include // argument-feeding functions -//#include // format-string parsing (member-)functions - -// **** Implementation of the free functions ---------------------- -//#include - - -#endif // BOOST_FORMAT_HPP diff --git a/nix/boost/format/exceptions.hpp b/nix/boost/format/exceptions.hpp deleted file mode 100644 index 80da6d57189a1d9b2881e8cb06b9f49214fd7bac..0000000000000000000000000000000000000000 --- a/nix/boost/format/exceptions.hpp +++ /dev/null @@ -1,96 +0,0 @@ -// -*- C++ -*- -// Boost general library 'format' --------------------------- -// See http://www.boost.org for updates, documentation, and revision history. - -// (C) Samuel Krempp 2001 -// krempp@crans.ens-cachan.fr -// Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. - -// ideas taken from Rüdiger Loos's format class -// and Karl Nelson's ofstream (also took its parsing code as basis for printf parsing) - -// ------------------------------------------------------------------------------ -// exceptions.hpp -// ------------------------------------------------------------------------------ - - -#ifndef BOOST_FORMAT_EXCEPTIONS_HPP -#define BOOST_FORMAT_EXCEPTIONS_HPP - - -#include - - -namespace boost { - -namespace io { - -// **** exceptions ----------------------------------------------- - -class format_error : public std::exception -{ -public: - format_error() {} - virtual const char *what() const throw() - { - return "boost::format_error: " - "format generic failure"; - } -}; - -class bad_format_string : public format_error -{ -public: - bad_format_string() {} - virtual const char *what() const throw() - { - return "boost::bad_format_string: " - "format-string is ill-formed"; - } -}; - -class too_few_args : public format_error -{ -public: - too_few_args() {} - virtual const char *what() const throw() - { - return "boost::too_few_args: " - "format-string referred to more arguments than were passed"; - } -}; - -class too_many_args : public format_error -{ -public: - too_many_args() {} - virtual const char *what() const throw() - { - return "boost::too_many_args: " - "format-string referred to less arguments than were passed"; - } -}; - - -class out_of_range : public format_error -{ -public: - out_of_range() {} - virtual const char *what() const throw() - { - return "boost::out_of_range: " - "tried to refer to an argument (or item) number which is out of range, " - "according to the format string."; - } -}; - - -} // namespace io - -} // namespace boost - - -#endif // BOOST_FORMAT_EXCEPTIONS_HPP diff --git a/nix/boost/format/feed_args.hpp b/nix/boost/format/feed_args.hpp deleted file mode 100644 index 3d0b47b4a12ee2fef0c9f23e76ab67b5e6cfede7..0000000000000000000000000000000000000000 --- a/nix/boost/format/feed_args.hpp +++ /dev/null @@ -1,247 +0,0 @@ -// -*- C++ -*- -// Boost general library 'format' --------------------------- -// See http://www.boost.org for updates, documentation, and revision history. - -// (C) Samuel Krempp 2001 -// krempp@crans.ens-cachan.fr -// Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. - -// ideas taken from Rüdiger Loos's format class -// and Karl Nelson's ofstream - -// ---------------------------------------------------------------------------- -// feed_args.hpp : functions for processing each argument -// (feed, feed_manip, and distribute) -// ---------------------------------------------------------------------------- - - -#ifndef BOOST_FORMAT_FEED_ARGS_HPP -#define BOOST_FORMAT_FEED_ARGS_HPP - -#include "boost/format/format_class.hpp" -#include "boost/format/group.hpp" - -#include "boost/throw_exception.hpp" - -namespace boost { -namespace io { -namespace detail { -namespace { - - inline - void empty_buf(BOOST_IO_STD ostringstream & os) { - static const std::string emptyStr; - os.str(emptyStr); - } - - void do_pad( std::string & s, - std::streamsize w, - const char c, - std::ios::fmtflags f, - bool center) - // applies centered / left / right padding to the string s. - // Effects : string s is padded. - { - std::streamsize n=w-s.size(); - if(n<=0) { - return; - } - if(center) - { - s.reserve(w); // allocate once for the 2 inserts - const std::streamsize n1 = n /2, n0 = n - n1; - s.insert(s.begin(), n0, c); - s.append(n1, c); - } - else - { - if(f & std::ios::left) { - s.append(n, c); - } - else { - s.insert(s.begin(), n, c); - } - } - } // -do_pad(..) - - - template inline - void put_head(BOOST_IO_STD ostream& , const T& ) { - } - - template inline - void put_head( BOOST_IO_STD ostream& os, const group1& x ) { - os << group_head(x.a1_); // send the first N-1 items, not the last - } - - template inline - void put_last( BOOST_IO_STD ostream& os, const T& x ) { - os << x ; - } - - template inline - void put_last( BOOST_IO_STD ostream& os, const group1& x ) { - os << group_last(x.a1_); // this selects the last element - } - -#ifndef BOOST_NO_OVERLOAD_FOR_NON_CONST - template inline - void put_head( BOOST_IO_STD ostream& , T& ) { - } - - template inline - void put_last( BOOST_IO_STD ostream& os, T& x ) { - os << x ; - } -#endif - - - - -template -void put( T x, - const format_item& specs, - std::string & res, - BOOST_IO_STD ostringstream& oss_ ) -{ - // does the actual conversion of x, with given params, into a string - // using the *supplied* strinstream. (the stream state is important) - - typedef std::string string_t; - typedef format_item format_item_t; - - stream_format_state prev_state(oss_); - - specs.state_.apply_on(oss_); - - // in case x is a group, apply the manip part of it, - // in order to find width - put_head( oss_, x ); - empty_buf( oss_); - - const std::streamsize w=oss_.width(); - const std::ios::fmtflags fl=oss_.flags(); - const bool internal = (fl & std::ios::internal) != 0; - const bool two_stepped_padding = internal - && ! ( specs.pad_scheme_ & format_item_t::spacepad ) - && specs.truncate_ < 0 ; - - - if(! two_stepped_padding) - { - if(w>0) // handle simple padding via do_pad, not natively in stream - oss_.width(0); - put_last( oss_, x); - res = oss_.str(); - - if (specs.truncate_ >= 0) - res.erase(specs.truncate_); - - // complex pads : - if(specs.pad_scheme_ & format_item_t::spacepad) - { - if( res.size()==0 || ( res[0]!='+' && res[0]!='-' )) - { - res.insert(res.begin(), 1, ' '); // insert 1 space at pos 0 - } - } - if(w > 0) // need do_pad - { - do_pad(res,w,oss_.fill(), fl, (specs.pad_scheme_ & format_item_t::centered) !=0 ); - } - } - else // 2-stepped padding - { - put_last( oss_, x); // oss_.width() may result in padding. - res = oss_.str(); - - if (specs.truncate_ >= 0) - res.erase(specs.truncate_); - - if( res.size() - w > 0) - { // length w exceeded - // either it was multi-output with first output padding up all width.. - // either it was one big arg and we are fine. - empty_buf( oss_); - oss_.width(0); - put_last(oss_, x ); - string_t tmp = oss_.str(); // minimal-length output - std::streamsize d; - if( (d=w - tmp.size()) <=0 ) - { - // minimal length is already >= w, so no padding (cool!) - res.swap(tmp); - } - else - { // hum.. we need to pad (it was necessarily multi-output) - typedef typename string_t::size_type size_type; - size_type i = 0; - while( i( d ), oss_.fill()); - res.swap( tmp ); - } - } - else - { // okay, only one thing was printed and padded, so res is fine. - } - } - - prev_state.apply_on(oss_); - empty_buf( oss_); - oss_.clear(); -} // end- put(..) - - -} // local namespace - - - - - -template -void distribute(basic_format& self, T x) - // call put(x, ..) on every occurence of the current argument : -{ - if(self.cur_arg_ >= self.num_args_) - { - if( self.exceptions() & too_many_args_bit ) - boost::throw_exception(too_many_args()); // too many variables have been supplied ! - else return; - } - for(unsigned long i=0; i < self.items_.size(); ++i) - { - if(self.items_[i].argN_ == self.cur_arg_) - { - put (x, self.items_[i], self.items_[i].res_, self.oss_ ); - } - } -} - -template -basic_format& feed(basic_format& self, T x) -{ - if(self.dumped_) self.clear(); - distribute (self, x); - ++self.cur_arg_; - if(self.bound_.size() != 0) - { - while( self.cur_arg_ < self.num_args_ && self.bound_[self.cur_arg_] ) - ++self.cur_arg_; - } - - // this arg is finished, reset the stream's format state - self.state0_.apply_on(self.oss_); - return self; -} - - -} // namespace detail -} // namespace io -} // namespace boost - - -#endif // BOOST_FORMAT_FEED_ARGS_HPP diff --git a/nix/boost/format/format_class.hpp b/nix/boost/format/format_class.hpp deleted file mode 100644 index 6875623acb47464afa7db1f9675b20ff72722966..0000000000000000000000000000000000000000 --- a/nix/boost/format/format_class.hpp +++ /dev/null @@ -1,135 +0,0 @@ -// -*- C++ -*- -// Boost general library 'format' --------------------------- -// See http://www.boost.org for updates, documentation, and revision history. - -// (C) Samuel Krempp 2001 -// krempp@crans.ens-cachan.fr -// Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. - -// ideas taken from Rüdiger Loos's format class -// and Karl Nelson's ofstream (also took its parsing code as basis for printf parsing) - -// ------------------------------------------------------------------------------ -// format_class.hpp : class interface -// ------------------------------------------------------------------------------ - - -#ifndef BOOST_FORMAT_CLASS_HPP -#define BOOST_FORMAT_CLASS_HPP - -#include -#include - -#include -#include - -#include - -namespace boost { - -class basic_format -{ -public: - typedef std::string string_t; - typedef BOOST_IO_STD ostringstream internal_stream_t; -private: - typedef BOOST_IO_STD ostream stream_t; - typedef io::detail::stream_format_state stream_format_state; - typedef io::detail::format_item format_item_t; - -public: - basic_format(const char* str); - basic_format(const string_t& s); -#ifndef BOOST_NO_STD_LOCALE - basic_format(const char* str, const std::locale & loc); - basic_format(const string_t& s, const std::locale & loc); -#endif // no locale - basic_format(const basic_format& x); - basic_format& operator= (const basic_format& x); - - basic_format& clear(); // empty the string buffers (except bound arguments, see clear_binds() ) - - // pass arguments through those operators : - template basic_format& operator%(const T& x) - { - return io::detail::feed(*this,x); - } - -#ifndef BOOST_NO_OVERLOAD_FOR_NON_CONST - template basic_format& operator%(T& x) - { - return io::detail::feed(*this,x); - } -#endif - - - // system for binding arguments : - template - basic_format& bind_arg(int argN, const T& val) - { - return io::detail::bind_arg_body(*this, argN, val); - } - basic_format& clear_bind(int argN); - basic_format& clear_binds(); - - // modify the params of a directive, by applying a manipulator : - template - basic_format& modify_item(int itemN, const T& manipulator) - { - return io::detail::modify_item_body(*this, itemN, manipulator) ; - } - - // Choosing which errors will throw exceptions : - unsigned char exceptions() const; - unsigned char exceptions(unsigned char newexcept); - - // final output - string_t str() const; - friend BOOST_IO_STD ostream& - operator<< ( BOOST_IO_STD ostream& , const basic_format& ); - - - template friend basic_format& - io::detail::feed(basic_format&, T); - - template friend - void io::detail::distribute(basic_format&, T); - - template friend - basic_format& io::detail::modify_item_body(basic_format&, int, const T&); - - template friend - basic_format& io::detail::bind_arg_body(basic_format&, int, const T&); - -// make the members private only if the friend templates are supported -private: - - // flag bits, used for style_ - enum style_values { ordered = 1, // set only if all directives are positional directives - special_needs = 4 }; - - // parse the format string : - void parse(const string_t&); - - int style_; // style of format-string : positional or not, etc - int cur_arg_; // keep track of wich argument will come - int num_args_; // number of expected arguments - mutable bool dumped_; // true only after call to str() or << - std::vector items_; // vector of directives (aka items) - string_t prefix_; // piece of string to insert before first item - - std::vector bound_; // stores which arguments were bound - // size = num_args OR zero - internal_stream_t oss_; // the internal stream. - stream_format_state state0_; // reference state for oss_ - unsigned char exceptions_; -}; // class basic_format - - -} // namespace boost - - -#endif // BOOST_FORMAT_CLASS_HPP diff --git a/nix/boost/format/format_fwd.hpp b/nix/boost/format/format_fwd.hpp deleted file mode 100644 index 97c55f6684c3c778c840d1a5eb94bccd797c4bdb..0000000000000000000000000000000000000000 --- a/nix/boost/format/format_fwd.hpp +++ /dev/null @@ -1,49 +0,0 @@ -// -*- C++ -*- -// Boost general library 'format' --------------------------- -// See http://www.boost.org for updates, documentation, and revision history. - -// (C) Samuel Krempp 2001 -// krempp@crans.ens-cachan.fr -// Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. - -// ideas taken from Rüdiger Loos's format class -// and Karl Nelson's ofstream (also took its parsing code as basis for printf parsing) - -// ------------------------------------------------------------------------------ -// format_fwd.hpp : forward declarations, for primary header format.hpp -// ------------------------------------------------------------------------------ - -#ifndef BOOST_FORMAT_FWD_HPP -#define BOOST_FORMAT_FWD_HPP - -#include -#include - -namespace boost { - -class basic_format; - -typedef basic_format format; - -namespace io { -enum format_error_bits { bad_format_string_bit = 1, - too_few_args_bit = 2, too_many_args_bit = 4, - out_of_range_bit = 8, - all_error_bits = 255, no_error_bits=0 }; - -// Convertion: format to string -std::string str(const basic_format& ) ; - -} // namespace io - - -BOOST_IO_STD ostream& -operator<<( BOOST_IO_STD ostream&, const basic_format&); - - -} // namespace boost - -#endif // BOOST_FORMAT_FWD_HPP diff --git a/nix/boost/format/format_implementation.cc b/nix/boost/format/format_implementation.cc deleted file mode 100644 index aa191afe11325a1c0904d88f945c0e8b686b6654..0000000000000000000000000000000000000000 --- a/nix/boost/format/format_implementation.cc +++ /dev/null @@ -1,256 +0,0 @@ -// -*- C++ -*- -// Boost general library format --------------------------- -// See http://www.boost.org for updates, documentation, and revision history. - -// (C) Samuel Krempp 2001 -// krempp@crans.ens-cachan.fr -// Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. - -// ideas taken from Rüdiger Loos's format class -// and Karl Nelson's ofstream - -// ---------------------------------------------------------------------------- -// format_implementation.hpp Implementation of the basic_format class -// ---------------------------------------------------------------------------- - - -#ifndef BOOST_FORMAT_IMPLEMENTATION_HPP -#define BOOST_FORMAT_IMPLEMENTATION_HPP - -#include -#include -#include - -namespace boost { - -// -------- format:: ------------------------------------------- -basic_format::basic_format(const char* str) - : style_(0), cur_arg_(0), num_args_(0), dumped_(false), - items_(), oss_(), exceptions_(io::all_error_bits) -{ - state0_.set_by_stream(oss_); - string_t emptyStr; - if( !str) str = emptyStr.c_str(); - parse( str ); -} - -#ifndef BOOST_NO_STD_LOCALE -basic_format::basic_format(const char* str, const std::locale & loc) - : style_(0), cur_arg_(0), num_args_(0), dumped_(false), - items_(), oss_(), exceptions_(io::all_error_bits) -{ - oss_.imbue( loc ); - state0_.set_by_stream(oss_); - string_t emptyStr; - if( !str) str = emptyStr.c_str(); - parse( str ); -} - -basic_format::basic_format(const string_t& s, const std::locale & loc) - : style_(0), cur_arg_(0), num_args_(0), dumped_(false), - items_(), oss_(), exceptions_(io::all_error_bits) -{ - oss_.imbue( loc ); - state0_.set_by_stream(oss_); - parse(s); -} -#endif //BOOST_NO_STD_LOCALE - -basic_format::basic_format(const string_t& s) - : style_(0), cur_arg_(0), num_args_(0), dumped_(false), - items_(), oss_(), exceptions_(io::all_error_bits) -{ - state0_.set_by_stream(oss_); - parse(s); -} - -basic_format:: basic_format(const basic_format& x) - : style_(x.style_), cur_arg_(x.cur_arg_), num_args_(x.num_args_), dumped_(false), - items_(x.items_), prefix_(x.prefix_), bound_(x.bound_), - oss_(), // <- we obviously can't copy x.oss_ - state0_(x.state0_), exceptions_(x.exceptions_) -{ - state0_.apply_on(oss_); -} - -basic_format& basic_format::operator= (const basic_format& x) -{ - if(this == &x) - return *this; - state0_ = x.state0_; - state0_.apply_on(oss_); - - // plus all the other (trivial) assignments : - exceptions_ = x.exceptions_; - items_ = x.items_; - prefix_ = x.prefix_; - bound_=x.bound_; - style_=x.style_; - cur_arg_=x.cur_arg_; - num_args_=x.num_args_; - dumped_=x.dumped_; - return *this; -} - - -unsigned char basic_format::exceptions() const -{ - return exceptions_; -} - -unsigned char basic_format::exceptions(unsigned char newexcept) -{ - unsigned char swp = exceptions_; - exceptions_ = newexcept; - return swp; -} - - -basic_format& basic_format ::clear() - // empty the string buffers (except bound arguments, see clear_binds() ) - // and make the format object ready for formatting a new set of arguments -{ - BOOST_ASSERT( bound_.size()==0 || num_args_ == static_cast(bound_.size()) ); - - for(unsigned long i=0; i num_args_ || bound_.size()==0 || !bound_[argN-1] ) - { - if( exceptions() & io::out_of_range_bit ) - boost::throw_exception(io::out_of_range()); // arg not in range. - else return *this; - } - bound_[argN-1]=false; - clear(); - return *this; -} - - - -std::string basic_format::str() const -{ - dumped_=true; - if(items_.size()==0) - return prefix_; - if( cur_arg_ < num_args_) - if( exceptions() & io::too_few_args_bit ) - boost::throw_exception(io::too_few_args()); // not enough variables have been supplied ! - - unsigned long sz = prefix_.size(); - unsigned long i; - for(i=0; i < items_.size(); ++i) - sz += items_[i].res_.size() + items_[i].appendix_.size(); - string_t res; - res.reserve(sz); - - res += prefix_; - for(i=0; i < items_.size(); ++i) - { - const format_item_t& item = items_[i]; - res += item.res_; - if( item.argN_ == format_item_t::argN_tabulation) - { - BOOST_ASSERT( item.pad_scheme_ & format_item_t::tabulation); - std::streamsize n = item.state_.width_ - res.size(); - if( n > 0 ) - res.append( n, item.state_.fill_ ); - } - res += item.appendix_; - } - return res; -} - -namespace io { -namespace detail { - -template -basic_format& bind_arg_body( basic_format& self, - int argN, - const T& val) - // bind one argument to a fixed value - // this is persistent over clear() calls, thus also over str() and << -{ - if(self.dumped_) self.clear(); // needed, because we will modify cur_arg_.. - if(argN<1 || argN > self.num_args_) - { - if( self.exceptions() & io::out_of_range_bit ) - boost::throw_exception(io::out_of_range()); // arg not in range. - else return self; - } - if(self.bound_.size()==0) - self.bound_.assign(self.num_args_,false); - else - BOOST_ASSERT( self.num_args_ == static_cast(self.bound_.size()) ); - int o_cur_arg = self.cur_arg_; - self.cur_arg_ = argN-1; // arrays begin at 0 - - self.bound_[self.cur_arg_]=false; // if already set, we unset and re-sets.. - self.operator%(val); // put val at the right place, because cur_arg is set - - - // Now re-position cur_arg before leaving : - self.cur_arg_ = o_cur_arg; - self.bound_[argN-1]=true; - if(self.cur_arg_ == argN-1 ) - // hum, now this arg is bound, so move to next free arg - { - while(self.cur_arg_ < self.num_args_ && self.bound_[self.cur_arg_]) ++self.cur_arg_; - } - // In any case, we either have all args, or are on a non-binded arg : - BOOST_ASSERT( self.cur_arg_ >= self.num_args_ || ! self.bound_[self.cur_arg_]); - return self; -} - -template -basic_format& modify_item_body( basic_format& self, - int itemN, - const T& manipulator) - // applies a manipulator to the format_item describing a given directive. - // this is a permanent change, clear or clear_binds won't cancel that. -{ - if(itemN<1 || itemN >= static_cast(self.items_.size() )) - { - if( self.exceptions() & io::out_of_range_bit ) - boost::throw_exception(io::out_of_range()); // item not in range. - else return self; - } - self.items_[itemN-1].ref_state_.apply_manip( manipulator ); - self.items_[itemN-1].state_ = self.items_[itemN-1].ref_state_; - return self; -} - -} // namespace detail - -} // namespace io - -} // namespace boost - - - -#endif // BOOST_FORMAT_IMPLEMENTATION_HPP diff --git a/nix/boost/format/free_funcs.cc b/nix/boost/format/free_funcs.cc deleted file mode 100644 index 151db37a0ac939d1c0581565472115389ddeea63..0000000000000000000000000000000000000000 --- a/nix/boost/format/free_funcs.cc +++ /dev/null @@ -1,71 +0,0 @@ -// -*- C++ -*- -// Boost general library 'format' --------------------------- -// See http://www.boost.org for updates, documentation, and revision history. - -// (C) Samuel Krempp 2001 -// krempp@crans.ens-cachan.fr -// Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. - -// ideas taken from Rüdiger Loos's format class -// and Karl Nelson's ofstream (also took its parsing code as basis for printf parsing) - -// ------------------------------------------------------------------------------ -// free_funcs.hpp : implementation of the free functions declared in namespace format -// ------------------------------------------------------------------------------ - -#ifndef BOOST_FORMAT_FUNCS_HPP -#define BOOST_FORMAT_FUNCS_HPP - -#include "boost/format.hpp" -#include "boost/throw_exception.hpp" - -namespace boost { - -namespace io { - inline - std::string str(const basic_format& f) - // adds up all pieces of strings and converted items, and return the formatted string - { - return f.str(); - } -} // - namespace io - -BOOST_IO_STD ostream& -operator<<( BOOST_IO_STD ostream& os, - const boost::basic_format& f) - // effect: "return os << str(f);" but we can try to do it faster -{ - typedef boost::basic_format format_t; - if(f.items_.size()==0) - os << f.prefix_; - else { - if(f.cur_arg_ < f.num_args_) - if( f.exceptions() & io::too_few_args_bit ) - boost::throw_exception(io::too_few_args()); // not enough variables have been supplied ! - if(f.style_ & format_t::special_needs) - os << f.str(); - else { - // else we dont have to count chars output, so we dump directly to os : - os << f.prefix_; - for(unsigned long i=0; i -inline -BOOST_IO_STD ostream& -operator << ( BOOST_IO_STD ostream& os, - const group0& ) -{ - return os; -} - -template -struct group1 -{ - T1 a1_; - group1(T1 a1) - : a1_(a1) - {} -}; - -template -inline -BOOST_IO_STD ostream& -operator << (BOOST_IO_STD ostream& os, - const group1& x) -{ - os << x.a1_; - return os; -} - - - - -template -struct group2 -{ - T1 a1_; - T2 a2_; - group2(T1 a1,T2 a2) - : a1_(a1),a2_(a2) - {} -}; - -template -inline -BOOST_IO_STD ostream& -operator << (BOOST_IO_STD ostream& os, - const group2& x) -{ - os << x.a1_<< x.a2_; - return os; -} - -template -struct group3 -{ - T1 a1_; - T2 a2_; - T3 a3_; - group3(T1 a1,T2 a2,T3 a3) - : a1_(a1),a2_(a2),a3_(a3) - {} -}; - -template -inline -BOOST_IO_STD ostream& -operator << (BOOST_IO_STD ostream& os, - const group3& x) -{ - os << x.a1_<< x.a2_<< x.a3_; - return os; -} - -template -struct group4 -{ - T1 a1_; - T2 a2_; - T3 a3_; - T4 a4_; - group4(T1 a1,T2 a2,T3 a3,T4 a4) - : a1_(a1),a2_(a2),a3_(a3),a4_(a4) - {} -}; - -template -inline -BOOST_IO_STD ostream& -operator << (BOOST_IO_STD ostream& os, - const group4& x) -{ - os << x.a1_<< x.a2_<< x.a3_<< x.a4_; - return os; -} - -template -struct group5 -{ - T1 a1_; - T2 a2_; - T3 a3_; - T4 a4_; - T5 a5_; - group5(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5) - : a1_(a1),a2_(a2),a3_(a3),a4_(a4),a5_(a5) - {} -}; - -template -inline -BOOST_IO_STD ostream& -operator << (BOOST_IO_STD ostream& os, - const group5& x) -{ - os << x.a1_<< x.a2_<< x.a3_<< x.a4_<< x.a5_; - return os; -} - -template -struct group6 -{ - T1 a1_; - T2 a2_; - T3 a3_; - T4 a4_; - T5 a5_; - T6 a6_; - group6(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6) - : a1_(a1),a2_(a2),a3_(a3),a4_(a4),a5_(a5),a6_(a6) - {} -}; - -template -inline -BOOST_IO_STD ostream& -operator << (BOOST_IO_STD ostream& os, - const group6& x) -{ - os << x.a1_<< x.a2_<< x.a3_<< x.a4_<< x.a5_<< x.a6_; - return os; -} - -template -struct group7 -{ - T1 a1_; - T2 a2_; - T3 a3_; - T4 a4_; - T5 a5_; - T6 a6_; - T7 a7_; - group7(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7) - : a1_(a1),a2_(a2),a3_(a3),a4_(a4),a5_(a5),a6_(a6),a7_(a7) - {} -}; - -template -inline -BOOST_IO_STD ostream& -operator << (BOOST_IO_STD ostream& os, - const group7& x) -{ - os << x.a1_<< x.a2_<< x.a3_<< x.a4_<< x.a5_<< x.a6_<< x.a7_; - return os; -} - -template -struct group8 -{ - T1 a1_; - T2 a2_; - T3 a3_; - T4 a4_; - T5 a5_; - T6 a6_; - T7 a7_; - T8 a8_; - group8(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7,T8 a8) - : a1_(a1),a2_(a2),a3_(a3),a4_(a4),a5_(a5),a6_(a6),a7_(a7),a8_(a8) - {} -}; - -template -inline -BOOST_IO_STD ostream& -operator << (BOOST_IO_STD ostream& os, - const group8& x) -{ - os << x.a1_<< x.a2_<< x.a3_<< x.a4_<< x.a5_<< x.a6_<< x.a7_<< x.a8_; - return os; -} - -template -struct group9 -{ - T1 a1_; - T2 a2_; - T3 a3_; - T4 a4_; - T5 a5_; - T6 a6_; - T7 a7_; - T8 a8_; - T9 a9_; - group9(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7,T8 a8,T9 a9) - : a1_(a1),a2_(a2),a3_(a3),a4_(a4),a5_(a5),a6_(a6),a7_(a7),a8_(a8),a9_(a9) - {} -}; - -template -inline -BOOST_IO_STD ostream& -operator << (BOOST_IO_STD ostream& os, - const group9& x) -{ - os << x.a1_<< x.a2_<< x.a3_<< x.a4_<< x.a5_<< x.a6_<< x.a7_<< x.a8_<< x.a9_; - return os; -} - -template -struct group10 -{ - T1 a1_; - T2 a2_; - T3 a3_; - T4 a4_; - T5 a5_; - T6 a6_; - T7 a7_; - T8 a8_; - T9 a9_; - T10 a10_; - group10(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7,T8 a8,T9 a9,T10 a10) - : a1_(a1),a2_(a2),a3_(a3),a4_(a4),a5_(a5),a6_(a6),a7_(a7),a8_(a8),a9_(a9),a10_(a10) - {} -}; - -template -inline -BOOST_IO_STD ostream& -operator << (BOOST_IO_STD ostream& os, - const group10& x) -{ - os << x.a1_<< x.a2_<< x.a3_<< x.a4_<< x.a5_<< x.a6_<< x.a7_<< x.a8_<< x.a9_<< x.a10_; - return os; -} - - - - -template -inline -group1 -group_head( group2 const& x) -{ - return group1 (x.a1_); -} - -template -inline -group1 -group_last( group2 const& x) -{ - return group1 (x.a2_); -} - - - -template -inline -group2 -group_head( group3 const& x) -{ - return group2 (x.a1_,x.a2_); -} - -template -inline -group1 -group_last( group3 const& x) -{ - return group1 (x.a3_); -} - - - -template -inline -group3 -group_head( group4 const& x) -{ - return group3 (x.a1_,x.a2_,x.a3_); -} - -template -inline -group1 -group_last( group4 const& x) -{ - return group1 (x.a4_); -} - - - -template -inline -group4 -group_head( group5 const& x) -{ - return group4 (x.a1_,x.a2_,x.a3_,x.a4_); -} - -template -inline -group1 -group_last( group5 const& x) -{ - return group1 (x.a5_); -} - - - -template -inline -group5 -group_head( group6 const& x) -{ - return group5 (x.a1_,x.a2_,x.a3_,x.a4_,x.a5_); -} - -template -inline -group1 -group_last( group6 const& x) -{ - return group1 (x.a6_); -} - - - -template -inline -group6 -group_head( group7 const& x) -{ - return group6 (x.a1_,x.a2_,x.a3_,x.a4_,x.a5_,x.a6_); -} - -template -inline -group1 -group_last( group7 const& x) -{ - return group1 (x.a7_); -} - - - -template -inline -group7 -group_head( group8 const& x) -{ - return group7 (x.a1_,x.a2_,x.a3_,x.a4_,x.a5_,x.a6_,x.a7_); -} - -template -inline -group1 -group_last( group8 const& x) -{ - return group1 (x.a8_); -} - - - -template -inline -group8 -group_head( group9 const& x) -{ - return group8 (x.a1_,x.a2_,x.a3_,x.a4_,x.a5_,x.a6_,x.a7_,x.a8_); -} - -template -inline -group1 -group_last( group9 const& x) -{ - return group1 (x.a9_); -} - - - -template -inline -group9 -group_head( group10 const& x) -{ - return group9 (x.a1_,x.a2_,x.a3_,x.a4_,x.a5_,x.a6_,x.a7_,x.a8_,x.a9_); -} - -template -inline -group1 -group_last( group10 const& x) -{ - return group1 (x.a10_); -} - - - - - -} // namespace detail - - - -// helper functions - - -inline detail::group1< detail::group0 > -group() { return detail::group1< detail::group0 > ( detail::group0() ); } - -template -inline -detail::group1< detail::group2 > - group(T1 a1, Var const& var) -{ - return detail::group1< detail::group2 > - ( detail::group2 - (a1, var) - ); -} - -template -inline -detail::group1< detail::group3 > - group(T1 a1,T2 a2, Var const& var) -{ - return detail::group1< detail::group3 > - ( detail::group3 - (a1,a2, var) - ); -} - -template -inline -detail::group1< detail::group4 > - group(T1 a1,T2 a2,T3 a3, Var const& var) -{ - return detail::group1< detail::group4 > - ( detail::group4 - (a1,a2,a3, var) - ); -} - -template -inline -detail::group1< detail::group5 > - group(T1 a1,T2 a2,T3 a3,T4 a4, Var const& var) -{ - return detail::group1< detail::group5 > - ( detail::group5 - (a1,a2,a3,a4, var) - ); -} - -template -inline -detail::group1< detail::group6 > - group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5, Var const& var) -{ - return detail::group1< detail::group6 > - ( detail::group6 - (a1,a2,a3,a4,a5, var) - ); -} - -template -inline -detail::group1< detail::group7 > - group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6, Var const& var) -{ - return detail::group1< detail::group7 > - ( detail::group7 - (a1,a2,a3,a4,a5,a6, var) - ); -} - -template -inline -detail::group1< detail::group8 > - group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7, Var const& var) -{ - return detail::group1< detail::group8 > - ( detail::group8 - (a1,a2,a3,a4,a5,a6,a7, var) - ); -} - -template -inline -detail::group1< detail::group9 > - group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7,T8 a8, Var const& var) -{ - return detail::group1< detail::group9 > - ( detail::group9 - (a1,a2,a3,a4,a5,a6,a7,a8, var) - ); -} - -template -inline -detail::group1< detail::group10 > - group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7,T8 a8,T9 a9, Var const& var) -{ - return detail::group1< detail::group10 > - ( detail::group10 - (a1,a2,a3,a4,a5,a6,a7,a8,a9, var) - ); -} - - -#ifndef BOOST_NO_OVERLOAD_FOR_NON_CONST - -template -inline -detail::group1< detail::group2 > - group(T1 a1, Var& var) -{ - return detail::group1< detail::group2 > - ( detail::group2 - (a1, var) - ); -} - -template -inline -detail::group1< detail::group3 > - group(T1 a1,T2 a2, Var& var) -{ - return detail::group1< detail::group3 > - ( detail::group3 - (a1,a2, var) - ); -} - -template -inline -detail::group1< detail::group4 > - group(T1 a1,T2 a2,T3 a3, Var& var) -{ - return detail::group1< detail::group4 > - ( detail::group4 - (a1,a2,a3, var) - ); -} - -template -inline -detail::group1< detail::group5 > - group(T1 a1,T2 a2,T3 a3,T4 a4, Var& var) -{ - return detail::group1< detail::group5 > - ( detail::group5 - (a1,a2,a3,a4, var) - ); -} - -template -inline -detail::group1< detail::group6 > - group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5, Var& var) -{ - return detail::group1< detail::group6 > - ( detail::group6 - (a1,a2,a3,a4,a5, var) - ); -} - -template -inline -detail::group1< detail::group7 > - group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6, Var& var) -{ - return detail::group1< detail::group7 > - ( detail::group7 - (a1,a2,a3,a4,a5,a6, var) - ); -} - -template -inline -detail::group1< detail::group8 > - group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7, Var& var) -{ - return detail::group1< detail::group8 > - ( detail::group8 - (a1,a2,a3,a4,a5,a6,a7, var) - ); -} - -template -inline -detail::group1< detail::group9 > - group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7,T8 a8, Var& var) -{ - return detail::group1< detail::group9 > - ( detail::group9 - (a1,a2,a3,a4,a5,a6,a7,a8, var) - ); -} - -template -inline -detail::group1< detail::group10 > - group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7,T8 a8,T9 a9, Var& var) -{ - return detail::group1< detail::group10 > - ( detail::group10 - (a1,a2,a3,a4,a5,a6,a7,a8,a9, var) - ); -} - - -#endif //end- #ifndef BOOST_NO_OVERLOAD_FOR_NON_CONST - - -} // namespace io - -} // namespace boost - - -#endif // BOOST_FORMAT_GROUP_HPP diff --git a/nix/boost/format/internals.hpp b/nix/boost/format/internals.hpp deleted file mode 100644 index d25eb4c864c482f0fb738500867af80971b4e1aa..0000000000000000000000000000000000000000 --- a/nix/boost/format/internals.hpp +++ /dev/null @@ -1,167 +0,0 @@ -// -*- C++ -*- -// Boost general library 'format' --------------------------- -// See http://www.boost.org for updates, documentation, and revision history. - -// (C) Samuel Krempp 2001 -// krempp@crans.ens-cachan.fr -// Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. - -// ideas taken from Rüdiger Loos's format class -// and Karl Nelson's ofstream - -// ---------------------------------------------------------------------------- -// internals.hpp : internal structs. included by format.hpp -// stream_format_state, and format_item -// ---------------------------------------------------------------------------- - - -#ifndef BOOST_FORMAT_INTERNALS_HPP -#define BOOST_FORMAT_INTERNALS_HPP - - -#include -#include - -namespace boost { -namespace io { -namespace detail { - - -// -------------- -// set of params that define the format state of a stream - -struct stream_format_state -{ - typedef std::ios basic_ios; - - std::streamsize width_; - std::streamsize precision_; - char fill_; - std::ios::fmtflags flags_; - - stream_format_state() : width_(-1), precision_(-1), fill_(0), flags_(std::ios::dec) {} - stream_format_state(basic_ios& os) {set_by_stream(os); } - - void apply_on(basic_ios & os) const; //- applies format_state to the stream - template void apply_manip(T manipulator) //- modifies state by applying manipulator. - { apply_manip_body( *this, manipulator) ; } - void reset(); //- sets to default state. - void set_by_stream(const basic_ios& os); //- sets to os's state. -}; - - - -// -------------- -// format_item : stores all parameters that can be defined by directives in the format-string - -struct format_item -{ - enum pad_values { zeropad = 1, spacepad =2, centered=4, tabulation = 8 }; - - enum arg_values { argN_no_posit = -1, // non-positional directive. argN will be set later. - argN_tabulation = -2, // tabulation directive. (no argument read) - argN_ignored = -3 // ignored directive. (no argument read) - }; - typedef BOOST_IO_STD ios basic_ios; - typedef detail::stream_format_state stream_format_state; - typedef std::string string_t; - typedef BOOST_IO_STD ostringstream internal_stream_t; - - - int argN_; //- argument number (starts at 0, eg : %1 => argN=0) - // negative values are used for items that don't process - // an argument - string_t res_; //- result of the formatting of this item - string_t appendix_; //- piece of string between this item and the next - - stream_format_state ref_state_;// set by parsing the format_string, is only affected by modify_item - stream_format_state state_; // always same as ref_state, _unless_ modified by manipulators 'group(..)' - - // non-stream format-state parameters - signed int truncate_; //- is >=0 for directives like %.5s (take 5 chars from the string) - unsigned int pad_scheme_; //- several possible padding schemes can mix. see pad_values - - format_item() : argN_(argN_no_posit), truncate_(-1), pad_scheme_(0) {} - - void compute_states(); // sets states according to truncate and pad_scheme. -}; - - - -// ----------------------------------------------------------- -// Definitions -// ----------------------------------------------------------- - -// --- stream_format_state:: ------------------------------------------- -inline -void stream_format_state::apply_on(basic_ios & os) const - // set the state of this stream according to our params -{ - if(width_ != -1) - os.width(width_); - if(precision_ != -1) - os.precision(precision_); - if(fill_ != 0) - os.fill(fill_); - os.flags(flags_); -} - -inline -void stream_format_state::set_by_stream(const basic_ios& os) - // set our params according to the state of this stream -{ - flags_ = os.flags(); - width_ = os.width(); - precision_ = os.precision(); - fill_ = os.fill(); -} - -template inline -void apply_manip_body( stream_format_state& self, - T manipulator) - // modify our params according to the manipulator -{ - BOOST_IO_STD stringstream ss; - self.apply_on( ss ); - ss << manipulator; - self.set_by_stream( ss ); -} - -inline -void stream_format_state::reset() - // set our params to standard's default state -{ - width_=-1; precision_=-1; fill_=0; - flags_ = std::ios::dec; -} - - -// --- format_items:: ------------------------------------------- -inline -void format_item::compute_states() - // reflect pad_scheme_ on state_ and ref_state_ - // because some pad_schemes has complex consequences on several state params. -{ - if(pad_scheme_ & zeropad) - { - if(ref_state_.flags_ & std::ios::left) - { - pad_scheme_ = pad_scheme_ & (~zeropad); // ignore zeropad in left alignment - } - else - { - ref_state_.fill_='0'; - ref_state_.flags_ |= std::ios::internal; - } - } - state_ = ref_state_; -} - - -} } } // namespaces boost :: io :: detail - - -#endif // BOOST_FORMAT_INTERNALS_HPP diff --git a/nix/boost/format/internals_fwd.hpp b/nix/boost/format/internals_fwd.hpp deleted file mode 100644 index a8ebf7c3abc105fb99b3d629ec79ca7216a1a208..0000000000000000000000000000000000000000 --- a/nix/boost/format/internals_fwd.hpp +++ /dev/null @@ -1,65 +0,0 @@ -// -*- C++ -*- -// Boost general library 'format' --------------------------- -// See http://www.boost.org for updates, documentation, and revision history. - -// (C) Samuel Krempp 2001 -// krempp@crans.ens-cachan.fr -// Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. - -// ideas taken from Rüdiger Loos's format class -// and Karl Nelson's ofstream (also took its parsing code as basis for printf parsing) - -// ------------------------------------------------------------------------------ -// internals_fwd.hpp : forward declarations, for internal headers -// ------------------------------------------------------------------------------ - -#ifndef BOOST_FORMAT_INTERNAL_FWD_HPP -#define BOOST_FORMAT_INTERNAL_FWD_HPP - -#include "boost/format/format_fwd.hpp" - - -namespace boost { -namespace io { - -namespace detail { - struct stream_format_state; - struct format_item; -} - - -namespace detail { - - // these functions were intended as methods, - // but MSVC have problems with template member functions : - - // defined in format_implementation.hpp : - template - basic_format& modify_item_body( basic_format& self, - int itemN, const T& manipulator); - - template - basic_format& bind_arg_body( basic_format& self, - int argN, const T& val); - - template - void apply_manip_body( stream_format_state& self, - T manipulator); - - // argument feeding (defined in feed_args.hpp ) : - template - void distribute(basic_format& self, T x); - - template - basic_format& feed(basic_format& self, T x); - -} // namespace detail - -} // namespace io -} // namespace boost - - -#endif // BOOST_FORMAT_INTERNAL_FWD_HPP diff --git a/nix/boost/format/macros_default.hpp b/nix/boost/format/macros_default.hpp deleted file mode 100644 index 4fd84a163fb371e540b341558064854c952c9f83..0000000000000000000000000000000000000000 --- a/nix/boost/format/macros_default.hpp +++ /dev/null @@ -1,48 +0,0 @@ -// -*- C++ -*- -// Boost general library 'format' --------------------------- -// See http://www.boost.org for updates, documentation, and revision history. - -// (C) Samuel Krempp 2001 -// krempp@crans.ens-cachan.fr -// Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. - -// ideas taken from Rüdiger Loos's format class -// and Karl Nelson's ofstream (also took its parsing code as basis for printf parsing) - -// ------------------------------------------------------------------------------ -// macros_default.hpp : configuration for the format library -// provides default values for the stl workaround macros -// ------------------------------------------------------------------------------ - -#ifndef BOOST_FORMAT_MACROS_DEFAULT_HPP -#define BOOST_FORMAT_MACROS_DEFAULT_HPP - -// *** This should go to "boost/config/suffix.hpp". - -#ifndef BOOST_IO_STD -# define BOOST_IO_STD std:: -#endif - -// **** Workaround for io streams, stlport and msvc. -#ifdef BOOST_IO_NEEDS_USING_DECLARATION -namespace boost { - using std::char_traits; - using std::basic_ostream; - using std::basic_ostringstream; - namespace io { - using std::basic_ostream; - namespace detail { - using std::basic_ios; - using std::basic_ostream; - using std::basic_ostringstream; - } - } -} -#endif - -// ------------------------------------------------------------------------------ - -#endif // BOOST_FORMAT_MACROS_DEFAULT_HPP diff --git a/nix/boost/format/parsing.cc b/nix/boost/format/parsing.cc deleted file mode 100644 index 34c36adeb7343339051936f0801493641a001b1e..0000000000000000000000000000000000000000 --- a/nix/boost/format/parsing.cc +++ /dev/null @@ -1,454 +0,0 @@ -// -*- C++ -*- -// Boost general library 'format' --------------------------- -// See http://www.boost.org for updates, documentation, and revision history. - -// (C) Samuel Krempp 2001 -// krempp@crans.ens-cachan.fr -// Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. - -// ideas taken from Rudiger Loos's format class -// and Karl Nelson's ofstream (also took its parsing code as basis for printf parsing) - -// ------------------------------------------------------------------------------ -// parsing.hpp : implementation of the parsing member functions -// ( parse, parse_printf_directive) -// ------------------------------------------------------------------------------ - - -#ifndef BOOST_FORMAT_PARSING_HPP -#define BOOST_FORMAT_PARSING_HPP - - -#include -#include -#include - - -namespace boost { -namespace io { -namespace detail { - - template inline - bool wrap_isdigit(char c, Stream &os) - { -#ifndef BOOST_NO_LOCALE_ISIDIGIT - return std::isdigit(c, os.rdbuf()->getloc() ); -# else - using namespace std; - return isdigit(c); -#endif - } //end- wrap_isdigit(..) - - template inline - Res str2int(const std::string& s, - std::string::size_type start, - BOOST_IO_STD ios &os, - const Res = Res(0) ) - // Input : char string, with starting index - // a basic_ios& merely to call its widen/narrow member function in the desired locale. - // Effects : reads s[start:] and converts digits into an integral n, of type Res - // Returns : n - { - Res n = 0; - while(start= buf.size() ) return; - if(buf[ *pos_p]=='*') { - ++ (*pos_p); - while (*pos_p < buf.size() && wrap_isdigit(buf[*pos_p],os)) ++(*pos_p); - if(buf[*pos_p]=='$') ++(*pos_p); - } - } - - - inline void maybe_throw_exception( unsigned char exceptions) - // auxiliary func called by parse_printf_directive - // for centralising error handling - // it either throws if user sets the corresponding flag, or does nothing. - { - if(exceptions & io::bad_format_string_bit) - boost::throw_exception(io::bad_format_string()); - } - - - - bool parse_printf_directive(const std::string & buf, - std::string::size_type * pos_p, - detail::format_item * fpar, - BOOST_IO_STD ios &os, - unsigned char exceptions) - // Input : a 'printf-directive' in the format-string, starting at buf[ *pos_p ] - // a basic_ios& merely to call its widen/narrow member function in the desired locale. - // a bitset'excpetions' telling whether to throw exceptions on errors. - // Returns : true if parse somehow succeeded (possibly ignoring errors if exceptions disabled) - // false if it failed so bad that the directive should be printed verbatim - // Effects : - *pos_p is incremented so that buf[*pos_p] is the first char after the directive - // - *fpar is set with the parameters read in the directive - { - typedef format_item format_item_t; - BOOST_ASSERT( pos_p != 0); - std::string::size_type &i1 = *pos_p, - i0; - fpar->argN_ = format_item_t::argN_no_posit; // if no positional-directive - - bool in_brackets=false; - if(buf[i1]=='|') - { - in_brackets=true; - if( ++i1 >= buf.size() ) { - maybe_throw_exception(exceptions); - return false; - } - } - - // the flag '0' would be picked as a digit for argument order, but here it's a flag : - if(buf[i1]=='0') - goto parse_flags; - - // handle argument order (%2$d) or possibly width specification: %2d - i0 = i1; // save position before digits - while (i1 < buf.size() && wrap_isdigit(buf[i1], os)) - ++i1; - if (i1!=i0) - { - if( i1 >= buf.size() ) { - maybe_throw_exception(exceptions); - return false; - } - int n=str2int(buf,i0, os, int(0) ); - - // %N% case : this is already the end of the directive - if( buf[i1] == '%' ) - { - fpar->argN_ = n-1; - ++i1; - if( in_brackets) - maybe_throw_exception(exceptions); - // but don't return. maybe "%" was used in lieu of '$', so we go on. - else return true; - } - - if ( buf[i1]=='$' ) - { - fpar->argN_ = n-1; - ++i1; - } - else - { - // non-positionnal directive - fpar->ref_state_.width_ = n; - fpar->argN_ = format_item_t::argN_no_posit; - goto parse_precision; - } - } - - parse_flags: - // handle flags - while ( i1 ref_state_.flags_ |= std::ios::left; - break; - case '=': - fpar->pad_scheme_ |= format_item_t::centered; - break; - case ' ': - fpar->pad_scheme_ |= format_item_t::spacepad; - break; - case '+': - fpar->ref_state_.flags_ |= std::ios::showpos; - break; - case '0': - fpar->pad_scheme_ |= format_item_t::zeropad; - // need to know alignment before really setting flags, - // so just add 'zeropad' flag for now, it will be processed later. - break; - case '#': - fpar->ref_state_.flags_ |= std::ios::showpoint | std::ios::showbase; - break; - default: - goto parse_width; - } - ++i1; - } // loop on flag. - if( i1>=buf.size()) { - maybe_throw_exception(exceptions); - return true; - } - - parse_width: - // handle width spec - skip_asterisk(buf, &i1, os); // skips 'asterisk fields' : *, or *N$ - i0 = i1; // save position before digits - while (i1ref_state_.width_ = str2int( buf,i0, os, std::streamsize(0) ); } - - parse_precision: - if( i1>=buf.size()) { - maybe_throw_exception(exceptions); - return true; - } - // handle precision spec - if (buf[i1]=='.') - { - ++i1; - skip_asterisk(buf, &i1, os); - i0 = i1; // save position before digits - while (i1ref_state_.precision_ = 0; - else - fpar->ref_state_.precision_ = str2int(buf,i0, os, std::streamsize(0) ); - } - - // handle formatting-type flags : - while( i1=buf.size()) { - maybe_throw_exception(exceptions); - return true; - } - - if( in_brackets && buf[i1]=='|' ) - { - ++i1; - return true; - } - switch (buf[i1]) - { - case 'X': - fpar->ref_state_.flags_ |= std::ios::uppercase; - case 'p': // pointer => set hex. - case 'x': - fpar->ref_state_.flags_ &= ~std::ios::basefield; - fpar->ref_state_.flags_ |= std::ios::hex; - break; - - case 'o': - fpar->ref_state_.flags_ &= ~std::ios::basefield; - fpar->ref_state_.flags_ |= std::ios::oct; - break; - - case 'E': - fpar->ref_state_.flags_ |= std::ios::uppercase; - case 'e': - fpar->ref_state_.flags_ &= ~std::ios::floatfield; - fpar->ref_state_.flags_ |= std::ios::scientific; - - fpar->ref_state_.flags_ &= ~std::ios::basefield; - fpar->ref_state_.flags_ |= std::ios::dec; - break; - - case 'f': - fpar->ref_state_.flags_ &= ~std::ios::floatfield; - fpar->ref_state_.flags_ |= std::ios::fixed; - case 'u': - case 'd': - case 'i': - fpar->ref_state_.flags_ &= ~std::ios::basefield; - fpar->ref_state_.flags_ |= std::ios::dec; - break; - - case 'T': - ++i1; - if( i1 >= buf.size()) - maybe_throw_exception(exceptions); - else - fpar->ref_state_.fill_ = buf[i1]; - fpar->pad_scheme_ |= format_item_t::tabulation; - fpar->argN_ = format_item_t::argN_tabulation; - break; - case 't': - fpar->ref_state_.fill_ = ' '; - fpar->pad_scheme_ |= format_item_t::tabulation; - fpar->argN_ = format_item_t::argN_tabulation; - break; - - case 'G': - fpar->ref_state_.flags_ |= std::ios::uppercase; - break; - case 'g': // 'g' conversion is default for floats. - fpar->ref_state_.flags_ &= ~std::ios::basefield; - fpar->ref_state_.flags_ |= std::ios::dec; - - // CLEAR all floatield flags, so stream will CHOOSE - fpar->ref_state_.flags_ &= ~std::ios::floatfield; - break; - - case 'C': - case 'c': - fpar->truncate_ = 1; - break; - case 'S': - case 's': - fpar->truncate_ = fpar->ref_state_.precision_; - fpar->ref_state_.precision_ = -1; - break; - case 'n' : - fpar->argN_ = format_item_t::argN_ignored; - break; - default: - maybe_throw_exception(exceptions); - } - ++i1; - - if( in_brackets ) - { - if( i1= buf.size() ) { - if(exceptions() & io::bad_format_string_bit) - boost::throw_exception(io::bad_format_string()); // must not end in "bla bla %" - else break; // stop there, ignore last '%' - } - if(buf[i1+1] == buf[i1] ) { i1+=2; continue; } // escaped "%%" / "##" - ++i1; - - // in case of %N% directives, dont count it double (wastes allocations..) : - while(i1 < buf.size() && io::detail::wrap_isdigit(buf[i1],oss_)) ++i1; - if( i1 < buf.size() && buf[i1] == arg_mark ) ++ i1; - - ++num_items; - } - items_.assign( num_items, format_item_t() ); - - // B: Now the real parsing of the format string : - num_items=0; - i1 = 0; - string_t::size_type i0 = i1; - bool special_things=false; - int cur_it=0; - while( (i1=buf.find(arg_mark,i1)) != string::npos ) - { - string_t & piece = (cur_it==0) ? prefix_ : items_[cur_it-1].appendix_; - - if( buf[i1+1] == buf[i1] ) // escaped mark, '%%' - { - piece += buf.substr(i0, i1-i0) + buf[i1]; - i1+=2; i0=i1; - continue; - } - BOOST_ASSERT( static_cast(cur_it) < items_.size() || cur_it==0); - - if(i1!=i0) piece += buf.substr(i0, i1-i0); - ++i1; - - bool parse_ok; - parse_ok = io::detail::parse_printf_directive(buf, &i1, &items_[cur_it], oss_, exceptions()); - if( ! parse_ok ) continue; // the directive will be printed verbatim - - i0=i1; - items_[cur_it].compute_states(); // process complex options, like zeropad, into stream params. - - int argN=items_[cur_it].argN_; - if(argN == format_item_t::argN_ignored) - continue; - if(argN ==format_item_t::argN_no_posit) - ordered_args=false; - else if(argN == format_item_t::argN_tabulation) special_things=true; - else if(argN > max_argN) max_argN = argN; - ++num_items; - ++cur_it; - } // loop on %'s - BOOST_ASSERT(cur_it == num_items); - - // store the final piece of string - string_t & piece = (cur_it==0) ? prefix_ : items_[cur_it-1].appendix_; - piece += buf.substr(i0); - - if( !ordered_args) - { - if(max_argN >= 0 ) // dont mix positional with non-positionnal directives - { - if(exceptions() & io::bad_format_string_bit) - boost::throw_exception(io::bad_format_string()); - // else do nothing. => positionnal arguments are processed as non-positionnal - } - // set things like it would have been with positional directives : - int non_ordered_items = 0; - for(int i=0; i< num_items; ++i) - if(items_[i].argN_ == format_item_t::argN_no_posit) - { - items_[i].argN_ = non_ordered_items; - ++non_ordered_items; - } - max_argN = non_ordered_items-1; - } - - // C: set some member data : - items_.resize(num_items); - - if(special_things) style_ |= special_needs; - num_args_ = max_argN + 1; - if(ordered_args) style_ |= ordered; - else style_ &= ~ordered; -} - -} // namespace boost - - -#endif // BOOST_FORMAT_PARSING_HPP diff --git a/nix/boost/throw_exception.hpp b/nix/boost/throw_exception.hpp deleted file mode 100644 index 07b4ae5ceae7f1eb9a4b494110e73b71281d7b46..0000000000000000000000000000000000000000 --- a/nix/boost/throw_exception.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef BOOST_THROW_EXCEPTION_HPP_INCLUDED -#define BOOST_THROW_EXCEPTION_HPP_INCLUDED - -// MS compatible compilers support #pragma once - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - -// -// boost/throw_exception.hpp -// -// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -// http://www.boost.org/libs/utility/throw_exception.html -// - -//#include - -#ifdef BOOST_NO_EXCEPTIONS -# include -#endif - -namespace boost -{ - -#ifdef BOOST_NO_EXCEPTIONS - -void throw_exception(std::exception const & e); // user defined - -#else - -template void throw_exception(E const & e) -{ - throw e; -} - -#endif - -} // namespace boost - -#endif // #ifndef BOOST_THROW_EXCEPTION_HPP_INCLUDED diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index f455343c189975dfbf28b794b840b4274600cc07..bf2e9150d6a25ba6f4015f9a25ae497c632b92f7 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -7,14 +7,14 @@ #include "local-store.hh" #include "util.hh" #include "archive.hh" -#include "affinity.hh" #include "builtins.hh" #include "spawn.hh" #include -#include #include #include +#include +#include #include #include @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include @@ -195,7 +195,7 @@ public: abort(); } - void trace(const format & f); + void trace(std::string_view s); string getName() { @@ -372,8 +372,7 @@ void Goal::waiteeDone(GoalPtr waitee, ExitCode result) assert(waitees.find(waitee) != waitees.end()); waitees.erase(waitee); - trace(format("waitee `%1%' done; %2% left") % - waitee->name % waitees.size()); + trace(std::format("waitee `{}' done; {} left", waitee->name, waitees.size())); if (result == ecFailed || result == ecNoSubstituters || result == ecIncompleteClosure) ++nrFailed; @@ -414,9 +413,9 @@ void Goal::amDone(ExitCode result) } -void Goal::trace(const format & f) +void Goal::trace(std::string_view f) { - debug(format("%1%: %2%") % name % f); + debug(std::format("{}: {}", name, f)); } @@ -483,34 +482,34 @@ void UserLock::acquire() /* Get the members of the build-users-group. */ struct group * gr = getgrnam(settings.buildUsersGroup.c_str()); if (!gr) - throw Error(format("the group `%1%' specified in `build-users-group' does not exist") - % settings.buildUsersGroup); + throw Error(std::format("the group `{}' specified in `build-users-group' does not exist", + settings.buildUsersGroup)); gid = gr->gr_gid; /* Copy the result of getgrnam. */ Strings users; for (char * * p = gr->gr_mem; *p; ++p) { - debug(format("found build user `%1%'") % *p); + debug(std::format("found build user `{}'", *p)); users.push_back(*p); } if (users.empty()) - throw Error(format("the build users group `%1%' has no members") - % settings.buildUsersGroup); + throw Error(std::format("the build users group `{}' has no members", + settings.buildUsersGroup)); /* Find a user account that isn't currently in use for another build. */ for (auto& i : users) { - debug(format("trying user `%1%'") % i); + debug(std::format("trying user `{}'", i)); struct passwd * pw = getpwnam(i.c_str()); if (!pw) - throw Error(format("the user `%1%' in the group `%2%' does not exist") - % i % settings.buildUsersGroup); + throw Error(std::format("the user `{}' in the group `{}' does not exist", + i, settings.buildUsersGroup)); createDirs(settings.nixStateDir + "/userpool"); - fnUserLock = (format("%1%/userpool/%2%") % settings.nixStateDir % pw->pw_uid).str(); + fnUserLock = std::format("{}/userpool/{}", settings.nixStateDir, pw->pw_uid); if (lockedPaths.find(fnUserLock) != lockedPaths.end()) /* We already have a lock on this one. */ @@ -518,7 +517,7 @@ void UserLock::acquire() AutoCloseFD fd = open(fnUserLock.c_str(), O_RDWR | O_CREAT, 0600); if (fd == -1) - throw SysError(format("opening user lock `%1%'") % fnUserLock); + throw SysError(std::format("opening user lock `{}'", fnUserLock)); closeOnExec(fd); if (lockFile(fd, ltWrite, false)) { @@ -529,8 +528,8 @@ void UserLock::acquire() /* Sanity check... */ if (uid == getuid() || uid == geteuid()) - throw Error(format("the build user should not be a member of `%1%'") - % settings.buildUsersGroup); + throw Error(std::format("the build user should not be a member of `{}'", + settings.buildUsersGroup)); /* Get the list of supplementary groups of this build user. This is usually either empty or contains a group such as "kvm". */ @@ -539,7 +538,7 @@ void UserLock::acquire() int err = getgrouplist(pw->pw_name, pw->pw_gid, supplementaryGIDs.data(), &ngroups); if (err == -1) - throw Error(format("failed to get list of supplementary groups for ‘%1%’") % pw->pw_name); + throw Error(std::format("failed to get list of supplementary groups for `{}'", pw->pw_name)); supplementaryGIDs.resize(ngroups); @@ -547,9 +546,9 @@ void UserLock::acquire() } } - throw Error(format("all build users are currently in use; " - "consider creating additional users and adding them to the `%1%' group") - % settings.buildUsersGroup); + throw Error(std::format("all build users are currently in use; " + "consider creating additional users and adding them to the `{}' group", + settings.buildUsersGroup)); } @@ -582,7 +581,7 @@ string rewriteHashes(string s, const HashRewrites & rewrites) assert(i.first.size() == i.second.size()); size_t j = 0; while ((j = s.find(i.first, j)) != string::npos) { - debug(format("rewriting @ %1%") % j); + debug(std::format("rewriting @ {}", j)); s.replace(j, i.second.size(), i.second); } } @@ -716,7 +715,7 @@ public: void timedOut() override; - string key() + string key() override { /* Ensure that derivations get built in order of their name, i.e. a derivation named "aardvark" always comes before @@ -725,7 +724,7 @@ public: return "b$" + storePathToName(drvPath) + "$" + drvPath; } - void work(); + void work() override; Path getDrvPath() { @@ -771,8 +770,8 @@ private: void deleteTmpDir(bool force); /* Callback used by the worker to write to the log. */ - void handleChildOutput(int fd, const string & data); - void handleEOF(int fd); + void handleChildOutput(int fd, const string & data) override; + void handleEOF(int fd) override; /* Return the set of (in)valid paths. */ PathSet checkPathValidity(bool returnValid, bool checkHash); @@ -806,7 +805,7 @@ DerivationGoal::DerivationGoal(const Path & drvPath, const StringSet & wantedOut { this->drvPath = drvPath; state = &DerivationGoal::init; - name = (format("building of `%1%'") % drvPath).str(); + name = std::format("building of `{}'", drvPath); trace("created"); /* Prevent the .chroot directory from being @@ -862,7 +861,7 @@ void DerivationGoal::killChild() void DerivationGoal::timedOut() { if (settings.printBuildTrace) - printMsg(lvlError, format("@ build-failed %1% - timeout") % drvPath); + printMsg(lvlError, std::format("@ build-failed {} - timeout", drvPath)); killChild(); done(BuildResult::TimedOut); } @@ -896,7 +895,7 @@ void DerivationGoal::init() trace("init"); if (settings.readOnlyMode) - throw Error(format("cannot build derivation `%1%' - no write access to the store") % drvPath); + throw Error(std::format("cannot build derivation `{}' - no write access to the store", drvPath)); /* The first thing to do is to make sure that the derivation exists. If it doesn't, it may be created through a @@ -917,7 +916,7 @@ void DerivationGoal::haveDerivation() trace("loading derivation"); if (nrFailed != 0) { - printMsg(lvlError, format("cannot build missing derivation ‘%1%’") % drvPath); + printMsg(lvlError, std::format("cannot build missing derivation `{}'", drvPath)); done(BuildResult::MiscFailure); return; } @@ -968,7 +967,7 @@ void DerivationGoal::outputsSubstituted() trace("all outputs substituted (maybe)"); if (nrFailed > 0 && nrFailed > nrNoSubstituters + nrIncompleteClosure && !settings.tryFallback) - throw Error(format("some substitutes for the outputs of derivation `%1%' failed (usually happens due to networking issues); try `--fallback' to build derivation from source ") % drvPath); + throw Error(std::format("some substitutes for the outputs of derivation `{}' failed (usually happens due to networking issues); try `--fallback' to build derivation from source ", drvPath)); /* If the substitutes form an incomplete closure, then we should build the dependencies of this derivation, but after that, we @@ -993,7 +992,7 @@ void DerivationGoal::outputsSubstituted() return; } if (buildMode == bmCheck && nrInvalid > 0) - throw Error(format("`%1%' is missing outputs; build it normally before using `--check'") % drvPath); + throw Error(std::format("`{}' is missing outputs; build it normally before using `--check'", drvPath)); /* Otherwise, at least one of the output paths could not be produced using a substitute. So we have to build instead. */ @@ -1051,7 +1050,7 @@ void DerivationGoal::repairClosure() PathSet broken; for (auto& i : outputClosure) { if (worker.store.pathContentsGood(i)) continue; - printMsg(lvlError, format("found corrupted or missing path `%1%' in the output closure of `%2%'") % i % drvPath); + printMsg(lvlError, std::format("found corrupted or missing path `{}' in the output closure of `{}'", i, drvPath)); Path drvPath2 = outputsToDrv[i]; if (drvPath2 == "") addWaitee(worker.makeSubstitutionGoal(i, true)); @@ -1072,7 +1071,7 @@ void DerivationGoal::closureRepaired() { trace("closure repaired"); if (nrFailed > 0) - throw Error(format("some paths in the output closure of derivation ‘%1%’ could not be repaired") % drvPath); + throw Error(std::format("some paths in the output closure of derivation `{}' could not be repaired", drvPath)); done(BuildResult::AlreadyValid); } @@ -1083,8 +1082,8 @@ void DerivationGoal::inputsRealised() if (nrFailed != 0) { printMsg(lvlError, - format("cannot build derivation `%1%': %2% dependencies couldn't be built") - % drvPath % nrFailed); + std::format("cannot build derivation `{}': {} dependencies couldn't be built", + drvPath, nrFailed)); done(BuildResult::DependencyFailed); return; } @@ -1099,7 +1098,7 @@ void DerivationGoal::inputsRealised() /* The outputs are referenceable paths. */ for (auto& i : drv.outputs) { - debug(format("building path `%1%'") % i.second.path); + debug(std::format("building path `{}'", i.second.path)); allPaths.insert(i.second.path); } @@ -1117,15 +1116,15 @@ void DerivationGoal::inputsRealised() computeFSClosure(worker.store, inDrv.outputs[j].path, inputPaths); else throw Error( - format("derivation `%1%' requires non-existent output `%2%' from input derivation `%3%'") - % drvPath % j % i.first); + std::format("derivation `{}' requires non-existent output `{}' from input derivation `{}'", + drvPath, j, i.first)); } /* Second, the input sources. */ for (auto& i : drv.inputSrcs) computeFSClosure(worker.store, i, inputPaths); - debug(format("added input paths %1%") % showPaths(inputPaths)); + debug(std::format("added input paths {}", showPaths(inputPaths))); allPaths.insert(inputPaths.begin(), inputPaths.end()); @@ -1187,8 +1186,8 @@ void DerivationGoal::tryToBuild() goal to sleep until another goal finishes, then try again. */ for (auto& i : drv.outputs) if (pathIsLockedByMe(i.second.path)) { - debug(format("putting derivation `%1%' to sleep because `%2%' is locked by another goal") - % drvPath % i.second.path); + debug(std::format("putting derivation `{}' to sleep because `{}' is locked by another goal", + drvPath, i.second.path)); worker.waitForAnyGoal(shared_from_this()); return; } @@ -1212,7 +1211,7 @@ void DerivationGoal::tryToBuild() build this derivation, so no further checks are necessary. */ validPaths = checkPathValidity(true, buildMode == bmRepair); if (buildMode != bmCheck && validPaths.size() == drv.outputs.size()) { - debug(format("skipping build of derivation `%1%', someone beat us to it") % drvPath); + debug(std::format("skipping build of derivation `{}', someone beat us to it", drvPath)); outputLocks.setDeletion(true); outputLocks.unlock(); done(BuildResult::AlreadyValid); @@ -1229,7 +1228,7 @@ void DerivationGoal::tryToBuild() Path path = i.second.path; if (worker.store.isValidPath(path)) continue; if (!pathExists(path)) continue; - debug(format("removing invalid path `%1%'") % path); + debug(std::format("removing invalid path `{}'", path)); deletePath(path); } @@ -1284,8 +1283,8 @@ void DerivationGoal::tryToBuild() outputLocks.unlock(); buildUser.release(); if (settings.printBuildTrace) - printMsg(lvlError, format("@ build-failed %1% - %2% %3%") - % drvPath % 0 % e.msg()); + printMsg(lvlError, std::format("@ build-failed {} - {} {}", + drvPath, 0, e.msg())); worker.permanentFailure = true; done(BuildResult::InputRejected, e.msg()); return; @@ -1303,11 +1302,11 @@ void replaceValidPath(const Path & storePath, const Path tmpPath) tmpPath (the replacement), so we have to move it out of the way first. We'd better not be interrupted here, because if we're repairing (say) Glibc, we end up with a broken system. */ - Path oldPath = (format("%1%.old-%2%-%3%") % storePath % getpid() % rand()).str(); + Path oldPath = std::format("{}.old-{}-{}", storePath, getpid(), rand()); if (pathExists(storePath)) rename(storePath.c_str(), oldPath.c_str()); if (rename(tmpPath.c_str(), storePath.c_str()) == -1) - throw SysError(format("moving `%1%' to `%2%'") % tmpPath % storePath); + throw SysError(std::format("moving `{}' to `{}'", tmpPath, storePath)); if (pathExists(oldPath)) deletePath(oldPath); } @@ -1349,7 +1348,7 @@ static void secureFilePerms(Path path, bool allowSpecialFiles = false) /* FALLTHROUGH */ default: - throw Error(format("file `%1%' has an unsupported type") % path); + throw Error(std::format("file `{}' has an unsupported type", path)); } } @@ -1373,7 +1372,7 @@ void DerivationGoal::buildDone() status = pid.wait(true); } - debug(format("builder process for `%1%' finished") % drvPath); + debug(std::format("builder process for `{}' finished", drvPath)); /* So the child is gone now. */ worker.childTerminated(savedPid); @@ -1436,8 +1435,8 @@ void DerivationGoal::buildDone() if (diskFull) printMsg(lvlError, "note: build failure may have been caused by lack of free disk space"); - throw BuildError(format("builder for `%1%' %2%") - % drvPath % statusToString(status)); + throw BuildError(std::format("builder for `{}' {}", + drvPath, statusToString(status))); } if (fixedOutput) { @@ -1451,8 +1450,8 @@ void DerivationGoal::buildDone() copyFileRecursively(output, pivot, true); int err = rename(pivot.c_str(), output.c_str()); if (err != 0) - throw SysError(format("renaming `%1%' to `%2%'") - % pivot % output); + throw SysError(std::format("renaming `{}' to `{}'", + pivot, output)); } } } @@ -1496,20 +1495,20 @@ void DerivationGoal::buildDone() if (hook && WIFEXITED(status) && WEXITSTATUS(status) == 101) { if (settings.printBuildTrace) - printMsg(lvlError, format("@ build-failed %1% - timeout") % drvPath); + printMsg(lvlError, std::format("@ build-failed {} - timeout", drvPath)); st = BuildResult::TimedOut; } else if (hook && (!WIFEXITED(status) || WEXITSTATUS(status) != 100)) { if (settings.printBuildTrace) - printMsg(lvlError, format("@ hook-failed %1% - %2% %3%") - % drvPath % status % e.msg()); + printMsg(lvlError, std::format("@ hook-failed {} - {} {}", + drvPath, status, e.msg())); } else { if (settings.printBuildTrace) - printMsg(lvlError, format("@ build-failed %1% - %2% %3%") - % drvPath % 1 % e.msg()); + printMsg(lvlError, std::format("@ build-failed {} - {} {}", + drvPath, 1, e.msg())); st = statusOk(status) ? BuildResult::OutputRejected : @@ -1536,7 +1535,7 @@ void DerivationGoal::buildDone() buildUser.release(); if (settings.printBuildTrace) - printMsg(lvlError, format("@ build-succeeded %1% -") % drvPath); + printMsg(lvlError, std::format("@ build-succeeded {} -", drvPath)); done(BuildResult::Built); } @@ -1549,10 +1548,10 @@ HookReply DerivationGoal::tryBuildHook() if (!worker.hook) { Strings args = { "offload", - settings.thisSystem.c_str(), - (format("%1%") % settings.maxSilentTime).str().c_str(), - (format("%1%") % settings.printBuildTrace).str().c_str(), - (format("%1%") % settings.buildTimeout).str().c_str() + settings.thisSystem, + std::format("{}", settings.maxSilentTime), + std::format("{}", settings.printBuildTrace), + std::format("{}", settings.buildTimeout) }; worker.hook = std::make_shared(settings.guixProgram, args); @@ -1565,9 +1564,9 @@ HookReply DerivationGoal::tryBuildHook() for (auto& i : features) checkStoreName(i); /* !!! abuse */ /* Send the request to the hook. */ - writeLine(worker.hook->toAgent.writeSide, (format("%1% %2% %3% %4%") - % (worker.getNrLocalBuilds() < settings.maxBuildJobs ? "1" : "0") - % drv.platform % drvPath % concatStringsSep(",", features)).str()); + writeLine(worker.hook->toAgent.writeSide, std::format("{} {} {} {}", + (worker.getNrLocalBuilds() < settings.maxBuildJobs ? "1" : "0"), + drv.platform, drvPath, concatStringsSep(",", features))); /* Read the first line of input, which should be a word indicating whether the hook wishes to perform the build. */ @@ -1582,14 +1581,14 @@ HookReply DerivationGoal::tryBuildHook() writeToStderr(s); } - debug(format("hook reply is `%1%'") % reply); + debug(std::format("hook reply is `{}'", reply)); if (reply == "decline" || reply == "postpone") return reply == "decline" ? rpDecline : rpPostpone; else if (reply != "accept") - throw Error(format("bad hook reply `%1%'") % reply); + throw Error(std::format("bad hook reply `{}'", reply)); - printMsg(lvlTalkative, format("using hook to build path(s) %1%") % showPaths(missingPaths)); + printMsg(lvlTalkative, std::format("using hook to build path(s) {}", showPaths(missingPaths))); hook = worker.hook; worker.hook.reset(); @@ -1624,8 +1623,8 @@ HookReply DerivationGoal::tryBuildHook() worker.childStarted(shared_from_this(), hook->pid, fds, false, true); if (settings.printBuildTrace) - printMsg(lvlError, format("@ build-started %1% - %2% %3% %4%") - % drvPath % drv.platform % logFile % hook->pid); + printMsg(lvlError, std::format("@ build-started {} - {} {} {}", + drvPath, drv.platform, logFile, pid_t(hook->pid))); return rpAccept; } @@ -1634,7 +1633,7 @@ HookReply DerivationGoal::tryBuildHook() void chmod_(const Path & path, mode_t mode) { if (chmod(path.c_str(), mode) == -1) - throw SysError(format("setting permissions on `%1%'") % path); + throw SysError(std::format("setting permissions on `{}'", path)); } @@ -1652,7 +1651,7 @@ static void initializeUserNamespace(pid_t child, bool haveCapSetGID = false) { writeFile("/proc/" + std::to_string(child) + "/uid_map", - (format("%d %d 1") % guestUID % hostUID).str()); + std::format("{} {} 1", guestUID, hostUID)); if (!haveCapSetGID && !extraGIDs.empty()) { try { @@ -1668,8 +1667,8 @@ static void initializeUserNamespace(pid_t child, runProgram("newgidmap", true, args); printMsg(lvlChatty, - format("mapped %1% extra GIDs into namespace of PID %2%") - % extraGIDs.size() % child); + std::format("mapped {} extra GIDs into namespace of PID {}", + extraGIDs.size(), child)); return; } catch (const ExecError &e) { @@ -1680,10 +1679,10 @@ static void initializeUserNamespace(pid_t child, if (!haveCapSetGID) writeFile("/proc/" + std::to_string(child) + "/setgroups", "deny"); - auto content = (format("%d %d 1\n") % guestGID % hostGID).str(); + auto content = std::format("{} {} 1\n", guestGID, hostGID); if (haveCapSetGID) { for (auto &mapping: extraGIDs) { - content += (format("%d %d 1\n") % mapping.second % mapping.first).str(); + content += std::format("{} {} 1\n", mapping.second, mapping.first); } } writeFile("/proc/" + std::to_string(child) + "/gid_map", content); @@ -1963,7 +1962,7 @@ static void prepareSlirpChrootAction(SpawnContext & sctx) struct stat st; if(stat(fs.c_str(), &st) != 0) { if(errno == EACCES) continue; /* Not accessible anyway */ - else throw SysError(format("stat of `%1%'") % fs); + else throw SysError(std::format("stat of `{}'", fs)); } ctx.readOnlyFilesInChroot.insert(fs); @@ -2408,7 +2407,7 @@ void DerivationGoal::execBuilderOrBuiltin(SpawnContext & ctx) buildDrv(drv, drvPath, output); } else - throw Error(format("unsupported builtin function '%1%'") % string(drv.builder, 8)); + throw Error(std::format("unsupported builtin function '{}'", string(drv.builder, 8))); _exit(0); } catch (std::exception & e) { writeFull(STDERR_FILENO, "error: " + string(e.what()) + "\n"); @@ -2427,7 +2426,7 @@ void DerivationGoal::execBuilderOrBuiltin(SpawnContext & ctx) chroot. */ ctx.program = canonPath(ctx.program, true); if(!isInStore(ctx.program)) - throw Error(format("derivation builder `%1' is outside the store") % ctx.program); + throw Error(std::format("derivation builder `{}' is outside the store", ctx.program)); /* If DRV targets the same operating system kernel, try to execute it: there might be binfmt_misc set up for user-land emulation of other architectures. However, if it targets a different operating @@ -2450,13 +2449,13 @@ void DerivationGoal::execBuilderOrBuiltin(SpawnContext & ctx) that invoke QEMU. */ if (error == ENOEXEC && !canBuildLocally(drv.platform)) { if (settings.printBuildTrace) - printMsg(lvlError, format("@ unsupported-platform %1% %2%") % drvPath % drv.platform); - throw Error(format("a `%1%' is required to build `%3%', but I am a `%2%'") - % drv.platform % settings.thisSystem % drvPath); + printMsg(lvlError, std::format("@ unsupported-platform {} {}", drvPath, drv.platform)); + throw Error(std::format("a `{}' is required to build `{}', but I am a `{}'", + drv.platform, settings.thisSystem, drvPath)); } errno = error; - throw SysError(format("executing `%1%'") % drv.builder); + throw SysError(std::format("executing `{}'", drv.builder)); } @@ -2468,13 +2467,14 @@ void execBuilderOrBuiltinAction(SpawnContext & ctx) void DerivationGoal::startBuilder() { - auto f = format( - buildMode == bmRepair ? "repairing path(s) %1%" : - buildMode == bmCheck ? "checking path(s) %1%" : - nrRounds > 1 ? "building path(s) %1% (round %2%/%3%)" : - "building path(s) %1%"); - f.exceptions(boost::io::all_error_bits ^ boost::io::too_many_args_bit); - startNest(nest, lvlInfo, f % showPaths(missingPaths) % curRound % nrRounds); + auto path = showPaths(missingPaths); + auto f = std::vformat( + buildMode == bmRepair ? "repairing path(s) {0}" : + buildMode == bmCheck ? "checking path(s) {0}" : + nrRounds > 1 ? "building path(s) {0} (round {1}/{2})" : + "building path(s) {0}", + std::make_format_args(path, curRound, nrRounds)); + startNest(nest, lvlInfo, f); /* A ChrootBuildSpawnContext reference can be passed to procedures expecting a SpawnContext reference */ @@ -2558,7 +2558,7 @@ void DerivationGoal::startBuilder() ctx.env["NIX_STORE"] = settings.nixStore; /* The maximum number of cores to utilize for parallel building. */ - ctx.env["NIX_BUILD_CORES"] = (format("%d") % settings.buildCores).str(); + ctx.env["NIX_BUILD_CORES"] = std::format("{}", settings.buildCores); /* Add all bindings specified in the derivation. */ for (auto& i : drv.env) @@ -2630,7 +2630,7 @@ void DerivationGoal::startBuilder() string s = get(drv.env, "exportReferencesGraph"); Strings ss = tokenizeString(s); if (ss.size() % 2 != 0) - throw BuildError(format("odd number of tokens in `exportReferencesGraph': `%1%'") % s); + throw BuildError(std::format("odd number of tokens in `exportReferencesGraph': `{}'", s)); for (Strings::iterator i = ss.begin(); i != ss.end(); ) { string fileName = *i++; checkStoreName(fileName); /* !!! abuse of this function */ @@ -2638,12 +2638,12 @@ void DerivationGoal::startBuilder() /* Check that the store path is valid. */ Path storePath = *i++; if (!isInStore(storePath)) - throw BuildError(format("`exportReferencesGraph' contains a non-store path `%1%'") - % storePath); + throw BuildError(std::format("`exportReferencesGraph' contains a non-store path `{}'", + storePath)); storePath = toStorePath(storePath); if (!worker.store.isValidPath(storePath)) - throw BuildError(format("`exportReferencesGraph' contains an invalid path `%1%'") - % storePath); + throw BuildError(std::format("`exportReferencesGraph' contains an invalid path `{}'", + storePath)); /* If there are derivations in the graph, then include their outputs as well. This is useful if you want to do things @@ -2680,7 +2680,7 @@ void DerivationGoal::startBuilder() /* Change ownership of the temporary build directory. */ if (chown(tmpDir.c_str(), buildUser.getUID(), buildUser.getGID()) == -1) - throw SysError(format("cannot change ownership of '%1%'") % tmpDir); + throw SysError(std::format("cannot change ownership of '{}'", tmpDir)); ctx.setuid = true; ctx.user = buildUser.getUID(); @@ -2711,7 +2711,7 @@ void DerivationGoal::startBuilder() if(fixedOutput) { if(findProgram(settings.slirp4netns) == "") - printMsg(lvlError, format("`%1%' can't be found in PATH, network access disabled") % settings.slirp4netns); + printMsg(lvlError, std::format("`{}' can't be found in PATH, network access disabled", settings.slirp4netns)); else { if(!pathExists("/dev/net/tun")) printMsg(lvlError, "`/dev/net/tun' is missing, network access disabled"); @@ -2737,15 +2737,15 @@ void DerivationGoal::startBuilder() ctx.hostname = "localhost"; ctx.domainname = "(none)"; /* kernel default */ - printMsg(lvlChatty, format("setting up chroot environment in `%1%'") % chrootRootDir); + printMsg(lvlChatty, std::format("setting up chroot environment in `{}'", chrootRootDir)); if (mkdir(chrootRootTop.c_str(), 0750) == -1) - throw SysError(format("cannot create build root container '%1%'") % chrootRootTop); + throw SysError(std::format("cannot create build root container '{}'", chrootRootTop)); if (mkdir(chrootRootDir.c_str(), 0750) == -1) - throw SysError(format("cannot create build root '%1%'") % chrootRootDir); + throw SysError(std::format("cannot create build root '{}'", chrootRootDir)); if (buildUser.enabled() && chown(chrootRootDir.c_str(), 0, buildUser.getGID()) == -1) - throw SysError(format("cannot change ownership of ‘%1%’") % chrootRootDir); + throw SysError(std::format("cannot change ownership of `{}'", chrootRootDir)); /* Create a writable /tmp in the chroot. Many builders need this. (Of course they should really respect $TMPDIR @@ -2760,17 +2760,17 @@ void DerivationGoal::startBuilder() createDirs(chrootRootDir + "/etc"); writeFile(chrootRootDir + "/etc/passwd", - (format( - "nixbld:x:%1%:%2%:Nix build user:/:/noshell\n" - "nobody:x:65534:65534:Nobody:/:/noshell\n") - % (buildUser.enabled() ? buildUser.getUID() : guestUID) - % (buildUser.enabled() ? buildUser.getGID() : guestGID)).str()); + std::format( + "nixbld:x:{}:{}:Nix build user:/:/noshell\n" + "nobody:x:65534:65534:Nobody:/:/noshell\n", + buildUser.enabled() ? buildUser.getUID() : guestUID, + buildUser.enabled() ? buildUser.getGID() : guestGID)); /* Declare the build user's group so that programs get a consistent view of the system (e.g., "id -gn"). */ writeFile(chrootRootDir + "/etc/group", - (format("nixbld:!:%1%:\n") - % (buildUser.enabled() ? buildUser.getGID() : guestGID)).str()); + std::format("nixbld:!:{}:\n", + buildUser.enabled() ? buildUser.getGID() : guestGID)); if (fixedOutput) { /* Fixed-output derivations typically need to access the network, @@ -2834,7 +2834,7 @@ void DerivationGoal::startBuilder() if (buildUser.enabled() && chown(chrootStoreDir.c_str(), 0, buildUser.getGID()) == -1) /* As an extra security precaution, make the fake store only writable by the build user. */ - throw SysError(format("cannot change ownership of ‘%1%’") % chrootStoreDir); + throw SysError(std::format("cannot change ownership of `{}'", chrootStoreDir)); /* Make the closure of the inputs available in the chroot, rather than the whole store. This prevents any access to undeclared @@ -2902,7 +2902,7 @@ void DerivationGoal::startBuilder() ctx.phases = getBasicSpawnPhases(); if (pathExists(homeDir)) - throw Error(format("directory `%1%' exists; please remove it") % homeDir); + throw Error(std::format("directory `{}' exists; please remove it", homeDir)); /* We're not doing a chroot build, but we have some valid output paths. Since we can't just overwrite or delete @@ -2930,7 +2930,7 @@ void DerivationGoal::startBuilder() replacePhase(ctx.phases, "exec", execBuilderOrBuiltinAction); /* Run the builder. */ - printMsg(lvlChatty, format("executing builder `%1%'") % drv.builder); + printMsg(lvlChatty, std::format("executing builder `{}'", drv.builder)); /* Create the log file. */ Path logFile = openLogFile(); @@ -3070,8 +3070,8 @@ void DerivationGoal::startBuilder() if (!msg.empty()) throw Error(msg); if (settings.printBuildTrace) { - printMsg(lvlError, format("@ build-started %1% - %2% %3% %4%") - % drvPath % drv.platform % logFile % pid); + printMsg(lvlError, std::format("@ build-started {} - {} {} {}", + drvPath, drv.platform, logFile, pid_t(pid))); } } @@ -3090,8 +3090,7 @@ PathSet parseReferenceSpecifiers(const Derivation & drv, string attr) else if (drv.outputs.find(i) != drv.outputs.end()) result.insert(drv.outputs.find(i)->second.path); else throw BuildError( - format("derivation contains an invalid reference specifier `%1%'") - % i); + std::format("derivation contains an invalid reference specifier `{}'", i)); } return result; } @@ -3142,9 +3141,9 @@ void DerivationGoal::registerOutputs() if (lstat(actualPath.c_str(), &st) == -1) { if (errno == ENOENT) throw BuildError( - format("builder for `%1%' failed to produce output path `%2%'") - % drvPath % path); - throw SysError(format("getting attributes of path `%1%'") % actualPath); + std::format("builder for `{}' failed to produce output path `{}'", + drvPath, path)); + throw SysError(std::format("getting attributes of path `{}'", actualPath)); } #ifndef __CYGWIN__ @@ -3154,13 +3153,13 @@ void DerivationGoal::registerOutputs() user. */ if ((!S_ISLNK(st.st_mode) && (st.st_mode & (S_IWGRP | S_IWOTH))) || (buildUser.enabled() && st.st_uid != buildUser.getUID())) - throw BuildError(format("suspicious ownership or permission on `%1%'; rejecting this build output") % path); + throw BuildError(std::format("suspicious ownership or permission on `{}'; rejecting this build output", path)); #endif /* Apply hash rewriting if necessary. */ bool rewritten = false; if (!rewritesFromTmp.empty()) { - printMsg(lvlError, format("warning: rewriting hashes in `%1%'; cross fingers") % path); + printMsg(lvlError, std::format("warning: rewriting hashes in `{}'; cross fingers", path)); /* Canonicalise first. This ensures that the path we're rewriting doesn't contain a hard link to /etc/shadow or @@ -3179,7 +3178,7 @@ void DerivationGoal::registerOutputs() } startNest(nest, lvlTalkative, - format("scanning for references inside `%1%'") % path); + std::format("scanning for references inside `{}'", path)); /* Check that fixed-output derivations produced the right outputs (i.e., the content hash should match the specified @@ -3194,17 +3193,17 @@ void DerivationGoal::registerOutputs() execute permission. */ if (!S_ISREG(st.st_mode) || (st.st_mode & S_IXUSR) != 0) throw BuildError( - format("output path `%1% should be a non-executable regular file") % path); + std::format("output path `{}' should be a non-executable regular file", path)); } /* Check the hash. */ Hash h2 = recursive ? hashPath(ht, actualPath).first : hashFile(ht, actualPath); if (h != h2) { if (settings.printBuildTrace) - printMsg(lvlError, format("@ hash-mismatch %1% %2% %3% %4%") - % path % i.second.hashAlgo - % printHash16or32(h) % printHash16or32(h2)); - throw BuildError(format("hash mismatch for store item '%1%'") % path); + printMsg(lvlError, std::format("@ hash-mismatch {} {} {} {}", + path, i.second.hashAlgo, + printHash16or32(h), printHash16or32(h2))); + throw BuildError(std::format("hash mismatch for store item '{}'", path)); } } @@ -3224,16 +3223,16 @@ void DerivationGoal::registerOutputs() if (buildMode != bmCheck) { if (S_ISDIR(st.st_mode)) { if (lstat(actualPath.c_str(), &st) == -1) - throw SysError(format("getting canonicalized permissions of directory `%1%'") % actualPath); + throw SysError(std::format("getting canonicalized permissions of directory `{}'", actualPath)); /* Change mode on the directory to allow for rename(2). */ if (chmod(actualPath.c_str(), st.st_mode | 0700) == -1) - throw SysError(format("making `%1%' writable for move from chroot to store") % actualPath); + throw SysError(std::format("making `{}' writable for move from chroot to store", actualPath)); } if (rename(actualPath.c_str(), path.c_str()) == -1) - throw SysError(format("moving build output `%1%' from the chroot to the store") % path); + throw SysError(std::format("moving build output `{}' from the chroot to the store", path)); if (S_ISDIR(st.st_mode) && chmod(path.c_str(), st.st_mode) == -1) - throw SysError(format("restoring permissions on directory `%1%'") % actualPath); + throw SysError(std::format("restoring permissions on directory `{}'", actualPath)); } } if (buildMode != bmCheck) actualPath = path; @@ -3254,16 +3253,16 @@ void DerivationGoal::registerOutputs() Path dst = path + checkSuffix; if (pathExists(dst)) deletePath(dst); if (rename(actualPath.c_str(), dst.c_str())) - throw SysError(format("renaming `%1%' to `%2%'") % actualPath % dst); - throw Error(format("derivation `%1%' may not be deterministic: output `%2%' differs from `%3%'") - % drvPath % path % dst); + throw SysError(std::format("renaming `{}' to `{}'", actualPath, dst)); + throw Error(std::format("derivation `{}' may not be deterministic: output `{}' differs from `{}'", + drvPath, path, dst)); } else - throw Error(format("derivation `%1%' may not be deterministic: output `%2%' differs") - % drvPath % path); + throw Error(std::format("derivation `{}' may not be deterministic: output `{}' differs", + drvPath, path)); } if (settings.printBuildTrace) - printMsg(lvlError, format("@ build-succeeded %1% -") % drvPath); + printMsg(lvlError, std::format("@ build-succeeded {} -", drvPath)); continue; } @@ -3273,9 +3272,9 @@ void DerivationGoal::registerOutputs() for (auto& i : inputPaths) { PathSet::iterator j = references.find(i); if (j == references.end()) - debug(format("unreferenced input: `%1%'") % i); + debug(std::format("unreferenced input: `{}'", i)); else - debug(format("referenced input: `%1%'") % i); + debug(std::format("referenced input: `{}'", i)); } /* Enforce `allowedReferences' and friends. */ @@ -3297,10 +3296,10 @@ void DerivationGoal::registerOutputs() for (auto & i : used) if (allowed) { if (spec.find(i) == spec.end()) - throw BuildError(format("output (`%1%') is not allowed to refer to path `%2%'") % actualPath % i); + throw BuildError(std::format("output (`{}') is not allowed to refer to path `{}'", actualPath, i)); } else { if (spec.find(i) != spec.end()) - throw BuildError(format("output (`%1%') is not allowed to refer to path `%2%'") % actualPath % i); + throw BuildError(std::format("output (`{}') is not allowed to refer to path `{}'", actualPath, i)); } }; @@ -3333,12 +3332,12 @@ void DerivationGoal::registerOutputs() Path prev = i->path + checkSuffix; if (pathExists(prev)) throw NotDeterministic( - format("output ‘%1%’ of ‘%2%’ differs from ‘%3%’ from previous round") - % i->path % drvPath % prev); + std::format("output `{}' of `{}' differs from `{}' from previous round", + i->path, drvPath, prev)); else throw NotDeterministic( - format("output ‘%1%’ of ‘%2%’ differs from previous round") - % i->path % drvPath); + std::format("output `{}' of `{}' differs from previous round", + i->path, drvPath)); } assert(false); // shouldn't happen } @@ -3350,7 +3349,7 @@ void DerivationGoal::registerOutputs() if (curRound < nrRounds) { Path dst = i.second.path + checkSuffix; if (rename(i.second.path.c_str(), dst.c_str())) - throw SysError(format("renaming ‘%1%’ to ‘%2%’") % i.second.path % dst); + throw SysError(std::format("renaming `{}' to `{}'", i.second.path, dst)); } } @@ -3380,20 +3379,20 @@ Path DerivationGoal::openLogFile() string baseName = baseNameOf(drvPath); /* Create a log file. */ - Path dir = (format("%1%/%2%/%3%/") % settings.nixLogDir % drvsLogDir % string(baseName, 0, 2)).str(); + Path dir = std::format("{}/{}/{}/", settings.nixLogDir, drvsLogDir, string(baseName, 0, 2)); createDirs(dir); switch (settings.logCompression) { case COMPRESSION_GZIP: { - Path logFileName = (format("%1%/%2%.gz") % dir % string(baseName, 2)).str(); + Path logFileName = std::format("{}/{}.gz", dir, string(baseName, 2)); AutoCloseFD fd = open(logFileName.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0666); - if (fd == -1) throw SysError(format("creating log file `%1%'") % logFileName); + if (fd == -1) throw SysError(std::format("creating log file `{}'", logFileName)); closeOnExec(fd); /* Note: FD will be closed by 'gzclose'. */ if (!(gzLogFile = gzdopen(fd.borrow(), "w"))) - throw Error(format("cannot open compressed log file `%1%'") % logFileName); + throw Error(std::format("cannot open compressed log file `{}'", logFileName)); gzbuffer(gzLogFile, 32768); gzsetparams(gzLogFile, Z_BEST_COMPRESSION, Z_DEFAULT_STRATEGY); @@ -3403,26 +3402,26 @@ Path DerivationGoal::openLogFile() #if HAVE_BZLIB_H case COMPRESSION_BZIP2: { - Path logFileName = (format("%1%/%2%.bz2") % dir % string(baseName, 2)).str(); + Path logFileName = std::format("{}/{}.bz2", dir, string(baseName, 2)); AutoCloseFD fd = open(logFileName.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0666); - if (fd == -1) throw SysError(format("creating log file `%1%'") % logFileName); + if (fd == -1) throw SysError(std::format("creating log file `{}'", logFileName)); closeOnExec(fd); if (!(fLogFile = fdopen(fd.borrow(), "w"))) - throw SysError(format("opening log file `%1%'") % logFileName); + throw SysError(std::format("opening log file `{}'", logFileName)); int err; if (!(bzLogFile = BZ2_bzWriteOpen(&err, fLogFile, 9, 0, 0))) - throw Error(format("cannot open compressed log file `%1%'") % logFileName); + throw Error(std::format("cannot open compressed log file `{}'", logFileName)); return logFileName; } #endif case COMPRESSION_NONE: { - Path logFileName = (format("%1%/%2%") % dir % string(baseName, 2)).str(); + Path logFileName = std::format("{}/{}", dir, string(baseName, 2)); fdLogFile = open(logFileName.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0666); - if (fdLogFile == -1) throw SysError(format("creating log file `%1%'") % logFileName); + if (fdLogFile == -1) throw SysError(std::format("creating log file `{}'", logFileName)); closeOnExec(fdLogFile); return logFileName; } @@ -3438,14 +3437,14 @@ void DerivationGoal::closeLogFile() int err; err = gzclose(gzLogFile); gzLogFile = NULL; - if (err != Z_OK) throw Error(format("cannot close compressed log file (gzip error = %1%)") % err); + if (err != Z_OK) throw Error(std::format("cannot close compressed log file (gzip error = {})", err)); } #if HAVE_BZLIB_H else if (bzLogFile) { int err; BZ2_bzWriteClose(&err, bzLogFile, 0, 0, 0); bzLogFile = 0; - if (err != BZ_OK) throw Error(format("cannot close compressed log file (BZip2 error = %1%)") % err); + if (err != BZ_OK) throw Error(std::format("cannot close compressed log file (BZip2 error = {})", err)); } #endif @@ -3463,7 +3462,7 @@ static void _chown(const Path & path, uid_t uid, gid_t gid) checkInterrupt(); if (lchown(path.c_str(), uid, gid) == -1) { - throw SysError(format("change owner and group of `%1%'") % path); + throw SysError(std::format("change owner and group of `{}'", path)); } struct stat st = lstat(path); if (S_ISDIR(st.st_mode)) { @@ -3486,8 +3485,7 @@ void DerivationGoal::deleteTmpDir(bool force) if (settings.keepFailed && !force) { printMsg(lvlError, - format("note: keeping build directory `%2%'") - % drvPath % top); + std::format("note: keeping build directory `{}'", top)); chmod(tmpDir.c_str(), 0755); // Change the ownership if clientUid is set. Never change the @@ -3516,8 +3514,8 @@ void DerivationGoal::deleteTmpDir(bool force) /* When running as an unprivileged user and without CAP_CHOWN, we cannot chown the build tree. Print a message and keep going. */ - printMsg(lvlInfo, format("cannot change ownership of build directory '%1%': %2%") - % tmpDir % strerror(e.errNo)); + printMsg(lvlInfo, std::format("cannot change ownership of build directory '{}': {}", + tmpDir, strerror(e.errNo))); } if (top != tmpDir) { @@ -3568,8 +3566,8 @@ void DerivationGoal::handleChildOutput(int fd, const string & data) logSize += data.size(); if (settings.maxLogSize && logSize > settings.maxLogSize) { printMsg(lvlError, - format("%1% killed after writing more than %2% bytes of log output") - % getName() % settings.maxLogSize); + std::format("{} killed after writing more than {} bytes of log output", + getName(), settings.maxLogSize)); timedOut(); // not really a timeout, but close enough return; } @@ -3580,13 +3578,13 @@ void DerivationGoal::handleChildOutput(int fd, const string & data) if (data.size() > 0) { int count, err; count = gzwrite(gzLogFile, data.data(), data.size()); - if (count == 0) throw Error(format("cannot write to compressed log file (gzip error = %1%)") % gzerror(gzLogFile, &err)); + if (count == 0) throw Error(std::format("cannot write to compressed log file (gzip error = {})", gzerror(gzLogFile, &err))); } #if HAVE_BZLIB_H } else if (bzLogFile) { int err; BZ2_bzWrite(&err, bzLogFile, (unsigned char *) data.data(), data.size()); - if (err != BZ_OK) throw Error(format("cannot write to compressed log file (BZip2 error = %1%)") % err); + if (err != BZ_OK) throw Error(std::format("cannot write to compressed log file (BZip2 error = {})", err)); #endif } else if (fdLogFile != -1) writeFull(fdLogFile, data); @@ -3623,10 +3621,10 @@ bool DerivationGoal::pathFailed(const Path & path) if (!worker.store.hasPathFailed(path)) return false; - printMsg(lvlError, format("builder for `%1%' failed previously (cached)") % path); + printMsg(lvlError, std::format("builder for `{}' failed previously (cached)", path)); if (settings.printBuildTrace) - printMsg(lvlError, format("@ build-failed %1% - cached") % drvPath); + printMsg(lvlError, std::format("@ build-failed {} - cached", drvPath)); done(BuildResult::CachedFailure); @@ -3644,8 +3642,8 @@ Path DerivationGoal::addHashRewrite(const Path & path) rewritesToTmp[h1] = h2; rewritesFromTmp[h2] = h1; redirectedOutputs[path] = p; - printMsg(lvlChatty, format("output '%1%' redirected to '%2%'") - % path % p); + printMsg(lvlChatty, std::format("output '{}' redirected to '{}'", + path, p)); return p; } @@ -3734,7 +3732,7 @@ SubstitutionGoal::SubstitutionGoal(const Path & storePath, Worker & worker, bool { this->storePath = storePath; state = &SubstitutionGoal::init; - name = (format("substitution of `%1%'") % storePath).str(); + name = std::format("substitution of `{}'", storePath); trace("created"); } @@ -3748,7 +3746,7 @@ SubstitutionGoal::~SubstitutionGoal() void SubstitutionGoal::timedOut() { if (settings.printBuildTrace) - printMsg(lvlError, format("@ substituter-failed %1% timeout") % storePath); + printMsg(lvlError, std::format("@ substituter-failed {} timeout", storePath)); if (substituter) { pid_t savedPid = substituter->pid; substituter.reset(); @@ -3777,7 +3775,7 @@ void SubstitutionGoal::init() } if (settings.readOnlyMode) - throw Error(format("cannot substitute path `%1%' - no write access to the store") % storePath); + throw Error(std::format("cannot substitute path `{}' - no write access to the store", storePath)); tryNext(); } @@ -3794,7 +3792,7 @@ void SubstitutionGoal::tryNext() if (k == infos.end()) { /* None left. Terminate this goal and let someone else deal with it. */ - debug(format("path `%1%' is required, but there is no substituter that can build it") % storePath); + debug(std::format("path `{}' is required, but there is no substituter that can build it", storePath)); /* Hack: don't indicate failure if there were no substituters. In that case the calling derivation should just do a build. */ @@ -3823,7 +3821,7 @@ void SubstitutionGoal::referencesValid() trace("all references realised"); if (nrFailed > 0) { - debug(format("some references of path `%1%' could not be realised") % storePath); + debug(std::format("some references of path `{}' could not be realised", storePath)); amDone(nrNoSubstituters > 0 || nrIncompleteClosure > 0 ? ecIncompleteClosure : ecFailed); return; } @@ -3855,8 +3853,8 @@ void SubstitutionGoal::tryToRun() first, but let's be defensive). */ outputLock.reset(); // make sure this goal's lock is gone if (pathIsLockedByMe(storePath)) { - debug(format("restarting substitution of `%1%' because it's locked by another goal") - % storePath); + debug(std::format("restarting substitution of `{}' because it's locked by another goal", + storePath)); worker.waitForAnyGoal(shared_from_this()); return; /* restart in the tryToRun() state when another goal finishes */ } @@ -3870,14 +3868,14 @@ void SubstitutionGoal::tryToRun() /* Check again whether the path is invalid. */ if (!repair && worker.store.isValidPath(storePath)) { - debug(format("store path `%1%' has become valid") % storePath); + debug(std::format("store path `{}' has become valid", storePath)); outputLock->setDeletion(true); outputLock.reset(); amDone(ecSuccess); return; } - printMsg(lvlInfo, format("fetching path `%1%'...") % storePath); + printMsg(lvlInfo, std::format("fetching path `{}'...", storePath)); destPath = repair ? storePath + ".tmp" : storePath; @@ -3901,7 +3899,7 @@ void SubstitutionGoal::tryToRun() /* Send the request to the substituter. */ writeLine(substituter->toAgent.writeSide, - (format("substitute %1% %2%") % storePath % destPath).str()); + std::format("substitute {} {}", storePath, destPath)); set fds; fds.insert(substituter->fromAgent.readSide); @@ -3913,7 +3911,7 @@ void SubstitutionGoal::tryToRun() if (settings.printBuildTrace) /* The second element in the message used to be the name of the substituter but we're left with only one. */ - printMsg(lvlError, format("@ substituter-started %1% substitute") % storePath); + printMsg(lvlError, std::format("@ substituter-started {} substitute", storePath)); } @@ -3939,35 +3937,33 @@ void SubstitutionGoal::finished() auto statusList = tokenizeString >(status); if (statusList.empty()) { - throw SubstError(format("fetching path `%1%' (empty status)") - % storePath); + throw SubstError(std::format("fetching path `{}' (empty status)", storePath)); } else if (statusList[0] == "hash-mismatch") { if (settings.printBuildTrace) { auto hashType = statusList[1]; auto expectedHash = statusList[2]; auto actualHash = statusList[3]; - printMsg(lvlError, format("@ hash-mismatch %1% %2% %3% %4%") - % storePath - % hashType % expectedHash % actualHash); + printMsg(lvlError, std::format("@ hash-mismatch {} {} {} {}", + storePath, hashType, expectedHash, actualHash)); } - throw SubstError(format("hash mismatch for substituted item `%1%'") % storePath); + throw SubstError(std::format("hash mismatch for substituted item `{}'", storePath)); } else if (statusList[0] == "success") { if (!pathExists(destPath)) - throw SubstError(format("substitute did not produce path `%1%'") % destPath); + throw SubstError(std::format("substitute did not produce path `{}'", destPath)); std::string hashStr = statusList[1]; size_t n = hashStr.find(':'); if (n == string::npos) - throw Error(format("bad hash from substituter: %1%") % hashStr); + throw Error(std::format("bad hash from substituter: {}", hashStr)); HashType hashType = parseHashType(string(hashStr, 0, n)); switch (hashType) { case htUnknown: - throw Error(format("unknown hash algorithm in `%1%'") % hashStr); + throw Error(std::format("unknown hash algorithm in `{}'", hashStr)); case htSHA256: hash.first = parseHash16or32(hashType, string(hashStr, n + 1)); if (!string2Int(statusList[2], hash.second)) - throw Error(format("invalid nar size for '%1%' substitute") % storePath); + throw Error(std::format("invalid nar size for '{}' substitute", storePath)); break; default: /* The database only stores SHA256 hashes, so compute it. */ @@ -3976,16 +3972,16 @@ void SubstitutionGoal::finished() } } else - throw SubstError(format("fetching path `%1%' (status: '%2%')") - % storePath % status); + throw SubstError(std::format("fetching path `{}' (status: '{}')", + storePath, status)); } catch (SubstError & e) { printMsg(lvlInfo, e.msg()); if (settings.printBuildTrace) { - printMsg(lvlError, format("@ substituter-failed %1% %2% %3%") - % storePath % status % e.msg()); + printMsg(lvlError, std::format("@ substituter-failed {} {} {}", + storePath, status, e.msg())); } amDone(ecFailed); @@ -4011,10 +4007,10 @@ void SubstitutionGoal::finished() worker.store.markContentsGood(storePath); printMsg(lvlChatty, - format("substitution of path `%1%' succeeded") % storePath); + std::format("substitution of path `{}' succeeded", storePath)); if (settings.printBuildTrace) - printMsg(lvlError, format("@ substituter-succeeded %1%") % storePath); + printMsg(lvlError, std::format("@ substituter-succeeded {}", storePath)); amDone(ecSuccess); } @@ -4042,7 +4038,7 @@ void SubstitutionGoal::handleChildOutput(int fd, const string & data) status = trimmed; worker.wakeUp(shared_from_this()); } else { - printMsg(lvlError, format("unexpected substituter message '%1%'") % input); + printMsg(lvlError, std::format("unexpected substituter message '{}'", input)); } input = (end != string::npos) ? input.substr(end + 1) : ""; @@ -4234,7 +4230,7 @@ void Worker::run(const Goals & _topGoals) { for (auto& i : _topGoals) topGoals.insert(i); - startNest(nest, lvlDebug, format("entered goal loop")); + startNest(nest, lvlDebug, "entered goal loop"); while (1) { @@ -4308,7 +4304,7 @@ void Worker::waitForInput() if (nearest != LONG_MAX) { timeout.tv_sec = std::max((time_t) 1, nearest - before); useTimeout = true; - printMsg(lvlVomit, format("sleeping %1% seconds") % timeout.tv_sec); + printMsg(lvlVomit, std::format("sleeping {} seconds", timeout.tv_sec)); } /* If we are polling goals that are waiting for a lock, then wake @@ -4365,15 +4361,14 @@ void Worker::waitForInput() ssize_t rd = read(k, buffer, sizeof(buffer)); if (rd == -1) { if (errno != EINTR) - throw SysError(format("reading from %1%") - % goal->getName()); + throw SysError(std::format("reading from {}", goal->getName())); } else if (rd == 0) { - debug(format("%1%: got EOF") % goal->getName()); + debug(std::format("{}: got EOF", goal->getName())); goal->handleEOF(k); j->second.fds.erase(k); } else { - printMsg(lvlVomit, format("%1%: read %2% bytes") - % goal->getName() % rd); + printMsg(lvlVomit, std::format("{}: read {} bytes", + goal->getName(), rd)); string data((char *) buffer, rd); j->second.lastOutput = after; goal->handleChildOutput(k, data); @@ -4387,8 +4382,8 @@ void Worker::waitForInput() after - j->second.lastOutput >= (time_t) settings.maxSilentTime) { printMsg(lvlError, - format("%1% timed out after %2% seconds of silence") - % goal->getName() % settings.maxSilentTime); + std::format("{} timed out after {} seconds of silence", + goal->getName(), settings.maxSilentTime)); goal->timedOut(); } @@ -4398,8 +4393,8 @@ void Worker::waitForInput() after - j->second.timeStarted >= (time_t) settings.buildTimeout) { printMsg(lvlError, - format("%1% timed out after %2% seconds") - % goal->getName() % settings.buildTimeout); + std::format("{} timed out after %2% seconds", + goal->getName(), settings.buildTimeout)); goal->timedOut(); } } @@ -4427,7 +4422,7 @@ unsigned int Worker::exitStatus() void LocalStore::buildPaths(const PathSet & drvPaths, BuildMode buildMode) { startNest(nest, lvlDebug, - format("building %1%") % showPaths(drvPaths)); + std::format("building {}", showPaths(drvPaths))); Worker worker(*this); @@ -4451,7 +4446,7 @@ void LocalStore::buildPaths(const PathSet & drvPaths, BuildMode buildMode) } if (!failed.empty()) - throw Error(format("build of %1% failed") % showPaths(failed), worker.exitStatus()); + throw Error(std::format("build of {} failed", showPaths(failed)), worker.exitStatus()); } @@ -4467,7 +4462,7 @@ void LocalStore::ensurePath(const Path & path) worker.run(goals); if (goal->getExitCode() != Goal::ecSuccess) - throw Error(format("path `%1%' does not exist and cannot be created") % path, worker.exitStatus()); + throw Error(std::format("path `{}' does not exist and cannot be created", path), worker.exitStatus()); } @@ -4488,7 +4483,7 @@ void LocalStore::repairPath(const Path & path) goals.insert(worker.makeDerivationGoal(deriver, StringSet(), bmRepair)); worker.run(goals); } else - throw Error(format("cannot repair path `%1%'") % path, worker.exitStatus()); + throw Error(std::format("cannot repair path `{}'", path), worker.exitStatus()); } } diff --git a/nix/libstore/builtins.cc b/nix/libstore/builtins.cc index 6bf467354a5a472cc6eac4533c428bcfd300b59a..b1a32480b55141b57d1462d306a413660f470419 100644 --- a/nix/libstore/builtins.cc +++ b/nix/libstore/builtins.cc @@ -22,6 +22,7 @@ #include #include +#include namespace nix { @@ -53,7 +54,7 @@ static void builtinDownload(const Derivation &drv, const string program = settings.guixProgram; execv(program.c_str(), (char *const *) argv); - throw SysError(format("failed to run download program '%1%'") % program); + throw SysError(std::format("failed to run download program '{}'", program)); } static const std::map builtins = diff --git a/nix/libstore/builtins.hh b/nix/libstore/builtins.hh index 396ea14ebc08146fe62a13a293338b8e73767628..602a5a1c58d0aebbc1401e0143647f431d8ac5eb 100644 --- a/nix/libstore/builtins.hh +++ b/nix/libstore/builtins.hh @@ -21,7 +21,6 @@ #pragma once #include -#include #include namespace nix { diff --git a/nix/libstore/derivations.cc b/nix/libstore/derivations.cc index 0c3a249228dd8d23aa4c68c6596caa3433def0e1..c253a2a438a4903614c11b6f8f404ba9f27817c2 100644 --- a/nix/libstore/derivations.cc +++ b/nix/libstore/derivations.cc @@ -4,6 +4,9 @@ #include "util.hh" #include "misc.hh" +#include + +#include namespace nix { @@ -20,7 +23,7 @@ void DerivationOutput::parseHashInfo(bool & recursive, HashType & hashType, Hash hashType = parseHashType(algo); if (hashType == htUnknown) - throw Error(format("unknown hash algorithm `%1%'") % algo); + throw Error(std::format("unknown hash algorithm `{}'", algo)); hash = parseHash(hashType, this->hash); } @@ -48,7 +51,7 @@ static Path parsePath(std::istream & str) { string s = parseString(str); if (s.size() == 0 || s[0] != '/') - throw FormatError(format("bad path `%1%' in derivation") % s); + throw FormatError(std::format("bad path `{}' in derivation", s)); return s; } @@ -117,7 +120,7 @@ Derivation readDerivation(const Path & drvPath) try { return parseDerivation(readFile(drvPath)); } catch (FormatError & e) { - throw Error(format("error parsing derivation `%1%': %2%") % drvPath % e.msg()); + throw Error(std::format("error parsing derivation `{}': {}", drvPath, e.msg())); } } diff --git a/nix/libstore/gc.cc b/nix/libstore/gc.cc index 610270f907e3096318d38468a47fd13d3df49433..96440077fb5be507972095c282604c6ea9c09862 100644 --- a/nix/libstore/gc.cc +++ b/nix/libstore/gc.cc @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -30,18 +31,17 @@ static string gcRootsDir = "gcroots"; yielded the GC lock. */ int LocalStore::openGCLock(LockType lockType) { - Path fnGCLock = (format("%1%/%2%") - % settings.nixStateDir % gcLockName).str(); + Path fnGCLock = std::format("{}/{}", settings.nixStateDir, gcLockName); - debug(format("acquiring global GC lock `%1%'") % fnGCLock); + debug(std::format("acquiring global GC lock `{}'", fnGCLock)); AutoCloseFD fdGCLock = open(fnGCLock.c_str(), O_RDWR | O_CREAT, 0600); if (fdGCLock == -1) - throw SysError(format("opening global GC lock `%1%'") % fnGCLock); + throw SysError(std::format("opening global GC lock `{}'", fnGCLock)); closeOnExec(fdGCLock); if (!lockFile(fdGCLock, lockType, false)) { - printMsg(lvlError, format("waiting for the big garbage collector lock...")); + printMsg(lvlError, "waiting for the big garbage collector lock..."); lockFile(fdGCLock, lockType, true); } @@ -59,14 +59,12 @@ static void makeSymlink(const Path & link, const Path & target) createDirs(dirOf(link)); /* Create the new symlink. */ - Path tempLink = (format("%1%.tmp-%2%-%3%") - % link % getpid() % rand()).str(); + Path tempLink = std::format("{}.tmp-{}-{}", link, getpid(), rand()); createSymlink(target, tempLink); /* Atomically replace the old one. */ if (rename(tempLink.c_str(), link.c_str()) == -1) - throw SysError(format("cannot rename `%1%' to `%2%'") - % tempLink % link); + throw SysError(std::format("cannot rename `{}' to `{}'", tempLink, link)); } @@ -79,8 +77,8 @@ void LocalStore::syncWithGC() void LocalStore::addIndirectRoot(const Path & path) { string hash = printHash32(hashString(htSHA1, path)); - Path realRoot = canonPath((format("%1%/%2%/auto/%3%") - % settings.nixStateDir % gcRootsDir % hash).str()); + Path realRoot = canonPath(std::format("{}/{}/auto/{}", + settings.nixStateDir, gcRootsDir, hash)); makeSymlink(realRoot, path); } @@ -93,28 +91,28 @@ Path addPermRoot(StoreAPI & store, const Path & _storePath, assertStorePath(storePath); if (isInStore(gcRoot)) - throw Error(format( - "creating a garbage collector root (%1%) in the store is forbidden " - "(are you running nix-build inside the store?)") % gcRoot); + throw Error(std::format( + "creating a garbage collector root ({}) in the store is forbidden " + "(are you running nix-build inside the store?)", gcRoot)); if (indirect) { /* Don't clobber the link if it already exists and doesn't point to the store. */ if (pathExists(gcRoot) && (!isLink(gcRoot) || !isInStore(readLink(gcRoot)))) - throw Error(format("cannot create symlink `%1%'; already exists") % gcRoot); + throw Error(std::format("cannot create symlink `{}'; already exists", gcRoot)); makeSymlink(gcRoot, storePath); store.addIndirectRoot(gcRoot); } else { if (!allowOutsideRootsDir) { - Path rootsDir = canonPath((format("%1%/%2%") % settings.nixStateDir % gcRootsDir).str()); + Path rootsDir = canonPath(std::format("{}/{}", settings.nixStateDir, gcRootsDir)); if (string(gcRoot, 0, rootsDir.size() + 1) != rootsDir + "/") - throw Error(format( - "path `%1%' is not a valid garbage collector root; " - "it's not in the directory `%2%'") - % gcRoot % rootsDir); + throw Error(std::format( + "path `{}' is not a valid garbage collector root; " + "it's not in the directory `{}'", + gcRoot, rootsDir)); } if (baseNameOf(gcRoot) == baseNameOf(storePath)) @@ -132,10 +130,10 @@ Path addPermRoot(StoreAPI & store, const Path & _storePath, Roots roots = store.findRoots(); if (roots.find(gcRoot) == roots.end()) printMsg(lvlError, - format( - "warning: `%1%' is not in a directory where the garbage collector looks for roots; " - "therefore, `%2%' might be removed by the garbage collector") - % gcRoot % storePath); + std::format( + "warning: `{}' is not in a directory where the garbage collector looks for roots; " + "therefore, `{}' might be removed by the garbage collector", + gcRoot, storePath)); } /* Grab the global GC root, causing us to block while a GC is in @@ -153,11 +151,10 @@ void LocalStore::addTempRoot(const Path & path) if (fdTempRoots == -1) { while (1) { - Path dir = (format("%1%/%2%") % settings.nixStateDir % tempRootsDir).str(); + Path dir = std::format("{}/{}", settings.nixStateDir, tempRootsDir); createDirs(dir); - fnTempRoots = (format("%1%/%2%") - % dir % getpid()).str(); + fnTempRoots = std::format("{}/{}", dir, getpid()); AutoCloseFD fdGCLock = openGCLock(ltRead); @@ -170,14 +167,14 @@ void LocalStore::addTempRoot(const Path & path) fdGCLock.close(); - debug(format("acquiring read lock on `%1%'") % fnTempRoots); + debug(std::format("acquiring read lock on `{}'", fnTempRoots)); lockFile(fdTempRoots, ltRead, true); /* Check whether the garbage collector didn't get in our way. */ struct stat st; if (fstat(fdTempRoots, &st) == -1) - throw SysError(format("statting `%1%'") % fnTempRoots); + throw SysError(std::format("statting `{}'", fnTempRoots)); if (st.st_size == 0) break; /* The garbage collector deleted this file before we could @@ -189,14 +186,14 @@ void LocalStore::addTempRoot(const Path & path) /* Upgrade the lock to a write lock. This will cause us to block if the garbage collector is holding our lock. */ - debug(format("acquiring write lock on `%1%'") % fnTempRoots); + debug(std::format("acquiring write lock on `{}'", fnTempRoots)); lockFile(fdTempRoots, ltWrite, true); string s = path + '\0'; writeFull(fdTempRoots, s); /* Downgrade to a read lock. */ - debug(format("downgrading to read lock on `%1%'") % fnTempRoots); + debug(std::format("downgrading to read lock on `{}'", fnTempRoots)); lockFile(fdTempRoots, ltRead, true); } @@ -210,17 +207,17 @@ static void readTempRoots(PathSet & tempRoots, FDs & fds) /* Read the `temproots' directory for per-process temporary root files. */ DirEntries tempRootFiles = readDirectory( - (format("%1%/%2%") % settings.nixStateDir % tempRootsDir).str()); + std::format("{}/{}", settings.nixStateDir, tempRootsDir)); for (auto & i : tempRootFiles) { - Path path = (format("%1%/%2%/%3%") % settings.nixStateDir % tempRootsDir % i.name).str(); + Path path = std::format("{}/{}/{}", settings.nixStateDir, tempRootsDir, i.name); - debug(format("reading temporary root file `%1%'") % path); + debug(std::format("reading temporary root file `{}'", path)); FDPtr fd(new AutoCloseFD(open(path.c_str(), O_RDWR, 0666))); if (*fd == -1) { /* It's okay if the file has disappeared. */ if (errno == ENOENT) continue; - throw SysError(format("opening temporary roots file `%1%'") % path); + throw SysError(std::format("opening temporary roots file `{}'", path)); } /* This should work, but doesn't, for some reason. */ @@ -231,7 +228,7 @@ static void readTempRoots(PathSet & tempRoots, FDs & fds) only succeed if the owning process has died. In that case we don't care about its temporary roots. */ if (lockFile(*fd, ltWrite, false)) { - printMsg(lvlError, format("removing stale temporary roots file `%1%'") % path); + printMsg(lvlError, std::format("removing stale temporary roots file `{}'", path)); unlink(path.c_str()); writeFull(*fd, "d"); continue; @@ -240,7 +237,7 @@ static void readTempRoots(PathSet & tempRoots, FDs & fds) /* Acquire a read lock. This will prevent the owning process from upgrading to a write lock, therefore it will block in addTempRoot(). */ - debug(format("waiting for read lock on `%1%'") % path); + debug(std::format("waiting for read lock on `{}'", path)); lockFile(*fd, ltRead, true); /* Read the entire file. */ @@ -251,7 +248,7 @@ static void readTempRoots(PathSet & tempRoots, FDs & fds) while ((end = contents.find((char) 0, pos)) != string::npos) { Path root(contents, pos, end - pos); - debug(format("got temporary root `%1%'") % root); + debug(std::format("got temporary root `{}'", root)); assertStorePath(root); tempRoots.insert(root); pos = end + 1; @@ -269,7 +266,7 @@ static void foundRoot(StoreAPI & store, if (store.isValidPath(storePath)) roots[path] = storePath; else - printMsg(lvlInfo, format("skipping invalid root from `%1%' to `%2%'") % path % storePath); + printMsg(lvlInfo, std::format("skipping invalid root from `{}' to `{}'", path, storePath)); } @@ -295,7 +292,7 @@ static void findRoots(StoreAPI & store, const Path & path, unsigned char type, R target = absPath(target, dirOf(path)); if (!pathExists(target)) { if (isInDir(path, settings.nixStateDir + "/" + gcRootsDir + "/auto")) { - printMsg(lvlInfo, format("removing stale link from `%1%' to `%2%'") % path % target); + printMsg(lvlInfo, std::format("removing stale link from `{}' to `{}'", path, target)); unlink(path.c_str()); } } else { @@ -318,8 +315,8 @@ static void findRoots(StoreAPI & store, const Path & path, unsigned char type, R catch (SysError & e) { /* We only ignore permanent failures. */ if (e.errNo == EACCES || e.errNo == ENOENT || e.errNo == ENOTDIR) - printMsg(lvlInfo, format("cannot read potential root '%1%': %2%") - % path % strerror(e.errNo)); + printMsg(lvlInfo, std::format("cannot read potential root '{}': {}", + path, strerror(e.errNo))); else throw; } @@ -342,8 +339,8 @@ Roots LocalStore::findRoots() static void addAdditionalRoots(StoreAPI & store, PathSet & roots) { - debug(format("executing `%1% gc --list-busy' to find additional roots") - % settings.guixProgram); + debug(std::format("executing `{} gc --list-busy' to find additional roots", + settings.guixProgram)); const Strings args = { "gc", "--list-busy" }; string result = runProgram(settings.guixProgram, false, args); @@ -354,7 +351,7 @@ static void addAdditionalRoots(StoreAPI & store, PathSet & roots) if (isInStore(i)) { Path path = toStorePath(i); if (roots.find(path) == roots.end() && store.isValidPath(path)) { - debug(format("got additional root `%1%'") % path); + debug(std::format("got additional root `{}'", path)); roots.insert(path); } } @@ -424,17 +421,17 @@ void LocalStore::deletePathRecursive(GCState & state, const Path & path) struct stat st; if (lstat(path.c_str(), &st)) { if (errno == ENOENT) return; - throw SysError(format("getting status of %1%") % path); + throw SysError(std::format("getting status of {}", path)); } if (state.options.maxFreed != ULLONG_MAX) { auto freed = state.results.bytesFreed + state.bytesInvalidated; double fraction = ((double) freed) / (double) state.options.maxFreed; unsigned int percentage = (fraction > 1. ? 1. : fraction) * 100.; - printMsg(lvlInfo, format("[%1%%%] deleting '%2%'") % percentage % path); + printMsg(lvlInfo, std::format("[{}%] deleting '{}'", percentage, path)); } else { auto freed = state.results.bytesFreed + state.bytesInvalidated; - printMsg(lvlInfo, format("[%1%] deleting '%2%'") % showBytes(freed) % path); + printMsg(lvlInfo, std::format("[{}] deleting '{}'", showBytes(freed), path)); } state.results.paths.insert(path); @@ -450,17 +447,17 @@ void LocalStore::deletePathRecursive(GCState & state, const Path & path) // size. try { if (chmod(path.c_str(), st.st_mode | S_IWUSR) == -1) - throw SysError(format("making `%1%' writable") % path); + throw SysError(std::format("making `{}' writable", path)); Path tmp = state.trashDir + "/" + baseNameOf(path); if (rename(path.c_str(), tmp.c_str())) - throw SysError(format("unable to rename `%1%' to `%2%'") % path % tmp); + throw SysError(std::format("unable to rename `{}' to `{}'", path, tmp)); state.bytesInvalidated += size; } catch (SysError & e) { /* In a Docker container, rename(2) returns EXDEV when the source and destination are not both on the "top layer". See: https://bugs.gnu.org/41607 */ if (e.errNo == ENOSPC || e.errNo == EXDEV) { - printMsg(lvlInfo, format("note: can't create move `%1%': %2%") % path % e.msg()); + printMsg(lvlInfo, std::format("note: can't create move `{}': {}", path, e.msg())); deleteGarbage(state, path); } } @@ -468,7 +465,7 @@ void LocalStore::deletePathRecursive(GCState & state, const Path & path) deleteGarbage(state, path); if (state.results.bytesFreed + state.bytesInvalidated > state.options.maxFreed) { - printMsg(lvlInfo, format("deleted or invalidated more than %1% bytes; stopping") % state.options.maxFreed); + printMsg(lvlInfo, std::format("deleted or invalidated more than {} bytes; stopping", state.options.maxFreed)); throw GCLimitReached(); } } @@ -487,7 +484,7 @@ bool LocalStore::canReachRoot(GCState & state, PathSet & visited, const Path & p } if (state.roots.find(path) != state.roots.end()) { - printMsg(lvlDebug, format("cannot delete `%1%' because it's a root") % path); + printMsg(lvlDebug, std::format("cannot delete `{}' because it's a root", path)); state.alive.insert(path); return true; } @@ -535,7 +532,7 @@ void LocalStore::tryToDelete(GCState & state, const Path & path) if (path == linksDir || path == state.trashDir) return; - startNest(nest, lvlDebug, format("considering whether to delete `%1%'") % path); + startNest(nest, lvlDebug, std::format("considering whether to delete `{}'", path)); if (!isValidPath(path)) { /* A lock file belonging to a path that we're building right @@ -550,7 +547,7 @@ void LocalStore::tryToDelete(GCState & state, const Path & path) PathSet visited; if (canReachRoot(state, visited, path)) { - printMsg(lvlDebug, format("cannot delete `%1%' because it's still reachable") % path); + printMsg(lvlDebug, std::format("cannot delete `{}' because it's still reachable", path)); } else { /* No path we visited was a root, so everything is garbage. But we only delete ‘path’ and its referrers here so that @@ -571,7 +568,7 @@ void LocalStore::tryToDelete(GCState & state, const Path & path) void LocalStore::removeUnusedLinks(const GCState & state) { AutoCloseDir dir = opendir(linksDir.c_str()); - if (!dir) throw SysError(format("opening directory `%1%'") % linksDir); + if (!dir) throw SysError(std::format("opening directory `{}'", linksDir)); long long actualSize = 0, unsharedSize = 0; @@ -596,15 +593,15 @@ void LocalStore::removeUnusedLinks(const GCState & state) statx_flags &= ~AT_STATX_DONT_SYNC; if (statx(AT_FDCWD, path.c_str(), statx_flags, STATX_SIZE | STATX_NLINK, &st) == -1) - throw SysError(format("statting `%1%'") % path); + throw SysError(std::format("statting `{}'", path)); } else { - throw SysError(format("statting `%1%'") % path); + throw SysError(std::format("statting `{}'", path)); } } #else struct stat st; if (lstat(path.c_str(), &st) == -1) - throw SysError(format("statting `%1%'") % path); + throw SysError(std::format("statting `{}'", path)); #endif /* Drop links for files smaller than 'deduplicationMinSize', even if @@ -616,10 +613,10 @@ void LocalStore::removeUnusedLinks(const GCState & state) continue; } - printMsg(lvlTalkative, format("deleting unused link `%1%'") % path); + printMsg(lvlTalkative, std::format("deleting unused link `{}'", path)); if (unlink(path.c_str()) == -1) - throw SysError(format("deleting `%1%'") % path); + throw SysError(std::format("deleting `{}'", path)); state.results.bytesFreed += st.st_size; #undef st_size @@ -628,11 +625,11 @@ void LocalStore::removeUnusedLinks(const GCState & state) struct stat st; if (stat(linksDir.c_str(), &st) == -1) - throw SysError(format("statting `%1%'") % linksDir); + throw SysError(std::format("statting `{}'", linksDir)); long long overhead = st.st_size; long long freedbytes = (unsharedSize - actualSize - overhead); - printMsg(lvlInfo, format("note: currently hard linking saves %1%") % showBytes(freedbytes)); + printMsg(lvlInfo, std::format("note: currently hard linking saves {}", showBytes(freedbytes))); } @@ -662,7 +659,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) /* Find the roots. Since we've grabbed the GC lock, the set of permanent roots cannot increase now. */ - printMsg(lvlError, format("finding garbage collector roots...")); + printMsg(lvlError, "finding garbage collector roots..."); Roots rootMap = options.ignoreLiveness ? Roots() : findRoots(); for (auto& i : rootMap) state.roots.insert(i.second); @@ -690,7 +687,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) createDirs(state.trashDir); } catch (SysError & e) { if (e.errNo == ENOSPC) { - printMsg(lvlInfo, format("note: can't create trash directory: %1%") % e.msg()); + printMsg(lvlInfo, std::format("note: can't create trash directory: {}", e.msg())); state.moveToTrash = false; } } @@ -705,20 +702,20 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) assertStorePath(i); tryToDelete(state, i); if (state.dead.find(i) == state.dead.end()) - throw Error(format("cannot delete path `%1%' since it is still alive") % i); + throw Error(std::format("cannot delete path `{}' since it is still alive", i)); } } else if (options.maxFreed > 0) { if (state.shouldDelete) - printMsg(lvlError, format("deleting garbage...")); + printMsg(lvlError, "deleting garbage..."); else - printMsg(lvlError, format("determining live/dead paths...")); + printMsg(lvlError, "determining live/dead paths..."); try { AutoCloseDir dir = opendir(settings.nixStore.c_str()); - if (!dir) throw SysError(format("opening directory `%1%'") % settings.nixStore); + if (!dir) throw SysError(std::format("opening directory `{}'", settings.nixStore)); /* Read the store and immediately delete all paths that aren't valid. When using --max-freed etc., deleting @@ -773,12 +770,12 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) fds.clear(); /* Delete the trash directory. */ - printMsg(lvlInfo, format("deleting `%1%'") % state.trashDir); + printMsg(lvlInfo, std::format("deleting `{}'", state.trashDir)); deleteGarbage(state, state.trashDir); /* Clean up the links directory. */ if (options.action == GCOptions::gcDeleteDead || options.action == GCOptions::gcDeleteSpecific) { - printMsg(lvlError, format("deleting unused links...")); + printMsg(lvlError, "deleting unused links..."); removeUnusedLinks(state); } diff --git a/nix/libstore/globals.cc b/nix/libstore/globals.cc index 31da8d4769d58300f8d027c088207d49b69f5cfd..16f43f6abcbe6f723c434c7765e2d3c67e146fdb 100644 --- a/nix/libstore/globals.cc +++ b/nix/libstore/globals.cc @@ -6,7 +6,7 @@ #include #include - +#include namespace nix { @@ -156,8 +156,8 @@ void Settings::_get(bool & res, const string & name) if (i == settings.end()) return; if (i->second == "true") res = true; else if (i->second == "false") res = false; - else throw Error(format("configuration option `%1%' should be either `true' or `false', not `%2%'") - % name % i->second); + else throw Error(std::format("configuration option `{}' should be either `true' or `false', not `{}'", + name, i->second)); } @@ -183,7 +183,7 @@ template void Settings::_get(N & res, const string & name) SettingsMap::iterator i = settings.find(name); if (i == settings.end()) return; if (!string2Int(i->second, res)) - throw Error(format("configuration setting `%1%' should have an integer value") % name); + throw Error(std::format("configuration setting `{}' should have an integer value", name)); } diff --git a/nix/libstore/local-store.cc b/nix/libstore/local-store.cc index 50ef707fdf3dfa589452d80168a6943e150edcf7..f11f48bcf078d07965593ece2a0d9812d8130131 100644 --- a/nix/libstore/local-store.cc +++ b/nix/libstore/local-store.cc @@ -9,7 +9,9 @@ #include #include +#include #include +#include #include #include @@ -45,12 +47,12 @@ void checkStoreNotSymlink() struct stat st; while (path != "/") { if (lstat(path.c_str(), &st)) - throw SysError(format("getting status of `%1%'") % path); + throw SysError(std::format("getting status of `{}'", path)); if (S_ISLNK(st.st_mode)) - throw Error(format( - "the path `%1%' is a symlink; " - "this is not allowed for the store and its parent directories") - % path); + throw Error(std::format( + "the path `{}' is a symlink; " + "this is not allowed for the store and its parent directories", + path)); path = dirOf(path); } } @@ -86,25 +88,24 @@ LocalStore::LocalStore(bool reserveSpace) if (getuid() == 0 && settings.buildUsersGroup != "") { if (chmod(perUserDir.c_str(), 0755) == -1) - throw SysError(format("could not set permissions on '%1%' to 755") - % perUserDir); + throw SysError(std::format("could not set permissions on '{}' to 755", perUserDir)); mode_t perm = 01775; struct group * gr = getgrnam(settings.buildUsersGroup.c_str()); if (!gr) - throw Error(format("the group `%1%' specified in `build-users-group' does not exist") - % settings.buildUsersGroup); + throw Error(std::format("the group `{}' specified in `build-users-group' does not exist", + settings.buildUsersGroup)); else { struct stat st; if (stat(settings.nixStore.c_str(), &st)) - throw SysError(format("getting attributes of path '%1%'") % settings.nixStore); + throw SysError(std::format("getting attributes of path '{}'", settings.nixStore)); if (st.st_uid != 0 || st.st_gid != gr->gr_gid || (st.st_mode & ~S_IFMT) != perm) { if (chown(settings.nixStore.c_str(), 0, gr->gr_gid) == -1) - throw SysError(format("changing ownership of path '%1%'") % settings.nixStore); + throw SysError(std::format("changing ownership of path '{}'", settings.nixStore)); if (chmod(settings.nixStore.c_str(), perm) == -1) - throw SysError(format("changing permissions on path '%1%'") % settings.nixStore); + throw SysError(std::format("changing permissions on path '{}'", settings.nixStore)); } } } @@ -159,20 +160,20 @@ LocalStore::LocalStore(bool reserveSpace) upgrade. */ int curSchema = getSchema(); if (curSchema > nixSchemaVersion) - throw Error(format("current store schema is version %1%, but I only support %2%") - % curSchema % nixSchemaVersion); + throw Error(std::format("current store schema is version {}, but I only support {}", + curSchema, nixSchemaVersion)); else if (curSchema == 0) { /* new store */ curSchema = nixSchemaVersion; openDB(true); - writeFile(schemaPath, (format("%1%") % nixSchemaVersion).str()); + writeFile(schemaPath, std::format("{}", nixSchemaVersion)); } else if (curSchema < nixSchemaVersion) { /* Guix always used version 7 of the schema. */ throw Error( - format("Your store database uses an implausibly old schema, version %1%.") - % curSchema); + std::format("Your store database uses an implausibly old schema, version {}.", + curSchema)); } else openDB(false); @@ -198,7 +199,7 @@ int LocalStore::getSchema() if (pathExists(schemaPath)) { string s = readFile(schemaPath); if (!string2Int(s, curSchema)) - throw Error(format("`%1%' is corrupt") % schemaPath); + throw Error(std::format("`{}' is corrupt", schemaPath)); } return curSchema; } @@ -207,13 +208,13 @@ int LocalStore::getSchema() void LocalStore::openDB(bool create) { if (access(settings.nixDBPath.c_str(), R_OK | W_OK)) - throw SysError(format("store database directory `%1%' is not writable") % settings.nixDBPath); + throw SysError(std::format("store database directory `{}' is not writable", settings.nixDBPath)); /* Open the store database. */ string dbPath = settings.nixDBPath + "/db.sqlite"; if (sqlite3_open_v2(dbPath.c_str(), &db.db, SQLITE_OPEN_READWRITE | (create ? SQLITE_OPEN_CREATE : 0), 0) != SQLITE_OK) - throw Error(format("cannot open store database `%1%'") % dbPath); + throw Error(std::format("cannot open store database `{}'", dbPath)); if (sqlite3_busy_timeout(db, 60 * 60 * 1000) != SQLITE_OK) throwSQLiteError(db, "setting timeout"); @@ -317,7 +318,7 @@ void LocalStore::makeStoreWritable() throw SysError("setting up a private mount namespace"); if (mount(0, settings.nixStore.c_str(), "none", MS_REMOUNT | MS_BIND, 0) == -1) - throw SysError(format("remounting %1% writable") % settings.nixStore); + throw SysError(std::format("remounting {} writable", settings.nixStore)); } #endif } @@ -338,7 +339,7 @@ static void canonicaliseTimestampAndPermissions(const Path & path, const struct | 0444 | (st.st_mode & S_IXUSR ? 0111 : 0); if (chmod(path.c_str(), mode) == -1) - throw SysError(format("changing mode of `%1%' to %2$o") % path % mode); + throw SysError(std::format("changing mode of `{}' to {:o}", path, mode)); } } @@ -356,7 +357,7 @@ static void canonicaliseTimestampAndPermissions(const Path & path, const struct #else if (!S_ISLNK(st.st_mode) && utimes(path.c_str(), times) == -1) #endif - throw SysError(format("changing modification time of `%1%'") % path); + throw SysError(std::format("changing modification time of `{}'", path)); } } @@ -365,7 +366,7 @@ void canonicaliseTimestampAndPermissions(const Path & path) { struct stat st; if (lstat(path.c_str(), &st)) - throw SysError(format("getting attributes of path `%1%'") % path); + throw SysError(std::format("getting attributes of path `{}'", path)); canonicaliseTimestampAndPermissions(path, st); } @@ -376,11 +377,11 @@ static void canonicalisePathMetaData_(const Path & path, uid_t fromUid, InodesSe struct stat st; if (lstat(path.c_str(), &st)) - throw SysError(format("getting attributes of path `%1%'") % path); + throw SysError(std::format("getting attributes of path `{}'", path)); /* Really make sure that the path is of a supported type. */ if (!(S_ISREG(st.st_mode) || S_ISDIR(st.st_mode) || S_ISLNK(st.st_mode))) - throw Error(format("file ‘%1%’ has an unsupported type") % path); + throw Error(std::format("file `{}' has an unsupported type", path)); /* Fail if the file is not owned by the build user. This prevents us from messing up the ownership/permissions of files @@ -391,7 +392,7 @@ static void canonicalisePathMetaData_(const Path & path, uid_t fromUid, InodesSe if (fromUid != (uid_t) -1 && st.st_uid != fromUid) { assert(!S_ISDIR(st.st_mode)); if (inodesSeen.find(Inode(st.st_dev, st.st_ino)) == inodesSeen.end()) - throw BuildError(format("invalid ownership on file `%1%'") % path); + throw BuildError(std::format("invalid ownership on file `{}'", path)); mode_t mode = st.st_mode & ~S_IFMT; assert(S_ISLNK(st.st_mode) || (st.st_uid == geteuid() && (mode == 0444 || mode == 0555) && st.st_mtime == mtimeStore)); return; @@ -415,8 +416,8 @@ static void canonicalisePathMetaData_(const Path & path, uid_t fromUid, InodesSe if (!S_ISLNK(st.st_mode) && chown(path.c_str(), geteuid(), getegid()) == -1) #endif - throw SysError(format("changing owner of `%1%' to %2%") - % path % geteuid()); + throw SysError(std::format("changing owner of `{}' to {}", + path, geteuid())); } if (S_ISDIR(st.st_mode)) { @@ -435,11 +436,11 @@ void canonicalisePathMetaData(const Path & path, uid_t fromUid, InodesSeen & ino be a symlink, since we can't change its ownership. */ struct stat st; if (lstat(path.c_str(), &st)) - throw SysError(format("getting attributes of path `%1%'") % path); + throw SysError(std::format("getting attributes of path `{}'", path)); if (st.st_uid != geteuid()) { assert(S_ISLNK(st.st_mode)); - throw Error(format("wrong ownership of top-level store path `%1%'") % path); + throw Error(std::format("wrong ownership of top-level store path `{}'", path)); } } @@ -460,7 +461,7 @@ void LocalStore::checkDerivationOutputs(const Path & drvPath, const Derivation & if (isFixedOutputDrv(drv)) { DerivationOutputs::const_iterator out = drv.outputs.find("out"); if (out == drv.outputs.end()) - throw Error(format("derivation `%1%' does not have an output named `out'") % drvPath); + throw Error(std::format("derivation `{}' does not have an output named `out'", drvPath)); bool recursive; HashType ht; Hash h; out->second.parseHashInfo(recursive, ht, h); @@ -468,8 +469,8 @@ void LocalStore::checkDerivationOutputs(const Path & drvPath, const Derivation & StringPairs::const_iterator j = drv.env.find("out"); if (out->second.path != outPath || j == drv.env.end() || j->second != outPath) - throw Error(format("derivation `%1%' has incorrect output `%2%', should be `%3%'") - % drvPath % out->second.path % outPath); + throw Error(std::format("derivation `{}' has incorrect output `{}', should be `{}'", + drvPath, out->second.path, outPath)); } else { @@ -485,8 +486,8 @@ void LocalStore::checkDerivationOutputs(const Path & drvPath, const Derivation & Path outPath = makeOutputPath(i.first, h, drvName); StringPairs::const_iterator j = drv.env.find(i.first); if (i.second.path != outPath || j == drv.env.end() || j->second != outPath) - throw Error(format("derivation `%1%' has incorrect output `%2%', should be `%3%'") - % drvPath % i.second.path % outPath); + throw Error(std::format("derivation `{}' has incorrect output `{}', should be `{}'", + drvPath, i.second.path, outPath)); } } } @@ -583,12 +584,12 @@ Hash parseHashField(const Path & path, const string & s) { string::size_type colon = s.find(':'); if (colon == string::npos) - throw Error(format("corrupt hash `%1%' in valid-path entry for `%2%'") - % s % path); + throw Error(std::format("corrupt hash `{}' in valid-path entry for `{}'", + s, path)); HashType ht = parseHashType(string(s, 0, colon)); if (ht == htUnknown) - throw Error(format("unknown hash type `%1%' in valid-path entry for `%2%'") - % string(s, 0, colon) % path); + throw Error(std::format("unknown hash type `{}' in valid-path entry for `{}'", + string(s, 0, colon), path)); return parseHash(ht, string(s, colon + 1)); } @@ -606,7 +607,7 @@ ValidPathInfo LocalStore::queryPathInfo(const Path & path) auto useQueryPathInfo(stmtQueryPathInfo.use()(path)); if (!useQueryPathInfo.next()) - throw Error(format("path `%1%' is not valid") % path); + throw Error(std::format("path `{}' is not valid", path)); info.id = useQueryPathInfo.getInt(0); @@ -647,7 +648,7 @@ uint64_t LocalStore::queryValidPathId(const Path & path) { auto use(stmtQueryPathInfo.use()(path)); if (!use.next()) - throw Error(format("path ‘%1%’ is not valid") % path); + throw Error(std::format("path `%1%' is not valid", path)); return use.getInt(0); } @@ -809,8 +810,8 @@ string LocalStore::getLineFromSubstituter(Agent & run) if (errno == EINTR) continue; throw SysError("reading from substituter's stderr"); } - if (n == 0) throw EndOfFile(format("`%1% substitute' died unexpectedly") - % settings.guixProgram); + if (n == 0) throw EndOfFile(std::format("`{} substitute' died unexpectedly", + settings.guixProgram)); err.append(buf, n); string::size_type p; while (((p = err.find('\n')) != string::npos) @@ -840,7 +841,7 @@ template T LocalStore::getIntLineFromSubstituter(Agent & run) string s = getLineFromSubstituter(run); T res; if (!string2Int(s, res)) - throw Error(format("integer expected from stream: %1%") % s); + throw Error(std::format("integer expected from stream: {}", s)); return res; } @@ -897,7 +898,7 @@ void LocalStore::querySubstitutablePathInfos(PathSet & paths, SubstitutablePathI Path path = getLineFromSubstituter(run); if (path == "") break; if (paths.find(path) == paths.end()) - throw Error(format("got unexpected path `%1%' from substituter") % path); + throw Error(std::format("got unexpected path `{}' from substituter", path)); paths.erase(path); SubstitutablePathInfo & info(infos[path]); info.deriver = getLineFromSubstituter(run); @@ -990,7 +991,7 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos) there are no referrers. */ void LocalStore::invalidatePath(const Path & path) { - debug(format("invalidating path `%1%'") % path); + debug(std::format("invalidating path `{}'", path)); drvHashes.erase(path); @@ -1060,7 +1061,7 @@ Path LocalStore::addToStore(const string & name, const Path & _srcPath, bool recursive, HashType hashAlgo, PathFilter & filter, bool repair) { Path srcPath(absPath(_srcPath)); - debug(format("adding `%1%' to the store") % srcPath); + debug(std::format("adding `{}' to the store", srcPath)); /* Read the whole path into memory. This is not a very scalable method for very large paths, but `copyPath' is mainly used for @@ -1139,9 +1140,9 @@ static void checkSecrecy(const Path & path) { struct stat st; if (stat(path.c_str(), &st)) - throw SysError(format("getting status of `%1%'") % path); + throw SysError(std::format("getting status of `{}'", path)); if ((st.st_mode & (S_IRWXG | S_IRWXO)) != 0) - throw Error(format("file `%1%' should be secret (inaccessible to everybody else)!") % path); + throw Error(std::format("file `{}' should be secret (inaccessible to everybody else)!", path)); } @@ -1212,9 +1213,9 @@ static std::string signHash(const string &secretKey, const Hash &hash) auto hexHash = printHash(hash); writeLine(agent->toAgent.writeSide, - (format("sign %1%:%2% %3%:%4%") - % secretKey.size() % secretKey - % hexHash.size() % hexHash).str()); + std::format("sign {}:{} {}:{}", + secretKey.size(), secretKey, + hexHash.size(), hexHash)); return readAuthenticateReply(agent->fromAgent.readSide); } @@ -1226,8 +1227,7 @@ static std::string verifySignature(const string &signature) auto agent = authenticationAgent(); writeLine(agent->toAgent.writeSide, - (format("verify %1%:%2%") - % signature.size() % signature).str()); + std::format("verify {}:{}", signature.size(), signature)); return readAuthenticateReply(agent->fromAgent.readSide); } @@ -1237,10 +1237,10 @@ void LocalStore::exportPath(const Path & path, bool sign, { assertStorePath(path); - printMsg(lvlInfo, format("exporting path `%1%'") % path); + printMsg(lvlInfo, std::format("exporting path `{}'", path)); if (!isValidPath(path)) - throw Error(format("path `%1%' is not valid") % path); + throw Error(std::format("path `{}' is not valid", path)); HashAndWriteSink hashAndWriteSink(sink); @@ -1252,8 +1252,8 @@ void LocalStore::exportPath(const Path & path, bool sign, Hash hash = hashAndWriteSink.currentHash(); Hash storedHash = queryPathHash(path); if (hash != storedHash && storedHash != Hash(storedHash.type)) - throw Error(format("hash of path `%1%' has changed from `%2%' to `%3%'!") % path - % printHash(storedHash) % printHash(hash)); + throw Error(std::format("hash of path `{}' has changed from `{}' to `{}'!", + path, printHash(storedHash), printHash(hash))); writeInt(EXPORT_MAGIC, hashAndWriteSink); @@ -1347,7 +1347,7 @@ Path LocalStore::importPath(bool requireSignature, Source & source) bool haveSignature = readInt(hashAndReadSource) == 1; if (requireSignature && !haveSignature) - throw Error(format("imported archive of `%1%' lacks a signature") % dstPath); + throw Error(std::format("imported archive of `{}' lacks a signature", dstPath)); if (haveSignature) { string signature = readString(hashAndReadSource); @@ -1387,8 +1387,8 @@ Path LocalStore::importPath(bool requireSignature, Source & source) if (pathExists(dstPath)) deletePath(dstPath); if (rename(unpacked.c_str(), dstPath.c_str()) == -1) - throw SysError(format("cannot move `%1%' to `%2%'") - % unpacked % dstPath); + throw SysError(std::format("cannot move `{}' to `{}'", + unpacked, dstPath)); canonicalisePathMetaData(dstPath, -1); @@ -1438,8 +1438,8 @@ void LocalStore::invalidatePathChecked(const Path & path) 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%") - % path % showPaths(referrers)); + throw PathInUse(std::format("cannot delete path `{}' because it is in use by {}", + path, showPaths(referrers))); invalidatePath(path); } @@ -1450,7 +1450,7 @@ void LocalStore::invalidatePathChecked(const Path & path) bool LocalStore::verifyStore(bool checkContents, bool repair) { - printMsg(lvlError, format("reading the store...")); + printMsg(lvlError, "reading the store..."); bool errors = false; @@ -1483,13 +1483,13 @@ bool LocalStore::verifyStore(bool checkContents, bool repair) ValidPathInfo info = queryPathInfo(i); /* Check the content hash (optionally - slow). */ - printMsg(lvlTalkative, format("checking contents of `%1%'") % i); + printMsg(lvlTalkative, std::format("checking contents of `{}'", i)); HashResult current = hashPath(info.hash.type, i); 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)); + printMsg(lvlError, std::format("path `{}' was modified! " + "expected hash `{}', got `{}'", + i, printHash(info.hash), printHash(current.first))); if (repair) repairPath(i); else errors = true; } else { @@ -1497,14 +1497,14 @@ bool LocalStore::verifyStore(bool checkContents, bool repair) /* Fill in missing hashes. */ if (info.hash == nullHash) { - printMsg(lvlError, format("fixing missing hash on `%1%'") % i); + printMsg(lvlError, std::format("fixing missing hash on `{}'", 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); + printMsg(lvlError, std::format("updating size field on `{}' to {}", i, current.second)); info.narSize = current.second; update = true; } @@ -1517,9 +1517,9 @@ bool LocalStore::verifyStore(bool checkContents, bool repair) /* It's possible that the path got GC'ed, so ignore errors on invalid paths. */ if (isValidPath(i)) - printMsg(lvlError, format("error: %1%") % e.msg()); + printMsg(lvlError, std::format("error: {}", e.msg())); else - printMsg(lvlError, format("warning: %1%") % e.msg()); + printMsg(lvlError, std::format("warning: {}", e.msg())); errors = true; } } @@ -1538,7 +1538,7 @@ void LocalStore::verifyPath(const Path & path, const PathSet & store, done.insert(path); if (!isStorePath(path)) { - printMsg(lvlError, format("path `%1%' is not in the store") % path); + printMsg(lvlError, std::format("path `{}' is not in the store", path)); invalidatePath(path); return; } @@ -1556,15 +1556,15 @@ void LocalStore::verifyPath(const Path & path, const PathSet & store, } if (canInvalidate) { - printMsg(lvlError, format("path `%1%' disappeared, removing from database...") % path); + printMsg(lvlError, std::format("path `{}' disappeared, removing from database...", path)); invalidatePath(path); } else { - printMsg(lvlError, format("path `%1%' disappeared, but it still has valid referrers!") % path); + printMsg(lvlError, std::format("path `{}' disappeared, but it still has valid referrers!", path)); if (repair) try { repairPath(path); } catch (Error & e) { - printMsg(lvlError, format("warning: %1%") % e.msg()); + printMsg(lvlError, std::format("warning: {}", e.msg())); errors = true; } else errors = true; @@ -1581,7 +1581,7 @@ bool LocalStore::pathContentsGood(const Path & path) { std::map::iterator i = pathContentsGoodCache.find(path); if (i != pathContentsGoodCache.end()) return i->second; - printMsg(lvlInfo, format("checking path `%1%'...") % path); + printMsg(lvlInfo, std::format("checking path `{}'...", path)); ValidPathInfo info = queryPathInfo(path); bool res; if (!pathExists(path)) @@ -1592,7 +1592,7 @@ bool LocalStore::pathContentsGood(const Path & path) res = info.hash == nullHash || info.hash == current.first; } pathContentsGoodCache[path] = res; - if (!res) printMsg(lvlError, format("path `%1%' is corrupted or missing!") % path); + if (!res) printMsg(lvlError, std::format("path `{}' is corrupted or missing!", path)); return res; } @@ -1617,14 +1617,14 @@ void LocalStore::createUser(const std::string & userName, uid_t userId) auto created = createDirs(dir); if (!created.empty()) { if (chmod(dir.c_str(), 0755) == -1) - throw SysError(format("changing permissions of directory '%s'") % dir); + throw SysError(std::format("changing permissions of directory '{}'", dir)); /* The following operation requires CAP_CHOWN or can be handled manually by a user with CAP_CHOWN. */ if (chown(dir.c_str(), userId, -1) == -1) { rmdir(dir.c_str()); string message = strerror(errno); - printMsg(lvlInfo, format("failed to change owner of directory '%1%' to %2%: %3%") % dir % userId % message); + printMsg(lvlInfo, std::format("failed to change owner of directory '{}' to {}: {}", dir, userId, message)); } } } diff --git a/nix/libstore/misc.cc b/nix/libstore/misc.cc index e9904f3c4f42ca495153584c7c9abf03b5c7b57e..943fb9c9719e765cf9b3ded8e35f2ae32ebfc806 100644 --- a/nix/libstore/misc.cc +++ b/nix/libstore/misc.cc @@ -4,6 +4,7 @@ #include "local-store.hh" #include "globals.hh" +#include namespace nix { @@ -65,7 +66,7 @@ static void dfsVisit(StoreAPI & store, const PathSet & paths, PathSet & parents) { if (parents.find(path) != parents.end()) - throw BuildError(format("cycle detected in the references of `%1%'") % path); + throw BuildError(std::format("cycle detected in the references of `{}'", path)); if (visited.find(path) != visited.end()) return; visited.insert(path); @@ -99,19 +100,19 @@ Paths topoSortPaths(StoreAPI & store, const PathSet & paths) string showBytes(long long bytes) { if (llabs(bytes > exp2l(60))) { - return (format("%7.2f EiB") % (bytes / exp2l(60))).str(); + return std::format("{:7.2f} EiB", bytes / exp2l(60)); } else if (llabs(bytes > exp2l(50))) { - return (format("%7.2f PiB") % (bytes / exp2l(50))).str(); + return std::format("{:7.2f} PiB", bytes / exp2l(50)); } else if (llabs(bytes > exp2l(40))) { - return (format("%7.2f TiB") % (bytes / exp2l(40))).str(); + return std::format("{:7.2f} TiB", bytes / exp2l(40)); } else if (llabs(bytes > exp2l(30))) { - return (format("%7.2f GiB") % (bytes / exp2l(30))).str(); + return std::format("{:7.2f} GiB", bytes / exp2l(30)); } else if (llabs(bytes > exp2l(20))) { - return (format("%7.2f MiB") % (bytes / exp2l(20))).str(); + return std::format("{:7.2f} MiB", bytes / exp2l(20)); } else if (llabs(bytes > exp2l(10))) { - return (format("%7.2f KiB") % (bytes / exp2l(10))).str(); + return std::format("{:7.2f} KiB", bytes / exp2l(10)); } else { - return (format("%4f bytes") % bytes).str(); + return std::format("{:4} bytes", bytes); } } diff --git a/nix/libstore/optimise-store.cc b/nix/libstore/optimise-store.cc index e17d9160d6cb9f665d9874c56a6418b8c0ad3ffa..d69c43e99788e59999b4519f6bad937b109f607b 100644 --- a/nix/libstore/optimise-store.cc +++ b/nix/libstore/optimise-store.cc @@ -12,7 +12,7 @@ #include #include #include - +#include namespace nix { @@ -24,9 +24,9 @@ static void makeWritable(const Path & path) { struct stat st; if (lstat(path.c_str(), &st)) - throw SysError(format("getting attributes of path `%1%'") % path); + throw SysError(std::format("getting attributes of path `{}'", path)); if (chmod(path.c_str(), st.st_mode | S_IWUSR) == -1) - throw SysError(format("changing writability of `%1%'") % path); + throw SysError(std::format("changing writability of `{}'", path)); } @@ -52,7 +52,7 @@ LocalStore::InodeHash LocalStore::loadInodeHash() InodeHash inodeHash; AutoCloseDir dir = opendir(linksDir.c_str()); - if (!dir) throw SysError(format("opening directory `%1%'") % linksDir); + if (!dir) throw SysError(std::format("opening directory `{}'", linksDir)); struct dirent * dirent; while (errno = 0, dirent = readdir(dir)) { /* sic */ @@ -60,9 +60,9 @@ LocalStore::InodeHash LocalStore::loadInodeHash() // We don't care if we hit non-hash files, anything goes inodeHash.insert(dirent->d_ino); } - if (errno) throw SysError(format("reading directory `%1%'") % linksDir); + if (errno) throw SysError(std::format("reading directory `{}'", linksDir)); - printMsg(lvlTalkative, format("loaded %1% hash inodes") % inodeHash.size()); + printMsg(lvlTalkative, std::format("loaded {} hash inodes", inodeHash.size())); return inodeHash; } @@ -73,14 +73,14 @@ Strings LocalStore::readDirectoryIgnoringInodes(const Path & path, const InodeHa Strings names; AutoCloseDir dir = opendir(path.c_str()); - if (!dir) throw SysError(format("opening directory `%1%'") % path); + if (!dir) throw SysError(std::format("opening directory `{}'", path)); struct dirent * dirent; while (errno = 0, dirent = readdir(dir)) { /* sic */ checkInterrupt(); if (inodeHash.count(dirent->d_ino)) { - printMsg(lvlDebug, format("`%1%' is already linked") % dirent->d_name); + printMsg(lvlDebug, std::format("`{}' is already linked", dirent->d_name)); continue; } @@ -88,7 +88,7 @@ Strings LocalStore::readDirectoryIgnoringInodes(const Path & path, const InodeHa if (name == "." || name == "..") continue; names.push_back(name); } - if (errno) throw SysError(format("reading directory `%1%'") % path); + if (errno) throw SysError(std::format("reading directory `{}'", path)); return names; } @@ -100,7 +100,7 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa struct stat st; if (lstat(path.c_str(), &st)) - throw SysError(format("getting attributes of path `%1%'") % path); + throw SysError(std::format("getting attributes of path `{}'", path)); if (S_ISDIR(st.st_mode)) { Strings names = readDirectoryIgnoringInodes(path, inodeHash); @@ -121,13 +121,13 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa Guix System (example: $fontconfig/var/cache being modified). Skip those files. FIXME: check the modification time. */ if (S_ISREG(st.st_mode) && (st.st_mode & S_IWUSR)) { - printMsg(lvlError, format("skipping suspicious writable file `%1%'") % path); + printMsg(lvlError, std::format("skipping suspicious writable file `{}'", path)); return; } /* This can still happen on top-level files. */ if (st.st_nlink > 1 && inodeHash.count(st.st_ino)) { - printMsg(lvlDebug, format("`%1%' is already linked, with %2% other file(s).") % path % (st.st_nlink - 2)); + printMsg(lvlDebug, std::format("`{}' is already linked, with {} other file(s).", path, (st.st_nlink - 2))); return; } @@ -141,7 +141,7 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa contents of the symlink (i.e. the result of readlink()), not the contents of the target (which may not even exist). */ Hash hash = hashPath(htSHA256, path).first; - printMsg(lvlDebug, format("`%1%' has hash `%2%'") % path % printHash(hash)); + printMsg(lvlDebug, std::format("`{}' has hash `{}'", path, printHash(hash))); /* Check if this is a known hash. */ Path linkPath = linksDir + "/" + printHash32(hash); @@ -164,12 +164,12 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa /* On ext4, that probably means the directory index is full. When that happens, it's fine to ignore it: we just effectively disable deduplication of this file. */ - printMsg(lvlInfo, format("cannot link `%1%' to `%2%': %3%") - % linkPath % path % strerror(ENOSPC)); + printMsg(lvlInfo, std::format("cannot link `{}' to `{}': {}", + linkPath, path, strerror(ENOSPC))); return; default: - throw SysError(format("cannot link `%1%' to `%2%'") % linkPath % path); + throw SysError(std::format("cannot link `{}' to `{}'", linkPath, path)); } } @@ -177,20 +177,20 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa current file with a hard link to that file. */ struct stat stLink; if (lstat(linkPath.c_str(), &stLink)) - throw SysError(format("getting attributes of path `%1%'") % linkPath); + throw SysError(std::format("getting attributes of path `{}'", linkPath)); if (st.st_ino == stLink.st_ino) { - printMsg(lvlDebug, format("`%1%' is already linked to `%2%'") % path % linkPath); + printMsg(lvlDebug, std::format("`{}' is already linked to `{}'", path, linkPath)); return; } if (st.st_size != stLink.st_size) { - printMsg(lvlError, format("removing corrupted link ‘%1%’") % linkPath); + printMsg(lvlError, std::format("removing corrupted link `%1%'", linkPath)); unlink(linkPath.c_str()); goto retry; } - printMsg(lvlTalkative, format("linking ‘%1%’ to ‘%2%’") % path % linkPath); + printMsg(lvlTalkative, std::format("linking `%1%' to `%2%'", path, linkPath)); /* Make the containing directory writable, but only if it's not the store itself (we don't want or need to mess with its @@ -202,8 +202,7 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa its timestamp back to 0. */ MakeReadOnly makeReadOnly(mustToggle ? dirOf(path) : ""); - Path tempLink = (format("%1%/.tmp-link-%2%-%3%") - % settings.nixStore % getpid() % rand()).str(); + Path tempLink = std::format("{}/.tmp-link-{}-{}", settings.nixStore, getpid(), rand()); if (link(linkPath.c_str(), tempLink.c_str()) == -1) { if (errno == EMLINK) { @@ -211,27 +210,27 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa systems). This is likely to happen with empty files. Just shrug and ignore. */ if (st.st_size) - printMsg(lvlInfo, format("`%1%' has maximum number of links") % linkPath); + printMsg(lvlInfo, std::format("`{}' has maximum number of links", linkPath)); return; } - throw SysError(format("cannot link `%1%' to `%2%'") % tempLink % linkPath); + throw SysError(std::format("cannot link `{}' to `{}'", tempLink, linkPath)); } /* Atomically replace the old file with the new hard link. */ if (rename(tempLink.c_str(), path.c_str()) == -1) { int renameErrno = errno; if (unlink(tempLink.c_str()) == -1) - printMsg(lvlError, format("unable to unlink `%1%'") % tempLink); + printMsg(lvlError, std::format("unable to unlink `{}'", tempLink)); if (renameErrno == EMLINK) { /* Some filesystems generate too many links on the rename, rather than on the original link. (Probably it temporarily increases the st_nlink field before decreasing it again.) */ if (st.st_size) - printMsg(lvlInfo, format("`%1%' has maximum number of links") % linkPath); + printMsg(lvlInfo, std::format("`{}' has maximum number of links", linkPath)); return; } - throw SysError(format("cannot rename `%1%' to `%2%'") % tempLink % path); + throw SysError(std::format("cannot rename `{}' to `{}'", tempLink, path)); } stats.filesLinked++; @@ -248,7 +247,7 @@ void LocalStore::optimiseStore(OptimiseStats & stats) for (auto& i : paths) { addTempRoot(i); if (!isValidPath(i)) continue; /* path was GC'ed, probably */ - startNest(nest, lvlChatty, format("hashing files in `%1%'") % i); + startNest(nest, lvlChatty, std::format("hashing files in `{}'", i)); optimisePath_(stats, i, inodeHash); } } @@ -260,9 +259,9 @@ void LocalStore::optimiseStore() optimiseStore(stats); printMsg(lvlError, - format("%1% freed by hard-linking %2% files") - % showBytes(stats.bytesFreed) - % stats.filesLinked); + std::format("{} freed by hard-linking {} files", + showBytes(stats.bytesFreed), + stats.filesLinked)); } void LocalStore::optimisePath(const Path & path) diff --git a/nix/libstore/pathlocks.cc b/nix/libstore/pathlocks.cc index c07f047192cc852ec1f14c885cd2f57cfb270f07..ce4671e20971dbf0b66c290c78562d4b4d954e56 100644 --- a/nix/libstore/pathlocks.cc +++ b/nix/libstore/pathlocks.cc @@ -3,6 +3,8 @@ #include #include +#include +#include #include #include @@ -18,7 +20,7 @@ int openLockFile(const Path & path, bool create) fd = open(path.c_str(), O_RDWR | (create ? O_CREAT : 0), 0600); if (fd == -1 && (create || errno != ENOENT)) - throw SysError(format("opening lock file `%1%'") % path); + throw SysError(std::format("opening lock file `{}'", path)); closeOnExec(fd); @@ -54,14 +56,14 @@ bool lockFile(int fd, LockType lockType, bool wait) while (fcntl(fd, F_SETLKW, &lock) != 0) { checkInterrupt(); if (errno != EINTR) - throw SysError(format("acquiring/releasing lock")); + throw SysError("acquiring/releasing lock"); } } else { while (fcntl(fd, F_SETLK, &lock) != 0) { checkInterrupt(); if (errno == EACCES || errno == EAGAIN) return false; if (errno != EINTR) - throw SysError(format("acquiring/releasing lock")); + throw SysError("acquiring/releasing lock"); } } @@ -109,7 +111,7 @@ bool PathLocks::lockPaths(const PathSet & _paths, Path path = i; Path lockPath = path + ".lock"; - debug(format("locking path `%1%'") % path); + debug(std::format("locking path `{}'", path)); if (lockedPaths.find(lockPath) != lockedPaths.end()) throw Error("deadlock: trying to re-acquire self-held lock"); @@ -134,19 +136,19 @@ bool PathLocks::lockPaths(const PathSet & _paths, } } - debug(format("lock acquired on `%1%'") % lockPath); + debug(std::format("lock acquired on `{}'", lockPath)); /* Check that the lock file hasn't become stale (i.e., hasn't been unlinked). */ struct stat st; if (fstat(fd, &st) == -1) - throw SysError(format("statting lock file `%1%'") % lockPath); + throw SysError(std::format("statting lock file `{}'", lockPath)); if (st.st_size != 0) /* This lock file has been unlinked, so we're holding a lock on a deleted file. This means that other processes may create and acquire a lock on `lockPath', and proceed. So we must retry. */ - debug(format("open lock file `%1%' has become stale") % lockPath); + debug(std::format("open lock file `{}' has become stale", lockPath)); else break; } @@ -178,9 +180,9 @@ void PathLocks::unlock() lockedPaths.erase(i.second); if (close(i.first) == -1) printMsg(lvlError, - format("error (ignored): cannot close lock file on `%1%'") % i.second); + std::format("error (ignored): cannot close lock file on `{}'", i.second)); - debug(format("lock released on `%1%'") % i.second); + debug(std::format("lock released on `{}'", i.second)); } fds.clear(); diff --git a/nix/libstore/references.cc b/nix/libstore/references.cc index d9c8a9fbe38c64e86b780e123aacfc4dcc9d5721..a8ec39ee34b44c3ced8aca018ad7d3a622f60a8f 100644 --- a/nix/libstore/references.cc +++ b/nix/libstore/references.cc @@ -5,7 +5,8 @@ #include #include - +#include +#include namespace nix { @@ -37,8 +38,7 @@ static void search(const unsigned char * s, unsigned int len, if (!match) continue; string ref((const char *) s + i, refLength); if (hashes.find(ref) != hashes.end()) { - debug(format("found reference to `%1%' at offset `%2%'") - % ref % i); + debug(std::format("found reference to `{}' at offset `{}'", ref, i)); seen.insert(ref); hashes.erase(ref); } @@ -93,7 +93,7 @@ PathSet scanForReferences(const string & path, string baseName = baseNameOf(i); string::size_type pos = baseName.find('-'); if (pos == string::npos) - throw Error(format("bad reference `%1%'") % i); + throw Error(std::format("bad reference `{}'", i)); string s = string(baseName, 0, pos); assert(s.size() == refLength); assert(backMap.find(s) == backMap.end()); diff --git a/nix/libstore/sqlite.cc b/nix/libstore/sqlite.cc index e08c67f40ed296cb5766ded6af1d55e20e9f6957..cbd768155ec4d11e6c1632026276486a2f1a342b 100644 --- a/nix/libstore/sqlite.cc +++ b/nix/libstore/sqlite.cc @@ -1,11 +1,14 @@ #include "sqlite.hh" #include "util.hh" +#include +#include + #include namespace nix { -[[noreturn]] void throwSQLiteError(sqlite3 * db, const format & f) +[[noreturn]] void throwSQLiteError(sqlite3 * db, std::string_view f) { int err = sqlite3_errcode(db); if (err == SQLITE_BUSY || err == SQLITE_PROTOCOL) { @@ -28,10 +31,10 @@ namespace nix { #else sleep(1); #endif - throw SQLiteBusy(format("%1%: %2%") % f.str() % sqlite3_errmsg(db)); + throw SQLiteBusy(std::format("{}: {}", f, sqlite3_errmsg(db))); } else - throw SQLiteError(format("%1%: %2%") % f.str() % sqlite3_errmsg(db)); + throw SQLiteError(std::format("{}: {}", f, sqlite3_errmsg(db))); } SQLite::~SQLite() diff --git a/nix/libstore/sqlite.hh b/nix/libstore/sqlite.hh index 6cadba68490123b6be40c30514461ac6e00a464c..0c0bc9e6f5aa9d545cab22c1c977966be763d976 100644 --- a/nix/libstore/sqlite.hh +++ b/nix/libstore/sqlite.hh @@ -3,6 +3,7 @@ #include #include #include +#include #include "types.hh" @@ -85,7 +86,7 @@ struct SQLiteTxn MakeError(SQLiteError, Error); MakeError(SQLiteBusy, SQLiteError); -[[noreturn]] void throwSQLiteError(sqlite3 * db, const format & f); +[[noreturn]] void throwSQLiteError(sqlite3 * db, std::string_view f); /* Convenience function for retrying a SQLite transaction when the database is busy. */ diff --git a/nix/libstore/store-api.cc b/nix/libstore/store-api.cc index 7282188fb3759eebf5a79ca5e7e3d083221f41f8..0596678b8b5fbdb748aa6dc8d62bb503770ead1b 100644 --- a/nix/libstore/store-api.cc +++ b/nix/libstore/store-api.cc @@ -3,7 +3,7 @@ #include "util.hh" #include - +#include namespace nix { @@ -32,14 +32,14 @@ bool isStorePath(const Path & path) void assertStorePath(const Path & path) { if (!isStorePath(path)) - throw Error(format("path `%1%' is not in the store") % path); + throw Error(std::format("path `{}' is not in the store", path)); } Path toStorePath(const Path & path) { if (!isInStore(path)) - throw Error(format("path `%1%' is not in the store") % path); + throw Error(std::format("path `{}' is not in the store", path)); Path::size_type slash = path.find('/', settings.nixStore.size() + 1); if (slash == Path::npos) return path; @@ -61,15 +61,14 @@ void checkStoreName(const string & name) /* Disallow names starting with a dot for possible security reasons (e.g., "." and ".."). */ if (string(name, 0, 1) == ".") - throw Error(format("invalid name: `%1%' (can't begin with dot)") % name); + throw Error(std::format("invalid name: `{}' (can't begin with dot)", name)); for (const auto& i : name) if (!((i >= 'A' && i <= 'Z') || (i >= 'a' && i <= 'z') || (i >= '0' && i <= '9') || validChars.find(i) != string::npos)) { - throw Error(format("invalid character `%1%' in name `%2%'") - % i % name); + throw Error(std::format("invalid character `{}' in name `{}'", i, name)); } } @@ -211,13 +210,13 @@ string StoreAPI::makeValidityRegistration(const PathSet & paths, if (showHash) { s += printHash(info.hash) + "\n"; - s += (format("%1%\n") % info.narSize).str(); + s += std::format("{}\n", info.narSize); } Path deriver = showDerivers ? info.deriver : ""; s += deriver + "\n"; - s += (format("%1%\n") % info.references.size()).str(); + s += std::format("{}\n", info.references.size()); for (auto& j : info.references) s += j + "\n"; diff --git a/nix/libutil/affinity.cc b/nix/libutil/affinity.cc index 3e21f43a2e9d1b23e40a7f524a514730981bdbfc..d50e9f3e9cdc5c999e1f39bdef9689b6b3b34d1f 100644 --- a/nix/libutil/affinity.cc +++ b/nix/libutil/affinity.cc @@ -2,6 +2,8 @@ #include "util.hh" #include "affinity.hh" +#include + #if HAVE_SCHED_H #include #endif @@ -20,12 +22,12 @@ void setAffinityTo(int cpu) #if HAVE_SCHED_SETAFFINITY if (sched_getaffinity(0, sizeof(cpu_set_t), &savedAffinity) == -1) return; didSaveAffinity = true; - printMsg(lvlDebug, format("locking this thread to CPU %1%") % cpu); + printMsg(lvlDebug, std::format("locking this thread to CPU {}", cpu)); cpu_set_t newAffinity; CPU_ZERO(&newAffinity); CPU_SET(cpu, &newAffinity); if (sched_setaffinity(0, sizeof(cpu_set_t), &newAffinity) == -1) - printMsg(lvlError, format("failed to lock thread to CPU %1%") % cpu); + printMsg(lvlError, std::format("failed to lock thread to CPU {}", cpu)); #endif } diff --git a/nix/libutil/archive.cc b/nix/libutil/archive.cc index 54bcd21f936118ced3317663a8642557383d68b3..0df5285860be493c55a0f8709b65a23857e4787a 100644 --- a/nix/libutil/archive.cc +++ b/nix/libutil/archive.cc @@ -6,6 +6,7 @@ #include #include #include +#include #include // for strcasecmp @@ -35,7 +36,7 @@ static void dumpContents(const Path & path, size_t size, writeLongLong(size, sink); AutoCloseFD fd = open(path.c_str(), O_RDONLY); - if (fd == -1) throw SysError(format("opening file `%1%'") % path); + if (fd == -1) throw SysError(std::format("opening file `{}'", path)); unsigned char buf[65536]; size_t left = size; @@ -55,7 +56,7 @@ static void dump(const Path & path, Sink & sink, PathFilter & filter) { struct stat st; if (lstat(path.c_str(), &st)) - throw SysError(format("getting attributes of path `%1%'") % path); + throw SysError(std::format("getting attributes of path `{}'", path)); writeString("(", sink); @@ -98,7 +99,7 @@ static void dump(const Path & path, Sink & sink, PathFilter & filter) writeString(readLink(path), sink); } - else throw Error(format("file `%1%' has an unsupported type") % path); + else throw Error(std::format("file `{}' has an unsupported type", path)); writeString(")", sink); } @@ -227,7 +228,7 @@ static void parse(ParseSink & sink, Source & source, const Path & path) } else if (s == "name") { name = readString(source); if (name.empty() || name == "." || name == ".." || name.find('/') != string::npos || name.find((char) 0) != string::npos) - throw Error(format("NAR contains invalid file name `%1%'") % name); + throw Error(std::format("NAR contains invalid file name `{}'", name)); if (name <= prevName) throw Error("NAR directory is not sorted"); prevName = name; @@ -274,7 +275,7 @@ struct RestoreSink : ParseSink { Path p = dstPath + path; if (mkdir(p.c_str(), 0777) == -1) - throw SysError(format("creating directory `%1%'") % p); + throw SysError(std::format("creating directory `{}'", p)); }; void createRegularFile(const Path & path) @@ -282,7 +283,7 @@ struct RestoreSink : ParseSink Path p = dstPath + path; fd.close(); fd = open(p.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0666); - if (fd == -1) throw SysError(format("creating file `%1%'") % p); + if (fd == -1) throw SysError(std::format("creating file `{}'", p)); } void isExecutable() @@ -304,7 +305,7 @@ struct RestoreSink : ParseSink OpenSolaris). Since preallocation is just an optimisation, ignore it. */ if (errno && errno != EINVAL) - throw SysError(format("preallocating file of %1% bytes") % len); + throw SysError(std::format("preallocating file of {} bytes", len)); } #endif } diff --git a/nix/libutil/hash.cc b/nix/libutil/hash.cc index 3cb4d05318bba5b0bc68df5bfbbc3f8a52201449..57b369d4a9b5c4196665dc5824f2171784c353e2 100644 --- a/nix/libutil/hash.cc +++ b/nix/libutil/hash.cc @@ -2,6 +2,9 @@ #include #include +#include +#include +#include #include "hash.hh" #include "archive.hh" @@ -73,18 +76,18 @@ string printHash(const Hash & hash) } -Hash parseHash(HashType ht, const string & s) +Hash parseHash(HashType ht, std::string_view s) { Hash hash(ht); if (s.length() != hash.hashSize * 2) { string algo = gcry_md_algo_name(ht); - throw Error(format("invalid %1% hash '%2%' (%3% bytes but expected %4%)") - % algo % s % (s.length() / 2) % hash.hashSize); + throw Error(std::format("invalid {} hash '{}' ({} bytes but expected {})", + algo, s, (s.length() / 2), hash.hashSize)); } for (unsigned int i = 0; i < hash.hashSize; i++) { string s2(s, i * 2, 2); if (!isxdigit(s2[0]) || !isxdigit(s2[1])) - throw Error(format("invalid hash `%1%'") % s); + throw Error(std::format("invalid hash `{}'", s)); std::istringstream str(s2); int n; str >> std::hex >> n; @@ -132,7 +135,7 @@ string printHash16or32(const Hash & hash) } -Hash parseHash32(HashType ht, const string & s) +Hash parseHash32(HashType ht, std::string_view s) { Hash hash(ht); unsigned int len = hashLength32(ht); @@ -144,7 +147,7 @@ Hash parseHash32(HashType ht, const string & s) for (digit = 0; digit < base32Chars.size(); ++digit) /* !!! slow */ if (base32Chars[digit] == c) break; if (digit >= 32) - throw Error(format("invalid base-32 hash '%1%'") % s); + throw Error(std::format("invalid base-32 hash '{}'", s)); unsigned int b = n * 5; unsigned int i = b / 8; unsigned int j = b % 8; @@ -156,7 +159,7 @@ Hash parseHash32(HashType ht, const string & s) } -Hash parseHash16or32(HashType ht, const string & s) +Hash parseHash16or32(HashType ht, std::string_view s) { Hash hash(ht); if (s.size() == hash.hashSize * 2) @@ -166,13 +169,13 @@ Hash parseHash16or32(HashType ht, const string & s) /* base-32 representation */ hash = parseHash32(ht, s); else - throw Error(format("hash `%1%' has wrong length for hash type `%2%'") - % s % printHashType(ht)); + throw Error(std::format("hash `{}' has wrong length for hash type `{}'", + s, printHashType(ht))); return hash; } -bool isHash(const string & s) +bool isHash(std::string_view s) { if (s.length() != 32) return false; for (int i = 0; i < 32; i++) { @@ -247,13 +250,13 @@ Hash hashFile(HashType ht, const Path & path) start(ht, ctx); AutoCloseFD fd = open(path.c_str(), O_RDONLY); - if (fd == -1) throw SysError(format("computing hash of file `%1%'") % path); + if (fd == -1) throw SysError(std::format("computing hash of file `{}'", path)); unsigned char buf[8192]; ssize_t n; while ((n = read(fd, buf, sizeof(buf)))) { checkInterrupt(); - if (n == -1) throw SysError(format("reading file `%1%'") % path); + if (n == -1) throw SysError(std::format("reading file `{}'", path)); update(ht, ctx, buf, n); } diff --git a/nix/libutil/hash.hh b/nix/libutil/hash.hh index ac58651a0286c3a0bf906781ea4bc6b8cbcf0183..1a6b35f074b22b3ec59fe75d2e8e5b728127db02 100644 --- a/nix/libutil/hash.hh +++ b/nix/libutil/hash.hh @@ -51,7 +51,7 @@ struct Hash string printHash(const Hash & hash); /* Parse a hexadecimal representation of a hash code. */ -Hash parseHash(HashType ht, const string & s); +Hash parseHash(HashType ht, std::string_view s); /* Returns the length of a base-32 hash representation. */ unsigned int hashLength32(const Hash & hash); @@ -63,13 +63,13 @@ string printHash32(const Hash & hash); string printHash16or32(const Hash & hash); /* Parse a base-32 representation of a hash code. */ -Hash parseHash32(HashType ht, const string & s); +Hash parseHash32(HashType ht, std::string_view s); /* Parse a base-16 or base-32 representation of a hash code. */ -Hash parseHash16or32(HashType ht, const string & s); +Hash parseHash16or32(HashType ht, std::string_view s); /* Verify that the given string is a valid hash code. */ -bool isHash(const string & s); +bool isHash(std::string_view s); /* Compute the hash of the given string. */ Hash hashString(HashType ht, const string & s); diff --git a/nix/libutil/serialise.cc b/nix/libutil/serialise.cc index 01aeea25c0caf6b7d216aa1b4a6d5ffd8f2e0370..befb049c8aee6eacc103443e4cd4900048e4cc98 100644 --- a/nix/libutil/serialise.cc +++ b/nix/libutil/serialise.cc @@ -3,7 +3,7 @@ #include #include - +#include namespace nix { diff --git a/nix/libutil/spawn.cc b/nix/libutil/spawn.cc index 7855275494f6c1668f4d039d921ec684ef07b97c..c25c3a681f259fd6cb2bbb8f65a5864285989342 100644 --- a/nix/libutil/spawn.cc +++ b/nix/libutil/spawn.cc @@ -30,6 +30,8 @@ #include #include #include +#include +#include #if HAVE_SYS_MOUNT_H #include @@ -61,8 +63,11 @@ #define pivot_root(new_root, put_old) (syscall(SYS_pivot_root, new_root,put_old)) #endif - -#define CLONE_ENABLED defined(CLONE_NEWNS) +#if defined(CLONE_NEWNS) +#define CLONE_ENABLED 1 +#else +#define CLONE_ENABLED 0 +#endif #if CLONE_ENABLED #include @@ -84,7 +89,7 @@ void addPhaseAfter(Phases & phases, string afterLabel, string addLabel, Action a phases.insert(i, p); return; } - throw Error(format("label `%1%' not found in phases") % afterLabel); + throw Error(std::format("label `{}' not found in phases", afterLabel)); } @@ -98,7 +103,7 @@ void addPhaseBefore(Phases & phases, string beforeLabel, string addLabel, Action phases.insert(i, p); return; } - throw Error(format("label `%1%' not found in phases") % beforeLabel); + throw Error(std::format("label `{}' not found in phases", beforeLabel)); } @@ -127,7 +132,7 @@ void deletePhase(Phases & phases, string delLabel) phases.erase(i); return; } - throw Error(format("label `%1%' not found in phases") % delLabel); + throw Error(std::format("label `{}' not found in phases", delLabel)); } @@ -138,7 +143,7 @@ void replacePhase(Phases & phases, string replaceLabel, Action newAction) (*i).action = newAction; return; } - throw Error(format("label `%1' not found in phases") % replaceLabel); + throw Error(std::format("label `{}' not found in phases", replaceLabel)); } @@ -190,7 +195,7 @@ static void earlyIOSetupAction(SpawnContext & ctx) /* Doesn't make sense for it to be writable, but compatibility... */ AutoCloseFD fd = open(ctx.stdinFile.c_str(), O_RDWR); if(fd == -1) - throw SysError(format("cannot open `%1%'") % ctx.stdinFile); + throw SysError(std::format("cannot open `{}'", ctx.stdinFile)); if(dup2(fd, STDIN_FILENO) == -1) throw SysError("cannot dup2 fd into stdin fd"); } @@ -216,7 +221,7 @@ static void chrootAction(SpawnContext & ctx) if(ctx.doChroot) #if HAVE_CHROOT if(chroot(ctx.chrootRootDir.c_str()) == -1) - throw SysError(format("cannot change root directory to '%1%'") % ctx.chrootRootDir); + throw SysError(std::format("cannot change root directory to '{}'", ctx.chrootRootDir)); #else throw Error("chroot is not supported on this system"); #endif @@ -227,7 +232,7 @@ static void chdirAction(SpawnContext & ctx) { if(ctx.setcwd) if(chdir(ctx.cwd.c_str()) == -1) - throw SysError(format("changing into `%1%'") % ctx.cwd); + throw SysError(std::format("changing into `{}'", ctx.cwd)); } @@ -353,7 +358,7 @@ void execAction(SpawnContext & ctx) // kept public for use in 'build.cc' env = envPtrs.data(); } if(execvpe(ctx.program.c_str(), stringsToCharPtrs(ctx.args).data(), env) == -1) - throw SysError(format("executing `%1%'") % ctx.program); + throw SysError(std::format("executing `{}'", ctx.program)); } @@ -478,11 +483,11 @@ static void makeChrootSeparateFilesystemAction(SpawnContext & sctx) a tmpfs on it. */ if(ctx.mountTmpfsOnChroot) { if(mount("none", ctx.chrootRootDir.c_str(), "tmpfs", 0, 0) == -1) - throw SysError(format("unable to mount tmpfs on `%1%'") % ctx.chrootRootDir); + throw SysError(std::format("unable to mount tmpfs on `{}'", ctx.chrootRootDir)); } else { if(mount(ctx.chrootRootDir.c_str(), ctx.chrootRootDir.c_str(), 0, MS_BIND, 0) == -1) - throw SysError(format("unable to bind mount ‘%1%’") % ctx.chrootRootDir); + throw SysError(std::format("unable to bind mount `{}'", ctx.chrootRootDir)); } } #endif @@ -526,7 +531,7 @@ static void bindMount(Path source, Path target, bool readOnly) #if HAVE_SYS_MOUNT_H && defined(MS_BIND) struct stat st; if (lstat(source.c_str(), &st) == -1) - throw SysError(format("getting attributes of path `%1%'") % source); + throw SysError(std::format("getting attributes of path `{}'", source)); if(S_ISDIR(st.st_mode)) createDirs(target); @@ -545,11 +550,11 @@ static void bindMount(Path source, Path target, bool readOnly) while(true){ if(lstat(target.c_str(), &st2) != -1) { if(!S_ISREG(st2.st_mode)) - throw Error(format("mount target `%1%' exists but is not a regular file") % target); + throw Error(std::format("mount target `{}' exists but is not a regular file", target)); break; } if(errno != ENOENT) { - throw SysError(format("stat'ing path `%1%'") % target); + throw SysError(std::format("stat'ing path `{}'", target)); } AutoCloseFD fd = open(target.c_str(), O_WRONLY | O_NOFOLLOW | O_CREAT | O_EXCL, @@ -561,7 +566,7 @@ static void bindMount(Path source, Path target, bool readOnly) /* Note: because of O_CREAT | O_EXCL, EACCES can only mean a * permission issue with the parent directory */ if(errno != EEXIST) - throw SysError(format("Creating placeholder regular file target mount `%1%'") % target); + throw SysError(std::format("Creating placeholder regular file target mount `{}'", target)); } } @@ -569,7 +574,7 @@ static void bindMount(Path source, Path target, bool readOnly) are in an unprivileged mount namespace and not specifying MS_REC would reveal subtrees that had been covered up. */ if (mount(source.c_str(), target.c_str(), 0, MS_BIND|MS_REC, 0) == -1) - throw SysError(format("bind mount from `%1%' to `%2%' failed") % source % target); + throw SysError(std::format("bind mount from `{}' to `{}' failed", source, target)); if(readOnly) { #if defined(MS_REMOUNT) && defined(MS_RDONLY) /* Extra flags passed with MS_BIND are ignored, hence the extra @@ -581,12 +586,12 @@ static void bindMount(Path source, Path target, bool readOnly) #if HAVE_STATVFS struct statvfs stvfs; if(statvfs(target.c_str(), &stvfs) == -1) - throw SysError(format("statvfs of `%1%'") % target); + throw SysError(std::format("statvfs of `{}'", target)); mount_flags |= statfsToMountFlags(stvfs.f_flag); #endif if (mount(source.c_str(), target.c_str(), 0, mount_flags, 0) == -1) - throw SysError(format("read-only remount of `%1%' failed") % target); + throw SysError(std::format("read-only remount of `{}' failed", target)); #else throw Error("remounting read-only is not supported on this platform"); #endif @@ -631,7 +636,7 @@ static void mountProcAction(SpawnContext & sctx) Path target = (ctx.doChroot ? ctx.chrootRootDir : "") + "/proc"; createDirs(target); if(mount("none", target.c_str(), "proc", 0, 0) == -1) - throw SysError(format("mounting `%1%'") % target); + throw SysError(std::format("mounting `{}'", target)); } #endif } @@ -645,7 +650,7 @@ static void mountDevshmAction(SpawnContext & sctx) Path target = (ctx.doChroot ? ctx.chrootRootDir : "") + "/dev/shm"; createDirs(target); if(mount("none", target.c_str(), "tmpfs", 0, 0) == -1) - throw SysError(format("mounting `%1%'") % target); + throw SysError(std::format("mounting `{}'", target)); } #endif } @@ -661,13 +666,13 @@ static void mountDevptsAction(SpawnContext & sctx) if(pathExists(chroot + "/dev/ptmx")) return; createDirs(target); if(mount("none", target.c_str(), "devpts", 0, "newinstance,mode=0620") == -1) - throw SysError(format("mounting `%1%'") % target); + throw SysError(std::format("mounting `{}'", target)); createSymlink("/dev/pts/ptmx", chroot + "/dev/ptmx"); /* Make sure /dev/pts/ptmx is world-writable. With some Linux versions, it is created with permissions 0. */ Path targetPtmx = chroot + "/dev/pts/ptmx"; if (chmod(targetPtmx.c_str(), 0666) == -1) - throw SysError(format("setting permissions on `%1%'") % targetPtmx); + throw SysError(std::format("setting permissions on `{}'", targetPtmx)); } #endif } @@ -679,16 +684,16 @@ static void pivotRootAction(SpawnContext & sctx) CloneSpawnContext & ctx = (CloneSpawnContext &) sctx; if((ctx.cloneFlags & CLONE_NEWNS) != 0 && ctx.doChroot) { if (chdir(ctx.chrootRootDir.c_str()) == -1) - throw SysError(format("cannot change directory to '%1%'") % ctx.chrootRootDir); + throw SysError(std::format("cannot change directory to '{}'", ctx.chrootRootDir)); if (mkdir("real-root", 0) == -1) throw SysError("cannot create real-root directory"); if (pivot_root(".", "real-root") == -1) - throw SysError(format("cannot pivot old root directory onto '%1%'") % (ctx.chrootRootDir + "/real-root")); + throw SysError(std::format("cannot pivot old root directory onto '{}'", (ctx.chrootRootDir + "/real-root"))); if (chroot(".") == -1) - throw SysError(format("cannot change root directory to '%1%'") % ctx.chrootRootDir); + throw SysError(std::format("cannot change root directory to '{}'", ctx.chrootRootDir)); if (umount2("real-root", MNT_DETACH) == -1) throw SysError("cannot unmount real root filesystem"); @@ -761,7 +766,7 @@ void unshareAndInitUserns(int flags, const string & uidMap, throw SysError("reaping userns init process"); } if(!(WIFEXITED(status) != 0 && WEXITSTATUS(status) == EXIT_SUCCESS)) - throw Error(format("userns init child exited with status %1%") % WEXITSTATUS(status)); + throw Error(std::format("userns init child exited with status {}", WEXITSTATUS(status))); } #endif } diff --git a/nix/libutil/types.hh b/nix/libutil/types.hh index 62889e6fa99c5d531e3fb1f4884cc37cfc218971..1ea5e96c01fe938143f349dd51a9ed8d3d6a2fa9 100644 --- a/nix/libutil/types.hh +++ b/nix/libutil/types.hh @@ -5,8 +5,9 @@ #include #include #include +#include +#include -#include /* Before 4.7, gcc's std::exception uses empty throw() specifiers for * its (virtual) destructor and what() in c++11 mode, in violation of spec @@ -26,16 +27,6 @@ using std::string; using std::list; using std::set; using std::vector; -using boost::format; - - -struct FormatOrString -{ - string s; - FormatOrString(const string & s) : s(s) { }; - FormatOrString(const format & f) : s(f.str()) { }; - FormatOrString(const char * s) : s(s) { }; -}; /* BaseError should generally not be caught, as it has Interrupted as @@ -47,7 +38,7 @@ protected: string err; public: unsigned int status; // exit status - BaseError(const FormatOrString & fs, unsigned int status = 1); + BaseError(std::string_view fs, unsigned int status = 1); #ifdef EXCEPTION_NEEDS_THROW_SPEC ~BaseError() throw () { }; const char * what() const throw () { return err.c_str(); } @@ -56,14 +47,14 @@ public: #endif const string & msg() const { return err; } const string & prefix() const { return prefix_; } - BaseError & addPrefix(const FormatOrString & fs); + BaseError & addPrefix(std::string fs); }; #define MakeError(newClass, superClass) \ class newClass : public superClass \ { \ public: \ - newClass(const FormatOrString & fs, unsigned int status = 1) : superClass(fs, status) { }; \ + newClass(std::string_view fs, unsigned int status = 1) : superClass(fs, status) { }; \ }; MakeError(Error, BaseError) @@ -72,7 +63,7 @@ class SysError : public Error { public: int errNo; - SysError(const FormatOrString & fs); + SysError(std::string_view fs); }; diff --git a/nix/libutil/util.cc b/nix/libutil/util.cc index 77f2547b0a587fe0ae617789f0c694e249764ea3..ddce9879caccd0feda812a4f2a177d5e52e871e5 100644 --- a/nix/libutil/util.cc +++ b/nix/libutil/util.cc @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include #include @@ -35,22 +37,22 @@ extern char * * environ; namespace nix { -BaseError::BaseError(const FormatOrString & fs, unsigned int status) +BaseError::BaseError(std::string_view fs, unsigned int status) : status(status) { - err = fs.s; + err = fs; } -BaseError & BaseError::addPrefix(const FormatOrString & fs) +BaseError & BaseError::addPrefix(std::string fs) { - prefix_ = fs.s + prefix_; + prefix_ = fs + prefix_; return *this; } -SysError::SysError(const FormatOrString & fs) - : Error(format("%1%: %2%") % fs.s % strerror(errno)) +SysError::SysError(std::string_view fs) + : Error(std::format("{}: {}", fs, strerror(errno))) , errNo(errno) { } @@ -114,7 +116,7 @@ Path canonPath(const Path & path, bool resolveSymlinks) string s; if (path[0] != '/') - throw Error(format("not an absolute path: `%1%'") % path); + throw Error(std::format("not an absolute path: `{}'", path)); string::const_iterator i = path.begin(), end = path.end(); string temp; @@ -150,7 +152,7 @@ Path canonPath(const Path & path, bool resolveSymlinks) the symlink target might contain new symlinks). */ if (resolveSymlinks && isLink(s)) { if (++followCount >= maxFollow) - throw Error(format("infinite symlink recursion in path `%1%'") % path); + throw Error(std::format("infinite symlink recursion in path `{}'", path)); temp = absPath(readLink(s), dirOf(s)) + string(i, end); i = temp.begin(); /* restart */ @@ -168,7 +170,7 @@ Path dirOf(const Path & path) { Path::size_type pos = path.rfind('/'); if (pos == string::npos) - throw Error(format("invalid file name `%1%'") % path); + throw Error(std::format("invalid file name `{}'", path)); return pos == 0 ? "/" : Path(path, 0, pos); } @@ -177,7 +179,7 @@ string baseNameOf(const Path & path) { Path::size_type pos = path.rfind('/'); if (pos == string::npos) - throw Error(format("invalid file name `%1%'") % path); + throw Error(std::format("invalid file name `{}'", path)); return string(path, pos + 1); } @@ -195,7 +197,7 @@ struct stat lstat(const Path & path) { struct stat st; if (lstat(path.c_str(), &st)) - throw SysError(format("getting status of `%1%'") % path); + throw SysError(std::format("getting status of `{}'", path)); return st; } @@ -212,7 +214,7 @@ bool pathExists(const Path & path) #endif if (!res) return true; if (errno != ENOENT && errno != ENOTDIR) - throw SysError(format("getting status of %1%") % path); + throw SysError(std::format("getting status of {}", path)); return false; } @@ -222,14 +224,14 @@ Path readLink(const Path & path) checkInterrupt(); struct stat st = lstat(path); if (!S_ISLNK(st.st_mode)) - throw Error(format("`%1%' is not a symlink") % path); + throw Error(std::format("`{}' is not a symlink", path)); std::vector buf(st.st_size); ssize_t rlsize = readlink(path.c_str(), buf.data(), st.st_size); if (rlsize == -1) - throw SysError(format("reading symbolic link '%1%'") % path); + throw SysError(std::format("reading symbolic link '{}'", path)); else if (rlsize > st.st_size) - throw Error(format("symbolic link ‘%1%’ size overflow %2% > %3%") - % path % rlsize % st.st_size); + throw Error(std::format("symbolic link `{}' size overflow {} > {}", + path, rlsize, st.st_size)); return string(buf.begin(), buf.end()); } @@ -253,7 +255,7 @@ static DirEntries readDirectory(DIR *dir) if (name == "." || name == "..") continue; entries.emplace_back(name, dirent->d_ino, dirent->d_type); } - if (errno) throw SysError(format("reading directory")); + if (errno) throw SysError("reading directory"); return entries; } @@ -261,7 +263,7 @@ static DirEntries readDirectory(DIR *dir) DirEntries readDirectory(const Path & path) { AutoCloseDir dir = opendir(path.c_str()); - if (!dir) throw SysError(format("opening directory `%1%'") % path); + if (!dir) throw SysError(std::format("opening directory `{}'", path)); return readDirectory(dir); } @@ -273,7 +275,7 @@ static DirEntries readDirectory(int fd) if (fdcopy < 0) throw SysError("dup"); AutoCloseDir dir = fdopendir(fdcopy); - if (!dir) throw SysError(format("opening directory from file descriptor `%1%'") % fd); + if (!dir) throw SysError(std::format("opening directory from file descriptor `{}'", fd)); return readDirectory(dir); } @@ -304,7 +306,7 @@ string readFile(const Path & path, bool drain) { AutoCloseFD fd = open(path.c_str(), O_RDONLY); if (fd == -1) - throw SysError(format("reading file `%1%'") % path); + throw SysError(std::format("reading file `{}'", path)); return drain ? drainFD(fd) : readFile(fd); } @@ -313,7 +315,7 @@ void writeFile(const Path & path, const string & s) { AutoCloseFD fd = open(path.c_str(), O_WRONLY | O_TRUNC | O_CREAT, 0666); if (fd == -1) - throw SysError(format("writing file '%1%'") % path); + throw SysError(std::format("writing file '{}'", path)); writeFull(fd, s); } @@ -349,7 +351,7 @@ static void _deletePathAt(int fd, const Path & path, const Path & fullPath, unsi { checkInterrupt(); - printMsg(lvlVomit, format("%1%") % fullPath); + printMsg(lvlVomit, std::format("{}", fullPath)); #ifdef HAVE_STATX # define st_mode stx_mode @@ -364,7 +366,7 @@ static void _deletePathAt(int fd, const Path & path, const Path & fullPath, unsi struct stat st; #endif if (fstatat(fd, path.c_str(), &st, AT_SYMLINK_NOFOLLOW)) - throw SysError(format("getting status of `%1%'") % fullPath); + throw SysError(std::format("getting status of `{}'", fullPath)); /* Note: if another process modifies what is at 'path' between now and when we actually delete it, this may be inaccurate, but I know of no @@ -380,17 +382,17 @@ static void _deletePathAt(int fd, const Path & path, const Path & fullPath, unsi O_NOFOLLOW | O_CLOEXEC); if(!dirfd.isOpen()) - throw SysError(format("opening `%1%'") % fullPath); + throw SysError(std::format("opening `{}'", fullPath)); /* st.st_mode may currently be from a different file than what we actually opened, get it straight from the file instead */ if(fstat(dirfd, &st)) - throw SysError(format("re-getting status of `%1'") % fullPath); + throw SysError(std::format("re-getting status of `{}'", fullPath)); /* Make the directory writable. */ if (!(st.st_mode & S_IWUSR)) { if (fchmod(dirfd, st.st_mode | S_IWUSR) == -1) - throw SysError(format("making `%1%' writable") % fullPath); + throw SysError(std::format("making `{}' writable", fullPath)); } for (auto & i : readDirectory(dirfd)) @@ -400,7 +402,7 @@ static void _deletePathAt(int fd, const Path & path, const Path & fullPath, unsi int ret; ret = unlinkat(fd, path.c_str(), S_ISDIR(st.st_mode) ? AT_REMOVEDIR : 0 ); if (ret == -1) - throw SysError(format("cannot unlink `%1%'") % fullPath); + throw SysError(std::format("cannot unlink `{}'", fullPath)); #undef st_mode #undef st_size @@ -425,7 +427,7 @@ void deletePath(const Path & path) void deletePath(const Path & path, unsigned long long & bytesFreed, size_t linkThreshold) { startNest(nest, lvlDebug, - format("recursively deleting path `%1%'") % path); + std::format("recursively deleting path `{}'", path)); bytesFreed = 0; _deletePath(path, bytesFreed, linkThreshold); } @@ -447,14 +449,14 @@ static void copyFile(int sourceFd, int destinationFd) } } else { if (result < 0) - throw SysError(format("copy_file_range `%1%' to `%2%'") % sourceFd % destinationFd); + throw SysError(std::format("copy_file_range `{}' to `{}'", sourceFd, destinationFd)); /* If 'copy_file_range' copied less than requested, try again. */ for (ssize_t copied = result; copied < st.st_size; copied += result) { result = copy_file_range(sourceFd, NULL, destinationFd, NULL, st.st_size - copied, 0); if (result < 0) - throw SysError(format("copy_file_range `%1%' to `%2%'") % sourceFd % destinationFd); + throw SysError(std::format("copy_file_range `{}' to `{}'", sourceFd, destinationFd)); } } } @@ -465,18 +467,18 @@ static void copyFileRecursively(int sourceroot, const Path &source, { struct stat st; if (fstatat(sourceroot, source.c_str(), &st, AT_SYMLINK_NOFOLLOW) == -1) - throw SysError(format("statting file `%1%'") % source); + throw SysError(std::format("statting file `{}'", source)); if (S_ISREG(st.st_mode)) { AutoCloseFD sourceFd = openat(sourceroot, source.c_str(), O_CLOEXEC | O_NOFOLLOW | O_RDONLY); - if (sourceFd == -1) throw SysError(format("opening `%1%'") % source); + if (sourceFd == -1) throw SysError(std::format("opening `{}'", source)); AutoCloseFD destinationFd = openat(destinationroot, destination.c_str(), O_CLOEXEC | O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW | O_EXCL, st.st_mode); - if (destinationFd == -1) throw SysError(format("opening `%1%'") % source); + if (destinationFd == -1) throw SysError(std::format("opening `{}'", source)); copyFile(sourceFd, destinationFd); fchown(destinationFd, st.st_uid, st.st_gid); @@ -487,37 +489,37 @@ static void copyFileRecursively(int sourceroot, const Path &source, target[st.st_size] = '\0'; int err = symlinkat(target.data(), destinationroot, destination.c_str()); if (err != 0) - throw SysError(format("creating symlink `%1%'") % destination); + throw SysError(std::format("creating symlink `{}'", destination)); fchownat(destinationroot, destination.c_str(), st.st_uid, st.st_gid, AT_SYMLINK_NOFOLLOW); } else if (S_ISDIR(st.st_mode)) { int err = mkdirat(destinationroot, destination.c_str(), 0755); if (err != 0) - throw SysError(format("creating directory `%1%'") % destination); + throw SysError(std::format("creating directory `{}'", destination)); AutoCloseFD destinationFd = openat(destinationroot, destination.c_str(), O_CLOEXEC | O_RDONLY | O_DIRECTORY | O_NOFOLLOW); if (err != 0) - throw SysError(format("opening directory `%1%'") % destination); + throw SysError(std::format("opening directory `{}'", destination)); AutoCloseFD sourceFd = openat(sourceroot, source.c_str(), O_CLOEXEC | O_NOFOLLOW | O_RDONLY); if (sourceFd == -1) - throw SysError(format("opening `%1%'") % source); + throw SysError(std::format("opening `{}'", source)); if (deleteSource && !(st.st_mode & S_IWUSR)) { /* Ensure the directory is writable so files within it can be deleted. */ if (fchmod(sourceFd, st.st_mode | S_IWUSR) == -1) - throw SysError(format("making `%1%' directory writable") % source); + throw SysError(std::format("making `{}' directory writable", source)); } for (auto & i : readDirectory(sourceFd)) copyFileRecursively((int)sourceFd, i.name, (int)destinationFd, i.name, deleteSource); fchown(destinationFd, st.st_uid, st.st_gid); - } else throw Error(format("refusing to copy irregular file `%1%'") % source); + } else throw Error(std::format("refusing to copy irregular file `{}'", source)); if (deleteSource) unlinkat(sourceroot, source.c_str(), @@ -534,9 +536,9 @@ static Path tempName(Path tmpRoot, const Path & prefix, bool includePid, { tmpRoot = canonPath(tmpRoot.empty() ? getEnv("TMPDIR", "/tmp") : tmpRoot, true); if (includePid) - return (format("%1%/%2%-%3%-%4%") % tmpRoot % prefix % getpid() % counter++).str(); + return std::format("{}/{}-{}-{}", tmpRoot, prefix, getpid(), counter++); else - return (format("%1%/%2%-%3%") % tmpRoot % prefix % counter++).str(); + return std::format("{}/{}-{}", tmpRoot, prefix, counter++); } @@ -560,11 +562,11 @@ Path createTempDir(const Path & tmpRoot, const Path & prefix, "wheel", then "tar" will fail to unpack archives that have the setgid bit set on directories. */ if (chown(tmpDir.c_str(), (uid_t) -1, getegid()) != 0) - throw SysError(format("setting group of directory `%1%'") % tmpDir); + throw SysError(std::format("setting group of directory `{}'", tmpDir)); return tmpDir; } if (errno != EEXIST) - throw SysError(format("creating directory `%1%'") % tmpDir); + throw SysError(std::format("creating directory `{}'", tmpDir)); } } @@ -578,15 +580,15 @@ Paths createDirs(const Path & path) if (lstat(path.c_str(), &st) == -1) { created = createDirs(dirOf(path)); if (mkdir(path.c_str(), 0777) == -1 && errno != EEXIST) - throw SysError(format("creating directory `%1%'") % path); + throw SysError(std::format("creating directory `{}'", path)); st = lstat(path); created.push_back(path); } if (S_ISLNK(st.st_mode) && stat(path.c_str(), &st) == -1) - throw SysError(format("statting symlink `%1%'") % path); + throw SysError(std::format("statting symlink `{}'", path)); - if (!S_ISDIR(st.st_mode)) throw Error(format("`%1%' is not a directory") % path); + if (!S_ISDIR(st.st_mode)) throw Error(std::format("`{}' is not a directory", path)); return created; } @@ -595,7 +597,7 @@ Paths createDirs(const Path & path) void createSymlink(const Path & target, const Path & link) { if (symlink(target.c_str(), link.c_str())) - throw SysError(format("creating symlink from `%1%' to `%2%'") % link % target); + throw SysError(std::format("creating symlink from `{}' to `{}'", link, target)); } @@ -623,12 +625,12 @@ static string escVerbosity(Verbosity level) } -void Nest::open(Verbosity level, const FormatOrString & fs) +void Nest::open(Verbosity level, std::string_view fs) { if (level <= verbosity) { if (logType == ltEscapes) std::cerr << "\033[" << escVerbosity(level) << "p" - << fs.s << "\n"; + << fs << "\n"; else printMsg_(level, fs); nest = true; @@ -648,7 +650,7 @@ void Nest::close() } -void printMsg_(Verbosity level, const FormatOrString & fs) +void printMsg_(Verbosity level, std::string_view fs) { checkInterrupt(); if (level > verbosity) return; @@ -658,15 +660,15 @@ void printMsg_(Verbosity level, const FormatOrString & fs) prefix += "| "; else if (logType == ltEscapes && level != lvlInfo) prefix = "\033[" + escVerbosity(level) + "s"; - string s = (format("%1%%2%\n") % prefix % fs.s).str(); + string s = std::format("{}{}\n", prefix, fs); writeToStderr(s); } -void warnOnce(bool & haveWarned, const FormatOrString & fs) +void warnOnce(bool & haveWarned, std::string_view fs) { if (!haveWarned) { - printMsg(lvlError, format("warning: %1%") % fs.s); + printMsg(lvlError, std::format("warning: {}", fs)); haveWarned = true; } } @@ -685,7 +687,7 @@ void writeToStderr(const string & s) write errors in exception handlers to ensure that cleanup code runs to completion if the other side of stderr has been closed unexpectedly. */ - if (!std::uncaught_exception()) throw; + if (std::uncaught_exceptions() == 0) throw; } } @@ -754,8 +756,8 @@ void waitForMessage(int fd, const string & message) string str(message.length(), '\0'); readFull(fd, (unsigned char*)str.data(), message.length()); if (str != message) - throw Error(format("did not receive message '%1%' on file descriptor %2%") - % message % fd); + throw Error(std::format("did not receive message '{}' on file descriptor {}", + message, fd)); } @@ -777,7 +779,7 @@ AutoDelete::~AutoDelete() deletePath(path); else { if (remove(path.c_str()) == -1) - throw SysError(format("cannot unlink `%1%'") % path); + throw SysError(std::format("cannot unlink `{}'", path)); } } } catch (...) { @@ -848,7 +850,7 @@ void AutoCloseFD::close() if (fd != -1) { if (::close(fd) == -1) /* This should never happen. */ - throw SysError(format("closing file descriptor %1%") % fd); + throw SysError(std::format("closing file descriptor {}", fd)); fd = -1; } } @@ -1024,13 +1026,13 @@ void Pid::kill(bool quiet) if (pid == -1 || pid == 0) return; if (!quiet) - printMsg(lvlError, format("killing process %1%") % pid); + printMsg(lvlError, std::format("killing process {}", pid)); /* Send the requested signal to the child. If it has its own process group, send the signal to every process in the child process group (which hopefully includes *all* its children). */ if (::kill(separatePG ? -pid : pid, killSignal) != 0) - printMsg(lvlError, (SysError(format("killing process %1%") % pid).msg())); + printMsg(lvlError, (SysError(std::format("killing process {}", pid)).msg())); /* Wait until the child dies, disregarding the exit status. */ int status; @@ -1038,7 +1040,7 @@ void Pid::kill(bool quiet) checkInterrupt(); if (errno != EINTR) { printMsg(lvlError, - (SysError(format("waiting for process %1%") % pid).msg())); + (SysError(std::format("waiting for process {}", pid)).msg())); break; } } @@ -1079,7 +1081,7 @@ void Pid::setKillSignal(int signal) void killUser(uid_t uid) { - debug(format("killing all processes running under uid `%1%'") % uid); + debug(std::format("killing all processes running under uid `{}'", uid)); assert(uid != 0); /* just to be safe... */ @@ -1109,7 +1111,7 @@ void killUser(uid_t uid) #endif if (errno == ESRCH) break; /* no more processes */ if (errno != EINTR) - throw SysError(format("cannot kill processes for uid `%1%'") % uid); + throw SysError(std::format("cannot kill processes for uid `{}'", uid)); } _exit(0); @@ -1121,7 +1123,7 @@ void killUser(uid_t uid) if (status == SIGKILL) return; #endif if (status != 0) - throw Error(format("cannot kill processes for uid `%1%': %2%") % uid % statusToString(status)); + throw Error(std::format("cannot kill processes for uid `{}': {}", uid, statusToString(status))); /* !!! We should really do some check to make sure that there are no processes left running under `uid', but there is no portable @@ -1193,9 +1195,9 @@ string runProgram(Path program, bool searchPath, const Strings & args) else execv(program.c_str(), stringsToCharPtrs(args_).data()); - int err = errno; - printMsg(lvlError, format("executing `%1%': %2%") % program % strerror(err)); - _exit(127); + int err = errno; + printMsg(lvlError, std::format("executing `{}': {}", program, strerror(err))); + _exit(127); }); pipe.writeSide.close(); @@ -1205,8 +1207,8 @@ string runProgram(Path program, bool searchPath, const Strings & args) /* Wait for the child to finish. */ int status = pid.wait(true); if (!statusOk(status)) - throw ExecError(format("program `%1%' %2%") - % program % statusToString(status)); + throw ExecError(std::format("program `{}' {}", + program, statusToString(status))); return result; } @@ -1256,7 +1258,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 (!std::uncaught_exception()) { + if (std::uncaught_exceptions() == 0) { _isInterrupted = 0; throw Interrupted("interrupted by the user"); } @@ -1319,14 +1321,14 @@ string statusToString(int status) { if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { if (WIFEXITED(status)) - return (format("failed with exit code %1%") % WEXITSTATUS(status)).str(); + return std::format("failed with exit code {}", WEXITSTATUS(status)); else if (WIFSIGNALED(status)) { int sig = WTERMSIG(status); #if HAVE_STRSIGNAL const char * description = strsignal(sig); - return (format("failed due to signal %1% (%2%)") % sig % description).str(); + return std::format("failed due to signal {} ({})", sig, description); #else - return (format("failed due to signal %1%") % sig).str(); + return std::format("failed due to signal {}", sig); #endif } else @@ -1347,12 +1349,12 @@ bool hasSuffix(const string & s, const string & suffix) } -void expect(std::istream & str, const string & s) +void expect(std::istream & str, std::string_view s) { std::vector s2(s.size()); str.read(s2.data(), s2.size()); if (string(s2.begin(), s2.end()) != s) - throw FormatError(format("expected string `%1%'") % s); + throw FormatError(std::format("expected string `{}'", s)); } @@ -1411,7 +1413,7 @@ void ignoreException() try { throw; } catch (std::exception & e) { - printMsg(lvlError, format("error (ignored): %1%") % e.what()); + printMsg(lvlError, std::format("error (ignored): {}", e.what())); } } @@ -1425,7 +1427,7 @@ void commonChildInit(Pipe & logPipe) that e.g. ssh cannot open /dev/tty) and it doesn't receive terminal signals. */ if (setsid() == -1) - throw SysError(format("creating a new session")); + throw SysError("creating a new session"); /* Close the read end so only the parent holds a reference to it. */ logPipe.readSide.close(); @@ -1441,7 +1443,7 @@ void commonChildInit(Pipe & logPipe) /* Reroute stdin to /dev/null. */ int fdDevNull = open(pathNullDevice.c_str(), O_RDWR); if (fdDevNull == -1) - throw SysError(format("cannot open `%1%'") % pathNullDevice); + throw SysError(std::format("cannot open `{}'", pathNullDevice)); if (dup2(fdDevNull, STDIN_FILENO) == -1) throw SysError("cannot dup null device into stdin"); close(fdDevNull); @@ -1451,7 +1453,7 @@ void commonChildInit(Pipe & logPipe) Agent::Agent(const string &command, const Strings &args, const std::map &env) { - debug(format("starting agent '%1%'") % command); + debug(std::format("starting agent '{}'", command)); /* Create a pipe to get the output of the child. */ fromAgent.create(); @@ -1487,7 +1489,7 @@ Agent::Agent(const string &command, const Strings &args, const std::map +#include + #include #include #include @@ -139,11 +142,11 @@ private: public: Nest(); ~Nest(); - void open(Verbosity level, const FormatOrString & fs); + void open(Verbosity level, std::string_view fs); void close(); }; -void printMsg_(Verbosity level, const FormatOrString & fs); +void printMsg_(Verbosity level, std::string_view fs); #define startNest(varName, level, f) \ Nest varName; \ @@ -160,7 +163,7 @@ void printMsg_(Verbosity level, const FormatOrString & fs); #define debug(f) printMsg(lvlDebug, f) -void warnOnce(bool & haveWarned, const FormatOrString & fs); +void warnOnce(bool & haveWarned, std::string_view fs); void writeToStderr(const string & s); @@ -367,7 +370,7 @@ bool hasSuffix(const string & s, const string & suffix); /* Read string `s' from stream `str'. */ -void expect(std::istream & str, const string & s); +void expect(std::istream & str, std::string_view s); MakeError(FormatError, Error) diff --git a/nix/local.mk b/nix/local.mk index 7c1b81e9a65a0043201880254c9266d2af46bc2a..819131b5d448240d0a424ffbe8fb01c62990bff1 100644 --- a/nix/local.mk +++ b/nix/local.mk @@ -25,31 +25,10 @@ BUILT_SOURCES += %D%/libstore/schema.sql.hh CLEANFILES += %D%/libstore/schema.sql.hh -noinst_LIBRARIES = libformat.a libutil.a libstore.a - -# Use '-std=c++11' for 'std::shared_ptr', 'auto', lambdas, and more. -AM_CXXFLAGS = -Wall -std=c++11 - -libformat_a_SOURCES = \ - %D%/boost/format/free_funcs.cc \ - %D%/boost/format/parsing.cc \ - %D%/boost/format/format_implementation.cc - -libformat_headers = \ - %D%/boost/throw_exception.hpp \ - %D%/boost/format.hpp \ - %D%/boost/assert.hpp \ - %D%/boost/format/macros_default.hpp \ - %D%/boost/format/format_fwd.hpp \ - %D%/boost/format/format_class.hpp \ - %D%/boost/format/exceptions.hpp \ - %D%/boost/format/group.hpp \ - %D%/boost/format/feed_args.hpp \ - %D%/boost/format/internals_fwd.hpp \ - %D%/boost/format/internals.hpp - -libformat_a_CPPFLAGS = \ - -I$(top_srcdir)/nix +noinst_LIBRARIES = libutil.a libstore.a + +# Use '-std=c++20' for 'std::shared_ptr', 'auto', lambdas, and more. +AM_CXXFLAGS = -Wall -std=c++20 libutil_a_SOURCES = \ %D%/libutil/archive.cc \ @@ -73,7 +52,6 @@ libutil_headers = \ libutil_a_CPPFLAGS = \ -I$(top_builddir)/nix \ -I$(top_srcdir)/%D%/libutil \ - $(libformat_a_CPPFLAGS) \ $(LIBGCRYPT_CPPFLAGS) libstore_a_SOURCES = \ @@ -131,7 +109,7 @@ guix_daemon_LDFLAGS = \ $(LIBGCRYPT_LDFLAGS) guix_daemon_LDADD = \ - libstore.a libutil.a libformat.a -lz \ + libstore.a libutil.a -lz \ $(SQLITE3_LIBS) $(LIBGCRYPT_LIBS) guix_daemon_headers = \ @@ -144,7 +122,7 @@ guix_daemon_LDADD += -lbz2 endif HAVE_LIBBZ2 noinst_HEADERS = \ - $(libformat_headers) $(libutil_headers) $(libstore_headers) \ + $(libutil_headers) $(libstore_headers) \ $(guix_daemon_headers) %D%/libstore/schema.sql.hh: guix/store/schema.sql diff --git a/nix/nix-daemon/guix-daemon.cc b/nix/nix-daemon/guix-daemon.cc index 30727d55593f7d9025ad530d202576d6ecba63f7..af09839932f7575e26b5a9b76a7c48e9e59f5166 100644 --- a/nix/nix-daemon/guix-daemon.cc +++ b/nix/nix-daemon/guix-daemon.cc @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -187,7 +188,7 @@ string_to_bool (const char *arg, bool dflt = true) else if (strcasecmp (arg, "no") == 0) return false; else - throw nix::Error (format ("'%1%': invalid Boolean value") % arg); + throw nix::Error(std::format("'{}': invalid Boolean value", arg)); } /* Parse a single option. */ @@ -201,10 +202,8 @@ parse_opt (int key, char *arg, struct argp_state *state) break; case GUIX_OPT_CHROOT_DIR: { - std::string chroot_dirs; + std::string chroot_dirs {settings.get("build-extra-chroot-dirs", "")}; - chroot_dirs = settings.get ("build-extra-chroot-dirs", - (std::string) ""); if (chroot_dirs == "") chroot_dirs = arg; else @@ -337,7 +336,8 @@ open_unix_domain_socket (const char *file) struct sockaddr_un addr; addr.sun_family = AF_UNIX; if (fileRel.size () >= sizeof (addr.sun_path)) - throw Error (format (_("socket file name '%1%' is too long")) % fileRel); + throw Error (std::vformat( (_("socket file name '%1%' is too long")), + std::make_format_args(fileRel))); strcpy (addr.sun_path, fileRel.c_str ()); unlink (file); @@ -349,13 +349,15 @@ open_unix_domain_socket (const char *file) int res = bind (fdSocket, (struct sockaddr *) &addr, sizeof addr); umask (oldMode); if (res == -1) - throw SysError (format (_("cannot bind to socket '%1%'")) % file); + throw SysError (std::vformat( (_("cannot bind to socket '{}'")), + std::make_format_args(file))); if (chdir ("/") == -1) /* back to the root */ throw SysError (_("cannot change current directory")); if (listen (fdSocket, 5) == -1) - throw SysError (format (_("cannot listen on socket '%1%'")) % file); + throw SysError (std::vformat( (_("cannot listen on socket '{}'")), + std::make_format_args(file))); return fdSocket.borrow (); } @@ -373,7 +375,7 @@ open_inet_socket (const struct sockaddr *address, socklen_t length) throw SysError (_("cannot bind TCP socket")); if (listen (fd, 5) == -1) - throw SysError (format (_("cannot listen on TCP socket"))); + throw SysError (_("cannot listen on TCP socket")); return fd.borrow (); } @@ -423,11 +425,9 @@ listening_sockets (const std::list &options) &hints, &res); if (err != 0) - throw Error(format ("failed to look up '%1%': %2%") - % option % gai_strerror (err)); + throw Error(std::format("failed to look up '{}': {}", option, gai_strerror(err))); - printMsg (lvlDebug, format ("listening on '%1%', port '%2%'") - % host % port); + printMsg(lvlDebug, std::format("listening on '{}', port '{}'", host, port)); /* XXX: Pick the first result, RES. */ result.push_back (open_inet_socket (res->ai_addr, @@ -530,17 +530,19 @@ main (int argc, char *argv[]) /* We were not "socket-activated" so open the sockets specified by LISTEN_OPTIONS. */ sockets = listening_sockets (listen_options); - else - printMsg (lvlInfo, - format (ngettext ("socket-activated with %1% socket", - "socket-activated with %1% sockets", - sockets.size ())) - % sockets.size ()); + else { + auto size = sockets.size(); + printMsg (lvlInfo, + std::vformat((ngettext ("socket-activated with %1% socket", + "socket-activated with %1% sockets", + size)), + std::make_format_args(size))); + } /* Effect all the changes made via 'settings.set'. */ settings.update (); printMsg(lvlDebug, - format ("build log compression: %1%") % settings.logCompression); + std::format("build log compression: {}", int(settings.logCompression))); if (geteuid () == 0 && settings.buildUsersGroup.empty ()) fprintf (stderr, _("warning: daemon is running as root, so \ @@ -553,7 +555,7 @@ using `--build-users-group' is highly recommended\n")); chroot_dirs = settings.get ("build-extra-chroot-dirs", (std::string) ""); printMsg (lvlDebug, - format ("extra chroot directories: '%1%'") % chroot_dirs); + std::format("extra chroot directories: '{}'", chroot_dirs)); } if (useDiscover) @@ -568,9 +570,8 @@ using `--build-users-group' is highly recommended\n")); }); } - printMsg (lvlDebug, - format ("automatic deduplication set to %1%") - % settings.autoOptimiseStore); + printMsg(lvlDebug, + std::format("automatic deduplication set to {}", settings.autoOptimiseStore)); run (sockets); } diff --git a/nix/nix-daemon/nix-daemon.cc b/nix/nix-daemon/nix-daemon.cc index f2ffe8fa6f82fa78706b13b1cc4c6b8c26767dee..3890adb2c7400b65d3a8e6af08fe04273306dc60 100644 --- a/nix/nix-daemon/nix-daemon.cc +++ b/nix/nix-daemon/nix-daemon.cc @@ -10,8 +10,10 @@ #include "builtins.hh" #include +#include #include +#include #include #include #include @@ -640,7 +642,7 @@ static void performOp(bool trusted, unsigned int clientVersion, if (pw != NULL) store->createUser(value, pw->pw_uid); else - printMsg(lvlInfo, format("user name %1% not found") % value); + printMsg(lvlInfo, std::format("user name {} not found", value)); } else settings.set(trusted ? name : "untrusted-" + name, value); @@ -772,7 +774,7 @@ static void performOp(bool trusted, unsigned int clientVersion, } default: - throw Error(format("invalid operation %1%") % op); + throw Error(std::format("invalid operation {}", op)); } } @@ -834,7 +836,7 @@ static void processConnection(bool trusted, uid_t userId) if (pw != NULL && pw->pw_name != NULL) store->createUser(pw->pw_name, userId); else - printMsg(lvlInfo, format("user with UID %1% not found") % userId); + printMsg(lvlInfo, std::format("user with UID {} not found", userId)); } stopWork(); @@ -882,7 +884,7 @@ static void processConnection(bool trusted, uid_t userId) canSendStderr = false; _isInterrupted = false; - printMsg(lvlDebug, format("%1% operations") % opCount); + printMsg(lvlDebug, std::format("{} operations", opCount)); } @@ -971,9 +973,8 @@ static void acceptConnection(int fdSocket) struct passwd * pw = getpwuid(cred.uid); string user = pw ? pw->pw_name : std::to_string(cred.uid); - printMsg(lvlInfo, - format((string) "accepted connection from pid %1%, user %2%") - % clientPid % user); + printMsg(lvlInfo, std::format("accepted connection from pid {}, user {}", + clientPid, user)); #endif } else { char address_str[128]; @@ -992,9 +993,7 @@ static void acceptConnection(int fdSocket) } if (result != NULL) { - printMsg(lvlInfo, - format("accepted connection from %1%") - % address_str); + printMsg(lvlInfo, std::format("accepted connection from {}", address_str)); } } @@ -1004,7 +1003,7 @@ static void acceptConnection(int fdSocket) /* Background the daemon. */ if (setsid() == -1) - throw SysError(format("creating a new session")); + throw SysError("creating a new session"); /* Restore normal handling of SIGCHLD. */ setSigChldAction(false); @@ -1033,7 +1032,7 @@ static void acceptConnection(int fdSocket) } catch (Interrupted & e) { throw; } catch (Error & e) { - printMsg(lvlError, format("error processing connection: %1%") % e.msg()); + printMsg(lvlError, std::format("error processing connection: {}", e.msg())); } } @@ -1072,7 +1071,7 @@ static void daemonLoop(const std::vector& sockets) int err = errno; if (err == EINTR) continue; - throw SysError(format("select error: %1%") % strerror(err)); + throw SysError(std::format("select error: {}", strerror(err))); } for (unsigned int i = 0; i < sockets.size(); i++) {