libexpr/eval: Deprecate shadowing <nix/fetchurl.nix>
If the NIX_PATH shadows internal files, this will often break things, hence we forbid it. Fixes #998 Change-Id: I70e5d389532ada1c9f910c60281abe565e3ce6bb
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
---
|
||||
synopsis: "Deprecate shadowing internal files through the Nix search path"
|
||||
issues: [998]
|
||||
cls: [4632]
|
||||
category: "Breaking Changes"
|
||||
credits: [thubrecht]
|
||||
---
|
||||
|
||||
As Lix uses the path `<nix/fetchurl.nix>` for bootstrapping purposes, the ability to shadow it by adding `nix=/some/path` (or `/other/path` that contains a `nix` directory) to the search path is not desirable.
|
||||
|
||||
To alleviate potential issues, Lix now emits a warning when the Nix search path contains potential shadows for internal files, which will be changed to an error in a future release.
|
||||
|
||||
The warning can be disabled by enabling the deprecated feature `nix-path-shadow`.
|
||||
@@ -4,12 +4,14 @@
|
||||
#include "lix/libutil/archive.hh"
|
||||
#include "lix/libutil/ansicolor.hh"
|
||||
#include "lix/libutil/async.hh"
|
||||
#include "lix/libutil/deprecated-features.hh"
|
||||
#include "lix/libutil/error.hh"
|
||||
#include "lix/libutil/english.hh"
|
||||
#include "lix/libutil/fmt.hh"
|
||||
#include "lix/libexpr/primops.hh"
|
||||
#include "lix/libexpr/print-options.hh"
|
||||
#include "lix/libmain/shared.hh"
|
||||
#include "lix/libutil/logging.hh"
|
||||
#include "lix/libutil/suggestions.hh"
|
||||
#include "lix/libutil/types.hh"
|
||||
#include "lix/libstore/store-api.hh"
|
||||
@@ -347,6 +349,61 @@ EvalPaths::EvalPaths(
|
||||
allowPath(path);
|
||||
}
|
||||
}
|
||||
|
||||
#if LIX_MAJOR >= 3 || (LIX_MAJOR == 2 && LIX_MINOR >= 96)
|
||||
#warning \
|
||||
"The feature nix-path-shadow was deprecated in 2.95 with a warning, which needs to be turned into an error in 2.96"
|
||||
#endif
|
||||
if (!featureSettings.isEnabled(DeprecatedFeature::NixPathShadow)) {
|
||||
for (auto & [prefix, path] : searchPath_.elements) {
|
||||
// Match on the 'nix' prefix
|
||||
if (prefix.s == "nix") {
|
||||
logWarning(
|
||||
{.msg = HintFmt(
|
||||
"The prefix '%s' is reserved for internal use by Lix in the Nix search "
|
||||
"path, its usage is deprecated and will be forbidden in the future.\n"
|
||||
"Use %s to silence this warning.\n"
|
||||
"This is due to adding '%s=%s' in the Nix search path, either through the "
|
||||
"environment variable '%s' or by passing the flag %s to the nix "
|
||||
"invocation.",
|
||||
"nix",
|
||||
"--extra-deprecated-features nix-path-shadow",
|
||||
prefix.s,
|
||||
path.s,
|
||||
"NIX_PATH",
|
||||
"-I"
|
||||
)}
|
||||
);
|
||||
} else
|
||||
// Match prefixless paths that contain a `nix` directory
|
||||
if (auto res =
|
||||
prefix.suffixIfPotentialMatch("nix").and_then([&](std::string_view s) {
|
||||
return aio.blockOn(resolveSearchPathPath(path))
|
||||
.and_then([&](std::string r) {
|
||||
Path res = s.length() ? concatStrings(r, "/", s): r;
|
||||
|
||||
return pathExists(res) ? std::optional(res) : std::nullopt;
|
||||
});
|
||||
}))
|
||||
{
|
||||
logWarning(
|
||||
{.msg = HintFmt(
|
||||
"Shadowing '%s' by configuring the nix-path is deprecated and "
|
||||
"will be forbidden in the future.\n"
|
||||
"Use %s to silence this warning.\n"
|
||||
"This is due to adding '%s' to the nix-path without a prefix, "
|
||||
"either by passing the flag '-I %s' to the nix invocation or by "
|
||||
"adding this path to the environment variable '%s'.",
|
||||
"<nix/...>",
|
||||
"--extra-deprecated-features nix-path-shadow",
|
||||
path.s,
|
||||
path.s,
|
||||
"NIX_PATH"
|
||||
)}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Evaluator::Evaluator(
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
name: nix-path-shadow
|
||||
internalName: NixPathShadow
|
||||
---
|
||||
|
||||
Allows shadowing `<nix/fetchurl.nix>` by configuration of the [*nix path*](@docroot@/language/builtin-constants.html#builtins-nixPath) to a value containing `nix=/some/path`.
|
||||
@@ -172,6 +172,7 @@ deprecated_feature_definitions = files(
|
||||
# keep-sorted start
|
||||
'deprecated-features/ancient-let.md',
|
||||
'deprecated-features/cr-line-endings.md',
|
||||
'deprecated-features/nix-path-shadow.md',
|
||||
'deprecated-features/nul-bytes.md',
|
||||
'deprecated-features/rec-set-overrides.md',
|
||||
'deprecated-features/shadow-internal-symbols.md',
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
/__corepkgs__/fetchurl.nix
|
||||
@@ -0,0 +1,3 @@
|
||||
warning: The prefix 'nix' is reserved for internal use by Lix in the Nix search path, its usage is deprecated and will be forbidden in the future.
|
||||
Use --extra-deprecated-features nix-path-shadow to silence this warning.
|
||||
This is due to adding 'nix=nix-shadow' in the Nix search path, either through the environment variable 'NIX_PATH' or by passing the flag -I to the nix invocation.
|
||||
@@ -0,0 +1 @@
|
||||
/__corepkgs__/fetchurl.nix
|
||||
@@ -0,0 +1,3 @@
|
||||
warning: Shadowing '<nix/...>' by configuring the nix-path is deprecated and will be forbidden in the future.
|
||||
Use --extra-deprecated-features nix-path-shadow to silence this warning.
|
||||
This is due to adding 'nix-shadow' to the nix-path without a prefix, either by passing the flag '-I nix-shadow' to the nix invocation or by adding this path to the environment variable 'NIX_PATH'.
|
||||
@@ -0,0 +1 @@
|
||||
/pwd/nix-shadow/nix/fetchurl.nix
|
||||
@@ -0,0 +1 @@
|
||||
<nix/fetchurl.nix>
|
||||
@@ -0,0 +1 @@
|
||||
assert false; "womp womp"
|
||||
@@ -2,7 +2,7 @@ from collections.abc import Callable
|
||||
from pathlib import Path
|
||||
|
||||
from functional2.lang.test_lang import test_eval as nix_eval
|
||||
from functional2.testlib.fixtures.file_helper import with_files, CopyTree, CopyFile, AssetSymlink
|
||||
from functional2.testlib.fixtures.file_helper import AssetSymlink, CopyFile, CopyTree, with_files
|
||||
from functional2.testlib.fixtures.nix import Nix
|
||||
from functional2.testlib.fixtures.snapshot import Snapshot
|
||||
|
||||
@@ -36,3 +36,39 @@ def test_search_path(files: Path, nix: Nix, snapshot: Callable[[str], Snapshot])
|
||||
],
|
||||
snapshot,
|
||||
)
|
||||
|
||||
|
||||
@with_files(
|
||||
{
|
||||
"nix-shadow": CopyTree("nix-shadow"),
|
||||
"in.nix": CopyFile("in-fetchurl.nix"),
|
||||
"out.exp": AssetSymlink("eval-okay-prefixed.out.exp"),
|
||||
"err.exp": AssetSymlink("eval-okay-prefixed.err.exp"),
|
||||
}
|
||||
)
|
||||
def test_prefixed_search_path(files: Path, nix: Nix, snapshot: Callable[[str], Snapshot]):
|
||||
nix.env.set_env("NIX_PATH", "nix=nix-shadow")
|
||||
nix_eval(files, nix, [], snapshot)
|
||||
|
||||
|
||||
@with_files(
|
||||
{
|
||||
"nix-shadow": CopyTree("nix-shadow"),
|
||||
"in.nix": CopyFile("in-fetchurl.nix"),
|
||||
"out.exp": AssetSymlink("eval-okay-prefixless.out.exp"),
|
||||
"err.exp": AssetSymlink("eval-okay-prefixless.err.exp"),
|
||||
}
|
||||
)
|
||||
def test_prefixless_search_path(files: Path, nix: Nix, snapshot: Callable[[str], Snapshot]):
|
||||
nix_eval(files, nix, ["-I", "nix-shadow"], snapshot)
|
||||
|
||||
|
||||
@with_files(
|
||||
{
|
||||
"in.nix": CopyFile("in-fetchurl.nix"),
|
||||
"out.exp": AssetSymlink("eval-okay-fetchurl.out.exp"),
|
||||
"err.exp": AssetSymlink("eval-okay-fetchurl.err.exp"),
|
||||
}
|
||||
)
|
||||
def test_empty_search_path(files: Path, nix: Nix, snapshot: Callable[[str], Snapshot]):
|
||||
nix_eval(files, nix, [], snapshot)
|
||||
|
||||
Reference in New Issue
Block a user