lix/src/libstore/content-address.hh

191 lines
5.1 KiB
C++
Raw Normal View History

2020-06-01 21:32:27 +00:00
#pragma once
2020-06-01 22:53:31 +00:00
#include <variant>
2020-06-01 21:32:27 +00:00
#include "hash.hh"
2020-10-07 13:52:20 +00:00
#include "path.hh"
#include "comparator.hh"
2020-06-01 21:32:27 +00:00
namespace nix {
2020-10-07 13:52:20 +00:00
/*
* Content addressing method
2020-10-07 13:52:20 +00:00
*/
/* We only have one way to hash text with references, so this is a single-value
type, mainly useful with std::variant.
*/
struct TextHashMethod : std::monostate { };
2020-06-01 21:32:27 +00:00
enum struct FileIngestionMethod : uint8_t {
Flat = false,
Recursive = true
};
/* Compute the prefix to the hash algorithm which indicates how the files were
ingested. */
std::string makeFileIngestionPrefix(FileIngestionMethod m);
/* 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. */
typedef std::variant<
TextHashMethod,
FileIngestionMethod
> ContentAddressMethod;
/* Parse and pretty print the algorithm which indicates how the files
were ingested, with the the fixed output case not prefixed for back
compat. */
std::string makeContentAddressingPrefix(ContentAddressMethod m);
ContentAddressMethod parseContentAddressingPrefix(std::string_view & m);
/* Parse and pretty print a content addressing method and hash in a
nicer way, prefixing both cases. */
std::string renderContentAddressMethodAndHash(ContentAddressMethod cam, HashType ht);
std::pair<ContentAddressMethod, HashType> parseContentAddressMethod(std::string_view caMethod);
2020-10-07 13:52:20 +00:00
/*
* Mini content address
*/
2020-10-07 13:52:20 +00:00
2020-06-01 23:26:40 +00:00
struct TextHash {
Hash hash;
GENERATE_CMP(TextHash, me->hash);
2020-06-01 23:26:40 +00:00
};
2020-06-01 21:32:27 +00:00
/// Pair of a hash, and how the file system was ingested
struct FixedOutputHash {
2020-06-01 21:32:27 +00:00
FileIngestionMethod method;
Hash hash;
std::string printMethodAlgo() const;
GENERATE_CMP(FixedOutputHash, me->method, me->hash);
2020-06-01 21:32:27 +00:00
};
2020-06-01 22:53:31 +00:00
/*
We've accumulated several types of content-addressed paths over the years;
fixed-output derivations support multiple hash algorithms and serialisation
methods (flat file vs NAR). Thus, ca has one of the following forms:
* text:sha256:<sha256 hash of file contents>: For paths
computed by makeTextPath() / addTextToStore().
* fixed:<r?>:<ht>:<h>: For paths computed by
makeFixedOutputPath() / addToStore().
*/
typedef std::variant<
2020-06-01 23:26:40 +00:00
TextHash, // for paths computed by makeTextPath() / addTextToStore
FixedOutputHash // for path computed by makeFixedOutputPath
2020-06-01 22:53:31 +00:00
> ContentAddress;
2020-06-01 23:26:40 +00:00
std::string renderContentAddress(ContentAddress ca);
std::string renderContentAddress(std::optional<ContentAddress> ca);
ContentAddress parseContentAddress(std::string_view rawCa);
2020-06-02 00:37:43 +00:00
std::optional<ContentAddress> parseContentAddressOpt(std::string_view rawCaOpt);
2020-06-02 00:37:43 +00:00
Hash getContentAddressHash(const ContentAddress & ca);
2020-10-07 13:52:20 +00:00
/*
* References set
*/
template<typename Ref>
struct PathReferences
{
std::set<Ref> references;
bool hasSelfReference = false;
/* Functions to view references + hasSelfReference as one set, mainly for
compatibility's sake. */
StorePathSet referencesPossiblyToSelf(const Ref & self) const;
void insertReferencePossiblyToSelf(const Ref & self, Ref && ref);
void setReferencesPossiblyToSelf(const Ref & self, std::set<Ref> && refs);
GENERATE_CMP(PathReferences<Ref>, me->references, me->hasSelfReference);
2020-10-07 13:52:20 +00:00
};
template<typename Ref>
StorePathSet PathReferences<Ref>::referencesPossiblyToSelf(const Ref & self) const
{
StorePathSet refs { references };
if (hasSelfReference)
refs.insert(self);
return refs;
}
template<typename Ref>
void PathReferences<Ref>::insertReferencePossiblyToSelf(const Ref & self, Ref && ref)
{
if (ref == self)
hasSelfReference = true;
else
references.insert(std::move(ref));
}
template<typename Ref>
void PathReferences<Ref>::setReferencesPossiblyToSelf(const Ref & self, std::set<Ref> && refs)
{
if (refs.count(self))
hasSelfReference = true;
refs.erase(self);
references = refs;
}
/*
* Full content address
*
* See the schema for store paths in store-api.cc
*/
// This matches the additional info that we need for makeTextPath
struct TextInfo : TextHash {
// References for the paths, self references disallowed
StorePathSet references;
GENERATE_CMP(TextInfo, *(const TextHash *)me, me->references);
2020-10-07 13:52:20 +00:00
};
struct FixedOutputInfo : FixedOutputHash {
// References for the paths
PathReferences<StorePath> references;
GENERATE_CMP(FixedOutputInfo, *(const FixedOutputHash *)me, me->references);
2020-10-07 13:52:20 +00:00
};
typedef std::variant<
TextInfo,
FixedOutputInfo
> ContentAddressWithReferences;
ContentAddressWithReferences caWithoutRefs(const ContentAddress &);
ContentAddressWithReferences contentAddressFromMethodHashAndRefs(
ContentAddressMethod method, Hash && hash, PathReferences<StorePath> && refs);
ContentAddressMethod getContentAddressMethod(const ContentAddressWithReferences & ca);
Hash getContentAddressHash(const ContentAddressWithReferences & ca);
std::string printMethodAlgo(const ContentAddressWithReferences &);
2020-10-07 13:52:20 +00:00
struct StorePathDescriptor {
std::string name;
ContentAddressWithReferences info;
GENERATE_CMP(StorePathDescriptor, me->name, me->info);
2020-10-07 13:52:20 +00:00
};
2020-06-01 21:32:27 +00:00
}