diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 984f9a9ea2d..a5005f8a002 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,36 +1,54 @@ --- name: Bug report -about: Create a report to help us improve +about: Report unexpected or incorrect behaviour title: '' labels: bug assignees: '' --- -**Describe the bug** +## Describe the bug -A clear and concise description of what the bug is. + -**Steps To Reproduce** +## Steps To Reproduce -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error + -A clear and concise description of what you expected to happen. +## Expected behavior -**`nix-env --version` output** + -**Additional context** +## Metadata -Add any other context about the problem here. + -**Priorities** +## Additional context + + + +## Checklist + + + +- [ ] checked [latest Nix manual] \([source]) +- [ ] checked [open bug issues and pull requests] for possible duplicates + +[latest Nix manual]: https://nixos.org/manual/nix/unstable/ +[source]: https://github.com/NixOS/nix/tree/master/doc/manual/source +[open bug issues and pull requests]: https://github.com/NixOS/nix/labels/bug + +--- Add :+1: to [issues you find important](https://github.com/NixOS/nix/issues?q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc). diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 42c658b522f..c75a4695170 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,24 +1,39 @@ --- name: Feature request -about: Suggest an idea for this project +about: Suggest a new feature title: '' labels: feature assignees: '' --- -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] +## Is your feature request related to a problem? -**Describe the solution you'd like** -A clear and concise description of what you want to happen. + -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. +## Proposed solution -**Additional context** -Add any other context or screenshots about the feature request here. + -**Priorities** +## Alternative solutions + + + +## Additional context + + + +## Checklist + + + +- [ ] checked [latest Nix manual] \([source]) +- [ ] checked [open feature issues and pull requests] for possible duplicates + +[latest Nix manual]: https://nixos.org/manual/nix/unstable/ +[source]: https://github.com/NixOS/nix/tree/master/doc/manual/source +[open feature issues and pull requests]: https://github.com/NixOS/nix/labels/feature + +--- Add :+1: to [issues you find important](https://github.com/NixOS/nix/issues?q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc). diff --git a/.github/ISSUE_TEMPLATE/installer.md b/.github/ISSUE_TEMPLATE/installer.md index 3768a49c9a3..ed5e1ce87b9 100644 --- a/.github/ISSUE_TEMPLATE/installer.md +++ b/.github/ISSUE_TEMPLATE/installer.md @@ -23,14 +23,25 @@ assignees: ''
Output -```log + - +```log ```
-## Priorities +## Checklist + + + +- [ ] checked [latest Nix manual] \([source]) +- [ ] checked [open installer issues and pull requests] for possible duplicates + +[latest Nix manual]: https://nixos.org/manual/nix/unstable/ +[source]: https://github.com/NixOS/nix/tree/master/doc/manual/source +[open installer issues and pull requests]: https://github.com/NixOS/nix/labels/installer + +--- Add :+1: to [issues you find important](https://github.com/NixOS/nix/issues?q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc). diff --git a/.github/ISSUE_TEMPLATE/missing_documentation.md b/.github/ISSUE_TEMPLATE/missing_documentation.md index cf663e28d33..6c334b72206 100644 --- a/.github/ISSUE_TEMPLATE/missing_documentation.md +++ b/.github/ISSUE_TEMPLATE/missing_documentation.md @@ -26,6 +26,6 @@ assignees: '' [source]: https://github.com/NixOS/nix/tree/master/doc/manual/source [open documentation issues and pull requests]: https://github.com/NixOS/nix/labels/documentation -## Priorities +--- Add :+1: to [issues you find important](https://github.com/NixOS/nix/issues?q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc). diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 69da87db727..c6843d86fa7 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -17,10 +17,12 @@ so you understand the process and the expectations. --> -# Motivation +## Motivation + -# Context +## Context + @@ -29,7 +31,7 @@ so you understand the process and the expectations. -# Priorities and Process +--- Add :+1: to [pull requests you find important](https://github.com/NixOS/nix/pulls?q=is%3Aopen+sort%3Areactions-%2B1-desc). diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cb97fd211dd..9918875d9b0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -220,4 +220,4 @@ jobs: path: flake-regressions/tests - uses: DeterminateSystems/nix-installer-action@main - uses: DeterminateSystems/magic-nix-cache-action@main - - run: nix build --out-link ./new-nix && PATH=$(pwd)/new-nix/bin:$PATH MAX_FLAKES=25 flake-regressions/eval-all.sh + - run: nix build -L --out-link ./new-nix && PATH=$(pwd)/new-nix/bin:$PATH MAX_FLAKES=25 flake-regressions/eval-all.sh diff --git a/build-utils-meson/common/meson.build b/build-utils-meson/common/meson.build new file mode 100644 index 00000000000..f0322183e8a --- /dev/null +++ b/build-utils-meson/common/meson.build @@ -0,0 +1,22 @@ +# This is only conditional to work around +# https://github.com/mesonbuild/meson/issues/13293. It should be +# unconditional. +if not (host_machine.system() == 'windows' and cxx.get_id() == 'gcc') + deps_private += dependency('threads') +endif + +add_project_arguments( + '-Wdeprecated-copy', + '-Werror=suggest-override', + '-Werror=switch', + '-Werror=switch-enum', + '-Werror=unused-result', + '-Wignored-qualifiers', + '-Wimplicit-fallthrough', + '-Wno-deprecated-declarations', + language : 'cpp', +) + +if get_option('buildtype') not in ['debug'] + add_project_arguments('-O3', language : 'cpp') +endif diff --git a/build-utils-meson/diagnostics/meson.build b/build-utils-meson/diagnostics/meson.build deleted file mode 100644 index 30eedfc13f8..00000000000 --- a/build-utils-meson/diagnostics/meson.build +++ /dev/null @@ -1,11 +0,0 @@ -add_project_arguments( - '-Wdeprecated-copy', - '-Werror=suggest-override', - '-Werror=switch', - '-Werror=switch-enum', - '-Werror=unused-result', - '-Wignored-qualifiers', - '-Wimplicit-fallthrough', - '-Wno-deprecated-declarations', - language : 'cpp', -) diff --git a/build-utils-meson/threads/meson.build b/build-utils-meson/threads/meson.build deleted file mode 100644 index 294160de130..00000000000 --- a/build-utils-meson/threads/meson.build +++ /dev/null @@ -1,6 +0,0 @@ -# This is only conditional to work around -# https://github.com/mesonbuild/meson/issues/13293. It should be -# unconditional. -if not (host_machine.system() == 'windows' and cxx.get_id() == 'gcc') - deps_private += dependency('threads') -endif diff --git a/doc/manual/rl-next/nix-copy-flags.md b/doc/manual/rl-next/nix-copy-flags.md new file mode 100644 index 00000000000..f5b2b9716a4 --- /dev/null +++ b/doc/manual/rl-next/nix-copy-flags.md @@ -0,0 +1,18 @@ +--- +synopsis: "`nix copy` supports `--profile` and `--out-link`" +prs: [11657] +--- + +The `nix copy` command now has flags `--profile` and `--out-link`, similar to `nix build`. `--profile` makes a profile point to the +top-level store path, while `--out-link` create symlinks to the top-level store paths. + +For example, when updating the local NixOS system profile from a NixOS system closure on a remote machine, instead of +``` +# nix copy --from ssh://server $path +# nix build --profile /nix/var/nix/profiles/system $path +``` +you can now do +``` +# nix copy --from ssh://server --profile /nix/var/nix/profiles/system $path +``` +The advantage is that this avoids a time window where *path* is not a garbage collector root, and so could be deleted by a concurrent `nix store gc` process. diff --git a/doc/manual/source/command-ref/nix-shell.md b/doc/manual/source/command-ref/nix-shell.md index 69a711bd5e6..e95db9bea5d 100644 --- a/doc/manual/source/command-ref/nix-shell.md +++ b/doc/manual/source/command-ref/nix-shell.md @@ -88,7 +88,9 @@ All options not listed here are passed to `nix-store cleared before the interactive shell is started, so you get an environment that more closely corresponds to the “real” Nix build. A few variables, in particular `HOME`, `USER` and `DISPLAY`, are - retained. + retained. Note that the shell used to run commands is obtained from + [`NIX_BUILD_SHELL`](#env-NIX_BUILD_SHELL) / `` from + `NIX_PATH`, and therefore not affected by `--pure`. - `--packages` / `-p` *packages*… @@ -112,11 +114,30 @@ All options not listed here are passed to `nix-store # Environment variables -- `NIX_BUILD_SHELL` - - Shell used to start the interactive environment. Defaults to the - `bash` found in ``, falling back to the `bash` found in - `PATH` if not found. +- [`NIX_BUILD_SHELL`](#env-NIX_BUILD_SHELL) + + Shell used to start the interactive environment. + Defaults to the `bash` from `bashInteractive` found in ``, falling back to the `bash` found in `PATH` if not found. + + > **Note** + > + > The shell obtained using this method may not necessarily be the same as any shells requested in *path*. + + + + > **Example + > + > Despite `--pure`, this invocation will not result in a fully reproducible shell environment: + > + > ```nix + > #!/usr/bin/env -S nix-shell --pure + > let + > pkgs = import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/854fdc68881791812eddd33b2fed94b954979a8e.tar.gz") {}; + > in + > pkgs.mkShell { + > buildInputs = pkgs.bashInteractive; + > } + > ``` {{#include ./env-common.md}} diff --git a/src/libcmd/command.cc b/src/libcmd/command.cc index 1a4c76ec5be..86d13fab796 100644 --- a/src/libcmd/command.cc +++ b/src/libcmd/command.cc @@ -179,30 +179,34 @@ BuiltPathsCommand::BuiltPathsCommand(bool recursive) void BuiltPathsCommand::run(ref store, Installables && installables) { - BuiltPaths paths; + BuiltPaths rootPaths, allPaths; + if (all) { if (installables.size()) throw UsageError("'--all' does not expect arguments"); // XXX: Only uses opaque paths, ignores all the realisations for (auto & p : store->queryAllValidPaths()) - paths.emplace_back(BuiltPath::Opaque{p}); + rootPaths.emplace_back(BuiltPath::Opaque{p}); + allPaths = rootPaths; } else { - paths = Installable::toBuiltPaths(getEvalStore(), store, realiseMode, operateOn, installables); + rootPaths = Installable::toBuiltPaths(getEvalStore(), store, realiseMode, operateOn, installables); + allPaths = rootPaths; + if (recursive) { // XXX: This only computes the store path closure, ignoring // intermediate realisations StorePathSet pathsRoots, pathsClosure; - for (auto & root : paths) { + for (auto & root : rootPaths) { auto rootFromThis = root.outPaths(); pathsRoots.insert(rootFromThis.begin(), rootFromThis.end()); } store->computeFSClosure(pathsRoots, pathsClosure); for (auto & path : pathsClosure) - paths.emplace_back(BuiltPath::Opaque{path}); + allPaths.emplace_back(BuiltPath::Opaque{path}); } } - run(store, std::move(paths)); + run(store, std::move(allPaths), std::move(rootPaths)); } StorePathsCommand::StorePathsCommand(bool recursive) @@ -210,10 +214,10 @@ StorePathsCommand::StorePathsCommand(bool recursive) { } -void StorePathsCommand::run(ref store, BuiltPaths && paths) +void StorePathsCommand::run(ref store, BuiltPaths && allPaths, BuiltPaths && rootPaths) { StorePathSet storePaths; - for (auto & builtPath : paths) + for (auto & builtPath : allPaths) for (auto & p : builtPath.outPaths()) storePaths.insert(p); @@ -245,7 +249,7 @@ void MixProfile::updateProfile(const StorePath & storePath) { if (!profile) return; - auto store = getStore().dynamic_pointer_cast(); + auto store = getDstStore().dynamic_pointer_cast(); if (!store) throw Error("'--profile' is not supported for this Nix store"); auto profile2 = absPath(*profile); @@ -365,4 +369,31 @@ void MixEnvironment::setEnviron() return; } +void createOutLinks(const std::filesystem::path & outLink, const BuiltPaths & buildables, LocalFSStore & store) +{ + for (const auto & [_i, buildable] : enumerate(buildables)) { + auto i = _i; + std::visit( + overloaded{ + [&](const BuiltPath::Opaque & bo) { + auto symlink = outLink; + if (i) + symlink += fmt("-%d", i); + store.addPermRoot(bo.path, absPath(symlink.string())); + }, + [&](const BuiltPath::Built & bfd) { + for (auto & output : bfd.outputs) { + auto symlink = outLink; + if (i) + symlink += fmt("-%d", i); + if (output.first != "out") + symlink += fmt("-%s", output.first); + store.addPermRoot(output.second, absPath(symlink.string())); + } + }, + }, + buildable.raw()); + } +} + } diff --git a/src/libcmd/command.hh b/src/libcmd/command.hh index 8da4327c25d..23529848f6b 100644 --- a/src/libcmd/command.hh +++ b/src/libcmd/command.hh @@ -18,6 +18,7 @@ extern char ** savedArgv; class EvalState; struct Pos; class Store; +class LocalFSStore; static constexpr Command::Category catHelp = -1; static constexpr Command::Category catSecondary = 100; @@ -46,7 +47,20 @@ struct StoreCommand : virtual Command { StoreCommand(); void run() override; + + /** + * Return the default Nix store. + */ ref getStore(); + + /** + * Return the destination Nix store. + */ + virtual ref getDstStore() + { + return getStore(); + } + virtual ref createStore(); /** * Main entry point, with a `Store` provided @@ -69,7 +83,7 @@ struct CopyCommand : virtual StoreCommand ref createStore() override; - ref getDstStore(); + ref getDstStore() override; }; /** @@ -239,7 +253,7 @@ public: BuiltPathsCommand(bool recursive = false); - virtual void run(ref store, BuiltPaths && paths) = 0; + virtual void run(ref store, BuiltPaths && allPaths, BuiltPaths && rootPaths) = 0; void run(ref store, Installables && installables) override; @@ -252,7 +266,7 @@ struct StorePathsCommand : public BuiltPathsCommand virtual void run(ref store, StorePaths && storePaths) = 0; - void run(ref store, BuiltPaths && paths) override; + void run(ref store, BuiltPaths && allPaths, BuiltPaths && rootPaths) override; }; /** @@ -354,4 +368,10 @@ std::string showVersions(const std::set & versions); void printClosureDiff( ref store, const StorePath & beforePath, const StorePath & afterPath, std::string_view indent); +/** + * Create symlinks prefixed by `outLink` to the store paths in + * `buildables`. + */ +void createOutLinks(const std::filesystem::path & outLink, const BuiltPaths & buildables, LocalFSStore & store); + } diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc index 227bb64edfe..f2b27af7c87 100644 --- a/src/libcmd/installables.cc +++ b/src/libcmd/installables.cc @@ -918,4 +918,12 @@ void BuiltPathsCommand::applyDefaultInstallables(std::vector & rawI rawInstallables.push_back("."); } +BuiltPaths toBuiltPaths(const std::vector & builtPathsWithResult) +{ + BuiltPaths res; + for (auto & i : builtPathsWithResult) + res.push_back(i.path); + return res; +} + } diff --git a/src/libcmd/installables.hh b/src/libcmd/installables.hh index bf5759230f3..c995c3019f4 100644 --- a/src/libcmd/installables.hh +++ b/src/libcmd/installables.hh @@ -86,6 +86,8 @@ struct BuiltPathWithResult std::optional result; }; +BuiltPaths toBuiltPaths(const std::vector & builtPathsWithResult); + /** * Shorthand, for less typing and helping us keep the choice of * collection in sync. diff --git a/src/libcmd/meson.build b/src/libcmd/meson.build index c484cf998aa..1f27c161402 100644 --- a/src/libcmd/meson.build +++ b/src/libcmd/meson.build @@ -30,8 +30,6 @@ deps_public_maybe_subproject = [ ] subdir('build-utils-meson/subprojects') -subdir('build-utils-meson/threads') - nlohmann_json = dependency('nlohmann_json', version : '>= 3.9') deps_public += nlohmann_json @@ -72,7 +70,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') sources = files( 'built-path.cc', diff --git a/src/libexpr-c/meson.build b/src/libexpr-c/meson.build index 4160f0d5a7b..5bcca29e0b8 100644 --- a/src/libexpr-c/meson.build +++ b/src/libexpr-c/meson.build @@ -29,8 +29,6 @@ deps_public_maybe_subproject = [ ] subdir('build-utils-meson/subprojects') -subdir('build-utils-meson/threads') - # TODO rename, because it will conflict with downstream projects configdata.set_quoted('PACKAGE_VERSION', meson.project_version()) @@ -55,7 +53,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') sources = files( 'nix_api_expr.cc', diff --git a/src/libexpr-test-support/meson.build b/src/libexpr-test-support/meson.build index b9e7f390d74..bdfd435a877 100644 --- a/src/libexpr-test-support/meson.build +++ b/src/libexpr-test-support/meson.build @@ -27,8 +27,6 @@ deps_public_maybe_subproject = [ ] subdir('build-utils-meson/subprojects') -subdir('build-utils-meson/threads') - rapidcheck = dependency('rapidcheck') deps_public += rapidcheck @@ -41,7 +39,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') sources = files( 'tests/value/context.cc', diff --git a/src/libexpr-tests/meson.build b/src/libexpr-tests/meson.build index 5a5c9f1d48a..b50c18c9c8f 100644 --- a/src/libexpr-tests/meson.build +++ b/src/libexpr-tests/meson.build @@ -25,8 +25,6 @@ deps_public_maybe_subproject = [ ] subdir('build-utils-meson/subprojects') -subdir('build-utils-meson/threads') - subdir('build-utils-meson/export-all-symbols') subdir('build-utils-meson/windows-version') @@ -51,7 +49,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') sources = files( 'derived-path.cc', diff --git a/src/libexpr/eval-inline.hh b/src/libexpr/eval-inline.hh index d5ce238b2ed..631c0f39610 100644 --- a/src/libexpr/eval-inline.hh +++ b/src/libexpr/eval-inline.hh @@ -87,11 +87,15 @@ void EvalState::forceValue(Value & v, const PosIdx pos) { if (v.isThunk()) { Env * env = v.payload.thunk.env; + assert(env || v.isBlackhole()); Expr * expr = v.payload.thunk.expr; try { v.mkBlackhole(); //checkInterrupt(); - expr->eval(*this, *env, v); + if (env) [[likely]] + expr->eval(*this, *env, v); + else + ExprBlackHole::throwInfiniteRecursionError(*this, v); } catch (...) { v.mkThunk(env, expr); tryFixupBlackHolePos(v, pos); diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 40bd3f42f20..de7d434ec2b 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -2106,9 +2106,12 @@ void ExprPos::eval(EvalState & state, Env & env, Value & v) state.mkPos(v, pos); } - -void ExprBlackHole::eval(EvalState & state, Env & env, Value & v) +void ExprBlackHole::eval(EvalState & state, [[maybe_unused]] Env & env, Value & v) { + throwInfiniteRecursionError(state, v); +} + +[[gnu::noinline]] [[noreturn]] void ExprBlackHole::throwInfiniteRecursionError(EvalState & state, Value &v) { state.error("infinite recursion encountered") .atPos(v.determinePos(noPos)) .debugThrow(); diff --git a/src/libexpr/meson.build b/src/libexpr/meson.build index 4d8a38b435c..28318579e92 100644 --- a/src/libexpr/meson.build +++ b/src/libexpr/meson.build @@ -27,8 +27,6 @@ deps_public_maybe_subproject = [ ] subdir('build-utils-meson/subprojects') -subdir('build-utils-meson/threads') - boost = dependency( 'boost', modules : ['container', 'context'], @@ -79,7 +77,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') parser_tab = custom_target( input : 'parser.y', diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh index 19ef3abf6a7..dc210abbf2e 100644 --- a/src/libexpr/nixexpr.hh +++ b/src/libexpr/nixexpr.hh @@ -468,6 +468,7 @@ struct ExprBlackHole : Expr void show(const SymbolTable & symbols, std::ostream & str) const override {} void eval(EvalState & state, Env & env, Value & v) override; void bindVars(EvalState & es, const std::shared_ptr & env) override {} + [[noreturn]] static void throwInfiniteRecursionError(EvalState & state, Value & v); }; extern ExprBlackHole eBlackHole; diff --git a/src/libfetchers-tests/meson.build b/src/libfetchers-tests/meson.build index d948dbad69a..fdab6ba6c41 100644 --- a/src/libfetchers-tests/meson.build +++ b/src/libfetchers-tests/meson.build @@ -24,8 +24,6 @@ deps_public_maybe_subproject = [ ] subdir('build-utils-meson/subprojects') -subdir('build-utils-meson/threads') - subdir('build-utils-meson/export-all-symbols') subdir('build-utils-meson/windows-version') @@ -44,7 +42,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') sources = files( 'public-key.cc', diff --git a/src/libfetchers/cache.cc b/src/libfetchers/cache.cc index b0b6cb8873d..6c2241f3af7 100644 --- a/src/libfetchers/cache.cc +++ b/src/libfetchers/cache.cc @@ -36,7 +36,7 @@ struct CacheImpl : Cache { auto state(_state.lock()); - auto dbPath = getCacheDir() + "/fetcher-cache-v2.sqlite"; + auto dbPath = getCacheDir() + "/fetcher-cache-v3.sqlite"; createDirs(dirOf(dbPath)); state->db = SQLite(dbPath); diff --git a/src/libfetchers/meson.build b/src/libfetchers/meson.build index 1d2543b10d7..914e6f05d84 100644 --- a/src/libfetchers/meson.build +++ b/src/libfetchers/meson.build @@ -26,8 +26,6 @@ deps_public_maybe_subproject = [ ] subdir('build-utils-meson/subprojects') -subdir('build-utils-meson/threads') - nlohmann_json = dependency('nlohmann_json', version : '>= 3.9') deps_public += nlohmann_json @@ -43,7 +41,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') sources = files( 'attrs.cc', diff --git a/src/libflake-tests/meson.build b/src/libflake-tests/meson.build index 592a7493b9e..c0a9b88478e 100644 --- a/src/libflake-tests/meson.build +++ b/src/libflake-tests/meson.build @@ -24,8 +24,6 @@ deps_public_maybe_subproject = [ ] subdir('build-utils-meson/subprojects') -subdir('build-utils-meson/threads') - subdir('build-utils-meson/export-all-symbols') subdir('build-utils-meson/windows-version') @@ -44,7 +42,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') sources = files( 'flakeref.cc', diff --git a/src/libflake/flake/flakeref.cc b/src/libflake/flake/flakeref.cc index e94aed35a0e..d0e7ce58812 100644 --- a/src/libflake/flake/flakeref.cc +++ b/src/libflake/flake/flakeref.cc @@ -79,8 +79,8 @@ static std::pair fromParsedURL( std::string fragment; std::swap(fragment, parsedURL.fragment); - return std::make_pair(FlakeRef(fetchers::Input::fromURL(fetchSettings, parsedURL, isFlake), dir), fragment); -}; + return {FlakeRef(fetchers::Input::fromURL(fetchSettings, parsedURL, isFlake), dir), fragment}; +} std::pair parsePathFlakeRefWithFragment( const fetchers::Settings & fetchSettings, @@ -203,8 +203,7 @@ std::pair parsePathFlakeRefWithFragment( .query = query, .fragment = fragment }, isFlake); -}; - +} /** * Check if `url` is a flake ID. This is an abbreviated syntax for diff --git a/src/libflake/meson.build b/src/libflake/meson.build index d2bb179dfd6..2c1a70a1840 100644 --- a/src/libflake/meson.build +++ b/src/libflake/meson.build @@ -26,8 +26,6 @@ deps_public_maybe_subproject = [ ] subdir('build-utils-meson/subprojects') -subdir('build-utils-meson/threads') - nlohmann_json = dependency('nlohmann_json', version : '>= 3.9') deps_public += nlohmann_json @@ -41,7 +39,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') sources = files( 'flake/config.cc', diff --git a/src/libmain-c/meson.build b/src/libmain-c/meson.build index 0ec0e3f6db1..3cb1e4baae7 100644 --- a/src/libmain-c/meson.build +++ b/src/libmain-c/meson.build @@ -29,8 +29,6 @@ deps_public_maybe_subproject = [ ] subdir('build-utils-meson/subprojects') -subdir('build-utils-meson/threads') - # TODO rename, because it will conflict with downstream projects configdata.set_quoted('PACKAGE_VERSION', meson.project_version()) @@ -55,7 +53,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') sources = files( 'nix_api_main.cc', diff --git a/src/libmain/meson.build b/src/libmain/meson.build index 7fcadf06ddc..6c6298e2be7 100644 --- a/src/libmain/meson.build +++ b/src/libmain/meson.build @@ -26,8 +26,6 @@ deps_public_maybe_subproject = [ ] subdir('build-utils-meson/subprojects') -subdir('build-utils-meson/threads') - pubsetbuf_test = ''' #include @@ -60,7 +58,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') sources = files( 'common-args.cc', diff --git a/src/libstore-c/meson.build b/src/libstore-c/meson.build index d4f86eeffdb..44b5fe11d81 100644 --- a/src/libstore-c/meson.build +++ b/src/libstore-c/meson.build @@ -27,8 +27,6 @@ deps_public_maybe_subproject = [ ] subdir('build-utils-meson/subprojects') -subdir('build-utils-meson/threads') - # TODO rename, because it will conflict with downstream projects configdata.set_quoted('PACKAGE_VERSION', meson.project_version()) @@ -51,7 +49,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') sources = files( 'nix_api_store.cc', diff --git a/src/libstore-test-support/meson.build b/src/libstore-test-support/meson.build index 98ec9882edf..f8308e7bbf6 100644 --- a/src/libstore-test-support/meson.build +++ b/src/libstore-test-support/meson.build @@ -25,8 +25,6 @@ deps_public_maybe_subproject = [ ] subdir('build-utils-meson/subprojects') -subdir('build-utils-meson/threads') - rapidcheck = dependency('rapidcheck') deps_public += rapidcheck @@ -38,7 +36,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') sources = files( 'tests/derived-path.cc', diff --git a/src/libstore-tests/meson.build b/src/libstore-tests/meson.build index f4f67d73a39..fc9152f2fb6 100644 --- a/src/libstore-tests/meson.build +++ b/src/libstore-tests/meson.build @@ -25,8 +25,6 @@ deps_public_maybe_subproject = [ ] subdir('build-utils-meson/subprojects') -subdir('build-utils-meson/threads') - subdir('build-utils-meson/export-all-symbols') subdir('build-utils-meson/windows-version') @@ -52,7 +50,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') sources = files( 'common-protocol.cc', diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index 73195794a5c..45dfe4ad871 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -4,6 +4,7 @@ #include "finally.hh" #include "unix-domain-socket.hh" #include "signals.hh" +#include "posix-fs-canonicalise.hh" #if !defined(__linux__) // For shelling out to lsof @@ -763,13 +764,18 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) } } } - for (auto & path : topoSortPaths(visited)) { if (!dead.insert(path).second) continue; if (shouldDelete) { - invalidatePathChecked(path); - deleteFromStore(path.to_string()); - referrersCache.erase(path); + try { + invalidatePathChecked(path); + deleteFromStore(path.to_string()); + referrersCache.erase(path); + } catch (PathInUse &e) { + // If we end up here, it's likely a new occurence + // of https://github.com/NixOS/nix/issues/11923 + printError("BUG: %s", e.what()); + } } } }; diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index eafdac0cd33..f708bd1b008 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -95,51 +95,6 @@ struct LocalStore::State::Stmts { SQLiteStmt AddRealisationReference; }; -static int getSchema(Path schemaPath) -{ - int curSchema = 0; - if (pathExists(schemaPath)) { - auto s = readFile(schemaPath); - auto n = string2Int(s); - if (!n) - throw Error("'%1%' is corrupt", schemaPath); - curSchema = *n; - } - return curSchema; -} - -void migrateCASchema(SQLite& db, Path schemaPath, AutoCloseFD& lockFd) -{ - const int nixCASchemaVersion = 4; - int curCASchema = getSchema(schemaPath); - if (curCASchema != nixCASchemaVersion) { - if (curCASchema > nixCASchemaVersion) { - throw Error("current Nix store ca-schema is version %1%, but I only support %2%", - curCASchema, nixCASchemaVersion); - } - - if (!lockFile(lockFd.get(), ltWrite, false)) { - printInfo("waiting for exclusive access to the Nix store for ca drvs..."); - lockFile(lockFd.get(), ltNone, false); // We have acquired a shared lock; release it to prevent deadlocks - lockFile(lockFd.get(), ltWrite, true); - } - - if (curCASchema == 0) { - static const char schema[] = - #include "ca-specific-schema.sql.gen.hh" - ; - db.exec(schema); - curCASchema = nixCASchemaVersion; - } - - if (curCASchema < 4) - throw Error("experimental CA schema version %d is no longer supported", curCASchema); - - writeFile(schemaPath, fmt("%d", nixCASchemaVersion), 0666, true); - lockFile(lockFd.get(), ltRead, true); - } -} - LocalStore::LocalStore( std::string_view scheme, PathView path, @@ -316,6 +271,10 @@ LocalStore::LocalStore( openDB(*state, false); + /* Legacy database schema migrations. Don't bump 'schema' for + new migrations; instead, add a migration to + upgradeDBSchema(). */ + if (curSchema < 8) { SQLiteTxn txn(state->db); state->db.exec("alter table ValidPaths add column ultimate integer"); @@ -342,13 +301,7 @@ LocalStore::LocalStore( else openDB(*state, false); - if (experimentalFeatureSettings.isEnabled(Xp::CaDerivations)) { - if (!readOnly) { - migrateCASchema(state->db, dbDir + "/ca-schema", globalLock); - } else { - throw Error("need to migrate to content-addressed schema, but this cannot be done in read-only mode"); - } - } + upgradeDBSchema(*state); /* Prepare SQL statements. */ state->stmts->RegisterValidPath.create(state->db, @@ -483,7 +436,17 @@ std::string LocalStore::getUri() int LocalStore::getSchema() -{ return nix::getSchema(schemaPath); } +{ + int curSchema = 0; + if (pathExists(schemaPath)) { + auto s = readFile(schemaPath); + auto n = string2Int(s); + if (!n) + throw Error("'%1%' is corrupt", schemaPath); + curSchema = *n; + } + return curSchema; +} void LocalStore::openDB(State & state, bool create) { @@ -566,6 +529,42 @@ void LocalStore::openDB(State & state, bool create) } +void LocalStore::upgradeDBSchema(State & state) +{ + state.db.exec("create table if not exists SchemaMigrations (migration text primary key not null);"); + + std::set schemaMigrations; + + { + SQLiteStmt querySchemaMigrations; + querySchemaMigrations.create(state.db, "select migration from SchemaMigrations;"); + auto useQuerySchemaMigrations(querySchemaMigrations.use()); + while (useQuerySchemaMigrations.next()) + schemaMigrations.insert(useQuerySchemaMigrations.getStr(0)); + } + + auto doUpgrade = [&](const std::string & migrationName, const std::string & stmt) + { + if (schemaMigrations.contains(migrationName)) + return; + + debug("executing Nix database schema migration '%s'...", migrationName); + + SQLiteTxn txn(state.db); + state.db.exec(stmt + fmt(";\ninsert into SchemaMigrations values('%s')", migrationName)); + txn.commit(); + + schemaMigrations.insert(migrationName); + }; + + if (experimentalFeatureSettings.isEnabled(Xp::CaDerivations)) + doUpgrade( + "20220326-ca-derivations", + #include "ca-specific-schema.sql.gen.hh" + ); +} + + /* To improve purity, users may want to make the Nix store a read-only bind mount. So make the Nix store writable for this process. */ void LocalStore::makeStoreWritable() diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh index 21848cc4d10..83154d65193 100644 --- a/src/libstore/local-store.hh +++ b/src/libstore/local-store.hh @@ -356,6 +356,8 @@ private: void openDB(State & state, bool create); + void upgradeDBSchema(State & state); + void makeStoreWritable(); uint64_t queryValidPathId(State & state, const StorePath & path); diff --git a/src/libstore/meson.build b/src/libstore/meson.build index 101879e9090..f836b8d4f62 100644 --- a/src/libstore/meson.build +++ b/src/libstore/meson.build @@ -82,7 +82,6 @@ if host_machine.system() == 'windows' endif subdir('build-utils-meson/libatomic') -subdir('build-utils-meson/threads') boost = dependency( 'boost', @@ -180,7 +179,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') sources = files( 'binary-cache-store.cc', diff --git a/src/libutil-c/meson.build b/src/libutil-c/meson.build index 3d5a0b9c23c..d44453676e9 100644 --- a/src/libutil-c/meson.build +++ b/src/libutil-c/meson.build @@ -25,8 +25,6 @@ deps_public_maybe_subproject = [ ] subdir('build-utils-meson/subprojects') -subdir('build-utils-meson/threads') - # TODO rename, because it will conflict with downstream projects configdata.set_quoted('PACKAGE_VERSION', meson.project_version()) @@ -47,7 +45,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') sources = files( 'nix_api_util.cc', diff --git a/src/libutil-test-support/meson.build b/src/libutil-test-support/meson.build index c5e1ba80b2b..fa1df732022 100644 --- a/src/libutil-test-support/meson.build +++ b/src/libutil-test-support/meson.build @@ -23,8 +23,6 @@ deps_public_maybe_subproject = [ ] subdir('build-utils-meson/subprojects') -subdir('build-utils-meson/threads') - rapidcheck = dependency('rapidcheck') deps_public += rapidcheck @@ -35,7 +33,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') sources = files( 'tests/hash.cc', diff --git a/src/libutil-tests/meson.build b/src/libutil-tests/meson.build index 5c3b5e5a3aa..f593507742b 100644 --- a/src/libutil-tests/meson.build +++ b/src/libutil-tests/meson.build @@ -25,8 +25,6 @@ deps_public_maybe_subproject = [ ] subdir('build-utils-meson/subprojects') -subdir('build-utils-meson/threads') - subdir('build-utils-meson/export-all-symbols') subdir('build-utils-meson/windows-version') @@ -44,7 +42,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') sources = files( 'args.cc', diff --git a/src/libutil/meson.build b/src/libutil/meson.build index a6dc8639478..11b4ea59243 100644 --- a/src/libutil/meson.build +++ b/src/libutil/meson.build @@ -54,7 +54,6 @@ endforeach configdata.set('HAVE_DECL_AT_SYMLINK_NOFOLLOW', cxx.has_header_symbol('fcntl.h', 'AT_SYMLINK_NOFOLLOW').to_int()) subdir('build-utils-meson/libatomic') -subdir('build-utils-meson/threads') if host_machine.system() == 'windows' socket = cxx.find_library('ws2_32') @@ -121,7 +120,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') sources = files( 'archive.cc', diff --git a/src/nix/build.cc b/src/nix/build.cc index da9132d02f0..3569b0cde2a 100644 --- a/src/nix/build.cc +++ b/src/nix/build.cc @@ -42,29 +42,6 @@ static nlohmann::json builtPathsWithResultToJSON(const std::vector& buildables, LocalFSStore& store2) -{ - for (const auto & [_i, buildable] : enumerate(buildables)) { - auto i = _i; - std::visit(overloaded { - [&](const BuiltPath::Opaque & bo) { - auto symlink = outLink; - if (i) symlink += fmt("-%d", i); - store2.addPermRoot(bo.path, absPath(symlink.string())); - }, - [&](const BuiltPath::Built & bfd) { - for (auto & output : bfd.outputs) { - auto symlink = outLink; - if (i) symlink += fmt("-%d", i); - if (output.first != "out") symlink += fmt("-%s", output.first); - store2.addPermRoot(output.second, absPath(symlink.string())); - } - }, - }, buildable.path.raw()); - } -} - struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile { Path outLink = "result"; @@ -140,7 +117,7 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile if (outLink != "") if (auto store2 = store.dynamic_pointer_cast()) - createOutLinks(outLink, buildables, *store2); + createOutLinks(outLink, toBuiltPaths(buildables), *store2); if (printOutputPaths) { stopProgressBar(); diff --git a/src/nix/copy.cc b/src/nix/copy.cc index 151d282772f..399a6c0fd34 100644 --- a/src/nix/copy.cc +++ b/src/nix/copy.cc @@ -1,11 +1,13 @@ #include "command.hh" #include "shared.hh" #include "store-api.hh" +#include "local-fs-store.hh" using namespace nix; -struct CmdCopy : virtual CopyCommand, virtual BuiltPathsCommand +struct CmdCopy : virtual CopyCommand, virtual BuiltPathsCommand, MixProfile { + std::optional outLink; CheckSigsFlag checkSigs = CheckSigs; SubstituteFlag substitute = NoSubstitute; @@ -13,6 +15,15 @@ struct CmdCopy : virtual CopyCommand, virtual BuiltPathsCommand CmdCopy() : BuiltPathsCommand(true) { + addFlag({ + .longName = "out-link", + .shortName = 'o', + .description = "Create symlinks prefixed with *path* to the top-level store paths fetched from the source store.", + .labels = {"path"}, + .handler = {&outLink}, + .completer = completePath + }); + addFlag({ .longName = "no-check-sigs", .description = "Do not require that paths are signed by trusted keys.", @@ -43,19 +54,28 @@ struct CmdCopy : virtual CopyCommand, virtual BuiltPathsCommand Category category() override { return catSecondary; } - void run(ref srcStore, BuiltPaths && paths) override + void run(ref srcStore, BuiltPaths && allPaths, BuiltPaths && rootPaths) override { auto dstStore = getDstStore(); RealisedPath::Set stuffToCopy; - for (auto & builtPath : paths) { + for (auto & builtPath : allPaths) { auto theseRealisations = builtPath.toRealisedPaths(*srcStore); stuffToCopy.insert(theseRealisations.begin(), theseRealisations.end()); } copyPaths( *srcStore, *dstStore, stuffToCopy, NoRepair, checkSigs, substitute); + + updateProfile(rootPaths); + + if (outLink) { + if (auto store2 = dstStore.dynamic_pointer_cast()) + createOutLinks(*outLink, rootPaths, *store2); + else + throw Error("'--out-link' is not supported for this Nix store"); + } } }; diff --git a/src/nix/copy.md b/src/nix/copy.md index 6ab7cdee3e1..813050fcbab 100644 --- a/src/nix/copy.md +++ b/src/nix/copy.md @@ -55,6 +55,15 @@ R""( # nix copy --to /tmp/nix nixpkgs#hello --no-check-sigs ``` +* Update the NixOS system profile to point to a closure copied from a + remote machine: + + ```console + # nix copy --from ssh://server \ + --profile /nix/var/nix/profiles/system \ + /nix/store/r14v3km89zm3prwsa521fab5kgzvfbw4-nixos-system-foobar-24.05.20240925.759537f + ``` + # Description `nix copy` copies store path closures between two Nix stores. The diff --git a/src/nix/meson.build b/src/nix/meson.build index 60ee480358c..5c70c8216f7 100644 --- a/src/nix/meson.build +++ b/src/nix/meson.build @@ -32,8 +32,6 @@ deps_public_maybe_subproject = [ ] subdir('build-utils-meson/subprojects') -subdir('build-utils-meson/threads') - subdir('build-utils-meson/export-all-symbols') subdir('build-utils-meson/windows-version') @@ -65,7 +63,7 @@ add_project_arguments( language : 'cpp', ) -subdir('build-utils-meson/diagnostics') +subdir('build-utils-meson/common') subdir('build-utils-meson/generate-header') nix_sources = [config_h] + files( diff --git a/src/nix/realisation.cc b/src/nix/realisation.cc index e1f23122255..a386d98eac9 100644 --- a/src/nix/realisation.cc +++ b/src/nix/realisation.cc @@ -36,7 +36,7 @@ struct CmdRealisationInfo : BuiltPathsCommand, MixJSON Category category() override { return catSecondary; } - void run(ref store, BuiltPaths && paths) override + void run(ref store, BuiltPaths && paths, BuiltPaths && rootPaths) override { experimentalFeatureSettings.require(Xp::CaDerivations); RealisedPath::Set realisations; diff --git a/tests/functional/flakes/commit-lock-file-summary.sh b/tests/functional/flakes/commit-lock-file-summary.sh new file mode 100644 index 00000000000..314d43ec3b9 --- /dev/null +++ b/tests/functional/flakes/commit-lock-file-summary.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash + +source ./common.sh + +TODO_NixOS + +createFlake1 + +lockfileSummaryFlake=$TEST_ROOT/lockfileSummaryFlake +createGitRepo "$lockfileSummaryFlake" "--initial-branch=main" + +# Test that the --commit-lock-file-summary flag and its alias work +cat > "$lockfileSummaryFlake/flake.nix" < "$flake2Dir/flake.nix" < "$flakeDir/flake.nix" < "$flake2Dir/flake.nix" < "$nonFlakeDir/README.md" < "$nonFlakeDir/shebang.sh" < $nonFlakeDir/shebang-comments.sh < $nonFlakeDir/shebang-different-comments.sh < $nonFlakeDir/shebang-reject.sh < $nonFlakeDir/shebang-inline-expr.sh <> $nonFlakeDir/shebang-inline-expr.sh <<"EOF" -#! nix --offline shell -#! nix --impure --expr `` -#! nix let flake = (builtins.getFlake (toString ../flake1)).packages; -#! nix fooScript = flake.${builtins.currentSystem}.fooScript; -#! nix /* just a comment !@#$%^&*()__+ # */ -#! nix in fooScript -#! nix `` -#! nix --no-write-lock-file --command bash -set -ex -foo -echo "$@" -EOF -chmod +x $nonFlakeDir/shebang-inline-expr.sh - -cat > $nonFlakeDir/fooScript.nix <<"EOF" -let flake = (builtins.getFlake (toString ../flake1)).packages; - fooScript = flake.${builtins.currentSystem}.fooScript; - in fooScript -EOF - -cat > $nonFlakeDir/shebang-file.sh <> $nonFlakeDir/shebang-file.sh <<"EOF" -#! nix --offline shell -#! nix --impure --file ./fooScript.nix -#! nix --no-write-lock-file --command bash -set -ex -foo -echo "$@" -EOF -chmod +x $nonFlakeDir/shebang-file.sh - # Construct a custom registry, additionally test the --registry flag nix registry add --registry "$registry" flake1 "git+file://$flake1Dir" -nix registry add --registry "$registry" flake2 "git+file://$percentEncodedFlake2Dir" nix registry add --registry "$registry" flake3 "git+file://$percentEncodedFlake3Dir" -nix registry add --registry "$registry" flake4 flake3 nix registry add --registry "$registry" nixpkgs flake1 # Test 'nix registry list'. -[[ $(nix registry list | wc -l) == 5 ]] +[[ $(nix registry list | wc -l) == 4 ]] nix registry list | grep '^global' nix registry list | grepInverse '^user' # nothing in user registry @@ -347,77 +221,8 @@ _NIX_FORCE_HTTP=1 nix build -o "$TEST_ROOT/result" "git+file://$percentEncodedFl mv "$flake1Dir.tmp" "$flake1Dir" mv "$flake2Dir.tmp" "$flake2Dir" -# Add nonFlakeInputs to flake3. -rm "$flake3Dir/flake.nix" - -cat > "$flake3Dir/flake.nix" < \$out - [[ \$(cat \${inputs.nonFlake}/README.md) = \$(cat \${inputs.nonFlakeFile}) ]] - ''; - # [[ \${inputs.nonFlakeFile} = \${inputs.nonFlakeFile2} ]] - }; - }; -} -EOF - -cp "${config_nix}" "$flake3Dir" - -git -C "$flake3Dir" add flake.nix config.nix -git -C "$flake3Dir" commit -m 'Add nonFlakeInputs' - -# Check whether `nix build` works with a lockfile which is missing a -# nonFlakeInputs. -nix build -o "$TEST_ROOT/result" "$flake3Dir#sth" --commit-lock-file - -nix build -o "$TEST_ROOT/result" flake3#fnord -[[ $(cat $TEST_ROOT/result) = FNORD ]] - -# Check whether flake input fetching is lazy: flake3#sth does not -# depend on flake2, so this shouldn't fail. -rm -rf "$TEST_HOME/.cache" -clearStore -mv "$flake2Dir" "$flake2Dir.tmp" -mv "$nonFlakeDir" "$nonFlakeDir.tmp" -nix build -o "$TEST_ROOT/result" flake3#sth -(! nix build -o "$TEST_ROOT/result" flake3#xyzzy) -(! nix build -o "$TEST_ROOT/result" flake3#fnord) -mv "$flake2Dir.tmp" "$flake2Dir" -mv "$nonFlakeDir.tmp" "$nonFlakeDir" -nix build -o "$TEST_ROOT/result" flake3#xyzzy flake3#fnord - # Test doing multiple `lookupFlake`s -nix build -o "$TEST_ROOT/result" flake4#xyzzy +nix build -o "$TEST_ROOT/result" flake3#xyzzy # Test 'nix flake update' and --override-flake. nix flake lock "$flake3Dir" @@ -426,53 +231,15 @@ nix flake lock "$flake3Dir" nix flake update --flake "$flake3Dir" --override-flake flake2 nixpkgs [[ ! -z $(git -C "$flake3Dir" diff master || echo failed) ]] -# Make branch "removeXyzzy" where flake3 doesn't have xyzzy anymore -git -C "$flake3Dir" checkout -b removeXyzzy -rm "$flake3Dir/flake.nix" - -cat > "$flake3Dir/flake.nix" < \$out - ''; - }; - }; -} -EOF -nix flake lock "$flake3Dir" -git -C "$flake3Dir" add flake.nix flake.lock -git -C "$flake3Dir" commit -m 'Remove packages.xyzzy' -git -C "$flake3Dir" checkout master - -# Test whether fuzzy-matching works for registry entries. -(! nix build -o "$TEST_ROOT/result" flake4/removeXyzzy#xyzzy) -nix build -o "$TEST_ROOT/result" flake4/removeXyzzy#sth - # Testing the nix CLI nix registry add flake1 flake3 -[[ $(nix registry list | wc -l) == 6 ]] +[[ $(nix registry list | wc -l) == 5 ]] nix registry pin flake1 -[[ $(nix registry list | wc -l) == 6 ]] +[[ $(nix registry list | wc -l) == 5 ]] nix registry pin flake1 flake3 -[[ $(nix registry list | wc -l) == 6 ]] -nix registry remove flake1 [[ $(nix registry list | wc -l) == 5 ]] +nix registry remove flake1 +[[ $(nix registry list | wc -l) == 4 ]] # Test 'nix registry list' with a disabled global registry. nix registry add user-flake1 git+file://$flake1Dir @@ -482,7 +249,7 @@ nix --flake-registry "" registry list | grepQuietInverse '^global' # nothing in nix --flake-registry "" registry list | grepQuiet '^user' nix registry remove user-flake1 nix registry remove user-flake2 -[[ $(nix registry list | wc -l) == 5 ]] +[[ $(nix registry list | wc -l) == 4 ]] # Test 'nix flake clone'. rm -rf $TEST_ROOT/flake1-v2 @@ -644,46 +411,3 @@ nix flake metadata "$flake2Dir" --reference-lock-file $TEST_ROOT/flake2-overridd # reference-lock-file can only be used if allow-dirty is set. expectStderr 1 nix flake metadata "$flake2Dir" --no-allow-dirty --reference-lock-file $TEST_ROOT/flake2-overridden.lock - -# Test shebang -[[ $($nonFlakeDir/shebang.sh) = "foo" ]] -[[ $($nonFlakeDir/shebang.sh "bar") = "foo"$'\n'"bar" ]] -[[ $($nonFlakeDir/shebang-comments.sh ) = "foo" ]] -[[ "$($nonFlakeDir/shebang-different-comments.sh)" = "$(cat $nonFlakeDir/shebang-different-comments.sh)" ]] -[[ $($nonFlakeDir/shebang-inline-expr.sh baz) = "foo"$'\n'"baz" ]] -[[ $($nonFlakeDir/shebang-file.sh baz) = "foo"$'\n'"baz" ]] -expect 1 $nonFlakeDir/shebang-reject.sh 2>&1 | grepQuiet -F 'error: unsupported unquoted character in nix shebang: *. Use double backticks to escape?' - -# Test that the --commit-lock-file-summary flag and its alias work -cat > "$lockfileSummaryFlake/flake.nix" < "$nonFlakeDir/README.md" < "$flake3Dir/flake.nix" < \$out + [[ \$(cat \${inputs.nonFlake}/README.md) = \$(cat \${inputs.nonFlakeFile}) ]] + ''; + # [[ \${inputs.nonFlakeFile} = \${inputs.nonFlakeFile2} ]] + }; + }; +} +EOF + +cp "${config_nix}" "$flake3Dir" + +git -C "$flake3Dir" add flake.nix config.nix +git -C "$flake3Dir" commit -m 'Add nonFlakeInputs' + +# Check whether `nix build` works with a lockfile which is missing a +# nonFlakeInputs. +nix build -o "$TEST_ROOT/result" "$flake3Dir#sth" --commit-lock-file + +nix registry add --registry "$registry" flake3 "git+file://$flake3Dir" + +nix build -o "$TEST_ROOT/result" flake3#fnord +[[ $(cat "$TEST_ROOT/result") = FNORD ]] + +# Check whether flake input fetching is lazy: flake3#sth does not +# depend on flake2, so this shouldn't fail. +rm -rf "$TEST_HOME/.cache" +clearStore +mv "$flake2Dir" "$flake2Dir.tmp" +mv "$nonFlakeDir" "$nonFlakeDir.tmp" +nix build -o "$TEST_ROOT/result" flake3#sth +(! nix build -o "$TEST_ROOT/result" flake3#xyzzy) +(! nix build -o "$TEST_ROOT/result" flake3#fnord) +mv "$flake2Dir.tmp" "$flake2Dir" +mv "$nonFlakeDir.tmp" "$nonFlakeDir" +nix build -o "$TEST_ROOT/result" flake3#xyzzy flake3#fnord + +# Make branch "removeXyzzy" where flake3 doesn't have xyzzy anymore +git -C "$flake3Dir" checkout -b removeXyzzy +rm "$flake3Dir/flake.nix" + +cat > "$flake3Dir/flake.nix" < \$out + ''; + }; + }; +} +EOF +nix flake lock "$flake3Dir" +git -C "$flake3Dir" add flake.nix flake.lock +git -C "$flake3Dir" commit -m 'Remove packages.xyzzy' +git -C "$flake3Dir" checkout master + +# Test whether fuzzy-matching works for registry entries. +nix registry add --registry "$registry" flake4 flake3 +(! nix build -o "$TEST_ROOT/result" flake4/removeXyzzy#xyzzy) +nix build -o "$TEST_ROOT/result" flake4/removeXyzzy#sth diff --git a/tests/functional/flakes/shebang.sh b/tests/functional/flakes/shebang.sh new file mode 100644 index 00000000000..576a62e2cb4 --- /dev/null +++ b/tests/functional/flakes/shebang.sh @@ -0,0 +1,109 @@ +#!/usr/bin/env bash + +source ./common.sh + +TODO_NixOS + +createFlake1 + +scriptDir="$TEST_ROOT/nonFlake" +mkdir -p "$scriptDir" + +cat > "$scriptDir/shebang.sh" < "$scriptDir/shebang-comments.sh" < "$scriptDir/shebang-different-comments.sh" < "$scriptDir/shebang-reject.sh" < "$scriptDir/shebang-inline-expr.sh" <> "$scriptDir/shebang-inline-expr.sh" <<"EOF" +#! nix --offline shell +#! nix --impure --expr `` +#! nix let flake = (builtins.getFlake (toString ../flake1)).packages; +#! nix fooScript = flake.${builtins.currentSystem}.fooScript; +#! nix /* just a comment !@#$%^&*()__+ # */ +#! nix in fooScript +#! nix `` +#! nix --no-write-lock-file --command bash +set -ex +foo +echo "$@" +EOF +chmod +x "$scriptDir/shebang-inline-expr.sh" + +cat > "$scriptDir/fooScript.nix" <<"EOF" +let flake = (builtins.getFlake (toString ../flake1)).packages; + fooScript = flake.${builtins.currentSystem}.fooScript; + in fooScript +EOF + +cat > "$scriptDir/shebang-file.sh" <> "$scriptDir/shebang-file.sh" <<"EOF" +#! nix --offline shell +#! nix --impure --file ./fooScript.nix +#! nix --no-write-lock-file --command bash +set -ex +foo +echo "$@" +EOF +chmod +x "$scriptDir/shebang-file.sh" + +[[ $("$scriptDir/shebang.sh") = "foo" ]] +[[ $("$scriptDir/shebang.sh" "bar") = "foo"$'\n'"bar" ]] +[[ $("$scriptDir/shebang-comments.sh" ) = "foo" ]] +[[ "$("$scriptDir/shebang-different-comments.sh")" = "$(cat "$scriptDir/shebang-different-comments.sh")" ]] +[[ $("$scriptDir/shebang-inline-expr.sh" baz) = "foo"$'\n'"baz" ]] +[[ $("$scriptDir/shebang-file.sh" baz) = "foo"$'\n'"baz" ]] +expect 1 "$scriptDir/shebang-reject.sh" 2>&1 | grepQuiet -F 'error: unsupported unquoted character in nix shebang: *. Use double backticks to escape?' diff --git a/tests/functional/zstd.sh b/tests/functional/zstd.sh index 450fb7d3529..226d5eb6813 100755 --- a/tests/functional/zstd.sh +++ b/tests/functional/zstd.sh @@ -18,7 +18,10 @@ HASH=$(nix hash path "$outPath") clearStore clearCacheCache -nix copy --from "$cacheURI" "$outPath" --no-check-sigs +nix copy --from "$cacheURI" "$outPath" --no-check-sigs --profile "$TEST_ROOT/profile" --out-link "$TEST_ROOT/result" + +[[ -e $TEST_ROOT/profile ]] +[[ -e $TEST_ROOT/result ]] if ls "$cacheDir/nar/"*.zst &> /dev/null; then echo "files do exist"