Compare commits

..

335 Commits

Author SHA1 Message Date
Bernardo Meurer Costa
377fc95bce release notes: 2.33.3 2026-02-13 04:53:45 +00:00
internal-nix-ci[bot]
48bbd96d2d Merge pull request #15220 from NixOS/backport-15216-to-2.33-maintenance
[Backport 2.33-maintenance] fix: #15208
2026-02-13 02:24:55 +00:00
Bernardo Meurer Costa
695501815b feat(libstore/s3): use virtual-hosted-style URLs and add addressing-style option
S3 binary caches now use virtual-hosted-style URLs by default for
standard AWS endpoints. Path-style endpoints (s3.region.amazonaws.com)
only serve HTTP/1.1, preventing HTTP/2 multiplexing and causing TCP
TIME_WAIT socket exhaustion under high concurrency. Virtual-hosted-style
endpoints (bucket.s3.region.amazonaws.com) support HTTP/2, enabling
multiplexing with the existing CURLPIPE_MULTIPLEX configuration.

Add a new `addressing-style` store option (auto/path/virtual) to control
this behavior. `auto` (default) uses virtual-hosted-style for standard
AWS endpoints and path-style for custom endpoints. `path` forces
path-style for backwards compatibility. `virtual` forces virtual-hosted-
style for all endpoints including custom ones.

Fixes: https://github.com/NixOS/nix/issues/15208
(cherry picked from commit 759f6c856b)
2026-02-13 01:44:05 +00:00
Bernardo Meurer Costa
5ac10221a6 fix(libstore/filetransfer): enable TCP keep-alive on curl handles
Idle connections in libcurl's connection pool can be silently dropped by
the OS or intermediate firewalls/NATs before they can be reused, forcing
new TCP connections to be created. This is especially problematic for
HTTP/1.1 endpoints where multiplexing is unavailable.

Enable TCP keep-alive with a 60-second idle/interval on all curl easy
handles to prevent idle connection drops and improve connection reuse.

(cherry picked from commit 736abd50ff)
2026-02-13 01:44:05 +00:00
internal-nix-ci[bot]
e9d77856f5 Merge pull request #15166 from NixOS/backport-15160-to-2.33-maintenance
[Backport 2.33-maintenance] builtins.flakeRefToString: Evaluate attributes
2026-02-06 19:39:04 +00:00
Eelco Dolstra
0c774b7ca4 builtins.flakeRefToString: Evaluate attributes
Fixes "attribute 'x' is a thunk".

(cherry picked from commit 2989a23fca)
2026-02-06 19:00:01 +00:00
internal-nix-ci[bot]
70e39c2721 Merge pull request #15152 from NixOS/backport-15149-to-2.33-maintenance
[Backport 2.33-maintenance] libutil: Add overflow check to alignUp
2026-02-05 02:22:28 +00:00
Sergei Zimmerman
18f8b70cd9 libutil: Add overflow check to alignUp
Old code with size + (size % 8 ? 8 - (size % 8) : 0) also suffered from this.

(cherry picked from commit d77c131df3)
2026-02-05 01:38:24 +00:00
internal-nix-ci[bot]
4aa2942014 Merge pull request #15140 from NixOS/backport-15134-to-2.33-maintenance
[Backport 2.33-maintenance] Fix: `QueryPathInfo` throws on invalid path error in daemon
2026-02-03 22:58:46 +00:00
Peter Bynum
f28e495294 Fix QueryPathInfo in daemon
(cherry picked from commit b9c77ecafc)
2026-02-03 22:19:27 +00:00
Eelco Dolstra
0142a88b8f Bump version 2026-02-02 18:43:54 +01:00
internal-nix-ci[bot]
9bf642b88d Merge pull request #15097 from NixOS/backport-15059-to-2.33-maintenance
[Backport 2.33-maintenance] feat(libstore/aws-creds): route AWS CRT logs through Nix logger
2026-01-27 14:43:13 +00:00
Sergei Zimmerman
e96a3f7a73 tests/nixos/s3-binary-cache-store: Drop superfluous prints
As requested in review.

(cherry picked from commit e3b788b4ca)
2026-01-27 14:01:44 +00:00
Bernardo Meurer Costa
d297aeca2c feat(libstore/aws-creds): route AWS CRT logs through Nix logger
Previously AWS CRT logs went directly to stderr via ApiHandle::InitializeLogging,
causing log spam that didn't respect Nix's verbosity settings.

This implements a custom aws_logger using the aws-c-common C API that:
- Routes all AWS logs through nix::logger
- Maps AWS log levels conservatively (ERROR/WARN -> lvlInfo) since the SDK
  treats expected conditions like missing IMDS as errors
- Prefixes messages with (aws) for clarity
- Respects Nix's verbosity flags (-v, -vv, etc.)

(cherry picked from commit 3b8b764e29)
2026-01-27 14:01:44 +00:00
internal-nix-ci[bot]
534de0df4e Merge pull request #15084 from NixOS/backport-14645-to-2.33-maintenance
[Backport 2.33-maintenance] feat(libstore): add AWS SSO support for S3 authentication
2026-01-26 18:44:56 +00:00
Jörg Thalheim
65c7ec71ce fix(libstore/aws-creds): respect AWS_PROFILE environment variable
The SSO provider was unconditionally setting profile_name_override to
the (potentially empty) profile string from the S3 URL. When profile
was empty, this prevented the AWS CRT SDK from falling back to the
AWS_PROFILE environment variable.

Only set profile_name_override when a profile is explicitly specified
in the URL, allowing the SDK's built-in AWS_PROFILE handling to work.

(cherry picked from commit 453dbab1e8)
2026-01-26 18:03:26 +00:00
Bernardo Meurer
50aecffbf9 test(s3-binary-cache-store): test profiles and provider chain
(cherry picked from commit 71bdb33a36)
2026-01-26 18:03:26 +00:00
Bernardo Meurer
2d85a6ba32 test(s3-binary-cache-store): clear credential cache between tests
(cherry picked from commit 0595c5f7ee)
2026-01-26 18:03:26 +00:00
Bernardo Meurer
73a0311ef8 test(s3-binary-cache-store): add profile support for setup_for_s3
(cherry picked from commit 11f108d898)
2026-01-26 18:03:26 +00:00
Bernardo Meurer
cb1c413db8 chore(libstore/aws-creds): remove unused includes
(cherry picked from commit 128b2b5c56)
2026-01-26 18:03:26 +00:00
Bernardo Meurer
8a4d8aabb2 fix(libstore/aws-creds): add STS support for default profile
The default (empty) profile case was using CreateCredentialsProviderChainDefault
which didn't properly support role_arn/source_profile based role assumption via
STS because TLS context wasn't being passed to the Profile provider.

This change unifies the credential chain for all profiles (default and named),
ensuring:
- Consistent behavior between default and named profiles
- Proper TLS context is passed for STS operations
- SSO support works for both cases

(cherry picked from commit 508d4463e5)
2026-01-26 18:03:26 +00:00
Bernardo Meurer
344a0eaed1 refactor(libstore/aws-creds): improve error handling and logging
Add validation for TLS context and client bootstrap initialization,
with appropriate error messages when these fail. The TLS context failure
is now a warning that gracefully disables SSO, while bootstrap failure
throws since it's required for all providers.

(cherry picked from commit 3c8e45c061)
2026-01-26 18:03:26 +00:00
Jörg Thalheim
3034589047 libstore: add AWS SSO support for S3 authentication
This enables seamless AWS SSO authentication for S3 binary caches
without requiring users to manually export credentials.

This adds SSO support by calling aws_credentials_provider_new_sso() from
the C library directly. It builds a custom credential chain: Env → SSO →
Profile → IMDS

The SSO provider requires a TLS context for HTTPS connections to SSO
endpoints, which is created once and shared across all providers.

(cherry picked from commit ec91479076)
2026-01-26 18:03:26 +00:00
John Ericson
a2b044dc8d Merge pull request #15078 from xokdvium/backport-15072-to-2.33-maintenance
[Backport 2.33-maintenance] Fix destruction of DerivationBuilder implementations
2026-01-24 19:07:48 -05:00
Sergei Zimmerman
70ecd8c8a9 Fix destruction of DerivationBuilder implementations
This unsures that we call the correct virtual functions when destroying a particular
DerivationBuilder.

Usually the order of destructors is in the reverse order of inheritance:

ChrootLinuxDerivationBuilder -> ChrootDerivationBuilder -> DerivationBuilderImpl

autoDelChroot was being destroyed before the DerivationBuilderImpl::killChild was
run and it would fail to clean up the chroot directory, since there were still processes
writing to it. Note that ChrootLinuxDerivationBuilder::killSandbox was never run in
the interrupted case at all, since virtual functions in destructors do not call derived class
methods.

I could reproduce the issue with the following derivation:

let
  pkgs = import <nixpkgs> { };
in
pkgs.runCommand "chroot-cleanup-race" { } ''
  mkdir -p $out

  for i in $(seq 1 200); do
    (
      mkfifo $out/fifo$i
      cat $out/fifo$i > /dev/null &

      while true; do
        : > $out/file$i
      done
    ) &
  done

  sleep 0.05
  echo done > $out/main
''

While interrupting it manually when it would hang.

Wrapping the unique pointer in a custom deleter function we can run all
of the necessary clean up code consistently and calling the right virtual
functions. Ideally we'd have a lint that bans the usage of virtual functions
in destructors completely.

(cherry picked from commit b752c5cb64)
2026-01-25 02:16:40 +03:00
internal-nix-ci[bot]
a7276a24b9 Merge pull request #15073 from NixOS/backport-15071-to-2.33-maintenance
[Backport 2.33-maintenance] tests: fix sandbox-paths in cancelled-builds test
2026-01-24 21:03:42 +00:00
Robert Hensing
48bf9a8e50 tests: fix sandbox-paths in cancelled-builds test
Don't add the whole store to sandbox-paths unconditionally. Exposing
the entire store defeats the purpose of sandboxing, and when the test
store is the same as the system store (NixOS VM), it causes an obscure
"Permission denied" error.

Only add sandbox-paths when not on NixOS, indicating a separate test
store that needs access to system store build tools.

(cherry picked from commit 7b4444f174)
2026-01-24 20:26:44 +00:00
internal-nix-ci[bot]
2d879efee0 Merge pull request #15068 from NixOS/backport-14972-to-2.33-maintenance
[Backport 2.33-maintenance] Fix concurrent builder failure empty message bugs
2026-01-23 02:16:00 +00:00
Robert Hensing
2ec62f1974 DerivationTrampolineGoal: improve error message wording
Change "cannot build missing derivation" to "failed to obtain derivation of"
since the path (e.g. '...drv^out') is a derivation output, not a derivation.

The message could be improved further to resolve ambiguity when multiple
outputOf links are involved, but for now we err on the side of brevity
since this message is already merged into larger error messages with
other context from the Worker and CLI.

(cherry picked from commit 3c3ceb18e9)
2026-01-23 01:34:46 +00:00
Robert Hensing
09884e2c1a buildPathsWithResults: don't report cancelled goals as failures
When !keepGoing and a goal fails, other goals are cancelled and
remain with exitCode == ecBusy. These cancelled goals have a default
BuildResult::Failure{} with empty errorMsg.

Previously, buildPathsWithResults would return these cancelled goals,
and throwBuildErrors would report them as failures. When only one such
cancelled goal was present, it would throw an error with an empty
message like:

    error: build of '/nix/store/...drv^*' failed:

Now we skip goals with ecBusy since their state is indeterminate.
Cancelled goals could be reported, but this keeps the output relevant.
Other indeterminate goal states were already not being reported, for
instance: derivations that weren't started for being blocked on a
concurrency limit, or blocked on a currently building dependency.

(cherry picked from commit 68f549def4)
2026-01-23 01:34:46 +00:00
Robert Hensing
753bf479f9 tests: don't expect cancelled goals to be reported as failures
When keepGoing=false and a build fails, other goals are cancelled.
Previously, these cancelled goals were reported in the "build of ...
failed" error message alongside actual failures. This was misleading
since cancelled goals didn't actually fail - they were never tried.

Update the test to expect only the actual failure (hash mismatch) to
be reported, not the cancelled goals.

(cherry picked from commit 3fd85c7d64)
2026-01-23 01:34:46 +00:00
Robert Hensing
a6c201e039 DerivationTrampolineGoal: use doneFailure to set buildResult
DerivationTrampolineGoal is the top-level goal whose buildResult is
returned by buildPathsWithResults. When it failed without setting
buildResult.inner, buildPathsWithResults would return failures with
empty errorMsg, producing error messages like:

  error: failed to build attribute 'checks.x86_64-linux.foo',
  build of '/nix/store/...drv^*' failed:

(note the empty message after "failed:")

Use the new doneFailure helper to ensure buildResult is populated
with meaningful error information.

(cherry picked from commit 25eb07a91b)
2026-01-23 01:34:46 +00:00
Robert Hensing
1d39afac38 Goal: add doneSuccess/doneFailure helpers to base class
Add helpers to the base Goal class that set buildResult and call amDone,
ensuring buildResult is always populated when a goal terminates.

Derived class helpers now call the base class versions. This reorders
operations: previously buildResult was set before bookkeeping (counter
resets, worker stats), now it's set after. This is safe because the
bookkeeping code (mcExpectedBuilds.reset(), worker.doneBuilds++,
worker.updateProgress(), etc.) only accesses worker counters, not
buildResult.

(cherry picked from commit cb2ade20d4)
2026-01-23 01:34:46 +00:00
internal-nix-ci[bot]
ba42159b63 Merge pull request #15067 from NixOS/backport-15062-to-2.33-maintenance
[Backport 2.33-maintenance] ci: Drop magic-nix-cache
2026-01-23 01:10:11 +00:00
Sergei Zimmerman
f42de47a40 ci: Drop magic-nix-cache
We are now seeing. I guess we are out with the cache. When the API responds with 418 (I'm a teapot)
it seems like the only reasonable solution is to oblige.

error: unable to download 'http://127.0.0.1:37515/7ms9f25xyxavf32pvdc3vb28nzzmkbn3.narinfo': HTTP error 418
       response body:
       GitHub API error: GitHub Actions Cache throttled Magic Nix Cache. Not trying to use it again on this run.
(cherry picked from commit dae41e06e8)
2026-01-23 00:35:25 +00:00
internal-nix-ci[bot]
a569ebca7e Merge pull request #15057 from NixOS/backport-15047-to-2.33-maintenance
[Backport 2.33-maintenance] fix(libstore/filetransfer): restart source before upload retries
2026-01-22 21:07:05 +00:00
Bernardo Meurer Costa
7808b682bb fix(libstore/filetransfer): restart source before upload retries
When an upload fails with a transient HTTP error (e.g., S3 rate limiting
with HTTP 503), retries would fail with "curl error: Failed to open/read
local data from file/application" because the upload source was already
exhausted from the previous attempt.

Restart the source in init() to ensure it's at the beginning for both
first attempts (no-op) and retries (necessary fix).

Fixes: #15023
(cherry picked from commit fbd787b910)
2026-01-22 20:28:22 +00:00
John Ericson
7672220083 Merge pull request #15052 from lovesegfault/backport-15048-to-2.33-maintenance
[Backport 2.33-maintenance] fix(libstore/filetransfer): skip Accept-Encoding header for S3 SigV4 requests
2026-01-22 14:03:07 -05:00
Bernardo Meurer Costa
ed28ceb12f fix(libstore/filetransfer): skip Accept-Encoding header for S3 SigV4 requests
Some S3-compatible services (like GCS) modify the Accept-Encoding header
in transit, which breaks AWS SigV4 signature verification since curl's
implementation signs all headers including Accept-Encoding.

Fixes: #15019
(cherry picked from commit fcfa1dc8ab)
2026-01-22 18:22:16 +00:00
internal-nix-ci[bot]
f99073b646 Merge pull request #15036 from NixOS/backport-15031-to-2.33-maintenance
[Backport 2.33-maintenance] ci: Bump magic-nix-cache to disable on 429
2026-01-21 05:28:36 +00:00
Sergei Zimmerman
fbffd5683e ci: Bump magic-nix-cache to disable on 429
(cherry picked from commit 1555677cd5)
2026-01-21 04:50:18 +00:00
internal-nix-ci[bot]
ad5cd0b9f3 Merge pull request #15012 from NixOS/backport-15011-to-2.33-maintenance
[Backport 2.33-maintenance] libutil: fix `linux` build on fresh `glibc` and `gcc`
2026-01-17 18:47:08 +00:00
Sergei Trofimovich
c0c13d7323 libutil: fix linux build on fresh glibc and gcc
Without the change the build fails for me as:

    ../unix/file-descriptor.cc:404:70: error: 'RESOLVE_BENEATH' was not declared in this scope
      404 |         dirFd, path.rel_c_str(), flags, static_cast<uint64_t>(mode), RESOLVE_BENEATH | RESOLVE_NO_SYMLINKS);
          |                                                                      ^~~~~~~~~~~~~~~

This happens for 2 reasons:
1. `__NR_openat2` constant was not pulled in from the according headers
   and as a result `<linux/openat2.h>` was not included.
2. `define HAVE_OPENAT2 0` build is broken: refers to missing
   `RESOLVE_BENEATH` normally pulled in from `<linux/openat2.h>`

This changes fixes both.

(cherry picked from commit 3256aba6a2)
2026-01-17 18:01:49 +00:00
Sergei Zimmerman
c272697224 Bump version 2026-01-15 23:37:30 +03:00
internal-nix-ci[bot]
fb562abba9 Merge pull request #14977 from NixOS/backport-14961-to-2.33-maintenance
[Backport 2.33-maintenance] libutil/union-source-accessor: Barf on non-existent directories
2026-01-11 19:46:37 +00:00
Sergei Zimmerman
a77d7b5251 libutil/union-source-accessor: Barf on non-existent directories
Previously builtins.readDir would return an empty attribute set
instead of barfing on non-existent paths. This is a regression from
2.32 for impure eval.

(cherry picked from commit 4ab2cdacfc)
2026-01-11 19:02:58 +00:00
internal-nix-ci[bot]
e12aca79fd Merge pull request #14908 from NixOS/backport-14903-to-2.33-maintenance
[Backport 2.33-maintenance] upload-release.pl: Fix up nix-channels bucket location, use awscli2
2026-01-01 22:05:36 +00:00
Sergei Zimmerman
0ea6142757 upload-release.pl: Fix up nix-channels bucket location, use awscli2
I messed up and accidentally configured the S3 client to use the same
host as the nix-releases bucket, but nix-channels is us-east-1 and
nix-releases is eu-west-1.

(cherry picked from commit 0900638f1d)
2026-01-01 21:17:51 +00:00
internal-nix-ci[bot]
d6d867582e Merge pull request #14902 from NixOS/backport-14888-to-2.33-maintenance
[Backport 2.33-maintenance] ci: GitHub releng for release automation
2026-01-01 15:22:38 +00:00
Sergei Zimmerman
6e098682bd release-process: Document usage of upload-release.yml workflow
(cherry picked from commit 84ff2ef347)
2026-01-01 14:45:35 +00:00
Sergei Zimmerman
9b49b5c050 upload-release: Only upload the newly created tag
(cherry picked from commit 3933e45d52)
2026-01-01 14:45:35 +00:00
Sergei Zimmerman
1e6dad7e2f upload-release: Also push to GHCR as part of the release process
(cherry picked from commit a1569458cc)
2026-01-01 14:45:35 +00:00
Sergei Zimmerman
e999426f05 ci: Add upload-release.yml
This workflow is supposed to automate release uploads by using OIDC
for AWS setup. DockerHub still uses long-lived credentials, but that's
not fixable. In a follow-up we could set up release uploads to GHCR too.

(cherry picked from commit 4599daa10e)
2026-01-01 14:45:35 +00:00
Sergei Zimmerman
32635e4449 maintainers: Document git tag signing
Previously it was only Eeclo doing releases that were signed with
B541D55301270E0BCF15CA5D8170B4726D7198DE. Other linux distributions
have the expectation (rightfully so) that our tags are signed. Let's
document this.

We could do cross-signing to make tracing the chain of trust easier
for all Nix team members [1].

[1]: https://nixos.org/community/teams/nix/

(cherry picked from commit 6cb8b58a47)
2026-01-01 14:45:35 +00:00
Sergei Zimmerman
bb07a0a222 maintainers/upload-release.pl: Make more configurable
This allows for testing with a local minio deployment like:

./upload-release.pl --skip-docker --skip-git --s3-endpoint http://localhost:9000 --s3-host localhost:9000 1821360

(cherry picked from commit d19b8d5f99)
2026-01-01 14:45:35 +00:00
internal-nix-ci[bot]
4c6a9cf2f7 Merge pull request #14886 from NixOS/backport-14872-to-2.33-maintenance
[Backport 2.33-maintenance] ci: Move docker_push_image into a separate workflow
2025-12-28 23:26:56 +00:00
Sergei Zimmerman
d042065a6d ci: Make docker-push workflow more configurable
This should allow reusing this workflow (with more tweaks)
in the releng workflow.

(cherry picked from commit c867ed6726)
2025-12-28 22:39:58 +00:00
Sergei Zimmerman
a6c7082103 ci: Pin actions in docker-push reusable workflow
(cherry picked from commit fb05f6de0d)
2025-12-28 22:39:58 +00:00
Sergei Zimmerman
6e837f6554 ci: Move docker_push_image into a separate workflow
Best reviewed with -w --color-moved. This just moves the code
into a separate workflow. This will allow us to reuse it in
the release job for github releng of releases.

(cherry picked from commit 745983dfc0)
2025-12-28 22:39:58 +00:00
Sergei Zimmerman
b89f9c77cb Merge pull request #14878 from NixOS/backport-14874-to-2.33-maintenance
[Backport 2.33-maintenance] ci: Run flake-regressions also with the newly built daemon
2025-12-29 00:05:08 +03:00
Sergei Zimmerman
c9ec76276d ci: Pin download-artifact actions sha
Also bumps download-artifact to v7.0.0.

(cherry picked from commit c54af23b41)
2025-12-28 18:19:42 +03:00
Sergei Zimmerman
7c8f40f29d ci: Run flake-regressions also with the newly built daemon
Runs the tests against the new daemon as well as the cli.

This more reliably shares the artifact (not relying directly on github
actions cache). We've seen github evict our caches super fast, so it would
be nice to move away from it entirely if possible.

(cherry picked from commit 6eebfe6274)
2025-12-28 18:18:41 +03:00
internal-nix-ci[bot]
59bd5dd874 Merge pull request #14860 from NixOS/backport-14792-to-2.33-maintenance
[Backport 2.33-maintenance] Fix `curl` with `c-ares` failing to resolve DNS inside sandbox on macOS
2025-12-23 10:33:33 +00:00
Michael Hoang
064f279568 Fix curl with c-ares failing to resolve DNS inside sandbox on macOS
(cherry picked from commit 7541129f04)
2025-12-23 09:53:36 +00:00
internal-nix-ci[bot]
986ef4849e Merge pull request #14850 from NixOS/backport-14785-to-2.33-maintenance
[Backport 2.33-maintenance] libstore: include path in the world-writable error
2025-12-21 19:19:29 +00:00
yawkar
d439050b49 libstore: include path in the world-writable error
The previous error message was ambiguous about which specific directory failed the check.

This commit updates checkNotWorldWritable to return the failing path so it can be included in the error message, making debugging easier.

(cherry picked from commit a1e24fa6ce)
2025-12-21 18:37:26 +00:00
internal-nix-ci[bot]
93929038e9 Merge pull request #14840 from NixOS/backport-14837-to-2.33-maintenance
[Backport 2.33-maintenance] libstore/store-api: Do not query all substituters for substitutable p…
2025-12-19 15:34:58 +00:00
Sergei Zimmerman
937ee193f6 libstore/store-api: Do not query all substituters for substitutable path infos
This was broken in 11d7c80370.

(cherry picked from commit 2308f200c8)
2025-12-19 14:48:28 +00:00
internal-nix-ci[bot]
87aca803d0 Merge pull request #14834 from NixOS/backport-14832-to-2.33-maintenance
[Backport 2.33-maintenance] libutil: Gracefully fall back from unsupported O_TMPFILE
2025-12-18 22:13:06 +00:00
Sergei Zimmerman
eb7ee5ad32 libutil: Gracefully fall back from unsupported O_TMPFILE
Some filesystems, notably most FUSE-based ones and some top-level overlaysfs
ones do not support this and we need a graceful fallback.

(cherry picked from commit 06f21596a0)
2025-12-18 21:27:16 +00:00
John Ericson
4d0d3a70b8 Merge pull request #14826 from NixOS/backport-14817-to-2.33-maintenance
[Backport 2.33-maintenance] Windows fixes
2025-12-17 23:07:25 -05:00
John Ericson
28c1f6c677 Fix select / fdset usage on Windows
These functions use `SOCKET` not `int`, despite them being unix
functions.

(cherry picked from commit 208ed3c538)
2025-12-17 22:18:48 -05:00
John Ericson
9c6885a0bf Split out socket.hh from unix-domain-socket.hh
There are other types of sockets.

(cherry picked from commit 79750a3ccc)
2025-12-17 22:18:48 -05:00
internal-nix-ci[bot]
37beb895a0 Merge pull request #14820 from NixOS/backport-14818-to-2.33-maintenance
[Backport 2.33-maintenance] Fix up dev shell in a few ways
2025-12-17 22:58:26 +00:00
John Ericson
e2efb62dcc Fix up dev shell in a few ways
- Skip packages that don't build for Windows when building for windows
- Automatically disable kaitai / json schema, fixing todo
- Skip native build of Nix for manual

(cherry picked from commit a5edc2d921)
2025-12-17 22:19:32 +00:00
internal-nix-ci[bot]
4e50751b26 Merge pull request #14813 from NixOS/backport-14806-to-2.33-maintenance
[Backport 2.33-maintenance] build(deps): bump korthout/backport-action from 3.4.1 to 4.0.1
2025-12-16 21:32:49 +00:00
dependabot[bot]
b009f0cd7a build(deps): bump korthout/backport-action from 3.4.1 to 4.0.1
Bumps [korthout/backport-action](https://github.com/korthout/backport-action) from 3.4.1 to 4.0.1.
- [Release notes](https://github.com/korthout/backport-action/releases)
- [Commits](d07416681c...c656f5d585)

---
updated-dependencies:
- dependency-name: korthout/backport-action
  dependency-version: 4.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
(cherry picked from commit 4227d24bc3)
2025-12-16 20:48:07 +00:00
Jörg Thalheim
2d5ea368e6 Merge pull request #14812 from Mic92/backport-14799-to-2.33-maintenance
libfetchers: Bump tarball-cache version to v2 [backport 2.33]
2025-12-16 20:58:19 +01:00
Sergei Zimmerman
b5e903974f libfetchers: Bump tarball-cache version to v2
Unfortunately previous tarball caches had loose objects written to
them and subsequent switch to thin packfiles. This results in possibly
broken thin packfiles when the loose objects backend is disabled. Thin
packfiles do not necessarily contain the whole closure of objects.
When packfilesOnly is true we end up with an inconsistent state where
a tree lives in a packfiles which refers to a blob in the loose objects
backend.

In the future we might want to nuke old cache directories and repack
the tarball cache.

(cherry picked from commit 0ffe83aa14)
2025-12-16 20:13:04 +01:00
internal-nix-ci[bot]
40c8a70224 Merge pull request #14783 from NixOS/backport-14772-to-2.33-maintenance
[Backport 2.33-maintenance] [libstore]: Fix a heap-use-after-free bug
2025-12-13 01:53:48 +00:00
Graham Dennis
8cedbcef67 [libstore]: Fix a heap-use-after-free bug
(cherry picked from commit 819a61acae)
2025-12-13 01:07:58 +00:00
Eelco Dolstra
87008315a9 Bump version 2025-12-10 23:00:34 +01:00
John Ericson
231d5b41ed Bring nix derivation show in compliance with JSON guidelines
This matches what we just did for `nix path-info`, and I hope will allow
us to avoiding any more breaking changes to this command for the
foreseeable future.

(cherry picked from commit 0f18076f3a)
2025-12-10 21:38:26 +01:00
Eelco Dolstra
72f62e1b19 Mark official release 2025-12-10 17:19:20 +01:00
Eelco Dolstra
8b955d80c2 Merge pull request #14752 from NixOS/release-notes
2.33 release notes
2025-12-10 15:37:55 +00:00
Eelco Dolstra
3e832b61ec Merge pull request #14759 from NixOS/fix-netrc-path
globals: Fix netrc-file default value
2025-12-10 12:19:58 +00:00
Sergei Zimmerman
fd6c4614cf globals: Fix netrc-file default value
std::filesystem::path does quoting by default so it resulted in:

> netrc-file = "/etc/nix"/netrc
2025-12-10 03:34:10 +03:00
Sergei Zimmerman
99baaf7444 Add more release notes 2025-12-10 02:08:02 +03:00
Eelco Dolstra
46895edfce Fix issues found by Claude 2025-12-09 16:53:40 +01:00
Eelco Dolstra
17f07f6c04 Add more release notes 2025-12-09 16:48:02 +01:00
Eelco Dolstra
9c2be01285 Organize release notes 2025-12-09 16:17:36 +01:00
Eelco Dolstra
8493c541fa Update release credits 2025-12-09 15:36:45 +01:00
Eelco Dolstra
68a802d253 release notes: 2.33.0 2025-12-09 15:26:59 +01:00
John Ericson
7448aedd74 Merge pull request #14745 from NixOS/fix-build-dir-docs
Correct `build-dir` error in manual, link relevant settings
2025-12-09 00:45:25 +00:00
John Ericson
19db567c67 Merge pull request #14744 from NixOS/gc-actions-daemon-check
daemon: Add WorkerProto serialiser for GCAction
2025-12-09 00:16:54 +00:00
John Ericson
c5fa5e503a Correct build-dir error in manual, link relevant settings
This fixes out-of-date information that is no longer true, and makes the
up-to-date information more accessible.
2025-12-08 18:55:31 -05:00
Sergei Zimmerman
afc2b96c5e Merge pull request #14741 from NixOS/better-variant-wrapper
Fix `MAKE_WRAPPER_CONSTRUCTOR` to not override special constructors
2025-12-08 23:26:03 +00:00
Sergei Zimmerman
f2465bccba daemon: Add WorkerProto serialiser for GCAction
Previously the daemon didn't validate that it got a valid GCAction
and did a naive C-style cast to the enum. This is certainly unintentional,
albeit mostly harmless in practice.
2025-12-09 01:57:39 +03:00
John Ericson
bc0af77ba7 Merge pull request #14743 from NixOS/sri-in-json
Use SRI hash (strings) as the official JSON format for Hash after all
2025-12-08 22:25:11 +00:00
Jörg Thalheim
8ab5c2bc21 Merge pull request #14736 from NixOS/builtins-path-references
builtins.path: Propagate references from derivation outputs
2025-12-08 22:22:24 +00:00
John Ericson
61de9222b0 Use SRI hash (strings) as the official JSON format for Hash after all
The fact that we were introducing a conversion from the output of `nix
path-info` into the input of `builtins.fetchTree` was the deciding
factor. We want scripting outputs into inputs like that to be easy.

Since JSON strings and objects are trivially distinguishable, we still
have the option of introducing the JSON format as an alternative input
scheme in the future, should we want to. (The output format would still
be SRI in that case, presumably.)
2025-12-08 16:50:25 -05:00
John Ericson
28107db1bb Merge pull request #14739 from Mic92/nix-develop
turn 'derivation has incorrect deferred output' into warning
2025-12-08 21:44:14 +00:00
John Ericson
6ffdd4652b Merge pull request #14742 from NixOS/fix-mingw
nix/cat: Fix mingw for real
2025-12-08 21:41:40 +00:00
John Ericson
401e08f839 Fix mistake in the release note for derivations
Floating CA outputs just have a hash algorith, not a whole hash. It is
fixed ones which are a pair of a method and a hash, just like the `ca`
field of store object info.
2025-12-08 16:18:09 -05:00
John Ericson
14feb36cd6 Hash::parseSRI add explicit XP settings parameter
This will be used for unit testing.
2025-12-08 16:18:08 -05:00
Sergei Zimmerman
8f89d8c139 nix/cat: Fix mingw for real 2025-12-08 23:57:28 +03:00
Jörg Thalheim
623f3d321e turn 'derivation has incorrect deferred output' into warning
this breaks nix develop when using a stable nix version

Update src/libstore/derivations.cc

Co-authored-by: John Ericson <git@JohnEricson.me>
2025-12-08 15:56:57 -05:00
John Ericson
e73bb666c5 Fix MAKE_WRAPPER_CONSTRUCTOR to not override special constructors
It should not effect move / copy / etc. constructors.
2025-12-08 14:19:19 -05:00
Eelco Dolstra
02055c5a48 addPath(): Restore catching InvalidPathError 2025-12-08 19:17:07 +01:00
Eelco Dolstra
c080c4ca56 builtins.path: Propagate references from derivation outputs
This restores compatibility with Nix 2.18, which behaved this
way. Note that this doesn't scan for the actually visible references.

Unlike in Nix 2.18, we only do this for paths with context, i.e. it
applies to `builtins.storePath "/nix/store/bla..."` but not
`"/nix/store/bla..."`. We don't want the latter because it shouldn't
matter whether a source file happens to be in the Nix store.
2025-12-08 19:16:44 +01:00
John Ericson
907a5761fa Merge pull request #14707 from obsidiansystems/store-dir-in-info
Make `storeDir` a part of `UnkeyedValidPathInfo`
2025-12-08 18:00:42 +00:00
Eelco Dolstra
a95580e468 Merge pull request #14723 from NixOS/peer-info
daemon.cc: Clean up PeerInfo by using std::optional
2025-12-08 17:57:31 +00:00
Eelco Dolstra
8c2027e138 authPeer(): Use std::optional instead of empty string 2025-12-08 12:57:19 +01:00
Eelco Dolstra
26bf932e41 Merge pull request #14731 from NixOS/fix-hydra-for-release
Fix failing hydra jobs for release
2025-12-08 11:18:55 +00:00
Eelco Dolstra
386d1d54bd Merge pull request #14724 from obsidiansystems/derivation-options-test-file-names
Organize some test JSON better to prevent confusion
2025-12-08 11:17:55 +00:00
Eelco Dolstra
32bc0ac43e Merge pull request #14720 from obsidiansystems/nix-hash-convert-improve-error
Improve wrong format message with `nix hash convert`
2025-12-08 11:17:07 +00:00
John Ericson
ffc5dffa65 Merge pull request #14732 from NixOS/optimize-nar-cat
nix nar {ls,cat}: Optimize, make nix nar cat work on pipes too
2025-12-08 06:08:02 +00:00
Sergei Zimmerman
c5c05e44b3 Make nix nar cat work on pipes too
This was lost after 2.32 while making the accessor lazy. We can restore the support
for it pretty easily. Also this is significant optimization for nix nar cat.
E.g. with a NAR of a linux repo this speeds up by ~3x:

Benchmark 1: nix nar cat /tmp/linux.nar README
  Time (mean ± σ):     737.2 ms ±   5.6 ms    [User: 298.1 ms, System: 435.7 ms]
  Range (min … max):   728.6 ms … 746.9 ms    10 runs

Benchmark 2: build/src/nix/nix nar cat /tmp/linux.nar README
  Time (mean ± σ):     253.5 ms ±   2.9 ms    [User: 56.4 ms, System: 196.3 ms]
  Range (min … max):   248.1 ms … 258.7 ms    12 runs
2025-12-08 03:26:03 +03:00
Sergei Zimmerman
b9b6defca6 nix nar {ls,cat}: Optimize
The whole NarAccessor -> listing -> lazy NarAccessor is very weird. Source
can now be seek-ed over when supported, so we can support it pretty easily.
Alternatively we could also make it single-pass very easily with a custom
FileSystemObjectSink. It will get removed in a follow-up commit anyway.
2025-12-08 03:26:02 +03:00
Sergei Zimmerman
22f993fab6 libutil: Get rid of TODO comments for O_CLOEXEC
By default windows doesn't allow inheriting handles anyway. These comments
are just confusing at this point.
2025-12-08 01:10:14 +03:00
Sergei Zimmerman
0302cd00c9 packaging/hydra: Don't build kaitai nar docs tests in hydra
It's not evaling on hydra currently and is only part of the docs. Support
for this it best effort at best so we should not build this in hydra, considering
the amount of effort required to support this. I would even consider dropping these
checks and component altogether, since there doesn't seem to be much interest in maintaining
these docs from the core team anyway.
2025-12-08 00:37:10 +03:00
Sergei Zimmerman
2f80fc473f libexpr-tests: Work around LTO issue with SAMPLE_USER_DATA on i686-linux with sanitizers
This somehow fails https://hydra.nixos.org/build/315675349/nixlog/1. I don't know the exact
details, but it seems that something goes very wrong with LTO and sanitizers that lead to the
string literal to be moved? Instead of relying on the string literal deduplication to provide
a consistent address we can use a global. That should have a single address (modulo wonky copy
relocations).
2025-12-08 00:24:46 +03:00
Sergei Zimmerman
d4434809fe tests/nixos/fethers-substitute: Fix for nix path-info --json-format 2 2025-12-07 22:59:22 +03:00
Sergei Zimmerman
1d56f413c2 Merge pull request #14728 from roberth/doc-evaluation-infinite-recursion
doc: Document "evaluation order", some strictness, equality quirk, `||`, `&&`
2025-12-07 19:06:51 +00:00
John Ericson
d8ad0006c0 Merge pull request #14729 from NixOS/fix-add-dep
Fix Non-virtual interface pattern for `RestrictedStore::addDependency`
2025-12-07 17:23:21 +00:00
John Ericson
4652345ac3 Fix Non-virtual interface pattern for RestrictedStore::addDependency
I didn't do things quite right in 496e43ec72:

- Forgot to remove the now-redundant `isAllowed` check.

- Called the non-virtual, not the superclass's impl, in
  `addDependencyPrep`, causing bad recursion / UB.

Doing this fixes a crash I encountered with manual testing an Nix Ninja
--- hopefully we will get Nix Ninja or similar in a NixOS test longer
term to defend against this thing happening again.
2025-12-07 11:33:41 -05:00
Robert Hensing
6fb5276e7b test: add tests for function equality behavior
Add tests for function equality covering both direct comparisons and
comparisons within composite types (lists and attribute sets).

Tests verify:
- Direct function comparisons always return false
- Value identity optimization in composite types allows identical
  functions to compare as equal when both references point to the
  same function value
2025-12-07 14:43:46 +01:00
Robert Hensing
97a60c1fab doc: Precedence aligns with disjunctive normal form 2025-12-07 14:10:16 +01:00
Robert Hensing
1039b6719b doc: Document "evaluation order", some strictness, equality quirk
Correct and clarify evaluation semantics including to help users
understand Nix language behavior without unnecessarily pinning down
the implementation.
2025-12-07 13:55:25 +01:00
John Ericson
42d7d9676d Merge pull request #14727 from roberth/issue-14548
Make mdBook dependency optional (#14548), fix manpage links
2025-12-06 22:49:31 +00:00
Robert Hensing
ab0ca5f922 doc: make HTML manual build optional
Add `html-manual` Meson option to allow building manpages without the
HTML manual, removing the mdbook dependency for manpage-only builds.

Changes:
- Add `html-manual` Meson option (default: true)
- Make HTML manual build conditional in meson.build
- Add `buildHtmlManual` parameter to package.nix
- Conditional outputs: ["out" "man"] when enabled, ["out"] when disabled
- Make mdbook/rsync/json-schema-for-humans dependencies conditional
- Add `nix-manual-manpages-only` package variant

This allows systems that only need manpages to avoid the mdbook build
dependency while preserving full functionality for HTML manual builds.
2025-12-06 22:35:45 +01:00
Robert Hensing
cca8b5ca60 doc: make manpage URLs configurable based on release type
Add configurable documentation URLs that change based on whether this is
an official release or development build:

- Nix builds:
  - Development (officialRelease = false): Use /latest/ URLs
  - Official releases (officialRelease = true): Use versioned URLs with
    MAJOR.MINOR only (e.g., /2.33/ instead of /2.33.0/)
- Plain meson builds: Default to versioned URLs (official-release = true)

Changes:
- Add --doc-url parameter to expand-includes.py
- Add meson option 'official-release' (defaults to true for Meson builds)
- Compute doc_url in meson.build based on version and official-release
- Forward Nix officialRelease variable to Meson in package.nix
- Update render-manpage.sh to pass doc-url parameter

This allows distros (Fedora, etc.) to have stable versioned URLs by default,
while Nix development builds point to /latest/ for up-to-date documentation.
2025-12-06 22:13:19 +01:00
Robert Hensing
d007b4e81b doc: make manpage generation independent of mdbook
Add standalone markdown preprocessor to generate manpages without requiring
mdbook's Rust toolchain. This removes a significant build dependency for
manpage generation while keeping the HTML manual (mdbook) working unchanged.

Changes:
- Add expand-includes.py: Python 3 script that recursively expands
  {{#include}} directives, resolves @docroot@ to nix.dev URLs, and handles
  @generated@/ paths for build-generated files
- Update render-manpage.sh: Replace mdbook-based implementation with
  standalone version that uses expand-includes.py + lowdown
- Update meson.build: All 134 manpage targets now use standalone renderer
  with proper dependencies (expand-includes.py, experimental-features-shortlist)
- Fix nix-hash.md: Remove extra parenthesis in markdown link syntax

Benefits:
- No mdbook/Rust toolchain required for manpage builds
- Manpages contain nix.dev/latest URLs instead of broken relative paths
- Fixes bug where mdbook didn't expand experimental-features-shortlist.md
- 98.5% identical output to mdbook (2 files differ, both acceptable)

All 134 manpages (131 section 1, 2 section 5, 1 section 8) build successfully.
2025-12-06 21:34:44 +01:00
John Ericson
843629f7bf Organize some test JSON better to prevent confusion
It was not clear which of thes were JSON for derivation vs JSON for
derivation options.
2025-12-05 19:37:07 -05:00
John Ericson
525755dadc Merge pull request #14722 from raboof/document-sembr
chore: document we use sembr in the docs
2025-12-06 00:03:17 +00:00
Eelco Dolstra
5d7f6efc82 daemon.cc: Clean up PeerInfo by using std::optional 2025-12-05 23:36:29 +01:00
Arnout Engelen
2bf3235115 chore: document we use sembr in the docs
https://github.com/NixOS/nix/pull/14557#issuecomment-3618664183
2025-12-05 23:17:13 +01:00
John Ericson
0db70b8184 Merge pull request #14711 from roberth/check-redirect-targets
Check and fix nix-manual redirect targets
2025-12-05 22:02:51 +00:00
John Ericson
b61885786d Improve wrong format message with nix hash convert
We have the machinery to make a more informative error, telling the
user what format was actually encountered, and not just that it is not
the format that was requested.
2025-12-05 15:12:08 -05:00
Robert Hensing
c8601a27df Fix redirects.json targets
Most of them were fixable.
The S3 ones were made available in c5ed22dd41.
2025-12-05 16:53:46 +01:00
Robert Hensing
d5099279f8 Remove _redirects from link checking for now
Since it is apparently not deployed correctly on nix.dev, we can't
meaningfully work with it now.
2025-12-05 16:53:46 +01:00
Robert Hensing
ee30827e20 Check nix-manual redirect targets in linkcheck
Augments the manual with a generated file before running the usual check.
2025-12-05 16:53:46 +01:00
Robert Hensing
3632abb7a5 nix-manual: Split out redirects.json 2025-12-05 16:53:46 +01:00
John Ericson
5f42e5ebb7 Merge pull request #14717 from NixOS/attr-path
Introduce AttrPath type
2025-12-05 15:51:09 +00:00
John Ericson
926092f67f Merge pull request #14714 from NixOS/derived-path-operator
DerivedPath: Remove superfluous operator ==
2025-12-05 15:46:28 +00:00
Eelco Dolstra
20fc54c00d Introduce AttrPath type
This is basically an alias for std::vector<Symbol>.
2025-12-05 13:41:59 +01:00
Eelco Dolstra
294e68a3f6 Rename AttrPath -> AttrSelectionPath 2025-12-05 12:57:19 +01:00
Eelco Dolstra
92d4fafd53 Merge pull request #14713 from lovesegfault/fix-s3-docs
fix(libstore/s3-binary-cache-store): include documentation from markdown file
2025-12-05 11:38:25 +00:00
Eelco Dolstra
953e7b8af4 DerivedPath: Remove superfluous operator ==
This is already implied by the fact that it inherits from
std::variant.
2025-12-05 10:26:36 +01:00
Bernardo Meurer
c5ed22dd41 fix(libstore/s3-binary-cache-store): include documentation from markdown file
The S3BinaryCacheStoreConfig::doc() function was returning a minimal
hardcoded 3-line string instead of including the comprehensive
documentation from s3-binary-cache-store.md.

This was introduced in PR #13752 which moved the prose documentation to
the markdown file but forgot to update the doc() function to use it.
2025-12-04 22:30:32 -05:00
Eelco Dolstra
a595348f7c Merge pull request #14709 from NixOS/fix-mingw
More mingw fixes
2025-12-04 17:33:40 +00:00
John Ericson
a4fc3863dd Merge pull request #14708 from obsidiansystems/version-path-info-outer
Make `nix path-info` follow the JSON guidelines
2025-12-04 17:16:17 +00:00
Eelco Dolstra
c555af2c77 More mingw fixes 2025-12-04 17:56:07 +01:00
John Ericson
5f73c6b416 Make nix path-info follow the JSON guildelines 2025-12-03 23:41:48 -05:00
John Ericson
f9089deb20 Make storeDir a part of UnkeyedValidPathInfo
The previous commit hacked it into the output of `nix path-info --json`,
this cleans that up my making it an actual field of that data type, and
part of the canonical JSON serializers for it (and `ValidPathInfo` and
`NarInfo`).

Beyond cleaning up the JSON code, this also opens the doors to things
like:

- Binary caches that contain store objects that don't all belong in the
  same store directory

- Relocatable store objects which carefully don't mention any store
  directory by absolute path, and instead use relative paths for
  anything. (#9549)
2025-12-03 23:20:06 -05:00
John Ericson
9246dca541 Merge pull request #14704 from NixOS/version-output
Introduce `--json-format` for `nix path-info`
2025-12-04 03:48:49 +00:00
John Ericson
676fb0fffc Merge pull request #14705 from NixOS/pathinfo-cache-string-to-store-path
libstore: Make Store::pathInfoCache use StorePath instead of std::string
2025-12-04 03:33:51 +00:00
John Ericson
9f0d1e9509 Merge pull request #14706 from roberth/document-scopedImport
Document scopedImport builtin
2025-12-04 03:32:40 +00:00
John Ericson
1ad13a1423 Introduce --json-format for nix path-info
As discussed today at great length in the Nix meeting, we don't want to
break the format, but we also don't want to impede the improvement of
JSON formats. The solution is to add a new flag for control the output
format.

Note that prior to the release, we may want to replace `--json
--json-format N` with `--json=N`, but this is being left for a separate
PR, as we don't yet have `=` support for CLI flags.
2025-12-03 22:04:21 -05:00
Sergei Zimmerman
7f1712957a Merge pull request #14681 from NixOS/cgroup-stats
Add getCgroupStats() function
2025-12-04 01:04:18 +00:00
Robert Hensing
a4680cd9bb Add link to scopedImport documentation 2025-12-04 01:53:54 +01:00
Robert Hensing
b69c565fdb Document scopedImport builtin 2025-12-04 01:40:06 +01:00
Sergei Zimmerman
ee9fb29c7b libstore: Make Store::pathInfoCache use StorePath instead of std::string
Just a simple cleanup.
2025-12-04 02:20:43 +03:00
John Ericson
69920f9557 Merge pull request #14536 from NixOS/clamp-down-hash
JSON for `Hash` now has to be `Base16`
2025-12-03 21:41:05 +00:00
John Ericson
bec3c5cfcd JSON for Hash now has to be Base16
Fix #14532.

As discussed on the call today:

1. We'll stick with `format = "base16"` and `hash = "<hash>"`, not do
   `base16 = "<hash>"`, in order to be forward compatible with
   supporting more versioning formats.

   The motivation we discussed for someday *possibly* doing this is
   making it easier to write very slap-dash lang2nix tools that create
   (not consume) derivations with dynamic derivations.

2. We will remove support for non-base16 (and make that the default, not
   base64) in `Hash`, so this is strictly forward contingency, *not*
   yet something we support. (And also not something we have concrete
   plans to start supporting.)
2025-12-03 16:08:05 -05:00
Eelco Dolstra
29849afa63 Merge pull request #14661 from roberth/issue-13994
Document and test -- separator behavior with installables
2025-12-03 20:14:43 +00:00
Eelco Dolstra
5b95745bc9 Merge pull request #14702 from NixOS/fix-mingw
Fix mingw build
2025-12-03 19:55:03 +00:00
Eelco Dolstra
8d0e289fb9 Fix FdSource::restart() warning 2025-12-03 20:09:33 +01:00
Eelco Dolstra
c338f9cc5d Fix mingw build 2025-12-03 20:09:33 +01:00
John Ericson
c7801fc347 Merge pull request #14701 from NixOS/print-table
Move printTable() into libutil
2025-12-03 18:49:51 +00:00
Eelco Dolstra
c4dc42f306 printTable(): Make destination stream explicit 2025-12-03 18:43:56 +01:00
Eelco Dolstra
ab6dcf2047 Table: Use std::vectors 2025-12-03 18:43:51 +01:00
Eelco Dolstra
863f6811e4 Move table stuff into libutil 2025-12-03 18:42:11 +01:00
John Ericson
96d8b54e42 Merge pull request #14696 from NixOS/even-faster-tarball-cache
libfetchers/git-utils: Do not refresh pack files in GitFileSystemObje…
2025-12-03 15:31:43 +00:00
Sergei Zimmerman
d1f9fe984b libfetchers/git-utils: Do not refresh pack files in GitFileSystemObjectSink
This leads to incredibly wasteful refreshes (see [^]) when oids are not found.
Since we are writing the pack files only once per unpacking we should not bother
with this refreshing at all.

This brings down the number of syscalls during `nix flake metadata "https://releases.nixos.org/nixos/25.05/nixos-25.05.813095.1c8ba8d3f763/nixexprs.tar.xz" --store "dummy://?read-only=false"`

Down from 576334 to just 6235 (100x less syscalls):

(Before)

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ------------------
 32.98    0.625288           3    162898           getdents64
 29.58    0.560686           3    163514     81917 openat
 15.01    0.284509           3     81819       186 newfstatat
 10.99    0.208349           2     81601           close
 10.56    0.200145           2     81552           fstat

All these are coming from [2] and are totally useless.

(After)

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ------------------
 76.47    0.108558         247       438        20 futex
  6.55    0.009292          18       513           munmap
  3.30    0.004680           7       639       492 openat
  2.68    0.003803          10       359           write
  2.30    0.003268           2      1146           read
  2.26    0.003215           3       870           mmap

[^]: 58d9363f02/include/git2/sys/odb_backend.h (L68-L75)
[2]: 58d9363f02/src/libgit2/odb_pack.c (L517-L546)
2025-12-03 03:23:12 +03:00
John Ericson
ec6789f9da Merge pull request #14690 from roberth/mdbook-0.5
Support mdbook 0.5
2025-12-02 13:40:03 +00:00
John Ericson
e67c97b5f0 Merge pull request #14689 from NixOS/tarball-cache-faster
libfetchers/git-utils: Avoid using git_writestream for small files
2025-12-02 03:53:54 +00:00
Sergei Zimmerman
1b2cb1d75c libfetchers/git-utils: Only create pack and mempack backends for the tarball cache
Now the unnecessary utimensat syscalls from the previous commit
are completely gone:

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ------------------
 33.39    0.646359           3    162898           getdents64
 29.34    0.567866           3    163523     81934 openat
 14.81    0.286739           3     81835       203 newfstatat
 10.98    0.212550           2     81593           close
 10.56    0.204458           2     81544           fstat
  0.15    0.002814           3       870           mmap

The rather crazy amount of getdents64 is still there though.
2025-12-02 06:09:03 +03:00
John Ericson
7f3ad17ac2 Merge pull request #14687 from NixOS/repl-print-interrupt
libutil/signals: Get rid of setInterruptThrown
2025-12-02 02:50:01 +00:00
Sergei Zimmerman
2f6550b7a7 libfetchers/git-utils: Avoid using git_writestream for small files
It turns out that libgit2 is incredibly naive and each git_writestream creates
a new temporary file like .cache/nix/tarball-cache/objects/streamed_git2_6a82bb68dc0a3918
that it reads from afterwards. It doesn't do any internal buffering.

Doing (with a fresh fetcher cache) a simple:

strace -c nix flake metadata "https://releases.nixos.org/nixos/25.05/nixos-25.05.813095.1c8ba8d3f763/nixexprs.tar.xz" --store "dummy://?read-only=false"

(Before)

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ------------------
 31.05    2.372728           9    259790     81917 openat
 19.21    1.467784          30     48157           unlink
 10.43    0.796793           4    162898           getdents64
  7.75    0.592637           4    145969           read
  7.67    0.585976           3    177877           close
  7.11    0.543032           4    129970       190 newfstatat
  6.98    0.533211          10     48488           write
  4.09    0.312585           3     81443     81443 utimensat
  3.22    0.246158           3     81552           fstat

(After)

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ------------------
 29.61    0.639393           3    162898           getdents64
 26.26    0.567119           3    163523     81934 openat
 12.50    0.269835           3     81848       207 newfstatat
 11.60    0.250429           3     81443     81443 utimensat
  9.82    0.212053           2     81593           close
  9.33    0.201390           2     81544           fstat
  0.18    0.003814           9       406        17 futex
2025-12-02 04:48:43 +03:00
Robert Hensing
0aef1ddb9e maint: Fix lowdown override compatibility with newer nixpkgs
Use `or ""` fallback for postInstall attribute which may not exist in
newer nixpkgs versions of lowdown.
2025-12-02 02:38:33 +01:00
Robert Hensing
2636f50dd4 maint: Remove mdbook-linkcheck and support mdbook 0.5.x
Fixes #14628

- Remove mdbook-linkcheck dependency and configuration (was blocking
  upgrades to mdbook 0.5.0+, configured with warning-policy = "ignore"
  due to false positives, and redundant with lychee-based link checking)
- Update substitute.py and anchors.jq to handle 'items' (mdbook 0.5.x)
  in addition to 'sections' (mdbook 0.4.x), as per mdbook 0.5.0
  changelog: "Book::sections was renamed to Book::items"
  https://github.com/rust-lang/mdBook/blob/master/CHANGELOG.md#05-migration-guide
2025-12-02 02:38:30 +01:00
Sergei Zimmerman
0ec93e7ae7 libfetchers/git-utils: Clean up
Makes private functions static and removes dead code that was used
for fetching, but is currently dead.
2025-12-02 04:11:57 +03:00
Sergei Zimmerman
c0c1bde506 libutil/signals: Get rid of setInterruptThrown
The interrupting code is no longer relevant. Since
054be50257 logging no longer checks for interrupts
and in general logging should be noexcept.

Co-authored-by: Alois Wohlschlager <alois1@gmx-topmail.de>
Cherry-picked-from: https://gerrit.lix.systems/c/lix/+/1097
2025-12-02 00:59:49 +03:00
Sergei Zimmerman
d2615571e2 Merge pull request #14669 from NixOS/bump-nixpkgs
flake: Bump nixpkgs
2025-12-01 21:07:05 +00:00
Eelco Dolstra
18e31d404b Merge pull request #14682 from NixOS/autodelete-move
AutoDelete: Add move constructor
2025-12-01 13:33:06 +00:00
Eelco Dolstra
0f4c7204f7 Mark move constructor as noexcept
Co-authored-by: Sergei Zimmerman <sergei@zimmerman.foo>
2025-12-01 13:46:59 +01:00
Eelco Dolstra
2c28502bc4 Add getCgroupStats() function 2025-12-01 13:43:51 +01:00
Eelco Dolstra
34e92724d6 AutoDelete: Add move constructor 2025-12-01 13:39:03 +01:00
John Ericson
890a4e980a Merge pull request #14677 from NixOS/restartable-source-no-path
libutil: Get rid of restartableSourceFromFactory, add createAnonymousTempFile
2025-12-01 03:46:48 +00:00
John Ericson
a922a42b33 Merge pull request #14678 from NixOS/fix-error-message-download-filetransfer
libstore/filetransfer: Fix error message for interrupted requests
2025-12-01 03:39:25 +00:00
Sergei Zimmerman
7eab0bf9aa libstore/filetransfer: Fix error message for interrupted requests
Sometimes we are uploading and that's confusing.
2025-12-01 05:34:29 +03:00
John Ericson
1e9b1ff851 Merge pull request #14676 from NixOS/fs-fixes
libstore: Use makeTempPath in optimizePath_, assorted fs fixes
2025-12-01 01:55:20 +00:00
Sergei Zimmerman
4b3536e092 libutil: Get rid of restartableSourceFromFactory
Instead we can just seek back in the file - duh. Also this makes use
of the anonymous temp file facility, since that is much safer (no need
window where the we don't have an open file descriptor for it).
2025-12-01 04:49:27 +03:00
Sergei Zimmerman
4ad272015e libutil: Implement createAnonymousTempFile
There are a lot of cases where we don't care about having
the temporary file linked anywhere at all -- just a descriptor is more
than enough.
2025-12-01 04:49:26 +03:00
Sergei Zimmerman
40e3f5c0a4 libutil: Make AutoDelete non-copyable and non-movable
This is a good precaution, since we don't want to delete
directories twice accidentally.
2025-12-01 03:09:20 +03:00
Sergei Zimmerman
bf7c53f2d3 libutil: Propagate error code in createSymlink 2025-12-01 03:00:45 +03:00
Sergei Zimmerman
1cc337bb5f libstore: Actually correctly call remove in case rename fails 2025-12-01 02:56:44 +03:00
Sergei Zimmerman
d888846b68 libstore: Use makeTempPath in optimizePath_
This was intended to be cherry-picked in 6aed9d877c,
but was left hanging. This is actually important for fixing [^]. emilazy let me know
of this bad cherry-pick and its significance.

[^]: https://github.com/NixOS/nix/issues/7273

Originally fixed by Lily Ballard <lily@ballards.net> in https://gerrit.lix.systems/c/lix/+/2100.
2025-12-01 02:51:37 +03:00
tomberek
8be9507a88 Merge pull request #14670 from juhp/RLO-chars
release-notes/rl-2.26.md: remove hidden Unicode RLO control chars
2025-11-30 20:00:38 +00:00
John Ericson
5b175ace18 Merge pull request #14675 from NixOS/cleanup-verb-filetransfer
libstore: Split FileTransferRequest::verb into verb + noun
2025-11-30 16:59:56 +00:00
Sergei Zimmerman
430bcda3ea libstore: Split FileTransferRequest::verb into verb + noun
With the addition of "delete" method we can no longer rely on
just concatenating "ing" to get the continuous form of the verb.
Also some use-cases actually need a noun instead.
2025-11-30 18:49:11 +03:00
John Ericson
d7c29383c6 Merge pull request #14674 from Mic92/ca-derivation
Fix crash when querying realisations without ca-derivations enabled
2025-11-30 14:30:53 +00:00
Jörg Thalheim
ee5860f542 Fix crash when querying realisations without ca-derivations enabled
queryRealisationUncached was crashing with an assertion failure when
ca-derivations experimental feature is not enabled, because the SQLite
statements for realisations are only initialized when ca-derivations
is enabled.

Return nullptr (no realisation found) when ca-derivations is disabled,
matching the behavior of other CA-related functions like registerDrvOutput
which check for the feature before proceeding.
2025-11-30 14:25:11 +01:00
Jens Petersen
dacd5eac64 release-notes/rl-2.26.md: remove hidden Unicode RLO control chars (#14666)
They are flagged by Fedora CI checks as a potential security issue.
Use of such raw Right-to-Left control characters in source code is
strongly discouraged

also update release-credits-handle-to-name.json
2025-11-30 18:38:18 +08:00
John Ericson
3a32039508 Merge pull request #14672 from NixOS/fix-13948
libfetchers: Fix fetchGit with ref = "HEAD"
2025-11-30 01:03:01 +00:00
John Ericson
01dbbc926f Merge pull request #14540 from lovesegfault/pre-compute-outputgraph
perf(libstore/derivation-builder): pre-compute outputGraph for linear complexity
2025-11-29 21:46:21 +00:00
Sergei Zimmerman
18f3598d57 libfetchers: Fix fetchGit with ref = "HEAD"
This seems to have been broken in ee9fa0d360.
Adding the HEAD:HEAD refspec looks like the correct solution.

Suggested-by: hxtmdev on github
2025-11-29 05:39:04 +03:00
John Ericson
c33b2c5834 perf(libstore/derivation-builder): Futher simplify / maybe optimize
We can precompute the exact information we need for topo sorting and
store it in `PerhapsNeedToRegister`. Depending on how `topoSort` works,
this is easy a performance improvement or just completely harmless.

Co-Authored-By: Bernardo Meurer Costa <beme@anthropic.com>
2025-11-28 21:38:59 -05:00
John Ericson
686ad9b052 perf(libstore/derivation-builder): pre-compute outputGraph for linear complexity
Build the inverse of `scratchOuputs` before running topoSort, avoiding
quadratic complexity when determining which outputs reference each
other. This fixes the FIXME comment about building the inverted map up
front.

Inspired by Lix commit 10c04ce84 / Change Id
Ibdd46e7b2e895bfeeebc173046d1297b41998181, but ended up being completely
different code.

Co-Authored-By: Maximilian Bosch <maximilian@mbosch.me>
Co-Authored-By: Bernardo Meurer Costa <beme@anthropic.com>
2025-11-28 21:38:59 -05:00
John Ericson
13b4512cbe topoSort: Optimize templating
- No `std::function` overhead

- Don't copy if not necessary

Co-authored-by: Sergei Zimmerman <sergei@zimmerman.foo>
2025-11-28 21:38:54 -05:00
Sergei Zimmerman
0903b0aa7d Merge pull request #14671 from NixOS/fix-asan-stack-overload-repl-doc
tests/functional: Work around stack overflows under ASAN in doc-funct…
2025-11-29 00:56:10 +00:00
Sergei Zimmerman
a2acb6d7aa tests/functional: Work around stack overflows under ASAN in doc-functor tests
This was failing under ASAN in https://hydra.nixos.org/build/315173638/nixlog/1.
ASAN uses a bit more stack space and the default max call depth is not enough.
Not sure what's so special about this particular test.
2025-11-29 01:10:26 +03:00
John Ericson
048a58d331 Merge pull request #14668 from NixOS/fix-i686-expr-tests
libexpr: Fix tests on 32 bit systems
2025-11-28 02:33:29 +00:00
Sergei Zimmerman
7dfad3dba7 libexpr: Fix tests on 32 bit systems
This test is now pointless and the comment is outdated. Also the test fails
on 32 bit systems with:

../nix_api_value_internal.cc:22: Failure
Expected equality of these values:
  sizeof(nix::Value)
    Which is: 12
  sizeof(nix_value)
    Which is: 8

It just happeneded to work because Value is 16 bytes and nix_value was also 16 bytes.

Also get rid of a pointless inline in new_nix_value, since it's already static and
inline there does nothing.
2025-11-28 00:35:56 +03:00
Sergei Zimmerman
140c5f69f0 flake: Bump nixpkgs
Updates nixpkgs flake input. Also switches the input type to the channel
tarballs, since infra now supports the lockable tarball protocol.
2025-11-27 23:43:41 +03:00
John Ericson
11b0fcd6cd Merge pull request #14667 from Mic92/fix-remote-builder-hang
daemon: fix hang on SSH disconnect during remote builds
2025-11-27 14:47:21 +00:00
Jörg Thalheim
98c7ca2c9f daemon: fix hang on SSH disconnect during remote builds
When an SSH connection dies during a remote build, MonitorFdHup correctly
detects the disconnect and calls triggerInterrupt(). However, without
ReceiveInterrupts instantiated, no SIGUSR1 is sent to interrupt the
blocking read() syscall. This causes the daemon to hang indefinitely
while holding file locks, blocking subsequent builds.

The fix instantiates ReceiveInterrupts in processConnection(), which
registers a callback to send SIGUSR1 to the current thread when
triggerInterrupt() is called. This allows the blocking read() to return
with EINTR, causing checkInterrupt() to throw and the daemon to exit
cleanly.

This pattern is already used in ThreadPool::doWork() and
SubstitutionGoal for the same purpose.
2025-11-27 13:56:37 +01:00
John Ericson
a3d77a4bf2 Merge pull request #14664 from NixOS/fix-i686-asan
libstore: Align LocalFSStore to 8 bytes even on i686-linux
2025-11-27 04:26:08 +00:00
John Ericson
ad07be0a55 Merge pull request #14665 from vinayakankugoyal/path
Use std::filesystem::path in libmain.
2025-11-27 03:01:56 +00:00
Ubuntu
16f218b37c Use std::filesystem::path in libmain. 2025-11-27 01:36:52 +00:00
John Ericson
35492fe94a Merge pull request #14632 from NixOS/path-setting
Add `Setting<std::filesystem::path>` and `Setting<std::optional<std::filesystem::path>>` specializations
2025-11-27 00:29:28 +00:00
Sergei Zimmerman
7c76a812fe libstore: Align LocalFSStore to 8 bytes even on i686-linux
This works around https://hydra.nixos.org/build/314579538/nixlog/1.
2025-11-27 03:08:11 +03:00
John Ericson
d3aa04561f Merge pull request #14659 from vinayakankugoyal/path
Use std::filesystem::path in libflake.
2025-11-27 00:07:58 +00:00
John Ericson
80c545bcdc Fix include errors masked by precompiled headers 2025-11-26 18:43:32 -05:00
John Ericson
1e36f203e6 Fix issues with std::filesystem::path settings 2025-11-26 18:18:50 -05:00
Robert Hensing
38bb7f532c Document and test -- separator behavior with installables
Clarifies that the first positional argument is always treated as the
installable, even after --. Adds tests to prevent accidental change.

Addresses https://github.com/NixOS/nix/issues/13994
2025-11-27 00:13:27 +01:00
John Ericson
37cf990b41 Merge branch 'master' into path-setting 2025-11-26 17:57:45 -05:00
Ubuntu
3e8c220b60 Use std::filesystem::path in libflake. 2025-11-27 01:39:37 +03:00
Eelco Dolstra
aa0265f77e Merge pull request #14656 from NixOS/cleanup-github-attrs
Move GitHub input attribute validation into inputFromAttrs()
2025-11-26 19:16:24 +00:00
Eelco Dolstra
e7f95783db Move GitHub input attribute validation into inputFromAttrs()
Previously inputFromAttrs() didn't do any validation. inputFromURL()
now calls inputFromAttrs(), so we only need to validate in one place.

Fixes #14655.
2025-11-26 19:38:42 +01:00
John Ericson
3c2d5a1bdc Merge pull request #14652 from vinayakankugoyal/path
Replace Path with std::filesystem::path in libfetchers.
2025-11-26 17:07:43 +00:00
Ubuntu
f0390758dd Replace Path with std::filesystem::path in libfetchers. 2025-11-26 11:23:41 -05:00
Ubuntu
e761a9fb6d Use std::filesystem::path instead of Path in libexpr. 2025-11-26 11:18:38 -05:00
Eelco Dolstra
2e262c6685 Merge pull request #14643 from NixOS/binary-cache-nar-from-path
BinaryCacheStore::narFromPath(): Fix unreachable code
2025-11-26 09:53:23 +00:00
John Ericson
15b222b6d6 Merge pull request #14650 from xokdvium/double-quotes-lockfiles
libstore: Fix double quotes in debug logs for pathlocks
2025-11-26 02:53:39 +00:00
John Ericson
c38349583f Merge pull request #14651 from NixOS/restore-sink-more-openat2
libutil: Use openFileEnsureBeneathNoSymlinks in RestoreSink::createRe…
2025-11-26 01:45:50 +00:00
John Ericson
31ce0c8169 Merge pull request #14649 from vinayakankugoyal/path
Use std::filesystem::path instead of Path in libexpr.
2025-11-26 01:23:16 +00:00
Sergei Zimmerman
0778b861a9 libutil: Use openFileEnsureBeneathNoSymlinks in RestoreSink::createRegularFile
Add more assertions for preconditions of openFileEnsureBeneathNoSymlinks to prevent
misuse. Also start using it for regular file creation as well.
2025-11-26 03:49:33 +03:00
Sergei Zimmerman
3716bd9a62 libstore: Fix double quotes in debug logs for pathlocks
This is now using std::filesystem which gets double-quoted.
2025-11-26 03:31:32 +03:00
Ubuntu
697b068756 Use std::filesystem::path instead of Path in libexpr. 2025-11-26 00:22:26 +00:00
John Ericson
6cc44e4fdf Merge pull request #14647 from NixOS/fix-progress-bar
libmain: Fix download progress rendering
2025-11-25 22:52:04 +00:00
Taeer Bar-Yam
952be9fc96 Merge pull request #14644 from Radvendii/fix-14642
parser.y: properly abstract over to-be-created strings
2025-11-25 22:39:38 +00:00
Sergei Zimmerman
4031343e44 libmain: Fix download progress rendering
This was broken in https://github.com/NixOS/nix/pull/14423 accidentally.
Add [[nodiscard]] to prevent such mistakes in the future.
2025-11-26 01:22:47 +03:00
Taeer Bar-Yam
0c0a41a81a tests: add tests for dynamic attribute in let and inherit
Regression tests for the previous commit.

Co-authored-by: Sergei Zimmerman <sergei@zimmerman.foo>
Co-authored-by: piegames <git@piegames.de>
2025-11-26 00:10:40 +03:00
Taeer Bar-Yam
97abcda9cc parser.y: correctly abstract over to-be-constructed ExprString
Fixes the regression from eab467ecfb with
dynamic attributes that a simple string expressions.

Co-authored-by: Sergei Zimmerman <sergei@zimmerman.foo>
2025-11-25 23:33:58 +03:00
John Ericson
423e732b22 Merge pull request #14641 from obsidiansystems/simplify-nix-develop
Simplify `nix develop` "gathering derivation environment"
2025-11-25 19:08:12 +00:00
John Ericson
05990fb2ec Merge pull request #14555 from NixOS/more-store-ffi
libstore-c: Add new derivation and store path functions
2025-11-25 18:51:56 +00:00
John Ericson
6a4a1e9f72 Skip new part of functional test on NixOS
It's very weird it doesn't work here, but I don't mind not debugging
this now as I just added this part of the functional test --- it's
already better than it was before.
2025-11-25 13:35:03 -05:00
John Ericson
1c10ce6047 libstore-c: Add new derivation and store path functions
Add several new functions to the C API:

StorePath operations:
- nix_store_path_hash: Extract the hash part from a store path
- nix_store_create_from_parts: Construct a store path from hash and name

Derivation operations:
- nix_derivation_clone: Clone a derivation
- nix_derivation_to_json: Serialize a derivation to JSON

Store operations:
- nix_store_drv_from_store_path: Load a derivation from a store path

Test the new functions, and improve documentation of some existing
functions to better distinguish them, also.

Co-authored-by: Tristan Ross <tristan.ross@determinate.systems>
Co-authored-by: Robert Hensing <roberth@users.noreply.github.com>
2025-11-25 13:18:10 -05:00
John Ericson
6f33f64ce5 C API: Need to try-catch around new
Per https://en.cppreference.com/w/cpp/memory/new/operator_new.html, it
can throw if the allocation fails.
2025-11-25 13:00:13 -05:00
John Ericson
801cb16131 Simplify nix develop "gathering derivation environment"
Before, had some funny logic with an unnecessary is CA enabled branch,
and erroneous use of the comma operator. Now, take advantage of the new
`Derivation::fillInOutputPaths` to fill in input addresses (and output
path env vars) in a much-more lightweight manner.

Also, fix `nix develop` on fixed-output derivations so that weird things
don't happen when we have that experimental feature enabled.

As a slight behavior change, if the original derivation was
content-addressing this one will be too, but I really don't think that
matters --- if anything, it is a slight improvement for users that have
already opted into content-addressing anyways.
2025-11-25 11:29:42 -05:00
John Ericson
e91b7d1732 Test nix develop on fixed-output derivations
It half works today, we should fix this but also not regress it!
2025-11-25 11:27:20 -05:00
John Ericson
ab58d2720c Make nix-shell.sh functional test debuggable
Without this change, when one runs wit with `meson test --interactive`,
that command will block waiting on standard input to be closed.
2025-11-25 11:11:55 -05:00
Eelco Dolstra
7ba84437be BinaryCacheStore::narFromPath(): Fix unreachable code
When this function is called as a coroutine (e.g. when it's called by
`copyStorePath()`), the code after `decompressor->finish()` is never
reached because the coroutine is destroyed when the caller reaches the
end of the NAR. So put that code in a `LambdaSink` destructor.
2025-11-25 14:23:36 +01:00
Eelco Dolstra
d7b6afecdb LambdaSink: Allow passing a destructor callback 2025-11-25 14:16:00 +01:00
Eelco Dolstra
c72f3dc27e Merge pull request #14638 from NixOS/dependabot/github_actions/actions/checkout-6
build(deps): bump actions/checkout from 5 to 6
2025-11-25 13:12:18 +00:00
John Ericson
d1470f76c7 Merge pull request #14640 from vinayakankugoyal/path
Use std::filesystem::path instead of Path in libcmd
2025-11-25 05:37:16 +00:00
John Ericson
84079e10cf No more Path in libnixcmd
Co-authored-by: Vinayak Goyal <vinayakankugoyal@gmail.com>
2025-11-25 05:00:09 +00:00
John Ericson
88c9c6d89d Merge pull request #14636 from NixOS/openat2-wrapper
libutil/file-descriptor: Add safer utilities for opening files relati…
2025-11-24 23:23:51 +00:00
John Ericson
4f4da90513 Merge pull request #13942 from NixOS/json-no-store-dir
JSON impl and Schema for `DummyStore`
2025-11-24 23:06:13 +00:00
Jörg Thalheim
3e9104c9ca Merge pull request #14637 from lovesegfault/aws-crt-cpp-log-level
feat(libstore): tie AWS CRT logging to Nix verbosity level
2025-11-24 22:45:45 +00:00
Sergei Zimmerman
3a9be9fd2f libutil: Use openFileEnsureBeneathNoSymlinks in RestoreSink::createDirectory
Starts using the new function.
2025-11-25 01:10:35 +03:00
John Ericson
0275b64b81 JSON impl and Schema for DummyStore
This is the "keystone" that puts most of the other store-layer JSON
formats together.

Also, add some documentation for JSON testing.
2025-11-24 17:04:24 -05:00
John Ericson
622a5cd1bf Add DummyStore::operator==
Will need it for tests.
2025-11-24 17:04:24 -05:00
John Ericson
b0c016ae7d DummyStore build trace holds UnkeyedRealisation by value
Otherwise the equality instance we need to add will be messed up.
2025-11-24 17:04:24 -05:00
John Ericson
f78e88c973 Add some infrastructure changes for better JSON ref<T> impls
Also skip a trailing semicolon inside a macro so the caller can use it
instead, which is generally nicer to the formatter.
2025-11-24 17:04:23 -05:00
dependabot[bot]
d8d75cff9f build(deps): bump actions/checkout from 5 to 6
Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-24 22:03:58 +00:00
John Ericson
f198e9a0b3 Document the JSON Schema testing a bit 2025-11-24 17:03:42 -05:00
Jörg Thalheim
439af1dca1 feat(libstore): tie AWS CRT logging to Nix verbosity level
Map Nix's verbosity levels to AWS CRT log levels so users can
debug SSO authentication issues without modifying code:

- Default/warn: AWS Warn (errors/warnings only)
- Chatty (-vvv): AWS Info (credential provider actions)
- Debug (-vvvv): AWS Debug (detailed auth flow)
- Vomit (-vvvvv): AWS Trace (full CRT internal tracing)

This makes it easy to diagnose SSO issues with:
  nix copy -vvvv --to s3://bucket?profile=foo ...
2025-11-24 17:02:19 -05:00
Sergei Zimmerman
77990e7cca libutil/file-descriptor: Add safer utilities for opening files relative to dirFd
Implements a safe no symlink following primitive operation for opening file descriptors.
This is unix-only for the time being, since windows doesn't really suffer from symlink
races, since they are admin-only.

Tested with enosys --syscall openat2 as well.
2025-11-25 00:42:57 +03:00
John Ericson
3bac0d7aa2 Merge pull request #14635 from Radvendii/alloc-exprlet-exprattrs
libexpr: move the ExprLet::attrs allocations into the arena
2025-11-24 21:14:52 +00:00
John Ericson
36419a6ccb Merge pull request #14507 from obsidiansystems/derivation-options-json-schema
JSON Schema for `DerivationOptions`
2025-11-24 21:11:07 +00:00
John Ericson
3ba51bf61b Merge pull request #14560 from obsidiansystems/fill-in-outputs
Dedup some derivation initialization logic, and test
2025-11-24 21:10:38 +00:00
John Ericson
209f413e80 JSON Schema for DerivationOutputs
Progress on #13570
2025-11-24 15:23:50 -05:00
John Ericson
b8d32388bc Move derivation JSON doc to index.md in dir
This prepares for more structure.
2025-11-24 15:23:50 -05:00
John Ericson
eb53e61e08 Fix stray derivation "v3" in manual
It's commented out, but we should still update it to "v4" to match the
link target.
2025-11-24 15:23:50 -05:00
Taeer Bar-Yam
60f09928d1 libexpr: move ExprLet::attrs data to arena as well
I missed this because I assumed all Exprs were recursed into by
bindVars, but ExprLet's ExprAttrs field is not really its own AST node,
so it doesn't get recursed into.
2025-11-24 21:14:13 +01:00
Taeer Bar-Yam
43a183120a libexpr: factor out functions for moving data to a new allocator 2025-11-24 21:14:13 +01:00
John Ericson
0c786f3a3c Merge pull request #14617 from vinayakankugoyal/path
Update profiles to use `std::filesystem::path`
2025-11-24 19:31:25 +00:00
John Ericson
504c5e7cf9 Convert profiles to use std::filesystem::path
Co-authored-by: Vinayak Goyal <vinayakankugoyal@gmail.com>
Co-authored-by: Eelco Dolstra <edolstra@gmail.com>
2025-11-24 13:38:01 -05:00
John Ericson
5d066386b5 Merge pull request #14260 from roberth/ulimit
Clarify setStackSize error message and warn if not possible
2025-11-24 17:12:31 +00:00
John Ericson
c7b61f3d13 Merge pull request #14631 from obsidiansystems/use-serialisation-abstraction
Use `WorkerProto::Serialise` abstraction for `DrvOutput`
2025-11-24 16:33:18 +00:00
Eelco Dolstra
93c51acfb5 Add Setting<std::filesystem::path> specialization
Like PathSetting, this normalizes the path (without resolving
symlinks).
2025-11-24 17:04:04 +01:00
John Ericson
d689b764f3 Use WorkerProto::Serialise abstraction for DrvOutput
It's better to consistently use the abstraction, rather than code which
happens to do the same thing.

See also d782c5e586 for the same sort of
change.
2025-11-24 10:44:45 -05:00
John Ericson
487c6b6c46 Merge pull request #14630 from NixOS/prefetch-fixes
nix/prefetch: Be honest about when path name is derived from URL
2025-11-23 22:24:17 +00:00
Sergei Zimmerman
28fac9fe4d nix/prefetch: Be honest about when path name is derived from URL
Only add the message to trace when name is really derived from URL.
2025-11-24 00:25:48 +03:00
Sergei Zimmerman
2594e417b5 Merge pull request #14627 from jonhermansen/libstore-curl-version-maximum
libstore: fix curl version check to allow 8.17.0
2025-11-23 09:57:09 +00:00
Jon Hermansen
76ed967f79 libstore: fix curl version check to allow 8.17.0
The single-string syntax '>=8.16.0 <8.17.0' only applied the lower
bound, causing curl 8.17.0 to be incorrectly rejected. Split into two
separate version_compare() calls for compatibility with Meson 1.1,
since multi-argument syntax requires Meson 1.8+.
2025-11-23 12:13:05 +03:00
John Ericson
327e8babf7 Merge pull request #14584 from Radvendii/allocbytes-stringdata
libexpr: use allocBytes() to allocate StringData
2025-11-23 00:38:50 +00:00
John Ericson
d5d4bafc2a Merge pull request #14620 from NixOS/revert-shared-tarball-cache
libfetchers: Don't have a single shared tarball cache
2025-11-23 00:33:51 +00:00
John Ericson
bd11043c67 Merge pull request #14623 from Radvendii/exprcall-alloc-shvach
libexpr: plug ExprCall memory leak
2025-11-23 00:08:10 +00:00
Taeer Bar-Yam
dbfe6318b3 libexpr: move ExprCall storage to the arena 2025-11-23 00:06:10 +01:00
Taeer Bar-Yam
484f40fc64 libexpr: make ExprCall::args an std::optional 2025-11-23 00:06:10 +01:00
Taeer Bar-Yam
43fc6c314d libexpr: ExprCall use std::pmr::vector 2025-11-23 00:06:10 +01:00
Sergei Zimmerman
2bbec7d573 Merge pull request #14622 from roberth/meson-commandlet-deps
src/nix: Make meson compile <cmdlet> valid
2025-11-22 19:55:02 +00:00
Sergei Zimmerman
385d7e77bd libfetchers: Don't have a single shared tarball cache
This partially reverts commit bc6b9ce.

This transformation is unsound and thread unsafe. Internal libgit2
structures must *never* be shared between threads. This causes
internal odb corruption with e.g.:

nix flake prefetch-inputs:

error:
       … while fetching the input 'github:nixos/nixpkgs/89c2b2330e733d6cdb5eae7b899326930c2c0648?narHash=sha256-Stk9ZYRkGrnnpyJ4eqt9eQtdFWRRIvMxpNRf4sIegnw%3D'

       error: adding a file to a tree builder: failed to insert entry: invalid object specified - upload-image.sh
error:
       … while fetching the input 'github:NixOS/nixpkgs/a8d610af3f1a5fb71e23e08434d8d61a466fc942?narHash=sha256-v5afmLjn/uyD9EQuPBn7nZuaZVV9r%2BJerayK/4wvdWA%3D'

       error: adding a file to a tree builder: failed to insert entry: invalid object specified - outline.nix
double free or corruption (!prev)

Thread 21 "nix" received signal SIGABRT, Aborted.
2025-11-22 22:48:40 +03:00
Robert Hensing
67f6a24171 src/nix: Make meson compile <cmdlet> valid
Without this dependency, e.g. `meson compile nix-instantiate`
would produce a broken symlink, or the `nix` it points to may be
stale.
With the dependency in place, `meson compile nix-instantiate`
produces a reliable outcome.
2025-11-22 20:19:34 +01:00
Sergei Zimmerman
8cdeab8f2e Merge pull request #14613 from roberth/deepSeq-stack-overflow
`deepSeq`, json: handle stack overflow, report list index
2025-11-22 17:49:32 +00:00
Sergei Zimmerman
ed176cb42e Merge pull request #14618 from jonhermansen/freebsd-path-null-terminator
fix(FreeBSD): remove null terminator from executable path
2025-11-22 11:51:01 +00:00
Jon Hermansen
3ff8d0ece4 fix(FreeBSD): remove null terminator from executable path
On FreeBSD, sysctl(KERN_PROC_PATHNAME) returns a null-terminated
string with pathLen including the terminator. This causes Nix to
fail during manual generation with:

  error:
         … while calling the 'concatStringsSep' builtin
           at /nix/var/nix/builds/nix-63232-402489527/source/doc/manual/generate-settings.nix:99:1:
             98| in
             99| concatStrings (attrValues (mapAttrs (showSetting prefix) settingsInfo))
               | ^
            100|

         error: input string '/nix/store/gq89cj02b5zs67cbd85vzg5cgsgnd8mj-nix-2.31.2/bin/nix␀'
                cannot be represented as Nix string because it contains null bytes

The issue occurs because generate-settings.nix reads the nix binary
path from JSON and evaluates it as a Nix string, which cannot contain
null bytes. Normal C++ string operations don't trigger this since they
handle null-terminated strings correctly.

Strip the null terminator on FreeBSD to match other platforms (Linux
uses /proc/self/exe, macOS uses _NSGetExecutablePath).

Credit: @wahjava (FreeBSD ports and Nixpkgs contributor)
2025-11-22 03:59:29 -05:00
John Ericson
c9fe290b30 Merge pull request #14616 from vinayakankugoyal/patch-1
Clarify build options in debugging documentation
2025-11-22 06:28:56 +00:00
Vinayak Goyal
48c800f7ef Clarify build options in debugging documentation
Updated documentation to clarify that building without optimization can lead to faster builds.
2025-11-22 01:00:35 -05:00
John Ericson
79dcc094b0 Merge pull request #14614 from NixOS/libcurl-pause
libstore/filetransfer: Pause transfers instead of stalling the download thread
2025-11-22 05:41:18 +00:00
Sergei Zimmerman
be28ad92fd rl-next: Add docs for libcurl pausing 2025-11-22 04:25:59 +03:00
Sergei Zimmerman
a2d6a69d45 libstore: Reduce the default download-buffer-size down to 1 MiB
Since the root cause (the lack of backpressure control) has
been fixed in the previous commit we can revert the change from
8ffea0a018 and make the default size much
smaller.
2025-11-22 04:23:25 +03:00
Sergei Zimmerman
4307420c44 libstore/filetransfer: Pause transfers instead of stalling the download thread
Instead of naively stalling the download thread we can instead stop the transfer.
This allows the other multiplexed connections to continue downloading (and unpacking),
if the result of the download gets piped into a GitFileSystemObjectSink.

Prior art in lix project:

- 4ae6fb5a8f
- 12156d3beb

This patch is very different from the lix one, since we are using a decompression sink
in the middle of the pipeline but the co-authored-by is there since I was motivated to
implement this by looking at the lix side of things.

Co-authored-by: eldritch horrors <pennae@lix.systems>
2025-11-22 04:23:24 +03:00
Sergei Zimmerman
ec0b270c6c libstore/filetransfer: Return an opaque handle from enqueueFileTransfer
This is necessary to make pausing/unpausing possible in a follow-up commit.
2025-11-22 03:33:13 +03:00
Sergei Zimmerman
3f8474a62f libstore/filetransfer: Use ref instead of std::shared_ptr
Those can never be nullptr, so we should use the type system
to ensure this invariant.
2025-11-22 03:33:12 +03:00
Robert Hensing
c7e1c612eb libexpr: fix stack overflow in toJSON on deeply nested structures
Similar to the deepSeq fix, toJSON on deeply nested structures caused
an uncontrolled OS-level stack overflow.

Fix by adding call depth tracking to printValueAsJSON.
2025-11-22 00:17:26 +01:00
Robert Hensing
a812b6c6e6 libexpr: add list index to deepSeq error traces
When deepSeq encounters an error while evaluating a list element, the
error trace now includes the list index, making it easier to locate
the problematic element.
2025-11-21 23:51:07 +01:00
Robert Hensing
59a566db13 libexpr: fix stack overflow in deepSeq on deeply nested structures
builtins.deepSeq on deeply nested structures (e.g., a linked list with
100,000 elements) caused an uncontrolled OS-level stack overflow with
no Nix stack trace.

Fix by adding call depth tracking to forceValueDeep, integrating with
Nix's existing max-call-depth mechanism. Now produces a controlled
"stack overflow; max-call-depth exceeded" error with a proper stack
trace.

Closes: https://github.com/NixOS/nix/issues/7816
2025-11-21 23:50:47 +01:00
John Ericson
eb654acdd1 Merge pull request #14610 from NixOS/git-accessor-options
Introduce GitAccessorOptions
2025-11-21 22:13:52 +00:00
Taeer Bar-Yam
7cd3252946 libexpr: use allocBytes() to allocate StringData 2025-11-21 21:26:23 +01:00
Taeer Bar-Yam
9b9446e860 c api: shovel EvalMemory * into nix_value
this is a painful change. we should really add EvalState or EvalMemory
as an argument to various functions as we need it, but because we want
to preserve the stablity API, we hack it in as a field of nix_value.
2025-11-21 21:26:23 +01:00
Eelco Dolstra
6c4d2a7d11 Introduce GitAccessorOptions 2025-11-21 20:29:47 +01:00
John Ericson
152e7e48c1 Merge pull request #14607 from NixOS/open-directory-cloexec
libutil/unix: Add O_CLOEXEC to openDirectory
2025-11-21 01:23:57 +00:00
Sergei Zimmerman
ea4854fda1 libutil/unix: Add O_CLOEXEC to openDirectory
As a precaution. This function might get used for some long persisted
file descriptor and we need good defaults.
2025-11-21 02:43:26 +03:00
John Ericson
d3ff01cb2e Merge pull request #14606 from NixOS/fix-copy-recursive
libutil: Fix copyRecursive and use for nix flake clone
2025-11-20 22:28:45 +00:00
John Ericson
a835d6ad2a Merge pull request #14319 from obsidiansystems/json-schema-fso
`nlohmann::json` instance and JSON Schema for `MemorySourceAccessor`
2025-11-20 21:52:57 +00:00
John Ericson
ec3c93f17f Merge pull request #14603 from NixOS/safe-cast
Turn one unsafe C cast into a safe `static_cast`
2025-11-20 21:26:00 +00:00
Sergei Zimmerman
6d0f4fa666 libutil: Fix copyRecursive and use for nix flake clone
The use of sourceToSink is an unnecessary serialization bottleneck.
While we are at it, fix the copyRecursive implementation to actually copy
the whole directory. It wasn't used for anything prior, but now it has a use
and accompanying tests for flake clone.
2025-11-21 00:21:23 +03:00
John Ericson
b2ead92791 Turn one unsafe C cast into a safe static_cast 2025-11-20 15:58:31 -05:00
John Ericson
50407ab63e Merge pull request #14598 from NixOS/nar-listing-dedup
Deduplicate `listNar` and `MemorySourceAccessor::File`
2025-11-20 20:54:48 +00:00
John Ericson
7357a654de nlohmann::json instance and JSON Schema for MemorySourceAccessor
Also do a better JSON and testing for deep and shallow NAR listings.

As documented, this for file system objects themselves, since
`MemorySourceAccessor` is an implementation detail.
2025-11-20 15:19:24 -05:00
John Ericson
c4906741a1 Deduplicate listNar and MemorySourceAccessor::File
`listNar` did the not-so-pretty thing of going straight to JSON. Now it
uses `MemorySourceAccessor::File`, or rather variations of it, to go to
a C++ data type first, and only JSON second.

To accomplish this we add some type parameters to the `File` data type.
Actually, we need to do two rounds of this, because shallow NAR
listings. There is `FileT` and `DirectoryT` accordingly.
2025-11-20 14:57:47 -05:00
John Ericson
ac36d74b66 listNar should just take the source accessor by simple reference
A shared pointer is not needed.
2025-11-20 14:44:41 -05:00
John Ericson
d17bfe3866 Move nar-accessor.{cc,hh} to libutil
File-system-object-layer functionality doesn't depend on store-layer
concets, and therefore doesn't need to live inside there.
2025-11-20 14:44:41 -05:00
John Ericson
437b9b9879 Rename MemorySourceAccessor::File::Directory::{contents -> entries}
This matches the "NAR Listing" JSON format, and also helps distinguish
from regular file contents.

Why we want to match that will become clear in the next comments, when
we will in fact use (variations of) this data type for NAR listings.
2025-11-20 14:44:41 -05:00
John Ericson
620a6947ab Dedup some derivation initialization logic, and test
`nix derivation add`, and its C API counterpart, now works a bit closer
to `builtins.derivation` in that they don't require the user to fill-in
input addressed paths correctly ahead of time.

The logic for this is carefully deduplicated, between all 3 entry
points, and also between the existing `checkInvariants` function. There
are some more functional tests, and there are also many more unit tests.

Co-authored-by: Sergei Zimmerman <sergei@zimmerman.foo>
Co-authored-by: edef <edef@edef.eu>
2025-11-20 00:49:48 -05:00
John Ericson
294acfd807 Create infrastructure for "checkpoint" characterization tests
These do a read/write test in the middles of some computation. They are
an imperative way to test intermediate values rather than functionally
testing end outputs.
2025-11-20 00:49:48 -05:00
Robert Hensing
261f674a25 tests: Suppress environment-dependent warnings
... via _NIX_TEST_NO_ENVIRONMENT_WARNINGS

This environment variable suppresses warnings that depend on the test
environment (such as ulimit warnings in builds on systems with lower
limits, which may well succeed if it weren't for the warning).

This prevents non-deterministic test failures in golden/characterization
tests.

Alternative considered: filtering stderr in test scripts, but that approach
is fragile with binary test output, and potentially multiple call sites.
2025-11-05 00:28:01 +01:00
Robert Hensing
08e218eb0b Reduce the stack size to a bit under 64 MiB 2025-11-04 23:38:50 +01:00
Robert Hensing
2349c3dbde setStackSize: Warn when the desired stack size can't be set 2025-11-04 23:38:50 +01:00
Robert Hensing
f6aeca0522 Clarify setStackSize error message
Show the actual attempted stack size value (capped at hard limit)
separately from the desired value, making it clearer what's happening
when the hard limit is lower than requested.
2025-11-04 23:38:50 +01:00
440 changed files with 9812 additions and 3413 deletions

View File

@@ -24,8 +24,8 @@ inputs:
description: "Github token"
required: true
use_cache:
description: "Whether to setup magic-nix-cache"
default: true
description: "Whether to setup github actions cache (not implemented currently)"
default: false
required: false
runs:
using: "composite"
@@ -122,10 +122,3 @@ runs:
source-url: ${{ inputs.experimental-installer-version != 'latest' && 'https://artifacts.nixos.org/experimental-installer/tag/${{ inputs.experimental-installer-version }}/${{ env.EXPERIMENTAL_INSTALLER_ARTIFACT }}' || '' }}
nix-package-url: ${{ inputs.dogfood == 'true' && steps.download-nix-installer.outputs.tarball-path || (inputs.tarball_url || '') }}
extra-conf: ${{ inputs.extra_nix_config }}
- uses: DeterminateSystems/magic-nix-cache-action@565684385bcd71bad329742eefe8d12f2e765b39 # v13
if: ${{ inputs.use_cache == 'true' }}
with:
diagnostic-endpoint: ''
use-flakehub: false
use-gha-cache: true
source-revision: 92d9581367be2233c2d5714a2640e1339f4087d8 # main

View File

@@ -20,13 +20,13 @@ jobs:
with:
app-id: ${{ vars.CI_APP_ID }}
private-key: ${{ secrets.CI_APP_PRIVATE_KEY }}
- uses: actions/checkout@v5
- uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha }}
# required to find all branches
fetch-depth: 0
- name: Create backport PRs
uses: korthout/backport-action@d07416681cab29bf2661702f925f020aaa962997 # v3.4.1
uses: korthout/backport-action@c656f5d5851037b2b38fb5db2691a03fa229e3b2 # v4.0.1
id: backport
with:
# Config README: https://github.com/korthout/backport-action#backport-action

View File

@@ -24,7 +24,7 @@ jobs:
eval:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: ./.github/actions/install-nix-action
@@ -40,7 +40,7 @@ jobs:
name: pre-commit checks
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- uses: ./.github/actions/install-nix-action
with:
dogfood: ${{ github.event_name == 'workflow_dispatch' && inputs.dogfood || github.event_name != 'workflow_dispatch' }}
@@ -87,7 +87,7 @@ jobs:
runs-on: ${{ matrix.runs-on }}
timeout-minutes: 60
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: ./.github/actions/install-nix-action
@@ -162,9 +162,9 @@ jobs:
name: installer test ${{ matrix.scenario }}
runs-on: ${{ matrix.runs-on }}
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- name: Download installer tarball
uses: actions/download-artifact@v6
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: installer-${{matrix.os}}
path: out
@@ -197,103 +197,52 @@ jobs:
- run: exec bash -c "nix-channel --add https://releases.nixos.org/nixos/unstable/nixos-23.05pre466020.60c1d71f2ba nixpkgs"
- run: exec bash -c "nix-channel --update && nix-env -iA nixpkgs.hello && hello"
# Steps to test CI automation in your own fork.
# 1. Sign-up for https://hub.docker.com/
# 2. Store your dockerhub username as DOCKERHUB_USERNAME in "Repository secrets" of your fork repository settings (https://github.com/$githubuser/nix/settings/secrets/actions)
# 3. Create an access token in https://hub.docker.com/settings/security and store it as DOCKERHUB_TOKEN in "Repository secrets" of your fork
check_secrets:
permissions:
contents: none
name: Check presence of secrets
runs-on: ubuntu-24.04
outputs:
docker: ${{ steps.secret.outputs.docker }}
steps:
- name: Check for DockerHub secrets
id: secret
env:
_DOCKER_SECRETS: ${{ secrets.DOCKERHUB_USERNAME }}${{ secrets.DOCKERHUB_TOKEN }}
run: |
echo "docker=${{ env._DOCKER_SECRETS != '' }}" >> $GITHUB_OUTPUT
docker_push_image:
needs: [tests, check_secrets]
name: Push docker image to DockerHub and GHCR
needs: [flake_regressions, installer_test]
if: github.event_name == 'push' && github.ref_name == 'master'
uses: ./.github/workflows/docker-push.yml
with:
ref: ${{ github.sha }}
is_master: true
permissions:
contents: read
packages: write
if: >-
needs.check_secrets.outputs.docker == 'true' &&
github.event_name == 'push' &&
github.ref_name == 'master'
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0
- uses: ./.github/actions/install-nix-action
with:
dogfood: false
extra_nix_config: |
experimental-features = flakes nix-command
- run: echo NIX_VERSION="$(nix eval .\#nix.version | tr -d \")" >> $GITHUB_ENV
- run: nix build .#dockerImage -L
- run: docker load -i ./result/image.tar.gz
- run: docker tag nix:$NIX_VERSION ${{ secrets.DOCKERHUB_USERNAME }}/nix:$NIX_VERSION
- run: docker tag nix:$NIX_VERSION ${{ secrets.DOCKERHUB_USERNAME }}/nix:master
# We'll deploy the newly built image to both Docker Hub and Github Container Registry.
#
# Push to Docker Hub first
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- run: docker push ${{ secrets.DOCKERHUB_USERNAME }}/nix:$NIX_VERSION
- run: docker push ${{ secrets.DOCKERHUB_USERNAME }}/nix:master
# Push to GitHub Container Registry as well
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Push image
run: |
IMAGE_ID=ghcr.io/${{ github.repository_owner }}/nix
# Change all uppercase to lowercase
IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')
docker tag nix:$NIX_VERSION $IMAGE_ID:$NIX_VERSION
docker tag nix:$NIX_VERSION $IMAGE_ID:latest
docker push $IMAGE_ID:$NIX_VERSION
docker push $IMAGE_ID:latest
# deprecated 2024-02-24
docker tag nix:$NIX_VERSION $IMAGE_ID:master
docker push $IMAGE_ID:master
secrets:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
flake_regressions:
needs: tests
runs-on: ubuntu-24.04
steps:
- name: Checkout nix
uses: actions/checkout@v5
uses: actions/checkout@v6
- name: Checkout flake-regressions
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
repository: NixOS/flake-regressions
path: flake-regressions
- name: Checkout flake-regressions-data
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
repository: NixOS/flake-regressions-data
path: flake-regressions/tests
- uses: ./.github/actions/install-nix-action
- name: Download installer tarball
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
dogfood: ${{ github.event_name == 'workflow_dispatch' && inputs.dogfood || github.event_name != 'workflow_dispatch' }}
extra_nix_config:
experimental-features = nix-command flakes
github_token: ${{ secrets.GITHUB_TOKEN }}
- run: nix build -L --out-link ./new-nix && PATH=$(pwd)/new-nix/bin:$PATH MAX_FLAKES=25 flake-regressions/eval-all.sh
name: installer-linux
path: out
- name: Looking up the installer tarball URL
id: installer-tarball-url
run: |
echo "installer-url=file://$GITHUB_WORKSPACE/out" >> "$GITHUB_OUTPUT"
- uses: cachix/install-nix-action@4e002c8ec80594ecd40e759629461e26c8abed15 # v31.9.0
with:
install_url: ${{ format('{0}/install', steps.installer-tarball-url.outputs.installer-url) }}
install_options: ${{ format('--tarball-url-prefix {0}', steps.installer-tarball-url.outputs.installer-url) }}
- name: Run flake regressions tests
run: MAX_FLAKES=25 flake-regressions/eval-all.sh
profile_build:
needs: tests
@@ -303,7 +252,7 @@ jobs:
github.event_name == 'push' &&
github.ref_name == 'master'
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: ./.github/actions/install-nix-action

101
.github/workflows/docker-push.yml vendored Normal file
View File

@@ -0,0 +1,101 @@
name: "Push Docker Image"
on:
workflow_call:
inputs:
ref:
description: "Git ref to build the docker image from"
required: true
type: string
is_master:
description: "Whether run from master branch"
required: true
type: boolean
secrets:
DOCKERHUB_USERNAME:
required: true
DOCKERHUB_TOKEN:
required: true
permissions: {}
jobs:
# Steps to test CI automation in your own fork.
# 1. Sign-up for https://hub.docker.com/
# 2. Store your dockerhub username as DOCKERHUB_USERNAME in "Repository secrets" of your fork repository settings (https://github.com/$githubuser/nix/settings/secrets/actions)
# 3. Create an access token in https://hub.docker.com/settings/security and store it as DOCKERHUB_TOKEN in "Repository secrets" of your fork
check_secrets:
permissions:
contents: none
name: Check presence of secrets
runs-on: ubuntu-24.04
outputs:
docker: ${{ steps.secret.outputs.docker }}
steps:
- name: Check for DockerHub secrets
id: secret
env:
_DOCKER_SECRETS: ${{ secrets.DOCKERHUB_USERNAME }}${{ secrets.DOCKERHUB_TOKEN }}
run: |
echo "docker=${{ env._DOCKER_SECRETS != '' }}" >> $GITHUB_OUTPUT
push:
name: Push docker image to DockerHub and GHCR
needs: [check_secrets]
permissions:
contents: read
packages: write
if: needs.check_secrets.outputs.docker == 'true'
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-depth: 0
ref: ${{ inputs.ref }}
- uses: ./.github/actions/install-nix-action
with:
dogfood: false
extra_nix_config: |
experimental-features = flakes nix-command
- run: echo NIX_VERSION="$(nix eval .\#nix.version | tr -d \")" >> $GITHUB_ENV
- run: nix build .#dockerImage -L
- run: docker load -i ./result/image.tar.gz
# We'll deploy the newly built image to both Docker Hub and Github Container Registry.
#
# Push to Docker Hub first
- name: Login to Docker Hub
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Push to Docker Hub
env:
IS_MASTER: ${{ inputs.is_master }}
DOCKERHUB_REPO: ${{ secrets.DOCKERHUB_USERNAME }}/nix
run: |
docker tag nix:$NIX_VERSION $DOCKERHUB_REPO:$NIX_VERSION
docker push $DOCKERHUB_REPO:$NIX_VERSION
if [ "$IS_MASTER" = "true" ]; then
docker tag nix:$NIX_VERSION $DOCKERHUB_REPO:master
docker push $DOCKERHUB_REPO:master
fi
# Push to GitHub Container Registry as well
- name: Login to GitHub Container Registry
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Push to GHCR
env:
IS_MASTER: ${{ inputs.is_master }}
run: |
IMAGE_ID=ghcr.io/${{ github.repository_owner }}/nix
IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')
docker tag nix:$NIX_VERSION $IMAGE_ID:$NIX_VERSION
docker push $IMAGE_ID:$NIX_VERSION
if [ "$IS_MASTER" = "true" ]; then
docker tag nix:$NIX_VERSION $IMAGE_ID:master
docker push $IMAGE_ID:master
fi

69
.github/workflows/upload-release.yml vendored Normal file
View File

@@ -0,0 +1,69 @@
name: Upload Release
on:
workflow_dispatch:
inputs:
eval_id:
description: "Hydra evaluation ID"
required: true
type: number
is_latest:
description: "Mark as latest release"
required: false
type: boolean
default: false
permissions:
contents: read
id-token: write
packages: write
jobs:
release:
runs-on: ubuntu-24.04
environment: releases
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: ./.github/actions/install-nix-action
with:
dogfood: false # Use stable version
use_cache: false # Don't want any cache injection shenanigans
extra_nix_config: |
experimental-features = nix-command flakes
- name: Set NIX_PATH from flake input
run: |
NIXPKGS_PATH=$(nix build --inputs-from .# nixpkgs#path --print-out-paths --no-link)
# Shebangs with perl have issues. Pin nixpkgs this way. nix shell should maybe
# get the same uberhack that nix-shell has to support it.
echo "NIX_PATH=nixpkgs=$NIXPKGS_PATH" >> "$GITHUB_ENV"
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@61815dcd50bd041e203e49132bacad1fd04d2708 # v5.1.1
with:
role-to-assume: "arn:aws:iam::080433136561:role/nix-release"
role-session-name: nix-release-oidc-${{ github.run_id }}
aws-region: eu-west-1
- name: Login to Docker Hub
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GitHub Container Registry
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Upload release
run: |
./maintainers/upload-release.pl \
${{ inputs.eval_id }} \
--skip-git
env:
IS_LATEST: ${{ inputs.is_latest && '1' || '' }}
- name: Push to GHCR
run: |
DOCKER_OWNER="ghcr.io/$(echo '${{ github.repository_owner }}' | tr '[A-Z]' '[a-z]')/nix"
./maintainers/upload-release.pl \
${{ inputs.eval_id }} \
--skip-git \
--skip-s3 \
--docker-owner "$DOCKER_OWNER"
env:
IS_LATEST: ${{ inputs.is_latest && '1' || '' }}

View File

@@ -1 +1 @@
2.33.0
2.33.3

View File

@@ -94,6 +94,8 @@ The underlying source files are located in [`doc/manual/source`](./doc/manual/so
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://nix.dev/manual/nix/development/development/contributing.html).
You're encouraged to add line breaks at semantic boundaries, per [sembr](https://sembr.org).
## Getting help
Whenever you're stuck or do not know how to proceed, you can always ask for help.

View File

@@ -24,8 +24,15 @@ def map_contents_recursively(transformer):
def process_command:
.[0] as $context |
.[1] as $body |
$body + {
sections: $body.sections | map(map_contents_recursively(if $context.renderer == "html" then transform_anchors_html else transform_anchors_strip end)),
};
# mdbook 0.5.x uses 'items' instead of 'sections'
if $body.items then
$body + {
items: $body.items | map(map_contents_recursively(if $context.renderer == "html" then transform_anchors_html else transform_anchors_strip end)),
}
else
$body + {
sections: $body.sections | map(map_contents_recursively(if $context.renderer == "html" then transform_anchors_html else transform_anchors_strip end)),
}
end;
process_command

View File

@@ -24,12 +24,3 @@ renderers = ["html"]
command = "jq --from-file ./anchors.jq"
[output.markdown]
[output.linkcheck]
# no Internet during the build (in the sandbox)
follow-web-links = false
# mdbook-linkcheck does not understand [foo]{#bar} style links, resulting in
# excessive "Potential incomplete link" warnings. No other kind of warning was
# produced at the time of writing.
warning-policy = "ignore"

View File

@@ -0,0 +1,223 @@
#!/usr/bin/env python3
"""
Standalone markdown preprocessor for manpage generation.
Expands {{#include}} directives and handles @docroot@ references
without requiring mdbook.
"""
from pathlib import Path
import sys
import argparse
import re
def expand_includes(
content: str,
current_file: Path,
source_root: Path,
generated_root: Path | None,
visited: set[Path] | None = None,
) -> str:
"""
Recursively expand {{#include path}} directives.
Args:
content: Markdown content to process
current_file: Path to the current file (for resolving relative includes)
source_root: Root of the source directory
generated_root: Root of generated files (for @generated@/ includes)
visited: Set of already-visited files (for cycle detection)
"""
if visited is None:
visited = set()
# Track current file to detect cycles
visited.add(current_file.resolve())
lines = []
include_pattern = re.compile(r'^\s*\{\{#include\s+(.+?)\}\}\s*$')
for line in content.splitlines(keepends=True):
match = include_pattern.match(line)
if not match:
lines.append(line)
continue
# Found an include directive
include_path_str = match.group(1).strip()
# Resolve the include path
if include_path_str.startswith("@generated@/"):
# Generated file
if generated_root is None:
raise ValueError(
f"Cannot resolve @generated@ path '{include_path_str}' "
f"without --generated-root"
)
include_path = generated_root / include_path_str[12:]
else:
# Relative to current file
include_path = (current_file.parent / include_path_str).resolve()
# Check for cycles
if include_path.resolve() in visited:
raise RuntimeError(
f"Include cycle detected: {include_path} is already being processed"
)
# Check that file exists
if not include_path.exists():
raise FileNotFoundError(
f"Include file not found: {include_path_str}\n"
f" Resolved to: {include_path}\n"
f" From: {current_file}"
)
# Recursively expand the included file
included_content = include_path.read_text()
expanded = expand_includes(
included_content,
include_path,
source_root,
generated_root,
visited.copy(), # Copy visited set for this branch
)
lines.append(expanded)
# Add newline if the included content doesn't end with one
if not expanded.endswith('\n'):
lines.append('\n')
return ''.join(lines)
def resolve_docroot(content: str, current_file: Path, source_root: Path, docroot_url: str) -> str:
"""
Replace @docroot@ with nix.dev URL and convert .md to .html.
For manpages, absolute URLs are more useful than relative paths since
manpages are viewed standalone. lowdown will display these as proper
references in the manpage output.
"""
# Replace @docroot@ with the base URL
content = content.replace("@docroot@", docroot_url)
# Convert .md extensions to .html for web links
# Use lookahead to ensure that .md occurs before a fragment or a possible URL end.
content = re.sub(
r'(https://nix\.dev/[^)\s]*?)\.md(?=[#)\s]|$)',
r'\1.html',
content
)
return content
def resolve_at_escapes(content: str) -> str:
"""Replace @_at_ with @"""
return content.replace("@_at_", "@")
def process_file(
input_file: Path,
source_root: Path,
generated_root: Path | None,
docroot_url: str,
) -> str:
"""Process a single markdown file."""
content = input_file.read_text()
# Expand includes
content = expand_includes(content, input_file, source_root, generated_root)
# Resolve @docroot@ references
content = resolve_docroot(content, input_file, source_root, docroot_url)
# Resolve @_at_ escapes
content = resolve_at_escapes(content)
return content
def main():
parser = argparse.ArgumentParser(
description="Expand markdown includes for manpage generation",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
# Expand a manpage source file
%(prog)s \\
--source-root doc/manual/source \\
--generated-root build/doc/manual/source \\
doc/manual/source/command-ref/nix-store/query.md
# Pipe to lowdown for manpage generation
%(prog)s -s doc/manual/source -g build/doc/manual/source \\
doc/manual/source/command-ref/nix-env.md | \\
lowdown -sT man -M section=1 -o nix-env.1
""",
)
parser.add_argument(
"input_file",
type=Path,
help="Input markdown file to process",
)
parser.add_argument(
"-s", "--source-root",
type=Path,
required=True,
help="Root directory of markdown sources",
)
parser.add_argument(
"-g", "--generated-root",
type=Path,
help="Root directory of generated files (for @generated@/ includes)",
)
parser.add_argument(
"-o", "--output",
type=Path,
help="Output file (default: stdout)",
)
parser.add_argument(
"-u", "--doc-url",
type=str,
default="https://nix.dev/manual/nix/latest",
help="Base URL for documentation links (default: https://nix.dev/manual/nix/latest)",
)
args = parser.parse_args()
# Validate paths
if not args.input_file.exists():
print(f"Error: Input file not found: {args.input_file}", file=sys.stderr)
return 1
if not args.source_root.is_dir():
print(f"Error: Source root is not a directory: {args.source_root}", file=sys.stderr)
return 1
if args.generated_root and not args.generated_root.is_dir():
print(f"Error: Generated root is not a directory: {args.generated_root}", file=sys.stderr)
return 1
try:
# Process the file
output = process_file(args.input_file, args.source_root, args.generated_root, args.doc_url)
# Write output
if args.output:
args.output.write_text(output)
else:
print(output, end='')
return 0
except Exception as e:
print(f"Error processing {args.input_file}: {e}", file=sys.stderr)
import traceback
traceback.print_exc(file=sys.stderr)
return 1
if __name__ == "__main__":
sys.exit(main())

View File

@@ -0,0 +1,15 @@
#!/usr/bin/env python3
"""Generate redirects.js from template and JSON data."""
import sys
template_path, json_path, output_path = sys.argv[1:]
with open(json_path) as f:
json_content = f.read().rstrip()
with open(template_path) as f:
template = f.read()
with open(output_path, 'w') as f:
f.write(template.replace('@REDIRECTS_JSON@', json_content))

View File

@@ -5,11 +5,29 @@ project(
license : 'LGPL-2.1-or-later',
)
# Compute documentation URL based on version and release type
version = meson.project_version()
official_release = get_option('official-release')
if official_release
# For official releases, use versioned URL (dropping patch version)
version_parts = version.split('.')
major_minor = '@0@.@1@'.format(version_parts[0], version_parts[1])
doc_url = 'https://nix.dev/manual/nix/@0@'.format(major_minor)
else
# For development builds, use /latest
doc_url = 'https://nix.dev/manual/nix/latest'
endif
nix = find_program('nix', native : true)
mdbook = find_program('mdbook', native : true)
bash = find_program('bash', native : true)
rsync = find_program('rsync', required : true, native : true)
# HTML manual dependencies (conditional)
if get_option('html-manual')
mdbook = find_program('mdbook', native : true)
rsync = find_program('rsync', required : true, native : true)
endif
pymod = import('python')
python = pymod.find_installation('python3')
@@ -57,6 +75,24 @@ generate_manual_deps = files(
'generate-deps.py',
)
# Generate redirects.js from template and JSON data
redirects_js = custom_target(
'redirects.js',
command : [
python,
'@INPUT0@',
'@INPUT1@',
'@INPUT2@',
'@OUTPUT@',
],
input : [
'generate-redirects.py',
'redirects.js.in',
'redirects.json',
],
output : 'redirects.js',
)
# Generates types
subdir('source/store')
# Generates builtins.md and builtin-constants.md.
@@ -77,66 +113,71 @@ else
nix_input = []
endif
manual = custom_target(
'manual',
command : [
bash,
'-euo',
'pipefail',
'-c',
'''
@0@ @INPUT0@ @CURRENT_SOURCE_DIR@ > @DEPFILE@
@0@ @INPUT1@ summary @2@ < @CURRENT_SOURCE_DIR@/source/SUMMARY.md.in > @2@/source/SUMMARY.md
sed -e 's|@version@|@3@|g' < @INPUT2@ > @2@/book.toml
@4@ -r -L --include='*.md' @CURRENT_SOURCE_DIR@/ @2@/
(cd @2@; RUST_LOG=warn @1@ build -d @2@ 3>&2 2>&1 1>&3) | { grep -Fv "because fragment resolution isn't implemented" || :; } 3>&2 2>&1 1>&3
rm -rf @2@/manual
mv @2@/html @2@/manual
# Remove Mathjax 2.7, because we will actually use MathJax 3.x
find @2@/manual | grep .html | xargs sed -i -e '/2.7.1.MathJax.js/d'
find @2@/manual -iname meson.build -delete
'''.format(
python.full_path(),
mdbook.full_path(),
meson.current_build_dir(),
meson.project_version(),
rsync.full_path(),
),
],
input : [
generate_manual_deps,
'substitute.py',
'book.toml.in',
'anchors.jq',
'custom.css',
nix3_cli_files,
experimental_features_shortlist_md,
experimental_feature_descriptions_md,
types_dir,
conf_file_md,
builtins_md,
rl_next_generated,
summary_rl_next,
json_schema_generated_files,
nix_input,
],
output : [
# HTML manual build (conditional)
if get_option('html-manual')
manual = custom_target(
'manual',
'markdown',
],
depfile : 'manual.d',
env : {
'RUST_LOG' : 'info',
'MDBOOK_SUBSTITUTE_SEARCH' : meson.current_build_dir() / 'source',
},
)
manual_html = manual[0]
manual_md = manual[1]
command : [
bash,
'-euo',
'pipefail',
'-c',
'''
@0@ @INPUT0@ @CURRENT_SOURCE_DIR@ > @DEPFILE@
@0@ @INPUT1@ summary @2@ < @CURRENT_SOURCE_DIR@/source/SUMMARY.md.in > @2@/source/SUMMARY.md
sed -e 's|@version@|@3@|g' < @INPUT2@ > @2@/book.toml
@4@ -r -L --exclude='*.drv' --include='*.md' @CURRENT_SOURCE_DIR@/ @2@/
(cd @2@; RUST_LOG=warn @1@ build -d @2@ 3>&2 2>&1 1>&3) | { grep -Fv "because fragment resolution isn't implemented" || :; } 3>&2 2>&1 1>&3
rm -rf @2@/manual
mv @2@/html @2@/manual
# Remove Mathjax 2.7, because we will actually use MathJax 3.x
find @2@/manual | grep .html | xargs sed -i -e '/2.7.1.MathJax.js/d'
find @2@/manual -iname meson.build -delete
'''.format(
python.full_path(),
mdbook.full_path(),
meson.current_build_dir(),
meson.project_version(),
rsync.full_path(),
),
],
input : [
generate_manual_deps,
'substitute.py',
'book.toml.in',
'anchors.jq',
'custom.css',
redirects_js,
nix3_cli_files,
experimental_features_shortlist_md,
experimental_feature_descriptions_md,
types_dir,
conf_file_md,
builtins_md,
rl_next_generated,
summary_rl_next,
json_schema_generated_files,
nix_input,
],
output : [
'manual',
'markdown',
],
depfile : 'manual.d',
build_by_default : true,
env : {
'RUST_LOG' : 'info',
'MDBOOK_SUBSTITUTE_SEARCH' : meson.current_build_dir() / 'source',
},
)
manual_html = manual[0]
manual_md = manual[1]
install_subdir(
manual_html.full_path(),
install_dir : get_option('datadir') / 'doc/nix',
)
install_subdir(
manual_html.full_path(),
install_dir : get_option('datadir') / 'doc/nix',
)
endif
nix_nested_manpages = [
[
@@ -182,6 +223,7 @@ nix_nested_manpages = [
],
]
# Manpage generation (standalone, no mdbook dependency)
foreach command : nix_nested_manpages
foreach page : command[1]
title = command[0] + ' --' + page
@@ -189,15 +231,19 @@ foreach command : nix_nested_manpages
custom_target(
command : [
bash,
files('./render-manpage.sh'),
'@INPUT0@',
'--out-no-smarty',
title,
section,
'@INPUT0@/command-ref' / command[0] / (page + '.md'),
meson.current_source_dir() / 'source',
meson.current_build_dir() / 'source',
doc_url,
meson.current_source_dir() / 'source/command-ref' / command[0] / (page + '.md'),
'@OUTPUT0@',
],
input : [
manual_md,
files('./render-manpage.sh'),
files('./expand-includes.py'),
nix_input,
],
output : command[0] + '-' + page + '.1',
@@ -306,14 +352,21 @@ foreach page : nix3_manpages
command : [
bash,
'@INPUT0@',
# Note: no --out-no-smarty flag (original behavior)
page,
section,
'@INPUT1@/command-ref/new-cli/@0@.md'.format(page),
meson.current_source_dir() / 'source',
meson.current_build_dir() / 'source',
doc_url,
meson.current_build_dir() / 'source/command-ref/new-cli/@0@.md'.format(
page,
),
'@OUTPUT@',
],
input : [
files('./render-manpage.sh'),
manual_md,
files('./expand-includes.py'),
nix3_cli_files,
nix_input,
],
output : page + '.1',
@@ -333,7 +386,12 @@ nix_manpages = [
[ 'nix-channel', 1 ],
[ 'nix-hash', 1 ],
[ 'nix-copy-closure', 1 ],
[ 'nix.conf', 5, conf_file_md.full_path() ],
[
'nix.conf',
5,
conf_file_md.full_path(),
[ conf_file_md, experimental_features_shortlist_md ],
],
[ 'nix-daemon', 8 ],
[ 'nix-profiles', 5, 'files/profiles.md' ],
]
@@ -345,19 +403,24 @@ foreach entry : nix_manpages
# Therefore we use an optional third element of this array to override the name pattern
md_file = entry.get(2, title + '.md')
section = entry[1].to_string()
md_file_resolved = join_paths('@INPUT1@/command-ref/', md_file)
input_file = meson.current_source_dir() / 'source/command-ref' / md_file
custom_target(
command : [
bash,
'@INPUT0@',
# Note: no --out-no-smarty flag (original behavior)
title,
section,
md_file_resolved,
meson.current_source_dir() / 'source',
meson.current_build_dir() / 'source',
doc_url,
input_file,
'@OUTPUT@',
],
input : [
files('./render-manpage.sh'),
manual_md,
files('./expand-includes.py'),
entry.get(3, []),
nix_input,
],

13
doc/manual/meson.options Normal file
View File

@@ -0,0 +1,13 @@
option(
'official-release',
type : 'boolean',
value : true,
description : 'Whether this is an official release build (affects documentation URLs)',
)
option(
'html-manual',
type : 'boolean',
value : true,
description : 'Whether to build the HTML manual (requires mdbook)',
)

View File

@@ -1,12 +1,13 @@
{
lib,
callPackage,
mkMesonDerivation,
runCommand,
meson,
ninja,
lowdown-unsandboxed,
mdbook,
mdbook-linkcheck,
jq,
python3,
rsync,
@@ -18,6 +19,11 @@
# Configuration Options
version,
/**
Whether to build the HTML manual.
When false, only manpages are built, avoiding the mdbook dependency.
*/
buildHtmlManual ? true,
# `tests` attribute
testers,
@@ -37,14 +43,17 @@ mkMesonDerivation (finalAttrs: {
(fileset.unions [
../../.version
# For example JSON
../../src/libutil-tests/data/memory-source-accessor
../../src/libutil-tests/data/hash
../../src/libstore-tests/data/content-address
../../src/libstore-tests/data/store-path
../../src/libstore-tests/data/realisation
../../src/libstore-tests/data/derivation
../../src/libstore-tests/data/derived-path
../../src/libstore-tests/data/path-info
../../src/libstore-tests/data/nar-info
../../src/libstore-tests/data/build-result
../../src/libstore-tests/data/dummy-store
# Too many different types of files to filter for now
../../doc/manual
./.
@@ -53,9 +62,22 @@ mkMesonDerivation (finalAttrs: {
../../doc/manual/package.nix;
# TODO the man pages should probably be separate
outputs = [
"out"
"man"
outputs =
if buildHtmlManual then
[
"out"
"man"
]
else
[ "out" ]; # Only one output when HTML manual is disabled; use "out" for manpages
# When HTML manual is disabled, install manpages to "out" instead of "man"
mesonFlags = [
(lib.mesonBool "official-release" officialRelease)
(lib.mesonBool "html-manual" buildHtmlManual)
]
++ lib.optionals (!buildHtmlManual) [
"--mandir=${placeholder "out"}/share/man"
];
nativeBuildInputs = [
@@ -63,15 +85,15 @@ mkMesonDerivation (finalAttrs: {
meson
ninja
(lib.getBin lowdown-unsandboxed)
mdbook
mdbook-linkcheck
jq
python3
]
++ lib.optionals buildHtmlManual [
mdbook
rsync
json-schema-for-humans
changelog-d
]
++ lib.optionals (!officialRelease) [
++ lib.optionals (!officialRelease && buildHtmlManual) [
# When not an official release, we likely have changelog entries that have
# yet to be rendered.
# When released, these are rendered into a committed file to save a dependency.
@@ -83,32 +105,47 @@ mkMesonDerivation (finalAttrs: {
echo ${finalAttrs.version} > ./.version
'';
postInstall = ''
postInstall = lib.optionalString buildHtmlManual ''
mkdir -p ''$out/nix-support
echo "doc manual ''$out/share/doc/nix/manual" >> ''$out/nix-support/hydra-build-products
'';
/**
The root of the HTML manual.
E.g. "${nix-manual.site}/index.html" exists.
*/
passthru.site = finalAttrs.finalPackage + "/share/doc/nix/manual";
passthru = lib.optionalAttrs buildHtmlManual {
/**
The root of the HTML manual.
E.g. "${nix-manual.site}/index.html" exists.
*/
passthru.tests = {
# https://nixos.org/manual/nixpkgs/stable/index.html#tester-lycheeLinkCheck
linkcheck = testers.lycheeLinkCheck {
inherit (finalAttrs.finalPackage) site;
extraConfig = {
exclude = [
# Exclude auto-generated JSON schema documentation which has
# auto-generated fragment IDs that don't match the link references
".*/protocols/json/.*\\.html"
# Exclude undocumented builtins
".*/language/builtins\\.html#builtins-addErrorContext"
".*/language/builtins\\.html#builtins-appendContext"
];
site = finalAttrs.finalPackage + "/share/doc/nix/manual";
tests =
let
redirect-targets = callPackage ./redirect-targets-html.nix { };
in
{
# https://nixos.org/manual/nixpkgs/stable/index.html#tester-lycheeLinkCheck
linkcheck = testers.lycheeLinkCheck {
site =
let
plain = finalAttrs.finalPackage.site;
in
runCommand "nix-manual-with-redirect-targets" { } ''
cp -r ${plain} $out
chmod -R u+w $out
cp ${redirect-targets}/redirect-targets.html $out/redirect-targets.html
'';
extraConfig = {
exclude = [
# Exclude auto-generated JSON schema documentation which has
# auto-generated fragment IDs that don't match the link references
".*/protocols/json/.*\\.html"
# Exclude undocumented builtins
".*/language/builtins\\.html#builtins-addErrorContext"
".*/language/builtins\\.html#builtins-appendContext"
];
};
};
};
};
};
meta = {

View File

@@ -0,0 +1,62 @@
# Generates redirect-targets.html containing all redirect targets for link checking.
# Used by: doc/manual/package.nix (passthru.tests.linkcheck)
{
stdenv,
lib,
jq,
}:
stdenv.mkDerivation {
name = "redirect-targets-html";
src = lib.fileset.toSource {
root = ./.;
fileset = ./redirects.json;
};
nativeBuildInputs = [ jq ];
installPhase = ''
mkdir -p $out
{
echo '<!DOCTYPE html>'
echo '<html><head><title>Nix Manual Redirect Targets</title></head><body>'
echo '<h1>Redirect Targets to Check</h1>'
echo '<p>This document contains all redirect targets from the Nix manual.</p>'
echo '<h2>Client-side redirects (from redirects.json)</h2>'
echo '<ul>'
# Extract all redirects with their source pages to properly resolve relative paths
jq -r 'to_entries[] | .key as $page | .value | to_entries[] | "\($page)\t\(.value)"' \
redirects.json | while IFS=$'\t' read -r page target; do
page_dir=$(dirname "$page")
# Handle fragment-only targets (e.g., #primitives)
if [[ "$target" == \#* ]]; then
# Fragment is on the same page
resolved="$page$target"
echo "<li><a href=\"$resolved\">$resolved</a> (fragment on $page)</li>"
continue
fi
# Resolve relative path based on the source page location
resolved="$page_dir/$target"
echo "<li><a href=\"$resolved\">$resolved</a> (from $page)</li>"
done
echo '</ul>'
echo '</body></html>'
} > $out/redirect-targets.html
echo "Generated redirect targets document with $(grep -c '<li>' $out/redirect-targets.html) links"
'';
meta = {
description = "HTML document listing all Nix manual redirect targets for link checking";
};
}

View File

@@ -1,460 +0,0 @@
// redirect rules for URL fragments (client-side) to prevent link rot.
// this must be done on the client side, as web servers do not see the fragment part of the URL.
// it will only work with JavaScript enabled in the browser, but this is the best we can do here.
// see source/_redirects for path redirects (server-side)
// redirects are declared as follows:
// each entry has as its key a path matching the requested URL path, relative to the mdBook document root.
//
// IMPORTANT: it must specify the full path with file name and suffix
//
// each entry is itself a set of key-value pairs, where
// - keys are anchors on the matched path.
// - values are redirection targets relative to the current path.
const redirects = {
"index.html": {
"part-advanced-topics": "advanced-topics/index.html",
"chap-tuning-cores-and-jobs": "advanced-topics/cores-vs-jobs.html",
"chap-diff-hook": "advanced-topics/diff-hook.html",
"check-dirs-are-unregistered": "advanced-topics/diff-hook.html#check-dirs-are-unregistered",
"chap-distributed-builds": "command-ref/conf-file.html#conf-builders",
"chap-post-build-hook": "advanced-topics/post-build-hook.html",
"chap-post-build-hook-caveats": "advanced-topics/post-build-hook.html#implementation-caveats",
"chap-writing-nix-expressions": "language/index.html",
"part-command-ref": "command-ref/index.html",
"conf-allow-import-from-derivation": "command-ref/conf-file.html#conf-allow-import-from-derivation",
"conf-allow-new-privileges": "command-ref/conf-file.html#conf-allow-new-privileges",
"conf-allowed-uris": "command-ref/conf-file.html#conf-allowed-uris",
"conf-allowed-users": "command-ref/conf-file.html#conf-allowed-users",
"conf-auto-optimise-store": "command-ref/conf-file.html#conf-auto-optimise-store",
"conf-binary-cache-public-keys": "command-ref/conf-file.html#conf-binary-cache-public-keys",
"conf-binary-caches": "command-ref/conf-file.html#conf-binary-caches",
"conf-build-compress-log": "command-ref/conf-file.html#conf-build-compress-log",
"conf-build-cores": "command-ref/conf-file.html#conf-build-cores",
"conf-build-extra-chroot-dirs": "command-ref/conf-file.html#conf-build-extra-chroot-dirs",
"conf-build-extra-sandbox-paths": "command-ref/conf-file.html#conf-build-extra-sandbox-paths",
"conf-build-fallback": "command-ref/conf-file.html#conf-build-fallback",
"conf-build-max-jobs": "command-ref/conf-file.html#conf-build-max-jobs",
"conf-build-max-log-size": "command-ref/conf-file.html#conf-build-max-log-size",
"conf-build-max-silent-time": "command-ref/conf-file.html#conf-build-max-silent-time",
"conf-build-timeout": "command-ref/conf-file.html#conf-build-timeout",
"conf-build-use-chroot": "command-ref/conf-file.html#conf-build-use-chroot",
"conf-build-use-sandbox": "command-ref/conf-file.html#conf-build-use-sandbox",
"conf-build-use-substitutes": "command-ref/conf-file.html#conf-build-use-substitutes",
"conf-build-users-group": "command-ref/conf-file.html#conf-build-users-group",
"conf-builders": "command-ref/conf-file.html#conf-builders",
"conf-builders-use-substitutes": "command-ref/conf-file.html#conf-builders-use-substitutes",
"conf-compress-build-log": "command-ref/conf-file.html#conf-compress-build-log",
"conf-connect-timeout": "command-ref/conf-file.html#conf-connect-timeout",
"conf-cores": "command-ref/conf-file.html#conf-cores",
"conf-diff-hook": "command-ref/conf-file.html#conf-diff-hook",
"conf-env-keep-derivations": "command-ref/conf-file.html#conf-env-keep-derivations",
"conf-extra-binary-caches": "command-ref/conf-file.html#conf-extra-binary-caches",
"conf-extra-platforms": "command-ref/conf-file.html#conf-extra-platforms",
"conf-extra-sandbox-paths": "command-ref/conf-file.html#conf-extra-sandbox-paths",
"conf-extra-substituters": "command-ref/conf-file.html#conf-extra-substituters",
"conf-fallback": "command-ref/conf-file.html#conf-fallback",
"conf-fsync-metadata": "command-ref/conf-file.html#conf-fsync-metadata",
"conf-gc-keep-derivations": "command-ref/conf-file.html#conf-gc-keep-derivations",
"conf-gc-keep-outputs": "command-ref/conf-file.html#conf-gc-keep-outputs",
"conf-hashed-mirrors": "command-ref/conf-file.html#conf-hashed-mirrors",
"conf-http-connections": "command-ref/conf-file.html#conf-http-connections",
"conf-keep-build-log": "command-ref/conf-file.html#conf-keep-build-log",
"conf-keep-derivations": "command-ref/conf-file.html#conf-keep-derivations",
"conf-keep-env-derivations": "command-ref/conf-file.html#conf-keep-env-derivations",
"conf-keep-outputs": "command-ref/conf-file.html#conf-keep-outputs",
"conf-max-build-log-size": "command-ref/conf-file.html#conf-max-build-log-size",
"conf-max-free": "command-ref/conf-file.html#conf-max-free",
"conf-max-jobs": "command-ref/conf-file.html#conf-max-jobs",
"conf-max-silent-time": "command-ref/conf-file.html#conf-max-silent-time",
"conf-min-free": "command-ref/conf-file.html#conf-min-free",
"conf-narinfo-cache-negative-ttl": "command-ref/conf-file.html#conf-narinfo-cache-negative-ttl",
"conf-narinfo-cache-positive-ttl": "command-ref/conf-file.html#conf-narinfo-cache-positive-ttl",
"conf-netrc-file": "command-ref/conf-file.html#conf-netrc-file",
"conf-plugin-files": "command-ref/conf-file.html#conf-plugin-files",
"conf-post-build-hook": "command-ref/conf-file.html#conf-post-build-hook",
"conf-pre-build-hook": "command-ref/conf-file.html#conf-pre-build-hook",
"conf-require-sigs": "command-ref/conf-file.html#conf-require-sigs",
"conf-restrict-eval": "command-ref/conf-file.html#conf-restrict-eval",
"conf-run-diff-hook": "command-ref/conf-file.html#conf-run-diff-hook",
"conf-sandbox": "command-ref/conf-file.html#conf-sandbox",
"conf-sandbox-dev-shm-size": "command-ref/conf-file.html#conf-sandbox-dev-shm-size",
"conf-sandbox-paths": "command-ref/conf-file.html#conf-sandbox-paths",
"conf-secret-key-files": "command-ref/conf-file.html#conf-secret-key-files",
"conf-show-trace": "command-ref/conf-file.html#conf-show-trace",
"conf-stalled-download-timeout": "command-ref/conf-file.html#conf-stalled-download-timeout",
"conf-substitute": "command-ref/conf-file.html#conf-substitute",
"conf-substituters": "command-ref/conf-file.html#conf-substituters",
"conf-system": "command-ref/conf-file.html#conf-system",
"conf-system-features": "command-ref/conf-file.html#conf-system-features",
"conf-tarball-ttl": "command-ref/conf-file.html#conf-tarball-ttl",
"conf-timeout": "command-ref/conf-file.html#conf-timeout",
"conf-trace-function-calls": "command-ref/conf-file.html#conf-trace-function-calls",
"conf-trusted-binary-caches": "command-ref/conf-file.html#conf-trusted-binary-caches",
"conf-trusted-public-keys": "command-ref/conf-file.html#conf-trusted-public-keys",
"conf-trusted-substituters": "command-ref/conf-file.html#conf-trusted-substituters",
"conf-trusted-users": "command-ref/conf-file.html#conf-trusted-users",
"extra-sandbox-paths": "command-ref/conf-file.html#extra-sandbox-paths",
"sec-conf-file": "command-ref/conf-file.html",
"env-NIX_PATH": "command-ref/env-common.html#env-NIX_PATH",
"env-common": "command-ref/env-common.html",
"envar-remote": "command-ref/env-common.html#env-NIX_REMOTE",
"sec-common-env": "command-ref/env-common.html",
"ch-files": "command-ref/files.html",
"ch-main-commands": "command-ref/main-commands.html",
"opt-out-link": "command-ref/nix-build.html#opt-out-link",
"sec-nix-build": "command-ref/nix-build.html",
"sec-nix-channel": "command-ref/nix-channel.html",
"sec-nix-collect-garbage": "command-ref/nix-collect-garbage.html",
"sec-nix-copy-closure": "command-ref/nix-copy-closure.html",
"sec-nix-daemon": "command-ref/nix-daemon.html",
"refsec-nix-env-install-examples": "command-ref/nix-env.html#examples",
"rsec-nix-env-install": "command-ref/nix-env.html#operation---install",
"rsec-nix-env-set": "command-ref/nix-env.html#operation---set",
"rsec-nix-env-set-flag": "command-ref/nix-env.html#operation---set-flag",
"rsec-nix-env-upgrade": "command-ref/nix-env.html#operation---upgrade",
"sec-nix-env": "command-ref/nix-env.html",
"ssec-version-comparisons": "command-ref/nix-env.html#versions",
"sec-nix-hash": "command-ref/nix-hash.html",
"sec-nix-instantiate": "command-ref/nix-instantiate.html",
"sec-nix-prefetch-url": "command-ref/nix-prefetch-url.html",
"sec-nix-shell": "command-ref/nix-shell.html",
"ssec-nix-shell-shebang": "command-ref/nix-shell.html#use-as-a--interpreter",
"nixref-queries": "command-ref/nix-store.html#queries",
"opt-add-root": "command-ref/nix-store.html#opt-add-root",
"refsec-nix-store-dump": "command-ref/nix-store.html#operation---dump",
"refsec-nix-store-export": "command-ref/nix-store.html#operation---export",
"refsec-nix-store-import": "command-ref/nix-store.html#operation---import",
"refsec-nix-store-query": "command-ref/nix-store.html#operation---query",
"refsec-nix-store-verify": "command-ref/nix-store.html#operation---verify",
"rsec-nix-store-gc": "command-ref/nix-store.html#operation---gc",
"rsec-nix-store-generate-binary-cache-key": "command-ref/nix-store.html#operation---generate-binary-cache-key",
"rsec-nix-store-realise": "command-ref/nix-store.html#operation---realise",
"rsec-nix-store-serve": "command-ref/nix-store.html#operation---serve",
"sec-nix-store": "command-ref/nix-store.html",
"opt-I": "command-ref/opt-common.html#opt-I",
"opt-attr": "command-ref/opt-common.html#opt-attr",
"opt-common": "command-ref/opt-common.html",
"opt-cores": "command-ref/opt-common.html#opt-cores",
"opt-log-format": "command-ref/opt-common.html#opt-log-format",
"opt-max-jobs": "command-ref/opt-common.html#opt-max-jobs",
"opt-max-silent-time": "command-ref/opt-common.html#opt-max-silent-time",
"opt-timeout": "command-ref/opt-common.html#opt-timeout",
"sec-common-options": "command-ref/opt-common.html",
"ch-utilities": "command-ref/utilities.html",
"chap-hacking": "development/building.html",
"adv-attr-allowSubstitutes": "language/advanced-attributes.html#adv-attr-allowSubstitutes",
"adv-attr-allowedReferences": "language/advanced-attributes.html#adv-attr-allowedReferences",
"adv-attr-allowedRequisites": "language/advanced-attributes.html#adv-attr-allowedRequisites",
"adv-attr-disallowedReferences": "language/advanced-attributes.html#adv-attr-disallowedReferences",
"adv-attr-disallowedRequisites": "language/advanced-attributes.html#adv-attr-disallowedRequisites",
"adv-attr-exportReferencesGraph": "language/advanced-attributes.html#adv-attr-exportReferencesGraph",
"adv-attr-impureEnvVars": "language/advanced-attributes.html#adv-attr-impureEnvVars",
"adv-attr-outputHash": "language/advanced-attributes.html#adv-attr-outputHash",
"adv-attr-outputHashAlgo": "language/advanced-attributes.html#adv-attr-outputHashAlgo",
"adv-attr-outputHashMode": "language/advanced-attributes.html#adv-attr-outputHashMode",
"adv-attr-passAsFile": "language/advanced-attributes.html#adv-attr-passAsFile",
"adv-attr-preferLocalBuild": "language/advanced-attributes.html#adv-attr-preferLocalBuild",
"fixed-output-drvs": "language/advanced-attributes.html#adv-attr-outputHash",
"sec-advanced-attributes": "language/advanced-attributes.html",
"builtin-abort": "language/builtins.html#builtins-abort",
"builtin-add": "language/builtins.html#builtins-add",
"builtin-all": "language/builtins.html#builtins-all",
"builtin-any": "language/builtins.html#builtins-any",
"builtin-attrNames": "language/builtins.html#builtins-attrNames",
"builtin-attrValues": "language/builtins.html#builtins-attrValues",
"builtin-baseNameOf": "language/builtins.html#builtins-baseNameOf",
"builtin-bitAnd": "language/builtins.html#builtins-bitAnd",
"builtin-bitOr": "language/builtins.html#builtins-bitOr",
"builtin-bitXor": "language/builtins.html#builtins-bitXor",
"builtin-builtins": "language/builtins.html#builtins-builtins",
"builtin-compareVersions": "language/builtins.html#builtins-compareVersions",
"builtin-concatLists": "language/builtins.html#builtins-concatLists",
"builtin-concatStringsSep": "language/builtins.html#builtins-concatStringsSep",
"builtin-currentSystem": "language/builtins.html#builtins-currentSystem",
"builtin-deepSeq": "language/builtins.html#builtins-deepSeq",
"builtin-derivation": "language/builtins.html#builtins-derivation",
"builtin-dirOf": "language/builtins.html#builtins-dirOf",
"builtin-div": "language/builtins.html#builtins-div",
"builtin-elem": "language/builtins.html#builtins-elem",
"builtin-elemAt": "language/builtins.html#builtins-elemAt",
"builtin-fetchGit": "language/builtins.html#builtins-fetchGit",
"builtin-fetchTarball": "language/builtins.html#builtins-fetchTarball",
"builtin-fetchurl": "language/builtins.html#builtins-fetchurl",
"builtin-filterSource": "language/builtins.html#builtins-filterSource",
"builtin-foldl-prime": "language/builtins.html#builtins-foldl-prime",
"builtin-fromJSON": "language/builtins.html#builtins-fromJSON",
"builtin-functionArgs": "language/builtins.html#builtins-functionArgs",
"builtin-genList": "language/builtins.html#builtins-genList",
"builtin-getAttr": "language/builtins.html#builtins-getAttr",
"builtin-getEnv": "language/builtins.html#builtins-getEnv",
"builtin-hasAttr": "language/builtins.html#builtins-hasAttr",
"builtin-hashFile": "language/builtins.html#builtins-hashFile",
"builtin-hashString": "language/builtins.html#builtins-hashString",
"builtin-head": "language/builtins.html#builtins-head",
"builtin-import": "language/builtins.html#builtins-import",
"builtin-intersectAttrs": "language/builtins.html#builtins-intersectAttrs",
"builtin-isAttrs": "language/builtins.html#builtins-isAttrs",
"builtin-isBool": "language/builtins.html#builtins-isBool",
"builtin-isFloat": "language/builtins.html#builtins-isFloat",
"builtin-isFunction": "language/builtins.html#builtins-isFunction",
"builtin-isInt": "language/builtins.html#builtins-isInt",
"builtin-isList": "language/builtins.html#builtins-isList",
"builtin-isNull": "language/builtins.html#builtins-isNull",
"builtin-isString": "language/builtins.html#builtins-isString",
"builtin-length": "language/builtins.html#builtins-length",
"builtin-lessThan": "language/builtins.html#builtins-lessThan",
"builtin-listToAttrs": "language/builtins.html#builtins-listToAttrs",
"builtin-map": "language/builtins.html#builtins-map",
"builtin-match": "language/builtins.html#builtins-match",
"builtin-mul": "language/builtins.html#builtins-mul",
"builtin-parseDrvName": "language/builtins.html#builtins-parseDrvName",
"builtin-path": "language/builtins.html#builtins-path",
"builtin-pathExists": "language/builtins.html#builtins-pathExists",
"builtin-placeholder": "language/builtins.html#builtins-placeholder",
"builtin-readDir": "language/builtins.html#builtins-readDir",
"builtin-readFile": "language/builtins.html#builtins-readFile",
"builtin-removeAttrs": "language/builtins.html#builtins-removeAttrs",
"builtin-replaceStrings": "language/builtins.html#builtins-replaceStrings",
"builtin-seq": "language/builtins.html#builtins-seq",
"builtin-sort": "language/builtins.html#builtins-sort",
"builtin-split": "language/builtins.html#builtins-split",
"builtin-splitVersion": "language/builtins.html#builtins-splitVersion",
"builtin-stringLength": "language/builtins.html#builtins-stringLength",
"builtin-sub": "language/builtins.html#builtins-sub",
"builtin-substring": "language/builtins.html#builtins-substring",
"builtin-tail": "language/builtins.html#builtins-tail",
"builtin-throw": "language/builtins.html#builtins-throw",
"builtin-toFile": "language/builtins.html#builtins-toFile",
"builtin-toJSON": "language/builtins.html#builtins-toJSON",
"builtin-toPath": "language/builtins.html#builtins-toPath",
"builtin-toString": "language/builtins.html#builtins-toString",
"builtin-toXML": "language/builtins.html#builtins-toXML",
"builtin-trace": "language/builtins.html#builtins-trace",
"builtin-tryEval": "language/builtins.html#builtins-tryEval",
"builtin-typeOf": "language/builtins.html#builtins-typeOf",
"ssec-builtins": "language/builtins.html",
"attr-system": "language/derivations.html#attr-system",
"ssec-derivation": "language/derivations.html",
"ch-expression-language": "language/index.html",
"sec-constructs": "language/syntax.html",
"sect-let-language": "language/syntax.html#let-expressions",
"ss-functions": "language/syntax.html#functions",
"sec-language-operators": "language/operators.html",
"table-operators": "language/operators.html",
"ssec-values": "language/types.html",
"gloss-closure": "glossary.html#gloss-closure",
"gloss-derivation": "glossary.html#gloss-derivation",
"gloss-deriver": "glossary.html#gloss-deriver",
"gloss-nar": "glossary.html#gloss-nar",
"gloss-output-path": "glossary.html#gloss-output-path",
"gloss-profile": "glossary.html#gloss-profile",
"gloss-reachable": "glossary.html#gloss-reachable",
"gloss-reference": "glossary.html#gloss-reference",
"gloss-substitute": "glossary.html#gloss-substitute",
"gloss-user-env": "glossary.html#gloss-user-env",
"gloss-validity": "glossary.html#gloss-validity",
"part-glossary": "glossary.html",
"sec-building-source": "installation/building-source.html",
"ch-env-variables": "installation/env-variables.html",
"sec-installer-proxy-settings": "installation/env-variables.html#proxy-environment-variables",
"sec-nix-ssl-cert-file": "installation/env-variables.html#nix_ssl_cert_file",
"sec-nix-ssl-cert-file-with-nix-daemon-and-macos": "installation/env-variables.html#nix_ssl_cert_file-with-macos-and-the-nix-daemon",
"chap-installation": "installation/index.html",
"ch-installing-binary": "installation/installing-binary.html",
"sect-macos-installation": "installation/installing-binary.html#macos-installation",
"sect-macos-installation-change-store-prefix": "installation/installing-binary.html#macos-installation",
"sect-macos-installation-encrypted-volume": "installation/installing-binary.html#macos-installation",
"sect-macos-installation-recommended-notes": "installation/installing-binary.html#macos-installation",
"sect-macos-installation-symlink": "installation/installing-binary.html#macos-installation",
"sect-multi-user-installation": "installation/installing-binary.html#multi-user-installation",
"sect-nix-install-binary-tarball": "installation/installing-binary.html#installing-from-a-binary-tarball",
"sect-nix-install-pinned-version-url": "installation/installing-binary.html#installing-a-pinned-nix-version-from-a-url",
"sect-single-user-installation": "installation/installing-binary.html#single-user-installation",
"ch-installing-source": "installation/installing-source.html",
"ssec-multi-user": "installation/multi-user.html",
"ch-nix-security": "installation/nix-security.html",
"sec-obtaining-source": "installation/obtaining-source.html",
"sec-prerequisites-source": "installation/prerequisites-source.html",
"sec-single-user": "installation/single-user.html",
"ch-supported-platforms": "installation/supported-platforms.html",
"ch-upgrading-nix": "installation/upgrading.html",
"ch-about-nix": "introduction.html",
"chap-introduction": "introduction.html",
"ch-basic-package-mgmt": "package-management/basic-package-mgmt.html",
"ssec-binary-cache-substituter": "package-management/binary-cache-substituter.html",
"sec-channels": "command-ref/nix-channel.html",
"ssec-copy-closure": "command-ref/nix-copy-closure.html",
"sec-garbage-collection": "package-management/garbage-collection.html",
"ssec-gc-roots": "package-management/garbage-collector-roots.html",
"chap-package-management": "package-management/index.html",
"sec-profiles": "package-management/profiles.html",
"ssec-s3-substituter": "store/types/s3-substituter.html",
"ssec-s3-substituter-anonymous-reads": "store/types/s3-substituter.html#anonymous-reads-to-your-s3-compatible-binary-cache",
"ssec-s3-substituter-authenticated-reads": "store/types/s3-substituter.html#authenticated-reads-to-your-s3-binary-cache",
"ssec-s3-substituter-authenticated-writes": "store/types/s3-substituter.html#authenticated-writes-to-your-s3-compatible-binary-cache",
"sec-sharing-packages": "package-management/sharing-packages.html",
"ssec-ssh-substituter": "package-management/ssh-substituter.html",
"chap-quick-start": "quick-start.html",
"sec-relnotes": "release-notes/index.html",
"ch-relnotes-0.10.1": "release-notes/rl-0.10.1.html",
"ch-relnotes-0.10": "release-notes/rl-0.10.html",
"ssec-relnotes-0.11": "release-notes/rl-0.11.html",
"ssec-relnotes-0.12": "release-notes/rl-0.12.html",
"ssec-relnotes-0.13": "release-notes/rl-0.13.html",
"ssec-relnotes-0.14": "release-notes/rl-0.14.html",
"ssec-relnotes-0.15": "release-notes/rl-0.15.html",
"ssec-relnotes-0.16": "release-notes/rl-0.16.html",
"ch-relnotes-0.5": "release-notes/rl-0.5.html",
"ch-relnotes-0.6": "release-notes/rl-0.6.html",
"ch-relnotes-0.7": "release-notes/rl-0.7.html",
"ch-relnotes-0.8.1": "release-notes/rl-0.8.1.html",
"ch-relnotes-0.8": "release-notes/rl-0.8.html",
"ch-relnotes-0.9.1": "release-notes/rl-0.9.1.html",
"ch-relnotes-0.9.2": "release-notes/rl-0.9.2.html",
"ch-relnotes-0.9": "release-notes/rl-0.9.html",
"ssec-relnotes-1.0": "release-notes/rl-1.0.html",
"ssec-relnotes-1.1": "release-notes/rl-1.1.html",
"ssec-relnotes-1.10": "release-notes/rl-1.10.html",
"ssec-relnotes-1.11.10": "release-notes/rl-1.11.10.html",
"ssec-relnotes-1.11": "release-notes/rl-1.11.html",
"ssec-relnotes-1.2": "release-notes/rl-1.2.html",
"ssec-relnotes-1.3": "release-notes/rl-1.3.html",
"ssec-relnotes-1.4": "release-notes/rl-1.4.html",
"ssec-relnotes-1.5.1": "release-notes/rl-1.5.1.html",
"ssec-relnotes-1.5.2": "release-notes/rl-1.5.2.html",
"ssec-relnotes-1.5": "release-notes/rl-1.5.html",
"ssec-relnotes-1.6.1": "release-notes/rl-1.6.1.html",
"ssec-relnotes-1.6.0": "release-notes/rl-1.6.html",
"ssec-relnotes-1.7": "release-notes/rl-1.7.html",
"ssec-relnotes-1.8": "release-notes/rl-1.8.html",
"ssec-relnotes-1.9": "release-notes/rl-1.9.html",
"ssec-relnotes-2.0": "release-notes/rl-2.0.html",
"ssec-relnotes-2.1": "release-notes/rl-2.1.html",
"ssec-relnotes-2.2": "release-notes/rl-2.2.html",
"ssec-relnotes-2.3": "release-notes/rl-2.3.html",
},
"language/types.html": {
"simple-values": "#primitives",
"lists": "#list",
"strings": "#string",
"attribute-sets": "#attribute-set",
"type-number": "#type-int",
},
"language/syntax.html": {
"scoping-rules": "scoping.html",
"string-literal": "string-literals.html",
},
"language/derivations.md": {
"builder-execution": "store/drv/building.md#builder-execution",
},
"installation/installing-binary.html": {
"linux": "uninstall.html#linux",
"macos": "uninstall.html#macos",
"uninstalling": "uninstall.html",
},
"development/building.html": {
"nix-with-flakes": "#building-nix-with-flakes",
"classic-nix": "#building-nix",
"running-tests": "testing.html#running-tests",
"unit-tests": "testing.html#unit-tests",
"functional-tests": "testing.html#functional-tests",
"debugging-failing-functional-tests": "testing.html#debugging-failing-functional-tests",
"integration-tests": "testing.html#integration-tests",
"installer-tests": "testing.html#installer-tests",
"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",
"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": {
"gloss-local-store": "store/types/local-store.html",
"package-attribute-set": "#package",
"gloss-chroot-store": "store/types/local-store.html",
"gloss-content-addressed-derivation": "#gloss-content-addressing-derivation",
},
};
// the following code matches the current page's URL against the set of redirects.
//
// it is written to minimize the latency between page load and redirect.
// therefore we avoid function calls, copying data, and unnecessary loops.
// IMPORTANT: we use stateful array operations and their order matters!
//
// matching URLs is more involved than it should be:
//
// 1. `document.location.pathname` can have an arbitrary prefix.
//
// 2. `path_to_root` is set by mdBook. it consists only of `../`s and
// determines the depth of `<path>` relative to the prefix:
//
// `document.location.pathname`
// |------------------------------|
// /<prefix>/<path>/[<file>[.html]][#<anchor>]
// |----|
// `path_to_root` has same number of path segments
//
// source: https://phaiax.github.io/mdBook/format/theme/index-hbs.html#data
//
// 3. the following paths are equivalent:
//
// /foo/bar/
// /foo/bar/index.html
// /foo/bar/index
//
// 4. the following paths are also equivalent:
//
// /foo/bar/baz
// /foo/bar/baz.html
//
let segments = document.location.pathname.split('/');
let file = segments.pop();
// normalize file name
if (file === '') { file = "index.html"; }
else if (!file.endsWith('.html')) { file = file + '.html'; }
segments.push(file);
// use `path_to_root` to discern prefix from path.
const depth = path_to_root.split('/').length;
// remove segments containing prefix. the following works because
// 1. the original `document.location.pathname` is absolute,
// hence first element of `segments` is always empty.
// 2. last element of splitting `path_to_root` is also always empty.
// 3. last element of `segments` is the file name.
//
// visual example:
//
// '/foo/bar/baz.html'.split('/') -> [ '', 'foo', 'bar', 'baz.html' ]
// '../'.split('/') -> [ '..', '' ]
//
// the following operations will then result in
//
// path = 'bar/baz.html'
//
segments.splice(0, segments.length - depth);
const path = segments.join('/');
// anchor starts with the hash character (`#`),
// but our redirect declarations don't, so we strip it.
// example:
// document.location.hash -> '#foo'
// document.location.hash.substring(1) -> 'foo'
const anchor = document.location.hash.substring(1);
const redirect = redirects[path];
if (redirect) {
const target = redirect[anchor];
if (target) {
document.location.href = target;
}
}

View File

@@ -0,0 +1,94 @@
// redirect rules for URL fragments (client-side) to prevent link rot.
// this must be done on the client side, as web servers do not see the fragment part of the URL.
// it will only work with JavaScript enabled in the browser, but this is the best we can do here.
// see source/_redirects for path redirects (server-side)
// redirects are declared as follows:
// each entry has as its key a path matching the requested URL path, relative to the mdBook document root.
//
// IMPORTANT: it must specify the full path with file name and suffix
//
// each entry is itself a set of key-value pairs, where
// - keys are anchors on the matched path.
// - values are redirection targets relative to the current path.
const redirects = @REDIRECTS_JSON@;
// the following code matches the current page's URL against the set of redirects.
//
// it is written to minimize the latency between page load and redirect.
// therefore we avoid function calls, copying data, and unnecessary loops.
// IMPORTANT: we use stateful array operations and their order matters!
//
// matching URLs is more involved than it should be:
//
// 1. `document.location.pathname` can have an arbitrary prefix.
//
// 2. `path_to_root` is set by mdBook. it consists only of `../`s and
// determines the depth of `<path>` relative to the prefix:
//
// `document.location.pathname`
// |------------------------------|
// /<prefix>/<path>/[<file>[.html]][#<anchor>]
// |----|
// `path_to_root` has same number of path segments
//
// source: https://phaiax.github.io/mdBook/format/theme/index-hbs.html#data
//
// 3. the following paths are equivalent:
//
// /foo/bar/
// /foo/bar/index.html
// /foo/bar/index
//
// 4. the following paths are also equivalent:
//
// /foo/bar/baz
// /foo/bar/baz.html
//
let segments = document.location.pathname.split('/');
let file = segments.pop();
// normalize file name
if (file === '') { file = "index.html"; }
else if (!file.endsWith('.html')) { file = file + '.html'; }
segments.push(file);
// use `path_to_root` to discern prefix from path.
const depth = path_to_root.split('/').length;
// remove segments containing prefix. the following works because
// 1. the original `document.location.pathname` is absolute,
// hence first element of `segments` is always empty.
// 2. last element of splitting `path_to_root` is also always empty.
// 3. last element of `segments` is the file name.
//
// visual example:
//
// '/foo/bar/baz.html'.split('/') -> [ '', 'foo', 'bar', 'baz.html' ]
// '../'.split('/') -> [ '..', '' ]
//
// the following operations will then result in
//
// path = 'bar/baz.html'
//
segments.splice(0, segments.length - depth);
const path = segments.join('/');
// anchor starts with the hash character (`#`),
// but our redirect declarations don't, so we strip it.
// example:
// document.location.hash -> '#foo'
// document.location.hash.substring(1) -> 'foo'
const anchor = document.location.hash.substring(1);
const redirect = redirects[path];
if (redirect) {
const target = redirect[anchor];
if (target) {
document.location.href = target;
}
}

372
doc/manual/redirects.json Normal file
View File

@@ -0,0 +1,372 @@
{
"index.html": {
"part-advanced-topics": "advanced-topics/index.html",
"chap-tuning-cores-and-jobs": "advanced-topics/cores-vs-jobs.html",
"chap-diff-hook": "advanced-topics/diff-hook.html",
"check-dirs-are-unregistered": "advanced-topics/diff-hook.html#check-dirs-are-unregistered",
"chap-distributed-builds": "command-ref/conf-file.html#conf-builders",
"chap-post-build-hook": "advanced-topics/post-build-hook.html",
"chap-post-build-hook-caveats": "advanced-topics/post-build-hook.html#implementation-caveats",
"chap-writing-nix-expressions": "language/index.html",
"part-command-ref": "command-ref/index.html",
"conf-allow-import-from-derivation": "command-ref/conf-file.html#conf-allow-import-from-derivation",
"conf-allow-new-privileges": "command-ref/conf-file.html#conf-allow-new-privileges",
"conf-allowed-uris": "command-ref/conf-file.html#conf-allowed-uris",
"conf-allowed-users": "command-ref/conf-file.html#conf-allowed-users",
"conf-auto-optimise-store": "command-ref/conf-file.html#conf-auto-optimise-store",
"conf-binary-cache-public-keys": "command-ref/conf-file.html#conf-trusted-public-keys",
"conf-binary-caches": "command-ref/conf-file.html#conf-substituters",
"conf-build-compress-log": "command-ref/conf-file.html#conf-compress-build-log",
"conf-build-cores": "command-ref/conf-file.html#conf-cores",
"conf-build-extra-chroot-dirs": "command-ref/conf-file.html#conf-sandbox-paths",
"conf-build-extra-sandbox-paths": "command-ref/conf-file.html#conf-sandbox-paths",
"conf-build-fallback": "command-ref/conf-file.html#conf-fallback",
"conf-build-max-jobs": "command-ref/conf-file.html#conf-max-jobs",
"conf-build-max-log-size": "command-ref/conf-file.html#conf-max-build-log-size",
"conf-build-max-silent-time": "command-ref/conf-file.html#conf-max-silent-time",
"conf-build-timeout": "command-ref/conf-file.html#conf-timeout",
"conf-build-use-chroot": "command-ref/conf-file.html#conf-sandbox",
"conf-build-use-sandbox": "command-ref/conf-file.html#conf-sandbox",
"conf-build-use-substitutes": "command-ref/conf-file.html#conf-substitute",
"conf-build-users-group": "command-ref/conf-file.html#conf-build-users-group",
"conf-builders": "command-ref/conf-file.html#conf-builders",
"conf-builders-use-substitutes": "command-ref/conf-file.html#conf-builders-use-substitutes",
"conf-compress-build-log": "command-ref/conf-file.html#conf-compress-build-log",
"conf-connect-timeout": "command-ref/conf-file.html#conf-connect-timeout",
"conf-cores": "command-ref/conf-file.html#conf-cores",
"conf-diff-hook": "command-ref/conf-file.html#conf-diff-hook",
"conf-env-keep-derivations": "command-ref/conf-file.html#conf-keep-env-derivations",
"conf-extra-binary-caches": "command-ref/conf-file.html#conf-substituters",
"conf-extra-platforms": "command-ref/conf-file.html#conf-extra-platforms",
"conf-extra-sandbox-paths": "command-ref/conf-file.html#conf-sandbox-paths",
"conf-extra-substituters": "command-ref/conf-file.html#conf-substituters",
"conf-fallback": "command-ref/conf-file.html#conf-fallback",
"conf-fsync-metadata": "command-ref/conf-file.html#conf-fsync-metadata",
"conf-gc-keep-derivations": "command-ref/conf-file.html#conf-keep-derivations",
"conf-gc-keep-outputs": "command-ref/conf-file.html#conf-keep-outputs",
"conf-hashed-mirrors": "command-ref/conf-file.html#conf-hashed-mirrors",
"conf-http-connections": "command-ref/conf-file.html#conf-http-connections",
"conf-keep-build-log": "command-ref/conf-file.html#conf-keep-build-log",
"conf-keep-derivations": "command-ref/conf-file.html#conf-keep-derivations",
"conf-keep-env-derivations": "command-ref/conf-file.html#conf-keep-env-derivations",
"conf-keep-outputs": "command-ref/conf-file.html#conf-keep-outputs",
"conf-max-build-log-size": "command-ref/conf-file.html#conf-max-build-log-size",
"conf-max-free": "command-ref/conf-file.html#conf-max-free",
"conf-max-jobs": "command-ref/conf-file.html#conf-max-jobs",
"conf-max-silent-time": "command-ref/conf-file.html#conf-max-silent-time",
"conf-min-free": "command-ref/conf-file.html#conf-min-free",
"conf-narinfo-cache-negative-ttl": "command-ref/conf-file.html#conf-narinfo-cache-negative-ttl",
"conf-narinfo-cache-positive-ttl": "command-ref/conf-file.html#conf-narinfo-cache-positive-ttl",
"conf-netrc-file": "command-ref/conf-file.html#conf-netrc-file",
"conf-plugin-files": "command-ref/conf-file.html#conf-plugin-files",
"conf-post-build-hook": "command-ref/conf-file.html#conf-post-build-hook",
"conf-pre-build-hook": "command-ref/conf-file.html#conf-pre-build-hook",
"conf-require-sigs": "command-ref/conf-file.html#conf-require-sigs",
"conf-restrict-eval": "command-ref/conf-file.html#conf-restrict-eval",
"conf-run-diff-hook": "command-ref/conf-file.html#conf-run-diff-hook",
"conf-sandbox": "command-ref/conf-file.html#conf-sandbox",
"conf-sandbox-dev-shm-size": "command-ref/conf-file.html#conf-sandbox-dev-shm-size",
"conf-sandbox-paths": "command-ref/conf-file.html#conf-sandbox-paths",
"conf-secret-key-files": "command-ref/conf-file.html#conf-secret-key-files",
"conf-show-trace": "command-ref/conf-file.html#conf-show-trace",
"conf-stalled-download-timeout": "command-ref/conf-file.html#conf-stalled-download-timeout",
"conf-substitute": "command-ref/conf-file.html#conf-substitute",
"conf-substituters": "command-ref/conf-file.html#conf-substituters",
"conf-system": "command-ref/conf-file.html#conf-system",
"conf-system-features": "command-ref/conf-file.html#conf-system-features",
"conf-tarball-ttl": "command-ref/conf-file.html#conf-tarball-ttl",
"conf-timeout": "command-ref/conf-file.html#conf-timeout",
"conf-trace-function-calls": "command-ref/conf-file.html#conf-trace-function-calls",
"conf-trusted-binary-caches": "command-ref/conf-file.html#conf-trusted-substituters",
"conf-trusted-public-keys": "command-ref/conf-file.html#conf-trusted-public-keys",
"conf-trusted-substituters": "command-ref/conf-file.html#conf-trusted-substituters",
"conf-trusted-users": "command-ref/conf-file.html#conf-trusted-users",
"extra-sandbox-paths": "command-ref/conf-file.html#conf-sandbox-paths",
"sec-conf-file": "command-ref/conf-file.html",
"env-NIX_PATH": "command-ref/env-common.html#env-NIX_PATH",
"env-common": "command-ref/env-common.html",
"envar-remote": "command-ref/env-common.html#env-NIX_REMOTE",
"sec-common-env": "command-ref/env-common.html",
"ch-files": "command-ref/files.html",
"ch-main-commands": "command-ref/main-commands.html",
"opt-out-link": "command-ref/nix-build.html#opt-out-link",
"sec-nix-build": "command-ref/nix-build.html",
"sec-nix-channel": "command-ref/nix-channel.html",
"sec-nix-collect-garbage": "command-ref/nix-collect-garbage.html",
"sec-nix-copy-closure": "command-ref/nix-copy-closure.html",
"sec-nix-daemon": "command-ref/nix-daemon.html",
"refsec-nix-env-install-examples": "command-ref/nix-env/install.html#examples",
"rsec-nix-env-install": "command-ref/nix-env/install.html",
"rsec-nix-env-set": "command-ref/nix-env/set.html",
"rsec-nix-env-set-flag": "command-ref/nix-env/set-flag.html",
"rsec-nix-env-upgrade": "command-ref/nix-env/upgrade.html",
"sec-nix-env": "command-ref/nix-env.html",
"ssec-version-comparisons": "command-ref/nix-env.html#selectors",
"sec-nix-hash": "command-ref/nix-hash.html",
"sec-nix-instantiate": "command-ref/nix-instantiate.html",
"sec-nix-prefetch-url": "command-ref/nix-prefetch-url.html",
"sec-nix-shell": "command-ref/nix-shell.html",
"ssec-nix-shell-shebang": "command-ref/nix-shell.html#use-as-a--interpreter",
"nixref-queries": "command-ref/nix-store/query.html#queries",
"opt-add-root": "command-ref/nix-store/query.html#opt-add-root",
"refsec-nix-store-dump": "command-ref/nix-store/dump.html",
"refsec-nix-store-export": "command-ref/nix-store/export.html",
"refsec-nix-store-import": "command-ref/nix-store/import.html",
"refsec-nix-store-query": "command-ref/nix-store/query.html",
"refsec-nix-store-verify": "command-ref/nix-store/verify.html",
"rsec-nix-store-gc": "command-ref/nix-store/gc.html",
"rsec-nix-store-generate-binary-cache-key": "command-ref/nix-store/generate-binary-cache-key.html",
"rsec-nix-store-realise": "command-ref/nix-store/realise.html",
"rsec-nix-store-serve": "command-ref/nix-store/serve.html",
"sec-nix-store": "command-ref/nix-store.html",
"opt-I": "command-ref/opt-common.html#opt-I",
"opt-attr": "command-ref/opt-common.html#opt-attr",
"opt-common": "command-ref/opt-common.html",
"opt-cores": "command-ref/opt-common.html#opt-cores",
"opt-log-format": "command-ref/opt-common.html#opt-log-format",
"opt-max-jobs": "command-ref/opt-common.html#opt-max-jobs",
"opt-max-silent-time": "command-ref/opt-common.html#opt-max-silent-time",
"opt-timeout": "command-ref/opt-common.html#opt-timeout",
"sec-common-options": "command-ref/opt-common.html",
"ch-utilities": "command-ref/utilities.html",
"chap-hacking": "development/building.html",
"adv-attr-allowSubstitutes": "language/advanced-attributes.html#adv-attr-allowSubstitutes",
"adv-attr-allowedReferences": "language/advanced-attributes.html#adv-attr-allowedReferences",
"adv-attr-allowedRequisites": "language/advanced-attributes.html#adv-attr-allowedRequisites",
"adv-attr-disallowedReferences": "language/advanced-attributes.html#adv-attr-disallowedReferences",
"adv-attr-disallowedRequisites": "language/advanced-attributes.html#adv-attr-disallowedRequisites",
"adv-attr-exportReferencesGraph": "language/advanced-attributes.html#adv-attr-exportReferencesGraph",
"adv-attr-impureEnvVars": "language/advanced-attributes.html#adv-attr-impureEnvVars",
"adv-attr-outputHash": "language/advanced-attributes.html#adv-attr-outputHash",
"adv-attr-outputHashAlgo": "language/advanced-attributes.html#adv-attr-outputHashAlgo",
"adv-attr-outputHashMode": "language/advanced-attributes.html#adv-attr-outputHashMode",
"adv-attr-passAsFile": "language/advanced-attributes.html#adv-attr-passAsFile",
"adv-attr-preferLocalBuild": "language/advanced-attributes.html#adv-attr-preferLocalBuild",
"fixed-output-drvs": "language/advanced-attributes.html#adv-attr-outputHash",
"sec-advanced-attributes": "language/advanced-attributes.html",
"builtin-abort": "language/builtins.html#builtins-abort",
"builtin-add": "language/builtins.html#builtins-add",
"builtin-all": "language/builtins.html#builtins-all",
"builtin-any": "language/builtins.html#builtins-any",
"builtin-attrNames": "language/builtins.html#builtins-attrNames",
"builtin-attrValues": "language/builtins.html#builtins-attrValues",
"builtin-baseNameOf": "language/builtins.html#builtins-baseNameOf",
"builtin-bitAnd": "language/builtins.html#builtins-bitAnd",
"builtin-bitOr": "language/builtins.html#builtins-bitOr",
"builtin-bitXor": "language/builtins.html#builtins-bitXor",
"builtin-builtins": "language/builtins.html#builtins-builtins",
"builtin-compareVersions": "language/builtins.html#builtins-compareVersions",
"builtin-concatLists": "language/builtins.html#builtins-concatLists",
"builtin-concatStringsSep": "language/builtins.html#builtins-concatStringsSep",
"builtin-currentSystem": "language/builtins.html#builtins-currentSystem",
"builtin-deepSeq": "language/builtins.html#builtins-deepSeq",
"builtin-derivation": "language/builtins.html#builtins-derivation",
"builtin-dirOf": "language/builtins.html#builtins-dirOf",
"builtin-div": "language/builtins.html#builtins-div",
"builtin-elem": "language/builtins.html#builtins-elem",
"builtin-elemAt": "language/builtins.html#builtins-elemAt",
"builtin-fetchGit": "language/builtins.html#builtins-fetchGit",
"builtin-fetchTarball": "language/builtins.html#builtins-fetchTarball",
"builtin-fetchurl": "language/builtins.html#builtins-fetchurl",
"builtin-filterSource": "language/builtins.html#builtins-filterSource",
"builtin-foldl-prime": "language/builtins.html#builtins-foldl'",
"builtin-fromJSON": "language/builtins.html#builtins-fromJSON",
"builtin-functionArgs": "language/builtins.html#builtins-functionArgs",
"builtin-genList": "language/builtins.html#builtins-genList",
"builtin-getAttr": "language/builtins.html#builtins-getAttr",
"builtin-getEnv": "language/builtins.html#builtins-getEnv",
"builtin-hasAttr": "language/builtins.html#builtins-hasAttr",
"builtin-hashFile": "language/builtins.html#builtins-hashFile",
"builtin-hashString": "language/builtins.html#builtins-hashString",
"builtin-head": "language/builtins.html#builtins-head",
"builtin-import": "language/builtins.html#builtins-import",
"builtin-intersectAttrs": "language/builtins.html#builtins-intersectAttrs",
"builtin-isAttrs": "language/builtins.html#builtins-isAttrs",
"builtin-isBool": "language/builtins.html#builtins-isBool",
"builtin-isFloat": "language/builtins.html#builtins-isFloat",
"builtin-isFunction": "language/builtins.html#builtins-isFunction",
"builtin-isInt": "language/builtins.html#builtins-isInt",
"builtin-isList": "language/builtins.html#builtins-isList",
"builtin-isNull": "language/builtins.html#builtins-isNull",
"builtin-isString": "language/builtins.html#builtins-isString",
"builtin-length": "language/builtins.html#builtins-length",
"builtin-lessThan": "language/builtins.html#builtins-lessThan",
"builtin-listToAttrs": "language/builtins.html#builtins-listToAttrs",
"builtin-map": "language/builtins.html#builtins-map",
"builtin-match": "language/builtins.html#builtins-match",
"builtin-mul": "language/builtins.html#builtins-mul",
"builtin-parseDrvName": "language/builtins.html#builtins-parseDrvName",
"builtin-path": "language/builtins.html#builtins-path",
"builtin-pathExists": "language/builtins.html#builtins-pathExists",
"builtin-placeholder": "language/builtins.html#builtins-placeholder",
"builtin-readDir": "language/builtins.html#builtins-readDir",
"builtin-readFile": "language/builtins.html#builtins-readFile",
"builtin-removeAttrs": "language/builtins.html#builtins-removeAttrs",
"builtin-replaceStrings": "language/builtins.html#builtins-replaceStrings",
"builtin-seq": "language/builtins.html#builtins-seq",
"builtin-sort": "language/builtins.html#builtins-sort",
"builtin-split": "language/builtins.html#builtins-split",
"builtin-splitVersion": "language/builtins.html#builtins-splitVersion",
"builtin-stringLength": "language/builtins.html#builtins-stringLength",
"builtin-sub": "language/builtins.html#builtins-sub",
"builtin-substring": "language/builtins.html#builtins-substring",
"builtin-tail": "language/builtins.html#builtins-tail",
"builtin-throw": "language/builtins.html#builtins-throw",
"builtin-toFile": "language/builtins.html#builtins-toFile",
"builtin-toJSON": "language/builtins.html#builtins-toJSON",
"builtin-toPath": "language/builtins.html#builtins-toPath",
"builtin-toString": "language/builtins.html#builtins-toString",
"builtin-toXML": "language/builtins.html#builtins-toXML",
"builtin-trace": "language/builtins.html#builtins-trace",
"builtin-tryEval": "language/builtins.html#builtins-tryEval",
"builtin-typeOf": "language/builtins.html#builtins-typeOf",
"ssec-builtins": "language/builtins.html",
"attr-system": "language/derivations.html#attr-system",
"ssec-derivation": "language/derivations.html",
"ch-expression-language": "language/index.html",
"sec-constructs": "language/syntax.html",
"sect-let-language": "language/syntax.html#let-expressions",
"ss-functions": "language/syntax.html#functions",
"sec-language-operators": "language/operators.html",
"table-operators": "language/operators.html",
"ssec-values": "language/types.html",
"gloss-closure": "glossary.html#gloss-closure",
"gloss-derivation": "glossary.html#gloss-derivation",
"gloss-deriver": "glossary.html#gloss-deriver",
"gloss-nar": "glossary.html#gloss-nar",
"gloss-output-path": "glossary.html#gloss-output-path",
"gloss-profile": "glossary.html#gloss-profile",
"gloss-reachable": "glossary.html#gloss-reachable",
"gloss-reference": "glossary.html#gloss-reference",
"gloss-substitute": "glossary.html#gloss-substitute",
"gloss-user-env": "glossary.html#gloss-user-env",
"gloss-validity": "glossary.html#gloss-validity",
"part-glossary": "glossary.html",
"sec-building-source": "installation/building-source.html",
"ch-env-variables": "installation/env-variables.html",
"sec-installer-proxy-settings": "installation/env-variables.html#proxy-environment-variables",
"sec-nix-ssl-cert-file": "installation/env-variables.html#nix_ssl_cert_file",
"sec-nix-ssl-cert-file-with-nix-daemon-and-macos": "installation/env-variables.html#nix_ssl_cert_file",
"chap-installation": "installation/index.html",
"ch-installing-binary": "installation/installing-binary.html",
"sect-macos-installation": "installation/installing-binary.html#macos-installation",
"sect-macos-installation-change-store-prefix": "installation/installing-binary.html#macos-installation",
"sect-macos-installation-encrypted-volume": "installation/installing-binary.html#macos-installation",
"sect-macos-installation-recommended-notes": "installation/installing-binary.html#macos-installation",
"sect-macos-installation-symlink": "installation/installing-binary.html#macos-installation",
"sect-multi-user-installation": "installation/installing-binary.html#multi-user-installation",
"sect-nix-install-binary-tarball": "installation/installing-binary.html#installing-from-a-binary-tarball",
"sect-nix-install-pinned-version-url":
"installation/installing-binary.html#installing-a-pinned-nix-version-from-a-url",
"sect-single-user-installation": "installation/installing-binary.html#single-user-installation",
"ch-installing-source": "installation/installing-source.html",
"ssec-multi-user": "installation/multi-user.html",
"ch-nix-security": "installation/nix-security.html",
"sec-obtaining-source": "installation/obtaining-source.html",
"sec-prerequisites-source": "installation/prerequisites-source.html",
"sec-single-user": "installation/single-user.html",
"ch-supported-platforms": "installation/supported-platforms.html",
"ch-upgrading-nix": "installation/upgrading.html",
"ch-about-nix": "introduction.html",
"chap-introduction": "introduction.html",
"ch-basic-package-mgmt": "package-management/index.html",
"ssec-binary-cache-substituter": "package-management/binary-cache-substituter.html",
"sec-channels": "command-ref/nix-channel.html",
"ssec-copy-closure": "command-ref/nix-copy-closure.html",
"sec-garbage-collection": "package-management/garbage-collection.html",
"ssec-gc-roots": "package-management/garbage-collector-roots.html",
"chap-package-management": "package-management/index.html",
"sec-profiles": "package-management/profiles.html",
"ssec-s3-substituter": "store/types/s3-binary-cache-store.html",
"ssec-s3-substituter-anonymous-reads":
"store/types/s3-binary-cache-store.html#anonymous-reads-to-your-s3-compatible-binary-cache",
"ssec-s3-substituter-authenticated-reads":
"store/types/s3-binary-cache-store.html#authenticated-reads-to-your-s3-binary-cache",
"ssec-s3-substituter-authenticated-writes":
"store/types/s3-binary-cache-store.html#authenticated-writes-to-your-s3-compatible-binary-cache",
"sec-sharing-packages": "package-management/sharing-packages.html",
"ssec-ssh-substituter": "package-management/ssh-substituter.html",
"chap-quick-start": "quick-start.html",
"sec-relnotes": "release-notes/index.html",
"ch-relnotes-0.10.1": "release-notes/rl-0.10.1.html",
"ch-relnotes-0.10": "release-notes/rl-0.10.html",
"ssec-relnotes-0.11": "release-notes/rl-0.11.html",
"ssec-relnotes-0.12": "release-notes/rl-0.12.html",
"ssec-relnotes-0.13": "release-notes/rl-0.13.html",
"ssec-relnotes-0.14": "release-notes/rl-0.14.html",
"ssec-relnotes-0.15": "release-notes/rl-0.15.html",
"ssec-relnotes-0.16": "release-notes/rl-0.16.html",
"ch-relnotes-0.5": "release-notes/rl-0.5.html",
"ch-relnotes-0.6": "release-notes/rl-0.6.html",
"ch-relnotes-0.7": "release-notes/rl-0.7.html",
"ch-relnotes-0.8.1": "release-notes/rl-0.8.1.html",
"ch-relnotes-0.8": "release-notes/rl-0.8.html",
"ch-relnotes-0.9.1": "release-notes/rl-0.9.1.html",
"ch-relnotes-0.9.2": "release-notes/rl-0.9.2.html",
"ch-relnotes-0.9": "release-notes/rl-0.9.html",
"ssec-relnotes-1.0": "release-notes/rl-1.0.html",
"ssec-relnotes-1.1": "release-notes/rl-1.1.html",
"ssec-relnotes-1.10": "release-notes/rl-1.10.html",
"ssec-relnotes-1.11.10": "release-notes/rl-1.11.10.html",
"ssec-relnotes-1.11": "release-notes/rl-1.11.html",
"ssec-relnotes-1.2": "release-notes/rl-1.2.html",
"ssec-relnotes-1.3": "release-notes/rl-1.3.html",
"ssec-relnotes-1.4": "release-notes/rl-1.4.html",
"ssec-relnotes-1.5.1": "release-notes/rl-1.5.html",
"ssec-relnotes-1.5.2": "release-notes/rl-1.5.2.html",
"ssec-relnotes-1.5": "release-notes/rl-1.5.html",
"ssec-relnotes-1.6.1": "release-notes/rl-1.6.1.html",
"ssec-relnotes-1.6.0": "release-notes/rl-1.6.html",
"ssec-relnotes-1.7": "release-notes/rl-1.7.html",
"ssec-relnotes-1.8": "release-notes/rl-1.8.html",
"ssec-relnotes-1.9": "release-notes/rl-1.9.html",
"ssec-relnotes-2.0": "release-notes/rl-2.0.html",
"ssec-relnotes-2.1": "release-notes/rl-2.1.html",
"ssec-relnotes-2.2": "release-notes/rl-2.2.html",
"ssec-relnotes-2.3": "release-notes/rl-2.3.html"
},
"language/types.html": {
"simple-values": "#primitives",
"lists": "#type-list",
"strings": "#type-string",
"attribute-sets": "#type-attrs",
"type-number": "#type-int"
},
"language/syntax.html": {
"scoping-rules": "scope.html",
"string-literal": "string-literals.html"
},
"language/derivations.html": {
"builder-execution": "../store/building.html#builder-execution"
},
"installation/installing-binary.html": {
"linux": "uninstall.html#linux",
"macos": "uninstall.html#macos",
"uninstalling": "uninstall.html"
},
"development/building.html": {
"nix-with-flakes": "#building-nix-with-flakes",
"classic-nix": "#building-nix",
"running-tests": "testing.html#running-tests",
"unit-tests": "testing.html#unit-tests",
"functional-tests": "testing.html#functional-tests",
"debugging-failing-functional-tests": "testing.html#debugging-failing-functional-tests",
"integration-tests": "testing.html#integration-tests",
"installer-tests": "testing.html#installer-tests",
"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",
"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": {
"gloss-local-store": "store/types/local-store.html",
"package-attribute-set": "#package",
"gloss-chroot-store": "store/types/local-store.html",
"gloss-content-addressed-derivation": "#gloss-content-addressing-derivation"
}
}

40
doc/manual/render-manpage.sh Executable file → Normal file
View File

@@ -1,25 +1,55 @@
#!/usr/bin/env bash
#
# Standalone manpage renderer that doesn't require mdbook.
# Uses expand-includes.py to preprocess markdown, then lowdown to generate manpages.
set -euo pipefail
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
lowdown_args=
# Optional --out-no-smarty flag for compatibility with nix_nested_manpages
if [ "$1" = --out-no-smarty ]; then
lowdown_args=--out-no-smarty
shift
fi
[ "$#" = 4 ] || {
echo "wrong number of args passed" >&2
[ "$#" = 7 ] || {
cat >&2 <<EOF
Usage: $0 [--out-no-smarty] <title> <section> <source-root> <generated-root> <doc-url> <infile> <outfile>
Arguments:
title - Manpage title (e.g., "nix-env --install")
section - Manpage section number (1, 5, 8, etc.)
source-root - Root directory of markdown sources
generated-root - Root directory of generated markdown files
doc-url - Base URL for documentation links
infile - Input markdown file (relative to build directory)
outfile - Output manpage file
Examples:
$0 "nix-store --query" 1 doc/manual/source build/doc/manual/source \\
https://nix.dev/manual/nix/latest \\
build/doc/manual/source/command-ref/nix-store/query.md nix-store-query.1
EOF
exit 1
}
title="$1"
section="$2"
infile="$3"
outfile="$4"
source_root="$3"
generated_root="$4"
doc_url="$5"
infile="$6"
outfile="$7"
# Expand includes and pipe to lowdown
(
printf "Title: %s\n\n" "$title"
cat "$infile"
python3 "$script_dir/expand-includes.py" \
--source-root "$source_root" \
--generated-root "$generated_root" \
--doc-url "$doc_url" \
"$infile"
) | lowdown -sT man --nroff-nolinks $lowdown_args -M section="$section" -o "$outfile"

View File

@@ -1,9 +0,0 @@
---
synopsis: Channel URLs migrated to channels.nixos.org subdomain
prs: [14518]
issues: [14517]
---
Channel URLs have been updated from `https://nixos.org/channels/` to `https://channels.nixos.org/` throughout Nix.
The subdomain provides better reliability with IPv6 support and improved CDN distribution. The old domain apex (`nixos.org/channels/`) currently redirects to the new location but may be deprecated in the future.

View File

@@ -1,55 +0,0 @@
---
synopsis: "JSON format changes for store path info and derivations"
prs: []
issues: []
---
JSON formats for store path info and derivations have been updated with new versions and structured fields.
## Store Path Info JSON (Version 2)
The store path info JSON format has been updated from version 1 to version 2:
- **Added `version` field**:
All store path info JSON now includes `"version": 2`.
- **Structured `ca` field**:
Content address is now a structured JSON object instead of a string:
- Old: `"ca": "fixed:r:sha256:1abc..."`
- New: `"ca": {"method": "nar", "hash": {"algorithm": "sha256", "format": "base64", "hash": "EMIJ+giQ..."}}`
- Still `null` values for input-addressed store objects
- **Structured hash fields**:
Hash values (`narHash` and `downloadHash`) are now structured JSON objects instead of strings:
- Old: `"narHash": "sha256:FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="`
- New: `"narHash": {"algorithm": "sha256", "format": "base64", "hash": "FePFYIlM..."}`
- Same structure applies to `downloadHash` in NAR info contexts
Nix currently only produces, and doesn't consume this format.
**Affected command**: `nix path-info --json`
## Derivation JSON (Version 4)
The derivation JSON format has been updated from version 3 to version 4:
- **Restructured inputs**:
Inputs are now nested under an `inputs` object:
- Old: `"inputSrcs": [...], "inputDrvs": {...}`
- New: `"inputs": {"srcs": [...], "drvs": {...}}`
- **Consistent content addresses**:
Floating content-addressed outputs now use structured JSON format.
This is the same format as `ca` in in store path info (after the new version).
Version 3 and earlier formats are *not* accepted when reading.
**Affected command**: `nix derivation`, namely it's `show` and `add` sub-commands.

View File

@@ -1,40 +0,0 @@
---
synopsis: "Improved S3 binary cache support via HTTP"
prs: [13752, 13823, 14026, 14120, 14131, 14135, 14144, 14170, 14190, 14198, 14206, 14209, 14222, 14223, 14330, 14333, 14335, 14336, 14337, 14350, 14356, 14357, 14374, 14375, 14376, 14377, 14391, 14393, 14420, 14421]
issues: [13084, 12671, 11748, 12403]
---
S3 binary cache operations now happen via HTTP, leveraging `libcurl`'s native
AWS SigV4 authentication instead of the AWS C++ SDK, providing significant
improvements:
- **Reduced memory usage**: Eliminates memory buffering issues that caused
segfaults with large files
- **Fixed upload reliability**: Resolves AWS SDK chunking errors
(`InvalidChunkSizeError`)
- **Lighter dependencies**: Uses lightweight `aws-crt-cpp` instead of full
`aws-cpp-sdk`, reducing build complexity
The new implementation requires curl >= 7.75.0 and `aws-crt-cpp` for credential
management.
All existing S3 URL formats and parameters remain supported, however the store
settings for configuring multipart uploads have changed:
- **`multipart-upload`** (default: `false`): Enable multipart uploads for large
files. When enabled, files exceeding the multipart threshold will be uploaded
in multiple parts.
- **`multipart-threshold`** (default: `100 MiB`): Minimum file size for using
multipart uploads. Files smaller than this will use regular PUT requests.
Only takes effect when `multipart-upload` is enabled.
- **`multipart-chunk-size`** (default: `5 MiB`): Size of each part in multipart
uploads. Must be at least 5 MiB (AWS S3 requirement). Larger chunk sizes
reduce the number of requests but use more memory.
- **`buffer-size`**: Has been replaced by `multipart-chunk-size` and is now an alias to it.
Note that this change also means Nix now supports S3 binary cache stores even
if built without `aws-crt-cpp`, but only for public buckets which do not
require authentication.

View File

@@ -1,14 +0,0 @@
---
synopsis: "S3 URLs now support object versioning via versionId parameter"
prs: [14274]
issues: [13955]
---
S3 URLs now support a `versionId` query parameter to fetch specific versions
of objects from S3 buckets with versioning enabled. This allows pinning to
exact object versions for reproducibility and protection against unexpected
changes:
```
s3://bucket/key?region=us-east-1&versionId=abc123def456
```

View File

@@ -1,21 +0,0 @@
---
synopsis: "S3 binary cache stores now support storage class configuration"
prs: [14464]
issues: [7015]
---
S3 binary cache stores now support configuring the storage class for uploaded objects via the `storage-class` parameter. This allows users to optimize costs by selecting appropriate storage tiers based on access patterns.
Example usage:
```bash
# Use Glacier storage for long-term archival
nix copy --to 's3://my-bucket?storage-class=GLACIER' /nix/store/...
# Use Intelligent Tiering for automatic cost optimization
nix copy --to 's3://my-bucket?storage-class=INTELLIGENT_TIERING' /nix/store/...
```
The storage class applies to both regular uploads and multipart uploads. When not specified, objects use the bucket's default storage class.
See the [S3 storage classes documentation](https://docs.aws.amazon.com/AmazonS3/latest/userguide/storage-class-intro.html) for available storage classes and their characteristics.

View File

@@ -121,14 +121,17 @@
- [Architecture and Design](architecture/architecture.md)
- [Formats and Protocols](protocols/index.md)
- [JSON Formats](protocols/json/index.md)
- [File System Object](protocols/json/file-system-object.md)
- [Hash](protocols/json/hash.md)
- [Content Address](protocols/json/content-address.md)
- [Store Path](protocols/json/store-path.md)
- [Store Object Info](protocols/json/store-object-info.md)
- [Derivation](protocols/json/derivation.md)
- [Derivation](protocols/json/derivation/index.md)
- [Derivation Options](protocols/json/derivation/options.md)
- [Deriving Path](protocols/json/deriving-path.md)
- [Build Trace Entry](protocols/json/build-trace-entry.md)
- [Build Result](protocols/json/build-result.md)
- [Store](protocols/json/store.md)
- [Serving Tarball Flakes](protocols/tarball-fetcher.md)
- [Store Path Specification](protocols/store-path.md)
- [Nix Archive (NAR) Format](protocols/nix-archive/index.md)
@@ -148,6 +151,7 @@
- [Contributing](development/contributing.md)
- [Releases](release-notes/index.md)
{{#include ./SUMMARY-rl-next.md}}
- [Release 2.33 (2025-12-09)](release-notes/rl-2.33.md)
- [Release 2.32 (2025-10-06)](release-notes/rl-2.32.md)
- [Release 2.31 (2025-08-21)](release-notes/rl-2.31.md)
- [Release 2.30 (2025-07-07)](release-notes/rl-2.30.md)

View File

@@ -34,7 +34,7 @@ md5sum`.
Print the cryptographic hash of the contents of each regular file *path*.
That is, instead of computing
the hash of the [Nix Archive (NAR)](@docroot@/store/file-system-object/content-address.md#serial-nix-archive) of *path*,
just [directly hash]((@docroot@/store/file-system-object/content-address.md#serial-flat) *path* as is.
just [directly hash](@docroot@/store/file-system-object/content-address.md#serial-flat) *path* as is.
This requires *path* to resolve to a regular file rather than directory.
The result is identical to that produced by the GNU commands
`md5sum` and `sha1sum`.

View File

@@ -15,7 +15,7 @@ In the development shell, set the `mesonBuildType` environment variable to `debu
Then, proceed to build Nix as described in [Building Nix](./building.md).
This will build Nix with debug symbols, which are essential for effective debugging.
It is also possible to build without debugging for faster build:
It is also possible to build without optimization for faster build:
```console
[nix-shell]$ NIX_HARDENING_ENABLE=$(printLines $NIX_HARDENING_ENABLE | grep -v fortify)

View File

@@ -137,6 +137,12 @@ $ _NIX_TEST_ACCEPT=1 meson test nix-store-tests -v
will regenerate the "golden master" expected result for the `libnixstore` characterisation tests.
The characterisation tests will mark themselves "skipped" since they regenerated the expected result instead of actually testing anything.
### JSON Schema testing
In `doc/manual/source/protocols/json/` we have a number of manual pages generated from [JSON Schema](https://json-schema.org/).
That JSON schema is tested against the JSON file test data used in [characterisation tests](#characterisation-testing-unit ) for JSON (de)serialization, in `src/json-schema-checks`.
Between the JSON (de)serialization testing, and this testing of the same data against the schema, we make sure that the manual, the implementation, and a machine-readable schema are are all in sync.
### Unit test support libraries
There are headers and code which are not just used to test the library in question, but also downstream libraries.

View File

@@ -23,7 +23,7 @@ Some built-ins are also exposed directly in the global scope:
- [`null`](#builtins-null)
- [`placeholder`](#builtins-placeholder)
- [`removeAttrs`](#builtins-removeAttrs)
- `scopedImport`
- [`scopedImport`](#builtins-scopedImport)
- [`throw`](#builtins-throw)
- [`toString`](#builtins-toString)
- [`true`](#builtins-true)

View File

@@ -74,4 +74,48 @@ in f { x = throw "error"; y = throw "error"; }
=> "ok"
```
## Evaluation order
The order in which expressions are evaluated is generally unspecified, because it does not affect successful evaluation outcomes.
This allows more freedom for the evaluator to evolve and to evaluate efficiently.
Data dependencies naturally impose some ordering constraints: a value cannot be used before it is computed.
Beyond these constraints, the evaluator is free to choose any order.
The order in which side effects such as [`builtins.trace`](@docroot@/language/builtins.md#builtins-trace) output occurs is not defined, but may be expected to follow data dependencies. <!-- we may want to be more specific about this. -->
In a lazy language, evaluation order is often opposite to expectations from strict languages.
For example, in `let wrap = x: { wrapped = x; }; in wrap (1 + 2)`, the function body produces a result (`{ wrapped = ...; }`) *before* evaluating `x`.
## Infinite recursion and stack overflow
During evaluation, two types of errors can occur when expressions reference themselves or call functions too deeply:
### Infinite recursion
This error occurs when a value depends on itself through a cycle, making it impossible to compute.
```nix
let x = x; in x
=> error: infinite recursion encountered
```
Infinite recursion happens at the value level when evaluating an expression requires evaluating the same expression again.
Despite the name, infinite recursion is cheap to compute and does not involve a stack overflow.
The cycle is finite and fairly easy to detect.
### Stack overflow
This error occurs when the call depth exceeds the maximum allowed limit.
```nix
let f = x: f (x + 1);
in f 0
=> error: stack overflow; max-call-depth exceeded
```
Stack overflow happens when too many function calls are nested without returning.
The maximum call depth is controlled by the [`max-call-depth` setting](@docroot@/command-ref/conf-file.md#conf-max-call-depth).
[C API]: @docroot@/c-api.md

View File

@@ -23,8 +23,8 @@
| [Greater than or equal to][Comparison] | *expr* `>=` *expr* | none | 10 |
| [Equality] | *expr* `==` *expr* | none | 11 |
| Inequality | *expr* `!=` *expr* | none | 11 |
| Logical conjunction (`AND`) | *bool* `&&` *bool* | left | 12 |
| Logical disjunction (`OR`) | *bool* <code>\|\|</code> *bool* | left | 13 |
| [Logical conjunction] (`AND`) | *bool* `&&` *bool* | left | [12](#precedence-and-disjunctive-normal-form) |
| [Logical disjunction] (`OR`) | *bool* <code>\|\|</code> *bool* | left | [13](#precedence-and-disjunctive-normal-form) |
| [Logical implication] | *bool* `->` *bool* | right | 14 |
| [Pipe operator] (experimental) | *expr* `\|>` *func* | left | 15 |
| [Pipe operator] (experimental) | *func* `<\|` *expr* | right | 15 |
@@ -162,6 +162,9 @@ Update [attribute set] *attrset1* with names and values from *attrset2*.
The returned attribute set will have all of the attributes in *attrset1* and *attrset2*.
If an attribute name is present in both, the attribute value from the latter is taken.
This operator is [strict](@docroot@/language/evaluation.md#strictness) in both *attrset1* and *attrset2*.
That means that both arguments are evaluated to [weak head normal form](@docroot@/language/evaluation.md#values), so the attribute sets themselves are evaluated, but their attribute values are not evaluated.
[Update]: #update
## Comparison
@@ -185,18 +188,95 @@ All comparison operators are implemented in terms of `<`, and the following equi
## Equality
- [Attribute sets][attribute set] and [lists][list] are compared recursively, and therefore are fully evaluated.
- Comparison of [functions][function] always returns `false`.
- [Attribute sets][attribute set] are compared first by attribute names and then by items until a difference is found.
- [Lists][list] are compared first by length and then by items until a difference is found.
- Comparison of distinct [functions][function] returns `false`, but identical functions may be subject to [value identity optimization](#value-identity-optimization).
- Numbers are type-compatible, see [arithmetic] operators.
- Floating point numbers only differ up to a limited precision.
The `==` operator is [strict](@docroot@/language/evaluation.md#strictness) in both arguments; when comparing composite types ([attribute sets][attribute set] and [lists][list]), it is partially strict in their contained values: they are evaluated until a difference is found. <!-- this is woefully underspecified, affecting which expressions evaluate correctly; not just "ordering" or error messages. -->
### Value identity optimization
Nix performs equality comparisons of nested values by pointer equality or more abstractly, _identity_.
Nix semantics ideally do not assign a unique identity to values as they are created, but equality is an exception to this rule.
The disputable benefit of this is that it is more efficient, and it allows cyclical structures to be compared, e.g. `let x = { x = x; }; in x == x` evaluates to `true`.
However, as a consequence, it makes a function equal to itself when the comparison is made in a list or attribute set, in contradiction to a simple direct comparison.
[function]: ./syntax.md#functions
[Equality]: #equality
## Logical conjunction
> **Syntax**
>
> *bool1* `&&` *bool2*
Logical AND. Equivalent to `if` *bool1* `then` *bool2* `else false`.
This operator is [strict](@docroot@/language/evaluation.md#strictness) in *bool1*, but only evaluates *bool2* if *bool1* is `true`.
> **Example**
>
> ```nix
> true && false
> => false
>
> false && throw "never evaluated"
> => false
> ```
[Logical conjunction]: #logical-conjunction
## Logical disjunction
> **Syntax**
>
> *bool1* `||` *bool2*
Logical OR. Equivalent to `if` *bool1* `then true` `else` *bool2*.
This operator is [strict](@docroot@/language/evaluation.md#strictness) in *bool1*, but only evaluates *bool2* if *bool1* is `false`.
> **Example**
>
> ```nix
> true || false
> => true
>
> true || throw "never evaluated"
> => true
> ```
[Logical disjunction]: #logical-disjunction
### Precedence and disjunctive normal form
The precedence of `&&` and `||` aligns with disjunctive normal form.
Without parentheses, an expression describes multiple "permissible situations" (connected by `||`), where each situation consists of multiple simultaneous conditions (connected by `&&`).
For example, `A || B && C || D && E` is parsed as `A || (B && C) || (D && E)`, describing three permissible situations: A holds, or both B and C hold, or both D and E hold.
## Logical implication
Equivalent to `!`*b1* `||` *b2* (or `if` *b1* `then` *b2* `else true`)
> **Syntax**
>
> *bool1* `->` *bool2*
Logical implication. Equivalent to `!`*bool1* `||` *bool2* (or `if` *bool1* `then` *bool2* `else true`).
This operator is [strict](@docroot@/language/evaluation.md#strictness) in *bool1*, but only evaluates *bool2* if *bool1* is `true`.
> **Example**
>
> ```nix
> true -> false
> => false
>
> false -> throw "never evaluated"
> => true
> ```
[Logical implication]: #logical-implication

View File

@@ -1,7 +0,0 @@
{{#include derivation-v4-fixed.md}}
<!-- need to convert YAML to JSON first
## Raw Schema
[JSON Schema for Derivation v3](schema/derivation-v4.json)
-->

View File

@@ -0,0 +1,7 @@
{{#include ../derivation-v4-fixed.md}}
<!-- need to convert YAML to JSON first
## Raw Schema
[JSON Schema for Derivation v4](schema/derivation-v4.json)
-->

View File

@@ -0,0 +1,49 @@
{{#include ../derivation-options-v1-fixed.md}}
## Examples
### Input-addressed derivations
#### Default options
```json
{{#include ../schema/derivation-options-v1/ia/derivation-options/defaults.json}}
```
#### All options set
```json
{{#include ../schema/derivation-options-v1/ia/derivation-options/all_set.json}}
```
#### Default options (structured attributes)
```json
{{#include ../schema/derivation-options-v1/ia/derivation-options/structuredAttrs_defaults.json}}
```
#### All options set (structured attributes)
```json
{{#include ../schema/derivation-options-v1/ia/derivation-options/structuredAttrs_all_set.json}}
```
### Content-addressed derivations
#### All options set
```json
{{#include ../schema/derivation-options-v1/ca/derivation-options/all_set.json}}
```
#### All options set (structured attributes)
```json
{{#include ../schema/derivation-options-v1/ca/derivation-options/structuredAttrs_all_set.json}}
```
<!-- need to convert YAML to JSON first
## Raw Schema
[JSON Schema for Derivation Options v1](schema/derivation-options-v1.json)
-->

View File

@@ -0,0 +1,21 @@
{{#include file-system-object-v1-fixed.md}}
## Examples
### Simple
```json
{{#include schema/file-system-object-v1/simple.json}}
```
### Complex
```json
{{#include schema/file-system-object-v1/complex.json}}
```
<!-- need to convert YAML to JSON first
## Raw Schema
[JSON Schema for File System Object v1](schema/file-system-object-v1.json)
-->

View File

@@ -11,7 +11,8 @@ s/\\`/`/g
#
# As we have more such relative links, more replacements of this nature
# should appear below.
s^\(./hash-v1.yaml\)\?#/$defs/algorithm^[JSON format for `Hash`](./hash.html#algorithm)^g
s^\(./hash-v1.yaml\)^[JSON format for `Hash`](./hash.html)^g
s^\(./content-address-v1.yaml\)\?#/$defs/method^[JSON format for `ContentAddress`](./content-address.html#method)^g
s^\(./content-address-v1.yaml\)^[JSON format for `ContentAddress`](./content-address.html)^g
s^#/\$defs/\(regular\|symlink\|directory\)^In this schema^g
s^\(./hash-v1.yaml\)\?#/$defs/algorithm^[JSON format for `Hash`](@docroot@/protocols/json/hash.html#algorithm)^g
s^\(./hash-v1.yaml\)^[JSON format for `Hash`](@docroot@/protocols/json/hash.html)^g
s^\(./content-address-v1.yaml\)\?#/$defs/method^[JSON format for `ContentAddress`](@docroot@/protocols/json/content-address.html#method)^g
s^\(./content-address-v1.yaml\)^[JSON format for `ContentAddress`](@docroot@/protocols/json/content-address.html)^g

View File

@@ -2,28 +2,16 @@
## Examples
### SHA-256 with Base64 encoding
### SHA-256
```json
{{#include schema/hash-v1/sha256-base64.json}}
{{#include schema/hash-v1/sha256.json}}
```
### SHA-256 with Base16 (hexadecimal) encoding
### BLAKE3
```json
{{#include schema/hash-v1/sha256-base16.json}}
```
### SHA-256 with Nix32 encoding
```json
{{#include schema/hash-v1/sha256-nix32.json}}
```
### BLAKE3 with Base64 encoding
```json
{{#include schema/hash-v1/blake3-base64.json}}
{{#include schema/hash-v1/blake3.json}}
```
<!-- need to convert YAML to JSON first

View File

@@ -9,14 +9,17 @@ json_schema_for_humans = find_program('generate-schema-doc', required : false)
json_schema_config = files('json-schema-for-humans-config.yaml')
schemas = [
'file-system-object-v1',
'hash-v1',
'content-address-v1',
'store-path-v1',
'store-object-info-v2',
'derivation-v4',
'derivation-options-v1',
'deriving-path-v1',
'build-trace-entry-v1',
'build-result-v1',
'store-v1',
]
schema_files = files()
@@ -32,27 +35,27 @@ endforeach
json_schema_generated_files = []
# Generate markdown documentation from JSON schema
# Note: output must be just a filename, not a path
gen_file = custom_target(
schema_name + '-schema-docs.tmp',
command : [
json_schema_for_humans,
'--config-file',
json_schema_config,
meson.current_source_dir() / 'schema',
meson.current_build_dir(),
],
input : schema_files + [
json_schema_config,
],
output : schema_outputs,
capture : false,
build_by_default : true,
)
idx = 0
if json_schema_for_humans.found()
# Generate markdown documentation from JSON schema
# Note: output must be just a filename, not a path
gen_file = custom_target(
schema_name + '-schema-docs.tmp',
command : [
json_schema_for_humans,
'--config-file',
json_schema_config,
meson.current_source_dir() / 'schema',
meson.current_build_dir(),
],
input : schema_files + [
json_schema_config,
],
output : schema_outputs,
capture : false,
build_by_default : true,
)
idx = 0
foreach schema_name : schemas
#schema_file = 'schema' / schema_name + '.yaml'

View File

@@ -4,71 +4,97 @@ title: Build Trace Entry
description: |
A record of a successful build outcome for a specific derivation output.
This schema describes the JSON representation of a [build trace entry](@docroot@/store/build-trace.md) entry.
This schema describes the JSON representation of a [build trace entry](@docroot@/store/build-trace.md).
> **Warning**
>
> This JSON format is currently
> [**experimental**](@docroot@/development/experimental-features.md#xp-feature-ca-derivations)
> and subject to change.
type: object
required:
- id
- outPath
- dependentRealisations
- signatures
allOf:
- "$ref": "#/$defs/key"
- "$ref": "#/$defs/value"
properties:
id:
type: string
title: Derivation Output ID
pattern: "^sha256:[0-9a-f]{64}![a-zA-Z_][a-zA-Z0-9_-]*$"
description: |
Unique identifier for the derivation output that was built.
Format: `{hash-quotient-drv}!{output-name}`
- **hash-quotient-drv**: SHA-256 [hash of the quotient derivation](@docroot@/store/derivation/outputs/input-address.md#hash-quotient-drv).
Begins with `sha256:`.
- **output-name**: Name of the specific output (e.g., "out", "dev", "doc")
Example: `"sha256:ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad!foo"`
outPath:
"$ref": "store-path-v1.yaml"
title: Output Store Path
description: |
The path to the store object that resulted from building this derivation for the given output name.
dependentRealisations:
type: object
title: Underlying Base Build Trace
description: |
This is for [*derived*](@docroot@/store/build-trace.md#derived) build trace entries to ensure coherence.
Keys are derivation output IDs (same format as the main `id` field).
Values are the store paths that those dependencies resolved to.
As described in the linked section on derived build trace traces, derived build trace entries must be kept in addition and not instead of the underlying base build entries.
This is the set of base build trace entries that this derived build trace is derived from.
(The set is also a map since this miniature base build trace must be coherent, mapping each key to a single value.)
patternProperties:
"^sha256:[0-9a-f]{64}![a-zA-Z_][a-zA-Z0-9_-]*$":
$ref: "store-path-v1.yaml"
title: Dependent Store Path
description: Store path that this dependency resolved to during the build
additionalProperties: false
signatures:
type: array
title: Build Signatures
description: |
A set of cryptographic signatures attesting to the authenticity of this build trace entry.
items:
type: string
title: Signature
description: A single cryptographic signature
id: {}
outPath: {}
dependentRealisations: {}
signatures: {}
additionalProperties: false
"$defs":
key:
title: Build Trace Key
description: |
A [build trace entry](@docroot@/store/build-trace.md) is a key-value pair.
This is the "key" part, refering to a derivation and output.
type: object
required:
- id
properties:
id:
type: string
title: Derivation Output ID
pattern: "^sha256:[0-9a-f]{64}![a-zA-Z_][a-zA-Z0-9_-]*$"
description: |
Unique identifier for the derivation output that was built.
Format: `{hash-quotient-drv}!{output-name}`
- **hash-quotient-drv**: SHA-256 [hash of the quotient derivation](@docroot@/store/derivation/outputs/input-address.md#hash-quotient-drv).
Begins with `sha256:`.
- **output-name**: Name of the specific output (e.g., "out", "dev", "doc")
Example: `"sha256:ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad!foo"`
value:
title: Build Trace Value
description: |
A [build trace entry](@docroot@/store/build-trace.md) is a key-value pair.
This is the "value" part, describing an output.
type: object
required:
- outPath
- dependentRealisations
- signatures
properties:
outPath:
"$ref": "store-path-v1.yaml"
title: Output Store Path
description: |
The path to the store object that resulted from building this derivation for the given output name.
dependentRealisations:
type: object
title: Underlying Base Build Trace
description: |
This is for [*derived*](@docroot@/store/build-trace.md#derived) build trace entries to ensure coherence.
Keys are derivation output IDs (same format as the main `id` field).
Values are the store paths that those dependencies resolved to.
As described in the linked section on derived build trace traces, derived build trace entries must be kept in addition and not instead of the underlying base build entries.
This is the set of base build trace entries that this derived build trace is derived from.
(The set is also a map since this miniature base build trace must be coherent, mapping each key to a single value.)
patternProperties:
"^sha256:[0-9a-f]{64}![a-zA-Z_][a-zA-Z0-9_-]*$":
"$ref": "store-path-v1.yaml"
title: Dependent Store Path
description: Store path that this dependency resolved to during the build
additionalProperties: false
signatures:
type: array
title: Build Signatures
description: |
A set of cryptographic signatures attesting to the authenticity of this build trace entry.
items:
type: string
title: Signature
description: A single cryptographic signature

View File

@@ -0,0 +1 @@
../../../../../../src/libstore-tests/data/derivation

View File

@@ -0,0 +1,242 @@
"$schema": "http://json-schema.org/draft-04/schema"
"$id": "https://nix.dev/manual/nix/latest/protocols/json/schema/derivation-options-v1.json"
title: Derivation Options
description: |
JSON representation of Nix's `DerivationOptions` type.
This schema describes various build-time options and constraints that can be specified for a derivation.
> **Warning**
>
> This JSON format is currently
> [**experimental**](@docroot@/development/experimental-features.md#xp-feature-nix-command)
> and subject to change.
type: object
required:
- outputChecks
- unsafeDiscardReferences
- passAsFile
- exportReferencesGraph
- additionalSandboxProfile
- noChroot
- impureHostDeps
- impureEnvVars
- allowLocalNetworking
- requiredSystemFeatures
- preferLocalBuild
- allowSubstitutes
properties:
outputChecks:
type: object
title: Output Check
description: |
Constraints on what the derivation's outputs can and cannot reference.
Can either apply to all outputs or be specified per output.
oneOf:
- title: Output Checks For All Outputs
description: |
Output checks that apply to all outputs of the derivation.
required:
- forAllOutputs
properties:
forAllOutputs:
"$ref": "#/$defs/outputCheckSpec"
additionalProperties: false
- title: Output Checks Per Output
description: |
Output checks specified individually for each output.
required:
- perOutput
properties:
perOutput:
type: object
additionalProperties:
"$ref": "#/$defs/outputCheckSpec"
additionalProperties: false
unsafeDiscardReferences:
type: object
title: Unsafe Discard References
description: |
A map specifying which references should be unsafely discarded from each output.
This is generally not recommended and requires special permissions.
additionalProperties:
type: array
items:
type: string
passAsFile:
type: array
title: Pass As File
description: |
List of environment variable names whose values should be passed as files rather than directly.
items:
type: string
exportReferencesGraph:
type: object
title: Export References Graph
description: |
Specify paths whose references graph should be exported to files.
additionalProperties:
type: array
items:
"$ref": "deriving-path-v1.yaml"
additionalSandboxProfile:
type: string
title: Additional Sandbox Profile
description: |
Additional sandbox profile directives (macOS specific).
noChroot:
type: boolean
title: No Chroot
description: |
Whether to disable the build sandbox, if allowed.
impureHostDeps:
type: array
title: Impure Host Dependencies
description: |
List of host paths that the build can access.
items:
type: string
impureEnvVars:
type: array
title: Impure Environment Variables
description: |
List of environment variable names that should be passed through to the build from the calling environment.
items:
type: string
allowLocalNetworking:
type: boolean
title: Allow Local Networking
description: |
Whether the build should have access to local network (macOS specific).
requiredSystemFeatures:
type: array
title: Required System Features
description: |
List of system features required to build this derivation (e.g., "kvm", "nixos-test").
items:
type: string
preferLocalBuild:
type: boolean
title: Prefer Local Build
description: |
Whether this derivation should preferably be built locally rather than its outputs substituted.
allowSubstitutes:
type: boolean
title: Allow Substitutes
description: |
Whether substituting from other stores should be allowed for this derivation's outputs.
additionalProperties: false
$defs:
outputCheckSpec:
type: object
title: Output Check Specification
description: |
Constraints on what a specific output can reference.
required:
- ignoreSelfRefs
- maxSize
- maxClosureSize
- allowedReferences
- allowedRequisites
- disallowedReferences
- disallowedRequisites
properties:
ignoreSelfRefs:
type: boolean
title: Ignore Self References
description: |
Whether references from this output to itself should be ignored when checking references.
maxSize:
type: ["integer", "null"]
title: Maximum Size
description: |
Maximum allowed size of this output in bytes, or null for no limit.
minimum: 0
maxClosureSize:
type: ["integer", "null"]
title: Maximum Closure Size
description: |
Maximum allowed size of this output's closure in bytes, or null for no limit.
minimum: 0
allowedReferences:
oneOf:
- type: array
items:
"$ref": "#/$defs/drvRef"
- type: "null"
title: Allowed References
description: |
If set, the output can only reference paths in this list.
If null, no restrictions apply.
allowedRequisites:
oneOf:
- type: array
items:
"$ref": "#/$defs/drvRef"
- type: "null"
title: Allowed Requisites
description: |
If set, the output's closure can only contain paths in this list.
If null, no restrictions apply.
disallowedReferences:
type: array
title: Disallowed References
description: |
The output must not reference any paths in this list.
items:
"$ref": "#/$defs/drvRef"
disallowedRequisites:
type: array
title: Disallowed Requisites
description: |
The output's closure must not contain any paths in this list.
items:
"$ref": "#/$defs/drvRef"
additionalProperties: false
drvRef:
# TODO fix bug in checker, should be `oneOf`
anyOf:
- type: object
title: Current derivation Output Reference
description: |
A reference to a specific output of the current derivation.
required:
- drvPath
- output
properties:
drvPath:
type: string
const: "self"
title: This derivation
description: |
Won't be confused for a deriving path
output:
type: string
title: Output Name
description: |
The name of the output being referenced.
additionalProperties: false
- "$ref": "deriving-path-v1.yaml"

View File

@@ -0,0 +1 @@
../../../../../../src/libutil-tests/data/memory-source-accessor

View File

@@ -0,0 +1,71 @@
"$schema": http://json-schema.org/draft-04/schema#
"$id": https://nix.dev/manual/nix/latest/protocols/json/schema/file-system-object-v1.json
title: File System Object
description: |
This schema describes the JSON representation of Nix's [File System Object](@docroot@/store/file-system-object.md).
The schema is recursive because file system objects contain other file system objects.
type: object
required: ["type"]
properties:
type:
type: string
enum: ["regular", "symlink", "directory"]
# Enforce conditional structure based on `type`
anyOf:
- $ref: "#/$defs/regular"
required: ["type", "contents"]
- $ref: "#/$defs/directory"
required: ["type", "entries"]
- $ref: "#/$defs/symlink"
required: ["type", "target"]
"$defs":
regular:
title: Regular File
description: |
See [Regular File](@docroot@/store/file-system-object.md#regular) in the manual for details.
required: ["contents"]
properties:
type:
const: "regular"
contents:
type: string
description: File contents
executable:
type: boolean
description: Whether the file is executable.
default: false
additionalProperties: false
directory:
title: Directory
description: |
See [Directory](@docroot@/store/file-system-object.md#directory) in the manual for details.
required: ["entries"]
properties:
type:
const: "directory"
entries:
type: object
description: |
Map of names to nested file system objects (for type=directory)
additionalProperties:
$ref: "#"
additionalProperties: false
symlink:
title: Symbolic Link
description: |
See [Symbolic Link](@docroot@/store/file-system-object.md#symlink) in the manual for details.
required: ["target"]
properties:
type:
const: "symlink"
target:
type: string
description: Target path of the symlink.
additionalProperties: false

View File

@@ -4,40 +4,13 @@ title: Hash
description: |
A cryptographic hash value used throughout Nix for content addressing and integrity verification.
This schema describes the JSON representation of Nix's `Hash` type.
type: object
properties:
algorithm:
"$ref": "#/$defs/algorithm"
format:
type: string
enum:
- base64
- nix32
- base16
- sri
title: Hash format
description: |
The encoding format of the hash value.
This schema describes the JSON representation of Nix's `Hash` type as an [SRI](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity) string.
type: string
pattern: "^(blake3|md5|sha1|sha256|sha512)-[A-Za-z0-9+/]+=*$"
examples:
- "sha256-ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0="
- "sha512-IEqPxt2oLwoM7XvrjgikFlfBbvRosiioJ5vjMacDwzWW/RXBOxsH+aodO+pXeJygMa2Fx6cd1wNU7GMSOMo0RQ=="
- `base64` uses standard Base64 encoding [RFC 4648, section 4](https://datatracker.ietf.org/doc/html/rfc4648#section-4)
- `nix32` is Nix-specific base-32 encoding
- `base16` is lowercase hexadecimal
- `sri` is the [Subresource Integrity format](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity).
hash:
type: string
title: Hash
description: |
The encoded hash value, itself.
It is specified in the format specified by the `format` field.
It must be the right length for the hash algorithm specified in the `algorithm` field, also.
The hash value does not include any algorithm prefix.
required:
- algorithm
- format
- hash
additionalProperties: false
"$defs":
algorithm:
type: string

View File

@@ -1 +0,0 @@
../../../../../../src/libstore-tests/data/nar-info

View File

@@ -0,0 +1 @@
../../../../../../src/libstore-tests/data/nar-info/json-2

View File

@@ -1 +1 @@
../../../../../../src/libstore-tests/data/path-info
../../../../../../src/libstore-tests/data/path-info/json-2

View File

@@ -46,6 +46,7 @@ $defs:
- narSize
- references
- ca
- storeDir
properties:
version:
type: integer
@@ -63,7 +64,7 @@ $defs:
- Version 2: Use structured JSON type for `ca`
path:
type: string
"$ref": "./store-path-v1.yaml"
title: Store Path
description: |
[Store path](@docroot@/store/store-path.md) to the given store object.
@@ -89,7 +90,7 @@ $defs:
description: |
An array of [store paths](@docroot@/store/store-path.md), possibly including this one.
items:
type: string
"$ref": "./store-path-v1.yaml"
ca:
oneOf:
@@ -101,6 +102,12 @@ $defs:
If the store object is [content-addressed](@docroot@/store/store-object/content-address.md),
this is the content address of this store object's file system object, used to compute its store path.
Otherwise (i.e. if it is [input-addressed](@docroot@/glossary.md#gloss-input-addressed-store-object)), this is `null`.
storeDir:
type: string
title: Store Directory
description: |
The [store directory](@docroot@/store/store-path.md#store-directory) this store object belongs to (e.g. `/nix/store`).
additionalProperties: false
impure:
@@ -115,6 +122,7 @@ $defs:
- narSize
- references
- ca
- storeDir
# impure
- deriver
- registrationTime
@@ -127,8 +135,11 @@ $defs:
narSize: { $ref: "#/$defs/base/properties/narSize" }
references: { $ref: "#/$defs/base/properties/references" }
ca: { $ref: "#/$defs/base/properties/ca" }
storeDir: { $ref: "#/$defs/base/properties/storeDir" }
deriver:
type: ["string", "null"]
oneOf:
- "$ref": "./store-path-v1.yaml"
- type: "null"
title: Deriver
description: |
If known, the path to the [store derivation](@docroot@/glossary.md#gloss-store-derivation) from which this store object was produced.
@@ -190,6 +201,7 @@ $defs:
- narSize
- references
- ca
- storeDir
# impure
- deriver
- registrationTime
@@ -207,6 +219,7 @@ $defs:
narSize: { $ref: "#/$defs/base/properties/narSize" }
references: { $ref: "#/$defs/base/properties/references" }
ca: { $ref: "#/$defs/base/properties/ca" }
storeDir: { $ref: "#/$defs/base/properties/storeDir" }
deriver: { $ref: "#/$defs/impure/properties/deriver" }
registrationTime: { $ref: "#/$defs/impure/properties/registrationTime" }
ultimate: { $ref: "#/$defs/impure/properties/ultimate" }

View File

@@ -0,0 +1 @@
../../../../../../src/libstore-tests/data/dummy-store

View File

@@ -0,0 +1,90 @@
"$schema": "http://json-schema.org/draft-04/schema"
"$id": "https://nix.dev/manual/nix/latest/protocols/json/schema/store-v1.json"
title: Store
description: |
Experimental JSON representation of a Nix [Store](@docroot@/store/index.md).
This schema describes the JSON serialization of a Nix store.
We use it for (de)serializing in-memory "dummy stores" used for testing, but in principle the data represented in this schema could live in any type of store.
> **Warning**
>
> This JSON format is currently
> [**experimental**](@docroot@/development/experimental-features.md#xp-feature-nix-command)
> and subject to change.
type: object
required:
- config
- contents
- derivations
- buildTrace
properties:
config:
"$ref": "#/$defs/storeConfig"
contents:
type: object
title: Store Objects
description: |
Map of [store path](@docroot@/store/store-path.md) base names to [store objects](@docroot@/store/store-object.md).
patternProperties:
"^[0123456789abcdfghijklmnpqrsvwxyz]{32}-.+$":
type: object
title: Store Object
required:
- info
- contents
properties:
info:
"$ref": "./store-object-info-v2.yaml#/$defs/impure"
title: Store Object Info
description: |
Metadata about the [store object](@docroot@/store/store-object.md) including hash, size, references, etc.
contents:
"$ref": "./file-system-object-v1.yaml"
title: File System Object Contents
description: |
The actual [file system object](@docroot@/store/file-system-object.md) contents of this store path.
additionalProperties: false
additionalProperties: false
derivations:
type: object
title: Derivations
description: |
Map of [store path](@docroot@/store/store-path.md) base names (always ending in `.drv`) to [derivations](@docroot@/store/derivation/index.md).
patternProperties:
"^[0123456789abcdfghijklmnpqrsvwxyz]{32}-.+\\.drv$":
"$ref": "./derivation-v4.yaml"
additionalProperties: false
buildTrace:
type: object
title: Build Trace
description: |
Map of output hashes (base64 SHA256) to maps of output names to realisations.
Records which outputs have been built and their realisations.
See [Build Trace](@docroot@/store/build-trace.md) for more details.
patternProperties:
"^[A-Za-z0-9+/]{43}=$":
type: object
additionalProperties:
"$ref": "./build-trace-entry-v1.yaml#/$defs/value"
additionalProperties: false
"$defs":
storeConfig:
title: Store Configuration
description: |
Configuration for the store, including the store directory path.
type: object
required:
- store
properties:
store:
type: string
title: Store Directory
description: |
The store directory path (e.g., `/nix/store`).
additionalProperties: false

View File

@@ -29,13 +29,13 @@
### NAR info (minimal)
```json
{{#include schema/nar-info-v1/pure.json}}
{{#include schema/nar-info-v2/pure.json}}
```
### NAR info (with binary cache fields)
```json
{{#include schema/nar-info-v1/impure.json}}
{{#include schema/nar-info-v2/impure.json}}
```
<!-- need to convert YAML to JSON first

View File

@@ -0,0 +1,21 @@
{{#include store-v1-fixed.md}}
## Examples
### Empty store
```json
{{#include schema/store-v1/empty.json}}
```
### Store with one file
```json
{{#include schema/store-v1/one-flat-file.json}}
```
### Store with one derivation
```json
{{#include schema/store-v1/one-derivation.json}}
```

View File

@@ -112,7 +112,7 @@ This release was made possible by the following 45 contributors:
- Connor Baker [**(@ConnorBaker)**](https://github.com/ConnorBaker)
- Cole Helbling [**(@cole-h)**](https://github.com/cole-h)
- Jack Wilsdon [**(@jackwilsdon)**](https://github.com/jackwilsdon)
- rekcäH nitraM [**(@dwt)**](https://github.com/dwt)
- Martin Häcker [**(@dwt)**](https://github.com/dwt)
- Martin Fischer [**(@not-my-profile)**](https://github.com/not-my-profile)
- John Ericson [**(@Ericson2314)**](https://github.com/Ericson2314)
- Graham Christensen [**(@grahamc)**](https://github.com/grahamc)

View File

@@ -12,7 +12,7 @@
We ultimately want to rectify this issue with all JSON formats to the extent allowed by our stability promises. To start with, we are changing the JSON format for derivations because the `nix derivation` commands are — in addition to being formally unstable — less widely used than other unstable commands.
See the documentation on the [JSON format for derivations](@docroot@/protocols/json/derivation.md) for further details.
See the documentation on the [JSON format for derivations](@docroot@/protocols/json/derivation/index.md) for further details.
- C API: `nix_get_attr_name_byidx`, `nix_get_attr_byidx` take a `nix_value *` instead of `const nix_value *` [#13987](https://github.com/NixOS/nix/pull/13987)

View File

@@ -0,0 +1,313 @@
# Release 2.33.0 (2025-12-09)
## New features
- New command `nix registry resolve` [#14595](https://github.com/NixOS/nix/pull/14595)
This command looks up a flake registry input name and returns the flakeref it resolves to.
For example, looking up Nixpkgs:
```
$ nix registry resolve nixpkgs
github:NixOS/nixpkgs/nixpkgs-unstable
```
Upstreamed from [Determinate Nix 3.14.0](https://github.com/DeterminateSystems/nix-src/pull/273).
- `nix flake clone` supports all input types [#14581](https://github.com/NixOS/nix/pull/14581)
`nix flake clone` now supports arbitrary input types. In particular, this allows you to clone tarball flakes, such as flakes on FlakeHub.
Upstreamed from [Determinate Nix 3.12.0](https://github.com/DeterminateSystems/nix-src/pull/229).
## Performance improvements
- Git fetcher computes `revCount`s using multiple threads [#14462](https://github.com/NixOS/nix/pull/14462)
When using Git repositories with a long history, calculating the `revCount` attribute can take a long time. Nix now computes `revCount` using multiple threads, making it much faster (e.g. 9.1s to 3.7s for Nixpkgs).
Note that if you don't need `revCount`, you can disable it altogether by setting the flake input attribute `shallow = true`.
Upstreamed from [Determinate Nix 3.12.2](https://github.com/DeterminateSystems/nix-src/pull/245).
- `builtins.stringLength` now runs in constant time [#14442](https://github.com/NixOS/nix/pull/14442)
The internal representation of strings has been replaced with a size-prefixed Pascal style string. Previously Nix stored strings as a NUL-terminated array of bytes, necessitating a linear scan to calculate the length.
- Uploads to `http://` and `https://` binary cache stores now run in constant memory [#14390](https://github.com/NixOS/nix/pull/14390)
Nix used to buffer the whole compressed NAR contents in memory. It now reads it in a streaming fashion.
- Channel URLs migrated to channels.nixos.org subdomain [#14517](https://github.com/NixOS/nix/issues/14517) [#14518](https://github.com/NixOS/nix/pull/14518)
Channel URLs have been updated from `https://nixos.org/channels/` to `https://channels.nixos.org/` throughout Nix. This subdomain provides better reliability with IPv6 support and improved CDN distribution. The old domain apex (`nixos.org/channels/`) currently redirects to the new location but may be deprecated in the future.
- Fix `download buffer is full; consider increasing the 'download-buffer-size' setting` warning [#11728](https://github.com/NixOS/nix/issues/11728) [#14614](https://github.com/NixOS/nix/pull/14614)
The underlying issue that led to [#11728](https://github.com/NixOS/nix/issues/11728) has been resolved by utilizing
[libcurl write pausing functionality](https://curl.se/libcurl/c/curl_easy_pause.html) to control backpressure when unpacking to slow destinations like the git-backed tarball cache. The default value of `download-buffer-size` is now 1 MiB and it's no longer recommended to increase it, since the root cause has been fixed.
This is expected to improve download performance on fast connections, since previously a single slow download consumer would stall the thread and prevent any other transfers from progressing.
Many thanks go out to the [Lix project](https://lix.systems/) for the [implementation](https://git.lix.systems/lix-project/lix/commit/4ae6fb5a8f0d456b8d2ba2aaca3712b4e49057fc) that served as inspiration for this change and for triaging libcurl [issues with pausing](https://github.com/curl/curl/issues/19334).
- Significantly improve tarball unpacking performance [#14689](https://github.com/NixOS/nix/pull/14689) [#14696](https://github.com/NixOS/nix/pull/14696) [#10683](https://github.com/NixOS/nix/issues/10683) [#11098](https://github.com/NixOS/nix/issues/11098)
Nix uses a content-addressed cache backed by libgit2 for deduplicating files fetched via `fetchTarball` and `github`, `tarball` flake inputs. Its usage has been significantly optimised to reduce the amount of I/O operations that are performed. For a typical nixpkgs source tarball this results in 200 times fewer system calls on Linux. In combination with libcurl pausing this alleviates performance regressions stemming from the tarball cache.
- Already valid derivations are no longer copied to the store [#14219](https://github.com/NixOS/nix/pull/14219)
This results in a modest speedup when using the Nix daemon.
- `nix nar ls` and `nix nar cat` are significantly faster and no longer buffer the whole NAR in memory [#14273](https://github.com/NixOS/nix/pull/14273) [#14732](https://github.com/NixOS/nix/pull/14732)
## S3 improvements
- Improved S3 binary cache support via HTTP [#11748](https://github.com/NixOS/nix/issues/11748) [#12403](https://github.com/NixOS/nix/issues/12403) [#12671](https://github.com/NixOS/nix/issues/12671) [#13084](https://github.com/NixOS/nix/issues/13084) [#13752](https://github.com/NixOS/nix/pull/13752) [#13823](https://github.com/NixOS/nix/pull/13823) [#14026](https://github.com/NixOS/nix/pull/14026) [#14120](https://github.com/NixOS/nix/pull/14120) [#14131](https://github.com/NixOS/nix/pull/14131) [#14135](https://github.com/NixOS/nix/pull/14135) [#14144](https://github.com/NixOS/nix/pull/14144) [#14170](https://github.com/NixOS/nix/pull/14170) [#14190](https://github.com/NixOS/nix/pull/14190) [#14198](https://github.com/NixOS/nix/pull/14198) [#14206](https://github.com/NixOS/nix/pull/14206) [#14209](https://github.com/NixOS/nix/pull/14209) [#14222](https://github.com/NixOS/nix/pull/14222) [#14223](https://github.com/NixOS/nix/pull/14223) [#14330](https://github.com/NixOS/nix/pull/14330) [#14333](https://github.com/NixOS/nix/pull/14333) [#14335](https://github.com/NixOS/nix/pull/14335) [#14336](https://github.com/NixOS/nix/pull/14336) [#14337](https://github.com/NixOS/nix/pull/14337) [#14350](https://github.com/NixOS/nix/pull/14350) [#14356](https://github.com/NixOS/nix/pull/14356) [#14357](https://github.com/NixOS/nix/pull/14357) [#14374](https://github.com/NixOS/nix/pull/14374) [#14375](https://github.com/NixOS/nix/pull/14375) [#14376](https://github.com/NixOS/nix/pull/14376) [#14377](https://github.com/NixOS/nix/pull/14377) [#14391](https://github.com/NixOS/nix/pull/14391) [#14393](https://github.com/NixOS/nix/pull/14393) [#14420](https://github.com/NixOS/nix/pull/14420) [#14421](https://github.com/NixOS/nix/pull/14421)
S3 binary cache operations now happen via HTTP, leveraging `libcurl`'s native AWS SigV4 authentication instead of the AWS C++ SDK, providing significant improvements:
- **Reduced memory usage**: Eliminates memory buffering issues that caused segfaults with large files
- **Fixed upload reliability**: Resolves AWS SDK chunking errors (`InvalidChunkSizeError`)
- **Lighter dependencies**: Uses lightweight `aws-crt-cpp` instead of full `aws-cpp-sdk`, reducing build complexity
The new implementation requires curl >= 7.75.0 and `aws-crt-cpp` for credential management.
All existing S3 URL formats and parameters remain supported, however the store settings for configuring multipart uploads have changed:
- **`multipart-upload`** (default: `false`): Enable multipart uploads for large files. When enabled, files exceeding the multipart threshold will be uploaded in multiple parts.
- **`multipart-threshold`** (default: `100 MiB`): Minimum file size for using multipart uploads. Files smaller than this will use regular PUT requests. Only takes effect when `multipart-upload` is enabled.
- **`multipart-chunk-size`** (default: `5 MiB`): Size of each part in multipart uploads. Must be at least 5 MiB (AWS S3 requirement). Larger chunk sizes reduce the number of requests but use more memory.
- **`buffer-size`**: Has been replaced by `multipart-chunk-size` and is now an alias to it.
Note that this change also means Nix now supports S3 binary cache stores even if built without `aws-crt-cpp`, but only for public buckets which do not require authentication.
- S3 URLs now support object versioning via `versionId` parameter [#13955](https://github.com/NixOS/nix/issues/13955) [#14274](https://github.com/NixOS/nix/pull/14274)
S3 URLs now support a `versionId` query parameter to fetch specific versions
of objects from S3 buckets with versioning enabled. This allows pinning to
exact object versions for reproducibility and protection against unexpected
changes:
```
s3://bucket/key?region=us-east-1&versionId=abc123def456
```
- S3 binary cache stores now support storage class configuration [#7015](https://github.com/NixOS/nix/issues/7015) [#14464](https://github.com/NixOS/nix/pull/14464)
S3 binary cache stores now support configuring the storage class for uploaded objects via the `storage-class` parameter. This allows users to optimize costs by selecting appropriate storage tiers based on access patterns.
Example usage:
```bash
# Use Glacier storage for long-term archival
nix copy --to 's3://my-bucket?storage-class=GLACIER' /nix/store/...
# Use Intelligent Tiering for automatic cost optimization
nix copy --to 's3://my-bucket?storage-class=INTELLIGENT_TIERING' /nix/store/...
```
The storage class applies to both regular uploads and multipart uploads. When not specified, objects use the bucket's default storage class.
See the [S3 storage classes documentation](https://docs.aws.amazon.com/AmazonS3/latest/userguide/storage-class-intro.html) for available storage classes and their characteristics.
## Store path info JSON format changes
The JSON format emitted by `nix path-info --json` has been updated to a new version with improved structure.
To maintain compatibility, `nix path-info --json` now requires a `--json-format` flag to specify the output format version.
Using `--json` without `--json-format` is deprecated and will become an error in a future release.
For now, it defaults to version 1 with a warning, for a smoother migration.
### Version 1 (`--json-format 1`)
This is the legacy format, preserved for backwards compatibility:
- String-based hash values (e.g., `"narHash": "sha256:FePFYIlM..."`)
- String-based content addresses (e.g., `"ca": "fixed:r:sha256:1abc..."`)
- Full store paths for map keys and references (e.g., `"/nix/store/abc...-foo"`)
- Now includes `"storeDir"` field at the top level
### Version 2 (`--json-format 2`)
The new structured format follows the [JSON guidelines](@docroot@/development/json-guideline.md) with the following changes:
- **Nested structure with top-level metadata**:
The output is now wrapped in an object with `version`, `storeDir`, and `info` fields:
```json
{
"version": 2,
"storeDir": "/nix/store",
"info": { ... }
}
```
The map from store path base names to store object info is nested under the `info` field.
- **Store path base names instead of full paths**:
Map keys and references use store path base names (e.g., `"abc...-foo"`) instead of full absolute store paths.
Combined with `storeDir`, the full path can be reconstructed.
- **Structured `ca` field**:
Content address is now a structured JSON object instead of a string:
- Old: `"ca": "fixed:r:sha256:1abc..."`
- New: `"ca": {"method": "nar", "hash": "sha256-ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0="}`
- Still `null` values for input-addressed store objects
The `hash` field uses the [SRI](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity) format like other hashes.
Additionally the following fields are added to both formats:
- **`version` field**:
All store path info JSON now includes `"version": <1|2>`. The `version` tracks breaking changes, and adding fields to outputted JSON is not a breaking change.
- **`storeDir` field**:
Top-level `"storeDir"` field contains the store directory path (e.g., `"/nix/store"`).
## Derivation JSON format changes
The derivation JSON format has been updated from version 3 to version 4:
- **Nested structure with top-level metadata**:
The output of `nix derivation show` is now wrapped in an object with `version` and `derivations` fields:
```json
{
"version": 4,
"derivations": { ... }
}
```
The map from derivation paths to derivation info is nested under the `derivations` field.
This matches the structure used for `nix path-info --json --json-format 2`, and likewise brings this command into compliance with the JSON guidelines.
- **Restructured inputs**:
Inputs are now nested under an `inputs` object:
- Old: `"inputSrcs": [...], "inputDrvs": {...}`
- New: `"inputs": {"srcs": [...], "drvs": {...}}`
- **Consistent content addresses**:
Fixed content-addressed outputs now use structured JSON format.
This is the same format as `ca` in store path info (after the new version).
Version 3 and earlier formats are *not* accepted when reading.
**Affected command**: `nix derivation`, namely its `show` and `add` sub-commands.
## Miscellaneous changes
- Git fetcher: Restore progress indication [#14487](https://github.com/NixOS/nix/pull/14487)
Nix used to feel "stuck" while it was cloning large repositories. Nix now shows Git's native progress indicator while fetching.
Upstreamed from [Determinate Nix 3.13.0](https://github.com/DeterminateSystems/nix-src/pull/250).
- Interrupting REPL commands works more than once [#13481](https://github.com/NixOS/nix/issues/13481)
Previously, this only worked once per REPL session; further attempts would be ignored.
This issue is now fixed, so REPL commands such as `:b` or `:p` can be canceled consistently.
This is a cherry-pick of the change from the [Lix project](https://gerrit.lix.systems/c/lix/+/1097).
- NAR unpacking code has been rewritten to make use of dirfd-based `openat` and `openat2` system calls when available [#14597](https://github.com/NixOS/nix/pull/14597)
- Dynamic size unit rendering [#14423](https://github.com/NixOS/nix/pull/14423) [#14364](https://github.com/NixOS/nix/pull/14364)
Various commands and the progress bar now use dynamically determined size units instead
of always using `MiB`. For example, the progress bar now reports download status like:
```
[1/196/197 copied (773.7 MiB/2.1 GiB), 172.4/421.5 MiB DL]
```
Instead of:
```
[1/196/197 copied (773.7/2147.3 MiB), 172.4/421.5 MiB DL]
```
## Contributors
This release was made possible by the following 33 contributors:
- Adam Dinwoodie [**(@me-and)**](https://github.com/me-and)
- jonhermansen [**(@jonhermansen)**](https://github.com/jonhermansen)
- Arnout Engelen [**(@raboof)**](https://github.com/raboof)
- Jean-François Roche [**(@jfroche)**](https://github.com/jfroche)
- tomberek [**(@tomberek)**](https://github.com/tomberek)
- Eelco Dolstra [**(@edolstra)**](https://github.com/edolstra)
- Marcel [**(@MarcelCoding)**](https://github.com/MarcelCoding)
- David McFarland [**(@corngood)**](https://github.com/corngood)
- Soumyadip Sarkar [**(@neuralsorcerer)**](https://github.com/neuralsorcerer)
- Cole Helbling [**(@cole-h)**](https://github.com/cole-h)
- John Ericson [**(@Ericson2314)**](https://github.com/Ericson2314)
- Tristan Ross [**(@RossComputerGuy)**](https://github.com/RossComputerGuy)
- Alex Auvolat [**(@Alexis211)**](https://github.com/Alexis211)
- edef [**(@edef1c)**](https://github.com/edef1c)
- Sergei Zimmerman [**(@xokdvium)**](https://github.com/xokdvium)
- Vinayak Goyal [**(@vinayakankugoyal)**](https://github.com/vinayakankugoyal)
- Graham Dennis [**(@GrahamDennis)**](https://github.com/GrahamDennis)
- Aspen Smith [**(@glittershark)**](https://github.com/glittershark)
- Jens Petersen [**(@juhp)**](https://github.com/juhp)
- Bernardo Meurer [**(@lovesegfault)**](https://github.com/lovesegfault)
- Peter Bynum [**(@pkpbynum)**](https://github.com/pkpbynum)
- Jörg Thalheim [**(@Mic92)**](https://github.com/Mic92)
- Alex Decious [**(@adeci)**](https://github.com/adeci)
- Matthieu Coudron [**(@teto)**](https://github.com/teto)
- Domen Kožar [**(@domenkozar)**](https://github.com/domenkozar)
- Taeer Bar-Yam [**(@Radvendii)**](https://github.com/Radvendii)
- Seth Flynn [**(@getchoo)**](https://github.com/getchoo)
- Robert Hensing [**(@roberth)**](https://github.com/roberth)
- Vladimir Panteleev [**(@CyberShadow)**](https://github.com/CyberShadow)
- bryango [**(@bryango)**](https://github.com/bryango)
- Henry [**(@cootshk)**](https://github.com/cootshk)
- Martin Joerg [**(@mjoerg)**](https://github.com/mjoerg)
- Farid Zakaria [**(@fzakaria)**](https://github.com/fzakaria)
# Release 2.33.3 (2026-02-13)
- S3 binary caches now use virtual-hosted-style addressing by default [#15208](https://github.com/NixOS/nix/issues/15208)
S3 binary caches now use virtual-hosted-style URLs
(`https://bucket.s3.region.amazonaws.com/key`) instead of path-style URLs
(`https://s3.region.amazonaws.com/bucket/key`) when connecting to standard AWS
S3 endpoints. This enables HTTP/2 multiplexing and fixes TCP connection
exhaustion (TIME_WAIT socket accumulation) under high-concurrency workloads.
A new `addressing-style` store option controls this behavior:
- `auto` (default): virtual-hosted-style for standard AWS endpoints, path-style
for custom endpoints.
- `path`: forces path-style addressing (deprecated by AWS).
- `virtual`: forces virtual-hosted-style addressing (bucket names must not
contain dots).
Bucket names containing dots (e.g., `my.bucket.name`) automatically fall back
to path-style addressing in `auto` mode, because dotted names create
multi-level subdomains that break TLS wildcard certificate validation.
Example using path-style for backwards compatibility:
```
s3://my-bucket/key?region=us-east-1&addressing-style=path
```
Additionally, TCP keep-alive is now enabled on all HTTP connections, preventing
idle connections from being silently dropped by intermediate network devices
(NATs, firewalls, load balancers).

View File

@@ -12,10 +12,11 @@
The [`builder`](./derivation/index.md#builder) is executed as follows:
- A temporary directory is created under the directory specified by
`TMPDIR` (default `/tmp`) where the build will take place. The
- A temporary directory is created where the build will take place. The
current directory is changed to this directory.
See the per-store [`build-dir`](@docroot@/store/types/local-store.md#store-local-store-build-dir) setting for more information.
- The environment is cleared and set to the derivation attributes, as
specified above.

View File

@@ -192,7 +192,7 @@ There are two formats, documented separately:
- The legacy ["ATerm" format](@docroot@/protocols/derivation-aterm.md)
- The experimental, currently under development and changing [JSON format](@docroot@/protocols/json/derivation.md)
- The experimental, currently under development and changing [JSON format](@docroot@/protocols/json/derivation/index.md)
Every derivation has a canonical choice of encoding used to serialize it to a store object.
This ensures that there is a canonical [store path] used to refer to the derivation, as described in [Referencing derivations](#derivation-path).

View File

@@ -3,19 +3,23 @@
Nix uses a simplified model of the file system, which consists of file system objects.
Every file system object is one of the following:
- File
- [**Regular File**]{#regular}
- A possibly empty sequence of bytes for contents
- A single boolean representing the [executable](https://en.m.wikipedia.org/wiki/File-system_permissions#Permissions) permission
- Directory
- [**Directory**]{#directory}
Mapping of names to child file system objects
- [Symbolic link](https://en.m.wikipedia.org/wiki/Symbolic_link)
- [**Symbolic link**]{#symlink}
An arbitrary string.
Nix does not assign any semantics to symbolic links.
An arbitrary string, known as the *target* of the symlink.
In general, Nix does not assign any semantics to symbolic links.
Certain operations however, may make additional assumptions and attempt to use the target to find another file system object.
> See [the Wikpedia article on symbolic links](https://en.m.wikipedia.org/wiki/Symbolic_link) for background information if you are unfamiliar with this Unix concept.
File system objects and their children form a tree.
A bare file or symlink can be a root file system object.

View File

@@ -41,6 +41,10 @@ def recursive_replace(data: dict[str, t.Any], book_root: Path, search_path: Path
return data | dict(
sections = [recursive_replace(section, book_root, search_path) for section in sections],
)
case {'items': items}:
return data | dict(
items = [recursive_replace(item, book_root, search_path) for item in items],
)
case {'Chapter': chapter}:
path_to_chapter = Path(chapter['path'])
chapter_content = chapter['content']

17
flake.lock generated
View File

@@ -63,18 +63,15 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1761597516,
"narHash": "sha256-wxX7u6D2rpkJLWkZ2E932SIvDJW8+ON/0Yy8+a5vsDU=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "daf6dc47aa4b44791372d6139ab7b25269184d55",
"type": "github"
"lastModified": 1763948260,
"narHash": "sha256-zZk7fn2ARAqmLwaYTpxBJmj81KIdz11NiWt7ydHHD/M=",
"rev": "1c8ba8d3f7634acac4a2094eef7c32ad9106532c",
"type": "tarball",
"url": "https://releases.nixos.org/nixos/25.05/nixos-25.05.813095.1c8ba8d3f763/nixexprs.tar.xz"
},
"original": {
"owner": "NixOS",
"ref": "nixos-25.05",
"repo": "nixpkgs",
"type": "github"
"type": "tarball",
"url": "https://channels.nixos.org/nixos-25.05/nixexprs.tar.xz"
}
},
"nixpkgs-23-11": {

View File

@@ -1,7 +1,7 @@
{
description = "The purely functional package manager";
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05";
inputs.nixpkgs.url = "https://channels.nixos.org/nixos-25.05/nixexprs.tar.xz";
inputs.nixpkgs-regression.url = "github:NixOS/nixpkgs/215d4d0fd80ca5163643b03a33fde804a29cc1e2";
inputs.nixpkgs-23-11.url = "github:NixOS/nixpkgs/a62e6edd6d5e1fa0329b8653c801147986f8d446";
@@ -32,7 +32,7 @@
let
inherit (nixpkgs) lib;
officialRelease = false;
officialRelease = true;
linux32BitSystems = [ "i686-linux" ];
linux64BitSystems = [
@@ -369,6 +369,7 @@
# TODO probably should be `nix-cli`
nix = self.packages.${system}.nix-everything;
nix-manual = nixpkgsFor.${system}.native.nixComponents2.nix-manual;
nix-manual-manpages-only = nixpkgsFor.${system}.native.nixComponents2.nix-manual-manpages-only;
nix-internal-api-docs = nixpkgsFor.${system}.native.nixComponents2.nix-internal-api-docs;
nix-external-api-docs = nixpkgsFor.${system}.native.nixComponents2.nix-external-api-docs;
}

View File

@@ -224,5 +224,25 @@
"42688647+netadr@users.noreply.github.com": "netadr",
"matej.urbas@gmail.com": "urbas",
"ethanalexevans@gmail.com": "ethanavatar",
"greg.marti@gmail.com": "gmarti"
"greg.marti@gmail.com": "gmarti",
"arnout@bzzt.net": "raboof",
"vinayakankugoyal@gmail.com": "vinayakankugoyal",
"Radvendii@users.noreply.github.com": "Radvendii",
"jon@jh86.org": "jonhermansen",
"edef@edef.eu": "edef1c",
"pkpbynum@gmail.com": "pkpbynum",
"886074+teto@users.noreply.github.com": "teto",
"alex@adnab.me": "Alexis211",
"root@gws.fyi": "glittershark",
"me@m4rc3l.de": "MarcelCoding",
"taeer.bar-yam@bevuta.com": "Radvendii",
"martin.joerg@gmail.com": "mjoerg",
"git@cy.md": "CyberShadow",
"cootshk@duck.com": "cootshk",
"adam@dinwoodie.org": "me-and",
"domen@cachix.org": "domenkozar",
"alex.decious@gmail.com": "adeci",
"soumya.papanvk18@gmail.com": "neuralsorcerer",
"gdennis@anduril.com": null,
"graham.dennis@gmail.com": "GrahamDennis"
}

View File

@@ -118,7 +118,7 @@
"wh0": null,
"mupdt": "Matej Urbas",
"momeemt": "Mutsuha Asada",
"dwt": "\u202erekc\u00e4H nitraM\u202e",
"dwt": "Martin H\u00e4cker",
"aidenfoxivey": "Aiden Fox Ivey",
"ilya-bobyr": "Illia Bobyr",
"B4dM4n": "Fabian M\u00f6ller",
@@ -196,5 +196,21 @@
"gmarti": "Gr\u00e9gory Marti",
"lovesegfault": "Bernardo Meurer",
"EphraimSiegfried": "Ephraim Siegfried",
"hgl": "Glen Huang"
"hgl": "Glen Huang",
"mjoerg": "Martin Joerg",
"Alexis211": "Alex Auvolat",
"domenkozar": "Domen Ko\u017ear",
"edef1c": "edef",
"cootshk": "Henry",
"raboof": "Arnout Engelen",
"pkpbynum": "Peter Bynum",
"glittershark": "Aspen Smith",
"MarcelCoding": "Marcel",
"teto": "Matthieu Coudron",
"jonhermansen": null,
"neuralsorcerer": "Soumyadip Sarkar",
"adeci": "Alex Decious",
"vinayakankugoyal": "Vinayak Goyal",
"me-and": "Adam Dinwoodie",
"GrahamDennis": "Graham Dennis"
}

View File

@@ -79,6 +79,8 @@
# Not supported by nixfmt
''^tests/functional/lang/eval-okay-deprecate-cursed-or\.nix$''
''^tests/functional/lang/eval-okay-attrs5\.nix$''
''^tests/functional/lang/eval-fail-dynamic-attrs-inherit\.nix$''
''^tests/functional/lang/eval-fail-dynamic-attrs-inherit-2\.nix$''
# More syntax tests
# These tests, or parts of them, should have been parse-* test cases.

View File

@@ -0,0 +1,110 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBGPtMiwBEAC0sFZW2QW/OaDjKm5zGRpDvHXDsMIUtlHfoi5ce8pocC63W05o
FSXbUZjZ1VfYO8lT8DFANCzTkiXYaZx0cPRG2pVY4AOQZDNFt5XrAyvw496XCAIM
DTYGFLjCqgjPt9RUFEy4MyHPJTEpB0x3rXgT4ILNu9vsj9Q0vttps7SpbZ3Ldq5H
o/BBbLW77q/vNjpYzCbBIXF7ycUGpnNv9Go/WuiDnrBMcyxh+8kjjIHB5cxZSnjJ
DUv681+m83v+gLZQGX/jexQrrf5JpS0X9qEnhGLrNUDhtyv5ud3Je4EfamkjLVVC
RlNLofgflOCsl/tP80i+K7S1QdKhUALxuJ6H0prYUflGBDxDyC8XYuJ62TT0OUpa
vJvgwVlCq8/jq+ykYQXlbuBVOzi5wAuI4l3+HqreSQYPSiwe+6N590Zbafdv1fvN
WFtZKCTGMqfyaaAnppioH9/+NWkI2AQxaYVasYM/JEYvY9pJgA7alh51jHW4JglP
ErypKfBKPKJID0QENqYoa3bDDCihuNWhgQf9dxzPlj2ckd35Zb6w4DfuSmtjaa9D
o0jZVY1JbFuxBqP09+saVPrxLHgmPxjcdzPGQQtAqdO2vyJXNEGLFMoVEZPNaLo3
QmcIJnT7oSck+4vGfOYtWUHXQynu/Tnwsv2XkA/uyw8HNe+RRMqv/apnzQARAQAB
tCdTZXJnZWkgWmltbWVybWFuIDxzZXJnZWlAemltbWVybWFuLmZvbz6JAlEEEwEK
ADsCGwEFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AWIQQVim9TDqIC5fZRYRMU+upj
RI4d+QUCaUbsaAIZAQAKCRAU+upjRI4d+VdDD/492HRaJ/8V7R7VUzkafmb2Hb28
SLf7oiB8Uq9I7SukiDEaIT1fUhquYWQ9KWpPRNR1TX6ApXnIeuJRMGFoDVIRnmnr
cKnYYXfqqc81VxIyKvaumB7KWbS7G4Nbor8AH1ouOOOMMS50OTJOWQA4A26inIuG
n+7L8MeS5aT+3uNKDoTKsidC47vnaxNMcke1taPfbfo7vn69PsRCM/g9/7TQYU8b
6xp+pM9Ao9nJneRk2YCpsGYRrWTpaik0DFKnfpPKJM/yunhtGLF2IYAp3l1mvHPK
nnzo92zjpQuZwazEIK+23V1vRT4IjM2BewbJPAzf2/UuxEjjgNQm0tOtH2JhFNeB
VM0BVrGxWrrwrsmv6lWghTtBc6zRWyHrj/rpjtVQNmeKYrHWJeXwVz1rqgGPmB2N
k0MZD1UjHHhEs1Cntn7yLmxTPztRJCtR+euRu81Uo2NAvrMJ4xsDjaM0LeLTnzjV
9AsPjD188dOFyz7VExZum4+XaaEJ41FIPLEqU3U0GAa6stEy0ylSlIN4x9aiXXVW
xfzHHchS5jK6QAjuZxN8t01GRactNylINRf7uoTECFZTtXNqfeuk0HQxBH0LuKVE
0PxJbcNI4mVWw1KgTJ8PUVC1IXP3sEpqPdJOYiRXgnpcS26fWOBu0aQ4mhxiaJhr
/zBfrkLEqp20TdNDZLkCDQRj7TM1ARAAt73xO24curnHTTgXkkVMMRzcMLx3Mb1a
2FuddxC5hzTpEpw01L91UBrXVJEg9K2KAwP5CtCLgPCqXr47Tm7krvHxWwBksgY/
6aHRsoPQfCFUZHc0aiO+C4NCzR+aEeGKn66Oc1Hq9oUTpDgiBWhsuEPiyA1OSGF0
4L0jeTCqfm68kWp4PIK9yuugkdDsoyj6TonuMsb3V5ctHLqop9KH+eHSkUTPo+Lk
+bxaeAOJ1UfbohgbRbrYKAfsaghhOMDH3R1w2pvtUJz+sDbuQsiPFTqbxsXDTFws
H4N/AQCYnnvOhqEek2sOEZ19bJXt5UrAr10mX4PGmAkWqE1JWBxpOKG3BXSGOTu1
3dFhQfPMK+PmvUrs0kcWQr53K/aRUdKKhIfTcMfkqYTGPK5HclHph24WjXj3QFFA
SjksQTdm6486ZmLZK4CTbAFOPfTF/aWg8gu9v4ihdq6lqHNNXxv2xBAChcd59H7p
D5zy9z8SpwWR9V5JDmlF6HWIIau1c6lSsQq1xHvYM8EuPe03vJvor+2u/cn5zYF1
5ZxAuPI2i5vtavg1s8ZGAAogJ9dVcP36LdJfL9quXWvmovkd//qHIepBB+l/zQio
ZRDZlIcfV3Xycaqsb5OqHGARHE0097koipMt5y/iXlqG4Ruue6Idb8bW96EKpaWj
kKy/iNfQfQMAEQEAAYkEcgQYAQoAJgIbAhYhBBWKb1MOogLl9lFhExT66mNEjh35
BQJpRuz3BQkJHCDCAkDBdCAEGQEKAB0WIQRK3hK0WyJ4BicGpcmpsLVXymMjJQUC
Y+0zNQAKCRCpsLVXymMjJbdSD/9+f1FOOeGDAJI6Duo5fsWnf4xJJdtQtDbz6d2A
SeDapxeJ3zWfKBD0wu5sISEa0uiWsYSmLtsa2SqVAKHlEaMGRR+tkBMPQ+rvgI4c
62YjGTgm+IPd+NFIn+ixFU1hpinTh+KhUEoeOwWCvKs9nZfSG9vkienfiG0bBxo2
zrvBzXA50x5hbUL+ghKu/AVfN9qZDwh30O4KZTwk4g4cM9SeaQa4YvHYIS3IEhDZ
hGybwrrqV9cs92ln4IJw9WCy9QReBNrdeFgC4+3ziUp1QsG3RvqrtuMttwBVC1Z3
bj5QjLLOREhhodfvk98t9yVkragObb4rGrLo1mWuF0c4mJGvXwnrqhCMvzv4M+0T
Zdrmw6YpGkGOaOPghVuwoTtqSAkl+zFWIJS89jidvkYG3EqKAkgLKog/TQReCq13
HWrF8cMck+Rf2K8k26q/RNZaA9ZUKjLExzz8lsWmd2C7rvkGLrlxnzxz0gGyNR3Q
KK74vcPhqeABt2GSkHtEXZFFA9IVVzwlRWK3e0S+mVQnZVjNL+cBPn3/hZHMLesB
CucyYZv+DxvT+JkYXBkGSw4s3hpABqGym7gdPUIa0q4rbBFG6xP5sLLBG4yru8vV
2dyCMmFqRuxpT49uNfyQ6Vj+dobN6qHnP/9NwfzOixXYBHXR6LBqb/M+iCiJaaIn
uiRLHwkQFPrqY0SOHfkQpA//W51vj8meuz7snRO+vZFcjLneFFzqfh1Jdz8IqDpO
CkI5pBJmi8e0oSe6r68MkahiQLlYPwm7d+sjHvJhPWipNKWq/uwCgBs+Ac1lpPXR
MwLbrZukcLMYlLmb2MrCKmjcMt0BZsZKBNYL3a3X9nHgwXdeqFYS4WQDMCCc09lz
9YqfdoEsqRO4qN7D0hFqnwjOzb34ixZ6UO8a8ekY9QKxAgWc9fJWGMg6Pjdg4qsK
nqymOIAdGVOJdoRM46wKGVBvbsF2gNfQU4XyzgJo5vHGFwJm6EoSnODlL5e2wsQh
uN1oqBt/8ef/plloMEqVBweUBATqSqjRF6IhhYJvWVuQHQL1p1vnV9FebiVj34ir
Z8ID+o0AnTJcclbUcDwannGJ0cuDcPhk/v/ahVuoMERCi12qnMBo5B/e6Omyh1yB
4pbf4GATGGQipDQG75eC/kP2GQEqJP5WYN0Ar8Le/AA/2xyL7upW0yIByyXCwGEb
JRwEgU3+bPyu58bFt8Pftit6J7rA3oBVVMOPrYH5eZwRaj5m2RptwKGL6BfHnhNv
ZqmCq9EBGX6L1NI0xHMjEFfXJ8jU01XdfG8nCqkwqsHwslXLhqjJphfHcx89YwbV
/15GCuURAv1cKe/7277sOhcvP/QpQqSWgvYExHw8PeFJcTYtF2NrRgNwcQsWS1Rj
gXa5Ag0EY+0zcAEQANC5N6kSfezuucAgi+X3BD+MT37mxQyvICSggEJf1LDSmy0+
bnvD7setL8CP9etTA2fcVNYKI1oboMyhoCnsRP2jDdv1iXOI/hZg4wSb/D1yUkae
fUpxv3Wuci2QKavH2MfraDD7BFMbsQeMcHtn4Rk216T6jndZHnzT1Ih7iX0XeQPb
li5fojOiZssgWAVT4HPXFCJB6lI35Hjp35oRYwrtMmu5INinZ79n9h1igGtt1ItZ
b7rQKNd772Jxcn4UU71ovORSL/xT5i5sxZ+evQOxkpqUAokMOFaoHcOXLmA1NsFv
yryXHK4Ioq9ap2jKlLTWkJWjua9JZ4AmKhbvT8X4ELxIKSCAdJKAWP8ZHbXNu5MD
aznyzZQLxSO7uFvu356De75mI5iohZNj5wB5Wju71pBiorTKVj4+iJ4e+xVIzFdG
hFC0DehNcl2t9w/y8qHwIQ1yUAjXHLXq0/2jsVeH6bU5q/MsgvUP1jcFe0eyOpxy
CDvyFdzZFbI57TnB/fvcZTRZ5ewXMFpH8gzuoFzAjUAP95UjYKgaGdrNPNIy28Ii
4zhvdghei2+n9jgiMfcGQg8lyfH5yF0vWWWynX0KcJsRwEZoL2EauVdwq4PcYOoU
pQFhpcreCjD4LdZ4yRU4InbhcUogXjrQ9Dz01TbPmQD5b5iso21bCEFBXrhzABEB
AAGJAjwEGAEKACYCGwwWIQQVim9TDqIC5fZRYRMU+upjRI4d+QUCaUbs9wUJCRwg
hwAKCRAU+upjRI4d+X/XD/sH5xvHPfTJq52v8weFmB52up+DzqG2lyhGdoUQ1Muw
dRDLTLXLJrFdfpoOo7/j4Scr0rdc7/dpCn0DLcPuCoPxu+SkjEnVehFmZrGSv7Ga
x9dHr3DBh42fdlX/U/EnDuyosY0JU1gNF2/6FIA+bTTOFE3RxfN906RjslYQDjMZ
UAlSeLYHOZofdltI0YIr32vrxgdWQGZXPxU4XusDUc0z163OO+TGg7iUNWFZP5Qj
ubM7e0YbDX0NPIshk8us99YJmrWnhaix1/W5ryO3DXiGaQ7XFi9u7QofRqvRIctg
QXavdepkzJow9V9qpMECAJePIuICq7rm+xy+njjbuF436W7390bfVBwRr+FPADsl
jgQP4KvY5rykss30kheom8wNEbveWkhH5oTfH9b7O4KXJfpfJzrlgOWp2BD9JL8t
/M4HvFXTr2a75H/QbHK5OFrZeGATuv9OTxv7EZvnrPXU+DYTFldpu7TrNNqKCoj3
ZyXmc3Hhg5kskDhfHJppaeOayuhMOpT3ud1MFzROY5SLVIH8rBR12KUgsCUYQcGs
Iy0+0QvEGkjb4cAH1NK3VlbqVNsy1RmqRt2B28R2ueewDfTOoqkzt4MmzLqTdnAx
mTqmHmkEKhEf3K4MRNUPO2yieUg2COk5l6x9HhAnoxxeOZrTmcMsPY/UViG2HEPm
ybkCDQRj7TRDARAA9DZuKdfKq4Bs2+NwxC0aplljWOl8VIsEVg+Q8agD7/HU6/b6
Dry0njtWybn2x6Axf/nUdeOC01Fi1lmht/fpj6mRkgAvd/V6P10xnsUoykPSDSTh
P25MFFGW3JAA82bwdJ4AJpEQvTZG2nTb3237vlBiI1qHQrac8GYkju2O4UfySRN6
7cyi7bMf2pjWBBOEhaNy4b6CMDsb32P/N5J7sTE/TXgrS+u4ITIgjzSrkUkh5Z+B
8QVRa7xPIDZJdvZWTEXWu5fgRPZvxbr154GIkWJkFzlDoB1UcO56/uzRUuKhEV6o
HW3LMUuWdPMjpHpq8hrL0G2rDniJFUtbDFzHdZK1LUU3T2BJM8rjI3D/euph+IDT
27vl5qo72zCYE/iKzx4FMLZcQvx1kUAxkPX8l+dzZEwKeRIIpFDxQvatRtl+z0bM
jbkpDb+Yjv66sC4dYRpgTTGX6rok0PWHR3IxDNzyf2j8zQ4LFJ+rVBM1GjGSt6mG
j9TeL8CVeiSp4SuJ7I/FJVPHsKb50m+BDzeB31qTydNqh2kKr0DVAUa+TUsCr7e0
OYr8WE2adJcRXIW0qw50xXF+W7/05GqSCVD0dpeOUdBTQTsSkQmM3/0hcj9aVo9e
UDCM9RF0WRqiDAoHzJFfg+ztamkQI5HO6CklC4Ok22qrHRf6HDNYSuT6QFkAEQEA
AYkCPQQYAQoAJwMbIAQWIQQVim9TDqIC5fZRYRMU+upjRI4d+QUCaUbs9wUJCRwf
tAAKCRAU+upjRI4d+Y+cD/9yllG6uo934pcHNsVppZBfREFwSc8ywlbosCuSVpay
PjSqgrWwDrnqrsk0F2kUdC6rR3BIcXbn+lA9KqylH+cCXAJCkh8EDq6TlQ7Lt5EV
w1U0MAMXOyxPwDymQ/BO+iDyjXWkRRYgbF5XiFhCfGeuKyhkhACisAgNZ1uA1P5k
0SJYc14YfEhQkB46Y20SpfVHRsQ46FyNB6GHbmTmfoO8La8VTh++7GBdh85HfvkG
VNQ3wpi5oXsOLN9+MJOezc0XsW2LQsKQj1/J7QKzGh+lxN5cemsA5aqPzh8dyxeT
0lYRFp4AHkimqGUomVpRkbegMIPxXqOE+ZAmsddErw0UtmrKxcmMptOJwNgYzEgu
++2vtqerL/NYp+wsdcWaBjCz2F3NiwHgNli7NSB/FPwucZZ5gN5C4SnmeFzrGdHg
Oy+tQUN6ayQKljHeBO7CjMlsFNo/dcVrEMa1ShxBMqlj/6ivoEhktLz0Nru4FwNU
xE5SJYDYfpjD7Ws8y4LoXgWXjFHrMO6N9GzqLN/e8LT7I+w4ps2MrgJ8QSrelmQ3
rjkxp3uWp5v2lqy4rLfpi9iB6zIAeoN2eU1yOM9joxOYMxKYaYeYyP1Mm90wFol8
LcTSaN+tVniPddBiL6zvsGBEMbCR9XN3EQ+mErbuw5ovWBOCrr+dvN3FxvD11y4J
7w==
=mXYP
-----END PGP PUBLIC KEY BLOCK-----

View File

@@ -0,0 +1,51 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQENBFZu2zwBCADfatenjH3cvhlU6AeInvp4R0JmPBG942aghFj1Qh57smRcO5Bv
y9mqrX3UDdmVvu58V3k1k9/GzPnAG1t+c7ohdymv/AMuNY4pE2sfxx7bX+mncTHX
5wthipn8kTNm4WjREjCJM1Bm5sozzEZetED3+0/dWlnHl8b38evnLsD+WbSrDPVp
o6M6Eg9IfMwTfcXzdmLmSnGolBWDQ9i1a0x0r3o+sDW5UTnr7jVP+zILcnOZ1Ewl
Rn9OJ4Qg3ULM7WTMDYpKH4BO7RLR3aJgmsFAHp17vgUnzzFBZ10MCS3UOyUNoyph
xo3belf7Q9nrHcSNbqSeQuBnW/vafAZUreAlABEBAAG0IkVlbGNvIERvbHN0cmEg
PGVkb2xzdHJhQGdtYWlsLmNvbT6JATwEEwEIACYCGyMHCwkIBwMCAQYVCAIJCgsE
FgIDAQIeAQIXgAUCVm7etAIZAQAKCRCBcLRybXGY3q51B/96qt41tmcDSzrj/UTl
O6rErfW5zFvVsJTZ95Duwu87t/DVhw5lKBQcjALqVddufw1nMzyN/tSOMVDW8xe4
wMEdcU4+QAMzNX80enuyinsw1glxfLcK0+VbTvqNIfw0sG3MjPqNs6cK2VRfMHK4
paJjytBVICszNX9TfjLyIpKKoSSo1vqnT47LDZ5GIMy7l9Cs2sO/rqQHSPcR79yz
8m8tbHpDDEMZmJeklckKP2QoiqnHiIvlisDxLclYnUmNaPdaN/f++qZz5Yqvu1n+
sNUBA5eLaZH64Uy2SwtABxO3JPJ8nQ2+SFZ7ocFm4Gcdv4aM+Ura9S6fvM91tEJp
yAQOiQE5BBMBCAAjBQJWbts8AhsjBwsJCAcDAgEGFQgCCQoLBBYCAwECHgECF4AA
CgkQgXC0cm1xmN6sIAgAielxO8zJREqEkA2xudg/o4e9ZlNZ3X1NvY8OzJH/qlB2
SmwKqwifhtbC1K0uavXA7eaxdtd2zrI+Yq7IooUyv7juMjHTZhLcFbR5iVkQ4Mfp
JmeHXJ/ChYKxD5mMj/C3WbCZ91oCSNZ6Iyi5fvQj/691OC4q+y/2NEUcOI8D8cw8
XKHbKtceFYc+nZmdOv3ZZrNTSN/kszGViNNLKgnpPdDVPtLp+vjXtbmitiFG2HL/
WfbJ+3Gh2Yr1Vy3O9dWKH++e1AmIv7WWqmUjRFVpqC/wr7/BLaScWT8WKF5vkshU
gq8Ez1/cuizsgs3wQIZWgXKQK5njvwnbKg+Zmh/uGbQmRWVsY28gRG9sc3RyYSA8
ZWVsY28uZG9sc3RyYUB0d2VhZy5pbz6JAU4EEwEIADgWIQS1QdVTAScOC88Vyl2B
cLRybXGY3gUCXELt4gIbIwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRCBcLRy
bXGY3ujFCADfS5D1xHU8KH6TpqgssSggYVq62Wwn/Ga+4XPPetM+ajcXagyH6SwB
mxlHICcnv9xC93ryiTI10P1ADJl+aBsI66wEdHBU+ty4RTDy4JZNUPtmRCk9LhSc
mtUO3ry/wtWkRLdJxP49hg7BbQvWoU0M6WODp7SJjPKPWNX64mzHBeOuy+DqGCbM
lpGNCvW8ahU/ewbm7+xwWmzqLDoWzXjHsdF4QdzMVM/vkAgWEP4y0wEqFASzIYaR
GNEkBWU4OQVq5Bdm9+wWWAgsbM0FJAQl0GDqnz4QxWzxxCAAXdbh9F5ffafWYsA9
bise4ZQLkvYo6iUnrcFm4dtZbT8iL3gptCtFZWxjbyBEb2xzdHJhIDxlZWxjby5k
b2xzdHJhQGxvZ2ljYmxveC5jb20+iQE5BBMBCAAjBQJWbt6nAhsjBwsJCAcDAgEG
FQgCCQoLBBYCAwECHgECF4AACgkQgXC0cm1xmN4b/wf8DApMV/jSPEpibekrUPQu
Ye3Z8cxBQuRm/nOPowtPEH/ShAevrCdRiob2nuEZWNoqZ2e5/+6ud07Hs9bslvco
cDv1jeY1dof1idxfKhH3kfSpuD2XJhuzQBxBqOrIlCS/rdnW+Y9wOGD7+bs9QpcA
IyAeQGLLkfggAxaGYQ2Aev8pS7i3a/+lOWbFhcTe02I49KemCOJqBorG5FfILLNr
DjO3EoutNGpuz6rZvc/BlymphWBoAdUmxgoObr7NYWgw9pI8WeE6C7bbSOO7p5aQ
spWXU7Hm17DkzsVDpaJlyClllqK+DdKza5oWlBMe/P02jD3Y+0P/2rCCyQQwmH3D
RbkBDQRWbts8AQgA0g556xc08dH5YNEjbCwEt1j+XoRnV4+GfbSJIXOl9joIgzRC
4IaijvL8+4biWvX7HiybfvBKto0XB1AWLZRC3jWKX5p74I77UAcrD+VQ/roWQqlJ
BKbiQMlRYEsj/5Xnf72G90IP4DAFKvNl+rLChe+jUySA91BCtrYoP75Sw1BE9Cyz
xEtm4WUzKAJdXI+ZTBttA2Nbqy+GSuzBs7fSKDwREJaZmVrosvmns+pQVG4WPWf4
0l4mPguDQmZ9wSWZvBDkpG7AgHYDRYRGkMbAGsVfc6cScN2VsSTa6cbeeAEowKxM
qx9RbY3WOq6aKAm0qDvow1nl7WwXwe8K0wQxfQARAQABiQEfBBgBCAAJBQJWbts8
AhsMAAoJEIFwtHJtcZjeuAAH/0YNz2Qe1IAEO5oqEZNFOccL4KxVPrBhWUen83/b
C6PjOnOqv6q5ztAcms88WIKxBlfzIfq+dzJcbKVS/H7TEXgcaC+7EYW8sJVEsipN
BtEZ3LQNJ5coDjm7WZygniah1lfXNuiritAXduK5FWNNndqGArEaeZ8Shzdo/Uyi
b9lOsBIL6xc2ZcnX5f+rTu02LCEtEb0FwCycZLEWYf8hG4k8uttIOZOC+CLk/k8d
kBmPikMwUVTTV0CdT1cemQKdTaoAaK+kurF6FYXwcnjhRlHrisSt/tVMEwTw4LUM
3MYf6qfjjvE4HlDwZal8th7ccoQp/flfJIuRv85xCcKK+PI=
=u5cX
-----END PGP PUBLIC KEY BLOCK-----

View File

@@ -0,0 +1,13 @@
# Maintainer GPG Keys
Release tags are signed by members of the [Nix maintainer team](https://nixos.org/community/teams/nix/) as part of the [release process](../release-process.md). This directory contains the public GPG keys used for signing.
## Keys
- **Eelco Dolstra**
GPG Fingerprint: `B541 D553 0127 0E0B CF15 CA5D 8170 B472 6D71 98DE`
- **Sergei Zimmerman**
GPG Fingerprint: [`158A 6F53 0EA2 02E5 F651 6113 14FA EA63 448E 1DF9`](https://keys.openpgp.org/vks/v1/by-fingerprint/158A6F530EA202E5F651611314FAEA63448E1DF9)
<!-- TODO: Add keys for other Nix team members -->

View File

@@ -5,11 +5,11 @@
The release process is intended to create the following for each
release:
* A Git tag
* A signed Git tag (public keys in `maintainers/keys/`)
* Binary tarballs in https://releases.nixos.org/?prefix=nix/
* Docker images
* Docker images (arm64 and amd64 variants, uploaded to DockerHub and GHCR)
* Closures in https://cache.nixos.org
@@ -104,21 +104,17 @@ release:
evaluation ID (e.g. `1780832` in
`https://hydra.nixos.org/eval/1780832`).
* Tag the release and upload the release artifacts to
[`releases.nixos.org`](https://releases.nixos.org/) and [Docker Hub](https://hub.docker.com/):
* Tag the release:
```console
$ IS_LATEST=1 ./maintainers/upload-release.pl <EVAL-ID>
$ IS_LATEST=1 ./maintainers/upload-release.pl --skip-docker --skip-s3 --project-root $PWD <EVAL-ID>
```
Note: `IS_LATEST=1` causes the `latest-release` branch to be
force-updated. This is used by the `nixos.org` website to get the
[latest Nix manual](https://nixos.org/manual/nixpkgs/unstable/).
TODO: This script requires the right AWS credentials. Document.
TODO: This script currently requires a
`/home/eelco/Dev/nix-pristine`.
* Trigger the [`upload-release.yml` workflow](https://github.com/NixOS/nix/actions/workflows/upload-release.yml) via `workflow_dispatch` trigger. At the top click `Run workflow` -> select the current release branch from `Use workflow from` -> fill in `Hydra evaluation ID` with `<EVAL-ID>` value from previous steps -> click `Run workflow`. Wait for the run to be approved by `NixOS/nix-team` (or bypass checks if warranted). Wait for the workflow to succeed.
TODO: trigger nixos.org netlify: https://docs.netlify.com/configure-builds/build-hooks/
@@ -181,16 +177,18 @@ release:
* Wait for the desired evaluation of the maintenance jobset to finish
building.
* Run
* Tag the release
```console
$ IS_LATEST=1 ./maintainers/upload-release.pl <EVAL-ID>
$ IS_LATEST=1 ./maintainers/upload-release.pl --skip-docker --skip-s3 --project-root $PWD <EVAL-ID>
```
Omit `IS_LATEST=1` when creating a point release that is not on the
most recent stable branch. This prevents `nixos.org` to going back
to an older release.
* Trigger the [`upload-release.yml` workflow](https://github.com/NixOS/nix/actions/workflows/upload-release.yml) via `workflow_dispatch` trigger. At the top click `Run workflow` -> select the current release branch from `Use workflow from` -> fill in `Hydra evaluation ID` with `<EVAL-ID>` value from previous steps -> click `Run workflow`. Wait for the run to be approved by `NixOS/nix-team` (or bypass checks if warranted). Wait for the workflow to succeed.
* Bump the version number of the release branch as above (e.g. to
`2.12.2`).

View File

@@ -1,7 +1,8 @@
#! /usr/bin/env nix-shell
#! nix-shell -i perl -p perl perlPackages.LWPUserAgent perlPackages.LWPProtocolHttps perlPackages.FileSlurp perlPackages.NetAmazonS3 gnupg1
#! nix-shell -i perl -p awscli2 perl perlPackages.LWPUserAgent perlPackages.LWPProtocolHttps perlPackages.FileSlurp perlPackages.NetAmazonS3 perlPackages.GetoptLongDescriptive gnupg1
use strict;
use Getopt::Long::Descriptive;
use Data::Dumper;
use File::Basename;
use File::Path;
@@ -13,7 +14,30 @@ use Net::Amazon::S3;
delete $ENV{'shell'}; # shut up a LWP::UserAgent.pm warning
my $evalId = $ARGV[0] or die "Usage: $0 EVAL-ID\n";
my ($opt, $usage) = describe_options(
'%c %o <eval-id>',
[ 'skip-docker', 'Skip Docker image upload' ],
[ 'skip-git', 'Skip Git tagging' ],
[ 'skip-s3', 'Skip S3 upload' ],
[ 'docker-owner=s', 'Docker image owner', { default => 'nixos/nix' } ],
[ 'project-root=s', 'Pristine git repository path' ],
[ 's3-endpoint=s', 'Custom S3 endpoint' ],
[ 's3-host=s', 'S3 host', { default => 's3-eu-west-1.amazonaws.com' } ],
[],
[ 'help|h', 'Show this help message', { shortcircuit => 1 } ],
[],
[ 'Environment variables:' ],
[ 'AWS_ACCESS_KEY_ID' ],
[ 'AWS_SECRET_ACCESS_KEY' ],
[ 'AWS_SESSION_TOKEN For OIDC' ],
[ 'IS_LATEST Set to "1" to mark as latest release' ],
);
print($usage->text), exit if $opt->help;
my $evalId = $ARGV[0] or do { print STDERR $usage->text; exit 1 };
die "--project-root is required unless --skip-git is specified\n" unless $opt->skip_git || $opt->project_root;
my $releasesBucketName = "nix-releases";
my $channelsBucketName = "nix-channels";
@@ -62,25 +86,38 @@ File::Path::make_path($narCache);
my $binaryCache = "https://cache.nixos.org/?local-nar-cache=$narCache";
# S3 setup.
my $aws_access_key_id = $ENV{'AWS_ACCESS_KEY_ID'} or die "No AWS_ACCESS_KEY_ID given.";
my $aws_secret_access_key = $ENV{'AWS_SECRET_ACCESS_KEY'} or die "No AWS_SECRET_ACCESS_KEY given.";
my $aws_access_key_id = $ENV{'AWS_ACCESS_KEY_ID'};
my $aws_secret_access_key = $ENV{'AWS_SECRET_ACCESS_KEY'};
my $aws_session_token = $ENV{'AWS_SESSION_TOKEN'};
my $s3 = Net::Amazon::S3->new(
{ aws_access_key_id => $aws_access_key_id,
aws_secret_access_key => $aws_secret_access_key,
retry => 1,
host => "s3-eu-west-1.amazonaws.com",
});
my ($s3, $releasesBucket, $s3_channels, $channelsBucket);
my $releasesBucket = $s3->bucket($releasesBucketName) or die;
unless ($opt->skip_s3) {
$aws_access_key_id or die "No AWS_ACCESS_KEY_ID given.";
$aws_secret_access_key or die "No AWS_SECRET_ACCESS_KEY given.";
my $s3_us = Net::Amazon::S3->new(
{ aws_access_key_id => $aws_access_key_id,
aws_secret_access_key => $aws_secret_access_key,
retry => 1,
});
$s3 = Net::Amazon::S3->new(
{ aws_access_key_id => $aws_access_key_id,
aws_secret_access_key => $aws_secret_access_key,
$aws_session_token ? (aws_session_token => $aws_session_token) : (),
retry => 1,
host => $opt->s3_host,
secure => ($opt->s3_endpoint && $opt->s3_endpoint =~ /^http:/) ? 0 : 1,
});
my $channelsBucket = $s3_us->bucket($channelsBucketName) or die;
$releasesBucket = $s3->bucket($releasesBucketName) or die;
$s3_channels = Net::Amazon::S3->new(
{ aws_access_key_id => $aws_access_key_id,
aws_secret_access_key => $aws_secret_access_key,
$aws_session_token ? (aws_session_token => $aws_session_token) : (),
retry => 1,
$opt->s3_endpoint ? (host => $opt->s3_host) : (),
$opt->s3_endpoint ? (secure => ($opt->s3_endpoint =~ /^http:/) ? 0 : 1) : (),
});
$channelsBucket = $s3_channels->bucket($channelsBucketName) or die;
}
sub getStorePath {
my ($jobName, $output) = @_;
@@ -115,11 +152,12 @@ sub copyManual {
File::Path::remove_tree("$tmpDir/manual.tmp", {safe => 1});
}
system("aws s3 sync '$tmpDir/manual' s3://$releasesBucketName/$releaseDir/manual") == 0
my $awsEndpoint = $opt->s3_endpoint ? "--endpoint-url " . $opt->s3_endpoint : "";
system("aws $awsEndpoint s3 sync '$tmpDir/manual' s3://$releasesBucketName/$releaseDir/manual") == 0
or die "syncing manual to S3\n";
}
copyManual;
copyManual unless $opt->skip_s3;
sub downloadFile {
my ($jobName, $productNr, $dstName) = @_;
@@ -158,30 +196,12 @@ sub downloadFile {
return $sha256_expected;
}
downloadFile("binaryTarball.i686-linux", "1");
downloadFile("binaryTarball.x86_64-linux", "1");
downloadFile("binaryTarball.aarch64-linux", "1");
downloadFile("binaryTarball.x86_64-darwin", "1");
downloadFile("binaryTarball.aarch64-darwin", "1");
eval {
downloadFile("binaryTarballCross.x86_64-linux.armv6l-unknown-linux-gnueabihf", "1");
};
warn "$@" if $@;
eval {
downloadFile("binaryTarballCross.x86_64-linux.armv7l-unknown-linux-gnueabihf", "1");
};
warn "$@" if $@;
eval {
downloadFile("binaryTarballCross.x86_64-linux.riscv64-unknown-linux-gnu", "1");
};
warn "$@" if $@;
downloadFile("installerScript", "1");
# Upload docker images to dockerhub.
# Upload docker images.
my $dockerManifest = "";
my $dockerManifestLatest = "";
my $haveDocker = 0;
unless ($opt->skip_docker) {
for my $platforms (["x86_64-linux", "amd64"], ["aarch64-linux", "arm64"]) {
my $system = $platforms->[0];
my $dockerPlatform = $platforms->[1];
@@ -195,8 +215,8 @@ for my $platforms (["x86_64-linux", "amd64"], ["aarch64-linux", "arm64"]) {
print STDERR "loading docker image for $dockerPlatform...\n";
system("docker load -i $tmpDir/$fn") == 0 or die;
my $tag = "nixos/nix:$version-$dockerPlatform";
my $latestTag = "nixos/nix:latest-$dockerPlatform";
my $tag = $opt->docker_owner . ":$version-$dockerPlatform";
my $latestTag = $opt->docker_owner . ":latest-$dockerPlatform";
print STDERR "tagging $version docker image for $dockerPlatform...\n";
system("docker tag nix:$version $tag") == 0 or die;
@@ -219,68 +239,94 @@ for my $platforms (["x86_64-linux", "amd64"], ["aarch64-linux", "arm64"]) {
}
if ($haveDocker) {
my $dockerOwner = $opt->docker_owner;
print STDERR "creating multi-platform docker manifest...\n";
system("docker manifest rm nixos/nix:$version");
system("docker manifest create nixos/nix:$version $dockerManifest") == 0 or die;
system("docker manifest rm $dockerOwner:$version");
system("docker manifest create $dockerOwner:$version $dockerManifest") == 0 or die;
if ($isLatest) {
print STDERR "creating latest multi-platform docker manifest...\n";
system("docker manifest rm nixos/nix:latest");
system("docker manifest create nixos/nix:latest $dockerManifestLatest") == 0 or die;
system("docker manifest rm $dockerOwner:latest");
system("docker manifest create $dockerOwner:latest $dockerManifestLatest") == 0 or die;
}
print STDERR "pushing multi-platform docker manifest...\n";
system("docker manifest push nixos/nix:$version") == 0 or die;
system("docker manifest push $dockerOwner:$version") == 0 or die;
if ($isLatest) {
print STDERR "pushing latest multi-platform docker manifest...\n";
system("docker manifest push nixos/nix:latest") == 0 or die;
system("docker manifest push $dockerOwner:latest") == 0 or die;
}
}
}
# Upload nix-fallback-paths.nix.
write_file("$tmpDir/fallback-paths.nix",
"{\n" .
" x86_64-linux = \"" . getStorePath("build.nix-everything.x86_64-linux") . "\";\n" .
" i686-linux = \"" . getStorePath("build.nix-everything.i686-linux") . "\";\n" .
" aarch64-linux = \"" . getStorePath("build.nix-everything.aarch64-linux") . "\";\n" .
" riscv64-linux = \"" . getStorePath("buildCross.nix-everything.riscv64-unknown-linux-gnu.x86_64-linux") . "\";\n" .
" x86_64-darwin = \"" . getStorePath("build.nix-everything.x86_64-darwin") . "\";\n" .
" aarch64-darwin = \"" . getStorePath("build.nix-everything.aarch64-darwin") . "\";\n" .
"}\n");
# Upload release files to S3.
for my $fn (glob "$tmpDir/*") {
my $name = basename($fn);
next if $name eq "manual";
my $dstKey = "$releaseDir/" . $name;
unless (defined $releasesBucket->head_key($dstKey)) {
print STDERR "uploading $fn to s3://$releasesBucketName/$dstKey...\n";
unless ($opt->skip_s3) {
downloadFile("binaryTarball.i686-linux", "1");
downloadFile("binaryTarball.x86_64-linux", "1");
downloadFile("binaryTarball.aarch64-linux", "1");
downloadFile("binaryTarball.x86_64-darwin", "1");
downloadFile("binaryTarball.aarch64-darwin", "1");
eval {
downloadFile("binaryTarballCross.x86_64-linux.armv6l-unknown-linux-gnueabihf", "1");
};
warn "$@" if $@;
eval {
downloadFile("binaryTarballCross.x86_64-linux.armv7l-unknown-linux-gnueabihf", "1");
};
warn "$@" if $@;
eval {
downloadFile("binaryTarballCross.x86_64-linux.riscv64-unknown-linux-gnu", "1");
};
warn "$@" if $@;
downloadFile("installerScript", "1");
my $configuration = ();
$configuration->{content_type} = "application/octet-stream";
# Upload nix-fallback-paths.nix.
write_file("$tmpDir/fallback-paths.nix",
"{\n" .
" x86_64-linux = \"" . getStorePath("build.nix-everything.x86_64-linux") . "\";\n" .
" i686-linux = \"" . getStorePath("build.nix-everything.i686-linux") . "\";\n" .
" aarch64-linux = \"" . getStorePath("build.nix-everything.aarch64-linux") . "\";\n" .
" riscv64-linux = \"" . getStorePath("buildCross.nix-everything.riscv64-unknown-linux-gnu.x86_64-linux") . "\";\n" .
" x86_64-darwin = \"" . getStorePath("build.nix-everything.x86_64-darwin") . "\";\n" .
" aarch64-darwin = \"" . getStorePath("build.nix-everything.aarch64-darwin") . "\";\n" .
"}\n");
if ($fn =~ /.sha256|install|\.nix$/) {
$configuration->{content_type} = "text/plain";
for my $fn (glob "$tmpDir/*") {
my $name = basename($fn);
next if $name eq "manual";
my $dstKey = "$releaseDir/" . $name;
unless (defined $releasesBucket->head_key($dstKey)) {
print STDERR "uploading $fn to s3://$releasesBucketName/$dstKey...\n";
my $configuration = ();
$configuration->{content_type} = "application/octet-stream";
if ($fn =~ /.sha256|install|\.nix$/) {
$configuration->{content_type} = "text/plain";
}
$releasesBucket->add_key_filename($dstKey, $fn, $configuration)
or die $releasesBucket->err . ": " . $releasesBucket->errstr;
}
$releasesBucket->add_key_filename($dstKey, $fn, $configuration)
or die $releasesBucket->err . ": " . $releasesBucket->errstr;
}
# Update the "latest" symlink.
$channelsBucket->add_key(
"nix-latest/install", "",
{ "x-amz-website-redirect-location" => "https://releases.nixos.org/$releaseDir/install" })
or die $channelsBucket->err . ": " . $channelsBucket->errstr
if $isLatest;
}
# Update the "latest" symlink.
$channelsBucket->add_key(
"nix-latest/install", "",
{ "x-amz-website-redirect-location" => "https://releases.nixos.org/$releaseDir/install" })
or die $channelsBucket->err . ": " . $channelsBucket->errstr
if $isLatest;
# Tag the release in Git.
chdir("/home/eelco/Dev/nix-pristine") or die;
system("git remote update origin") == 0 or die;
system("git tag --force --sign $version $nixRev -m 'Tagging release $version'") == 0 or die;
system("git push --tags") == 0 or die;
system("git push --force-with-lease origin $nixRev:refs/heads/latest-release") == 0 or die if $isLatest;
unless ($opt->skip_git) {
chdir($opt->project_root) or die "Cannot chdir to " . $opt->project_root . ": $!";
system("git remote update origin") == 0 or die;
system("git tag --force --sign $version $nixRev -m 'Tagging release $version'") == 0 or die;
system("git push origin refs/tags/$version") == 0 or die;
system("git push --force-with-lease origin $nixRev:refs/heads/latest-release") == 0 or die if $isLatest;
}
File::Path::remove_tree($narCache, {safe => 1});
File::Path::remove_tree($tmpDir, {safe => 1});

View File

@@ -429,6 +429,15 @@ in
The manual as would be published on https://nix.dev/reference/nix-manual
*/
nix-manual = callPackage ../doc/manual/package.nix { version = fineVersion; };
/**
Manpages only (no HTML manual, no mdbook dependency)
*/
nix-manual-manpages-only = callPackage ../doc/manual/package.nix {
version = fineVersion;
buildHtmlManual = false;
};
/**
Doxygen pages for C++ code
*/

View File

@@ -39,7 +39,7 @@ scope: {
nativeBuildInputs = prevAttrs.nativeBuildInputs ++ [ pkgs.buildPackages.bmake ];
postInstall =
lib.replaceStrings [ "lowdown.so.1" "lowdown.1.dylib" ] [ "lowdown.so.2" "lowdown.2.dylib" ]
prevAttrs.postInstall;
(prevAttrs.postInstall or "");
});
# TODO: Remove this when https://github.com/NixOS/nixpkgs/pull/442682 is included in a stable release

View File

@@ -148,6 +148,15 @@ pkgs.nixComponents2.nix-util.overrideAttrs (
isInternal =
dep: internalDrvs ? ${builtins.unsafeDiscardStringContext dep.drvPath or "_non-existent_"};
activeComponentNames = lib.listToAttrs (
map (c: {
name = c.pname or c.name;
value = null;
}) activeComponents
);
isActiveComponent = name: activeComponentNames ? ${name};
in
{
pname = "shell-for-nix";
@@ -190,27 +199,19 @@ pkgs.nixComponents2.nix-util.overrideAttrs (
}
);
small =
(finalAttrs.finalPackage.withActiveComponents (
c:
lib.intersectAttrs (lib.genAttrs [
"nix-cli"
"nix-util-tests"
"nix-store-tests"
"nix-expr-tests"
"nix-fetchers-tests"
"nix-flake-tests"
"nix-functional-tests"
"nix-perl-bindings"
] (_: null)) c
)).overrideAttrs
(o: {
mesonFlags = o.mesonFlags ++ [
# TODO: infer from activeComponents or vice versa
"-Dkaitai-struct-checks=false"
"-Djson-schema-checks=false"
];
});
small = finalAttrs.finalPackage.withActiveComponents (
c:
lib.intersectAttrs (lib.genAttrs [
"nix-cli"
"nix-util-tests"
"nix-store-tests"
"nix-expr-tests"
"nix-fetchers-tests"
"nix-flake-tests"
"nix-functional-tests"
"nix-perl-bindings"
] (_: null)) c
);
};
# Remove the version suffix to avoid unnecessary attempts to substitute in nix develop
@@ -275,21 +276,33 @@ pkgs.nixComponents2.nix-util.overrideAttrs (
dontUseCmakeConfigure = true;
mesonFlags =
map (transformFlag "libutil") (ignoreCrossFile pkgs.nixComponents2.nix-util.mesonFlags)
++ map (transformFlag "libstore") (ignoreCrossFile pkgs.nixComponents2.nix-store.mesonFlags)
++ map (transformFlag "libfetchers") (ignoreCrossFile pkgs.nixComponents2.nix-fetchers.mesonFlags)
++ lib.optionals havePerl (
map (transformFlag "perl") (ignoreCrossFile pkgs.nixComponents2.nix-perl-bindings.mesonFlags)
)
++ map (transformFlag "libexpr") (ignoreCrossFile pkgs.nixComponents2.nix-expr.mesonFlags)
++ map (transformFlag "libcmd") (ignoreCrossFile pkgs.nixComponents2.nix-cmd.mesonFlags);
mesonFlags = [
(lib.mesonBool "kaitai-struct-checks" (isActiveComponent "nix-kaitai-struct-checks"))
(lib.mesonBool "json-schema-checks" (isActiveComponent "nix-json-schema-checks"))
]
++ map (transformFlag "libutil") (ignoreCrossFile pkgs.nixComponents2.nix-util.mesonFlags)
++ map (transformFlag "libstore") (ignoreCrossFile pkgs.nixComponents2.nix-store.mesonFlags)
++ map (transformFlag "libfetchers") (ignoreCrossFile pkgs.nixComponents2.nix-fetchers.mesonFlags)
++ lib.optionals havePerl (
map (transformFlag "perl") (ignoreCrossFile pkgs.nixComponents2.nix-perl-bindings.mesonFlags)
)
++ map (transformFlag "libexpr") (ignoreCrossFile pkgs.nixComponents2.nix-expr.mesonFlags)
++ map (transformFlag "libcmd") (ignoreCrossFile pkgs.nixComponents2.nix-cmd.mesonFlags);
nativeBuildInputs =
let
inputs =
dedupByString (v: "${v}") (
lib.filter (x: !isInternal x) (lib.lists.concatMap (c: c.nativeBuildInputs) activeComponents)
lib.filter (x: !isInternal x) (
lib.lists.concatMap (
# Nix manual has a build-time dependency on nix, but we
# don't want to do a native build just to enter the ross
# dev shell.
#
# TODO: think of a more principled fix for this.
c: lib.filter (f: f.pname or null != "nix") c.nativeBuildInputs
) activeComponents
)
)
++ lib.optional (
!buildCanExecuteHost
@@ -305,8 +318,8 @@ pkgs.nixComponents2.nix-util.overrideAttrs (
pkgs.buildPackages.nixfmt-rfc-style
pkgs.buildPackages.shellcheck
pkgs.buildPackages.include-what-you-use
pkgs.buildPackages.gdb
]
++ lib.optional pkgs.hostPlatform.isUnix pkgs.buildPackages.gdb
++ lib.optional (stdenv.cc.isClang && stdenv.hostPlatform == stdenv.buildPlatform) (
lib.hiPrio pkgs.buildPackages.clang-tools
)
@@ -322,13 +335,13 @@ pkgs.nixComponents2.nix-util.overrideAttrs (
)
);
buildInputs = [
pkgs.gbenchmark
]
++ dedupByString (v: "${v}") (
lib.filter (x: !isInternal x) (lib.lists.concatMap (c: c.buildInputs) activeComponents)
)
++ lib.optional havePerl pkgs.perl;
buildInputs =
# TODO change Nixpkgs to mark gbenchmark as building on Windows
lib.optional pkgs.hostPlatform.isUnix pkgs.gbenchmark
++ dedupByString (v: "${v}") (
lib.filter (x: !isInternal x) (lib.lists.concatMap (c: c.buildInputs) activeComponents)
)
++ lib.optional havePerl pkgs.perl;
propagatedBuildInputs = dedupByString (v: "${v}") (
lib.filter (x: !isInternal x) (lib.lists.concatMap (c: c.propagatedBuildInputs) activeComponents)

View File

@@ -63,15 +63,16 @@ let
"nix-cli"
"nix-functional-tests"
"nix-json-schema-checks"
"nix-kaitai-struct-checks"
]
++ lib.optionals enableBindings [
"nix-perl-bindings"
]
++ lib.optionals enableDocs [
"nix-manual"
"nix-manual-manpages-only"
"nix-internal-api-docs"
"nix-external-api-docs"
"nix-kaitai-struct-checks"
]
);
in

View File

@@ -0,0 +1 @@
../libstore-tests/data/derivation

View File

@@ -0,0 +1 @@
../../src/libutil-tests/data/memory-source-accessor

View File

@@ -20,14 +20,20 @@ schema_dir = meson.current_source_dir() / 'schema'
# Get all example files
schemas = [
{
'stem' : 'file-system-object',
'schema' : schema_dir / 'file-system-object-v1.yaml',
'files' : [
'simple.json',
'complex.json',
],
},
{
'stem' : 'hash',
'schema' : schema_dir / 'hash-v1.yaml',
'files' : [
'sha256-base64.json',
'sha256-base16.json',
'sha256-nix32.json',
'blake3-base64.json',
'sha256.json',
'blake3.json',
],
},
{
@@ -63,6 +69,18 @@ schemas = [
'with-signature.json',
],
},
{
'stem' : 'derivation-options',
'schema' : schema_dir / 'derivation-options-v1.yaml',
'files' : [
'ia' / 'derivation-options' / 'defaults.json',
'ia' / 'derivation-options' / 'all_set.json',
'ia' / 'derivation-options' / 'structuredAttrs_defaults.json',
'ia' / 'derivation-options' / 'structuredAttrs_all_set.json',
'ca' / 'derivation-options' / 'all_set.json',
'ca' / 'derivation-options' / 'structuredAttrs_all_set.json',
],
},
]
# Derivation and Derivation output
@@ -136,18 +154,18 @@ schemas += [
'stem' : 'store-object-info',
'schema' : schema_dir / 'store-object-info-v2.yaml',
'files' : [
'pure.json',
'impure.json',
'empty_pure.json',
'empty_impure.json',
'json-2' / 'pure.json',
'json-2' / 'impure.json',
'json-2' / 'empty_pure.json',
'json-2' / 'empty_impure.json',
],
},
{
'stem' : 'nar-info',
'schema' : schema_dir / 'store-object-info-v2.yaml',
'files' : [
'pure.json',
'impure.json',
'json-2' / 'pure.json',
'json-2' / 'impure.json',
],
},
{
@@ -164,30 +182,43 @@ schemas += [
'stem' : 'store-object-info',
'schema' : schema_dir / 'store-object-info-v2.yaml#/$defs/base',
'files' : [
'pure.json',
'empty_pure.json',
'json-2' / 'pure.json',
'json-2' / 'empty_pure.json',
],
},
{
'stem' : 'store-object-info',
'schema' : schema_dir / 'store-object-info-v2.yaml#/$defs/impure',
'files' : [
'impure.json',
'empty_impure.json',
'json-2' / 'impure.json',
'json-2' / 'empty_impure.json',
],
},
{
'stem' : 'nar-info',
'schema' : schema_dir / 'store-object-info-v2.yaml#/$defs/base',
'files' : [
'pure.json',
'json-2' / 'pure.json',
],
},
{
'stem' : 'nar-info',
'schema' : schema_dir / 'store-object-info-v2.yaml#/$defs/narInfo',
'files' : [
'impure.json',
'json-2' / 'impure.json',
],
},
]
# Dummy store
schemas += [
{
'stem' : 'store',
'schema' : schema_dir / 'store-v1.yaml',
'files' : [
'empty.json',
'one-flat-file.json',
'one-derivation.json',
],
},
]

View File

@@ -20,6 +20,7 @@ mkMesonDerivation (finalAttrs: {
fileset = lib.fileset.unions [
../../.version
../../doc/manual/source/protocols/json/schema
../../src/libutil-tests/data/memory-source-accessor
../../src/libutil-tests/data/hash
../../src/libstore-tests/data/content-address
../../src/libstore-tests/data/store-path
@@ -29,6 +30,7 @@ mkMesonDerivation (finalAttrs: {
../../src/libstore-tests/data/path-info
../../src/libstore-tests/data/nar-info
../../src/libstore-tests/data/build-result
../../src/libstore-tests/data/dummy-store
./.
];

View File

@@ -0,0 +1 @@
../../src/libstore-tests/data/dummy-store

View File

@@ -297,7 +297,7 @@ void MixProfile::updateProfile(const BuiltPaths & buildables)
MixDefaultProfile::MixDefaultProfile()
{
profile = getDefaultProfile();
profile = getDefaultProfile().string();
}
MixEnvironment::MixEnvironment()
@@ -391,7 +391,7 @@ void createOutLinks(const std::filesystem::path & outLink, const BuiltPaths & bu
auto symlink = outLink;
if (i)
symlink += fmt("-%d", i);
store.addPermRoot(bo.path, absPath(symlink.string()));
store.addPermRoot(bo.path, absPath(symlink).string());
},
[&](const BuiltPath::Built & bfd) {
for (auto & output : bfd.outputs) {
@@ -400,7 +400,7 @@ void createOutLinks(const std::filesystem::path & outLink, const BuiltPaths & bu
symlink += fmt("-%d", i);
if (output.first != "out")
symlink += fmt("-%s", output.first);
store.addPermRoot(output.second, absPath(symlink.string()));
store.addPermRoot(output.second, absPath(symlink).string());
}
},
},

View File

@@ -165,19 +165,19 @@ Bindings * MixEvalArgs::getAutoArgs(EvalState & state)
state.parseExprFromString(
arg.expr,
compatibilitySettings.nixShellShebangArgumentsRelativeToScript
? state.rootPath(absPath(getCommandBaseDir()))
? state.rootPath(absPath(getCommandBaseDir()).string())
: state.rootPath(".")));
},
[&](const AutoArgString & arg) { v->mkString(arg.s); },
[&](const AutoArgFile & arg) { v->mkString(readFile(arg.path.string())); },
[&](const AutoArgStdin & arg) { v->mkString(readFile(STDIN_FILENO)); }},
[&](const AutoArgString & arg) { v->mkString(arg.s, state.mem); },
[&](const AutoArgFile & arg) { v->mkString(readFile(arg.path.string()), state.mem); },
[&](const AutoArgStdin & arg) { v->mkString(readFile(STDIN_FILENO), state.mem); }},
arg);
res.insert(state.symbols.create(name), v);
}
return res.finish();
}
SourcePath lookupFileArg(EvalState & state, std::string_view s, const Path * baseDir)
SourcePath lookupFileArg(EvalState & state, std::string_view s, const std::filesystem::path * baseDir)
{
if (EvalSettings::isPseudoUrl(s)) {
auto accessor = fetchers::downloadTarball(*state.store, state.fetchSettings, EvalSettings::resolvePseudoUrl(s));
@@ -197,12 +197,13 @@ SourcePath lookupFileArg(EvalState & state, std::string_view s, const Path * bas
}
else if (s.size() > 2 && s.at(0) == '<' && s.at(s.size() - 1) == '>') {
Path p(s.substr(1, s.size() - 2));
// Should perhaps be a `CanonPath`?
std::string p(s.substr(1, s.size() - 2));
return state.findFile(p);
}
else
return state.rootPath(baseDir ? absPath(s, *baseDir) : absPath(s));
return state.rootPath(absPath(std::filesystem::path{s}, baseDir).string());
}
} // namespace nix

View File

@@ -134,7 +134,7 @@ struct MixFlakeOptions : virtual Args, EvalCommand
struct SourceExprCommand : virtual Args, MixFlakeOptions
{
std::optional<Path> file;
std::optional<std::filesystem::path> file;
std::optional<std::string> expr;
SourceExprCommand();
@@ -310,7 +310,7 @@ static RegisterCommand registerCommand2(std::vector<std::string> && name)
struct MixProfile : virtual StoreCommand
{
std::optional<Path> profile;
std::optional<std::filesystem::path> profile;
MixProfile();

View File

@@ -84,6 +84,6 @@ private:
/**
* @param baseDir Optional [base directory](https://nix.dev/manual/nix/development/glossary#gloss-base-directory)
*/
SourcePath lookupFileArg(EvalState & state, std::string_view s, const Path * baseDir = nullptr);
SourcePath lookupFileArg(EvalState & state, std::string_view s, const std::filesystem::path * baseDir = nullptr);
} // namespace nix

View File

@@ -17,7 +17,7 @@ class AttrCursor;
struct App
{
std::vector<DerivedPath> context;
Path program;
std::filesystem::path program;
// FIXME: add args, sandbox settings, metadata, ...
};

View File

@@ -19,7 +19,16 @@ struct AbstractNixRepl
typedef std::vector<std::pair<Value *, std::string>> AnnotatedValues;
using RunNix = void(Path program, const Strings & args, const std::optional<std::string> & input);
/**
* Run a nix executable
*
* @todo this is a layer violation
*
* @param programName Name of the command, e.g. `nix` or `nix-env`.
* @param args aguments to the command.
*/
using RunNix =
void(const std::string & programName, const Strings & args, const std::optional<std::string> & input);
/**
* @param runNix Function to run the nix CLI to support various

View File

@@ -171,7 +171,7 @@ std::vector<ref<eval_cache::AttrCursor>> InstallableFlake::getCursors(EvalState
for (auto & attrPath : attrPaths) {
debug("trying flake output attribute '%s'", attrPath);
auto attr = root->findAlongAttrPath(parseAttrPath(state, attrPath));
auto attr = root->findAlongAttrPath(AttrPath::parse(state, attrPath));
if (attr) {
res.push_back(ref(*attr));
} else {

View File

@@ -132,7 +132,7 @@ MixFlakeOptions::MixFlakeOptions()
lockFlags.writeLockFile = false;
lockFlags.inputOverrides.insert_or_assign(
flake::parseInputAttrPath(inputAttrPath),
parseFlakeRef(fetchSettings, flakeRef, absPath(getCommandBaseDir()), true));
parseFlakeRef(fetchSettings, flakeRef, absPath(getCommandBaseDir()).string(), true));
}},
.completer = {[&](AddCompletions & completions, size_t n, std::string_view prefix) {
if (n == 0) {
@@ -173,7 +173,7 @@ MixFlakeOptions::MixFlakeOptions()
auto flake = flake::lockFlake(
flakeSettings,
*evalState,
parseFlakeRef(fetchSettings, flakeRef, absPath(getCommandBaseDir())),
parseFlakeRef(fetchSettings, flakeRef, absPath(getCommandBaseDir()).string()),
{.writeLockFile = false});
for (auto & [inputName, input] : flake.lockFile.root->inputs) {
auto input2 = flake.lockFile.findInput({inputName}); // resolve 'follows' nodes
@@ -263,7 +263,7 @@ void SourceExprCommand::completeInstallable(AddCompletions & completions, std::s
evalSettings.pureEval = false;
auto state = getEvalState();
auto e = state->parseExprFromFile(resolveExprPath(lookupFileArg(*state, *file)));
auto e = state->parseExprFromFile(resolveExprPath(lookupFileArg(*state, file->string())));
Value root;
state->eval(e, root);
@@ -355,9 +355,9 @@ void completeFlakeRefWithFragment(
attrPathPrefixes.push_back("");
for (auto & attrPathPrefixS : attrPathPrefixes) {
auto attrPathPrefix = parseAttrPath(*evalState, attrPathPrefixS);
auto attrPathPrefix = AttrPath::parse(*evalState, attrPathPrefixS);
auto attrPathS = attrPathPrefixS + std::string(fragment);
auto attrPath = parseAttrPath(*evalState, attrPathS);
auto attrPath = AttrPath::parse(*evalState, attrPathS);
std::string lastAttr;
if (!attrPath.empty() && !hasSuffix(attrPathS, ".")) {
@@ -375,9 +375,7 @@ void completeFlakeRefWithFragment(
/* Strip the attrpath prefix. */
attrPath2.erase(attrPath2.begin(), attrPath2.begin() + attrPathPrefix.size());
// FIXME: handle names with dots
completions.add(
flakeRefS + "#" + prefixRoot
+ concatStringsSep(".", evalState->symbols.resolve(attrPath2)));
completions.add(flakeRefS + "#" + prefixRoot + attrPath2.to_string(*evalState));
}
}
}
@@ -386,7 +384,7 @@ void completeFlakeRefWithFragment(
attrpaths. */
if (fragment.empty()) {
for (auto & attrPath : defaultFlakeAttrPaths) {
auto attr = root->findAlongAttrPath(parseAttrPath(*evalState, attrPath));
auto attr = root->findAlongAttrPath(AttrPath::parse(*evalState, attrPath));
if (!attr)
continue;
completions.add(flakeRefS + "#" + prefixRoot);
@@ -465,10 +463,10 @@ Installables SourceExprCommand::parseInstallables(ref<Store> store, std::vector<
state->eval(e, *vFile);
} else if (file) {
auto dir = absPath(getCommandBaseDir());
state->evalFile(lookupFileArg(*state, *file, &dir), *vFile);
state->evalFile(lookupFileArg(*state, file->string(), &dir), *vFile);
} else {
Path dir = absPath(getCommandBaseDir());
auto e = state->parseExprFromString(*expr, state->rootPath(dir));
auto dir = absPath(getCommandBaseDir());
auto e = state->parseExprFromString(*expr, state->rootPath(dir.string()));
state->eval(e, *vFile);
}
@@ -801,7 +799,8 @@ std::vector<FlakeRef> RawInstallablesCommand::getFlakeRefsForCompletion()
std::vector<FlakeRef> res;
res.reserve(rawInstallables.size());
for (const auto & i : rawInstallables)
res.push_back(parseFlakeRefWithFragment(fetchSettings, expandTilde(i), absPath(getCommandBaseDir())).first);
res.push_back(
parseFlakeRefWithFragment(fetchSettings, expandTilde(i), absPath(getCommandBaseDir()).string()).first);
return res;
}
@@ -820,7 +819,8 @@ void RawInstallablesCommand::run(ref<Store> store)
std::vector<FlakeRef> InstallableCommand::getFlakeRefsForCompletion()
{
return {parseFlakeRefWithFragment(fetchSettings, expandTilde(_installable), absPath(getCommandBaseDir())).first};
return {parseFlakeRefWithFragment(fetchSettings, expandTilde(_installable), absPath(getCommandBaseDir()).string())
.first};
}
void InstallablesCommand::run(ref<Store> store, std::vector<std::string> && rawInstallables)

View File

@@ -58,8 +58,7 @@ struct NixRepl : AbstractNixRepl, detail::ReplCompleterMixin, gc
{
size_t debugTraceIndex;
// Arguments passed to :load, saved so they can be reloaded with :reload
Strings loadedFiles;
std::list<std::filesystem::path> loadedFiles;
// Arguments passed to :load-flake, saved so they can be reloaded with :reload
Strings loadedFlakes;
std::function<AnnotatedValues()> getValues;
@@ -73,7 +72,7 @@ struct NixRepl : AbstractNixRepl, detail::ReplCompleterMixin, gc
RunNix * runNixPtr;
void runNix(Path program, const Strings & args, const std::optional<std::string> & input = {});
void runNix(const std::string & program, const Strings & args, const std::optional<std::string> & input = {});
std::unique_ptr<ReplInteracter> interacter;
@@ -92,7 +91,7 @@ struct NixRepl : AbstractNixRepl, detail::ReplCompleterMixin, gc
StorePath getDerivationPath(Value & v);
ProcessLineResult processLine(std::string line);
void loadFile(const Path & path);
void loadFile(const std::filesystem::path & path);
void loadFlake(const std::string & flakeRef);
void loadFiles();
void loadFlakes();
@@ -143,7 +142,7 @@ NixRepl::NixRepl(
, getValues(getValues)
, staticEnv(new StaticEnv(nullptr, state->staticBaseEnv))
, runNixPtr{runNix}
, interacter(make_unique<ReadlineLikeInteracter>(getDataDir() + "/repl-history"))
, interacter(make_unique<ReadlineLikeInteracter>((getDataDir() / "repl-history").string()))
{
}
@@ -539,7 +538,9 @@ ProcessLineResult NixRepl::processLine(std::string line)
Value v;
evalString(arg, v);
StorePath drvPath = getDerivationPath(v);
Path drvPathRaw = state->store->printStorePath(drvPath);
// N.B. This need not be a local / native file path. For
// example, we might be using an SSH store to a different OS.
std::string drvPathRaw = state->store->printStorePath(drvPath);
if (command == ":b" || command == ":bl") {
state->store->buildPaths({
@@ -712,12 +713,12 @@ ProcessLineResult NixRepl::processLine(std::string line)
return ProcessLineResult::PromptAgain;
}
void NixRepl::loadFile(const Path & path)
void NixRepl::loadFile(const std::filesystem::path & path)
{
loadedFiles.remove(path);
loadedFiles.push_back(path);
Value v, v2;
state->evalFile(lookupFileArg(*state, path), v);
state->evalFile(lookupFileArg(*state, path.string()), v);
state->autoCallFunction(*autoArgs, v, v2);
addAttrsToScope(v2);
}
@@ -790,7 +791,7 @@ void NixRepl::reloadFilesAndFlakes()
void NixRepl::loadFiles()
{
Strings old = loadedFiles;
decltype(loadedFiles) old = loadedFiles;
loadedFiles.clear();
for (auto & i : old) {
@@ -888,7 +889,7 @@ void NixRepl::evalString(std::string s, Value & v)
state->forceValue(v, v.determinePos(noPos));
}
void NixRepl::runNix(Path program, const Strings & args, const std::optional<std::string> & input)
void NixRepl::runNix(const std::string & program, const Strings & args, const std::optional<std::string> & input)
{
if (runNixPtr)
(*runNixPtr)(program, args, input);

View File

@@ -69,8 +69,8 @@ nix_err nix_expr_eval_from_string(
context->last_err_code = NIX_OK;
try {
nix::Expr * parsedExpr = state->state.parseExprFromString(expr, state->state.rootPath(nix::CanonPath(path)));
state->state.eval(parsedExpr, value->value);
state->state.forceValue(value->value, nix::noPos);
state->state.eval(parsedExpr, *value->value);
state->state.forceValue(*value->value, nix::noPos);
}
NIXC_CATCH_ERRS
}
@@ -80,8 +80,8 @@ nix_err nix_value_call(nix_c_context * context, EvalState * state, Value * fn, n
if (context)
context->last_err_code = NIX_OK;
try {
state->state.callFunction(fn->value, arg->value, value->value, nix::noPos);
state->state.forceValue(value->value, nix::noPos);
state->state.callFunction(*fn->value, *arg->value, *value->value, nix::noPos);
state->state.forceValue(*value->value, nix::noPos);
}
NIXC_CATCH_ERRS
}
@@ -91,9 +91,15 @@ nix_err nix_value_call_multi(
{
if (context)
context->last_err_code = NIX_OK;
std::vector<nix::Value *> internal_args;
internal_args.reserve(nargs);
for (size_t i = 0; i < nargs; i++)
internal_args.push_back(args[i]->value);
try {
state->state.callFunction(fn->value, {(nix::Value **) args, nargs}, value->value, nix::noPos);
state->state.forceValue(value->value, nix::noPos);
state->state.callFunction(*fn->value, {internal_args.data(), nargs}, *value->value, nix::noPos);
state->state.forceValue(*value->value, nix::noPos);
}
NIXC_CATCH_ERRS
}
@@ -103,7 +109,7 @@ nix_err nix_value_force(nix_c_context * context, EvalState * state, nix_value *
if (context)
context->last_err_code = NIX_OK;
try {
state->state.forceValue(value->value, nix::noPos);
state->state.forceValue(*value->value, nix::noPos);
}
NIXC_CATCH_ERRS
}
@@ -113,7 +119,7 @@ nix_err nix_value_force_deep(nix_c_context * context, EvalState * state, nix_val
if (context)
context->last_err_code = NIX_OK;
try {
state->state.forceValueDeep(value->value);
state->state.forceValueDeep(*value->value);
}
NIXC_CATCH_ERRS
}

View File

@@ -39,7 +39,13 @@ struct ListBuilder
struct nix_value
{
nix::Value value;
nix::Value * value;
/**
* As we move to a managed heap, we need EvalMemory in more places. Ideally, we would take in EvalState or
* EvalMemory as an argument when we need it, but we don't want to make changes to the stable C api, so we stuff it
* into the nix_value that will get passed in to the relevant functions.
*/
nix::EvalMemory * mem;
};
struct nix_string_return

View File

@@ -20,7 +20,7 @@ static const nix::Value & check_value_not_null(const nix_value * value)
if (!value) {
throw std::runtime_error("nix_value is null");
}
return *((const nix::Value *) value);
return *value->value;
}
static nix::Value & check_value_not_null(nix_value * value)
@@ -28,7 +28,7 @@ static nix::Value & check_value_not_null(nix_value * value)
if (!value) {
throw std::runtime_error("nix_value is null");
}
return value->value;
return *value->value;
}
static const nix::Value & check_value_in(const nix_value * value)
@@ -58,9 +58,14 @@ static nix::Value & check_value_out(nix_value * value)
return v;
}
static inline nix_value * as_nix_value_ptr(nix::Value * v)
static nix_value * new_nix_value(nix::Value * v, nix::EvalMemory & mem)
{
return reinterpret_cast<nix_value *>(v);
nix_value * ret = new (mem.allocBytes(sizeof(nix_value))) nix_value{
.value = v,
.mem = &mem,
};
nix_gc_incref(nullptr, ret);
return ret;
}
/**
@@ -69,7 +74,13 @@ static inline nix_value * as_nix_value_ptr(nix::Value * v)
* Deals with errors and converts arguments from C++ into C types.
*/
static void nix_c_primop_wrapper(
PrimOpFun f, void * userdata, nix::EvalState & state, const nix::PosIdx pos, nix::Value ** args, nix::Value & v)
PrimOpFun f,
void * userdata,
int arity,
nix::EvalState & state,
const nix::PosIdx pos,
nix::Value ** args,
nix::Value & v)
{
nix_c_context ctx;
@@ -85,8 +96,15 @@ static void nix_c_primop_wrapper(
// ok because we don't see a need for this yet (e.g. inspecting thunks,
// or maybe something to make blackholes work better; we don't know).
nix::Value vTmp;
nix_value * vTmpPtr = new_nix_value(&vTmp, state.mem);
f(userdata, &ctx, (EvalState *) &state, (nix_value **) args, (nix_value *) &vTmp);
std::vector<nix_value *> external_args;
external_args.reserve(arity);
for (int i = 0; i < arity; i++) {
nix_value * external_arg = new_nix_value(args[i], state.mem);
external_args.push_back(external_arg);
}
f(userdata, &ctx, (EvalState *) &state, external_args.data(), vTmpPtr);
if (ctx.last_err_code != NIX_OK) {
/* TODO: Throw different errors depending on the error code */
@@ -135,7 +153,7 @@ PrimOp * nix_alloc_primop(
.args = {},
.arity = (size_t) arity,
.doc = doc,
.fun = std::bind(nix_c_primop_wrapper, fun, user_data, _1, _2, _3, _4)};
.fun = std::bind(nix_c_primop_wrapper, fun, user_data, arity, _1, _2, _3, _4)};
if (args)
for (size_t i = 0; args[i]; i++)
p->args.emplace_back(*args);
@@ -160,8 +178,7 @@ nix_value * nix_alloc_value(nix_c_context * context, EvalState * state)
if (context)
context->last_err_code = NIX_OK;
try {
nix_value * res = as_nix_value_ptr(state->state.allocValue());
nix_gc_incref(nullptr, res);
nix_value * res = new_nix_value(state->state.allocValue(), state->state.mem);
return res;
}
NIXC_CATCH_ERRS_NULL
@@ -331,10 +348,10 @@ nix_value * nix_get_list_byidx(nix_c_context * context, const nix_value * value,
return nullptr;
}
auto * p = v.listView()[ix];
nix_gc_incref(nullptr, p);
if (p != nullptr)
state->state.forceValue(*p, nix::noPos);
return as_nix_value_ptr(p);
if (p == nullptr)
return nullptr;
state->state.forceValue(*p, nix::noPos);
return new_nix_value(p, state->state.mem);
}
NIXC_CATCH_ERRS_NULL
}
@@ -352,9 +369,8 @@ nix_get_list_byidx_lazy(nix_c_context * context, const nix_value * value, EvalSt
return nullptr;
}
auto * p = v.listView()[ix];
nix_gc_incref(nullptr, p);
// Note: intentionally NOT calling forceValue() to keep the element lazy
return as_nix_value_ptr(p);
return new_nix_value(p, state->state.mem);
}
NIXC_CATCH_ERRS_NULL
}
@@ -369,9 +385,8 @@ nix_value * nix_get_attr_byname(nix_c_context * context, const nix_value * value
nix::Symbol s = state->state.symbols.create(name);
auto attr = v.attrs()->get(s);
if (attr) {
nix_gc_incref(nullptr, attr->value);
state->state.forceValue(*attr->value, nix::noPos);
return as_nix_value_ptr(attr->value);
return new_nix_value(attr->value, state->state.mem);
}
nix_set_err_msg(context, NIX_ERR_KEY, "missing attribute");
return nullptr;
@@ -390,9 +405,8 @@ nix_get_attr_byname_lazy(nix_c_context * context, const nix_value * value, EvalS
nix::Symbol s = state->state.symbols.create(name);
auto attr = v.attrs()->get(s);
if (attr) {
nix_gc_incref(nullptr, attr->value);
// Note: intentionally NOT calling forceValue() to keep the attribute lazy
return as_nix_value_ptr(attr->value);
return new_nix_value(attr->value, state->state.mem);
}
nix_set_err_msg(context, NIX_ERR_KEY, "missing attribute");
return nullptr;
@@ -440,9 +454,8 @@ nix_get_attr_byidx(nix_c_context * context, nix_value * value, EvalState * state
}
const nix::Attr & a = (*v.attrs())[i];
*name = state->state.symbols[a.name].c_str();
nix_gc_incref(nullptr, a.value);
state->state.forceValue(*a.value, nix::noPos);
return as_nix_value_ptr(a.value);
return new_nix_value(a.value, state->state.mem);
}
NIXC_CATCH_ERRS_NULL
}
@@ -461,9 +474,8 @@ nix_value * nix_get_attr_byidx_lazy(
}
const nix::Attr & a = (*v.attrs())[i];
*name = state->state.symbols[a.name].c_str();
nix_gc_incref(nullptr, a.value);
// Note: intentionally NOT calling forceValue() to keep the attribute lazy
return as_nix_value_ptr(a.value);
return new_nix_value(a.value, state->state.mem);
}
NIXC_CATCH_ERRS_NULL
}
@@ -503,7 +515,7 @@ nix_err nix_init_string(nix_c_context * context, nix_value * value, const char *
context->last_err_code = NIX_OK;
try {
auto & v = check_value_out(value);
v.mkString(std::string_view(str));
v.mkString(std::string_view(str), *value->mem);
}
NIXC_CATCH_ERRS
}
@@ -514,7 +526,7 @@ nix_err nix_init_path_string(nix_c_context * context, EvalState * s, nix_value *
context->last_err_code = NIX_OK;
try {
auto & v = check_value_out(value);
v.mkPath(s->state.rootPath(nix::CanonPath(str)));
v.mkPath(s->state.rootPath(nix::CanonPath(str)), s->state.mem);
}
NIXC_CATCH_ERRS
}

View File

@@ -73,7 +73,7 @@ TEST_F(JSONValueTest, StringQuotes)
TEST_F(JSONValueTest, DISABLED_Path)
{
Value v;
v.mkPath(state.rootPath(CanonPath("/test")));
v.mkPath(state.rootPath(CanonPath("/test")), state.mem);
ASSERT_EQ(getJSONValue(v), "\"/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x\"");
}
} /* namespace nix */

View File

@@ -18,13 +18,13 @@ TEST_F(nix_api_expr_test, nix_eval_state_lookup_path)
{
auto tmpDir = nix::createTempDir();
auto delTmpDir = std::make_unique<nix::AutoDelete>(tmpDir, true);
auto nixpkgs = tmpDir + "/pkgs";
auto nixos = tmpDir + "/cfg";
auto nixpkgs = tmpDir / "pkgs";
auto nixos = tmpDir / "cfg";
std::filesystem::create_directories(nixpkgs);
std::filesystem::create_directories(nixos);
std::string nixpkgsEntry = "nixpkgs=" + nixpkgs;
std::string nixosEntry = "nixos-config=" + nixos;
std::string nixpkgsEntry = "nixpkgs=" + nixpkgs.string();
std::string nixosEntry = "nixos-config=" + nixos.string();
const char * lookupPath[] = {nixpkgsEntry.c_str(), nixosEntry.c_str(), nullptr};
auto builder = nix_eval_state_builder_new(ctx, store);
@@ -49,7 +49,7 @@ TEST_F(nix_api_expr_test, nix_eval_state_lookup_path)
auto pathStr = nix_get_path_string(ctx, value);
assert_ctx_ok();
ASSERT_EQ(0, strcmp(pathStr, nixpkgs.c_str()));
ASSERT_EQ(0, strcmp(pathStr, nixpkgs.string().c_str()));
nix_gc_decref(nullptr, value);
}
@@ -232,22 +232,22 @@ TEST_F(nix_api_expr_test, nix_expr_realise_context)
nix_realised_string_free(r);
}
const char * SAMPLE_USER_DATA = "whatever";
static const char SAMPLE_USER_DATA = 0;
static void
primop_square(void * user_data, nix_c_context * context, EvalState * state, nix_value ** args, nix_value * ret)
{
assert(context);
assert(state);
assert(user_data == SAMPLE_USER_DATA);
assert(user_data == &SAMPLE_USER_DATA);
auto i = nix_get_int(context, args[0]);
nix_init_int(context, ret, i * i);
}
TEST_F(nix_api_expr_test, nix_expr_primop)
{
PrimOp * primop =
nix_alloc_primop(ctx, primop_square, 1, "square", nullptr, "square an integer", (void *) SAMPLE_USER_DATA);
PrimOp * primop = nix_alloc_primop(
ctx, primop_square, 1, "square", nullptr, "square an integer", const_cast<char *>(&SAMPLE_USER_DATA));
assert_ctx_ok();
nix_value * primopValue = nix_alloc_value(ctx, state);
assert_ctx_ok();
@@ -273,7 +273,7 @@ primop_repeat(void * user_data, nix_c_context * context, EvalState * state, nix_
{
assert(context);
assert(state);
assert(user_data == SAMPLE_USER_DATA);
assert(user_data == &SAMPLE_USER_DATA);
// Get the string to repeat
std::string s;
@@ -295,8 +295,8 @@ primop_repeat(void * user_data, nix_c_context * context, EvalState * state, nix_
TEST_F(nix_api_expr_test, nix_expr_primop_arity_2_multiple_calls)
{
PrimOp * primop =
nix_alloc_primop(ctx, primop_repeat, 2, "repeat", nullptr, "repeat a string", (void *) SAMPLE_USER_DATA);
PrimOp * primop = nix_alloc_primop(
ctx, primop_repeat, 2, "repeat", nullptr, "repeat a string", const_cast<char *>(&SAMPLE_USER_DATA));
assert_ctx_ok();
nix_value * primopValue = nix_alloc_value(ctx, state);
assert_ctx_ok();
@@ -330,8 +330,8 @@ TEST_F(nix_api_expr_test, nix_expr_primop_arity_2_multiple_calls)
TEST_F(nix_api_expr_test, nix_expr_primop_arity_2_single_call)
{
PrimOp * primop =
nix_alloc_primop(ctx, primop_repeat, 2, "repeat", nullptr, "repeat a string", (void *) SAMPLE_USER_DATA);
PrimOp * primop = nix_alloc_primop(
ctx, primop_repeat, 2, "repeat", nullptr, "repeat a string", const_cast<char *>(&SAMPLE_USER_DATA));
assert_ctx_ok();
nix_value * primopValue = nix_alloc_value(ctx, state);
assert_ctx_ok();

View File

@@ -14,12 +14,4 @@
namespace nixC {
TEST_F(nix_api_expr_test, as_nix_value_ptr)
{
// nix_alloc_value casts nix::Value to nix_value
// It should be obvious from the decl that that works, but if it doesn't,
// the whole implementation would be utterly broken.
ASSERT_EQ(sizeof(nix::Value), sizeof(nix_value));
}
} // namespace nixC

View File

@@ -268,7 +268,7 @@ struct StringPrintingTests : LibExprTest
void test(std::string_view literal, std::string_view expected, unsigned int maxLength, A... args)
{
Value v;
v.mkString(literal);
v.mkString(literal, state.mem);
std::stringstream out;
printValue(state, out, v, PrintOptions{.maxStringLength = maxLength});
@@ -353,7 +353,7 @@ TEST_F(ValuePrintingTests, ansiColorsStringElided)
TEST_F(ValuePrintingTests, ansiColorsPath)
{
Value v;
v.mkPath(state.rootPath(CanonPath("puppy")));
v.mkPath(state.rootPath(CanonPath("puppy")), state.mem);
test(v, ANSI_GREEN "/puppy" ANSI_NORMAL, PrintOptions{.ansiColors = true});
}

View File

@@ -1,5 +1,6 @@
#include "nix/expr/attr-path.hh"
#include "nix/expr/eval-inline.hh"
#include "nix/util/strings-inline.hh"
namespace nix {
@@ -30,14 +31,24 @@ static Strings parseAttrPath(std::string_view s)
return res;
}
std::vector<Symbol> parseAttrPath(EvalState & state, std::string_view s)
AttrPath AttrPath::parse(EvalState & state, std::string_view s)
{
std::vector<Symbol> res;
AttrPath res;
for (auto & a : parseAttrPath(s))
res.push_back(state.symbols.create(a));
return res;
}
std::string AttrPath::to_string(EvalState & state) const
{
return dropEmptyInitThenConcatStringsSep(".", state.symbols.resolve({*this}));
}
std::vector<SymbolStr> AttrPath::resolve(EvalState & state) const
{
return state.symbols.resolve({*this});
}
std::pair<Value *, PosIdx>
findAlongAttrPath(EvalState & state, const std::string & attrPath, Bindings & autoArgs, Value & vIn)
{

View File

@@ -364,7 +364,7 @@ void AttrCursor::fetchCachedValue()
throw CachedEvalError(parent->first, parent->second);
}
std::vector<Symbol> AttrCursor::getAttrPath() const
AttrPath AttrCursor::getAttrPath() const
{
if (parent) {
auto attrPath = parent->first->getAttrPath();
@@ -374,7 +374,7 @@ std::vector<Symbol> AttrCursor::getAttrPath() const
return {};
}
std::vector<Symbol> AttrCursor::getAttrPath(Symbol name) const
AttrPath AttrCursor::getAttrPath(Symbol name) const
{
auto attrPath = getAttrPath();
attrPath.push_back(name);
@@ -383,12 +383,12 @@ std::vector<Symbol> AttrCursor::getAttrPath(Symbol name) const
std::string AttrCursor::getAttrPathStr() const
{
return dropEmptyInitThenConcatStringsSep(".", root->state.symbols.resolve(getAttrPath()));
return getAttrPath().to_string(root->state);
}
std::string AttrCursor::getAttrPathStr(Symbol name) const
{
return dropEmptyInitThenConcatStringsSep(".", root->state.symbols.resolve(getAttrPath(name)));
return getAttrPath(name).to_string(root->state);
}
Value & AttrCursor::forceValue()
@@ -511,7 +511,7 @@ ref<AttrCursor> AttrCursor::getAttr(std::string_view name)
return getAttr(root->state.symbols.create(name));
}
OrSuggestions<ref<AttrCursor>> AttrCursor::findAlongAttrPath(const std::vector<Symbol> & attrPath)
OrSuggestions<ref<AttrCursor>> AttrCursor::findAlongAttrPath(const AttrPath & attrPath)
{
auto res = shared_from_this();
for (auto & attr : attrPath) {

View File

@@ -60,18 +60,18 @@ EvalSettings::EvalSettings(bool & readOnlyMode, EvalSettings::LookupPathHooks lo
Strings EvalSettings::getDefaultNixPath()
{
Strings res;
auto add = [&](const Path & p, const std::string & s = std::string()) {
auto add = [&](const std::filesystem::path & p, const std::string & s = std::string()) {
if (std::filesystem::exists(p)) {
if (s.empty()) {
res.push_back(p);
res.push_back(p.string());
} else {
res.push_back(s + "=" + p);
res.push_back(s + "=" + p.string());
}
}
};
add(getNixDefExpr() + "/channels");
add(rootChannelsDir() + "/nixpkgs", "nixpkgs");
add(std::filesystem::path{getNixDefExpr()} / "channels");
add(rootChannelsDir() / "nixpkgs", "nixpkgs");
add(rootChannelsDir());
return res;
@@ -103,9 +103,9 @@ const std::string & EvalSettings::getCurrentSystem() const
return evalSystem != "" ? evalSystem : settings.thisSystem.get();
}
Path getNixDefExpr()
std::filesystem::path getNixDefExpr()
{
return settings.useXDGBaseDirectories ? getStateDir() + "/defexpr" : getHome() + "/.nix-defexpr";
return settings.useXDGBaseDirectories ? getStateDir() / "defexpr" : getHome() / ".nix-defexpr";
}
} // namespace nix
} // namespace nix

View File

@@ -81,20 +81,20 @@ static const char * makeImmutableString(std::string_view s)
return t;
}
StringData & StringData::alloc(size_t size)
StringData & StringData::alloc(EvalMemory & mem, size_t size)
{
void * t = GC_MALLOC_ATOMIC(sizeof(StringData) + size + 1);
void * t = mem.allocBytes(sizeof(StringData) + size + 1);
if (!t)
throw std::bad_alloc();
auto res = new (t) StringData(size);
return *res;
}
const StringData & StringData::make(std::string_view s)
const StringData & StringData::make(EvalMemory & mem, std::string_view s)
{
if (s.empty())
return ""_sds;
auto & res = alloc(s.size());
auto & res = alloc(mem, s.size());
std::memcpy(&res.data_, s.data(), s.size());
res.data_[s.size()] = '\0';
return res;
@@ -849,9 +849,9 @@ DebugTraceStacker::DebugTraceStacker(EvalState & evalState, DebugTrace t)
evalState.runDebugRepl(nullptr, trace.env, trace.expr);
}
void Value::mkString(std::string_view s)
void Value::mkString(std::string_view s, EvalMemory & mem)
{
mkStringNoCopy(StringData::make(s));
mkStringNoCopy(StringData::make(mem, s));
}
Value::StringWithContext::Context *
@@ -862,13 +862,13 @@ Value::StringWithContext::Context::fromBuilder(const NixStringContext & context,
auto ctx = new (mem.allocBytes(sizeof(Context) + context.size() * sizeof(value_type))) Context(context.size());
std::ranges::transform(
context, ctx->elems, [](const NixStringContextElem & elt) { return &StringData::make(elt.to_string()); });
context, ctx->elems, [&](const NixStringContextElem & elt) { return &StringData::make(mem, elt.to_string()); });
return ctx;
}
void Value::mkString(std::string_view s, const NixStringContext & context, EvalMemory & mem)
{
mkStringNoCopy(StringData::make(s), Value::StringWithContext::Context::fromBuilder(context, mem));
mkStringNoCopy(StringData::make(mem, s), Value::StringWithContext::Context::fromBuilder(context, mem));
}
void Value::mkStringMove(const StringData & s, const NixStringContext & context, EvalMemory & mem)
@@ -876,9 +876,9 @@ void Value::mkStringMove(const StringData & s, const NixStringContext & context,
mkStringNoCopy(s, Value::StringWithContext::Context::fromBuilder(context, mem));
}
void Value::mkPath(const SourcePath & path)
void Value::mkPath(const SourcePath & path, EvalMemory & mem)
{
mkPath(&*path.accessor, StringData::make(path.path.abs()));
mkPath(&*path.accessor, StringData::make(mem, path.path.abs()));
}
inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval)
@@ -943,7 +943,7 @@ void EvalState::mkPos(Value & v, PosIdx p)
auto origin = positions.originOf(p);
if (auto path = std::get_if<SourcePath>(&origin)) {
auto attrs = buildBindings(3);
attrs.alloc(s.file).mkString(path->path.abs());
attrs.alloc(s.file).mkString(path->path.abs(), mem);
makePositionThunks(*this, p, attrs.alloc(s.line), attrs.alloc(s.column));
v.mkAttrs(attrs);
} else
@@ -1368,7 +1368,7 @@ void ExprVar::eval(EvalState & state, Env & env, Value & v)
v = *v2;
}
static std::string showAttrPath(EvalState & state, Env & env, std::span<const AttrName> attrPath)
static std::string showAttrSelectionPath(EvalState & state, Env & env, std::span<const AttrName> attrPath)
{
std::ostringstream out;
bool first = true;
@@ -1404,7 +1404,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
env,
getPos(),
"while evaluating the attribute '%1%'",
showAttrPath(state, env, getAttrPath()))
showAttrSelectionPath(state, env, getAttrPath()))
: nullptr;
for (auto & i : getAttrPath()) {
@@ -1445,7 +1445,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
auto origin = std::get_if<SourcePath>(&pos2r.origin);
if (!(origin && *origin == state.derivationInternal))
state.addErrorTrace(
e, pos2, "while evaluating the attribute '%1%'", showAttrPath(state, env, getAttrPath()));
e, pos2, "while evaluating the attribute '%1%'", showAttrSelectionPath(state, env, getAttrPath()));
}
throw;
}
@@ -1751,9 +1751,9 @@ void ExprCall::eval(EvalState & state, Env & env, Value & v)
// 4: about 60
// 5: under 10
// This excluded attrset lambdas (`{...}:`). Contributions of mixed lambdas appears insignificant at ~150 total.
SmallValueVector<4> vArgs(args.size());
for (size_t i = 0; i < args.size(); ++i)
vArgs[i] = args[i]->maybeThunk(state, env);
SmallValueVector<4> vArgs(args->size());
for (size_t i = 0; i < args->size(); ++i)
vArgs[i] = (*args)[i]->maybeThunk(state, env);
state.callFunction(vFun, vArgs, v, pos);
}
@@ -2139,9 +2139,9 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v)
for (const auto & part : strings) {
resultStr += *part;
}
v.mkPath(state.rootPath(CanonPath(resultStr)));
v.mkPath(state.rootPath(CanonPath(resultStr)), state.mem);
} else {
auto & resultStr = StringData::alloc(sSize);
auto & resultStr = StringData::alloc(state.mem, sSize);
auto * tmp = resultStr.data();
for (const auto & part : strings) {
std::memcpy(tmp, part->data(), part->size());
@@ -2188,6 +2188,8 @@ void EvalState::forceValueDeep(Value & v)
std::set<const Value *> seen;
[&, &state(*this)](this const auto & recurse, Value & v) {
auto _level = state.addCallDepth(v.determinePos(noPos));
if (!seen.insert(&v).second)
return;
@@ -2214,8 +2216,15 @@ void EvalState::forceValueDeep(Value & v)
}
else if (v.isList()) {
size_t index = 0;
for (auto v2 : v.listView())
recurse(*v2);
try {
recurse(*v2);
index++;
} catch (Error & e) {
state.addErrorTrace(e, "while evaluating list element at index %1%", index);
throw;
}
}
}(v);
}

View File

@@ -19,6 +19,15 @@ findAlongAttrPath(EvalState & state, const std::string & attrPath, Bindings & au
*/
std::pair<SourcePath, uint32_t> findPackageFilename(EvalState & state, Value & v, std::string what);
std::vector<Symbol> parseAttrPath(EvalState & state, std::string_view s);
struct AttrPath : std::vector<Symbol>
{
using std::vector<Symbol>::vector;
static AttrPath parse(EvalState & state, std::string_view s);
std::string to_string(EvalState & state) const;
std::vector<SymbolStr> resolve(EvalState & state) const;
};
} // namespace nix

View File

@@ -4,6 +4,7 @@
#include "nix/util/sync.hh"
#include "nix/util/hash.hh"
#include "nix/expr/eval.hh"
#include "nix/expr/attr-path.hh"
#include <functional>
#include <variant>
@@ -124,9 +125,9 @@ public:
Value * value = nullptr,
std::optional<std::pair<AttrId, AttrValue>> && cachedValue = {});
std::vector<Symbol> getAttrPath() const;
AttrPath getAttrPath() const;
std::vector<Symbol> getAttrPath(Symbol name) const;
AttrPath getAttrPath(Symbol name) const;
std::string getAttrPathStr() const;
@@ -146,7 +147,7 @@ public:
* Get an attribute along a chain of attrsets. Note that this does
* not auto-call functors or functions.
*/
OrSuggestions<ref<AttrCursor>> findAlongAttrPath(const std::vector<Symbol> & attrPath);
OrSuggestions<ref<AttrCursor>> findAlongAttrPath(const AttrPath & attrPath);
std::string getString();

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