1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-06-28 13:41:15 +02:00

Merge pull request #36 from DeterminateSystems/sync-2.24.2

Sync with Nix 2.24.2
This commit is contained in:
Eelco Dolstra 2024-08-09 12:59:36 +02:00 committed by GitHub
commit 6ff6baaa35
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
330 changed files with 4871 additions and 1825 deletions

View file

@ -1 +1 @@
2.24.0 2.24.2

View file

@ -41,9 +41,9 @@ Check out the [security policy](https://github.com/NixOS/nix/security/policy).
There are many open pull requests that might already do what you intend to work on. There are many open pull requests that might already do what you intend to work on.
You can use [labels](https://github.com/NixOS/nix/labels) to filter for relevant topics. You can use [labels](https://github.com/NixOS/nix/labels) to filter for relevant topics.
3. Check the [Nix reference manual](https://nixos.org/manual/nix/unstable/contributing/hacking.html) for information on building Nix and running its tests. 3. Check the [Nix reference manual](https://nix.dev/manual/nix/development/development/building.html) for information on building Nix and running its tests.
For contributions to the command line interface, please check the [CLI guidelines](https://nixos.org/manual/nix/unstable/contributing/cli-guideline.html). For contributions to the command line interface, please check the [CLI guidelines](https://nix.dev/manual/nix/development/development/cli-guideline.html).
4. Make your change! 4. Make your change!
@ -69,7 +69,7 @@ Check out the [security policy](https://github.com/NixOS/nix/security/policy).
- [ ] API documentation in header files - [ ] API documentation in header files
- [ ] Code and comments are self-explanatory - [ ] Code and comments are self-explanatory
- [ ] Commit message explains **why** the change was made - [ ] Commit message explains **why** the change was made
- [ ] New feature or incompatible change: [add a release note](https://nixos.org/manual/nix/stable/contributing/hacking#add-a-release-note) - [ ] New feature or incompatible change: [add a release note](https://nix.dev/manual/nix/development/development/contributing.html#add-a-release-note)
7. If you need additional feedback or help to getting pull request into shape, ask other contributors using [@mentions](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#mentioning-people-and-teams). 7. If you need additional feedback or help to getting pull request into shape, ask other contributors using [@mentions](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#mentioning-people-and-teams).
@ -78,7 +78,7 @@ Check out the [security policy](https://github.com/NixOS/nix/security/policy).
The Nix reference manual is hosted on https://nixos.org/manual/nix. The Nix reference manual is hosted on https://nixos.org/manual/nix.
The underlying source files are located in [`doc/manual/src`](./doc/manual/src). The underlying source files are located in [`doc/manual/src`](./doc/manual/src).
For small changes you can [use GitHub to edit these files](https://docs.github.com/en/repositories/working-with-files/managing-files/editing-files) For small changes you can [use GitHub to edit these files](https://docs.github.com/en/repositories/working-with-files/managing-files/editing-files)
For larger changes see the [Nix reference manual](https://nixos.org/manual/nix/unstable/contributing/hacking.html). For larger changes see the [Nix reference manual](https://nix.dev/manual/nix/development/development/contributing.html).
## Getting help ## Getting help

View file

@ -54,6 +54,7 @@ ifeq ($(ENABLE_FUNCTIONAL_TESTS), yes)
ifdef HOST_UNIX ifdef HOST_UNIX
makefiles += \ makefiles += \
tests/functional/local.mk \ tests/functional/local.mk \
tests/functional/flakes/local.mk \
tests/functional/ca/local.mk \ tests/functional/ca/local.mk \
tests/functional/git-hashing/local.mk \ tests/functional/git-hashing/local.mk \
tests/functional/dyn-drv/local.mk \ tests/functional/dyn-drv/local.mk \
@ -92,7 +93,7 @@ ifdef HOST_WINDOWS
GLOBAL_LDFLAGS += -Wl,--export-all-symbols GLOBAL_LDFLAGS += -Wl,--export-all-symbols
endif endif
GLOBAL_CXXFLAGS += -g -Wall -Wdeprecated-copy -Wignored-qualifiers -Wimplicit-fallthrough -Werror=unused-result -include $(buildprefix)config.h -std=c++2a -I src GLOBAL_CXXFLAGS += -g -Wall -Wdeprecated-copy -Wignored-qualifiers -Wimplicit-fallthrough -Werror=unused-result -Werror=suggest-override -include $(buildprefix)config.h -std=c++2a -I src
# Include the main lib, causing rules to be defined # Include the main lib, causing rules to be defined

View file

@ -4,19 +4,18 @@
[![Test](https://github.com/NixOS/nix/workflows/Test/badge.svg)](https://github.com/NixOS/nix/actions) [![Test](https://github.com/NixOS/nix/workflows/Test/badge.svg)](https://github.com/NixOS/nix/actions)
Nix is a powerful package manager for Linux and other Unix systems that makes package Nix is a powerful package manager for Linux and other Unix systems that makes package
management reliable and reproducible. Please refer to the [Nix manual](https://nixos.org/nix/manual) management reliable and reproducible. Please refer to the [Nix manual](https://nix.dev/reference/nix-manual)
for more details. for more details.
## Installation and first steps ## Installation and first steps
Visit [nix.dev](https://nix.dev) for [installation instructions](https://nix.dev/tutorials/install-nix) and [beginner tutorials](https://nix.dev/tutorials/first-steps). Visit [nix.dev](https://nix.dev) for [installation instructions](https://nix.dev/tutorials/install-nix) and [beginner tutorials](https://nix.dev/tutorials/first-steps).
Full reference documentation can be found in the [Nix manual](https://nixos.org/nix/manual). Full reference documentation can be found in the [Nix manual](https://nix.dev/reference/nix-manual).
## Building and developing ## Building and developing
See our [Hacking guide](https://nixos.org/manual/nix/unstable/contributing/hacking.html) in our manual for instruction on how to Follow instructions in the Nix reference manual to [set up a development environment and build Nix from source](https://nix.dev/manual/nix/development/building.html).
set up a development environment and build Nix from source.
## Contributing ## Contributing

View file

@ -1,13 +1,11 @@
add_project_arguments( add_project_arguments(
'-Wno-deprecated-declarations', '-Wdeprecated-copy',
'-Wimplicit-fallthrough', '-Werror=suggest-override',
'-Werror=switch', '-Werror=switch',
'-Werror=switch-enum', '-Werror=switch-enum',
'-Werror=unused-result', '-Werror=unused-result',
'-Wdeprecated-copy',
'-Wignored-qualifiers', '-Wignored-qualifiers',
# Enable assertions in libstdc++ by default. Harmless on libc++. Benchmarked '-Wimplicit-fallthrough',
# at ~1% overhead in `nix search`. '-Wno-deprecated-declarations',
#
language : 'cpp', language : 'cpp',
) )

View file

@ -340,13 +340,6 @@ AC_CHECK_HEADERS([aws/s3/S3Client.h],
AC_SUBST(ENABLE_S3, [$enable_s3]) AC_SUBST(ENABLE_S3, [$enable_s3])
AC_LANG_POP(C++) AC_LANG_POP(C++)
if test -n "$enable_s3"; then
declare -a aws_version_tokens=($(printf '#include <aws/core/VersionConfig.h>\nAWS_SDK_VERSION_STRING' | $CPP $CPPFLAGS - | grep -v '^#.*' | sed 's/"//g' | tr '.' ' '))
AC_DEFINE_UNQUOTED([AWS_VERSION_MAJOR], ${aws_version_tokens@<:@0@:>@}, [Major version of aws-sdk-cpp.])
AC_DEFINE_UNQUOTED([AWS_VERSION_MINOR], ${aws_version_tokens@<:@1@:>@}, [Minor version of aws-sdk-cpp.])
AC_DEFINE_UNQUOTED([AWS_VERSION_PATCH], ${aws_version_tokens@<:@2@:>@}, [Patch version of aws-sdk-cpp.])
fi
# Whether to use the Boehm garbage collector. # Whether to use the Boehm garbage collector.
AC_ARG_ENABLE(gc, AS_HELP_STRING([--enable-gc],[enable garbage collection in the Nix expression evaluator (requires Boehm GC) [default=yes]]), AC_ARG_ENABLE(gc, AS_HELP_STRING([--enable-gc],[enable garbage collection in the Nix expression evaluator (requires Boehm GC) [default=yes]]),

View file

@ -12,7 +12,7 @@ let
experimentalNotice = optionalString (experimental-feature != null) '' experimentalNotice = optionalString (experimental-feature != null) ''
> **Note** > **Note**
> >
> This function is only available if the [`${experimental-feature}` experimental feature](@docroot@/contributing/experimental-features.md#xp-feature-${experimental-feature}) is enabled. > This function is only available if the [`${experimental-feature}` experimental feature](@docroot@/development/experimental-features.md#xp-feature-${experimental-feature}) is enabled.
> >
> For example, include the following in [`nix.conf`](@docroot@/command-ref/conf-file.md): > For example, include the following in [`nix.conf`](@docroot@/command-ref/conf-file.md):
> >

View file

@ -33,10 +33,10 @@ let
> **Warning** > **Warning**
> >
> This setting is part of an > This setting is part of an
> [experimental feature](@docroot@/contributing/experimental-features.md). > [experimental feature](@docroot@/development/experimental-features.md).
> >
> To change this setting, make sure the > To change this setting, make sure the
> [`${experimentalFeature}` experimental feature](@docroot@/contributing/experimental-features.md#xp-feature-${experimentalFeature}) > [`${experimentalFeature}` experimental feature](@docroot@/development/experimental-features.md#xp-feature-${experimentalFeature})
> is enabled. > is enabled.
> For example, include the following in [`nix.conf`](@docroot@/command-ref/conf-file.md): > For example, include the following in [`nix.conf`](@docroot@/command-ref/conf-file.md):
> >

View file

@ -32,10 +32,10 @@ let
> **Warning** > **Warning**
> >
> This store is part of an > This store is part of an
> [experimental feature](@docroot@/contributing/experimental-features.md). > [experimental feature](@docroot@/development/experimental-features.md).
> >
> To use this store, make sure the > To use this store, make sure the
> [`${experimentalFeature}` experimental feature](@docroot@/contributing/experimental-features.md#xp-feature-${experimentalFeature}) > [`${experimentalFeature}` experimental feature](@docroot@/development/experimental-features.md#xp-feature-${experimentalFeature})
> is enabled. > is enabled.
> For example, include the following in [`nix.conf`](@docroot@/command-ref/conf-file.md): > For example, include the following in [`nix.conf`](@docroot@/command-ref/conf-file.md):
> >

View file

@ -4,6 +4,6 @@ with import <nix/utils.nix>;
let let
showExperimentalFeature = name: doc: showExperimentalFeature = name: doc:
'' ''
- [`${name}`](@docroot@/contributing/experimental-features.md#xp-feature-${name}) - [`${name}`](@docroot@/development/experimental-features.md#xp-feature-${name})
''; '';
in xps: indent " " (concatStrings (attrValues (mapAttrs showExperimentalFeature xps))) in xps: indent " " (concatStrings (attrValues (mapAttrs showExperimentalFeature xps)))

View file

@ -95,7 +95,7 @@ $(d)/nix-profiles.5: $(d)/src/command-ref/files/profiles.md
$(trace-gen) lowdown -sT man --nroff-nolinks -M section=5 $^.tmp -o $@ $(trace-gen) lowdown -sT man --nroff-nolinks -M section=5 $^.tmp -o $@
@rm $^.tmp @rm $^.tmp
$(d)/src/SUMMARY.md: $(d)/src/SUMMARY.md.in $(d)/src/SUMMARY-rl-next.md $(d)/src/store/types $(d)/src/command-ref/new-cli $(d)/src/contributing/experimental-feature-descriptions.md $(d)/src/SUMMARY.md: $(d)/src/SUMMARY.md.in $(d)/src/SUMMARY-rl-next.md $(d)/src/store/types $(d)/src/command-ref/new-cli $(d)/src/development/experimental-feature-descriptions.md
@cp $< $@ @cp $< $@
@$(call process-includes,$@,$@) @$(call process-includes,$@,$@)
@ -124,7 +124,7 @@ $(d)/conf-file.json: $(doc_nix)
$(trace-gen) $(dummy-env) $(doc_nix) config show --json > $@.tmp $(trace-gen) $(dummy-env) $(doc_nix) config show --json > $@.tmp
@mv $@.tmp $@ @mv $@.tmp $@
$(d)/src/contributing/experimental-feature-descriptions.md: $(d)/xp-features.json $(d)/utils.nix $(d)/generate-xp-features.nix $(doc_nix) $(d)/src/development/experimental-feature-descriptions.md: $(d)/xp-features.json $(d)/utils.nix $(d)/generate-xp-features.nix $(doc_nix)
@rm -rf $@ $@.tmp @rm -rf $@ $@.tmp
$(trace-gen) $(nix-eval) --write-to $@.tmp --expr 'import doc/manual/generate-xp-features.nix (builtins.fromJSON (builtins.readFile $<))' $(trace-gen) $(nix-eval) --write-to $@.tmp --expr 'import doc/manual/generate-xp-features.nix (builtins.fromJSON (builtins.readFile $<))'
@mv $@.tmp $@ @mv $@.tmp $@
@ -207,11 +207,11 @@ doc/manual/generated/man1/nix3-manpages: $(d)/src/command-ref/new-cli
done done
@touch $@ @touch $@
# the `! -name 'contributing.md'` filter excludes the one place where # the `! -name 'documentation.md'` filter excludes the one place where
# `@docroot@` is to be preserved for documenting the mechanism # `@docroot@` is to be preserved for documenting the mechanism
# FIXME: maybe contributing guides should live right next to the code # FIXME: maybe contributing guides should live right next to the code
# instead of in the manual # instead of in the manual
$(docdir)/manual/index.html: $(MANUAL_SRCS) $(d)/book.toml $(d)/anchors.jq $(d)/custom.css $(d)/src/SUMMARY.md $(d)/src/store/types $(d)/src/command-ref/new-cli $(d)/src/contributing/experimental-feature-descriptions.md $(d)/src/command-ref/conf-file.md $(d)/src/language/builtins.md $(d)/src/release-notes/rl-next.md $(d)/src/figures $(d)/src/favicon.png $(d)/src/favicon.svg $(docdir)/manual/index.html: $(MANUAL_SRCS) $(d)/book.toml $(d)/anchors.jq $(d)/custom.css $(d)/src/SUMMARY.md $(d)/src/store/types $(d)/src/command-ref/new-cli $(d)/src/development/experimental-feature-descriptions.md $(d)/src/command-ref/conf-file.md $(d)/src/language/builtins.md $(d)/src/release-notes/rl-next.md $(d)/src/figures $(d)/src/favicon.png $(d)/src/favicon.svg
$(trace-gen) \ $(trace-gen) \
tmp="$$(mktemp -d)"; \ tmp="$$(mktemp -d)"; \
cp -r doc/manual "$$tmp"; \ cp -r doc/manual "$$tmp"; \

View file

@ -143,7 +143,7 @@ const redirects = {
"opt-timeout": "command-ref/opt-common.html#opt-timeout", "opt-timeout": "command-ref/opt-common.html#opt-timeout",
"sec-common-options": "command-ref/opt-common.html", "sec-common-options": "command-ref/opt-common.html",
"ch-utilities": "command-ref/utilities.html", "ch-utilities": "command-ref/utilities.html",
"chap-hacking": "contributing/hacking.html", "chap-hacking": "development/building.html",
"adv-attr-allowSubstitutes": "language/advanced-attributes.html#adv-attr-allowSubstitutes", "adv-attr-allowSubstitutes": "language/advanced-attributes.html#adv-attr-allowSubstitutes",
"adv-attr-allowedReferences": "language/advanced-attributes.html#adv-attr-allowedReferences", "adv-attr-allowedReferences": "language/advanced-attributes.html#adv-attr-allowedReferences",
"adv-attr-allowedRequisites": "language/advanced-attributes.html#adv-attr-allowedRequisites", "adv-attr-allowedRequisites": "language/advanced-attributes.html#adv-attr-allowedRequisites",
@ -350,7 +350,7 @@ const redirects = {
"macos": "uninstall.html#macos", "macos": "uninstall.html#macos",
"uninstalling": "uninstall.html", "uninstalling": "uninstall.html",
}, },
"contributing/hacking.html": { "development/building.html": {
"nix-with-flakes": "#building-nix-with-flakes", "nix-with-flakes": "#building-nix-with-flakes",
"classic-nix": "#building-nix", "classic-nix": "#building-nix",
"running-tests": "testing.html#running-tests", "running-tests": "testing.html#running-tests",
@ -361,7 +361,12 @@ const redirects = {
"installer-tests": "testing.html#installer-tests", "installer-tests": "testing.html#installer-tests",
"one-time-setup": "testing.html#one-time-setup", "one-time-setup": "testing.html#one-time-setup",
"using-the-ci-generated-installer-for-manual-testing": "testing.html#using-the-ci-generated-installer-for-manual-testing", "using-the-ci-generated-installer-for-manual-testing": "testing.html#using-the-ci-generated-installer-for-manual-testing",
"characterization-testing": "#characterisation-testing-unit", "characterization-testing": "testing.html#characterisation-testing-unit",
"add-a-release-note": "contributing.html#add-a-release-note",
"add-an-entry": "contributing.html#add-an-entry",
"build-process": "contributing.html#build-process",
"reverting": "contributing.html#reverting",
"branches": "contributing.html#branches",
}, },
"glossary.html": { "glossary.html": {
"gloss-local-store": "store/types/local-store.html", "gloss-local-store": "store/types/local-store.html",

View file

@ -1,6 +0,0 @@
---
synopsis: Stop vendoring toml11
---
We don't apply any patches to it, and vendoring it locks users into
bugs (it hasn't been updated since its introduction in late 2021).

View file

@ -1,7 +0,0 @@
---
synopsis: Harden the user sandboxing
significance: significant
issues:
---
The build directory has been hardened against interference with the outside world by nesting it inside another directory owned by (and only readable by) the daemon user.

View file

@ -1,28 +0,0 @@
---
synopsis: "`nix-shell <directory>` looks for `shell.nix`"
significance: significant
issues:
- 496
- 2279
- 4529
- 5431
- 11053
prs:
- 11057
---
`nix-shell $x` now looks for `$x/shell.nix` when `$x` resolves to a directory.
Although this might be seen as a breaking change, its primarily interactive usage makes it a minor issue.
This adjustment addresses a commonly reported problem.
This also applies to `nix-shell` shebang scripts. Consider the following example:
```shell
#!/usr/bin/env nix-shell
#!nix-shell -i bash
```
This will now load `shell.nix` from the script's directory, if it exists; `default.nix` otherwise.
The old behavior can be opted into by setting the option [`nix-shell-always-looks-for-shell-nix`](@docroot@/command-ref/conf-file.md#conf-nix-shell-always-looks-for-shell-nix) to `false`.

View file

@ -1,53 +0,0 @@
---
synopsis: "`nix-repl`'s `:doc` shows documentation comments"
significance: significant
issues:
- 3904
- 10771
prs:
- 1652
- 9054
- 11072
---
`nix repl` has a `:doc` command that previously only rendered documentation for internally defined functions.
This feature has been extended to also render function documentation comments, in accordance with [RFC 145].
Example:
```
nix-repl> :doc lib.toFunction
Function toFunction
… defined at /home/user/h/nixpkgs/lib/trivial.nix:1072:5
Turns any non-callable values into constant functions. Returns
callable values as is.
Inputs
v
: Any value
Examples
:::{.example}
## lib.trivial.toFunction usage example
| nix-repl> lib.toFunction 1 2
| 1
|
| nix-repl> lib.toFunction (x: x + 1) 2
| 3
:::
```
Known limitations:
- It does not render documentation for "formals", such as `{ /** the value to return */ x, ... }: x`.
- Some extensions to markdown are not yet supported, as you can see in the example above.
We'd like to acknowledge Yingchi Long for proposing a proof of concept for this functionality in [#9054](https://github.com/NixOS/nix/pull/9054), as well as @sternenseemann and Johannes Kirschbauer for their contributions, proposals, and their work on [RFC 145].
[RFC 145]: https://github.com/NixOS/rfcs/pull/145

View file

@ -28,6 +28,7 @@
- [Data Types](language/types.md) - [Data Types](language/types.md)
- [String context](language/string-context.md) - [String context](language/string-context.md)
- [Syntax and semantics](language/syntax.md) - [Syntax and semantics](language/syntax.md)
- [Identifiers](language/identifiers.md)
- [Scoping rules](language/scope.md) - [Scoping rules](language/scope.md)
- [String interpolation](language/string-interpolation.md) - [String interpolation](language/string-interpolation.md)
- [Lookup path](language/constructs/lookup-path.md) - [Lookup path](language/constructs/lookup-path.md)
@ -116,16 +117,18 @@
- [Flake Schemas](protocols/flake-schemas.md) - [Flake Schemas](protocols/flake-schemas.md)
- [C API](c-api.md) - [C API](c-api.md)
- [Glossary](glossary.md) - [Glossary](glossary.md)
- [Contributing](contributing/index.md) - [Development](development/index.md)
- [Hacking](contributing/hacking.md) - [Building](development/building.md)
- [Testing](contributing/testing.md) - [Testing](development/testing.md)
- [Documentation](contributing/documentation.md) - [Documentation](development/documentation.md)
- [Experimental Features](contributing/experimental-features.md) - [CLI guideline](development/cli-guideline.md)
- [CLI guideline](contributing/cli-guideline.md) - [JSON guideline](development/json-guideline.md)
- [JSON guideline](contributing/json-guideline.md) - [C++ style guide](development/cxx.md)
- [C++ style guide](contributing/cxx.md) - [Experimental Features](development/experimental-features.md)
- [Contributing](development/contributing.md)
- [Releases](release-notes/index.md) - [Releases](release-notes/index.md)
{{#include ./SUMMARY-rl-next.md}} {{#include ./SUMMARY-rl-next.md}}
- [Release 2.24 (2024-07-31)](release-notes/rl-2.24.md)
- [Release 2.23 (2024-06-03)](release-notes/rl-2.23.md) - [Release 2.23 (2024-06-03)](release-notes/rl-2.23.md)
- [Release 2.22 (2024-04-23)](release-notes/rl-2.22.md) - [Release 2.22 (2024-04-23)](release-notes/rl-2.22.md)
- [Release 2.21 (2024-03-11)](release-notes/rl-2.21.md) - [Release 2.21 (2024-03-11)](release-notes/rl-2.21.md)

View file

@ -20,7 +20,15 @@
/command-ref/command-ref /command-ref 301! /command-ref/command-ref /command-ref 301!
/contributing/contributing /contributing 301! /contributing/contributing /development 301!
/contributing /development 301!
/contributing/hacking /development/building 301!
/contributing/testing /development/testing 301!
/contributing/documentation /development/documentation 301!
/contributing/experimental-features /development/experimental-features 301!
/contributing/cli-guideline /development/cli-guideline 301!
/contributing/json-guideline /development/json-guideline 301!
/contributing/cxx /development/cxx 301!
/expressions/expression-language /language/ 301! /expressions/expression-language /language/ 301!
/expressions/language-constructs /language/constructs 301! /expressions/language-constructs /language/constructs 301!

View file

@ -10,7 +10,7 @@ See:
- [Matrix Room *Nix Bindings*](https://matrix.to/#/#nix-bindings:nixos.org) for discussion and questions. - [Matrix Room *Nix Bindings*](https://matrix.to/#/#nix-bindings:nixos.org) for discussion and questions.
- [Stabilisation Milestone](https://github.com/NixOS/nix/milestone/52) - [Stabilisation Milestone](https://github.com/NixOS/nix/milestone/52)
- [Other C API PRs and issues](https://github.com/NixOS/nix/labels/c%20api) - [Other C API PRs and issues](https://github.com/NixOS/nix/labels/c%20api)
- [Contributing C API Documentation](contributing/documentation.md#c-api-documentation), including how to build it locally. - [Contributing C API Documentation](development/documentation.md#c-api-documentation), including how to build it locally.
[Getting Started]: https://hydra.nixos.org/job/nix/master/external-api-docs/latest/download-by-type/doc/external-api-docs [Getting Started]: https://hydra.nixos.org/job/nix/master/external-api-docs/latest/download-by-type/doc/external-api-docs
[Index]: https://hydra.nixos.org/job/nix/master/external-api-docs/latest/download-by-type/doc/external-api-docs/globals.html [Index]: https://hydra.nixos.org/job/nix/master/external-api-docs/latest/download-by-type/doc/external-api-docs/globals.html

View file

@ -9,22 +9,26 @@ Most Nix commands interpret the following environment variables:
- <span id="env-NIX_PATH">[`NIX_PATH`](#env-NIX_PATH)</span> - <span id="env-NIX_PATH">[`NIX_PATH`](#env-NIX_PATH)</span>
A colon-separated list of directories used to look up the location of Nix A colon-separated list of search path entries used to resolve [lookup paths](@docroot@/language/constructs/lookup-path.md).
expressions using [paths](@docroot@/language/types.md#type-path)
enclosed in angle brackets (i.e., `<path>`),
e.g. `/home/eelco/Dev:/etc/nixos`. It can be extended using the
[`-I` option](@docroot@/command-ref/opt-common.md#opt-I).
If `NIX_PATH` is not set at all, Nix will fall back to the following list in [impure](@docroot@/command-ref/conf-file.md#conf-pure-eval) and [unrestricted](@docroot@/command-ref/conf-file.md#conf-restrict-eval) evaluation mode: This environment variable overrides the value of the [`nix-path` configuration setting](@docroot@/command-ref/conf-file.md#conf-nix-path).
1. `$HOME/.nix-defexpr/channels` It can be extended using the [`-I` option](@docroot@/command-ref/opt-common.md#opt-I).
2. `nixpkgs=/nix/var/nix/profiles/per-user/root/channels/nixpkgs`
3. `/nix/var/nix/profiles/per-user/root/channels` > **Example**
>
> ```bash
> $ export NIX_PATH=`/home/eelco/Dev:nixos-config=/etc/nixos
> ```
If `NIX_PATH` is set to an empty string, resolving search paths will always fail. If `NIX_PATH` is set to an empty string, resolving search paths will always fail.
For example, attempting to use `<nixpkgs>` will produce:
error: file 'nixpkgs' was not found in the Nix search path > **Example**
>
> ```bash
> $ NIX_PATH= nix-instantiate --eval '<nixpkgs>'
> error: file 'nixpkgs' was not found in the Nix search path (add it using $NIX_PATH or -I)
> ```
- <span id="env-NIX_IGNORE_SYMLINK_STORE">[`NIX_IGNORE_SYMLINK_STORE`](#env-NIX_IGNORE_SYMLINK_STORE)</span> - <span id="env-NIX_IGNORE_SYMLINK_STORE">[`NIX_IGNORE_SYMLINK_STORE`](#env-NIX_IGNORE_SYMLINK_STORE)</span>

View file

@ -1,6 +1,6 @@
# Experimental Commands # Experimental Commands
This section lists [experimental commands](@docroot@/contributing/experimental-features.md#xp-feature-nix-command). This section lists [experimental commands](@docroot@/development/experimental-features.md#xp-feature-nix-command).
> **Warning** > **Warning**
> >

View file

@ -297,3 +297,8 @@ with import <nixpkgs> {};
runCommand "dummy" { buildInputs = [ python pythonPackages.prettytable ]; } "" runCommand "dummy" { buildInputs = [ python pythonPackages.prettytable ]; } ""
``` ```
The script's file name is passed as the first argument to the interpreter specified by the `-i` flag.
Aside from the very first line, which is a directive to the operating system, the additional `#! nix-shell` lines do not need to be at the beginning of the file.
This allows wrapping them in block comments for languages where `#` does not start a comment, such as ECMAScript, Erlang, PHP, or Ruby.

View file

@ -32,7 +32,7 @@ If no substitutes are available and no store derivation is given, realisation fa
[store objects]: @docroot@/store/store-object.md [store objects]: @docroot@/store/store-object.md
[closure]: @docroot@/glossary.md#gloss-closure [closure]: @docroot@/glossary.md#gloss-closure
[substituters]: @docroot@/command-ref/conf-file.md#conf-substituters [substituters]: @docroot@/command-ref/conf-file.md#conf-substituters
[content-addressed derivations]: @docroot@/contributing/experimental-features.md#xp-feature-ca-derivations [content-addressed derivations]: @docroot@/development/experimental-features.md#xp-feature-ca-derivations
[Nix database]: @docroot@/glossary.md#gloss-nix-database [Nix database]: @docroot@/glossary.md#gloss-nix-database
The resulting paths are printed on standard output. The resulting paths are printed on standard output.

View file

@ -187,11 +187,12 @@ Most Nix commands accept the following command-line options:
For `nix-shell`, this option is commonly used to give you a shell in which you can build the packages returned by the expression. For `nix-shell`, this option is commonly used to give you a shell in which you can build the packages returned by the expression.
If you want to get a shell which contain the *built* packages ready for use, give your expression to the `nix-shell --packages ` convenience flag instead. If you want to get a shell which contain the *built* packages ready for use, give your expression to the `nix-shell --packages ` convenience flag instead.
- <span id="opt-I">[`-I`](#opt-I)</span> *path* - <span id="opt-I">[`-I` / `--include`](#opt-I)</span> *path*
Add an entry to the [Nix expression search path](@docroot@/command-ref/conf-file.md#conf-nix-path). Add an entry to the list of search paths used to resolve [lookup paths](@docroot@/language/constructs/lookup-path.md).
This option may be given multiple times. This option may be given multiple times.
Paths added through `-I` take precedence over [`NIX_PATH`](@docroot@/command-ref/env-common.md#env-NIX_PATH).
Paths added through `-I` take precedence over the [`nix-path` configuration setting](@docroot@/command-ref/conf-file.md#conf-nix-path) and the [`NIX_PATH` environment variable](@docroot@/command-ref/env-common.md#env-NIX_PATH).
- <span id="opt-option">[`--option`](#opt-option)</span> *name* *value* - <span id="opt-option">[`--option`](#opt-option)</span> *name* *value*

View file

@ -1,18 +1,4 @@
# Hacking ## Building Nix
This section provides some notes on how to hack on Nix. To get the
latest version of Nix from GitHub:
```console
$ git clone https://github.com/NixOS/nix.git
$ cd nix
```
The following instructions assume you already have some version of Nix installed locally, so that you can use it to set up the development environment. If you don't have it installed, follow the [installation instructions].
[installation instructions]: ../installation/index.md
## Building Nix with flakes
To build all dependencies and start a shell in which all environment variables are set up so that those dependencies can be found: To build all dependencies and start a shell in which all environment variables are set up so that those dependencies can be found:
@ -61,50 +47,6 @@ $ nix build
You can also build Nix for one of the [supported platforms](#platforms). You can also build Nix for one of the [supported platforms](#platforms).
## Building Nix
To build all dependencies and start a shell in which all environment variables are set up so that those dependencies can be found:
```console
$ nix-shell
```
To get a shell with one of the other [supported compilation environments](#compilation-environments):
```console
$ nix-shell --attr devShells.x86_64-linux.native-clangStdenvPackages
```
> **Note**
>
> You can use `native-ccacheStdenvPackages` to drastically improve rebuild time.
> By default, [ccache](https://ccache.dev) keeps artifacts in `~/.cache/ccache/`.
To build Nix itself in this shell:
```console
[nix-shell]$ autoreconfPhase
[nix-shell]$ ./configure $configureFlags --prefix=$(pwd)/outputs/out
[nix-shell]$ make -j $NIX_BUILD_CORES
```
To install it in `$(pwd)/outputs` and test it:
```console
[nix-shell]$ make install
[nix-shell]$ make installcheck -j $NIX_BUILD_CORES
[nix-shell]$ ./outputs/out/bin/nix --version
nix (Nix) 2.12
```
To build a release version of Nix for the current operating system and CPU architecture:
```console
$ nix build
```
You can also build Nix for one of the [supported platforms](#platforms).
## Makefile variables ## Makefile variables
You may need `profiledir=$out/etc/profile.d` and `sysconfdir=$out/etc` to run `make install`. You may need `profiledir=$out/etc/profile.d` and `sysconfdir=$out/etc` to run `make install`.
@ -274,81 +216,3 @@ If it fails, run `git add --patch` to approve the suggestions _and commit again_
To refresh pre-commit hook's config file, do the following: To refresh pre-commit hook's config file, do the following:
1. Exit the development shell and start it again by running `nix develop`. 1. Exit the development shell and start it again by running `nix develop`.
2. If you also use the pre-commit hook, also run `pre-commit-hooks-install` again. 2. If you also use the pre-commit hook, also run `pre-commit-hooks-install` again.
## Add a release note
`doc/manual/rl-next` contains release notes entries for all unreleased changes.
User-visible changes should come with a release note.
### Add an entry
Here's what a complete entry looks like. The file name is not incorporated in the document.
```
---
synopsis: Basically a title
issues: 1234
prs: 1238
---
Here's one or more paragraphs that describe the change.
- It's markdown
- Add references to the manual using @docroot@
```
Significant changes should add the following header, which moves them to the top.
```
significance: significant
```
<!-- Keep an eye on https://codeberg.org/fgaz/changelog-d/issues/1 -->
See also the [format documentation](https://github.com/haskell/cabal/blob/master/CONTRIBUTING.md#changelog).
### Build process
Releases have a precomputed `rl-MAJOR.MINOR.md`, and no `rl-next.md`.
## Branches
- [`master`](https://github.com/NixOS/nix/commits/master)
The main development branch. All changes are approved and merged here.
When developing a change, create a branch based on the latest `master`.
Maintainers try to [keep it in a release-worthy state](#reverting).
- [`maintenance-*.*`](https://github.com/NixOS/nix/branches/all?query=maintenance)
These branches are the subject of backports only, and are
also [kept](#reverting) in a release-worthy state.
See [`maintainers/backporting.md`](https://github.com/NixOS/nix/blob/master/maintainers/backporting.md)
- [`latest-release`](https://github.com/NixOS/nix/tree/latest-release)
The latest patch release of the latest minor version.
See [`maintainers/release-process.md`](https://github.com/NixOS/nix/blob/master/maintainers/release-process.md)
- [`backport-*-to-*`](https://github.com/NixOS/nix/branches/all?query=backport)
Generally branches created by the backport action.
See [`maintainers/backporting.md`](https://github.com/NixOS/nix/blob/master/maintainers/backporting.md)
- [_other_](https://github.com/NixOS/nix/branches/all)
Branches that do not conform to the above patterns should be feature branches.
## Reverting
If a change turns out to be merged by mistake, or contain a regression, it may be reverted.
A revert is not a rejection of the contribution, but merely part of an effective development process.
It makes sure that development keeps running smoothly, with minimal uncertainty, and less overhead.
If maintainers have to worry too much about avoiding reverts, they would not be able to merge as much.
By embracing reverts as a good part of the development process, everyone wins.
However, taking a step back may be frustrating, so maintainers will be extra supportive on the next try.

View file

@ -0,0 +1,79 @@
# Contributing
## Add a release note
`doc/manual/rl-next` contains release notes entries for all unreleased changes.
User-visible changes should come with a release note.
### Add an entry
Here's what a complete entry looks like. The file name is not incorporated in the document.
```
---
synopsis: Basically a title
issues: 1234
prs: 1238
---
Here's one or more paragraphs that describe the change.
- It's markdown
- Add references to the manual using @docroot@
```
Significant changes should add the following header, which moves them to the top.
```
significance: significant
```
<!-- Keep an eye on https://codeberg.org/fgaz/changelog-d/issues/1 -->
See also the [format documentation](https://github.com/haskell/cabal/blob/master/CONTRIBUTING.md#changelog).
### Build process
Releases have a precomputed `rl-MAJOR.MINOR.md`, and no `rl-next.md`.
## Branches
- [`master`](https://github.com/NixOS/nix/commits/master)
The main development branch. All changes are approved and merged here.
When developing a change, create a branch based on the latest `master`.
Maintainers try to [keep it in a release-worthy state](#reverting).
- [`maintenance-*.*`](https://github.com/NixOS/nix/branches/all?query=maintenance)
These branches are the subject of backports only, and are
also [kept](#reverting) in a release-worthy state.
See [`maintainers/backporting.md`](https://github.com/NixOS/nix/blob/master/maintainers/backporting.md)
- [`latest-release`](https://github.com/NixOS/nix/tree/latest-release)
The latest patch release of the latest minor version.
See [`maintainers/release-process.md`](https://github.com/NixOS/nix/blob/master/maintainers/release-process.md)
- [`backport-*-to-*`](https://github.com/NixOS/nix/branches/all?query=backport)
Generally branches created by the backport action.
See [`maintainers/backporting.md`](https://github.com/NixOS/nix/blob/master/maintainers/backporting.md)
- [_other_](https://github.com/NixOS/nix/branches/all)
Branches that do not conform to the above patterns should be feature branches.
## Reverting
If a change turns out to be merged by mistake, or contain a regression, it may be reverted.
A revert is not a rejection of the contribution, but merely part of an effective development process.
It makes sure that development keeps running smoothly, with minimal uncertainty, and less overhead.
If maintainers have to worry too much about avoiding reverts, they would not be able to merge as much.
By embracing reverts as a good part of the development process, everyone wins.
However, taking a step back may be frustrating, so maintainers will be extra supportive on the next try.

View file

@ -24,7 +24,7 @@ nix build .#^doc
and open `./result-doc/share/doc/nix/manual/index.html`. and open `./result-doc/share/doc/nix/manual/index.html`.
To build the manual incrementally, [enter the development shell](./hacking.md) and run: To build the manual incrementally, [enter the development shell](./building.md) and run:
```console ```console
make manual-html-open -j $NIX_BUILD_CORES make manual-html-open -j $NIX_BUILD_CORES

View file

@ -5,4 +5,4 @@ Check the [contributing guide](https://github.com/NixOS/nix/blob/master/CONTRIBU
This chapter is a collection of guides for making changes to the code and documentation. This chapter is a collection of guides for making changes to the code and documentation.
If you're not sure where to start, try to [compile Nix from source](./hacking.md) and consider [making improvements to documentation](./documentation.md). If you're not sure where to start, try to [compile Nix from source](./building.md) and consider [making improvements to documentation](./documentation.md).

View file

@ -168,7 +168,7 @@
- [impure derivation]{#gloss-impure-derivation} - [impure derivation]{#gloss-impure-derivation}
[An experimental feature](#@docroot@/contributing/experimental-features.md#xp-feature-impure-derivations) that allows derivations to be explicitly marked as impure, [An experimental feature](#@docroot@/development/experimental-features.md#xp-feature-impure-derivations) that allows derivations to be explicitly marked as impure,
so that they are always rebuilt, and their outputs not reused by subsequent calls to realise them. so that they are always rebuilt, and their outputs not reused by subsequent calls to realise them.
- [Nix database]{#gloss-nix-database} - [Nix database]{#gloss-nix-database}
@ -353,7 +353,7 @@
Not yet stabilized functionality guarded by named experimental feature flags. Not yet stabilized functionality guarded by named experimental feature flags.
These flags are enabled or disabled with the [`experimental-features`](./command-ref/conf-file.html#conf-experimental-features) setting. These flags are enabled or disabled with the [`experimental-features`](./command-ref/conf-file.html#conf-experimental-features) setting.
See the contribution guide on the [purpose and lifecycle of experimental feaures](@docroot@/contributing/experimental-features.md). See the contribution guide on the [purpose and lifecycle of experimental feaures](@docroot@/development/experimental-features.md).
[Nix language]: ./language/index.md [Nix language]: ./language/index.md

View file

@ -77,7 +77,7 @@ $ su root
# Installing from a binary tarball # Installing from a binary tarball
You can also download a binary tarball that contains Nix and all its dependencies: You can also download a binary tarball that contains Nix and all its dependencies:
- Choose a [version](https://releases.nixos.org/?prefix=nix/) and [system type](../contributing/hacking.md#platforms) - Choose a [version](https://releases.nixos.org/?prefix=nix/) and [system type](../development/building.md#platforms)
- Download and unpack the tarball - Download and unpack the tarball
- Run the installer - Run the installer

View file

@ -113,7 +113,7 @@ Derivations can declare some infrequently used optional attributes.
> `nix-build`. > `nix-build`.
If the [`configurable-impure-env` experimental If the [`configurable-impure-env` experimental
feature](@docroot@/contributing/experimental-features.md#xp-feature-configurable-impure-env) feature](@docroot@/development/experimental-features.md#xp-feature-configurable-impure-env)
is enabled, these environment variables can also be controlled is enabled, these environment variables can also be controlled
through the through the
[`impure-env`](@docroot@/command-ref/conf-file.md#conf-impure-env) [`impure-env`](@docroot@/command-ref/conf-file.md#conf-impure-env)
@ -226,7 +226,7 @@ Derivations can declare some infrequently used optional attributes.
- [`__contentAddressed`]{#adv-attr-__contentAddressed} - [`__contentAddressed`]{#adv-attr-__contentAddressed}
> **Warning** > **Warning**
> This attribute is part of an [experimental feature](@docroot@/contributing/experimental-features.md). > This attribute is part of an [experimental feature](@docroot@/development/experimental-features.md).
> >
> To use this attribute, you must enable the > To use this attribute, you must enable the
> [`ca-derivations`][xp-feature-ca-derivations] experimental feature. > [`ca-derivations`][xp-feature-ca-derivations] experimental feature.
@ -370,6 +370,6 @@ Derivations can declare some infrequently used optional attributes.
ensures that the derivation can only be built on a machine with the `kvm` feature. ensures that the derivation can only be built on a machine with the `kvm` feature.
[xp-feature-ca-derivations]: @docroot@/contributing/experimental-features.md#xp-feature-ca-derivations [xp-feature-ca-derivations]: @docroot@/development/experimental-features.md#xp-feature-ca-derivations
[xp-feature-dynamic-derivations]: @docroot@/contributing/experimental-features.md#xp-feature-dynamic-derivations [xp-feature-dynamic-derivations]: @docroot@/development/experimental-features.md#xp-feature-dynamic-derivations
[xp-feature-git-hashing]: @docroot@/contributing/experimental-features.md#xp-feature-git-hashing [xp-feature-git-hashing]: @docroot@/development/experimental-features.md#xp-feature-git-hashing

View file

@ -0,0 +1,50 @@
# Identifiers
An *identifier* is an [ASCII](https://en.wikipedia.org/wiki/ASCII) character sequence that:
- Starts with a letter (`a-z`, `A-Z`) or underscore (`_`)
- Can contain any number of:
- Letters (`a-z`, `A-Z`)
- Digits (`0-9`)
- Underscores (`_`)
- Apostrophes (`'`)
- Hyphens (`-`)
- Is not one of the [keywords](#keywords)
> **Syntax**
>
> *identifier* ~ `[A-Za-z_][A-Za-z0-9_'-]*`
# Names
A name can be an [identifier](#identifier) or a [string literal](./syntax.md#string-literal).
> **Syntax**
>
> *name**identifier* | *string*
Names are used in [attribute sets](./syntax.md#attrs-literal), [`let` bindings](./syntax.md#let-expressions), and [`inherit`](./syntax.md#inheriting attributes).
# Keywords
These keywords are reserved and cannot be used as [identifiers](#identifiers):
- [`assert`](./syntax.md#assertions)
- [`else`][if]
- [`if`][if]
- [`in`][let]
- [`inherit`](./syntax.md#inheriting-attributes)
- [`let`][let]
- [`or`](./operators.md#attribute-selection) (see note)
- [`rec`](./syntax.md#recursive-sets)
- [`then`][if]
- [`with`](./syntax.md#with-expressions)
[if]: ./syntax.md#conditionals
[let]: ./syntax.md#let-expressions
> **Note**
>
> The Nix language evaluator currently allows `or` to be used as a name in some contexts, for backwards compatibility reasons.
> Users are advised not to rely on this.
>
> There are long-standing issues with how `or` is parsed as a name, which can't be resolved without making a breaking change to the language.

View file

@ -26,13 +26,17 @@
| Logical conjunction (`AND`) | *bool* `&&` *bool* | left | 12 | | Logical conjunction (`AND`) | *bool* `&&` *bool* | left | 12 |
| Logical disjunction (`OR`) | *bool* <code>\|\|</code> *bool* | left | 13 | | Logical disjunction (`OR`) | *bool* <code>\|\|</code> *bool* | left | 13 |
| [Logical implication] | *bool* `->` *bool* | right | 14 | | [Logical implication] | *bool* `->` *bool* | right | 14 |
| [Pipe operator] (experimental) | *expr* `\|>` *func* | left | 15 |
| [Pipe operator] (experimental) | *func* `<\|` *expr* | right | 15 |
[string]: ./types.md#type-string [string]: ./types.md#type-string
[path]: ./types.md#type-path [path]: ./types.md#type-path
[number]: ./types.md#type-float <!-- TODO(@rhendric, #10970): rationalize this --> [number]: ./types.md#type-float
[list]: ./types.md#list [list]: ./types.md#list
[attribute set]: ./types.md#attribute-set [attribute set]: ./types.md#attribute-set
<!-- TODO(@rhendric, #10970): ^ rationalize number -> int/float -->
## Attribute selection ## Attribute selection
> **Syntax** > **Syntax**
@ -42,12 +46,6 @@
Select the attribute denoted by attribute path *attrpath* from [attribute set] *attrset*. Select the attribute denoted by attribute path *attrpath* from [attribute set] *attrset*.
If the attribute doesnt exist, return the *expr* after `or` if provided, otherwise abort evaluation. If the attribute doesnt exist, return the *expr* after `or` if provided, otherwise abort evaluation.
An attribute path is a dot-separated list of [attribute names](./types.md#attribute-set).
> **Syntax**
>
> *attrpath* = *name* [ `.` *name* ]...
[Attribute selection]: #attribute-selection [Attribute selection]: #attribute-selection
## Has attribute ## Has attribute
@ -182,3 +180,34 @@ Equivalent to `!`*b1* `||` *b2*.
[Logical implication]: #logical-implication [Logical implication]: #logical-implication
## Pipe operators
- *a* `|>` *b* is equivalent to *b* *a*
- *a* `<|` *b* is equivalent to *a* *b*
> **Example**
>
> ```
> nix-repl> 1 |> builtins.add 2 |> builtins.mul 3
> 9
>
> nix-repl> builtins.add 1 <| builtins.mul 2 <| 3
> 7
> ```
> **Warning**
>
> This syntax is part of an
> [experimental feature](@docroot@/development/experimental-features.md)
> and may change in future releases.
>
> To use this syntax, make sure the
> [`pipe-operators` experimental feature](@docroot@/development/experimental-features.md#xp-feature-pipe-operators)
> is enabled.
> For example, include the following in [`nix.conf`](@docroot@/command-ref/conf-file.md):
>
> ```
> extra-experimental-features = pipe-operators
> ```
[Pipe operator]: #pipe-operators

View file

@ -190,18 +190,13 @@ This section covers syntax and semantics of the Nix language.
### Path {#path-literal} ### Path {#path-literal}
*Paths* are distinct from strings and can be expressed by path literals such as `./builder.sh`. *Paths* can be expressed by path literals such as `./builder.sh`.
Paths are suitable for referring to local files, and are often preferable over strings.
- Path values do not contain trailing slashes, `.` and `..`, as they are resolved when evaluating a path literal.
- Path literals are automatically resolved relative to their [base directory](@docroot@/glossary.md#gloss-base-directory).
- The files referred to by path values are automatically copied into the Nix store when used in a string interpolation or concatenation.
- Tooling can recognize path literals and provide additional features, such as autocompletion, refactoring automation and jump-to-file.
A path literal must contain at least one slash to be recognised as such. A path literal must contain at least one slash to be recognised as such.
For instance, `builder.sh` is not a path: For instance, `builder.sh` is not a path:
it's parsed as an expression that selects the attribute `sh` from the variable `builder`. it's parsed as an expression that selects the attribute `sh` from the variable `builder`.
Path literals are resolved relative to their [base directory](@docroot@/glossary.md#gloss-base-directory).
Path literals may also refer to absolute paths by starting with a slash. Path literals may also refer to absolute paths by starting with a slash.
> **Note** > **Note**
@ -215,15 +210,6 @@ This section covers syntax and semantics of the Nix language.
For example, `~/foo` would be equivalent to `/home/edolstra/foo` for a user whose home directory is `/home/edolstra`. For example, `~/foo` would be equivalent to `/home/edolstra/foo` for a user whose home directory is `/home/edolstra`.
Path literals that start with `~` are not allowed in [pure](@docroot@/command-ref/conf-file.md#conf-pure-eval) evaluation. Path literals that start with `~` are not allowed in [pure](@docroot@/command-ref/conf-file.md#conf-pure-eval) evaluation.
Paths can be used in [string interpolation] and string concatenation.
For instance, evaluating `"${./foo.txt}"` will cause `foo.txt` from the same directory to be copied into the Nix store and result in the string `"/nix/store/<hash>-foo.txt"`.
Note that the Nix language assumes that all input files will remain _unchanged_ while evaluating a Nix expression.
For example, assume you used a file path in an interpolated string during a `nix repl` session.
Later in the same session, after having changed the file contents, evaluating the interpolated string with the file path again might not return a new [store path], since Nix might not re-read the file contents. Use `:r` to reset the repl as needed.
[store path]: @docroot@/store/store-path.md
Path literals can also include [string interpolation], besides being [interpolated into other expressions]. Path literals can also include [string interpolation], besides being [interpolated into other expressions].
[interpolated into other expressions]: ./string-interpolation.md#interpolated-expressions [interpolated into other expressions]: ./string-interpolation.md#interpolated-expressions
@ -261,37 +247,76 @@ Elements in a list can be accessed using [`builtins.elemAt`](./builtins.md#built
## Attribute Set {#attrs-literal} ## Attribute Set {#attrs-literal}
An attribute set is a collection of name-value-pairs (called *attributes*) enclosed in curly brackets (`{ }`). An attribute set is a collection of name-value-pairs called *attributes*.
An attribute name can be an identifier or a [string](#string). Attribute sets are written enclosed in curly brackets (`{ }`).
An identifier must start with a letter (`a-z`, `A-Z`) or underscore (`_`), and can otherwise contain letters (`a-z`, `A-Z`), numbers (`0-9`), underscores (`_`), apostrophes (`'`), or dashes (`-`). Attribute names and attribute values are separated by an equal sign (`=`).
Each value can be an arbitrary expression, terminated by a semicolon (`;`)
An attribute name is a string without context, and is denoted by a [name] (an [identifier](./identifiers.md#identifiers) or [string literal](#string-literal)).
[name]: ./identifiers.md#names
> **Syntax** > **Syntax**
> >
> *name* = *identifier* | *string* \ > *attrset*`{` { *name* `=` *expr* `;` } `}`
> *identifier* ~ `[a-zA-Z_][a-zA-Z0-9_'-]*`
Names and values are separated by an equal sign (`=`).
Each value is an arbitrary expression terminated by a semicolon (`;`).
> **Syntax**
>
> *attrset* = `{` [ *name* `=` *expr* `;` ]... `}`
Attributes can appear in any order. Attributes can appear in any order.
An attribute name may only occur once. An attribute name may only occur once in each attribute set.
Example: > **Example**
>
> This defines an attribute set with attributes named:
> - `x` with the value `123`, an integer
> - `text` with the value `"Hello"`, a string
> - `y` where the value is the result of applying the function `f` to the attribute set `{ bla = 456; }`
>
> ```nix
> {
> x = 123;
> text = "Hello";
> y = f { bla = 456; };
> }
> ```
```nix Attributes in nested attribute sets can be written using *attribute paths*.
{
x = 123;
text = "Hello";
y = f { bla = 456; };
}
```
This defines a set with attributes named `x`, `text`, `y`. > **Syntax**
>
> *attrset*`{` { *attrpath* `=` *expr* `;` } `}`
An attribute path is a dot-separated list of [names][name].
> **Syntax**
>
> *attrpath* = *name* { `.` *name* }
<!-- -->
> **Example**
>
> ```nix
> { a.b.c = 1; a.b.d = 2; }
> ```
>
> {
> a = {
> b = {
> c = 1;
> d = 2;
> };
> };
> }
Attribute names can also be set implicitly by using the [`inherit` keyword](#inheriting-attributes).
> **Example**
>
> ```nix
> { inherit (builtins) true; }
> ```
>
> { true = true; }
Attributes can be accessed with the [`.` operator](./operators.md#attribute-selection). Attributes can be accessed with the [`.` operator](./operators.md#attribute-selection).

View file

@ -50,8 +50,37 @@ The function [`builtins.isString`](builtins.md#builtins-isString) can be used to
### Path {#type-path} ### Path {#type-path}
<!-- TODO(@rhendric, #10970): Incorporate content from syntax.md#path-literal --> A _path_ in the Nix language is an immutable, finite-length sequence of bytes starting with `/`, representing a POSIX-style, canonical file system path.
Path values are distinct from string values, even if they contain the same sequence of bytes.
Operations that produce paths will simplify the result as the standard C function [`realpath`] would, except that there is no symbolic link resolution.
[`realpath`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/realpath.html
Paths are suitable for referring to local files, and are often preferable over strings.
- Path values do not contain trailing or duplicate slashes, `.`, or `..`.
- Relative path literals are automatically resolved relative to their [base directory].
- Tooling can recognize path literals and provide additional features, such as autocompletion, refactoring automation and jump-to-file.
[base directory]: @docroot@/glossary.md#gloss-base-directory
A file is not required to exist at a given path in order for that path value to be valid, but a path that is converted to a string with [string interpolation] or [string-and-path concatenation] must resolve to a readable file or directory which will be copied into the Nix store.
For instance, evaluating `"${./foo.txt}"` will cause `foo.txt` from the same directory to be copied into the Nix store and result in the string `"/nix/store/<hash>-foo.txt"`.
Operations such as [`import`] can also expect a path to resolve to a readable file or directory.
[string interpolation]: string-interpolation.md#interpolated-expression
[string-and-path concatenation]: operators.md#string-and-path-concatenation
[`import`]: builtins.md#builtins-import
> **Note**
>
> The Nix language assumes that all input files will remain _unchanged_ while evaluating a Nix expression.
> For example, assume you used a file path in an interpolated string during a `nix repl` session.
> Later in the same session, after having changed the file contents, evaluating the interpolated string with the file path again might not return a new [store path], since Nix might not re-read the file contents.
> Use `:r` to reset the repl as needed.
[store path]: @docroot@/store/store-path.md
Path values can be expressed as [path literals](syntax.md#path-literal).
The function [`builtins.isPath`](builtins.md#builtins-isPath) can be used to determine if a value is a path. The function [`builtins.isPath`](builtins.md#builtins-isPath) can be used to determine if a value is a path.
### Null {#type-null} ### Null {#type-null}

View file

@ -14,6 +14,6 @@ Derivations are serialised in one of the following formats:
DrvWithVersion(<version-string>, ...) DrvWithVersion(<version-string>, ...)
``` ```
The only `version-string`s that are in use today are for [experimental features](@docroot@/contributing/experimental-features.md): The only `version-string`s that are in use today are for [experimental features](@docroot@/development/experimental-features.md):
- `"xp-dyn-drv"` for the [`dynamic-derivations`](@docroot@/contributing/experimental-features.md#xp-feature-dynamic-derivations) experimental feature. - `"xp-dyn-drv"` for the [`dynamic-derivations`](@docroot@/development/experimental-features.md#xp-feature-dynamic-derivations) experimental feature.

View file

@ -41,4 +41,30 @@ Link: <https://example.org/hello/442793d9ec0584f6a6e82fa253850c8085bb150a.tar.gz
For tarball flakes, the value of the `lastModified` flake attribute is For tarball flakes, the value of the `lastModified` flake attribute is
defined as the timestamp of the newest file inside the tarball. defined as the timestamp of the newest file inside the tarball.
## Gitea and Forgejo support
This protocol is supported by Gitea since v1.22.1 and by Forgejo since v7.0.4/v8.0.0 and can be used with the following flake URL schema:
```
https://<domain name>/<owner>/<repo>/archive/<reference or revison>.tar.gz
```
> **Example**
>
>
> ```nix
> # flake.nix
> {
> inputs = {
> foo.url = "https://gitea.example.org/some-person/some-flake/archive/main.tar.gz";
> bar.url = "https://gitea.example.org/some-other-person/other-flake/archive/442793d9ec0584f6a6e82fa253850c8085bb150a.tar.gz";
> qux = {
> url = "https://forgejo.example.org/another-person/some-non-flake-repo/archive/development.tar.gz";
> flake = false;
> };
> };
> outputs = { foo, bar, qux }: { /* ... */ };
> }
```
[Nix Archive]: @docroot@/store/file-system-object/content-address.md#serial-nix-archive [Nix Archive]: @docroot@/store/file-system-object/content-address.md#serial-nix-archive

View file

@ -13,7 +13,7 @@
- The `discard-references` feature has been stabilized. - The `discard-references` feature has been stabilized.
This means that the This means that the
[unsafeDiscardReferences](@docroot@/contributing/experimental-features.md#xp-feature-discard-references) [unsafeDiscardReferences](@docroot@/development/experimental-features.md#xp-feature-discard-references)
attribute is no longer guarded by an experimental flag and can be used attribute is no longer guarded by an experimental flag and can be used
freely. freely.
@ -21,7 +21,7 @@
This only affects `nix-build --json` when "building" non-derivation things like fetched sources, which is a no-op. This only affects `nix-build --json` when "building" non-derivation things like fetched sources, which is a no-op.
- A new builtin [`outputOf`](@docroot@/language/builtins.md#builtins-outputOf) has been added. - A new builtin [`outputOf`](@docroot@/language/builtins.md#builtins-outputOf) has been added.
It is part of the [`dynamic-derivations`](@docroot@/contributing/experimental-features.md#xp-feature-dynamic-derivations) experimental feature. It is part of the [`dynamic-derivations`](@docroot@/development/experimental-features.md#xp-feature-dynamic-derivations) experimental feature.
- Flake follow paths at depths greater than 2 are now handled correctly, preventing "follows a non-existent input" errors. - Flake follow paths at depths greater than 2 are now handled correctly, preventing "follows a non-existent input" errors.

View file

@ -17,8 +17,8 @@
- `nix-shell` shebang lines now support single-quoted arguments. - `nix-shell` shebang lines now support single-quoted arguments.
- `builtins.fetchTree` is now its own experimental feature, [`fetch-tree`](@docroot@/contributing/experimental-features.md#xp-fetch-tree). - `builtins.fetchTree` is now its own experimental feature, [`fetch-tree`](@docroot@/development/experimental-features.md#xp-fetch-tree).
This allows stabilising it independently of the rest of what is encompassed by [`flakes`](@docroot@/contributing/experimental-features.md#xp-fetch-tree). This allows stabilising it independently of the rest of what is encompassed by [`flakes`](@docroot@/development/experimental-features.md#xp-fetch-tree).
- The interface for creating and updating lock files has been overhauled: - The interface for creating and updating lock files has been overhauled:
@ -33,7 +33,7 @@
- The flake-specific flags `--recreate-lock-file` and `--update-input` have been removed from all commands operating on installables. - The flake-specific flags `--recreate-lock-file` and `--update-input` have been removed from all commands operating on installables.
They are superceded by `nix flake update`. They are superceded by `nix flake update`.
- Commit signature verification for the [`builtins.fetchGit`](@docroot@/language/builtins.md#builtins-fetchGit) is added as the new [`verified-fetches` experimental feature](@docroot@/contributing/experimental-features.md#xp-feature-verified-fetches). - Commit signature verification for the [`builtins.fetchGit`](@docroot@/language/builtins.md#builtins-fetchGit) is added as the new [`verified-fetches` experimental feature](@docroot@/development/experimental-features.md#xp-feature-verified-fetches).
- [`nix path-info --json`](@docroot@/command-ref/new-cli/nix3-path-info.md) - [`nix path-info --json`](@docroot@/command-ref/new-cli/nix3-path-info.md)
(experimental) now returns a JSON map rather than JSON list. (experimental) now returns a JSON map rather than JSON list.

View file

@ -14,7 +14,7 @@
- Modify `nix derivation {add,show}` JSON format [#9866](https://github.com/NixOS/nix/issues/9866) [#10722](https://github.com/NixOS/nix/pull/10722) - Modify `nix derivation {add,show}` JSON format [#9866](https://github.com/NixOS/nix/issues/9866) [#10722](https://github.com/NixOS/nix/pull/10722)
The JSON format for derivations has been slightly revised to better conform to our [JSON guidelines](@docroot@/contributing/cli-guideline.md#returning-future-proof-json). The JSON format for derivations has been slightly revised to better conform to our [JSON guidelines](@docroot@/development/cli-guideline.md#returning-future-proof-json).
In particular, the hash algorithm and content addressing method of content-addresed derivation outputs are now separated into two fields `hashAlgo` and `method`, In particular, the hash algorithm and content addressing method of content-addresed derivation outputs are now separated into two fields `hashAlgo` and `method`,
rather than one field with an arcane `:`-separated format. rather than one field with an arcane `:`-separated format.
@ -89,7 +89,7 @@
This makes records of this sort more self-describing, and easier to consume programmatically. This makes records of this sort more self-describing, and easier to consume programmatically.
We will follow this design principle going forward; We will follow this design principle going forward;
the [JSON guidelines](@docroot@/contributing/json-guideline.md) in the contributing section have been updated accordingly. the [JSON guidelines](@docroot@/development/json-guideline.md) in the contributing section have been updated accordingly.
- Large path warnings [#10661](https://github.com/NixOS/nix/pull/10661) - Large path warnings [#10661](https://github.com/NixOS/nix/pull/10661)

View file

@ -0,0 +1,324 @@
# Release 2.24.0 (2024-07-31)
### Significant changes
- Harden user sandboxing
The build directory has been hardened against interference with the outside world by nesting it inside another directory owned by (and only readable by) the daemon user.
This is a low severity security fix, [CVE-2024-38531](https://www.cve.org/CVERecord?id=CVE-2024-38531).
Credit: [**@alois31**](https://github.com/alois31), [**Linus Heckemann (@lheckemann)**](https://github.com/lheckemann)
Co-authors: [**@edolstra**](https://github.com/edolstra)
- `nix-shell <directory>` looks for `shell.nix` [#496](https://github.com/NixOS/nix/issues/496) [#2279](https://github.com/NixOS/nix/issues/2279) [#4529](https://github.com/NixOS/nix/issues/4529) [#5431](https://github.com/NixOS/nix/issues/5431) [#11053](https://github.com/NixOS/nix/issues/11053) [#11057](https://github.com/NixOS/nix/pull/11057)
`nix-shell $x` now looks for `$x/shell.nix` when `$x` resolves to a directory.
Although this might be seen as a breaking change, its primarily interactive usage makes it a minor issue.
This adjustment addresses a commonly reported problem.
This also applies to `nix-shell` shebang scripts. Consider the following example:
```shell
#!/usr/bin/env nix-shell
#!nix-shell -i bash
```
This will now load `shell.nix` from the script's directory, if it exists; `default.nix` otherwise.
The old behavior can be opted into by setting the option [`nix-shell-always-looks-for-shell-nix`](@docroot@/command-ref/conf-file.md#conf-nix-shell-always-looks-for-shell-nix) to `false`.
Author: [**Robert Hensing (@roberth)**](https://github.com/roberth)
- `nix-repl`'s `:doc` shows documentation comments [#3904](https://github.com/NixOS/nix/issues/3904) [#10771](https://github.com/NixOS/nix/issues/10771) [#1652](https://github.com/NixOS/nix/pull/1652) [#9054](https://github.com/NixOS/nix/pull/9054) [#11072](https://github.com/NixOS/nix/pull/11072)
`nix repl` has a `:doc` command that previously only rendered documentation for internally defined functions.
This feature has been extended to also render function documentation comments, in accordance with [RFC 145].
Example:
```
nix-repl> :doc lib.toFunction
Function toFunction
… defined at /home/user/h/nixpkgs/lib/trivial.nix:1072:5
Turns any non-callable values into constant functions. Returns
callable values as is.
Inputs
v
: Any value
Examples
:::{.example}
## lib.trivial.toFunction usage example
| nix-repl> lib.toFunction 1 2
| 1
|
| nix-repl> lib.toFunction (x: x + 1) 2
| 3
:::
```
Known limitations:
- It does not render documentation for "formals", such as `{ /** the value to return */ x, ... }: x`.
- Some extensions to markdown are not yet supported, as you can see in the example above.
We'd like to acknowledge [Yingchi Long (@inclyc)](https://github.com/inclyc) for proposing a proof of concept for this functionality in [#9054](https://github.com/NixOS/nix/pull/9054), as well as [@sternenseemann](https://github.com/sternenseemann) and [Johannes Kirschbauer (@hsjobeki)](https://github.com/hsjobeki) for their contributions, proposals, and their work on [RFC 145].
Author: [**Robert Hensing (@roberth)**](https://github.com/roberth)
[RFC 145]: https://github.com/NixOS/rfcs/pull/145
### Other changes
- Solve `cached failure of attribute X` [#9165](https://github.com/NixOS/nix/issues/9165) [#10513](https://github.com/NixOS/nix/issues/10513) [#10564](https://github.com/NixOS/nix/pull/10564)
This eliminates all "cached failure of attribute X" messages by forcing evaluation of the original value when needed to show the exception to the user. This enhancement improves error reporting by providing the underlying message and stack trace.
Author: [**Eelco Dolstra (@edolstra)**](https://github.com/edolstra)
- Run the flake regressions test suite [#10603](https://github.com/NixOS/nix/pull/10603)
This update introduces a GitHub action to run a subset of the [flake regressions test suite](https://github.com/NixOS/flake-regressions), which includes 259 flakes with their expected evaluation results. Currently, the action runs the first 25 flakes due to the full test suite's extensive runtime. A manually triggered action may be implemented later to run the entire test suite.
Author: [**Eelco Dolstra (@edolstra)**](https://github.com/edolstra)
- Support unit prefixes in configuration settings [#10668](https://github.com/NixOS/nix/pull/10668)
Configuration settings in Nix now support unit prefixes, allowing for more intuitive and readable configurations. For example, you can now specify [`--min-free 1G`](@docroot@/command-ref/opt-common.md#opt-min-free) to set the minimum free space to 1 gigabyte.
This enhancement was extracted from [#7851](https://github.com/NixOS/nix/pull/7851) and is also useful for PR [#10661](https://github.com/NixOS/nix/pull/10661).
Author: [**Eelco Dolstra (@edolstra)**](https://github.com/edolstra)
- `nix build`: show all FOD errors with `--keep-going` [#10734](https://github.com/NixOS/nix/pull/10734)
The [`nix build`](@docroot@/command-ref/new-cli/nix3-build.md) command has been updated to improve the behavior of the [`--keep-going`] flag. Now, when `--keep-going` is used, all hash-mismatch errors of failing fixed-output derivations (FODs) are displayed, similar to the behavior for other build failures. This enhancement ensures that all relevant build errors are shown, making it easier for users to update multiple derivations at once or to diagnose and fix issues.
Author: [**Jörg Thalheim (@Mic92)**](https://github.com/Mic92), [**Maximilian Bosch (@Ma27)**](https://github.com/Ma27)
[`--keep-going`](@docroot@/command-ref/opt-common.md#opt-keep-going)
- Build with Meson [#2503](https://github.com/NixOS/nix/issues/2503) [#10378](https://github.com/NixOS/nix/pull/10378) [#10855](https://github.com/NixOS/nix/pull/10855) [#10904](https://github.com/NixOS/nix/pull/10904) [#10908](https://github.com/NixOS/nix/pull/10908) [#10914](https://github.com/NixOS/nix/pull/10914) [#10933](https://github.com/NixOS/nix/pull/10933) [#10936](https://github.com/NixOS/nix/pull/10936) [#10954](https://github.com/NixOS/nix/pull/10954) [#10955](https://github.com/NixOS/nix/pull/10955) [#10963](https://github.com/NixOS/nix/pull/10963) [#10967](https://github.com/NixOS/nix/pull/10967) [#10973](https://github.com/NixOS/nix/pull/10973) [#11034](https://github.com/NixOS/nix/pull/11034) [#11054](https://github.com/NixOS/nix/pull/11054) [#11055](https://github.com/NixOS/nix/pull/11055) [#11060](https://github.com/NixOS/nix/pull/11060) [#11064](https://github.com/NixOS/nix/pull/11064) [#11155](https://github.com/NixOS/nix/pull/11155)
These changes aim to replace the use of autotools and `make` with Meson for building various components of Nix. Additionally, each library is built in its own derivation, leveraging Meson's "subprojects" feature to allow a single development shell for building all libraries while also supporting separate builds. This approach aims to improve productivity and build modularity, compared to both make and a monolithic Meson-based derivation.
Special thanks to everyone who has contributed to the Meson port, particularly [**@p01arst0rm**](https://github.com/p01arst0rm) and [**@Qyriad**](https://github.com/Qyriad).
Authors: [**John Ericson (@Ericson2314)**](https://github.com/Ericson2314), [**Tom Bereknyei**](https://github.com/tomberek), [**Théophane Hufschmitt (@thufschmitt)**](https://github.com/thufschmitt), [**Valentin Gagarin (@fricklerhandwerk)**](https://github.com/fricklerhandwerk), [**Robert Hensing (@roberth)**](https://github.com/roberth)
Co-authors: [**@p01arst0rm**](https://github.com/p01arst0rm), [**@Qyriad**](https://github.com/Qyriad)
- Evaluation cache: fix cache regressions [#10570](https://github.com/NixOS/nix/issues/10570) [#11086](https://github.com/NixOS/nix/pull/11086)
This update addresses two bugs in the evaluation cache system:
1. Regression in #10570: The evaluation cache was not being persisted in `nix develop`.
2. Nix could sometimes try to commit the evaluation cache SQLite transaction without there being an active transaction, resulting in non-error errors being printed.
Author: [**Lexi Mattick (@kognise)**](https://github.com/kognise)
- Introduce `libnixflake` [#9063](https://github.com/NixOS/nix/pull/9063)
A new library, `libnixflake`, has been introduced to better separate the Flakes layer within Nix. This change refactors the codebase to encapsulate Flakes-specific functionality within its own library.
See the commits in the pull request for detailed changes, with the only significant code modifications happening in the initial commit.
This change was alluded to in [RFC 134](https://github.com/nixos/rfcs/blob/master/rfcs/0134-nix-store-layer.md) and is a step towards a more modular and maintainable codebase.
Author: [**John Ericson (@Ericson2314)**](https://github.com/Ericson2314)
- CLI options `--arg-from-file` and `--arg-from-stdin` [#9913](https://github.com/NixOS/nix/pull/9913)
- The `--debugger` now prints source location information, instead of the
pointers of source location information. Before:
```
nix-repl> :bt
0: while evaluating the attribute 'python311.pythonForBuild.pkgs'
0x600001522598
```
After:
```
0: while evaluating the attribute 'python311.pythonForBuild.pkgs'
/nix/store/hg65h51xnp74ikahns9hyf3py5mlbbqq-source/overrides/default.nix:132:27
131|
132| bootstrappingBase = pkgs.${self.python.pythonAttr}.pythonForBuild.pkgs;
| ^
133| in
```
- Stop vendoring `toml11`
We don't apply any patches to it, and vendoring it locks users into
bugs (it hasn't been updated since its introduction in late 2021).
Author: [**Winter (@winterqt)**](https://github.com/winterqt)
- Rename hash format `base32` to `nix32` [#8678](https://github.com/NixOS/nix/pull/8678)
Hash format `base32` was renamed to `nix32` since it used a special nix-specific character set for
[Base32](https://en.wikipedia.org/wiki/Base32).
**Deprecation**: Use `nix32` instead of `base32` as `toHashFormat`
For the builtin `convertHash`, the `toHashFormat` parameter now accepts the same hash formats as the `--to`/`--from`
parameters of the `nix hash conert` command: `"base16"`, `"nix32"`, `"base64"`, and `"sri"`. The former `"base32"` value
remains as a deprecated alias for `"nix32"`. Please convert your code from:
```nix
builtins.convertHash { inherit hash hashAlgo; toHashFormat = "base32";}
```
to
```nix
builtins.convertHash { inherit hash hashAlgo; toHashFormat = "nix32";}
```
- Add `pipe-operators` experimental feature [#11131](https://github.com/NixOS/nix/pull/11131)
This is a draft implementation of [RFC 0148](https://github.com/NixOS/rfcs/pull/148).
The `pipe-operators` experimental feature adds [`<|` and `|>` operators][pipe operators] to the Nix language.
*a* `|>` *b* is equivalent to the function application *b* *a*, and
*a* `<|` *b* is equivalent to the function application *a* *b*.
For example:
```
nix-repl> 1 |> builtins.add 2 |> builtins.mul 3
9
nix-repl> builtins.add 1 <| builtins.mul 2 <| 3
7
```
`<|` and `|>` are right and left associative, respectively, and have lower precedence than any other operator.
These properties may change in future releases.
See [the RFC](https://github.com/NixOS/rfcs/pull/148) for more examples and rationale.
[pipe operators]: @docroot@/language/operators.md#pipe-operators
- `nix-shell` shebang uses relative path [#4232](https://github.com/NixOS/nix/issues/4232) [#5088](https://github.com/NixOS/nix/pull/5088) [#11058](https://github.com/NixOS/nix/pull/11058)
<!-- unfortunately no link target for the specific syntax -->
Relative [path](@docroot@/language/types.md#type-path) literals in `nix-shell` shebang scripts' options are now resolved relative to the [script's location](@docroot@/glossary.md?highlight=base%20directory#gloss-base-directory).
Previously they were resolved relative to the current working directory.
For example, consider the following script in `~/myproject/say-hi`:
```shell
#!/usr/bin/env nix-shell
#!nix-shell --expr 'import ./shell.nix'
#!nix-shell --arg toolset './greeting-tools.nix'
#!nix-shell -i bash
hello
```
Older versions of `nix-shell` would resolve `shell.nix` relative to the current working directory, such as the user's home directory in this example:
```console
[hostname:~]$ ./myproject/say-hi
error:
… while calling the 'import' builtin
at «string»:1:2:
1| (import ./shell.nix)
| ^
error: path '/home/user/shell.nix' does not exist
```
Since this release, `nix-shell` resolves `shell.nix` relative to the script's location, and `~/myproject/shell.nix` is used.
```console
$ ./myproject/say-hi
Hello, world!
```
**Opt-out**
This is technically a breaking change, so we have added an option so you can adapt independently of your Nix update.
The old behavior can be opted into by setting the option [`nix-shell-shebang-arguments-relative-to-script`](@docroot@/command-ref/conf-file.md#conf-nix-shell-shebang-arguments-relative-to-script) to `false`.
This option will be removed in a future release.
Author: [**Robert Hensing (@roberth)**](https://github.com/roberth)
- Improve handling of tarballs that don't consist of a single top-level directory [#11195](https://github.com/NixOS/nix/pull/11195)
In previous Nix releases, the tarball fetcher (used by `builtins.fetchTarball`) erroneously merged top-level directories into a single directory, and silently discarded top-level files that are not directories. This is no longer the case. The new behaviour is that *only* if the tarball consists of a single directory, the top-level path component of the files in the tarball is removed (similar to `tar`'s `--strip-components=1`).
Author: [**Eelco Dolstra (@edolstra)**](https://github.com/edolstra)
- Improve handling of tarballs that don't consist of a single top-level directory [#11195](https://github.com/NixOS/nix/pull/11195)
In previous Nix releases, the tarball fetcher (used by `builtins.fetchTarball`) erroneously merged top-level directories into a single directory, and silently discarded top-level files that are not directories. This is no longer the case.
Author: [**Eelco Dolstra (@edolstra)**](https://github.com/edolstra)
- Setting to warn about large paths [#10778](https://github.com/NixOS/nix/pull/10778)
Nix can now warn when evaluation of a Nix expression causes a large
path to be copied to the Nix store. The threshold for this warning can
be configured using the `warn-large-path-threshold` setting,
e.g. `--warn-large-path-threshold 100M`.
# Contributors
This release was made possible by the following 43 contributors:
- Andreas Rammhold [**(@andir)**](https://github.com/andir)
- Andrew Marshall [**(@amarshall)**](https://github.com/amarshall)
- Brian McKenna [**(@puffnfresh)**](https://github.com/puffnfresh)
- Cameron [**(@SkamDart)**](https://github.com/SkamDart)
- Cole Helbling [**(@cole-h)**](https://github.com/cole-h)
- Corbin Simpson [**(@MostAwesomeDude)**](https://github.com/MostAwesomeDude)
- Eelco Dolstra [**(@edolstra)**](https://github.com/edolstra)
- Emily [**(@emilazy)**](https://github.com/emilazy)
- Enno Richter [**(@elohmeier)**](https://github.com/elohmeier)
- Farid Zakaria [**(@fzakaria)**](https://github.com/fzakaria)
- HaeNoe [**(@haenoe)**](https://github.com/haenoe)
- Hamir Mahal [**(@hamirmahal)**](https://github.com/hamirmahal)
- Harmen [**(@alicebob)**](https://github.com/alicebob)
- Ivan Trubach [**(@tie)**](https://github.com/tie)
- Jared Baur [**(@jmbaur)**](https://github.com/jmbaur)
- John Ericson [**(@Ericson2314)**](https://github.com/Ericson2314)
- Jonathan De Troye [**(@detroyejr)**](https://github.com/detroyejr)
- Jörg Thalheim [**(@Mic92)**](https://github.com/Mic92)
- Klemens Nanni [**(@klemensn)**](https://github.com/klemensn)
- Las Safin [**(@L-as)**](https://github.com/L-as)
- Lexi Mattick [**(@kognise)**](https://github.com/kognise)
- Matthew Bauer [**(@matthewbauer)**](https://github.com/matthewbauer)
- Max “Goldstein” Siling [**(@GoldsteinE)**](https://github.com/GoldsteinE)
- Mingye Wang [**(@Artoria2e5)**](https://github.com/Artoria2e5)
- Philip Taron [**(@philiptaron)**](https://github.com/philiptaron)
- Pierre Bourdon [**(@delroth)**](https://github.com/delroth)
- Pino Toscano [**(@pinotree)**](https://github.com/pinotree)
- RTUnreal [**(@RTUnreal)**](https://github.com/RTUnreal)
- Robert Hensing [**(@roberth)**](https://github.com/roberth)
- Romain Neil [**(@romain-neil)**](https://github.com/romain-neil)
- Ryan Hendrickson [**(@rhendric)**](https://github.com/rhendric)
- Sergei Trofimovich [**(@trofi)**](https://github.com/trofi)
- Shogo Takata [**(@pineapplehunter)**](https://github.com/pineapplehunter)
- Siddhant Kumar [**(@siddhantk232)**](https://github.com/siddhantk232)
- Silvan Mosberger [**(@infinisil)**](https://github.com/infinisil)
- Théophane Hufschmitt [**(@thufschmitt)**](https://github.com/thufschmitt)
- Valentin Gagarin [**(@fricklerhandwerk)**](https://github.com/fricklerhandwerk)
- Winter [**(@winterqt)**](https://github.com/winterqt)
- jade [**(@lf-)**](https://github.com/lf-)
- kirillrdy [**(@kirillrdy)**](https://github.com/kirillrdy)
- pennae [**(@pennae)**](https://github.com/pennae)
- poweredbypie [**(@poweredbypie)**](https://github.com/poweredbypie)
- tomberek [**(@tomberek)**](https://github.com/tomberek)

View file

@ -23,7 +23,7 @@ more than 2800 commits from 195 contributors since release 2.3.
* The **`nix` command** has seen a lot of work and is now almost at * The **`nix` command** has seen a lot of work and is now almost at
feature parity with the old command-line interface (the `nix-*` feature parity with the old command-line interface (the `nix-*`
commands). It aims to be [more modern, consistent and pleasant to commands). It aims to be [more modern, consistent and pleasant to
use](../contributing/cli-guideline.md) than the old CLI. It is still use](../development/cli-guideline.md) than the old CLI. It is still
marked as experimental but its interface should not change much marked as experimental but its interface should not change much
anymore in future releases. anymore in future releases.

View file

@ -82,4 +82,4 @@ In the future, we may support a Git-like hash for such file system objects, or w
[file system object]: ../file-system-object.md [file system object]: ../file-system-object.md
[store object]: ../store-object.md [store object]: ../store-object.md
[xp-feature-git-hashing]: @docroot@/contributing/experimental-features.md#xp-feature-git-hashing [xp-feature-git-hashing]: @docroot@/development/experimental-features.md#xp-feature-git-hashing

View file

@ -92,4 +92,4 @@ becomes more widespread, this restriction will be revisited.
[fso-ca]: ../file-system-object/content-address.md [fso-ca]: ../file-system-object/content-address.md
[sp-spec]: @docroot@/protocols/store-path.md [sp-spec]: @docroot@/protocols/store-path.md
[xp-feature-git-hashing]: @docroot@/contributing/experimental-features.md#xp-feature-git-hashing [xp-feature-git-hashing]: @docroot@/development/experimental-features.md#xp-feature-git-hashing

83
flake.lock generated
View file

@ -3,11 +3,11 @@
"flake-compat": { "flake-compat": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1673956053, "lastModified": 1696426674,
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
"owner": "edolstra", "owner": "edolstra",
"repo": "flake-compat", "repo": "flake-compat",
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -23,11 +23,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1712014858, "lastModified": 1719994518,
"narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=", "narHash": "sha256-pQMhCCHyQGRzdfAkdJ4cIWiw+JNuWsTX7f0ZYSyz0VY=",
"owner": "hercules-ci", "owner": "hercules-ci",
"repo": "flake-parts", "repo": "flake-parts",
"rev": "9126214d0a59633752a136528f5f3b9aa8565b7d", "rev": "9227223f6d922fee3c7b190b2cc238a99527bbb7",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -51,49 +51,60 @@
"type": "github" "type": "github"
} }
}, },
"flake-utils": { "git-hooks-nix": {
"inputs": {
"flake-compat": [],
"gitignore": [],
"nixpkgs": [
"nixpkgs"
],
"nixpkgs-stable": [
"nixpkgs"
]
},
"locked": { "locked": {
"lastModified": 1667395993, "lastModified": 1721042469,
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", "narHash": "sha256-6FPUl7HVtvRHCCBQne7Ylp4p+dpP3P/OYuzjztZ4s70=",
"owner": "numtide", "owner": "cachix",
"repo": "flake-utils", "repo": "git-hooks.nix",
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", "rev": "f451c19376071a90d8c58ab1a953c6e9840527fd",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "numtide", "owner": "cachix",
"repo": "flake-utils", "repo": "git-hooks.nix",
"type": "github" "type": "github"
} }
}, },
"libgit2": { "libgit2": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1697646580, "lastModified": 1715853528,
"narHash": "sha256-oX4Z3S9WtJlwvj0uH9HlYcWv+x1hqp8mhXl7HsLu2f0=", "narHash": "sha256-J2rCxTecyLbbDdsyBWn9w7r3pbKRMkI9E7RvRgAqBdY=",
"owner": "libgit2", "owner": "libgit2",
"repo": "libgit2", "repo": "libgit2",
"rev": "45fd9ed7ae1a9b74b957ef4f337bc3c8b3df01b5", "rev": "36f7e21ad757a3dacc58cf7944329da6bc1d6e96",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "libgit2", "owner": "libgit2",
"ref": "v1.8.1",
"repo": "libgit2", "repo": "libgit2",
"type": "github" "type": "github"
} }
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1717432640, "lastModified": 1721548954,
"narHash": "sha256-+f9c4/ZX5MWDOuB1rKoWj+lBNm0z0rs4CK47HBLxy1o=", "narHash": "sha256-7cCC8+Tdq1+3OPyc3+gVo9dzUNkNIQfwSDJ2HSi2u3o=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "88269ab3044128b7c2f4c7d68448b2fb50456870", "rev": "63d37ccd2d178d54e7fb691d7ec76000740ea24a",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "NixOS", "owner": "NixOS",
"ref": "release-24.05", "ref": "nixos-24.05",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
} }
@ -130,42 +141,16 @@
"type": "github" "type": "github"
} }
}, },
"pre-commit-hooks": {
"inputs": {
"flake-compat": [],
"flake-utils": "flake-utils",
"gitignore": [],
"nixpkgs": [
"nixpkgs"
],
"nixpkgs-stable": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1712897695,
"narHash": "sha256-nMirxrGteNAl9sWiOhoN5tIHyjBbVi5e2tgZUgZlK3Y=",
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"rev": "40e6053ecb65fcbf12863338a6dcefb3f55f1bf8",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"type": "github"
}
},
"root": { "root": {
"inputs": { "inputs": {
"flake-compat": "flake-compat", "flake-compat": "flake-compat",
"flake-parts": "flake-parts", "flake-parts": "flake-parts",
"flake-schemas": "flake-schemas", "flake-schemas": "flake-schemas",
"git-hooks-nix": "git-hooks-nix",
"libgit2": "libgit2", "libgit2": "libgit2",
"nixpkgs": "nixpkgs", "nixpkgs": "nixpkgs",
"nixpkgs-23-11": "nixpkgs-23-11", "nixpkgs-23-11": "nixpkgs-23-11",
"nixpkgs-regression": "nixpkgs-regression", "nixpkgs-regression": "nixpkgs-regression"
"pre-commit-hooks": "pre-commit-hooks"
} }
} }
}, },

View file

@ -1,32 +1,30 @@
{ {
description = "The purely functional package manager"; description = "The purely functional package manager";
# TODO switch to nixos-23.11-small inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05";
# https://nixpk.gs/pr-tracker.html?pr=291954
inputs.nixpkgs.url = "github:NixOS/nixpkgs/release-24.05";
inputs.nixpkgs-regression.url = "github:NixOS/nixpkgs/215d4d0fd80ca5163643b03a33fde804a29cc1e2"; inputs.nixpkgs-regression.url = "github:NixOS/nixpkgs/215d4d0fd80ca5163643b03a33fde804a29cc1e2";
inputs.nixpkgs-23-11.url = "github:NixOS/nixpkgs/a62e6edd6d5e1fa0329b8653c801147986f8d446"; inputs.nixpkgs-23-11.url = "github:NixOS/nixpkgs/a62e6edd6d5e1fa0329b8653c801147986f8d446";
inputs.flake-compat = { url = "github:edolstra/flake-compat"; flake = false; }; inputs.flake-compat = { url = "github:edolstra/flake-compat"; flake = false; };
inputs.libgit2 = { url = "github:libgit2/libgit2"; flake = false; }; inputs.libgit2 = { url = "github:libgit2/libgit2/v1.8.1"; flake = false; };
inputs.flake-schemas.url = "github:DeterminateSystems/flake-schemas"; inputs.flake-schemas.url = "github:DeterminateSystems/flake-schemas";
# dev tooling # dev tooling
inputs.flake-parts.url = "github:hercules-ci/flake-parts"; inputs.flake-parts.url = "github:hercules-ci/flake-parts";
inputs.pre-commit-hooks.url = "github:cachix/pre-commit-hooks.nix"; inputs.git-hooks-nix.url = "github:cachix/git-hooks.nix";
# work around https://github.com/NixOS/nix/issues/7730 # work around https://github.com/NixOS/nix/issues/7730
inputs.flake-parts.inputs.nixpkgs-lib.follows = "nixpkgs"; inputs.flake-parts.inputs.nixpkgs-lib.follows = "nixpkgs";
inputs.pre-commit-hooks.inputs.nixpkgs.follows = "nixpkgs"; inputs.git-hooks-nix.inputs.nixpkgs.follows = "nixpkgs";
inputs.pre-commit-hooks.inputs.nixpkgs-stable.follows = "nixpkgs"; inputs.git-hooks-nix.inputs.nixpkgs-stable.follows = "nixpkgs";
# work around 7730 and https://github.com/NixOS/nix/issues/7807 # work around 7730 and https://github.com/NixOS/nix/issues/7807
inputs.pre-commit-hooks.inputs.flake-compat.follows = ""; inputs.git-hooks-nix.inputs.flake-compat.follows = "";
inputs.pre-commit-hooks.inputs.gitignore.follows = ""; inputs.git-hooks-nix.inputs.gitignore.follows = "";
outputs = inputs@{ self, nixpkgs, nixpkgs-regression, libgit2, flake-schemas, ... }: outputs = inputs@{ self, nixpkgs, nixpkgs-regression, libgit2, flake-schemas, ... }:
let let
inherit (nixpkgs) lib; inherit (nixpkgs) lib;
officialRelease = false; officialRelease = true;
version = lib.fileContents ./.version + versionSuffix; version = lib.fileContents ./.version + versionSuffix;
versionSuffix = versionSuffix =
@ -145,6 +143,7 @@
nix_noTests = final.nix.override { nix_noTests = final.nix.override {
doInstallCheck = false; doInstallCheck = false;
doCheck = false;
}; };
# See https://github.com/NixOS/nixpkgs/pull/214409 # See https://github.com/NixOS/nixpkgs/pull/214409
@ -280,6 +279,7 @@
in in
"-D${prefix}:${rest}"; "-D${prefix}:${rest}";
havePerl = stdenv.buildPlatform == stdenv.hostPlatform && stdenv.hostPlatform.isUnix; havePerl = stdenv.buildPlatform == stdenv.hostPlatform && stdenv.hostPlatform.isUnix;
ignoreCrossFile = flags: builtins.filter (flag: !(lib.strings.hasInfix "cross-file" flag)) flags;
in { in {
pname = "shell-for-" + attrs.pname; pname = "shell-for-" + attrs.pname;
@ -311,10 +311,12 @@
}; };
mesonFlags = mesonFlags =
map (transformFlag "libutil") pkgs.nixComponents.nix-util.mesonFlags map (transformFlag "libutil") (ignoreCrossFile pkgs.nixComponents.nix-util.mesonFlags)
++ map (transformFlag "libstore") pkgs.nixComponents.nix-store.mesonFlags ++ map (transformFlag "libstore") (ignoreCrossFile pkgs.nixComponents.nix-store.mesonFlags)
++ map (transformFlag "libfetchers") pkgs.nixComponents.nix-fetchers.mesonFlags ++ map (transformFlag "libfetchers") (ignoreCrossFile pkgs.nixComponents.nix-fetchers.mesonFlags)
++ lib.optionals havePerl (map (transformFlag "perl") pkgs.nixComponents.nix-perl-bindings.mesonFlags) ++ lib.optionals havePerl (map (transformFlag "perl") (ignoreCrossFile pkgs.nixComponents.nix-perl-bindings.mesonFlags))
++ map (transformFlag "libexpr") (ignoreCrossFile pkgs.nixComponents.nix-expr.mesonFlags)
++ map (transformFlag "libcmd") (ignoreCrossFile pkgs.nixComponents.nix-cmd.mesonFlags)
; ;
nativeBuildInputs = attrs.nativeBuildInputs or [] nativeBuildInputs = attrs.nativeBuildInputs or []
@ -324,8 +326,17 @@
++ lib.optionals havePerl pkgs.nixComponents.nix-perl-bindings.nativeBuildInputs ++ lib.optionals havePerl pkgs.nixComponents.nix-perl-bindings.nativeBuildInputs
++ pkgs.nixComponents.nix-internal-api-docs.nativeBuildInputs ++ pkgs.nixComponents.nix-internal-api-docs.nativeBuildInputs
++ pkgs.nixComponents.nix-external-api-docs.nativeBuildInputs ++ pkgs.nixComponents.nix-external-api-docs.nativeBuildInputs
++ lib.optional
(!stdenv.buildPlatform.canExecute stdenv.hostPlatform
# Hack around https://github.com/nixos/nixpkgs/commit/bf7ad8cfbfa102a90463433e2c5027573b462479
&& !(stdenv.hostPlatform.isWindows && stdenv.buildPlatform.isDarwin)
&& stdenv.hostPlatform.emulatorAvailable pkgs.buildPackages
&& lib.meta.availableOn stdenv.buildPlatform (stdenv.hostPlatform.emulator pkgs.buildPackages))
pkgs.buildPackages.mesonEmulatorHook
++ [ ++ [
pkgs.buildPackages.cmake pkgs.buildPackages.cmake
pkgs.buildPackages.shellcheck
pkgs.buildPackages.changelog-d
modular.pre-commit.settings.package modular.pre-commit.settings.package
(pkgs.writeScriptBin "pre-commit-hooks-install" (pkgs.writeScriptBin "pre-commit-hooks-install"
modular.pre-commit.settings.installationScript) modular.pre-commit.settings.installationScript)

View file

@ -50,7 +50,7 @@ The team meets twice a week (times are denoted in the [Europe/Amsterdam](https:/
- mark it as draft if it is blocked on the contributor - mark it as draft if it is blocked on the contributor
- escalate it back to the team by moving it to To discuss, and leaving a comment as to why the issue needs to be discussed again. - escalate it back to the team by moving it to To discuss, and leaving a comment as to why the issue needs to be discussed again.
- Work meeting: [Mondays 13:00-15:00 Europe/Amsterdam](https://www.google.com/calendar/event?eid=Ym52NDdzYnRic2NzcDcybjZiNDhpNzhpa3NfMjAyNDA1MTNUMTIwMDAwWiBiOW81MmZvYnFqYWs4b3E4bGZraGczdDBxZ0Bn) - Work meeting: [Mondays 14:00-16:00 Europe/Amsterdam](https://www.google.com/calendar/event?eid=Ym52NDdzYnRic2NzcDcybjZiNDhpNzhpa3NfMjAyNDA1MTNUMTIwMDAwWiBiOW81MmZvYnFqYWs4b3E4bGZraGczdDBxZ0Bn)
1. Code review on pull requests from [In review](#in-review). 1. Code review on pull requests from [In review](#in-review).
2. Other chores and tasks. 2. Other chores and tasks.

View file

@ -0,0 +1,52 @@
{
"bogus": "bogus",
"edolstra@gmail.com": "edolstra",
"roberth@users.noreply.github.com": "roberth",
"toscano.pino@tiscali.it": "pinotree",
"valentin@gagarin.work": "fricklerhandwerk",
"mr.trubach@icloud.com": "tie",
"robert@roberthensing.nl": "roberth",
"lix@jade.fyi": "lf-",
"cole.e.helbling@outlook.com": "cole-h",
"joerg@thalheim.io": "Mic92",
"John.Ericson@Obsidian.Systems": "Ericson2314",
"ryan.hendrickson@alum.mit.edu": "rhendric",
"67135060+poweredbypie@users.noreply.github.com": "poweredbypie",
"detroyejr@outlook.com": "detroyejr",
"silvan.mosberger@tweag.io": "infinisil",
"vcs@emily.moe": "emilazy",
"farid.m.zakaria@gmail.com": "fzakaria",
"22859658+RTUnreal@users.noreply.github.com": "RTUnreal",
"me@las.rs": "L-as",
"philip.taron@gmail.com": "philiptaron",
"root@goldstein.rs": "GoldsteinE",
"tomberek@users.noreply.github.com": "tomberek",
"lexi.mattick@neuralink.com": "kognise",
"andrew@johnandrewmarshall.com": "amarshall",
"contact@romain-neil.fr": "romain-neil",
"Mic92@users.noreply.github.com": "Mic92",
"valentin.gagarin@tweag.io": "fricklerhandwerk",
"siddhantk232@gmail.com": "siddhantk232",
"kn@openbsd.org": "klemensn",
"slyich@gmail.com": "trofi",
"theophane.hufschmitt@tweag.io": "thufschmitt",
"alicebob@lijzij.de": "alicebob",
"winter@winter.cafe": "winterqt",
"brian@brianmckenna.org": "puffnfresh",
"git@haenoe.party": "haenoe",
"peshogo@gmail.com": "pineapplehunter",
"poweredbypie@users.noreply.github.com": "poweredbypie",
"arthur200126@gmail.com": "Artoria2e5",
"tomberek@gmail.com": "tomberek",
"jaredbaur@fastmail.com": "jmbaur",
"andreas@rammhold.de": "andir",
"hamirmahal@gmail.com": "hamirmahal",
"git@JohnEricson.me": "Ericson2314",
"8763518+SkamDart@users.noreply.github.com": "SkamDart",
"kirillrdy@gmail.com": "kirillrdy",
"pennae@lix.systems": "pennae",
"delroth@gmail.com": "delroth",
"enno@nerdworks.de": "elohmeier",
"mjbauer95@gmail.com": "matthewbauer",
"MostAwesomeDude@gmail.com": "MostAwesomeDude"
}

View file

@ -0,0 +1,45 @@
{
"fzakaria": "Farid Zakaria",
"kognise": "Lexi Mattick",
"L-as": "Las Safin",
"haenoe": "HaeNoe",
"andir": "Andreas Rammhold",
"matthewbauer": "Matthew Bauer",
"emilazy": "Emily",
"pineapplehunter": "Shogo Takata",
"RTUnreal": null,
"jmbaur": "Jared Baur",
"Ericson2314": "John Ericson",
"pinotree": "Pino Toscano",
"tie": "Ivan Trubach",
"poweredbypie": null,
"fricklerhandwerk": "Valentin Gagarin",
"Mic92": "J\u00f6rg Thalheim",
"alicebob": "Harmen",
"elohmeier": "Enno Richter",
"delroth": "Pierre Bourdon",
"kirillrdy": null,
"thufschmitt": "Th\u00e9ophane Hufschmitt",
"detroyejr": "Jonathan De Troye",
"klemensn": "Klemens Nanni",
"tomberek": null,
"rhendric": "Ryan Hendrickson",
"philiptaron": "Philip Taron",
"puffnfresh": "Brian McKenna",
"lf-": "jade",
"romain-neil": "Romain Neil",
"hamirmahal": "Hamir Mahal",
"edolstra": "Eelco Dolstra",
"Artoria2e5": "Mingye Wang",
"SkamDart": "Cameron",
"roberth": "Robert Hensing",
"amarshall": "Andrew Marshall",
"trofi": "Sergei Trofimovich",
"cole-h": "Cole Helbling",
"infinisil": "Silvan Mosberger",
"siddhantk232": "Siddhant Kumar",
"winterqt": "Winter",
"GoldsteinE": "Max \u201cGoldstein\u201d Siling",
"pennae": null,
"MostAwesomeDude": "Corbin Simpson"
}

View file

@ -2,7 +2,7 @@
{ {
imports = [ imports = [
inputs.pre-commit-hooks.flakeModule inputs.git-hooks-nix.flakeModule
]; ];
perSystem = { config, pkgs, ... }: { perSystem = { config, pkgs, ... }: {
@ -495,7 +495,6 @@
excludes = [ excludes = [
# We haven't linted these files yet # We haven't linted these files yet
''^config/install-sh$'' ''^config/install-sh$''
''^misc/systemv/nix-daemon$''
''^misc/bash/completion\.sh$'' ''^misc/bash/completion\.sh$''
''^misc/fish/completion\.fish$'' ''^misc/fish/completion\.fish$''
''^misc/zsh/completion\.zsh$'' ''^misc/zsh/completion\.zsh$''

184
maintainers/release-credits Executable file
View file

@ -0,0 +1,184 @@
#!/usr/bin/env nix
# vim: set filetype=python:
#!nix develop --impure --expr
#!nix ``
#!nix let flake = builtins.getFlake ("git+file://" + toString ../.);
#!nix pkgs = flake.inputs.nixpkgs.legacyPackages.${builtins.currentSystem};
#!nix in pkgs.mkShell { nativeBuildInputs = [
#!nix (pkgs.python3.withPackages (ps: with ps; [ requests ]))
#!nix ]; }
#!nix `` --command python3
# This script lists out the contributors for a given release.
# It must be run from the root of the Nix repository.
import os
import sys
import json
import requests
github_token = os.environ.get("GITHUB_TOKEN")
if not github_token:
print("GITHUB_TOKEN is not set. If you hit the rate limit, set it", file=sys.stderr)
# Might be ok, as we have a cache.
# raise ValueError("GITHUB_TOKEN must be set")
# 1. Read the current version in .version
version = os.environ.get("VERSION")
if not version:
version = open(".version").read().strip()
print(f"Generating release credits for Nix {version}", file=sys.stderr)
# 2. Compute previous version
vcomponents = version.split(".")
if len(vcomponents) >= 2:
prev_version = f"{vcomponents[0]}.{int(vcomponents[1])-1}.0"
else:
raise ValueError(".version must have at least two components")
# For unreleased versions
endref = "HEAD"
# For older releases
# endref = version
# 2. Find the merge base between the current version and the previous version
mergeBase = os.popen(f"git merge-base {prev_version} {endref}").read().strip()
print(f"Merge base between {prev_version} and {endref} is {mergeBase}", file=sys.stderr)
# 3. Find the date of the merge base
mergeBaseDate = os.popen(f"git show -s --format=%ci {mergeBase}").read().strip()[0:10]
print(f"Merge base date is {mergeBaseDate}", file=sys.stderr)
# 4. Get the commits between the merge base and the current version
def get_commits():
raw = os.popen(f"git log --pretty=format:'%H\t%an\t%ae' {mergeBase}..{endref}").read().strip()
lines = raw.split("\n")
return [ { "hash": items[0], "author": items[1], "email": items[2] }
for line in lines
for items in (line.split("\t"),)
]
def commits_to_first_commit_by_email(commits):
by_email = dict()
for commit in commits:
email = commit["email"]
if email not in by_email:
by_email[email] = commit
return by_email
samples = commits_to_first_commit_by_email(get_commits())
# For quick testing, only pick two samples from the dict
# samples = dict(list(samples.items())[:2])
# Query the GitHub API to get handle
def get_github_commit(commit):
url = f"https://api.github.com/repos/NixOS/nix/commits/{commit['hash']}"
headers = {'Authorization': f'token {github_token}'}
response = requests.get(url, headers=headers)
response.raise_for_status()
return response.json()
class Cache:
def __init__(self, filename, require = True):
self.filename = filename
try:
with open(filename, "r") as f:
self.values = json.load(f)
except FileNotFoundError:
if require:
raise
self.values = dict()
def save(self):
with open(self.filename, "w") as f:
json.dump(self.values, f, indent=4)
print(f"Saved cache to {self.filename}", file=sys.stderr)
# The email to handle cache maps email addresses to either
# - a handle (string)
# - None (if no handle was found)
email_to_handle_cache = Cache("maintainers/data/release-credits-email-to-handle.json")
handles = set()
emails = dict()
for sample in samples:
s = samples[sample]
email = s["email"]
if not email in email_to_handle_cache.values:
print(f"Querying GitHub API for {s['hash']}, to get handle for {s['email']}")
ghc = get_github_commit(samples[sample])
gha = ghc["author"]
if gha and gha["login"]:
handle = gha["login"]
print(f"Handle: {handle}")
email_to_handle_cache.values[email] = handle
else:
print(f"Found no handle for {s['email']}")
email_to_handle_cache.values[email] = None
handle = email_to_handle_cache.values[email]
if handle is not None:
handles.add(handle)
else:
emails[email] = s["author"]
# print(email_to_handle_cache.values)
email_to_handle_cache.save()
handle_to_name_cache = Cache("maintainers/data/release-credits-handle-to-name.json")
print(f"Found {len(handles)} handles", file=sys.stderr)
for handle in handles:
if not handle in handle_to_name_cache.values:
print(f"Querying GitHub API for {handle}, to get name", file=sys.stderr)
url = f"https://api.github.com/users/{handle}"
headers = {'Authorization': f'token {github_token}'}
response = requests.get(url, headers=headers)
response.raise_for_status()
user = response.json()
name = user["name"]
print(f"Name: {name}", file=sys.stderr)
handle_to_name_cache.values[handle] = name
handle_to_name_cache.save()
entries = list()
def is_bot(handle):
return handle.endswith("[bot]")
for handle in handles:
name = handle_to_name_cache.values[handle]
if name is None:
# This way it looks more regular
name = handle
# Note to bots: I'm only doing this because it would distract humans, and
# therefore delay your creation. I'm sorry; it's for your benefit.
if not is_bot(handle):
entries += [ f"- {name} [**(@{handle})**](https://github.com/{handle})" ]
def shuffle(entries):
salt = os.urandom(16)
return sorted(entries, key=lambda x: hash((x, salt)))
# Fair ordering is undecidable
entries = shuffle(entries)
# For a sanity check, we could sort the entries by handle instead.
# entries = sorted(entries)
print("")
print(f"This release was made possible by the following {len(entries)} contributors:")
print("")
for entry in entries:
print(entry)
for email in emails:
print(f"- {emails[email]}")

View file

@ -1,4 +1,5 @@
#!/usr/bin/env nix #!/usr/bin/env nix
# vim: set filetype=bash:
#!nix shell .#changelog-d --command bash #!nix shell .#changelog-d --command bash
# --- CONFIGURATION --- # --- CONFIGURATION ---
@ -151,6 +152,13 @@ section_title="Release $version_full ($DATE)"
echo "# $section_title" echo "# $section_title"
echo echo
changelog-d doc/manual/rl-next | sed -e 's/ *$//' changelog-d doc/manual/rl-next | sed -e 's/ *$//'
if ! $IS_PATCH; then
echo
echo "# Contributors"
echo
VERSION=$version_full ./maintainers/release-credits
fi
) | tee -a $file ) | tee -a $file
log "Wrote $file" log "Wrote $file"

View file

@ -39,6 +39,10 @@ release:
* Proof-read / edit / rearrange the release notes if needed. Breaking changes * Proof-read / edit / rearrange the release notes if needed. Breaking changes
and highlights should go to the top. and highlights should go to the top.
* Run `maintainers/release-credits` to make sure the credits script works
and produces a sensible output. Some emails might not automatically map to
a GitHub handle.
* Push. * Push.
```console ```console

View file

@ -26,9 +26,12 @@ subproject('external-api-docs')
subproject('libutil-c') subproject('libutil-c')
subproject('libstore-c') subproject('libstore-c')
subproject('libexpr-c') subproject('libexpr-c')
subproject('libmain-c')
# Language Bindings # Language Bindings
subproject('perl') if not meson.is_cross_build()
subproject('perl')
endif
# Testing # Testing
subproject('nix-util-test-support') subproject('nix-util-test-support')

View file

@ -34,6 +34,7 @@ else
fi fi
# Source function library. # Source function library.
# shellcheck source=/dev/null
. /etc/init.d/functions . /etc/init.d/functions
LOCKFILE=/var/lock/subsys/nix-daemon LOCKFILE=/var/lock/subsys/nix-daemon
@ -41,14 +42,20 @@ RUNDIR=/var/run/nix
PIDFILE=${RUNDIR}/nix-daemon.pid PIDFILE=${RUNDIR}/nix-daemon.pid
RETVAL=0 RETVAL=0
base=${0##*/} # https://www.shellcheck.net/wiki/SC3004
# Check if gettext exists
if ! type gettext > /dev/null 2>&1
then
# If not, create a dummy function that returns the input verbatim
gettext() { printf '%s' "$1"; }
fi
start() { start() {
mkdir -p ${RUNDIR} mkdir -p ${RUNDIR}
chown ${NIX_DAEMON_USER}:${NIX_DAEMON_USER} ${RUNDIR} chown ${NIX_DAEMON_USER}:${NIX_DAEMON_USER} ${RUNDIR}
echo -n $"Starting nix daemon... " printf '%s' "$(gettext 'Starting nix daemon... ')"
daemonize -u $NIX_DAEMON_USER -p ${PIDFILE} $NIX_DAEMON_BIN $NIX_DAEMON_OPTS daemonize -u $NIX_DAEMON_USER -p ${PIDFILE} $NIX_DAEMON_BIN $NIX_DAEMON_OPTS
RETVAL=$? RETVAL=$?
@ -58,7 +65,7 @@ start() {
} }
stop() { stop() {
echo -n $"Shutting down nix daemon: " printf '%s' "$(gettext 'Shutting down nix daemon: ')"
killproc -p ${PIDFILE} $NIX_DAEMON_BIN killproc -p ${PIDFILE} $NIX_DAEMON_BIN
RETVAL=$? RETVAL=$?
[ $RETVAL -eq 0 ] && rm -f ${LOCKFILE} ${PIDFILE} [ $RETVAL -eq 0 ] && rm -f ${LOCKFILE} ${PIDFILE}
@ -67,7 +74,7 @@ stop() {
} }
reload() { reload() {
echo -n $"Reloading nix daemon... " printf '%s' "$(gettext 'Reloading nix daemon... ')"
killproc -p ${PIDFILE} $NIX_DAEMON_BIN -HUP killproc -p ${PIDFILE} $NIX_DAEMON_BIN -HUP
RETVAL=$? RETVAL=$?
echo echo
@ -105,7 +112,7 @@ case "$1" in
fi fi
;; ;;
*) *)
echo $"Usage: $0 {start|stop|status|restart|condrestart}" printf '%s' "$(gettext "Usage: $0 {start|stop|status|restart|condrestart}")"
exit 2 exit 2
;; ;;
esac esac

View file

@ -29,4 +29,8 @@ ifdef HOST_OS
HOST_SOLARIS = 1 HOST_SOLARIS = 1
HOST_UNIX = 1 HOST_UNIX = 1
endif endif
ifeq ($(HOST_KERNEL), gnu)
HOST_HURD = 1
HOST_UNIX = 1
endif
endif endif

View file

@ -28,7 +28,7 @@ run_test
if [[ "$status" = 0 ]]; then if [[ "$status" = 0 ]]; then
echo "$post_run_msg [${green}PASS$normal]" echo "$post_run_msg [${green}PASS$normal]"
elif [[ "$status" = 99 ]]; then elif [[ "$status" = 77 ]]; then
echo "$post_run_msg [${yellow}SKIP$normal]" echo "$post_run_msg [${yellow}SKIP$normal]"
else else
echo "$post_run_msg [${red}FAIL$normal]" echo "$post_run_msg [${red}FAIL$normal]"

View file

@ -218,7 +218,8 @@ in {
] ++ lib.optional stdenv.hostPlatform.isStatic unixtools.hexdump ] ++ lib.optional stdenv.hostPlatform.isStatic unixtools.hexdump
; ;
buildInputs = lib.optionals doBuild [ buildInputs = lib.optionals doBuild (
[
brotli brotli
bzip2 bzip2
curl curl
@ -239,16 +240,14 @@ in {
++ lib.optional stdenv.hostPlatform.isx86_64 libcpuid ++ lib.optional stdenv.hostPlatform.isx86_64 libcpuid
# There have been issues building these dependencies # There have been issues building these dependencies
++ lib.optional (stdenv.hostPlatform == stdenv.buildPlatform && (stdenv.isLinux || stdenv.isDarwin)) ++ lib.optional (stdenv.hostPlatform == stdenv.buildPlatform && (stdenv.isLinux || stdenv.isDarwin))
(aws-sdk-cpp.override { aws-sdk-cpp
apis = ["s3" "transfer"]; );
customMemoryManagement = false;
})
;
propagatedBuildInputs = [ propagatedBuildInputs = lib.optionals doBuild ([
boost boost
nlohmann_json nlohmann_json
] ++ lib.optional enableGC boehmgc; ] ++ lib.optional enableGC boehmgc
);
dontBuild = !attrs.doBuild; dontBuild = !attrs.doBuild;
doCheck = attrs.doCheck; doCheck = attrs.doCheck;

View file

@ -29,6 +29,7 @@ in
nix-flake-tests = callPackage ../tests/unit/libflake/package.nix { }; nix-flake-tests = callPackage ../tests/unit/libflake/package.nix { };
nix-main = callPackage ../src/libmain/package.nix { }; nix-main = callPackage ../src/libmain/package.nix { };
nix-main-c = callPackage ../src/libmain-c/package.nix { };
nix-cmd = callPackage ../src/libcmd/package.nix { }; nix-cmd = callPackage ../src/libcmd/package.nix { };

View file

@ -61,11 +61,33 @@ let
workDir = null; workDir = null;
}; };
# Work around weird `--as-needed` linker behavior with BSD, see
# https://github.com/mesonbuild/meson/issues/3593
bsdNoLinkAsNeeded = finalAttrs: prevAttrs:
lib.optionalAttrs stdenv.hostPlatform.isBSD {
mesonFlags = [ (lib.mesonBool "b_asneeded" false) ] ++ prevAttrs.mesonFlags or [];
};
miscGoodPractice = finalAttrs: prevAttrs:
{
strictDeps = prevAttrs.strictDeps or true;
enableParallelBuilding = true;
};
in in
scope: { scope: {
inherit stdenv versionSuffix; inherit stdenv versionSuffix;
version = lib.fileContents ../.version + versionSuffix; version = lib.fileContents ../.version + versionSuffix;
aws-sdk-cpp = (pkgs.aws-sdk-cpp.override {
apis = [ "s3" "transfer" ];
customMemoryManagement = false;
}).overrideAttrs {
# only a stripped down version is built, which takes a lot less resources
# to build, so we don't need a "big-parallel" machine.
requiredSystemFeatures = [ ];
};
libseccomp = pkgs.libseccomp.overrideAttrs (_: rec { libseccomp = pkgs.libseccomp.overrideAttrs (_: rec {
version = "2.5.5"; version = "2.5.5";
src = pkgs.fetchurl { src = pkgs.fetchurl {
@ -130,7 +152,16 @@ scope: {
inherit resolvePath filesetToSource; inherit resolvePath filesetToSource;
mkMesonDerivation = f: stdenv.mkDerivation (lib.extends localSourceLayer f); mkMesonDerivation = f: let
exts = [
miscGoodPractice
bsdNoLinkAsNeeded
localSourceLayer
];
in stdenv.mkDerivation
(lib.extends
(lib.foldr lib.composeExtensions (_: _: {}) exts)
f);
inherit (inputs) flake-schemas; inherit (inputs) flake-schemas;
} }

View file

@ -54,6 +54,7 @@ let
"nix-flake" "nix-flake"
"nix-flake-tests" "nix-flake-tests"
"nix-main" "nix-main"
"nix-main-c"
"nix-cmd" "nix-cmd"
"nix-ng" "nix-ng"
]; ];

View file

@ -11,6 +11,7 @@
#include "machines.hh" #include "machines.hh"
#include "shared.hh" #include "shared.hh"
#include "plugin.hh"
#include "pathlocks.hh" #include "pathlocks.hh"
#include "globals.hh" #include "globals.hh"
#include "serialise.hh" #include "serialise.hh"
@ -100,7 +101,7 @@ static int main_build_remote(int argc, char * * argv)
} }
std::optional<StorePath> drvPath; std::optional<StorePath> drvPath;
StoreReference storeUri; std::string storeUri;
while (true) { while (true) {
@ -233,17 +234,16 @@ static int main_build_remote(int argc, char * * argv)
lock = -1; lock = -1;
try { try {
storeUri = bestMachine->storeUri.render();
Activity act(*logger, lvlTalkative, actUnknown, fmt("connecting to '%s'", bestMachine->storeUri.render())); Activity act(*logger, lvlTalkative, actUnknown, fmt("connecting to '%s'", storeUri));
sshStore = bestMachine->openStore(); sshStore = bestMachine->openStore();
sshStore->connect(); sshStore->connect();
storeUri = bestMachine->storeUri;
} catch (std::exception & e) { } catch (std::exception & e) {
auto msg = chomp(drainFD(5, false)); auto msg = chomp(drainFD(5, false));
printError("cannot build on '%s': %s%s", printError("cannot build on '%s': %s%s",
bestMachine->storeUri.render(), e.what(), storeUri, e.what(),
msg.empty() ? "" : ": " + msg); msg.empty() ? "" : ": " + msg);
bestMachine->enabled = false; bestMachine->enabled = false;
continue; continue;
@ -258,15 +258,28 @@ connected:
assert(sshStore); assert(sshStore);
std::cerr << "# accept\n" << storeUri.render() << "\n"; std::cerr << "# accept\n" << storeUri << "\n";
auto inputs = readStrings<PathSet>(source); auto inputs = readStrings<PathSet>(source);
auto wantedOutputs = readStrings<StringSet>(source); auto wantedOutputs = readStrings<StringSet>(source);
AutoCloseFD uploadLock = openLockFile(currentLoad + "/" + escapeUri(storeUri.render()) + ".upload-lock", true); AutoCloseFD uploadLock;
{
auto setUpdateLock = [&](auto && fileName){
uploadLock = openLockFile(currentLoad + "/" + escapeUri(fileName) + ".upload-lock", true);
};
try {
setUpdateLock(storeUri);
} catch (SysError & e) {
if (e.errNo != ENAMETOOLONG) throw;
// Try again hashing the store URL so we have a shorter path
auto h = hashString(HashAlgorithm::MD5, storeUri);
setUpdateLock(h.to_string(HashFormat::Base64, false));
}
}
{ {
Activity act(*logger, lvlTalkative, actUnknown, fmt("waiting for the upload lock to '%s'", storeUri.render())); Activity act(*logger, lvlTalkative, actUnknown, fmt("waiting for the upload lock to '%s'", storeUri));
auto old = signal(SIGALRM, handleAlarm); auto old = signal(SIGALRM, handleAlarm);
alarm(15 * 60); alarm(15 * 60);
@ -279,7 +292,7 @@ connected:
auto substitute = settings.buildersUseSubstitutes ? Substitute : NoSubstitute; auto substitute = settings.buildersUseSubstitutes ? Substitute : NoSubstitute;
{ {
Activity act(*logger, lvlTalkative, actUnknown, fmt("copying dependencies to '%s'", storeUri.render())); Activity act(*logger, lvlTalkative, actUnknown, fmt("copying dependencies to '%s'", storeUri));
copyPaths(*store, *sshStore, store->parseStorePathSet(inputs), NoRepair, NoCheckSigs, substitute); copyPaths(*store, *sshStore, store->parseStorePathSet(inputs), NoRepair, NoCheckSigs, substitute);
} }
@ -317,7 +330,7 @@ connected:
optResult = sshStore->buildDerivation(*drvPath, (const BasicDerivation &) drv); optResult = sshStore->buildDerivation(*drvPath, (const BasicDerivation &) drv);
auto & result = *optResult; auto & result = *optResult;
if (!result.success()) if (!result.success())
throw Error("build of '%s' on '%s' failed: %s", store->printStorePath(*drvPath), storeUri.render(), result.errorMsg); throw Error("build of '%s' on '%s' failed: %s", store->printStorePath(*drvPath), storeUri, result.errorMsg);
} else { } else {
copyClosure(*store, *sshStore, StorePathSet {*drvPath}, NoRepair, NoCheckSigs, substitute); copyClosure(*store, *sshStore, StorePathSet {*drvPath}, NoRepair, NoCheckSigs, substitute);
auto res = sshStore->buildPathsWithResults({ auto res = sshStore->buildPathsWithResults({
@ -360,7 +373,7 @@ connected:
} }
if (!missingPaths.empty()) { if (!missingPaths.empty()) {
Activity act(*logger, lvlTalkative, actUnknown, fmt("copying outputs from '%s'", storeUri.render())); Activity act(*logger, lvlTalkative, actUnknown, fmt("copying outputs from '%s'", storeUri));
if (auto localStore = store.dynamic_pointer_cast<LocalStore>()) if (auto localStore = store.dynamic_pointer_cast<LocalStore>())
for (auto & path : missingPaths) for (auto & path : missingPaths)
localStore->locksHeld.insert(store->printStorePath(path)); /* FIXME: ugly */ localStore->locksHeld.insert(store->printStorePath(path)); /* FIXME: ugly */

View file

@ -53,10 +53,6 @@ mkMesonDerivation (finalAttrs: {
echo "doc external-api-docs $out/share/doc/nix/external-api/html" >> ''${!outputDoc}/nix-support/hydra-build-products echo "doc external-api-docs $out/share/doc/nix/external-api/html" >> ''${!outputDoc}/nix-support/hydra-build-products
''; '';
enableParallelBuilding = true;
strictDeps = true;
meta = { meta = {
platforms = lib.platforms.all; platforms = lib.platforms.all;
}; };

View file

@ -48,10 +48,6 @@ mkMesonDerivation (finalAttrs: {
echo "doc internal-api-docs $out/share/doc/nix/internal-api/html" >> ''${!outputDoc}/nix-support/hydra-build-products echo "doc internal-api-docs $out/share/doc/nix/internal-api/html" >> ''${!outputDoc}/nix-support/hydra-build-products
''; '';
enableParallelBuilding = true;
strictDeps = true;
meta = { meta = {
platforms = lib.platforms.all; platforms = lib.platforms.all;
}; };

View file

@ -90,75 +90,11 @@ MixEvalArgs::MixEvalArgs()
.longName = "include", .longName = "include",
.shortName = 'I', .shortName = 'I',
.description = R"( .description = R"(
Add *path* to the Nix search path. The Nix search path is Add *path* to search path entries used to resolve [lookup paths](@docroot@/language/constructs/lookup-path.md)
initialized from the colon-separated [`NIX_PATH`](@docroot@/command-ref/env-common.md#env-NIX_PATH) environment
variable, and is used to look up the location of Nix expressions using [paths](@docroot@/language/types.md#type-path) enclosed in angle
brackets (i.e., `<nixpkgs>`).
For instance, passing This option may be given multiple times.
``` Paths added through `-I` take precedence over the [`nix-path` configuration setting](@docroot@/command-ref/conf-file.md#conf-nix-path) and the [`NIX_PATH` environment variable](@docroot@/command-ref/env-common.md#env-NIX_PATH).
-I /home/eelco/Dev
-I /etc/nixos
```
will cause Nix to look for paths relative to `/home/eelco/Dev` and
`/etc/nixos`, in that order. This is equivalent to setting the
`NIX_PATH` environment variable to
```
/home/eelco/Dev:/etc/nixos
```
It is also possible to match paths against a prefix. For example,
passing
```
-I nixpkgs=/home/eelco/Dev/nixpkgs-branch
-I /etc/nixos
```
will cause Nix to search for `<nixpkgs/path>` in
`/home/eelco/Dev/nixpkgs-branch/path` and `/etc/nixos/nixpkgs/path`.
If a path in the Nix search path starts with `http://` or `https://`,
it is interpreted as the URL of a tarball that will be downloaded and
unpacked to a temporary location. The tarball must consist of a single
top-level directory. For example, passing
```
-I nixpkgs=https://github.com/NixOS/nixpkgs/archive/master.tar.gz
```
tells Nix to download and use the current contents of the `master`
branch in the `nixpkgs` repository.
The URLs of the tarballs from the official `nixos.org` channels
(see [the manual page for `nix-channel`](../nix-channel.md)) can be
abbreviated as `channel:<channel-name>`. For instance, the
following two flags are equivalent:
```
-I nixpkgs=channel:nixos-21.05
-I nixpkgs=https://nixos.org/channels/nixos-21.05/nixexprs.tar.xz
```
You can also fetch source trees using [flake URLs](./nix3-flake.md#url-like-syntax) and add them to the
search path. For instance,
```
-I nixpkgs=flake:nixpkgs
```
specifies that the prefix `nixpkgs` shall refer to the source tree
downloaded from the `nixpkgs` entry in the flake registry. Similarly,
```
-I nixpkgs=flake:github:NixOS/nixpkgs/nixos-22.05
```
makes `<nixpkgs>` refer to a particular branch of the
`NixOS/nixpkgs` repository on GitHub.
)", )",
.category = category, .category = category,
.labels = {"path"}, .labels = {"path"},
@ -213,7 +149,7 @@ Bindings * MixEvalArgs::getAutoArgs(EvalState & state)
auto v = state.allocValue(); auto v = state.allocValue();
std::visit(overloaded { std::visit(overloaded {
[&](const AutoArgExpr & arg) { [&](const AutoArgExpr & arg) {
state.mkThunk_(*v, state.parseExprFromString(arg.expr, state.rootPath("."))); state.mkThunk_(*v, state.parseExprFromString(arg.expr, compatibilitySettings.nixShellShebangArgumentsRelativeToScript ? state.rootPath(absPath(getCommandBaseDir())) : state.rootPath(".")));
}, },
[&](const AutoArgString & arg) { [&](const AutoArgString & arg) {
v->mkString(arg.s); v->mkString(arg.s);

View file

@ -7,12 +7,29 @@ struct CompatibilitySettings : public Config
CompatibilitySettings() = default; CompatibilitySettings() = default;
// Added in Nix 2.24, July 2024.
Setting<bool> nixShellAlwaysLooksForShellNix{this, true, "nix-shell-always-looks-for-shell-nix", R"( Setting<bool> nixShellAlwaysLooksForShellNix{this, true, "nix-shell-always-looks-for-shell-nix", R"(
Before Nix 2.24, [`nix-shell`](@docroot@/command-ref/nix-shell.md) would only look at `shell.nix` if it was in the working directory - when no file was specified. Before Nix 2.24, [`nix-shell`](@docroot@/command-ref/nix-shell.md) would only look at `shell.nix` if it was in the working directory - when no file was specified.
Since Nix 2.24, `nix-shell` always looks for a `shell.nix`, whether that's in the working directory, or in a directory that was passed as an argument. Since Nix 2.24, `nix-shell` always looks for a `shell.nix`, whether that's in the working directory, or in a directory that was passed as an argument.
You may set this to `false` to revert to the Nix 2.3 behavior. You may set this to `false` to temporarily revert to the behavior of Nix 2.23 and older.
Using this setting is not recommended.
It will be deprecated and removed.
)"};
// Added in Nix 2.24, July 2024.
Setting<bool> nixShellShebangArgumentsRelativeToScript{
this, true, "nix-shell-shebang-arguments-relative-to-script", R"(
Before Nix 2.24, relative file path expressions in arguments in a `nix-shell` shebang were resolved relative to the working directory.
Since Nix 2.24, `nix-shell` resolves these paths in a manner that is relative to the [base directory](@docroot@/glossary.md#gloss-base-directory), defined as the script's directory.
You may set this to `false` to temporarily revert to the behavior of Nix 2.23 and older.
Using this setting is not recommended.
It will be deprecated and removed.
)"}; )"};
}; };

View file

@ -66,7 +66,7 @@ struct ExtraPathInfoValue : ExtraPathInfo
}; };
/** /**
* An Installable which corresponds a Nix langauge value, in addition to * An Installable which corresponds a Nix language value, in addition to
* a collection of \ref DerivedPath "derived paths". * a collection of \ref DerivedPath "derived paths".
*/ */
struct InstallableValue : Installable struct InstallableValue : Installable

View file

@ -1,21 +1,23 @@
#include "markdown.hh" #include "markdown.hh"
#include "util.hh" #include "environment-variables.hh"
#include "error.hh"
#include "finally.hh" #include "finally.hh"
#include "terminal.hh" #include "terminal.hh"
#if HAVE_LOWDOWN #if HAVE_LOWDOWN
# include <sys/queue.h> # include <sys/queue.h>
# include <lowdown.h> # include <lowdown.h>
#endif #endif
namespace nix { namespace nix {
std::string renderMarkdownToTerminal(std::string_view markdown)
{
#if HAVE_LOWDOWN #if HAVE_LOWDOWN
static std::string doRenderMarkdownToTerminal(std::string_view markdown)
{
int windowWidth = getWindowSize().second; int windowWidth = getWindowSize().second;
struct lowdown_opts opts { struct lowdown_opts opts
{
.type = LOWDOWN_TERM, .type = LOWDOWN_TERM,
.maxdepth = 20, .maxdepth = 20,
.cols = (size_t) std::max(windowWidth - 5, 60), .cols = (size_t) std::max(windowWidth - 5, 60),
@ -51,9 +53,21 @@ std::string renderMarkdownToTerminal(std::string_view markdown)
throw Error("allocation error while rendering Markdown"); throw Error("allocation error while rendering Markdown");
return filterANSIEscapes(std::string(buf->data, buf->size), !isTTY()); return filterANSIEscapes(std::string(buf->data, buf->size), !isTTY());
#else
return std::string(markdown);
#endif
} }
std::string renderMarkdownToTerminal(std::string_view markdown)
{
if (auto e = getEnv("_NIX_TEST_RAW_MARKDOWN"); e && *e == "1")
return std::string(markdown);
else
return doRenderMarkdownToTerminal(markdown);
} }
#else
std::string renderMarkdownToTerminal(std::string_view markdown)
{
return std::string(markdown);
}
#endif
} // namespace nix

View file

@ -1,10 +1,17 @@
#pragma once #pragma once
///@file ///@file
#include "types.hh" #include <string_view>
namespace nix { namespace nix {
/**
* Render the given Markdown text to the terminal.
*
* If Nix is compiled without Markdown support, this function will return the input text as-is.
*
* The renderer takes into account the terminal width, and wraps text accordingly.
*/
std::string renderMarkdownToTerminal(std::string_view markdown); std::string renderMarkdownToTerminal(std::string_view markdown);
} }

View file

@ -30,6 +30,8 @@ deps_public_maybe_subproject = [
] ]
subdir('build-utils-meson/subprojects') subdir('build-utils-meson/subprojects')
subdir('build-utils-meson/threads')
nlohmann_json = dependency('nlohmann_json', version : '>= 3.9') nlohmann_json = dependency('nlohmann_json', version : '>= 3.9')
deps_public += nlohmann_json deps_public += nlohmann_json

View file

@ -93,14 +93,8 @@ mkMesonDerivation (finalAttrs: {
LDFLAGS = "-fuse-ld=gold"; LDFLAGS = "-fuse-ld=gold";
}; };
enableParallelBuilding = true;
separateDebugInfo = !stdenv.hostPlatform.isStatic; separateDebugInfo = !stdenv.hostPlatform.isStatic;
# TODO `releaseTools.coverageAnalysis` in Nixpkgs needs to be updated
# to work with `strictDeps`.
strictDeps = true;
hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie"; hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie";
meta = { meta = {

View file

@ -19,6 +19,7 @@ extern "C" {
#include "repl-interacter.hh" #include "repl-interacter.hh"
#include "file-system.hh" #include "file-system.hh"
#include "repl.hh" #include "repl.hh"
#include "environment-variables.hh"
namespace nix { namespace nix {
@ -34,6 +35,7 @@ void sigintHandler(int signo)
static detail::ReplCompleterMixin * curRepl; // ugly static detail::ReplCompleterMixin * curRepl; // ugly
#ifndef USE_READLINE
static char * completionCallback(char * s, int * match) static char * completionCallback(char * s, int * match)
{ {
auto possible = curRepl->completePrefix(s); auto possible = curRepl->completePrefix(s);
@ -100,6 +102,7 @@ static int listPossibleCallback(char * s, char *** avp)
return ac; return ac;
} }
#endif
ReadlineLikeInteracter::Guard ReadlineLikeInteracter::init(detail::ReplCompleterMixin * repl) ReadlineLikeInteracter::Guard ReadlineLikeInteracter::init(detail::ReplCompleterMixin * repl)
{ {
@ -175,10 +178,23 @@ bool ReadlineLikeInteracter::getLine(std::string & input, ReplPromptType promptT
return true; return true;
} }
// editline doesn't echo the input to the output when non-interactive, unlike readline
// this results in a different behavior when running tests. The echoing is
// quite useful for reading the test output, so we add it here.
if (auto e = getEnv("_NIX_TEST_REPL_ECHO"); s && e && *e == "1")
{
#ifndef USE_READLINE
// This is probably not right for multi-line input, but we don't use that
// in the characterisation tests, so it's fine.
std::cout << promptForType(promptType) << s << std::endl;
#endif
}
if (!s) if (!s)
return false; return false;
input += s; input += s;
input += '\n'; input += '\n';
return true; return true;
} }

View file

@ -217,7 +217,7 @@ ReplExitStatus NixRepl::mainLoop()
case ProcessLineResult::PromptAgain: case ProcessLineResult::PromptAgain:
break; break;
default: default:
abort(); unreachable();
} }
} catch (ParseError & e) { } catch (ParseError & e) {
if (e.msg().find("unexpected end of file") != std::string::npos) { if (e.msg().find("unexpected end of file") != std::string::npos) {
@ -644,9 +644,6 @@ ProcessLineResult NixRepl::processLine(std::string line)
fallbackPos = attr->pos; fallbackPos = attr->pos;
fallbackDoc = state->getDocCommentForPos(fallbackPos); fallbackDoc = state->getDocCommentForPos(fallbackPos);
} }
} else {
evalString(arg, v);
} }
evalString(arg, v); evalString(arg, v);

View file

@ -29,6 +29,8 @@ deps_public_maybe_subproject = [
] ]
subdir('build-utils-meson/subprojects') subdir('build-utils-meson/subprojects')
subdir('build-utils-meson/threads')
# TODO rename, because it will conflict with downstream projects # TODO rename, because it will conflict with downstream projects
configdata.set_quoted('PACKAGE_VERSION', meson.project_version()) configdata.set_quoted('PACKAGE_VERSION', meson.project_version())

View file

@ -14,10 +14,10 @@
#include "nix_api_util.h" #include "nix_api_util.h"
#include "nix_api_util_internal.h" #include "nix_api_util_internal.h"
#ifdef HAVE_BOEHMGC #if HAVE_BOEHMGC
#include <mutex> # include <mutex>
#define GC_INCLUDE_NEW 1 # define GC_INCLUDE_NEW 1
#include "gc_cpp.h" # include "gc_cpp.h"
#endif #endif
nix_err nix_libexpr_init(nix_c_context * context) nix_err nix_libexpr_init(nix_c_context * context)
@ -131,7 +131,7 @@ void nix_state_free(EvalState * state)
delete state; delete state;
} }
#ifdef HAVE_BOEHMGC #if HAVE_BOEHMGC
std::unordered_map< std::unordered_map<
const void *, const void *,
unsigned int, unsigned int,
@ -207,7 +207,7 @@ nix_err nix_value_decref(nix_c_context * context, nix_value *x)
void nix_gc_register_finalizer(void * obj, void * cd, void (*finalizer)(void * obj, void * cd)) void nix_gc_register_finalizer(void * obj, void * cd, void (*finalizer)(void * obj, void * cd))
{ {
#ifdef HAVE_BOEHMGC #if HAVE_BOEHMGC
GC_REGISTER_FINALIZER(obj, finalizer, cd, 0, 0); GC_REGISTER_FINALIZER(obj, finalizer, cd, 0, 0);
#endif #endif
} }

View file

@ -14,6 +14,16 @@
#include "nix_api_util.h" #include "nix_api_util.h"
#include <stddef.h> #include <stddef.h>
#ifndef __has_c_attribute
# define __has_c_attribute(x) 0
#endif
#if __has_c_attribute(deprecated)
# define NIX_DEPRECATED(msg) [[deprecated(msg)]]
#else
# define NIX_DEPRECATED(msg)
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -45,7 +55,7 @@ typedef struct EvalState EvalState; // nix::EvalState
* @see nix_value_incref, nix_value_decref * @see nix_value_incref, nix_value_decref
*/ */
typedef struct nix_value nix_value; typedef struct nix_value nix_value;
[[deprecated("use nix_value instead")]] typedef nix_value Value; NIX_DEPRECATED("use nix_value instead") typedef nix_value Value;
// Function prototypes // Function prototypes
/** /**

View file

@ -14,7 +14,7 @@
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#ifdef HAVE_BOEHMGC #if HAVE_BOEHMGC
# include "gc/gc.h" # include "gc/gc.h"
# define GC_INCLUDE_NEW 1 # define GC_INCLUDE_NEW 1
# include "gc_cpp.h" # include "gc_cpp.h"
@ -174,7 +174,7 @@ ExternalValue * nix_create_external_value(nix_c_context * context, NixCExternalV
context->last_err_code = NIX_OK; context->last_err_code = NIX_OK;
try { try {
auto ret = new auto ret = new
#ifdef HAVE_BOEHMGC #if HAVE_BOEHMGC
(GC) (GC)
#endif #endif
NixCExternalValue(*desc, v); NixCExternalValue(*desc, v);

View file

@ -14,7 +14,7 @@
#include "nix_api_value.h" #include "nix_api_value.h"
#include "value/context.hh" #include "value/context.hh"
#ifdef HAVE_BOEHMGC #if HAVE_BOEHMGC
# include "gc/gc.h" # include "gc/gc.h"
# define GC_INCLUDE_NEW 1 # define GC_INCLUDE_NEW 1
# include "gc_cpp.h" # include "gc_cpp.h"
@ -131,7 +131,7 @@ PrimOp * nix_alloc_primop(
try { try {
using namespace std::placeholders; using namespace std::placeholders;
auto p = new auto p = new
#ifdef HAVE_BOEHMGC #if HAVE_BOEHMGC
(GC) (GC)
#endif #endif
nix::PrimOp{ nix::PrimOp{

View file

@ -63,12 +63,8 @@ mkMesonDerivation (finalAttrs: {
LDFLAGS = "-fuse-ld=gold"; LDFLAGS = "-fuse-ld=gold";
}; };
enableParallelBuilding = true;
separateDebugInfo = !stdenv.hostPlatform.isStatic; separateDebugInfo = !stdenv.hostPlatform.isStatic;
strictDeps = true;
hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie"; hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie";
meta = { meta = {

View file

@ -134,7 +134,7 @@ std::pair<SourcePath, uint32_t> findPackageFilename(EvalState & state, Value & v
return {SourcePath{path.accessor, CanonPath(fn.substr(0, colon))}, lineno}; return {SourcePath{path.accessor, CanonPath(fn.substr(0, colon))}, lineno};
} catch (std::invalid_argument & e) { } catch (std::invalid_argument & e) {
fail(); fail();
abort(); unreachable();
} }
} }

View file

@ -95,7 +95,7 @@ struct AttrDb
{ {
try { try {
auto state(_state->lock()); auto state(_state->lock());
if (!failed) if (!failed && state->txn->active)
state->txn->commit(); state->txn->commit();
state->txn.reset(); state->txn.reset();
} catch (...) { } catch (...) {

View file

@ -92,6 +92,14 @@ void EvalErrorBuilder<T>::debugThrow()
throw error; throw error;
} }
template<class T>
void EvalErrorBuilder<T>::panic()
{
logError(error.info());
printError("This is a bug! An unexpected condition occurred, causing the Nix evaluator to have to stop. If you could share a reproducible example or a core dump, please open an issue at https://github.com/NixOS/nix/issues");
abort();
}
template class EvalErrorBuilder<EvalBaseError>; template class EvalErrorBuilder<EvalBaseError>;
template class EvalErrorBuilder<EvalError>; template class EvalErrorBuilder<EvalError>;
template class EvalErrorBuilder<AssertionError>; template class EvalErrorBuilder<AssertionError>;

View file

@ -110,6 +110,12 @@ public:
* Delete the `EvalErrorBuilder` and throw the underlying exception. * Delete the `EvalErrorBuilder` and throw the underlying exception.
*/ */
[[gnu::noinline, gnu::noreturn]] void debugThrow(); [[gnu::noinline, gnu::noreturn]] void debugThrow();
/**
* A programming error or fatal condition occurred. Abort the process for core dump and debugging.
* This does not print a proper backtrace, because unwinding the stack is destructive.
*/
[[gnu::noinline, gnu::noreturn]] void panic();
}; };
} }

View file

@ -1,5 +1,7 @@
#include "error.hh" #include "error.hh"
#include "environment-variables.hh" #include "environment-variables.hh"
#include "eval-settings.hh"
#include "config-global.hh"
#include "serialise.hh" #include "serialise.hh"
#include "eval-gc.hh" #include "eval-gc.hh"
@ -84,14 +86,17 @@ void fixupBoehmStackPointer(void ** sp_ptr, void * _pthread_id)
{ {
void *& sp = *sp_ptr; void *& sp = *sp_ptr;
auto pthread_id = reinterpret_cast<pthread_t>(_pthread_id); auto pthread_id = reinterpret_cast<pthread_t>(_pthread_id);
# ifndef __APPLE__
pthread_attr_t pattr; pthread_attr_t pattr;
# endif
size_t osStackSize; size_t osStackSize;
void * osStackLow; // The low address of the stack, which grows down.
void * osStackLimit;
void * osStackBase; void * osStackBase;
# ifdef __APPLE__ # ifdef __APPLE__
osStackSize = pthread_get_stacksize_np(pthread_id); osStackSize = pthread_get_stacksize_np(pthread_id);
osStackLow = pthread_get_stackaddr_np(pthread_id); osStackLimit = pthread_get_stackaddr_np(pthread_id);
# else # else
if (pthread_attr_init(&pattr)) { if (pthread_attr_init(&pattr)) {
throw Error("fixupBoehmStackPointer: pthread_attr_init failed"); throw Error("fixupBoehmStackPointer: pthread_attr_init failed");
@ -110,18 +115,18 @@ void fixupBoehmStackPointer(void ** sp_ptr, void * _pthread_id)
# else # else
# error "Need one of `pthread_attr_get_np` or `pthread_getattr_np`" # error "Need one of `pthread_attr_get_np` or `pthread_getattr_np`"
# endif # endif
if (pthread_attr_getstack(&pattr, &osStackLow, &osStackSize)) { if (pthread_attr_getstack(&pattr, &osStackLimit, &osStackSize)) {
throw Error("fixupBoehmStackPointer: pthread_attr_getstack failed"); throw Error("fixupBoehmStackPointer: pthread_attr_getstack failed");
} }
if (pthread_attr_destroy(&pattr)) { if (pthread_attr_destroy(&pattr)) {
throw Error("fixupBoehmStackPointer: pthread_attr_destroy failed"); throw Error("fixupBoehmStackPointer: pthread_attr_destroy failed");
} }
# endif # endif
osStackBase = (char *) osStackLow + osStackSize; osStackBase = (char *) osStackLimit + osStackSize;
// NOTE: We assume the stack grows down, as it does on all architectures we support. // NOTE: We assume the stack grows down, as it does on all architectures we support.
// Architectures that grow the stack up are rare. // Architectures that grow the stack up are rare.
if (sp >= osStackBase || sp < osStackLow) { // lo is outside the os stack if (sp >= osStackBase || sp < osStackLimit) { // sp is outside the os stack
sp = osStackBase; sp = osStackLimit;
} }
} }
@ -155,6 +160,10 @@ static inline void initGCReal()
there. */ there. */
GC_set_no_dls(1); GC_set_no_dls(1);
/* Enable perf measurements. This is just a setting; not much of a
start of something. */
GC_start_performance_measurement();
GC_INIT(); GC_INIT();
GC_set_oom_fn(oomHandler); GC_set_oom_fn(oomHandler);
@ -202,6 +211,14 @@ static inline void initGCReal()
} }
} }
static size_t gcCyclesAfterInit = 0;
size_t getGCCycles()
{
assertGCInitialized();
return static_cast<size_t>(GC_get_gc_no()) - gcCyclesAfterInit;
}
#endif #endif
static bool gcInitialised = false; static bool gcInitialised = false;
@ -213,8 +230,16 @@ void initGC()
#if HAVE_BOEHMGC #if HAVE_BOEHMGC
initGCReal(); initGCReal();
gcCyclesAfterInit = GC_get_gc_no();
#endif #endif
// NIX_PATH must override the regular setting
// See the comment in applyConfig
if (auto nixPathEnv = getEnv("NIX_PATH")) {
globalConfig.set("nix-path", concatStringsSep(" ", EvalSettings::parseNixPath(nixPathEnv.value())));
}
gcInitialised = true; gcInitialised = true;
} }
@ -223,4 +248,4 @@ void assertGCInitialized()
assert(gcInitialised); assert(gcInitialised);
} }
} } // namespace nix

View file

@ -1,6 +1,8 @@
#pragma once #pragma once
///@file ///@file
#include <cstddef>
namespace nix { namespace nix {
/** /**
@ -13,4 +15,11 @@ void initGC();
*/ */
void assertGCInitialized(); void assertGCInitialized();
} #ifdef HAVE_BOEHMGC
/**
* The number of GC cycles since initGC().
*/
size_t getGCCycles();
#endif
} // namespace nix

View file

@ -8,7 +8,7 @@ namespace nix {
/* Very hacky way to parse $NIX_PATH, which is colon-separated, but /* Very hacky way to parse $NIX_PATH, which is colon-separated, but
can contain URLs (e.g. "nixpkgs=https://bla...:foo=https://"). */ can contain URLs (e.g. "nixpkgs=https://bla...:foo=https://"). */
static Strings parseNixPath(const std::string & s) Strings EvalSettings::parseNixPath(const std::string & s)
{ {
Strings res; Strings res;
@ -48,15 +48,12 @@ EvalSettings::EvalSettings(bool & readOnlyMode, EvalSettings::LookupPathHooks lo
: readOnlyMode{readOnlyMode} : readOnlyMode{readOnlyMode}
, lookupPathHooks{lookupPathHooks} , lookupPathHooks{lookupPathHooks}
{ {
auto var = getEnv("NIX_PATH"); auto var = getEnv("NIX_ABORT_ON_WARN");
if (var) nixPath = parseNixPath(*var);
var = getEnv("NIX_ABORT_ON_WARN");
if (var && (var == "1" || var == "yes" || var == "true")) if (var && (var == "1" || var == "yes" || var == "true"))
builtinsAbortOnWarn = true; builtinsAbortOnWarn = true;
} }
Strings EvalSettings::getDefaultNixPath() const Strings EvalSettings::getDefaultNixPath()
{ {
Strings res; Strings res;
auto add = [&](const Path & p, const std::string & s = std::string()) { auto add = [&](const Path & p, const std::string & s = std::string()) {
@ -69,11 +66,9 @@ Strings EvalSettings::getDefaultNixPath() const
} }
}; };
if (!restrictEval && !pureEval) { add(getNixDefExpr() + "/channels");
add(getNixDefExpr() + "/channels"); add(rootChannelsDir() + "/nixpkgs", "nixpkgs");
add(rootChannelsDir() + "/nixpkgs", "nixpkgs"); add(rootChannelsDir());
add(rootChannelsDir());
}
return res; return res;
} }

View file

@ -43,10 +43,12 @@ struct EvalSettings : Config
bool & readOnlyMode; bool & readOnlyMode;
Strings getDefaultNixPath() const; static Strings getDefaultNixPath();
static bool isPseudoUrl(std::string_view s); static bool isPseudoUrl(std::string_view s);
static Strings parseNixPath(const std::string & s);
static std::string resolvePseudoUrl(std::string_view url); static std::string resolvePseudoUrl(std::string_view url);
LookupPathHooks lookupPathHooks; LookupPathHooks lookupPathHooks;
@ -63,7 +65,7 @@ struct EvalSettings : Config
extern "C" typedef void (*ValueInitialiser) (EvalState & state, Value & v); extern "C" typedef void (*ValueInitialiser) (EvalState & state, Value & v);
``` ```
The [Nix C++ API documentation](@docroot@/contributing/documentation.md#api-documentation) has more details on evaluator internals. The [Nix C++ API documentation](@docroot@/development/documentation.md#api-documentation) has more details on evaluator internals.
- `builtins.exec` *arguments* - `builtins.exec` *arguments*
@ -71,25 +73,30 @@ struct EvalSettings : Config
)"}; )"};
Setting<Strings> nixPath{ Setting<Strings> nixPath{
this, getDefaultNixPath(), "nix-path", this, {}, "nix-path",
R"( R"(
List of search paths to use for [lookup path](@docroot@/language/constructs/lookup-path.md) resolution. List of search paths to use for [lookup path](@docroot@/language/constructs/lookup-path.md) resolution.
This setting determines the value of This setting determines the value of
[`builtins.nixPath`](@docroot@/language/builtins.md#builtins-nixPath) and can be used with [`builtins.findFile`](@docroot@/language/builtins.md#builtins-findFile). [`builtins.nixPath`](@docroot@/language/builtins.md#builtins-nixPath) and can be used with [`builtins.findFile`](@docroot@/language/builtins.md#builtins-findFile).
The default value is - The configuration setting is overridden by the [`NIX_PATH`](@docroot@/command-ref/env-common.md#env-NIX_PATH)
environment variable.
- `NIX_PATH` is overridden by [specifying the setting as the command line flag](@docroot@/command-ref/conf-file.md#command-line-flags) `--nix-path`.
- Any current value is extended by the [`-I` option](@docroot@/command-ref/opt-common.md#opt-I) or `--extra-nix-path`.
``` If the respective paths are accessible, the default values are:
$HOME/.nix-defexpr/channels
nixpkgs=$NIX_STATE_DIR/profiles/per-user/root/channels/nixpkgs
$NIX_STATE_DIR/profiles/per-user/root/channels
```
It can be overridden with the [`NIX_PATH` environment variable](@docroot@/command-ref/env-common.md#env-NIX_PATH) or the [`-I` command line option](@docroot@/command-ref/opt-common.md#opt-I). - `$HOME/.nix-defexpr/channels`
- `nixpkgs=$NIX_STATE_DIR/profiles/per-user/root/channels/nixpkgs`
- `$NIX_STATE_DIR/profiles/per-user/root/channels`
See [`NIX_STATE_DIR`](@docroot@/command-ref/env-common.md#env-NIX_STATE_DIR) for details.
> **Note** > **Note**
> >
> If [pure evaluation](#conf-pure-eval) is enabled, `nixPath` evaluates to the empty list `[ ]`. > If [restricted evaluation](@docroot@/command-ref/conf-file.md#conf-restrict-eval) is enabled, the default value is empty.
>
> If [pure evaluation](#conf-pure-eval) is enabled, `builtins.nixPath` *always* evaluates to the empty list `[ ]`.
)", {}, false}; )", {}, false};
Setting<std::string> currentSystem{ Setting<std::string> currentSystem{

View file

@ -149,7 +149,7 @@ std::string_view showType(ValueType type, bool withArticle)
case nFloat: return WA("a", "float"); case nFloat: return WA("a", "float");
case nThunk: return WA("a", "thunk"); case nThunk: return WA("a", "thunk");
} }
abort(); unreachable();
} }
@ -215,7 +215,7 @@ static Symbol getName(const AttrName & name, EvalState & state, Env & env)
static constexpr size_t BASE_ENV_SIZE = 128; static constexpr size_t BASE_ENV_SIZE = 128;
EvalState::EvalState( EvalState::EvalState(
const LookupPath & _lookupPath, const LookupPath & lookupPathFromArguments,
ref<Store> store, ref<Store> store,
const fetchers::Settings & fetchSettings, const fetchers::Settings & fetchSettings,
const EvalSettings & settings, const EvalSettings & settings,
@ -331,12 +331,21 @@ EvalState::EvalState(
vStringSymlink.mkString("symlink"); vStringSymlink.mkString("symlink");
vStringUnknown.mkString("unknown"); vStringUnknown.mkString("unknown");
/* Initialise the Nix expression search path. */ /* Construct the Nix expression search path. */
assert(lookupPath.elements.empty());
if (!settings.pureEval) { if (!settings.pureEval) {
for (auto & i : _lookupPath.elements) for (auto & i : lookupPathFromArguments.elements) {
lookupPath.elements.emplace_back(LookupPath::Elem {i}); lookupPath.elements.emplace_back(LookupPath::Elem {i});
for (auto & i : settings.nixPath.get()) }
/* $NIX_PATH overriding regular settings is implemented as a hack in `initGC()` */
for (auto & i : settings.nixPath.get()) {
lookupPath.elements.emplace_back(LookupPath::Elem::parse(i)); lookupPath.elements.emplace_back(LookupPath::Elem::parse(i));
}
if (!settings.restrictEval) {
for (auto & i : EvalSettings::getDefaultNixPath()) {
lookupPath.elements.emplace_back(LookupPath::Elem::parse(i));
}
}
} }
/* Allow access to all paths in the search path. */ /* Allow access to all paths in the search path. */
@ -771,7 +780,7 @@ void EvalState::runDebugRepl(const Error * error, const Env & env, const Expr &
case ReplExitStatus::Continue: case ReplExitStatus::Continue:
break; break;
default: default:
abort(); unreachable();
} }
} }
} }
@ -1140,7 +1149,7 @@ inline void EvalState::evalAttrs(Env & env, Expr * e, Value & v, const PosIdx po
void Expr::eval(EvalState & state, Env & env, Value & v) void Expr::eval(EvalState & state, Env & env, Value & v)
{ {
abort(); unreachable();
} }
@ -1573,7 +1582,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
.withFrame(*fun.payload.lambda.env, lambda) .withFrame(*fun.payload.lambda.env, lambda)
.debugThrow(); .debugThrow();
} }
abort(); // can't happen unreachable();
} }
} }
@ -1825,9 +1834,24 @@ void ExprIf::eval(EvalState & state, Env & env, Value & v)
void ExprAssert::eval(EvalState & state, Env & env, Value & v) void ExprAssert::eval(EvalState & state, Env & env, Value & v)
{ {
if (!state.evalBool(env, cond, pos, "in the condition of the assert statement")) { if (!state.evalBool(env, cond, pos, "in the condition of the assert statement")) {
std::ostringstream out; auto exprStr = ({
cond->show(state.symbols, out); std::ostringstream out;
state.error<AssertionError>("assertion '%1%' failed", out.str()).atPos(pos).withFrame(env, *this).debugThrow(); cond->show(state.symbols, out);
out.str();
});
if (auto eq = dynamic_cast<ExprOpEq *>(cond)) {
try {
Value v1; eq->e1->eval(state, env, v1);
Value v2; eq->e2->eval(state, env, v2);
state.assertEqValues(v1, v2, eq->pos, "in an equality assertion");
} catch (AssertionError & e) {
e.addTrace(state.positions[pos], "while evaluating the condition of the assertion '%s'", exprStr);
throw;
}
}
state.error<AssertionError>("assertion '%1%' failed", exprStr).atPos(pos).withFrame(env, *this).debugThrow();
} }
body->eval(state, env, v); body->eval(state, env, v);
} }
@ -2484,6 +2508,214 @@ SingleDerivedPath EvalState::coerceToSingleDerivedPath(const PosIdx pos, Value &
} }
// NOTE: This implementation must match eqValues!
// We accept this burden because informative error messages for
// `assert a == b; x` are critical for our users' testing UX.
void EvalState::assertEqValues(Value & v1, Value & v2, const PosIdx pos, std::string_view errorCtx)
{
// This implementation must match eqValues.
forceValue(v1, pos);
forceValue(v2, pos);
if (&v1 == &v2)
return;
// Special case type-compatibility between float and int
if ((v1.type() == nInt || v1.type() == nFloat) && (v2.type() == nInt || v2.type() == nFloat)) {
if (eqValues(v1, v2, pos, errorCtx)) {
return;
} else {
error<AssertionError>(
"%s with value '%s' is not equal to %s with value '%s'",
showType(v1),
ValuePrinter(*this, v1, errorPrintOptions),
showType(v2),
ValuePrinter(*this, v2, errorPrintOptions))
.debugThrow();
}
}
if (v1.type() != v2.type()) {
error<AssertionError>(
"%s of value '%s' is not equal to %s of value '%s'",
showType(v1),
ValuePrinter(*this, v1, errorPrintOptions),
showType(v2),
ValuePrinter(*this, v2, errorPrintOptions))
.debugThrow();
}
switch (v1.type()) {
case nInt:
if (v1.integer() != v2.integer()) {
error<AssertionError>("integer '%d' is not equal to integer '%d'", v1.integer(), v2.integer()).debugThrow();
}
return;
case nBool:
if (v1.boolean() != v2.boolean()) {
error<AssertionError>(
"boolean '%s' is not equal to boolean '%s'",
ValuePrinter(*this, v1, errorPrintOptions),
ValuePrinter(*this, v2, errorPrintOptions))
.debugThrow();
}
return;
case nString:
if (strcmp(v1.c_str(), v2.c_str()) != 0) {
error<AssertionError>(
"string '%s' is not equal to string '%s'",
ValuePrinter(*this, v1, errorPrintOptions),
ValuePrinter(*this, v2, errorPrintOptions))
.debugThrow();
}
return;
case nPath:
if (v1.payload.path.accessor != v2.payload.path.accessor) {
error<AssertionError>(
"path '%s' is not equal to path '%s' because their accessors are different",
ValuePrinter(*this, v1, errorPrintOptions),
ValuePrinter(*this, v2, errorPrintOptions))
.debugThrow();
}
if (strcmp(v1.payload.path.path, v2.payload.path.path) != 0) {
error<AssertionError>(
"path '%s' is not equal to path '%s'",
ValuePrinter(*this, v1, errorPrintOptions),
ValuePrinter(*this, v2, errorPrintOptions))
.debugThrow();
}
return;
case nNull:
return;
case nList:
if (v1.listSize() != v2.listSize()) {
error<AssertionError>(
"list of size '%d' is not equal to list of size '%d', left hand side is '%s', right hand side is '%s'",
v1.listSize(),
v2.listSize(),
ValuePrinter(*this, v1, errorPrintOptions),
ValuePrinter(*this, v2, errorPrintOptions))
.debugThrow();
}
for (size_t n = 0; n < v1.listSize(); ++n) {
try {
assertEqValues(*v1.listElems()[n], *v2.listElems()[n], pos, errorCtx);
} catch (Error & e) {
e.addTrace(positions[pos], "while comparing list element %d", n);
throw;
}
}
return;
case nAttrs: {
if (isDerivation(v1) && isDerivation(v2)) {
auto i = v1.attrs()->get(sOutPath);
auto j = v2.attrs()->get(sOutPath);
if (i && j) {
try {
assertEqValues(*i->value, *j->value, pos, errorCtx);
return;
} catch (Error & e) {
e.addTrace(positions[pos], "while comparing a derivation by its '%s' attribute", "outPath");
throw;
}
assert(false);
}
}
if (v1.attrs()->size() != v2.attrs()->size()) {
error<AssertionError>(
"attribute names of attribute set '%s' differs from attribute set '%s'",
ValuePrinter(*this, v1, errorPrintOptions),
ValuePrinter(*this, v2, errorPrintOptions))
.debugThrow();
}
// Like normal comparison, we compare the attributes in non-deterministic Symbol index order.
// This function is called when eqValues has found a difference, so to reliably
// report about its result, we should follow in its literal footsteps and not
// try anything fancy that could lead to an error.
Bindings::const_iterator i, j;
for (i = v1.attrs()->begin(), j = v2.attrs()->begin(); i != v1.attrs()->end(); ++i, ++j) {
if (i->name != j->name) {
// A difference in a sorted list means that one attribute is not contained in the other, but we don't
// know which. Let's find out. Could use <, but this is more clear.
if (!v2.attrs()->get(i->name)) {
error<AssertionError>(
"attribute name '%s' is contained in '%s', but not in '%s'",
symbols[i->name],
ValuePrinter(*this, v1, errorPrintOptions),
ValuePrinter(*this, v2, errorPrintOptions))
.debugThrow();
}
if (!v1.attrs()->get(j->name)) {
error<AssertionError>(
"attribute name '%s' is missing in '%s', but is contained in '%s'",
symbols[j->name],
ValuePrinter(*this, v1, errorPrintOptions),
ValuePrinter(*this, v2, errorPrintOptions))
.debugThrow();
}
assert(false);
}
try {
assertEqValues(*i->value, *j->value, pos, errorCtx);
} catch (Error & e) {
// The order of traces is reversed, so this presents as
// where left hand side is
// at <pos>
// where right hand side is
// at <pos>
// while comparing attribute '<name>'
if (j->pos != noPos)
e.addTrace(positions[j->pos], "where right hand side is");
if (i->pos != noPos)
e.addTrace(positions[i->pos], "where left hand side is");
e.addTrace(positions[pos], "while comparing attribute '%s'", symbols[i->name]);
throw;
}
}
return;
}
case nFunction:
error<AssertionError>("distinct functions and immediate comparisons of identical functions compare as unequal")
.debugThrow();
case nExternal:
if (!(*v1.external() == *v2.external())) {
error<AssertionError>(
"external value '%s' is not equal to external value '%s'",
ValuePrinter(*this, v1, errorPrintOptions),
ValuePrinter(*this, v2, errorPrintOptions))
.debugThrow();
}
return;
case nFloat:
// !!!
if (!(v1.fpoint() == v2.fpoint())) {
error<AssertionError>("float '%f' is not equal to float '%f'", v1.fpoint(), v2.fpoint()).debugThrow();
}
return;
case nThunk: // Must not be left by forceValue
assert(false);
default: // Note that we pass compiler flags that should make `default:` unreachable.
// Also note that this probably ran after `eqValues`, which implements
// the same logic more efficiently (without having to unwind stacks),
// so maybe `assertEqValues` and `eqValues` are out of sync. Check it for solutions.
error<EvalError>("assertEqValues: cannot compare %1% with %2%", showType(v1), showType(v2)).withTrace(pos, errorCtx).panic();
}
}
// This implementation must match assertEqValues
bool EvalState::eqValues(Value & v1, Value & v2, const PosIdx pos, std::string_view errorCtx) bool EvalState::eqValues(Value & v1, Value & v2, const PosIdx pos, std::string_view errorCtx)
{ {
forceValue(v1, pos); forceValue(v1, pos);
@ -2557,11 +2789,13 @@ bool EvalState::eqValues(Value & v1, Value & v2, const PosIdx pos, std::string_v
return *v1.external() == *v2.external(); return *v1.external() == *v2.external();
case nFloat: case nFloat:
// !!!
return v1.fpoint() == v2.fpoint(); return v1.fpoint() == v2.fpoint();
case nThunk: // Must not be left by forceValue case nThunk: // Must not be left by forceValue
default: assert(false);
error<EvalError>("cannot compare %1% with %2%", showType(v1), showType(v2)).withTrace(pos, errorCtx).debugThrow(); default: // Note that we pass compiler flags that should make `default:` unreachable.
error<EvalError>("eqValues: cannot compare %1% with %2%", showType(v1), showType(v2)).withTrace(pos, errorCtx).panic();
} }
} }
@ -2610,6 +2844,11 @@ void EvalState::printStatistics()
#if HAVE_BOEHMGC #if HAVE_BOEHMGC
GC_word heapSize, totalBytes; GC_word heapSize, totalBytes;
GC_get_heap_usage_safe(&heapSize, 0, 0, 0, &totalBytes); GC_get_heap_usage_safe(&heapSize, 0, 0, 0, &totalBytes);
double gcFullOnlyTime = ({
auto ms = GC_get_full_gc_total_time();
ms * 0.001;
});
auto gcCycles = getGCCycles();
#endif #endif
auto outPath = getEnv("NIX_SHOW_STATS_PATH").value_or("-"); auto outPath = getEnv("NIX_SHOW_STATS_PATH").value_or("-");
@ -2620,6 +2859,15 @@ void EvalState::printStatistics()
#ifndef _WIN32 // TODO implement #ifndef _WIN32 // TODO implement
topObj["cpuTime"] = cpuTime; topObj["cpuTime"] = cpuTime;
#endif #endif
topObj["time"] = {
#ifndef _WIN32 // TODO implement
{"cpu", cpuTime},
#endif
#if HAVE_BOEHMGC
{GC_is_incremental_mode() ? "gcNonIncremental" : "gc", gcFullOnlyTime},
{GC_is_incremental_mode() ? "gcNonIncrementalFraction" : "gcFraction", gcFullOnlyTime / cpuTime},
#endif
};
topObj["envs"] = { topObj["envs"] = {
{"number", nrEnvs}, {"number", nrEnvs},
{"elements", nrValuesInEnvs}, {"elements", nrValuesInEnvs},
@ -2661,6 +2909,7 @@ void EvalState::printStatistics()
topObj["gc"] = { topObj["gc"] = {
{"heapSize", heapSize}, {"heapSize", heapSize},
{"totalBytes", totalBytes}, {"totalBytes", totalBytes},
{"cycles", gcCycles},
}; };
#endif #endif

View file

@ -130,7 +130,7 @@ struct Constant
typedef std::map<std::string, Value *> ValMap; typedef std::map<std::string, Value *> ValMap;
#endif #endif
typedef std::map<PosIdx, DocComment> DocCommentMap; typedef std::unordered_map<PosIdx, DocComment> DocCommentMap;
struct Env struct Env
{ {
@ -335,7 +335,7 @@ private:
* Associate source positions of certain AST nodes with their preceding doc comment, if they have one. * Associate source positions of certain AST nodes with their preceding doc comment, if they have one.
* Grouped by file. * Grouped by file.
*/ */
std::map<SourcePath, DocCommentMap> positionToDocComment; std::unordered_map<SourcePath, DocCommentMap> positionToDocComment;
LookupPath lookupPath; LookupPath lookupPath;
@ -655,6 +655,15 @@ public:
*/ */
bool eqValues(Value & v1, Value & v2, const PosIdx pos, std::string_view errorCtx); bool eqValues(Value & v1, Value & v2, const PosIdx pos, std::string_view errorCtx);
/**
* Like `eqValues`, but throws an `AssertionError` if not equal.
*
* WARNING:
* Callers should call `eqValues` first and report if `assertEqValues` behaves
* incorrectly. (e.g. if it doesn't throw if eqValues returns false or vice versa)
*/
void assertEqValues(Value & v1, Value & v2, const PosIdx pos, std::string_view errorCtx);
bool isFunctor(Value & fun); bool isFunctor(Value & fun);
// FIXME: use std::span // FIXME: use std::span

View file

@ -42,7 +42,7 @@ class JSONSax : nlohmann::json_sax<json> {
auto attrs2 = state.buildBindings(attrs.size()); auto attrs2 = state.buildBindings(attrs.size());
for (auto & i : attrs) for (auto & i : attrs)
attrs2.insert(i.first, i.second); attrs2.insert(i.first, i.second);
parent->value(state).mkAttrs(attrs2.alreadySorted()); parent->value(state).mkAttrs(attrs2);
return std::move(parent); return std::move(parent);
} }
void add() override { v = nullptr; } void add() override { v = nullptr; }
@ -80,42 +80,42 @@ class JSONSax : nlohmann::json_sax<json> {
public: public:
JSONSax(EvalState & state, Value & v) : state(state), rs(new JSONState(&v)) {}; JSONSax(EvalState & state, Value & v) : state(state), rs(new JSONState(&v)) {};
bool null() bool null() override
{ {
rs->value(state).mkNull(); rs->value(state).mkNull();
rs->add(); rs->add();
return true; return true;
} }
bool boolean(bool val) bool boolean(bool val) override
{ {
rs->value(state).mkBool(val); rs->value(state).mkBool(val);
rs->add(); rs->add();
return true; return true;
} }
bool number_integer(number_integer_t val) bool number_integer(number_integer_t val) override
{ {
rs->value(state).mkInt(val); rs->value(state).mkInt(val);
rs->add(); rs->add();
return true; return true;
} }
bool number_unsigned(number_unsigned_t val) bool number_unsigned(number_unsigned_t val) override
{ {
rs->value(state).mkInt(val); rs->value(state).mkInt(val);
rs->add(); rs->add();
return true; return true;
} }
bool number_float(number_float_t val, const string_t & s) bool number_float(number_float_t val, const string_t & s) override
{ {
rs->value(state).mkFloat(val); rs->value(state).mkFloat(val);
rs->add(); rs->add();
return true; return true;
} }
bool string(string_t & val) bool string(string_t & val) override
{ {
rs->value(state).mkString(val); rs->value(state).mkString(val);
rs->add(); rs->add();
@ -123,7 +123,7 @@ public:
} }
#if NLOHMANN_JSON_VERSION_MAJOR >= 3 && NLOHMANN_JSON_VERSION_MINOR >= 8 #if NLOHMANN_JSON_VERSION_MAJOR >= 3 && NLOHMANN_JSON_VERSION_MINOR >= 8
bool binary(binary_t&) bool binary(binary_t&) override
{ {
// This function ought to be unreachable // This function ought to be unreachable
assert(false); assert(false);
@ -131,35 +131,35 @@ public:
} }
#endif #endif
bool start_object(std::size_t len) bool start_object(std::size_t len) override
{ {
rs = std::make_unique<JSONObjectState>(std::move(rs)); rs = std::make_unique<JSONObjectState>(std::move(rs));
return true; return true;
} }
bool key(string_t & name) bool key(string_t & name) override
{ {
dynamic_cast<JSONObjectState*>(rs.get())->key(name, state); dynamic_cast<JSONObjectState*>(rs.get())->key(name, state);
return true; return true;
} }
bool end_object() { bool end_object() override {
rs = rs->resolve(state); rs = rs->resolve(state);
rs->add(); rs->add();
return true; return true;
} }
bool end_array() { bool end_array() override {
return end_object(); return end_object();
} }
bool start_array(size_t len) { bool start_array(size_t len) override {
rs = std::make_unique<JSONListState>(std::move(rs), rs = std::make_unique<JSONListState>(std::move(rs),
len != std::numeric_limits<size_t>::max() ? len : 128); len != std::numeric_limits<size_t>::max() ? len : 128);
return true; return true;
} }
bool parse_error(std::size_t, const std::string&, const nlohmann::detail::exception& ex) { bool parse_error(std::size_t, const std::string&, const nlohmann::detail::exception& ex) override {
throw JSONParseError("%s", ex.what()); throw JSONParseError("%s", ex.what());
} }
}; };

View file

@ -67,6 +67,14 @@ static StringToken unescapeStr(SymbolTable & symbols, char * s, size_t length)
return {result, size_t(t - result)}; return {result, size_t(t - result)};
} }
static void requireExperimentalFeature(const ExperimentalFeature & feature, const Pos & pos)
{
if (!experimentalFeatureSettings.isEnabled(feature))
throw ParseError(ErrorInfo{
.msg = HintFmt("experimental Nix feature '%1%' is disabled; add '--extra-experimental-features %1%' to enable it", showExperimentalFeature(feature)),
.pos = pos,
});
}
} }
@ -119,6 +127,12 @@ or { return OR_KW; }
\-\> { return IMPL; } \-\> { return IMPL; }
\/\/ { return UPDATE; } \/\/ { return UPDATE; }
\+\+ { return CONCAT; } \+\+ { return CONCAT; }
\<\| { requireExperimentalFeature(Xp::PipeOperators, state->positions[CUR_POS]);
return PIPE_FROM;
}
\|\> { requireExperimentalFeature(Xp::PipeOperators, state->positions[CUR_POS]);
return PIPE_INTO;
}
{ID} { yylval->id = {yytext, (size_t) yyleng}; return ID; } {ID} { yylval->id = {yytext, (size_t) yyleng}; return ID; }
{INT} { errno = 0; {INT} { errno = 0;

View file

@ -32,6 +32,7 @@ subdir('build-utils-meson/threads')
boost = dependency( boost = dependency(
'boost', 'boost',
modules : ['container', 'context'], modules : ['container', 'context'],
include_type: 'system',
) )
# boost is a public dependency, but not a pkg-config dependency unfortunately, so we # boost is a public dependency, but not a pkg-config dependency unfortunately, so we
# put in `deps_other`. # put in `deps_other`.
@ -55,7 +56,12 @@ if bdw_gc.found()
endif endif
configdata.set('HAVE_BOEHMGC', bdw_gc.found().to_int()) configdata.set('HAVE_BOEHMGC', bdw_gc.found().to_int())
toml11 = dependency('toml11', version : '>=3.7.0', method : 'cmake') toml11 = dependency(
'toml11',
version : '>=3.7.0',
method : 'cmake',
include_type: 'system',
)
deps_other += toml11 deps_other += toml11
config_h = configure_file( config_h = configure_file(

View file

@ -25,7 +25,7 @@ std::ostream & operator <<(std::ostream & str, const SymbolStr & symbol)
void Expr::show(const SymbolTable & symbols, std::ostream & str) const void Expr::show(const SymbolTable & symbols, std::ostream & str) const
{ {
abort(); unreachable();
} }
void ExprInt::show(const SymbolTable & symbols, std::ostream & str) const void ExprInt::show(const SymbolTable & symbols, std::ostream & str) const
@ -82,7 +82,9 @@ void ExprAttrs::showBindings(const SymbolTable & symbols, std::ostream & str) co
return sa < sb; return sa < sb;
}); });
std::vector<Symbol> inherits; std::vector<Symbol> inherits;
std::map<ExprInheritFrom *, std::vector<Symbol>> inheritsFrom; // We can use the displacement as a proxy for the order in which the symbols were parsed.
// The assignment of displacements should be deterministic, so that showBindings is deterministic.
std::map<Displacement, std::vector<Symbol>> inheritsFrom;
for (auto & i : sorted) { for (auto & i : sorted) {
switch (i->second.kind) { switch (i->second.kind) {
case AttrDef::Kind::Plain: case AttrDef::Kind::Plain:
@ -93,7 +95,7 @@ void ExprAttrs::showBindings(const SymbolTable & symbols, std::ostream & str) co
case AttrDef::Kind::InheritedFrom: { case AttrDef::Kind::InheritedFrom: {
auto & select = dynamic_cast<ExprSelect &>(*i->second.e); auto & select = dynamic_cast<ExprSelect &>(*i->second.e);
auto & from = dynamic_cast<ExprInheritFrom &>(*select.e); auto & from = dynamic_cast<ExprInheritFrom &>(*select.e);
inheritsFrom[&from].push_back(i->first); inheritsFrom[from.displ].push_back(i->first);
break; break;
} }
} }
@ -105,7 +107,7 @@ void ExprAttrs::showBindings(const SymbolTable & symbols, std::ostream & str) co
} }
for (const auto & [from, syms] : inheritsFrom) { for (const auto & [from, syms] : inheritsFrom) {
str << "inherit ("; str << "inherit (";
(*inheritFromExprs)[from->displ]->show(symbols, str); (*inheritFromExprs)[from]->show(symbols, str);
str << ")"; str << ")";
for (auto sym : syms) str << " " << symbols[sym]; for (auto sym : syms) str << " " << symbols[sym];
str << "; "; str << "; ";
@ -269,7 +271,7 @@ std::string showAttrPath(const SymbolTable & symbols, const AttrPath & attrPath)
void Expr::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env) void Expr::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
{ {
abort(); unreachable();
} }
void ExprInt::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env) void ExprInt::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)

View file

@ -186,7 +186,7 @@ struct ExprInheritFrom : ExprVar
this->fromWith = nullptr; this->fromWith = nullptr;
} }
void bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env); void bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env) override;
}; };
struct ExprSelect : Expr struct ExprSelect : Expr

View file

@ -102,12 +102,8 @@ mkMesonDerivation (finalAttrs: {
LDFLAGS = "-fuse-ld=gold"; LDFLAGS = "-fuse-ld=gold";
}; };
enableParallelBuilding = true;
separateDebugInfo = !stdenv.hostPlatform.isStatic; separateDebugInfo = !stdenv.hostPlatform.isStatic;
strictDeps = true;
hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie"; hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie";
meta = { meta = {

Some files were not shown because too many files have changed in this diff Show more