Skip to content

Commit

Permalink
Merge branch 'new-store-settings' into settings-split
Browse files Browse the repository at this point in the history
  • Loading branch information
Ericson2314 committed Jul 18, 2024
2 parents afee3ee + de1ec5a commit f7df182
Show file tree
Hide file tree
Showing 100 changed files with 1,420 additions and 584 deletions.
62 changes: 62 additions & 0 deletions doc/manual/rl-next/shebang-relative.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
synopsis: "`nix-shell` shebang uses relative path"
prs:
- 5088
- 11058
issues:
- 4232
---

<!-- unfortunately no link target for the specific syntax -->
Relative [path](@docroot@/language/values.md#type-path) literals in `nix-shell` shebang scripts' options are now resolved relative to the [script's location](@docroot@/glossary?highlight=base%20directory#gloss-base-directory).
Previously they were resolved relative to the current working directory.

For example, consider the following script in `~/myproject/say-hi`:

```shell
#!/usr/bin/env nix-shell
#!nix-shell --expr 'import ./shell.nix'
#!nix-shell --arg toolset './greeting-tools.nix'
#!nix-shell -i bash
hello
```

Older versions of `nix-shell` would resolve `shell.nix` relative to the current working directory; home in this example:

```console
[hostname:~]$ ./myproject/say-hi
error:
… while calling the 'import' builtin
at «string»:1:2:
1| (import ./shell.nix)
| ^

error: path '/home/user/shell.nix' does not exist
```

Since this release, `nix-shell` resolves `shell.nix` relative to the script's location, and `~/myproject/shell.nix` is used.

```console
$ ./myproject/say-hi
Hello, world!
```

**Opt-out**

This is technically a breaking change, so we have added an option so you can adapt independently of your Nix update.
The old behavior can be opted into by setting the option [`nix-shell-shebang-arguments-relative-to-script`](@docroot@/command-ref/conf-file.md#conf-nix-shell-shebang-arguments-relative-to-script) to `false`.
This option will be removed in a future release.

**`nix` command shebang**

The experimental [`nix` command shebang](@docroot@/command-ref/new-cli/nix.md?highlight=shebang#shebang-interpreter) already behaves in this script-relative manner.

Example:

```shell
#!/usr/bin/env nix
#!nix develop
#!nix --expr ``import ./shell.nix``
#!nix -c bash
hello
```
18 changes: 2 additions & 16 deletions doc/manual/src/language/syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,18 +190,13 @@ This section covers syntax and semantics of the Nix language.

### Path {#path-literal}

*Paths* are distinct from strings and can be expressed by path literals such as `./builder.sh`.

Paths are suitable for referring to local files, and are often preferable over strings.
- Path values do not contain trailing slashes, `.` and `..`, as they are resolved when evaluating a path literal.
- Path literals are automatically resolved relative to their [base directory](@docroot@/glossary.md#gloss-base-directory).
- The files referred to by path values are automatically copied into the Nix store when used in a string interpolation or concatenation.
- Tooling can recognize path literals and provide additional features, such as autocompletion, refactoring automation and jump-to-file.
*Paths* can be expressed by path literals such as `./builder.sh`.

A path literal must contain at least one slash to be recognised as such.
For instance, `builder.sh` is not a path:
it's parsed as an expression that selects the attribute `sh` from the variable `builder`.

Path literals are resolved relative to their [base directory](@docroot@/glossary.md#gloss-base-directory).
Path literals may also refer to absolute paths by starting with a slash.

> **Note**
Expand All @@ -215,15 +210,6 @@ This section covers syntax and semantics of the Nix language.
For example, `~/foo` would be equivalent to `/home/edolstra/foo` for a user whose home directory is `/home/edolstra`.
Path literals that start with `~` are not allowed in [pure](@docroot@/command-ref/conf-file.md#conf-pure-eval) evaluation.

Paths can be used in [string interpolation] and string concatenation.
For instance, evaluating `"${./foo.txt}"` will cause `foo.txt` from the same directory to be copied into the Nix store and result in the string `"/nix/store/<hash>-foo.txt"`.

Note that the Nix language assumes that all input files will remain _unchanged_ while evaluating a Nix expression.
For example, assume you used a file path in an interpolated string during a `nix repl` session.
Later in the same session, after having changed the file contents, evaluating the interpolated string with the file path again might not return a new [store path], since Nix might not re-read the file contents. Use `:r` to reset the repl as needed.

[store path]: @docroot@/store/store-path.md

Path literals can also include [string interpolation], besides being [interpolated into other expressions].

[interpolated into other expressions]: ./string-interpolation.md#interpolated-expressions
Expand Down
31 changes: 30 additions & 1 deletion doc/manual/src/language/types.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,37 @@ The function [`builtins.isString`](builtins.md#builtins-isString) can be used to

### Path {#type-path}

<!-- TODO(@rhendric, #10970): Incorporate content from syntax.md#path-literal -->
A _path_ in the Nix language is an immutable, finite-length sequence of bytes starting with `/`, representing a POSIX-style, canonical file system path.
Path values are distinct from string values, even if they contain the same sequence of bytes.
Operations that produce paths will simplify the result as the standard C function [`realpath`] would, except that there is no symbolic link resolution.

[`realpath`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/realpath.html

Paths are suitable for referring to local files, and are often preferable over strings.
- Path values do not contain trailing or duplicate slashes, `.`, or `..`.
- Relative path literals are automatically resolved relative to their [base directory].
- Tooling can recognize path literals and provide additional features, such as autocompletion, refactoring automation and jump-to-file.

[base directory]: @docroot@/glossary.md#gloss-base-directory

A file is not required to exist at a given path in order for that path value to be valid, but a path that is converted to a string with [string interpolation] or [string-and-path concatenation] must resolve to a readable file or directory which will be copied into the Nix store.
For instance, evaluating `"${./foo.txt}"` will cause `foo.txt` from the same directory to be copied into the Nix store and result in the string `"/nix/store/<hash>-foo.txt"`.
Operations such as [`import`] can also expect a path to resolve to a readable file or directory.

[string interpolation]: string-interpolation.md#interpolated-expression
[string-and-path concatenation]: operators.md#string-and-path-concatenation
[`import`]: builtins.md#builtins-import

> **Note**
>
> The Nix language assumes that all input files will remain _unchanged_ while evaluating a Nix expression.
> For example, assume you used a file path in an interpolated string during a `nix repl` session.
> Later in the same session, after having changed the file contents, evaluating the interpolated string with the file path again might not return a new [store path], since Nix might not re-read the file contents.
> Use `:r` to reset the repl as needed.
[store path]: @docroot@/store/store-path.md

Path values can be expressed as [path literals](syntax.md#path-literal).
The function [`builtins.isPath`](builtins.md#builtins-isPath) can be used to determine if a value is a path.

### Null {#type-null}
Expand Down
26 changes: 26 additions & 0 deletions doc/manual/src/protocols/tarball-fetcher.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,30 @@ Link: <https://example.org/hello/442793d9ec0584f6a6e82fa253850c8085bb150a.tar.gz
For tarball flakes, the value of the `lastModified` flake attribute is
defined as the timestamp of the newest file inside the tarball.

## Gitea and Forgejo support

This protocol is supported by Gitea since v1.22.1 and by Forgejo since v7.0.4/v8.0.0 and can be used with the following flake URL schema:

```
https://<domain name>/<owner>/<repo>/archive/<reference or revison>.tar.gz
```

> **Example**
>
>
> ```nix
> # flake.nix
> {
> inputs = {
> foo.url = "https://gitea.example.org/some-person/some-flake/archive/main.tar.gz";
> bar.url = "https://gitea.example.org/some-other-person/other-flake/archive/442793d9ec0584f6a6e82fa253850c8085bb150a.tar.gz";
> qux = {
> url = "https://forgejo.example.org/another-person/some-non-flake-repo/archive/development.tar.gz";
> flake = false;
> };
> };
> outputs = { foo, bar, qux }: { /* ... */ };
> }
```
[Nix Archive]: @docroot@/store/file-system-object/content-address.md#serial-nix-archive
1 change: 1 addition & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@
++ pkgs.nixComponents.nix-external-api-docs.nativeBuildInputs
++ [
pkgs.buildPackages.cmake
pkgs.shellcheck
modular.pre-commit.settings.package
(pkgs.writeScriptBin "pre-commit-hooks-install"
modular.pre-commit.settings.installationScript)
Expand Down
1 change: 0 additions & 1 deletion maintainers/flake-module.nix
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,6 @@
excludes = [
# We haven't linted these files yet
''^config/install-sh$''
''^misc/systemv/nix-daemon$''
''^misc/bash/completion\.sh$''
''^misc/fish/completion\.fish$''
''^misc/zsh/completion\.zsh$''
Expand Down
1 change: 1 addition & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ subproject('external-api-docs')
subproject('libutil-c')
subproject('libstore-c')
subproject('libexpr-c')
subproject('libmain-c')

# Language Bindings
subproject('perl')
Expand Down
17 changes: 12 additions & 5 deletions misc/systemv/nix-daemon
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,28 @@ else
fi

# Source function library.
# shellcheck source=/dev/null
. /etc/init.d/functions

LOCKFILE=/var/lock/subsys/nix-daemon
RUNDIR=/var/run/nix
PIDFILE=${RUNDIR}/nix-daemon.pid
RETVAL=0

base=${0##*/}
# https://www.shellcheck.net/wiki/SC3004
# Check if gettext exists
if ! type gettext > /dev/null 2>&1
then
# If not, create a dummy function that returns the input verbatim
gettext() { printf '%s' "$1"; }
fi

start() {

mkdir -p ${RUNDIR}
chown ${NIX_DAEMON_USER}:${NIX_DAEMON_USER} ${RUNDIR}

echo -n $"Starting nix daemon... "
printf '%s' "$(gettext 'Starting nix daemon... ')"

daemonize -u $NIX_DAEMON_USER -p ${PIDFILE} $NIX_DAEMON_BIN $NIX_DAEMON_OPTS
RETVAL=$?
Expand All @@ -58,7 +65,7 @@ start() {
}

stop() {
echo -n $"Shutting down nix daemon: "
printf '%s' "$(gettext 'Shutting down nix daemon: ')"
killproc -p ${PIDFILE} $NIX_DAEMON_BIN
RETVAL=$?
[ $RETVAL -eq 0 ] && rm -f ${LOCKFILE} ${PIDFILE}
Expand All @@ -67,7 +74,7 @@ stop() {
}

reload() {
echo -n $"Reloading nix daemon... "
printf '%s' "$(gettext 'Reloading nix daemon... ')"
killproc -p ${PIDFILE} $NIX_DAEMON_BIN -HUP
RETVAL=$?
echo
Expand Down Expand Up @@ -105,7 +112,7 @@ case "$1" in
fi
;;
*)
echo $"Usage: $0 {start|stop|status|restart|condrestart}"
printf '%s' "$(gettext "Usage: $0 {start|stop|status|restart|condrestart}")"
exit 2
;;
esac
Expand Down
1 change: 1 addition & 0 deletions packaging/components.nix
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ in
nix-flake-tests = callPackage ../tests/unit/libflake/package.nix { };

nix-main = callPackage ../src/libmain/package.nix { };
nix-main-c = callPackage ../src/libmain-c/package.nix { };

nix-cmd = callPackage ../src/libcmd/package.nix { };

Expand Down
1 change: 1 addition & 0 deletions packaging/hydra.nix
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ let
"nix-flake"
"nix-flake-tests"
"nix-main"
"nix-main-c"
"nix-cmd"
"nix-ng"
];
Expand Down
3 changes: 2 additions & 1 deletion src/build-remote/build-remote.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@

#include "machines.hh"
#include "shared.hh"
#include "plugin.hh"
#include "pathlocks.hh"
#include "globals.hh"
#include "serialise.hh"
#include "build-result.hh"
#include "store-api.hh"
#include "store-open.hh"
#include "strings.hh"
#include "derivations.hh"
#include "local-store.hh"
Expand Down
2 changes: 1 addition & 1 deletion src/libcmd/command.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#include "command.hh"
#include "markdown.hh"
#include "store-api.hh"
#include "store-open.hh"
#include "local-fs-store.hh"
#include "derivations.hh"
#include "nixexpr.hh"
Expand Down
2 changes: 1 addition & 1 deletion src/libcmd/common-eval-args.cc
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ Bindings * MixEvalArgs::getAutoArgs(EvalState & state)
auto v = state.allocValue();
std::visit(overloaded {
[&](const AutoArgExpr & arg) {
state.mkThunk_(*v, state.parseExprFromString(arg.expr, state.rootPath(".")));
state.mkThunk_(*v, state.parseExprFromString(arg.expr, compatibilitySettings.nixShellShebangArgumentsRelativeToScript ? state.rootPath(absPath(getCommandBaseDir())) : state.rootPath(".")));
},
[&](const AutoArgString & arg) {
v->mkString(arg.s);
Expand Down
19 changes: 18 additions & 1 deletion src/libcmd/compatibility-settings.hh
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,29 @@ struct CompatibilitySettings : public Config

CompatibilitySettings() = default;

// Added in Nix 2.24, July 2024.
Setting<bool> nixShellAlwaysLooksForShellNix{this, true, "nix-shell-always-looks-for-shell-nix", R"(
Before Nix 2.24, [`nix-shell`](@docroot@/command-ref/nix-shell.md) would only look at `shell.nix` if it was in the working directory - when no file was specified.
Since Nix 2.24, `nix-shell` always looks for a `shell.nix`, whether that's in the working directory, or in a directory that was passed as an argument.
You may set this to `false` to revert to the Nix 2.3 behavior.
You may set this to `false` to temporarily revert to the behavior of Nix 2.23 and older.
Using this setting is not recommended.
It will be deprecated and removed.
)"};

// Added in Nix 2.24, July 2024.
Setting<bool> nixShellShebangArgumentsRelativeToScript{
this, true, "nix-shell-shebang-arguments-relative-to-script", R"(
Before Nix 2.24, relative file path expressions in arguments in a `nix-shell` shebang were resolved relative to the working directory.
Since Nix 2.24, `nix-shell` resolves these paths in a manner that is relative to the [base directory](@docroot@/glossary.md#gloss-base-directory), defined as the script's directory.
You may set this to `false` to temporarily revert to the behavior of Nix 2.23 and older.
Using this setting is not recommended.
It will be deprecated and removed.
)"};
};

Expand Down
10 changes: 4 additions & 6 deletions src/libexpr/eval-settings.cc
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ EvalSettings::EvalSettings(bool & readOnlyMode, EvalSettings::LookupPathHooks lo
builtinsAbortOnWarn = true;
}

Strings EvalSettings::getDefaultNixPath() const
Strings EvalSettings::getDefaultNixPath()
{
Strings res;
auto add = [&](const Path & p, const std::string & s = std::string()) {
Expand All @@ -69,11 +69,9 @@ Strings EvalSettings::getDefaultNixPath() const
}
};

if (!restrictEval && !pureEval) {
add(getNixDefExpr() + "/channels");
add(rootChannelsDir() + "/nixpkgs", "nixpkgs");
add(rootChannelsDir());
}
add(getNixDefExpr() + "/channels");
add(rootChannelsDir() + "/nixpkgs", "nixpkgs");
add(rootChannelsDir());

return res;
}
Expand Down
2 changes: 1 addition & 1 deletion src/libexpr/eval-settings.hh
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ struct EvalSettings : Config

bool & readOnlyMode;

Strings getDefaultNixPath() const;
static Strings getDefaultNixPath();

static bool isPseudoUrl(std::string_view s);

Expand Down
4 changes: 2 additions & 2 deletions src/libexpr/eval.hh
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ struct Constant
typedef std::map<std::string, Value *> ValMap;
#endif

typedef std::map<PosIdx, DocComment> DocCommentMap;
typedef std::unordered_map<PosIdx, DocComment> DocCommentMap;

struct Env
{
Expand Down Expand Up @@ -335,7 +335,7 @@ private:
* Associate source positions of certain AST nodes with their preceding doc comment, if they have one.
* Grouped by file.
*/
std::map<SourcePath, DocCommentMap> positionToDocComment;
std::unordered_map<SourcePath, DocCommentMap> positionToDocComment;

LookupPath lookupPath;

Expand Down
2 changes: 1 addition & 1 deletion src/libexpr/parser-state.hh
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ struct LexerState
/**
* @brief Maps some positions to a DocComment, where the comment is relevant to the location.
*/
std::map<PosIdx, DocComment> & positionToDocComment;
std::unordered_map<PosIdx, DocComment> & positionToDocComment;

PosTable & positions;
PosTable::Origin origin;
Expand Down
2 changes: 1 addition & 1 deletion src/libexpr/parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@

namespace nix {

typedef std::map<PosIdx, DocComment> DocCommentMap;
typedef std::unordered_map<PosIdx, DocComment> DocCommentMap;

Expr * parseExprFromBuf(
char * text,
Expand Down
Loading

0 comments on commit f7df182

Please sign in to comment.