1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-06-28 09:31:16 +02:00

Merge remote-tracking branch 'detsys/detsys-main' into lazy-trees-tmp

This commit is contained in:
Eelco Dolstra 2025-04-23 12:25:28 +02:00
commit a6faa69fc8
109 changed files with 1219 additions and 546 deletions

View file

@ -136,7 +136,10 @@ jobs:
production-branch: detsys-main
github-token: ${{ secrets.GITHUB_TOKEN }}
deploy-message: "Deploy from GitHub Actions"
enable-pull-request-comment: true
# NOTE(cole-h): We have a perpetual PR displaying our changes against upstream open, but
# its conversation is locked, so this PR comment can never be posted.
# https://github.com/DeterminateSystems/nix-src/pull/4
enable-pull-request-comment: ${{ github.event.pull_request.number != 4 }}
enable-commit-comment: true
enable-commit-status: true
overwrites-pull-request-comment: true

View file

@ -1 +1 @@
2.28.1
2.28.2

View file

@ -1 +1 @@
3.2.1
3.3.1

View file

@ -250,7 +250,6 @@ nix3_manpages = [
'nix3-print-dev-env',
'nix3-profile-diff-closures',
'nix3-profile-history',
'nix3-profile-install',
'nix3-profile-list',
'nix3-profile',
'nix3-profile-remove',
@ -283,7 +282,6 @@ nix3_manpages = [
'nix3-store',
'nix3-store-optimise',
'nix3-store-path-from-hash-part',
'nix3-store-ping',
'nix3-store-prefetch-file',
'nix3-store-repair',
'nix3-store-sign',

View file

@ -128,6 +128,7 @@
- [Contributing](development/contributing.md)
- [Determinate Nix Release Notes](release-notes-determinate/index.md)
- [Changes between Nix and Determinate Nix](release-notes-determinate/changes.md)
- [Release 3.3.0 (2025-04-11)](release-notes-determinate/rl-3.3.0.md)
- [Release 3.1.0 (2025-03-27)](release-notes-determinate/rl-3.1.0.md)
- [Release 3.0.0 (2025-03-04)](release-notes-determinate/rl-3.0.0.md)
- [Nix Release Notes](release-notes/index.md)

View file

@ -115,7 +115,7 @@ It creates an [attribute set] representing the string context, which can be insp
## Clearing string contexts
[`buitins.unsafeDiscardStringContext`](./builtins.md#builtins-unsafeDiscardStringContext) will make a copy of a string, but with an empty string context.
[`builtins.unsafeDiscardStringContext`](./builtins.md#builtins-unsafeDiscardStringContext) will make a copy of a string, but with an empty string context.
The returned string can be used in more ways, e.g. by operators that require the string context to be empty.
The requirement to explicitly discard the string context in such use cases helps ensure that string context elements are not lost by mistake.
The "unsafe" marker is only there to remind that Nix normally guarantees that dependencies are tracked, whereas the returned string has lost them.

View file

@ -1,9 +1,11 @@
# Changes between Nix and Determinate Nix
This section lists the differences between upstream Nix 2.24 and Determinate Nix 3.1.0.
This section lists the differences between upstream Nix 2.24 and Determinate Nix 3.3.0.
* In Determinate Nix, flakes are stable. You no longer need to enable the `flakes` experimental feature.
* In Determinate Nix, the new Nix CLI (i.e. the `nix` command) is stable. You no longer need to enable the `nix-command` experimental feature.
* Determinate Nix has a setting [`json-log-path`](@docroot@/command-ref/conf-file.md#conf-json-log-path) to send a copy of all Nix log messages (in JSON format) to a file or Unix domain socket.
* Determinate Nix has made `nix profile install` an alias to `nix profile add`, a more symmetrical antonym of `nix profile remove`.

View file

@ -0,0 +1,5 @@
# Release 3.3.0 (2025-04-11)
* Based on [upstream Nix 2.28.1](../release-notes/rl-2.28.md).
* The `nix profile install` command is now an alias to `nix profile add`, a more symmetrical antonym of `nix profile remove`.

View file

@ -38,6 +38,15 @@
Curl created sockets without setting `FD_CLOEXEC`/`SOCK_CLOEXEC`. This could previously cause connections to remain open forever when using commands like `nix shell`. This change sets the `FD_CLOEXEC` flag using a `CURLOPT_SOCKOPTFUNCTION` callback.
- Add BLAKE3 hash algorithm [#12379](https://github.com/NixOS/nix/pull/12379)
Nix now supports the BLAKE3 hash algorithm as an experimental feature (`blake3-hashes`):
```console
# nix hash file ./file --type blake3 --extra-experimental-features blake3-hashes
blake3-34P4p+iZXcbbyB1i4uoF7eWCGcZHjmaRn6Y7QdynLwU=
```
# Contributors
This release was made possible by the following 21 contributors:

View file

@ -2,6 +2,8 @@
# vim: set filetype=bash:
#!nix shell .#changelog-d --command bash
set -euo pipefail
# --- CONFIGURATION ---
# This does double duty for

View file

@ -237,12 +237,13 @@ void StorePathCommand::run(ref<Store> store, StorePaths && storePaths)
MixProfile::MixProfile()
{
addFlag(
{.longName = "profile",
.description = "The profile to operate on.",
.labels = {"path"},
.handler = {&profile},
.completer = completePath});
addFlag({
.longName = "profile",
.description = "The profile to operate on.",
.labels = {"path"},
.handler = {&profile},
.completer = completePath,
});
}
void MixProfile::updateProfile(const StorePath & storePath)

View file

@ -62,7 +62,7 @@ MixEvalArgs::MixEvalArgs()
.description = "Pass the value *expr* as the argument *name* to Nix functions.",
.category = category,
.labels = {"name", "expr"},
.handler = {[&](std::string name, std::string expr) { autoArgs.insert_or_assign(name, AutoArg{AutoArgExpr{expr}}); }}
.handler = {[&](std::string name, std::string expr) { autoArgs.insert_or_assign(name, AutoArg{AutoArgExpr{expr}}); }},
});
addFlag({
@ -79,7 +79,7 @@ MixEvalArgs::MixEvalArgs()
.category = category,
.labels = {"name", "path"},
.handler = {[&](std::string name, std::string path) { autoArgs.insert_or_assign(name, AutoArg{AutoArgFile{path}}); }},
.completer = completePath
.completer = completePath,
});
addFlag({
@ -104,7 +104,7 @@ MixEvalArgs::MixEvalArgs()
.labels = {"path"},
.handler = {[&](std::string s) {
lookupPath.elements.emplace_back(LookupPath::Elem::parse(s));
}}
}},
});
addFlag({
@ -130,7 +130,7 @@ MixEvalArgs::MixEvalArgs()
}},
.completer = {[&](AddCompletions & completions, size_t, std::string_view prefix) {
completeFlakeRef(completions, openStore(), prefix);
}}
}},
});
addFlag({

View file

@ -64,21 +64,21 @@ MixFlakeOptions::MixFlakeOptions()
.handler = {[&]() {
lockFlags.recreateLockFile = true;
warn("'--recreate-lock-file' is deprecated and will be removed in a future version; use 'nix flake update' instead.");
}}
}},
});
addFlag({
.longName = "no-update-lock-file",
.description = "Do not allow any updates to the flake's lock file.",
.category = category,
.handler = {&lockFlags.updateLockFile, false}
.handler = {&lockFlags.updateLockFile, false},
});
addFlag({
.longName = "no-write-lock-file",
.description = "Do not write the flake's newly generated lock file.",
.category = category,
.handler = {&lockFlags.writeLockFile, false}
.handler = {&lockFlags.writeLockFile, false},
});
addFlag({
@ -94,14 +94,14 @@ MixFlakeOptions::MixFlakeOptions()
.handler = {[&]() {
lockFlags.useRegistries = false;
warn("'--no-registries' is deprecated; use '--no-use-registries'");
}}
}},
});
addFlag({
.longName = "commit-lock-file",
.description = "Commit changes to the flake's lock file.",
.category = category,
.handler = {&lockFlags.commitLockFile, true}
.handler = {&lockFlags.commitLockFile, true},
});
addFlag({
@ -121,7 +121,7 @@ MixFlakeOptions::MixFlakeOptions()
}},
.completer = {[&](AddCompletions & completions, size_t, std::string_view prefix) {
completeFlakeInputAttrPath(completions, getEvalState(), getFlakeRefsForCompletion(), prefix);
}}
}},
});
addFlag({
@ -141,7 +141,7 @@ MixFlakeOptions::MixFlakeOptions()
} else if (n == 1) {
completeFlakeRef(completions, getEvalState()->store, prefix);
}
}}
}},
});
addFlag({
@ -152,7 +152,7 @@ MixFlakeOptions::MixFlakeOptions()
.handler = {[&](std::string lockFilePath) {
lockFlags.referenceLockFilePath = {getFSSourceAccessor(), CanonPath(absPath(lockFilePath))};
}},
.completer = completePath
.completer = completePath,
});
addFlag({
@ -163,7 +163,7 @@ MixFlakeOptions::MixFlakeOptions()
.handler = {[&](std::string lockFilePath) {
lockFlags.outputLockFilePath = lockFilePath;
}},
.completer = completePath
.completer = completePath,
});
addFlag({
@ -190,7 +190,7 @@ MixFlakeOptions::MixFlakeOptions()
}},
.completer = {[&](AddCompletions & completions, size_t, std::string_view prefix) {
completeFlakeRef(completions, getEvalState()->store, prefix);
}}
}},
});
}
@ -206,7 +206,7 @@ SourceExprCommand::SourceExprCommand()
.category = installablesCategory,
.labels = {"file"},
.handler = {&file},
.completer = completePath
.completer = completePath,
});
addFlag({
@ -214,7 +214,7 @@ SourceExprCommand::SourceExprCommand()
.description = "Interpret [*installables*](@docroot@/command-ref/new-cli/nix.md#installables) as attribute paths relative to the Nix expression *expr*.",
.category = installablesCategory,
.labels = {"expr"},
.handler = {&expr}
.handler = {&expr},
});
}
@ -831,7 +831,7 @@ RawInstallablesCommand::RawInstallablesCommand()
addFlag({
.longName = "stdin",
.description = "Read installables from the standard input. No default installable applied.",
.handler = {&readFromStdIn, true}
.handler = {&readFromStdIn, true},
});
expectArgs({
@ -844,7 +844,7 @@ RawInstallablesCommand::RawInstallablesCommand()
void RawInstallablesCommand::applyDefaultInstallables(std::vector<std::string> & rawInstallables)
{
if (rawInstallables.empty()) {
// FIXME: commands like "nix profile install" should not have a
// FIXME: commands like "nix profile add" should not have a
// default, probably.
rawInstallables.push_back(".");
}

View file

@ -20,7 +20,6 @@ headers = [config_pub_h] + files(
'gc-small-vector.hh',
'get-drvs.hh',
'json-to-value.hh',
# internal: 'lexer-helpers.hh',
'nixexpr.hh',
'parser-state.hh',
'primops.hh',

View file

@ -65,7 +65,7 @@ struct DocComment {
struct AttrName
{
Symbol symbol;
Expr * expr;
Expr * expr = nullptr;
AttrName(Symbol s) : symbol(s) {};
AttrName(Expr * e) : expr(e) {};
};
@ -159,7 +159,7 @@ struct ExprVar : Expr
`nullptr`: Not from a `with`.
Valid pointer: the nearest, innermost `with` expression to query first. */
ExprWith * fromWith;
ExprWith * fromWith = nullptr;
/* In the former case, the value is obtained by going `level`
levels up from the current environment and getting the
@ -167,7 +167,7 @@ struct ExprVar : Expr
value is obtained by getting the attribute named `name` from
the set stored in the environment that is `level` levels up
from the current one.*/
Level level;
Level level = 0;
Displacement displ = 0;
ExprVar(Symbol name) : name(name) { };

View file

@ -1,7 +1,4 @@
#include "lexer-tab.hh"
#include "parser-tab.hh"
#include "nix/expr/lexer-helpers.hh"
#include "lexer-helpers.hh"
void nix::lexer::internal::initLoc(YYLTYPE * loc)
{

View file

@ -25,8 +25,7 @@
#endif
#include "nix/expr/nixexpr.hh"
#include "parser-tab.hh"
#include "nix/expr/lexer-helpers.hh"
#include "lexer-helpers.hh"
namespace nix {
struct LexerState;

View file

@ -14,6 +14,7 @@ overrides:
fetchTreeFinal:
let
inherit (builtins) mapAttrs;
lockFile = builtins.fromJSON lockFileStr;
@ -35,19 +36,26 @@ let
(resolveInput lockFile.nodes.${nodeName}.inputs.${builtins.head path})
(builtins.tail path);
allNodes = builtins.mapAttrs (
allNodes = mapAttrs (
key: node:
let
parentNode = allNodes.${getInputByPath lockFile.root node.parent};
flakeDir =
let
dir = overrides.${key}.dir or node.locked.path or "";
parentDir = parentNode.flakeDir;
in
if node ? parent then parentDir + ("/" + dir) else dir;
sourceInfo =
if overrides ? ${key} then
overrides.${key}.sourceInfo
else if node.locked.type == "path" && builtins.substring 0 1 node.locked.path != "/" then
parentNode.sourceInfo
// {
outPath = parentNode.outPath + ("/" + node.locked.path);
outPath = parentNode.sourceInfo.outPath + ("/" + flakeDir);
}
else
# FIXME: remove obsolete node.info.
@ -60,7 +68,7 @@ let
flake = import (outPath + "/flake.nix");
inputs = builtins.mapAttrs (inputName: inputSpec: allNodes.${resolveInput inputSpec}) (
inputs = mapAttrs (inputName: inputSpec: allNodes.${resolveInput inputSpec}.result) (
node.inputs or { }
);
@ -85,12 +93,17 @@ let
};
in
if node.flake or true then
assert builtins.isFunction flake.outputs;
result
else
sourceInfo
{
result =
if node.flake or true then
assert builtins.isFunction flake.outputs;
result
else
sourceInfo;
inherit flakeDir sourceInfo;
}
) lockFile.nodes;
in
allNodes.${lockFile.root}
allNodes.${lockFile.root}.result

View file

@ -57,7 +57,7 @@ MixCommonArgs::MixCommonArgs(const std::string & programName)
if (hasPrefix(s.first, prefix))
completions.add(s.first, fmt("Set the `%s` setting.", s.first));
}
}
},
});
addFlag({
@ -75,7 +75,7 @@ MixCommonArgs::MixCommonArgs(const std::string & programName)
.labels = Strings{"jobs"},
.handler = {[=](std::string s) {
settings.set("max-jobs", s);
}}
}},
});
std::string cat = "Options to override configuration settings";

View file

@ -231,7 +231,7 @@ LegacyArgs::LegacyArgs(const std::string & programName,
.handler = {[=](std::string s) {
auto n = string2IntWithUnitPrefix<uint64_t>(s);
settings.set(dest, std::to_string(n));
}}
}},
});
};

View file

@ -1 +0,0 @@
../../../../tests/functional/derivation/advanced-attributes-defaults.drv

View file

@ -1 +0,0 @@
../../../../tests/functional/derivation/advanced-attributes-structured-attrs-defaults.drv

View file

@ -1 +0,0 @@
../../../../tests/functional/derivation/advanced-attributes-structured-attrs.drv

View file

@ -1,41 +0,0 @@
{
"args": [
"-c",
"echo hello > $out"
],
"builder": "/bin/bash",
"env": {
"__json": "{\"__darwinAllowLocalNetworking\":true,\"__impureHostDeps\":[\"/usr/bin/ditto\"],\"__noChroot\":true,\"__sandboxProfile\":\"sandcastle\",\"allowSubstitutes\":false,\"builder\":\"/bin/bash\",\"impureEnvVars\":[\"UNICORN\"],\"name\":\"advanced-attributes-structured-attrs\",\"outputChecks\":{\"bin\":{\"disallowedReferences\":[\"/nix/store/7rhsm8i393hm1wcsmph782awg1hi2f7x-bar\"],\"disallowedRequisites\":[\"/nix/store/7rhsm8i393hm1wcsmph782awg1hi2f7x-bar\"]},\"dev\":{\"maxClosureSize\":5909,\"maxSize\":789},\"out\":{\"allowedReferences\":[\"/nix/store/3c08bzb71z4wiag719ipjxr277653ynp-foo\"],\"allowedRequisites\":[\"/nix/store/3c08bzb71z4wiag719ipjxr277653ynp-foo\"]}},\"outputs\":[\"out\",\"bin\",\"dev\"],\"preferLocalBuild\":true,\"requiredSystemFeatures\":[\"rainbow\",\"uid-range\"],\"system\":\"my-system\"}",
"bin": "/nix/store/pbzb48v0ycf80jgligcp4n8z0rblna4n-advanced-attributes-structured-attrs-bin",
"dev": "/nix/store/7xapi8jv7flcz1qq8jhw55ar8ag8hldh-advanced-attributes-structured-attrs-dev",
"out": "/nix/store/mpq3l1l1qc2yr50q520g08kprprwv79f-advanced-attributes-structured-attrs"
},
"inputDrvs": {
"/nix/store/4xm4wccqsvagz9gjksn24s7rip2fdy7v-foo.drv": {
"dynamicOutputs": {},
"outputs": [
"out"
]
},
"/nix/store/plsq5jbr5nhgqwcgb2qxw7jchc09dnl8-bar.drv": {
"dynamicOutputs": {},
"outputs": [
"out"
]
}
},
"inputSrcs": [],
"name": "advanced-attributes-structured-attrs",
"outputs": {
"bin": {
"path": "/nix/store/pbzb48v0ycf80jgligcp4n8z0rblna4n-advanced-attributes-structured-attrs-bin"
},
"dev": {
"path": "/nix/store/7xapi8jv7flcz1qq8jhw55ar8ag8hldh-advanced-attributes-structured-attrs-dev"
},
"out": {
"path": "/nix/store/mpq3l1l1qc2yr50q520g08kprprwv79f-advanced-attributes-structured-attrs"
}
},
"system": "my-system"
}

View file

@ -1 +0,0 @@
../../../../tests/functional/derivation/advanced-attributes.drv

View file

@ -0,0 +1 @@
../../../../../tests/functional/derivation/ca/advanced-attributes-defaults.drv

View file

@ -0,0 +1,25 @@
{
"args": [
"-c",
"echo hello > $out"
],
"builder": "/bin/bash",
"env": {
"builder": "/bin/bash",
"name": "advanced-attributes-defaults",
"out": "/1rz4g4znpzjwh1xymhjpm42vipw92pr73vdgl6xs1hycac8kf2n9",
"outputHashAlgo": "sha256",
"outputHashMode": "recursive",
"system": "my-system"
},
"inputDrvs": {},
"inputSrcs": [],
"name": "advanced-attributes-defaults",
"outputs": {
"out": {
"hashAlgo": "sha256",
"method": "nar"
}
},
"system": "my-system"
}

View file

@ -0,0 +1 @@
../../../../../tests/functional/derivation/ca/advanced-attributes-structured-attrs-defaults.drv

View file

@ -0,0 +1,26 @@
{
"args": [
"-c",
"echo hello > $out"
],
"builder": "/bin/bash",
"env": {
"__json": "{\"builder\":\"/bin/bash\",\"name\":\"advanced-attributes-structured-attrs-defaults\",\"outputHashAlgo\":\"sha256\",\"outputHashMode\":\"recursive\",\"outputs\":[\"out\",\"dev\"],\"system\":\"my-system\"}",
"dev": "/02qcpld1y6xhs5gz9bchpxaw0xdhmsp5dv88lh25r2ss44kh8dxz",
"out": "/1rz4g4znpzjwh1xymhjpm42vipw92pr73vdgl6xs1hycac8kf2n9"
},
"inputDrvs": {},
"inputSrcs": [],
"name": "advanced-attributes-structured-attrs-defaults",
"outputs": {
"dev": {
"hashAlgo": "sha256",
"method": "nar"
},
"out": {
"hashAlgo": "sha256",
"method": "nar"
}
},
"system": "my-system"
}

View file

@ -0,0 +1 @@
../../../../../tests/functional/derivation/ca/advanced-attributes-structured-attrs.drv

View file

@ -0,0 +1,46 @@
{
"args": [
"-c",
"echo hello > $out"
],
"builder": "/bin/bash",
"env": {
"__json": "{\"__darwinAllowLocalNetworking\":true,\"__impureHostDeps\":[\"/usr/bin/ditto\"],\"__noChroot\":true,\"__sandboxProfile\":\"sandcastle\",\"allowSubstitutes\":false,\"builder\":\"/bin/bash\",\"impureEnvVars\":[\"UNICORN\"],\"name\":\"advanced-attributes-structured-attrs\",\"outputChecks\":{\"bin\":{\"disallowedReferences\":[\"/0nyw57wm2iicnm9rglvjmbci3ikmcp823czdqdzdcgsnnwqps71g\"],\"disallowedRequisites\":[\"/07f301yqyz8c6wf6bbbavb2q39j4n8kmcly1s09xadyhgy6x2wr8\"]},\"dev\":{\"maxClosureSize\":5909,\"maxSize\":789},\"out\":{\"allowedReferences\":[\"/164j69y6zir9z0339n8pjigg3rckinlr77bxsavzizdaaljb7nh9\"],\"allowedRequisites\":[\"/0nr45p69vn6izw9446wsh9bng9nndhvn19kpsm4n96a5mycw0s4z\"]}},\"outputHashAlgo\":\"sha256\",\"outputHashMode\":\"recursive\",\"outputs\":[\"out\",\"bin\",\"dev\"],\"preferLocalBuild\":true,\"requiredSystemFeatures\":[\"rainbow\",\"uid-range\"],\"system\":\"my-system\"}",
"bin": "/04f3da1kmbr67m3gzxikmsl4vjz5zf777sv6m14ahv22r65aac9m",
"dev": "/02qcpld1y6xhs5gz9bchpxaw0xdhmsp5dv88lh25r2ss44kh8dxz",
"out": "/1rz4g4znpzjwh1xymhjpm42vipw92pr73vdgl6xs1hycac8kf2n9"
},
"inputDrvs": {
"/nix/store/j56sf12rxpcv5swr14vsjn5cwm6bj03h-foo.drv": {
"dynamicOutputs": {},
"outputs": [
"dev",
"out"
]
},
"/nix/store/qnml92yh97a6fbrs2m5qg5cqlc8vni58-bar.drv": {
"dynamicOutputs": {},
"outputs": [
"dev",
"out"
]
}
},
"inputSrcs": [],
"name": "advanced-attributes-structured-attrs",
"outputs": {
"bin": {
"hashAlgo": "sha256",
"method": "nar"
},
"dev": {
"hashAlgo": "sha256",
"method": "nar"
},
"out": {
"hashAlgo": "sha256",
"method": "nar"
}
},
"system": "my-system"
}

View file

@ -0,0 +1 @@
../../../../../tests/functional/derivation/ca/advanced-attributes.drv

View file

@ -0,0 +1,52 @@
{
"args": [
"-c",
"echo hello > $out"
],
"builder": "/bin/bash",
"env": {
"__darwinAllowLocalNetworking": "1",
"__impureHostDeps": "/usr/bin/ditto",
"__noChroot": "1",
"__sandboxProfile": "sandcastle",
"allowSubstitutes": "",
"allowedReferences": "/164j69y6zir9z0339n8pjigg3rckinlr77bxsavzizdaaljb7nh9",
"allowedRequisites": "/0nr45p69vn6izw9446wsh9bng9nndhvn19kpsm4n96a5mycw0s4z",
"builder": "/bin/bash",
"disallowedReferences": "/0nyw57wm2iicnm9rglvjmbci3ikmcp823czdqdzdcgsnnwqps71g",
"disallowedRequisites": "/07f301yqyz8c6wf6bbbavb2q39j4n8kmcly1s09xadyhgy6x2wr8",
"impureEnvVars": "UNICORN",
"name": "advanced-attributes",
"out": "/1rz4g4znpzjwh1xymhjpm42vipw92pr73vdgl6xs1hycac8kf2n9",
"outputHashAlgo": "sha256",
"outputHashMode": "recursive",
"preferLocalBuild": "1",
"requiredSystemFeatures": "rainbow uid-range",
"system": "my-system"
},
"inputDrvs": {
"/nix/store/j56sf12rxpcv5swr14vsjn5cwm6bj03h-foo.drv": {
"dynamicOutputs": {},
"outputs": [
"dev",
"out"
]
},
"/nix/store/qnml92yh97a6fbrs2m5qg5cqlc8vni58-bar.drv": {
"dynamicOutputs": {},
"outputs": [
"dev",
"out"
]
}
},
"inputSrcs": [],
"name": "advanced-attributes",
"outputs": {
"out": {
"hashAlgo": "sha256",
"method": "nar"
}
},
"system": "my-system"
}

View file

@ -0,0 +1 @@
../../../../../tests/functional/derivation/ia/advanced-attributes-defaults.drv

View file

@ -0,0 +1 @@
../../../../../tests/functional/derivation/ia/advanced-attributes-structured-attrs-defaults.drv

View file

@ -0,0 +1 @@
../../../../../tests/functional/derivation/ia/advanced-attributes-structured-attrs.drv

View file

@ -0,0 +1,43 @@
{
"args": [
"-c",
"echo hello > $out"
],
"builder": "/bin/bash",
"env": {
"__json": "{\"__darwinAllowLocalNetworking\":true,\"__impureHostDeps\":[\"/usr/bin/ditto\"],\"__noChroot\":true,\"__sandboxProfile\":\"sandcastle\",\"allowSubstitutes\":false,\"builder\":\"/bin/bash\",\"impureEnvVars\":[\"UNICORN\"],\"name\":\"advanced-attributes-structured-attrs\",\"outputChecks\":{\"bin\":{\"disallowedReferences\":[\"/nix/store/r5cff30838majxk5mp3ip2diffi8vpaj-bar\"],\"disallowedRequisites\":[\"/nix/store/9b61w26b4avv870dw0ymb6rw4r1hzpws-bar-dev\"]},\"dev\":{\"maxClosureSize\":5909,\"maxSize\":789},\"out\":{\"allowedReferences\":[\"/nix/store/p0hax2lzvjpfc2gwkk62xdglz0fcqfzn-foo\"],\"allowedRequisites\":[\"/nix/store/z0rjzy29v9k5qa4nqpykrbzirj7sd43v-foo-dev\"]}},\"outputs\":[\"out\",\"bin\",\"dev\"],\"preferLocalBuild\":true,\"requiredSystemFeatures\":[\"rainbow\",\"uid-range\"],\"system\":\"my-system\"}",
"bin": "/nix/store/qjjj3zrlimpjbkk686m052b3ks9iz2sl-advanced-attributes-structured-attrs-bin",
"dev": "/nix/store/lpz5grl48v93pdadavyg5is1rqvfdipf-advanced-attributes-structured-attrs-dev",
"out": "/nix/store/nzvz1bmh1g89a5dkpqcqan0av7q3hgv3-advanced-attributes-structured-attrs"
},
"inputDrvs": {
"/nix/store/afc3vbjbzql750v2lp8gxgaxsajphzih-foo.drv": {
"dynamicOutputs": {},
"outputs": [
"dev",
"out"
]
},
"/nix/store/vj2i49jm2868j2fmqvxm70vlzmzvgv14-bar.drv": {
"dynamicOutputs": {},
"outputs": [
"dev",
"out"
]
}
},
"inputSrcs": [],
"name": "advanced-attributes-structured-attrs",
"outputs": {
"bin": {
"path": "/nix/store/qjjj3zrlimpjbkk686m052b3ks9iz2sl-advanced-attributes-structured-attrs-bin"
},
"dev": {
"path": "/nix/store/lpz5grl48v93pdadavyg5is1rqvfdipf-advanced-attributes-structured-attrs-dev"
},
"out": {
"path": "/nix/store/nzvz1bmh1g89a5dkpqcqan0av7q3hgv3-advanced-attributes-structured-attrs"
}
},
"system": "my-system"
}

View file

@ -0,0 +1 @@
../../../../../tests/functional/derivation/ia/advanced-attributes.drv

View file

@ -0,0 +1,49 @@
{
"args": [
"-c",
"echo hello > $out"
],
"builder": "/bin/bash",
"env": {
"__darwinAllowLocalNetworking": "1",
"__impureHostDeps": "/usr/bin/ditto",
"__noChroot": "1",
"__sandboxProfile": "sandcastle",
"allowSubstitutes": "",
"allowedReferences": "/nix/store/p0hax2lzvjpfc2gwkk62xdglz0fcqfzn-foo",
"allowedRequisites": "/nix/store/z0rjzy29v9k5qa4nqpykrbzirj7sd43v-foo-dev",
"builder": "/bin/bash",
"disallowedReferences": "/nix/store/r5cff30838majxk5mp3ip2diffi8vpaj-bar",
"disallowedRequisites": "/nix/store/9b61w26b4avv870dw0ymb6rw4r1hzpws-bar-dev",
"impureEnvVars": "UNICORN",
"name": "advanced-attributes",
"out": "/nix/store/swkj0mrq0cq3dfli95v4am0427mi2hxf-advanced-attributes",
"preferLocalBuild": "1",
"requiredSystemFeatures": "rainbow uid-range",
"system": "my-system"
},
"inputDrvs": {
"/nix/store/afc3vbjbzql750v2lp8gxgaxsajphzih-foo.drv": {
"dynamicOutputs": {},
"outputs": [
"dev",
"out"
]
},
"/nix/store/vj2i49jm2868j2fmqvxm70vlzmzvgv14-bar.drv": {
"dynamicOutputs": {},
"outputs": [
"dev",
"out"
]
}
},
"inputSrcs": [],
"name": "advanced-attributes",
"outputs": {
"out": {
"path": "/nix/store/swkj0mrq0cq3dfli95v4am0427mi2hxf-advanced-attributes"
}
},
"system": "my-system"
}

View file

@ -18,68 +18,93 @@ using nlohmann::json;
class DerivationAdvancedAttrsTest : public CharacterizationTest, public LibStoreTest
{
std::filesystem::path unitTestData = getUnitTestData() / "derivation";
protected:
std::filesystem::path unitTestData = getUnitTestData() / "derivation" / "ia";
public:
std::filesystem::path goldenMaster(std::string_view testStem) const override
{
return unitTestData / testStem;
}
/**
* We set these in tests rather than the regular globals so we don't have
* to worry about race conditions if the tests run concurrently.
*/
ExperimentalFeatureSettings mockXpSettings;
};
#define TEST_ATERM_JSON(STEM, NAME) \
TEST_F(DerivationAdvancedAttrsTest, Derivation_##STEM##_from_json) \
{ \
readTest(NAME ".json", [&](const auto & encoded_) { \
auto encoded = json::parse(encoded_); \
/* Use DRV file instead of C++ literal as source of truth. */ \
auto aterm = readFile(goldenMaster(NAME ".drv")); \
auto expected = parseDerivation(*store, std::move(aterm), NAME); \
Derivation got = Derivation::fromJSON(*store, encoded); \
EXPECT_EQ(got, expected); \
}); \
} \
\
TEST_F(DerivationAdvancedAttrsTest, Derivation_##STEM##_to_json) \
{ \
writeTest( \
NAME ".json", \
[&]() -> json { \
/* Use DRV file instead of C++ literal as source of truth. */ \
auto aterm = readFile(goldenMaster(NAME ".drv")); \
return parseDerivation(*store, std::move(aterm), NAME).toJSON(*store); \
}, \
[](const auto & file) { return json::parse(readFile(file)); }, \
[](const auto & file, const auto & got) { return writeFile(file, got.dump(2) + "\n"); }); \
} \
\
TEST_F(DerivationAdvancedAttrsTest, Derivation_##STEM##_from_aterm) \
{ \
readTest(NAME ".drv", [&](auto encoded) { \
/* Use JSON file instead of C++ literal as source of truth. */ \
auto json = json::parse(readFile(goldenMaster(NAME ".json"))); \
auto expected = Derivation::fromJSON(*store, json); \
auto got = parseDerivation(*store, std::move(encoded), NAME); \
EXPECT_EQ(got.toJSON(*store), expected.toJSON(*store)); \
EXPECT_EQ(got, expected); \
}); \
} \
\
class CaDerivationAdvancedAttrsTest : public DerivationAdvancedAttrsTest
{
void SetUp() override
{
unitTestData = getUnitTestData() / "derivation" / "ca";
mockXpSettings.set("experimental-features", "ca-derivations");
}
};
template<class Fixture>
class DerivationAdvancedAttrsBothTest : public Fixture
{};
using BothFixtures = ::testing::Types<DerivationAdvancedAttrsTest, CaDerivationAdvancedAttrsTest>;
TYPED_TEST_SUITE(DerivationAdvancedAttrsBothTest, BothFixtures);
#define TEST_ATERM_JSON(STEM, NAME) \
TYPED_TEST(DerivationAdvancedAttrsBothTest, Derivation_##STEM##_from_json) \
{ \
this->readTest(NAME ".json", [&](const auto & encoded_) { \
auto encoded = json::parse(encoded_); \
/* Use DRV file instead of C++ literal as source of truth. */ \
auto aterm = readFile(this->goldenMaster(NAME ".drv")); \
auto expected = parseDerivation(*this->store, std::move(aterm), NAME, this->mockXpSettings); \
Derivation got = Derivation::fromJSON(*this->store, encoded, this->mockXpSettings); \
EXPECT_EQ(got, expected); \
}); \
} \
\
TYPED_TEST(DerivationAdvancedAttrsBothTest, Derivation_##STEM##_to_json) \
{ \
this->writeTest( \
NAME ".json", \
[&]() -> json { \
/* Use DRV file instead of C++ literal as source of truth. */ \
auto aterm = readFile(this->goldenMaster(NAME ".drv")); \
return parseDerivation(*this->store, std::move(aterm), NAME, this->mockXpSettings) \
.toJSON(*this->store); \
}, \
[](const auto & file) { return json::parse(readFile(file)); }, \
[](const auto & file, const auto & got) { return writeFile(file, got.dump(2) + "\n"); }); \
} \
\
TYPED_TEST(DerivationAdvancedAttrsBothTest, Derivation_##STEM##_from_aterm) \
{ \
this->readTest(NAME ".drv", [&](auto encoded) { \
/* Use JSON file instead of C++ literal as source of truth. */ \
auto json = json::parse(readFile(this->goldenMaster(NAME ".json"))); \
auto expected = Derivation::fromJSON(*this->store, json, this->mockXpSettings); \
auto got = parseDerivation(*this->store, std::move(encoded), NAME, this->mockXpSettings); \
EXPECT_EQ(got.toJSON(*this->store), expected.toJSON(*this->store)); \
EXPECT_EQ(got, expected); \
}); \
} \
\
/* No corresponding write test, because we need to read the drv to write the json file */
TEST_ATERM_JSON(advancedAttributes_defaults, "advanced-attributes-defaults");
TEST_ATERM_JSON(advancedAttributes, "advanced-attributes-defaults");
TEST_ATERM_JSON(advancedAttributes_structuredAttrs_defaults, "advanced-attributes-structured-attrs");
TEST_ATERM_JSON(advancedAttributes_defaults, "advanced-attributes");
TEST_ATERM_JSON(advancedAttributes_structuredAttrs, "advanced-attributes-structured-attrs-defaults");
TEST_ATERM_JSON(advancedAttributes_structuredAttrs_defaults, "advanced-attributes-structured-attrs");
#undef TEST_ATERM_JSON
TEST_F(DerivationAdvancedAttrsTest, Derivation_advancedAttributes_defaults)
TYPED_TEST(DerivationAdvancedAttrsBothTest, advancedAttributes_defaults)
{
readTest("advanced-attributes-defaults.drv", [&](auto encoded) {
auto got = parseDerivation(*store, std::move(encoded), "foo");
this->readTest("advanced-attributes-defaults.drv", [&](auto encoded) {
auto got = parseDerivation(*this->store, std::move(encoded), "foo", this->mockXpSettings);
auto drvPath = writeDerivation(*store, got, NoRepair, true);
auto drvPath = writeDerivation(*this->store, got, NoRepair, true);
ParsedDerivation parsedDrv(drvPath, got);
DerivationOptions options = DerivationOptions::fromParsedDerivation(parsedDrv);
@ -101,25 +126,50 @@ TEST_F(DerivationAdvancedAttrsTest, Derivation_advancedAttributes_defaults)
EXPECT_EQ(checksForAllOutputs.disallowedReferences, StringSet{});
EXPECT_EQ(checksForAllOutputs.disallowedRequisites, StringSet{});
}
EXPECT_EQ(options.getRequiredSystemFeatures(got), StringSet());
EXPECT_EQ(options.canBuildLocally(*store, got), false);
EXPECT_EQ(options.willBuildLocally(*store, got), false);
EXPECT_EQ(options.canBuildLocally(*this->store, got), false);
EXPECT_EQ(options.willBuildLocally(*this->store, got), false);
EXPECT_EQ(options.substitutesAllowed(), true);
EXPECT_EQ(options.useUidRange(got), false);
});
};
TEST_F(DerivationAdvancedAttrsTest, Derivation_advancedAttributes)
TEST_F(DerivationAdvancedAttrsTest, advancedAttributes_defaults)
{
readTest("advanced-attributes.drv", [&](auto encoded) {
auto got = parseDerivation(*store, std::move(encoded), "foo");
this->readTest("advanced-attributes-defaults.drv", [&](auto encoded) {
auto got = parseDerivation(*this->store, std::move(encoded), "foo", this->mockXpSettings);
auto drvPath = writeDerivation(*store, got, NoRepair, true);
auto drvPath = writeDerivation(*this->store, got, NoRepair, true);
ParsedDerivation parsedDrv(drvPath, got);
DerivationOptions options = DerivationOptions::fromParsedDerivation(parsedDrv);
StringSet systemFeatures{"rainbow", "uid-range"};
EXPECT_EQ(options.getRequiredSystemFeatures(got), StringSet{});
});
};
TEST_F(CaDerivationAdvancedAttrsTest, advancedAttributes_defaults)
{
this->readTest("advanced-attributes-defaults.drv", [&](auto encoded) {
auto got = parseDerivation(*this->store, std::move(encoded), "foo", this->mockXpSettings);
auto drvPath = writeDerivation(*this->store, got, NoRepair, true);
ParsedDerivation parsedDrv(drvPath, got);
DerivationOptions options = DerivationOptions::fromParsedDerivation(parsedDrv);
EXPECT_EQ(options.getRequiredSystemFeatures(got), StringSet{"ca-derivations"});
});
};
TYPED_TEST(DerivationAdvancedAttrsBothTest, advancedAttributes)
{
this->readTest("advanced-attributes.drv", [&](auto encoded) {
auto got = parseDerivation(*this->store, std::move(encoded), "foo", this->mockXpSettings);
auto drvPath = writeDerivation(*this->store, got, NoRepair, true);
ParsedDerivation parsedDrv(drvPath, got);
DerivationOptions options = DerivationOptions::fromParsedDerivation(parsedDrv);
EXPECT_TRUE(!parsedDrv.hasStructuredAttrs());
@ -128,34 +178,88 @@ TEST_F(DerivationAdvancedAttrsTest, Derivation_advancedAttributes)
EXPECT_EQ(options.impureHostDeps, StringSet{"/usr/bin/ditto"});
EXPECT_EQ(options.impureEnvVars, StringSet{"UNICORN"});
EXPECT_EQ(options.allowLocalNetworking, true);
EXPECT_EQ(options.canBuildLocally(*this->store, got), false);
EXPECT_EQ(options.willBuildLocally(*this->store, got), false);
EXPECT_EQ(options.substitutesAllowed(), false);
EXPECT_EQ(options.useUidRange(got), true);
});
};
TEST_F(DerivationAdvancedAttrsTest, advancedAttributes)
{
this->readTest("advanced-attributes.drv", [&](auto encoded) {
auto got = parseDerivation(*this->store, std::move(encoded), "foo", this->mockXpSettings);
auto drvPath = writeDerivation(*this->store, got, NoRepair, true);
ParsedDerivation parsedDrv(drvPath, got);
DerivationOptions options = DerivationOptions::fromParsedDerivation(parsedDrv);
{
auto * checksForAllOutputs_ = std::get_if<0>(&options.outputChecks);
ASSERT_TRUE(checksForAllOutputs_ != nullptr);
auto & checksForAllOutputs = *checksForAllOutputs_;
EXPECT_EQ(
checksForAllOutputs.allowedReferences, StringSet{"/nix/store/3c08bzb71z4wiag719ipjxr277653ynp-foo"});
checksForAllOutputs.allowedReferences, StringSet{"/nix/store/p0hax2lzvjpfc2gwkk62xdglz0fcqfzn-foo"});
EXPECT_EQ(
checksForAllOutputs.allowedRequisites, StringSet{"/nix/store/3c08bzb71z4wiag719ipjxr277653ynp-foo"});
checksForAllOutputs.allowedRequisites,
StringSet{"/nix/store/z0rjzy29v9k5qa4nqpykrbzirj7sd43v-foo-dev"});
EXPECT_EQ(
checksForAllOutputs.disallowedReferences, StringSet{"/nix/store/7rhsm8i393hm1wcsmph782awg1hi2f7x-bar"});
checksForAllOutputs.disallowedReferences, StringSet{"/nix/store/r5cff30838majxk5mp3ip2diffi8vpaj-bar"});
EXPECT_EQ(
checksForAllOutputs.disallowedRequisites, StringSet{"/nix/store/7rhsm8i393hm1wcsmph782awg1hi2f7x-bar"});
checksForAllOutputs.disallowedRequisites,
StringSet{"/nix/store/9b61w26b4avv870dw0ymb6rw4r1hzpws-bar-dev"});
}
StringSet systemFeatures{"rainbow", "uid-range"};
EXPECT_EQ(options.getRequiredSystemFeatures(got), systemFeatures);
EXPECT_EQ(options.canBuildLocally(*store, got), false);
EXPECT_EQ(options.willBuildLocally(*store, got), false);
EXPECT_EQ(options.substitutesAllowed(), false);
EXPECT_EQ(options.useUidRange(got), true);
});
};
TEST_F(DerivationAdvancedAttrsTest, Derivation_advancedAttributes_structuredAttrs_defaults)
TEST_F(CaDerivationAdvancedAttrsTest, advancedAttributes)
{
readTest("advanced-attributes-structured-attrs-defaults.drv", [&](auto encoded) {
auto got = parseDerivation(*store, std::move(encoded), "foo");
this->readTest("advanced-attributes.drv", [&](auto encoded) {
auto got = parseDerivation(*this->store, std::move(encoded), "foo", this->mockXpSettings);
auto drvPath = writeDerivation(*store, got, NoRepair, true);
auto drvPath = writeDerivation(*this->store, got, NoRepair, true);
ParsedDerivation parsedDrv(drvPath, got);
DerivationOptions options = DerivationOptions::fromParsedDerivation(parsedDrv);
{
auto * checksForAllOutputs_ = std::get_if<0>(&options.outputChecks);
ASSERT_TRUE(checksForAllOutputs_ != nullptr);
auto & checksForAllOutputs = *checksForAllOutputs_;
EXPECT_EQ(
checksForAllOutputs.allowedReferences,
StringSet{"/164j69y6zir9z0339n8pjigg3rckinlr77bxsavzizdaaljb7nh9"});
EXPECT_EQ(
checksForAllOutputs.allowedRequisites,
StringSet{"/0nr45p69vn6izw9446wsh9bng9nndhvn19kpsm4n96a5mycw0s4z"});
EXPECT_EQ(
checksForAllOutputs.disallowedReferences,
StringSet{"/0nyw57wm2iicnm9rglvjmbci3ikmcp823czdqdzdcgsnnwqps71g"});
EXPECT_EQ(
checksForAllOutputs.disallowedRequisites,
StringSet{"/07f301yqyz8c6wf6bbbavb2q39j4n8kmcly1s09xadyhgy6x2wr8"});
}
StringSet systemFeatures{"rainbow", "uid-range"};
systemFeatures.insert("ca-derivations");
EXPECT_EQ(options.getRequiredSystemFeatures(got), systemFeatures);
});
};
TYPED_TEST(DerivationAdvancedAttrsBothTest, advancedAttributes_structuredAttrs_defaults)
{
this->readTest("advanced-attributes-structured-attrs-defaults.drv", [&](auto encoded) {
auto got = parseDerivation(*this->store, std::move(encoded), "foo", this->mockXpSettings);
auto drvPath = writeDerivation(*this->store, got, NoRepair, true);
ParsedDerivation parsedDrv(drvPath, got);
DerivationOptions options = DerivationOptions::fromParsedDerivation(parsedDrv);
@ -176,25 +280,50 @@ TEST_F(DerivationAdvancedAttrsTest, Derivation_advancedAttributes_structuredAttr
EXPECT_EQ(checksPerOutput.size(), 0);
}
EXPECT_EQ(options.getRequiredSystemFeatures(got), StringSet());
EXPECT_EQ(options.canBuildLocally(*store, got), false);
EXPECT_EQ(options.willBuildLocally(*store, got), false);
EXPECT_EQ(options.canBuildLocally(*this->store, got), false);
EXPECT_EQ(options.willBuildLocally(*this->store, got), false);
EXPECT_EQ(options.substitutesAllowed(), true);
EXPECT_EQ(options.useUidRange(got), false);
});
};
TEST_F(DerivationAdvancedAttrsTest, Derivation_advancedAttributes_structuredAttrs)
TEST_F(DerivationAdvancedAttrsTest, advancedAttributes_structuredAttrs_defaults)
{
readTest("advanced-attributes-structured-attrs.drv", [&](auto encoded) {
auto got = parseDerivation(*store, std::move(encoded), "foo");
this->readTest("advanced-attributes-structured-attrs-defaults.drv", [&](auto encoded) {
auto got = parseDerivation(*this->store, std::move(encoded), "foo", this->mockXpSettings);
auto drvPath = writeDerivation(*store, got, NoRepair, true);
auto drvPath = writeDerivation(*this->store, got, NoRepair, true);
ParsedDerivation parsedDrv(drvPath, got);
DerivationOptions options = DerivationOptions::fromParsedDerivation(parsedDrv);
StringSet systemFeatures{"rainbow", "uid-range"};
EXPECT_EQ(options.getRequiredSystemFeatures(got), StringSet{});
});
};
TEST_F(CaDerivationAdvancedAttrsTest, advancedAttributes_structuredAttrs_defaults)
{
this->readTest("advanced-attributes-structured-attrs-defaults.drv", [&](auto encoded) {
auto got = parseDerivation(*this->store, std::move(encoded), "foo", this->mockXpSettings);
auto drvPath = writeDerivation(*this->store, got, NoRepair, true);
ParsedDerivation parsedDrv(drvPath, got);
DerivationOptions options = DerivationOptions::fromParsedDerivation(parsedDrv);
EXPECT_EQ(options.getRequiredSystemFeatures(got), StringSet{"ca-derivations"});
});
};
TYPED_TEST(DerivationAdvancedAttrsBothTest, advancedAttributes_structuredAttrs)
{
this->readTest("advanced-attributes-structured-attrs.drv", [&](auto encoded) {
auto got = parseDerivation(*this->store, std::move(encoded), "foo", this->mockXpSettings);
auto drvPath = writeDerivation(*this->store, got, NoRepair, true);
ParsedDerivation parsedDrv(drvPath, got);
DerivationOptions options = DerivationOptions::fromParsedDerivation(parsedDrv);
EXPECT_TRUE(parsedDrv.hasStructuredAttrs());
@ -204,14 +333,40 @@ TEST_F(DerivationAdvancedAttrsTest, Derivation_advancedAttributes_structuredAttr
EXPECT_EQ(options.impureEnvVars, StringSet{"UNICORN"});
EXPECT_EQ(options.allowLocalNetworking, true);
{
auto output_ = get(std::get<1>(options.outputChecks), "dev");
ASSERT_TRUE(output_);
auto & output = *output_;
EXPECT_EQ(output.maxSize, 789);
EXPECT_EQ(output.maxClosureSize, 5909);
}
EXPECT_EQ(options.canBuildLocally(*this->store, got), false);
EXPECT_EQ(options.willBuildLocally(*this->store, got), false);
EXPECT_EQ(options.substitutesAllowed(), false);
EXPECT_EQ(options.useUidRange(got), true);
});
};
TEST_F(DerivationAdvancedAttrsTest, advancedAttributes_structuredAttrs)
{
this->readTest("advanced-attributes-structured-attrs.drv", [&](auto encoded) {
auto got = parseDerivation(*this->store, std::move(encoded), "foo", this->mockXpSettings);
auto drvPath = writeDerivation(*this->store, got, NoRepair, true);
ParsedDerivation parsedDrv(drvPath, got);
DerivationOptions options = DerivationOptions::fromParsedDerivation(parsedDrv);
{
{
auto output_ = get(std::get<1>(options.outputChecks), "out");
ASSERT_TRUE(output_);
auto & output = *output_;
EXPECT_EQ(output.allowedReferences, StringSet{"/nix/store/3c08bzb71z4wiag719ipjxr277653ynp-foo"});
EXPECT_EQ(output.allowedRequisites, StringSet{"/nix/store/3c08bzb71z4wiag719ipjxr277653ynp-foo"});
EXPECT_EQ(output.allowedReferences, StringSet{"/nix/store/p0hax2lzvjpfc2gwkk62xdglz0fcqfzn-foo"});
EXPECT_EQ(output.allowedRequisites, StringSet{"/nix/store/z0rjzy29v9k5qa4nqpykrbzirj7sd43v-foo-dev"});
}
{
@ -219,25 +374,54 @@ TEST_F(DerivationAdvancedAttrsTest, Derivation_advancedAttributes_structuredAttr
ASSERT_TRUE(output_);
auto & output = *output_;
EXPECT_EQ(output.disallowedReferences, StringSet{"/nix/store/7rhsm8i393hm1wcsmph782awg1hi2f7x-bar"});
EXPECT_EQ(output.disallowedRequisites, StringSet{"/nix/store/7rhsm8i393hm1wcsmph782awg1hi2f7x-bar"});
}
{
auto output_ = get(std::get<1>(options.outputChecks), "dev");
ASSERT_TRUE(output_);
auto & output = *output_;
EXPECT_EQ(output.maxSize, 789);
EXPECT_EQ(output.maxClosureSize, 5909);
EXPECT_EQ(output.disallowedReferences, StringSet{"/nix/store/r5cff30838majxk5mp3ip2diffi8vpaj-bar"});
EXPECT_EQ(
output.disallowedRequisites, StringSet{"/nix/store/9b61w26b4avv870dw0ymb6rw4r1hzpws-bar-dev"});
}
}
StringSet systemFeatures{"rainbow", "uid-range"};
EXPECT_EQ(options.getRequiredSystemFeatures(got), systemFeatures);
});
};
TEST_F(CaDerivationAdvancedAttrsTest, advancedAttributes_structuredAttrs)
{
this->readTest("advanced-attributes-structured-attrs.drv", [&](auto encoded) {
auto got = parseDerivation(*this->store, std::move(encoded), "foo", this->mockXpSettings);
auto drvPath = writeDerivation(*this->store, got, NoRepair, true);
ParsedDerivation parsedDrv(drvPath, got);
DerivationOptions options = DerivationOptions::fromParsedDerivation(parsedDrv);
{
{
auto output_ = get(std::get<1>(options.outputChecks), "out");
ASSERT_TRUE(output_);
auto & output = *output_;
EXPECT_EQ(output.allowedReferences, StringSet{"/164j69y6zir9z0339n8pjigg3rckinlr77bxsavzizdaaljb7nh9"});
EXPECT_EQ(output.allowedRequisites, StringSet{"/0nr45p69vn6izw9446wsh9bng9nndhvn19kpsm4n96a5mycw0s4z"});
}
{
auto output_ = get(std::get<1>(options.outputChecks), "bin");
ASSERT_TRUE(output_);
auto & output = *output_;
EXPECT_EQ(
output.disallowedReferences, StringSet{"/0nyw57wm2iicnm9rglvjmbci3ikmcp823czdqdzdcgsnnwqps71g"});
EXPECT_EQ(
output.disallowedRequisites, StringSet{"/07f301yqyz8c6wf6bbbavb2q39j4n8kmcly1s09xadyhgy6x2wr8"});
}
}
StringSet systemFeatures{"rainbow", "uid-range"};
systemFeatures.insert("ca-derivations");
EXPECT_EQ(options.getRequiredSystemFeatures(got), systemFeatures);
EXPECT_EQ(options.canBuildLocally(*store, got), false);
EXPECT_EQ(options.willBuildLocally(*store, got), false);
EXPECT_EQ(options.substitutesAllowed(), false);
EXPECT_EQ(options.useUidRange(got), true);
});
};

View file

@ -73,6 +73,32 @@ TEST(machines, getMachinesWithSemicolonSeparator) {
EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, AuthorityMatches("nix@itchy.labs.cs.uu.nl"))));
}
TEST(machines, getMachinesWithCommentsAndSemicolonSeparator) {
auto actual = Machine::parseConfig({},
"# This is a comment ; this is still that comment\n"
"nix@scratchy.labs.cs.uu.nl ; nix@itchy.labs.cs.uu.nl\n"
"# This is also a comment ; this also is still that comment\n"
"nix@scabby.labs.cs.uu.nl\n");
EXPECT_THAT(actual, SizeIs(3));
EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, AuthorityMatches("nix@scratchy.labs.cs.uu.nl"))));
EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, AuthorityMatches("nix@itchy.labs.cs.uu.nl"))));
EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, AuthorityMatches("nix@scabby.labs.cs.uu.nl"))));
}
TEST(machines, getMachinesWithFunnyWhitespace) {
auto actual = Machine::parseConfig({},
" # commment ; comment\n"
" nix@scratchy.labs.cs.uu.nl ; nix@itchy.labs.cs.uu.nl \n"
"\n \n"
"\n ;;; \n"
"\n ; ; \n"
"nix@scabby.labs.cs.uu.nl\n\n");
EXPECT_THAT(actual, SizeIs(3));
EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, AuthorityMatches("nix@scratchy.labs.cs.uu.nl"))));
EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, AuthorityMatches("nix@itchy.labs.cs.uu.nl"))));
EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, AuthorityMatches("nix@scabby.labs.cs.uu.nl"))));
}
TEST(machines, getMachinesWithCorrectCompleteSingleBuilder) {
auto actual = Machine::parseConfig({},
"nix@scratchy.labs.cs.uu.nl i686-linux "

View file

@ -68,7 +68,6 @@ DerivationOptions DerivationOptions::fromParsedDerivation(const ParsedDerivation
throw Error("attribute '%s' must be a list of strings", name);
res.insert(j->get<std::string>());
}
checks.disallowedRequisites = res;
return res;
}
return {};

View file

@ -1368,7 +1368,7 @@ Derivation Derivation::fromJSON(
for (auto & [outputName, output] : getObject(valueAt(json, "outputs"))) {
res.outputs.insert_or_assign(
outputName,
DerivationOutput::fromJSON(store, res.name, outputName, output));
DerivationOutput::fromJSON(store, res.name, outputName, output, xpSettings));
}
} catch (Error & e) {
e.addTrace({}, "while reading key 'outputs'");

View file

@ -22,10 +22,8 @@
#include <curl/curl.h>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <iostream>
#include <queue>
#include <random>
#include <thread>
@ -95,7 +93,7 @@ struct curlFileTransfer : public FileTransfer
: fileTransfer(fileTransfer)
, request(request)
, act(*logger, lvlTalkative, actFileTransfer,
request.post ? "" : fmt(request.data ? "uploading '%s'" : "downloading '%s'", request.uri),
fmt("%sing '%s'", request.verb(), request.uri),
{request.uri}, request.parentAct)
, callback(std::move(callback))
, finalSink([this](std::string_view data) {
@ -272,19 +270,11 @@ struct curlFileTransfer : public FileTransfer
return getInterrupted();
}
int silentProgressCallback(curl_off_t dltotal, curl_off_t dlnow)
{
return getInterrupted();
}
static int progressCallbackWrapper(void * userp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
{
return ((TransferItem *) userp)->progressCallback(dltotal, dlnow);
}
static int silentProgressCallbackWrapper(void * userp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
{
return ((TransferItem *) userp)->silentProgressCallback(dltotal, dlnow);
auto & item = *static_cast<TransferItem *>(userp);
auto isUpload = bool(item.request.data);
return item.progressCallback(isUpload ? ultotal : dltotal, isUpload ? ulnow : dlnow);
}
static int debugCallback(CURL * handle, curl_infotype type, char * data, size_t size, void * userptr)
@ -353,10 +343,7 @@ struct curlFileTransfer : public FileTransfer
curl_easy_setopt(req, CURLOPT_HEADERFUNCTION, TransferItem::headerCallbackWrapper);
curl_easy_setopt(req, CURLOPT_HEADERDATA, this);
if (request.post)
curl_easy_setopt(req, CURLOPT_XFERINFOFUNCTION, silentProgressCallbackWrapper);
else
curl_easy_setopt(req, CURLOPT_XFERINFOFUNCTION, progressCallbackWrapper);
curl_easy_setopt(req, CURLOPT_XFERINFOFUNCTION, progressCallbackWrapper);
curl_easy_setopt(req, CURLOPT_XFERINFODATA, this);
curl_easy_setopt(req, CURLOPT_NOPROGRESS, 0);
@ -449,8 +436,7 @@ struct curlFileTransfer : public FileTransfer
if (httpStatus == 304 && result.etag == "")
result.etag = request.expectedETag;
if (!request.post)
act.progress(result.bodySize, result.bodySize);
act.progress(result.bodySize, result.bodySize);
done = true;
callback(std::move(result));
}
@ -539,6 +525,8 @@ struct curlFileTransfer : public FileTransfer
warn("%s; retrying from offset %d in %d ms", exc.what(), writtenToSink, ms);
else
warn("%s; retrying in %d ms", exc.what(), ms);
decompressionSink.reset();
errorSink.reset();
embargo = std::chrono::steady_clock::now() + std::chrono::milliseconds(ms);
fileTransfer.enqueueItem(shared_from_this());
}
@ -791,10 +779,6 @@ struct curlFileTransfer : public FileTransfer
S3Helper s3Helper(profile, region, scheme, endpoint);
Activity act(*logger, lvlTalkative, actFileTransfer,
fmt("downloading '%s'", request.uri),
{request.uri}, request.parentAct);
// FIXME: implement ETag
auto s3Res = s3Helper.getObject(bucketName, key);
FileTransferResult res;

View file

@ -280,21 +280,21 @@ template<> void BaseSetting<SandboxMode>::convertToArg(Args & args, const std::s
.aliases = aliases,
.description = "Enable sandboxing.",
.category = category,
.handler = {[this]() { override(smEnabled); }}
.handler = {[this]() { override(smEnabled); }},
});
args.addFlag({
.longName = "no-" + name,
.aliases = aliases,
.description = "Disable sandboxing.",
.category = category,
.handler = {[this]() { override(smDisabled); }}
.handler = {[this]() { override(smDisabled); }},
});
args.addFlag({
.longName = "relaxed-" + name,
.aliases = aliases,
.description = "Enable sandboxing, but allow builds to disable it.",
.category = category,
.handler = {[this]() { override(smRelaxed); }}
.handler = {[this]() { override(smRelaxed); }},
});
}

View file

@ -77,7 +77,7 @@ struct FileTransferRequest
FileTransferRequest(std::string_view uri)
: uri(uri), parentAct(getCurActivity()) { }
std::string verb()
std::string verb() const
{
return data ? "upload" : "download";
}

View file

@ -1,6 +1,5 @@
include_dirs += include_directories('../..')
headers += files(
'fchmodat2-compat.hh',
'personality.hh',
)

View file

@ -105,28 +105,31 @@ ref<Store> Machine::openStore() const
static std::vector<std::string> expandBuilderLines(const std::string & builders)
{
std::vector<std::string> result;
for (auto line : tokenizeString<std::vector<std::string>>(builders, "\n;")) {
trim(line);
for (auto line : tokenizeString<std::vector<std::string>>(builders, "\n")) {
line.erase(std::find(line.begin(), line.end(), '#'), line.end());
if (line.empty()) continue;
for (auto entry : tokenizeString<std::vector<std::string>>(line, ";")) {
entry = trim(entry);
if (line[0] == '@') {
const std::string path = trim(std::string(line, 1));
std::string text;
try {
text = readFile(path);
} catch (const SysError & e) {
if (e.errNo != ENOENT)
throw;
debug("cannot find machines file '%s'", path);
if (entry.empty()) {
// skip blank entries
} else if (entry[0] == '@') {
const std::string path = trim(std::string_view{entry}.substr(1));
std::string text;
try {
text = readFile(path);
} catch (const SysError & e) {
if (e.errNo != ENOENT)
throw;
debug("cannot find machines file '%s'", path);
continue;
}
const auto entrys = expandBuilderLines(text);
result.insert(end(result), begin(entrys), end(entrys));
} else {
result.emplace_back(entry);
}
const auto lines = expandBuilderLines(text);
result.insert(end(result), begin(lines), end(lines));
continue;
}
result.emplace_back(line);
}
return result;
}

View file

@ -160,7 +160,10 @@ ref<Aws::Client::ClientConfiguration> S3Helper::makeConfig(
S3Helper::FileTransferResult S3Helper::getObject(
const std::string & bucketName, const std::string & key)
{
debug("fetching 's3://%s/%s'...", bucketName, key);
std::string uri = "s3://" + bucketName + "/" + key;
Activity act(*logger, lvlTalkative, actFileTransfer,
fmt("downloading '%s'", uri),
Logger::Fields{uri}, getCurActivity());
auto request =
Aws::S3::Model::GetObjectRequest()
@ -171,6 +174,22 @@ S3Helper::FileTransferResult S3Helper::getObject(
return Aws::New<std::stringstream>("STRINGSTREAM");
});
size_t bytesDone = 0;
size_t bytesExpected = 0;
request.SetDataReceivedEventHandler([&](const Aws::Http::HttpRequest * req, Aws::Http::HttpResponse * resp, long long l) {
if (!bytesExpected && resp->HasHeader("Content-Length")) {
if (auto length = string2Int<size_t>(resp->GetHeader("Content-Length"))) {
bytesExpected = *length;
}
}
bytesDone += l;
act.progress(bytesDone, bytesExpected);
});
request.SetContinueRequestHandler([](const Aws::Http::HttpRequest*) {
return !isInterrupted();
});
FileTransferResult res;
auto now1 = std::chrono::steady_clock::now();
@ -180,6 +199,8 @@ S3Helper::FileTransferResult S3Helper::getObject(
auto result = checkAws(fmt("AWS error fetching '%s'", key),
client->GetObject(request));
act.progress(result.GetContentLength(), result.GetContentLength());
res.data = decompress(result.GetContentEncoding(),
dynamic_cast<std::stringstream &>(result.GetBody()).str());
@ -307,11 +328,35 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual
std::shared_ptr<TransferManager> transferManager;
std::once_flag transferManagerCreated;
struct AsyncContext : public Aws::Client::AsyncCallerContext
{
mutable std::mutex mutex;
mutable std::condition_variable cv;
const Activity & act;
void notify() const
{
cv.notify_one();
}
void wait() const
{
std::unique_lock<std::mutex> lk(mutex);
cv.wait(lk);
}
AsyncContext(const Activity & act) : act(act) {}
};
void uploadFile(const std::string & path,
std::shared_ptr<std::basic_iostream<char>> istream,
const std::string & mimeType,
const std::string & contentEncoding)
{
std::string uri = "s3://" + bucketName + "/" + path;
Activity act(*logger, lvlTalkative, actFileTransfer,
fmt("uploading '%s'", uri),
Logger::Fields{uri}, getCurActivity());
istream->seekg(0, istream->end);
auto size = istream->tellg();
istream->seekg(0, istream->beg);
@ -330,16 +375,25 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual
transferConfig.bufferSize = bufferSize;
transferConfig.uploadProgressCallback =
[](const TransferManager *transferManager,
const std::shared_ptr<const TransferHandle>
&transferHandle)
[](const TransferManager * transferManager,
const std::shared_ptr<const TransferHandle> & transferHandle)
{
//FIXME: find a way to properly abort the multipart upload.
//checkInterrupt();
debug("upload progress ('%s'): '%d' of '%d' bytes",
transferHandle->GetKey(),
transferHandle->GetBytesTransferred(),
transferHandle->GetBytesTotalSize());
auto context = std::dynamic_pointer_cast<const AsyncContext>(transferHandle->GetContext());
size_t bytesDone = transferHandle->GetBytesTransferred();
size_t bytesTotal = transferHandle->GetBytesTotalSize();
try {
checkInterrupt();
context->act.progress(bytesDone, bytesTotal);
} catch (...) {
context->notify();
}
};
transferConfig.transferStatusUpdatedCallback =
[](const TransferManager * transferManager,
const std::shared_ptr<const TransferHandle> & transferHandle)
{
auto context = std::dynamic_pointer_cast<const AsyncContext>(transferHandle->GetContext());
context->notify();
};
transferManager = TransferManager::Create(transferConfig);
@ -353,29 +407,51 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual
if (contentEncoding != "")
throw Error("setting a content encoding is not supported with S3 multi-part uploads");
auto context = std::make_shared<AsyncContext>(act);
std::shared_ptr<TransferHandle> transferHandle =
transferManager->UploadFile(
istream, bucketName, path, mimeType,
Aws::Map<Aws::String, Aws::String>(),
nullptr /*, contentEncoding */);
context /*, contentEncoding */);
transferHandle->WaitUntilFinished();
TransferStatus status = transferHandle->GetStatus();
while (status == TransferStatus::IN_PROGRESS || status == TransferStatus::NOT_STARTED) {
if (!isInterrupted()) {
context->wait();
} else {
transferHandle->Cancel();
transferHandle->WaitUntilFinished();
}
status = transferHandle->GetStatus();
}
act.progress(transferHandle->GetBytesTransferred(), transferHandle->GetBytesTotalSize());
if (transferHandle->GetStatus() == TransferStatus::FAILED)
if (status == TransferStatus::FAILED)
throw Error("AWS error: failed to upload 's3://%s/%s': %s",
bucketName, path, transferHandle->GetLastError().GetMessage());
if (transferHandle->GetStatus() != TransferStatus::COMPLETED)
if (status != TransferStatus::COMPLETED)
throw Error("AWS error: transfer status of 's3://%s/%s' in unexpected state",
bucketName, path);
} else {
act.progress(0, size);
auto request =
Aws::S3::Model::PutObjectRequest()
.WithBucket(bucketName)
.WithKey(path);
size_t bytesSent = 0;
request.SetDataSentEventHandler([&](const Aws::Http::HttpRequest * req, long long l) {
bytesSent += l;
act.progress(bytesSent, size);
});
request.SetContinueRequestHandler([](const Aws::Http::HttpRequest*) {
return !isInterrupted();
});
request.SetContentType(mimeType);
if (contentEncoding != "")
@ -385,6 +461,8 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual
auto result = checkAws(fmt("AWS error uploading '%s'", path),
s3Helper.client->PutObject(request));
act.progress(size, size);
}
auto now2 = std::chrono::steady_clock::now();

View file

@ -42,7 +42,7 @@
/* Includes required for chroot support. */
#ifdef __linux__
# include "nix/store/fchmodat2-compat.hh"
# include "linux/fchmodat2-compat.hh"
# include <sys/ioctl.h>
# include <net/if.h>
# include <netinet/ip.h>

View file

@ -1,41 +0,0 @@
#pragma once
#include "nix/util/fs-sink.hh"
namespace nix::test {
/**
* A `FileSystemObjectSink` that traces calls, writing to stderr.
*/
class TracingFileSystemObjectSink : public virtual FileSystemObjectSink
{
FileSystemObjectSink & sink;
public:
TracingFileSystemObjectSink(FileSystemObjectSink & sink)
: sink(sink)
{
}
void createDirectory(const CanonPath & path) override;
void createRegularFile(const CanonPath & path, std::function<void(CreateRegularFileSink &)> fn) override;
void createSymlink(const CanonPath & path, const std::string & target) override;
};
/**
* A `ExtendedFileSystemObjectSink` that traces calls, writing to stderr.
*/
class TracingExtendedFileSystemObjectSink : public TracingFileSystemObjectSink, public ExtendedFileSystemObjectSink
{
ExtendedFileSystemObjectSink & sink;
public:
TracingExtendedFileSystemObjectSink(ExtendedFileSystemObjectSink & sink)
: TracingFileSystemObjectSink(sink)
, sink(sink)
{
}
void createHardlink(const CanonPath & path, const CanonPath & target) override;
};
}

View file

@ -1,34 +0,0 @@
#include <iostream>
#include "nix/tracing-file-system-object-sink.hh"
namespace nix::test {
void TracingFileSystemObjectSink::createDirectory(const CanonPath & path)
{
std::cerr << "createDirectory(" << path << ")\n";
sink.createDirectory(path);
}
void TracingFileSystemObjectSink::createRegularFile(
const CanonPath & path, std::function<void(CreateRegularFileSink &)> fn)
{
std::cerr << "createRegularFile(" << path << ")\n";
sink.createRegularFile(path, [&](CreateRegularFileSink & crf) {
// We could wrap this and trace about the chunks of data and such
fn(crf);
});
}
void TracingFileSystemObjectSink::createSymlink(const CanonPath & path, const std::string & target)
{
std::cerr << "createSymlink(" << path << ", target: " << target << ")\n";
sink.createSymlink(path, target);
}
void TracingExtendedFileSystemObjectSink::createHardlink(const CanonPath & path, const CanonPath & target)
{
std::cerr << "createHardlink(" << path << ", target: " << target << ")\n";
sink.createHardlink(path, target);
}
} // namespace nix::test

View file

@ -59,6 +59,7 @@ sources = files(
'json-utils.cc',
'logging.cc',
'lru-cache.cc',
'monitorfdhup.cc',
'nix_api_util.cc',
'pool.cc',
'position.cc',

View file

@ -1,5 +1,5 @@
#include "util.hh"
#include "monitor-fd.hh"
#include "nix/util/util.hh"
#include "nix/util/monitor-fd.hh"
#include <sys/file.h>
#include <gtest/gtest.h>

View file

@ -647,4 +647,25 @@ nlohmann::json MultiCommand::toJSON()
return res;
}
Strings::iterator MultiCommand::rewriteArgs(Strings & args, Strings::iterator pos)
{
if (command)
return command->second->rewriteArgs(args, pos);
if (aliasUsed || pos == args.end()) return pos;
auto arg = *pos;
auto i = aliases.find(arg);
if (i == aliases.end()) return pos;
auto & info = i->second;
if (info.status == AliasStatus::Deprecated) {
warn("'%s' is a deprecated alias for '%s'",
arg, concatStringsSep(" ", info.replacement));
}
pos = args.erase(pos);
for (auto j = info.replacement.rbegin(); j != info.replacement.rend(); ++j)
pos = args.insert(pos, *j);
aliasUsed = true;
return pos;
}
}

View file

@ -393,8 +393,30 @@ public:
nlohmann::json toJSON() override;
enum struct AliasStatus {
/** Aliases that don't go away */
AcceptedShorthand,
/** Aliases that will go away */
Deprecated,
};
/** An alias, except for the original syntax, which is in the map key. */
struct AliasInfo {
AliasStatus status;
std::vector<std::string> replacement;
};
/**
* A list of aliases (remapping a deprecated/shorthand subcommand
* to something else).
*/
std::map<std::string, AliasInfo> aliases;
Strings::iterator rewriteArgs(Strings & args, Strings::iterator pos) override;
protected:
std::string commandName = "";
bool aliasUsed = false;
};
Strings argvToStrings(int argc, char * * argv);

View file

@ -26,6 +26,11 @@ static inline bool getInterrupted();
*/
void setInterruptThrown();
/**
* @note Does nothing on Windows
*/
static inline bool isInterrupted();
/**
* @note Does nothing on Windows
*/

View file

@ -85,17 +85,22 @@ static inline bool getInterrupted()
return unix::_isInterrupted;
}
static inline bool isInterrupted()
{
using namespace unix;
return _isInterrupted || (interruptCheck && interruptCheck());
}
/**
* Throw `Interrupted` exception if the process has been interrupted.
*
* Call this in long-running loops and between slow operations to terminate
* them as needed.
*/
void inline checkInterrupt()
inline void checkInterrupt()
{
using namespace unix;
if (_isInterrupted || (interruptCheck && interruptCheck()))
_interrupted();
if (isInterrupted())
unix::_interrupted();
}
/**

View file

@ -22,7 +22,12 @@ inline void setInterruptThrown()
/* Do nothing for now */
}
void inline checkInterrupt()
static inline bool isInterrupted()
{
/* Do nothing for now */
}
inline void checkInterrupt()
{
/* Do nothing for now */
}

View file

@ -55,7 +55,7 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile
.description = "Use *path* as prefix for the symlinks to the build results. It defaults to `result`.",
.labels = {"path"},
.handler = {&outLink},
.completer = completePath
.completer = completePath,
});
addFlag({

View file

@ -24,7 +24,7 @@ struct CmdBundle : InstallableValueCommand
.handler = {&bundler},
.completer = {[&](AddCompletions & completions, size_t, std::string_view prefix) {
completeFlakeRef(completions, getStore(), prefix);
}}
}},
});
addFlag({
@ -33,7 +33,7 @@ struct CmdBundle : InstallableValueCommand
.description = "Override the name of the symlink to the build result. It defaults to the base name of the app.",
.labels = {"path"},
.handler = {&outLink},
.completer = completePath
.completer = completePath,
});
}

View file

@ -21,7 +21,7 @@ struct CmdCopy : virtual CopyCommand, virtual BuiltPathsCommand, MixProfile
.description = "Create symlinks prefixed with *path* to the top-level store paths fetched from the source store.",
.labels = {"path"},
.handler = {&outLink},
.completer = completePath
.completer = completePath,
});
addFlag({

View file

@ -21,7 +21,7 @@ struct CmdShowDerivation : InstallablesCommand
.longName = "recursive",
.shortName = 'r',
.description = "Include the dependencies of the specified derivations.",
.handler = {&recursive, true}
.handler = {&recursive, true},
});
}

View file

@ -334,7 +334,7 @@ struct Common : InstallableCommand, MixProfile
.labels = {"installable", "outputs-dir"},
.handler = {[&](std::string installable, std::string outputsDir) {
redirects.push_back({installable, outputsDir});
}}
}},
});
}
@ -524,7 +524,7 @@ struct CmdDevelop : Common, MixEnvironment
.handler = {[&](std::vector<std::string> ss) {
if (ss.empty()) throw UsageError("--command requires at least one argument");
command = ss;
}}
}},
});
addFlag({

View file

@ -38,16 +38,17 @@ struct CmdShell : InstallablesCommand, MixEnvironment
CmdShell()
{
addFlag(
{.longName = "command",
.shortName = 'c',
.description = "Command and arguments to be executed, defaulting to `$SHELL`",
.labels = {"command", "args"},
.handler = {[&](std::vector<std::string> ss) {
if (ss.empty())
throw UsageError("--command requires at least one argument");
command = ss;
}}});
addFlag({
.longName = "command",
.shortName = 'c',
.description = "Command and arguments to be executed, defaulting to `$SHELL`",
.labels = {"command", "args"},
.handler = {[&](std::vector<std::string> ss) {
if (ss.empty())
throw UsageError("--command requires at least one argument");
command = ss;
}},
});
}
std::string description() override

View file

@ -90,7 +90,7 @@ public:
.handler={&flakeUrl},
.completer = {[&](AddCompletions & completions, size_t, std::string_view prefix) {
completeFlakeRef(completions, getStore(), prefix);
}}
}},
});
expectArgs({
.label="inputs",
@ -111,7 +111,7 @@ public:
}},
.completer = {[&](AddCompletions & completions, size_t, std::string_view prefix) {
completeFlakeInputAttrPath(completions, getEvalState(), getFlakeRefsForCompletion(), prefix);
}}
}},
});
/* Remove flags that don't make sense. */
@ -342,12 +342,12 @@ struct CmdFlakeCheck : FlakeCommand
addFlag({
.longName = "no-build",
.description = "Do not build checks.",
.handler = {&build, false}
.handler = {&build, false},
});
addFlag({
.longName = "all-systems",
.description = "Check the outputs for all systems.",
.handler = {&checkAllSystems, true}
.handler = {&checkAllSystems, true},
});
}
@ -880,7 +880,7 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand
defaultTemplateAttrPathsPrefixes,
defaultTemplateAttrPaths,
prefix);
}}
}},
});
}
@ -1040,7 +1040,7 @@ struct CmdFlakeClone : FlakeCommand
.shortName = 'f',
.description = "Clone the flake to path *dest*.",
.labels = {"path"},
.handler = {&destDir}
.handler = {&destDir},
});
}
@ -1063,7 +1063,7 @@ struct CmdFlakeArchive : FlakeCommand, MixJSON, MixDryRun
.longName = "to",
.description = "URI of the destination Nix store",
.labels = {"store-uri"},
.handler = {&dstUri}
.handler = {&dstUri},
});
}
@ -1146,12 +1146,12 @@ struct CmdFlakeShow : FlakeCommand, MixJSON
addFlag({
.longName = "legacy",
.description = "Show the contents of the `legacyPackages` output.",
.handler = {&showLegacy, true}
.handler = {&showLegacy, true},
});
addFlag({
.longName = "all-systems",
.description = "Show the contents of outputs for all systems.",
.handler = {&showAllSystems, true}
.handler = {&showAllSystems, true},
});
}
@ -1452,7 +1452,7 @@ struct CmdFlakePrefetch : FlakeCommand, MixJSON
.description = "Create symlink named *path* to the resulting store path.",
.labels = {"path"},
.handler = {&outLink},
.completer = completePath
.completer = completePath,
});
}

View file

@ -51,19 +51,6 @@ void chrootHelper(int argc, char * * argv);
namespace nix {
enum struct AliasStatus {
/** Aliases that don't go away */
AcceptedShorthand,
/** Aliases that will go away */
Deprecated,
};
/** An alias, except for the original syntax, which is in the map key. */
struct AliasInfo {
AliasStatus status;
std::vector<std::string> replacement;
};
/* Check if we have a non-loopback/link-local network interface. */
static bool haveInternet()
{
@ -151,54 +138,34 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs, virtual RootArgs
.category = miscCategory,
.handler = {[&]() { refresh = true; }},
});
}
std::map<std::string, AliasInfo> aliases = {
{"add-to-store", { AliasStatus::Deprecated, {"store", "add-path"}}},
{"cat-nar", { AliasStatus::Deprecated, {"nar", "cat"}}},
{"cat-store", { AliasStatus::Deprecated, {"store", "cat"}}},
{"copy-sigs", { AliasStatus::Deprecated, {"store", "copy-sigs"}}},
{"dev-shell", { AliasStatus::Deprecated, {"develop"}}},
{"diff-closures", { AliasStatus::Deprecated, {"store", "diff-closures"}}},
{"dump-path", { AliasStatus::Deprecated, {"store", "dump-path"}}},
{"hash-file", { AliasStatus::Deprecated, {"hash", "file"}}},
{"hash-path", { AliasStatus::Deprecated, {"hash", "path"}}},
{"ls-nar", { AliasStatus::Deprecated, {"nar", "ls"}}},
{"ls-store", { AliasStatus::Deprecated, {"store", "ls"}}},
{"make-content-addressable", { AliasStatus::Deprecated, {"store", "make-content-addressed"}}},
{"optimise-store", { AliasStatus::Deprecated, {"store", "optimise"}}},
{"ping-store", { AliasStatus::Deprecated, {"store", "info"}}},
{"sign-paths", { AliasStatus::Deprecated, {"store", "sign"}}},
{"shell", { AliasStatus::AcceptedShorthand, {"env", "shell"}}},
{"show-derivation", { AliasStatus::Deprecated, {"derivation", "show"}}},
{"show-config", { AliasStatus::Deprecated, {"config", "show"}}},
{"to-base16", { AliasStatus::Deprecated, {"hash", "to-base16"}}},
{"to-base32", { AliasStatus::Deprecated, {"hash", "to-base32"}}},
{"to-base64", { AliasStatus::Deprecated, {"hash", "to-base64"}}},
{"verify", { AliasStatus::Deprecated, {"store", "verify"}}},
{"doctor", { AliasStatus::Deprecated, {"config", "check"}}},
aliases = {
{"add-to-store", { AliasStatus::Deprecated, {"store", "add-path"}}},
{"cat-nar", { AliasStatus::Deprecated, {"nar", "cat"}}},
{"cat-store", { AliasStatus::Deprecated, {"store", "cat"}}},
{"copy-sigs", { AliasStatus::Deprecated, {"store", "copy-sigs"}}},
{"dev-shell", { AliasStatus::Deprecated, {"develop"}}},
{"diff-closures", { AliasStatus::Deprecated, {"store", "diff-closures"}}},
{"dump-path", { AliasStatus::Deprecated, {"store", "dump-path"}}},
{"hash-file", { AliasStatus::Deprecated, {"hash", "file"}}},
{"hash-path", { AliasStatus::Deprecated, {"hash", "path"}}},
{"ls-nar", { AliasStatus::Deprecated, {"nar", "ls"}}},
{"ls-store", { AliasStatus::Deprecated, {"store", "ls"}}},
{"make-content-addressable", { AliasStatus::Deprecated, {"store", "make-content-addressed"}}},
{"optimise-store", { AliasStatus::Deprecated, {"store", "optimise"}}},
{"ping-store", { AliasStatus::Deprecated, {"store", "info"}}},
{"sign-paths", { AliasStatus::Deprecated, {"store", "sign"}}},
{"shell", { AliasStatus::AcceptedShorthand, {"env", "shell"}}},
{"show-derivation", { AliasStatus::Deprecated, {"derivation", "show"}}},
{"show-config", { AliasStatus::Deprecated, {"config", "show"}}},
{"to-base16", { AliasStatus::Deprecated, {"hash", "to-base16"}}},
{"to-base32", { AliasStatus::Deprecated, {"hash", "to-base32"}}},
{"to-base64", { AliasStatus::Deprecated, {"hash", "to-base64"}}},
{"verify", { AliasStatus::Deprecated, {"store", "verify"}}},
{"doctor", { AliasStatus::Deprecated, {"config", "check"}}},
};
};
bool aliasUsed = false;
Strings::iterator rewriteArgs(Strings & args, Strings::iterator pos) override
{
if (aliasUsed || command || pos == args.end()) return pos;
auto arg = *pos;
auto i = aliases.find(arg);
if (i == aliases.end()) return pos;
auto & info = i->second;
if (info.status == AliasStatus::Deprecated) {
warn("'%s' is a deprecated alias for '%s'",
arg, concatStringsSep(" ", info.replacement));
}
pos = args.erase(pos);
for (auto j = info.replacement.rbegin(); j != info.replacement.rend(); ++j)
pos = args.insert(pos, *j);
aliasUsed = true;
return pos;
}
std::string description() override
{
return "a tool for reproducible and declarative configuration management";

View file

@ -7,7 +7,7 @@ project('nix', 'cpp',
'errorlogs=true', # Please print logs for tests that fail
'localstatedir=/nix/var',
],
meson_version : '>= 1.1',
meson_version : '>= 1.4',
license : 'LGPL-2.1-or-later',
)

View file

@ -275,7 +275,7 @@ struct CmdStorePrefetchFile : StoreCommand, MixJSON
.longName = "name",
.description = "Override the name component of the resulting store path. It defaults to the base name of *url*.",
.labels = {"name"},
.handler = {&name}
.handler = {&name},
});
addFlag({
@ -284,7 +284,7 @@ struct CmdStorePrefetchFile : StoreCommand, MixJSON
.labels = {"hash"},
.handler = {[&](std::string s) {
expectedHash = Hash::parseAny(s, hashAlgo);
}}
}},
});
addFlag(flag::hashAlgo("hash-type", &hashAlgo));

37
src/nix/profile-add.md Normal file
View file

@ -0,0 +1,37 @@
R""(
# Examples
- Add a package from Nixpkgs:
```console
# nix profile add nixpkgs#hello
```
- Add a package from a specific branch of Nixpkgs:
```console
# nix profile add nixpkgs/release-20.09#hello
```
- Add a package from a specific revision of Nixpkgs:
```console
# nix profile add nixpkgs/d73407e8e6002646acfdef0e39ace088bacc83da#hello
```
- Add a specific output of a package:
```console
# nix profile add nixpkgs#bash^man
```
# Description
This command adds [_installables_](./nix.md#installables) to a Nix profile.
> **Note**
>
> `nix profile install` is an alias for `nix profile add` in Determinate Nix.
)""

View file

@ -1,34 +0,0 @@
R""(
# Examples
* Install a package from Nixpkgs:
```console
# nix profile install nixpkgs#hello
```
* Install a package from a specific branch of Nixpkgs:
```console
# nix profile install nixpkgs/release-20.09#hello
```
* Install a package from a specific revision of Nixpkgs:
```console
# nix profile install nixpkgs/d73407e8e6002646acfdef0e39ace088bacc83da#hello
```
* Install a specific output of a package:
```console
# nix profile install nixpkgs#bash^man
```
# Description
This command adds [*installables*](./nix.md#installables) to a Nix profile.
)""

View file

@ -338,14 +338,14 @@ builtPathsPerInstallable(
return res;
}
struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile
struct CmdProfileAdd : InstallablesCommand, MixDefaultProfile
{
std::optional<int64_t> priority;
CmdProfileInstall() {
CmdProfileAdd() {
addFlag({
.longName = "priority",
.description = "The priority of the package to install.",
.description = "The priority of the package to add.",
.labels = {"priority"},
.handler = {&priority},
});
@ -353,13 +353,13 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile
std::string description() override
{
return "install a package into a profile";
return "add a package to a profile";
}
std::string doc() override
{
return
#include "profile-install.md"
#include "profile-add.md"
;
}
@ -415,7 +415,7 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile
&& existingSource->originalRef == elementSource->originalRef
&& existingSource->attrPath == elementSource->attrPath
) {
warn("'%s' is already installed", elementName);
warn("'%s' is already added", elementName);
continue;
}
}
@ -462,15 +462,15 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile
"\n"
" nix profile remove %3%\n"
"\n"
"The new package can also be installed next to the existing one by assigning a different priority.\n"
"The new package can also be added next to the existing one by assigning a different priority.\n"
"The conflicting packages have a priority of %5%.\n"
"To prioritise the new package:\n"
"\n"
" nix profile install %4% --priority %6%\n"
" nix profile add %4% --priority %6%\n"
"\n"
"To prioritise the existing package:\n"
"\n"
" nix profile install %4% --priority %7%\n",
" nix profile add %4% --priority %7%\n",
originalConflictingFilePath,
newConflictingFilePath,
originalEntryName,
@ -708,16 +708,14 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf
if (!element.source) {
warn(
"Found package '%s', but it was not installed from a flake, so it can't be checked for upgrades!",
element.identifier()
);
"Found package '%s', but it was not added from a flake, so it can't be checked for upgrades!",
element.identifier());
continue;
}
if (element.source->originalRef.input.isLocked()) {
warn(
"Found package '%s', but it was installed from a locked flake reference so it can't be upgraded!",
element.identifier()
);
"Found package '%s', but it was added from a locked flake reference so it can't be upgraded!",
element.identifier());
continue;
}
@ -787,7 +785,7 @@ struct CmdProfileList : virtual EvalCommand, virtual StoreCommand, MixDefaultPro
{
std::string description() override
{
return "list installed packages";
return "list packages in the profile";
}
std::string doc() override
@ -978,7 +976,7 @@ struct CmdProfile : NixMultiCommand
: NixMultiCommand(
"profile",
{
{"install", []() { return make_ref<CmdProfileInstall>(); }},
{"add", []() { return make_ref<CmdProfileAdd>(); }},
{"remove", []() { return make_ref<CmdProfileRemove>(); }},
{"upgrade", []() { return make_ref<CmdProfileUpgrade>(); }},
{"list", []() { return make_ref<CmdProfileList>(); }},
@ -987,7 +985,11 @@ struct CmdProfile : NixMultiCommand
{"rollback", []() { return make_ref<CmdProfileRollback>(); }},
{"wipe-history", []() { return make_ref<CmdProfileWipeHistory>(); }},
})
{ }
{
aliases = {
{"install", { AliasStatus::Deprecated, {"add"}}},
};
}
std::string description() override
{

View file

@ -104,7 +104,7 @@ struct CmdSign : StorePathsCommand
.description = "File containing the secret signing key.",
.labels = {"file"},
.handler = {&secretKeyFile},
.completer = completePath
.completer = completePath,
});
}

View file

@ -16,7 +16,7 @@ struct CmdStoreDelete : StorePathsCommand
addFlag({
.longName = "ignore-liveness",
.description = "Do not check whether the paths are reachable from a root.",
.handler = {&options.ignoreLiveness, true}
.handler = {&options.ignoreLiveness, true},
});
}

View file

@ -17,7 +17,7 @@ struct CmdStoreGC : StoreCommand, MixDryRun
.longName = "max",
.description = "Stop after freeing *n* bytes of disk space.",
.labels = {"n"},
.handler = {&options.maxFreed}
.handler = {&options.maxFreed},
});
}

View file

@ -7,7 +7,7 @@
using namespace nix;
struct CmdPingStore : StoreCommand, MixJSON
struct CmdInfoStore : StoreCommand, MixJSON
{
std::string description() override
{
@ -46,15 +46,4 @@ struct CmdPingStore : StoreCommand, MixJSON
}
};
struct CmdInfoStore : CmdPingStore
{
void run(nix::ref<nix::Store> store) override
{
warn("'nix store ping' is a deprecated alias for 'nix store info'");
CmdPingStore::run(store);
}
};
static auto rCmdPingStore = registerCommand2<CmdPingStore>({"store", "info"});
static auto rCmdInfoStore = registerCommand2<CmdInfoStore>({"store", "ping"});
static auto rCmdInfoStore = registerCommand2<CmdInfoStore>({"store", "info"});

View file

@ -5,7 +5,11 @@ using namespace nix;
struct CmdStore : NixMultiCommand
{
CmdStore() : NixMultiCommand("store", RegisterCommand::getCommandsFor({"store"}))
{ }
{
aliases = {
{"ping", { AliasStatus::Deprecated, {"info"}}},
};
}
std::string description() override
{

View file

@ -23,14 +23,14 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand
.shortName = 'p',
.description = "The path to the Nix profile to upgrade.",
.labels = {"profile-dir"},
.handler = {&profileDir}
.handler = {&profileDir},
});
addFlag({
.longName = "nix-store-paths-url",
.description = "The URL of the file that contains the store paths of the latest Nix release.",
.labels = {"url"},
.handler = {&(std::string&) settings.upgradeNixStorePathUrl}
.handler = {&(std::string&) settings.upgradeNixStorePathUrl},
});
}

View file

@ -37,7 +37,7 @@ struct CmdVerify : StorePathsCommand
.shortName = 's',
.description = "Use signatures from the specified store.",
.labels = {"store-uri"},
.handler = {[&](std::string s) { substituterUris.push_back(s); }}
.handler = {[&](std::string s) { substituterUris.push_back(s); }},
});
addFlag({
@ -45,7 +45,7 @@ struct CmdVerify : StorePathsCommand
.shortName = 'n',
.description = "Require that each path is signed by at least *n* different keys.",
.labels = {"n"},
.handler = {&sigsNeeded}
.handler = {&sigsNeeded},
});
}

View file

@ -6,6 +6,6 @@ file=build-hook-ca-floating.nix
enableFeatures "ca-derivations"
CONTENT_ADDRESSED=true
NIX_TESTS_CA_BY_DEFAULT=true
source build-remote.sh

View file

@ -13,7 +13,7 @@ unset NIX_STATE_DIR
function join_by { local d=$1; shift; echo -n "$1"; shift; printf "%s" "${@/#/$d}"; }
EXTRA_SYSTEM_FEATURES=()
if [[ -n "${CONTENT_ADDRESSED-}" ]]; then
if [[ -n "${NIX_TESTS_CA_BY_DEFAULT-}" ]]; then
EXTRA_SYSTEM_FEATURES=("ca-derivations")
fi

View file

@ -0,0 +1,6 @@
#!/usr/bin/env bash
export NIX_TESTS_CA_BY_DEFAULT=1
cd ..
source derivation-advanced-attributes.sh

View file

@ -8,10 +8,11 @@ suites += {
'name': 'ca',
'deps': [],
'tests': [
'build-cache.sh',
'build-with-garbage-path.sh',
'build.sh',
'build-cache.sh',
'concurrent-builds.sh',
'derivation-advanced-attributes.sh',
'derivation-json.sh',
'duplicate-realisation-in-closure.sh',
'eval-store.sh',

View file

@ -2,6 +2,6 @@
source common.sh
CONTENT_ADDRESSED=true
NIX_TESTS_CA_BY_DEFAULT=true
cd ..
source ./nix-shell.sh

View file

@ -12,11 +12,19 @@ badExitCode=0
store="$TEST_ROOT/store"
if [[ -z "${NIX_TESTS_CA_BY_DEFAULT:-}" ]]; then
drvDir=ia
flags=(--arg contentAddress false)
else
drvDir=ca
flags=(--arg contentAddress true --extra-experimental-features ca-derivations)
fi
for nixFile in derivation/*.nix; do
drvPath=$(env -u NIX_STORE nix-instantiate --store "$store" --pure-eval --expr "$(< "$nixFile")")
drvPath=$(env -u NIX_STORE nix-instantiate --store "$store" --pure-eval "${flags[@]}" --expr "$(< "$nixFile")")
testName=$(basename "$nixFile" .nix)
got="${store}${drvPath}"
expected="derivation/$testName.drv"
expected="derivation/${drvDir}/${testName}.drv"
diffAndAcceptInner "$testName" "$got" "$expected"
done

View file

@ -1,6 +1,24 @@
derivation {
name = "advanced-attributes-defaults";
{ contentAddress }:
let
caArgs =
if contentAddress then
{
__contentAddressed = true;
outputHashMode = "recursive";
outputHashAlgo = "sha256";
}
else
{ };
derivation' = args: derivation (caArgs // args);
system = "my-system";
in
derivation' {
inherit system;
name = "advanced-attributes-defaults";
builder = "/bin/bash";
args = [
"-c"

View file

@ -1,6 +1,24 @@
derivation {
name = "advanced-attributes-structured-attrs-defaults";
{ contentAddress }:
let
caArgs =
if contentAddress then
{
__contentAddressed = true;
outputHashMode = "recursive";
outputHashAlgo = "sha256";
}
else
{ };
derivation' = args: derivation (caArgs // args);
system = "my-system";
in
derivation' {
inherit system;
name = "advanced-attributes-structured-attrs-defaults";
builder = "/bin/bash";
args = [
"-c"

View file

@ -1 +0,0 @@
Derive([("bin","/nix/store/pbzb48v0ycf80jgligcp4n8z0rblna4n-advanced-attributes-structured-attrs-bin","",""),("dev","/nix/store/7xapi8jv7flcz1qq8jhw55ar8ag8hldh-advanced-attributes-structured-attrs-dev","",""),("out","/nix/store/mpq3l1l1qc2yr50q520g08kprprwv79f-advanced-attributes-structured-attrs","","")],[("/nix/store/4xm4wccqsvagz9gjksn24s7rip2fdy7v-foo.drv",["out"]),("/nix/store/plsq5jbr5nhgqwcgb2qxw7jchc09dnl8-bar.drv",["out"])],[],"my-system","/bin/bash",["-c","echo hello > $out"],[("__json","{\"__darwinAllowLocalNetworking\":true,\"__impureHostDeps\":[\"/usr/bin/ditto\"],\"__noChroot\":true,\"__sandboxProfile\":\"sandcastle\",\"allowSubstitutes\":false,\"builder\":\"/bin/bash\",\"impureEnvVars\":[\"UNICORN\"],\"name\":\"advanced-attributes-structured-attrs\",\"outputChecks\":{\"bin\":{\"disallowedReferences\":[\"/nix/store/7rhsm8i393hm1wcsmph782awg1hi2f7x-bar\"],\"disallowedRequisites\":[\"/nix/store/7rhsm8i393hm1wcsmph782awg1hi2f7x-bar\"]},\"dev\":{\"maxClosureSize\":5909,\"maxSize\":789},\"out\":{\"allowedReferences\":[\"/nix/store/3c08bzb71z4wiag719ipjxr277653ynp-foo\"],\"allowedRequisites\":[\"/nix/store/3c08bzb71z4wiag719ipjxr277653ynp-foo\"]}},\"outputs\":[\"out\",\"bin\",\"dev\"],\"preferLocalBuild\":true,\"requiredSystemFeatures\":[\"rainbow\",\"uid-range\"],\"system\":\"my-system\"}"),("bin","/nix/store/pbzb48v0ycf80jgligcp4n8z0rblna4n-advanced-attributes-structured-attrs-bin"),("dev","/nix/store/7xapi8jv7flcz1qq8jhw55ar8ag8hldh-advanced-attributes-structured-attrs-dev"),("out","/nix/store/mpq3l1l1qc2yr50q520g08kprprwv79f-advanced-attributes-structured-attrs")])

View file

@ -1,6 +1,21 @@
{ contentAddress }:
let
caArgs =
if contentAddress then
{
__contentAddressed = true;
outputHashMode = "recursive";
outputHashAlgo = "sha256";
}
else
{ };
derivation' = args: derivation (caArgs // args);
system = "my-system";
foo = derivation {
foo = derivation' {
inherit system;
name = "foo";
builder = "/bin/bash";
@ -8,8 +23,13 @@ let
"-c"
"echo foo > $out"
];
outputs = [
"out"
"dev"
];
};
bar = derivation {
bar = derivation' {
inherit system;
name = "bar";
builder = "/bin/bash";
@ -17,9 +37,14 @@ let
"-c"
"echo bar > $out"
];
outputs = [
"out"
"dev"
];
};
in
derivation {
derivation' {
inherit system;
name = "advanced-attributes-structured-attrs";
builder = "/bin/bash";
@ -41,11 +66,11 @@ derivation {
outputChecks = {
out = {
allowedReferences = [ foo ];
allowedRequisites = [ foo ];
allowedRequisites = [ foo.dev ];
};
bin = {
disallowedReferences = [ bar ];
disallowedRequisites = [ bar ];
disallowedRequisites = [ bar.dev ];
};
dev = {
maxSize = 789;

View file

@ -1 +0,0 @@
Derive([("out","/nix/store/33a6fdmn8q9ih9d7npbnrxn2q56a4l8q-advanced-attributes","","")],[("/nix/store/4xm4wccqsvagz9gjksn24s7rip2fdy7v-foo.drv",["out"]),("/nix/store/plsq5jbr5nhgqwcgb2qxw7jchc09dnl8-bar.drv",["out"])],[],"my-system","/bin/bash",["-c","echo hello > $out"],[("__darwinAllowLocalNetworking","1"),("__impureHostDeps","/usr/bin/ditto"),("__noChroot","1"),("__sandboxProfile","sandcastle"),("allowSubstitutes",""),("allowedReferences","/nix/store/3c08bzb71z4wiag719ipjxr277653ynp-foo"),("allowedRequisites","/nix/store/3c08bzb71z4wiag719ipjxr277653ynp-foo"),("builder","/bin/bash"),("disallowedReferences","/nix/store/7rhsm8i393hm1wcsmph782awg1hi2f7x-bar"),("disallowedRequisites","/nix/store/7rhsm8i393hm1wcsmph782awg1hi2f7x-bar"),("impureEnvVars","UNICORN"),("name","advanced-attributes"),("out","/nix/store/33a6fdmn8q9ih9d7npbnrxn2q56a4l8q-advanced-attributes"),("preferLocalBuild","1"),("requiredSystemFeatures","rainbow uid-range"),("system","my-system")])

View file

@ -1,6 +1,21 @@
{ contentAddress }:
let
caArgs =
if contentAddress then
{
__contentAddressed = true;
outputHashMode = "recursive";
outputHashAlgo = "sha256";
}
else
{ };
derivation' = args: derivation (caArgs // args);
system = "my-system";
foo = derivation {
foo = derivation' {
inherit system;
name = "foo";
builder = "/bin/bash";
@ -8,8 +23,13 @@ let
"-c"
"echo foo > $out"
];
outputs = [
"out"
"dev"
];
};
bar = derivation {
bar = derivation' {
inherit system;
name = "bar";
builder = "/bin/bash";
@ -17,9 +37,14 @@ let
"-c"
"echo bar > $out"
];
outputs = [
"out"
"dev"
];
};
in
derivation {
derivation' {
inherit system;
name = "advanced-attributes";
builder = "/bin/bash";
@ -33,9 +58,9 @@ derivation {
impureEnvVars = [ "UNICORN" ];
__darwinAllowLocalNetworking = true;
allowedReferences = [ foo ];
allowedRequisites = [ foo ];
allowedRequisites = [ foo.dev ];
disallowedReferences = [ bar ];
disallowedRequisites = [ bar ];
disallowedRequisites = [ bar.dev ];
requiredSystemFeatures = [
"rainbow"
"uid-range"

View file

@ -0,0 +1 @@
Derive([("out","","r:sha256","")],[],[],"my-system","/bin/bash",["-c","echo hello > $out"],[("builder","/bin/bash"),("name","advanced-attributes-defaults"),("out","/1rz4g4znpzjwh1xymhjpm42vipw92pr73vdgl6xs1hycac8kf2n9"),("outputHashAlgo","sha256"),("outputHashMode","recursive"),("system","my-system")])

View file

@ -0,0 +1 @@
Derive([("dev","","r:sha256",""),("out","","r:sha256","")],[],[],"my-system","/bin/bash",["-c","echo hello > $out"],[("__json","{\"builder\":\"/bin/bash\",\"name\":\"advanced-attributes-structured-attrs-defaults\",\"outputHashAlgo\":\"sha256\",\"outputHashMode\":\"recursive\",\"outputs\":[\"out\",\"dev\"],\"system\":\"my-system\"}"),("dev","/02qcpld1y6xhs5gz9bchpxaw0xdhmsp5dv88lh25r2ss44kh8dxz"),("out","/1rz4g4znpzjwh1xymhjpm42vipw92pr73vdgl6xs1hycac8kf2n9")])

View file

@ -0,0 +1 @@
Derive([("bin","","r:sha256",""),("dev","","r:sha256",""),("out","","r:sha256","")],[("/nix/store/j56sf12rxpcv5swr14vsjn5cwm6bj03h-foo.drv",["dev","out"]),("/nix/store/qnml92yh97a6fbrs2m5qg5cqlc8vni58-bar.drv",["dev","out"])],[],"my-system","/bin/bash",["-c","echo hello > $out"],[("__json","{\"__darwinAllowLocalNetworking\":true,\"__impureHostDeps\":[\"/usr/bin/ditto\"],\"__noChroot\":true,\"__sandboxProfile\":\"sandcastle\",\"allowSubstitutes\":false,\"builder\":\"/bin/bash\",\"impureEnvVars\":[\"UNICORN\"],\"name\":\"advanced-attributes-structured-attrs\",\"outputChecks\":{\"bin\":{\"disallowedReferences\":[\"/0nyw57wm2iicnm9rglvjmbci3ikmcp823czdqdzdcgsnnwqps71g\"],\"disallowedRequisites\":[\"/07f301yqyz8c6wf6bbbavb2q39j4n8kmcly1s09xadyhgy6x2wr8\"]},\"dev\":{\"maxClosureSize\":5909,\"maxSize\":789},\"out\":{\"allowedReferences\":[\"/164j69y6zir9z0339n8pjigg3rckinlr77bxsavzizdaaljb7nh9\"],\"allowedRequisites\":[\"/0nr45p69vn6izw9446wsh9bng9nndhvn19kpsm4n96a5mycw0s4z\"]}},\"outputHashAlgo\":\"sha256\",\"outputHashMode\":\"recursive\",\"outputs\":[\"out\",\"bin\",\"dev\"],\"preferLocalBuild\":true,\"requiredSystemFeatures\":[\"rainbow\",\"uid-range\"],\"system\":\"my-system\"}"),("bin","/04f3da1kmbr67m3gzxikmsl4vjz5zf777sv6m14ahv22r65aac9m"),("dev","/02qcpld1y6xhs5gz9bchpxaw0xdhmsp5dv88lh25r2ss44kh8dxz"),("out","/1rz4g4znpzjwh1xymhjpm42vipw92pr73vdgl6xs1hycac8kf2n9")])

View file

@ -0,0 +1 @@
Derive([("out","","r:sha256","")],[("/nix/store/j56sf12rxpcv5swr14vsjn5cwm6bj03h-foo.drv",["dev","out"]),("/nix/store/qnml92yh97a6fbrs2m5qg5cqlc8vni58-bar.drv",["dev","out"])],[],"my-system","/bin/bash",["-c","echo hello > $out"],[("__darwinAllowLocalNetworking","1"),("__impureHostDeps","/usr/bin/ditto"),("__noChroot","1"),("__sandboxProfile","sandcastle"),("allowSubstitutes",""),("allowedReferences","/164j69y6zir9z0339n8pjigg3rckinlr77bxsavzizdaaljb7nh9"),("allowedRequisites","/0nr45p69vn6izw9446wsh9bng9nndhvn19kpsm4n96a5mycw0s4z"),("builder","/bin/bash"),("disallowedReferences","/0nyw57wm2iicnm9rglvjmbci3ikmcp823czdqdzdcgsnnwqps71g"),("disallowedRequisites","/07f301yqyz8c6wf6bbbavb2q39j4n8kmcly1s09xadyhgy6x2wr8"),("impureEnvVars","UNICORN"),("name","advanced-attributes"),("out","/1rz4g4znpzjwh1xymhjpm42vipw92pr73vdgl6xs1hycac8kf2n9"),("outputHashAlgo","sha256"),("outputHashMode","recursive"),("preferLocalBuild","1"),("requiredSystemFeatures","rainbow uid-range"),("system","my-system")])

Some files were not shown because too many files have changed in this diff Show more