unsafeDiscardReferences

Adds a new boolean structured attribute
`outputChecks.<output>.unsafeDiscardReferences` which disables scanning
an output for runtime references.

    __structuredAttrs = true;
    outputChecks.out.unsafeDiscardReferences = true;

This is useful when creating filesystem images containing their own embedded Nix
store: they are self-contained blobs of data with no runtime dependencies.

Setting this attribute requires the experimental feature
`discard-references` to be enabled.
This commit is contained in:
Naïm Favier 2022-09-23 23:30:29 +02:00
parent 15341334b5
commit 15f7fa59be
No known key found for this signature in database
GPG key ID: 95AFCE8211908325
7 changed files with 58 additions and 7 deletions

View file

@ -212,7 +212,7 @@ Derivations can declare some infrequently used optional attributes.
If this **experimental** attribute is set to true, then the derivation If this **experimental** attribute is set to true, then the derivation
outputs will be stored in a content-addressed location rather than the outputs will be stored in a content-addressed location rather than the
traditional input-addressed one. traditional input-addressed one.
This only has an effect if the `ca-derivation` experimental feature is enabled. This only has an effect if the `ca-derivations` experimental feature is enabled.
Setting this attribute also requires setting `outputHashMode` and `outputHashAlgo` like for *fixed-output derivations* (see above). Setting this attribute also requires setting `outputHashMode` and `outputHashAlgo` like for *fixed-output derivations* (see above).

View file

@ -21,3 +21,15 @@
* Error traces have been reworked to provide detailed explanations and more * Error traces have been reworked to provide detailed explanations and more
accurate error locations. A short excerpt of the trace is now shown by accurate error locations. A short excerpt of the trace is now shown by
default when an error occurs. default when an error occurs.
* In derivations that use structured attributes, you can now use `unsafeDiscardReferences`
to disable scanning a given output for runtime dependencies:
```nix
__structuredAttrs = true;
outputChecks.out.unsafeDiscardReferences = true;
```
This is useful e.g. when generating self-contained filesystem images with
their own embedded Nix store: hashes found inside such an image refer
to the embedded store and not to the host's Nix store.
This requires the `discard-references` experimental feature.

View file

@ -2319,11 +2319,30 @@ DrvOutputs LocalDerivationGoal::registerOutputs()
buildUser ? std::optional(buildUser->getUIDRange()) : std::nullopt, buildUser ? std::optional(buildUser->getUIDRange()) : std::nullopt,
inodesSeen); inodesSeen);
debug("scanning for references for output '%s' in temp location '%s'", outputName, actualPath); bool discardReferences = false;
if (auto structuredAttrs = parsedDrv->getStructuredAttrs()) {
if (auto outputChecks = get(*structuredAttrs, "outputChecks")) {
if (auto output = get(*outputChecks, outputName)) {
if (auto unsafeDiscardReferences = get(*output, "unsafeDiscardReferences")) {
settings.requireExperimentalFeature(Xp::DiscardReferences);
if (!unsafeDiscardReferences->is_boolean())
throw Error("attribute 'outputChecks.\"%s\".unsafeDiscardReferences' of derivation '%s' must be a Boolean", outputName, drvPath.to_string());
discardReferences = unsafeDiscardReferences->get<bool>();
}
}
}
}
/* Pass blank Sink as we are not ready to hash data at this stage. */ StorePathSet references;
NullSink blank; if (discardReferences)
auto references = scanForReferences(blank, actualPath, referenceablePaths); debug("discarding references of output '%s'", outputName);
else {
debug("scanning for references for output '%s' in temp location '%s'", outputName, actualPath);
/* Pass blank Sink as we are not ready to hash data at this stage. */
NullSink blank;
references = scanForReferences(blank, actualPath, referenceablePaths);
}
outputReferencesIfUnregistered.insert_or_assign( outputReferencesIfUnregistered.insert_or_assign(
outputName, outputName,

View file

@ -16,6 +16,7 @@ std::map<ExperimentalFeature, std::string> stringifiedXpFeatures = {
{ Xp::ReplFlake, "repl-flake" }, { Xp::ReplFlake, "repl-flake" },
{ Xp::AutoAllocateUids, "auto-allocate-uids" }, { Xp::AutoAllocateUids, "auto-allocate-uids" },
{ Xp::Cgroups, "cgroups" }, { Xp::Cgroups, "cgroups" },
{ Xp::DiscardReferences, "discard-references" },
}; };
const std::optional<ExperimentalFeature> parseExperimentalFeature(const std::string_view & name) const std::optional<ExperimentalFeature> parseExperimentalFeature(const std::string_view & name)

View file

@ -25,6 +25,7 @@ enum struct ExperimentalFeature
ReplFlake, ReplFlake,
AutoAllocateUids, AutoAllocateUids,
Cgroups, Cgroups,
DiscardReferences,
}; };
/** /**

View file

@ -67,4 +67,13 @@ rec {
disallowedReferences = [test5]; disallowedReferences = [test5];
}; };
test11 = makeTest 11 {
__structuredAttrs = true;
outputChecks.out = {
unsafeDiscardReferences = true;
allowedReferences = [];
};
buildCommand = ''echo ${dep} > "''${outputs[out]}"'';
};
} }

View file

@ -40,3 +40,12 @@ nix-build -o $RESULT check-refs.nix -A test7
# test10 should succeed (no disallowed references). # test10 should succeed (no disallowed references).
nix-build -o $RESULT check-refs.nix -A test10 nix-build -o $RESULT check-refs.nix -A test10
if isDaemonNewer 2.12pre20230103; then
enableFeatures discard-references
restartDaemon
# test11 should succeed.
test11=$(nix-build -o $RESULT check-refs.nix -A test11)
[[ -z $(nix-store -q --references "$test11") ]]
fi