mirror of
https://github.com/NixOS/nix
synced 2025-07-07 01:51:47 +02:00
Merge remote-tracking branch 'origin/master' into lazy-trees
This commit is contained in:
commit
022390af5a
13 changed files with 197 additions and 23 deletions
6
flake.lock
generated
6
flake.lock
generated
|
@ -18,11 +18,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1653988320,
|
"lastModified": 1657693803,
|
||||||
"narHash": "sha256-ZaqFFsSDipZ6KVqriwM34T739+KLYJvNmCWzErjAg7c=",
|
"narHash": "sha256-G++2CJ9u0E7NNTAi9n5G8TdDmGJXcIjkJ3NF8cetQB8=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "2fa57ed190fd6c7c746319444f34b5917666e5c1",
|
"rev": "365e1b3a859281cf11b94f87231adeabbdd878a2",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
|
@ -108,7 +108,7 @@
|
||||||
++ lib.optionals stdenv.hostPlatform.isLinux [(buildPackages.util-linuxMinimal or buildPackages.utillinuxMinimal)];
|
++ lib.optionals stdenv.hostPlatform.isLinux [(buildPackages.util-linuxMinimal or buildPackages.utillinuxMinimal)];
|
||||||
|
|
||||||
buildDeps =
|
buildDeps =
|
||||||
[ curl
|
[ (curl.override { patchNetrcRegression = true; })
|
||||||
bzip2 xz brotli editline
|
bzip2 xz brotli editline
|
||||||
openssl sqlite
|
openssl sqlite
|
||||||
libarchive
|
libarchive
|
||||||
|
@ -367,7 +367,7 @@
|
||||||
|
|
||||||
buildInputs =
|
buildInputs =
|
||||||
[ nix
|
[ nix
|
||||||
curl
|
(curl.override { patchNetrcRegression = true; })
|
||||||
bzip2
|
bzip2
|
||||||
xz
|
xz
|
||||||
pkgs.perl
|
pkgs.perl
|
||||||
|
|
|
@ -845,18 +845,43 @@ void LocalDerivationGoal::startBuilder()
|
||||||
/* Some distros patch Linux to not allow unprivileged
|
/* Some distros patch Linux to not allow unprivileged
|
||||||
* user namespaces. If we get EPERM or EINVAL, try
|
* user namespaces. If we get EPERM or EINVAL, try
|
||||||
* without CLONE_NEWUSER and see if that works.
|
* without CLONE_NEWUSER and see if that works.
|
||||||
|
* Details: https://salsa.debian.org/kernel-team/linux/-/commit/d98e00eda6bea437e39b9e80444eee84a32438a6
|
||||||
*/
|
*/
|
||||||
usingUserNamespace = false;
|
usingUserNamespace = false;
|
||||||
flags &= ~CLONE_NEWUSER;
|
flags &= ~CLONE_NEWUSER;
|
||||||
child = clone(childEntry, stack + stackSize, flags, this);
|
child = clone(childEntry, stack + stackSize, flags, this);
|
||||||
}
|
}
|
||||||
/* Otherwise exit with EPERM so we can handle this in the
|
if (child == -1) {
|
||||||
parent. This is only done when sandbox-fallback is set
|
switch(errno) {
|
||||||
to true (the default). */
|
case EPERM:
|
||||||
if (child == -1 && (errno == EPERM || errno == EINVAL) && settings.sandboxFallback)
|
case EINVAL: {
|
||||||
_exit(1);
|
int errno_ = errno;
|
||||||
if (child == -1) throw SysError("cloning builder process");
|
if (!userNamespacesEnabled && errno==EPERM)
|
||||||
|
notice("user namespaces appear to be disabled; they are required for sandboxing; check /proc/sys/user/max_user_namespaces");
|
||||||
|
if (userNamespacesEnabled) {
|
||||||
|
Path procSysKernelUnprivilegedUsernsClone = "/proc/sys/kernel/unprivileged_userns_clone";
|
||||||
|
if (pathExists(procSysKernelUnprivilegedUsernsClone)
|
||||||
|
&& trim(readFile(procSysKernelUnprivilegedUsernsClone)) == "0") {
|
||||||
|
notice("user namespaces appear to be disabled; they are required for sandboxing; check /proc/sys/kernel/unprivileged_userns_clone");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Path procSelfNsUser = "/proc/self/ns/user";
|
||||||
|
if (!pathExists(procSelfNsUser))
|
||||||
|
notice("/proc/self/ns/user does not exist; your kernel was likely built without CONFIG_USER_NS=y, which is required for sandboxing");
|
||||||
|
/* Otherwise exit with EPERM so we can handle this in the
|
||||||
|
parent. This is only done when sandbox-fallback is set
|
||||||
|
to true (the default). */
|
||||||
|
if (settings.sandboxFallback)
|
||||||
|
_exit(1);
|
||||||
|
/* Mention sandbox-fallback in the error message so the user
|
||||||
|
knows that having it disabled contributed to the
|
||||||
|
unrecoverability of this failure */
|
||||||
|
throw SysError(errno_, "creating sandboxed builder process using clone(), without sandbox-fallback");
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw SysError("creating sandboxed builder process using clone()");
|
||||||
|
}
|
||||||
|
}
|
||||||
writeFull(builderOut.writeSide.get(),
|
writeFull(builderOut.writeSide.get(),
|
||||||
fmt("%d %d\n", usingUserNamespace, child));
|
fmt("%d %d\n", usingUserNamespace, child));
|
||||||
_exit(0);
|
_exit(0);
|
||||||
|
|
|
@ -114,7 +114,13 @@ std::vector<Path> getUserConfigFiles()
|
||||||
|
|
||||||
unsigned int Settings::getDefaultCores()
|
unsigned int Settings::getDefaultCores()
|
||||||
{
|
{
|
||||||
return std::max(1U, std::thread::hardware_concurrency());
|
const unsigned int concurrency = std::max(1U, std::thread::hardware_concurrency());
|
||||||
|
const unsigned int maxCPU = getMaxCPU();
|
||||||
|
|
||||||
|
if (maxCPU > 0)
|
||||||
|
return maxCPU;
|
||||||
|
else
|
||||||
|
return concurrency;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringSet Settings::getDefaultSystemFeatures()
|
StringSet Settings::getDefaultSystemFeatures()
|
||||||
|
|
|
@ -98,7 +98,9 @@
|
||||||
(allow file*
|
(allow file*
|
||||||
(literal "/private/var/select/sh"))
|
(literal "/private/var/select/sh"))
|
||||||
|
|
||||||
; Allow Rosetta 2 to run x86_64 binaries on aarch64-darwin.
|
; Allow Rosetta 2 to run x86_64 binaries on aarch64-darwin (and vice versa).
|
||||||
(allow file-read*
|
(allow file-read*
|
||||||
(subpath "/Library/Apple/usr/libexec/oah")
|
(subpath "/Library/Apple/usr/libexec/oah")
|
||||||
(subpath "/System/Library/Apple/usr/libexec/oah"))
|
(subpath "/System/Library/Apple/usr/libexec/oah")
|
||||||
|
(subpath "/System/Library/LaunchDaemons/com.apple.oahd.plist")
|
||||||
|
(subpath "/Library/Apple/System/Library/LaunchDaemons/com.apple.oahd.plist"))
|
||||||
|
|
|
@ -1325,7 +1325,12 @@ std::shared_ptr<Store> openFromNonUri(const std::string & uri, const Store::Para
|
||||||
else if (pathExists(settings.nixDaemonSocketFile))
|
else if (pathExists(settings.nixDaemonSocketFile))
|
||||||
return std::make_shared<UDSRemoteStore>(params);
|
return std::make_shared<UDSRemoteStore>(params);
|
||||||
#if __linux__
|
#if __linux__
|
||||||
else if (!pathExists(stateDir) && params.empty() && getuid() != 0) {
|
else if (!pathExists(stateDir)
|
||||||
|
&& params.empty()
|
||||||
|
&& getuid() != 0
|
||||||
|
&& !getEnv("NIX_STORE_DIR").has_value()
|
||||||
|
&& !getEnv("NIX_STATE_DIR").has_value())
|
||||||
|
{
|
||||||
/* If /nix doesn't exist, there is no daemon socket, and
|
/* If /nix doesn't exist, there is no daemon socket, and
|
||||||
we're not root, then automatically set up a chroot
|
we're not root, then automatically set up a chroot
|
||||||
store in ~/.local/share/nix/root. */
|
store in ~/.local/share/nix/root. */
|
||||||
|
|
|
@ -180,13 +180,19 @@ public:
|
||||||
int errNo;
|
int errNo;
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
SysError(const Args & ... args)
|
SysError(int errNo_, const Args & ... args)
|
||||||
: Error("")
|
: Error("")
|
||||||
{
|
{
|
||||||
errNo = errno;
|
errNo = errNo_;
|
||||||
auto hf = hintfmt(args...);
|
auto hf = hintfmt(args...);
|
||||||
err.msg = hintfmt("%1%: %2%", normaltxt(hf.str()), strerror(errNo));
|
err.msg = hintfmt("%1%: %2%", normaltxt(hf.str()), strerror(errNo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
SysError(const Args & ... args)
|
||||||
|
: SysError(errno, args ...)
|
||||||
|
{
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,9 @@
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
|
|
||||||
|
#include <mntent.h>
|
||||||
|
#include <cmath>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -788,7 +791,55 @@ void drainFD(int fd, Sink & sink, bool block)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
unsigned int getMaxCPU()
|
||||||
|
{
|
||||||
|
#if __linux__
|
||||||
|
try {
|
||||||
|
FILE *fp = fopen("/proc/mounts", "r");
|
||||||
|
if (!fp)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Strings cgPathParts;
|
||||||
|
|
||||||
|
struct mntent *ent;
|
||||||
|
while ((ent = getmntent(fp))) {
|
||||||
|
std::string mountType, mountPath;
|
||||||
|
|
||||||
|
mountType = ent->mnt_type;
|
||||||
|
mountPath = ent->mnt_dir;
|
||||||
|
|
||||||
|
if (mountType == "cgroup2") {
|
||||||
|
cgPathParts.push_back(mountPath);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
if (cgPathParts.size() > 0 && pathExists("/proc/self/cgroup")) {
|
||||||
|
std::string currentCgroup = readFile("/proc/self/cgroup");
|
||||||
|
Strings cgValues = tokenizeString<Strings>(currentCgroup, ":");
|
||||||
|
cgPathParts.push_back(trim(cgValues.back(), "\n"));
|
||||||
|
cgPathParts.push_back("cpu.max");
|
||||||
|
std::string fullCgPath = canonPath(concatStringsSep("/", cgPathParts));
|
||||||
|
|
||||||
|
if (pathExists(fullCgPath)) {
|
||||||
|
std::string cpuMax = readFile(fullCgPath);
|
||||||
|
std::vector<std::string> cpuMaxParts = tokenizeString<std::vector<std::string>>(cpuMax, " ");
|
||||||
|
std::string quota = cpuMaxParts[0];
|
||||||
|
std::string period = trim(cpuMaxParts[1], "\n");
|
||||||
|
|
||||||
|
if (quota != "max")
|
||||||
|
return std::ceil(std::stoi(quota) / std::stof(period));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Error &) { ignoreException(); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
|
@ -182,6 +182,9 @@ std::string drainFD(int fd, bool block = true, const size_t reserveSize=0);
|
||||||
|
|
||||||
void drainFD(int fd, Sink & sink, bool block = true);
|
void drainFD(int fd, Sink & sink, bool block = true);
|
||||||
|
|
||||||
|
/* If cgroups are active, attempt to calculate the number of CPUs available.
|
||||||
|
If cgroups are unavailable or if cpu.max is set to "max", return 0. */
|
||||||
|
unsigned int getMaxCPU();
|
||||||
|
|
||||||
/* Automatic cleanup of resources. */
|
/* Automatic cleanup of resources. */
|
||||||
|
|
||||||
|
|
|
@ -288,8 +288,10 @@ struct Common : InstallableCommand, MixProfile
|
||||||
|
|
||||||
out << "unset shellHook\n";
|
out << "unset shellHook\n";
|
||||||
|
|
||||||
for (auto & var : savedVars)
|
for (auto & var : savedVars) {
|
||||||
|
out << fmt("%s=${%s:-}\n", var, var);
|
||||||
out << fmt("nix_saved_%s=\"$%s\"\n", var, var);
|
out << fmt("nix_saved_%s=\"$%s\"\n", var, var);
|
||||||
|
}
|
||||||
|
|
||||||
buildEnvironment.toBash(out, ignoreVars);
|
buildEnvironment.toBash(out, ignoreVars);
|
||||||
|
|
||||||
|
|
|
@ -119,11 +119,11 @@ killDaemon() {
|
||||||
}
|
}
|
||||||
|
|
||||||
restartDaemon() {
|
restartDaemon() {
|
||||||
[[ -z "${pidDaemon:-}" ]] && return 0
|
[[ -z "${pidDaemon:-}" ]] && return 0
|
||||||
|
|
||||||
killDaemon
|
killDaemon
|
||||||
unset NIX_REMOTE
|
unset NIX_REMOTE
|
||||||
startDaemon
|
startDaemon
|
||||||
}
|
}
|
||||||
|
|
||||||
if [[ $(uname) == Linux ]] && [[ -L /proc/self/ns/user ]] && unshare --user true; then
|
if [[ $(uname) == Linux ]] && [[ -L /proc/self/ns/user ]] && unshare --user true; then
|
||||||
|
@ -190,4 +190,15 @@ if [[ -n "${NIX_DAEMON_PACKAGE:-}" ]]; then
|
||||||
startDaemon
|
startDaemon
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
onError() {
|
||||||
|
set +x
|
||||||
|
echo "$0: test failed at:" >&2
|
||||||
|
for ((i = 1; i < 16; i++)); do
|
||||||
|
if [[ -z ${BASH_SOURCE[i]} ]]; then break; fi
|
||||||
|
echo " ${FUNCNAME[i]} in ${BASH_SOURCE[i]}:${BASH_LINENO[i-1]}" >&2
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
trap onError ERR
|
||||||
|
|
||||||
fi # COMMON_SH_SOURCED
|
fi # COMMON_SH_SOURCED
|
||||||
|
|
62
tests/completions.sh
Normal file
62
tests/completions.sh
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
source common.sh
|
||||||
|
|
||||||
|
cd "$TEST_ROOT"
|
||||||
|
|
||||||
|
mkdir -p dep
|
||||||
|
cat <<EOF > dep/flake.nix
|
||||||
|
{
|
||||||
|
outputs = i: { };
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
mkdir -p foo
|
||||||
|
cat <<EOF > foo/flake.nix
|
||||||
|
{
|
||||||
|
inputs.a.url = "path:$(realpath dep)";
|
||||||
|
|
||||||
|
outputs = i: {
|
||||||
|
sampleOutput = 1;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
mkdir -p bar
|
||||||
|
cat <<EOF > bar/flake.nix
|
||||||
|
{
|
||||||
|
inputs.b.url = "path:$(realpath dep)";
|
||||||
|
|
||||||
|
outputs = i: {
|
||||||
|
sampleOutput = 1;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Test the completion of a subcommand
|
||||||
|
[[ "$(NIX_GET_COMPLETIONS=1 nix buil)" == $'normal\nbuild\t' ]]
|
||||||
|
[[ "$(NIX_GET_COMPLETIONS=2 nix flake metad)" == $'normal\nmetadata\t' ]]
|
||||||
|
|
||||||
|
# Filename completion
|
||||||
|
[[ "$(NIX_GET_COMPLETIONS=2 nix build ./f)" == $'filenames\n./foo\t' ]]
|
||||||
|
[[ "$(NIX_GET_COMPLETIONS=2 nix build ./nonexistent)" == $'filenames' ]]
|
||||||
|
|
||||||
|
# Input override completion
|
||||||
|
[[ "$(NIX_GET_COMPLETIONS=4 nix build ./foo --override-input '')" == $'normal\na\t' ]]
|
||||||
|
[[ "$(NIX_GET_COMPLETIONS=5 nix flake show ./foo --override-input '')" == $'normal\na\t' ]]
|
||||||
|
## With multiple input flakes
|
||||||
|
[[ "$(NIX_GET_COMPLETIONS=5 nix build ./foo ./bar --override-input '')" == $'normal\na\t\nb\t' ]]
|
||||||
|
## With tilde expansion
|
||||||
|
[[ "$(HOME=$PWD NIX_GET_COMPLETIONS=4 nix build '~/foo' --override-input '')" == $'normal\na\t' ]]
|
||||||
|
## Out of order
|
||||||
|
[[ "$(NIX_GET_COMPLETIONS=3 nix build --update-input '' ./foo)" == $'normal\na\t' ]]
|
||||||
|
[[ "$(NIX_GET_COMPLETIONS=4 nix build ./foo --update-input '' ./bar)" == $'normal\na\t\nb\t' ]]
|
||||||
|
|
||||||
|
# Cli flag completion
|
||||||
|
NIX_GET_COMPLETIONS=2 nix build --log-form | grep -- "--log-format"
|
||||||
|
|
||||||
|
# Config option completion
|
||||||
|
## With `--option`
|
||||||
|
NIX_GET_COMPLETIONS=3 nix build --option allow-import-from | grep -- "allow-import-from-derivation"
|
||||||
|
## As a cli flag – not working atm
|
||||||
|
# NIX_GET_COMPLETIONS=2 nix build --allow-import-from | grep -- "allow-import-from-derivation"
|
||||||
|
|
||||||
|
# Attr path completions
|
||||||
|
[[ "$(NIX_GET_COMPLETIONS=2 nix eval ./foo\#sam)" == $'attrs\n./foo#sampleOutput\t' ]]
|
||||||
|
[[ "$(NIX_GET_COMPLETIONS=4 nix eval --file ./foo/flake.nix outp)" == $'attrs\noutputs\t' ]]
|
|
@ -108,6 +108,7 @@ nix_tests = \
|
||||||
suggestions.sh \
|
suggestions.sh \
|
||||||
store-ping.sh \
|
store-ping.sh \
|
||||||
fetchClosure.sh \
|
fetchClosure.sh \
|
||||||
|
completions.sh \
|
||||||
impure-derivations.sh
|
impure-derivations.sh
|
||||||
|
|
||||||
ifeq ($(HAVE_LIBCPUID), 1)
|
ifeq ($(HAVE_LIBCPUID), 1)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue