forked from lix-project/lix
Merge remote-tracking branch 'origin/master' into non-blocking-gc
This commit is contained in:
commit
a7d4f3411e
6
.github/workflows/test.yml
vendored
6
.github/workflows/test.yml
vendored
|
@ -11,7 +11,7 @@ jobs:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2.3.4
|
- uses: actions/checkout@v2.3.5
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- uses: cachix/install-nix-action@v14
|
- uses: cachix/install-nix-action@v14
|
||||||
|
@ -41,7 +41,7 @@ jobs:
|
||||||
outputs:
|
outputs:
|
||||||
installerURL: ${{ steps.prepare-installer.outputs.installerURL }}
|
installerURL: ${{ steps.prepare-installer.outputs.installerURL }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2.3.4
|
- uses: actions/checkout@v2.3.5
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV
|
- run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV
|
||||||
|
@ -61,7 +61,7 @@ jobs:
|
||||||
os: [ubuntu-latest, macos-latest]
|
os: [ubuntu-latest, macos-latest]
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2.3.4
|
- uses: actions/checkout@v2.3.5
|
||||||
- run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV
|
- run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV
|
||||||
- uses: cachix/install-nix-action@v14
|
- uses: cachix/install-nix-action@v14
|
||||||
with:
|
with:
|
||||||
|
|
|
@ -70,7 +70,8 @@
|
||||||
- [Hacking](contributing/hacking.md)
|
- [Hacking](contributing/hacking.md)
|
||||||
- [CLI guideline](contributing/cli-guideline.md)
|
- [CLI guideline](contributing/cli-guideline.md)
|
||||||
- [Release Notes](release-notes/release-notes.md)
|
- [Release Notes](release-notes/release-notes.md)
|
||||||
- [Release 2.4 (2021-XX-XX)](release-notes/rl-2.4.md)
|
- [Release X.Y (202?-??-??)](release-notes/rl-next.md)
|
||||||
|
- [Release 2.4 (2021-11-01)](release-notes/rl-2.4.md)
|
||||||
- [Release 2.3 (2019-09-04)](release-notes/rl-2.3.md)
|
- [Release 2.3 (2019-09-04)](release-notes/rl-2.3.md)
|
||||||
- [Release 2.2 (2019-01-11)](release-notes/rl-2.2.md)
|
- [Release 2.2 (2019-01-11)](release-notes/rl-2.2.md)
|
||||||
- [Release 2.1 (2018-09-02)](release-notes/rl-2.1.md)
|
- [Release 2.1 (2018-09-02)](release-notes/rl-2.1.md)
|
||||||
|
|
|
@ -110,13 +110,19 @@ shell in which to build it:
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ nix-shell '<nixpkgs>' -A pan
|
$ nix-shell '<nixpkgs>' -A pan
|
||||||
[nix-shell]$ unpackPhase
|
[nix-shell]$ eval ${unpackPhase:-unpackPhase}
|
||||||
[nix-shell]$ cd pan-*
|
[nix-shell]$ cd pan-*
|
||||||
[nix-shell]$ configurePhase
|
[nix-shell]$ eval ${configurePhase:-configurePhase}
|
||||||
[nix-shell]$ buildPhase
|
[nix-shell]$ eval ${buildPhase:-buildPhase}
|
||||||
[nix-shell]$ ./pan/gui/pan
|
[nix-shell]$ ./pan/gui/pan
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The reason we use form `eval ${configurePhase:-configurePhase}` here is because
|
||||||
|
those packages that override these phases do so by exporting the overridden
|
||||||
|
values in the environment variable of the same name.
|
||||||
|
Here bash is being told to either evaluate the contents of 'configurePhase',
|
||||||
|
if it exists as a variable, otherwise evaluate the configurePhase function.
|
||||||
|
|
||||||
To clear the environment first, and do some additional automatic
|
To clear the environment first, and do some additional automatic
|
||||||
initialisation of the interactive shell:
|
initialisation of the interactive shell:
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Release 2.4 (2021-10-XX)
|
# Release 2.4 (2021-11-01)
|
||||||
|
|
||||||
This is the first release in more than two years and is the result of
|
This is the first release in more than two years and is the result of
|
||||||
more than 2800 commits from 195 contributors since release 2.3.
|
more than 2800 commits from 195 contributors since release 2.3.
|
||||||
|
@ -286,8 +286,35 @@ more than 2800 commits from 195 contributors since release 2.3.
|
||||||
to your `nix.conf` if you want to use it, or pass
|
to your `nix.conf` if you want to use it, or pass
|
||||||
`--extra-experimental-features nix-command` on the command line.
|
`--extra-experimental-features nix-command` on the command line.
|
||||||
|
|
||||||
* The old `nix run` has been renamed to `nix shell` (and there is a
|
* The `nix` command no longer has a syntax for referring to packages
|
||||||
new `nix run` that does something else, as described above).
|
in a channel. This means that the following no longer works:
|
||||||
|
|
||||||
|
> nix build nixpkgs.hello # Nix 2.3
|
||||||
|
|
||||||
|
Instead, you can either use the `#` syntax to select a package from
|
||||||
|
a flake, e.g.
|
||||||
|
|
||||||
|
> nix build nixpkgs#hello
|
||||||
|
|
||||||
|
Or, if you want to use the `nixpkgs` channel in the `NIX_PATH`
|
||||||
|
environment variable:
|
||||||
|
|
||||||
|
> nix build -f '<nixpkgs>' hello
|
||||||
|
|
||||||
|
* The old `nix run` has been renamed to `nix shell`, while there is a
|
||||||
|
new `nix run` that runs a default command. So instead of
|
||||||
|
|
||||||
|
> nix run nixpkgs.hello -c hello # Nix 2.3
|
||||||
|
|
||||||
|
you should use
|
||||||
|
|
||||||
|
> nix shell nixpkgs#hello -c hello
|
||||||
|
|
||||||
|
or just
|
||||||
|
|
||||||
|
> nix run nixpkgs#hello
|
||||||
|
|
||||||
|
if the command you want to run has the same name as the package.
|
||||||
|
|
||||||
* It is now an error to modify the `plugin-files` setting via a
|
* It is now an error to modify the `plugin-files` setting via a
|
||||||
command-line flag that appears after the first non-flag argument to
|
command-line flag that appears after the first non-flag argument to
|
||||||
|
|
|
@ -61,6 +61,7 @@
|
||||||
|
|
||||||
configureFlags =
|
configureFlags =
|
||||||
lib.optionals stdenv.isLinux [
|
lib.optionals stdenv.isLinux [
|
||||||
|
"--with-boost=${boost}/lib"
|
||||||
"--with-sandbox-shell=${sh}/bin/busybox"
|
"--with-sandbox-shell=${sh}/bin/busybox"
|
||||||
"LDFLAGS=-fuse-ld=gold"
|
"LDFLAGS=-fuse-ld=gold"
|
||||||
];
|
];
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "derivations.hh"
|
#include "derivations.hh"
|
||||||
#include "local-store.hh"
|
#include "local-store.hh"
|
||||||
#include "legacy.hh"
|
#include "legacy.hh"
|
||||||
|
#include "experimental-features.hh"
|
||||||
|
|
||||||
using namespace nix;
|
using namespace nix;
|
||||||
using std::cin;
|
using std::cin;
|
||||||
|
@ -130,11 +131,14 @@ static int main_build_remote(int argc, char * * argv)
|
||||||
for (auto & m : machines) {
|
for (auto & m : machines) {
|
||||||
debug("considering building on remote machine '%s'", m.storeUri);
|
debug("considering building on remote machine '%s'", m.storeUri);
|
||||||
|
|
||||||
if (m.enabled && std::find(m.systemTypes.begin(),
|
if (m.enabled
|
||||||
m.systemTypes.end(),
|
&& (neededSystem == "builtin"
|
||||||
neededSystem) != m.systemTypes.end() &&
|
|| std::find(m.systemTypes.begin(),
|
||||||
|
m.systemTypes.end(),
|
||||||
|
neededSystem) != m.systemTypes.end()) &&
|
||||||
m.allSupported(requiredFeatures) &&
|
m.allSupported(requiredFeatures) &&
|
||||||
m.mandatoryMet(requiredFeatures)) {
|
m.mandatoryMet(requiredFeatures))
|
||||||
|
{
|
||||||
rightType = true;
|
rightType = true;
|
||||||
AutoCloseFD free;
|
AutoCloseFD free;
|
||||||
uint64_t load = 0;
|
uint64_t load = 0;
|
||||||
|
@ -295,7 +299,7 @@ connected:
|
||||||
|
|
||||||
std::set<Realisation> missingRealisations;
|
std::set<Realisation> missingRealisations;
|
||||||
StorePathSet missingPaths;
|
StorePathSet missingPaths;
|
||||||
if (settings.isExperimentalFeatureEnabled("ca-derivations") && !derivationHasKnownOutputPaths(drv.type())) {
|
if (settings.isExperimentalFeatureEnabled(Xp::CaDerivations) && !derivationHasKnownOutputPaths(drv.type())) {
|
||||||
for (auto & outputName : wantedOutputs) {
|
for (auto & outputName : wantedOutputs) {
|
||||||
auto thisOutputHash = outputHashes.at(outputName);
|
auto thisOutputHash = outputHashes.at(outputName);
|
||||||
auto thisOutputId = DrvOutput{ thisOutputHash, outputName };
|
auto thisOutputId = DrvOutput{ thisOutputHash, outputName };
|
||||||
|
@ -327,7 +331,7 @@ connected:
|
||||||
for (auto & realisation : missingRealisations) {
|
for (auto & realisation : missingRealisations) {
|
||||||
// Should hold, because if the feature isn't enabled the set
|
// Should hold, because if the feature isn't enabled the set
|
||||||
// of missing realisations should be empty
|
// of missing realisations should be empty
|
||||||
settings.requireExperimentalFeature("ca-derivations");
|
settings.requireExperimentalFeature(Xp::CaDerivations);
|
||||||
store->registerDrvOutput(realisation);
|
store->registerDrvOutput(realisation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -714,7 +714,7 @@ BuiltPaths getBuiltPaths(ref<Store> evalStore, ref<Store> store, const DerivedPa
|
||||||
"the derivation '%s' doesn't have an output named '%s'",
|
"the derivation '%s' doesn't have an output named '%s'",
|
||||||
store->printStorePath(bfd.drvPath), output);
|
store->printStorePath(bfd.drvPath), output);
|
||||||
if (settings.isExperimentalFeatureEnabled(
|
if (settings.isExperimentalFeatureEnabled(
|
||||||
"ca-derivations")) {
|
Xp::CaDerivations)) {
|
||||||
auto outputId =
|
auto outputId =
|
||||||
DrvOutput{outputHashes.at(output), output};
|
DrvOutput{outputHashes.at(output), output};
|
||||||
auto realisation =
|
auto realisation =
|
||||||
|
|
|
@ -466,7 +466,7 @@ EvalState::~EvalState()
|
||||||
|
|
||||||
|
|
||||||
void EvalState::requireExperimentalFeatureOnEvaluation(
|
void EvalState::requireExperimentalFeatureOnEvaluation(
|
||||||
const std::string & feature,
|
const ExperimentalFeature & feature,
|
||||||
const std::string_view fName,
|
const std::string_view fName,
|
||||||
const Pos & pos)
|
const Pos & pos)
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "nixexpr.hh"
|
#include "nixexpr.hh"
|
||||||
#include "symbol-table.hh"
|
#include "symbol-table.hh"
|
||||||
#include "config.hh"
|
#include "config.hh"
|
||||||
|
#include "experimental-features.hh"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
@ -141,7 +142,7 @@ public:
|
||||||
~EvalState();
|
~EvalState();
|
||||||
|
|
||||||
void requireExperimentalFeatureOnEvaluation(
|
void requireExperimentalFeatureOnEvaluation(
|
||||||
const std::string & feature,
|
const ExperimentalFeature &,
|
||||||
const std::string_view fName,
|
const std::string_view fName,
|
||||||
const Pos & pos
|
const Pos & pos
|
||||||
);
|
);
|
||||||
|
|
|
@ -297,7 +297,7 @@ LockedFlake lockFlake(
|
||||||
const FlakeRef & topRef,
|
const FlakeRef & topRef,
|
||||||
const LockFlags & lockFlags)
|
const LockFlags & lockFlags)
|
||||||
{
|
{
|
||||||
settings.requireExperimentalFeature("flakes");
|
settings.requireExperimentalFeature(Xp::Flakes);
|
||||||
|
|
||||||
FlakeCache flakeCache;
|
FlakeCache flakeCache;
|
||||||
|
|
||||||
|
@ -687,7 +687,7 @@ void callFlake(EvalState & state,
|
||||||
|
|
||||||
static void prim_getFlake(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_getFlake(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
state.requireExperimentalFeatureOnEvaluation("flakes", "builtins.getFlake", pos);
|
state.requireExperimentalFeatureOnEvaluation(Xp::Flakes, "builtins.getFlake", pos);
|
||||||
|
|
||||||
auto flakeRefS = state.forceStringNoCtx(*args[0], pos);
|
auto flakeRefS = state.forceStringNoCtx(*args[0], pos);
|
||||||
auto flakeRef = parseFlakeRef(flakeRefS, {}, true);
|
auto flakeRef = parseFlakeRef(flakeRefS, {}, true);
|
||||||
|
|
|
@ -418,7 +418,7 @@ expr_simple
|
||||||
new ExprString(data->symbols.create(path)));
|
new ExprString(data->symbols.create(path)));
|
||||||
}
|
}
|
||||||
| URI {
|
| URI {
|
||||||
static bool noURLLiterals = settings.isExperimentalFeatureEnabled("no-url-literals");
|
static bool noURLLiterals = settings.isExperimentalFeatureEnabled(Xp::NoUrlLiterals);
|
||||||
if (noURLLiterals)
|
if (noURLLiterals)
|
||||||
throw ParseError({
|
throw ParseError({
|
||||||
.msg = hintfmt("URL literals are disabled"),
|
.msg = hintfmt("URL literals are disabled"),
|
||||||
|
@ -752,7 +752,7 @@ std::pair<bool, std::string> EvalState::resolveSearchPathElem(const SearchPathEl
|
||||||
res = { true, path };
|
res = { true, path };
|
||||||
else {
|
else {
|
||||||
logWarning({
|
logWarning({
|
||||||
.msg = hintfmt("warning: Nix search path entry '%1%' does not exist, ignoring", elem.second)
|
.msg = hintfmt("Nix search path entry '%1%' does not exist, ignoring", elem.second)
|
||||||
});
|
});
|
||||||
res = { false, "" };
|
res = { false, "" };
|
||||||
}
|
}
|
||||||
|
|
|
@ -985,7 +985,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i->name == state.sContentAddressed) {
|
if (i->name == state.sContentAddressed) {
|
||||||
settings.requireExperimentalFeature("ca-derivations");
|
settings.requireExperimentalFeature(Xp::CaDerivations);
|
||||||
contentAddressed = state.forceBool(*i->value, pos);
|
contentAddressed = state.forceBool(*i->value, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ static void prim_fetchMercurial(EvalState & state, const Pos & pos, Value * * ar
|
||||||
std::string name = "source";
|
std::string name = "source";
|
||||||
PathSet context;
|
PathSet context;
|
||||||
|
|
||||||
state.forceValue(*args[0]);
|
state.forceValue(*args[0], pos);
|
||||||
|
|
||||||
if (args[0]->type() == nAttrs) {
|
if (args[0]->type() == nAttrs) {
|
||||||
|
|
||||||
|
|
|
@ -97,7 +97,7 @@ static void fetchTree(
|
||||||
fetchers::Input input;
|
fetchers::Input input;
|
||||||
PathSet context;
|
PathSet context;
|
||||||
|
|
||||||
state.forceValue(*args[0]);
|
state.forceValue(*args[0], pos);
|
||||||
|
|
||||||
if (args[0]->type() == nAttrs) {
|
if (args[0]->type() == nAttrs) {
|
||||||
state.forceAttrs(*args[0], pos);
|
state.forceAttrs(*args[0], pos);
|
||||||
|
@ -121,7 +121,7 @@ static void fetchTree(
|
||||||
|
|
||||||
for (auto & attr : *args[0]->attrs) {
|
for (auto & attr : *args[0]->attrs) {
|
||||||
if (attr.name == state.sType) continue;
|
if (attr.name == state.sType) continue;
|
||||||
state.forceValue(*attr.value);
|
state.forceValue(*attr.value, *attr.pos);
|
||||||
if (attr.value->type() == nPath || attr.value->type() == nString) {
|
if (attr.value->type() == nPath || attr.value->type() == nString) {
|
||||||
auto s = state.coerceToString(*attr.pos, *attr.value, context, false, false);
|
auto s = state.coerceToString(*attr.pos, *attr.value, context, false, false);
|
||||||
attrs.emplace(attr.name,
|
attrs.emplace(attr.name,
|
||||||
|
@ -176,7 +176,7 @@ static void fetchTree(
|
||||||
|
|
||||||
static void prim_fetchTree(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_fetchTree(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
settings.requireExperimentalFeature("flakes");
|
settings.requireExperimentalFeature(Xp::Flakes);
|
||||||
fetchTree(state, pos, args, v, std::nullopt, FetchTreeParams { .allowNameArgument = false });
|
fetchTree(state, pos, args, v, std::nullopt, FetchTreeParams { .allowNameArgument = false });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,7 +189,7 @@ static void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v,
|
||||||
std::optional<std::string> url;
|
std::optional<std::string> url;
|
||||||
std::optional<Hash> expectedHash;
|
std::optional<Hash> expectedHash;
|
||||||
|
|
||||||
state.forceValue(*args[0]);
|
state.forceValue(*args[0], pos);
|
||||||
|
|
||||||
if (args[0]->type() == nAttrs) {
|
if (args[0]->type() == nAttrs) {
|
||||||
|
|
||||||
|
@ -287,13 +287,13 @@ static RegisterPrimOp primop_fetchTarball({
|
||||||
stdenv.mkDerivation { … }
|
stdenv.mkDerivation { … }
|
||||||
```
|
```
|
||||||
|
|
||||||
The fetched tarball is cached for a certain amount of time (1 hour
|
The fetched tarball is cached for a certain amount of time (1
|
||||||
by default) in `~/.cache/nix/tarballs/`. You can change the cache
|
hour by default) in `~/.cache/nix/tarballs/`. You can change the
|
||||||
timeout either on the command line with `--option tarball-ttl number
|
cache timeout either on the command line with `--tarball-ttl`
|
||||||
of seconds` or in the Nix configuration file with this option: `
|
*number-of-seconds* or in the Nix configuration file by adding
|
||||||
number of seconds to cache `.
|
the line `tarball-ttl = ` *number-of-seconds*.
|
||||||
|
|
||||||
Note that when obtaining the hash with ` nix-prefetch-url ` the
|
Note that when obtaining the hash with `nix-prefetch-url` the
|
||||||
option `--unpack` is required.
|
option `--unpack` is required.
|
||||||
|
|
||||||
This function can also verify the contents against a hash. In that
|
This function can also verify the contents against a hash. In that
|
||||||
|
@ -393,7 +393,7 @@ static RegisterPrimOp primop_fetchGit({
|
||||||
```
|
```
|
||||||
|
|
||||||
> **Note**
|
> **Note**
|
||||||
>
|
>
|
||||||
> It is nice to always specify the branch which a revision
|
> It is nice to always specify the branch which a revision
|
||||||
> belongs to. Without the branch being specified, the fetcher
|
> belongs to. Without the branch being specified, the fetcher
|
||||||
> might fail if the default branch changes. Additionally, it can
|
> might fail if the default branch changes. Additionally, it can
|
||||||
|
@ -430,12 +430,12 @@ static RegisterPrimOp primop_fetchGit({
|
||||||
```
|
```
|
||||||
|
|
||||||
> **Note**
|
> **Note**
|
||||||
>
|
>
|
||||||
> Nix will refetch the branch in accordance with
|
> Nix will refetch the branch in accordance with
|
||||||
> the option `tarball-ttl`.
|
> the option `tarball-ttl`.
|
||||||
|
|
||||||
> **Note**
|
> **Note**
|
||||||
>
|
>
|
||||||
> This behavior is disabled in *Pure evaluation mode*.
|
> This behavior is disabled in *Pure evaluation mode*.
|
||||||
)",
|
)",
|
||||||
.fun = prim_fetchGit,
|
.fun = prim_fetchGit,
|
||||||
|
|
|
@ -204,7 +204,7 @@ void DerivationGoal::haveDerivation()
|
||||||
trace("have derivation");
|
trace("have derivation");
|
||||||
|
|
||||||
if (drv->type() == DerivationType::CAFloating)
|
if (drv->type() == DerivationType::CAFloating)
|
||||||
settings.requireExperimentalFeature("ca-derivations");
|
settings.requireExperimentalFeature(Xp::CaDerivations);
|
||||||
|
|
||||||
retrySubstitution = false;
|
retrySubstitution = false;
|
||||||
|
|
||||||
|
@ -453,7 +453,7 @@ void DerivationGoal::inputsRealised()
|
||||||
if (useDerivation) {
|
if (useDerivation) {
|
||||||
auto & fullDrv = *dynamic_cast<Derivation *>(drv.get());
|
auto & fullDrv = *dynamic_cast<Derivation *>(drv.get());
|
||||||
|
|
||||||
if (settings.isExperimentalFeatureEnabled("ca-derivations") &&
|
if (settings.isExperimentalFeatureEnabled(Xp::CaDerivations) &&
|
||||||
((!fullDrv.inputDrvs.empty() && derivationIsCA(fullDrv.type()))
|
((!fullDrv.inputDrvs.empty() && derivationIsCA(fullDrv.type()))
|
||||||
|| fullDrv.type() == DerivationType::DeferredInputAddressed)) {
|
|| fullDrv.type() == DerivationType::DeferredInputAddressed)) {
|
||||||
/* We are be able to resolve this derivation based on the
|
/* We are be able to resolve this derivation based on the
|
||||||
|
@ -616,7 +616,9 @@ void DerivationGoal::tryToBuild()
|
||||||
/* Don't do a remote build if the derivation has the attribute
|
/* Don't do a remote build if the derivation has the attribute
|
||||||
`preferLocalBuild' set. Also, check and repair modes are only
|
`preferLocalBuild' set. Also, check and repair modes are only
|
||||||
supported for local builds. */
|
supported for local builds. */
|
||||||
bool buildLocally = buildMode != bmNormal || parsedDrv->willBuildLocally(worker.store);
|
bool buildLocally =
|
||||||
|
(buildMode != bmNormal || parsedDrv->willBuildLocally(worker.store))
|
||||||
|
&& settings.maxBuildJobs.get() != 0;
|
||||||
|
|
||||||
if (!buildLocally) {
|
if (!buildLocally) {
|
||||||
switch (tryBuildHook()) {
|
switch (tryBuildHook()) {
|
||||||
|
@ -1273,7 +1275,7 @@ void DerivationGoal::checkPathValidity()
|
||||||
: PathStatus::Corrupt,
|
: PathStatus::Corrupt,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (settings.isExperimentalFeatureEnabled("ca-derivations")) {
|
if (settings.isExperimentalFeatureEnabled(Xp::CaDerivations)) {
|
||||||
auto drvOutput = DrvOutput{initialOutputs.at(i.first).outputHash, i.first};
|
auto drvOutput = DrvOutput{initialOutputs.at(i.first).outputHash, i.first};
|
||||||
if (auto real = worker.store.queryRealisation(drvOutput)) {
|
if (auto real = worker.store.queryRealisation(drvOutput)) {
|
||||||
info.known = {
|
info.known = {
|
||||||
|
|
|
@ -74,7 +74,7 @@ BuildResult Store::buildDerivation(const StorePath & drvPath, const BasicDerivat
|
||||||
outputId,
|
outputId,
|
||||||
Realisation{ outputId, *staticOutput.second}
|
Realisation{ outputId, *staticOutput.second}
|
||||||
);
|
);
|
||||||
if (settings.isExperimentalFeatureEnabled("ca-derivations") && !derivationHasKnownOutputPaths(drv.type())) {
|
if (settings.isExperimentalFeatureEnabled(Xp::CaDerivations) && !derivationHasKnownOutputPaths(drv.type())) {
|
||||||
auto realisation = this->queryRealisation(outputId);
|
auto realisation = this->queryRealisation(outputId);
|
||||||
if (realisation)
|
if (realisation)
|
||||||
result.builtOutputs.insert_or_assign(
|
result.builtOutputs.insert_or_assign(
|
||||||
|
|
|
@ -1259,7 +1259,7 @@ struct RestrictedStore : public virtual RestrictedStoreConfig, public virtual Lo
|
||||||
for (auto & [outputName, outputPath] : outputs)
|
for (auto & [outputName, outputPath] : outputs)
|
||||||
if (wantOutput(outputName, bfd.outputs)) {
|
if (wantOutput(outputName, bfd.outputs)) {
|
||||||
newPaths.insert(outputPath);
|
newPaths.insert(outputPath);
|
||||||
if (settings.isExperimentalFeatureEnabled("ca-derivations")) {
|
if (settings.isExperimentalFeatureEnabled(Xp::CaDerivations)) {
|
||||||
auto thisRealisation = next->queryRealisation(
|
auto thisRealisation = next->queryRealisation(
|
||||||
DrvOutput{drvHashes.at(outputName), outputName}
|
DrvOutput{drvHashes.at(outputName), outputName}
|
||||||
);
|
);
|
||||||
|
@ -1320,7 +1320,7 @@ struct RestrictedStore : public virtual RestrictedStoreConfig, public virtual Lo
|
||||||
|
|
||||||
void LocalDerivationGoal::startDaemon()
|
void LocalDerivationGoal::startDaemon()
|
||||||
{
|
{
|
||||||
settings.requireExperimentalFeature("recursive-nix");
|
settings.requireExperimentalFeature(Xp::RecursiveNix);
|
||||||
|
|
||||||
Store::Params params;
|
Store::Params params;
|
||||||
params["path-info-cache-size"] = "0";
|
params["path-info-cache-size"] = "0";
|
||||||
|
@ -2561,7 +2561,7 @@ void LocalDerivationGoal::registerOutputs()
|
||||||
that for floating CA derivations, which otherwise couldn't be cached,
|
that for floating CA derivations, which otherwise couldn't be cached,
|
||||||
but it's fine to do in all cases. */
|
but it's fine to do in all cases. */
|
||||||
|
|
||||||
if (settings.isExperimentalFeatureEnabled("ca-derivations")) {
|
if (settings.isExperimentalFeatureEnabled(Xp::CaDerivations)) {
|
||||||
for (auto& [outputName, newInfo] : infos) {
|
for (auto& [outputName, newInfo] : infos) {
|
||||||
auto thisRealisation = Realisation{
|
auto thisRealisation = Realisation{
|
||||||
.id = DrvOutput{initialOutputs.at(outputName).outputHash,
|
.id = DrvOutput{initialOutputs.at(outputName).outputHash,
|
||||||
|
|
|
@ -230,11 +230,12 @@ struct ClientSettings
|
||||||
else if (name == settings.experimentalFeatures.name) {
|
else if (name == settings.experimentalFeatures.name) {
|
||||||
// We don’t want to forward the experimental features to
|
// We don’t want to forward the experimental features to
|
||||||
// the daemon, as that could cause some pretty weird stuff
|
// the daemon, as that could cause some pretty weird stuff
|
||||||
if (tokenizeString<Strings>(value) != settings.experimentalFeatures.get())
|
if (parseFeatures(tokenizeString<StringSet>(value)) != settings.experimentalFeatures.get())
|
||||||
debug("Ignoring the client-specified experimental features");
|
debug("Ignoring the client-specified experimental features");
|
||||||
}
|
}
|
||||||
else if (trusted
|
else if (trusted
|
||||||
|| name == settings.buildTimeout.name
|
|| name == settings.buildTimeout.name
|
||||||
|
|| name == settings.buildRepeat.name
|
||||||
|| name == "connect-timeout"
|
|| name == "connect-timeout"
|
||||||
|| (name == "builders" && value == ""))
|
|| (name == "builders" && value == ""))
|
||||||
settings.set(name, value);
|
settings.set(name, value);
|
||||||
|
|
|
@ -187,7 +187,7 @@ static DerivationOutput parseDerivationOutput(const Store & store,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
settings.requireExperimentalFeature("ca-derivations");
|
settings.requireExperimentalFeature(Xp::CaDerivations);
|
||||||
assert(pathS == "");
|
assert(pathS == "");
|
||||||
return DerivationOutput {
|
return DerivationOutput {
|
||||||
.output = DerivationOutputCAFloating {
|
.output = DerivationOutputCAFloating {
|
||||||
|
|
|
@ -100,7 +100,7 @@ RealisedPath::Set BuiltPath::toRealisedPaths(Store & store) const
|
||||||
staticOutputHashes(store, store.readDerivation(p.drvPath));
|
staticOutputHashes(store, store.readDerivation(p.drvPath));
|
||||||
for (auto& [outputName, outputPath] : p.outputs) {
|
for (auto& [outputName, outputPath] : p.outputs) {
|
||||||
if (settings.isExperimentalFeatureEnabled(
|
if (settings.isExperimentalFeatureEnabled(
|
||||||
"ca-derivations")) {
|
Xp::CaDerivations)) {
|
||||||
auto thisRealisation = store.queryRealisation(
|
auto thisRealisation = store.queryRealisation(
|
||||||
DrvOutput{drvHashes.at(outputName), outputName});
|
DrvOutput{drvHashes.at(outputName), outputName});
|
||||||
assert(thisRealisation); // We’ve built it, so we must h
|
assert(thisRealisation); // We’ve built it, so we must h
|
||||||
|
|
|
@ -148,7 +148,8 @@ StringSet Settings::getDefaultExtraPlatforms()
|
||||||
// machines. Note that we can’t force processes from executing
|
// machines. Note that we can’t force processes from executing
|
||||||
// x86_64 in aarch64 environments or vice versa since they can
|
// x86_64 in aarch64 environments or vice versa since they can
|
||||||
// always exec with their own binary preferences.
|
// always exec with their own binary preferences.
|
||||||
if (pathExists("/Library/Apple/System/Library/LaunchDaemons/com.apple.oahd.plist")) {
|
if (pathExists("/Library/Apple/System/Library/LaunchDaemons/com.apple.oahd.plist") ||
|
||||||
|
pathExists("/System/Library/LaunchDaemons/com.apple.oahd.plist")) {
|
||||||
if (std::string{SYSTEM} == "x86_64-darwin")
|
if (std::string{SYSTEM} == "x86_64-darwin")
|
||||||
extraPlatforms.insert("aarch64-darwin");
|
extraPlatforms.insert("aarch64-darwin");
|
||||||
else if (std::string{SYSTEM} == "aarch64-darwin")
|
else if (std::string{SYSTEM} == "aarch64-darwin")
|
||||||
|
@ -159,21 +160,16 @@ StringSet Settings::getDefaultExtraPlatforms()
|
||||||
return extraPlatforms;
|
return extraPlatforms;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Settings::isExperimentalFeatureEnabled(const std::string & name)
|
bool Settings::isExperimentalFeatureEnabled(const ExperimentalFeature & feature)
|
||||||
{
|
{
|
||||||
auto & f = experimentalFeatures.get();
|
auto & f = experimentalFeatures.get();
|
||||||
return std::find(f.begin(), f.end(), name) != f.end();
|
return std::find(f.begin(), f.end(), feature) != f.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
MissingExperimentalFeature::MissingExperimentalFeature(std::string feature)
|
void Settings::requireExperimentalFeature(const ExperimentalFeature & feature)
|
||||||
: Error("experimental Nix feature '%1%' is disabled; use '--extra-experimental-features %1%' to override", feature)
|
|
||||||
, missingFeature(feature)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void Settings::requireExperimentalFeature(const std::string & name)
|
|
||||||
{
|
{
|
||||||
if (!isExperimentalFeatureEnabled(name))
|
if (!isExperimentalFeatureEnabled(feature))
|
||||||
throw MissingExperimentalFeature(name);
|
throw MissingExperimentalFeature(feature);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Settings::isWSL1()
|
bool Settings::isWSL1()
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "types.hh"
|
#include "types.hh"
|
||||||
#include "config.hh"
|
#include "config.hh"
|
||||||
#include "util.hh"
|
#include "util.hh"
|
||||||
|
#include "experimental-features.hh"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
@ -45,15 +46,6 @@ struct PluginFilesSetting : public BaseSetting<Paths>
|
||||||
void set(const std::string & str, bool append = false) override;
|
void set(const std::string & str, bool append = false) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MissingExperimentalFeature: public Error
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
std::string missingFeature;
|
|
||||||
|
|
||||||
MissingExperimentalFeature(std::string feature);
|
|
||||||
virtual const char* sname() const override { return "MissingExperimentalFeature"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class Settings : public Config {
|
class Settings : public Config {
|
||||||
|
|
||||||
unsigned int getDefaultCores();
|
unsigned int getDefaultCores();
|
||||||
|
@ -925,12 +917,12 @@ public:
|
||||||
value.
|
value.
|
||||||
)"};
|
)"};
|
||||||
|
|
||||||
Setting<Strings> experimentalFeatures{this, {}, "experimental-features",
|
Setting<std::set<ExperimentalFeature>> experimentalFeatures{this, {}, "experimental-features",
|
||||||
"Experimental Nix features to enable."};
|
"Experimental Nix features to enable."};
|
||||||
|
|
||||||
bool isExperimentalFeatureEnabled(const std::string & name);
|
bool isExperimentalFeatureEnabled(const ExperimentalFeature &);
|
||||||
|
|
||||||
void requireExperimentalFeature(const std::string & name);
|
void requireExperimentalFeature(const ExperimentalFeature &);
|
||||||
|
|
||||||
Setting<bool> allowDirty{this, true, "allow-dirty",
|
Setting<bool> allowDirty{this, true, "allow-dirty",
|
||||||
"Whether to allow dirty Git/Mercurial trees."};
|
"Whether to allow dirty Git/Mercurial trees."};
|
||||||
|
|
|
@ -308,7 +308,7 @@ LocalStore::LocalStore(const Params & params)
|
||||||
|
|
||||||
else openDB(*state, false);
|
else openDB(*state, false);
|
||||||
|
|
||||||
if (settings.isExperimentalFeatureEnabled("ca-derivations")) {
|
if (settings.isExperimentalFeatureEnabled(Xp::CaDerivations)) {
|
||||||
migrateCASchema(state->db, dbDir + "/ca-schema", globalLock);
|
migrateCASchema(state->db, dbDir + "/ca-schema", globalLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,7 +338,7 @@ LocalStore::LocalStore(const Params & params)
|
||||||
state->stmts->QueryPathFromHashPart.create(state->db,
|
state->stmts->QueryPathFromHashPart.create(state->db,
|
||||||
"select path from ValidPaths where path >= ? limit 1;");
|
"select path from ValidPaths where path >= ? limit 1;");
|
||||||
state->stmts->QueryValidPaths.create(state->db, "select path from ValidPaths");
|
state->stmts->QueryValidPaths.create(state->db, "select path from ValidPaths");
|
||||||
if (settings.isExperimentalFeatureEnabled("ca-derivations")) {
|
if (settings.isExperimentalFeatureEnabled(Xp::CaDerivations)) {
|
||||||
state->stmts->RegisterRealisedOutput.create(state->db,
|
state->stmts->RegisterRealisedOutput.create(state->db,
|
||||||
R"(
|
R"(
|
||||||
insert into Realisations (drvPath, outputName, outputPath, signatures)
|
insert into Realisations (drvPath, outputName, outputPath, signatures)
|
||||||
|
@ -717,7 +717,7 @@ void LocalStore::checkDerivationOutputs(const StorePath & drvPath, const Derivat
|
||||||
|
|
||||||
void LocalStore::registerDrvOutput(const Realisation & info, CheckSigsFlag checkSigs)
|
void LocalStore::registerDrvOutput(const Realisation & info, CheckSigsFlag checkSigs)
|
||||||
{
|
{
|
||||||
settings.requireExperimentalFeature("ca-derivations");
|
settings.requireExperimentalFeature(Xp::CaDerivations);
|
||||||
if (checkSigs == NoCheckSigs || !realisationIsUntrusted(info))
|
if (checkSigs == NoCheckSigs || !realisationIsUntrusted(info))
|
||||||
registerDrvOutput(info);
|
registerDrvOutput(info);
|
||||||
else
|
else
|
||||||
|
@ -726,7 +726,7 @@ void LocalStore::registerDrvOutput(const Realisation & info, CheckSigsFlag check
|
||||||
|
|
||||||
void LocalStore::registerDrvOutput(const Realisation & info)
|
void LocalStore::registerDrvOutput(const Realisation & info)
|
||||||
{
|
{
|
||||||
settings.requireExperimentalFeature("ca-derivations");
|
settings.requireExperimentalFeature(Xp::CaDerivations);
|
||||||
retrySQLite<void>([&]() {
|
retrySQLite<void>([&]() {
|
||||||
auto state(_state.lock());
|
auto state(_state.lock());
|
||||||
if (auto oldR = queryRealisation_(*state, info.id)) {
|
if (auto oldR = queryRealisation_(*state, info.id)) {
|
||||||
|
@ -1012,7 +1012,7 @@ LocalStore::queryPartialDerivationOutputMap(const StorePath & path_)
|
||||||
return outputs;
|
return outputs;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!settings.isExperimentalFeatureEnabled("ca-derivations"))
|
if (!settings.isExperimentalFeatureEnabled(Xp::CaDerivations))
|
||||||
return outputs;
|
return outputs;
|
||||||
|
|
||||||
auto drv = readInvalidDerivation(path);
|
auto drv = readInvalidDerivation(path);
|
||||||
|
|
|
@ -355,7 +355,7 @@ ValidPathInfo Store::addToStoreSlow(std::string_view name, const Path & srcPath,
|
||||||
StringSet StoreConfig::getDefaultSystemFeatures()
|
StringSet StoreConfig::getDefaultSystemFeatures()
|
||||||
{
|
{
|
||||||
auto res = settings.systemFeatures.get();
|
auto res = settings.systemFeatures.get();
|
||||||
if (settings.isExperimentalFeatureEnabled("ca-derivations"))
|
if (settings.isExperimentalFeatureEnabled(Xp::CaDerivations))
|
||||||
res.insert("ca-derivations");
|
res.insert("ca-derivations");
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -854,7 +854,7 @@ std::map<StorePath, StorePath> copyPaths(
|
||||||
for (auto & path : paths) {
|
for (auto & path : paths) {
|
||||||
storePaths.insert(path.path());
|
storePaths.insert(path.path());
|
||||||
if (auto realisation = std::get_if<Realisation>(&path.raw)) {
|
if (auto realisation = std::get_if<Realisation>(&path.raw)) {
|
||||||
settings.requireExperimentalFeature("ca-derivations");
|
settings.requireExperimentalFeature(Xp::CaDerivations);
|
||||||
toplevelRealisations.insert(*realisation);
|
toplevelRealisations.insert(*realisation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -886,7 +886,7 @@ std::map<StorePath, StorePath> copyPaths(
|
||||||
// Don't fail if the remote doesn't support CA derivations is it might
|
// Don't fail if the remote doesn't support CA derivations is it might
|
||||||
// not be within our control to change that, and we might still want
|
// not be within our control to change that, and we might still want
|
||||||
// to at least copy the output paths.
|
// to at least copy the output paths.
|
||||||
if (e.missingFeature == "ca-derivations")
|
if (e.missingFeature == Xp::CaDerivations)
|
||||||
ignoreException();
|
ignoreException();
|
||||||
else
|
else
|
||||||
throw;
|
throw;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "config.hh"
|
#include "config.hh"
|
||||||
#include "args.hh"
|
#include "args.hh"
|
||||||
#include "abstract-setting-to-json.hh"
|
#include "abstract-setting-to-json.hh"
|
||||||
|
#include "experimental-features.hh"
|
||||||
|
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
@ -313,6 +314,31 @@ template<> std::string BaseSetting<StringSet>::to_string() const
|
||||||
return concatStringsSep(" ", value);
|
return concatStringsSep(" ", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<> void BaseSetting<std::set<ExperimentalFeature>>::set(const std::string & str, bool append)
|
||||||
|
{
|
||||||
|
if (!append) value.clear();
|
||||||
|
for (auto & s : tokenizeString<StringSet>(str)) {
|
||||||
|
auto thisXpFeature = parseExperimentalFeature(s);
|
||||||
|
if (thisXpFeature)
|
||||||
|
value.insert(thisXpFeature.value());
|
||||||
|
else
|
||||||
|
warn("unknown experimental feature '%s'", s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<> bool BaseSetting<std::set<ExperimentalFeature>>::isAppendable()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<> std::string BaseSetting<std::set<ExperimentalFeature>>::to_string() const
|
||||||
|
{
|
||||||
|
StringSet stringifiedXpFeatures;
|
||||||
|
for (auto & feature : value)
|
||||||
|
stringifiedXpFeatures.insert(std::string(showExperimentalFeature(feature)));
|
||||||
|
return concatStringsSep(" ", stringifiedXpFeatures);
|
||||||
|
}
|
||||||
|
|
||||||
template<> void BaseSetting<StringMap>::set(const std::string & str, bool append)
|
template<> void BaseSetting<StringMap>::set(const std::string & str, bool append)
|
||||||
{
|
{
|
||||||
if (!append) value.clear();
|
if (!append) value.clear();
|
||||||
|
@ -348,6 +374,7 @@ template class BaseSetting<std::string>;
|
||||||
template class BaseSetting<Strings>;
|
template class BaseSetting<Strings>;
|
||||||
template class BaseSetting<StringSet>;
|
template class BaseSetting<StringSet>;
|
||||||
template class BaseSetting<StringMap>;
|
template class BaseSetting<StringMap>;
|
||||||
|
template class BaseSetting<std::set<ExperimentalFeature>>;
|
||||||
|
|
||||||
void PathSetting::set(const std::string & str, bool append)
|
void PathSetting::set(const std::string & str, bool append)
|
||||||
{
|
{
|
||||||
|
|
59
src/libutil/experimental-features.cc
Normal file
59
src/libutil/experimental-features.cc
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
#include "experimental-features.hh"
|
||||||
|
#include "util.hh"
|
||||||
|
|
||||||
|
#include "nlohmann/json.hpp"
|
||||||
|
|
||||||
|
namespace nix {
|
||||||
|
|
||||||
|
std::map<ExperimentalFeature, std::string> stringifiedXpFeatures = {
|
||||||
|
{ Xp::CaDerivations, "ca-derivations" },
|
||||||
|
{ Xp::Flakes, "flakes" },
|
||||||
|
{ Xp::NixCommand, "nix-command" },
|
||||||
|
{ Xp::RecursiveNix, "recursive-nix" },
|
||||||
|
{ Xp::NoUrlLiterals, "no-url-literals" },
|
||||||
|
};
|
||||||
|
|
||||||
|
const std::optional<ExperimentalFeature> parseExperimentalFeature(const std::string_view & name)
|
||||||
|
{
|
||||||
|
using ReverseXpMap = std::map<std::string_view, ExperimentalFeature>;
|
||||||
|
|
||||||
|
static auto reverseXpMap = []()
|
||||||
|
{
|
||||||
|
auto reverseXpMap = std::make_unique<ReverseXpMap>();
|
||||||
|
for (auto & [feature, name] : stringifiedXpFeatures)
|
||||||
|
(*reverseXpMap)[name] = feature;
|
||||||
|
return reverseXpMap;
|
||||||
|
}();
|
||||||
|
|
||||||
|
if (auto feature = get(*reverseXpMap, name))
|
||||||
|
return *feature;
|
||||||
|
else
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string_view showExperimentalFeature(const ExperimentalFeature feature)
|
||||||
|
{
|
||||||
|
return stringifiedXpFeatures.at(feature);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<ExperimentalFeature> parseFeatures(const std::set<std::string> & rawFeatures)
|
||||||
|
{
|
||||||
|
std::set<ExperimentalFeature> res;
|
||||||
|
for (auto & rawFeature : rawFeatures) {
|
||||||
|
if (auto feature = parseExperimentalFeature(rawFeature))
|
||||||
|
res.insert(*feature);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
MissingExperimentalFeature::MissingExperimentalFeature(ExperimentalFeature feature)
|
||||||
|
: Error("experimental Nix feature '%1%' is disabled; use '--extra-experimental-features %1%' to override", showExperimentalFeature(feature))
|
||||||
|
, missingFeature(feature)
|
||||||
|
{}
|
||||||
|
|
||||||
|
std::ostream & operator <<(std::ostream & str, const ExperimentalFeature & feature)
|
||||||
|
{
|
||||||
|
return str << showExperimentalFeature(feature);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
56
src/libutil/experimental-features.hh
Normal file
56
src/libutil/experimental-features.hh
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "comparator.hh"
|
||||||
|
#include "error.hh"
|
||||||
|
#include "nlohmann/json_fwd.hpp"
|
||||||
|
#include "types.hh"
|
||||||
|
|
||||||
|
namespace nix {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The list of available experimental features.
|
||||||
|
*
|
||||||
|
* If you update this, don’t forget to also change the map defining their
|
||||||
|
* string representation in the corresponding `.cc` file.
|
||||||
|
**/
|
||||||
|
enum struct ExperimentalFeature
|
||||||
|
{
|
||||||
|
CaDerivations,
|
||||||
|
Flakes,
|
||||||
|
NixCommand,
|
||||||
|
RecursiveNix,
|
||||||
|
NoUrlLiterals
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Just because writing `ExperimentalFeature::CaDerivations` is way too long
|
||||||
|
*/
|
||||||
|
using Xp = ExperimentalFeature;
|
||||||
|
|
||||||
|
const std::optional<ExperimentalFeature> parseExperimentalFeature(
|
||||||
|
const std::string_view & name);
|
||||||
|
std::string_view showExperimentalFeature(const ExperimentalFeature);
|
||||||
|
|
||||||
|
std::ostream & operator<<(
|
||||||
|
std::ostream & str,
|
||||||
|
const ExperimentalFeature & feature);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a set of strings to the corresponding set of experimental features,
|
||||||
|
* ignoring (but warning for) any unkwown feature.
|
||||||
|
*/
|
||||||
|
std::set<ExperimentalFeature> parseFeatures(const std::set<std::string> &);
|
||||||
|
|
||||||
|
class MissingExperimentalFeature : public Error
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ExperimentalFeature missingFeature;
|
||||||
|
|
||||||
|
MissingExperimentalFeature(ExperimentalFeature);
|
||||||
|
virtual const char * sname() const override
|
||||||
|
{
|
||||||
|
return "MissingExperimentalFeature";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -17,7 +17,7 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ref<T>(const ref<T> & r)
|
ref(const ref<T> & r)
|
||||||
: p(r.p)
|
: p(r.p)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
|
@ -401,7 +401,7 @@ static void main_nix_build(int argc, char * * argv)
|
||||||
|
|
||||||
if (dryRun) return;
|
if (dryRun) return;
|
||||||
|
|
||||||
if (settings.isExperimentalFeatureEnabled("ca-derivations")) {
|
if (settings.isExperimentalFeatureEnabled(Xp::CaDerivations)) {
|
||||||
auto resolvedDrv = drv.tryResolve(*store);
|
auto resolvedDrv = drv.tryResolve(*store);
|
||||||
assert(resolvedDrv && "Successfully resolved the derivation");
|
assert(resolvedDrv && "Successfully resolved the derivation");
|
||||||
drv = *resolvedDrv;
|
drv = *resolvedDrv;
|
||||||
|
|
|
@ -195,7 +195,7 @@ static StorePath getDerivationEnvironment(ref<Store> store, ref<Store> evalStore
|
||||||
'buildDerivation', but that's privileged. */
|
'buildDerivation', but that's privileged. */
|
||||||
drv.name += "-env";
|
drv.name += "-env";
|
||||||
drv.inputSrcs.insert(std::move(getEnvShPath));
|
drv.inputSrcs.insert(std::move(getEnvShPath));
|
||||||
if (settings.isExperimentalFeatureEnabled("ca-derivations")) {
|
if (settings.isExperimentalFeatureEnabled(Xp::CaDerivations)) {
|
||||||
for (auto & output : drv.outputs) {
|
for (auto & output : drv.outputs) {
|
||||||
output.second = {
|
output.second = {
|
||||||
.output = DerivationOutputDeferred{},
|
.output = DerivationOutputDeferred{},
|
||||||
|
|
|
@ -1138,7 +1138,7 @@ struct CmdFlake : NixMultiCommand
|
||||||
{
|
{
|
||||||
if (!command)
|
if (!command)
|
||||||
throw UsageError("'nix flake' requires a sub-command.");
|
throw UsageError("'nix flake' requires a sub-command.");
|
||||||
settings.requireExperimentalFeature("flakes");
|
settings.requireExperimentalFeature(Xp::Flakes);
|
||||||
command->second->prepare();
|
command->second->prepare();
|
||||||
command->second->run();
|
command->second->run();
|
||||||
}
|
}
|
||||||
|
|
|
@ -337,7 +337,7 @@ void mainWrapped(int argc, char * * argv)
|
||||||
if (args.command->first != "repl"
|
if (args.command->first != "repl"
|
||||||
&& args.command->first != "doctor"
|
&& args.command->first != "doctor"
|
||||||
&& args.command->first != "upgrade-nix")
|
&& args.command->first != "upgrade-nix")
|
||||||
settings.requireExperimentalFeature("nix-command");
|
settings.requireExperimentalFeature(Xp::NixCommand);
|
||||||
|
|
||||||
if (args.useNet && !haveInternet()) {
|
if (args.useNet && !haveInternet()) {
|
||||||
warn("you don't have Internet access; disabling some network-dependent features");
|
warn("you don't have Internet access; disabling some network-dependent features");
|
||||||
|
|
|
@ -46,7 +46,7 @@ struct CmdRealisationInfo : BuiltPathsCommand, MixJSON
|
||||||
|
|
||||||
void run(ref<Store> store, BuiltPaths && paths) override
|
void run(ref<Store> store, BuiltPaths && paths) override
|
||||||
{
|
{
|
||||||
settings.requireExperimentalFeature("ca-derivations");
|
settings.requireExperimentalFeature(Xp::CaDerivations);
|
||||||
RealisedPath::Set realisations;
|
RealisedPath::Set realisations;
|
||||||
|
|
||||||
for (auto & builtPath : paths) {
|
for (auto & builtPath : paths) {
|
||||||
|
|
|
@ -219,7 +219,7 @@ struct CmdKey : NixMultiCommand
|
||||||
{
|
{
|
||||||
if (!command)
|
if (!command)
|
||||||
throw UsageError("'nix flake' requires a sub-command.");
|
throw UsageError("'nix flake' requires a sub-command.");
|
||||||
settings.requireExperimentalFeature("flakes");
|
settings.requireExperimentalFeature(Xp::Flakes);
|
||||||
command->second->prepare();
|
command->second->prepare();
|
||||||
command->second->run();
|
command->second->run();
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,7 +126,7 @@ isDaemonNewer () {
|
||||||
[[ -n "${NIX_DAEMON_PACKAGE:-}" ]] || return 0
|
[[ -n "${NIX_DAEMON_PACKAGE:-}" ]] || return 0
|
||||||
local requiredVersion="$1"
|
local requiredVersion="$1"
|
||||||
local daemonVersion=$($NIX_DAEMON_PACKAGE/bin/nix-daemon --version | cut -d' ' -f3)
|
local daemonVersion=$($NIX_DAEMON_PACKAGE/bin/nix-daemon --version | cut -d' ' -f3)
|
||||||
return [[ $(nix eval --expr "builtins.compareVersions ''$daemonVersion'' ''2.4''") -ge 0 ]]
|
[[ $(nix eval --expr "builtins.compareVersions ''$daemonVersion'' ''$requiredVersion''") -ge 0 ]]
|
||||||
}
|
}
|
||||||
|
|
||||||
requireDaemonNewerThan () {
|
requireDaemonNewerThan () {
|
||||||
|
|
|
@ -50,4 +50,4 @@ exp_cores=$(nix show-config | grep '^cores' | cut -d '=' -f 2 | xargs)
|
||||||
exp_features=$(nix show-config | grep '^experimental-features' | cut -d '=' -f 2 | xargs)
|
exp_features=$(nix show-config | grep '^experimental-features' | cut -d '=' -f 2 | xargs)
|
||||||
[[ $prev != $exp_cores ]]
|
[[ $prev != $exp_cores ]]
|
||||||
[[ $exp_cores == "4242" ]]
|
[[ $exp_cores == "4242" ]]
|
||||||
[[ $exp_features == "nix-command flakes" ]]
|
[[ $exp_features == "flakes nix-command" ]]
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
source common.sh
|
source common.sh
|
||||||
|
|
||||||
requireDaemonNewerThan "2.4pre20210727"
|
# Using `--eval-store` with the daemon will eventually copy everything
|
||||||
|
# to the build store, invalidating most of the tests here
|
||||||
|
needLocalStore
|
||||||
|
|
||||||
eval_store=$TEST_ROOT/eval-store
|
eval_store=$TEST_ROOT/eval-store
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ source common.sh
|
||||||
|
|
||||||
# 27ce722638 required some incompatible changes to the nix file, so skip this
|
# 27ce722638 required some incompatible changes to the nix file, so skip this
|
||||||
# tests for the older versions
|
# tests for the older versions
|
||||||
requireDaemonNewerThan "2.4pre20210622"
|
requireDaemonNewerThan "2.4pre20210712"
|
||||||
|
|
||||||
clearStore
|
clearStore
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue