From 556974f33bf0a50a107c725d628db7795b244d0f Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman Date: Tue, 20 Jan 2026 01:32:43 +0300 Subject: [PATCH 1/3] libutil: Remove unused overload of unpackTarfile --- src/libutil/include/nix/util/tarfile.hh | 2 -- src/libutil/tarfile.cc | 8 -------- 2 files changed, 10 deletions(-) diff --git a/src/libutil/include/nix/util/tarfile.hh b/src/libutil/include/nix/util/tarfile.hh index c66e05ef6709..324c7c8a8a99 100644 --- a/src/libutil/include/nix/util/tarfile.hh +++ b/src/libutil/include/nix/util/tarfile.hh @@ -37,8 +37,6 @@ struct TarArchive int getArchiveFilterCodeByName(const std::string & method); -void unpackTarfile(Source & source, const std::filesystem::path & destDir); - void unpackTarfile(const std::filesystem::path & tarFile, const std::filesystem::path & destDir); time_t unpackTarfileToSink(TarArchive & archive, ExtendedFileSystemObjectSink & parseSink); diff --git a/src/libutil/tarfile.cc b/src/libutil/tarfile.cc index e71c1103735b..eea03766375c 100644 --- a/src/libutil/tarfile.cc +++ b/src/libutil/tarfile.cc @@ -158,14 +158,6 @@ static void extract_archive(TarArchive & archive, const std::filesystem::path & archive.close(); } -void unpackTarfile(Source & source, const std::filesystem::path & destDir) -{ - auto archive = TarArchive(source); - - createDirs(destDir); - extract_archive(archive, destDir); -} - void unpackTarfile(const std::filesystem::path & tarFile, const std::filesystem::path & destDir) { auto archive = TarArchive(tarFile); From b24df97a116731dafbb0bcbcfa795aa07d90258f Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman Date: Tue, 20 Jan 2026 02:39:12 +0300 Subject: [PATCH 2/3] binary-cache-store: Update compression setting documentation to match reality The docs were out of date. Since 8a0c00b85600991cdb9aa05902defec6ac44b777 Nix supports all compression algorithms exposed by libarchive (if it's built with native support for them). Let's be honest about it in the docs. --- src/libstore/include/nix/store/binary-cache-store.hh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/libstore/include/nix/store/binary-cache-store.hh b/src/libstore/include/nix/store/binary-cache-store.hh index 80c0bc9d0cb0..9ec209d8c806 100644 --- a/src/libstore/include/nix/store/binary-cache-store.hh +++ b/src/libstore/include/nix/store/binary-cache-store.hh @@ -19,7 +19,13 @@ struct BinaryCacheStoreConfig : virtual StoreConfig using StoreConfig::StoreConfig; const Setting compression{ - this, "xz", "compression", "NAR compression method (`xz`, `bzip2`, `gzip`, `zstd`, or `none`)."}; + this, + "xz", + "compression", + R"( + NAR compression method. One of: `xz`, `bzip2`, `gzip`, `zstd`, `none`, `br`, `compress`, `grzip`, `lrzip`, `lz4`, `lzip`, `lzma` or `lzop`. + To use a particular compression method Nix has to be built with a version of libarchive that natively supports that compression algorithm. + )"}; const Setting writeNARListing{ this, false, "write-nar-listing", "Whether to write a JSON file that lists the files in each NAR."}; From 6ba067831a32ead02a40b1200702daef7212c48e Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman Date: Tue, 20 Jan 2026 04:35:16 +0300 Subject: [PATCH 3/3] Use CompressionAlgo throughout Instead of the stringly typed code we should use an enum class, this is more clear and less error-prone. Also adds settings implementations for CompressionAlgo and std::optional. The first is used for NAR compression, since we never accepted empty strings there: error: unknown compression method '' The other one is used for optional .narinfo, .ls, and log/ compression. Those treated empty strings as compression being disabled. The same exact semantics is kept. This has the benefit of improving error messages for incorrect values: error: option 'compression' has invalid value 'bz' Did you mean one of br, xz or lz4? --- src/libstore/binary-cache-store.cc | 16 ++--- src/libstore/http-binary-cache-store.cc | 12 ++-- .../include/nix/store/binary-cache-store.hh | 6 +- .../nix/store/http-binary-cache-store.hh | 13 ++-- src/libstore/include/nix/store/nar-info.hh | 5 +- src/libstore/local-store.cc | 2 +- src/libstore/s3-binary-cache-store.cc | 4 +- src/libutil-tests/compression.cc | 17 ++--- src/libutil/compression-algo.cc | 46 +++++++++++++ src/libutil/compression-settings.cc | 68 +++++++++++++++++++ src/libutil/compression.cc | 37 +--------- .../include/nix/util/compression-algo.hh | 42 ++++++++++++ .../include/nix/util/compression-settings.hh | 21 ++++++ src/libutil/include/nix/util/compression.hh | 24 +------ src/libutil/include/nix/util/meson.build | 2 + src/libutil/include/nix/util/serialise.hh | 12 ++-- src/libutil/meson.build | 2 + src/libutil/serialise.cc | 2 +- 18 files changed, 228 insertions(+), 103 deletions(-) create mode 100644 src/libutil/compression-algo.cc create mode 100644 src/libutil/compression-settings.cc create mode 100644 src/libutil/include/nix/util/compression-algo.hh create mode 100644 src/libutil/include/nix/util/compression-settings.hh diff --git a/src/libstore/binary-cache-store.cc b/src/libstore/binary-cache-store.cc index b5a47c6ce0fc..806ebb4c9c6d 100644 --- a/src/libstore/binary-cache-store.cc +++ b/src/libstore/binary-cache-store.cc @@ -165,18 +165,18 @@ ref BinaryCacheStore::addToStoreCommon( auto info = mkInfo(narHashSink.finish()); auto narInfo = make_ref(info); - narInfo->compression = config.compression; + narInfo->compression = config.compression.to_string(); // FIXME: Make NarInfo use CompressionAlgo auto [fileHash, fileSize] = fileHashSink.finish(); narInfo->fileHash = fileHash; narInfo->fileSize = fileSize; narInfo->url = "nar/" + narInfo->fileHash->to_string(HashFormat::Nix32, false) + ".nar" - + (config.compression == "xz" ? ".xz" - : config.compression == "bzip2" ? ".bz2" - : config.compression == "zstd" ? ".zst" - : config.compression == "lzip" ? ".lzip" - : config.compression == "lz4" ? ".lz4" - : config.compression == "br" ? ".br" - : ""); + + (config.compression == CompressionAlgo::xz ? ".xz" + : config.compression == CompressionAlgo::bzip2 ? ".bz2" + : config.compression == CompressionAlgo::zstd ? ".zst" + : config.compression == CompressionAlgo::lzip ? ".lzip" + : config.compression == CompressionAlgo::lz4 ? ".lz4" + : config.compression == CompressionAlgo::brotli ? ".br" + : ""); auto duration = std::chrono::duration_cast(now2 - now1).count(); printMsg( diff --git a/src/libstore/http-binary-cache-store.cc b/src/libstore/http-binary-cache-store.cc index d4361264edf6..92a551de8805 100644 --- a/src/libstore/http-binary-cache-store.cc +++ b/src/libstore/http-binary-cache-store.cc @@ -78,13 +78,13 @@ void HttpBinaryCacheStore::init() } } -std::optional HttpBinaryCacheStore::getCompressionMethod(const std::string & path) +std::optional HttpBinaryCacheStore::getCompressionMethod(const std::string & path) { - if (hasSuffix(path, ".narinfo") && !config->narinfoCompression.get().empty()) + if (hasSuffix(path, ".narinfo") && config->narinfoCompression.get()) return config->narinfoCompression; - else if (hasSuffix(path, ".ls") && !config->lsCompression.get().empty()) + else if (hasSuffix(path, ".ls") && config->lsCompression.get()) return config->lsCompression; - else if (hasPrefix(path, "log/") && !config->logCompression.get().empty()) + else if (hasPrefix(path, "log/") && config->logCompression.get()) return config->logCompression; else return std::nullopt; @@ -160,7 +160,9 @@ void HttpBinaryCacheStore::upsertFile( try { if (auto compressionMethod = getCompressionMethod(path)) { CompressedSource compressed(source, *compressionMethod); - Headers headers = {{"Content-Encoding", *compressionMethod}}; + /* TODO: Validate that this is a valid content encoding. We probably shouldn't set non-standard values here. + */ + Headers headers = {{"Content-Encoding", showCompressionAlgo(*compressionMethod)}}; upload(path, compressed, compressed.size(), mimeType, std::move(headers)); } else { upload(path, source, sizeHint, mimeType, std::nullopt); diff --git a/src/libstore/include/nix/store/binary-cache-store.hh b/src/libstore/include/nix/store/binary-cache-store.hh index 9ec209d8c806..f083eebb2064 100644 --- a/src/libstore/include/nix/store/binary-cache-store.hh +++ b/src/libstore/include/nix/store/binary-cache-store.hh @@ -1,7 +1,7 @@ #pragma once ///@file -#include "nix/util/signature/local-keys.hh" +#include "nix/util/compression-settings.hh" #include "nix/store/store-api.hh" #include "nix/store/log-store.hh" @@ -18,9 +18,9 @@ struct BinaryCacheStoreConfig : virtual StoreConfig { using StoreConfig::StoreConfig; - const Setting compression{ + const Setting compression{ this, - "xz", + CompressionAlgo::xz, "compression", R"( NAR compression method. One of: `xz`, `bzip2`, `gzip`, `zstd`, `none`, `br`, `compress`, `grzip`, `lrzip`, `lz4`, `lzip`, `lzma` or `lzop`. diff --git a/src/libstore/include/nix/store/http-binary-cache-store.hh b/src/libstore/include/nix/store/http-binary-cache-store.hh index ea3d77b7987b..12a21b27b080 100644 --- a/src/libstore/include/nix/store/http-binary-cache-store.hh +++ b/src/libstore/include/nix/store/http-binary-cache-store.hh @@ -21,14 +21,15 @@ struct HttpBinaryCacheStoreConfig : std::enable_shared_from_this narinfoCompression{ - this, "", "narinfo-compression", "Compression method for `.narinfo` files."}; + const Setting> narinfoCompression{ + this, std::nullopt, "narinfo-compression", "Compression method for `.narinfo` files."}; - const Setting lsCompression{this, "", "ls-compression", "Compression method for `.ls` files."}; + const Setting> lsCompression{ + this, std::nullopt, "ls-compression", "Compression method for `.ls` files."}; - const Setting logCompression{ + const Setting> logCompression{ this, - "", + std::nullopt, "log-compression", R"( Compression method for `log/*` files. It is recommended to @@ -72,7 +73,7 @@ public: protected: - std::optional getCompressionMethod(const std::string & path); + std::optional getCompressionMethod(const std::string & path); void maybeDisable(); diff --git a/src/libstore/include/nix/store/nar-info.hh b/src/libstore/include/nix/store/nar-info.hh index ac25f75c2cdf..7403dc1d4452 100644 --- a/src/libstore/include/nix/store/nar-info.hh +++ b/src/libstore/include/nix/store/nar-info.hh @@ -1,6 +1,7 @@ #pragma once ///@file +#include "nix/util/compression-algo.hh" #include "nix/util/types.hh" #include "nix/util/hash.hh" #include "nix/store/path-info.hh" @@ -12,7 +13,7 @@ struct StoreDirConfig; struct UnkeyedNarInfo : virtual UnkeyedValidPathInfo { std::string url; - std::string compression; + std::string compression; // FIXME: Use CompressionAlgo std::optional fileHash; uint64_t fileSize = 0; @@ -42,7 +43,7 @@ struct NarInfo : ValidPathInfo, UnkeyedNarInfo /* Later copies from `*this` are pointless. The argument is only there so the constructors can also call `UnkeyedValidPathInfo`, but this won't happen since the base - class is virtual. Only this counstructor (assuming it is most + class is virtual. Only this constructor (assuming it is most derived) will initialize that virtual base class. */ , ValidPathInfo{info.path, static_cast(*this)} , UnkeyedNarInfo{static_cast(*this)} diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 4b92d752291e..ad1c5db0aa4d 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -1564,7 +1564,7 @@ void LocalStore::addBuildLog(const StorePath & drvPath, std::string_view log) auto tmpFile = fmt("%s.tmp.%d", logPath, getpid()); - writeFile(tmpFile, compress("bzip2", log)); + writeFile(tmpFile, compress(CompressionAlgo::bzip2, log)); std::filesystem::rename(tmpFile, logPath); } diff --git a/src/libstore/s3-binary-cache-store.cc b/src/libstore/s3-binary-cache-store.cc index fea5e467f7b7..d2e964edcf43 100644 --- a/src/libstore/s3-binary-cache-store.cc +++ b/src/libstore/s3-binary-cache-store.cc @@ -148,7 +148,9 @@ void S3BinaryCacheStore::upsertFile( try { if (auto compressionMethod = getCompressionMethod(path)) { CompressedSource compressed(source, *compressionMethod); - Headers headers = {{"Content-Encoding", *compressionMethod}}; + /* TODO: Validate that this is a valid content encoding. We probably shouldn't set non-standard values here. + */ + Headers headers = {{"Content-Encoding", showCompressionAlgo(*compressionMethod)}}; doUpload(compressed, compressed.size(), std::move(headers)); } else { doUpload(source, sizeHint, std::nullopt); diff --git a/src/libutil-tests/compression.cc b/src/libutil-tests/compression.cc index c6d57047118d..53d476fa8593 100644 --- a/src/libutil-tests/compression.cc +++ b/src/libutil-tests/compression.cc @@ -7,14 +7,9 @@ namespace nix { * compress / decompress * --------------------------------------------------------------------------*/ -TEST(compress, compressWithUnknownMethod) -{ - ASSERT_THROW(compress("invalid-method", "something-to-compress"), UnknownCompressionMethod); -} - TEST(compress, noneMethodDoesNothingToTheInput) { - auto o = compress("none", "this-is-a-test"); + auto o = compress(CompressionAlgo::none, "this-is-a-test"); ASSERT_EQ(o, "this-is-a-test"); } @@ -43,7 +38,7 @@ TEST(decompress, decompressXzCompressed) { auto method = "xz"; auto str = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; - auto o = decompress(method, compress(method, str)); + auto o = decompress(method, compress(CompressionAlgo::xz, str)); ASSERT_EQ(o, str); } @@ -52,7 +47,7 @@ TEST(decompress, decompressBzip2Compressed) { auto method = "bzip2"; auto str = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; - auto o = decompress(method, compress(method, str)); + auto o = decompress(method, compress(CompressionAlgo::bzip2, str)); ASSERT_EQ(o, str); } @@ -61,7 +56,7 @@ TEST(decompress, decompressBrCompressed) { auto method = "br"; auto str = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; - auto o = decompress(method, compress(method, str)); + auto o = decompress(method, compress(CompressionAlgo::brotli, str)); ASSERT_EQ(o, str); } @@ -82,7 +77,7 @@ TEST(makeCompressionSink, noneSinkDoesNothingToInput) { StringSink strSink; auto inputString = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; - auto sink = makeCompressionSink("none", strSink); + auto sink = makeCompressionSink(CompressionAlgo::none, strSink); (*sink)(inputString); sink->finish(); @@ -94,7 +89,7 @@ TEST(makeCompressionSink, compressAndDecompress) StringSink strSink; auto inputString = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf"; auto decompressionSink = makeDecompressionSink("bzip2", strSink); - auto sink = makeCompressionSink("bzip2", *decompressionSink); + auto sink = makeCompressionSink(CompressionAlgo::bzip2, *decompressionSink); (*sink)(inputString); sink->finish(); diff --git a/src/libutil/compression-algo.cc b/src/libutil/compression-algo.cc new file mode 100644 index 000000000000..dab53b124f13 --- /dev/null +++ b/src/libutil/compression-algo.cc @@ -0,0 +1,46 @@ +#include "nix/util/compression-algo.hh" +#include "nix/util/error.hh" +#include "nix/util/types.hh" + +#include + +namespace nix { + +CompressionAlgo parseCompressionAlgo(std::string_view method, bool suggestions) +{ +#define NIX_COMPRESSION_ALGO_FROM_STRING(name, value) {name, CompressionAlgo::value}, + static const std::unordered_map lookupTable = { + NIX_FOR_EACH_COMPRESSION_ALGO(NIX_COMPRESSION_ALGO_FROM_STRING)}; +#undef NIX_COMPRESSION_ALGO_FROM_STRING + + if (auto it = lookupTable.find(method); it != lookupTable.end()) + return it->second; + + ErrorInfo err = {.level = lvlError, .msg = HintFmt("unknown compression method '%s'", method)}; + + if (suggestions) { + static const StringSet allNames = [&]() { + StringSet res; + for (auto & [name, _] : lookupTable) + res.emplace(name); + return res; + }(); + err.suggestions = Suggestions::bestMatches(allNames, method); + } + + throw UnknownCompressionMethod(std::move(err)); +} + +std::string showCompressionAlgo(CompressionAlgo method) +{ + switch (method) { +#define NIX_COMPRESSION_ALGO_TO_STRING(name, value) \ + case CompressionAlgo::value: \ + return name; + NIX_FOR_EACH_COMPRESSION_ALGO(NIX_COMPRESSION_ALGO_TO_STRING); +#undef NIX_COMPRESSION_ALGO_TO_STRING + } + unreachable(); +} + +} // namespace nix diff --git a/src/libutil/compression-settings.cc b/src/libutil/compression-settings.cc new file mode 100644 index 000000000000..6e30811ef1b2 --- /dev/null +++ b/src/libutil/compression-settings.cc @@ -0,0 +1,68 @@ +#include "nix/util/configuration.hh" +#include "nix/util/compression-settings.hh" +#include "nix/util/json-impls.hh" +#include "nix/util/config-impl.hh" +#include "nix/util/abstract-setting-to-json.hh" + +#include + +namespace nix { + +template<> +CompressionAlgo BaseSetting::parse(const std::string & str) const +try { + return parseCompressionAlgo(str, /*suggestions=*/true); +} catch (UnknownCompressionMethod & e) { + throw UsageError(e.info().suggestions, "option '%s' has invalid value '%s'", name, str); +} + +template<> +std::optional BaseSetting>::parse(const std::string & str) const +try { + if (str.empty()) + return std::nullopt; + return parseCompressionAlgo(str, /*suggestions=*/true); +} catch (UnknownCompressionMethod & e) { + throw UsageError(e.info().suggestions, "option '%s' has invalid value '%s'", name, str); +} + +template<> +struct BaseSetting::trait +{ + static constexpr bool appendable = false; +}; + +template<> +struct BaseSetting>::trait +{ + static constexpr bool appendable = false; +}; + +template<> +std::string BaseSetting::to_string() const +{ + return std::string{showCompressionAlgo(value)}; +} + +template<> +std::string BaseSetting>::to_string() const +{ + if (value) + return std::string{showCompressionAlgo(*value)}; + return ""; +} + +/* Same as with all settings - empty string means std::nullopt. */ +template<> +struct json_avoids_null : std::true_type +{}; + +#define NIX_COMPRESSION_JSON(name, value) {CompressionAlgo::value, name}, +NLOHMANN_JSON_SERIALIZE_ENUM(CompressionAlgo, {NIX_FOR_EACH_COMPRESSION_ALGO(NIX_COMPRESSION_JSON)}); +#undef NIX_COMPRESSION_JSON + +/* Explicit instantiation of templates */ +template class BaseSetting; +template class BaseSetting>; + +} // namespace nix diff --git a/src/libutil/compression.cc b/src/libutil/compression.cc index 38b2cdb7e947..8b55c44a2db2 100644 --- a/src/libutil/compression.cc +++ b/src/libutil/compression.cc @@ -69,8 +69,7 @@ struct ArchiveDecompressionSource : Source } }; -/* These strings are a part of the public API in store parameters and such. Do not change! - Happens to match enum names. */ +/* Happens to match enum names. */ #define NIX_FOR_EACH_LA_ALGO(MACRO) \ MACRO(bzip2) \ MACRO(compress) \ @@ -319,38 +318,6 @@ struct BrotliCompressionSink : ChunkedCompressionSink } }; -/* Parses a *compression* method into the corresponding enum. This is only used - in the *compression* case and user interface. Content-Encoding should not use - these. */ -static CompressionAlgo parseNixCompressionAlgoString(std::string_view method) -{ - static const std::unordered_map lookupTable = { - {"none", CompressionAlgo::none}, - {"br", CompressionAlgo::brotli}, -#define NIX_DEF_LA_ALGO_NAME(algo) {#algo, CompressionAlgo::algo}, - NIX_FOR_EACH_LA_ALGO(NIX_DEF_LA_ALGO_NAME) -#undef NIX_DEF_LA_ALGO_NAME - }; - - if (auto it = lookupTable.find(method); it != lookupTable.end()) - return it->second; - - static const StringSet allNames = [&]() { - StringSet res; - for (auto & [name, _] : lookupTable) - res.emplace(name); - return res; - }(); - - throw UnknownCompressionMethod( - Suggestions::bestMatches(allNames, method), "unknown compression method '%s'", method); -} - -ref makeCompressionSink(const std::string & method, Sink & nextSink, const bool parallel, int level) -{ - return makeCompressionSink(parseNixCompressionAlgoString(method), nextSink, parallel, level); -} - ref makeCompressionSink(CompressionAlgo method, Sink & nextSink, const bool parallel, int level) { switch (method) { @@ -367,7 +334,7 @@ ref makeCompressionSink(CompressionAlgo method, Sink & nextSink unreachable(); } -std::string compress(const std::string & method, std::string_view in, const bool parallel, int level) +std::string compress(CompressionAlgo method, std::string_view in, const bool parallel, int level) { StringSink ssink; auto sink = makeCompressionSink(method, ssink, parallel, level); diff --git a/src/libutil/include/nix/util/compression-algo.hh b/src/libutil/include/nix/util/compression-algo.hh new file mode 100644 index 000000000000..fe1fc57596c3 --- /dev/null +++ b/src/libutil/include/nix/util/compression-algo.hh @@ -0,0 +1,42 @@ +#pragma once +///@file + +#include "nix/util/error.hh" + +#include + +namespace nix { + +#define NIX_FOR_EACH_COMPRESSION_ALGO(MACRO) \ + MACRO("none", none) \ + MACRO("br", brotli) \ + MACRO("bzip2", bzip2) \ + MACRO("compress", compress) \ + MACRO("grzip", grzip) \ + MACRO("gzip", gzip) \ + MACRO("lrzip", lrzip) \ + MACRO("lz4", lz4) \ + MACRO("lzip", lzip) \ + MACRO("lzma", lzma) \ + MACRO("lzop", lzop) \ + MACRO("xz", xz) \ + MACRO("zstd", zstd) + +#define NIX_DEFINE_COMPRESSION_ALGO(name, value) value, +enum class CompressionAlgo { NIX_FOR_EACH_COMPRESSION_ALGO(NIX_DEFINE_COMPRESSION_ALGO) }; +#undef NIX_DEFINE_COMPRESSION_ALGO + +/** + * Parses a *compression* method into the corresponding enum. This is only used + * in the *compression* case and user interface. Content-Encoding should not use + * these. + * + * @param suggestions Whether to throw an exception with suggestions. + */ +CompressionAlgo parseCompressionAlgo(std::string_view method, bool suggestions = false); + +std::string showCompressionAlgo(CompressionAlgo method); + +MakeError(UnknownCompressionMethod, Error); + +} // namespace nix diff --git a/src/libutil/include/nix/util/compression-settings.hh b/src/libutil/include/nix/util/compression-settings.hh new file mode 100644 index 000000000000..f9d42c298c6d --- /dev/null +++ b/src/libutil/include/nix/util/compression-settings.hh @@ -0,0 +1,21 @@ +#pragma once +///@file + +#include "nix/util/configuration.hh" +#include "nix/util/compression-algo.hh" + +namespace nix { + +template<> +CompressionAlgo BaseSetting::parse(const std::string & str) const; + +template<> +std::string BaseSetting::to_string() const; + +template<> +std::optional BaseSetting>::parse(const std::string & str) const; + +template<> +std::string BaseSetting>::to_string() const; + +} // namespace nix diff --git a/src/libutil/include/nix/util/compression.hh b/src/libutil/include/nix/util/compression.hh index 7569c39331cd..db49c8dfd6c1 100644 --- a/src/libutil/include/nix/util/compression.hh +++ b/src/libutil/include/nix/util/compression.hh @@ -4,6 +4,7 @@ #include "nix/util/ref.hh" #include "nix/util/types.hh" #include "nix/util/serialise.hh" +#include "nix/util/compression-algo.hh" #include @@ -16,36 +17,15 @@ struct CompressionSink : BufferedSink, FinishSink using FinishSink::finish; }; -enum class CompressionAlgo { - none, - brotli, - bzip2, - compress, - grzip, - gzip, - lrzip, - lz4, - lzip, - lzma, - lzop, - xz, - zstd, -}; - std::string decompress(const std::string & method, std::string_view in); std::unique_ptr makeDecompressionSink(const std::string & method, Sink & nextSink); -std::string compress(const std::string & method, std::string_view in, const bool parallel = false, int level = -1); - -ref -makeCompressionSink(const std::string & method, Sink & nextSink, const bool parallel = false, int level = -1); +std::string compress(CompressionAlgo method, std::string_view in, const bool parallel = false, int level = -1); ref makeCompressionSink(CompressionAlgo method, Sink & nextSink, const bool parallel = false, int level = -1); -MakeError(UnknownCompressionMethod, Error); - MakeError(CompressionError, Error); } // namespace nix diff --git a/src/libutil/include/nix/util/meson.build b/src/libutil/include/nix/util/meson.build index 37a93238aca2..1ab2c47e47de 100644 --- a/src/libutil/include/nix/util/meson.build +++ b/src/libutil/include/nix/util/meson.build @@ -18,6 +18,8 @@ headers = files( 'chunked-vector.hh', 'closure.hh', 'comparator.hh', + 'compression-algo.hh', + 'compression-settings.hh', 'compression.hh', 'compute-levels.hh', 'config-global.hh', diff --git a/src/libutil/include/nix/util/serialise.hh b/src/libutil/include/nix/util/serialise.hh index 2821540f67b1..e1b5e220fee5 100644 --- a/src/libutil/include/nix/util/serialise.hh +++ b/src/libutil/include/nix/util/serialise.hh @@ -4,6 +4,7 @@ #include #include +#include "nix/util/compression-algo.hh" #include "nix/util/types.hh" #include "nix/util/util.hh" #include "nix/util/file-descriptor.hh" @@ -290,7 +291,7 @@ struct CompressedSource : RestartableSource { private: std::string compressedData; - std::string compressionMethod; + CompressionAlgo compressionMethod; StringSource stringSource; public: @@ -298,9 +299,9 @@ public: * Compress a RestartableSource using the specified compression method. * * @param source The source data to compress - * @param compressionMethod The compression method to use (e.g., "xz", "br") + * @param compressionMethod The compression method to use */ - CompressedSource(RestartableSource & source, const std::string & compressionMethod); + CompressedSource(RestartableSource & source, CompressionAlgo compressionMethod); size_t read(char * data, size_t len) override { @@ -316,11 +317,6 @@ public: { return compressedData.size(); } - - std::string_view getCompressionMethod() const - { - return compressionMethod; - } }; /** diff --git a/src/libutil/meson.build b/src/libutil/meson.build index e05b38cdb9bf..fdd310ad8e4f 100644 --- a/src/libutil/meson.build +++ b/src/libutil/meson.build @@ -125,6 +125,8 @@ sources = [ config_priv_h ] + files( 'base-n.cc', 'base-nix-32.cc', 'canon-path.cc', + 'compression-algo.cc', + 'compression-settings.cc', 'compression.cc', 'compute-levels.cc', 'config-global.cc', diff --git a/src/libutil/serialise.cc b/src/libutil/serialise.cc index 8297f5599946..e930a1964f97 100644 --- a/src/libutil/serialise.cc +++ b/src/libutil/serialise.cc @@ -308,7 +308,7 @@ void StringSource::skip(size_t len) pos += len; } -CompressedSource::CompressedSource(RestartableSource & source, const std::string & compressionMethod) +CompressedSource::CompressedSource(RestartableSource & source, CompressionAlgo compressionMethod) : compressedData([&]() { StringSink sink; auto compressionSink = makeCompressionSink(compressionMethod, sink);