mirror of
https://github.com/NixOS/nix
synced 2025-06-27 21:01:16 +02:00
Merge remote-tracking branch 'upstream/master' into single-ca-drv-build
This commit is contained in:
commit
ef278d00f9
267 changed files with 12456 additions and 17851 deletions
|
@ -29,7 +29,7 @@ MixEvalArgs::MixEvalArgs()
|
|||
addFlag({
|
||||
.longName = "include",
|
||||
.shortName = 'I',
|
||||
.description = "add a path to the list of locations used to look up <...> file names",
|
||||
.description = "add a path to the list of locations used to look up `<...>` file names",
|
||||
.labels = {"path"},
|
||||
.handler = {[&](std::string s) { searchPath.push_back(s); }}
|
||||
});
|
||||
|
|
|
@ -381,10 +381,14 @@ EvalState::EvalState(const Strings & _searchPath, ref<Store> store)
|
|||
auto path = r.second;
|
||||
|
||||
if (store->isInStore(r.second)) {
|
||||
StorePathSet closure;
|
||||
store->computeFSClosure(store->toStorePath(r.second).first, closure);
|
||||
for (auto & path : closure)
|
||||
allowedPaths->insert(store->printStorePath(path));
|
||||
try {
|
||||
StorePathSet closure;
|
||||
store->computeFSClosure(store->toStorePath(r.second).first, closure);
|
||||
for (auto & path : closure)
|
||||
allowedPaths->insert(store->printStorePath(path));
|
||||
} catch (InvalidPath &) {
|
||||
allowedPaths->insert(r.second);
|
||||
}
|
||||
} else
|
||||
allowedPaths->insert(r.second);
|
||||
}
|
||||
|
@ -509,7 +513,7 @@ Value * EvalState::addPrimOp(const string & name,
|
|||
if (arity == 0) {
|
||||
auto vPrimOp = allocValue();
|
||||
vPrimOp->type = tPrimOp;
|
||||
vPrimOp->primOp = new PrimOp(primOp, 1, sym);
|
||||
vPrimOp->primOp = new PrimOp { .fun = primOp, .arity = 1, .name = sym };
|
||||
Value v;
|
||||
mkApp(v, *vPrimOp, *vPrimOp);
|
||||
return addConstant(name, v);
|
||||
|
@ -517,7 +521,7 @@ Value * EvalState::addPrimOp(const string & name,
|
|||
|
||||
Value * v = allocValue();
|
||||
v->type = tPrimOp;
|
||||
v->primOp = new PrimOp(primOp, arity, sym);
|
||||
v->primOp = new PrimOp { .fun = primOp, .arity = arity, .name = sym };
|
||||
staticBaseEnv.vars[symbols.create(name)] = baseEnvDispl;
|
||||
baseEnv.values[baseEnvDispl++] = v;
|
||||
baseEnv.values[0]->attrs->push_back(Attr(sym, v));
|
||||
|
@ -525,12 +529,59 @@ Value * EvalState::addPrimOp(const string & name,
|
|||
}
|
||||
|
||||
|
||||
Value * EvalState::addPrimOp(PrimOp && primOp)
|
||||
{
|
||||
/* Hack to make constants lazy: turn them into a application of
|
||||
the primop to a dummy value. */
|
||||
if (primOp.arity == 0) {
|
||||
primOp.arity = 1;
|
||||
auto vPrimOp = allocValue();
|
||||
vPrimOp->type = tPrimOp;
|
||||
vPrimOp->primOp = new PrimOp(std::move(primOp));
|
||||
Value v;
|
||||
mkApp(v, *vPrimOp, *vPrimOp);
|
||||
return addConstant(primOp.name, v);
|
||||
}
|
||||
|
||||
Symbol envName = primOp.name;
|
||||
if (hasPrefix(primOp.name, "__"))
|
||||
primOp.name = symbols.create(std::string(primOp.name, 2));
|
||||
|
||||
Value * v = allocValue();
|
||||
v->type = tPrimOp;
|
||||
v->primOp = new PrimOp(std::move(primOp));
|
||||
staticBaseEnv.vars[envName] = baseEnvDispl;
|
||||
baseEnv.values[baseEnvDispl++] = v;
|
||||
baseEnv.values[0]->attrs->push_back(Attr(primOp.name, v));
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
Value & EvalState::getBuiltin(const string & name)
|
||||
{
|
||||
return *baseEnv.values[0]->attrs->find(symbols.create(name))->value;
|
||||
}
|
||||
|
||||
|
||||
std::optional<EvalState::Doc> EvalState::getDoc(Value & v)
|
||||
{
|
||||
if (v.type == tPrimOp || v.type == tPrimOpApp) {
|
||||
auto v2 = &v;
|
||||
while (v2->type == tPrimOpApp)
|
||||
v2 = v2->primOpApp.left;
|
||||
if (v2->primOp->doc)
|
||||
return Doc {
|
||||
.pos = noPos,
|
||||
.name = v2->primOp->name,
|
||||
.arity = v2->primOp->arity,
|
||||
.args = v2->primOp->args,
|
||||
.doc = v2->primOp->doc,
|
||||
};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
/* Every "format" object (even temporary) takes up a few hundred bytes
|
||||
of stack space, which is a real killer in the recursive
|
||||
evaluator. So here are some helper functions for throwing
|
||||
|
|
|
@ -30,8 +30,8 @@ struct PrimOp
|
|||
PrimOpFun fun;
|
||||
size_t arity;
|
||||
Symbol name;
|
||||
PrimOp(PrimOpFun fun, size_t arity, Symbol name)
|
||||
: fun(fun), arity(arity), name(name) { }
|
||||
std::vector<std::string> args;
|
||||
const char * doc = nullptr;
|
||||
};
|
||||
|
||||
|
||||
|
@ -242,10 +242,23 @@ private:
|
|||
Value * addPrimOp(const string & name,
|
||||
size_t arity, PrimOpFun primOp);
|
||||
|
||||
Value * addPrimOp(PrimOp && primOp);
|
||||
|
||||
public:
|
||||
|
||||
Value & getBuiltin(const string & name);
|
||||
|
||||
struct Doc
|
||||
{
|
||||
Pos pos;
|
||||
std::optional<Symbol> name;
|
||||
size_t arity;
|
||||
std::vector<std::string> args;
|
||||
const char * doc;
|
||||
};
|
||||
|
||||
std::optional<Doc> getDoc(Value & v);
|
||||
|
||||
private:
|
||||
|
||||
inline Value * lookupVar(Env * env, const ExprVar & var, bool noEval);
|
||||
|
@ -357,24 +370,57 @@ struct EvalSettings : Config
|
|||
Setting<bool> enableNativeCode{this, false, "allow-unsafe-native-code-during-evaluation",
|
||||
"Whether builtin functions that allow executing native code should be enabled."};
|
||||
|
||||
Setting<Strings> nixPath{this, getDefaultNixPath(), "nix-path",
|
||||
"List of directories to be searched for <...> file references."};
|
||||
Setting<Strings> nixPath{
|
||||
this, getDefaultNixPath(), "nix-path",
|
||||
"List of directories to be searched for `<...>` file references."};
|
||||
|
||||
Setting<bool> restrictEval{this, false, "restrict-eval",
|
||||
"Whether to restrict file system access to paths in $NIX_PATH, "
|
||||
"and network access to the URI prefixes listed in 'allowed-uris'."};
|
||||
Setting<bool> restrictEval{
|
||||
this, false, "restrict-eval",
|
||||
R"(
|
||||
If set to `true`, the Nix evaluator will not allow access to any
|
||||
files outside of the Nix search path (as set via the `NIX_PATH`
|
||||
environment variable or the `-I` option), or to URIs outside of
|
||||
`allowed-uri`. The default is `false`.
|
||||
)"};
|
||||
|
||||
Setting<bool> pureEval{this, false, "pure-eval",
|
||||
"Whether to restrict file system and network access to files specified by cryptographic hash."};
|
||||
|
||||
Setting<bool> enableImportFromDerivation{this, true, "allow-import-from-derivation",
|
||||
"Whether the evaluator allows importing the result of a derivation."};
|
||||
Setting<bool> enableImportFromDerivation{
|
||||
this, true, "allow-import-from-derivation",
|
||||
R"(
|
||||
By default, Nix allows you to `import` from a derivation, allowing
|
||||
building at evaluation time. With this option set to false, Nix will
|
||||
throw an error when evaluating an expression that uses this feature,
|
||||
allowing users to ensure their evaluation will not require any
|
||||
builds to take place.
|
||||
)"};
|
||||
|
||||
Setting<Strings> allowedUris{this, {}, "allowed-uris",
|
||||
"Prefixes of URIs that builtin functions such as fetchurl and fetchGit are allowed to fetch."};
|
||||
R"(
|
||||
A list of URI prefixes to which access is allowed in restricted
|
||||
evaluation mode. For example, when set to
|
||||
`https://github.com/NixOS`, builtin functions such as `fetchGit` are
|
||||
allowed to access `https://github.com/NixOS/patchelf.git`.
|
||||
)"};
|
||||
|
||||
Setting<bool> traceFunctionCalls{this, false, "trace-function-calls",
|
||||
"Emit log messages for each function entry and exit at the 'vomit' log level (-vvvv)."};
|
||||
R"(
|
||||
If set to `true`, the Nix evaluator will trace every function call.
|
||||
Nix will print a log message at the "vomit" level for every function
|
||||
entrance and function exit.
|
||||
|
||||
function-trace entered undefined position at 1565795816999559622
|
||||
function-trace exited undefined position at 1565795816999581277
|
||||
function-trace entered /nix/store/.../example.nix:226:41 at 1565795253249935150
|
||||
function-trace exited /nix/store/.../example.nix:226:41 at 1565795253249941684
|
||||
|
||||
The `undefined position` means the function call is a builtin.
|
||||
|
||||
Use the `contrib/stack-collapse.py` script distributed with the Nix
|
||||
source code to convert the trace logs in to a format suitable for
|
||||
`flamegraph.pl`.
|
||||
)"};
|
||||
|
||||
Setting<bool> useEvalCache{this, true, "eval-cache",
|
||||
"Whether to use the flake evaluation cache."};
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -10,9 +10,11 @@ struct RegisterPrimOp
|
|||
struct Info
|
||||
{
|
||||
std::string name;
|
||||
size_t arity;
|
||||
PrimOpFun primOp;
|
||||
std::vector<std::string> args;
|
||||
size_t arity = 0;
|
||||
const char * doc;
|
||||
std::optional<std::string> requiredFeature;
|
||||
PrimOpFun fun;
|
||||
};
|
||||
|
||||
typedef std::vector<Info> PrimOps;
|
||||
|
@ -26,6 +28,8 @@ struct RegisterPrimOp
|
|||
size_t arity,
|
||||
PrimOpFun fun,
|
||||
std::optional<std::string> requiredFeature = {});
|
||||
|
||||
RegisterPrimOp(Info && info);
|
||||
};
|
||||
|
||||
/* These primops are disabled without enableNativeCode, but plugins
|
||||
|
|
|
@ -226,18 +226,187 @@ static void prim_fetchurl(EvalState & state, const Pos & pos, Value * * args, Va
|
|||
fetch(state, pos, args, v, "fetchurl", false, "");
|
||||
}
|
||||
|
||||
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.
|
||||
)",
|
||||
.fun = prim_fetchurl,
|
||||
});
|
||||
|
||||
static void prim_fetchTarball(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||
{
|
||||
fetch(state, pos, args, v, "fetchTarball", true, "source");
|
||||
}
|
||||
|
||||
static RegisterPrimOp primop_fetchTarball({
|
||||
.name = "fetchTarball",
|
||||
.args = {"args"},
|
||||
.doc = R"(
|
||||
Download the specified URL, unpack it and return the path of the
|
||||
unpacked tree. The file must be a tape archive (`.tar`) compressed
|
||||
with `gzip`, `bzip2` or `xz`. The top-level path component of the
|
||||
files in the tarball is removed, so it is best if the tarball
|
||||
contains a single directory at top level. The typical use of the
|
||||
function is to obtain external Nix expression dependencies, such as
|
||||
a particular version of Nixpkgs, e.g.
|
||||
|
||||
```nix
|
||||
with import (fetchTarball https://github.com/NixOS/nixpkgs/archive/nixos-14.12.tar.gz) {};
|
||||
|
||||
stdenv.mkDerivation { … }
|
||||
```
|
||||
|
||||
The fetched tarball is cached for a certain amount of time (1 hour
|
||||
by default) in `~/.cache/nix/tarballs/`. You can change the cache
|
||||
timeout either on the command line with `--option tarball-ttl number
|
||||
of seconds` or in the Nix configuration file with this option: `
|
||||
number of seconds to cache `.
|
||||
|
||||
Note that when obtaining the hash with ` nix-prefetch-url ` the
|
||||
option `--unpack` is required.
|
||||
|
||||
This function can also verify the contents against a hash. In that
|
||||
case, the function takes a set instead of a URL. The set requires
|
||||
the attribute `url` and the attribute `sha256`, e.g.
|
||||
|
||||
```nix
|
||||
with import (fetchTarball {
|
||||
url = "https://github.com/NixOS/nixpkgs/archive/nixos-14.12.tar.gz";
|
||||
sha256 = "1jppksrfvbk5ypiqdz4cddxdl8z6zyzdb2srq8fcffr327ld5jj2";
|
||||
}) {};
|
||||
|
||||
stdenv.mkDerivation { … }
|
||||
```
|
||||
|
||||
This function is not available if [restricted evaluation
|
||||
mode](../command-ref/conf-file.md) is enabled.
|
||||
)",
|
||||
.fun = prim_fetchTarball,
|
||||
});
|
||||
|
||||
static void prim_fetchGit(EvalState &state, const Pos &pos, Value **args, Value &v)
|
||||
{
|
||||
fetchTree(state, pos, args, v, "git", true);
|
||||
}
|
||||
|
||||
static RegisterPrimOp r2("__fetchurl", 1, prim_fetchurl);
|
||||
static RegisterPrimOp r3("fetchTarball", 1, prim_fetchTarball);
|
||||
static RegisterPrimOp r4("fetchGit", 1, prim_fetchGit);
|
||||
static RegisterPrimOp primop_fetchGit({
|
||||
.name = "fetchGit",
|
||||
.args = {"args"},
|
||||
.doc = R"(
|
||||
Fetch a path from git. *args* can be a URL, in which case the HEAD
|
||||
of the repo at that URL is fetched. Otherwise, it can be an
|
||||
attribute with the following attributes (all except `url` optional):
|
||||
|
||||
- url
|
||||
The URL of the repo.
|
||||
|
||||
- name
|
||||
The name of the directory the repo should be exported to in the
|
||||
store. Defaults to the basename of the URL.
|
||||
|
||||
- rev
|
||||
The git revision to fetch. Defaults to the tip of `ref`.
|
||||
|
||||
- ref
|
||||
The git ref to look for the requested revision under. This is
|
||||
often a branch or tag name. Defaults to `HEAD`.
|
||||
|
||||
By default, the `ref` value is prefixed with `refs/heads/`. As
|
||||
of Nix 2.3.0 Nix will not prefix `refs/heads/` if `ref` starts
|
||||
with `refs/`.
|
||||
|
||||
- submodules
|
||||
A Boolean parameter that specifies whether submodules should be
|
||||
checked out. Defaults to `false`.
|
||||
|
||||
Here are some examples of how to use `fetchGit`.
|
||||
|
||||
- To fetch a private repository over SSH:
|
||||
|
||||
```nix
|
||||
builtins.fetchGit {
|
||||
url = "git@github.com:my-secret/repository.git";
|
||||
ref = "master";
|
||||
rev = "adab8b916a45068c044658c4158d81878f9ed1c3";
|
||||
}
|
||||
```
|
||||
|
||||
- To fetch an arbitrary reference:
|
||||
|
||||
```nix
|
||||
builtins.fetchGit {
|
||||
url = "https://github.com/NixOS/nix.git";
|
||||
ref = "refs/heads/0.5-release";
|
||||
}
|
||||
```
|
||||
|
||||
- If the revision you're looking for is in the default branch of
|
||||
the git repository you don't strictly need to specify the branch
|
||||
name in the `ref` attribute.
|
||||
|
||||
However, if the revision you're looking for is in a future
|
||||
branch for the non-default branch you will need to specify the
|
||||
the `ref` attribute as well.
|
||||
|
||||
```nix
|
||||
builtins.fetchGit {
|
||||
url = "https://github.com/nixos/nix.git";
|
||||
rev = "841fcbd04755c7a2865c51c1e2d3b045976b7452";
|
||||
ref = "1.11-maintenance";
|
||||
}
|
||||
```
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> It is nice to always specify the branch which a revision
|
||||
> belongs to. Without the branch being specified, the fetcher
|
||||
> might fail if the default branch changes. Additionally, it can
|
||||
> be confusing to try a commit from a non-default branch and see
|
||||
> the fetch fail. If the branch is specified the fault is much
|
||||
> more obvious.
|
||||
|
||||
- If the revision you're looking for is in the default branch of
|
||||
the git repository you may omit the `ref` attribute.
|
||||
|
||||
```nix
|
||||
builtins.fetchGit {
|
||||
url = "https://github.com/nixos/nix.git";
|
||||
rev = "841fcbd04755c7a2865c51c1e2d3b045976b7452";
|
||||
}
|
||||
```
|
||||
|
||||
- To fetch a specific tag:
|
||||
|
||||
```nix
|
||||
builtins.fetchGit {
|
||||
url = "https://github.com/nixos/nix.git";
|
||||
ref = "refs/tags/1.9";
|
||||
}
|
||||
```
|
||||
|
||||
- To fetch the latest version of a remote branch:
|
||||
|
||||
```nix
|
||||
builtins.fetchGit {
|
||||
url = "ssh://git@github.com/nixos/nix.git";
|
||||
ref = "master";
|
||||
}
|
||||
```
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> Nix will refetch the branch in accordance with
|
||||
> the option `tarball-ttl`.
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> This behavior is disabled in *Pure evaluation mode*.
|
||||
)",
|
||||
.fun = prim_fetchGit,
|
||||
});
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue