aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libstore/build.cc6
-rw-r--r--src/libstore/remote-store.cc2
-rw-r--r--src/libutil/args.hh2
-rw-r--r--src/libutil/logging.hh11
-rw-r--r--src/libutil/types.hh69
-rw-r--r--src/libutil/util.cc13
6 files changed, 81 insertions, 22 deletions
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index 7b881941e..ac8572246 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -3768,7 +3768,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(worker.exitStatus(), "build of %s failed",showPaths(failed));
}
@@ -3804,7 +3804,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(worker.exitStatus(), "path ‘%s’ does not exist and cannot be created", path);
}
@@ -3825,7 +3825,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(worker.exitStatus(), "cannot repair path ‘%s’", path);
}
}
diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc
index 7b73557a5..5c9262dec 100644
--- a/src/libstore/remote-store.cc
+++ b/src/libstore/remote-store.cc
@@ -564,7 +564,7 @@ void RemoteStore::Connection::processStderr(Sink * sink, Source * source)
if (msg == STDERR_ERROR) {
string error = readString(from);
unsigned int status = readInt(from);
- throw Error(format("%1%") % error, status);
+ throw Error(status, error);
}
else if (msg != STDERR_LAST)
throw Error("protocol error processing standard error");
diff --git a/src/libutil/args.hh b/src/libutil/args.hh
index 6aa08aaca..ac12f8be6 100644
--- a/src/libutil/args.hh
+++ b/src/libutil/args.hh
@@ -8,7 +8,7 @@
namespace nix {
-MakeError(UsageError, nix::Error);
+MakeError(UsageError, Error);
enum HashType : char;
diff --git a/src/libutil/logging.hh b/src/libutil/logging.hh
index 277dff280..ba99a81c3 100644
--- a/src/libutil/logging.hh
+++ b/src/libutil/logging.hh
@@ -66,14 +66,19 @@ Logger * makeDefaultLogger();
extern Verbosity verbosity; /* suppress msgs > this */
-#define printMsg(level, f) \
+/* Print a message if the current log level is at least the specified
+ level. Note that this has to be implemented as a macro to ensure
+ that the arguments are evaluated lazily. */
+#define printMsg(level, args...) \
do { \
if (level <= nix::verbosity) { \
- logger->log(level, (f)); \
+ logger->log(level, fmt(args)); \
} \
} while (0)
-#define debug(f) printMsg(lvlDebug, f)
+#define printError(args...) printMsg(lvlError, args)
+#define printInfo(args...) printMsg(lvlInfo, args)
+#define debug(args...) printMsg(lvlDebug, args)
void warnOnce(bool & haveWarned, const FormatOrString & fs);
diff --git a/src/libutil/types.hh b/src/libutil/types.hh
index bd192b850..b9a93d27d 100644
--- a/src/libutil/types.hh
+++ b/src/libutil/types.hh
@@ -41,6 +41,45 @@ struct FormatOrString
};
+/* A helper for formatting strings. ‘fmt(format, a_0, ..., a_n)’ is
+ equivalent to ‘boost::format(format) % a_0 % ... %
+ ... a_n’. However, ‘fmt(s)’ is equivalent to ‘s’ (so no %-expansion
+ takes place). */
+
+inline void formatHelper(boost::format & f)
+{
+}
+
+template<typename T, typename... Args>
+inline void formatHelper(boost::format & f, T x, Args... args)
+{
+ formatHelper(f % x, args...);
+}
+
+inline std::string fmt(const std::string & s)
+{
+ return s;
+}
+
+inline std::string fmt(const char * s)
+{
+ return s;
+}
+
+inline std::string fmt(const FormatOrString & fs)
+{
+ return fs.s;
+}
+
+template<typename... Args>
+inline std::string fmt(const std::string & fs, Args... args)
+{
+ boost::format f(fs);
+ formatHelper(f, args...);
+ return f.str();
+}
+
+
/* BaseError should generally not be caught, as it has Interrupted as
a subclass. Catch Error instead. */
class BaseError : public std::exception
@@ -49,14 +88,28 @@ protected:
string prefix_; // used for location traces etc.
string err;
public:
- unsigned int status; // exit status
- BaseError(const FormatOrString & fs, unsigned int status = 1);
+ unsigned int status = 1; // exit status
+
+ template<typename... Args>
+ BaseError(unsigned int status, Args... args)
+ : err(fmt(args...))
+ , status(status)
+ {
+ }
+
+ template<typename... Args>
+ BaseError(Args... args)
+ : err(fmt(args...))
+ {
+ }
+
#ifdef EXCEPTION_NEEDS_THROW_SPEC
~BaseError() throw () { };
const char * what() const throw () { return err.c_str(); }
#else
const char * what() const noexcept { return err.c_str(); }
#endif
+
const string & msg() const { return err; }
const string & prefix() const { return prefix_; }
BaseError & addPrefix(const FormatOrString & fs);
@@ -66,7 +119,7 @@ public:
class newClass : public superClass \
{ \
public: \
- newClass(const FormatOrString & fs, unsigned int status = 1) : superClass(fs, status) { }; \
+ using superClass::superClass; \
};
MakeError(Error, BaseError)
@@ -75,7 +128,15 @@ class SysError : public Error
{
public:
int errNo;
- SysError(const FormatOrString & fs);
+
+ template<typename... Args>
+ SysError(Args... args)
+ : Error(addErrno(fmt(args...)))
+ { }
+
+private:
+
+ std::string addErrno(const std::string & s);
};
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index 68311a3df..ce54350d7 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -31,13 +31,6 @@ extern char * * environ;
namespace nix {
-BaseError::BaseError(const FormatOrString & fs, unsigned int status)
- : status(status)
-{
- err = fs.s;
-}
-
-
BaseError & BaseError::addPrefix(const FormatOrString & fs)
{
prefix_ = fs.s + prefix_;
@@ -45,10 +38,10 @@ BaseError & BaseError::addPrefix(const FormatOrString & fs)
}
-SysError::SysError(const FormatOrString & fs)
- : Error(format("%1%: %2%") % fs.s % strerror(errno))
- , errNo(errno)
+std::string SysError::addErrno(const std::string & s)
{
+ errNo = errno;
+ return s + ": " + strerror(errNo);
}