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"