aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Ericson <John.Ericson@Obsidian.Systems>2023-04-19 11:26:34 -0400
committerJohn Ericson <John.Ericson@Obsidian.Systems>2023-04-19 11:32:14 -0400
commit76baaeb341cf395c61877e6d598c290835529ca0 (patch)
treedddc7a7f8beec203acc77361538e76f819bd770e
parent668377f217c0fa4053d746f7094dfe887e07887c (diff)
parentd3e2394e9106416e57cd0da10facd8db00e622e6 (diff)
Merge remote-tracking branch 'upstream/master' into ca-drv-exotic
-rw-r--r--doc/manual/src/glossary.md2
-rw-r--r--doc/manual/src/installation/installing-binary.md3
-rw-r--r--src/libexpr/flake/config.cc2
-rw-r--r--src/libstore/derivations.cc5
-rw-r--r--src/libstore/derivations.hh6
-rw-r--r--src/libstore/nar-info.cc32
-rw-r--r--src/libstore/tests/derivation.cc44
-rw-r--r--src/nix/flake.md10
-rw-r--r--tests/ca/derivation-json.sh3
-rw-r--r--tests/impure-derivations.sh9
10 files changed, 87 insertions, 29 deletions
diff --git a/doc/manual/src/glossary.md b/doc/manual/src/glossary.md
index a9782be5c..eeb19ad50 100644
--- a/doc/manual/src/glossary.md
+++ b/doc/manual/src/glossary.md
@@ -127,7 +127,7 @@
builder can rely on external inputs such as the network or the
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.
This is an implementation detail of the [local store].
diff --git a/doc/manual/src/installation/installing-binary.md b/doc/manual/src/installation/installing-binary.md
index e3fd962bd..525654d35 100644
--- a/doc/manual/src/installation/installing-binary.md
+++ b/doc/manual/src/installation/installing-binary.md
@@ -136,7 +136,7 @@ which you may remove.
### 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:
```bash
@@ -153,6 +153,7 @@ which you may remove.
```console
sudo mv /etc/zshrc.backup-before-nix /etc/zshrc
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
diff --git a/src/libexpr/flake/config.cc b/src/libexpr/flake/config.cc
index 89ddbde7e..e89014862 100644
--- a/src/libexpr/flake/config.cc
+++ b/src/libexpr/flake/config.cc
@@ -31,7 +31,7 @@ static void writeTrustedList(const TrustedList & trustedList)
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) {
diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc
index 1f5f78964..9f529c753 100644
--- a/src/libstore/derivations.cc
+++ b/src/libstore/derivations.cc
@@ -991,7 +991,8 @@ nlohmann::json DerivationOutput::toJSON(
DerivationOutput DerivationOutput::fromJSON(
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;
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" })) {
+ xpSettings.require(Xp::CaDerivations);
auto [method, hashType] = methodAlgo();
return DerivationOutput::CAFloating {
.method = std::move(method),
@@ -1040,6 +1042,7 @@ DerivationOutput DerivationOutput::fromJSON(
}
else if (keys == (std::set<std::string_view> { "hashAlgo", "impure" })) {
+ xpSettings.require(Xp::ImpureDerivations);
auto [method, hashType] = methodAlgo();
return DerivationOutput::Impure {
.method = std::move(method),
diff --git a/src/libstore/derivations.hh b/src/libstore/derivations.hh
index b36e4ea91..666dbff41 100644
--- a/src/libstore/derivations.hh
+++ b/src/libstore/derivations.hh
@@ -136,11 +136,15 @@ struct DerivationOutput : _DerivationOutputRaw
const Store & store,
std::string_view drvName,
std::string_view outputName) const;
+ /**
+ * @param xpSettings Stop-gap to avoid globals during unit tests.
+ */
static DerivationOutput fromJSON(
const Store & store,
std::string_view drvName,
std::string_view outputName,
- const nlohmann::json & json);
+ const nlohmann::json & json,
+ const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings);
};
typedef std::map<std::string, DerivationOutput> DerivationOutputs;
diff --git a/src/libstore/nar-info.cc b/src/libstore/nar-info.cc
index 274cd861c..d17253741 100644
--- a/src/libstore/nar-info.cc
+++ b/src/libstore/nar-info.cc
@@ -7,15 +7,18 @@ namespace nix {
NarInfo::NarInfo(const Store & store, const std::string & s, const std::string & whence)
: ValidPathInfo(StorePath(StorePath::dummy), Hash(Hash::dummy)) // FIXME: hack
{
- auto corrupt = [&]() {
- return Error("NAR info file '%1%' is corrupt", whence);
+ unsigned line = 1;
+
+ 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) {
try {
return Hash::parseAnyPrefixed(s);
} 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()) {
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);
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);
@@ -47,7 +50,7 @@ NarInfo::NarInfo(const Store & store, const std::string & s, const std::string &
fileHash = parseHashField(value);
else if (name == "FileSize") {
auto n = string2Int<decltype(fileSize)>(value);
- if (!n) throw corrupt();
+ if (!n) throw corrupt("invalid FileSize");
fileSize = *n;
}
else if (name == "NarHash") {
@@ -56,12 +59,12 @@ NarInfo::NarInfo(const Store & store, const std::string & s, const std::string &
}
else if (name == "NarSize") {
auto n = string2Int<decltype(narSize)>(value);
- if (!n) throw corrupt();
+ if (!n) throw corrupt("invalid NarSize");
narSize = *n;
}
else if (name == "References") {
auto refs = tokenizeString<Strings>(value, " ");
- if (!references.empty()) throw corrupt();
+ if (!references.empty()) throw corrupt("extra References");
for (auto & r : refs)
references.insert(StorePath(r));
}
@@ -72,17 +75,26 @@ NarInfo::NarInfo(const Store & store, const std::string & s, const std::string &
else if (name == "Sig")
sigs.insert(value);
else if (name == "CA") {
- if (ca) throw corrupt();
+ if (ca) throw corrupt("extra CA");
// FIXME: allow blank ca or require skipping field?
ca = ContentAddress::parseOpt(value);
}
pos = eol + 1;
+ line += 1;
}
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
diff --git a/src/libstore/tests/derivation.cc b/src/libstore/tests/derivation.cc
index 1cab68e06..48524a710 100644
--- a/src/libstore/tests/derivation.cc
+++ b/src/libstore/tests/derivation.cc
@@ -1,6 +1,7 @@
#include <nlohmann/json.hpp>
#include <gtest/gtest.h>
+#include "experimental-features.hh"
#include "derivations.hh"
#include "tests/libstore.hh"
@@ -9,10 +10,32 @@ namespace nix {
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) \
- TEST_F(DerivationTest, DerivationOutput_ ## NAME ## _to_json) { \
+class CaDerivationTest : public DerivationTest
+{
+ 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; \
ASSERT_EQ( \
STR ## _json, \
@@ -22,7 +45,7 @@ class DerivationTest : public LibStoreTest
OUTPUT_NAME)); \
} \
\
- TEST_F(DerivationTest, DerivationOutput_ ## NAME ## _from_json) { \
+ TEST_F(FIXTURE, DerivationOutput_ ## NAME ## _from_json) { \
using nlohmann::literals::operator "" _json; \
ASSERT_EQ( \
DerivationOutput { VAL }, \
@@ -30,10 +53,11 @@ class DerivationTest : public LibStoreTest
*store, \
DRV_NAME, \
OUTPUT_NAME, \
- STR ## _json)); \
+ STR ## _json, \
+ mockXpSettings)); \
}
-TEST_JSON(inputAddressed,
+TEST_JSON(DerivationTest, inputAddressed,
R"({
"path": "/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-drv-name-output-name"
})",
@@ -42,7 +66,7 @@ TEST_JSON(inputAddressed,
}),
"drv-name", "output-name")
-TEST_JSON(caFixed,
+TEST_JSON(DerivationTest, caFixed,
R"({
"hashAlgo": "r:sha256",
"hash": "894517c9163c896ec31a2adbd33c0681fd5f45b2c0ef08a64c92a03fb97f390f",
@@ -59,7 +83,7 @@ TEST_JSON(caFixed,
}),
"drv-name", "output-name")
-TEST_JSON(caFixedText,
+TEST_JSON(CaDerivationTest, caFixedText,
R"({
"hashAlgo": "text:sha256",
"hash": "894517c9163c896ec31a2adbd33c0681fd5f45b2c0ef08a64c92a03fb97f390f",
@@ -75,7 +99,7 @@ TEST_JSON(caFixedText,
}),
"drv-name", "output-name")
-TEST_JSON(caFloating,
+TEST_JSON(CaDerivationTest, caFloating,
R"({
"hashAlgo": "r:sha256"
})",
@@ -85,12 +109,12 @@ TEST_JSON(caFloating,
}),
"drv-name", "output-name")
-TEST_JSON(deferred,
+TEST_JSON(DerivationTest, deferred,
R"({ })",
DerivationOutput::Deferred { },
"drv-name", "output-name")
-TEST_JSON(impure,
+TEST_JSON(ImpureDerivationTest, impure,
R"({
"hashAlgo": "r:sha256",
"impure": true
diff --git a/src/nix/flake.md b/src/nix/flake.md
index d70f34eeb..456fd0ea1 100644
--- a/src/nix/flake.md
+++ b/src/nix/flake.md
@@ -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
part of a flake. In the interests of security, only a small set of
- whitelisted options (currently `bash-prompt`, `bash-prompt-prefix`,
- `bash-prompt-suffix`, and `flake-registry`) are allowed to be set without
- confirmation so long as `accept-flake-config` is not set in the global
- configuration.
+ 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`](@docroot@/command-ref/conf-file.md#conf-bash-prompt)
+ - [`bash-prompt-prefix`](@docroot@/command-ref/conf-file.md#conf-bash-prompt-prefix)
+ - [`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
diff --git a/tests/ca/derivation-json.sh b/tests/ca/derivation-json.sh
index 3615177e9..c1480fd17 100644
--- a/tests/ca/derivation-json.sh
+++ b/tests/ca/derivation-json.sh
@@ -16,6 +16,9 @@ drvPath3=$(nix derivation add --dry-run < $TEST_HOME/foo.json)
# With --dry-run nothing is actually written
[[ ! -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
drvPath4=$(nix derivation add < $TEST_HOME/foo.json)
[[ "$drvPath4" = "$drvPath3" ]]
diff --git a/tests/impure-derivations.sh b/tests/impure-derivations.sh
index c7dadf397..39d053a04 100644
--- a/tests/impure-derivations.sh
+++ b/tests/impure-derivations.sh
@@ -10,6 +10,15 @@ clearStore
# Basic test of impure derivations: building one a second time should not use the previous result.
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
json=$(nix build -L --no-link --json --file ./impure-derivations.nix impure.all)
path1=$(echo $json | jq -r .[].outputs.out)