1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-07-07 18:31:49 +02:00

Merge branch 'master' into read-only-local-store

This commit is contained in:
Ben Radford 2023-06-06 11:07:36 +01:00
commit e484278e9b
No known key found for this signature in database
GPG key ID: 9DF5D4640AB888D5
31 changed files with 213 additions and 106 deletions

View file

@ -2620,7 +2620,7 @@ Strings EvalSettings::getDefaultNixPath()
{
Strings res;
auto add = [&](const Path & p, const std::string & s = std::string()) {
if (pathExists(p)) {
if (pathAccessible(p)) {
if (s.empty()) {
res.push_back(p);
} else {

View file

@ -745,7 +745,13 @@ struct EvalSettings : Config
)"};
Setting<bool> pureEval{this, false, "pure-eval",
"Whether to restrict file system and network access to files specified by cryptographic hash."};
R"(
Pure evaluation mode ensures that the result of Nix expressions is fully determined by explicitly declared inputs, and not influenced by external state:
- Restrict file system and network access to files specified by cryptographic hash
- Disable [`bultins.currentSystem`](@docroot@/language/builtin-constants.md#builtins-currentSystem) and [`builtins.currentTime`](@docroot@/language/builtin-constants.md#builtins-currentTime)
)"
};
Setting<bool> enableImportFromDerivation{
this, true, "allow-import-from-derivation",

View file

@ -1152,16 +1152,14 @@ drvName, Bindings * attrs, Value & v)
if (i->value->type() == nNull) continue;
}
if (i->name == state.sContentAddressed) {
contentAddressed = state.forceBool(*i->value, noPos, context_below);
if (contentAddressed)
experimentalFeatureSettings.require(Xp::CaDerivations);
if (i->name == state.sContentAddressed && state.forceBool(*i->value, noPos, context_below)) {
contentAddressed = true;
experimentalFeatureSettings.require(Xp::CaDerivations);
}
else if (i->name == state.sImpure) {
isImpure = state.forceBool(*i->value, noPos, context_below);
if (isImpure)
experimentalFeatureSettings.require(Xp::ImpureDerivations);
else if (i->name == state.sImpure && state.forceBool(*i->value, noPos, context_below)) {
isImpure = true;
experimentalFeatureSettings.require(Xp::ImpureDerivations);
}
/* The `args' attribute is special: it supplies the
@ -1503,7 +1501,7 @@ static RegisterPrimOp primop_storePath({
causes the path to be *copied* again to the Nix store, resulting
in a new path (e.g. `/nix/store/ld01dnzc-source-source`).
This function is not available in pure evaluation mode.
Not available in [pure evaluation mode](@docroot@/command-ref/conf-file.md#conf-pure-eval).
)",
.fun = prim_storePath,
});
@ -3910,13 +3908,8 @@ static void prim_replaceStrings(EvalState & state, const PosIdx pos, Value * * a
for (auto elem : args[0]->listItems())
from.emplace_back(state.forceString(*elem, pos, "while evaluating one of the strings to replace passed to builtins.replaceStrings"));
std::vector<std::pair<std::string, NixStringContext>> to;
to.reserve(args[1]->listSize());
for (auto elem : args[1]->listItems()) {
NixStringContext ctx;
auto s = state.forceString(*elem, ctx, pos, "while evaluating one of the replacement strings passed to builtins.replaceStrings");
to.emplace_back(s, std::move(ctx));
}
std::unordered_map<size_t, std::string> cache;
auto to = args[1]->listItems();
NixStringContext context;
auto s = state.forceString(*args[2], context, pos, "while evaluating the third argument passed to builtins.replaceStrings");
@ -3927,10 +3920,19 @@ static void prim_replaceStrings(EvalState & state, const PosIdx pos, Value * * a
bool found = false;
auto i = from.begin();
auto j = to.begin();
for (; i != from.end(); ++i, ++j)
size_t j_index = 0;
for (; i != from.end(); ++i, ++j, ++j_index)
if (s.compare(p, i->size(), *i) == 0) {
found = true;
res += j->first;
auto v = cache.find(j_index);
if (v == cache.end()) {
NixStringContext ctx;
auto ts = state.forceString(**j, ctx, pos, "while evaluating one of the replacement strings passed to builtins.replaceStrings");
v = (cache.emplace(j_index, ts)).first;
for (auto& path : ctx)
context.insert(path);
}
res += v->second;
if (i->empty()) {
if (p < s.size())
res += s[p];
@ -3938,9 +3940,6 @@ static void prim_replaceStrings(EvalState & state, const PosIdx pos, Value * * a
} else {
p += i->size();
}
for (auto& path : j->second)
context.insert(path);
j->second.clear();
break;
}
if (!found) {
@ -3958,7 +3957,11 @@ static RegisterPrimOp primop_replaceStrings({
.args = {"from", "to", "s"},
.doc = R"(
Given string *s*, replace every occurrence of the strings in *from*
with the corresponding string in *to*. For example,
with the corresponding string in *to*.
The argument *to* is lazy, that is, it is only evaluated when its corresponding pattern in *from* is matched in the string *s*
Example:
```nix
builtins.replaceStrings ["oo" "a"] ["a" "i"] "foobar"

View file

@ -286,9 +286,9 @@ static RegisterPrimOp primop_fetchurl({
.name = "__fetchurl",
.args = {"url"},
.doc = R"(
Download the specified URL and return the path of the downloaded
file. This function is not available if [restricted evaluation
mode](../command-ref/conf-file.md) is enabled.
Download the specified URL and return the path of the downloaded file.
Not available in [restricted evaluation mode](@docroot@/command-ref/conf-file.md#conf-restrict-eval).
)",
.fun = prim_fetchurl,
});
@ -338,8 +338,7 @@ static RegisterPrimOp primop_fetchTarball({
stdenv.mkDerivation { }
```
This function is not available if [restricted evaluation
mode](../command-ref/conf-file.md) is enabled.
Not available in [restricted evaluation mode](@docroot@/command-ref/conf-file.md#conf-restrict-eval).
)",
.fun = prim_fetchTarball,
});
@ -470,14 +469,9 @@ static RegisterPrimOp primop_fetchGit({
}
```
> **Note**
>
> Nix will refetch the branch in accordance with
> the option `tarball-ttl`.
Nix will refetch the branch according to the [`tarball-ttl`](@docroot@/command-ref/conf-file.md#conf-tarball-ttl) setting.
> **Note**
>
> This behavior is disabled in *Pure evaluation mode*.
This behavior is disabled in [pure evaluation mode](@docroot@/command-ref/conf-file.md#conf-pure-eval).
- To fetch the content of a checked-out work directory:

View file

@ -171,7 +171,7 @@ namespace nix {
hintfmt("value is %s while a string was expected", "an integer"),
hintfmt("while evaluating one of the strings to replace passed to builtins.replaceStrings"));
ASSERT_TRACE2("replaceStrings [ \"old\" ] [ true ] {}",
ASSERT_TRACE2("replaceStrings [ \"oo\" ] [ true ] \"foo\"",
TypeError,
hintfmt("value is %s while a string was expected", "a Boolean"),
hintfmt("while evaluating one of the replacement strings passed to builtins.replaceStrings"));

View file

@ -75,22 +75,28 @@ SourcePath SourcePath::resolveSymlinks() const
int linksAllowed = 1024;
for (auto & component : path) {
res.path.push(component);
while (true) {
if (auto st = res.maybeLstat()) {
std::list<std::string> todo;
for (auto & c : path)
todo.push_back(std::string(c));
while (!todo.empty()) {
auto c = *todo.begin();
todo.pop_front();
if (c == "" || c == ".")
;
else if (c == "..")
res.path.pop();
else {
res.path.push(c);
if (auto st = res.maybeLstat(); st && st->type == InputAccessor::tSymlink) {
if (!linksAllowed--)
throw Error("infinite symlink recursion in path '%s'", path);
if (st->type != InputAccessor::tSymlink) break;
auto target = res.readLink();
res.path.pop();
if (hasPrefix(target, "/"))
res = CanonPath(target);
else {
res.path.pop();
res.path.extend(CanonPath(target));
}
} else
break;
res.path = CanonPath::root;
todo.splice(todo.begin(), tokenizeString<std::list<std::string>>(target, "/"));
}
}
}

View file

@ -357,7 +357,7 @@ bool LocalDerivationGoal::cleanupDecideWhetherDiskFull()
for (auto & [_, status] : initialOutputs) {
if (!status.known) continue;
if (buildMode != bmCheck && status.known->isValid()) continue;
auto p = worker.store.printStorePath(status.known->path);
auto p = worker.store.toRealPath(status.known->path);
if (pathExists(chrootRootDir + p))
renameFile((chrootRootDir + p), p);
}

View file

@ -183,7 +183,7 @@ bool Settings::isWSL1()
Path Settings::getDefaultSSLCertFile()
{
for (auto & fn : {"/etc/ssl/certs/ca-certificates.crt", "/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt"})
if (pathExists(fn)) return fn;
if (pathAccessible(fn)) return fn;
return "";
}

View file

@ -995,6 +995,18 @@ public:
| `~/.nix-profile` | `$XDG_STATE_HOME/nix/profile` |
| `~/.nix-defexpr` | `$XDG_STATE_HOME/nix/defexpr` |
| `~/.nix-channels` | `$XDG_STATE_HOME/nix/channels` |
If you already have Nix installed and are using [profiles](@docroot@/package-management/profiles.md) or [channels](@docroot@/package-management/channels.md), you should migrate manually when you enable this option.
If `$XDG_STATE_HOME` is not set, use `$HOME/.local/state/nix` instead of `$XDG_STATE_HOME/nix`.
This can be achieved with the following shell commands:
```sh
nix_state_home=${XDG_STATE_HOME-$HOME/.local/state}/nix
mkdir -p $nix_state_home
mv $HOME/.nix-profile $nix_state_home/profile
mv $HOME/.nix-defexpr $nix_state_home/defexpr
mv $HOME/.nix-channels $nix_state_home/channels
```
)"
};
};

View file

@ -50,6 +50,8 @@ constexpr std::array<ExperimentalFeatureDetails, 14> xpFeatureDetails = {{
or other impure derivations can rely on impure derivations. Finally,
an impure derivation cannot also be
[content-addressed](#xp-feature-ca-derivations).
This is a more explicit alternative to using [`builtins.currentTime`](@docroot@/language/builtin-constants.md#builtins-currentTime).
)",
},
{

View file

@ -202,7 +202,7 @@ namespace nix {
}
TEST(pathExists, bogusPathDoesNotExist) {
ASSERT_FALSE(pathExists("/home/schnitzel/darmstadt/pommes"));
ASSERT_FALSE(pathExists("/schnitzel/darmstadt/pommes"));
}
/* ----------------------------------------------------------------------------

View file

@ -266,6 +266,17 @@ bool pathExists(const Path & path)
return false;
}
bool pathAccessible(const Path & path)
{
try {
return pathExists(path);
} catch (SysError & e) {
// swallow EPERM
if (e.errNo == EPERM) return false;
throw;
}
}
Path readLink(const Path & path)
{

View file

@ -120,6 +120,14 @@ struct stat lstat(const Path & path);
*/
bool pathExists(const Path & path);
/**
* A version of pathExists that returns false on a permission error.
* Useful for inferring default paths across directories that might not
* be readable.
* @return true iff the given path can be accessed and exists
*/
bool pathAccessible(const Path & path);
/**
* Read the contents (target) of a symbolic link. The result is not
* in any way canonicalised.

View file

@ -102,6 +102,7 @@ way:
available in the flake. If this is undesirable, specify `path:<directory>` explicitly;
For example, if `/foo/bar` is a git repository with the following structure:
```
.
└── baz