Merge remote-tracking branch 'upstream/master' into ca-drv-exotic
This commit is contained in:
commit
76baaeb341
|
@ -127,7 +127,7 @@
|
||||||
builder can rely on external inputs such as the network or the
|
builder can rely on external inputs such as the network or the
|
||||||
system time) but the Nix model assumes it.
|
system time) but the Nix model assumes it.
|
||||||
|
|
||||||
- Nix database{#gloss-nix-database}\
|
- [Nix database]{#gloss-nix-database}\
|
||||||
An SQlite database to track [reference]s between [store object]s.
|
An SQlite database to track [reference]s between [store object]s.
|
||||||
This is an implementation detail of the [local store].
|
This is an implementation detail of the [local store].
|
||||||
|
|
||||||
|
|
|
@ -136,7 +136,7 @@ which you may remove.
|
||||||
|
|
||||||
### macOS
|
### macOS
|
||||||
|
|
||||||
1. Edit `/etc/zshrc` and `/etc/bashrc` to remove the lines sourcing
|
1. Edit `/etc/zshrc`, `/etc/bashrc`, and `/etc/bash.bashrc` to remove the lines sourcing
|
||||||
`nix-daemon.sh`, which should look like this:
|
`nix-daemon.sh`, which should look like this:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
@ -153,6 +153,7 @@ which you may remove.
|
||||||
```console
|
```console
|
||||||
sudo mv /etc/zshrc.backup-before-nix /etc/zshrc
|
sudo mv /etc/zshrc.backup-before-nix /etc/zshrc
|
||||||
sudo mv /etc/bashrc.backup-before-nix /etc/bashrc
|
sudo mv /etc/bashrc.backup-before-nix /etc/bashrc
|
||||||
|
sudo mv /etc/bash.bashrc.backup-before-nix /etc/bash.bashrc
|
||||||
```
|
```
|
||||||
|
|
||||||
This will stop shells from sourcing the file and bringing everything you
|
This will stop shells from sourcing the file and bringing everything you
|
||||||
|
|
|
@ -31,7 +31,7 @@ static void writeTrustedList(const TrustedList & trustedList)
|
||||||
|
|
||||||
void ConfigFile::apply()
|
void ConfigFile::apply()
|
||||||
{
|
{
|
||||||
std::set<std::string> whitelist{"bash-prompt", "bash-prompt-prefix", "bash-prompt-suffix", "flake-registry"};
|
std::set<std::string> whitelist{"bash-prompt", "bash-prompt-prefix", "bash-prompt-suffix", "flake-registry", "commit-lockfile-summary"};
|
||||||
|
|
||||||
for (auto & [name, value] : settings) {
|
for (auto & [name, value] : settings) {
|
||||||
|
|
||||||
|
|
|
@ -991,7 +991,8 @@ nlohmann::json DerivationOutput::toJSON(
|
||||||
|
|
||||||
DerivationOutput DerivationOutput::fromJSON(
|
DerivationOutput DerivationOutput::fromJSON(
|
||||||
const Store & store, std::string_view drvName, std::string_view outputName,
|
const Store & store, std::string_view drvName, std::string_view outputName,
|
||||||
const nlohmann::json & _json)
|
const nlohmann::json & _json,
|
||||||
|
const ExperimentalFeatureSettings & xpSettings)
|
||||||
{
|
{
|
||||||
std::set<std::string_view> keys;
|
std::set<std::string_view> keys;
|
||||||
auto json = (std::map<std::string, nlohmann::json>) _json;
|
auto json = (std::map<std::string, nlohmann::json>) _json;
|
||||||
|
@ -1028,6 +1029,7 @@ DerivationOutput DerivationOutput::fromJSON(
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (keys == (std::set<std::string_view> { "hashAlgo" })) {
|
else if (keys == (std::set<std::string_view> { "hashAlgo" })) {
|
||||||
|
xpSettings.require(Xp::CaDerivations);
|
||||||
auto [method, hashType] = methodAlgo();
|
auto [method, hashType] = methodAlgo();
|
||||||
return DerivationOutput::CAFloating {
|
return DerivationOutput::CAFloating {
|
||||||
.method = std::move(method),
|
.method = std::move(method),
|
||||||
|
@ -1040,6 +1042,7 @@ DerivationOutput DerivationOutput::fromJSON(
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (keys == (std::set<std::string_view> { "hashAlgo", "impure" })) {
|
else if (keys == (std::set<std::string_view> { "hashAlgo", "impure" })) {
|
||||||
|
xpSettings.require(Xp::ImpureDerivations);
|
||||||
auto [method, hashType] = methodAlgo();
|
auto [method, hashType] = methodAlgo();
|
||||||
return DerivationOutput::Impure {
|
return DerivationOutput::Impure {
|
||||||
.method = std::move(method),
|
.method = std::move(method),
|
||||||
|
|
|
@ -136,11 +136,15 @@ struct DerivationOutput : _DerivationOutputRaw
|
||||||
const Store & store,
|
const Store & store,
|
||||||
std::string_view drvName,
|
std::string_view drvName,
|
||||||
std::string_view outputName) const;
|
std::string_view outputName) const;
|
||||||
|
/**
|
||||||
|
* @param xpSettings Stop-gap to avoid globals during unit tests.
|
||||||
|
*/
|
||||||
static DerivationOutput fromJSON(
|
static DerivationOutput fromJSON(
|
||||||
const Store & store,
|
const Store & store,
|
||||||
std::string_view drvName,
|
std::string_view drvName,
|
||||||
std::string_view outputName,
|
std::string_view outputName,
|
||||||
const nlohmann::json & json);
|
const nlohmann::json & json,
|
||||||
|
const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings);
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::map<std::string, DerivationOutput> DerivationOutputs;
|
typedef std::map<std::string, DerivationOutput> DerivationOutputs;
|
||||||
|
|
|
@ -7,15 +7,18 @@ namespace nix {
|
||||||
NarInfo::NarInfo(const Store & store, const std::string & s, const std::string & whence)
|
NarInfo::NarInfo(const Store & store, const std::string & s, const std::string & whence)
|
||||||
: ValidPathInfo(StorePath(StorePath::dummy), Hash(Hash::dummy)) // FIXME: hack
|
: ValidPathInfo(StorePath(StorePath::dummy), Hash(Hash::dummy)) // FIXME: hack
|
||||||
{
|
{
|
||||||
auto corrupt = [&]() {
|
unsigned line = 1;
|
||||||
return Error("NAR info file '%1%' is corrupt", whence);
|
|
||||||
|
auto corrupt = [&](const char * reason) {
|
||||||
|
return Error("NAR info file '%1%' is corrupt: %2%", whence,
|
||||||
|
std::string(reason) + (line > 0 ? " at line " + std::to_string(line) : ""));
|
||||||
};
|
};
|
||||||
|
|
||||||
auto parseHashField = [&](const std::string & s) {
|
auto parseHashField = [&](const std::string & s) {
|
||||||
try {
|
try {
|
||||||
return Hash::parseAnyPrefixed(s);
|
return Hash::parseAnyPrefixed(s);
|
||||||
} catch (BadHash &) {
|
} catch (BadHash &) {
|
||||||
throw corrupt();
|
throw corrupt("bad hash");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -26,12 +29,12 @@ NarInfo::NarInfo(const Store & store, const std::string & s, const std::string &
|
||||||
while (pos < s.size()) {
|
while (pos < s.size()) {
|
||||||
|
|
||||||
size_t colon = s.find(':', pos);
|
size_t colon = s.find(':', pos);
|
||||||
if (colon == std::string::npos) throw corrupt();
|
if (colon == std::string::npos) throw corrupt("expecting ':'");
|
||||||
|
|
||||||
std::string name(s, pos, colon - pos);
|
std::string name(s, pos, colon - pos);
|
||||||
|
|
||||||
size_t eol = s.find('\n', colon + 2);
|
size_t eol = s.find('\n', colon + 2);
|
||||||
if (eol == std::string::npos) throw corrupt();
|
if (eol == std::string::npos) throw corrupt("expecting '\\n'");
|
||||||
|
|
||||||
std::string value(s, colon + 2, eol - colon - 2);
|
std::string value(s, colon + 2, eol - colon - 2);
|
||||||
|
|
||||||
|
@ -47,7 +50,7 @@ NarInfo::NarInfo(const Store & store, const std::string & s, const std::string &
|
||||||
fileHash = parseHashField(value);
|
fileHash = parseHashField(value);
|
||||||
else if (name == "FileSize") {
|
else if (name == "FileSize") {
|
||||||
auto n = string2Int<decltype(fileSize)>(value);
|
auto n = string2Int<decltype(fileSize)>(value);
|
||||||
if (!n) throw corrupt();
|
if (!n) throw corrupt("invalid FileSize");
|
||||||
fileSize = *n;
|
fileSize = *n;
|
||||||
}
|
}
|
||||||
else if (name == "NarHash") {
|
else if (name == "NarHash") {
|
||||||
|
@ -56,12 +59,12 @@ NarInfo::NarInfo(const Store & store, const std::string & s, const std::string &
|
||||||
}
|
}
|
||||||
else if (name == "NarSize") {
|
else if (name == "NarSize") {
|
||||||
auto n = string2Int<decltype(narSize)>(value);
|
auto n = string2Int<decltype(narSize)>(value);
|
||||||
if (!n) throw corrupt();
|
if (!n) throw corrupt("invalid NarSize");
|
||||||
narSize = *n;
|
narSize = *n;
|
||||||
}
|
}
|
||||||
else if (name == "References") {
|
else if (name == "References") {
|
||||||
auto refs = tokenizeString<Strings>(value, " ");
|
auto refs = tokenizeString<Strings>(value, " ");
|
||||||
if (!references.empty()) throw corrupt();
|
if (!references.empty()) throw corrupt("extra References");
|
||||||
for (auto & r : refs)
|
for (auto & r : refs)
|
||||||
references.insert(StorePath(r));
|
references.insert(StorePath(r));
|
||||||
}
|
}
|
||||||
|
@ -72,17 +75,26 @@ NarInfo::NarInfo(const Store & store, const std::string & s, const std::string &
|
||||||
else if (name == "Sig")
|
else if (name == "Sig")
|
||||||
sigs.insert(value);
|
sigs.insert(value);
|
||||||
else if (name == "CA") {
|
else if (name == "CA") {
|
||||||
if (ca) throw corrupt();
|
if (ca) throw corrupt("extra CA");
|
||||||
// FIXME: allow blank ca or require skipping field?
|
// FIXME: allow blank ca or require skipping field?
|
||||||
ca = ContentAddress::parseOpt(value);
|
ca = ContentAddress::parseOpt(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
pos = eol + 1;
|
pos = eol + 1;
|
||||||
|
line += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compression == "") compression = "bzip2";
|
if (compression == "") compression = "bzip2";
|
||||||
|
|
||||||
if (!havePath || !haveNarHash || url.empty() || narSize == 0) throw corrupt();
|
if (!havePath || !haveNarHash || url.empty() || narSize == 0) {
|
||||||
|
line = 0; // don't include line information in the error
|
||||||
|
throw corrupt(
|
||||||
|
!havePath ? "StorePath missing" :
|
||||||
|
!haveNarHash ? "NarHash missing" :
|
||||||
|
url.empty() ? "URL missing" :
|
||||||
|
narSize == 0 ? "NarSize missing or zero"
|
||||||
|
: "?");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string NarInfo::to_string(const Store & store) const
|
std::string NarInfo::to_string(const Store & store) const
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "experimental-features.hh"
|
||||||
#include "derivations.hh"
|
#include "derivations.hh"
|
||||||
|
|
||||||
#include "tests/libstore.hh"
|
#include "tests/libstore.hh"
|
||||||
|
@ -9,10 +10,32 @@ namespace nix {
|
||||||
|
|
||||||
class DerivationTest : public LibStoreTest
|
class DerivationTest : public LibStoreTest
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* 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_JSON(NAME, STR, VAL, DRV_NAME, OUTPUT_NAME) \
|
class CaDerivationTest : public DerivationTest
|
||||||
TEST_F(DerivationTest, DerivationOutput_ ## NAME ## _to_json) { \
|
{
|
||||||
|
void SetUp() override
|
||||||
|
{
|
||||||
|
mockXpSettings.set("experimental-features", "ca-derivations");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ImpureDerivationTest : public DerivationTest
|
||||||
|
{
|
||||||
|
void SetUp() override
|
||||||
|
{
|
||||||
|
mockXpSettings.set("experimental-features", "impure-derivations");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TEST_JSON(FIXTURE, NAME, STR, VAL, DRV_NAME, OUTPUT_NAME) \
|
||||||
|
TEST_F(FIXTURE, DerivationOutput_ ## NAME ## _to_json) { \
|
||||||
using nlohmann::literals::operator "" _json; \
|
using nlohmann::literals::operator "" _json; \
|
||||||
ASSERT_EQ( \
|
ASSERT_EQ( \
|
||||||
STR ## _json, \
|
STR ## _json, \
|
||||||
|
@ -22,7 +45,7 @@ class DerivationTest : public LibStoreTest
|
||||||
OUTPUT_NAME)); \
|
OUTPUT_NAME)); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
TEST_F(DerivationTest, DerivationOutput_ ## NAME ## _from_json) { \
|
TEST_F(FIXTURE, DerivationOutput_ ## NAME ## _from_json) { \
|
||||||
using nlohmann::literals::operator "" _json; \
|
using nlohmann::literals::operator "" _json; \
|
||||||
ASSERT_EQ( \
|
ASSERT_EQ( \
|
||||||
DerivationOutput { VAL }, \
|
DerivationOutput { VAL }, \
|
||||||
|
@ -30,10 +53,11 @@ class DerivationTest : public LibStoreTest
|
||||||
*store, \
|
*store, \
|
||||||
DRV_NAME, \
|
DRV_NAME, \
|
||||||
OUTPUT_NAME, \
|
OUTPUT_NAME, \
|
||||||
STR ## _json)); \
|
STR ## _json, \
|
||||||
|
mockXpSettings)); \
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_JSON(inputAddressed,
|
TEST_JSON(DerivationTest, inputAddressed,
|
||||||
R"({
|
R"({
|
||||||
"path": "/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-drv-name-output-name"
|
"path": "/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-drv-name-output-name"
|
||||||
})",
|
})",
|
||||||
|
@ -42,7 +66,7 @@ TEST_JSON(inputAddressed,
|
||||||
}),
|
}),
|
||||||
"drv-name", "output-name")
|
"drv-name", "output-name")
|
||||||
|
|
||||||
TEST_JSON(caFixed,
|
TEST_JSON(DerivationTest, caFixed,
|
||||||
R"({
|
R"({
|
||||||
"hashAlgo": "r:sha256",
|
"hashAlgo": "r:sha256",
|
||||||
"hash": "894517c9163c896ec31a2adbd33c0681fd5f45b2c0ef08a64c92a03fb97f390f",
|
"hash": "894517c9163c896ec31a2adbd33c0681fd5f45b2c0ef08a64c92a03fb97f390f",
|
||||||
|
@ -59,7 +83,7 @@ TEST_JSON(caFixed,
|
||||||
}),
|
}),
|
||||||
"drv-name", "output-name")
|
"drv-name", "output-name")
|
||||||
|
|
||||||
TEST_JSON(caFixedText,
|
TEST_JSON(CaDerivationTest, caFixedText,
|
||||||
R"({
|
R"({
|
||||||
"hashAlgo": "text:sha256",
|
"hashAlgo": "text:sha256",
|
||||||
"hash": "894517c9163c896ec31a2adbd33c0681fd5f45b2c0ef08a64c92a03fb97f390f",
|
"hash": "894517c9163c896ec31a2adbd33c0681fd5f45b2c0ef08a64c92a03fb97f390f",
|
||||||
|
@ -75,7 +99,7 @@ TEST_JSON(caFixedText,
|
||||||
}),
|
}),
|
||||||
"drv-name", "output-name")
|
"drv-name", "output-name")
|
||||||
|
|
||||||
TEST_JSON(caFloating,
|
TEST_JSON(CaDerivationTest, caFloating,
|
||||||
R"({
|
R"({
|
||||||
"hashAlgo": "r:sha256"
|
"hashAlgo": "r:sha256"
|
||||||
})",
|
})",
|
||||||
|
@ -85,12 +109,12 @@ TEST_JSON(caFloating,
|
||||||
}),
|
}),
|
||||||
"drv-name", "output-name")
|
"drv-name", "output-name")
|
||||||
|
|
||||||
TEST_JSON(deferred,
|
TEST_JSON(DerivationTest, deferred,
|
||||||
R"({ })",
|
R"({ })",
|
||||||
DerivationOutput::Deferred { },
|
DerivationOutput::Deferred { },
|
||||||
"drv-name", "output-name")
|
"drv-name", "output-name")
|
||||||
|
|
||||||
TEST_JSON(impure,
|
TEST_JSON(ImpureDerivationTest, impure,
|
||||||
R"({
|
R"({
|
||||||
"hashAlgo": "r:sha256",
|
"hashAlgo": "r:sha256",
|
||||||
"impure": true
|
"impure": true
|
||||||
|
|
|
@ -381,10 +381,12 @@ The following attributes are supported in `flake.nix`:
|
||||||
|
|
||||||
* `nixConfig`: a set of `nix.conf` options to be set when evaluating any
|
* `nixConfig`: a set of `nix.conf` options to be set when evaluating any
|
||||||
part of a flake. In the interests of security, only a small set of
|
part of a flake. In the interests of security, only a small set of
|
||||||
whitelisted options (currently `bash-prompt`, `bash-prompt-prefix`,
|
set of options is allowed to be set without confirmation so long as [`accept-flake-config`](@docroot@/command-ref/conf-file.md#conf-accept-flake-config) is not enabled in the global configuration:
|
||||||
`bash-prompt-suffix`, and `flake-registry`) are allowed to be set without
|
- [`bash-prompt`](@docroot@/command-ref/conf-file.md#conf-bash-prompt)
|
||||||
confirmation so long as `accept-flake-config` is not set in the global
|
- [`bash-prompt-prefix`](@docroot@/command-ref/conf-file.md#conf-bash-prompt-prefix)
|
||||||
configuration.
|
- [`bash-prompt-suffix`](@docroot@/command-ref/conf-file.md#conf-bash-prompt-suffix)
|
||||||
|
- [`flake-registry`](@docroot@/command-ref/conf-file.md#conf-flake-registry)
|
||||||
|
- [`commit-lockfile-summary`](@docroot@/command-ref/conf-file.md#conf-commit-lockfile-summary)
|
||||||
|
|
||||||
## Flake inputs
|
## Flake inputs
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,9 @@ drvPath3=$(nix derivation add --dry-run < $TEST_HOME/foo.json)
|
||||||
# With --dry-run nothing is actually written
|
# With --dry-run nothing is actually written
|
||||||
[[ ! -e "$drvPath3" ]]
|
[[ ! -e "$drvPath3" ]]
|
||||||
|
|
||||||
|
# But the JSON is rejected without the experimental feature
|
||||||
|
expectStderr 1 nix derivation add < $TEST_HOME/foo.json --experimental-features nix-command | grepQuiet "experimental Nix feature 'ca-derivations' is disabled"
|
||||||
|
|
||||||
# Without --dry-run it is actually written
|
# Without --dry-run it is actually written
|
||||||
drvPath4=$(nix derivation add < $TEST_HOME/foo.json)
|
drvPath4=$(nix derivation add < $TEST_HOME/foo.json)
|
||||||
[[ "$drvPath4" = "$drvPath3" ]]
|
[[ "$drvPath4" = "$drvPath3" ]]
|
||||||
|
|
|
@ -10,6 +10,15 @@ clearStore
|
||||||
# Basic test of impure derivations: building one a second time should not use the previous result.
|
# Basic test of impure derivations: building one a second time should not use the previous result.
|
||||||
printf 0 > $TEST_ROOT/counter
|
printf 0 > $TEST_ROOT/counter
|
||||||
|
|
||||||
|
# `nix derivation add` with impure derivations work
|
||||||
|
drvPath=$(nix-instantiate ./impure-derivations.nix -A impure)
|
||||||
|
nix derivation show $drvPath | jq .[] > $TEST_HOME/impure-drv.json
|
||||||
|
drvPath2=$(nix derivation add < $TEST_HOME/impure-drv.json)
|
||||||
|
[[ "$drvPath" = "$drvPath2" ]]
|
||||||
|
|
||||||
|
# But only with the experimental feature!
|
||||||
|
expectStderr 1 nix derivation add < $TEST_HOME/impure-drv.json --experimental-features nix-command | grepQuiet "experimental Nix feature 'impure-derivations' is disabled"
|
||||||
|
|
||||||
nix build --dry-run --json --file ./impure-derivations.nix impure.all
|
nix build --dry-run --json --file ./impure-derivations.nix impure.all
|
||||||
json=$(nix build -L --no-link --json --file ./impure-derivations.nix impure.all)
|
json=$(nix build -L --no-link --json --file ./impure-derivations.nix impure.all)
|
||||||
path1=$(echo $json | jq -r .[].outputs.out)
|
path1=$(echo $json | jq -r .[].outputs.out)
|
||||||
|
|
Loading…
Reference in a new issue