mirror of
https://github.com/NixOS/nix
synced 2025-06-28 13:41:15 +02:00
Merge remote-tracking branch 'detsys/detsys-main' into lazy-trees-tmp
This commit is contained in:
commit
a6faa69fc8
109 changed files with 1219 additions and 546 deletions
5
.github/workflows/ci.yml
vendored
5
.github/workflows/ci.yml
vendored
|
@ -136,7 +136,10 @@ jobs:
|
||||||
production-branch: detsys-main
|
production-branch: detsys-main
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
deploy-message: "Deploy from GitHub Actions"
|
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-comment: true
|
||||||
enable-commit-status: true
|
enable-commit-status: true
|
||||||
overwrites-pull-request-comment: true
|
overwrites-pull-request-comment: true
|
||||||
|
|
2
.version
2
.version
|
@ -1 +1 @@
|
||||||
2.28.1
|
2.28.2
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
3.2.1
|
3.3.1
|
||||||
|
|
|
@ -250,7 +250,6 @@ nix3_manpages = [
|
||||||
'nix3-print-dev-env',
|
'nix3-print-dev-env',
|
||||||
'nix3-profile-diff-closures',
|
'nix3-profile-diff-closures',
|
||||||
'nix3-profile-history',
|
'nix3-profile-history',
|
||||||
'nix3-profile-install',
|
|
||||||
'nix3-profile-list',
|
'nix3-profile-list',
|
||||||
'nix3-profile',
|
'nix3-profile',
|
||||||
'nix3-profile-remove',
|
'nix3-profile-remove',
|
||||||
|
@ -283,7 +282,6 @@ nix3_manpages = [
|
||||||
'nix3-store',
|
'nix3-store',
|
||||||
'nix3-store-optimise',
|
'nix3-store-optimise',
|
||||||
'nix3-store-path-from-hash-part',
|
'nix3-store-path-from-hash-part',
|
||||||
'nix3-store-ping',
|
|
||||||
'nix3-store-prefetch-file',
|
'nix3-store-prefetch-file',
|
||||||
'nix3-store-repair',
|
'nix3-store-repair',
|
||||||
'nix3-store-sign',
|
'nix3-store-sign',
|
||||||
|
|
|
@ -128,6 +128,7 @@
|
||||||
- [Contributing](development/contributing.md)
|
- [Contributing](development/contributing.md)
|
||||||
- [Determinate Nix Release Notes](release-notes-determinate/index.md)
|
- [Determinate Nix Release Notes](release-notes-determinate/index.md)
|
||||||
- [Changes between Nix and Determinate Nix](release-notes-determinate/changes.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.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)
|
- [Release 3.0.0 (2025-03-04)](release-notes-determinate/rl-3.0.0.md)
|
||||||
- [Nix Release Notes](release-notes/index.md)
|
- [Nix Release Notes](release-notes/index.md)
|
||||||
|
|
|
@ -115,7 +115,7 @@ It creates an [attribute set] representing the string context, which can be insp
|
||||||
|
|
||||||
## Clearing string contexts
|
## 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 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 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.
|
The "unsafe" marker is only there to remind that Nix normally guarantees that dependencies are tracked, whereas the returned string has lost them.
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
# Changes between Nix and Determinate Nix
|
# 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, 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.
|
* 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 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`.
|
||||||
|
|
5
doc/manual/source/release-notes-determinate/rl-3.3.0.md
Normal file
5
doc/manual/source/release-notes-determinate/rl-3.3.0.md
Normal 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`.
|
|
@ -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.
|
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
|
# Contributors
|
||||||
|
|
||||||
This release was made possible by the following 21 contributors:
|
This release was made possible by the following 21 contributors:
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
# vim: set filetype=bash:
|
# vim: set filetype=bash:
|
||||||
#!nix shell .#changelog-d --command bash
|
#!nix shell .#changelog-d --command bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
# --- CONFIGURATION ---
|
# --- CONFIGURATION ---
|
||||||
|
|
||||||
# This does double duty for
|
# This does double duty for
|
||||||
|
|
|
@ -237,12 +237,13 @@ void StorePathCommand::run(ref<Store> store, StorePaths && storePaths)
|
||||||
|
|
||||||
MixProfile::MixProfile()
|
MixProfile::MixProfile()
|
||||||
{
|
{
|
||||||
addFlag(
|
addFlag({
|
||||||
{.longName = "profile",
|
.longName = "profile",
|
||||||
.description = "The profile to operate on.",
|
.description = "The profile to operate on.",
|
||||||
.labels = {"path"},
|
.labels = {"path"},
|
||||||
.handler = {&profile},
|
.handler = {&profile},
|
||||||
.completer = completePath});
|
.completer = completePath,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void MixProfile::updateProfile(const StorePath & storePath)
|
void MixProfile::updateProfile(const StorePath & storePath)
|
||||||
|
|
|
@ -62,7 +62,7 @@ MixEvalArgs::MixEvalArgs()
|
||||||
.description = "Pass the value *expr* as the argument *name* to Nix functions.",
|
.description = "Pass the value *expr* as the argument *name* to Nix functions.",
|
||||||
.category = category,
|
.category = category,
|
||||||
.labels = {"name", "expr"},
|
.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({
|
addFlag({
|
||||||
|
@ -79,7 +79,7 @@ MixEvalArgs::MixEvalArgs()
|
||||||
.category = category,
|
.category = category,
|
||||||
.labels = {"name", "path"},
|
.labels = {"name", "path"},
|
||||||
.handler = {[&](std::string name, std::string path) { autoArgs.insert_or_assign(name, AutoArg{AutoArgFile{path}}); }},
|
.handler = {[&](std::string name, std::string path) { autoArgs.insert_or_assign(name, AutoArg{AutoArgFile{path}}); }},
|
||||||
.completer = completePath
|
.completer = completePath,
|
||||||
});
|
});
|
||||||
|
|
||||||
addFlag({
|
addFlag({
|
||||||
|
@ -104,7 +104,7 @@ MixEvalArgs::MixEvalArgs()
|
||||||
.labels = {"path"},
|
.labels = {"path"},
|
||||||
.handler = {[&](std::string s) {
|
.handler = {[&](std::string s) {
|
||||||
lookupPath.elements.emplace_back(LookupPath::Elem::parse(s));
|
lookupPath.elements.emplace_back(LookupPath::Elem::parse(s));
|
||||||
}}
|
}},
|
||||||
});
|
});
|
||||||
|
|
||||||
addFlag({
|
addFlag({
|
||||||
|
@ -130,7 +130,7 @@ MixEvalArgs::MixEvalArgs()
|
||||||
}},
|
}},
|
||||||
.completer = {[&](AddCompletions & completions, size_t, std::string_view prefix) {
|
.completer = {[&](AddCompletions & completions, size_t, std::string_view prefix) {
|
||||||
completeFlakeRef(completions, openStore(), prefix);
|
completeFlakeRef(completions, openStore(), prefix);
|
||||||
}}
|
}},
|
||||||
});
|
});
|
||||||
|
|
||||||
addFlag({
|
addFlag({
|
||||||
|
|
|
@ -64,21 +64,21 @@ MixFlakeOptions::MixFlakeOptions()
|
||||||
.handler = {[&]() {
|
.handler = {[&]() {
|
||||||
lockFlags.recreateLockFile = true;
|
lockFlags.recreateLockFile = true;
|
||||||
warn("'--recreate-lock-file' is deprecated and will be removed in a future version; use 'nix flake update' instead.");
|
warn("'--recreate-lock-file' is deprecated and will be removed in a future version; use 'nix flake update' instead.");
|
||||||
}}
|
}},
|
||||||
});
|
});
|
||||||
|
|
||||||
addFlag({
|
addFlag({
|
||||||
.longName = "no-update-lock-file",
|
.longName = "no-update-lock-file",
|
||||||
.description = "Do not allow any updates to the flake's lock file.",
|
.description = "Do not allow any updates to the flake's lock file.",
|
||||||
.category = category,
|
.category = category,
|
||||||
.handler = {&lockFlags.updateLockFile, false}
|
.handler = {&lockFlags.updateLockFile, false},
|
||||||
});
|
});
|
||||||
|
|
||||||
addFlag({
|
addFlag({
|
||||||
.longName = "no-write-lock-file",
|
.longName = "no-write-lock-file",
|
||||||
.description = "Do not write the flake's newly generated lock file.",
|
.description = "Do not write the flake's newly generated lock file.",
|
||||||
.category = category,
|
.category = category,
|
||||||
.handler = {&lockFlags.writeLockFile, false}
|
.handler = {&lockFlags.writeLockFile, false},
|
||||||
});
|
});
|
||||||
|
|
||||||
addFlag({
|
addFlag({
|
||||||
|
@ -94,14 +94,14 @@ MixFlakeOptions::MixFlakeOptions()
|
||||||
.handler = {[&]() {
|
.handler = {[&]() {
|
||||||
lockFlags.useRegistries = false;
|
lockFlags.useRegistries = false;
|
||||||
warn("'--no-registries' is deprecated; use '--no-use-registries'");
|
warn("'--no-registries' is deprecated; use '--no-use-registries'");
|
||||||
}}
|
}},
|
||||||
});
|
});
|
||||||
|
|
||||||
addFlag({
|
addFlag({
|
||||||
.longName = "commit-lock-file",
|
.longName = "commit-lock-file",
|
||||||
.description = "Commit changes to the flake's lock file.",
|
.description = "Commit changes to the flake's lock file.",
|
||||||
.category = category,
|
.category = category,
|
||||||
.handler = {&lockFlags.commitLockFile, true}
|
.handler = {&lockFlags.commitLockFile, true},
|
||||||
});
|
});
|
||||||
|
|
||||||
addFlag({
|
addFlag({
|
||||||
|
@ -121,7 +121,7 @@ MixFlakeOptions::MixFlakeOptions()
|
||||||
}},
|
}},
|
||||||
.completer = {[&](AddCompletions & completions, size_t, std::string_view prefix) {
|
.completer = {[&](AddCompletions & completions, size_t, std::string_view prefix) {
|
||||||
completeFlakeInputAttrPath(completions, getEvalState(), getFlakeRefsForCompletion(), prefix);
|
completeFlakeInputAttrPath(completions, getEvalState(), getFlakeRefsForCompletion(), prefix);
|
||||||
}}
|
}},
|
||||||
});
|
});
|
||||||
|
|
||||||
addFlag({
|
addFlag({
|
||||||
|
@ -141,7 +141,7 @@ MixFlakeOptions::MixFlakeOptions()
|
||||||
} else if (n == 1) {
|
} else if (n == 1) {
|
||||||
completeFlakeRef(completions, getEvalState()->store, prefix);
|
completeFlakeRef(completions, getEvalState()->store, prefix);
|
||||||
}
|
}
|
||||||
}}
|
}},
|
||||||
});
|
});
|
||||||
|
|
||||||
addFlag({
|
addFlag({
|
||||||
|
@ -152,7 +152,7 @@ MixFlakeOptions::MixFlakeOptions()
|
||||||
.handler = {[&](std::string lockFilePath) {
|
.handler = {[&](std::string lockFilePath) {
|
||||||
lockFlags.referenceLockFilePath = {getFSSourceAccessor(), CanonPath(absPath(lockFilePath))};
|
lockFlags.referenceLockFilePath = {getFSSourceAccessor(), CanonPath(absPath(lockFilePath))};
|
||||||
}},
|
}},
|
||||||
.completer = completePath
|
.completer = completePath,
|
||||||
});
|
});
|
||||||
|
|
||||||
addFlag({
|
addFlag({
|
||||||
|
@ -163,7 +163,7 @@ MixFlakeOptions::MixFlakeOptions()
|
||||||
.handler = {[&](std::string lockFilePath) {
|
.handler = {[&](std::string lockFilePath) {
|
||||||
lockFlags.outputLockFilePath = lockFilePath;
|
lockFlags.outputLockFilePath = lockFilePath;
|
||||||
}},
|
}},
|
||||||
.completer = completePath
|
.completer = completePath,
|
||||||
});
|
});
|
||||||
|
|
||||||
addFlag({
|
addFlag({
|
||||||
|
@ -190,7 +190,7 @@ MixFlakeOptions::MixFlakeOptions()
|
||||||
}},
|
}},
|
||||||
.completer = {[&](AddCompletions & completions, size_t, std::string_view prefix) {
|
.completer = {[&](AddCompletions & completions, size_t, std::string_view prefix) {
|
||||||
completeFlakeRef(completions, getEvalState()->store, prefix);
|
completeFlakeRef(completions, getEvalState()->store, prefix);
|
||||||
}}
|
}},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,7 +206,7 @@ SourceExprCommand::SourceExprCommand()
|
||||||
.category = installablesCategory,
|
.category = installablesCategory,
|
||||||
.labels = {"file"},
|
.labels = {"file"},
|
||||||
.handler = {&file},
|
.handler = {&file},
|
||||||
.completer = completePath
|
.completer = completePath,
|
||||||
});
|
});
|
||||||
|
|
||||||
addFlag({
|
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*.",
|
.description = "Interpret [*installables*](@docroot@/command-ref/new-cli/nix.md#installables) as attribute paths relative to the Nix expression *expr*.",
|
||||||
.category = installablesCategory,
|
.category = installablesCategory,
|
||||||
.labels = {"expr"},
|
.labels = {"expr"},
|
||||||
.handler = {&expr}
|
.handler = {&expr},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -831,7 +831,7 @@ RawInstallablesCommand::RawInstallablesCommand()
|
||||||
addFlag({
|
addFlag({
|
||||||
.longName = "stdin",
|
.longName = "stdin",
|
||||||
.description = "Read installables from the standard input. No default installable applied.",
|
.description = "Read installables from the standard input. No default installable applied.",
|
||||||
.handler = {&readFromStdIn, true}
|
.handler = {&readFromStdIn, true},
|
||||||
});
|
});
|
||||||
|
|
||||||
expectArgs({
|
expectArgs({
|
||||||
|
@ -844,7 +844,7 @@ RawInstallablesCommand::RawInstallablesCommand()
|
||||||
void RawInstallablesCommand::applyDefaultInstallables(std::vector<std::string> & rawInstallables)
|
void RawInstallablesCommand::applyDefaultInstallables(std::vector<std::string> & rawInstallables)
|
||||||
{
|
{
|
||||||
if (rawInstallables.empty()) {
|
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.
|
// default, probably.
|
||||||
rawInstallables.push_back(".");
|
rawInstallables.push_back(".");
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ headers = [config_pub_h] + files(
|
||||||
'gc-small-vector.hh',
|
'gc-small-vector.hh',
|
||||||
'get-drvs.hh',
|
'get-drvs.hh',
|
||||||
'json-to-value.hh',
|
'json-to-value.hh',
|
||||||
# internal: 'lexer-helpers.hh',
|
|
||||||
'nixexpr.hh',
|
'nixexpr.hh',
|
||||||
'parser-state.hh',
|
'parser-state.hh',
|
||||||
'primops.hh',
|
'primops.hh',
|
||||||
|
|
|
@ -65,7 +65,7 @@ struct DocComment {
|
||||||
struct AttrName
|
struct AttrName
|
||||||
{
|
{
|
||||||
Symbol symbol;
|
Symbol symbol;
|
||||||
Expr * expr;
|
Expr * expr = nullptr;
|
||||||
AttrName(Symbol s) : symbol(s) {};
|
AttrName(Symbol s) : symbol(s) {};
|
||||||
AttrName(Expr * e) : expr(e) {};
|
AttrName(Expr * e) : expr(e) {};
|
||||||
};
|
};
|
||||||
|
@ -159,7 +159,7 @@ struct ExprVar : Expr
|
||||||
|
|
||||||
`nullptr`: Not from a `with`.
|
`nullptr`: Not from a `with`.
|
||||||
Valid pointer: the nearest, innermost `with` expression to query first. */
|
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`
|
/* In the former case, the value is obtained by going `level`
|
||||||
levels up from the current environment and getting the
|
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
|
value is obtained by getting the attribute named `name` from
|
||||||
the set stored in the environment that is `level` levels up
|
the set stored in the environment that is `level` levels up
|
||||||
from the current one.*/
|
from the current one.*/
|
||||||
Level level;
|
Level level = 0;
|
||||||
Displacement displ = 0;
|
Displacement displ = 0;
|
||||||
|
|
||||||
ExprVar(Symbol name) : name(name) { };
|
ExprVar(Symbol name) : name(name) { };
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
#include "lexer-tab.hh"
|
#include "lexer-helpers.hh"
|
||||||
#include "parser-tab.hh"
|
|
||||||
|
|
||||||
#include "nix/expr/lexer-helpers.hh"
|
|
||||||
|
|
||||||
void nix::lexer::internal::initLoc(YYLTYPE * loc)
|
void nix::lexer::internal::initLoc(YYLTYPE * loc)
|
||||||
{
|
{
|
||||||
|
|
|
@ -25,8 +25,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "nix/expr/nixexpr.hh"
|
#include "nix/expr/nixexpr.hh"
|
||||||
#include "parser-tab.hh"
|
#include "lexer-helpers.hh"
|
||||||
#include "nix/expr/lexer-helpers.hh"
|
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
struct LexerState;
|
struct LexerState;
|
||||||
|
|
|
@ -14,6 +14,7 @@ overrides:
|
||||||
fetchTreeFinal:
|
fetchTreeFinal:
|
||||||
|
|
||||||
let
|
let
|
||||||
|
inherit (builtins) mapAttrs;
|
||||||
|
|
||||||
lockFile = builtins.fromJSON lockFileStr;
|
lockFile = builtins.fromJSON lockFileStr;
|
||||||
|
|
||||||
|
@ -35,19 +36,26 @@ let
|
||||||
(resolveInput lockFile.nodes.${nodeName}.inputs.${builtins.head path})
|
(resolveInput lockFile.nodes.${nodeName}.inputs.${builtins.head path})
|
||||||
(builtins.tail path);
|
(builtins.tail path);
|
||||||
|
|
||||||
allNodes = builtins.mapAttrs (
|
allNodes = mapAttrs (
|
||||||
key: node:
|
key: node:
|
||||||
let
|
let
|
||||||
|
|
||||||
parentNode = allNodes.${getInputByPath lockFile.root node.parent};
|
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 =
|
sourceInfo =
|
||||||
if overrides ? ${key} then
|
if overrides ? ${key} then
|
||||||
overrides.${key}.sourceInfo
|
overrides.${key}.sourceInfo
|
||||||
else if node.locked.type == "path" && builtins.substring 0 1 node.locked.path != "/" then
|
else if node.locked.type == "path" && builtins.substring 0 1 node.locked.path != "/" then
|
||||||
parentNode.sourceInfo
|
parentNode.sourceInfo
|
||||||
// {
|
// {
|
||||||
outPath = parentNode.outPath + ("/" + node.locked.path);
|
outPath = parentNode.sourceInfo.outPath + ("/" + flakeDir);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
# FIXME: remove obsolete node.info.
|
# FIXME: remove obsolete node.info.
|
||||||
|
@ -60,7 +68,7 @@ let
|
||||||
|
|
||||||
flake = import (outPath + "/flake.nix");
|
flake = import (outPath + "/flake.nix");
|
||||||
|
|
||||||
inputs = builtins.mapAttrs (inputName: inputSpec: allNodes.${resolveInput inputSpec}) (
|
inputs = mapAttrs (inputName: inputSpec: allNodes.${resolveInput inputSpec}.result) (
|
||||||
node.inputs or { }
|
node.inputs or { }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -85,12 +93,17 @@ let
|
||||||
};
|
};
|
||||||
|
|
||||||
in
|
in
|
||||||
if node.flake or true then
|
{
|
||||||
assert builtins.isFunction flake.outputs;
|
result =
|
||||||
result
|
if node.flake or true then
|
||||||
else
|
assert builtins.isFunction flake.outputs;
|
||||||
sourceInfo
|
result
|
||||||
|
else
|
||||||
|
sourceInfo;
|
||||||
|
|
||||||
|
inherit flakeDir sourceInfo;
|
||||||
|
}
|
||||||
) lockFile.nodes;
|
) lockFile.nodes;
|
||||||
|
|
||||||
in
|
in
|
||||||
allNodes.${lockFile.root}
|
allNodes.${lockFile.root}.result
|
||||||
|
|
|
@ -57,7 +57,7 @@ MixCommonArgs::MixCommonArgs(const std::string & programName)
|
||||||
if (hasPrefix(s.first, prefix))
|
if (hasPrefix(s.first, prefix))
|
||||||
completions.add(s.first, fmt("Set the `%s` setting.", s.first));
|
completions.add(s.first, fmt("Set the `%s` setting.", s.first));
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
addFlag({
|
addFlag({
|
||||||
|
@ -75,7 +75,7 @@ MixCommonArgs::MixCommonArgs(const std::string & programName)
|
||||||
.labels = Strings{"jobs"},
|
.labels = Strings{"jobs"},
|
||||||
.handler = {[=](std::string s) {
|
.handler = {[=](std::string s) {
|
||||||
settings.set("max-jobs", s);
|
settings.set("max-jobs", s);
|
||||||
}}
|
}},
|
||||||
});
|
});
|
||||||
|
|
||||||
std::string cat = "Options to override configuration settings";
|
std::string cat = "Options to override configuration settings";
|
||||||
|
|
|
@ -231,7 +231,7 @@ LegacyArgs::LegacyArgs(const std::string & programName,
|
||||||
.handler = {[=](std::string s) {
|
.handler = {[=](std::string s) {
|
||||||
auto n = string2IntWithUnitPrefix<uint64_t>(s);
|
auto n = string2IntWithUnitPrefix<uint64_t>(s);
|
||||||
settings.set(dest, std::to_string(n));
|
settings.set(dest, std::to_string(n));
|
||||||
}}
|
}},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
../../../../tests/functional/derivation/advanced-attributes-defaults.drv
|
|
|
@ -1 +0,0 @@
|
||||||
../../../../tests/functional/derivation/advanced-attributes-structured-attrs-defaults.drv
|
|
|
@ -1 +0,0 @@
|
||||||
../../../../tests/functional/derivation/advanced-attributes-structured-attrs.drv
|
|
|
@ -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"
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
../../../../tests/functional/derivation/advanced-attributes.drv
|
|
|
@ -0,0 +1 @@
|
||||||
|
../../../../../tests/functional/derivation/ca/advanced-attributes-defaults.drv
|
|
@ -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"
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
../../../../../tests/functional/derivation/ca/advanced-attributes-structured-attrs-defaults.drv
|
|
@ -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"
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
../../../../../tests/functional/derivation/ca/advanced-attributes-structured-attrs.drv
|
|
@ -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"
|
||||||
|
}
|
1
src/libstore-tests/data/derivation/ca/advanced-attributes.drv
Symbolic link
1
src/libstore-tests/data/derivation/ca/advanced-attributes.drv
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../../../../tests/functional/derivation/ca/advanced-attributes.drv
|
|
@ -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"
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
../../../../../tests/functional/derivation/ia/advanced-attributes-defaults.drv
|
|
@ -0,0 +1 @@
|
||||||
|
../../../../../tests/functional/derivation/ia/advanced-attributes-structured-attrs-defaults.drv
|
|
@ -0,0 +1 @@
|
||||||
|
../../../../../tests/functional/derivation/ia/advanced-attributes-structured-attrs.drv
|
|
@ -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"
|
||||||
|
}
|
1
src/libstore-tests/data/derivation/ia/advanced-attributes.drv
Symbolic link
1
src/libstore-tests/data/derivation/ia/advanced-attributes.drv
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../../../../tests/functional/derivation/ia/advanced-attributes.drv
|
|
@ -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"
|
||||||
|
}
|
|
@ -18,68 +18,93 @@ using nlohmann::json;
|
||||||
|
|
||||||
class DerivationAdvancedAttrsTest : public CharacterizationTest, public LibStoreTest
|
class DerivationAdvancedAttrsTest : public CharacterizationTest, public LibStoreTest
|
||||||
{
|
{
|
||||||
std::filesystem::path unitTestData = getUnitTestData() / "derivation";
|
protected:
|
||||||
|
std::filesystem::path unitTestData = getUnitTestData() / "derivation" / "ia";
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::filesystem::path goldenMaster(std::string_view testStem) const override
|
std::filesystem::path goldenMaster(std::string_view testStem) const override
|
||||||
{
|
{
|
||||||
return unitTestData / testStem;
|
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) \
|
class CaDerivationAdvancedAttrsTest : public DerivationAdvancedAttrsTest
|
||||||
TEST_F(DerivationAdvancedAttrsTest, Derivation_##STEM##_from_json) \
|
{
|
||||||
{ \
|
void SetUp() override
|
||||||
readTest(NAME ".json", [&](const auto & encoded_) { \
|
{
|
||||||
auto encoded = json::parse(encoded_); \
|
unitTestData = getUnitTestData() / "derivation" / "ca";
|
||||||
/* Use DRV file instead of C++ literal as source of truth. */ \
|
mockXpSettings.set("experimental-features", "ca-derivations");
|
||||||
auto aterm = readFile(goldenMaster(NAME ".drv")); \
|
}
|
||||||
auto expected = parseDerivation(*store, std::move(aterm), NAME); \
|
};
|
||||||
Derivation got = Derivation::fromJSON(*store, encoded); \
|
|
||||||
EXPECT_EQ(got, expected); \
|
template<class Fixture>
|
||||||
}); \
|
class DerivationAdvancedAttrsBothTest : public Fixture
|
||||||
} \
|
{};
|
||||||
\
|
|
||||||
TEST_F(DerivationAdvancedAttrsTest, Derivation_##STEM##_to_json) \
|
using BothFixtures = ::testing::Types<DerivationAdvancedAttrsTest, CaDerivationAdvancedAttrsTest>;
|
||||||
{ \
|
|
||||||
writeTest( \
|
TYPED_TEST_SUITE(DerivationAdvancedAttrsBothTest, BothFixtures);
|
||||||
NAME ".json", \
|
|
||||||
[&]() -> json { \
|
#define TEST_ATERM_JSON(STEM, NAME) \
|
||||||
/* Use DRV file instead of C++ literal as source of truth. */ \
|
TYPED_TEST(DerivationAdvancedAttrsBothTest, Derivation_##STEM##_from_json) \
|
||||||
auto aterm = readFile(goldenMaster(NAME ".drv")); \
|
{ \
|
||||||
return parseDerivation(*store, std::move(aterm), NAME).toJSON(*store); \
|
this->readTest(NAME ".json", [&](const auto & encoded_) { \
|
||||||
}, \
|
auto encoded = json::parse(encoded_); \
|
||||||
[](const auto & file) { return json::parse(readFile(file)); }, \
|
/* Use DRV file instead of C++ literal as source of truth. */ \
|
||||||
[](const auto & file, const auto & got) { return writeFile(file, got.dump(2) + "\n"); }); \
|
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); \
|
||||||
TEST_F(DerivationAdvancedAttrsTest, Derivation_##STEM##_from_aterm) \
|
EXPECT_EQ(got, expected); \
|
||||||
{ \
|
}); \
|
||||||
readTest(NAME ".drv", [&](auto encoded) { \
|
} \
|
||||||
/* Use JSON file instead of C++ literal as source of truth. */ \
|
\
|
||||||
auto json = json::parse(readFile(goldenMaster(NAME ".json"))); \
|
TYPED_TEST(DerivationAdvancedAttrsBothTest, Derivation_##STEM##_to_json) \
|
||||||
auto expected = Derivation::fromJSON(*store, json); \
|
{ \
|
||||||
auto got = parseDerivation(*store, std::move(encoded), NAME); \
|
this->writeTest( \
|
||||||
EXPECT_EQ(got.toJSON(*store), expected.toJSON(*store)); \
|
NAME ".json", \
|
||||||
EXPECT_EQ(got, expected); \
|
[&]() -> 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 */
|
/* 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, "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, "advanced-attributes-structured-attrs-defaults");
|
||||||
|
TEST_ATERM_JSON(advancedAttributes_structuredAttrs_defaults, "advanced-attributes-structured-attrs");
|
||||||
|
|
||||||
#undef TEST_ATERM_JSON
|
#undef TEST_ATERM_JSON
|
||||||
|
|
||||||
TEST_F(DerivationAdvancedAttrsTest, Derivation_advancedAttributes_defaults)
|
TYPED_TEST(DerivationAdvancedAttrsBothTest, advancedAttributes_defaults)
|
||||||
{
|
{
|
||||||
readTest("advanced-attributes-defaults.drv", [&](auto encoded) {
|
this->readTest("advanced-attributes-defaults.drv", [&](auto encoded) {
|
||||||
auto got = parseDerivation(*store, std::move(encoded), "foo");
|
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);
|
ParsedDerivation parsedDrv(drvPath, got);
|
||||||
DerivationOptions options = DerivationOptions::fromParsedDerivation(parsedDrv);
|
DerivationOptions options = DerivationOptions::fromParsedDerivation(parsedDrv);
|
||||||
|
@ -101,25 +126,50 @@ TEST_F(DerivationAdvancedAttrsTest, Derivation_advancedAttributes_defaults)
|
||||||
EXPECT_EQ(checksForAllOutputs.disallowedReferences, StringSet{});
|
EXPECT_EQ(checksForAllOutputs.disallowedReferences, StringSet{});
|
||||||
EXPECT_EQ(checksForAllOutputs.disallowedRequisites, StringSet{});
|
EXPECT_EQ(checksForAllOutputs.disallowedRequisites, StringSet{});
|
||||||
}
|
}
|
||||||
EXPECT_EQ(options.getRequiredSystemFeatures(got), StringSet());
|
EXPECT_EQ(options.canBuildLocally(*this->store, got), false);
|
||||||
EXPECT_EQ(options.canBuildLocally(*store, got), false);
|
EXPECT_EQ(options.willBuildLocally(*this->store, got), false);
|
||||||
EXPECT_EQ(options.willBuildLocally(*store, got), false);
|
|
||||||
EXPECT_EQ(options.substitutesAllowed(), true);
|
EXPECT_EQ(options.substitutesAllowed(), true);
|
||||||
EXPECT_EQ(options.useUidRange(got), false);
|
EXPECT_EQ(options.useUidRange(got), false);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(DerivationAdvancedAttrsTest, Derivation_advancedAttributes)
|
TEST_F(DerivationAdvancedAttrsTest, advancedAttributes_defaults)
|
||||||
{
|
{
|
||||||
readTest("advanced-attributes.drv", [&](auto encoded) {
|
this->readTest("advanced-attributes-defaults.drv", [&](auto encoded) {
|
||||||
auto got = parseDerivation(*store, std::move(encoded), "foo");
|
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);
|
ParsedDerivation parsedDrv(drvPath, got);
|
||||||
DerivationOptions options = DerivationOptions::fromParsedDerivation(parsedDrv);
|
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());
|
EXPECT_TRUE(!parsedDrv.hasStructuredAttrs());
|
||||||
|
|
||||||
|
@ -128,34 +178,88 @@ TEST_F(DerivationAdvancedAttrsTest, Derivation_advancedAttributes)
|
||||||
EXPECT_EQ(options.impureHostDeps, StringSet{"/usr/bin/ditto"});
|
EXPECT_EQ(options.impureHostDeps, StringSet{"/usr/bin/ditto"});
|
||||||
EXPECT_EQ(options.impureEnvVars, StringSet{"UNICORN"});
|
EXPECT_EQ(options.impureEnvVars, StringSet{"UNICORN"});
|
||||||
EXPECT_EQ(options.allowLocalNetworking, true);
|
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);
|
auto * checksForAllOutputs_ = std::get_if<0>(&options.outputChecks);
|
||||||
ASSERT_TRUE(checksForAllOutputs_ != nullptr);
|
ASSERT_TRUE(checksForAllOutputs_ != nullptr);
|
||||||
auto & checksForAllOutputs = *checksForAllOutputs_;
|
auto & checksForAllOutputs = *checksForAllOutputs_;
|
||||||
|
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
checksForAllOutputs.allowedReferences, StringSet{"/nix/store/3c08bzb71z4wiag719ipjxr277653ynp-foo"});
|
checksForAllOutputs.allowedReferences, StringSet{"/nix/store/p0hax2lzvjpfc2gwkk62xdglz0fcqfzn-foo"});
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
checksForAllOutputs.allowedRequisites, StringSet{"/nix/store/3c08bzb71z4wiag719ipjxr277653ynp-foo"});
|
checksForAllOutputs.allowedRequisites,
|
||||||
|
StringSet{"/nix/store/z0rjzy29v9k5qa4nqpykrbzirj7sd43v-foo-dev"});
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
checksForAllOutputs.disallowedReferences, StringSet{"/nix/store/7rhsm8i393hm1wcsmph782awg1hi2f7x-bar"});
|
checksForAllOutputs.disallowedReferences, StringSet{"/nix/store/r5cff30838majxk5mp3ip2diffi8vpaj-bar"});
|
||||||
EXPECT_EQ(
|
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.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) {
|
this->readTest("advanced-attributes.drv", [&](auto encoded) {
|
||||||
auto got = parseDerivation(*store, std::move(encoded), "foo");
|
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);
|
ParsedDerivation parsedDrv(drvPath, got);
|
||||||
DerivationOptions options = DerivationOptions::fromParsedDerivation(parsedDrv);
|
DerivationOptions options = DerivationOptions::fromParsedDerivation(parsedDrv);
|
||||||
|
@ -176,25 +280,50 @@ TEST_F(DerivationAdvancedAttrsTest, Derivation_advancedAttributes_structuredAttr
|
||||||
EXPECT_EQ(checksPerOutput.size(), 0);
|
EXPECT_EQ(checksPerOutput.size(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPECT_EQ(options.getRequiredSystemFeatures(got), StringSet());
|
EXPECT_EQ(options.canBuildLocally(*this->store, got), false);
|
||||||
EXPECT_EQ(options.canBuildLocally(*store, got), false);
|
EXPECT_EQ(options.willBuildLocally(*this->store, got), false);
|
||||||
EXPECT_EQ(options.willBuildLocally(*store, got), false);
|
|
||||||
EXPECT_EQ(options.substitutesAllowed(), true);
|
EXPECT_EQ(options.substitutesAllowed(), true);
|
||||||
EXPECT_EQ(options.useUidRange(got), false);
|
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) {
|
this->readTest("advanced-attributes-structured-attrs-defaults.drv", [&](auto encoded) {
|
||||||
auto got = parseDerivation(*store, std::move(encoded), "foo");
|
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);
|
ParsedDerivation parsedDrv(drvPath, got);
|
||||||
DerivationOptions options = DerivationOptions::fromParsedDerivation(parsedDrv);
|
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());
|
EXPECT_TRUE(parsedDrv.hasStructuredAttrs());
|
||||||
|
|
||||||
|
@ -204,14 +333,40 @@ TEST_F(DerivationAdvancedAttrsTest, Derivation_advancedAttributes_structuredAttr
|
||||||
EXPECT_EQ(options.impureEnvVars, StringSet{"UNICORN"});
|
EXPECT_EQ(options.impureEnvVars, StringSet{"UNICORN"});
|
||||||
EXPECT_EQ(options.allowLocalNetworking, true);
|
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");
|
auto output_ = get(std::get<1>(options.outputChecks), "out");
|
||||||
ASSERT_TRUE(output_);
|
ASSERT_TRUE(output_);
|
||||||
auto & output = *output_;
|
auto & output = *output_;
|
||||||
|
|
||||||
EXPECT_EQ(output.allowedReferences, StringSet{"/nix/store/3c08bzb71z4wiag719ipjxr277653ynp-foo"});
|
EXPECT_EQ(output.allowedReferences, StringSet{"/nix/store/p0hax2lzvjpfc2gwkk62xdglz0fcqfzn-foo"});
|
||||||
EXPECT_EQ(output.allowedRequisites, StringSet{"/nix/store/3c08bzb71z4wiag719ipjxr277653ynp-foo"});
|
EXPECT_EQ(output.allowedRequisites, StringSet{"/nix/store/z0rjzy29v9k5qa4nqpykrbzirj7sd43v-foo-dev"});
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -219,25 +374,54 @@ TEST_F(DerivationAdvancedAttrsTest, Derivation_advancedAttributes_structuredAttr
|
||||||
ASSERT_TRUE(output_);
|
ASSERT_TRUE(output_);
|
||||||
auto & output = *output_;
|
auto & output = *output_;
|
||||||
|
|
||||||
EXPECT_EQ(output.disallowedReferences, StringSet{"/nix/store/7rhsm8i393hm1wcsmph782awg1hi2f7x-bar"});
|
EXPECT_EQ(output.disallowedReferences, StringSet{"/nix/store/r5cff30838majxk5mp3ip2diffi8vpaj-bar"});
|
||||||
EXPECT_EQ(output.disallowedRequisites, StringSet{"/nix/store/7rhsm8i393hm1wcsmph782awg1hi2f7x-bar"});
|
EXPECT_EQ(
|
||||||
}
|
output.disallowedRequisites, StringSet{"/nix/store/9b61w26b4avv870dw0ymb6rw4r1hzpws-bar-dev"});
|
||||||
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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.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);
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -73,6 +73,32 @@ TEST(machines, getMachinesWithSemicolonSeparator) {
|
||||||
EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, AuthorityMatches("nix@itchy.labs.cs.uu.nl"))));
|
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) {
|
TEST(machines, getMachinesWithCorrectCompleteSingleBuilder) {
|
||||||
auto actual = Machine::parseConfig({},
|
auto actual = Machine::parseConfig({},
|
||||||
"nix@scratchy.labs.cs.uu.nl i686-linux "
|
"nix@scratchy.labs.cs.uu.nl i686-linux "
|
||||||
|
|
|
@ -68,7 +68,6 @@ DerivationOptions DerivationOptions::fromParsedDerivation(const ParsedDerivation
|
||||||
throw Error("attribute '%s' must be a list of strings", name);
|
throw Error("attribute '%s' must be a list of strings", name);
|
||||||
res.insert(j->get<std::string>());
|
res.insert(j->get<std::string>());
|
||||||
}
|
}
|
||||||
checks.disallowedRequisites = res;
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
|
|
|
@ -1368,7 +1368,7 @@ Derivation Derivation::fromJSON(
|
||||||
for (auto & [outputName, output] : getObject(valueAt(json, "outputs"))) {
|
for (auto & [outputName, output] : getObject(valueAt(json, "outputs"))) {
|
||||||
res.outputs.insert_or_assign(
|
res.outputs.insert_or_assign(
|
||||||
outputName,
|
outputName,
|
||||||
DerivationOutput::fromJSON(store, res.name, outputName, output));
|
DerivationOutput::fromJSON(store, res.name, outputName, output, xpSettings));
|
||||||
}
|
}
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
e.addTrace({}, "while reading key 'outputs'");
|
e.addTrace({}, "while reading key 'outputs'");
|
||||||
|
|
|
@ -22,10 +22,8 @@
|
||||||
|
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iostream>
|
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <random>
|
#include <random>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
@ -95,7 +93,7 @@ struct curlFileTransfer : public FileTransfer
|
||||||
: fileTransfer(fileTransfer)
|
: fileTransfer(fileTransfer)
|
||||||
, request(request)
|
, request(request)
|
||||||
, act(*logger, lvlTalkative, actFileTransfer,
|
, 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)
|
{request.uri}, request.parentAct)
|
||||||
, callback(std::move(callback))
|
, callback(std::move(callback))
|
||||||
, finalSink([this](std::string_view data) {
|
, finalSink([this](std::string_view data) {
|
||||||
|
@ -272,19 +270,11 @@ struct curlFileTransfer : public FileTransfer
|
||||||
return getInterrupted();
|
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)
|
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);
|
auto & item = *static_cast<TransferItem *>(userp);
|
||||||
}
|
auto isUpload = bool(item.request.data);
|
||||||
|
return item.progressCallback(isUpload ? ultotal : dltotal, isUpload ? ulnow : 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int debugCallback(CURL * handle, curl_infotype type, char * data, size_t size, void * userptr)
|
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_HEADERFUNCTION, TransferItem::headerCallbackWrapper);
|
||||||
curl_easy_setopt(req, CURLOPT_HEADERDATA, this);
|
curl_easy_setopt(req, CURLOPT_HEADERDATA, this);
|
||||||
|
|
||||||
if (request.post)
|
curl_easy_setopt(req, CURLOPT_XFERINFOFUNCTION, progressCallbackWrapper);
|
||||||
curl_easy_setopt(req, CURLOPT_XFERINFOFUNCTION, silentProgressCallbackWrapper);
|
|
||||||
else
|
|
||||||
curl_easy_setopt(req, CURLOPT_XFERINFOFUNCTION, progressCallbackWrapper);
|
|
||||||
curl_easy_setopt(req, CURLOPT_XFERINFODATA, this);
|
curl_easy_setopt(req, CURLOPT_XFERINFODATA, this);
|
||||||
curl_easy_setopt(req, CURLOPT_NOPROGRESS, 0);
|
curl_easy_setopt(req, CURLOPT_NOPROGRESS, 0);
|
||||||
|
|
||||||
|
@ -449,8 +436,7 @@ struct curlFileTransfer : public FileTransfer
|
||||||
if (httpStatus == 304 && result.etag == "")
|
if (httpStatus == 304 && result.etag == "")
|
||||||
result.etag = request.expectedETag;
|
result.etag = request.expectedETag;
|
||||||
|
|
||||||
if (!request.post)
|
act.progress(result.bodySize, result.bodySize);
|
||||||
act.progress(result.bodySize, result.bodySize);
|
|
||||||
done = true;
|
done = true;
|
||||||
callback(std::move(result));
|
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);
|
warn("%s; retrying from offset %d in %d ms", exc.what(), writtenToSink, ms);
|
||||||
else
|
else
|
||||||
warn("%s; retrying in %d ms", exc.what(), ms);
|
warn("%s; retrying in %d ms", exc.what(), ms);
|
||||||
|
decompressionSink.reset();
|
||||||
|
errorSink.reset();
|
||||||
embargo = std::chrono::steady_clock::now() + std::chrono::milliseconds(ms);
|
embargo = std::chrono::steady_clock::now() + std::chrono::milliseconds(ms);
|
||||||
fileTransfer.enqueueItem(shared_from_this());
|
fileTransfer.enqueueItem(shared_from_this());
|
||||||
}
|
}
|
||||||
|
@ -791,10 +779,6 @@ struct curlFileTransfer : public FileTransfer
|
||||||
|
|
||||||
S3Helper s3Helper(profile, region, scheme, endpoint);
|
S3Helper s3Helper(profile, region, scheme, endpoint);
|
||||||
|
|
||||||
Activity act(*logger, lvlTalkative, actFileTransfer,
|
|
||||||
fmt("downloading '%s'", request.uri),
|
|
||||||
{request.uri}, request.parentAct);
|
|
||||||
|
|
||||||
// FIXME: implement ETag
|
// FIXME: implement ETag
|
||||||
auto s3Res = s3Helper.getObject(bucketName, key);
|
auto s3Res = s3Helper.getObject(bucketName, key);
|
||||||
FileTransferResult res;
|
FileTransferResult res;
|
||||||
|
|
|
@ -280,21 +280,21 @@ template<> void BaseSetting<SandboxMode>::convertToArg(Args & args, const std::s
|
||||||
.aliases = aliases,
|
.aliases = aliases,
|
||||||
.description = "Enable sandboxing.",
|
.description = "Enable sandboxing.",
|
||||||
.category = category,
|
.category = category,
|
||||||
.handler = {[this]() { override(smEnabled); }}
|
.handler = {[this]() { override(smEnabled); }},
|
||||||
});
|
});
|
||||||
args.addFlag({
|
args.addFlag({
|
||||||
.longName = "no-" + name,
|
.longName = "no-" + name,
|
||||||
.aliases = aliases,
|
.aliases = aliases,
|
||||||
.description = "Disable sandboxing.",
|
.description = "Disable sandboxing.",
|
||||||
.category = category,
|
.category = category,
|
||||||
.handler = {[this]() { override(smDisabled); }}
|
.handler = {[this]() { override(smDisabled); }},
|
||||||
});
|
});
|
||||||
args.addFlag({
|
args.addFlag({
|
||||||
.longName = "relaxed-" + name,
|
.longName = "relaxed-" + name,
|
||||||
.aliases = aliases,
|
.aliases = aliases,
|
||||||
.description = "Enable sandboxing, but allow builds to disable it.",
|
.description = "Enable sandboxing, but allow builds to disable it.",
|
||||||
.category = category,
|
.category = category,
|
||||||
.handler = {[this]() { override(smRelaxed); }}
|
.handler = {[this]() { override(smRelaxed); }},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,7 @@ struct FileTransferRequest
|
||||||
FileTransferRequest(std::string_view uri)
|
FileTransferRequest(std::string_view uri)
|
||||||
: uri(uri), parentAct(getCurActivity()) { }
|
: uri(uri), parentAct(getCurActivity()) { }
|
||||||
|
|
||||||
std::string verb()
|
std::string verb() const
|
||||||
{
|
{
|
||||||
return data ? "upload" : "download";
|
return data ? "upload" : "download";
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
include_dirs += include_directories('../..')
|
include_dirs += include_directories('../..')
|
||||||
|
|
||||||
headers += files(
|
headers += files(
|
||||||
'fchmodat2-compat.hh',
|
|
||||||
'personality.hh',
|
'personality.hh',
|
||||||
)
|
)
|
||||||
|
|
|
@ -105,28 +105,31 @@ ref<Store> Machine::openStore() const
|
||||||
static std::vector<std::string> expandBuilderLines(const std::string & builders)
|
static std::vector<std::string> expandBuilderLines(const std::string & builders)
|
||||||
{
|
{
|
||||||
std::vector<std::string> result;
|
std::vector<std::string> result;
|
||||||
for (auto line : tokenizeString<std::vector<std::string>>(builders, "\n;")) {
|
for (auto line : tokenizeString<std::vector<std::string>>(builders, "\n")) {
|
||||||
trim(line);
|
|
||||||
line.erase(std::find(line.begin(), line.end(), '#'), line.end());
|
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] == '@') {
|
if (entry.empty()) {
|
||||||
const std::string path = trim(std::string(line, 1));
|
// skip blank entries
|
||||||
std::string text;
|
} else if (entry[0] == '@') {
|
||||||
try {
|
const std::string path = trim(std::string_view{entry}.substr(1));
|
||||||
text = readFile(path);
|
std::string text;
|
||||||
} catch (const SysError & e) {
|
try {
|
||||||
if (e.errNo != ENOENT)
|
text = readFile(path);
|
||||||
throw;
|
} catch (const SysError & e) {
|
||||||
debug("cannot find machines file '%s'", path);
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -160,7 +160,10 @@ ref<Aws::Client::ClientConfiguration> S3Helper::makeConfig(
|
||||||
S3Helper::FileTransferResult S3Helper::getObject(
|
S3Helper::FileTransferResult S3Helper::getObject(
|
||||||
const std::string & bucketName, const std::string & key)
|
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 =
|
auto request =
|
||||||
Aws::S3::Model::GetObjectRequest()
|
Aws::S3::Model::GetObjectRequest()
|
||||||
|
@ -171,6 +174,22 @@ S3Helper::FileTransferResult S3Helper::getObject(
|
||||||
return Aws::New<std::stringstream>("STRINGSTREAM");
|
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;
|
FileTransferResult res;
|
||||||
|
|
||||||
auto now1 = std::chrono::steady_clock::now();
|
auto now1 = std::chrono::steady_clock::now();
|
||||||
|
@ -180,6 +199,8 @@ S3Helper::FileTransferResult S3Helper::getObject(
|
||||||
auto result = checkAws(fmt("AWS error fetching '%s'", key),
|
auto result = checkAws(fmt("AWS error fetching '%s'", key),
|
||||||
client->GetObject(request));
|
client->GetObject(request));
|
||||||
|
|
||||||
|
act.progress(result.GetContentLength(), result.GetContentLength());
|
||||||
|
|
||||||
res.data = decompress(result.GetContentEncoding(),
|
res.data = decompress(result.GetContentEncoding(),
|
||||||
dynamic_cast<std::stringstream &>(result.GetBody()).str());
|
dynamic_cast<std::stringstream &>(result.GetBody()).str());
|
||||||
|
|
||||||
|
@ -307,11 +328,35 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual
|
||||||
std::shared_ptr<TransferManager> transferManager;
|
std::shared_ptr<TransferManager> transferManager;
|
||||||
std::once_flag transferManagerCreated;
|
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,
|
void uploadFile(const std::string & path,
|
||||||
std::shared_ptr<std::basic_iostream<char>> istream,
|
std::shared_ptr<std::basic_iostream<char>> istream,
|
||||||
const std::string & mimeType,
|
const std::string & mimeType,
|
||||||
const std::string & contentEncoding)
|
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);
|
istream->seekg(0, istream->end);
|
||||||
auto size = istream->tellg();
|
auto size = istream->tellg();
|
||||||
istream->seekg(0, istream->beg);
|
istream->seekg(0, istream->beg);
|
||||||
|
@ -330,16 +375,25 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual
|
||||||
transferConfig.bufferSize = bufferSize;
|
transferConfig.bufferSize = bufferSize;
|
||||||
|
|
||||||
transferConfig.uploadProgressCallback =
|
transferConfig.uploadProgressCallback =
|
||||||
[](const TransferManager *transferManager,
|
[](const TransferManager * transferManager,
|
||||||
const std::shared_ptr<const TransferHandle>
|
const std::shared_ptr<const TransferHandle> & transferHandle)
|
||||||
&transferHandle)
|
|
||||||
{
|
{
|
||||||
//FIXME: find a way to properly abort the multipart upload.
|
auto context = std::dynamic_pointer_cast<const AsyncContext>(transferHandle->GetContext());
|
||||||
//checkInterrupt();
|
size_t bytesDone = transferHandle->GetBytesTransferred();
|
||||||
debug("upload progress ('%s'): '%d' of '%d' bytes",
|
size_t bytesTotal = transferHandle->GetBytesTotalSize();
|
||||||
transferHandle->GetKey(),
|
try {
|
||||||
transferHandle->GetBytesTransferred(),
|
checkInterrupt();
|
||||||
transferHandle->GetBytesTotalSize());
|
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);
|
transferManager = TransferManager::Create(transferConfig);
|
||||||
|
@ -353,29 +407,51 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual
|
||||||
if (contentEncoding != "")
|
if (contentEncoding != "")
|
||||||
throw Error("setting a content encoding is not supported with S3 multi-part uploads");
|
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 =
|
std::shared_ptr<TransferHandle> transferHandle =
|
||||||
transferManager->UploadFile(
|
transferManager->UploadFile(
|
||||||
istream, bucketName, path, mimeType,
|
istream, bucketName, path, mimeType,
|
||||||
Aws::Map<Aws::String, Aws::String>(),
|
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",
|
throw Error("AWS error: failed to upload 's3://%s/%s': %s",
|
||||||
bucketName, path, transferHandle->GetLastError().GetMessage());
|
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",
|
throw Error("AWS error: transfer status of 's3://%s/%s' in unexpected state",
|
||||||
bucketName, path);
|
bucketName, path);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
act.progress(0, size);
|
||||||
|
|
||||||
auto request =
|
auto request =
|
||||||
Aws::S3::Model::PutObjectRequest()
|
Aws::S3::Model::PutObjectRequest()
|
||||||
.WithBucket(bucketName)
|
.WithBucket(bucketName)
|
||||||
.WithKey(path);
|
.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);
|
request.SetContentType(mimeType);
|
||||||
|
|
||||||
if (contentEncoding != "")
|
if (contentEncoding != "")
|
||||||
|
@ -385,6 +461,8 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual
|
||||||
|
|
||||||
auto result = checkAws(fmt("AWS error uploading '%s'", path),
|
auto result = checkAws(fmt("AWS error uploading '%s'", path),
|
||||||
s3Helper.client->PutObject(request));
|
s3Helper.client->PutObject(request));
|
||||||
|
|
||||||
|
act.progress(size, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto now2 = std::chrono::steady_clock::now();
|
auto now2 = std::chrono::steady_clock::now();
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
|
|
||||||
/* Includes required for chroot support. */
|
/* Includes required for chroot support. */
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
# include "nix/store/fchmodat2-compat.hh"
|
# include "linux/fchmodat2-compat.hh"
|
||||||
# include <sys/ioctl.h>
|
# include <sys/ioctl.h>
|
||||||
# include <net/if.h>
|
# include <net/if.h>
|
||||||
# include <netinet/ip.h>
|
# include <netinet/ip.h>
|
||||||
|
|
|
@ -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;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -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
|
|
|
@ -59,6 +59,7 @@ sources = files(
|
||||||
'json-utils.cc',
|
'json-utils.cc',
|
||||||
'logging.cc',
|
'logging.cc',
|
||||||
'lru-cache.cc',
|
'lru-cache.cc',
|
||||||
|
'monitorfdhup.cc',
|
||||||
'nix_api_util.cc',
|
'nix_api_util.cc',
|
||||||
'pool.cc',
|
'pool.cc',
|
||||||
'position.cc',
|
'position.cc',
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#include "util.hh"
|
#include "nix/util/util.hh"
|
||||||
#include "monitor-fd.hh"
|
#include "nix/util/monitor-fd.hh"
|
||||||
|
|
||||||
#include <sys/file.h>
|
#include <sys/file.h>
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
|
@ -647,4 +647,25 @@ nlohmann::json MultiCommand::toJSON()
|
||||||
return res;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -393,8 +393,30 @@ public:
|
||||||
|
|
||||||
nlohmann::json toJSON() override;
|
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:
|
protected:
|
||||||
std::string commandName = "";
|
std::string commandName = "";
|
||||||
|
bool aliasUsed = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
Strings argvToStrings(int argc, char * * argv);
|
Strings argvToStrings(int argc, char * * argv);
|
||||||
|
|
|
@ -26,6 +26,11 @@ static inline bool getInterrupted();
|
||||||
*/
|
*/
|
||||||
void setInterruptThrown();
|
void setInterruptThrown();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @note Does nothing on Windows
|
||||||
|
*/
|
||||||
|
static inline bool isInterrupted();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @note Does nothing on Windows
|
* @note Does nothing on Windows
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -85,17 +85,22 @@ static inline bool getInterrupted()
|
||||||
return unix::_isInterrupted;
|
return unix::_isInterrupted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool isInterrupted()
|
||||||
|
{
|
||||||
|
using namespace unix;
|
||||||
|
return _isInterrupted || (interruptCheck && interruptCheck());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Throw `Interrupted` exception if the process has been interrupted.
|
* Throw `Interrupted` exception if the process has been interrupted.
|
||||||
*
|
*
|
||||||
* Call this in long-running loops and between slow operations to terminate
|
* Call this in long-running loops and between slow operations to terminate
|
||||||
* them as needed.
|
* them as needed.
|
||||||
*/
|
*/
|
||||||
void inline checkInterrupt()
|
inline void checkInterrupt()
|
||||||
{
|
{
|
||||||
using namespace unix;
|
if (isInterrupted())
|
||||||
if (_isInterrupted || (interruptCheck && interruptCheck()))
|
unix::_interrupted();
|
||||||
_interrupted();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -22,7 +22,12 @@ inline void setInterruptThrown()
|
||||||
/* Do nothing for now */
|
/* Do nothing for now */
|
||||||
}
|
}
|
||||||
|
|
||||||
void inline checkInterrupt()
|
static inline bool isInterrupted()
|
||||||
|
{
|
||||||
|
/* Do nothing for now */
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void checkInterrupt()
|
||||||
{
|
{
|
||||||
/* Do nothing for now */
|
/* Do nothing for now */
|
||||||
}
|
}
|
||||||
|
|
|
@ -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`.",
|
.description = "Use *path* as prefix for the symlinks to the build results. It defaults to `result`.",
|
||||||
.labels = {"path"},
|
.labels = {"path"},
|
||||||
.handler = {&outLink},
|
.handler = {&outLink},
|
||||||
.completer = completePath
|
.completer = completePath,
|
||||||
});
|
});
|
||||||
|
|
||||||
addFlag({
|
addFlag({
|
||||||
|
|
|
@ -24,7 +24,7 @@ struct CmdBundle : InstallableValueCommand
|
||||||
.handler = {&bundler},
|
.handler = {&bundler},
|
||||||
.completer = {[&](AddCompletions & completions, size_t, std::string_view prefix) {
|
.completer = {[&](AddCompletions & completions, size_t, std::string_view prefix) {
|
||||||
completeFlakeRef(completions, getStore(), prefix);
|
completeFlakeRef(completions, getStore(), prefix);
|
||||||
}}
|
}},
|
||||||
});
|
});
|
||||||
|
|
||||||
addFlag({
|
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.",
|
.description = "Override the name of the symlink to the build result. It defaults to the base name of the app.",
|
||||||
.labels = {"path"},
|
.labels = {"path"},
|
||||||
.handler = {&outLink},
|
.handler = {&outLink},
|
||||||
.completer = completePath
|
.completer = completePath,
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.",
|
.description = "Create symlinks prefixed with *path* to the top-level store paths fetched from the source store.",
|
||||||
.labels = {"path"},
|
.labels = {"path"},
|
||||||
.handler = {&outLink},
|
.handler = {&outLink},
|
||||||
.completer = completePath
|
.completer = completePath,
|
||||||
});
|
});
|
||||||
|
|
||||||
addFlag({
|
addFlag({
|
||||||
|
|
|
@ -21,7 +21,7 @@ struct CmdShowDerivation : InstallablesCommand
|
||||||
.longName = "recursive",
|
.longName = "recursive",
|
||||||
.shortName = 'r',
|
.shortName = 'r',
|
||||||
.description = "Include the dependencies of the specified derivations.",
|
.description = "Include the dependencies of the specified derivations.",
|
||||||
.handler = {&recursive, true}
|
.handler = {&recursive, true},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -334,7 +334,7 @@ struct Common : InstallableCommand, MixProfile
|
||||||
.labels = {"installable", "outputs-dir"},
|
.labels = {"installable", "outputs-dir"},
|
||||||
.handler = {[&](std::string installable, std::string outputsDir) {
|
.handler = {[&](std::string installable, std::string outputsDir) {
|
||||||
redirects.push_back({installable, outputsDir});
|
redirects.push_back({installable, outputsDir});
|
||||||
}}
|
}},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -524,7 +524,7 @@ struct CmdDevelop : Common, MixEnvironment
|
||||||
.handler = {[&](std::vector<std::string> ss) {
|
.handler = {[&](std::vector<std::string> ss) {
|
||||||
if (ss.empty()) throw UsageError("--command requires at least one argument");
|
if (ss.empty()) throw UsageError("--command requires at least one argument");
|
||||||
command = ss;
|
command = ss;
|
||||||
}}
|
}},
|
||||||
});
|
});
|
||||||
|
|
||||||
addFlag({
|
addFlag({
|
||||||
|
|
|
@ -38,16 +38,17 @@ struct CmdShell : InstallablesCommand, MixEnvironment
|
||||||
|
|
||||||
CmdShell()
|
CmdShell()
|
||||||
{
|
{
|
||||||
addFlag(
|
addFlag({
|
||||||
{.longName = "command",
|
.longName = "command",
|
||||||
.shortName = 'c',
|
.shortName = 'c',
|
||||||
.description = "Command and arguments to be executed, defaulting to `$SHELL`",
|
.description = "Command and arguments to be executed, defaulting to `$SHELL`",
|
||||||
.labels = {"command", "args"},
|
.labels = {"command", "args"},
|
||||||
.handler = {[&](std::vector<std::string> ss) {
|
.handler = {[&](std::vector<std::string> ss) {
|
||||||
if (ss.empty())
|
if (ss.empty())
|
||||||
throw UsageError("--command requires at least one argument");
|
throw UsageError("--command requires at least one argument");
|
||||||
command = ss;
|
command = ss;
|
||||||
}}});
|
}},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string description() override
|
std::string description() override
|
||||||
|
|
|
@ -90,7 +90,7 @@ public:
|
||||||
.handler={&flakeUrl},
|
.handler={&flakeUrl},
|
||||||
.completer = {[&](AddCompletions & completions, size_t, std::string_view prefix) {
|
.completer = {[&](AddCompletions & completions, size_t, std::string_view prefix) {
|
||||||
completeFlakeRef(completions, getStore(), prefix);
|
completeFlakeRef(completions, getStore(), prefix);
|
||||||
}}
|
}},
|
||||||
});
|
});
|
||||||
expectArgs({
|
expectArgs({
|
||||||
.label="inputs",
|
.label="inputs",
|
||||||
|
@ -111,7 +111,7 @@ public:
|
||||||
}},
|
}},
|
||||||
.completer = {[&](AddCompletions & completions, size_t, std::string_view prefix) {
|
.completer = {[&](AddCompletions & completions, size_t, std::string_view prefix) {
|
||||||
completeFlakeInputAttrPath(completions, getEvalState(), getFlakeRefsForCompletion(), prefix);
|
completeFlakeInputAttrPath(completions, getEvalState(), getFlakeRefsForCompletion(), prefix);
|
||||||
}}
|
}},
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Remove flags that don't make sense. */
|
/* Remove flags that don't make sense. */
|
||||||
|
@ -342,12 +342,12 @@ struct CmdFlakeCheck : FlakeCommand
|
||||||
addFlag({
|
addFlag({
|
||||||
.longName = "no-build",
|
.longName = "no-build",
|
||||||
.description = "Do not build checks.",
|
.description = "Do not build checks.",
|
||||||
.handler = {&build, false}
|
.handler = {&build, false},
|
||||||
});
|
});
|
||||||
addFlag({
|
addFlag({
|
||||||
.longName = "all-systems",
|
.longName = "all-systems",
|
||||||
.description = "Check the outputs for 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,
|
defaultTemplateAttrPathsPrefixes,
|
||||||
defaultTemplateAttrPaths,
|
defaultTemplateAttrPaths,
|
||||||
prefix);
|
prefix);
|
||||||
}}
|
}},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1040,7 +1040,7 @@ struct CmdFlakeClone : FlakeCommand
|
||||||
.shortName = 'f',
|
.shortName = 'f',
|
||||||
.description = "Clone the flake to path *dest*.",
|
.description = "Clone the flake to path *dest*.",
|
||||||
.labels = {"path"},
|
.labels = {"path"},
|
||||||
.handler = {&destDir}
|
.handler = {&destDir},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1063,7 +1063,7 @@ struct CmdFlakeArchive : FlakeCommand, MixJSON, MixDryRun
|
||||||
.longName = "to",
|
.longName = "to",
|
||||||
.description = "URI of the destination Nix store",
|
.description = "URI of the destination Nix store",
|
||||||
.labels = {"store-uri"},
|
.labels = {"store-uri"},
|
||||||
.handler = {&dstUri}
|
.handler = {&dstUri},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1146,12 +1146,12 @@ struct CmdFlakeShow : FlakeCommand, MixJSON
|
||||||
addFlag({
|
addFlag({
|
||||||
.longName = "legacy",
|
.longName = "legacy",
|
||||||
.description = "Show the contents of the `legacyPackages` output.",
|
.description = "Show the contents of the `legacyPackages` output.",
|
||||||
.handler = {&showLegacy, true}
|
.handler = {&showLegacy, true},
|
||||||
});
|
});
|
||||||
addFlag({
|
addFlag({
|
||||||
.longName = "all-systems",
|
.longName = "all-systems",
|
||||||
.description = "Show the contents of outputs for 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.",
|
.description = "Create symlink named *path* to the resulting store path.",
|
||||||
.labels = {"path"},
|
.labels = {"path"},
|
||||||
.handler = {&outLink},
|
.handler = {&outLink},
|
||||||
.completer = completePath
|
.completer = completePath,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,19 +51,6 @@ void chrootHelper(int argc, char * * argv);
|
||||||
|
|
||||||
namespace nix {
|
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. */
|
/* Check if we have a non-loopback/link-local network interface. */
|
||||||
static bool haveInternet()
|
static bool haveInternet()
|
||||||
{
|
{
|
||||||
|
@ -151,54 +138,34 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs, virtual RootArgs
|
||||||
.category = miscCategory,
|
.category = miscCategory,
|
||||||
.handler = {[&]() { refresh = true; }},
|
.handler = {[&]() { refresh = true; }},
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
std::map<std::string, AliasInfo> aliases = {
|
aliases = {
|
||||||
{"add-to-store", { AliasStatus::Deprecated, {"store", "add-path"}}},
|
{"add-to-store", { AliasStatus::Deprecated, {"store", "add-path"}}},
|
||||||
{"cat-nar", { AliasStatus::Deprecated, {"nar", "cat"}}},
|
{"cat-nar", { AliasStatus::Deprecated, {"nar", "cat"}}},
|
||||||
{"cat-store", { AliasStatus::Deprecated, {"store", "cat"}}},
|
{"cat-store", { AliasStatus::Deprecated, {"store", "cat"}}},
|
||||||
{"copy-sigs", { AliasStatus::Deprecated, {"store", "copy-sigs"}}},
|
{"copy-sigs", { AliasStatus::Deprecated, {"store", "copy-sigs"}}},
|
||||||
{"dev-shell", { AliasStatus::Deprecated, {"develop"}}},
|
{"dev-shell", { AliasStatus::Deprecated, {"develop"}}},
|
||||||
{"diff-closures", { AliasStatus::Deprecated, {"store", "diff-closures"}}},
|
{"diff-closures", { AliasStatus::Deprecated, {"store", "diff-closures"}}},
|
||||||
{"dump-path", { AliasStatus::Deprecated, {"store", "dump-path"}}},
|
{"dump-path", { AliasStatus::Deprecated, {"store", "dump-path"}}},
|
||||||
{"hash-file", { AliasStatus::Deprecated, {"hash", "file"}}},
|
{"hash-file", { AliasStatus::Deprecated, {"hash", "file"}}},
|
||||||
{"hash-path", { AliasStatus::Deprecated, {"hash", "path"}}},
|
{"hash-path", { AliasStatus::Deprecated, {"hash", "path"}}},
|
||||||
{"ls-nar", { AliasStatus::Deprecated, {"nar", "ls"}}},
|
{"ls-nar", { AliasStatus::Deprecated, {"nar", "ls"}}},
|
||||||
{"ls-store", { AliasStatus::Deprecated, {"store", "ls"}}},
|
{"ls-store", { AliasStatus::Deprecated, {"store", "ls"}}},
|
||||||
{"make-content-addressable", { AliasStatus::Deprecated, {"store", "make-content-addressed"}}},
|
{"make-content-addressable", { AliasStatus::Deprecated, {"store", "make-content-addressed"}}},
|
||||||
{"optimise-store", { AliasStatus::Deprecated, {"store", "optimise"}}},
|
{"optimise-store", { AliasStatus::Deprecated, {"store", "optimise"}}},
|
||||||
{"ping-store", { AliasStatus::Deprecated, {"store", "info"}}},
|
{"ping-store", { AliasStatus::Deprecated, {"store", "info"}}},
|
||||||
{"sign-paths", { AliasStatus::Deprecated, {"store", "sign"}}},
|
{"sign-paths", { AliasStatus::Deprecated, {"store", "sign"}}},
|
||||||
{"shell", { AliasStatus::AcceptedShorthand, {"env", "shell"}}},
|
{"shell", { AliasStatus::AcceptedShorthand, {"env", "shell"}}},
|
||||||
{"show-derivation", { AliasStatus::Deprecated, {"derivation", "show"}}},
|
{"show-derivation", { AliasStatus::Deprecated, {"derivation", "show"}}},
|
||||||
{"show-config", { AliasStatus::Deprecated, {"config", "show"}}},
|
{"show-config", { AliasStatus::Deprecated, {"config", "show"}}},
|
||||||
{"to-base16", { AliasStatus::Deprecated, {"hash", "to-base16"}}},
|
{"to-base16", { AliasStatus::Deprecated, {"hash", "to-base16"}}},
|
||||||
{"to-base32", { AliasStatus::Deprecated, {"hash", "to-base32"}}},
|
{"to-base32", { AliasStatus::Deprecated, {"hash", "to-base32"}}},
|
||||||
{"to-base64", { AliasStatus::Deprecated, {"hash", "to-base64"}}},
|
{"to-base64", { AliasStatus::Deprecated, {"hash", "to-base64"}}},
|
||||||
{"verify", { AliasStatus::Deprecated, {"store", "verify"}}},
|
{"verify", { AliasStatus::Deprecated, {"store", "verify"}}},
|
||||||
{"doctor", { AliasStatus::Deprecated, {"config", "check"}}},
|
{"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
|
std::string description() override
|
||||||
{
|
{
|
||||||
return "a tool for reproducible and declarative configuration management";
|
return "a tool for reproducible and declarative configuration management";
|
||||||
|
|
|
@ -7,7 +7,7 @@ project('nix', 'cpp',
|
||||||
'errorlogs=true', # Please print logs for tests that fail
|
'errorlogs=true', # Please print logs for tests that fail
|
||||||
'localstatedir=/nix/var',
|
'localstatedir=/nix/var',
|
||||||
],
|
],
|
||||||
meson_version : '>= 1.1',
|
meson_version : '>= 1.4',
|
||||||
license : 'LGPL-2.1-or-later',
|
license : 'LGPL-2.1-or-later',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -275,7 +275,7 @@ struct CmdStorePrefetchFile : StoreCommand, MixJSON
|
||||||
.longName = "name",
|
.longName = "name",
|
||||||
.description = "Override the name component of the resulting store path. It defaults to the base name of *url*.",
|
.description = "Override the name component of the resulting store path. It defaults to the base name of *url*.",
|
||||||
.labels = {"name"},
|
.labels = {"name"},
|
||||||
.handler = {&name}
|
.handler = {&name},
|
||||||
});
|
});
|
||||||
|
|
||||||
addFlag({
|
addFlag({
|
||||||
|
@ -284,7 +284,7 @@ struct CmdStorePrefetchFile : StoreCommand, MixJSON
|
||||||
.labels = {"hash"},
|
.labels = {"hash"},
|
||||||
.handler = {[&](std::string s) {
|
.handler = {[&](std::string s) {
|
||||||
expectedHash = Hash::parseAny(s, hashAlgo);
|
expectedHash = Hash::parseAny(s, hashAlgo);
|
||||||
}}
|
}},
|
||||||
});
|
});
|
||||||
|
|
||||||
addFlag(flag::hashAlgo("hash-type", &hashAlgo));
|
addFlag(flag::hashAlgo("hash-type", &hashAlgo));
|
||||||
|
|
37
src/nix/profile-add.md
Normal file
37
src/nix/profile-add.md
Normal 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.
|
||||||
|
|
||||||
|
)""
|
|
@ -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.
|
|
||||||
|
|
||||||
)""
|
|
|
@ -338,14 +338,14 @@ builtPathsPerInstallable(
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile
|
struct CmdProfileAdd : InstallablesCommand, MixDefaultProfile
|
||||||
{
|
{
|
||||||
std::optional<int64_t> priority;
|
std::optional<int64_t> priority;
|
||||||
|
|
||||||
CmdProfileInstall() {
|
CmdProfileAdd() {
|
||||||
addFlag({
|
addFlag({
|
||||||
.longName = "priority",
|
.longName = "priority",
|
||||||
.description = "The priority of the package to install.",
|
.description = "The priority of the package to add.",
|
||||||
.labels = {"priority"},
|
.labels = {"priority"},
|
||||||
.handler = {&priority},
|
.handler = {&priority},
|
||||||
});
|
});
|
||||||
|
@ -353,13 +353,13 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile
|
||||||
|
|
||||||
std::string description() override
|
std::string description() override
|
||||||
{
|
{
|
||||||
return "install a package into a profile";
|
return "add a package to a profile";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string doc() override
|
std::string doc() override
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
#include "profile-install.md"
|
#include "profile-add.md"
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -415,7 +415,7 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile
|
||||||
&& existingSource->originalRef == elementSource->originalRef
|
&& existingSource->originalRef == elementSource->originalRef
|
||||||
&& existingSource->attrPath == elementSource->attrPath
|
&& existingSource->attrPath == elementSource->attrPath
|
||||||
) {
|
) {
|
||||||
warn("'%s' is already installed", elementName);
|
warn("'%s' is already added", elementName);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -462,15 +462,15 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile
|
||||||
"\n"
|
"\n"
|
||||||
" nix profile remove %3%\n"
|
" nix profile remove %3%\n"
|
||||||
"\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"
|
"The conflicting packages have a priority of %5%.\n"
|
||||||
"To prioritise the new package:\n"
|
"To prioritise the new package:\n"
|
||||||
"\n"
|
"\n"
|
||||||
" nix profile install %4% --priority %6%\n"
|
" nix profile add %4% --priority %6%\n"
|
||||||
"\n"
|
"\n"
|
||||||
"To prioritise the existing package:\n"
|
"To prioritise the existing package:\n"
|
||||||
"\n"
|
"\n"
|
||||||
" nix profile install %4% --priority %7%\n",
|
" nix profile add %4% --priority %7%\n",
|
||||||
originalConflictingFilePath,
|
originalConflictingFilePath,
|
||||||
newConflictingFilePath,
|
newConflictingFilePath,
|
||||||
originalEntryName,
|
originalEntryName,
|
||||||
|
@ -708,16 +708,14 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf
|
||||||
|
|
||||||
if (!element.source) {
|
if (!element.source) {
|
||||||
warn(
|
warn(
|
||||||
"Found package '%s', but it was not installed from a flake, so it can't be checked for upgrades!",
|
"Found package '%s', but it was not added from a flake, so it can't be checked for upgrades!",
|
||||||
element.identifier()
|
element.identifier());
|
||||||
);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (element.source->originalRef.input.isLocked()) {
|
if (element.source->originalRef.input.isLocked()) {
|
||||||
warn(
|
warn(
|
||||||
"Found package '%s', but it was installed from a locked flake reference so it can't be upgraded!",
|
"Found package '%s', but it was added from a locked flake reference so it can't be upgraded!",
|
||||||
element.identifier()
|
element.identifier());
|
||||||
);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -787,7 +785,7 @@ struct CmdProfileList : virtual EvalCommand, virtual StoreCommand, MixDefaultPro
|
||||||
{
|
{
|
||||||
std::string description() override
|
std::string description() override
|
||||||
{
|
{
|
||||||
return "list installed packages";
|
return "list packages in the profile";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string doc() override
|
std::string doc() override
|
||||||
|
@ -978,7 +976,7 @@ struct CmdProfile : NixMultiCommand
|
||||||
: NixMultiCommand(
|
: NixMultiCommand(
|
||||||
"profile",
|
"profile",
|
||||||
{
|
{
|
||||||
{"install", []() { return make_ref<CmdProfileInstall>(); }},
|
{"add", []() { return make_ref<CmdProfileAdd>(); }},
|
||||||
{"remove", []() { return make_ref<CmdProfileRemove>(); }},
|
{"remove", []() { return make_ref<CmdProfileRemove>(); }},
|
||||||
{"upgrade", []() { return make_ref<CmdProfileUpgrade>(); }},
|
{"upgrade", []() { return make_ref<CmdProfileUpgrade>(); }},
|
||||||
{"list", []() { return make_ref<CmdProfileList>(); }},
|
{"list", []() { return make_ref<CmdProfileList>(); }},
|
||||||
|
@ -987,7 +985,11 @@ struct CmdProfile : NixMultiCommand
|
||||||
{"rollback", []() { return make_ref<CmdProfileRollback>(); }},
|
{"rollback", []() { return make_ref<CmdProfileRollback>(); }},
|
||||||
{"wipe-history", []() { return make_ref<CmdProfileWipeHistory>(); }},
|
{"wipe-history", []() { return make_ref<CmdProfileWipeHistory>(); }},
|
||||||
})
|
})
|
||||||
{ }
|
{
|
||||||
|
aliases = {
|
||||||
|
{"install", { AliasStatus::Deprecated, {"add"}}},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
std::string description() override
|
std::string description() override
|
||||||
{
|
{
|
||||||
|
|
|
@ -104,7 +104,7 @@ struct CmdSign : StorePathsCommand
|
||||||
.description = "File containing the secret signing key.",
|
.description = "File containing the secret signing key.",
|
||||||
.labels = {"file"},
|
.labels = {"file"},
|
||||||
.handler = {&secretKeyFile},
|
.handler = {&secretKeyFile},
|
||||||
.completer = completePath
|
.completer = completePath,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ struct CmdStoreDelete : StorePathsCommand
|
||||||
addFlag({
|
addFlag({
|
||||||
.longName = "ignore-liveness",
|
.longName = "ignore-liveness",
|
||||||
.description = "Do not check whether the paths are reachable from a root.",
|
.description = "Do not check whether the paths are reachable from a root.",
|
||||||
.handler = {&options.ignoreLiveness, true}
|
.handler = {&options.ignoreLiveness, true},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ struct CmdStoreGC : StoreCommand, MixDryRun
|
||||||
.longName = "max",
|
.longName = "max",
|
||||||
.description = "Stop after freeing *n* bytes of disk space.",
|
.description = "Stop after freeing *n* bytes of disk space.",
|
||||||
.labels = {"n"},
|
.labels = {"n"},
|
||||||
.handler = {&options.maxFreed}
|
.handler = {&options.maxFreed},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
using namespace nix;
|
using namespace nix;
|
||||||
|
|
||||||
struct CmdPingStore : StoreCommand, MixJSON
|
struct CmdInfoStore : StoreCommand, MixJSON
|
||||||
{
|
{
|
||||||
std::string description() override
|
std::string description() override
|
||||||
{
|
{
|
||||||
|
@ -46,15 +46,4 @@ struct CmdPingStore : StoreCommand, MixJSON
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CmdInfoStore : CmdPingStore
|
static auto rCmdInfoStore = registerCommand2<CmdInfoStore>({"store", "info"});
|
||||||
{
|
|
||||||
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"});
|
|
||||||
|
|
|
@ -5,7 +5,11 @@ using namespace nix;
|
||||||
struct CmdStore : NixMultiCommand
|
struct CmdStore : NixMultiCommand
|
||||||
{
|
{
|
||||||
CmdStore() : NixMultiCommand("store", RegisterCommand::getCommandsFor({"store"}))
|
CmdStore() : NixMultiCommand("store", RegisterCommand::getCommandsFor({"store"}))
|
||||||
{ }
|
{
|
||||||
|
aliases = {
|
||||||
|
{"ping", { AliasStatus::Deprecated, {"info"}}},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
std::string description() override
|
std::string description() override
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,14 +23,14 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand
|
||||||
.shortName = 'p',
|
.shortName = 'p',
|
||||||
.description = "The path to the Nix profile to upgrade.",
|
.description = "The path to the Nix profile to upgrade.",
|
||||||
.labels = {"profile-dir"},
|
.labels = {"profile-dir"},
|
||||||
.handler = {&profileDir}
|
.handler = {&profileDir},
|
||||||
});
|
});
|
||||||
|
|
||||||
addFlag({
|
addFlag({
|
||||||
.longName = "nix-store-paths-url",
|
.longName = "nix-store-paths-url",
|
||||||
.description = "The URL of the file that contains the store paths of the latest Nix release.",
|
.description = "The URL of the file that contains the store paths of the latest Nix release.",
|
||||||
.labels = {"url"},
|
.labels = {"url"},
|
||||||
.handler = {&(std::string&) settings.upgradeNixStorePathUrl}
|
.handler = {&(std::string&) settings.upgradeNixStorePathUrl},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ struct CmdVerify : StorePathsCommand
|
||||||
.shortName = 's',
|
.shortName = 's',
|
||||||
.description = "Use signatures from the specified store.",
|
.description = "Use signatures from the specified store.",
|
||||||
.labels = {"store-uri"},
|
.labels = {"store-uri"},
|
||||||
.handler = {[&](std::string s) { substituterUris.push_back(s); }}
|
.handler = {[&](std::string s) { substituterUris.push_back(s); }},
|
||||||
});
|
});
|
||||||
|
|
||||||
addFlag({
|
addFlag({
|
||||||
|
@ -45,7 +45,7 @@ struct CmdVerify : StorePathsCommand
|
||||||
.shortName = 'n',
|
.shortName = 'n',
|
||||||
.description = "Require that each path is signed by at least *n* different keys.",
|
.description = "Require that each path is signed by at least *n* different keys.",
|
||||||
.labels = {"n"},
|
.labels = {"n"},
|
||||||
.handler = {&sigsNeeded}
|
.handler = {&sigsNeeded},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,6 @@ file=build-hook-ca-floating.nix
|
||||||
|
|
||||||
enableFeatures "ca-derivations"
|
enableFeatures "ca-derivations"
|
||||||
|
|
||||||
CONTENT_ADDRESSED=true
|
NIX_TESTS_CA_BY_DEFAULT=true
|
||||||
|
|
||||||
source build-remote.sh
|
source build-remote.sh
|
||||||
|
|
|
@ -13,7 +13,7 @@ unset NIX_STATE_DIR
|
||||||
function join_by { local d=$1; shift; echo -n "$1"; shift; printf "%s" "${@/#/$d}"; }
|
function join_by { local d=$1; shift; echo -n "$1"; shift; printf "%s" "${@/#/$d}"; }
|
||||||
|
|
||||||
EXTRA_SYSTEM_FEATURES=()
|
EXTRA_SYSTEM_FEATURES=()
|
||||||
if [[ -n "${CONTENT_ADDRESSED-}" ]]; then
|
if [[ -n "${NIX_TESTS_CA_BY_DEFAULT-}" ]]; then
|
||||||
EXTRA_SYSTEM_FEATURES=("ca-derivations")
|
EXTRA_SYSTEM_FEATURES=("ca-derivations")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
6
tests/functional/ca/derivation-advanced-attributes.sh
Executable file
6
tests/functional/ca/derivation-advanced-attributes.sh
Executable file
|
@ -0,0 +1,6 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
export NIX_TESTS_CA_BY_DEFAULT=1
|
||||||
|
|
||||||
|
cd ..
|
||||||
|
source derivation-advanced-attributes.sh
|
|
@ -8,10 +8,11 @@ suites += {
|
||||||
'name': 'ca',
|
'name': 'ca',
|
||||||
'deps': [],
|
'deps': [],
|
||||||
'tests': [
|
'tests': [
|
||||||
|
'build-cache.sh',
|
||||||
'build-with-garbage-path.sh',
|
'build-with-garbage-path.sh',
|
||||||
'build.sh',
|
'build.sh',
|
||||||
'build-cache.sh',
|
|
||||||
'concurrent-builds.sh',
|
'concurrent-builds.sh',
|
||||||
|
'derivation-advanced-attributes.sh',
|
||||||
'derivation-json.sh',
|
'derivation-json.sh',
|
||||||
'duplicate-realisation-in-closure.sh',
|
'duplicate-realisation-in-closure.sh',
|
||||||
'eval-store.sh',
|
'eval-store.sh',
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
|
|
||||||
source common.sh
|
source common.sh
|
||||||
|
|
||||||
CONTENT_ADDRESSED=true
|
NIX_TESTS_CA_BY_DEFAULT=true
|
||||||
cd ..
|
cd ..
|
||||||
source ./nix-shell.sh
|
source ./nix-shell.sh
|
||||||
|
|
|
@ -12,11 +12,19 @@ badExitCode=0
|
||||||
|
|
||||||
store="$TEST_ROOT/store"
|
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
|
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)
|
testName=$(basename "$nixFile" .nix)
|
||||||
got="${store}${drvPath}"
|
got="${store}${drvPath}"
|
||||||
expected="derivation/$testName.drv"
|
expected="derivation/${drvDir}/${testName}.drv"
|
||||||
diffAndAcceptInner "$testName" "$got" "$expected"
|
diffAndAcceptInner "$testName" "$got" "$expected"
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,24 @@
|
||||||
derivation {
|
{ contentAddress }:
|
||||||
name = "advanced-attributes-defaults";
|
|
||||||
|
let
|
||||||
|
caArgs =
|
||||||
|
if contentAddress then
|
||||||
|
{
|
||||||
|
__contentAddressed = true;
|
||||||
|
outputHashMode = "recursive";
|
||||||
|
outputHashAlgo = "sha256";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ };
|
||||||
|
|
||||||
|
derivation' = args: derivation (caArgs // args);
|
||||||
|
|
||||||
system = "my-system";
|
system = "my-system";
|
||||||
|
|
||||||
|
in
|
||||||
|
derivation' {
|
||||||
|
inherit system;
|
||||||
|
name = "advanced-attributes-defaults";
|
||||||
builder = "/bin/bash";
|
builder = "/bin/bash";
|
||||||
args = [
|
args = [
|
||||||
"-c"
|
"-c"
|
||||||
|
|
|
@ -1,6 +1,24 @@
|
||||||
derivation {
|
{ contentAddress }:
|
||||||
name = "advanced-attributes-structured-attrs-defaults";
|
|
||||||
|
let
|
||||||
|
caArgs =
|
||||||
|
if contentAddress then
|
||||||
|
{
|
||||||
|
__contentAddressed = true;
|
||||||
|
outputHashMode = "recursive";
|
||||||
|
outputHashAlgo = "sha256";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ };
|
||||||
|
|
||||||
|
derivation' = args: derivation (caArgs // args);
|
||||||
|
|
||||||
system = "my-system";
|
system = "my-system";
|
||||||
|
|
||||||
|
in
|
||||||
|
derivation' {
|
||||||
|
inherit system;
|
||||||
|
name = "advanced-attributes-structured-attrs-defaults";
|
||||||
builder = "/bin/bash";
|
builder = "/bin/bash";
|
||||||
args = [
|
args = [
|
||||||
"-c"
|
"-c"
|
||||||
|
|
|
@ -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")])
|
|
|
@ -1,6 +1,21 @@
|
||||||
|
{ contentAddress }:
|
||||||
|
|
||||||
let
|
let
|
||||||
|
caArgs =
|
||||||
|
if contentAddress then
|
||||||
|
{
|
||||||
|
__contentAddressed = true;
|
||||||
|
outputHashMode = "recursive";
|
||||||
|
outputHashAlgo = "sha256";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ };
|
||||||
|
|
||||||
|
derivation' = args: derivation (caArgs // args);
|
||||||
|
|
||||||
system = "my-system";
|
system = "my-system";
|
||||||
foo = derivation {
|
|
||||||
|
foo = derivation' {
|
||||||
inherit system;
|
inherit system;
|
||||||
name = "foo";
|
name = "foo";
|
||||||
builder = "/bin/bash";
|
builder = "/bin/bash";
|
||||||
|
@ -8,8 +23,13 @@ let
|
||||||
"-c"
|
"-c"
|
||||||
"echo foo > $out"
|
"echo foo > $out"
|
||||||
];
|
];
|
||||||
|
outputs = [
|
||||||
|
"out"
|
||||||
|
"dev"
|
||||||
|
];
|
||||||
};
|
};
|
||||||
bar = derivation {
|
|
||||||
|
bar = derivation' {
|
||||||
inherit system;
|
inherit system;
|
||||||
name = "bar";
|
name = "bar";
|
||||||
builder = "/bin/bash";
|
builder = "/bin/bash";
|
||||||
|
@ -17,9 +37,14 @@ let
|
||||||
"-c"
|
"-c"
|
||||||
"echo bar > $out"
|
"echo bar > $out"
|
||||||
];
|
];
|
||||||
|
outputs = [
|
||||||
|
"out"
|
||||||
|
"dev"
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
in
|
in
|
||||||
derivation {
|
derivation' {
|
||||||
inherit system;
|
inherit system;
|
||||||
name = "advanced-attributes-structured-attrs";
|
name = "advanced-attributes-structured-attrs";
|
||||||
builder = "/bin/bash";
|
builder = "/bin/bash";
|
||||||
|
@ -41,11 +66,11 @@ derivation {
|
||||||
outputChecks = {
|
outputChecks = {
|
||||||
out = {
|
out = {
|
||||||
allowedReferences = [ foo ];
|
allowedReferences = [ foo ];
|
||||||
allowedRequisites = [ foo ];
|
allowedRequisites = [ foo.dev ];
|
||||||
};
|
};
|
||||||
bin = {
|
bin = {
|
||||||
disallowedReferences = [ bar ];
|
disallowedReferences = [ bar ];
|
||||||
disallowedRequisites = [ bar ];
|
disallowedRequisites = [ bar.dev ];
|
||||||
};
|
};
|
||||||
dev = {
|
dev = {
|
||||||
maxSize = 789;
|
maxSize = 789;
|
||||||
|
|
|
@ -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")])
|
|
|
@ -1,6 +1,21 @@
|
||||||
|
{ contentAddress }:
|
||||||
|
|
||||||
let
|
let
|
||||||
|
caArgs =
|
||||||
|
if contentAddress then
|
||||||
|
{
|
||||||
|
__contentAddressed = true;
|
||||||
|
outputHashMode = "recursive";
|
||||||
|
outputHashAlgo = "sha256";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ };
|
||||||
|
|
||||||
|
derivation' = args: derivation (caArgs // args);
|
||||||
|
|
||||||
system = "my-system";
|
system = "my-system";
|
||||||
foo = derivation {
|
|
||||||
|
foo = derivation' {
|
||||||
inherit system;
|
inherit system;
|
||||||
name = "foo";
|
name = "foo";
|
||||||
builder = "/bin/bash";
|
builder = "/bin/bash";
|
||||||
|
@ -8,8 +23,13 @@ let
|
||||||
"-c"
|
"-c"
|
||||||
"echo foo > $out"
|
"echo foo > $out"
|
||||||
];
|
];
|
||||||
|
outputs = [
|
||||||
|
"out"
|
||||||
|
"dev"
|
||||||
|
];
|
||||||
};
|
};
|
||||||
bar = derivation {
|
|
||||||
|
bar = derivation' {
|
||||||
inherit system;
|
inherit system;
|
||||||
name = "bar";
|
name = "bar";
|
||||||
builder = "/bin/bash";
|
builder = "/bin/bash";
|
||||||
|
@ -17,9 +37,14 @@ let
|
||||||
"-c"
|
"-c"
|
||||||
"echo bar > $out"
|
"echo bar > $out"
|
||||||
];
|
];
|
||||||
|
outputs = [
|
||||||
|
"out"
|
||||||
|
"dev"
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
in
|
in
|
||||||
derivation {
|
derivation' {
|
||||||
inherit system;
|
inherit system;
|
||||||
name = "advanced-attributes";
|
name = "advanced-attributes";
|
||||||
builder = "/bin/bash";
|
builder = "/bin/bash";
|
||||||
|
@ -33,9 +58,9 @@ derivation {
|
||||||
impureEnvVars = [ "UNICORN" ];
|
impureEnvVars = [ "UNICORN" ];
|
||||||
__darwinAllowLocalNetworking = true;
|
__darwinAllowLocalNetworking = true;
|
||||||
allowedReferences = [ foo ];
|
allowedReferences = [ foo ];
|
||||||
allowedRequisites = [ foo ];
|
allowedRequisites = [ foo.dev ];
|
||||||
disallowedReferences = [ bar ];
|
disallowedReferences = [ bar ];
|
||||||
disallowedRequisites = [ bar ];
|
disallowedRequisites = [ bar.dev ];
|
||||||
requiredSystemFeatures = [
|
requiredSystemFeatures = [
|
||||||
"rainbow"
|
"rainbow"
|
||||||
"uid-range"
|
"uid-range"
|
||||||
|
|
|
@ -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")])
|
|
@ -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")])
|
|
@ -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")])
|
1
tests/functional/derivation/ca/advanced-attributes.drv
Normal file
1
tests/functional/derivation/ca/advanced-attributes.drv
Normal 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
Loading…
Add table
Add a link
Reference in a new issue