diff options
Diffstat (limited to 'src/libstore/content-address.hh')
-rw-r--r-- | src/libstore/content-address.hh | 198 |
1 files changed, 166 insertions, 32 deletions
diff --git a/src/libstore/content-address.hh b/src/libstore/content-address.hh index 368a7ec48..2f98950fb 100644 --- a/src/libstore/content-address.hh +++ b/src/libstore/content-address.hh @@ -3,12 +3,30 @@ #include <variant> #include "hash.hh" +#include "path.hh" #include "comparator.hh" namespace nix { +/* + * Content addressing method + */ + +/* We only have one way to hash text with references, so this is a single-value + type, mainly useful with std::variant. +*/ + +/** + * The single way we can serialize "text" file system objects. + * + * Somewhat obscure, used by \ref Derivation derivations and + * `builtins.toFile` currently. + */ +struct TextHashMethod : std::monostate { }; + /** - * An enumeration of the ways we can serialize file system objects. + * An enumeration of the main ways we can serialize file system + * objects. */ enum struct FileIngestionMethod : uint8_t { /** @@ -23,6 +41,53 @@ enum struct FileIngestionMethod : uint8_t { }; /** + * Compute the prefix to the hash algorithm which indicates how the + * files were ingested. + */ +std::string makeFileIngestionPrefix(FileIngestionMethod m); + +struct FixedOutputHashMethod { + FileIngestionMethod fileIngestionMethod; + HashType hashType; + + GENERATE_CMP(FixedOutputHashMethod, me->fileIngestionMethod, me->hashType); +}; + +/** + * An enumeration of all the ways we can serialize file system objects. + * + * Just the type of a content address. Combine with the hash itself, and + * we have a `ContentAddress` as defined below. Combine that, in turn, + * with info on references, and we have `ContentAddressWithReferences`, + * as defined further below. + */ +struct ContentAddressMethod +{ + typedef std::variant< + TextHashMethod, + FixedOutputHashMethod + > Raw; + + Raw raw; + + GENERATE_CMP(ContentAddressMethod, me->raw); + + /* The moral equivalent of `using Raw::Raw;` */ + ContentAddressMethod(auto &&... arg) + : raw(std::forward<decltype(arg)>(arg)...) + { } + + static ContentAddressMethod parse(std::string_view rawCaMethod); + + std::string render() const; +}; + + +/* + * Mini content address + */ + +/** * Somewhat obscure, used by \ref Derivation derivations and * `builtins.toFile` currently. */ @@ -36,7 +101,7 @@ struct TextHash { }; /** - * For path computed by makeFixedOutputPath. + * Used by most store objects that are content-addressed. */ struct FixedOutputHash { /** @@ -65,41 +130,96 @@ struct FixedOutputHash { * - ‘fixed:<r?>:<ht>:<h>’: For paths computed by * Store::makeFixedOutputPath() / Store::addToStore(). */ -typedef std::variant< - TextHash, - FixedOutputHash -> ContentAddress; +struct ContentAddress +{ + typedef std::variant< + TextHash, + FixedOutputHash + > Raw; -/** - * Compute the prefix to the hash algorithm which indicates how the - * files were ingested. + Raw raw; + + GENERATE_CMP(ContentAddress, me->raw); + + /* The moral equivalent of `using Raw::Raw;` */ + ContentAddress(auto &&... arg) + : raw(std::forward<decltype(arg)>(arg)...) + { } + + /** + * Compute the content-addressability assertion (ValidPathInfo::ca) for + * paths created by Store::makeFixedOutputPath() / Store::addToStore(). + */ + std::string render() const; + + static ContentAddress parse(std::string_view rawCa); + + static std::optional<ContentAddress> parseOpt(std::string_view rawCaOpt); + + const Hash & getHash() const; +}; + +std::string renderContentAddress(std::optional<ContentAddress> ca); + + +/* + * Full content address + * + * See the schema for store paths in store-api.cc */ -std::string makeFileIngestionPrefix(const FileIngestionMethod m); /** - * Compute the content-addressability assertion (ValidPathInfo::ca) for - * paths created by Store::makeFixedOutputPath() / Store::addToStore(). + * A set of references to other store objects. + * + * References to other store objects are tracked with store paths, self + * references however are tracked with a boolean. */ -std::string makeFixedOutputCA(FileIngestionMethod method, const Hash & hash); +struct StoreReferences { + /** + * References to other store objects + */ + StorePathSet others; -std::string renderContentAddress(ContentAddress ca); + /** + * Reference to this store object + */ + bool self = false; -std::string renderContentAddress(std::optional<ContentAddress> ca); + /** + * @return true iff no references, i.e. others is empty and self is + * false. + */ + bool empty() const; -ContentAddress parseContentAddress(std::string_view rawCa); + /** + * Returns the numbers of references, i.e. the size of others + 1 + * iff self is true. + */ + size_t size() const; -std::optional<ContentAddress> parseContentAddressOpt(std::string_view rawCaOpt); + GENERATE_CMP(StoreReferences, me->self, me->others); +}; -Hash getContentAddressHash(const ContentAddress & ca); +// This matches the additional info that we need for makeTextPath +struct TextInfo { + TextHash hash; + /** + * References to other store objects only; self references + * disallowed + */ + StorePathSet references; -/* - We only have one way to hash text with references, so this is single-value - type is only useful in std::variant. -*/ -struct TextHashMethod { }; -struct FixedOutputHashMethod { - FileIngestionMethod fileIngestionMethod; - HashType hashType; + GENERATE_CMP(TextInfo, me->hash, me->references); +}; + +struct FixedOutputInfo { + FixedOutputHash hash; + /** + * References to other store objects or this one. + */ + StoreReferences references; + + GENERATE_CMP(FixedOutputInfo, me->hash, me->references); }; /** @@ -107,13 +227,27 @@ struct FixedOutputHashMethod { * * A ContentAddress without a Hash. */ -typedef std::variant< - TextHashMethod, - FixedOutputHashMethod - > ContentAddressMethod; +struct ContentAddressWithReferences +{ + typedef std::variant< + TextInfo, + FixedOutputInfo + > Raw; + + Raw raw; -ContentAddressMethod parseContentAddressMethod(std::string_view rawCaMethod); + GENERATE_CMP(ContentAddressWithReferences, me->raw); -std::string renderContentAddressMethod(ContentAddressMethod caMethod); + /* The moral equivalent of `using Raw::Raw;` */ + ContentAddressWithReferences(auto &&... arg) + : raw(std::forward<decltype(arg)>(arg)...) + { } + + /** + * Create a ContentAddressWithReferences from a mere ContentAddress, by + * assuming no references in all cases. + */ + static ContentAddressWithReferences withoutRefs(const ContentAddress &); +}; } |