Merge pull request #8111 from obsidiansystems/improve-internal-api-docs

Convert a bunch of comments in headers to Doxygen documentation
This commit is contained in:
John Ericson 2023-03-30 09:40:22 -04:00 committed by GitHub
commit 06d87b95bc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 756 additions and 394 deletions

View file

@ -5,44 +5,75 @@
namespace nix { namespace nix {
/**
* An enumeration of the ways we can serialize file system objects.
*/
enum struct FileIngestionMethod : uint8_t { enum struct FileIngestionMethod : uint8_t {
/**
* Flat-file hashing. Directly ingest the contents of a single file
*/
Flat = false, Flat = false,
/**
* Recursive (or NAR) hashing. Serializes the file-system object in Nix
* Archive format and ingest that
*/
Recursive = true Recursive = true
}; };
/**
* Somewhat obscure, used by \ref Derivation derivations and
* `builtins.toFile` currently.
*/
struct TextHash { struct TextHash {
/**
* Hash of the contents of the text/file.
*/
Hash hash; Hash hash;
}; };
/// Pair of a hash, and how the file system was ingested /**
* For path computed by makeFixedOutputPath.
*/
struct FixedOutputHash { struct FixedOutputHash {
/**
* How the file system objects are serialized
*/
FileIngestionMethod method; FileIngestionMethod method;
/**
* Hash of that serialization
*/
Hash hash; Hash hash;
std::string printMethodAlgo() const; std::string printMethodAlgo() const;
}; };
/* /**
We've accumulated several types of content-addressed paths over the years; * We've accumulated several types of content-addressed paths over the
fixed-output derivations support multiple hash algorithms and serialisation * years; fixed-output derivations support multiple hash algorithms and
methods (flat file vs NAR). Thus, ca has one of the following forms: * 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(). * - text:sha256:<sha256 hash of file contents>: For paths
* computed by Store::makeTextPath() / Store::addTextToStore().
* fixed:<r?>:<ht>:<h>: For paths computed by *
makeFixedOutputPath() / addToStore(). * - fixed:<r?>:<ht>:<h>: For paths computed by
*/ * Store::makeFixedOutputPath() / Store::addToStore().
*/
typedef std::variant< typedef std::variant<
TextHash, // for paths computed by makeTextPath() / addTextToStore TextHash,
FixedOutputHash // for path computed by makeFixedOutputPath FixedOutputHash
> ContentAddress; > ContentAddress;
/* Compute the prefix to the hash algorithm which indicates how the files were /**
ingested. */ * Compute the prefix to the hash algorithm which indicates how the
* files were ingested.
*/
std::string makeFileIngestionPrefix(const FileIngestionMethod m); std::string makeFileIngestionPrefix(const FileIngestionMethod m);
/* Compute the content-addressability assertion (ValidPathInfo::ca) /**
for paths created by makeFixedOutputPath() / addToStore(). */ * Compute the content-addressability assertion (ValidPathInfo::ca) for
* paths created by Store::makeFixedOutputPath() / Store::addToStore().
*/
std::string makeFixedOutputCA(FileIngestionMethod method, const Hash & hash); std::string makeFixedOutputCA(FileIngestionMethod method, const Hash & hash);
std::string renderContentAddress(ContentAddress ca); std::string renderContentAddress(ContentAddress ca);
@ -65,6 +96,11 @@ struct FixedOutputHashMethod {
HashType hashType; HashType hashType;
}; };
/**
* Ways of content addressing but not a complete ContentAddress.
*
* A ContentAddress without a Hash.
*/
typedef std::variant< typedef std::variant<
TextHashMethod, TextHashMethod,
FixedOutputHashMethod FixedOutputHashMethod

View file

@ -17,42 +17,72 @@ class Store;
/* Abstract syntax of derivations. */ /* Abstract syntax of derivations. */
/* The traditional non-fixed-output derivation type. */ /**
* The traditional non-fixed-output derivation type.
*/
struct DerivationOutputInputAddressed struct DerivationOutputInputAddressed
{ {
StorePath path; StorePath path;
}; };
/* Fixed-output derivations, whose output paths are content addressed /**
according to that fixed output. */ * Fixed-output derivations, whose output paths are content
* addressed according to that fixed output.
*/
struct DerivationOutputCAFixed struct DerivationOutputCAFixed
{ {
FixedOutputHash hash; /* hash used for expected hash computation */ /**
* hash used for expected hash computation
*/
FixedOutputHash hash;
/**
* Return the \ref StorePath "store path" corresponding to this output
*
* @param drvName The name of the derivation this is an output of, without the `.drv`.
* @param outputName The name of this output.
*/
StorePath path(const Store & store, std::string_view drvName, std::string_view outputName) const; StorePath path(const Store & store, std::string_view drvName, std::string_view outputName) const;
}; };
/* Floating-output derivations, whose output paths are content addressed, but /**
not fixed, and so are dynamically calculated from whatever the output ends * Floating-output derivations, whose output paths are content
up being. */ * addressed, but not fixed, and so are dynamically calculated from
* whatever the output ends up being.
* */
struct DerivationOutputCAFloating struct DerivationOutputCAFloating
{ {
/* information used for expected hash computation */ /**
* How the file system objects will be serialized for hashing
*/
FileIngestionMethod method; FileIngestionMethod method;
/**
* How the serialization will be hashed
*/
HashType hashType; HashType hashType;
}; };
/* Input-addressed output which depends on a (CA) derivation whose hash isn't /**
* known yet. * Input-addressed output which depends on a (CA) derivation whose hash
* isn't known yet.
*/ */
struct DerivationOutputDeferred {}; struct DerivationOutputDeferred {};
/* Impure output which is moved to a content-addressed location (like /**
CAFloating) but isn't registered as a realization. * Impure output which is moved to a content-addressed location (like
* CAFloating) but isn't registered as a realization.
*/ */
struct DerivationOutputImpure struct DerivationOutputImpure
{ {
/* information used for expected hash computation */ /**
* How the file system objects will be serialized for hashing
*/
FileIngestionMethod method; FileIngestionMethod method;
/**
* How the serialization will be hashed
*/
HashType hashType; HashType hashType;
}; };
@ -64,6 +94,9 @@ typedef std::variant<
DerivationOutputImpure DerivationOutputImpure
> _DerivationOutputRaw; > _DerivationOutputRaw;
/**
* A single output of a BasicDerivation (and Derivation).
*/
struct DerivationOutput : _DerivationOutputRaw struct DerivationOutput : _DerivationOutputRaw
{ {
using Raw = _DerivationOutputRaw; using Raw = _DerivationOutputRaw;
@ -75,9 +108,12 @@ struct DerivationOutput : _DerivationOutputRaw
using Deferred = DerivationOutputDeferred; using Deferred = DerivationOutputDeferred;
using Impure = DerivationOutputImpure; using Impure = DerivationOutputImpure;
/* Note, when you use this function you should make sure that you're passing /**
the right derivation name. When in doubt, you should use the safer * \note when you use this function you should make sure that you're
interface provided by BasicDerivation::outputsAndOptPaths */ * passing the right derivation name. When in doubt, you should use
* the safer interface provided by
* BasicDerivation::outputsAndOptPaths
*/
std::optional<StorePath> path(const Store & store, std::string_view drvName, std::string_view outputName) const; std::optional<StorePath> path(const Store & store, std::string_view drvName, std::string_view outputName) const;
inline const Raw & raw() const { inline const Raw & raw() const {
@ -92,26 +128,61 @@ struct DerivationOutput : _DerivationOutputRaw
typedef std::map<std::string, DerivationOutput> DerivationOutputs; typedef std::map<std::string, DerivationOutput> DerivationOutputs;
/* These are analogues to the previous DerivationOutputs data type, but they /**
also contains, for each output, the (optional) store path in which it would * These are analogues to the previous DerivationOutputs data type,
be written. To calculate values of these types, see the corresponding * but they also contains, for each output, the (optional) store
functions in BasicDerivation */ * path in which it would be written. To calculate values of these
* types, see the corresponding functions in BasicDerivation.
*/
typedef std::map<std::string, std::pair<DerivationOutput, std::optional<StorePath>>> typedef std::map<std::string, std::pair<DerivationOutput, std::optional<StorePath>>>
DerivationOutputsAndOptPaths; DerivationOutputsAndOptPaths;
/* For inputs that are sub-derivations, we specify exactly which /**
output IDs we are interested in. */ * For inputs that are sub-derivations, we specify exactly which
* output IDs we are interested in.
*/
typedef std::map<StorePath, StringSet> DerivationInputs; typedef std::map<StorePath, StringSet> DerivationInputs;
/**
* Input-addressed derivation types
*/
struct DerivationType_InputAddressed { struct DerivationType_InputAddressed {
/**
* True iff the derivation type can't be determined statically,
* for instance because it (transitively) depends on a content-addressed
* derivation.
*/
bool deferred; bool deferred;
}; };
/**
* Content-addressed derivation types
*/
struct DerivationType_ContentAddressed { struct DerivationType_ContentAddressed {
/**
* Whether the derivation should be built safely inside a sandbox.
*/
bool sandboxed; bool sandboxed;
/**
* Whether the derivation's outputs' content-addresses are "fixed"
* or "floating.
*
* - Fixed: content-addresses are written down as part of the
* derivation itself. If the outputs don't end up matching the
* build fails.
*
* - Floating: content-addresses are not written down, we do not
* know them until we perform the build.
*/
bool fixed; bool fixed;
}; };
/**
* Impure derivation type
*
* This is similar at buil-time to the content addressed, not standboxed, not fixed
* type, but has some restrictions on its usage.
*/
struct DerivationType_Impure { struct DerivationType_Impure {
}; };
@ -128,30 +199,38 @@ struct DerivationType : _DerivationTypeRaw {
using ContentAddressed = DerivationType_ContentAddressed; using ContentAddressed = DerivationType_ContentAddressed;
using Impure = DerivationType_Impure; using Impure = DerivationType_Impure;
/* Do the outputs of the derivation have paths calculated from their content, /**
or from the derivation itself? */ * Do the outputs of the derivation have paths calculated from their
* content, or from the derivation itself?
*/
bool isCA() const; bool isCA() const;
/* Is the content of the outputs fixed a-priori via a hash? Never true for /**
non-CA derivations. */ * Is the content of the outputs fixed <em>a priori</em> via a hash?
* Never true for non-CA derivations.
*/
bool isFixed() const; bool isFixed() const;
/* Whether the derivation is fully sandboxed. If false, the /**
sandbox is opened up, e.g. the derivation has access to the * Whether the derivation is fully sandboxed. If false, the sandbox
network. Note that whether or not we actually sandbox the * is opened up, e.g. the derivation has access to the network. Note
derivation is controlled separately. Always true for non-CA * that whether or not we actually sandbox the derivation is
derivations. */ * controlled separately. Always true for non-CA derivations.
*/
bool isSandboxed() const; bool isSandboxed() const;
/* Whether the derivation is expected to produce the same result /**
every time, and therefore it only needs to be built once. This * Whether the derivation is expected to produce the same result
is only false for derivations that have the attribute '__impure * every time, and therefore it only needs to be built once. This is
= true'. */ * only false for derivations that have the attribute '__impure =
* true'.
*/
bool isPure() const; bool isPure() const;
/* Does the derivation knows its own output paths? /**
Only true when there's no floating-ca derivation involved in the * Does the derivation knows its own output paths?
closure, or if fixed output. * Only true when there's no floating-ca derivation involved in the
* closure, or if fixed output.
*/ */
bool hasKnownOutputPaths() const; bool hasKnownOutputPaths() const;
@ -175,15 +254,21 @@ struct BasicDerivation
bool isBuiltin() const; bool isBuiltin() const;
/* Return true iff this is a fixed-output derivation. */ /**
* Return true iff this is a fixed-output derivation.
*/
DerivationType type() const; DerivationType type() const;
/* Return the output names of a derivation. */ /**
* Return the output names of a derivation.
*/
StringSet outputNames() const; StringSet outputNames() const;
/* Calculates the maps that contains all the DerivationOutputs, but /**
augmented with knowledge of the Store paths they would be written * Calculates the maps that contains all the DerivationOutputs, but
into. */ * augmented with knowledge of the Store paths they would be written
* into.
*/
DerivationOutputsAndOptPaths outputsAndOptPaths(const Store & store) const; DerivationOutputsAndOptPaths outputsAndOptPaths(const Store & store) const;
static std::string_view nameFromPath(const StorePath & storePath); static std::string_view nameFromPath(const StorePath & storePath);
@ -191,23 +276,33 @@ struct BasicDerivation
struct Derivation : BasicDerivation struct Derivation : BasicDerivation
{ {
DerivationInputs inputDrvs; /* inputs that are sub-derivations */ /**
* inputs that are sub-derivations
*/
DerivationInputs inputDrvs;
/* Print a derivation. */ /**
* Print a derivation.
*/
std::string unparse(const Store & store, bool maskOutputs, std::string unparse(const Store & store, bool maskOutputs,
std::map<std::string, StringSet> * actualInputs = nullptr) const; std::map<std::string, StringSet> * actualInputs = nullptr) const;
/* Return the underlying basic derivation but with these changes: /**
* Return the underlying basic derivation but with these changes:
1. Input drvs are emptied, but the outputs of them that were used are *
added directly to input sources. * 1. Input drvs are emptied, but the outputs of them that were used
* are added directly to input sources.
2. Input placeholders are replaced with realized input store paths. */ *
* 2. Input placeholders are replaced with realized input store
* paths.
*/
std::optional<BasicDerivation> tryResolve(Store & store) const; std::optional<BasicDerivation> tryResolve(Store & store) const;
/* Like the above, but instead of querying the Nix database for /**
realisations, uses a given mapping from input derivation paths * Like the above, but instead of querying the Nix database for
+ output names to actual output store paths. */ * realisations, uses a given mapping from input derivation paths +
* output names to actual output store paths.
*/
std::optional<BasicDerivation> tryResolve( std::optional<BasicDerivation> tryResolve(
Store & store, Store & store,
const std::map<std::pair<StorePath, std::string>, StorePath> & inputDrvOutputs) const; const std::map<std::pair<StorePath, std::string>, StorePath> & inputDrvOutputs) const;
@ -222,81 +317,108 @@ struct Derivation : BasicDerivation
class Store; class Store;
/* Write a derivation to the Nix store, and return its path. */ /**
* Write a derivation to the Nix store, and return its path.
*/
StorePath writeDerivation(Store & store, StorePath writeDerivation(Store & store,
const Derivation & drv, const Derivation & drv,
RepairFlag repair = NoRepair, RepairFlag repair = NoRepair,
bool readOnly = false); bool readOnly = false);
/* Read a derivation from a file. */ /**
* Read a derivation from a file.
*/
Derivation parseDerivation(const Store & store, std::string && s, std::string_view name); Derivation parseDerivation(const Store & store, std::string && s, std::string_view name);
// FIXME: remove /**
* \todo Remove.
*
* Use Path::isDerivation instead.
*/
bool isDerivation(std::string_view fileName); bool isDerivation(std::string_view fileName);
/* Calculate the name that will be used for the store path for this /**
output. * Calculate the name that will be used for the store path for this
* output.
This is usually <drv-name>-<output-name>, but is just <drv-name> when *
the output name is "out". */ * This is usually <drv-name>-<output-name>, but is just <drv-name> when
* the output name is "out".
*/
std::string outputPathName(std::string_view drvName, std::string_view outputName); std::string outputPathName(std::string_view drvName, std::string_view outputName);
// The hashes modulo of a derivation. /**
// * The hashes modulo of a derivation.
// Each output is given a hash, although in practice only the content-addressed *
// derivations (fixed-output or not) will have a different hash for each * Each output is given a hash, although in practice only the content-addressed
// output. * derivations (fixed-output or not) will have a different hash for each
* output.
*/
struct DrvHash { struct DrvHash {
/**
* Map from output names to hashes
*/
std::map<std::string, Hash> hashes; std::map<std::string, Hash> hashes;
enum struct Kind : bool { enum struct Kind : bool {
// Statically determined derivations. /**
// This hash will be directly used to compute the output paths * Statically determined derivations.
* This hash will be directly used to compute the output paths
*/
Regular, Regular,
// Floating-output derivations (and their reverse dependencies).
/**
* Floating-output derivations (and their reverse dependencies).
*/
Deferred, Deferred,
}; };
/**
* The kind of derivation this is, simplified for just "derivation hash
* modulo" purposes.
*/
Kind kind; Kind kind;
}; };
void operator |= (DrvHash::Kind & self, const DrvHash::Kind & other) noexcept; void operator |= (DrvHash::Kind & self, const DrvHash::Kind & other) noexcept;
/* Returns hashes with the details of fixed-output subderivations /**
expunged. * Returns hashes with the details of fixed-output subderivations
* expunged.
A fixed-output derivation is a derivation whose outputs have a *
specified content hash and hash algorithm. (Currently they must have * A fixed-output derivation is a derivation whose outputs have a
exactly one output (`out'), which is specified using the `outputHash' * specified content hash and hash algorithm. (Currently they must have
and `outputHashAlgo' attributes, but the algorithm doesn't assume * exactly one output (`out'), which is specified using the `outputHash'
this.) We don't want changes to such derivations to propagate upwards * and `outputHashAlgo' attributes, but the algorithm doesn't assume
through the dependency graph, changing output paths everywhere. * this.) We don't want changes to such derivations to propagate upwards
* through the dependency graph, changing output paths everywhere.
For instance, if we change the url in a call to the `fetchurl' *
function, we do not want to rebuild everything depending on it---after * For instance, if we change the url in a call to the `fetchurl'
all, (the hash of) the file being downloaded is unchanged. So the * function, we do not want to rebuild everything depending on it---after
*output paths* should not change. On the other hand, the *derivation * all, (the hash of) the file being downloaded is unchanged. So the
paths* should change to reflect the new dependency graph. * *output paths* should not change. On the other hand, the *derivation
* paths* should change to reflect the new dependency graph.
For fixed-output derivations, this returns a map from the name of *
each output to its hash, unique up to the output's contents. * For fixed-output derivations, this returns a map from the name of
* each output to its hash, unique up to the output's contents.
For regular derivations, it returns a single hash of the derivation *
ATerm, after subderivations have been likewise expunged from that * For regular derivations, it returns a single hash of the derivation
derivation. * ATerm, after subderivations have been likewise expunged from that
* derivation.
*/ */
DrvHash hashDerivationModulo(Store & store, const Derivation & drv, bool maskOutputs); DrvHash hashDerivationModulo(Store & store, const Derivation & drv, bool maskOutputs);
/* /**
Return a map associating each output to a hash that uniquely identifies its * Return a map associating each output to a hash that uniquely identifies its
derivation (modulo the self-references). * derivation (modulo the self-references).
*
FIXME: what is the Hash in this map? * \todo What is the Hash in this map?
*/ */
std::map<std::string, Hash> staticOutputHashes(Store & store, const Derivation & drv); std::map<std::string, Hash> staticOutputHashes(Store & store, const Derivation & drv);
/* Memoisation of hashDerivationModulo(). */ /**
* Memoisation of hashDerivationModulo().
*/
typedef std::map<StorePath, DrvHash> DrvHashes; typedef std::map<StorePath, DrvHash> DrvHashes;
// FIXME: global, though at least thread-safe. // FIXME: global, though at least thread-safe.
@ -308,21 +430,25 @@ struct Sink;
Source & readDerivation(Source & in, const Store & store, BasicDerivation & drv, std::string_view name); Source & readDerivation(Source & in, const Store & store, BasicDerivation & drv, std::string_view name);
void writeDerivation(Sink & out, const Store & store, const BasicDerivation & drv); void writeDerivation(Sink & out, const Store & store, const BasicDerivation & drv);
/* This creates an opaque and almost certainly unique string /**
deterministically from the output name. * This creates an opaque and almost certainly unique string
* deterministically from the output name.
It is used as a placeholder to allow derivations to refer to their *
own outputs without needing to use the hash of a derivation in * It is used as a placeholder to allow derivations to refer to their
itself, making the hash near-impossible to calculate. */ * own outputs without needing to use the hash of a derivation in
* itself, making the hash near-impossible to calculate.
*/
std::string hashPlaceholder(const std::string_view outputName); std::string hashPlaceholder(const std::string_view outputName);
/* This creates an opaque and almost certainly unique string /**
deterministically from a derivation path and output name. * This creates an opaque and almost certainly unique string
* deterministically from a derivation path and output name.
It is used as a placeholder to allow derivations to refer to *
content-addressed paths whose content --- and thus the path * It is used as a placeholder to allow derivations to refer to
themselves --- isn't yet known. This occurs when a derivation has a * content-addressed paths whose content --- and thus the path
dependency which is a CA derivation. */ * themselves --- isn't yet known. This occurs when a derivation has a
* dependency which is a CA derivation.
*/
std::string downstreamPlaceholder(const Store & store, const StorePath & drvPath, std::string_view outputName); std::string downstreamPlaceholder(const Store & store, const StorePath & drvPath, std::string_view outputName);
extern const Hash impureOutputHash; extern const Hash impureOutputHash;

View file

@ -105,7 +105,7 @@ using _BuiltPathRaw = std::variant<
>; >;
/** /**
* A built path. Similar to a `DerivedPath`, but enriched with the corresponding * A built path. Similar to a DerivedPath, but enriched with the corresponding
* output path(s). * output path(s).
*/ */
struct BuiltPath : _BuiltPathRaw { struct BuiltPath : _BuiltPathRaw {

View file

@ -9,6 +9,9 @@
namespace nix { namespace nix {
/**
* A non-empty set of outputs, specified by name
*/
struct OutputNames : std::set<std::string> { struct OutputNames : std::set<std::string> {
using std::set<std::string>::set; using std::set<std::string>::set;
@ -18,6 +21,9 @@ struct OutputNames : std::set<std::string> {
: std::set<std::string>(s) : std::set<std::string>(s)
{ assert(!empty()); } { assert(!empty()); }
/**
* Needs to be "inherited manually"
*/
OutputNames(std::set<std::string> && s) OutputNames(std::set<std::string> && s)
: std::set<std::string>(s) : std::set<std::string>(s)
{ assert(!empty()); } { assert(!empty()); }
@ -28,6 +34,9 @@ struct OutputNames : std::set<std::string> {
OutputNames() = delete; OutputNames() = delete;
}; };
/**
* The set of all outputs, without needing to name them explicitly
*/
struct AllOutputs : std::monostate { }; struct AllOutputs : std::monostate { };
typedef std::variant<AllOutputs, OutputNames> _OutputsSpecRaw; typedef std::variant<AllOutputs, OutputNames> _OutputsSpecRaw;
@ -36,7 +45,9 @@ struct OutputsSpec : _OutputsSpecRaw {
using Raw = _OutputsSpecRaw; using Raw = _OutputsSpecRaw;
using Raw::Raw; using Raw::Raw;
/* Force choosing a variant */ /**
* Force choosing a variant
*/
OutputsSpec() = delete; OutputsSpec() = delete;
using Names = OutputNames; using Names = OutputNames;
@ -52,14 +63,20 @@ struct OutputsSpec : _OutputsSpecRaw {
bool contains(const std::string & output) const; bool contains(const std::string & output) const;
/* Create a new OutputsSpec which is the union of this and that. */ /**
* Create a new OutputsSpec which is the union of this and that.
*/
OutputsSpec union_(const OutputsSpec & that) const; OutputsSpec union_(const OutputsSpec & that) const;
/* Whether this OutputsSpec is a subset of that. */ /**
* Whether this OutputsSpec is a subset of that.
*/
bool isSubsetOf(const OutputsSpec & outputs) const; bool isSubsetOf(const OutputsSpec & outputs) const;
/* Parse a string of the form 'output1,...outputN' or /**
'*', returning the outputs spec. */ * Parse a string of the form 'output1,...outputN' or '*', returning
* the outputs spec.
*/
static OutputsSpec parse(std::string_view s); static OutputsSpec parse(std::string_view s);
static std::optional<OutputsSpec> parseOpt(std::string_view s); static std::optional<OutputsSpec> parseOpt(std::string_view s);
@ -81,8 +98,10 @@ struct ExtendedOutputsSpec : _ExtendedOutputsSpecRaw {
return static_cast<const Raw &>(*this); return static_cast<const Raw &>(*this);
} }
/* Parse a string of the form 'prefix^output1,...outputN' or /**
'prefix^*', returning the prefix and the extended outputs spec. */ * Parse a string of the form 'prefix^output1,...outputN' or
* 'prefix^*', returning the prefix and the extended outputs spec.
*/
static std::pair<std::string_view, ExtendedOutputsSpec> parse(std::string_view s); static std::pair<std::string_view, ExtendedOutputsSpec> parse(std::string_view s);
static std::optional<std::pair<std::string_view, ExtendedOutputsSpec>> parseOpt(std::string_view s); static std::optional<std::pair<std::string_view, ExtendedOutputsSpec>> parseOpt(std::string_view s);

View file

@ -8,13 +8,22 @@ namespace nix {
struct Hash; struct Hash;
/**
* \ref StorePath "Store path" is the fundamental reference type of Nix.
* A store paths refers to a Store object.
*
* See glossary.html#gloss-store-path for more information on a
* conceptual level.
*/
class StorePath class StorePath
{ {
std::string baseName; std::string baseName;
public: public:
/* Size of the hash part of store paths, in base-32 characters. */ /**
* Size of the hash part of store paths, in base-32 characters.
*/
constexpr static size_t HashLen = 32; // i.e. 160 bits constexpr static size_t HashLen = 32; // i.e. 160 bits
constexpr static size_t MaxPathLen = 211; constexpr static size_t MaxPathLen = 211;
@ -45,8 +54,9 @@ public:
return baseName != other.baseName; return baseName != other.baseName;
} }
/* Check whether a file name ends with the extension for /**
derivations. */ * Check whether a file name ends with the extension for derivations.
*/
bool isDerivation() const; bool isDerivation() const;
std::string_view name() const std::string_view name() const
@ -67,7 +77,10 @@ public:
typedef std::set<StorePath> StorePathSet; typedef std::set<StorePath> StorePathSet;
typedef std::vector<StorePath> StorePaths; typedef std::vector<StorePath> StorePaths;
/* Extension of derivations in the Nix store. */ /**
* The file extension of \ref Derivation derivations when serialized
* into store objects.
*/
const std::string drvExtension = ".drv"; const std::string drvExtension = ".drv";
} }

View file

@ -55,7 +55,10 @@ namespace nix {
*/ */
MakeError(SubstError, Error); MakeError(SubstError, Error);
MakeError(BuildError, Error); // denotes a permanent build failure /**
* denotes a permanent build failure
*/
MakeError(BuildError, Error);
MakeError(InvalidPath, Error); MakeError(InvalidPath, Error);
MakeError(Unsupported, Error); MakeError(Unsupported, Error);
MakeError(SubstituteGone, Error); MakeError(SubstituteGone, Error);
@ -78,7 +81,9 @@ enum CheckSigsFlag : bool { NoCheckSigs = false, CheckSigs = true };
enum SubstituteFlag : bool { NoSubstitute = false, Substitute = true }; enum SubstituteFlag : bool { NoSubstitute = false, Substitute = true };
enum AllowInvalidFlag : bool { DisallowInvalid = false, AllowInvalid = true }; enum AllowInvalidFlag : bool { DisallowInvalid = false, AllowInvalid = true };
/* Magic header of exportPath() output (obsolete). */ /**
* Magic header of exportPath() output (obsolete).
*/
const uint32_t exportMagic = 0x4558494e; const uint32_t exportMagic = 0x4558494e;
@ -153,17 +158,26 @@ protected:
struct PathInfoCacheValue { struct PathInfoCacheValue {
// Time of cache entry creation or update /**
* Time of cache entry creation or update
*/
std::chrono::time_point<std::chrono::steady_clock> time_point = std::chrono::steady_clock::now(); std::chrono::time_point<std::chrono::steady_clock> time_point = std::chrono::steady_clock::now();
// Null if missing /**
* Null if missing
*/
std::shared_ptr<const ValidPathInfo> value; std::shared_ptr<const ValidPathInfo> value;
// Whether the value is valid as a cache entry. The path may not exist. /**
* Whether the value is valid as a cache entry. The path may not
* exist.
*/
bool isKnownNow(); bool isKnownNow();
// Past tense, because a path can only be assumed to exists when /**
// isKnownNow() && didExist() * Past tense, because a path can only be assumed to exists when
* isKnownNow() && didExist()
*/
inline bool didExist() { inline bool didExist() {
return value != nullptr; return value != nullptr;
} }
@ -197,35 +211,53 @@ public:
std::string printStorePath(const StorePath & path) const; std::string printStorePath(const StorePath & path) const;
// FIXME: remove /**
* Deprecated
*
* \todo remove
*/
StorePathSet parseStorePathSet(const PathSet & paths) const; StorePathSet parseStorePathSet(const PathSet & paths) const;
PathSet printStorePathSet(const StorePathSet & path) const; PathSet printStorePathSet(const StorePathSet & path) const;
/* Display a set of paths in human-readable form (i.e., between quotes /**
and separated by commas). */ * Display a set of paths in human-readable form (i.e., between quotes
* and separated by commas).
*/
std::string showPaths(const StorePathSet & paths); std::string showPaths(const StorePathSet & paths);
/* Return true if path is in the Nix store (but not the Nix /**
store itself). */ * @return true if path is in the Nix store (but not the Nix
* store itself).
*/
bool isInStore(PathView path) const; bool isInStore(PathView path) const;
/* Return true if path is a store path, i.e. a direct child of /**
the Nix store. */ * @return true if path is a store path, i.e. a direct child of the
* Nix store.
*/
bool isStorePath(std::string_view path) const; bool isStorePath(std::string_view path) const;
/* Split a path like /nix/store/<hash>-<name>/<bla> into /**
/nix/store/<hash>-<name> and /<bla>. */ * Split a path like /nix/store/<hash>-<name>/<bla> into
* /nix/store/<hash>-<name> and /<bla>.
*/
std::pair<StorePath, Path> toStorePath(PathView path) const; std::pair<StorePath, Path> toStorePath(PathView path) const;
/* Follow symlinks until we end up with a path in the Nix store. */ /**
* Follow symlinks until we end up with a path in the Nix store.
*/
Path followLinksToStore(std::string_view path) const; Path followLinksToStore(std::string_view path) const;
/* Same as followLinksToStore(), but apply toStorePath() to the /**
result. */ * Same as followLinksToStore(), but apply toStorePath() to the
* result.
*/
StorePath followLinksToStorePath(std::string_view path) const; StorePath followLinksToStorePath(std::string_view path) const;
/* Constructs a unique store path name. */ /**
* Constructs a unique store path name.
*/
StorePath makeStorePath(std::string_view type, StorePath makeStorePath(std::string_view type,
std::string_view hash, std::string_view name) const; std::string_view hash, std::string_view name) const;
StorePath makeStorePath(std::string_view type, StorePath makeStorePath(std::string_view type,
@ -246,33 +278,40 @@ public:
const StorePathSet & references = {}, const StorePathSet & references = {},
bool hasSelfReference = false) const; bool hasSelfReference = false) const;
/* This is the preparatory part of addToStore(); it computes the /**
store path to which srcPath is to be copied. Returns the store * Preparatory part of addToStore().
path and the cryptographic hash of the contents of srcPath. */ *
* @return the store path to which srcPath is to be copied
* and the cryptographic hash of the contents of srcPath.
*/
std::pair<StorePath, Hash> computeStorePathForPath(std::string_view name, std::pair<StorePath, Hash> computeStorePathForPath(std::string_view name,
const Path & srcPath, FileIngestionMethod method = FileIngestionMethod::Recursive, const Path & srcPath, FileIngestionMethod method = FileIngestionMethod::Recursive,
HashType hashAlgo = htSHA256, PathFilter & filter = defaultPathFilter) const; HashType hashAlgo = htSHA256, PathFilter & filter = defaultPathFilter) const;
/* Preparatory part of addTextToStore(). /**
* Preparatory part of addTextToStore().
!!! Computation of the path should take the references given to *
addTextToStore() into account, otherwise we have a (relatively * !!! Computation of the path should take the references given to
minor) security hole: a caller can register a source file with * addTextToStore() into account, otherwise we have a (relatively
bogus references. If there are too many references, the path may * minor) security hole: a caller can register a source file with
not be garbage collected when it has to be (not really a problem, * bogus references. If there are too many references, the path may
the caller could create a root anyway), or it may be garbage * not be garbage collected when it has to be (not really a problem,
collected when it shouldn't be (more serious). * the caller could create a root anyway), or it may be garbage
* collected when it shouldn't be (more serious).
Hashing the references would solve this (bogus references would *
simply yield a different store path, so other users wouldn't be * Hashing the references would solve this (bogus references would
affected), but it has some backwards compatibility issues (the * simply yield a different store path, so other users wouldn't be
hashing scheme changes), so I'm not doing that for now. */ * affected), but it has some backwards compatibility issues (the
* hashing scheme changes), so I'm not doing that for now.
*/
StorePath computeStorePathForText( StorePath computeStorePathForText(
std::string_view name, std::string_view name,
std::string_view s, std::string_view s,
const StorePathSet & references) const; const StorePathSet & references) const;
/* Check whether a path is valid. */ /**
* Check whether a path is valid.
*/
bool isValidPath(const StorePath & path); bool isValidPath(const StorePath & path);
protected: protected:
@ -281,52 +320,67 @@ protected:
public: public:
/* If requested, substitute missing paths. This /**
implements nix-copy-closure's --use-substitutes * If requested, substitute missing paths. This
flag. */ * implements nix-copy-closure's --use-substitutes
* flag.
*/
void substitutePaths(const StorePathSet & paths); void substitutePaths(const StorePathSet & paths);
/* Query which of the given paths is valid. Optionally, try to /**
substitute missing paths. */ * Query which of the given paths is valid. Optionally, try to
* substitute missing paths.
*/
virtual StorePathSet queryValidPaths(const StorePathSet & paths, virtual StorePathSet queryValidPaths(const StorePathSet & paths,
SubstituteFlag maybeSubstitute = NoSubstitute); SubstituteFlag maybeSubstitute = NoSubstitute);
/* Query the set of all valid paths. Note that for some store /**
backends, the name part of store paths may be replaced by 'x' * Query the set of all valid paths. Note that for some store
(i.e. you'll get /nix/store/<hash>-x rather than * backends, the name part of store paths may be replaced by 'x'
/nix/store/<hash>-<name>). Use queryPathInfo() to obtain the * (i.e. you'll get /nix/store/<hash>-x rather than
full store path. FIXME: should return a set of * /nix/store/<hash>-<name>). Use queryPathInfo() to obtain the
std::variant<StorePath, HashPart> to get rid of this hack. */ * full store path. FIXME: should return a set of
* std::variant<StorePath, HashPart> to get rid of this hack.
*/
virtual StorePathSet queryAllValidPaths() virtual StorePathSet queryAllValidPaths()
{ unsupported("queryAllValidPaths"); } { unsupported("queryAllValidPaths"); }
constexpr static const char * MissingName = "x"; constexpr static const char * MissingName = "x";
/* Query information about a valid path. It is permitted to omit /**
the name part of the store path. */ * Query information about a valid path. It is permitted to omit
* the name part of the store path.
*/
ref<const ValidPathInfo> queryPathInfo(const StorePath & path); ref<const ValidPathInfo> queryPathInfo(const StorePath & path);
/* Asynchronous version of queryPathInfo(). */ /**
* Asynchronous version of queryPathInfo().
*/
void queryPathInfo(const StorePath & path, void queryPathInfo(const StorePath & path,
Callback<ref<const ValidPathInfo>> callback) noexcept; Callback<ref<const ValidPathInfo>> callback) noexcept;
/* Query the information about a realisation. */ /**
* Query the information about a realisation.
*/
std::shared_ptr<const Realisation> queryRealisation(const DrvOutput &); std::shared_ptr<const Realisation> queryRealisation(const DrvOutput &);
/* Asynchronous version of queryRealisation(). */ /**
* Asynchronous version of queryRealisation().
*/
void queryRealisation(const DrvOutput &, void queryRealisation(const DrvOutput &,
Callback<std::shared_ptr<const Realisation>> callback) noexcept; Callback<std::shared_ptr<const Realisation>> callback) noexcept;
/* Check whether the given valid path info is sufficiently attested, by /**
either being signed by a trusted public key or content-addressed, in * Check whether the given valid path info is sufficiently attested, by
order to be included in the given store. * either being signed by a trusted public key or content-addressed, in
* order to be included in the given store.
These same checks would be performed in addToStore, but this allows an *
earlier failure in the case where dependencies need to be added too, but * These same checks would be performed in addToStore, but this allows an
the addToStore wouldn't fail until those dependencies are added. Also, * earlier failure in the case where dependencies need to be added too, but
we don't really want to add the dependencies listed in a nar info we * the addToStore wouldn't fail until those dependencies are added. Also,
don't trust anyyways. * we don't really want to add the dependencies listed in a nar info we
* don't trust anyyways.
*/ */
virtual bool pathInfoIsUntrusted(const ValidPathInfo &) virtual bool pathInfoIsUntrusted(const ValidPathInfo &)
{ {
@ -347,53 +401,77 @@ protected:
public: public:
/* Queries the set of incoming FS references for a store path. /**
The result is not cleared. */ * Queries the set of incoming FS references for a store path.
* The result is not cleared.
*/
virtual void queryReferrers(const StorePath & path, StorePathSet & referrers) virtual void queryReferrers(const StorePath & path, StorePathSet & referrers)
{ unsupported("queryReferrers"); } { unsupported("queryReferrers"); }
/* Return all currently valid derivations that have `path' as an /**
output. (Note that the result of `queryDeriver()' is the * @return all currently valid derivations that have `path' as an
derivation that was actually used to produce `path', which may * output.
not exist anymore.) */ *
* (Note that the result of `queryDeriver()' is the derivation that
* was actually used to produce `path', which may not exist
* anymore.)
*/
virtual StorePathSet queryValidDerivers(const StorePath & path) { return {}; }; virtual StorePathSet queryValidDerivers(const StorePath & path) { return {}; };
/* Query the outputs of the derivation denoted by `path'. */ /**
* Query the outputs of the derivation denoted by `path'.
*/
virtual StorePathSet queryDerivationOutputs(const StorePath & path); virtual StorePathSet queryDerivationOutputs(const StorePath & path);
/* Query the mapping outputName => outputPath for the given derivation. All /**
outputs are mentioned so ones mising the mapping are mapped to * Query the mapping outputName => outputPath for the given
`std::nullopt`. */ * derivation. All outputs are mentioned so ones mising the mapping
* are mapped to `std::nullopt`.
*/
virtual std::map<std::string, std::optional<StorePath>> queryPartialDerivationOutputMap(const StorePath & path); virtual std::map<std::string, std::optional<StorePath>> queryPartialDerivationOutputMap(const StorePath & path);
/* Query the mapping outputName=>outputPath for the given derivation. /**
Assume every output has a mapping and throw an exception otherwise. */ * Query the mapping outputName=>outputPath for the given derivation.
* Assume every output has a mapping and throw an exception otherwise.
*/
OutputPathMap queryDerivationOutputMap(const StorePath & path); OutputPathMap queryDerivationOutputMap(const StorePath & path);
/* Query the full store path given the hash part of a valid store /**
path, or empty if the path doesn't exist. */ * Query the full store path given the hash part of a valid store
* path, or empty if the path doesn't exist.
*/
virtual std::optional<StorePath> queryPathFromHashPart(const std::string & hashPart) = 0; virtual std::optional<StorePath> queryPathFromHashPart(const std::string & hashPart) = 0;
/* Query which of the given paths have substitutes. */ /**
* Query which of the given paths have substitutes.
*/
virtual StorePathSet querySubstitutablePaths(const StorePathSet & paths) { return {}; }; virtual StorePathSet querySubstitutablePaths(const StorePathSet & paths) { return {}; };
/* Query substitute info (i.e. references, derivers and download /**
sizes) of a map of paths to their optional ca values. The info * Query substitute info (i.e. references, derivers and download
of the first succeeding substituter for each path will be * sizes) of a map of paths to their optional ca values. The info of
returned. If a path does not have substitute info, it's omitted * the first succeeding substituter for each path will be returned.
from the resulting infos map. */ * If a path does not have substitute info, it's omitted from the
* resulting infos map.
*/
virtual void querySubstitutablePathInfos(const StorePathCAMap & paths, virtual void querySubstitutablePathInfos(const StorePathCAMap & paths,
SubstitutablePathInfos & infos) { return; }; SubstitutablePathInfos & infos) { return; };
/* Import a path into the store. */ /**
* Import a path into the store.
*/
virtual void addToStore(const ValidPathInfo & info, Source & narSource, virtual void addToStore(const ValidPathInfo & info, Source & narSource,
RepairFlag repair = NoRepair, CheckSigsFlag checkSigs = CheckSigs) = 0; RepairFlag repair = NoRepair, CheckSigsFlag checkSigs = CheckSigs) = 0;
// A list of paths infos along with a source providing the content of the /**
// associated store path * A list of paths infos along with a source providing the content
* of the associated store path
*/
using PathsSource = std::vector<std::pair<ValidPathInfo, std::unique_ptr<Source>>>; using PathsSource = std::vector<std::pair<ValidPathInfo, std::unique_ptr<Source>>>;
/* Import multiple paths into the store. */ /**
* Import multiple paths into the store.
*/
virtual void addMultipleToStore( virtual void addMultipleToStore(
Source & source, Source & source,
RepairFlag repair = NoRepair, RepairFlag repair = NoRepair,
@ -405,10 +483,14 @@ public:
RepairFlag repair = NoRepair, RepairFlag repair = NoRepair,
CheckSigsFlag checkSigs = CheckSigs); CheckSigsFlag checkSigs = CheckSigs);
/* Copy the contents of a path to the store and register the /**
validity the resulting path. The resulting path is returned. * Copy the contents of a path to the store and register the
The function object `filter' can be used to exclude files (see * validity the resulting path.
libutil/archive.hh). */ *
* @return The resulting path is returned.
* @param filter This function can be used to exclude files (see
* libutil/archive.hh).
*/
virtual StorePath addToStore( virtual StorePath addToStore(
std::string_view name, std::string_view name,
const Path & srcPath, const Path & srcPath,
@ -418,26 +500,33 @@ public:
RepairFlag repair = NoRepair, RepairFlag repair = NoRepair,
const StorePathSet & references = StorePathSet()); const StorePathSet & references = StorePathSet());
/* Copy the contents of a path to the store and register the /**
validity the resulting path, using a constant amount of * Copy the contents of a path to the store and register the
memory. */ * validity the resulting path, using a constant amount of
* memory.
*/
ValidPathInfo addToStoreSlow(std::string_view name, const Path & srcPath, ValidPathInfo addToStoreSlow(std::string_view name, const Path & srcPath,
FileIngestionMethod method = FileIngestionMethod::Recursive, HashType hashAlgo = htSHA256, FileIngestionMethod method = FileIngestionMethod::Recursive, HashType hashAlgo = htSHA256,
std::optional<Hash> expectedCAHash = {}); std::optional<Hash> expectedCAHash = {});
/* Like addToStore(), but the contents of the path are contained /**
in `dump', which is either a NAR serialisation (if recursive == * Like addToStore(), but the contents of the path are contained
true) or simply the contents of a regular file (if recursive == * in `dump', which is either a NAR serialisation (if recursive ==
false). * true) or simply the contents of a regular file (if recursive ==
`dump` may be drained */ * false).
// FIXME: remove? * `dump` may be drained
*
* \todo remove?
*/
virtual StorePath addToStoreFromDump(Source & dump, std::string_view name, virtual StorePath addToStoreFromDump(Source & dump, std::string_view name,
FileIngestionMethod method = FileIngestionMethod::Recursive, HashType hashAlgo = htSHA256, RepairFlag repair = NoRepair, FileIngestionMethod method = FileIngestionMethod::Recursive, HashType hashAlgo = htSHA256, RepairFlag repair = NoRepair,
const StorePathSet & references = StorePathSet()) const StorePathSet & references = StorePathSet())
{ unsupported("addToStoreFromDump"); } { unsupported("addToStoreFromDump"); }
/* Like addToStore, but the contents written to the output path is /**
a regular file containing the given string. */ * Like addToStore, but the contents written to the output path is a
* regular file containing the given string.
*/
virtual StorePath addTextToStore( virtual StorePath addTextToStore(
std::string_view name, std::string_view name,
std::string_view s, std::string_view s,
@ -458,140 +547,180 @@ public:
virtual void registerDrvOutput(const Realisation & output, CheckSigsFlag checkSigs) virtual void registerDrvOutput(const Realisation & output, CheckSigsFlag checkSigs)
{ return registerDrvOutput(output); } { return registerDrvOutput(output); }
/* Write a NAR dump of a store path. */ /**
* Write a NAR dump of a store path.
*/
virtual void narFromPath(const StorePath & path, Sink & sink) = 0; virtual void narFromPath(const StorePath & path, Sink & sink) = 0;
/* For each path, if it's a derivation, build it. Building a /**
derivation means ensuring that the output paths are valid. If * For each path, if it's a derivation, build it. Building a
they are already valid, this is a no-op. Otherwise, validity * derivation means ensuring that the output paths are valid. If
can be reached in two ways. First, if the output paths is * they are already valid, this is a no-op. Otherwise, validity
substitutable, then build the path that way. Second, the * can be reached in two ways. First, if the output paths is
output paths can be created by running the builder, after * substitutable, then build the path that way. Second, the
recursively building any sub-derivations. For inputs that are * output paths can be created by running the builder, after
not derivations, substitute them. */ * recursively building any sub-derivations. For inputs that are
* not derivations, substitute them.
*/
virtual void buildPaths( virtual void buildPaths(
const std::vector<DerivedPath> & paths, const std::vector<DerivedPath> & paths,
BuildMode buildMode = bmNormal, BuildMode buildMode = bmNormal,
std::shared_ptr<Store> evalStore = nullptr); std::shared_ptr<Store> evalStore = nullptr);
/* Like `buildPaths()`, but return a vector of `BuildResult`s /**
corresponding to each element in `paths`. Note that in case of * Like buildPaths(), but return a vector of \ref BuildResult
a build/substitution error, this function won't throw an * BuildResults corresponding to each element in paths. Note that in
exception, but return a `BuildResult` containing an error * case of a build/substitution error, this function won't throw an
message. */ * exception, but return a BuildResult containing an error message.
*/
virtual std::vector<BuildResult> buildPathsWithResults( virtual std::vector<BuildResult> buildPathsWithResults(
const std::vector<DerivedPath> & paths, const std::vector<DerivedPath> & paths,
BuildMode buildMode = bmNormal, BuildMode buildMode = bmNormal,
std::shared_ptr<Store> evalStore = nullptr); std::shared_ptr<Store> evalStore = nullptr);
/* Build a single non-materialized derivation (i.e. not from an /**
on-disk .drv file). * Build a single non-materialized derivation (i.e. not from an
* on-disk .drv file).
drvPath is used to deduplicate worker goals so it is imperative that *
is correct. That said, it doesn't literally need to be store path that * @param drvPath This is used to deduplicate worker goals so it is
would be calculated from writing this derivation to the store: it is OK * imperative that is correct. That said, it doesn't literally need
if it instead is that of a Derivation which would resolve to this (by * to be store path that would be calculated from writing this
taking the outputs of it's input derivations and adding them as input * derivation to the store: it is OK if it instead is that of a
sources) such that the build time referenceable-paths are the same. * Derivation which would resolve to this (by taking the outputs of
* it's input derivations and adding them as input sources) such
In the input-addressed case, we usually *do* use an "original" * that the build time referenceable-paths are the same.
unresolved derivations's path, as that is what will be used in the *
`buildPaths` case. Also, the input-addressed output paths are verified * In the input-addressed case, we usually *do* use an "original"
only by that contents of that specific unresolved derivation, so it is * unresolved derivations's path, as that is what will be used in the
nice to keep that information around so if the original derivation is * buildPaths case. Also, the input-addressed output paths are verified
ever obtained later, it can be verified whether the trusted user in fact * only by that contents of that specific unresolved derivation, so it is
used the proper output path. * nice to keep that information around so if the original derivation is
* ever obtained later, it can be verified whether the trusted user in fact
In the content-addressed case, we want to always use the * used the proper output path.
resolved drv path calculated from the provided derivation. This serves *
two purposes: * In the content-addressed case, we want to always use the resolved
* drv path calculated from the provided derivation. This serves two
- It keeps the operation trustless, by ruling out a maliciously * purposes:
invalid drv path corresponding to a non-resolution-equivalent *
derivation. * - It keeps the operation trustless, by ruling out a maliciously
* invalid drv path corresponding to a non-resolution-equivalent
- For the floating case in particular, it ensures that the derivation * derivation.
to output mapping respects the resolution equivalence relation, so *
one cannot choose different resolution-equivalent derivations to * - For the floating case in particular, it ensures that the derivation
subvert dependency coherence (i.e. the property that one doesn't end * to output mapping respects the resolution equivalence relation, so
up with multiple different versions of dependencies without * one cannot choose different resolution-equivalent derivations to
explicitly choosing to allow it). * subvert dependency coherence (i.e. the property that one doesn't end
* up with multiple different versions of dependencies without
* explicitly choosing to allow it).
*/ */
virtual BuildResult buildDerivation(const StorePath & drvPath, const BasicDerivation & drv, virtual BuildResult buildDerivation(const StorePath & drvPath, const BasicDerivation & drv,
BuildMode buildMode = bmNormal); BuildMode buildMode = bmNormal);
/* Ensure that a path is valid. If it is not currently valid, it /**
may be made valid by running a substitute (if defined for the * Ensure that a path is valid. If it is not currently valid, it
path). */ * may be made valid by running a substitute (if defined for the
* path).
*/
virtual void ensurePath(const StorePath & path); virtual void ensurePath(const StorePath & path);
/* Add a store path as a temporary root of the garbage collector. /**
The root disappears as soon as we exit. */ * Add a store path as a temporary root of the garbage collector.
* The root disappears as soon as we exit.
*/
virtual void addTempRoot(const StorePath & path) virtual void addTempRoot(const StorePath & path)
{ debug("not creating temporary root, store doesn't support GC"); } { debug("not creating temporary root, store doesn't support GC"); }
/* Return a string representing information about the path that /**
can be loaded into the database using `nix-store --load-db' or * @return a string representing information about the path that
`nix-store --register-validity'. */ * can be loaded into the database using `nix-store --load-db' or
* `nix-store --register-validity'.
*/
std::string makeValidityRegistration(const StorePathSet & paths, std::string makeValidityRegistration(const StorePathSet & paths,
bool showDerivers, bool showHash); bool showDerivers, bool showHash);
/* Write a JSON representation of store path metadata, such as the /**
hash and the references. If includeImpureInfo is true, * Write a JSON representation of store path metadata, such as the
variable elements such as the registration time are * hash and the references.
included. If showClosureSize is true, the closure size of *
each path is included. */ * @param includeImpureInfo If true, variable elements such as the
* registration time are included.
*
* @param showClosureSize If true, the closure size of each path is
* included.
*/
nlohmann::json pathInfoToJSON(const StorePathSet & storePaths, nlohmann::json pathInfoToJSON(const StorePathSet & storePaths,
bool includeImpureInfo, bool showClosureSize, bool includeImpureInfo, bool showClosureSize,
Base hashBase = Base32, Base hashBase = Base32,
AllowInvalidFlag allowInvalid = DisallowInvalid); AllowInvalidFlag allowInvalid = DisallowInvalid);
/* Return the size of the closure of the specified path, that is, /**
the sum of the size of the NAR serialisation of each path in * @return the size of the closure of the specified path, that is,
the closure. */ * the sum of the size of the NAR serialisation of each path in the
* closure.
*/
std::pair<uint64_t, uint64_t> getClosureSize(const StorePath & storePath); std::pair<uint64_t, uint64_t> getClosureSize(const StorePath & storePath);
/* Optimise the disk space usage of the Nix store by hard-linking files /**
with the same contents. */ * Optimise the disk space usage of the Nix store by hard-linking files
* with the same contents.
*/
virtual void optimiseStore() { }; virtual void optimiseStore() { };
/* Check the integrity of the Nix store. Returns true if errors /**
remain. */ * Check the integrity of the Nix store.
*
* @return true if errors remain.
*/
virtual bool verifyStore(bool checkContents, RepairFlag repair = NoRepair) { return false; }; virtual bool verifyStore(bool checkContents, RepairFlag repair = NoRepair) { return false; };
/* Return an object to access files in the Nix store. */ /**
* @return An object to access files in the Nix store.
*/
virtual ref<FSAccessor> getFSAccessor() virtual ref<FSAccessor> getFSAccessor()
{ unsupported("getFSAccessor"); } { unsupported("getFSAccessor"); }
/* Repair the contents of the given path by redownloading it using /**
a substituter (if available). */ * Repair the contents of the given path by redownloading it using
* a substituter (if available).
*/
virtual void repairPath(const StorePath & path) virtual void repairPath(const StorePath & path)
{ unsupported("repairPath"); } { unsupported("repairPath"); }
/* Add signatures to the specified store path. The signatures are /**
not verified. */ * Add signatures to the specified store path. The signatures are
* not verified.
*/
virtual void addSignatures(const StorePath & storePath, const StringSet & sigs) virtual void addSignatures(const StorePath & storePath, const StringSet & sigs)
{ unsupported("addSignatures"); } { unsupported("addSignatures"); }
/* Utility functions. */ /* Utility functions. */
/* Read a derivation, after ensuring its existence through /**
ensurePath(). */ * Read a derivation, after ensuring its existence through
* ensurePath().
*/
Derivation derivationFromPath(const StorePath & drvPath); Derivation derivationFromPath(const StorePath & drvPath);
/* Read a derivation (which must already be valid). */ /**
* Read a derivation (which must already be valid).
*/
Derivation readDerivation(const StorePath & drvPath); Derivation readDerivation(const StorePath & drvPath);
/* Read a derivation from a potentially invalid path. */ /**
* Read a derivation from a potentially invalid path.
*/
Derivation readInvalidDerivation(const StorePath & drvPath); Derivation readInvalidDerivation(const StorePath & drvPath);
/* Place in `out' the set of all store paths in the file system /**
closure of `storePath'; that is, all paths than can be directly * @param [out] out Place in here the set of all store paths in the
or indirectly reached from it. `out' is not cleared. If * file system closure of `storePath'; that is, all paths than can
`flipDirection' is true, the set of paths that can reach * be directly or indirectly reached from it. `out' is not cleared.
`storePath' is returned; that is, the closures under the *
`referrers' relation instead of the `references' relation is * @param flipDirection If true, the set of paths that can reach
returned. */ * `storePath' is returned; that is, the closures under the
* `referrers' relation instead of the `references' relation is
* returned.
*/
virtual void computeFSClosure(const StorePathSet & paths, virtual void computeFSClosure(const StorePathSet & paths,
StorePathSet & out, bool flipDirection = false, StorePathSet & out, bool flipDirection = false,
bool includeOutputs = false, bool includeDerivers = false); bool includeOutputs = false, bool includeDerivers = false);
@ -600,27 +729,34 @@ public:
StorePathSet & out, bool flipDirection = false, StorePathSet & out, bool flipDirection = false,
bool includeOutputs = false, bool includeDerivers = false); bool includeOutputs = false, bool includeDerivers = false);
/* Given a set of paths that are to be built, return the set of /**
derivations that will be built, and the set of output paths * Given a set of paths that are to be built, return the set of
that will be substituted. */ * derivations that will be built, and the set of output paths that
* will be substituted.
*/
virtual void queryMissing(const std::vector<DerivedPath> & targets, virtual void queryMissing(const std::vector<DerivedPath> & targets,
StorePathSet & willBuild, StorePathSet & willSubstitute, StorePathSet & unknown, StorePathSet & willBuild, StorePathSet & willSubstitute, StorePathSet & unknown,
uint64_t & downloadSize, uint64_t & narSize); uint64_t & downloadSize, uint64_t & narSize);
/* Sort a set of paths topologically under the references /**
relation. If p refers to q, then p precedes q in this list. */ * Sort a set of paths topologically under the references
* relation. If p refers to q, then p precedes q in this list.
*/
StorePaths topoSortPaths(const StorePathSet & paths); StorePaths topoSortPaths(const StorePathSet & paths);
/* Export multiple paths in the format expected by nix-store /**
--import. */ * Export multiple paths in the format expected by nix-store
* --import.
*/
void exportPaths(const StorePathSet & paths, Sink & sink); void exportPaths(const StorePathSet & paths, Sink & sink);
void exportPath(const StorePath & path, Sink & sink); void exportPath(const StorePath & path, Sink & sink);
/* Import a sequence of NAR dumps created by exportPaths() into /**
the Nix store. Optionally, the contents of the NARs are * Import a sequence of NAR dumps created by exportPaths() into the
preloaded into the specified FS accessor to speed up subsequent * Nix store. Optionally, the contents of the NARs are preloaded
access. */ * into the specified FS accessor to speed up subsequent access.
*/
StorePaths importPaths(Source & source, CheckSigsFlag checkSigs = CheckSigs); StorePaths importPaths(Source & source, CheckSigsFlag checkSigs = CheckSigs);
struct Stats struct Stats
@ -642,8 +778,9 @@ public:
const Stats & getStats(); const Stats & getStats();
/* Computes the full closure of of a set of store-paths for e.g. /**
derivations that need this information for `exportReferencesGraph`. * Computes the full closure of of a set of store-paths for e.g.
* derivations that need this information for `exportReferencesGraph`.
*/ */
StorePathSet exportReferences(const StorePathSet & storePaths, const StorePathSet & inputPaths); StorePathSet exportReferences(const StorePathSet & storePaths, const StorePathSet & inputPaths);
@ -654,18 +791,24 @@ public:
*/ */
std::optional<StorePath> getBuildDerivationPath(const StorePath &); std::optional<StorePath> getBuildDerivationPath(const StorePath &);
/* Hack to allow long-running processes like hydra-queue-runner to /**
occasionally flush their path info cache. */ * Hack to allow long-running processes like hydra-queue-runner to
* occasionally flush their path info cache.
*/
void clearPathInfoCache() void clearPathInfoCache()
{ {
state.lock()->pathInfoCache.clear(); state.lock()->pathInfoCache.clear();
} }
/* Establish a connection to the store, for store types that have /**
a notion of connection. Otherwise this is a no-op. */ * Establish a connection to the store, for store types that have
* a notion of connection. Otherwise this is a no-op.
*/
virtual void connect() { }; virtual void connect() { };
/* Get the protocol version of this store or it's connection. */ /**
* Get the protocol version of this store or it's connection.
*/
virtual unsigned int getProtocol() virtual unsigned int getProtocol()
{ {
return 0; return 0;
@ -681,7 +824,7 @@ public:
return toRealPath(printStorePath(storePath)); return toRealPath(printStorePath(storePath));
} }
/* /**
* Synchronises the options of the client with those of the daemon * Synchronises the options of the client with those of the daemon
* (a no-op when theres no daemon) * (a no-op when theres no daemon)
*/ */
@ -693,7 +836,13 @@ protected:
Stats stats; Stats stats;
/* Unsupported methods. */ /**
* Helper for methods that are not unsupported: this is used for
* default definitions for virtual methods that are meant to be overriden.
*
* \todo Using this should be a last resort. It is better to make
* the method "virtual pure" and/or move it to a subclass.
*/
[[noreturn]] void unsupported(const std::string & op) [[noreturn]] void unsupported(const std::string & op)
{ {
throw Unsupported("operation '%s' is not supported by store '%s'", op, getUri()); throw Unsupported("operation '%s' is not supported by store '%s'", op, getUri());
@ -702,7 +851,9 @@ protected:
}; };
/* Copy a path from one store to another. */ /**
* Copy a path from one store to another.
*/
void copyStorePath( void copyStorePath(
Store & srcStore, Store & srcStore,
Store & dstStore, Store & dstStore,
@ -711,12 +862,14 @@ void copyStorePath(
CheckSigsFlag checkSigs = CheckSigs); CheckSigsFlag checkSigs = CheckSigs);
/* Copy store paths from one store to another. The paths may be copied /**
in parallel. They are copied in a topologically sorted order (i.e. * Copy store paths from one store to another. The paths may be copied
if A is a reference of B, then A is copied before B), but the set * in parallel. They are copied in a topologically sorted order (i.e. if
of store paths is not automatically closed; use copyClosure() for * A is a reference of B, then A is copied before B), but the set of
that. Returns a map of what each path was copied to the dstStore * store paths is not automatically closed; use copyClosure() for that.
as. */ *
* @return a map of what each path was copied to the dstStore as.
*/
std::map<StorePath, StorePath> copyPaths( std::map<StorePath, StorePath> copyPaths(
Store & srcStore, Store & dstStore, Store & srcStore, Store & dstStore,
const RealisedPath::Set &, const RealisedPath::Set &,
@ -731,7 +884,9 @@ std::map<StorePath, StorePath> copyPaths(
CheckSigsFlag checkSigs = CheckSigs, CheckSigsFlag checkSigs = CheckSigs,
SubstituteFlag substitute = NoSubstitute); SubstituteFlag substitute = NoSubstitute);
/* Copy the closure of `paths` from `srcStore` to `dstStore`. */ /**
* Copy the closure of `paths` from `srcStore` to `dstStore`.
*/
void copyClosure( void copyClosure(
Store & srcStore, Store & dstStore, Store & srcStore, Store & dstStore,
const RealisedPath::Set & paths, const RealisedPath::Set & paths,
@ -746,52 +901,61 @@ void copyClosure(
CheckSigsFlag checkSigs = CheckSigs, CheckSigsFlag checkSigs = CheckSigs,
SubstituteFlag substitute = NoSubstitute); SubstituteFlag substitute = NoSubstitute);
/* Remove the temporary roots file for this process. Any temporary /**
root becomes garbage after this point unless it has been registered * Remove the temporary roots file for this process. Any temporary
as a (permanent) root. */ * root becomes garbage after this point unless it has been registered
* as a (permanent) root.
*/
void removeTempRoots(); void removeTempRoots();
/* Resolve the derived path completely, failing if any derivation output /**
is unknown. */ * Resolve the derived path completely, failing if any derivation output
* is unknown.
*/
OutputPathMap resolveDerivedPath(Store &, const DerivedPath::Built &, Store * evalStore = nullptr); OutputPathMap resolveDerivedPath(Store &, const DerivedPath::Built &, Store * evalStore = nullptr);
/* Return a Store object to access the Nix store denoted by /**
uri (slight misnomer...). Supported values are: * @return a Store object to access the Nix store denoted by
* uri (slight misnomer...).
* local: The Nix store in /nix/store and database in *
/nix/var/nix/db, accessed directly. * @param uri Supported values are:
*
* daemon: The Nix store accessed via a Unix domain socket * - local: The Nix store in /nix/store and database in
connection to nix-daemon. * /nix/var/nix/db, accessed directly.
*
* unix://<path>: The Nix store accessed via a Unix domain socket * - daemon: The Nix store accessed via a Unix domain socket
connection to nix-daemon, with the socket located at <path>. * connection to nix-daemon.
*
* auto or : Equivalent to local or daemon depending on * - unix://<path>: The Nix store accessed via a Unix domain socket
whether the user has write access to the local Nix * connection to nix-daemon, with the socket located at <path>.
store/database. *
* - auto or : Equivalent to local or daemon depending on
* file://<path>: A binary cache stored in <path>. * whether the user has write access to the local Nix
* store/database.
* https://<path>: A binary cache accessed via HTTP. *
* - file://<path>: A binary cache stored in <path>.
* s3://<path>: A writable binary cache stored on Amazon's Simple *
Storage Service. * - https://<path>: A binary cache accessed via HTTP.
*
* ssh://[user@]<host>: A remote Nix store accessed by running * - s3://<path>: A writable binary cache stored on Amazon's Simple
nix-store --serve via SSH. * Storage Service.
*
You can pass parameters to the store implementation by appending * - ssh://[user@]<host>: A remote Nix store accessed by running
?key=value&key=value&... to the URI. * nix-store --serve via SSH.
*/ *
* You can pass parameters to the store implementation by appending
* ?key=value&key=value&... to the URI.
*/
ref<Store> openStore(const std::string & uri = settings.storeUri.get(), ref<Store> openStore(const std::string & uri = settings.storeUri.get(),
const Store::Params & extraParams = Store::Params()); const Store::Params & extraParams = Store::Params());
/* Return the default substituter stores, defined by the /**
substituters option and various legacy options. */ * @return the default substituter stores, defined by the
* substituters option and various legacy options.
*/
std::list<ref<Store>> getDefaultSubstituters(); std::list<ref<Store>> getDefaultSubstituters();
struct StoreFactory struct StoreFactory
@ -834,8 +998,10 @@ struct RegisterStoreImplementation
}; };
/* Display a set of paths in human-readable form (i.e., between quotes /**
and separated by commas). */ * Display a set of paths in human-readable form (i.e., between quotes
* and separated by commas).
*/
std::string showPaths(const PathSet & paths); std::string showPaths(const PathSet & paths);
@ -844,7 +1010,9 @@ std::optional<ValidPathInfo> decodeValidPathInfo(
std::istream & str, std::istream & str,
std::optional<HashResult> hashGiven = std::nullopt); std::optional<HashResult> hashGiven = std::nullopt);
/* Split URI into protocol+hierarchy part and its parameter set. */ /**
* Split URI into protocol+hierarchy part and its parameter set.
*/
std::pair<std::string, Store::Params> splitUriAndParams(const std::string & uri); std::pair<std::string, Store::Params> splitUriAndParams(const std::string & uri);
std::optional<ContentAddress> getDerivationCA(const BasicDerivation & drv); std::optional<ContentAddress> getDerivationCA(const BasicDerivation & drv);