mirror of
https://github.com/NixOS/nix
synced 2025-06-27 21:01:16 +02:00
Merge remote-tracking branch 'upstream/master' into lfs
This commit is contained in:
commit
134530a534
32 changed files with 324 additions and 196 deletions
6
nix-meson-build-support/big-objs/meson.build
Normal file
6
nix-meson-build-support/big-objs/meson.build
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
if host_machine.system() == 'windows'
|
||||||
|
# libexpr's primops creates a large object
|
||||||
|
# Without the following flag, we'll get errors when cross-compiling to mingw32:
|
||||||
|
# Fatal error: can't write 66 bytes to section .text of src/libexpr/libnixexpr.dll.p/primops.cc.obj: 'file too big'
|
||||||
|
add_project_arguments([ '-Wa,-mbig-obj' ], language: 'cpp')
|
||||||
|
endif
|
|
@ -93,6 +93,7 @@ let
|
||||||
libs = throw "`nix.dev.libs` is not meant to be used; use `nix.libs` instead.";
|
libs = throw "`nix.dev.libs` is not meant to be used; use `nix.libs` instead.";
|
||||||
};
|
};
|
||||||
meta = {
|
meta = {
|
||||||
|
mainProgram = "nix";
|
||||||
pkgConfigModules = [
|
pkgConfigModules = [
|
||||||
"nix-cmd"
|
"nix-cmd"
|
||||||
"nix-expr"
|
"nix-expr"
|
||||||
|
|
|
@ -1,3 +1,13 @@
|
||||||
|
# Only execute this file once per shell.
|
||||||
|
if test -z "$HOME" || \
|
||||||
|
test -n "$__ETC_PROFILE_NIX_SOURCED"
|
||||||
|
exit
|
||||||
|
end
|
||||||
|
|
||||||
|
set --global __ETC_PROFILE_NIX_SOURCED 1
|
||||||
|
|
||||||
|
# Local helpers
|
||||||
|
|
||||||
function add_path --argument-names new_path
|
function add_path --argument-names new_path
|
||||||
if type -q fish_add_path
|
if type -q fish_add_path
|
||||||
# fish 3.2.0 or newer
|
# fish 3.2.0 or newer
|
||||||
|
@ -10,13 +20,7 @@ function add_path --argument-names new_path
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Only execute this file once per shell.
|
# Main configuration
|
||||||
if test -n "$__ETC_PROFILE_NIX_SOURCED"
|
|
||||||
exit
|
|
||||||
end
|
|
||||||
|
|
||||||
set __ETC_PROFILE_NIX_SOURCED 1
|
|
||||||
|
|
||||||
set --export NIX_PROFILES "@localstatedir@/nix/profiles/default $HOME/.nix-profile"
|
set --export NIX_PROFILES "@localstatedir@/nix/profiles/default $HOME/.nix-profile"
|
||||||
|
|
||||||
# Populate bash completions, .desktop files, etc
|
# Populate bash completions, .desktop files, etc
|
||||||
|
@ -29,29 +33,31 @@ end
|
||||||
|
|
||||||
# Set $NIX_SSL_CERT_FILE so that Nixpkgs applications like curl work.
|
# Set $NIX_SSL_CERT_FILE so that Nixpkgs applications like curl work.
|
||||||
if test -n "$NIX_SSL_CERT_FILE"
|
if test -n "$NIX_SSL_CERT_FILE"
|
||||||
: # Allow users to override the NIX_SSL_CERT_FILE
|
: # Allow users to override the NIX_SSL_CERT_FILE
|
||||||
else if test -e /etc/ssl/certs/ca-certificates.crt # NixOS, Ubuntu, Debian, Gentoo, Arch
|
else if test -e /etc/ssl/certs/ca-certificates.crt # NixOS, Ubuntu, Debian, Gentoo, Arch
|
||||||
set --export NIX_SSL_CERT_FILE /etc/ssl/certs/ca-certificates.crt
|
set --export NIX_SSL_CERT_FILE /etc/ssl/certs/ca-certificates.crt
|
||||||
else if test -e /etc/ssl/ca-bundle.pem # openSUSE Tumbleweed
|
else if test -e /etc/ssl/ca-bundle.pem # openSUSE Tumbleweed
|
||||||
set --export NIX_SSL_CERT_FILE /etc/ssl/ca-bundle.pem
|
set --export NIX_SSL_CERT_FILE /etc/ssl/ca-bundle.pem
|
||||||
else if test -e /etc/ssl/certs/ca-bundle.crt # Old NixOS
|
else if test -e /etc/ssl/certs/ca-bundle.crt # Old NixOS
|
||||||
set --export NIX_SSL_CERT_FILE /etc/ssl/certs/ca-bundle.crt
|
set --export NIX_SSL_CERT_FILE /etc/ssl/certs/ca-bundle.crt
|
||||||
else if test -e /etc/pki/tls/certs/ca-bundle.crt # Fedora, CentOS
|
else if test -e /etc/pki/tls/certs/ca-bundle.crt # Fedora, CentOS
|
||||||
set --export NIX_SSL_CERT_FILE /etc/pki/tls/certs/ca-bundle.crt
|
set --export NIX_SSL_CERT_FILE /etc/pki/tls/certs/ca-bundle.crt
|
||||||
else if test -e "$NIX_LINK/etc/ssl/certs/ca-bundle.crt" # fall back to cacert in Nix profile
|
else if test -e "$NIX_LINK/etc/ssl/certs/ca-bundle.crt" # fall back to cacert in Nix profile
|
||||||
set --export NIX_SSL_CERT_FILE "$NIX_LINK/etc/ssl/certs/ca-bundle.crt"
|
set --export NIX_SSL_CERT_FILE "$NIX_LINK/etc/ssl/certs/ca-bundle.crt"
|
||||||
else if test -e "$NIX_LINK/etc/ca-bundle.crt" # old cacert in Nix profile
|
else if test -e "$NIX_LINK/etc/ca-bundle.crt" # old cacert in Nix profile
|
||||||
set --export NIX_SSL_CERT_FILE "$NIX_LINK/etc/ca-bundle.crt"
|
set --export NIX_SSL_CERT_FILE "$NIX_LINK/etc/ca-bundle.crt"
|
||||||
else
|
else
|
||||||
# Fall back to what is in the nix profiles, favouring whatever is defined last.
|
# Fall back to what is in the nix profiles, favouring whatever is defined last.
|
||||||
for i in (string split ' ' $NIX_PROFILES)
|
for i in (string split ' ' $NIX_PROFILES)
|
||||||
if test -e "$i/etc/ssl/certs/ca-bundle.crt"
|
if test -e "$i/etc/ssl/certs/ca-bundle.crt"
|
||||||
set --export NIX_SSL_CERT_FILE "$i/etc/ssl/certs/ca-bundle.crt"
|
set --export NIX_SSL_CERT_FILE "$i/etc/ssl/certs/ca-bundle.crt"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
add_path "@localstatedir@/nix/profiles/default/bin"
|
add_path "@localstatedir@/nix/profiles/default/bin"
|
||||||
add_path "$HOME/.nix-profile/bin"
|
add_path "$HOME/.nix-profile/bin"
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
|
||||||
functions -e add_path
|
functions -e add_path
|
||||||
|
|
|
@ -1,3 +1,13 @@
|
||||||
|
# Only execute this file once per shell.
|
||||||
|
if test -z "$HOME" || test -z "$USER" || \
|
||||||
|
test -n "$__ETC_PROFILE_NIX_SOURCED"
|
||||||
|
exit
|
||||||
|
end
|
||||||
|
|
||||||
|
set --global __ETC_PROFILE_NIX_SOURCED 1
|
||||||
|
|
||||||
|
# Local helpers
|
||||||
|
|
||||||
function add_path --argument-names new_path
|
function add_path --argument-names new_path
|
||||||
if type -q fish_add_path
|
if type -q fish_add_path
|
||||||
# fish 3.2.0 or newer
|
# fish 3.2.0 or newer
|
||||||
|
@ -10,50 +20,51 @@ function add_path --argument-names new_path
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if test -n "$HOME" && test -n "$USER"
|
# Main configuration
|
||||||
|
|
||||||
# Set up the per-user profile.
|
# Set up the per-user profile.
|
||||||
|
|
||||||
set NIX_LINK $HOME/.nix-profile
|
set NIX_LINK $HOME/.nix-profile
|
||||||
|
|
||||||
# Set up environment.
|
# Set up environment.
|
||||||
# This part should be kept in sync with nixpkgs:nixos/modules/programs/environment.nix
|
# This part should be kept in sync with nixpkgs:nixos/modules/programs/environment.nix
|
||||||
set --export NIX_PROFILES "@localstatedir@/nix/profiles/default $HOME/.nix-profile"
|
set --export NIX_PROFILES "@localstatedir@/nix/profiles/default $HOME/.nix-profile"
|
||||||
|
|
||||||
# Populate bash completions, .desktop files, etc
|
# Populate bash completions, .desktop files, etc
|
||||||
if test -z "$XDG_DATA_DIRS"
|
if test -z "$XDG_DATA_DIRS"
|
||||||
# According to XDG spec the default is /usr/local/share:/usr/share, don't set something that prevents that default
|
# According to XDG spec the default is /usr/local/share:/usr/share, don't set something that prevents that default
|
||||||
set --export XDG_DATA_DIRS "/usr/local/share:/usr/share:$NIX_LINK/share:/nix/var/nix/profiles/default/share"
|
set --export XDG_DATA_DIRS "/usr/local/share:/usr/share:$NIX_LINK/share:/nix/var/nix/profiles/default/share"
|
||||||
else
|
else
|
||||||
set --export XDG_DATA_DIRS "$XDG_DATA_DIRS:$NIX_LINK/share:/nix/var/nix/profiles/default/share"
|
set --export XDG_DATA_DIRS "$XDG_DATA_DIRS:$NIX_LINK/share:/nix/var/nix/profiles/default/share"
|
||||||
end
|
|
||||||
|
|
||||||
# Set $NIX_SSL_CERT_FILE so that Nixpkgs applications like curl work.
|
|
||||||
if test -n "$NIX_SSH_CERT_FILE"
|
|
||||||
: # Allow users to override the NIX_SSL_CERT_FILE
|
|
||||||
else if test -e /etc/ssl/certs/ca-certificates.crt # NixOS, Ubuntu, Debian, Gentoo, Arch
|
|
||||||
set --export NIX_SSL_CERT_FILE /etc/ssl/certs/ca-certificates.crt
|
|
||||||
else if test -e /etc/ssl/ca-bundle.pem # openSUSE Tumbleweed
|
|
||||||
set --export NIX_SSL_CERT_FILE /etc/ssl/ca-bundle.pem
|
|
||||||
else if test -e /etc/ssl/certs/ca-bundle.crt # Old NixOS
|
|
||||||
set --export NIX_SSL_CERT_FILE /etc/ssl/certs/ca-bundle.crt
|
|
||||||
else if test -e /etc/pki/tls/certs/ca-bundle.crt # Fedora, CentOS
|
|
||||||
set --export NIX_SSL_CERT_FILE /etc/pki/tls/certs/ca-bundle.crt
|
|
||||||
else if test -e "$NIX_LINK/etc/ssl/certs/ca-bundle.crt" # fall back to cacert in Nix profile
|
|
||||||
set --export NIX_SSL_CERT_FILE "$NIX_LINK/etc/ssl/certs/ca-bundle.crt"
|
|
||||||
else if test -e "$NIX_LINK/etc/ca-bundle.crt" # old cacert in Nix profile
|
|
||||||
set --export NIX_SSL_CERT_FILE "$NIX_LINK/etc/ca-bundle.crt"
|
|
||||||
end
|
|
||||||
|
|
||||||
# Only use MANPATH if it is already set. In general `man` will just simply
|
|
||||||
# pick up `.nix-profile/share/man` because is it close to `.nix-profile/bin`
|
|
||||||
# which is in the $PATH. For more info, run `manpath -d`.
|
|
||||||
if set --query MANPATH
|
|
||||||
set --export --prepend --path MANPATH "$NIX_LINK/share/man"
|
|
||||||
end
|
|
||||||
|
|
||||||
add_path "$NIX_LINK/bin"
|
|
||||||
set --erase NIX_LINK
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Set $NIX_SSL_CERT_FILE so that Nixpkgs applications like curl work.
|
||||||
|
if test -n "$NIX_SSL_CERT_FILE"
|
||||||
|
: # Allow users to override the NIX_SSL_CERT_FILE
|
||||||
|
else if test -e /etc/ssl/certs/ca-certificates.crt # NixOS, Ubuntu, Debian, Gentoo, Arch
|
||||||
|
set --export NIX_SSL_CERT_FILE /etc/ssl/certs/ca-certificates.crt
|
||||||
|
else if test -e /etc/ssl/ca-bundle.pem # openSUSE Tumbleweed
|
||||||
|
set --export NIX_SSL_CERT_FILE /etc/ssl/ca-bundle.pem
|
||||||
|
else if test -e /etc/ssl/certs/ca-bundle.crt # Old NixOS
|
||||||
|
set --export NIX_SSL_CERT_FILE /etc/ssl/certs/ca-bundle.crt
|
||||||
|
else if test -e /etc/pki/tls/certs/ca-bundle.crt # Fedora, CentOS
|
||||||
|
set --export NIX_SSL_CERT_FILE /etc/pki/tls/certs/ca-bundle.crt
|
||||||
|
else if test -e "$NIX_LINK/etc/ssl/certs/ca-bundle.crt" # fall back to cacert in Nix profile
|
||||||
|
set --export NIX_SSL_CERT_FILE "$NIX_LINK/etc/ssl/certs/ca-bundle.crt"
|
||||||
|
else if test -e "$NIX_LINK/etc/ca-bundle.crt" # old cacert in Nix profile
|
||||||
|
set --export NIX_SSL_CERT_FILE "$NIX_LINK/etc/ca-bundle.crt"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Only use MANPATH if it is already set. In general `man` will just simply
|
||||||
|
# pick up `.nix-profile/share/man` because is it close to `.nix-profile/bin`
|
||||||
|
# which is in the $PATH. For more info, run `manpath -d`.
|
||||||
|
if set --query MANPATH
|
||||||
|
set --export --prepend --path MANPATH "$NIX_LINK/share/man"
|
||||||
|
end
|
||||||
|
|
||||||
|
add_path "$NIX_LINK/bin"
|
||||||
|
set --erase NIX_LINK
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
|
||||||
functions -e add_path
|
functions -e add_path
|
||||||
|
|
|
@ -613,12 +613,8 @@ nix_realised_string * nix_string_realise(nix_c_context * context, EvalState * st
|
||||||
context->last_err_code = NIX_OK;
|
context->last_err_code = NIX_OK;
|
||||||
try {
|
try {
|
||||||
auto & v = check_value_in(value);
|
auto & v = check_value_in(value);
|
||||||
nix::NixStringContext stringContext;
|
|
||||||
auto rawStr = state->state.coerceToString(nix::noPos, v, stringContext, "while realising a string").toOwned();
|
|
||||||
nix::StorePathSet storePaths;
|
nix::StorePathSet storePaths;
|
||||||
auto rewrites = state->state.realiseContext(stringContext, &storePaths);
|
auto s = state->state.realiseString(v, &storePaths, isIFD);
|
||||||
|
|
||||||
auto s = nix::rewriteStrings(rawStr, rewrites);
|
|
||||||
|
|
||||||
// Convert to the C API StorePath type and convert to vector for index-based access
|
// Convert to the C API StorePath type and convert to vector for index-based access
|
||||||
std::vector<StorePath> vec;
|
std::vector<StorePath> vec;
|
||||||
|
|
|
@ -820,6 +820,15 @@ public:
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] StringMap realiseContext(const NixStringContext & context, StorePathSet * maybePaths = nullptr, bool isIFD = true);
|
[[nodiscard]] StringMap realiseContext(const NixStringContext & context, StorePathSet * maybePaths = nullptr, bool isIFD = true);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Realise the given string with context, and return the string with outputs instead of downstream output placeholders.
|
||||||
|
* @param[in] str the string to realise
|
||||||
|
* @param[out] paths all referenced store paths will be added to this set
|
||||||
|
* @return the realised string
|
||||||
|
* @throw EvalError if the value is not a string, path or derivation (see `coerceToString`)
|
||||||
|
*/
|
||||||
|
std::string realiseString(Value & str, StorePathSet * storePathsOutMaybe, bool isIFD = true, const PosIdx pos = noPos);
|
||||||
|
|
||||||
/* Call the binary path filter predicate used builtins.path etc. */
|
/* Call the binary path filter predicate used builtins.path etc. */
|
||||||
bool callPathFilter(
|
bool callPathFilter(
|
||||||
Value * filterFun,
|
Value * filterFun,
|
||||||
|
|
|
@ -24,6 +24,7 @@ deps_public_maybe_subproject = [
|
||||||
dependency('nix-fetchers'),
|
dependency('nix-fetchers'),
|
||||||
]
|
]
|
||||||
subdir('nix-meson-build-support/subprojects')
|
subdir('nix-meson-build-support/subprojects')
|
||||||
|
subdir('nix-meson-build-support/big-objs')
|
||||||
|
|
||||||
boost = dependency(
|
boost = dependency(
|
||||||
'boost',
|
'boost',
|
||||||
|
|
|
@ -47,6 +47,15 @@ static inline Value * mkString(EvalState & state, const std::csub_match & match)
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string EvalState::realiseString(Value & s, StorePathSet * storePathsOutMaybe, bool isIFD, const PosIdx pos)
|
||||||
|
{
|
||||||
|
nix::NixStringContext stringContext;
|
||||||
|
auto rawStr = coerceToString(pos, s, stringContext, "while realising a string").toOwned();
|
||||||
|
auto rewrites = realiseContext(stringContext, storePathsOutMaybe, isIFD);
|
||||||
|
|
||||||
|
return nix::rewriteStrings(rawStr, rewrites);
|
||||||
|
}
|
||||||
|
|
||||||
StringMap EvalState::realiseContext(const NixStringContext & context, StorePathSet * maybePathsOut, bool isIFD)
|
StringMap EvalState::realiseContext(const NixStringContext & context, StorePathSet * maybePathsOut, bool isIFD)
|
||||||
{
|
{
|
||||||
std::vector<DerivedPath::Built> drvs;
|
std::vector<DerivedPath::Built> drvs;
|
||||||
|
|
|
@ -90,24 +90,26 @@ static void fetchTree(
|
||||||
fetchers::Input input { state.fetchSettings };
|
fetchers::Input input { state.fetchSettings };
|
||||||
NixStringContext context;
|
NixStringContext context;
|
||||||
std::optional<std::string> type;
|
std::optional<std::string> type;
|
||||||
|
auto fetcher = params.isFetchGit ? "fetchGit" : "fetchTree";
|
||||||
if (params.isFetchGit) type = "git";
|
if (params.isFetchGit) type = "git";
|
||||||
|
|
||||||
state.forceValue(*args[0], pos);
|
state.forceValue(*args[0], pos);
|
||||||
|
|
||||||
if (args[0]->type() == nAttrs) {
|
if (args[0]->type() == nAttrs) {
|
||||||
state.forceAttrs(*args[0], pos, "while evaluating the argument passed to builtins.fetchTree");
|
state.forceAttrs(*args[0], pos, fmt("while evaluating the argument passed to '%s'", fetcher));
|
||||||
|
|
||||||
fetchers::Attrs attrs;
|
fetchers::Attrs attrs;
|
||||||
|
|
||||||
if (auto aType = args[0]->attrs()->get(state.sType)) {
|
if (auto aType = args[0]->attrs()->get(state.sType)) {
|
||||||
if (type)
|
if (type)
|
||||||
state.error<EvalError>(
|
state.error<EvalError>(
|
||||||
"unexpected attribute 'type'"
|
"unexpected argument 'type'"
|
||||||
).atPos(pos).debugThrow();
|
).atPos(pos).debugThrow();
|
||||||
type = state.forceStringNoCtx(*aType->value, aType->pos, "while evaluating the `type` attribute passed to builtins.fetchTree");
|
type = state.forceStringNoCtx(*aType->value, aType->pos,
|
||||||
|
fmt("while evaluating the `type` argument passed to '%s'", fetcher));
|
||||||
} else if (!type)
|
} else if (!type)
|
||||||
state.error<EvalError>(
|
state.error<EvalError>(
|
||||||
"attribute 'type' is missing in call to 'fetchTree'"
|
"argument 'type' is missing in call to '%s'", fetcher
|
||||||
).atPos(pos).debugThrow();
|
).atPos(pos).debugThrow();
|
||||||
|
|
||||||
attrs.emplace("type", type.value());
|
attrs.emplace("type", type.value());
|
||||||
|
@ -127,9 +129,8 @@ static void fetchTree(
|
||||||
else if (attr.value->type() == nInt) {
|
else if (attr.value->type() == nInt) {
|
||||||
auto intValue = attr.value->integer().value;
|
auto intValue = attr.value->integer().value;
|
||||||
|
|
||||||
if (intValue < 0) {
|
if (intValue < 0)
|
||||||
state.error<EvalError>("negative value given for fetchTree attr %1%: %2%", state.symbols[attr.name], intValue).atPos(pos).debugThrow();
|
state.error<EvalError>("negative value given for '%s' argument '%s': %d", fetcher, state.symbols[attr.name], intValue).atPos(pos).debugThrow();
|
||||||
}
|
|
||||||
|
|
||||||
attrs.emplace(state.symbols[attr.name], uint64_t(intValue));
|
attrs.emplace(state.symbols[attr.name], uint64_t(intValue));
|
||||||
} else if (state.symbols[attr.name] == "publicKeys") {
|
} else if (state.symbols[attr.name] == "publicKeys") {
|
||||||
|
@ -137,8 +138,8 @@ static void fetchTree(
|
||||||
attrs.emplace(state.symbols[attr.name], printValueAsJSON(state, true, *attr.value, pos, context).dump());
|
attrs.emplace(state.symbols[attr.name], printValueAsJSON(state, true, *attr.value, pos, context).dump());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
state.error<TypeError>("fetchTree argument '%s' is %s while a string, Boolean or integer is expected",
|
state.error<TypeError>("argument '%s' to '%s' is %s while a string, Boolean or integer is expected",
|
||||||
state.symbols[attr.name], showType(*attr.value)).debugThrow();
|
state.symbols[attr.name], fetcher, showType(*attr.value)).debugThrow();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.isFetchGit && !attrs.contains("exportIgnore") && (!attrs.contains("submodules") || !*fetchers::maybeGetBoolAttr(attrs, "submodules"))) {
|
if (params.isFetchGit && !attrs.contains("exportIgnore") && (!attrs.contains("submodules") || !*fetchers::maybeGetBoolAttr(attrs, "submodules"))) {
|
||||||
|
@ -153,14 +154,14 @@ static void fetchTree(
|
||||||
if (!params.allowNameArgument)
|
if (!params.allowNameArgument)
|
||||||
if (auto nameIter = attrs.find("name"); nameIter != attrs.end())
|
if (auto nameIter = attrs.find("name"); nameIter != attrs.end())
|
||||||
state.error<EvalError>(
|
state.error<EvalError>(
|
||||||
"attribute 'name' isn’t supported in call to 'fetchTree'"
|
"argument 'name' isn’t supported in call to '%s'", fetcher
|
||||||
).atPos(pos).debugThrow();
|
).atPos(pos).debugThrow();
|
||||||
|
|
||||||
input = fetchers::Input::fromAttrs(state.fetchSettings, std::move(attrs));
|
input = fetchers::Input::fromAttrs(state.fetchSettings, std::move(attrs));
|
||||||
} else {
|
} else {
|
||||||
auto url = state.coerceToString(pos, *args[0], context,
|
auto url = state.coerceToString(pos, *args[0], context,
|
||||||
"while evaluating the first argument passed to the fetcher",
|
fmt("while evaluating the first argument passed to '%s'", fetcher),
|
||||||
false, false).toOwned();
|
false, false).toOwned();
|
||||||
|
|
||||||
if (params.isFetchGit) {
|
if (params.isFetchGit) {
|
||||||
fetchers::Attrs attrs;
|
fetchers::Attrs attrs;
|
||||||
|
@ -173,7 +174,7 @@ static void fetchTree(
|
||||||
} else {
|
} else {
|
||||||
if (!experimentalFeatureSettings.isEnabled(Xp::Flakes))
|
if (!experimentalFeatureSettings.isEnabled(Xp::Flakes))
|
||||||
state.error<EvalError>(
|
state.error<EvalError>(
|
||||||
"passing a string argument to 'fetchTree' requires the 'flakes' experimental feature"
|
"passing a string argument to '%s' requires the 'flakes' experimental feature", fetcher
|
||||||
).atPos(pos).debugThrow();
|
).atPos(pos).debugThrow();
|
||||||
input = fetchers::Input::fromURL(state.fetchSettings, url);
|
input = fetchers::Input::fromURL(state.fetchSettings, url);
|
||||||
}
|
}
|
||||||
|
@ -182,15 +183,16 @@ static void fetchTree(
|
||||||
if (!state.settings.pureEval && !input.isDirect() && experimentalFeatureSettings.isEnabled(Xp::Flakes))
|
if (!state.settings.pureEval && !input.isDirect() && experimentalFeatureSettings.isEnabled(Xp::Flakes))
|
||||||
input = lookupInRegistries(state.store, input).first;
|
input = lookupInRegistries(state.store, input).first;
|
||||||
|
|
||||||
if (state.settings.pureEval && !input.isConsideredLocked(state.fetchSettings)) {
|
if (state.settings.pureEval && !input.isLocked()) {
|
||||||
auto fetcher = "fetchTree";
|
if (input.getNarHash())
|
||||||
if (params.isFetchGit)
|
warn(
|
||||||
fetcher = "fetchGit";
|
"Input '%s' is unlocked (e.g. lacks a Git revision) but does have a NAR hash. "
|
||||||
|
"This is deprecated since such inputs are verifiable but may not be reproducible.",
|
||||||
state.error<EvalError>(
|
input.to_string());
|
||||||
"in pure evaluation mode, '%s' will not fetch unlocked input '%s'",
|
else
|
||||||
fetcher, input.to_string()
|
state.error<EvalError>(
|
||||||
).atPos(pos).debugThrow();
|
"in pure evaluation mode, '%s' will not fetch unlocked input '%s'",
|
||||||
|
fetcher, input.to_string()).atPos(pos).debugThrow();
|
||||||
}
|
}
|
||||||
|
|
||||||
state.checkURI(input.toURLString());
|
state.checkURI(input.toURLString());
|
||||||
|
|
|
@ -155,12 +155,6 @@ bool Input::isLocked() const
|
||||||
return scheme && scheme->isLocked(*this);
|
return scheme && scheme->isLocked(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Input::isConsideredLocked(
|
|
||||||
const Settings & settings) const
|
|
||||||
{
|
|
||||||
return isLocked() || (settings.allowDirtyLocks && getNarHash());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Input::isFinal() const
|
bool Input::isFinal() const
|
||||||
{
|
{
|
||||||
return maybeGetBoolAttr(attrs, "__final").value_or(false);
|
return maybeGetBoolAttr(attrs, "__final").value_or(false);
|
||||||
|
|
|
@ -90,15 +90,6 @@ public:
|
||||||
*/
|
*/
|
||||||
bool isLocked() const;
|
bool isLocked() const;
|
||||||
|
|
||||||
/**
|
|
||||||
* Return whether the input is either locked, or, if
|
|
||||||
* `allow-dirty-locks` is enabled, it has a NAR hash. In the
|
|
||||||
* latter case, we can verify the input but we may not be able to
|
|
||||||
* fetch it from anywhere.
|
|
||||||
*/
|
|
||||||
bool isConsideredLocked(
|
|
||||||
const Settings & settings) const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Only for relative path flakes, i.e. 'path:./foo', returns the
|
* Only for relative path flakes, i.e. 'path:./foo', returns the
|
||||||
* relative path, i.e. './foo'.
|
* relative path, i.e. './foo'.
|
||||||
|
|
|
@ -509,7 +509,11 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
|
||||||
*/
|
*/
|
||||||
ref<GitSourceAccessor> getRawAccessor(const Hash & rev, bool smudgeLfs);
|
ref<GitSourceAccessor> getRawAccessor(const Hash & rev, bool smudgeLfs);
|
||||||
|
|
||||||
ref<SourceAccessor> getAccessor(const Hash & rev, bool exportIgnore, bool smudgeLfs) override;
|
ref<SourceAccessor> getAccessor(
|
||||||
|
const Hash & rev,
|
||||||
|
bool exportIgnore,
|
||||||
|
std::string displayPrefix,
|
||||||
|
bool smudgeLfs) override;
|
||||||
|
|
||||||
ref<SourceAccessor> getAccessor(const WorkdirInfo & wd, bool exportIgnore, MakeNotAllowedError e) override;
|
ref<SourceAccessor> getAccessor(const WorkdirInfo & wd, bool exportIgnore, MakeNotAllowedError e) override;
|
||||||
|
|
||||||
|
@ -628,7 +632,7 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
|
||||||
|
|
||||||
Hash treeHashToNarHash(const Hash & treeHash) override
|
Hash treeHashToNarHash(const Hash & treeHash) override
|
||||||
{
|
{
|
||||||
auto accessor = getAccessor(treeHash, false, false);
|
auto accessor = getAccessor(treeHash, false, "", false);
|
||||||
|
|
||||||
fetchers::Cache::Key cacheKey{"treeHashToNarHash", {{"treeHash", treeHash.gitRev()}}};
|
fetchers::Cache::Key cacheKey{"treeHashToNarHash", {{"treeHash", treeHash.gitRev()}}};
|
||||||
|
|
||||||
|
@ -1212,16 +1216,19 @@ ref<GitSourceAccessor> GitRepoImpl::getRawAccessor(const Hash & rev, bool smudge
|
||||||
return make_ref<GitSourceAccessor>(self, rev, smudgeLfs);
|
return make_ref<GitSourceAccessor>(self, rev, smudgeLfs);
|
||||||
}
|
}
|
||||||
|
|
||||||
ref<SourceAccessor> GitRepoImpl::getAccessor(const Hash & rev, bool exportIgnore, bool smudgeLfs)
|
ref<SourceAccessor> GitRepoImpl::getAccessor(
|
||||||
|
const Hash & rev,
|
||||||
|
bool exportIgnore,
|
||||||
|
std::string displayPrefix,
|
||||||
|
bool smudgeLfs)
|
||||||
{
|
{
|
||||||
auto self = ref<GitRepoImpl>(shared_from_this());
|
auto self = ref<GitRepoImpl>(shared_from_this());
|
||||||
ref<GitSourceAccessor> rawGitAccessor = getRawAccessor(rev, smudgeLfs);
|
ref<GitSourceAccessor> rawGitAccessor = getRawAccessor(rev, smudgeLfs);
|
||||||
if (exportIgnore) {
|
rawGitAccessor->setPathDisplay(std::move(displayPrefix));
|
||||||
|
if (exportIgnore)
|
||||||
return make_ref<GitExportIgnoreSourceAccessor>(self, rawGitAccessor, rev);
|
return make_ref<GitExportIgnoreSourceAccessor>(self, rawGitAccessor, rev);
|
||||||
}
|
else
|
||||||
else {
|
|
||||||
return rawGitAccessor;
|
return rawGitAccessor;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ref<SourceAccessor> GitRepoImpl::getAccessor(const WorkdirInfo & wd, bool exportIgnore, MakeNotAllowedError makeNotAllowedError)
|
ref<SourceAccessor> GitRepoImpl::getAccessor(const WorkdirInfo & wd, bool exportIgnore, MakeNotAllowedError makeNotAllowedError)
|
||||||
|
@ -1254,7 +1261,7 @@ std::vector<std::tuple<GitRepoImpl::Submodule, Hash>> GitRepoImpl::getSubmodules
|
||||||
/* Read the .gitmodules files from this revision. */
|
/* Read the .gitmodules files from this revision. */
|
||||||
CanonPath modulesFile(".gitmodules");
|
CanonPath modulesFile(".gitmodules");
|
||||||
|
|
||||||
auto accessor = getAccessor(rev, exportIgnore, false);
|
auto accessor = getAccessor(rev, exportIgnore, "", false);
|
||||||
if (!accessor->pathExists(modulesFile)) return {};
|
if (!accessor->pathExists(modulesFile)) return {};
|
||||||
|
|
||||||
/* Parse it and get the revision of each submodule. */
|
/* Parse it and get the revision of each submodule. */
|
||||||
|
|
|
@ -86,7 +86,11 @@ struct GitRepo
|
||||||
|
|
||||||
virtual bool hasObject(const Hash & oid) = 0;
|
virtual bool hasObject(const Hash & oid) = 0;
|
||||||
|
|
||||||
virtual ref<SourceAccessor> getAccessor(const Hash & rev, bool exportIgnore, bool smudgeLfs) = 0;
|
virtual ref<SourceAccessor> getAccessor(
|
||||||
|
const Hash & rev,
|
||||||
|
bool exportIgnore,
|
||||||
|
std::string displayPrefix,
|
||||||
|
bool smudgeLfs) = 0;
|
||||||
|
|
||||||
virtual ref<SourceAccessor> getAccessor(const WorkdirInfo & wd, bool exportIgnore, MakeNotAllowedError makeNotAllowedError) = 0;
|
virtual ref<SourceAccessor> getAccessor(const WorkdirInfo & wd, bool exportIgnore, MakeNotAllowedError makeNotAllowedError) = 0;
|
||||||
|
|
||||||
|
|
|
@ -681,9 +681,7 @@ struct GitInputScheme : InputScheme
|
||||||
|
|
||||||
bool exportIgnore = getExportIgnoreAttr(input);
|
bool exportIgnore = getExportIgnoreAttr(input);
|
||||||
bool smudgeLfs = getLfsAttr(input);
|
bool smudgeLfs = getLfsAttr(input);
|
||||||
auto accessor = repo->getAccessor(rev, exportIgnore, smudgeLfs);
|
auto accessor = repo->getAccessor(rev, exportIgnore, "«" + input.to_string() + "»", smudgeLfs);
|
||||||
|
|
||||||
accessor->setPathDisplay("«" + input.to_string() + "»");
|
|
||||||
|
|
||||||
/* If the repo has submodules, fetch them and return a mounted
|
/* If the repo has submodules, fetch them and return a mounted
|
||||||
input accessor consisting of the accessor for the top-level
|
input accessor consisting of the accessor for the top-level
|
||||||
|
@ -747,8 +745,6 @@ struct GitInputScheme : InputScheme
|
||||||
exportIgnore,
|
exportIgnore,
|
||||||
makeNotAllowedError(repoInfo.locationToArg()));
|
makeNotAllowedError(repoInfo.locationToArg()));
|
||||||
|
|
||||||
accessor->setPathDisplay(repoInfo.locationToArg());
|
|
||||||
|
|
||||||
/* If the repo has submodules, return a mounted input accessor
|
/* If the repo has submodules, return a mounted input accessor
|
||||||
consisting of the accessor for the top-level repo and the
|
consisting of the accessor for the top-level repo and the
|
||||||
accessors for the submodule workdirs. */
|
accessors for the submodule workdirs. */
|
||||||
|
|
|
@ -294,9 +294,11 @@ struct GitArchiveInputScheme : InputScheme
|
||||||
#endif
|
#endif
|
||||||
input.attrs.insert_or_assign("lastModified", uint64_t(tarballInfo.lastModified));
|
input.attrs.insert_or_assign("lastModified", uint64_t(tarballInfo.lastModified));
|
||||||
|
|
||||||
auto accessor = getTarballCache()->getAccessor(tarballInfo.treeHash, false, false);
|
auto accessor = getTarballCache()->getAccessor(
|
||||||
|
tarballInfo.treeHash,
|
||||||
accessor->setPathDisplay("«" + input.to_string() + "»");
|
false,
|
||||||
|
"«" + input.to_string() + "»",
|
||||||
|
false);
|
||||||
|
|
||||||
return {accessor, input};
|
return {accessor, input};
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,7 +105,8 @@ DownloadFileResult downloadFile(
|
||||||
|
|
||||||
static DownloadTarballResult downloadTarball_(
|
static DownloadTarballResult downloadTarball_(
|
||||||
const std::string & url,
|
const std::string & url,
|
||||||
const Headers & headers)
|
const Headers & headers,
|
||||||
|
const std::string & displayPrefix)
|
||||||
{
|
{
|
||||||
Cache::Key cacheKey{"tarball", {{"url", url}}};
|
Cache::Key cacheKey{"tarball", {{"url", url}}};
|
||||||
|
|
||||||
|
@ -118,7 +119,7 @@ static DownloadTarballResult downloadTarball_(
|
||||||
.treeHash = treeHash,
|
.treeHash = treeHash,
|
||||||
.lastModified = (time_t) getIntAttr(infoAttrs, "lastModified"),
|
.lastModified = (time_t) getIntAttr(infoAttrs, "lastModified"),
|
||||||
.immutableUrl = maybeGetStrAttr(infoAttrs, "immutableUrl"),
|
.immutableUrl = maybeGetStrAttr(infoAttrs, "immutableUrl"),
|
||||||
.accessor = getTarballCache()->getAccessor(treeHash, false, false),
|
.accessor = getTarballCache()->getAccessor(treeHash, false, displayPrefix, false),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -371,9 +372,10 @@ struct TarballInputScheme : CurlInputScheme
|
||||||
{
|
{
|
||||||
auto input(_input);
|
auto input(_input);
|
||||||
|
|
||||||
auto result = downloadTarball_(getStrAttr(input.attrs, "url"), {});
|
auto result = downloadTarball_(
|
||||||
|
getStrAttr(input.attrs, "url"),
|
||||||
result.accessor->setPathDisplay("«" + input.to_string() + "»");
|
{},
|
||||||
|
"«" + input.to_string() + "»");
|
||||||
|
|
||||||
if (result.immutableUrl) {
|
if (result.immutableUrl) {
|
||||||
auto immutableInput = Input::fromURL(*input.settings, *result.immutableUrl);
|
auto immutableInput = Input::fromURL(*input.settings, *result.immutableUrl);
|
||||||
|
|
|
@ -107,7 +107,7 @@ std::pair<FlakeRef, std::string> parsePathFlakeRefWithFragment(
|
||||||
to 'baseDir'). If so, search upward to the root of the
|
to 'baseDir'). If so, search upward to the root of the
|
||||||
repo (i.e. the directory containing .git). */
|
repo (i.e. the directory containing .git). */
|
||||||
|
|
||||||
path = absPath(path, baseDir);
|
path = absPath(path, baseDir, true);
|
||||||
|
|
||||||
if (isFlake) {
|
if (isFlake) {
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
|
#include "fetch-settings.hh"
|
||||||
|
#include "flake/settings.hh"
|
||||||
#include "lockfile.hh"
|
#include "lockfile.hh"
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
|
#include "strings.hh"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
@ -9,8 +12,6 @@
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
#include "strings.hh"
|
|
||||||
#include "flake/settings.hh"
|
|
||||||
|
|
||||||
namespace nix::flake {
|
namespace nix::flake {
|
||||||
|
|
||||||
|
@ -45,9 +46,16 @@ LockedNode::LockedNode(
|
||||||
, isFlake(json.find("flake") != json.end() ? (bool) json["flake"] : true)
|
, isFlake(json.find("flake") != json.end() ? (bool) json["flake"] : true)
|
||||||
, parentInputAttrPath(json.find("parent") != json.end() ? (std::optional<InputAttrPath>) json["parent"] : std::nullopt)
|
, parentInputAttrPath(json.find("parent") != json.end() ? (std::optional<InputAttrPath>) json["parent"] : std::nullopt)
|
||||||
{
|
{
|
||||||
if (!lockedRef.input.isConsideredLocked(fetchSettings) && !lockedRef.input.isRelative())
|
if (!lockedRef.input.isLocked() && !lockedRef.input.isRelative()) {
|
||||||
throw Error("Lock file contains unlocked input '%s'. Use '--allow-dirty-locks' to accept this lock file.",
|
if (lockedRef.input.getNarHash())
|
||||||
fetchers::attrsToJSON(lockedRef.input.toAttrs()));
|
warn(
|
||||||
|
"Lock file entry '%s' is unlocked (e.g. lacks a Git revision) but does have a NAR hash. "
|
||||||
|
"This is deprecated since such inputs are verifiable but may not be reproducible.",
|
||||||
|
lockedRef.to_string());
|
||||||
|
else
|
||||||
|
throw Error("Lock file contains unlocked input '%s'. Use '--allow-dirty-locks' to accept this lock file.",
|
||||||
|
fetchers::attrsToJSON(lockedRef.input.toAttrs()));
|
||||||
|
}
|
||||||
|
|
||||||
// For backward compatibility, lock file entries are implicitly final.
|
// For backward compatibility, lock file entries are implicitly final.
|
||||||
assert(!lockedRef.input.attrs.contains("__final"));
|
assert(!lockedRef.input.attrs.contains("__final"));
|
||||||
|
@ -248,11 +256,20 @@ std::optional<FlakeRef> LockFile::isUnlocked(const fetchers::Settings & fetchSet
|
||||||
|
|
||||||
visit(root);
|
visit(root);
|
||||||
|
|
||||||
|
/* Return whether the input is either locked, or, if
|
||||||
|
`allow-dirty-locks` is enabled, it has a NAR hash. In the
|
||||||
|
latter case, we can verify the input but we may not be able to
|
||||||
|
fetch it from anywhere. */
|
||||||
|
auto isConsideredLocked = [&](const fetchers::Input & input)
|
||||||
|
{
|
||||||
|
return input.isLocked() || (fetchSettings.allowDirtyLocks && input.getNarHash());
|
||||||
|
};
|
||||||
|
|
||||||
for (auto & i : nodes) {
|
for (auto & i : nodes) {
|
||||||
if (i == ref<const Node>(root)) continue;
|
if (i == ref<const Node>(root)) continue;
|
||||||
auto node = i.dynamic_pointer_cast<const LockedNode>();
|
auto node = i.dynamic_pointer_cast<const LockedNode>();
|
||||||
if (node
|
if (node
|
||||||
&& (!node->lockedRef.input.isConsideredLocked(fetchSettings)
|
&& (!isConsideredLocked(node->lockedRef.input)
|
||||||
|| !node->lockedRef.input.isFinal())
|
|| !node->lockedRef.input.isFinal())
|
||||||
&& !node->lockedRef.input.isRelative())
|
&& !node->lockedRef.input.isRelative())
|
||||||
return node->lockedRef;
|
return node->lockedRef;
|
||||||
|
|
|
@ -167,16 +167,15 @@ LocalStore::LocalStore(
|
||||||
|
|
||||||
/* Ensure that the store and its parents are not symlinks. */
|
/* Ensure that the store and its parents are not symlinks. */
|
||||||
if (!settings.allowSymlinkedStore) {
|
if (!settings.allowSymlinkedStore) {
|
||||||
Path path = realStoreDir;
|
std::filesystem::path path = realStoreDir.get();
|
||||||
struct stat st;
|
std::filesystem::path root = path.root_path();
|
||||||
while (path != "/") {
|
while (path != root) {
|
||||||
st = lstat(path);
|
if (std::filesystem::is_symlink(path))
|
||||||
if (S_ISLNK(st.st_mode))
|
|
||||||
throw Error(
|
throw Error(
|
||||||
"the path '%1%' is a symlink; "
|
"the path '%1%' is a symlink; "
|
||||||
"this is not allowed for the Nix store and its parent directories",
|
"this is not allowed for the Nix store and its parent directories",
|
||||||
path);
|
path);
|
||||||
path = dirOf(path);
|
path = path.parent_path();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,10 +19,6 @@
|
||||||
# include "namespaces.hh"
|
# include "namespaces.hh"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
# include <sys/resource.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
unsigned int getMaxCPU()
|
unsigned int getMaxCPU()
|
||||||
|
@ -55,11 +51,11 @@ unsigned int getMaxCPU()
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
size_t savedStackSize = 0;
|
size_t savedStackSize = 0;
|
||||||
|
|
||||||
void setStackSize(size_t stackSize)
|
void setStackSize(size_t stackSize)
|
||||||
{
|
{
|
||||||
#ifndef _WIN32
|
|
||||||
struct rlimit limit;
|
struct rlimit limit;
|
||||||
if (getrlimit(RLIMIT_STACK, &limit) == 0 && limit.rlim_cur < stackSize) {
|
if (getrlimit(RLIMIT_STACK, &limit) == 0 && limit.rlim_cur < stackSize) {
|
||||||
savedStackSize = limit.rlim_cur;
|
savedStackSize = limit.rlim_cur;
|
||||||
|
@ -77,31 +73,8 @@ void setStackSize(size_t stackSize)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
ULONG_PTR stackLow, stackHigh;
|
|
||||||
GetCurrentThreadStackLimits(&stackLow, &stackHigh);
|
|
||||||
ULONG maxStackSize = stackHigh - stackLow;
|
|
||||||
ULONG currStackSize = 0;
|
|
||||||
// This retrieves the current promised stack size
|
|
||||||
SetThreadStackGuarantee(&currStackSize);
|
|
||||||
if (currStackSize < stackSize) {
|
|
||||||
savedStackSize = currStackSize;
|
|
||||||
ULONG newStackSize = std::min(static_cast<ULONG>(stackSize), maxStackSize);
|
|
||||||
if (SetThreadStackGuarantee(&newStackSize) == 0) {
|
|
||||||
logger->log(
|
|
||||||
lvlError,
|
|
||||||
HintFmt(
|
|
||||||
"Failed to increase stack size from %1% to %2% (maximum allowed stack size: %3%): %4%",
|
|
||||||
savedStackSize,
|
|
||||||
stackSize,
|
|
||||||
maxStackSize,
|
|
||||||
std::to_string(GetLastError())
|
|
||||||
).str()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void restoreProcessContext(bool restoreMounts)
|
void restoreProcessContext(bool restoreMounts)
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,10 +17,13 @@ namespace nix {
|
||||||
*/
|
*/
|
||||||
unsigned int getMaxCPU();
|
unsigned int getMaxCPU();
|
||||||
|
|
||||||
|
// It does not seem possible to dynamically change stack size on Windows.
|
||||||
|
#ifndef _WIN32
|
||||||
/**
|
/**
|
||||||
* Change the stack size.
|
* Change the stack size.
|
||||||
*/
|
*/
|
||||||
void setStackSize(size_t stackSize);
|
void setStackSize(size_t stackSize);
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Restore the original inherited Unix process context (such as signal
|
* Restore the original inherited Unix process context (such as signal
|
||||||
|
|
|
@ -557,9 +557,11 @@ void mainWrapped(int argc, char * * argv)
|
||||||
|
|
||||||
int main(int argc, char * * argv)
|
int main(int argc, char * * argv)
|
||||||
{
|
{
|
||||||
|
#ifndef _WIN32
|
||||||
// Increase the default stack size for the evaluator and for
|
// Increase the default stack size for the evaluator and for
|
||||||
// libstdc++'s std::regex.
|
// libstdc++'s std::regex.
|
||||||
nix::setStackSize(64 * 1024 * 1024);
|
nix::setStackSize(64 * 1024 * 1024);
|
||||||
|
#endif
|
||||||
|
|
||||||
return nix::handleExceptions(argv[0], [&]() {
|
return nix::handleExceptions(argv[0], [&]() {
|
||||||
nix::mainWrapped(argc, argv);
|
nix::mainWrapped(argc, argv);
|
||||||
|
|
|
@ -103,6 +103,7 @@ mkMesonExecutable (finalAttrs: {
|
||||||
];
|
];
|
||||||
|
|
||||||
meta = {
|
meta = {
|
||||||
|
mainProgram = "nix";
|
||||||
platforms = lib.platforms.unix ++ lib.platforms.windows;
|
platforms = lib.platforms.unix ++ lib.platforms.windows;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
# shellcheck shell=bash
|
# shellcheck shell=bash
|
||||||
|
|
||||||
|
badTestNames=()
|
||||||
|
|
||||||
# Golden test support
|
# Golden test support
|
||||||
#
|
#
|
||||||
# Test that the output of the given test matches what is expected. If
|
# Test that the output of the given test matches what is expected. If
|
||||||
|
@ -18,10 +20,11 @@ function diffAndAcceptInner() {
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Diff so we get a nice message
|
# Diff so we get a nice message
|
||||||
if ! diff --color=always --unified "$expectedOrEmpty" "$got"; then
|
if ! diff >&2 --color=always --unified "$expectedOrEmpty" "$got"; then
|
||||||
echo "FAIL: evaluation result of $testName not as expected"
|
echo >&2 "FAIL: evaluation result of $testName not as expected"
|
||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
badDiff=1
|
badDiff=1
|
||||||
|
badTestNames+=("$testName")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Update expected if `_NIX_TEST_ACCEPT` is non-empty.
|
# Update expected if `_NIX_TEST_ACCEPT` is non-empty.
|
||||||
|
@ -42,14 +45,14 @@ function characterisationTestExit() {
|
||||||
if test -n "${_NIX_TEST_ACCEPT-}"; then
|
if test -n "${_NIX_TEST_ACCEPT-}"; then
|
||||||
if (( "$badDiff" )); then
|
if (( "$badDiff" )); then
|
||||||
set +x
|
set +x
|
||||||
echo 'Output did mot match, but accepted output as the persisted expected output.'
|
echo >&2 'Output did mot match, but accepted output as the persisted expected output.'
|
||||||
echo 'That means the next time the tests are run, they should pass.'
|
echo >&2 'That means the next time the tests are run, they should pass.'
|
||||||
set -x
|
set -x
|
||||||
else
|
else
|
||||||
set +x
|
set +x
|
||||||
echo 'NOTE: Environment variable _NIX_TEST_ACCEPT is defined,'
|
echo >&2 'NOTE: Environment variable _NIX_TEST_ACCEPT is defined,'
|
||||||
echo 'indicating the unexpected output should be accepted as the expected output going forward,'
|
echo >&2 'indicating the unexpected output should be accepted as the expected output going forward,'
|
||||||
echo 'but no tests had unexpected output so there was no expected output to update.'
|
echo >&2 'but no tests had unexpected output so there was no expected output to update.'
|
||||||
set -x
|
set -x
|
||||||
fi
|
fi
|
||||||
if (( "$badExitCode" )); then
|
if (( "$badExitCode" )); then
|
||||||
|
@ -60,16 +63,21 @@ function characterisationTestExit() {
|
||||||
else
|
else
|
||||||
if (( "$badDiff" )); then
|
if (( "$badDiff" )); then
|
||||||
set +x
|
set +x
|
||||||
echo ''
|
echo >&2 ''
|
||||||
echo 'You can rerun this test with:'
|
echo >&2 'The following tests had unexpected output:'
|
||||||
echo ''
|
for testName in "${badTestNames[@]}"; do
|
||||||
echo " _NIX_TEST_ACCEPT=1 make tests/functional/${TEST_NAME}.sh.test"
|
echo >&2 " $testName"
|
||||||
echo ''
|
done
|
||||||
echo 'to regenerate the files containing the expected output,'
|
echo >&2 ''
|
||||||
echo 'and then view the git diff to decide whether a change is'
|
echo >&2 'You can rerun this test with:'
|
||||||
echo 'good/intentional or bad/unintentional.'
|
echo >&2 ''
|
||||||
echo 'If the diff contains arbitrary or impure information,'
|
echo >&2 " _NIX_TEST_ACCEPT=1 meson test ${TEST_NAME}"
|
||||||
echo 'please improve the normalization that the test applies to the output.'
|
echo >&2 ''
|
||||||
|
echo >&2 'to regenerate the files containing the expected output,'
|
||||||
|
echo >&2 'and then view the git diff to decide whether a change is'
|
||||||
|
echo >&2 'good/intentional or bad/unintentional.'
|
||||||
|
echo >&2 'If the diff contains arbitrary or impure information,'
|
||||||
|
echo >&2 'please improve the normalization that the test applies to the output.'
|
||||||
set -x
|
set -x
|
||||||
fi
|
fi
|
||||||
exit $(( "$badExitCode" + "$badDiff" ))
|
exit $(( "$badExitCode" + "$badDiff" ))
|
||||||
|
|
|
@ -37,6 +37,7 @@ nix-instantiate --eval -E "builtins.readFile ((builtins.fetchGit file://$TEST_RO
|
||||||
|
|
||||||
# Fetch a worktree.
|
# Fetch a worktree.
|
||||||
unset _NIX_FORCE_HTTP
|
unset _NIX_FORCE_HTTP
|
||||||
|
expectStderr 0 nix eval -vvvv --impure --raw --expr "(builtins.fetchGit file://$TEST_ROOT/worktree).outPath" | grepQuiet "copying '$TEST_ROOT/worktree/' to the store"
|
||||||
path0=$(nix eval --impure --raw --expr "(builtins.fetchGit file://$TEST_ROOT/worktree).outPath")
|
path0=$(nix eval --impure --raw --expr "(builtins.fetchGit file://$TEST_ROOT/worktree).outPath")
|
||||||
path0_=$(nix eval --impure --raw --expr "(builtins.fetchTree { type = \"git\"; url = file://$TEST_ROOT/worktree; }).outPath")
|
path0_=$(nix eval --impure --raw --expr "(builtins.fetchTree { type = \"git\"; url = file://$TEST_ROOT/worktree; }).outPath")
|
||||||
[[ $path0 = $path0_ ]]
|
[[ $path0 = $path0_ ]]
|
||||||
|
@ -64,7 +65,7 @@ git -C $repo add differentbranch
|
||||||
git -C $repo commit -m 'Test2'
|
git -C $repo commit -m 'Test2'
|
||||||
git -C $repo checkout master
|
git -C $repo checkout master
|
||||||
devrev=$(git -C $repo rev-parse devtest)
|
devrev=$(git -C $repo rev-parse devtest)
|
||||||
nix eval --impure --raw --expr "builtins.fetchGit { url = file://$repo; rev = \"$devrev\"; }"
|
nix eval --raw --expr "builtins.fetchGit { url = file://$repo; rev = \"$devrev\"; }"
|
||||||
|
|
||||||
[[ $(nix eval --raw --expr "builtins.readFile (builtins.fetchGit { url = file://$repo; rev = \"$devrev\"; allRefs = true; } + \"/differentbranch\")") = 'different file' ]]
|
[[ $(nix eval --raw --expr "builtins.readFile (builtins.fetchGit { url = file://$repo; rev = \"$devrev\"; allRefs = true; } + \"/differentbranch\")") = 'different file' ]]
|
||||||
|
|
||||||
|
@ -79,7 +80,7 @@ path2=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$repo; rev = \"
|
||||||
# In pure eval mode, fetchGit with a revision should succeed.
|
# In pure eval mode, fetchGit with a revision should succeed.
|
||||||
[[ $(nix eval --raw --expr "builtins.readFile (fetchGit { url = file://$repo; rev = \"$rev2\"; } + \"/hello\")") = world ]]
|
[[ $(nix eval --raw --expr "builtins.readFile (fetchGit { url = file://$repo; rev = \"$rev2\"; } + \"/hello\")") = world ]]
|
||||||
|
|
||||||
# But without a hash, it fails
|
# But without a hash, it fails.
|
||||||
expectStderr 1 nix eval --expr 'builtins.fetchGit "file:///foo"' | grepQuiet "'fetchGit' will not fetch unlocked input"
|
expectStderr 1 nix eval --expr 'builtins.fetchGit "file:///foo"' | grepQuiet "'fetchGit' will not fetch unlocked input"
|
||||||
|
|
||||||
# Fetch again. This should be cached.
|
# Fetch again. This should be cached.
|
||||||
|
@ -141,13 +142,17 @@ path4=$(nix eval --impure --refresh --raw --expr "(builtins.fetchGit file://$rep
|
||||||
[[ $(nix eval --impure --expr "builtins.hasAttr \"dirtyRev\" (builtins.fetchGit $repo)") == "false" ]]
|
[[ $(nix eval --impure --expr "builtins.hasAttr \"dirtyRev\" (builtins.fetchGit $repo)") == "false" ]]
|
||||||
[[ $(nix eval --impure --expr "builtins.hasAttr \"dirtyShortRev\" (builtins.fetchGit $repo)") == "false" ]]
|
[[ $(nix eval --impure --expr "builtins.hasAttr \"dirtyShortRev\" (builtins.fetchGit $repo)") == "false" ]]
|
||||||
|
|
||||||
status=0
|
expect 102 nix eval --raw --expr "(builtins.fetchGit { url = $repo; rev = \"$rev2\"; narHash = \"sha256-B5yIPHhEm0eysJKEsO7nqxprh9vcblFxpJG11gXJus1=\"; }).outPath"
|
||||||
nix eval --impure --raw --expr "(builtins.fetchGit { url = $repo; rev = \"$rev2\"; narHash = \"sha256-B5yIPHhEm0eysJKEsO7nqxprh9vcblFxpJG11gXJus1=\"; }).outPath" || status=$?
|
|
||||||
[[ "$status" = "102" ]]
|
|
||||||
|
|
||||||
path5=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = $repo; rev = \"$rev2\"; narHash = \"sha256-Hr8g6AqANb3xqX28eu1XnjK/3ab8Gv6TJSnkb1LezG9=\"; }).outPath")
|
path5=$(nix eval --raw --expr "(builtins.fetchGit { url = $repo; rev = \"$rev2\"; narHash = \"sha256-Hr8g6AqANb3xqX28eu1XnjK/3ab8Gv6TJSnkb1LezG9=\"; }).outPath")
|
||||||
[[ $path = $path5 ]]
|
[[ $path = $path5 ]]
|
||||||
|
|
||||||
|
# Ensure that NAR hashes are checked.
|
||||||
|
expectStderr 102 nix eval --raw --expr "(builtins.fetchGit { url = $repo; rev = \"$rev2\"; narHash = \"sha256-Hr8g6AqANb4xqX28eu1XnjK/3ab8Gv6TJSnkb1LezG9=\"; }).outPath" | grepQuiet "error: NAR hash mismatch"
|
||||||
|
|
||||||
|
# It's allowed to use only a narHash, but you should get a warning.
|
||||||
|
expectStderr 0 nix eval --raw --expr "(builtins.fetchGit { url = $repo; ref = \"tag2\"; narHash = \"sha256-Hr8g6AqANb3xqX28eu1XnjK/3ab8Gv6TJSnkb1LezG9=\"; }).outPath" | grepQuiet "warning: Input .* is unlocked"
|
||||||
|
|
||||||
# tarball-ttl should be ignored if we specify a rev
|
# tarball-ttl should be ignored if we specify a rev
|
||||||
echo delft > $repo/hello
|
echo delft > $repo/hello
|
||||||
git -C $repo add hello
|
git -C $repo add hello
|
||||||
|
@ -255,7 +260,7 @@ echo "/exported-wonky export-ignore=wonk" >> $repo/.gitattributes
|
||||||
git -C $repo add not-exported-file exported-wonky .gitattributes
|
git -C $repo add not-exported-file exported-wonky .gitattributes
|
||||||
git -C $repo commit -m 'Bla6'
|
git -C $repo commit -m 'Bla6'
|
||||||
rev5=$(git -C $repo rev-parse HEAD)
|
rev5=$(git -C $repo rev-parse HEAD)
|
||||||
path12=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = file://$repo; rev = \"$rev5\"; }).outPath")
|
path12=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$repo; rev = \"$rev5\"; }).outPath")
|
||||||
[[ ! -e $path12/not-exported-file ]]
|
[[ ! -e $path12/not-exported-file ]]
|
||||||
[[ -e $path12/exported-wonky ]]
|
[[ -e $path12/exported-wonky ]]
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ suites += {
|
||||||
'commit-lock-file-summary.sh',
|
'commit-lock-file-summary.sh',
|
||||||
'non-flake-inputs.sh',
|
'non-flake-inputs.sh',
|
||||||
'relative-paths.sh',
|
'relative-paths.sh',
|
||||||
|
'symlink-paths.sh'
|
||||||
],
|
],
|
||||||
'workdir': meson.current_source_dir(),
|
'workdir': meson.current_source_dir(),
|
||||||
}
|
}
|
||||||
|
|
75
tests/functional/flakes/symlink-paths.sh
Normal file
75
tests/functional/flakes/symlink-paths.sh
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
source ./common.sh
|
||||||
|
|
||||||
|
requireGit
|
||||||
|
|
||||||
|
create_flake() {
|
||||||
|
local flakeDir="$1"
|
||||||
|
createGitRepo $flakeDir
|
||||||
|
cat > $flakeDir/flake.nix <<EOF
|
||||||
|
{
|
||||||
|
outputs = { self }: { x = 2; };
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
git -C $flakeDir add flake.nix
|
||||||
|
git -C $flakeDir commit -m Initial
|
||||||
|
}
|
||||||
|
|
||||||
|
test_symlink_points_to_flake() {
|
||||||
|
create_flake "$TEST_ROOT/flake1"
|
||||||
|
ln -sn "$TEST_ROOT/flake1" "$TEST_ROOT/flake1_sym"
|
||||||
|
[[ $(nix eval "$TEST_ROOT/flake1_sym#x") = 2 ]]
|
||||||
|
rm -rf "$TEST_ROOT/flake1" "$TEST_ROOT/flake1_sym"
|
||||||
|
}
|
||||||
|
test_symlink_points_to_flake
|
||||||
|
|
||||||
|
test_symlink_points_to_flake_in_subdir() {
|
||||||
|
create_flake "$TEST_ROOT/subdir/flake1"
|
||||||
|
ln -sn "$TEST_ROOT/subdir" "$TEST_ROOT/subdir_sym"
|
||||||
|
[[ $(nix eval "$TEST_ROOT/subdir_sym/flake1#x") = 2 ]]
|
||||||
|
rm -rf "$TEST_ROOT/subdir" "$TEST_ROOT/subdir_sym"
|
||||||
|
}
|
||||||
|
test_symlink_points_to_flake_in_subdir
|
||||||
|
|
||||||
|
test_symlink_points_to_dir_in_repo() {
|
||||||
|
local repoDir="$TEST_ROOT/flake1"
|
||||||
|
createGitRepo $repoDir
|
||||||
|
mkdir -p "$repoDir/subdir"
|
||||||
|
cat > $repoDir/subdir/flake.nix <<EOF
|
||||||
|
{
|
||||||
|
outputs = { self }: { x = 2; };
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
git -C $repoDir add subdir/flake.nix
|
||||||
|
git -C $repoDir commit -m Initial
|
||||||
|
ln -sn "$TEST_ROOT/flake1/subdir" "$TEST_ROOT/flake1_sym"
|
||||||
|
[[ $(nix eval "$TEST_ROOT/flake1_sym#x") = 2 ]]
|
||||||
|
rm -rf "$TEST_ROOT/flake1" "$TEST_ROOT/flake1_sym"
|
||||||
|
}
|
||||||
|
test_symlink_points_to_dir_in_repo
|
||||||
|
|
||||||
|
test_symlink_from_repo_to_another() {
|
||||||
|
local repoDir="$TEST_ROOT/repo1"
|
||||||
|
createGitRepo $repoDir
|
||||||
|
echo "Hello" > $repoDir/file
|
||||||
|
mkdir $repoDir/subdir
|
||||||
|
cat > $repoDir/subdir/flake.nix <<EOF
|
||||||
|
{
|
||||||
|
outputs = { self }: { x = builtins.readFile ../file; };
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
git -C $repoDir add subdir/flake.nix file
|
||||||
|
git -C $repoDir commit -m Initial
|
||||||
|
[[ $(nix eval "$TEST_ROOT/repo1/subdir#x") == \"Hello\\n\" ]]
|
||||||
|
|
||||||
|
local repo2Dir="$TEST_ROOT/repo2"
|
||||||
|
createGitRepo $repo2Dir
|
||||||
|
ln -sn "$repoDir/subdir" "$repo2Dir/flake1_sym"
|
||||||
|
echo "World" > $repo2Dir/file
|
||||||
|
git -C "$repo2Dir" add flake1_sym file
|
||||||
|
git -C "$repo2Dir" commit -m Initial
|
||||||
|
[[ $(nix eval "$repo2Dir/flake1_sym#x") == \"Hello\\n\" ]]
|
||||||
|
rm -rf "$TEST_ROOT/repo1" "$TEST_ROOT/repo2"
|
||||||
|
}
|
||||||
|
test_symlink_from_repo_to_another
|
|
@ -37,8 +37,8 @@ expectStderr 1 nix flake lock "$flake2Dir" --override-input flake1 "$TEST_ROOT/f
|
||||||
|
|
||||||
nix flake lock "$flake2Dir" --override-input flake1 "$TEST_ROOT/flake1" --allow-dirty-locks
|
nix flake lock "$flake2Dir" --override-input flake1 "$TEST_ROOT/flake1" --allow-dirty-locks
|
||||||
|
|
||||||
# Using a lock file with a dirty lock requires --allow-dirty-locks as well.
|
# Using a lock file with a dirty lock does not require --allow-dirty-locks, but should print a warning.
|
||||||
expectStderr 1 nix eval "$flake2Dir#x" |
|
expectStderr 0 nix eval "$flake2Dir#x" |
|
||||||
grepQuiet "Lock file contains unlocked input"
|
grepQuiet "warning: Lock file entry .* is unlocked"
|
||||||
|
|
||||||
[[ $(nix eval "$flake2Dir#x" --allow-dirty-locks) = 456 ]]
|
[[ $(nix eval "$flake2Dir#x") = 456 ]]
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
source common.sh
|
source common.sh
|
||||||
|
|
||||||
# Store layer needs bugfix
|
# Store layer needs bugfix
|
||||||
|
|
|
@ -25,7 +25,7 @@ done
|
||||||
|
|
||||||
# FIXME: we don't know whether we built the manpages, so we can't
|
# FIXME: we don't know whether we built the manpages, so we can't
|
||||||
# reliably test them here.
|
# reliably test them here.
|
||||||
exit 0
|
if false; then
|
||||||
|
|
||||||
# test help output
|
# test help output
|
||||||
|
|
||||||
|
@ -74,3 +74,5 @@ nix-daemon --help
|
||||||
nix-hash --help
|
nix-hash --help
|
||||||
nix-instantiate --help
|
nix-instantiate --help
|
||||||
nix-prefetch-url --help
|
nix-prefetch-url --help
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
|
@ -5,4 +5,4 @@ error:
|
||||||
| ^
|
| ^
|
||||||
2| type = "file";
|
2| type = "file";
|
||||||
|
|
||||||
error: negative value given for fetchTree attr owner: -1
|
error: negative value given for 'fetchTree' argument 'owner': -1
|
||||||
|
|
|
@ -32,7 +32,10 @@ in
|
||||||
services.gitea.lfs.enable = true;
|
services.gitea.lfs.enable = true;
|
||||||
services.gitea.settings = {
|
services.gitea.settings = {
|
||||||
service.DISABLE_REGISTRATION = true;
|
service.DISABLE_REGISTRATION = true;
|
||||||
server = { DOMAIN = "gitea"; HTTP_PORT = 3000; };
|
server = {
|
||||||
|
DOMAIN = "gitea";
|
||||||
|
HTTP_PORT = 3000;
|
||||||
|
};
|
||||||
log.LEVEL = "Info";
|
log.LEVEL = "Info";
|
||||||
database.LOG_SQL = false;
|
database.LOG_SQL = false;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue