From d5fdb995d3425df88e9e08a4fae724515309c47a Mon Sep 17 00:00:00 2001 From: Alois Wohlschlager Date: Fri, 17 May 2024 09:33:13 +0200 Subject: [PATCH 01/14] doc: fix repl-interrupt release note entry The timing of the merge resulted in the newly introduced metadata not being present. Change-Id: I07f28cf37703ec05c3e1b96301797a42d913264b --- doc/manual/change-authors.yml | 4 ++++ doc/manual/rl-next/repl-interrupt.md | 2 ++ 2 files changed, 6 insertions(+) diff --git a/doc/manual/change-authors.yml b/doc/manual/change-authors.yml index 46164f5b1..1b59da9ca 100644 --- a/doc/manual/change-authors.yml +++ b/doc/manual/change-authors.yml @@ -71,3 +71,7 @@ puck: display_name: puck forgejo: puck github: puckipedia + +alois31: + forgejo: alois31 + github: alois31 diff --git a/doc/manual/rl-next/repl-interrupt.md b/doc/manual/rl-next/repl-interrupt.md index 61a8ab71e..da0bc698e 100644 --- a/doc/manual/rl-next/repl-interrupt.md +++ b/doc/manual/rl-next/repl-interrupt.md @@ -1,6 +1,8 @@ --- synopsis: Interrupting builds in the REPL works more than once cls: 1097 +category: Fixes +credits: alois31 --- Builds in the REPL can be interrupted by pressing Ctrl+C. From 47523944c5f13250dd0eb9d56d5c6621f4722bea Mon Sep 17 00:00:00 2001 From: eldritch horrors Date: Wed, 22 May 2024 18:26:01 +0200 Subject: [PATCH 02/14] libstore: remove unused copyPath function Change-Id: Ibfb0848d8b337bd38947a745c240838865cea401 --- src/libutil/archive.cc | 9 --------- src/libutil/archive.hh | 2 -- 2 files changed, 11 deletions(-) diff --git a/src/libutil/archive.cc b/src/libutil/archive.cc index 00536c1e1..a18c54ebf 100644 --- a/src/libutil/archive.cc +++ b/src/libutil/archive.cc @@ -389,13 +389,4 @@ void copyNAR(Source & source, Sink & sink) } -void copyPath(const Path & from, const Path & to) -{ - auto source = sinkToSource([&](Sink & sink) { - dumpPath(from, sink); - }); - restorePath(to, *source); -} - - } diff --git a/src/libutil/archive.hh b/src/libutil/archive.hh index 2cf164a41..017b6633c 100644 --- a/src/libutil/archive.hh +++ b/src/libutil/archive.hh @@ -124,8 +124,6 @@ void restorePath(const Path & path, Source & source); */ void copyNAR(Source & source, Sink & sink); -void copyPath(const Path & from, const Path & to); - inline constexpr std::string_view narVersionMagic1 = "nix-archive-1"; From dcc7ea54986e0712666b15b502b6f89dd42b000c Mon Sep 17 00:00:00 2001 From: Jade Lovelace Date: Mon, 20 May 2024 12:17:54 -0700 Subject: [PATCH 03/14] release notes: add a bunch of them Also fix typos introduced by the commits I read. I have run the addDrvOutputDependencies release note past Ericson since I was confused by what the heck it was doing, and he was saying it was reasonable. Change-Id: Id015353b00938682f7faae7de43df7f991a5237e --- doc/manual/change-authors.yml | 34 ++++++++++++ .../rl-next/addDrvOutputDependencies.md | 14 +++++ .../rl-next/always-allow-substitutes.md | 13 +++++ doc/manual/rl-next/cve-fod-fix.md | 21 +++++++ doc/manual/rl-next/gc-roots-darwin.md | 8 +++ doc/manual/rl-next/macos-stack-size.md | 9 +++ doc/manual/rl-next/more-logs.md | 9 +++ doc/manual/rl-next/nix-eval-derivations.md | 9 +++ .../rl-next/nix-store-prefetch-unpack.md | 18 ++++++ doc/manual/rl-next/print-in-repl.md | 55 +++++++++++++++++++ doc/manual/rl-next/shebang-single-quotes.md | 13 +++++ doc/manual/rl-next/ssh-ng-phase-reporting.md | 8 +++ doc/manual/rl-next/ssh-ng-substitute.md | 9 +++ .../rl-next/warn-ignored-client-settings.md | 9 +++ doc/manual/src/language/derivations.md | 2 +- src/libexpr/primops/context.cc | 6 +- 16 files changed, 233 insertions(+), 4 deletions(-) create mode 100644 doc/manual/rl-next/addDrvOutputDependencies.md create mode 100644 doc/manual/rl-next/always-allow-substitutes.md create mode 100644 doc/manual/rl-next/cve-fod-fix.md create mode 100644 doc/manual/rl-next/gc-roots-darwin.md create mode 100644 doc/manual/rl-next/macos-stack-size.md create mode 100644 doc/manual/rl-next/more-logs.md create mode 100644 doc/manual/rl-next/nix-eval-derivations.md create mode 100644 doc/manual/rl-next/nix-store-prefetch-unpack.md create mode 100644 doc/manual/rl-next/print-in-repl.md create mode 100644 doc/manual/rl-next/shebang-single-quotes.md create mode 100644 doc/manual/rl-next/ssh-ng-phase-reporting.md create mode 100644 doc/manual/rl-next/ssh-ng-substitute.md create mode 100644 doc/manual/rl-next/warn-ignored-client-settings.md diff --git a/doc/manual/change-authors.yml b/doc/manual/change-authors.yml index 1b59da9ca..6f0008eea 100644 --- a/doc/manual/change-authors.yml +++ b/doc/manual/change-authors.yml @@ -62,6 +62,27 @@ roberth: display_name: Robert Hensing github: roberth +ericson: + display_name: John Ericson + github: ericson2314 + +tomberek: + display_name: Tom Bereknyei + github: tomberek + +valentin: + display_name: Valentin Gagarin + github: fricklerhandwerk + +lovesegfault: + github: lovesegfault + +yshui: + github: yshui + +ncfavier: + github: ncfavier + midnightveil: display_name: julia forgejo: midnightveil @@ -75,3 +96,16 @@ puck: alois31: forgejo: alois31 github: alois31 + +DavHau: + github: DavHau + +SharzyL: + github: SharzyL + +r-vdp: + github: r-vdp + +artemist: + display_name: Artemis Tosini + forgejo: artemist diff --git a/doc/manual/rl-next/addDrvOutputDependencies.md b/doc/manual/rl-next/addDrvOutputDependencies.md new file mode 100644 index 000000000..0442383ec --- /dev/null +++ b/doc/manual/rl-next/addDrvOutputDependencies.md @@ -0,0 +1,14 @@ +--- +synopsis: "Add a builtin `addDrvOutputDependencies`" +prs: 9216 +issues: 7910 +credits: [ericson, horrors] +category: Features +--- + +This builtin allows taking a `drvPath`-like string and turning it into a string +with context such that, when it lands in a derivation, it will create +dependencies on *all the outputs* in its closure (!). Although `drvPath` does this +today, this builtin starts forming a path to migrate to making `drvPath` have a +more normal and less surprising string context behaviour (see linked issue and +PR for more details). diff --git a/doc/manual/rl-next/always-allow-substitutes.md b/doc/manual/rl-next/always-allow-substitutes.md new file mode 100644 index 000000000..60b588fd7 --- /dev/null +++ b/doc/manual/rl-next/always-allow-substitutes.md @@ -0,0 +1,13 @@ +--- +synopsis: "Add an option `always-allow-substitutes` to ignore `allowSubstitutes` in derivations" +prs: 8047 +credits: [lovesegfault, horrors] +category: Improvements +--- + +You can set this setting to force a system to always allow substituting even +trivial derivations like `pkgs.writeText`. This is useful for +[`nix-fast-build --skip-cached`][skip-cached] and similar to be able to also +ignore trivial derivations. + +[skip-cached]: https://github.com/Mic92/nix-fast-build?tab=readme-ov-file#avoiding-redundant-package-downloads diff --git a/doc/manual/rl-next/cve-fod-fix.md b/doc/manual/rl-next/cve-fod-fix.md new file mode 100644 index 000000000..4499f639b --- /dev/null +++ b/doc/manual/rl-next/cve-fod-fix.md @@ -0,0 +1,21 @@ +--- +synopsis: "Fix CVE-2024-27297 (GHSA-2ffj-w4mj-pg37)" +cls: 266 +credits: [puck, jade, thufschmitt, tomberek, valentin] +category: Fixes +--- + +Since Lix fixed-output derivations run in the host network namespace (which we +wish to change in the future, see +[lix#285](https://git.lix.systems/lix-project/lix/issues/285)), they may open +abstract-namespace Unix sockets to each other and to programs on the host. Lix +contained a now-fixed time-of-check/time-of-use vulnerability where one +derivation could send writable handles to files in their final location in the +store to another over an abstract-namespace Unix socket, exit, then the other +derivation could wait for Lix to hash the paths and overwrite them. + +The impact of this vulnerability is that two malicious fixed-output derivations +could create a poisoned path for the sources to Bash or similarly important +software containing a backdoor, leading to local privilege execution. + +CppNix advisory: https://github.com/NixOS/nix/security/advisories/GHSA-2ffj-w4mj-pg37 diff --git a/doc/manual/rl-next/gc-roots-darwin.md b/doc/manual/rl-next/gc-roots-darwin.md new file mode 100644 index 000000000..e8e90a397 --- /dev/null +++ b/doc/manual/rl-next/gc-roots-darwin.md @@ -0,0 +1,8 @@ +--- +synopsis: Find GC roots using libproc on Darwin +cls: 723 +credits: artemist +category: Improvements +--- + +Previously, the garbage collector found runtime roots on Darwin by shelling out to `lsof -n -w -F n` then parsing the result. The version of `lsof` packaged in Nixpkgs is very slow on Darwin, so Lix now uses `libproc` directly to speed up GC root discovery, in some tests taking 250ms now instead of 40s. diff --git a/doc/manual/rl-next/macos-stack-size.md b/doc/manual/rl-next/macos-stack-size.md new file mode 100644 index 000000000..efbba1577 --- /dev/null +++ b/doc/manual/rl-next/macos-stack-size.md @@ -0,0 +1,9 @@ +--- +synopsis: Increase default stack size on macOS +prs: 9860 +credits: 9999years +category: Improvements +--- + +Increase the default stack size on macOS to the same value as on Linux, subject to system restrictions to maximum stack size. +This should reduce the number of stack overflow crashes on macOS when evaluating Nix code with deep call stacks. diff --git a/doc/manual/rl-next/more-logs.md b/doc/manual/rl-next/more-logs.md new file mode 100644 index 000000000..e239da5ad --- /dev/null +++ b/doc/manual/rl-next/more-logs.md @@ -0,0 +1,9 @@ +--- +synopsis: Show more log context for failed builds +prs: 9670 +credits: DavHau +category: Improvements +--- + +Show 25 lines of log tail instead of 10 for failed builds. +This increases the chances of having useful information in the shown logs. diff --git a/doc/manual/rl-next/nix-eval-derivations.md b/doc/manual/rl-next/nix-eval-derivations.md new file mode 100644 index 000000000..ae1952283 --- /dev/null +++ b/doc/manual/rl-next/nix-eval-derivations.md @@ -0,0 +1,9 @@ +--- +synopsis: Print derivation paths in `nix eval` +cls: 446 +credits: 9999years +category: Improvements +--- + +`nix eval` previously printed derivations as attribute sets, so commands that print derivations (e.g. `nix eval nixpkgs#bash`) would infinitely loop and segfault. +It now prints the `.drv` path the derivation generates instead. diff --git a/doc/manual/rl-next/nix-store-prefetch-unpack.md b/doc/manual/rl-next/nix-store-prefetch-unpack.md new file mode 100644 index 000000000..5627c2c75 --- /dev/null +++ b/doc/manual/rl-next/nix-store-prefetch-unpack.md @@ -0,0 +1,18 @@ +--- +synopsis: "Add an option `--unpack` to unpack archives in `nix store prefetch-file`" +prs: 9805 +cls: 224 +credits: [yshui, horrors] +category: Improvements +--- + +It is now possible to fetch an archive then NAR-hash it (as in, hash it in the +same manner as `builtins.fetchTarball` or fixed-output derivations with +recursive hash type) in one command. + +Example: + +``` +~ » nix store prefetch-file --name source --unpack https://git.lix.systems/lix-project/lix/archive/2.90-beta.1.tar.gz +Downloaded 'https://git.lix.systems/lix-project/lix/archive/2.90-beta.1.tar.gz' to '/nix/store/yvfqnq52ryjc3janw02ziv7kr6gd0cs1-source' (hash 'sha256-REWlo2RYHfJkxnmZTEJu3Cd/2VM+wjjpPy7Xi4BdDTQ='). +``` diff --git a/doc/manual/rl-next/print-in-repl.md b/doc/manual/rl-next/print-in-repl.md new file mode 100644 index 000000000..e0ac8e17f --- /dev/null +++ b/doc/manual/rl-next/print-in-repl.md @@ -0,0 +1,55 @@ +--- +synopsis: "REPL printing improvements" +prs: [9931, 10208] +cls: [375, 492] +credits: [9999years, horrors] +category: Improvements +--- + +The REPL printer has been improved to do the following: +- If a string is passed to `:print`, it is printed literally to the screen +- Structures will be printed as multiple lines when necessary + +Before: + +``` +nix-repl> { attrs = { a = { b = { c = { }; }; }; }; list = [ 1 ]; list' = [ 1 2 3 ]; } +{ attrs = { ... }; list = [ ... ]; list' = [ ... ]; } + +nix-repl> :p { attrs = { a = { b = { c = { }; }; }; }; list = [ 1 ]; list' = [ 1 2 3 ]; } +{ attrs = { a = { b = { c = { }; }; }; }; list = [ 1 ]; list' = [ 1 2 3 ]; } + +nix-repl> :p "meow" +"meow" +``` + +After: + +``` +nix-repl> { attrs = { a = { b = { c = { }; }; }; }; list = [ 1 ]; list' = [ 1 2 3 ]; } +{ + attrs = { ... }; + list = [ ... ]; + list' = [ ... ]; +} + +nix-repl> :p { attrs = { a = { b = { c = { }; }; }; }; list = [ 1 ]; list' = [ 1 2 3 ]; } +{ + attrs = { + a = { + b = { + c = { }; + }; + }; + }; + list = [ 1 ]; + list' = [ + 1 + 2 + 3 + ]; +} + +nix-repl> :p "meow" +meow +``` diff --git a/doc/manual/rl-next/shebang-single-quotes.md b/doc/manual/rl-next/shebang-single-quotes.md new file mode 100644 index 000000000..f60caad84 --- /dev/null +++ b/doc/manual/rl-next/shebang-single-quotes.md @@ -0,0 +1,13 @@ +--- +synopsis: Allow single quotes in nix-shell shebangs +prs: 8470 +credits: [ncfavier, horrors] +category: Improvements +--- + +Example: + +```bash +#! /usr/bin/env nix-shell +#! nix-shell -i bash --packages 'terraform.withPlugins (plugins: [ plugins.openstack ])' +``` diff --git a/doc/manual/rl-next/ssh-ng-phase-reporting.md b/doc/manual/rl-next/ssh-ng-phase-reporting.md new file mode 100644 index 000000000..02f357410 --- /dev/null +++ b/doc/manual/rl-next/ssh-ng-phase-reporting.md @@ -0,0 +1,8 @@ +--- +synopsis: Include phase reporting in log file for ssh-ng builds +prs: 9280 +credits: r-vdp +category: Fixes +--- + +Store phase information of remote builds run via `ssh-ng` remotes in the local log file, matching logging behavior of local builds. diff --git a/doc/manual/rl-next/ssh-ng-substitute.md b/doc/manual/rl-next/ssh-ng-substitute.md new file mode 100644 index 000000000..20f79c106 --- /dev/null +++ b/doc/manual/rl-next/ssh-ng-substitute.md @@ -0,0 +1,9 @@ +--- +synopsis: Fix `ssh-ng://` remotes not respecting `--substitute-on-destination` +prs: 9600 +credits: SharzyL +category: Fixes +--- + +`nix copy ssh-ng://` now respects `--substitute-on-destination`, as does `nix-copy-closure` and other commands that operate on remote `ssh-ng` stores. +Previously this was always set by `builders-use-substitutes` setting. diff --git a/doc/manual/rl-next/warn-ignored-client-settings.md b/doc/manual/rl-next/warn-ignored-client-settings.md new file mode 100644 index 000000000..88edd27fb --- /dev/null +++ b/doc/manual/rl-next/warn-ignored-client-settings.md @@ -0,0 +1,9 @@ +--- +synopsis: Warn about ignored client settings +cls: 1026 +credits: jade +category: Improvements +--- + +Emit a warning for every client-provided setting the daemon ignores because the requesting client is not run by a trusted user. +Previously this was only a debug message. diff --git a/doc/manual/src/language/derivations.md b/doc/manual/src/language/derivations.md index c10e8149d..28e686889 100644 --- a/doc/manual/src/language/derivations.md +++ b/doc/manual/src/language/derivations.md @@ -125,7 +125,7 @@ The builder is executed as follows: directory (typically, `/nix/store`). - `NIX_ATTRS_JSON_FILE` & `NIX_ATTRS_SH_FILE` if `__structuredAttrs` - is set to `true` for the dervation. A detailed explanation of this + is set to `true` for the derivation. A detailed explanation of this behavior can be found in the [section about structured attrs](./advanced-attributes.md#adv-attr-structuredAttrs). diff --git a/src/libexpr/primops/context.cc b/src/libexpr/primops/context.cc index 1eec8b316..36692aafb 100644 --- a/src/libexpr/primops/context.cc +++ b/src/libexpr/primops/context.cc @@ -36,7 +36,7 @@ static RegisterPrimOp primop_hasContext({ > **Example** > - > Many operations require a string context to be empty because they are intended only to work with "regular" strings, and also to help users avoid unintentionally loosing track of string context elements. + > Many operations require a string context to be empty because they are intended only to work with "regular" strings, and also to help users avoid unintentionally losing track of string context elements. > `builtins.hasContext` can help create better domain-specific errors in those case. > > ```nix @@ -137,14 +137,14 @@ static RegisterPrimOp primop_addDrvOutputDependencies({ .name = "__addDrvOutputDependencies", .args = {"s"}, .doc = R"( - Create a copy of the given string where a single consant string context element is turned into a "derivation deep" string context element. + Create a copy of the given string where a single constant string context element is turned into a "derivation deep" string context element. The store path that is the constant string context element should point to a valid derivation, and end in `.drv`. The original string context element must not be empty or have multiple elements, and it must not have any other type of element other than a constant or derivation deep element. The latter is supported so this function is idempotent. - This is the opposite of [`builtins.unsafeDiscardOutputDependency`](#builtins-addDrvOutputDependencies). + This is the opposite of [`builtins.unsafeDiscardOutputDependency`](#builtins-unsafeDiscardOutputDependency). )", .fun = prim_addDrvOutputDependencies }); From d05e0b9f1fedfe1700959cc6045ce9bc25b9e955 Mon Sep 17 00:00:00 2001 From: Jade Lovelace Date: Wed, 22 May 2024 16:58:35 -0700 Subject: [PATCH 04/14] fix: enlarge envSize by several times to not be close to nixpkgs size nixpkgs has 23000 attributes, and our previous limit would be hit if you have more than one nixpkgs in the environment, for example, because `repl-overlays` will load the new stuff from the environment on top of the existing environment. This is not really testable since if we did write such a test, it would just be testing this constant tbh... Fixes: https://git.lix.systems/lix-project/lix/issues/337 Change-Id: I49197bfb4db55b082f914f0d70e84f5f5f110954 --- src/libcmd/repl.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/libcmd/repl.cc b/src/libcmd/repl.cc index 525c25560..89691d33a 100644 --- a/src/libcmd/repl.cc +++ b/src/libcmd/repl.cc @@ -90,7 +90,8 @@ struct NixRepl Strings loadedFiles; std::function getValues; - const static int envSize = 32768; + // Uses 8MiB of memory. It's fine. + const static int envSize = 1 << 20; std::shared_ptr staticEnv; Env * env; int displ; @@ -854,6 +855,11 @@ void NixRepl::loadReplOverlays() replInitFilesFunction->determinePos(noPos) ); + // n.b. this does in fact load the stuff into the environment twice (once + // from the superset of the environment returned by repl-overlays and once + // from the thing itself), but it's not fixable because clearEnv here could + // lead to dangling references to the old environment in thunks. + // https://git.lix.systems/lix-project/lix/issues/337#issuecomment-3745 addAttrsToScope(newAttrs); } From 9a75150d19dab87a3e2cbd636397b9561eb98ad4 Mon Sep 17 00:00:00 2001 From: eldritch horrors Date: Wed, 22 May 2024 21:18:02 +0200 Subject: [PATCH 05/14] doc: sort change-authors.yml this should make it easier to spot future instances of entries being duplicated by accident. also add a pre-commit check to remain sorted Change-Id: I500caf862e93480b38c9d51144273bb2dcab1af0 --- doc/manual/change-authors.yml | 148 +++++++++++++++++----------------- misc/pre-commit.nix | 12 +++ 2 files changed, 86 insertions(+), 74 deletions(-) diff --git a/doc/manual/change-authors.yml b/doc/manual/change-authors.yml index 6f0008eea..98a135397 100644 --- a/doc/manual/change-authors.yml +++ b/doc/manual/change-authors.yml @@ -3,68 +3,97 @@ # # It's used for crediting people accurately in release notes. The release notes # script will link to forgejo, then to GitHub if forgejo is not present. -horrors: - display_name: eldritch horrors - forgejo: pennae - github: pennae +9999years: + display_name: wiggles + forgejo: rbt + github: 9999years -Qyriad: - forgejo: Qyriad - github: Qyriad +Artturin: + github: Artturin -jade: - forgejo: jade - github: lf- +DavHau: + github: DavHau -iFreilicht: - github: iFreilicht - -ma27: - forgejo: ma27 - github: ma27 +Kha: + github: Kha Lunaphied: forgejo: Lunaphied github: Lunaphied -9999years: - display_name: wiggles - github: 9999years - forgejo: rbt +Qyriad: + forgejo: Qyriad + github: Qyriad -matthewbauer: - github: matthewbauer +SharzyL: + github: SharzyL -raito: - display_name: Raito Bezarius - github: RaitoBezarius - forgejo: raito +alois31: + forgejo: alois31 + github: alois31 -winter: - github: winterqt - forgejo: winter - -Kha: - github: Kha - -Artturin: - github: Artturin - -thufschmitt: - display_name: Théophane Hufschmitt - github: thufschmitt +artemist: + display_name: Artemis Tosini + forgejo: artemist edolstra: display_name: Eelco Dolstra github: edolstra +ericson: + display_name: John Ericson + github: ericson2314 + +horrors: + display_name: eldritch horrors + forgejo: pennae + github: pennae + +iFreilicht: + github: iFreilicht + +jade: + forgejo: jade + github: lf- + +lovesegfault: + github: lovesegfault + +ma27: + forgejo: ma27 + github: ma27 + +matthewbauer: + github: matthewbauer + +midnightveil: + display_name: julia + forgejo: midnightveil + github: midnightveil + +ncfavier: + github: ncfavier + +puck: + display_name: puck + forgejo: puck + github: puckipedia + +r-vdp: + github: r-vdp + +raito: + display_name: Raito Bezarius + forgejo: raito + github: RaitoBezarius + roberth: display_name: Robert Hensing github: roberth -ericson: - display_name: John Ericson - github: ericson2314 +thufschmitt: + display_name: Théophane Hufschmitt + github: thufschmitt tomberek: display_name: Tom Bereknyei @@ -74,38 +103,9 @@ valentin: display_name: Valentin Gagarin github: fricklerhandwerk -lovesegfault: - github: lovesegfault +winter: + forgejo: winter + github: winterqt yshui: github: yshui - -ncfavier: - github: ncfavier - -midnightveil: - display_name: julia - forgejo: midnightveil - github: midnightveil - -puck: - display_name: puck - forgejo: puck - github: puckipedia - -alois31: - forgejo: alois31 - github: alois31 - -DavHau: - github: DavHau - -SharzyL: - github: SharzyL - -r-vdp: - github: r-vdp - -artemist: - display_name: Artemis Tosini - forgejo: artemist diff --git a/misc/pre-commit.nix b/misc/pre-commit.nix index ea39bc21d..ed2b152a3 100644 --- a/misc/pre-commit.nix +++ b/misc/pre-commit.nix @@ -66,6 +66,18 @@ pre-commit-run { ${lib.getExe pkgs.build-release-notes} --change-authors doc/manual/change-authors.yml doc/manual/rl-next doc/manual/rl-next-dev ''; }; + change-authors-sorted = { + enable = true; + package = pkgs.yq; + files = ''^doc/manual/change-authors\.yml''; + entry = "${pkgs.writeShellScript "change-authors-sorted" '' + set -euo pipefail + shopt -s inherit_errexit + + echo "changes necessary to sort $1:" + diff -U3 <(${lib.getExe pkgs.yq} -y . "$1") <(${lib.getExe pkgs.yq} -Sy . "$1") + ''}"; + }; check-headers = { enable = true; package = pkgs.check-headers; From 93948fb9f571eafe1cbaeb114dc586f901625cdc Mon Sep 17 00:00:00 2001 From: Qyriad Date: Sun, 19 May 2024 12:57:14 -0600 Subject: [PATCH 06/14] repl: log errors writing to history file These errors are now logged and explicitly ignored, rather than implicitly ignored. Change-Id: Ia26015466a17f2b11952df5317a4d150d79dc184 --- src/libcmd/repl-interacter.cc | 33 +++++++++++++++++++++++++++++++-- src/libcmd/repl-interacter.hh | 5 +++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/libcmd/repl-interacter.cc b/src/libcmd/repl-interacter.cc index d3567e021..41589cda1 100644 --- a/src/libcmd/repl-interacter.cc +++ b/src/libcmd/repl-interacter.cc @@ -1,6 +1,8 @@ #include #include #include +#include +#include #ifdef READLINE #include @@ -176,15 +178,42 @@ bool ReadlineLikeInteracter::getLine(std::string & input, ReplPromptType promptT if (!s) return false; - write_history(historyFile.c_str()); + this->writeHistory(); input += s; input += '\n'; return true; } +void ReadlineLikeInteracter::writeHistory() +{ + int ret = write_history(historyFile.c_str()); + int writeHistErr = errno; + + if (ret == 0) { + return; + } + + // If the open fails, editline returns EOF. If the close fails, editline + // forwards the return value of fclose(), which is EOF on error. + // readline however, returns the errno. + // So if we didn't get exactly EOF, then consider the return value the error + // code; otherwise use the errno we saved above. + // https://github.com/troglobit/editline/issues/66 + if (ret != EOF) { + writeHistErr = ret; + } + + // In any of these cases, we should explicitly ignore the error, but log + // them so the user isn't confused why their history is getting eaten. + + std::string_view const errMsg(std::strerror(writeHistErr)); + warn("ignoring error writing repl history to %s: %s", this->historyFile, errMsg); + +} + ReadlineLikeInteracter::~ReadlineLikeInteracter() { - write_history(historyFile.c_str()); + this->writeHistory(); } AutomationInteracter::Guard AutomationInteracter::init(detail::ReplCompleterMixin *) diff --git a/src/libcmd/repl-interacter.hh b/src/libcmd/repl-interacter.hh index c31b1a1e6..8f815fceb 100644 --- a/src/libcmd/repl-interacter.hh +++ b/src/libcmd/repl-interacter.hh @@ -42,6 +42,11 @@ public: } virtual Guard init(detail::ReplCompleterMixin * repl) override; virtual bool getLine(std::string & input, ReplPromptType promptType) override; + /** Writes the current history to the history file. + * + * This function logs but ignores errors from readline's write_history(). + */ + virtual void writeHistory(); virtual ~ReadlineLikeInteracter() override; }; From 509d1390134f9fd8d3de7a5fd128f13f2a8aac4e Mon Sep 17 00:00:00 2001 From: Qyriad Date: Tue, 21 May 2024 12:10:24 -0600 Subject: [PATCH 07/14] add libcmd test for lookupFileArg Change-Id: I9e2ef170ffe916f902daec8b5630d29434c5d5f2 --- tests/unit/libcmd/args.cc | 57 +++++++++++++++++++++++++++++++++++++++ tests/unit/meson.build | 27 +++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 tests/unit/libcmd/args.cc diff --git a/tests/unit/libcmd/args.cc b/tests/unit/libcmd/args.cc new file mode 100644 index 000000000..73550dacf --- /dev/null +++ b/tests/unit/libcmd/args.cc @@ -0,0 +1,57 @@ +#include +#include +#include + +#include +#include + +#include "common-eval-args.hh" +#include "eval.hh" +#include "filetransfer.hh" +#include "shared.hh" +#include "store-api.hh" +#include "util.hh" + +constexpr std::string_view INVALID_CHANNEL = "channel:example"; +constexpr std::string_view CHANNEL_URL = "https://nixos.org/channels/example/nixexprs.tar.xz"; + +namespace nix +{ + +TEST(Arguments, lookupFileArg) { + initNix(); + initGC(); + + std::string const unitDataPath = getEnv("_NIX_TEST_UNIT_DATA").value(); + // Meson should be allowed to pass us a relative path here tbh. + auto const canonDataPath = CanonPath::fromCwd(unitDataPath); + + std::string const searchPathElem = fmt("example=%s", unitDataPath); + + SearchPath searchPath; + searchPath.elements.push_back(SearchPath::Elem::parse(searchPathElem)); + + auto store = openStore("dummy://"); + auto statePtr = std::make_shared(searchPath, store, store); + auto & state = *statePtr; + + SourcePath const foundUnitData = lookupFileArg(state, ""); + EXPECT_EQ(foundUnitData.path, canonDataPath); + + // lookupFileArg should not resolve if anything else is before or after it. + SourcePath const yepEvenSpaces = lookupFileArg(state, " "); + EXPECT_EQ(yepEvenSpaces.path, CanonPath::fromCwd(" ")); + EXPECT_EQ(lookupFileArg(state, "/nixos").path, CanonPath::fromCwd("/nixos")); + + try { + lookupFileArg(state, INVALID_CHANNEL); + } catch (FileTransferError const & ex) { + std::string_view const msg(ex.what()); + EXPECT_NE(msg.find(CHANNEL_URL), msg.npos); + } + + SourcePath const normalFile = lookupFileArg(state, unitDataPath); + EXPECT_EQ(normalFile.path, canonDataPath); +} + +} diff --git a/tests/unit/meson.build b/tests/unit/meson.build index f5355cce8..6041ba497 100644 --- a/tests/unit/meson.build +++ b/tests/unit/meson.build @@ -212,3 +212,30 @@ test( protocol : 'gtest', verbose : true, ) + +libcmd_tester = executable( + 'liblixcmd-tests', + files('libcmd/args.cc'), + dependencies : [ + liblixcmd, + liblixutil, + liblixmain, + liblixexpr, + liblixstore, + gtest, + boost, + ], +) + +test( + 'libcmd-unit-tests', + libcmd_tester, + args : tests_args, + env : { + # No special meaning here, it's just a file laying around that is unlikely to go anywhere + # any time soon. + '_NIX_TEST_UNIT_DATA': meson.project_source_root() / 'src/nix-env/buildenv.nix', + }, + suite : 'check', + protocol : 'gtest', +) From c5f1cdf055548338a52fe20ee65b86d0647969a2 Mon Sep 17 00:00:00 2001 From: Qyriad Date: Mon, 20 May 2024 13:16:09 -0600 Subject: [PATCH 08/14] add docstring to lookupFileArg Change-Id: Ifc149764f5a15725d3d630677c6da29def4b0f3e --- src/libcmd/common-eval-args.hh | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/libcmd/common-eval-args.hh b/src/libcmd/common-eval-args.hh index 6359b2579..08a4b65e4 100644 --- a/src/libcmd/common-eval-args.hh +++ b/src/libcmd/common-eval-args.hh @@ -28,6 +28,26 @@ private: std::map autoArgs; }; -SourcePath lookupFileArg(EvalState & state, std::string_view s); +/** @brief Resolve an argument that is generally a file, but could be something that + * is easy to resolve to a file, like a or a tarball URL. + * + * In particular, this will resolve and fetch pseudo-URLs starting with + * @c channel:, flakerefs starting with @c flake:, and anything that + * @ref nix::fetchers::downloadTarball() can take. + * + * Non-absolute files are looked up relative to the current directory(?) + * FIXME: the process's current directory or EvalState's current directory? + * + * @param state The nix::EvalState to base settings, store, and nixPath from. + * + * @param fileArg The the path-ish to resolve. + * + * @return A nix::SourcePath to the resolved and fetched file. + * + * @exception nix::FileTransferError from nix::fetchers::downloadTarball(). Probably others. + * + * @exception nix::ThrownError for failed search path lookup. Probably others. + */ +SourcePath lookupFileArg(EvalState & state, std::string_view fileArg); } From 2478e80e7147c1765fced0735e3e3434495e24d3 Mon Sep 17 00:00:00 2001 From: Qyriad Date: Mon, 20 May 2024 13:51:42 -0600 Subject: [PATCH 09/14] cleanup lookupFileArg Change-Id: I2acd56e7a542b12138f43c95af78fdd50e944619 --- src/libcmd/common-eval-args.cc | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/libcmd/common-eval-args.cc b/src/libcmd/common-eval-args.cc index 94a4b7922..9beea5aa2 100644 --- a/src/libcmd/common-eval-args.cc +++ b/src/libcmd/common-eval-args.cc @@ -164,28 +164,30 @@ Bindings * MixEvalArgs::getAutoArgs(EvalState & state) return res.finish(); } -SourcePath lookupFileArg(EvalState & state, std::string_view s) +SourcePath lookupFileArg(EvalState & state, std::string_view fileArg) { - if (EvalSettings::isPseudoUrl(s)) { - auto storePath = fetchers::downloadTarball( - state.store, EvalSettings::resolvePseudoUrl(s), "source", false).tree.storePath; + if (EvalSettings::isPseudoUrl(fileArg)) { + auto const url = EvalSettings::resolvePseudoUrl(fileArg); + auto const downloaded = fetchers::downloadTarball( + state.store, + url, + /* name */ "source", + /* locked */ false + ); + StorePath const storePath = downloaded.tree.storePath; return state.rootPath(CanonPath(state.store->toRealPath(storePath))); - } - - else if (s.starts_with("flake:")) { + } else if (fileArg.starts_with("flake:")) { experimentalFeatureSettings.require(Xp::Flakes); - auto flakeRef = parseFlakeRef(std::string(s.substr(6)), {}, true, false); + static constexpr size_t FLAKE_LEN = std::string_view("flake:").size(); + auto flakeRef = parseFlakeRef(std::string(fileArg.substr(FLAKE_LEN)), {}, true, false); auto storePath = flakeRef.resolve(state.store).fetchTree(state.store).first.storePath; return state.rootPath(CanonPath(state.store->toRealPath(storePath))); - } - - else if (s.size() > 2 && s.at(0) == '<' && s.at(s.size() - 1) == '>') { - Path p(s.substr(1, s.size() - 2)); + } else if (fileArg.size() > 2 && fileArg.at(0) == '<' && fileArg.at(fileArg.size() - 1) == '>') { + Path p(fileArg.substr(1, fileArg.size() - 2)); return state.findFile(p); + } else { + return state.rootPath(CanonPath::fromCwd(fileArg)); } - - else - return state.rootPath(CanonPath::fromCwd(s)); } } From 94978101e452be64fc7cd6a96a874e6983f333c5 Mon Sep 17 00:00:00 2001 From: Qyriad Date: Mon, 20 May 2024 20:54:00 -0600 Subject: [PATCH 10/14] build: make internal-api-docs PHONY Since we're skipping Meson's dependency tracking, for the internal-api-docs custom target, we should just consider it a phony target and build it on every request. Change-Id: I3b0bcea30ee9a4830023ccc5bededf995e96cccc --- doc/internal-api/meson.build | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/internal-api/meson.build b/doc/internal-api/meson.build index 35d8a0e5b..faa30f194 100644 --- a/doc/internal-api/meson.build +++ b/doc/internal-api/meson.build @@ -28,6 +28,7 @@ internal_api_docs = custom_target( output : 'html', install : true, install_dir : datadir / 'doc/nix/internal-api', + build_always_stale : true, ) alias_target('internal-api-html', internal_api_docs) From 3ddf2ccacdc47b22fd081d4aff3eae7badcd1fab Mon Sep 17 00:00:00 2001 From: Qyriad Date: Mon, 20 May 2024 21:58:27 -0600 Subject: [PATCH 11/14] docs: linkify nix3-build mention in nix-build.md Change-Id: I462a8cf0da42b5045ce84b48dc1841ecdccbb89e --- doc/manual/src/command-ref/nix-build.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/doc/manual/src/command-ref/nix-build.md b/doc/manual/src/command-ref/nix-build.md index b548edf82..92e642ddd 100644 --- a/doc/manual/src/command-ref/nix-build.md +++ b/doc/manual/src/command-ref/nix-build.md @@ -14,9 +14,8 @@ # Disambiguation -This man page describes the command `nix-build`, which is distinct from `nix -build`. For documentation on the latter, run `nix build --help` or see `man -nix3-build`. +This man page describes the command [`nix-build`](./new-cli/nix3-build.md), which is distinct from `nix build`. +For documentation on the latter, run `nix build --help` or see `man nix3-build`. # Description From 28aeb9df2c47f5ef79bbe531e17cda9ed494ea74 Mon Sep 17 00:00:00 2001 From: Qyriad Date: Tue, 21 May 2024 15:37:08 -0600 Subject: [PATCH 12/14] docs: document the cursed file syntax for old cli This documents the fact that nix-build, nix-env, nix-instantiate, and nix-shell accept an extended syntax for their file arguments, including some well-known (but not well documented) aspects, like being able to specify ``, but also https:// tarball URLs, `flake:` prefixed flakerefs, and the cursed `channel:` prefixed hardcoded URLs Same thing for the new CLI incoming :) Change-Id: Ib6d68594a16132805ba5d97526e16f7b3633117e --- doc/manual/src/command-ref/fileish-summary.md | 14 ++++++ doc/manual/src/command-ref/nix-build.md | 50 ++++++++++++++++--- doc/manual/src/command-ref/nix-env.md | 2 +- .../src/command-ref/nix-env/opt-common.md | 16 ++++-- doc/manual/src/command-ref/nix-instantiate.md | 9 ++-- doc/manual/src/command-ref/nix-shell.md | 5 +- 6 files changed, 76 insertions(+), 20 deletions(-) create mode 100644 doc/manual/src/command-ref/fileish-summary.md diff --git a/doc/manual/src/command-ref/fileish-summary.md b/doc/manual/src/command-ref/fileish-summary.md new file mode 100644 index 000000000..31b68aada --- /dev/null +++ b/doc/manual/src/command-ref/fileish-summary.md @@ -0,0 +1,14 @@ + +- A normal filesystem path, like `/home/meow/nixfiles/default.nix` + - Including a directory, like `/home/meow/nixfiles`, equivalent to above +- A single lookup path, like `` or `` +- A URL to a tarball, like `https://github.com/NixOS/nixpkgs/archive/refs/heads/release-23.11.tar.gz` +- A flakeref, introduced by the prefix `flake:`, like `flake:git+https://git.lix.systems/lix-project/lix` +- A channel name, introduced by the prefix `channel:`, like `channel:nixpkgs-unstable`. + - This uses a hard-coded URL pattern and is *not* related to the subscribed channels managed by the [nix-channel](@docroot@/command-ref/nix-channel.md) command. diff --git a/doc/manual/src/command-ref/nix-build.md b/doc/manual/src/command-ref/nix-build.md index 92e642ddd..bb0a6272a 100644 --- a/doc/manual/src/command-ref/nix-build.md +++ b/doc/manual/src/command-ref/nix-build.md @@ -4,7 +4,7 @@ # Synopsis -`nix-build` [*paths…*] +`nix-build` [*fileish…*] [`--arg` *name* *value*] [`--argstr` *name* *value*] [{`--attr` | `-A`} *attrPath*] @@ -20,19 +20,55 @@ For documentation on the latter, run `nix build --help` or see `man nix3-build`. # Description The `nix-build` command builds the derivations described by the Nix -expressions in *paths*. If the build succeeds, it places a symlink to +expressions in each *fileish*. If the build succeeds, it places a symlink to the result in the current directory. The symlink is called `result`. If there are multiple Nix expressions, or the Nix expressions evaluate to multiple derivations, multiple sequentially numbered symlinks are created (`result`, `result-2`, and so on). -If no *paths* are specified, then `nix-build` will use `default.nix` in +If no *fileish* is specified, then `nix-build` will use `default.nix` in the current directory, if it exists. -If an element of *paths* starts with `http://` or `https://`, it is -interpreted as the URL of a tarball that will be downloaded and unpacked -to a temporary location. The tarball must include a single top-level -directory containing at least a file named `default.nix`. +## Fileish Syntax + +A given *fileish* may take one of a few different forms, the first being a simple filesystem path, e.g. `nix-build /tmp/some-file.nix`. +Like the [import builtin](../language/builtins.md#builtins-import) specifying a directory is equivalent to specifying `default.nix` within that directory. +It may also be a [search path](./env-common.md#env-NIX_PATH) (also known as a lookup path) like ``, which is convenient to use with `--attr`/`-A`: + +```console +$ nix-build '' -A firefox +``` + +(Note the quotation marks around ``, which will be necessary in most Unix shells.) + +If a *fileish* starts with `http://` or `https://`, it is interpreted as the URL of a tarball which will be fetched and unpacked. +Lix will then `import` the unpacked directory, so these tarballs must include at least a single top-level directory with a file called `default.nix` +For example, you could build from a specific version of Nixpkgs with something like: + +```console +$ nix-build "https://github.com/NixOS/nixpkgs/archive/refs/heads/release-23.11.tar.gz" -A firefox +``` + +If a path starts with `flake:`, the rest of the argument is interpreted as a [flakeref](./new-cli/nix3-flake.md#flake-references) (see `nix flake --help` or `man nix3-flake`), which requires the "flakes" experimental feature to be enabled. +Lix will fetch the flake, and then `import` its unpacked directory, so the flake must include a file called `default.nix`. +For example, the flake analogues to the above `nix-build` commands are: + +```console +$ nix-build flake:nixpkgs -A firefox +$ nix-build flake:github:NixOS/nixpkgs/release-23.11 -A firefox +``` + +Finally, for legacy reasons, if a path starts with `channel:`, the rest of the argument is interpreted as the name of a channel to fetch from `https://nixos.org/channels/$CHANNEL_NAME/nixexprs.tar.xz`. +This is a **hard coded URL** pattern and is *not* related to the subscribed channels managed by the [nix-channel](./nix-channel.md) command. + +> **Note**: any of the special syntaxes may always be disambiguated by prefixing the path. +> For example: a file in the current directory literally called `` can be addressed as `./`, to escape the special interpretation. + +In summary, a path argument may be one of: + +{{#include ./fileish-summary.md}} + +## Notes `nix-build` is essentially a wrapper around [`nix-instantiate`](nix-instantiate.md) (to translate a high-level Nix diff --git a/doc/manual/src/command-ref/nix-env.md b/doc/manual/src/command-ref/nix-env.md index 5a9e05fed..b3940aeaa 100644 --- a/doc/manual/src/command-ref/nix-env.md +++ b/doc/manual/src/command-ref/nix-env.md @@ -8,7 +8,7 @@ [`--option` *name* *value*] [`--arg` *name* *value*] [`--argstr` *name* *value*] - [{`--file` | `-f`} *path*] + [{`--file` | `-f`} *fileish*] [{`--profile` | `-p`} *path*] [`--system-filter` *system*] [`--dry-run`] diff --git a/doc/manual/src/command-ref/nix-env/opt-common.md b/doc/manual/src/command-ref/nix-env/opt-common.md index 636281b6d..6efd6a4e3 100644 --- a/doc/manual/src/command-ref/nix-env/opt-common.md +++ b/doc/manual/src/command-ref/nix-env/opt-common.md @@ -2,16 +2,22 @@ The following options are allowed for all `nix-env` operations, but may not always have an effect. - - `--file` / `-f` *path*\ + - `--file` / `-f` *fileish*\ Specifies the Nix expression (designated below as the *active Nix expression*) used by the `--install`, `--upgrade`, and `--query --available` operations to obtain derivations. The default is `~/.nix-defexpr`. - If the argument starts with `http://` or `https://`, it is - interpreted as the URL of a tarball that will be downloaded and - unpacked to a temporary location. The tarball must include a single - top-level directory containing at least a file named `default.nix`. + *fileish* is interpreted the same as with [nix-build](../nix-build.md#Path_Syntax). + See that section for complete details (`nix-build --help`), but in summary, a path argument may be one of: + + - A normal filesystem path, like `/home/meow/nixfiles/default.nix` + - Including a directory, like `/home/meow/nixfiles`, equivalent to above + - A single lookup path, like `` or `` + - A URL to a tarball, like `https://github.com/NixOS/nixpkgs/archive/refs/heads/release-23.11.tar.gz` + - A flakeref, introduced by the prefix `flake:`, like `flake:git+https://git.lix.systems/lix-project/lix` + - A channel name, introduced by the prefix `channel:`, like `channel:nixpkgs-unstable`. + - This uses a hard-coded URL pattern and is *not* related to the subscribed channels managed by the [nix-channel](@docroot@/command-ref/nix-channel.md) command. - `--profile` / `-p` *path*\ Specifies the profile to be used by those operations that operate on diff --git a/doc/manual/src/command-ref/nix-instantiate.md b/doc/manual/src/command-ref/nix-instantiate.md index 479c9abcf..f9c7fcac5 100644 --- a/doc/manual/src/command-ref/nix-instantiate.md +++ b/doc/manual/src/command-ref/nix-instantiate.md @@ -11,7 +11,7 @@ [{`--attr`| `-A`} *attrPath*] [`--add-root` *path*] [`--expr` | `-E`] - *files…* + *fileish…* `nix-instantiate` `--find-file` *files…* @@ -25,8 +25,11 @@ of the resulting store derivations are printed on standard output. [store derivation]: ../glossary.md#gloss-store-derivation -If *files* is the character `-`, then a Nix expression will be read from -standard input. +If *fileish* is the character `-`, then a Nix expression will be read from standard input. +Otherwise, each *fileish* is interpreted the same as with [nix-build](./nix-build.md#Path_Syntax). +See that section for complete details (`nix-build --help`), but in summary, a path argument may be one of: + +{{#include ./fileish-summary.md}} # Options diff --git a/doc/manual/src/command-ref/nix-shell.md b/doc/manual/src/command-ref/nix-shell.md index 1eaf3c36a..ce33b264f 100644 --- a/doc/manual/src/command-ref/nix-shell.md +++ b/doc/manual/src/command-ref/nix-shell.md @@ -33,10 +33,7 @@ the environment of a derivation for development. If *path* is not given, `nix-shell` defaults to `shell.nix` if it exists, and `default.nix` otherwise. -If *path* starts with `http://` or `https://`, it is interpreted as the -URL of a tarball that will be downloaded and unpacked to a temporary -location. The tarball must include a single top-level directory -containing at least a file named `default.nix`. +{{#include ./fileish-summary.md}} If the derivation defines the variable `shellHook`, it will be run after `$stdenv/setup` has been sourced. Since this hook is not executed From 48d419feb863ba162b590758d24a0d85c470ad32 Mon Sep 17 00:00:00 2001 From: Qyriad Date: Wed, 22 May 2024 17:15:45 -0600 Subject: [PATCH 13/14] docstrings: NixRepl::getDerivationPath: exceptions directly thrown getDerivationPath() directly throws nix::Error for invalid derivations Change-Id: I81ead950060b789794fa683b61c6349fece1690d --- src/libcmd/repl.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libcmd/repl.cc b/src/libcmd/repl.cc index 89691d33a..4c5654408 100644 --- a/src/libcmd/repl.cc +++ b/src/libcmd/repl.cc @@ -107,6 +107,11 @@ struct NixRepl void initEnv() override; virtual StringSet completePrefix(const std::string & prefix) override; + + /** + * @exception nix::Error thrown directly if the expression does not evaluate + * to a derivation, or evaluates to an invalid derivation. + */ StorePath getDerivationPath(Value & v); ProcessLineResult processLine(std::string line); From 6c8685dd22a573b84f7bf3297297aa31597e1064 Mon Sep 17 00:00:00 2001 From: Qyriad Date: Wed, 22 May 2024 22:31:19 -0600 Subject: [PATCH 14/14] docs: document the cursed file syntax for new CLI This documents that all installables in the nix3 commands, in their --file/-f form accept an extended syntax for the file argument, which is the same as it is for nix-build and friends, some of which were well known in their nix-build forms (e.g. `nix-build '' -A hello) but are not well known in their nix3 forms (people rarely know that you can `nix build -f '' firefox`). Like the old CLI syntax, as documented in [1], file arguments also accept https:// tarball URLs, `flake:` prefixed flakerefs, and the cursed `channel:` prefixed hardened URLs. [1]: Ib6d68594a16132805ba5d97526e16f7b3633117e Change-Id: Ib81a5db1f60d5916f0f792d82054f3ac65717121 --- doc/manual/src/command-ref/fileish-summary.md | 1 + src/nix/nix.md | 44 ++++++++++++++++++- 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/doc/manual/src/command-ref/fileish-summary.md b/doc/manual/src/command-ref/fileish-summary.md index 31b68aada..496a451db 100644 --- a/doc/manual/src/command-ref/fileish-summary.md +++ b/doc/manual/src/command-ref/fileish-summary.md @@ -4,6 +4,7 @@ this also links to nix-build.md for the full explanation. This include file is manually duplicated in nix-env/opt-common.md because list indentation sadness. + It is also manually duplicated in src/nix/nix.md, because those files don't support include?? busted. --> - A normal filesystem path, like `/home/meow/nixfiles/default.nix` - Including a directory, like `/home/meow/nixfiles`, equivalent to above diff --git a/src/nix/nix.md b/src/nix/nix.md index 0d588cd01..f39d84fda 100644 --- a/src/nix/nix.md +++ b/src/nix/nix.md @@ -158,16 +158,58 @@ Example: `/nix/store/p7gp6lxdg32h4ka1q398wd9r2zkbbz2v-hello-2.10.drv^*` Example: `--file /path/to/nixpkgs hello` -When the option `-f` / `--file` *path* \[*attrpath*...\] is given, installables are interpreted as the value of the expression in the Nix file at *path*. +When the option `-f` / `--file` *fileish* \[*attrpath*...\] is given, installables are interpreted as the value of the Nix file specified by *fileish*. If attribute paths are provided, commands will operate on the corresponding values accessible at these paths. The Nix expression in that file, or any selected attribute, must evaluate to a derivation. +The *fileish* itself may take one of a few different forms, the first being a simple filesystem path, e.g. `nix build /tmp/some-file.nix`. +Like the [import builtin](../../language/builtins.md#builtins-import), specifying a directory is equivalent to specify `default.nix` within that directory. +It may also be a [search path](../env-common.md#env-NIX_PATH) (also known as a lookup path), like ``. +Unlike using `` in a `--expr` argument, this does not require `--impure`. + To emulate the `nix-build '' -A hello` pattern, use: ```console $ nix build -f '' hello ``` +If a *fileish* starts with `http://` or `https://`, it is interpreted as the URL of a tarball which will be fetched and unpacked. +Lix will then `import` the unpacked directory, so these tarballs must include at least a single top-level directory with a file called `default.nix`. +For example, you could build from a specific version of Nixpkgs with something like: + +```console +$ nix build "https://github.com/NixOS/nixpkgs/archive/refs/heads/release-23.11.tar.gz" firefox +``` + +If a *fileish* starts with `flake:`, the rest of the argument is interpreted as a [flakeref](./nix3-flake.md#flake-reference) (see `nix flake --help` or `man nix3-flake`), which requires the "flakes" experimental feature to be enabled. +This is is *not quite* the same as specifying a [flake output attrpath](#flake-output-attribute). +It does *not* access the flake directly, but instead fetches it and `import`s the unpacked directory. +In other words, it assumes that the flake has a `default.nix` file, and then interprets the attribute path relative to what `default.nix` evaluates to. + +For many flakes — including Nixpkgs — this will end up evaluating to the same thing. +These two commands build the same derivation, but one from the flake, and the other from `default.nix`: + +```console +$ nix build 'nixpkgs#firefox' # from flake.nix +$ nix build flake:nixpkgs firefox # from default.nix in the flake directory +``` + +Finally, for legacy reasons, if a *fileish* starts with `channel:`, the rest of the argument is interpreted as the name of a channel to fetch from `https://nixos.org/channels/$CHANNEL_NAME/nixexprs.tar.gz`. +This is a **hard coded URL** pattern and is *not* related to the subscribed channels managed by the [nix-channel](../nix-channel.md) command. + +> **Note**: any of the special syntaxes may always be disambiguated by prefixing the path. +> For example: a file in the current directory literally called `` can be addressed as `./`, to escape the special interpretation. + +In summary, a file path argument may be one of: + +- A normal filesystem path, like `/home/meow/nixfiles/default.nix` + - Including a directory, like `/home/meow/nixfiles`, equivalent to above +- A single lookup path, like `` or `` +- A URL to a tarball, like `https://github.com/NixOS/nixpkgs/archive/refs/heads/release-23.11.tar.gz` +- A flakeref, introduced by the prefix `flake:`, like `flake:git+https://git.lix.systems/lix-project/lix` +- A channel name, introduced by the prefix `channel:`, like `channel:nixpkgs-unstable`. + - This uses a hard-coded URL pattern and is *not* related to the subscribed channels managed by the [nix-channel](@docroot@/command-ref/nix-channel.md) command. + ### Nix expression Example: `--expr 'import {}' hello`