From 14d82baba4ebb82df28c2d4e9517f8c3a81d8f6c Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 16 Dec 2019 17:41:56 +0100 Subject: [PATCH 1/3] StorePath::new(): Check store directory --- nix-rust/src/c.rs | 3 ++- nix-rust/src/error.rs | 4 ++++ nix-rust/src/store/path.rs | 6 ++++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/nix-rust/src/c.rs b/nix-rust/src/c.rs index e0462742f..8d2507d37 100644 --- a/nix-rust/src/c.rs +++ b/nix-rust/src/c.rs @@ -34,7 +34,8 @@ pub extern "C" fn ffi_StorePath_new( path: &str, store_dir: &str, ) -> Result { - StorePath::new(std::path::Path::new(path), store_dir).map_err(|err| err.into()) + StorePath::new(std::path::Path::new(path), std::path::Path::new(store_dir)) + .map_err(|err| err.into()) } #[no_mangle] diff --git a/nix-rust/src/error.rs b/nix-rust/src/error.rs index 9abcacc06..bb0c9a933 100644 --- a/nix-rust/src/error.rs +++ b/nix-rust/src/error.rs @@ -4,6 +4,7 @@ use std::fmt; pub enum Error { InvalidPath(crate::store::StorePath), BadStorePath(std::path::PathBuf), + NotInStore(std::path::PathBuf), BadNarInfo, BadBase32, StorePathNameEmpty, @@ -46,6 +47,9 @@ impl fmt::Display for Error { Error::InvalidPath(_) => write!(f, "invalid path"), Error::BadNarInfo => write!(f, ".narinfo file is corrupt"), Error::BadStorePath(path) => write!(f, "path '{}' is not a store path", path.display()), + Error::NotInStore(path) => { + write!(f, "path '{}' is not in the Nix store", path.display()) + } Error::BadBase32 => write!(f, "invalid base32 string"), Error::StorePathNameEmpty => write!(f, "store path name is empty"), Error::StorePathNameTooLong => { diff --git a/nix-rust/src/store/path.rs b/nix-rust/src/store/path.rs index 2a2232475..2a5170bef 100644 --- a/nix-rust/src/store/path.rs +++ b/nix-rust/src/store/path.rs @@ -13,8 +13,10 @@ pub const STORE_PATH_HASH_BYTES: usize = 20; pub const STORE_PATH_HASH_CHARS: usize = 32; impl StorePath { - pub fn new(path: &Path, _store_dir: &str) -> Result { - // FIXME: check store_dir + pub fn new(path: &Path, store_dir: &Path) -> Result { + if path.parent() != Some(store_dir) { + return Err(Error::NotInStore(path.into())); + } Self::new_from_base_name( path.file_name() .ok_or(Error::BadStorePath(path.into()))? From 54bf5ba4227a234f8cd5102634b9a3b535e6fbdb Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 16 Dec 2019 19:11:47 +0100 Subject: [PATCH 2/3] nix-store -r: Handle symlinks to store paths Fixes #3270. --- src/libexpr/get-drvs.cc | 2 +- src/libstore/daemon.cc | 4 ++-- src/libstore/derivations.cc | 10 ---------- src/libstore/path.cc | 15 +++++++++++++++ src/libstore/path.hh | 24 ++++++++++++++++++++++++ src/libstore/store-api.cc | 13 ++++++++++--- src/libstore/store-api.hh | 25 +++++-------------------- src/libutil/util.cc | 8 ++++---- src/libutil/util.hh | 2 +- src/nix-store/nix-store.cc | 4 ++-- tests/nix-build.sh | 3 +++ 11 files changed, 67 insertions(+), 43 deletions(-) diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc index a3412eab9..ca9c547fa 100644 --- a/src/libexpr/get-drvs.cc +++ b/src/libexpr/get-drvs.cc @@ -19,7 +19,7 @@ DrvInfo::DrvInfo(EvalState & state, const string & attrPath, Bindings * attrs) DrvInfo::DrvInfo(EvalState & state, ref store, const std::string & drvPathWithOutputs) : state(&state), attrs(nullptr), attrPath("") { - auto [drvPath, selectedOutputs] = store->parseDrvPathWithOutputs(drvPathWithOutputs); + auto [drvPath, selectedOutputs] = store->parsePathWithOutputs(drvPathWithOutputs); this->drvPath = store->printStorePath(drvPath); diff --git a/src/libstore/daemon.cc b/src/libstore/daemon.cc index c53dfdd56..8e9f9d71b 100644 --- a/src/libstore/daemon.cc +++ b/src/libstore/daemon.cc @@ -424,7 +424,7 @@ static void performOp(TunnelLogger * logger, ref store, case wopBuildPaths: { std::vector drvs; for (auto & s : readStrings(from)) - drvs.push_back(store->parseDrvPathWithOutputs(s)); + drvs.push_back(store->parsePathWithOutputs(s)); BuildMode mode = bmNormal; if (GET_PROTOCOL_MINOR(clientVersion) >= 15) { mode = (BuildMode) readInt(from); @@ -721,7 +721,7 @@ static void performOp(TunnelLogger * logger, ref store, case wopQueryMissing: { std::vector targets; for (auto & s : readStrings(from)) - targets.push_back(store->parseDrvPathWithOutputs(s)); + targets.push_back(store->parsePathWithOutputs(s)); logger->startWork(); StorePathSet willBuild, willSubstitute, unknown; unsigned long long downloadSize, narSize; diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc index 726e34479..1a061149a 100644 --- a/src/libstore/derivations.cc +++ b/src/libstore/derivations.cc @@ -375,16 +375,6 @@ Hash hashDerivationModulo(Store & store, const Derivation & drv, bool maskOutput } -StorePathWithOutputs Store::parseDrvPathWithOutputs(const std::string & s) -{ - size_t n = s.find("!"); - return n == s.npos - ? StorePathWithOutputs{parseStorePath(s), std::set()} - : StorePathWithOutputs{parseStorePath(std::string_view(s.data(), n)), - tokenizeString>(string(s, n + 1), ",")}; -} - - std::string StorePathWithOutputs::to_string(const Store & store) const { return outputs.empty() diff --git a/src/libstore/path.cc b/src/libstore/path.cc index 81ae495a1..cda5f9968 100644 --- a/src/libstore/path.cc +++ b/src/libstore/path.cc @@ -96,4 +96,19 @@ StorePathSet singleton(const StorePath & path) return res; } +std::pair parsePathWithOutputs(std::string_view s) +{ + size_t n = s.find("!"); + return n == s.npos + ? std::make_pair(s, std::set()) + : std::make_pair(((std::string_view) s).substr(0, n), + tokenizeString>(((std::string_view) s).substr(n + 1), ",")); +} + +StorePathWithOutputs Store::parsePathWithOutputs(const std::string & s) +{ + auto [path, outputs] = nix::parsePathWithOutputs(s); + return {parseStorePath(path), std::move(outputs)}; +} + } diff --git a/src/libstore/path.hh b/src/libstore/path.hh index 273808f02..5ebb57480 100644 --- a/src/libstore/path.hh +++ b/src/libstore/path.hh @@ -7,6 +7,8 @@ namespace nix { /* See path.rs. */ struct StorePath; +struct Store; + extern "C" { void ffi_StorePath_drop(void *); bool ffi_StorePath_less_than(const StorePath & a, const StorePath & b); @@ -67,6 +69,28 @@ const size_t storePathHashLen = 32; // i.e. 160 bits /* Extension of derivations in the Nix store. */ const std::string drvExtension = ".drv"; +struct StorePathWithOutputs +{ + StorePath path; + std::set outputs; + + StorePathWithOutputs(const StorePath & path, const std::set & outputs = {}) + : path(path.clone()), outputs(outputs) + { } + + StorePathWithOutputs(StorePath && path, std::set && outputs) + : path(std::move(path)), outputs(std::move(outputs)) + { } + + StorePathWithOutputs(const StorePathWithOutputs & other) + : path(other.path.clone()), outputs(other.outputs) + { } + + std::string to_string(const Store & store) const; +}; + +std::pair parsePathWithOutputs(std::string_view s); + } namespace std { diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index c98931885..1781e0c68 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -39,9 +39,9 @@ Path Store::toStorePath(const Path & path) const } -Path Store::followLinksToStore(const Path & _path) const +Path Store::followLinksToStore(std::string_view _path) const { - Path path = absPath(_path); + Path path = absPath(std::string(_path)); while (!isInStore(path)) { if (!isLink(path)) break; string target = readLink(path); @@ -53,12 +53,19 @@ Path Store::followLinksToStore(const Path & _path) const } -StorePath Store::followLinksToStorePath(const Path & path) const +StorePath Store::followLinksToStorePath(std::string_view path) const { return parseStorePath(toStorePath(followLinksToStore(path))); } +StorePathWithOutputs Store::followLinksToStorePathWithOutputs(std::string_view path) const +{ + auto [path2, outputs] = nix::parsePathWithOutputs(path); + return StorePathWithOutputs(followLinksToStorePath(path2), std::move(outputs)); +} + + string storePathToHash(const Path & path) { auto base = baseNameOf(path); diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh index 552bbd67d..d77d6bad8 100644 --- a/src/libstore/store-api.hh +++ b/src/libstore/store-api.hh @@ -241,23 +241,6 @@ struct BuildResult }; -struct StorePathWithOutputs -{ - StorePath path; - std::set outputs; - - StorePathWithOutputs(const StorePath & path, const std::set & outputs = {}) - : path(path.clone()), outputs(outputs) - { } - - StorePathWithOutputs(const StorePathWithOutputs & other) - : path(other.path.clone()), outputs(other.outputs) - { } - - std::string to_string(const Store & store) const; -}; - - class Store : public std::enable_shared_from_this, public Config { public: @@ -304,7 +287,7 @@ public: /* Split a string specifying a derivation and a set of outputs (/nix/store/hash-foo!out1,out2,...) into the derivation path and the outputs. */ - StorePathWithOutputs parseDrvPathWithOutputs(const string & s); + StorePathWithOutputs parsePathWithOutputs(const string & s); /* Display a set of paths in human-readable form (i.e., between quotes and separated by commas). */ @@ -323,11 +306,13 @@ public: Path toStorePath(const Path & path) const; /* Follow symlinks until we end up with a path in the Nix store. */ - Path followLinksToStore(const Path & path) const; + Path followLinksToStore(std::string_view path) const; /* Same as followLinksToStore(), but apply toStorePath() to the result. */ - StorePath followLinksToStorePath(const Path & path) const; + StorePath followLinksToStorePath(std::string_view path) const; + + StorePathWithOutputs followLinksToStorePathWithOutputs(std::string_view path) const; /* Constructs a unique store path name. */ StorePath makeStorePath(const string & type, diff --git a/src/libutil/util.cc b/src/libutil/util.cc index e67bdcdeb..012f1d071 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -1186,7 +1186,7 @@ void _interrupted() ////////////////////////////////////////////////////////////////////// -template C tokenizeString(const string & s, const string & separators) +template C tokenizeString(std::string_view s, const string & separators) { C result; string::size_type pos = s.find_first_not_of(separators, 0); @@ -1200,9 +1200,9 @@ template C tokenizeString(const string & s, const string & separators) return result; } -template Strings tokenizeString(const string & s, const string & separators); -template StringSet tokenizeString(const string & s, const string & separators); -template vector tokenizeString(const string & s, const string & separators); +template Strings tokenizeString(std::string_view s, const string & separators); +template StringSet tokenizeString(std::string_view s, const string & separators); +template vector tokenizeString(std::string_view s, const string & separators); string concatStringsSep(const string & sep, const Strings & ss) diff --git a/src/libutil/util.hh b/src/libutil/util.hh index abd91b81c..abf1c95d6 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -340,7 +340,7 @@ MakeError(FormatError, Error); /* String tokenizer. */ -template C tokenizeString(const string & s, const string & separators = " \t\n\r"); +template C tokenizeString(std::string_view s, const string & separators = " \t\n\r"); /* Concatenate the given strings with a separator between the diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc index e2e2939f4..45e152c47 100644 --- a/src/nix-store/nix-store.cc +++ b/src/nix-store/nix-store.cc @@ -128,7 +128,7 @@ static void opRealise(Strings opFlags, Strings opArgs) std::vector paths; for (auto & i : opArgs) - paths.push_back(store->parseDrvPathWithOutputs(i)); + paths.push_back(store->followLinksToStorePathWithOutputs(i)); unsigned long long downloadSize, narSize; StorePathSet willBuild, willSubstitute, unknown; @@ -893,7 +893,7 @@ static void opServe(Strings opFlags, Strings opArgs) std::vector paths; for (auto & s : readStrings(in)) - paths.emplace_back(store->parseDrvPathWithOutputs(s)); + paths.emplace_back(store->parsePathWithOutputs(s)); getBuildSettings(); diff --git a/tests/nix-build.sh b/tests/nix-build.sh index 395264863..0eb599608 100644 --- a/tests/nix-build.sh +++ b/tests/nix-build.sh @@ -23,3 +23,6 @@ outPath2=$(nix-build $(nix-instantiate dependencies.nix) --no-out-link) outPath2=$(nix-build $(nix-instantiate dependencies.nix)!out --no-out-link) [[ $outPath = $outPath2 ]] + +outPath2=$(nix-store -r $(nix-instantiate --indirect --add-root $TEST_ROOT/indirect dependencies.nix)!out) +[[ $outPath = $outPath2 ]] From f8abbdd4565542464f31f4dc203a9c3e091b3536 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 17 Dec 2019 17:17:53 +0100 Subject: [PATCH 3/3] Add priority setting to stores This allows overriding the priority of substituters, e.g. $ nix-store --store ~/my-nix/ -r /nix/store/df3m4da96d84ljzxx4mygfshm1p0r2n3-geeqie-1.4 \ --substituters 'http://cache.nixos.org?priority=100 daemon?priority=10' Fixes #3264. --- src/libstore/binary-cache-store.cc | 4 ++-- src/libstore/binary-cache-store.hh | 9 --------- src/libstore/globals.cc | 2 +- src/libstore/http-binary-cache-store.cc | 7 +++++-- src/libstore/local-store.cc | 2 +- src/libstore/nar-info-disk-cache.cc | 16 ++++++++-------- src/libstore/nar-info-disk-cache.hh | 9 +++++++-- src/libstore/s3-binary-cache-store.cc | 9 +++++---- src/libstore/sqlite.hh | 4 ++-- src/libstore/store-api.cc | 2 +- src/libstore/store-api.hh | 11 ++++------- src/libutil/config.cc | 15 ++++++++++----- src/libutil/config.hh | 8 +++++--- 13 files changed, 51 insertions(+), 47 deletions(-) diff --git a/src/libstore/binary-cache-store.cc b/src/libstore/binary-cache-store.cc index aaacf8281..717faec92 100644 --- a/src/libstore/binary-cache-store.cc +++ b/src/libstore/binary-cache-store.cc @@ -49,9 +49,9 @@ void BinaryCacheStore::init() throw Error(format("binary cache '%s' is for Nix stores with prefix '%s', not '%s'") % getUri() % value % storeDir); } else if (name == "WantMassQuery") { - wantMassQuery_ = value == "1"; + wantMassQuery.setDefault(value == "1" ? "true" : "false"); } else if (name == "Priority") { - string2Int(value, priority); + priority.setDefault(fmt("%d", std::stoi(value))); } } } diff --git a/src/libstore/binary-cache-store.hh b/src/libstore/binary-cache-store.hh index fa2200ad8..aa13c1cb4 100644 --- a/src/libstore/binary-cache-store.hh +++ b/src/libstore/binary-cache-store.hh @@ -52,11 +52,6 @@ public: std::shared_ptr getFile(const std::string & path); -protected: - - bool wantMassQuery_ = false; - int priority = 50; - public: virtual void init(); @@ -79,8 +74,6 @@ public: std::optional queryPathFromHashPart(const std::string & hashPart) override { unsupported("queryPathFromHashPart"); } - bool wantMassQuery() override { return wantMassQuery_; } - void addToStore(const ValidPathInfo & info, const ref & nar, RepairFlag repair, CheckSigsFlag checkSigs, std::shared_ptr accessor) override; @@ -107,8 +100,6 @@ public: std::shared_ptr getBuildLog(const StorePath & path) override; - int getPriority() override { return priority; } - }; MakeError(NoSuchBinaryCacheFile, Error); diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc index 6fedf3d56..cec85edca 100644 --- a/src/libstore/globals.cc +++ b/src/libstore/globals.cc @@ -127,7 +127,7 @@ template<> void BaseSetting::set(const std::string & str) else throw UsageError("option '%s' has invalid value '%s'", name, str); } -template<> std::string BaseSetting::to_string() +template<> std::string BaseSetting::to_string() const { if (value == smEnabled) return "true"; else if (value == smRelaxed) return "relaxed"; diff --git a/src/libstore/http-binary-cache-store.cc b/src/libstore/http-binary-cache-store.cc index 779f89e68..d4ae36662 100644 --- a/src/libstore/http-binary-cache-store.cc +++ b/src/libstore/http-binary-cache-store.cc @@ -42,13 +42,16 @@ public: void init() override { // FIXME: do this lazily? - if (!diskCache->cacheExists(cacheUri, wantMassQuery_, priority)) { + if (auto cacheInfo = diskCache->cacheExists(cacheUri)) { + wantMassQuery.setDefault(cacheInfo->wantMassQuery ? "true" : "false"); + priority.setDefault(fmt("%d", cacheInfo->priority)); + } else { try { BinaryCacheStore::init(); } catch (UploadToHTTP &) { throw Error("'%s' does not appear to be a binary cache", cacheUri); } - diskCache->createCache(cacheUri, storeDir, wantMassQuery_, priority); + diskCache->createCache(cacheUri, storeDir, wantMassQuery, priority); } } diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index c1380ef09..b254d766a 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -840,7 +840,7 @@ StorePathSet LocalStore::querySubstitutablePaths(const StorePathSet & paths) for (auto & sub : getDefaultSubstituters()) { if (remaining.empty()) break; if (sub->storeDir != storeDir) continue; - if (!sub->wantMassQuery()) continue; + if (!sub->wantMassQuery) continue; auto valid = sub->queryValidPaths(remaining); diff --git a/src/libstore/nar-info-disk-cache.cc b/src/libstore/nar-info-disk-cache.cc index 3a2cde55f..907645d86 100644 --- a/src/libstore/nar-info-disk-cache.cc +++ b/src/libstore/nar-info-disk-cache.cc @@ -147,26 +147,26 @@ public: }); } - bool cacheExists(const std::string & uri, - bool & wantMassQuery, int & priority) override + std::optional cacheExists(const std::string & uri) override { - return retrySQLite([&]() { + return retrySQLite>([&]() -> std::optional { auto state(_state.lock()); auto i = state->caches.find(uri); if (i == state->caches.end()) { auto queryCache(state->queryCache.use()(uri)); - if (!queryCache.next()) return false; + if (!queryCache.next()) + return std::nullopt; state->caches.emplace(uri, Cache{(int) queryCache.getInt(0), queryCache.getStr(1), queryCache.getInt(2) != 0, (int) queryCache.getInt(3)}); } auto & cache(getCache(*state, uri)); - wantMassQuery = cache.wantMassQuery; - priority = cache.priority; - - return true; + return CacheInfo { + .wantMassQuery = cache.wantMassQuery, + .priority = cache.priority + }; }); } diff --git a/src/libstore/nar-info-disk-cache.hh b/src/libstore/nar-info-disk-cache.hh index 285873f7e..878acbb87 100644 --- a/src/libstore/nar-info-disk-cache.hh +++ b/src/libstore/nar-info-disk-cache.hh @@ -15,8 +15,13 @@ public: virtual void createCache(const std::string & uri, const Path & storeDir, bool wantMassQuery, int priority) = 0; - virtual bool cacheExists(const std::string & uri, - bool & wantMassQuery, int & priority) = 0; + struct CacheInfo + { + bool wantMassQuery; + int priority; + }; + + virtual std::optional cacheExists(const std::string & uri) = 0; virtual std::pair> lookupNarInfo( const std::string & uri, const std::string & hashPart) = 0; diff --git a/src/libstore/s3-binary-cache-store.cc b/src/libstore/s3-binary-cache-store.cc index 58966a5b7..f2e4b63e0 100644 --- a/src/libstore/s3-binary-cache-store.cc +++ b/src/libstore/s3-binary-cache-store.cc @@ -205,11 +205,12 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore void init() override { - if (!diskCache->cacheExists(getUri(), wantMassQuery_, priority)) { - + if (auto cacheInfo = diskCache->cacheExists(getUri())) { + wantMassQuery.setDefault(cacheInfo->wantMassQuery ? "true" : "false"); + priority.setDefault(fmt("%d", cacheInfo->priority)); + } else { BinaryCacheStore::init(); - - diskCache->createCache(getUri(), storeDir, wantMassQuery_, priority); + diskCache->createCache(getUri(), storeDir, wantMassQuery, priority); } } diff --git a/src/libstore/sqlite.hh b/src/libstore/sqlite.hh index 115679b84..bd012d9b9 100644 --- a/src/libstore/sqlite.hh +++ b/src/libstore/sqlite.hh @@ -99,8 +99,8 @@ void handleSQLiteBusy(const SQLiteBusy & e); /* Convenience function for retrying a SQLite transaction when the database is busy. */ -template -T retrySQLite(std::function fun) +template +T retrySQLite(F && fun) { while (true) { try { diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index 1781e0c68..d8f6c22bc 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -975,7 +975,7 @@ std::list> getDefaultSubstituters() addStore(uri); stores.sort([](ref & a, ref & b) { - return a->getPriority() < b->getPriority(); + return a->priority < b->priority; }); return stores; diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh index d77d6bad8..743be9410 100644 --- a/src/libstore/store-api.hh +++ b/src/libstore/store-api.hh @@ -255,6 +255,10 @@ public: const Setting isTrusted{this, false, "trusted", "whether paths from this store can be used as substitutes even when they lack trusted signatures"}; + Setting priority{this, 0, "priority", "priority of this substituter (lower value means higher priority)"}; + + Setting wantMassQuery{this, false, "want-mass-query", "whether this substituter can be queried efficiently for path validity"}; + protected: struct State @@ -422,8 +426,6 @@ public: virtual void querySubstitutablePathInfos(const StorePathSet & paths, SubstitutablePathInfos & infos) { return; }; - virtual bool wantMassQuery() { return false; } - /* Import a path into the store. */ virtual void addToStore(const ValidPathInfo & info, Source & narSource, RepairFlag repair = NoRepair, CheckSigsFlag checkSigs = CheckSigs, @@ -648,11 +650,6 @@ public: return 0; }; - /* Get the priority of the store, used to order substituters. In - particular, binary caches can specify a priority field in their - "nix-cache-info" file. Lower value means higher priority. */ - virtual int getPriority() { return 0; } - virtual Path toRealPath(const Path & storePath) { return storePath; diff --git a/src/libutil/config.cc b/src/libutil/config.cc index 9023cb1bb..7551d97d1 100644 --- a/src/libutil/config.cc +++ b/src/libutil/config.cc @@ -154,6 +154,11 @@ AbstractSetting::AbstractSetting( { } +void AbstractSetting::setDefault(const std::string & str) +{ + if (!overriden) set(str); +} + void AbstractSetting::toJSON(JSONPlaceholder & out) { out.write(to_string()); @@ -185,7 +190,7 @@ template<> void BaseSetting::set(const std::string & str) value = str; } -template<> std::string BaseSetting::to_string() +template<> std::string BaseSetting::to_string() const { return value; } @@ -199,7 +204,7 @@ void BaseSetting::set(const std::string & str) } template -std::string BaseSetting::to_string() +std::string BaseSetting::to_string() const { static_assert(std::is_integral::value, "Integer required."); return std::to_string(value); @@ -215,7 +220,7 @@ template<> void BaseSetting::set(const std::string & str) throw UsageError("Boolean setting '%s' has invalid value '%s'", name, str); } -template<> std::string BaseSetting::to_string() +template<> std::string BaseSetting::to_string() const { return value ? "true" : "false"; } @@ -239,7 +244,7 @@ template<> void BaseSetting::set(const std::string & str) value = tokenizeString(str); } -template<> std::string BaseSetting::to_string() +template<> std::string BaseSetting::to_string() const { return concatStringsSep(" ", value); } @@ -256,7 +261,7 @@ template<> void BaseSetting::set(const std::string & str) value = tokenizeString(str); } -template<> std::string BaseSetting::to_string() +template<> std::string BaseSetting::to_string() const { return concatStringsSep(" ", value); } diff --git a/src/libutil/config.hh b/src/libutil/config.hh index d86c65ff0..7ea78fdaf 100644 --- a/src/libutil/config.hh +++ b/src/libutil/config.hh @@ -115,6 +115,8 @@ public: bool overriden = false; + void setDefault(const std::string & str); + protected: AbstractSetting( @@ -131,13 +133,13 @@ protected: virtual void set(const std::string & value) = 0; - virtual std::string to_string() = 0; + virtual std::string to_string() const = 0; virtual void toJSON(JSONPlaceholder & out); virtual void convertToArg(Args & args, const std::string & category); - bool isOverriden() { return overriden; } + bool isOverriden() const { return overriden; } }; /* A setting of type T. */ @@ -174,7 +176,7 @@ public: value = v; } - std::string to_string() override; + std::string to_string() const override; void convertToArg(Args & args, const std::string & category) override;