From 69431edbc174c7644f7143ba5c81681b7ece186e Mon Sep 17 00:00:00 2001 From: "Travis A. Everett" Date: Mon, 8 Nov 2021 17:03:09 -0600 Subject: [PATCH 01/40] installer: clarify starting assumption task We had a macOS user present in Matrix with some confusion because the lack of a clear task statement here made them think the error meant that a problem had occurred during the preceding task in a macOS install: "Fixing any leftover Nix volume state" --- scripts/install-multi-user.sh | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/scripts/install-multi-user.sh b/scripts/install-multi-user.sh index 7d1cb8c5a..c91dd404a 100644 --- a/scripts/install-multi-user.sh +++ b/scripts/install-multi-user.sh @@ -377,6 +377,11 @@ cure_artifacts() { } validate_starting_assumptions() { + task "Checking for artifacts of previous installs" + cat < /dev/null >&2; then warning < Date: Thu, 18 Nov 2021 14:32:52 +0100 Subject: [PATCH 02/40] Offer suggestions for nix-env -i Closes https://github.com/NixOS/nix/issues/972 --- src/libstore/names.cc | 2 +- src/libstore/names.hh | 2 +- src/nix-env/nix-env.cc | 174 ++++++++++++++++++++++++++--------------- 3 files changed, 113 insertions(+), 65 deletions(-) diff --git a/src/libstore/names.cc b/src/libstore/names.cc index ce808accc..54c95055d 100644 --- a/src/libstore/names.cc +++ b/src/libstore/names.cc @@ -42,7 +42,7 @@ DrvName::~DrvName() { } -bool DrvName::matches(DrvName & n) +bool DrvName::matches(const DrvName & n) { if (name != "*") { if (!regex) { diff --git a/src/libstore/names.hh b/src/libstore/names.hh index bc62aac93..3f861bc44 100644 --- a/src/libstore/names.hh +++ b/src/libstore/names.hh @@ -19,7 +19,7 @@ struct DrvName DrvName(std::string_view s); ~DrvName(); - bool matches(DrvName & n); + bool matches(const DrvName & n); private: std::unique_ptr regex; diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index 4056d973d..1c78b5307 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -224,6 +224,91 @@ static void checkSelectorUse(DrvNames & selectors) } +namespace { + +std::set searchByPrefix(const DrvInfos & allElems, std::string_view prefix) { + constexpr std::size_t maxResults = 3; + std::set result; + for (const auto & drvInfo : allElems) { + const auto drvName = DrvName { drvInfo.queryName() }; + if (hasPrefix(drvName.name, prefix)) { + result.emplace(drvName.name); + + if (result.size() >= maxResults) { + break; + } + } + } + return result; +} + +struct Match +{ + DrvInfo drvInfo; + std::size_t index; + + Match(DrvInfo drvInfo_, std::size_t index_) + : drvInfo{std::move(drvInfo_)} + , index{index_} + {} +}; + +/* If a selector matches multiple derivations + with the same name, pick the one matching the current + system. If there are still multiple derivations, pick the + one with the highest priority. If there are still multiple + derivations, pick the one with the highest version. + Finally, if there are still multiple derivations, + arbitrarily pick the first one. */ +std::vector pickNewestOnly(EvalState & state, std::vector matches) { + /* Map from package names to derivations. */ + std::map newest; + StringSet multiple; + + for (auto & match : matches) { + auto & oneDrv = match.drvInfo; + + const auto drvName = DrvName { oneDrv.queryName() }; + long comparison = 1; + + const auto itOther = newest.find(drvName.name); + + if (itOther != newest.end()) { + auto & newestDrv = itOther->second.drvInfo; + + comparison = + oneDrv.querySystem() == newestDrv.querySystem() ? 0 : + oneDrv.querySystem() == settings.thisSystem ? 1 : + newestDrv.querySystem() == settings.thisSystem ? -1 : 0; + if (comparison == 0) + comparison = comparePriorities(state, oneDrv, newestDrv); + if (comparison == 0) + comparison = compareVersions(drvName.version, DrvName { newestDrv.queryName() }.version); + } + + if (comparison > 0) { + newest.erase(drvName.name); + newest.emplace(drvName.name, match); + multiple.erase(drvName.fullName); + } else if (comparison == 0) { + multiple.insert(drvName.fullName); + } + } + + matches.clear(); + for (auto & [name, match] : newest) { + if (multiple.find(name) != multiple.end()) + printInfo( + "warning: there are multiple derivations named '%1%'; using the first one", + name); + matches.push_back(match); + } + + return matches; +} + +} // end namespace + static DrvInfos filterBySelector(EvalState & state, const DrvInfos & allElems, const Strings & args, bool newestOnly) { @@ -232,79 +317,42 @@ static DrvInfos filterBySelector(EvalState & state, const DrvInfos & allElems, selectors.emplace_back("*"); DrvInfos elems; - set done; + std::set done; - for (auto & i : selectors) { - typedef list > Matches; - Matches matches; - unsigned int n = 0; - for (DrvInfos::const_iterator j = allElems.begin(); - j != allElems.end(); ++j, ++n) - { - DrvName drvName(j->queryName()); - if (i.matches(drvName)) { - i.hits++; - matches.push_back(std::pair(*j, n)); + for (auto & selector : selectors) { + std::vector matches; + for (const auto & [index, drvInfo] : enumerate(allElems)) { + const auto drvName = DrvName { drvInfo.queryName() }; + if (selector.matches(drvName)) { + ++selector.hits; + matches.emplace_back(drvInfo, index); } } - /* If `newestOnly', if a selector matches multiple derivations - with the same name, pick the one matching the current - system. If there are still multiple derivations, pick the - one with the highest priority. If there are still multiple - derivations, pick the one with the highest version. - Finally, if there are still multiple derivations, - arbitrarily pick the first one. */ if (newestOnly) { - - /* Map from package names to derivations. */ - typedef map > Newest; - Newest newest; - StringSet multiple; - - for (auto & j : matches) { - DrvName drvName(j.first.queryName()); - long d = 1; - - Newest::iterator k = newest.find(drvName.name); - - if (k != newest.end()) { - d = j.first.querySystem() == k->second.first.querySystem() ? 0 : - j.first.querySystem() == settings.thisSystem ? 1 : - k->second.first.querySystem() == settings.thisSystem ? -1 : 0; - if (d == 0) - d = comparePriorities(state, j.first, k->second.first); - if (d == 0) - d = compareVersions(drvName.version, DrvName(k->second.first.queryName()).version); - } - - if (d > 0) { - newest.erase(drvName.name); - newest.insert(Newest::value_type(drvName.name, j)); - multiple.erase(j.first.queryName()); - } else if (d == 0) { - multiple.insert(j.first.queryName()); - } - } - - matches.clear(); - for (auto & j : newest) { - if (multiple.find(j.second.first.queryName()) != multiple.end()) - printInfo( - "warning: there are multiple derivations named '%1%'; using the first one", - j.second.first.queryName()); - matches.push_back(j.second); - } + matches = pickNewestOnly(state, std::move(matches)); } /* Insert only those elements in the final list that we haven't inserted before. */ - for (auto & j : matches) - if (done.insert(j.second).second) - elems.push_back(j.first); - } + for (auto & match : matches) + if (done.insert(match.index).second) + elems.push_back(match.drvInfo); - checkSelectorUse(selectors); + if (selector.hits == 0 && selector.fullName != "*") { + const auto prefixHits = searchByPrefix(allElems, selector.name); + + if (prefixHits.empty()) { + throw Error("selector '%1%' matches no derivations", selector.fullName); + } else { + std::string suggestionMessage = ", maybe you meant:"; + for (const auto & drvName : prefixHits) { + suggestionMessage += fmt("\n%s", drvName); + } + throw Error("selector '%1%' matches no derivations" + suggestionMessage, selector.fullName); + } + } + } return elems; } From 86b79628073154b853b2e57360c062654826f5ee Mon Sep 17 00:00:00 2001 From: Alex Shabalin Date: Fri, 19 Nov 2021 16:29:55 +0100 Subject: [PATCH 03/40] Use warn to print a warning --- src/nix-env/nix-env.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index 1c78b5307..490f450df 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -298,8 +298,8 @@ std::vector pickNewestOnly(EvalState & state, std::vector matches) matches.clear(); for (auto & [name, match] : newest) { if (multiple.find(name) != multiple.end()) - printInfo( - "warning: there are multiple derivations named '%1%'; using the first one", + warn( + "there are multiple derivations named '%1%'; using the first one", name); matches.push_back(match); } From d41af23a6c879fe2b5f88e40e0ad87db099a23cf Mon Sep 17 00:00:00 2001 From: Farid Zakaria Date: Thu, 18 Nov 2021 14:54:50 -0800 Subject: [PATCH 04/40] Fix heap use after free in progress-bar.cc Fix some heap-use-after-free in progress-bar.cc These are somewhat tricky failures here due to temporary variable creation and string_view --- src/libmain/progress-bar.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libmain/progress-bar.cc b/src/libmain/progress-bar.cc index 63955eed1..f4306ab91 100644 --- a/src/libmain/progress-bar.cc +++ b/src/libmain/progress-bar.cc @@ -11,7 +11,7 @@ namespace nix { -static std::string getS(const std::vector & fields, size_t n) +static std::string_view getS(const std::vector & fields, size_t n) { assert(n < fields.size()); assert(fields[n].type == Logger::Field::tString); From 05081bedc156c8e6556b66fe2470fec14e074caf Mon Sep 17 00:00:00 2001 From: regnat Date: Fri, 26 Nov 2021 09:56:48 +0100 Subject: [PATCH 05/40] Make `nix-shell` work when nixpkgs is content-addressed Fix #5259 --- src/nix-build/nix-build.cc | 9 ++++++-- tests/ca-shell.nix | 1 + tests/nix-shell.sh | 42 ++++++++++++++++---------------------- tests/shell.nix | 4 ++++ 4 files changed, 30 insertions(+), 26 deletions(-) create mode 100644 tests/ca-shell.nix diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc index 75576ef8a..e2325c91f 100755 --- a/src/nix-build/nix-build.cc +++ b/src/nix-build/nix-build.cc @@ -359,6 +359,7 @@ static void main_nix_build(int argc, char * * argv) is not set, then build bashInteractive from . */ auto shell = getEnv("NIX_BUILD_SHELL"); + std::optional shellDrv; if (!shell) { @@ -375,8 +376,7 @@ static void main_nix_build(int argc, char * * argv) auto bashDrv = store->parseStorePath(drv->queryDrvPath()); pathsToBuild.push_back({bashDrv}); pathsToCopy.insert(bashDrv); - - shell = drv->queryOutPath() + "/bin/bash"; + shellDrv = bashDrv; } catch (Error & e) { logError(e.info()); @@ -402,6 +402,11 @@ static void main_nix_build(int argc, char * * argv) if (dryRun) return; + if (shellDrv) { + auto shellDrvOutputs = store->queryPartialDerivationOutputMap(shellDrv.value()); + shell = store->printStorePath(shellDrvOutputs.at("out").value()) + "/bin/bash"; + } + if (settings.isExperimentalFeatureEnabled(Xp::CaDerivations)) { auto resolvedDrv = drv.tryResolve(*store); assert(resolvedDrv && "Successfully resolved the derivation"); diff --git a/tests/ca-shell.nix b/tests/ca-shell.nix new file mode 100644 index 000000000..ad2ab6aff --- /dev/null +++ b/tests/ca-shell.nix @@ -0,0 +1 @@ +{ ... }@args: import ./shell.nix (args // { contentAddressed = true; }) diff --git a/tests/nix-shell.sh b/tests/nix-shell.sh index a31d35887..3241d7a0f 100644 --- a/tests/nix-shell.sh +++ b/tests/nix-shell.sh @@ -3,59 +3,53 @@ source common.sh clearStore if [[ -n ${CONTENT_ADDRESSED:-} ]]; then - nix-shell () { - command nix-shell --arg contentAddressed true "$@" - } - - nix_develop() { - nix develop --arg contentAddressed true "$@" - } + shellDotNix="$PWD/ca-shell.nix" else - nix_develop() { - nix develop "$@" - } + shellDotNix="$PWD/shell.nix" fi +export NIX_PATH=nixpkgs="$shellDotNix" + # Test nix-shell -A export IMPURE_VAR=foo export SELECTED_IMPURE_VAR=baz -export NIX_BUILD_SHELL=$SHELL -output=$(nix-shell --pure shell.nix -A shellDrv --run \ + +output=$(nix-shell --pure "$shellDotNix" -A shellDrv --run \ 'echo "$IMPURE_VAR - $VAR_FROM_STDENV_SETUP - $VAR_FROM_NIX - $TEST_inNixShell"') [ "$output" = " - foo - bar - true" ] # Test --keep -output=$(nix-shell --pure --keep SELECTED_IMPURE_VAR shell.nix -A shellDrv --run \ +output=$(nix-shell --pure --keep SELECTED_IMPURE_VAR "$shellDotNix" -A shellDrv --run \ 'echo "$IMPURE_VAR - $VAR_FROM_STDENV_SETUP - $VAR_FROM_NIX - $SELECTED_IMPURE_VAR"') [ "$output" = " - foo - bar - baz" ] # Test nix-shell on a .drv -[[ $(nix-shell --pure $(nix-instantiate shell.nix -A shellDrv) --run \ +[[ $(nix-shell --pure $(nix-instantiate "$shellDotNix" -A shellDrv) --run \ 'echo "$IMPURE_VAR - $VAR_FROM_STDENV_SETUP - $VAR_FROM_NIX - $TEST_inNixShell"') = " - foo - bar - false" ]] -[[ $(nix-shell --pure $(nix-instantiate shell.nix -A shellDrv) --run \ +[[ $(nix-shell --pure $(nix-instantiate "$shellDotNix" -A shellDrv) --run \ 'echo "$IMPURE_VAR - $VAR_FROM_STDENV_SETUP - $VAR_FROM_NIX - $TEST_inNixShell"') = " - foo - bar - false" ]] # Test nix-shell on a .drv symlink # Legacy: absolute path and .drv extension required -nix-instantiate shell.nix -A shellDrv --add-root $TEST_ROOT/shell.drv +nix-instantiate "$shellDotNix" -A shellDrv --add-root $TEST_ROOT/shell.drv [[ $(nix-shell --pure $TEST_ROOT/shell.drv --run \ 'echo "$IMPURE_VAR - $VAR_FROM_STDENV_SETUP - $VAR_FROM_NIX"') = " - foo - bar" ]] # New behaviour: just needs to resolve to a derivation in the store -nix-instantiate shell.nix -A shellDrv --add-root $TEST_ROOT/shell +nix-instantiate "$shellDotNix" -A shellDrv --add-root $TEST_ROOT/shell [[ $(nix-shell --pure $TEST_ROOT/shell --run \ 'echo "$IMPURE_VAR - $VAR_FROM_STDENV_SETUP - $VAR_FROM_NIX"') = " - foo - bar" ]] # Test nix-shell -p -output=$(NIX_PATH=nixpkgs=shell.nix nix-shell --pure -p foo bar --run 'echo "$(foo) $(bar)"') +output=$(NIX_PATH=nixpkgs="$shellDotNix" nix-shell --pure -p foo bar --run 'echo "$(foo) $(bar)"') [ "$output" = "foo bar" ] # Test nix-shell -p --arg x y -output=$(NIX_PATH=nixpkgs=shell.nix nix-shell --pure -p foo --argstr fooContents baz --run 'echo "$(foo)"') +output=$(NIX_PATH=nixpkgs="$shellDotNix" nix-shell --pure -p foo --argstr fooContents baz --run 'echo "$(foo)"') [ "$output" = "baz" ] # Test nix-shell shebang mode @@ -91,18 +85,18 @@ output=$($TEST_ROOT/spaced\ \\\'\"shell.shebang.rb abc ruby) [ "$output" = '-e load(ARGV.shift) -- '"$TEST_ROOT"'/spaced \'\''"shell.shebang.rb abc ruby' ] # Test 'nix develop'. -nix_develop -f shell.nix shellDrv -c bash -c '[[ -n $stdenv ]]' +nix develop -f "$shellDotNix" shellDrv -c bash -c '[[ -n $stdenv ]]' # Ensure `nix develop -c` preserves stdin -echo foo | nix develop -f shell.nix shellDrv -c cat | grep -q foo +echo foo | nix develop -f "$shellDotNix" shellDrv -c cat | grep -q foo # Ensure `nix develop -c` actually executes the command if stdout isn't a terminal -nix_develop -f shell.nix shellDrv -c echo foo |& grep -q foo +nix develop -f "$shellDotNix" shellDrv -c echo foo |& grep -q foo # Test 'nix print-dev-env'. -[[ $(nix print-dev-env -f shell.nix shellDrv --json | jq -r .variables.arr1.value[2]) = '3 4' ]] +[[ $(nix print-dev-env -f "$shellDotNix" shellDrv --json | jq -r .variables.arr1.value[2]) = '3 4' ]] -source <(nix print-dev-env -f shell.nix shellDrv) +source <(nix print-dev-env -f "$shellDotNix" shellDrv) [[ -n $stdenv ]] [[ ${arr1[2]} = "3 4" ]] [[ ${arr2[1]} = $'\n' ]] diff --git a/tests/shell.nix b/tests/shell.nix index 4912d295a..92d94fbc2 100644 --- a/tests/shell.nix +++ b/tests/shell.nix @@ -74,6 +74,10 @@ let pkgs = rec { ''; bash = shell; + bashInteractive = runCommand "bash" {} '' + mkdir -p $out/bin + ln -s ${shell} $out/bin/bash + ''; # ruby "interpreter" that outputs "$@" ruby = runCommand "ruby" {} '' From e588f4c6558cb486aa065e17a124f272ccc1fcdb Mon Sep 17 00:00:00 2001 From: regnat Date: Thu, 8 Jul 2021 17:01:51 +0200 Subject: [PATCH 06/40] Add a matrix of stdenvs to the flake For a (currently hardcoded and limited) list of stdenvs, make `.#$nix-${stdenvName}` correspond to a Nix built with the corresponding stdenv. For example, `.#nix-${clang11Stdenv}` is Nix built with clang11. Likewise, `devShells.x86_64-linux.clang11StdenvPackages` is a development shell for Nix with clang11, that can be used with ```shell nix develop .#clang11StdenvPackages ``` Fix #4129 /cc @pamplemousse --- flake.nix | 80 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 55 insertions(+), 25 deletions(-) diff --git a/flake.nix b/flake.nix index ff152ebd6..9a5d188ae 100644 --- a/flake.nix +++ b/flake.nix @@ -22,15 +22,36 @@ crossSystems = [ "armv6l-linux" "armv7l-linux" ]; + stdenvs = [ "gccStdenv" "clangStdenv" "clang11Stdenv" "stdenv" ]; + forAllSystems = f: nixpkgs.lib.genAttrs systems (system: f system); + forAllSystemsAndStdenvs = f: forAllSystems (system: + nixpkgs.lib.listToAttrs + (map + (n: + nixpkgs.lib.nameValuePair "${n}Packages" ( + f system n + )) stdenvs + ) + ); + + forAllStdenvs = stdenvs: f: nixpkgs.lib.genAttrs stdenvs (stdenv: f stdenv); # Memoize nixpkgs for different platforms for efficiency. - nixpkgsFor = forAllSystems (system: - import nixpkgs { - inherit system; - overlays = [ self.overlay ]; - } - ); + nixpkgsFor = + let stdenvsPackages = forAllSystemsAndStdenvs + (system: stdenv: + import nixpkgs { + inherit system; + overlays = [ + (overlayFor (p: p.${stdenv})) + ]; + } + ); + in + # Add the `stdenvPackages` at toplevel, both because these are the ones + # we want most of the time and for backwards compatibility + forAllSystems (system: stdenvsPackages.${system} // stdenvsPackages.${system}.stdenvPackages); commonDeps = pkgs: with pkgs; rec { # Use "busybox-sandbox-shell" if present, @@ -255,18 +276,15 @@ $(cat ${installerClosureInfo}/store-paths) ''; - in { - - # A Nixpkgs overlay that overrides the 'nix' and - # 'nix.perl-bindings' packages. - overlay = final: prev: { - + overlayFor = getStdenv: final: prev: + let currentStdenv = getStdenv final; in + { nixStable = prev.nix; # Forward from the previous stage as we don’t want it to pick the lowdown override nixUnstable = prev.nixUnstable; - nix = with final; with commonDeps pkgs; stdenv.mkDerivation { + nix = with final; with commonDeps pkgs; currentStdenv.mkDerivation { name = "nix-${version}"; inherit version; @@ -288,9 +306,9 @@ mkdir -p $out/lib cp -pd ${boost}/lib/{libboost_context*,libboost_thread*,libboost_system*} $out/lib rm -f $out/lib/*.a - ${lib.optionalString stdenv.isLinux '' + ${lib.optionalString currentStdenv.isLinux '' chmod u+w $out/lib/*.so.* - patchelf --set-rpath $out/lib:${stdenv.cc.cc.lib}/lib $out/lib/libboost_thread.so.* + patchelf --set-rpath $out/lib:${currentStdenv.cc.cc.lib}/lib $out/lib/libboost_thread.so.* ''} ''; @@ -317,7 +335,7 @@ strictDeps = true; - passthru.perl-bindings = with final; stdenv.mkDerivation { + passthru.perl-bindings = with final; currentStdenv.mkDerivation { name = "nix-perl-${version}"; src = self; @@ -336,8 +354,8 @@ pkgs.perl boost ] - ++ lib.optional (stdenv.isLinux || stdenv.isDarwin) libsodium - ++ lib.optional stdenv.isDarwin darwin.apple_sdk.frameworks.Security; + ++ lib.optional (currentStdenv.isLinux || currentStdenv.isDarwin) libsodium + ++ lib.optional currentStdenv.isDarwin darwin.apple_sdk.frameworks.Security; configureFlags = '' --with-dbi=${perlPackages.DBI}/${pkgs.perl.libPrefix} @@ -351,7 +369,7 @@ }; - lowdown-nix = with final; stdenv.mkDerivation rec { + lowdown-nix = with final; currentStdenv.mkDerivation rec { name = "lowdown-0.9.0"; src = lowdown-src; @@ -361,15 +379,20 @@ nativeBuildInputs = [ buildPackages.which ]; configurePhase = '' - ${if (stdenv.isDarwin && stdenv.isAarch64) then "echo \"HAVE_SANDBOX_INIT=false\" > configure.local" else ""} + ${if (currentStdenv.isDarwin && currentStdenv.isAarch64) then "echo \"HAVE_SANDBOX_INIT=false\" > configure.local" else ""} ./configure \ PREFIX=${placeholder "dev"} \ BINDIR=${placeholder "bin"}/bin - ''; + ''; }; - }; + in { + + # A Nixpkgs overlay that overrides the 'nix' and + # 'nix.perl-bindings' packages. + overlay = overlayFor (p: p.stdenv); + hydraJobs = { # Binary package for various platforms. @@ -610,15 +633,22 @@ doInstallCheck = true; installCheckFlags = "sysconfdir=$(out)/etc"; }; - }) crossSystems))); + }) crossSystems)) // (builtins.listToAttrs (map (stdenvName: + nixpkgsFor.${system}.lib.nameValuePair + "nix-${stdenvName}" + nixpkgsFor.${system}."${stdenvName}Packages".nix + ) stdenvs)) + ); defaultPackage = forAllSystems (system: self.packages.${system}.nix); - devShell = forAllSystems (system: + devShell = forAllSystems (system: self.devShells.${system}.stdenvPackages); + + devShells = forAllSystemsAndStdenvs (system: stdenv: with nixpkgsFor.${system}; with commonDeps pkgs; - stdenv.mkDerivation { + nixpkgsFor.${system}.${stdenv}.mkDerivation { name = "nix"; outputs = [ "out" "dev" "doc" ]; From 288c25257074e70e69a5d51f63dc783695ff4175 Mon Sep 17 00:00:00 2001 From: Pamplemousse Date: Thu, 8 Jul 2021 09:13:55 -0700 Subject: [PATCH 07/40] Documentation: alternative `stdenv` for hacking Signed-off-by: Pamplemousse --- doc/manual/src/contributing/hacking.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/doc/manual/src/contributing/hacking.md b/doc/manual/src/contributing/hacking.md index 2a1e55e5b..90a8f1f94 100644 --- a/doc/manual/src/contributing/hacking.md +++ b/doc/manual/src/contributing/hacking.md @@ -35,6 +35,25 @@ variables are set up so that those dependencies can be found: $ nix-shell ``` +or if you have a flake-enabled nix: + +```console +$ nix develop +``` + +To get a shell with a different compilation environment (e.g. stdenv, +gccStdenv, clangStdenv, clang11Stdenv): + +```console +$ nix-shell -A devShells.x86_64-linux.clang11StdenvPackages +``` + +or if you have a flake-enabled nix: + +```console +$ nix develop .#clang11StdenvPackages +``` + To build Nix itself in this shell: ```console From 6d166d19a6c1ffc8e651b7045ca1a8a7fff42e57 Mon Sep 17 00:00:00 2001 From: Alex Shabalin Date: Fri, 26 Nov 2021 11:03:48 +0100 Subject: [PATCH 08/40] Catch flake-related exception type in REPL Closes https://github.com/NixOS/nix/issues/5656 --- src/nix/repl.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/nix/repl.cc b/src/nix/repl.cc index 41283c5f2..22a57de60 100644 --- a/src/nix/repl.cc +++ b/src/nix/repl.cc @@ -356,6 +356,8 @@ StringSet NixRepl::completePrefix(string prefix) // Quietly ignore evaluation errors. } catch (UndefinedVarError & e) { // Quietly ignore undefined variable errors. + } catch (BadURL & e) { + // Quietly ignore BadURL flake-related errors. } } From 3ef66cd23a81ae809bee8c27c0d65c3699be5c66 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 26 Nov 2021 13:10:28 +0100 Subject: [PATCH 09/40] nix repl: Reset the terminal on exceptional exits --- src/nix/repl.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/nix/repl.cc b/src/nix/repl.cc index 22a57de60..2649eb0bd 100644 --- a/src/nix/repl.cc +++ b/src/nix/repl.cc @@ -279,6 +279,7 @@ bool NixRepl::getLine(string & input, const std::string &prompt) }; setupSignals(); + Finally resetTerminal([&]() { rl_deprep_terminal(); }); char * s = readline(prompt.c_str()); Finally doFree([&]() { free(s); }); restoreSignals(); From 152e3cda0c3e2309b37593b06f9e113ec44f506a Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Fri, 26 Nov 2021 10:55:43 -0500 Subject: [PATCH 10/40] reproducibility: determinstic man page output for cores --- doc/manual/local.mk | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/manual/local.mk b/doc/manual/local.mk index e43d9f2fb..6b232a736 100644 --- a/doc/manual/local.mk +++ b/doc/manual/local.mk @@ -12,11 +12,13 @@ man-pages := $(foreach n, \ clean-files += $(d)/*.1 $(d)/*.5 $(d)/*.8 # Provide a dummy environment for nix, so that it will not access files outside the macOS sandbox. +# Set cores to 0 because otherwise nix show-config resolves the cores based on the current machine dummy-env = env -i \ HOME=/dummy \ NIX_CONF_DIR=/dummy \ NIX_SSL_CERT_FILE=/dummy/no-ca-bundle.crt \ - NIX_STATE_DIR=/dummy + NIX_STATE_DIR=/dummy \ + NIX_CONFIG='cores = 0' nix-eval = $(dummy-env) $(bindir)/nix eval --experimental-features nix-command -I nix/corepkgs=corepkgs --store dummy:// --impure --raw From 3a0277305a5d86f29e5bdc1c425c45e4bd7dbe71 Mon Sep 17 00:00:00 2001 From: regnat Date: Fri, 26 Nov 2021 16:56:25 +0100 Subject: [PATCH 11/40] =?UTF-8?q?Don=E2=80=99t=20try=20to=20complete=20fla?= =?UTF-8?q?kes=20is=20the=20feature=20isn=E2=80=99t=20enabled?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix #5661 --- src/libcmd/installables.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc index 5758b52ad..ef200b1d2 100644 --- a/src/libcmd/installables.cc +++ b/src/libcmd/installables.cc @@ -291,6 +291,9 @@ void completeFlakeRefWithFragment( void completeFlakeRef(ref store, std::string_view prefix) { + if (!settings.isExperimentalFeatureEnabled(Xp::Flakes)) + return; + if (prefix == "") completions->add("."); From 1d5a881da574fc4883e4950c82f520fcf59d583a Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 27 Nov 2021 23:29:48 +0300 Subject: [PATCH 12/40] Fix typo --- src/nix/registry.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nix/registry.md b/src/nix/registry.md index a1674bd2e..d5c9ef442 100644 --- a/src/nix/registry.md +++ b/src/nix/registry.md @@ -2,7 +2,7 @@ R""( # Description -`nix flake` provides subcommands for managing *flake +`nix registry` provides subcommands for managing *flake registries*. Flake registries are a convenience feature that allows you to refer to flakes using symbolic identifiers such as `nixpkgs`, rather than full URLs such as `git://github.com/NixOS/nixpkgs`. You From 33a227503adfaa570174c48d8c893f968ed8337f Mon Sep 17 00:00:00 2001 From: Alexander Sosedkin Date: Sat, 27 Nov 2021 23:02:04 +0100 Subject: [PATCH 13/40] Document libsodium, which is now mandatory, as a dependency --- configure.ac | 2 +- doc/manual/src/installation/prerequisites-source.md | 5 +++++ perl/configure.ac | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 65478ecc5..bca650005 100644 --- a/configure.ac +++ b/configure.ac @@ -188,7 +188,7 @@ PKG_CHECK_MODULES([EDITLINE], [libeditline], [CXXFLAGS="$EDITLINE_CFLAGS $CXXFLA [AC_MSG_ERROR([Nix requires libeditline; it was not found via pkg-config, but via its header, but required functions do not work. Maybe it is too old? >= 1.14 is required.])]) ]) -# Look for libsodium, an optional dependency. +# Look for libsodium. PKG_CHECK_MODULES([SODIUM], [libsodium], [CXXFLAGS="$SODIUM_CFLAGS $CXXFLAGS"]) # Look for libbrotli{enc,dec}. diff --git a/doc/manual/src/installation/prerequisites-source.md b/doc/manual/src/installation/prerequisites-source.md index 0323a4f55..b3753b53b 100644 --- a/doc/manual/src/installation/prerequisites-source.md +++ b/doc/manual/src/installation/prerequisites-source.md @@ -44,6 +44,11 @@ obtained from the its repository . + - The `libsodium` library for verifying cryptographic signatures + of contents fetched from binary caches. + It can be obtained from the official web site + . + - Recent versions of Bison and Flex to build the parser. (This is because Nix needs GLR support in Bison and reentrancy support in Flex.) For Bison, you need version 2.6, which can be obtained from diff --git a/perl/configure.ac b/perl/configure.ac index eb65ac17b..a02cb06c9 100644 --- a/perl/configure.ac +++ b/perl/configure.ac @@ -41,7 +41,7 @@ perlarchname=$($perl -e 'use Config; print $Config{archname};') AC_SUBST(perllibdir, [${libdir}/perl5/site_perl/$perlversion/$perlarchname]) AC_MSG_RESULT($perllibdir) -# Look for libsodium, an optional dependency. +# Look for libsodium. PKG_CHECK_MODULES([SODIUM], [libsodium], [CXXFLAGS="$SODIUM_CFLAGS $CXXFLAGS"]) # Check for the required Perl dependencies (DBI and DBD::SQLite). From b73a1c06386f43b0b0d7ce99448b8c55f4c5156c Mon Sep 17 00:00:00 2001 From: Alexander Sosedkin Date: Sun, 28 Nov 2021 00:47:25 +0100 Subject: [PATCH 14/40] Document libcpuid dependency --- doc/manual/src/installation/prerequisites-source.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/manual/src/installation/prerequisites-source.md b/doc/manual/src/installation/prerequisites-source.md index 0323a4f55..37e0b5a10 100644 --- a/doc/manual/src/installation/prerequisites-source.md +++ b/doc/manual/src/installation/prerequisites-source.md @@ -58,3 +58,9 @@ `--disable-seccomp-sandboxing` option to the `configure` script (Not recommended unless your system doesn't support `libseccomp`). To get the library, visit . + + - On 64-bit x86 machines only, `libcpuid` library + is used to determine which microarchitecture levels are supported + (e.g., as whether to have `x86_64-v2-linux` among additional system types). + The library is available from its homepage + . From a9bd06d0ea2c7af9fa33763bdca174db76400ee0 Mon Sep 17 00:00:00 2001 From: Alexander Sosedkin Date: Sun, 28 Nov 2021 00:48:04 +0100 Subject: [PATCH 15/40] Make libcpuid dependency optional with --disable-cpuid --- configure.ac | 13 ++++++++++--- doc/manual/src/installation/prerequisites-source.md | 2 ++ tests/local.mk | 5 ++++- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 65478ecc5..4108eb0a8 100644 --- a/configure.ac +++ b/configure.ac @@ -195,10 +195,17 @@ PKG_CHECK_MODULES([SODIUM], [libsodium], [CXXFLAGS="$SODIUM_CFLAGS $CXXFLAGS"]) PKG_CHECK_MODULES([LIBBROTLI], [libbrotlienc libbrotlidec], [CXXFLAGS="$LIBBROTLI_CFLAGS $CXXFLAGS"]) # Look for libcpuid. +have_libcpuid= if test "$machine_name" = "x86_64"; then - PKG_CHECK_MODULES([LIBCPUID], [libcpuid], [CXXFLAGS="$LIBCPUID_CFLAGS $CXXFLAGS"]) - have_libcpuid=1 - AC_DEFINE([HAVE_LIBCPUID], [1], [Use libcpuid]) + AC_ARG_ENABLE([cpuid], + AS_HELP_STRING([--disable-cpuid], [Do not determine microarchitecture levels with libcpuid (relevant to x86_64 only)])) + if test "x$enable_cpuid" != "xno"; then + PKG_CHECK_MODULES([LIBCPUID], [libcpuid], + [CXXFLAGS="$LIBCPUID_CFLAGS $CXXFLAGS" + have_libcpuid=1 + AC_DEFINE([HAVE_LIBCPUID], [1], [Use libcpuid])] + ) + fi fi AC_SUBST(HAVE_LIBCPUID, [$have_libcpuid]) diff --git a/doc/manual/src/installation/prerequisites-source.md b/doc/manual/src/installation/prerequisites-source.md index 37e0b5a10..1b03bacd3 100644 --- a/doc/manual/src/installation/prerequisites-source.md +++ b/doc/manual/src/installation/prerequisites-source.md @@ -64,3 +64,5 @@ (e.g., as whether to have `x86_64-v2-linux` among additional system types). The library is available from its homepage . + This is an optional dependency and can be disabled + by providing a `--disable-cpuid` to the `configure` script. diff --git a/tests/local.mk b/tests/local.mk index 6f38853bc..936b72c2a 100644 --- a/tests/local.mk +++ b/tests/local.mk @@ -48,7 +48,6 @@ nix_tests = \ flakes.sh \ flake-local-settings.sh \ build.sh \ - compute-levels.sh \ repl.sh ca/repl.sh \ ca/build.sh \ ca/build-with-garbage-path.sh \ @@ -63,6 +62,10 @@ nix_tests = \ eval-store.sh # parallel.sh +ifeq ($(HAVE_LIBCPUID), 1) + nix_tests += compute-levels.sh +endif + install-tests += $(foreach x, $(nix_tests), tests/$(x)) tests-environment = NIX_REMOTE= $(bash) -e From 90d8178009381fe7ad6f0380127df2bc5a0d1dc9 Mon Sep 17 00:00:00 2001 From: Andreas Rammhold Date: Sat, 6 Nov 2021 19:50:27 +0100 Subject: [PATCH 16/40] Don't move the arguments of the primOp Moving arguments of the primOp into the registration structure makes it impossible to initialize a second EvalState with the correct primOp registration. It will end up registering all those "RegisterPrimOp"'s with an arity of zero on all but the 2nd instance of the EvalState. Not moving the memory will add a tiny bit of memory overhead during the eval since we need a copy of all the argument lists of all the primOp's. The overhead shouldn't be too bad as it is static (based on the amonut of registered operations) and only occurs once during the interpreter startup. --- src/libexpr/primops.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index c0d59da8c..d1f4d9009 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -3732,7 +3732,7 @@ void EvalState::createBaseEnv() .fun = primOp.fun, .arity = std::max(primOp.args.size(), primOp.arity), .name = symbols.create(primOp.name), - .args = std::move(primOp.args), + .args = primOp.args, .doc = primOp.doc, }); From 6e0cbc666b60515b5e201dd28855f5fe1de9a107 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 29 Nov 2021 11:20:50 +0100 Subject: [PATCH 17/40] createTempFile(): Mark file as CLOEEXEC Fixes #5674. --- src/libutil/util.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libutil/util.cc b/src/libutil/util.cc index defb77a10..1b6467eb2 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -512,6 +512,7 @@ std::pair createTempFile(const Path & prefix) AutoCloseFD fd(mkstemp((char *) tmpl.c_str())); if (!fd) throw SysError("creating temporary file '%s'", tmpl); + closeOnExec(fd.get()); return {std::move(fd), tmpl}; } From a473e85c808120def9a645235e1e6bfa746753b5 Mon Sep 17 00:00:00 2001 From: Eli Flanagan Date: Tue, 30 Nov 2021 11:13:46 -0500 Subject: [PATCH 18/40] docs: document set theory symbols These symbols confused me so I wanted to gloss them to help future users. You can see the context here: https://discourse.nixos.org/t/flakes-what-does-mean-big-bundle-of-questions --- doc/manual/src/glossary.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/manual/src/glossary.md b/doc/manual/src/glossary.md index bb350d9de..92192e4cb 100644 --- a/doc/manual/src/glossary.md +++ b/doc/manual/src/glossary.md @@ -47,7 +47,7 @@ the store object at `P` contains the path `Q` somewhere. The *references* of a store path are the set of store paths to which it has a reference. - + A derivation can reference other derivations and sources (but not output paths), whereas an output path only references other output paths. @@ -66,7 +66,7 @@ is necessary to deploy whole closures, since otherwise at runtime files could be missing. The command `nix-store -qR` prints out closures of store paths. - + As an example, if the store object at path `P` contains a reference to path `Q`, then `Q` is in the closure of `P`. Further, if `Q` references `R` then `R` is also in the closure of `P`. @@ -98,3 +98,7 @@ store. It can contain regular files, directories and symbolic links. NARs are generated and unpacked using `nix-store --dump` and `nix-store --restore`. + - `∅` \ + The empty set symbol. In the context of package history, this denotes a package was not present prior to installation. + - `ε` \ + The epsilon symbol. In the context of a package, this means the version is empty. More precisely, the derivation does not have a version attribute. From 5f64b69d23bfee70d222671a7d10f2efe22b99c6 Mon Sep 17 00:00:00 2001 From: regnat Date: Tue, 30 Nov 2021 17:32:40 +0100 Subject: [PATCH 19/40] Add a github cron to check the hydra status MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a regular github action that will check the status of the latest hydra evaluation. Things aren’t ideal right now because this job will only notify “the user who last modified the cron syntax in the workflow file” (so myself atm). But at least that’ll give a notification for failing hydra jobs --- .github/workflows/hydra_status.yml | 16 ++++++++++++++++ scripts/check-hydra-status.sh | 28 ++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 .github/workflows/hydra_status.yml create mode 100644 scripts/check-hydra-status.sh diff --git a/.github/workflows/hydra_status.yml b/.github/workflows/hydra_status.yml new file mode 100644 index 000000000..b97076bd7 --- /dev/null +++ b/.github/workflows/hydra_status.yml @@ -0,0 +1,16 @@ +name: Hydra status +on: + schedule: + - cron: "12,42 * * * *" + workflow_dispatch: +jobs: + check_hydra_status: + name: Check Hydra status + if: github.repository_owner == 'NixOS' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2.4.0 + with: + fetch-depth: 0 + - run: bash scripts/check-hydra-status.sh + diff --git a/scripts/check-hydra-status.sh b/scripts/check-hydra-status.sh new file mode 100644 index 000000000..c1d2d7c40 --- /dev/null +++ b/scripts/check-hydra-status.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash + +set -euo pipefail +# set -x + + +# mapfile BUILDS_FOR_LATEST_EVAL < <( +# curl -H 'Accept: application/json' https://hydra.nixos.org/jobset/nix/master/evals | \ +# jq -r '.evals[0].builds[] | @sh') +BUILDS_FOR_LATEST_EVAL=$( +curl -sS -H 'Accept: application/json' https://hydra.nixos.org/jobset/nix/master/evals | \ + jq -r '.evals[0].builds[]') + +someBuildFailed=0 + +for buildId in $BUILDS_FOR_LATEST_EVAL; do + buildInfo=$(curl -sS -H 'Accept: application/json' "https://hydra.nixos.org/build/$buildId") + + buildStatus=$(echo "$buildInfo" | \ + jq -r '.buildstatus') + + if [[ "$buildStatus" -ne 0 ]]; then + someBuildFailed=1 + echo "Job “$(echo "$buildInfo" | jq -r '.job')” failed on hydra" + fi +done + +exit "$someBuildFailed" From 092c375cda9efc24f9a3d6b56d818792406b232b Mon Sep 17 00:00:00 2001 From: Eli Flanagan Date: Tue, 30 Nov 2021 13:19:42 -0500 Subject: [PATCH 20/40] Update doc/manual/src/glossary.md Co-authored-by: Eelco Dolstra --- doc/manual/src/glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/manual/src/glossary.md b/doc/manual/src/glossary.md index 92192e4cb..71ff13275 100644 --- a/doc/manual/src/glossary.md +++ b/doc/manual/src/glossary.md @@ -99,6 +99,6 @@ links. NARs are generated and unpacked using `nix-store --dump` and `nix-store --restore`. - `∅` \ - The empty set symbol. In the context of package history, this denotes a package was not present prior to installation. + The empty set symbol. In the context of profile history, this denotes a package is not present in a particular version of the profile. - `ε` \ The epsilon symbol. In the context of a package, this means the version is empty. More precisely, the derivation does not have a version attribute. From 70a717f7a8feb15d9daf1215e305162b999b6175 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Tue, 30 Nov 2021 20:53:10 +0000 Subject: [PATCH 21/40] Nix daemon stream old wopAddToStore No more buffering in string. --- src/libstore/daemon.cc | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/src/libstore/daemon.cc b/src/libstore/daemon.cc index 2eb566080..773794ffc 100644 --- a/src/libstore/daemon.cc +++ b/src/libstore/daemon.cc @@ -431,25 +431,23 @@ static void performOp(TunnelLogger * logger, ref store, hashAlgo = parseHashType(hashAlgoRaw); } - StringSink saved; - TeeSource savedNARSource(from, saved); - RetrieveRegularNARSink savedRegular { saved }; + auto dumpSource = sinkToSource([&](Sink & saved) { + TeeSource savedNARSource(from, saved); + RetrieveRegularNARSink savedRegular { saved }; - if (method == FileIngestionMethod::Recursive) { - /* Get the entire NAR dump from the client and save it to - a string so that we can pass it to - addToStoreFromDump(). */ - ParseSink sink; /* null sink; just parse the NAR */ - parseDump(sink, savedNARSource); - } else - parseDump(savedRegular, from); + if (method == FileIngestionMethod::Recursive) { + /* Get the entire NAR dump from the client and save it to + a string so that we can pass it to + addToStoreFromDump(). */ + ParseSink sink; /* null sink; just parse the NAR */ + parseDump(sink, savedNARSource); + } else + parseDump(savedRegular, from); + if (!savedRegular.regular) throw Error("regular file expected"); + }); logger->startWork(); - if (!savedRegular.regular) throw Error("regular file expected"); - - // FIXME: try to stream directly from `from`. - StringSource dumpSource { *saved.s }; - auto path = store->addToStoreFromDump(dumpSource, baseName, method, hashAlgo); + auto path = store->addToStoreFromDump(*dumpSource, baseName, method, hashAlgo); logger->stopWork(); to << store->printStorePath(path); From 95157b4e664dc6f4dece15beac6fa1143086323e Mon Sep 17 00:00:00 2001 From: John Ericson Date: Tue, 30 Nov 2021 21:02:45 +0000 Subject: [PATCH 22/40] Push wopAddToStore old style stream adapters into smaller scopes This doesn't fix the bug, but makes the code less difficult to read. Also improve the comments, now that it is clear what part is needed in each code path. --- src/libstore/daemon.cc | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/libstore/daemon.cc b/src/libstore/daemon.cc index 773794ffc..dc4889dfd 100644 --- a/src/libstore/daemon.cc +++ b/src/libstore/daemon.cc @@ -432,19 +432,26 @@ static void performOp(TunnelLogger * logger, ref store, } auto dumpSource = sinkToSource([&](Sink & saved) { - TeeSource savedNARSource(from, saved); - RetrieveRegularNARSink savedRegular { saved }; - if (method == FileIngestionMethod::Recursive) { - /* Get the entire NAR dump from the client and save it to - a string so that we can pass it to - addToStoreFromDump(). */ + /* We parse the NAR dump through into `saved` unmodified, + so why all this extra work? We still parse the NAR so + that we aren't sending arbitrary data to `saved` + unwittingly`, and we know when the NAR ends so we don't + consume the rest of `from` and can't parse another + command. (We don't trust `addToStoreFromDump` to not + eagerly consume the entire stream it's given, past the + length of the Nar. */ + TeeSource savedNARSource(from, saved); ParseSink sink; /* null sink; just parse the NAR */ parseDump(sink, savedNARSource); - } else + } else { + /* Incrementally parse the NAR file, stripping the + metadata, and streaming the sole file we expect into + `saved`. */ + RetrieveRegularNARSink savedRegular { saved }; parseDump(savedRegular, from); - - if (!savedRegular.regular) throw Error("regular file expected"); + if (!savedRegular.regular) throw Error("regular file expected"); + } }); logger->startWork(); auto path = store->addToStoreFromDump(*dumpSource, baseName, method, hashAlgo); From 2f5c913d4a21c60799290d6efe769d188c57b906 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Tue, 30 Nov 2021 21:48:43 +0000 Subject: [PATCH 23/40] Fix #5299 No matter what, we need to resize the buffer to not have any scratch space after we do the `read`. In the end of file case, `got` will be 0 from it's initial value. Before, we forgot to resize in the EOF case with the break. Yes, we know we didn't recieve any data in that case, but we still have the scatch space to undo. Co-Authored-By: Will Fancher --- src/libstore/local-store.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 64019314f..3a1688272 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -8,6 +8,7 @@ #include "references.hh" #include "callback.hh" #include "topo-sort.hh" +#include "finally.hh" #include #include @@ -1333,13 +1334,15 @@ StorePath LocalStore::addToStoreFromDump(Source & source0, const string & name, auto want = std::min(chunkSize, settings.narBufferSize - oldSize); dump.resize(oldSize + want); auto got = 0; + Finally cleanup([&]() { + dump.resize(oldSize + got); + }); try { got = source.read(dump.data() + oldSize, want); } catch (EndOfFile &) { inMemory = true; break; } - dump.resize(oldSize + got); } std::unique_ptr delTempDir; From c32a5f4d380daafc33d129a097a494e1af8d9600 Mon Sep 17 00:00:00 2001 From: Sergei Trofimovich Date: Wed, 1 Dec 2021 22:06:15 +0000 Subject: [PATCH 24/40] src/libutil/util.hh: fix build on gcc-11 Due to missing declaration the build fails as: src/libutil/util.hh:350:24: error: no match for 'operator||' (operand types are 'std::atomic' and 'bool') 350 | if (_isInterrupted || (interruptCheck && interruptCheck())) | ~~~~~~~~~~~~~~ ^~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | | | std::atomic bool --- src/libutil/util.hh | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libutil/util.hh b/src/libutil/util.hh index 0bdb37a79..bc96bfed1 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -11,6 +11,7 @@ #include #include +#include #include #include #include From 74898117360733bfc7ee57d1180a13f354c2ebbf Mon Sep 17 00:00:00 2001 From: David Arnold Date: Wed, 1 Dec 2021 18:36:19 -0500 Subject: [PATCH 25/40] Fix parent path check boundary - Previous to this commit the boundary was exclusive of the top level flake. - This is wrong since the top level flake is still a valid relative reference. - Now, the check boundary is inclusive of the top level flake. Signed-off-by: Timothy DeHerrera --- src/libfetchers/path.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libfetchers/path.cc b/src/libfetchers/path.cc index fb5702c4c..07e543c53 100644 --- a/src/libfetchers/path.cc +++ b/src/libfetchers/path.cc @@ -97,7 +97,7 @@ struct PathInputScheme : InputScheme // for security, ensure that if the parent is a store path, it's inside it if (store->isInStore(parent)) { auto storePath = store->printStorePath(store->toStorePath(parent).first); - if (!isInDir(absPath, storePath)) + if (!isDirOrInDir(absPath, storePath)) throw BadStorePath("relative path '%s' points outside of its parent's store path '%s'", path, storePath); } } else From 3bf7a868eefa5388400a63efd5c5b92b9177ff56 Mon Sep 17 00:00:00 2001 From: "Travis A. Everett" Date: Wed, 1 Dec 2021 18:38:32 -0600 Subject: [PATCH 26/40] darwin-install: nail down diskutil Same purpose as de9efa3b79af7886fcf2a67b6ce97d4f96a57421 For some unclear reason, we get occasional reports from people who do not have /usr/sbin on their PATH that the installer fails. It's a standard part of the PATH, so I have no clue what they're doing to remove it--but it's also fairly cheap to avoid. --- scripts/install-darwin-multi-user.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/install-darwin-multi-user.sh b/scripts/install-darwin-multi-user.sh index 96eba8310..afaa6783b 100644 --- a/scripts/install-darwin-multi-user.sh +++ b/scripts/install-darwin-multi-user.sh @@ -218,7 +218,7 @@ EOF setup_darwin_volume fi - if [ "$(diskutil info -plist /nix | xmllint --xpath "(/plist/dict/key[text()='GlobalPermissionsEnabled'])/following-sibling::*[1]" -)" = "" ]; then - failure "This script needs a /nix volume with global permissions! This may require running sudo diskutil enableOwnership /nix." + if [ "$(/usr/sbin/diskutil info -plist /nix | xmllint --xpath "(/plist/dict/key[text()='GlobalPermissionsEnabled'])/following-sibling::*[1]" -)" = "" ]; then + failure "This script needs a /nix volume with global permissions! This may require running sudo /usr/sbin/diskutil enableOwnership /nix." fi } From 8cbf862e6f6e8250d59491fdb88dfc11a805a970 Mon Sep 17 00:00:00 2001 From: Alexander Bantyev Date: Thu, 2 Dec 2021 11:35:50 +0300 Subject: [PATCH 27/40] Flakes: computeLocks: pass correct LockParent when reusing oldLock Previously, when we were attempting to reuse the old lockfile information in the computeLocks function, we have passed the parent of the current input to the next computeLocks call. This was incorrect, since the follows are resolved relative to the parent. This caused issues when we tried to reuse oldLock but couldn't for some reason (read: mustRefetch is true), in that case the follows were resolved incorrectly. Fix this by passing the correct parent, and adding some tests to prevent this particular regression from happening again. Closes https://github.com/NixOS/nix/issues/5697 --- src/libexpr/flake/flake.cc | 7 ++++++- tests/flakes.sh | 12 ++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/libexpr/flake/flake.cc b/src/libexpr/flake/flake.cc index 06136579e..33d253eee 100644 --- a/src/libexpr/flake/flake.cc +++ b/src/libexpr/flake/flake.cc @@ -480,11 +480,16 @@ LockedFlake lockFlake( } } + LockParent newParent { + .path = inputPath, + .absolute = false + }; + computeLocks( mustRefetch ? getFlake(state, oldLock->lockedRef, false, flakeCache).inputs : fakeInputs, - childNode, inputPath, oldLock, parent, parentPath); + childNode, inputPath, oldLock, newParent, parentPath); } else { /* We need to create a new lock file entry. So fetch diff --git a/tests/flakes.sh b/tests/flakes.sh index 9e10322b9..20966ab2a 100644 --- a/tests/flakes.sh +++ b/tests/flakes.sh @@ -722,6 +722,7 @@ cat > $flakeFollowsB/flake.nix < $flakeFollowsC/flake.nix < Date: Thu, 2 Dec 2021 17:46:44 +0100 Subject: [PATCH 28/40] Introduce builtins.groupBy primop This function is very useful in nixpkgs, but its implementation in Nix itself is rather slow due to it requiring a lot of attribute set and list appends. --- doc/manual/src/release-notes/rl-next.md | 3 ++ src/libexpr/primops.cc | 50 +++++++++++++++++++++++++ src/libexpr/value.hh | 2 + 3 files changed, 55 insertions(+) diff --git a/doc/manual/src/release-notes/rl-next.md b/doc/manual/src/release-notes/rl-next.md index 26c7d2cce..a6b22dfa7 100644 --- a/doc/manual/src/release-notes/rl-next.md +++ b/doc/manual/src/release-notes/rl-next.md @@ -5,3 +5,6 @@ * `nix develop` now has a flag `--unpack` to run `unpackPhase`. * Lists can now be compared lexicographically using the `<` operator. + +* New built-in function: `builtins.groupBy`, with the same functionality as + Nixpkgs' `lib.groupBy`, but faster. diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index d1f4d9009..66af373d7 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -2928,6 +2928,56 @@ static RegisterPrimOp primop_partition({ .fun = prim_partition, }); +static void prim_groupBy(EvalState & state, const Pos & pos, Value * * args, Value & v) +{ + state.forceFunction(*args[0], pos); + state.forceList(*args[1], pos); + + ValueVectorMap attrs; + + for (auto vElem : args[1]->listItems()) { + Value res; + state.callFunction(*args[0], *vElem, res, pos); + string name = state.forceStringNoCtx(res, pos); + Symbol sym = state.symbols.create(name); + auto vector = attrs.try_emplace(sym, ValueVector()).first; + vector->second.push_back(vElem); + } + + state.mkAttrs(v, attrs.size()); + + for (auto & i : attrs) { + Value * list = state.allocAttr(v, i.first); + auto size = i.second.size(); + state.mkList(*list, size); + memcpy(list->listElems(), i.second.data(), sizeof(Value *) * size); + } +} + +static RegisterPrimOp primop_groupBy({ + .name = "__groupBy", + .args = {"f", "list"}, + .doc = R"( + Groups elements of *list* together by the string returned from the + function *f* called on each element. It returns an attribute set + where each attribute value contains the elements of *list* that are + mapped to the same corresponding attribute name returned by *f*. + + For example, + + ```nix + builtins.groupBy (builtins.substring 0 1) ["foo" "bar" "baz"] + ``` + + evaluates to + + ```nix + { b = [ "bar" "baz" ]; f = [ "foo" ]; } + ``` + )", + .fun = prim_groupBy, +}); + static void prim_concatMap(EvalState & state, const Pos & pos, Value * * args, Value & v) { state.forceFunction(*args[0], pos); diff --git a/src/libexpr/value.hh b/src/libexpr/value.hh index 4b43e47ae..6b4f3c0ae 100644 --- a/src/libexpr/value.hh +++ b/src/libexpr/value.hh @@ -425,9 +425,11 @@ void mkPath(Value & v, const char * s); #if HAVE_BOEHMGC typedef std::vector > ValueVector; typedef std::map, traceable_allocator > > ValueMap; +typedef std::map, traceable_allocator > > ValueVectorMap; #else typedef std::vector ValueVector; typedef std::map ValueMap; +typedef std::map ValueVectorMap; #endif From 69b919887550483925b5a30388c13a63dabcca1a Mon Sep 17 00:00:00 2001 From: David Purdum Date: Thu, 2 Dec 2021 23:38:33 -0500 Subject: [PATCH 29/40] Fix docker command `docker -ti run nixos` does not run on docker version 20.10.7 (my machine). This fixes it to read `docker run -ti nixos`. --- doc/manual/src/installation/installing-docker.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/manual/src/installation/installing-docker.md b/doc/manual/src/installation/installing-docker.md index 3d2255b7a..ee7614bdb 100644 --- a/doc/manual/src/installation/installing-docker.md +++ b/doc/manual/src/installation/installing-docker.md @@ -3,7 +3,7 @@ To run the latest stable release of Nix with Docker run the following command: ```console -$ docker -ti run nixos/nix +$ docker run -ti nixos/nix Unable to find image 'nixos/nix:latest' locally latest: Pulling from nixos/nix 5843afab3874: Pull complete From d9b3adca756bdc10c298439f4502626bbcefcc2a Mon Sep 17 00:00:00 2001 From: Zhong Jianxin Date: Sat, 4 Dec 2021 20:46:29 +0800 Subject: [PATCH 30/40] launchd: Set NumberOfFiles to 4096 The default maxfiles on macOS 11 and macOS 12 is 256, which is too low for nix to work: ``` $ launchctl limit maxfiles maxfiles 256 unlimited ``` Set NumberOfFiles of nix-daemon to 4096 to avoid `Too many open files` error. --- misc/launchd/org.nixos.nix-daemon.plist.in | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/misc/launchd/org.nixos.nix-daemon.plist.in b/misc/launchd/org.nixos.nix-daemon.plist.in index f1b439840..da1970f69 100644 --- a/misc/launchd/org.nixos.nix-daemon.plist.in +++ b/misc/launchd/org.nixos.nix-daemon.plist.in @@ -25,5 +25,10 @@ /var/log/nix-daemon.log StandardOutPath /dev/null + SoftResourceLimits + + NumberOfFiles + 4096 + From 80934561114df14137ef07b6c07e17dff3a95544 Mon Sep 17 00:00:00 2001 From: "Travis A. Everett" Date: Sat, 4 Dec 2021 23:07:17 -0600 Subject: [PATCH 31/40] document some darwin mount settings --- .../src/installation/installing-binary.md | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/doc/manual/src/installation/installing-binary.md b/doc/manual/src/installation/installing-binary.md index 96fa34635..4367654a2 100644 --- a/doc/manual/src/installation/installing-binary.md +++ b/doc/manual/src/installation/installing-binary.md @@ -119,6 +119,30 @@ this to run the installer, but it may help if you run into trouble: - update `/etc/synthetic.conf` to direct macOS to create a "synthetic" empty root directory to mount your volume - specify mount options for the volume in `/etc/fstab` + - `rw`: read-write + - `noauto`: prevent the system from auto-mounting the volume (so the + LaunchDaemon mentioned below can control mounting it, and to avoid + masking problems with that mounting service). + - `nobrowse`: prevent the Nix Store volume from showing up on your + desktop; also keeps Spotlight from spending resources to index + this volume + - if you have FileVault enabled - generate an encryption password - put it in your system Keychain From fa58bff1ab9aacffd50f8200d72843af7abd827f Mon Sep 17 00:00:00 2001 From: regnat Date: Mon, 6 Dec 2021 11:45:18 +0100 Subject: [PATCH 32/40] Fallback when the daemon is too old for CA derivations Fix #5712 --- src/libstore/remote-store.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index a627e9cf1..c3d23affb 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -684,6 +684,14 @@ void RemoteStore::queryRealisationUncached(const DrvOutput & id, Callback> callback) noexcept { auto conn(getConnection()); + + if (GET_PROTOCOL_MINOR(conn->daemonVersion) < 27) { + warn("The daemon is too old for content-addressed derivations. I’ll do what I can"); + try { + callback(nullptr); + } catch (...) { return callback.rethrow(); } + } + conn->to << wopQueryRealisation; conn->to << id.to_string(); conn.processStderr(); From d1aaa7ef71713b6693ad3ddf8704ce62bab82095 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 6 Dec 2021 13:33:39 +0100 Subject: [PATCH 33/40] Change version to X.Y.Z Fixes #5732. --- .version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.version b/.version index 68151b2e1..fad066f80 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -2.5 \ No newline at end of file +2.5.0 \ No newline at end of file From 0a2fa2d68460eca946c91b72cd264725e5cda7db Mon Sep 17 00:00:00 2001 From: Alexander Bantyev Date: Fri, 26 Nov 2021 17:38:46 +0300 Subject: [PATCH 34/40] RunPager: restore stdout upon pager exit Before this change, stdout was closed after the pager exits. This is fine for non-interactive commands where we want to exit right after the pager exits anyways, but for interactive things (e.g. nix repl) this breaks the output after we quit the pager. Keep the initial stdout fd as part of RunPager, and restore it in RunPager::~RunPager using dup2. --- src/libmain/shared.cc | 4 ++-- src/libmain/shared.hh | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc index b6bfea8cb..4404e0195 100644 --- a/src/libmain/shared.cc +++ b/src/libmain/shared.cc @@ -427,7 +427,7 @@ RunPager::RunPager() }); pid.setKillSignal(SIGINT); - + stdout = fcntl(STDOUT_FILENO, F_DUPFD_CLOEXEC, 0); if (dup2(toPager.writeSide.get(), STDOUT_FILENO) == -1) throw SysError("dupping stdout"); } @@ -438,7 +438,7 @@ RunPager::~RunPager() try { if (pid != -1) { std::cout.flush(); - close(STDOUT_FILENO); + dup2(stdout, STDOUT_FILENO); pid.wait(); } } catch (...) { diff --git a/src/libmain/shared.hh b/src/libmain/shared.hh index 05277d90a..ed012959b 100644 --- a/src/libmain/shared.hh +++ b/src/libmain/shared.hh @@ -88,6 +88,7 @@ public: private: Pid pid; + int stdout; }; extern volatile ::sig_atomic_t blockInt; From 33926ed1e75c06cbf70a920e462841cc9daa0520 Mon Sep 17 00:00:00 2001 From: Alexander Bantyev Date: Fri, 26 Nov 2021 18:03:07 +0300 Subject: [PATCH 35/40] nix repl: add :log Add a :log command that shows logs for a derivation. Closes https://github.com/NixOS/nix/issues/3504 Co-authored-by: Taeer Bar-Yam --- doc/manual/src/release-notes/rl-next.md | 2 ++ src/nix/repl.cc | 26 +++++++++++++++++++++++-- src/nix/repl.md | 7 +++++-- tests/repl.sh | 13 +++++++++++++ tests/simple-failing.builder.sh | 2 ++ tests/simple-failing.nix | 8 ++++++++ 6 files changed, 54 insertions(+), 4 deletions(-) create mode 100644 tests/simple-failing.builder.sh create mode 100644 tests/simple-failing.nix diff --git a/doc/manual/src/release-notes/rl-next.md b/doc/manual/src/release-notes/rl-next.md index a6b22dfa7..cf2da9aa8 100644 --- a/doc/manual/src/release-notes/rl-next.md +++ b/doc/manual/src/release-notes/rl-next.md @@ -8,3 +8,5 @@ * New built-in function: `builtins.groupBy`, with the same functionality as Nixpkgs' `lib.groupBy`, but faster. + +* `nix repl` now has a `:log` command. diff --git a/src/nix/repl.cc b/src/nix/repl.cc index 2649eb0bd..42143871f 100644 --- a/src/nix/repl.cc +++ b/src/nix/repl.cc @@ -430,7 +430,8 @@ bool NixRepl::processLine(string line) << " :s Build dependencies of derivation, then start nix-shell\n" << " :t Describe result of evaluation\n" << " :u Build derivation, then start nix-shell\n" - << " :doc Show documentation of a builtin function\n"; + << " :doc Show documentation of a builtin function\n" + << " :log Show logs for a derivation\n"; } else if (command == ":a" || command == ":add") { @@ -500,7 +501,7 @@ bool NixRepl::processLine(string line) runNix("nix-shell", {state->store->printStorePath(drvPath)}); } - else if (command == ":b" || command == ":i" || command == ":s") { + else if (command == ":b" || command == ":i" || command == ":s" || command == ":log") { Value v; evalString(arg, v); StorePath drvPath = getDerivationPath(v); @@ -514,6 +515,27 @@ bool NixRepl::processLine(string line) logger->cout(" %s -> %s", outputName, state->store->printStorePath(outputPath)); } else if (command == ":i") { runNix("nix-env", {"-i", drvPathRaw}); + } else if (command == ":log") { + settings.readOnlyMode = true; + Finally roModeReset([&]() { + settings.readOnlyMode = false; + }); + auto subs = getDefaultSubstituters(); + + subs.push_front(state->store); + + bool foundLog = false; + RunPager pager; + for (auto & sub : subs) { + auto log = sub->getBuildLog(drvPath); + if (log) { + printInfo("got build log for '%s' from '%s'", drvPathRaw, sub->getUri()); + logger->writeToStdout(*log); + foundLog = true; + break; + } + } + if (!foundLog) throw Error("build log of '%s' is not available", drvPathRaw); } else { runNix("nix-shell", {drvPathRaw}); } diff --git a/src/nix/repl.md b/src/nix/repl.md index bba60f871..9b6f2bee3 100644 --- a/src/nix/repl.md +++ b/src/nix/repl.md @@ -35,14 +35,17 @@ R""( nix-repl> emacs.drvPath "/nix/store/lp0sjrhgg03y2n0l10n70rg0k7hhyz0l-emacs-27.1.drv" - nix-repl> drv = runCommand "hello" { buildInputs = [ hello ]; } "hello > $out" + nix-repl> drv = runCommand "hello" { buildInputs = [ hello ]; } "hello; hello > $out" - nix-repl> :b x + nix-repl> :b drv this derivation produced the following outputs: out -> /nix/store/0njwbgwmkwls0w5dv9mpc1pq5fj39q0l-hello nix-repl> builtins.readFile drv "Hello, world!\n" + + nix-repl> :log drv + Hello, world! ``` # Description diff --git a/tests/repl.sh b/tests/repl.sh index d360821f2..f592822bc 100644 --- a/tests/repl.sh +++ b/tests/repl.sh @@ -3,6 +3,13 @@ source common.sh replCmds=" simple = import ./simple.nix :b simple +:log simple +" + +replFailingCmds=" +failing = import ./simple-failing.nix +:b failing +:log failing " testRepl () { @@ -12,6 +19,12 @@ testRepl () { local outPath=$(echo "$replOutput" |& grep -o -E "$NIX_STORE_DIR/\w*-simple") nix path-info "${nixArgs[@]}" "$outPath" + # simple.nix prints a PATH during build + echo "$replOutput" | grep -qs 'PATH=' || fail "nix repl :log doesn't output logs" + local replOutput="$(nix repl "${nixArgs[@]}" <<< "$replFailingCmds")" + echo "$replOutput" + echo "$replOutput" | grep -qs 'This should fail' \ + || fail "nix repl :log doesn't output logs for a failed derivation" } # Simple test, try building a drv diff --git a/tests/simple-failing.builder.sh b/tests/simple-failing.builder.sh new file mode 100644 index 000000000..6285488ca --- /dev/null +++ b/tests/simple-failing.builder.sh @@ -0,0 +1,2 @@ +echo "This should fail" +exit 1 diff --git a/tests/simple-failing.nix b/tests/simple-failing.nix new file mode 100644 index 000000000..1e3a080ed --- /dev/null +++ b/tests/simple-failing.nix @@ -0,0 +1,8 @@ +with import ./config.nix; + +mkDerivation { + name = "simple-failing"; + builder = ./simple-failing.builder.sh; + PATH = ""; + goodPath = path; +} From ae21aab456f4e07fa621d87487c40381e45947dc Mon Sep 17 00:00:00 2001 From: Jan Tojnar Date: Mon, 6 Dec 2021 16:42:57 +0100 Subject: [PATCH 36/40] Update manual links Fixes: https://github.com/NixOS/nixos-homepage/issues/762 --- scripts/install-nix-from-closure.sh | 6 +++--- src/libstore/build/derivation-goal.cc | 2 +- src/libstore/build/worker.cc | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/install-nix-from-closure.sh b/scripts/install-nix-from-closure.sh index b5e2fea83..d543b4463 100644 --- a/scripts/install-nix-from-closure.sh +++ b/scripts/install-nix-from-closure.sh @@ -38,7 +38,7 @@ fi # Determine if we could use the multi-user installer or not if [ "$(uname -s)" = "Linux" ]; then - echo "Note: a multi-user installation is possible. See https://nixos.org/nix/manual/#sect-multi-user-installation" >&2 + echo "Note: a multi-user installation is possible. See https://nixos.org/manual/nix/stable/installation/installing-binary.html#multi-user-installation" >&2 fi case "$(uname -s)" in @@ -98,7 +98,7 @@ while [ $# -gt 0 ]; do echo " providing multi-user support and better isolation for local builds." echo " Both for security and reproducibility, this method is recommended if" echo " supported on your platform." - echo " See https://nixos.org/nix/manual/#sect-multi-user-installation" + echo " See https://nixos.org/manual/nix/stable/installation/installing-binary.html#multi-user-installation" echo "" echo " --no-daemon: Simple, single-user installation that does not require root and is" echo " trivial to uninstall." @@ -144,7 +144,7 @@ if ! [ -e "$dest" ]; then fi if ! [ -w "$dest" ]; then - echo "$0: directory $dest exists, but is not writable by you. This could indicate that another user has already performed a single-user installation of Nix on this system. If you wish to enable multi-user support see https://nixos.org/nix/manual/#ssec-multi-user. If you wish to continue with a single-user install for $USER please run 'chown -R $USER $dest' as root." >&2 + echo "$0: directory $dest exists, but is not writable by you. This could indicate that another user has already performed a single-user installation of Nix on this system. If you wish to enable multi-user support see https://nixos.org/manual/nix/stable/installation/multi-user.html. If you wish to continue with a single-user install for $USER please run 'chown -R $USER $dest' as root." >&2 exit 1 fi diff --git a/src/libstore/build/derivation-goal.cc b/src/libstore/build/derivation-goal.cc index b924d23b2..60945403e 100644 --- a/src/libstore/build/derivation-goal.cc +++ b/src/libstore/build/derivation-goal.cc @@ -655,7 +655,7 @@ void DerivationGoal::tryLocalBuild() { throw Error( "unable to build with a primary store that isn't a local store; " "either pass a different '--store' or enable remote builds." - "\nhttps://nixos.org/nix/manual/#chap-distributed-builds"); + "\nhttps://nixos.org/manual/nix/stable/advanced-topics/distributed-builds.html"); } diff --git a/src/libstore/build/worker.cc b/src/libstore/build/worker.cc index 55afb5cca..f11c5ce68 100644 --- a/src/libstore/build/worker.cc +++ b/src/libstore/build/worker.cc @@ -281,11 +281,11 @@ void Worker::run(const Goals & _topGoals) if (getMachines().empty()) throw Error("unable to start any build; either increase '--max-jobs' " "or enable remote builds." - "\nhttps://nixos.org/nix/manual/#chap-distributed-builds"); + "\nhttps://nixos.org/manual/nix/stable/advanced-topics/distributed-builds.html"); else throw Error("unable to start any build; remote machines may not have " "all required system features." - "\nhttps://nixos.org/nix/manual/#chap-distributed-builds"); + "\nhttps://nixos.org/manual/nix/stable/advanced-topics/distributed-builds.html"); } assert(!awake.empty()); From 853ef1304c379f03ef33f40bc68225d528cc6105 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 7 Dec 2021 21:45:09 +0100 Subject: [PATCH 37/40] Inline file --- tests/simple-failing.builder.sh | 2 -- tests/simple-failing.nix | 6 +++++- 2 files changed, 5 insertions(+), 3 deletions(-) delete mode 100644 tests/simple-failing.builder.sh diff --git a/tests/simple-failing.builder.sh b/tests/simple-failing.builder.sh deleted file mode 100644 index 6285488ca..000000000 --- a/tests/simple-failing.builder.sh +++ /dev/null @@ -1,2 +0,0 @@ -echo "This should fail" -exit 1 diff --git a/tests/simple-failing.nix b/tests/simple-failing.nix index 1e3a080ed..d176c9c51 100644 --- a/tests/simple-failing.nix +++ b/tests/simple-failing.nix @@ -2,7 +2,11 @@ with import ./config.nix; mkDerivation { name = "simple-failing"; - builder = ./simple-failing.builder.sh; + builder = builtins.toFile "builder.sh" + '' + echo "This should fail" + exit 1 + ''; PATH = ""; goodPath = path; } From 92ff5b4254b1a38a9dba4529d3dd4e9b11ea9333 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 7 Dec 2021 22:22:02 +0100 Subject: [PATCH 38/40] Tweak warning --- src/libstore/remote-store.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index c3d23affb..7f7e973e9 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -686,7 +686,7 @@ void RemoteStore::queryRealisationUncached(const DrvOutput & id, auto conn(getConnection()); if (GET_PROTOCOL_MINOR(conn->daemonVersion) < 27) { - warn("The daemon is too old for content-addressed derivations. I’ll do what I can"); + warn("the daemon is too old to support content-addressed derivations, please upgrade it to 2.4"); try { callback(nullptr); } catch (...) { return callback.rethrow(); } From b6d08a9e3ff76a38636377abe383b179b38e37b5 Mon Sep 17 00:00:00 2001 From: "Travis A. Everett" Date: Wed, 3 Nov 2021 23:17:48 -0500 Subject: [PATCH 39/40] darwin-install: fix break from bad vim plugins --- scripts/create-darwin-volume.sh | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/scripts/create-darwin-volume.sh b/scripts/create-darwin-volume.sh index b52232dd3..7e1a38cbd 100755 --- a/scripts/create-darwin-volume.sh +++ b/scripts/create-darwin-volume.sh @@ -440,7 +440,22 @@ add_nix_vol_fstab_line() { # shellcheck disable=SC1003,SC2026 local escaped_mountpoint="${NIX_ROOT/ /'\\\'040}" shift - EDITOR="/usr/bin/ex" _sudo "to add nix to fstab" "$@" < "$SCRATCH/ex_cleanroom_wrapper" <&2 - _sudo "to install the Nix volume mounter" /usr/bin/ex "$NIX_VOLUME_MOUNTD_DEST" < Date: Wed, 8 Dec 2021 19:55:34 -0500 Subject: [PATCH 40/40] Better diagnostics if no valid signature found I downloaded Nix tonight, and immediately broke it by accidentally removing the default binary caching. After figuring this out, I also failed to fix it properly, due to using the wrong key for Nix's default binary cache If the diagnostic message would have been clearer about what/where a "signature" for a "substituter" is + comes from, it probably would have saved me a few hours. Maybe we can save other noobs the same pain? --- src/libstore/build/substitution-goal.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libstore/build/substitution-goal.cc b/src/libstore/build/substitution-goal.cc index 29a8cfb87..4c3701b27 100644 --- a/src/libstore/build/substitution-goal.cc +++ b/src/libstore/build/substitution-goal.cc @@ -140,6 +140,8 @@ void PathSubstitutionGoal::tryNext() { warn("substituter '%s' does not have a valid signature for path '%s'", sub->getUri(), worker.store.printStorePath(storePath)); + warn("verify that your nix.conf contains a correct signature in 'trusted-public-keys' for %s", + sub->getUri()); tryNext(); return; }