Compare commits
55 Commits
replace-lo
...
2.14-maint
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c27b9c8af9 | ||
|
|
9e19aca31b | ||
|
|
2dd715ef0b | ||
|
|
f092ae4478 | ||
|
|
cbabc40c30 | ||
|
|
2978cc2583 | ||
|
|
f37a5ed83c | ||
|
|
956096843e | ||
|
|
9ec640f2a7 | ||
|
|
d020050509 | ||
|
|
33b54fc1f7 | ||
|
|
21d5e846c1 | ||
|
|
efa096c3ab | ||
|
|
397de7bf24 | ||
|
|
0ffb20a81d | ||
|
|
d9bdbd2c47 | ||
|
|
a5fa42c5ed | ||
|
|
3065960f2a | ||
|
|
4504ee2957 | ||
|
|
15d1f8b89c | ||
|
|
9588d2e939 | ||
|
|
3b371e2924 | ||
|
|
8a2a2fbc63 | ||
|
|
bb53873253 | ||
|
|
f8cc1dc435 | ||
|
|
40627612ec | ||
|
|
74393024d6 | ||
|
|
bf38c5df51 | ||
|
|
e0aa691061 | ||
|
|
8a3f3d6a46 | ||
|
|
22860dddff | ||
|
|
52c7261898 | ||
|
|
f9b8193555 | ||
|
|
d2ee9fc61f | ||
|
|
a64ab82c30 | ||
|
|
d3e3001f5e | ||
|
|
1a7f2e0742 | ||
|
|
d30682eb37 | ||
|
|
cb76292148 | ||
|
|
3dfbf03407 | ||
|
|
2639911c8b | ||
|
|
cae8edb207 | ||
|
|
3913366f6d | ||
|
|
6527dc1614 | ||
|
|
0dd3be153a | ||
|
|
b9b4e2275c | ||
|
|
7f5e1c8e0a | ||
|
|
18c5e9e6db | ||
|
|
70d01bdec1 | ||
|
|
892b699ea6 | ||
|
|
ceee213591 | ||
|
|
f53b3c8c14 | ||
|
|
9ccd835fdf | ||
|
|
71a619642d | ||
|
|
4b156ad944 |
17
.github/workflows/ci.yml
vendored
17
.github/workflows/ci.yml
vendored
@@ -11,6 +11,7 @@ jobs:
|
||||
tests:
|
||||
needs: [check_secrets]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
@@ -19,7 +20,10 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: cachix/install-nix-action@v19
|
||||
- uses: cachix/install-nix-action@v22
|
||||
with:
|
||||
# The sandbox would otherwise be disabled by default on Darwin
|
||||
extra_nix_config: "sandbox = true"
|
||||
- run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV
|
||||
- uses: cachix/cachix-action@v12
|
||||
if: needs.check_secrets.outputs.cachix == 'true'
|
||||
@@ -58,7 +62,9 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV
|
||||
- uses: cachix/install-nix-action@v19
|
||||
- uses: cachix/install-nix-action@v22
|
||||
with:
|
||||
install_url: https://releases.nixos.org/nix/nix-2.13.3/install
|
||||
- uses: cachix/cachix-action@v12
|
||||
with:
|
||||
name: '${{ env.CACHIX_NAME }}'
|
||||
@@ -71,13 +77,14 @@ jobs:
|
||||
needs: [installer, check_secrets]
|
||||
if: github.event_name == 'push' && needs.check_secrets.outputs.cachix == 'true'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV
|
||||
- uses: cachix/install-nix-action@v19
|
||||
- uses: cachix/install-nix-action@v22
|
||||
with:
|
||||
install_url: '${{needs.installer.outputs.installerURL}}'
|
||||
install_options: "--tarball-url-prefix https://${{ env.CACHIX_NAME }}.cachix.org/serve"
|
||||
@@ -102,7 +109,9 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: cachix/install-nix-action@v19
|
||||
- uses: cachix/install-nix-action@v22
|
||||
with:
|
||||
install_url: https://releases.nixos.org/nix/nix-2.13.3/install
|
||||
- run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV
|
||||
- run: echo NIX_VERSION="$(nix --experimental-features 'nix-command flakes' eval .\#default.version | tr -d \")" >> $GITHUB_ENV
|
||||
- uses: cachix/cachix-action@v12
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
diff --git a/darwin_stop_world.c b/darwin_stop_world.c
|
||||
index 3dbaa3fb..36a1d1f7 100644
|
||||
index 0468aaec..b348d869 100644
|
||||
--- a/darwin_stop_world.c
|
||||
+++ b/darwin_stop_world.c
|
||||
@@ -352,6 +352,7 @@ GC_INNER void GC_push_all_stacks(void)
|
||||
@@ -356,6 +356,7 @@ GC_INNER void GC_push_all_stacks(void)
|
||||
int nthreads = 0;
|
||||
word total_size = 0;
|
||||
mach_msg_type_number_t listcount = (mach_msg_type_number_t)THREAD_TABLE_SZ;
|
||||
@@ -10,7 +10,7 @@ index 3dbaa3fb..36a1d1f7 100644
|
||||
if (!EXPECT(GC_thr_initialized, TRUE))
|
||||
GC_thr_init();
|
||||
|
||||
@@ -407,6 +408,19 @@ GC_INNER void GC_push_all_stacks(void)
|
||||
@@ -411,6 +412,19 @@ GC_INNER void GC_push_all_stacks(void)
|
||||
GC_push_all_stack_sections(lo, hi, p->traced_stack_sect);
|
||||
}
|
||||
if (altstack_lo) {
|
||||
@@ -30,6 +30,22 @@ index 3dbaa3fb..36a1d1f7 100644
|
||||
total_size += altstack_hi - altstack_lo;
|
||||
GC_push_all_stack(altstack_lo, altstack_hi);
|
||||
}
|
||||
diff --git a/include/gc.h b/include/gc.h
|
||||
index edab6c22..f2c61282 100644
|
||||
--- a/include/gc.h
|
||||
+++ b/include/gc.h
|
||||
@@ -2172,6 +2172,11 @@ GC_API void GC_CALL GC_win32_free_heap(void);
|
||||
(*GC_amiga_allocwrapper_do)(a,GC_malloc_atomic_ignore_off_page)
|
||||
#endif /* _AMIGA && !GC_AMIGA_MAKINGLIB */
|
||||
|
||||
+#if !__APPLE__
|
||||
+/* Patch doesn't work on apple */
|
||||
+#define NIX_BOEHM_PATCH_VERSION 1
|
||||
+#endif
|
||||
+
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
diff --git a/pthread_stop_world.c b/pthread_stop_world.c
|
||||
index b5d71e62..aed7b0bf 100644
|
||||
--- a/pthread_stop_world.c
|
||||
|
||||
@@ -1,3 +1,25 @@
|
||||
:root {
|
||||
--sidebar-width: 23em;
|
||||
}
|
||||
|
||||
h1.menu-title::before {
|
||||
content: "";
|
||||
background-image: url("./favicon.svg");
|
||||
padding: 1.25em;
|
||||
background-position: center center;
|
||||
background-size: 2em;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
|
||||
h1.menu-title {
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.sidebar .sidebar-scrollbox {
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
h1:not(:first-of-type) {
|
||||
margin-top: 1.3em;
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ doc/manual/generated/man1/nix3-manpages: $(d)/src/command-ref/new-cli
|
||||
done
|
||||
@touch $@
|
||||
|
||||
$(docdir)/manual/index.html: $(MANUAL_SRCS) $(d)/book.toml $(d)/anchors.jq $(d)/custom.css $(d)/src/SUMMARY.md $(d)/src/command-ref/new-cli $(d)/src/command-ref/conf-file.md $(d)/src/language/builtins.md
|
||||
$(docdir)/manual/index.html: $(MANUAL_SRCS) $(d)/book.toml $(d)/anchors.jq $(d)/custom.css $(d)/src/SUMMARY.md $(d)/src/command-ref/new-cli $(d)/src/command-ref/conf-file.md $(d)/src/language/builtins.md $(d)/src/favicon.png $(d)/src/favicon.svg
|
||||
$(trace-gen) \
|
||||
set -euo pipefail; \
|
||||
RUST_LOG=warn mdbook build doc/manual -d $(DESTDIR)$(docdir)/manual.tmp 2>&1 \
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
// redirect rules for anchors ensure backwards compatibility of URLs.
|
||||
// this must be done on the client side, as web servers do not see the anchor part of the URL.
|
||||
// redirect rules for URL fragments (client-side) to prevent link rot.
|
||||
// this must be done on the client side, as web servers do not see the fragment part of the URL.
|
||||
// it will only work with JavaScript enabled in the browser, but this is the best we can do here.
|
||||
// see ./_redirects for path redirects (client-side)
|
||||
|
||||
// redirections are declared as follows:
|
||||
// redirects are declared as follows:
|
||||
// each entry has as its key a path matching the requested URL path, relative to the mdBook document root.
|
||||
//
|
||||
// IMPORTANT: it must specify the full path with file name and suffix
|
||||
@@ -19,6 +21,7 @@ const redirects = {
|
||||
"chap-distributed-builds": "advanced-topics/distributed-builds.html",
|
||||
"chap-post-build-hook": "advanced-topics/post-build-hook.html",
|
||||
"chap-post-build-hook-caveats": "advanced-topics/post-build-hook.html#implementation-caveats",
|
||||
"chap-writing-nix-expressions": "language/index.html",
|
||||
"part-command-ref": "command-ref/command-ref.html",
|
||||
"conf-allow-import-from-derivation": "command-ref/conf-file.html#conf-allow-import-from-derivation",
|
||||
"conf-allow-new-privileges": "command-ref/conf-file.html#conf-allow-new-privileges",
|
||||
|
||||
@@ -66,7 +66,6 @@
|
||||
- [Hacking](contributing/hacking.md)
|
||||
- [CLI guideline](contributing/cli-guideline.md)
|
||||
- [Release Notes](release-notes/release-notes.md)
|
||||
- [Release X.Y (202?-??-??)](release-notes/rl-next.md)
|
||||
- [Release 2.14 (2023-02-28)](release-notes/rl-2.14.md)
|
||||
- [Release 2.13 (2023-01-17)](release-notes/rl-2.13.md)
|
||||
- [Release 2.12 (2022-12-06)](release-notes/rl-2.12.md)
|
||||
|
||||
30
doc/manual/src/_redirects
Normal file
30
doc/manual/src/_redirects
Normal file
@@ -0,0 +1,30 @@
|
||||
# redirect rules for paths (server-side) to prevent link rot.
|
||||
# see ./redirects.js for redirects based on URL fragments (client-side)
|
||||
#
|
||||
# concrete user story this supports:
|
||||
# - user finds URL to the manual for Nix x.y
|
||||
# - Nix x.z (z > y) is the most recent release
|
||||
# - updating the version in the URL will show the right thing
|
||||
#
|
||||
# format documentation:
|
||||
# - https://docs.netlify.com/routing/redirects/#syntax-for-the-redirects-file
|
||||
# - https://docs.netlify.com/routing/redirects/redirect-options/
|
||||
#
|
||||
# conventions:
|
||||
# - always force (<CODE>!) since this allows re-using file names
|
||||
# - group related paths to ease readability
|
||||
# - always append new redirects to the end of the file
|
||||
# - redirects that should have been there but are missing can be inserted where they belong
|
||||
|
||||
/expressions/expression-language /language/ 301!
|
||||
/expressions/language-values /language/values 301!
|
||||
/expressions/language-constructs /language/constructs 301!
|
||||
/expressions/language-operators /language/operators 301!
|
||||
/expressions/* /language/:splat 301!
|
||||
|
||||
/package-management/basic-package-mgmt /command-ref/nix-env 301!
|
||||
|
||||
/package-management/channels* /command-ref/nix-channel 301!
|
||||
|
||||
/package-management/s3-substituter* /command-ref/new-cli/nix3-help-stores#s3-binary-cache-store 301!
|
||||
|
||||
@@ -70,7 +70,7 @@ $ nix-instantiate --eval -E '(import <nixpkgs> {}).lib.version'
|
||||
|
||||
# Files
|
||||
|
||||
- `/nix/var/nix/profiles/per-user/username/channels`\
|
||||
- `${XDG_STATE_HOME-$HOME/.local/state}/nix/profiles/channels`\
|
||||
`nix-channel` uses a `nix-env` profile to keep track of previous
|
||||
versions of the subscribed channels. Every time you run `nix-channel
|
||||
--update`, a new channel generation (that is, a symlink to the
|
||||
@@ -79,7 +79,7 @@ $ nix-instantiate --eval -E '(import <nixpkgs> {}).lib.version'
|
||||
|
||||
- `~/.nix-defexpr/channels`\
|
||||
This is a symlink to
|
||||
`/nix/var/nix/profiles/per-user/username/channels`. It ensures that
|
||||
`${XDG_STATE_HOME-$HOME/.local/state}/nix/profiles/channels`. It ensures that
|
||||
`nix-env` can find your channels. In a multi-user installation, you
|
||||
may also have `~/.nix-defexpr/channels_root`, which links to the
|
||||
channels of the root user.
|
||||
|
||||
@@ -488,7 +488,7 @@ depends on `svn`:
|
||||
$ nix-store -q --roots $(which svn)
|
||||
/nix/var/nix/profiles/default-81-link
|
||||
/nix/var/nix/profiles/default-82-link
|
||||
/nix/var/nix/profiles/per-user/eelco/profile-97-link
|
||||
/home/eelco/.local/state/nix/profiles/profile-97-link
|
||||
```
|
||||
|
||||
# Operation `--add`
|
||||
|
||||
BIN
doc/manual/src/favicon.png
Normal file
BIN
doc/manual/src/favicon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
1
doc/manual/src/favicon.svg
Normal file
1
doc/manual/src/favicon.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="587.11" height="516.604" viewBox="0 0 550.416 484.317"><defs><linearGradient id="a"><stop offset="0" style="stop-color:#699ad7;stop-opacity:1"/><stop offset=".243" style="stop-color:#7eb1dd;stop-opacity:1"/><stop offset="1" style="stop-color:#7ebae4;stop-opacity:1"/></linearGradient><linearGradient id="b"><stop offset="0" style="stop-color:#415e9a;stop-opacity:1"/><stop offset=".232" style="stop-color:#4a6baf;stop-opacity:1"/><stop offset="1" style="stop-color:#5277c3;stop-opacity:1"/></linearGradient><linearGradient xlink:href="#a" id="c" x1="200.597" x2="290.087" y1="351.411" y2="506.188" gradientTransform="translate(70.65 -1055.151)" gradientUnits="userSpaceOnUse"/><linearGradient xlink:href="#b" id="e" x1="-584.199" x2="-496.297" y1="782.336" y2="937.714" gradientTransform="translate(864.696 -1491.34)" gradientUnits="userSpaceOnUse"/></defs><g style="display:inline;opacity:1" transform="translate(-132.651 958.04)"><path id="d" d="m309.549-710.388 122.197 211.675-56.157.527-32.624-56.87-32.856 56.566-27.903-.011-14.29-24.69 46.81-80.49-33.23-57.826z" style="opacity:1;fill:url(#c);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><use xlink:href="#d" width="100%" height="100%" transform="rotate(60 407.112 -715.787)"/><use xlink:href="#d" width="100%" height="100%" transform="rotate(-60 407.312 -715.7)"/><use xlink:href="#d" width="100%" height="100%" transform="rotate(180 407.419 -715.756)"/><path id="f" d="m309.549-710.388 122.197 211.675-56.157.527-32.624-56.87-32.856 56.566-27.903-.011-14.29-24.69 46.81-80.49-33.23-57.826z" style="color:#000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000;solid-opacity:1;fill:url(#e);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"/><use xlink:href="#f" width="100%" height="100%" style="display:inline" transform="rotate(120 407.34 -716.084)"/><use xlink:href="#f" width="100%" height="100%" style="display:inline" transform="rotate(-120 407.288 -715.87)"/></g></svg>
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
@@ -10,7 +10,7 @@
|
||||
let
|
||||
inherit (nixpkgs) lib;
|
||||
|
||||
officialRelease = false;
|
||||
officialRelease = true;
|
||||
|
||||
version = lib.fileContents ./.version + versionSuffix;
|
||||
versionSuffix =
|
||||
@@ -361,6 +361,10 @@
|
||||
postInstall = ''
|
||||
mkdir -p $doc/nix-support
|
||||
echo "doc manual $doc/share/doc/nix/manual" >> $doc/nix-support/hydra-build-products
|
||||
${lib.optionalString currentStdenv.hostPlatform.isStatic ''
|
||||
mkdir -p $out/nix-support
|
||||
echo "file binary-dist $out/bin/nix" >> $out/nix-support/hydra-build-products
|
||||
''}
|
||||
${lib.optionalString currentStdenv.isDarwin ''
|
||||
install_name_tool \
|
||||
-change ${boost}/lib/libboost_context.dylib \
|
||||
@@ -371,6 +375,7 @@
|
||||
|
||||
doInstallCheck = true;
|
||||
installCheckFlags = "sysconfdir=$(out)/etc";
|
||||
installCheckTarget = "installcheck"; # work around buggy detection in stdenv
|
||||
|
||||
separateDebugInfo = !currentStdenv.hostPlatform.isStatic;
|
||||
|
||||
|
||||
@@ -3,12 +3,12 @@ if [ -n "${__ETC_PROFILE_NIX_SOURCED:-}" ]; then return; fi
|
||||
__ETC_PROFILE_NIX_SOURCED=1
|
||||
|
||||
NIX_LINK=$HOME/.nix-profile
|
||||
if [ -n "$XDG_STATE_HOME" ]; then
|
||||
if [ -n "${XDG_STATE_HOME-}" ]; then
|
||||
NIX_LINK_NEW="$XDG_STATE_HOME/nix/profile"
|
||||
else
|
||||
NIX_LINK_NEW=$HOME/.local/state/nix/profile
|
||||
fi
|
||||
if ! [ -e "$NIX_LINK" ]; then
|
||||
if [ -e "$NIX_LINK_NEW" ]; then
|
||||
NIX_LINK="$NIX_LINK_NEW"
|
||||
else
|
||||
if [ -t 2 ] && [ -e "$NIX_LINK_NEW" ]; then
|
||||
|
||||
@@ -3,12 +3,12 @@ if [ -n "$HOME" ] && [ -n "$USER" ]; then
|
||||
# Set up the per-user profile.
|
||||
|
||||
NIX_LINK="$HOME/.nix-profile"
|
||||
if [ -n "$XDG_STATE_HOME" ]; then
|
||||
if [ -n "${XDG_STATE_HOME-}" ]; then
|
||||
NIX_LINK_NEW="$XDG_STATE_HOME/nix/profile"
|
||||
else
|
||||
NIX_LINK_NEW="$HOME/.local/state/nix/profile"
|
||||
fi
|
||||
if ! [ -e "$NIX_LINK" ]; then
|
||||
if [ -e "$NIX_LINK_NEW" ]; then
|
||||
NIX_LINK="$NIX_LINK_NEW"
|
||||
else
|
||||
if [ -t 2 ] && [ -e "$NIX_LINK_NEW" ]; then
|
||||
|
||||
@@ -178,8 +178,7 @@ std::pair<Value *, PosIdx> InstallableFlake::toValue(EvalState & state)
|
||||
std::vector<ref<eval_cache::AttrCursor>>
|
||||
InstallableFlake::getCursors(EvalState & state)
|
||||
{
|
||||
auto evalCache = openEvalCache(state,
|
||||
std::make_shared<flake::LockedFlake>(lockFlake(state, flakeRef, lockFlags)));
|
||||
auto evalCache = openEvalCache(state, getLockedFlake());
|
||||
|
||||
auto root = evalCache->getRoot();
|
||||
|
||||
|
||||
@@ -325,6 +325,22 @@ static Symbol getName(const AttrName & name, EvalState & state, Env & env)
|
||||
}
|
||||
}
|
||||
|
||||
#if HAVE_BOEHMGC
|
||||
/* Disable GC while this object lives. Used by CoroutineContext.
|
||||
*
|
||||
* Boehm keeps a count of GC_disable() and GC_enable() calls,
|
||||
* and only enables GC when the count matches.
|
||||
*/
|
||||
class BoehmDisableGC {
|
||||
public:
|
||||
BoehmDisableGC() {
|
||||
GC_disable();
|
||||
};
|
||||
~BoehmDisableGC() {
|
||||
GC_enable();
|
||||
};
|
||||
};
|
||||
#endif
|
||||
|
||||
static bool gcInitialised = false;
|
||||
|
||||
@@ -349,6 +365,15 @@ void initGC()
|
||||
|
||||
StackAllocator::defaultAllocator = &boehmGCStackAllocator;
|
||||
|
||||
|
||||
#if NIX_BOEHM_PATCH_VERSION != 1
|
||||
printTalkative("Unpatched BoehmGC, disabling GC inside coroutines");
|
||||
/* Used to disable GC when entering coroutines on macOS */
|
||||
create_coro_gc_hook = []() -> std::shared_ptr<void> {
|
||||
return std::make_shared<BoehmDisableGC>();
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Set the initial heap size to something fairly big (25% of
|
||||
physical RAM, up to a maximum of 384 MiB) so that in most cases
|
||||
we don't need to garbage collect at all. (Collection has a
|
||||
|
||||
@@ -89,7 +89,7 @@ LockFile::LockFile(const nlohmann::json & json, const Path & path)
|
||||
std::string inputKey = i.value();
|
||||
auto k = nodeMap.find(inputKey);
|
||||
if (k == nodeMap.end()) {
|
||||
auto nodes = json["nodes"];
|
||||
auto & nodes = json["nodes"];
|
||||
auto jsonNode2 = nodes.find(inputKey);
|
||||
if (jsonNode2 == nodes.end())
|
||||
throw Error("lock file references missing node '%s'", inputKey);
|
||||
|
||||
@@ -473,10 +473,10 @@ static RegisterPrimOp primop_fetchGit({
|
||||
builtins.fetchGit ./work-dir
|
||||
```
|
||||
|
||||
If the URL points to a local directory, and no `ref` or `rev` is
|
||||
given, `fetchGit` will use the current content of the checked-out
|
||||
files, even if they are not committed or added to Git's index. It will
|
||||
only consider files added to the Git repository, as listed by `git ls-files`.
|
||||
If the URL points to a local directory, and no `ref` or `rev` is
|
||||
given, `fetchGit` will use the current content of the checked-out
|
||||
files, even if they are not committed or added to Git's index. It will
|
||||
only consider files added to the Git repository, as listed by `git ls-files`.
|
||||
)",
|
||||
.fun = prim_fetchGit,
|
||||
});
|
||||
|
||||
@@ -16,4 +16,4 @@ libexpr-tests_CXXFLAGS += -I src/libexpr -I src/libutil -I src/libstore -I src/l
|
||||
|
||||
libexpr-tests_LIBS = libstore-tests libutils-tests libexpr libutil libstore libfetchers
|
||||
|
||||
libexpr-tests_LDFLAGS := $(GTEST_LIBS) -lgmock
|
||||
libexpr-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) -lgmock
|
||||
|
||||
@@ -61,20 +61,25 @@ void DrvOutputSubstitutionGoal::tryNext()
|
||||
|
||||
// FIXME: Make async
|
||||
// outputInfo = sub->queryRealisation(id);
|
||||
outPipe.create();
|
||||
promise = decltype(promise)();
|
||||
|
||||
/* The callback of the curl download below can outlive `this` (if
|
||||
some other error occurs), so it must not touch `this`. So put
|
||||
the shared state in a separate refcounted object. */
|
||||
downloadState = std::make_shared<DownloadState>();
|
||||
downloadState->outPipe.create();
|
||||
|
||||
sub->queryRealisation(
|
||||
id, { [&](std::future<std::shared_ptr<const Realisation>> res) {
|
||||
id,
|
||||
{ [downloadState(downloadState)](std::future<std::shared_ptr<const Realisation>> res) {
|
||||
try {
|
||||
Finally updateStats([this]() { outPipe.writeSide.close(); });
|
||||
promise.set_value(res.get());
|
||||
Finally updateStats([&]() { downloadState->outPipe.writeSide.close(); });
|
||||
downloadState->promise.set_value(res.get());
|
||||
} catch (...) {
|
||||
promise.set_exception(std::current_exception());
|
||||
downloadState->promise.set_exception(std::current_exception());
|
||||
}
|
||||
} });
|
||||
|
||||
worker.childStarted(shared_from_this(), {outPipe.readSide.get()}, true, false);
|
||||
worker.childStarted(shared_from_this(), {downloadState->outPipe.readSide.get()}, true, false);
|
||||
|
||||
state = &DrvOutputSubstitutionGoal::realisationFetched;
|
||||
}
|
||||
@@ -84,7 +89,7 @@ void DrvOutputSubstitutionGoal::realisationFetched()
|
||||
worker.childTerminated(this);
|
||||
|
||||
try {
|
||||
outputInfo = promise.get_future().get();
|
||||
outputInfo = downloadState->promise.get_future().get();
|
||||
} catch (std::exception & e) {
|
||||
printError(e.what());
|
||||
substituterFailed = true;
|
||||
@@ -155,7 +160,7 @@ void DrvOutputSubstitutionGoal::work()
|
||||
|
||||
void DrvOutputSubstitutionGoal::handleEOF(int fd)
|
||||
{
|
||||
if (fd == outPipe.readSide.get()) worker.wakeUp(shared_from_this());
|
||||
if (fd == downloadState->outPipe.readSide.get()) worker.wakeUp(shared_from_this());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ class Worker;
|
||||
// 2. Substitute the corresponding output path
|
||||
// 3. Register the output info
|
||||
class DrvOutputSubstitutionGoal : public Goal {
|
||||
private:
|
||||
|
||||
// The drv output we're trying to substitue
|
||||
DrvOutput id;
|
||||
|
||||
@@ -30,9 +30,13 @@ private:
|
||||
/* The current substituter. */
|
||||
std::shared_ptr<Store> sub;
|
||||
|
||||
Pipe outPipe;
|
||||
std::thread thr;
|
||||
std::promise<std::shared_ptr<const Realisation>> promise;
|
||||
struct DownloadState
|
||||
{
|
||||
Pipe outPipe;
|
||||
std::promise<std::shared_ptr<const Realisation>> promise;
|
||||
};
|
||||
|
||||
std::shared_ptr<DownloadState> downloadState;
|
||||
|
||||
/* Whether a substituter failed. */
|
||||
bool substituterFailed = false;
|
||||
|
||||
@@ -1155,10 +1155,10 @@ void LocalDerivationGoal::writeStructuredAttrs()
|
||||
|
||||
writeFile(tmpDir + "/.attrs.sh", rewriteStrings(jsonSh, inputRewrites));
|
||||
chownToBuilder(tmpDir + "/.attrs.sh");
|
||||
env["NIX_ATTRS_SH_FILE"] = tmpDir + "/.attrs.sh";
|
||||
env["NIX_ATTRS_SH_FILE"] = tmpDirInSandbox + "/.attrs.sh";
|
||||
writeFile(tmpDir + "/.attrs.json", rewriteStrings(json.dump(), inputRewrites));
|
||||
chownToBuilder(tmpDir + "/.attrs.json");
|
||||
env["NIX_ATTRS_JSON_FILE"] = tmpDir + "/.attrs.json";
|
||||
env["NIX_ATTRS_JSON_FILE"] = tmpDirInSandbox + "/.attrs.json";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
|
||||
namespace nix {
|
||||
|
||||
static constexpr std::string_view nameRegexStr = R"([0-9a-zA-Z\+\-\._\?=]+)";
|
||||
static constexpr std::string_view nameRegexStr = R"([0-9a-zA-Z\+\-_\?=][0-9a-zA-Z\+\-\._\?=]*)";
|
||||
|
||||
}
|
||||
|
||||
@@ -9,8 +9,10 @@ static void checkName(std::string_view path, std::string_view name)
|
||||
if (name.empty())
|
||||
throw BadStorePath("store path '%s' has an empty name", path);
|
||||
if (name.size() > StorePath::MaxPathLen)
|
||||
throw BadStorePath("store path '%s' has a name longer than '%d characters",
|
||||
StorePath::MaxPathLen, path);
|
||||
throw BadStorePath("store path '%s' has a name longer than %d characters",
|
||||
path, StorePath::MaxPathLen);
|
||||
if (name[0] == '.')
|
||||
throw BadStorePath("store path '%s' starts with illegal character '.'", path);
|
||||
// See nameRegexStr for the definition
|
||||
for (auto c : name)
|
||||
if (!((c >= '0' && c <= '9')
|
||||
|
||||
@@ -39,6 +39,7 @@ TEST_DONT_PARSE(double_star, "**")
|
||||
TEST_DONT_PARSE(star_first, "*,foo")
|
||||
TEST_DONT_PARSE(star_second, "foo,*")
|
||||
TEST_DONT_PARSE(bang, "foo!o")
|
||||
TEST_DONT_PARSE(dotfile, ".gitignore")
|
||||
|
||||
#undef TEST_DONT_PARSE
|
||||
|
||||
@@ -101,8 +102,12 @@ Gen<StorePathName> Arbitrary<StorePathName>::arbitrary()
|
||||
pre += '-';
|
||||
break;
|
||||
case 64:
|
||||
pre += '.';
|
||||
break;
|
||||
// names aren't permitted to start with a period,
|
||||
// so just fall through to the next case here
|
||||
if (c != 0) {
|
||||
pre += '.';
|
||||
break;
|
||||
}
|
||||
case 65:
|
||||
pre += '_';
|
||||
break;
|
||||
|
||||
@@ -186,6 +186,22 @@ static DefaultStackAllocator defaultAllocatorSingleton;
|
||||
StackAllocator *StackAllocator::defaultAllocator = &defaultAllocatorSingleton;
|
||||
|
||||
|
||||
std::shared_ptr<void> (*create_coro_gc_hook)() = []() -> std::shared_ptr<void> {
|
||||
return {};
|
||||
};
|
||||
|
||||
/* This class is used for entry and exit hooks on coroutines */
|
||||
class CoroutineContext {
|
||||
/* Disable GC when entering the coroutine without the boehm patch,
|
||||
* since it doesn't find the main thread stack in this case.
|
||||
* std::shared_ptr<void> performs type-erasure, so it will call the right
|
||||
* deleter. */
|
||||
const std::shared_ptr<void> coro_gc_hook = create_coro_gc_hook();
|
||||
public:
|
||||
CoroutineContext() {};
|
||||
~CoroutineContext() {};
|
||||
};
|
||||
|
||||
std::unique_ptr<FinishSink> sourceToSink(std::function<void(Source &)> fun)
|
||||
{
|
||||
struct SourceToSink : FinishSink
|
||||
@@ -206,7 +222,8 @@ std::unique_ptr<FinishSink> sourceToSink(std::function<void(Source &)> fun)
|
||||
if (in.empty()) return;
|
||||
cur = in;
|
||||
|
||||
if (!coro)
|
||||
if (!coro) {
|
||||
CoroutineContext ctx;
|
||||
coro = coro_t::push_type(VirtualStackAllocator{}, [&](coro_t::pull_type & yield) {
|
||||
LambdaSource source([&](char *out, size_t out_len) {
|
||||
if (cur.empty()) {
|
||||
@@ -223,17 +240,24 @@ std::unique_ptr<FinishSink> sourceToSink(std::function<void(Source &)> fun)
|
||||
});
|
||||
fun(source);
|
||||
});
|
||||
}
|
||||
|
||||
if (!*coro) { abort(); }
|
||||
|
||||
if (!cur.empty()) (*coro)(false);
|
||||
if (!cur.empty()) {
|
||||
CoroutineContext ctx;
|
||||
(*coro)(false);
|
||||
}
|
||||
}
|
||||
|
||||
void finish() override
|
||||
{
|
||||
if (!coro) return;
|
||||
if (!*coro) abort();
|
||||
(*coro)(true);
|
||||
{
|
||||
CoroutineContext ctx;
|
||||
(*coro)(true);
|
||||
}
|
||||
if (*coro) abort();
|
||||
}
|
||||
};
|
||||
@@ -264,18 +288,23 @@ std::unique_ptr<Source> sinkToSource(
|
||||
|
||||
size_t read(char * data, size_t len) override
|
||||
{
|
||||
if (!coro)
|
||||
if (!coro) {
|
||||
CoroutineContext ctx;
|
||||
coro = coro_t::pull_type(VirtualStackAllocator{}, [&](coro_t::push_type & yield) {
|
||||
LambdaSink sink([&](std::string_view data) {
|
||||
if (!data.empty()) yield(std::string(data));
|
||||
});
|
||||
fun(sink);
|
||||
});
|
||||
}
|
||||
|
||||
if (!*coro) { eof(); abort(); }
|
||||
|
||||
if (pos == cur.size()) {
|
||||
if (!cur.empty()) (*coro)();
|
||||
if (!cur.empty()) {
|
||||
CoroutineContext ctx;
|
||||
(*coro)();
|
||||
}
|
||||
cur = coro->get();
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
@@ -501,4 +501,10 @@ struct StackAllocator {
|
||||
static StackAllocator *defaultAllocator;
|
||||
};
|
||||
|
||||
/* Disabling GC when entering a coroutine (without the boehm patch).
|
||||
mutable to avoid boehm gc dependency in libutil.
|
||||
*/
|
||||
extern std::shared_ptr<void> (*create_coro_gc_hook)();
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -202,7 +202,7 @@ namespace nix {
|
||||
}
|
||||
|
||||
TEST(pathExists, bogusPathDoesNotExist) {
|
||||
ASSERT_FALSE(pathExists("/home/schnitzel/darmstadt/pommes"));
|
||||
ASSERT_FALSE(pathExists("/schnitzel/darmstadt/pommes"));
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
|
||||
@@ -1782,6 +1782,7 @@ void setStackSize(size_t stackSize)
|
||||
|
||||
#if __linux__
|
||||
static AutoCloseFD fdSavedMountNamespace;
|
||||
static AutoCloseFD fdSavedRoot;
|
||||
#endif
|
||||
|
||||
void saveMountNamespace()
|
||||
@@ -1789,10 +1790,11 @@ void saveMountNamespace()
|
||||
#if __linux__
|
||||
static std::once_flag done;
|
||||
std::call_once(done, []() {
|
||||
AutoCloseFD fd = open("/proc/self/ns/mnt", O_RDONLY);
|
||||
if (!fd)
|
||||
fdSavedMountNamespace = open("/proc/self/ns/mnt", O_RDONLY);
|
||||
if (!fdSavedMountNamespace)
|
||||
throw SysError("saving parent mount namespace");
|
||||
fdSavedMountNamespace = std::move(fd);
|
||||
|
||||
fdSavedRoot = open("/proc/self/root", O_RDONLY);
|
||||
});
|
||||
#endif
|
||||
}
|
||||
@@ -1805,9 +1807,16 @@ void restoreMountNamespace()
|
||||
|
||||
if (fdSavedMountNamespace && setns(fdSavedMountNamespace.get(), CLONE_NEWNS) == -1)
|
||||
throw SysError("restoring parent mount namespace");
|
||||
if (chdir(savedCwd.c_str()) == -1) {
|
||||
throw SysError("restoring cwd");
|
||||
|
||||
if (fdSavedRoot) {
|
||||
if (fchdir(fdSavedRoot.get()))
|
||||
throw SysError("chdir into saved root");
|
||||
if (chroot("."))
|
||||
throw SysError("chroot into saved root");
|
||||
}
|
||||
|
||||
if (chdir(savedCwd.c_str()) == -1)
|
||||
throw SysError("restoring cwd");
|
||||
} catch (Error & e) {
|
||||
debug(e.msg());
|
||||
}
|
||||
|
||||
@@ -77,8 +77,7 @@ static int main_nix_collect_garbage(int argc, char * * argv)
|
||||
return true;
|
||||
});
|
||||
|
||||
auto profilesDir = settings.nixStateDir + "/profiles";
|
||||
if (removeOld) removeOldGenerations(profilesDir);
|
||||
if (removeOld) removeOldGenerations(profilesDir());
|
||||
|
||||
// Run the actual garbage collector.
|
||||
if (!dryRun) {
|
||||
|
||||
@@ -1026,36 +1026,43 @@ struct CmdFlakeShow : FlakeCommand, MixJSON
|
||||
|
||||
auto visitor2 = visitor.getAttr(attrName);
|
||||
|
||||
if ((attrPathS[0] == "apps"
|
||||
|| attrPathS[0] == "checks"
|
||||
|| attrPathS[0] == "devShells"
|
||||
|| attrPathS[0] == "legacyPackages"
|
||||
|| attrPathS[0] == "packages")
|
||||
&& (attrPathS.size() == 1 || attrPathS.size() == 2)) {
|
||||
for (const auto &subAttr : visitor2->getAttrs()) {
|
||||
if (hasContent(*visitor2, attrPath2, subAttr)) {
|
||||
return true;
|
||||
try {
|
||||
if ((attrPathS[0] == "apps"
|
||||
|| attrPathS[0] == "checks"
|
||||
|| attrPathS[0] == "devShells"
|
||||
|| attrPathS[0] == "legacyPackages"
|
||||
|| attrPathS[0] == "packages")
|
||||
&& (attrPathS.size() == 1 || attrPathS.size() == 2)) {
|
||||
for (const auto &subAttr : visitor2->getAttrs()) {
|
||||
if (hasContent(*visitor2, attrPath2, subAttr)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((attrPathS.size() == 1)
|
||||
&& (attrPathS[0] == "formatter"
|
||||
|| attrPathS[0] == "nixosConfigurations"
|
||||
|| attrPathS[0] == "nixosModules"
|
||||
|| attrPathS[0] == "overlays"
|
||||
)) {
|
||||
for (const auto &subAttr : visitor2->getAttrs()) {
|
||||
if (hasContent(*visitor2, attrPath2, subAttr)) {
|
||||
return true;
|
||||
if ((attrPathS.size() == 1)
|
||||
&& (attrPathS[0] == "formatter"
|
||||
|| attrPathS[0] == "nixosConfigurations"
|
||||
|| attrPathS[0] == "nixosModules"
|
||||
|| attrPathS[0] == "overlays"
|
||||
)) {
|
||||
for (const auto &subAttr : visitor2->getAttrs()) {
|
||||
if (hasContent(*visitor2, attrPath2, subAttr)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we don't recognize it, it's probably content
|
||||
return true;
|
||||
// If we don't recognize it, it's probably content
|
||||
return true;
|
||||
} catch (EvalError & e) {
|
||||
// Some attrs may contain errors, eg. legacyPackages of
|
||||
// nixpkgs. We still want to recurse into it, instead of
|
||||
// skipping it at all.
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
std::function<nlohmann::json(
|
||||
|
||||
@@ -12,7 +12,7 @@ them to be rolled back easily.
|
||||
The default profile used by `nix profile` is `$HOME/.nix-profile`,
|
||||
which, if it does not exist, is created as a symlink to
|
||||
`/nix/var/nix/profiles/default` if Nix is invoked by the
|
||||
`root` user, or `/nix/var/nix/profiles/per-user/`*username* otherwise.
|
||||
`root` user, or `${XDG_STATE_HOME-$HOME/.local/state}/nix/profiles/profile` otherwise.
|
||||
|
||||
You can specify another profile location using `--profile` *path*.
|
||||
|
||||
@@ -24,11 +24,11 @@ the profile. In turn, *path*`-`*N* is a symlink to a path in the Nix
|
||||
store. For example:
|
||||
|
||||
```console
|
||||
$ ls -l /nix/var/nix/profiles/per-user/alice/profile*
|
||||
lrwxrwxrwx 1 alice users 14 Nov 25 14:35 /nix/var/nix/profiles/per-user/alice/profile -> profile-7-link
|
||||
lrwxrwxrwx 1 alice users 51 Oct 28 16:18 /nix/var/nix/profiles/per-user/alice/profile-5-link -> /nix/store/q69xad13ghpf7ir87h0b2gd28lafjj1j-profile
|
||||
lrwxrwxrwx 1 alice users 51 Oct 29 13:20 /nix/var/nix/profiles/per-user/alice/profile-6-link -> /nix/store/6bvhpysd7vwz7k3b0pndn7ifi5xr32dg-profile
|
||||
lrwxrwxrwx 1 alice users 51 Nov 25 14:35 /nix/var/nix/profiles/per-user/alice/profile-7-link -> /nix/store/mp0x6xnsg0b8qhswy6riqvimai4gm677-profile
|
||||
$ ls -l ~alice/.local/state/nix/profiles/profile*
|
||||
lrwxrwxrwx 1 alice users 14 Nov 25 14:35 /home/alice/.local/state/nix/profiles/profile -> profile-7-link
|
||||
lrwxrwxrwx 1 alice users 51 Oct 28 16:18 /home/alice/.local/state/nix/profiles/profile-5-link -> /nix/store/q69xad13ghpf7ir87h0b2gd28lafjj1j-profile
|
||||
lrwxrwxrwx 1 alice users 51 Oct 29 13:20 /home/alice/.local/state/nix/profiles/profile-6-link -> /nix/store/6bvhpysd7vwz7k3b0pndn7ifi5xr32dg-profile
|
||||
lrwxrwxrwx 1 alice users 51 Nov 25 14:35 /home/alice/.local/state/nix/profiles/profile-7-link -> /nix/store/mp0x6xnsg0b8qhswy6riqvimai4gm677-profile
|
||||
```
|
||||
|
||||
Each of these symlinks is a root for the Nix garbage collector.
|
||||
@@ -38,20 +38,20 @@ profile is a tree of symlinks to the files of the installed packages,
|
||||
e.g.
|
||||
|
||||
```console
|
||||
$ ll -R /nix/var/nix/profiles/per-user/eelco/profile-7-link/
|
||||
/nix/var/nix/profiles/per-user/eelco/profile-7-link/:
|
||||
$ ll -R ~eelco/.local/state/nix/profiles/profile-7-link/
|
||||
/home/eelco/.local/state/nix/profiles/profile-7-link/:
|
||||
total 20
|
||||
dr-xr-xr-x 2 root root 4096 Jan 1 1970 bin
|
||||
-r--r--r-- 2 root root 1402 Jan 1 1970 manifest.json
|
||||
dr-xr-xr-x 4 root root 4096 Jan 1 1970 share
|
||||
|
||||
/nix/var/nix/profiles/per-user/eelco/profile-7-link/bin:
|
||||
/home/eelco/.local/state/nix/profiles/profile-7-link/bin:
|
||||
total 20
|
||||
lrwxrwxrwx 5 root root 79 Jan 1 1970 chromium -> /nix/store/ijm5k0zqisvkdwjkc77mb9qzb35xfi4m-chromium-86.0.4240.111/bin/chromium
|
||||
lrwxrwxrwx 7 root root 87 Jan 1 1970 spotify -> /nix/store/w9182874m1bl56smps3m5zjj36jhp3rn-spotify-1.1.26.501.gbe11e53b-15/bin/spotify
|
||||
lrwxrwxrwx 3 root root 79 Jan 1 1970 zoom-us -> /nix/store/wbhg2ga8f3h87s9h5k0slxk0m81m4cxl-zoom-us-5.3.469451.0927/bin/zoom-us
|
||||
|
||||
/nix/var/nix/profiles/per-user/eelco/profile-7-link/share/applications:
|
||||
/home/eelco/.local/state/nix/profiles/profile-7-link/share/applications:
|
||||
total 12
|
||||
lrwxrwxrwx 4 root root 120 Jan 1 1970 chromium-browser.desktop -> /nix/store/4cf803y4vzfm3gyk3vzhzb2327v0kl8a-chromium-unwrapped-86.0.4240.111/share/applications/chromium-browser.desktop
|
||||
lrwxrwxrwx 7 root root 110 Jan 1 1970 spotify.desktop -> /nix/store/w9182874m1bl56smps3m5zjj36jhp3rn-spotify-1.1.26.501.gbe11e53b-15/share/applications/spotify.desktop
|
||||
|
||||
@@ -11,7 +11,7 @@ R""(
|
||||
* Upgrade Nix in a specific profile:
|
||||
|
||||
```console
|
||||
# nix upgrade-nix -p /nix/var/nix/profiles/per-user/alice/profile
|
||||
# nix upgrade-nix -p ~alice/.local/state/nix/profiles/profile
|
||||
```
|
||||
|
||||
# Description
|
||||
|
||||
@@ -64,3 +64,24 @@ in
|
||||
assert show_output == { };
|
||||
true
|
||||
'
|
||||
|
||||
# Test that attributes with errors are handled correctly.
|
||||
# nixpkgs.legacyPackages is a particularly prominent instance of this.
|
||||
cat >flake.nix <<EOF
|
||||
{
|
||||
outputs = inputs: {
|
||||
legacyPackages.$system = {
|
||||
AAAAAASomeThingsFailToEvaluate = throw "nooo";
|
||||
simple = import ./simple.nix;
|
||||
};
|
||||
};
|
||||
}
|
||||
EOF
|
||||
nix flake show --json --legacy --all-systems > show-output.json
|
||||
nix eval --impure --expr '
|
||||
let show_output = builtins.fromJSON (builtins.readFile ./show-output.json);
|
||||
in
|
||||
assert show_output.legacyPackages.${builtins.currentSystem}.AAAAAASomeThingsFailToEvaluate == { };
|
||||
assert show_output.legacyPackages.${builtins.currentSystem}.simple.name == "simple";
|
||||
true
|
||||
'
|
||||
|
||||
17
tests/gc.sh
17
tests/gc.sh
@@ -50,3 +50,20 @@ if test -e $outPath/foobar; then false; fi
|
||||
# Check that the store is empty.
|
||||
rmdir $NIX_STORE_DIR/.links
|
||||
rmdir $NIX_STORE_DIR
|
||||
|
||||
## Test `nix-collect-garbage -d`
|
||||
# `nix-env` doesn't work with CA derivations, so let's ignore that bit if we're
|
||||
# using them
|
||||
if [[ -z "${NIX_TESTS_CA_BY_DEFAULT:-}" ]]; then
|
||||
clearProfiles
|
||||
# Run two `nix-env` commands, should create two generations of
|
||||
# the profile
|
||||
nix-env -f ./user-envs.nix -i foo-1.0
|
||||
nix-env -f ./user-envs.nix -i foo-2.0pre1
|
||||
[[ $(nix-env --list-generations | wc -l) -eq 2 ]]
|
||||
|
||||
# Clear the profile history. There should be only one generation
|
||||
# left
|
||||
nix-collect-garbage -d
|
||||
[[ $(nix-env --list-generations | wc -l) -eq 1 ]]
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user