diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index 3a2d4de0e53..bd124fba60e 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -15,7 +15,7 @@ jobs: fetch-depth: 0 - name: Create backport PRs # should be kept in sync with `version` - uses: zeebe-io/backport-action@v0.0.8 + uses: zeebe-io/backport-action@v1.2.0 with: # Config README: https://github.com/zeebe-io/backport-action#backport-action github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 956f8168470..1005b48d589 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -77,7 +77,14 @@ jobs: with: install_url: '${{needs.installer.outputs.installerURL}}' install_options: "--tarball-url-prefix https://${{ env.CACHIX_NAME }}.cachix.org/serve" - - run: nix-instantiate -E 'builtins.currentTime' --eval + - run: sudo apt install fish zsh + if: matrix.os == 'ubuntu-latest' + - run: brew install fish + if: matrix.os == 'macos-latest' + - run: exec bash -c "nix-instantiate -E 'builtins.currentTime' --eval" + - run: exec sh -c "nix-instantiate -E 'builtins.currentTime' --eval" + - run: exec zsh -c "nix-instantiate -E 'builtins.currentTime' --eval" + - run: exec fish -c "nix-instantiate -E 'builtins.currentTime' --eval" docker_push_image: needs: [check_cachix, tests] diff --git a/.gitignore b/.gitignore index 0c1b89ace5d..8e0db013f8a 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,8 @@ perl/Makefile.config # /scripts/ /scripts/nix-profile.sh /scripts/nix-profile-daemon.sh +/scripts/nix-profile.fish +/scripts/nix-profile-daemon.fish # /src/libexpr/ /src/libexpr/lexer-tab.cc diff --git a/.version b/.version index ed0edc885be..c200bec4aff 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -2.11.0 \ No newline at end of file +2.11.1 \ No newline at end of file diff --git a/doc/manual/src/SUMMARY.md.in b/doc/manual/src/SUMMARY.md.in index 9b66ec3dbb7..4d1a5f79099 100644 --- a/doc/manual/src/SUMMARY.md.in +++ b/doc/manual/src/SUMMARY.md.in @@ -72,7 +72,6 @@ - [Hacking](contributing/hacking.md) - [CLI guideline](contributing/cli-guideline.md) - [Release Notes](release-notes/release-notes.md) - - [Release X.Y (202?-??-??)](release-notes/rl-next.md) - [Release 2.11 (2022-08-25)](release-notes/rl-2.11.md) - [Release 2.10 (2022-07-11)](release-notes/rl-2.10.md) - [Release 2.9 (2022-05-30)](release-notes/rl-2.9.md) diff --git a/flake.nix b/flake.nix index 1b26460e79c..36c90434844 100644 --- a/flake.nix +++ b/flake.nix @@ -15,7 +15,7 @@ then "" else "pre${builtins.substring 0 8 (self.lastModifiedDate or self.lastModified or "19700101")}_${self.shortRev or "dirty"}"; - officialRelease = false; + officialRelease = true; linux64BitSystems = [ "x86_64-linux" "aarch64-linux" ]; linuxSystems = linux64BitSystems ++ [ "i686-linux" ]; diff --git a/scripts/install-multi-user.sh b/scripts/install-multi-user.sh index 01dbf0c0ede..d44515bc2dc 100644 --- a/scripts/install-multi-user.sh +++ b/scripts/install-multi-user.sh @@ -37,6 +37,19 @@ readonly PROFILE_TARGETS=("/etc/bashrc" "/etc/profile.d/nix.sh" "/etc/zshrc" "/e readonly PROFILE_BACKUP_SUFFIX=".backup-before-nix" readonly PROFILE_NIX_FILE="$NIX_ROOT/var/nix/profiles/default/etc/profile.d/nix-daemon.sh" +# Fish has different syntax than zsh/bash, treat it separate +readonly PROFILE_FISH_SUFFIX="conf.d/nix.fish" +readonly PROFILE_FISH_PREFIXES=( + # each of these are common values of $__fish_sysconf_dir, + # under which Fish will look for a file named + # $PROFILE_FISH_SUFFIX. + "/etc/fish" # standard + "/usr/local/etc/fish" # their installer .pkg for macOS + "/opt/homebrew/etc/fish" # homebrew + "/opt/local/etc/fish" # macports +) +readonly PROFILE_NIX_FILE_FISH="$NIX_ROOT/var/nix/profiles/default/etc/profile.d/nix-daemon.fish" + readonly NIX_INSTALLED_NIX="@nix@" readonly NIX_INSTALLED_CACERT="@cacert@" #readonly NIX_INSTALLED_NIX="/nix/store/j8dbv5w6jl34caywh2ygdy88knx1mdf7-nix-2.3.6" @@ -828,6 +841,19 @@ fi EOF } +# Fish has differing syntax +fish_source_lines() { + cat <&2 - printf '\nif [ -e %s ]; then . %s; fi # added by Nix installer\n' "$p" "$p" >> "$fn" + printf '\nif [ -e %s ]; then . %s; fi # added by Nix installer\n' "$p_sh" "$p_sh" >> "$fn" fi added=1 + p=${p_sh} break fi done for i in .zshenv .zshrc; do fn="$HOME/$i" if [ -w "$fn" ]; then - if ! grep -q "$p" "$fn"; then + if ! grep -q "$p_sh" "$fn"; then echo "modifying $fn..." >&2 - printf '\nif [ -e %s ]; then . %s; fi # added by Nix installer\n' "$p" "$p" >> "$fn" + printf '\nif [ -e %s ]; then . %s; fi # added by Nix installer\n' "$p_sh" "$p_sh" >> "$fn" fi added=1 + p=${p_sh} break fi done + + if [ -d "$HOME/.config/fish" ]; then + fishdir=$HOME/.config/fish/conf.d + if [ ! -d "$fishdir" ]; then + mkdir -p "$fishdir" + fi + + fn="$fishdir/nix.fish" + echo "placing $fn..." >&2 + printf '\nif test -e %s; . %s; end # added by Nix installer\n' "$p_fish" "$p_fish" > "$fn" + added=1 + p=${p_fish} + fi +else + p=${p_sh} fi if [ -z "$added" ]; then diff --git a/scripts/local.mk b/scripts/local.mk index b8477178ec3..46255e43297 100644 --- a/scripts/local.mk +++ b/scripts/local.mk @@ -6,6 +6,8 @@ noinst-scripts += $(nix_noinst_scripts) profiledir = $(sysconfdir)/profile.d $(eval $(call install-file-as, $(d)/nix-profile.sh, $(profiledir)/nix.sh, 0644)) +$(eval $(call install-file-as, $(d)/nix-profile.fish, $(profiledir)/nix.fish, 0644)) $(eval $(call install-file-as, $(d)/nix-profile-daemon.sh, $(profiledir)/nix-daemon.sh, 0644)) +$(eval $(call install-file-as, $(d)/nix-profile-daemon.fish, $(profiledir)/nix-daemon.fish, 0644)) clean-files += $(nix_noinst_scripts) diff --git a/scripts/nix-profile-daemon.fish.in b/scripts/nix-profile-daemon.fish.in new file mode 100644 index 00000000000..56d851a9c39 --- /dev/null +++ b/scripts/nix-profile-daemon.fish.in @@ -0,0 +1,35 @@ +# Only execute this file once per shell. +if test -n "$__ETC_PROFILE_NIX_SOURCED" + return +end + +set __ETC_PROFILE_NIX_SOURCED 1 + +set --export NIX_PROFILES "@localstatedir@/nix/profiles/default $HOME/.nix-profile" + +# Set $NIX_SSL_CERT_FILE so that Nixpkgs applications like curl work. +if test -n "$NIX_SSH_CERT_FILE" + : # Allow users to override the NIX_SSL_CERT_FILE +else if test -e /etc/ssl/certs/ca-certificates.crt # NixOS, Ubuntu, Debian, Gentoo, Arch + set --export NIX_SSL_CERT_FILE /etc/ssl/certs/ca-certificates.crt +else if test -e /etc/ssl/ca-bundle.pem # openSUSE Tumbleweed + set --export NIX_SSL_CERT_FILE /etc/ssl/ca-bundle.pem +else if test -e /etc/ssl/certs/ca-bundle.crt # Old NixOS + set --export NIX_SSL_CERT_FILE /etc/ssl/certs/ca-bundle.crt +else if test -e /etc/pki/tls/certs/ca-bundle.crt # Fedora, CentOS + set --export NIX_SSL_CERT_FILE /etc/pki/tls/certs/ca-bundle.crt +else if test -e "$NIX_LINK/etc/ssl/certs/ca-bundle.crt" # fall back to cacert in Nix profile + set --export NIX_SSL_CERT_FILE "$NIX_LINK/etc/ssl/certs/ca-bundle.crt" +else if test -e "$NIX_LINK/etc/ca-bundle.crt" # old cacert in Nix profile + set --export NIX_SSL_CERT_FILE "$NIX_LINK/etc/ca-bundle.crt" +else + # Fall back to what is in the nix profiles, favouring whatever is defined last. + for i in $NIX_PROFILES + if test -e "$i/etc/ssl/certs/ca-bundle.crt" + set --export NIX_SSL_CERT_FILE "$i/etc/ssl/certs/ca-bundle.crt" + end + end +end + +fish_add_path --prepend --global "@localstatedir@/nix/profiles/default/bin" +fish_add_path --prepend --global "$HOME/.nix-profile/bin" diff --git a/scripts/nix-profile.fish.in b/scripts/nix-profile.fish.in new file mode 100644 index 00000000000..59d247771a5 --- /dev/null +++ b/scripts/nix-profile.fish.in @@ -0,0 +1,35 @@ +if test -n "$HOME" && test -n "$USER" + + # Set up the per-user profile. + + set NIX_LINK $HOME/.nix-profile + + # Set up environment. + # This part should be kept in sync with nixpkgs:nixos/modules/programs/environment.nix + set --export NIX_PROFILES "@localstatedir@/nix/profiles/default $HOME/.nix-profile" + + # Set $NIX_SSL_CERT_FILE so that Nixpkgs applications like curl work. + if test -n "$NIX_SSH_CERT_FILE" + : # Allow users to override the NIX_SSL_CERT_FILE + else if test -e /etc/ssl/certs/ca-certificates.crt # NixOS, Ubuntu, Debian, Gentoo, Arch + set --export NIX_SSL_CERT_FILE /etc/ssl/certs/ca-certificates.crt + else if test -e /etc/ssl/ca-bundle.pem # openSUSE Tumbleweed + set --export NIX_SSL_CERT_FILE /etc/ssl/ca-bundle.pem + else if test -e /etc/ssl/certs/ca-bundle.crt # Old NixOS + set --export NIX_SSL_CERT_FILE /etc/ssl/certs/ca-bundle.crt + else if test -e /etc/pki/tls/certs/ca-bundle.crt # Fedora, CentOS + set --export NIX_SSL_CERT_FILE /etc/pki/tls/certs/ca-bundle.crt + else if test -e "$NIX_LINK/etc/ssl/certs/ca-bundle.crt" # fall back to cacert in Nix profile + set --export NIX_SSL_CERT_FILE "$NIX_LINK/etc/ssl/certs/ca-bundle.crt" + else if test -e "$NIX_LINK/etc/ca-bundle.crt" # old cacert in Nix profile + set --export NIX_SSL_CERT_FILE "$NIX_LINK/etc/ca-bundle.crt" + end + + # Only use MANPATH if it is already set. In general `man` will just simply + # pick up `.nix-profile/share/man` because is it close to `.nix-profile/bin` + # which is in the $PATH. For more info, run `manpath -d`. + set --export --prepend --path MANPATH "$NIX_LINK/share/man" + + fish_add_path --prepend --global "$NIX_LINK/bin" + set --erase NIX_LINK +end diff --git a/scripts/nix-profile.sh.in b/scripts/nix-profile.sh.in index 45cbcbe743d..5636085d4df 100644 --- a/scripts/nix-profile.sh.in +++ b/scripts/nix-profile.sh.in @@ -1,7 +1,6 @@ if [ -n "$HOME" ] && [ -n "$USER" ]; then # Set up the per-user profile. - # This part should be kept in sync with nixpkgs:nixos/modules/programs/shell.nix NIX_LINK=$HOME/.nix-profile diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc index e097f23b303..18c536aea89 100644 --- a/src/libcmd/installables.cc +++ b/src/libcmd/installables.cc @@ -23,6 +23,23 @@ namespace nix { +std::string InstallablesSettings::getDefaultFlake(std::string_view url) +{ + std::string res = defaultFlake; + if (res == "") { + throw UsageError("don't know how to handle installable '%s' without flake URL, because the option 'default-flake' is not set", url); + } + return res; +} + +InstallablesSettings installablesSettings; + +static GlobalConfig::Register rInstallablesSettings(&installablesSettings); + +const static std::regex attrPathRegex( + R"((?:[a-zA-Z0-9_"-][a-zA-Z0-9_".-]*(?:\^((\*)|([a-z]+(,[a-z]+)*)))?))", + std::regex::ECMAScript); + MixFlakeOptions::MixFlakeOptions() { auto category = "Common flake-related options"; @@ -269,15 +286,29 @@ void completeFlakeRefWithFragment( /* Look for flake output attributes that match the prefix. */ try { + bool isAttrPath = std::regex_match(prefix.begin(), prefix.end(), attrPathRegex); auto hash = prefix.find('#'); + completionType = ctAttrs; + if (hash == std::string::npos) { completeFlakeRef(evalState->store, prefix); - } else { - completionType = ctAttrs; + } + + if (isAttrPath || hash != std::string::npos) { + auto fragment = + isAttrPath + ? prefix + : prefix.substr(hash + 1); + + auto flakeRefS = + isAttrPath + ? std::string(installablesSettings.getDefaultFlake(prefix)) + : std::string(prefix.substr(0, hash)); - auto fragment = prefix.substr(hash + 1); - auto flakeRefS = std::string(prefix.substr(0, hash)); - auto flakeRef = parseFlakeRef(expandTilde(flakeRefS), absPath(".")); + // FIXME: do tilde expansion. + auto flakeRef = parseFlakeRef( + flakeRefS, + isAttrPath ? std::optional{} : absPath(".")); auto evalCache = openEvalCache(*evalState, std::make_shared(lockFlake(*evalState, flakeRef, lockFlags))); @@ -308,7 +339,13 @@ void completeFlakeRefWithFragment( auto attrPath2 = (*attr)->getAttrPath(attr2); /* Strip the attrpath prefix. */ attrPath2.erase(attrPath2.begin(), attrPath2.begin() + attrPathPrefix.size()); - completions->add(flakeRefS + "#" + concatStringsSep(".", evalState->symbols.resolve(attrPath2))); + + std::string resolvedAttrPath2 = concatStringsSep(".", evalState->symbols.resolve(attrPath2)); + + if (isAttrPath) + completions->add(resolvedAttrPath2); + else + completions->add(flakeRefS + "#" + resolvedAttrPath2); } } } @@ -345,7 +382,7 @@ void completeFlakeRef(ref store, std::string_view prefix) if (!hasPrefix(prefix, "flake:") && hasPrefix(from, "flake:")) { std::string from2(from, 6); if (hasPrefix(from2, prefix)) - completions->add(from2); + completions->add(from2 + "#"); } else { if (hasPrefix(from, prefix)) completions->add(from); @@ -755,6 +792,16 @@ FlakeRef InstallableFlake::nixpkgsFlakeRef() const return Installable::nixpkgsFlakeRef(); } +static std::tuple parseOnlyAttrPath( + const std::string &s) { + auto [fragment, outputsSpec] = parseOutputsSpec(s); + return { + parseFlakeRef(installablesSettings.getDefaultFlake(s), {}), + fragment, + outputsSpec + }; +} + std::vector> SourceExprCommand::parseInstallables( ref store, std::vector ss) { @@ -810,7 +857,13 @@ std::vector> SourceExprCommand::parseInstallables( } try { - auto [flakeRef, fragment, outputsSpec] = parseFlakeRefWithFragmentAndOutputsSpec(s, absPath(".")); + bool isAttrPath = std::regex_match(s, attrPathRegex); + + auto [flakeRef, fragment, outputsSpec] = + isAttrPath + ? parseOnlyAttrPath(s) + : parseFlakeRefWithFragmentAndOutputsSpec(s, absPath(".")); + result.push_back(std::make_shared( this, getEvalState(), diff --git a/src/libcmd/installables.hh b/src/libcmd/installables.hh index 948f7891922..89d6221e0f7 100644 --- a/src/libcmd/installables.hh +++ b/src/libcmd/installables.hh @@ -12,6 +12,16 @@ namespace nix { +struct InstallablesSettings : Config +{ + Setting defaultFlake{this, "", "default-flake", + "The default flake URL when using the command line interface"}; + + std::string getDefaultFlake(std::string_view url); +}; + +extern InstallablesSettings installablesSettings; + struct DrvInfo; struct SourceExprCommand; diff --git a/src/libstore/sandbox-network.sb b/src/libstore/sandbox-network.sb index 56beec761fa..19e9eea9a71 100644 --- a/src/libstore/sandbox-network.sb +++ b/src/libstore/sandbox-network.sb @@ -14,3 +14,7 @@ ; Allow DNS lookups. (allow network-outbound (remote unix-socket (path-literal "/private/var/run/mDNSResponder"))) + +; Allow access to trustd. +(allow mach-lookup (global-name "com.apple.trustd")) +(allow mach-lookup (global-name "com.apple.trustd.agent")) diff --git a/src/nix/search.cc b/src/nix/search.cc index bdd45cbed95..2e56a69a3d0 100644 --- a/src/nix/search.cc +++ b/src/nix/search.cc @@ -21,8 +21,9 @@ std::string wrap(std::string prefix, std::string s) return concatStrings(prefix, s, ANSI_NORMAL); } -struct CmdSearch : InstallableCommand, MixJSON +struct CmdSearch : SourceExprCommand, MixJSON { + std::string _installable{installablesSettings.defaultFlake}; std::vector res; std::vector excludeRes; @@ -38,6 +39,24 @@ struct CmdSearch : InstallableCommand, MixJSON excludeRes.push_back(s); }}, }); + + bool hasInstallable = false; + + addFlag({ + .longName = "installable", + .shortName = 'i', + .description = "Search within this installable", + .labels = {"installable"}, + .handler = {[this, &hasInstallable](std::string ss) { + hasInstallable = true; + _installable = ss; + }}, + .completer = completePath + }); + + if (hasInstallable && (file || expr)) { + throw UsageError("'--installable' cannot be used together with '--file' or '--expr'"); + } } std::string description() override @@ -62,9 +81,15 @@ struct CmdSearch : InstallableCommand, MixJSON void run(ref store) override { + if (_installable == "" && ! file && ! expr) { + throw UsageError("nothing to search from, set 'default-flake' option or specify one of '--installable', '--file', '--expr'"); + } + settings.readOnlyMode = true; evalSettings.enableImportFromDerivation.setDefault(false); + auto installable = parseInstallable(store, (file || expr) ? "" : _installable); + // Empty search string should match all packages // Use "^" here instead of ".*" due to differences in resulting highlighting // (see #1893 -- libc++ claims empty search string is not in POSIX grammar) diff --git a/tests/flakes/flakes.sh b/tests/flakes/flakes.sh index 267e2cd6fe3..fef337efdc8 100644 --- a/tests/flakes/flakes.sh +++ b/tests/flakes/flakes.sh @@ -99,7 +99,7 @@ nix build -o $TEST_ROOT/result flake1#foo [[ -e $TEST_ROOT/result/hello ]] # Test packages.default. -nix build -o $TEST_ROOT/result flake1 +nix build -o $TEST_ROOT/result flake1# [[ -e $TEST_ROOT/result/hello ]] nix build -o $TEST_ROOT/result $flake1Dir diff --git a/tests/search.sh b/tests/search.sh index 1a98f5b49ca..df27e1a6452 100644 --- a/tests/search.sh +++ b/tests/search.sh @@ -3,40 +3,40 @@ source common.sh clearStore clearCache -(( $(nix search -f search.nix '' hello | wc -l) > 0 )) +(( $(nix search -f search.nix hello | wc -l) > 0 )) # Check descriptions are searched -(( $(nix search -f search.nix '' broken | wc -l) > 0 )) +(( $(nix search -f search.nix broken | wc -l) > 0 )) # Check search that matches nothing -(( $(nix search -f search.nix '' nosuchpackageexists | wc -l) == 0 )) +(( $(nix search -f search.nix nosuchpackageexists | wc -l) == 0 )) # Search for multiple arguments -(( $(nix search -f search.nix '' hello empty | wc -l) == 2 )) +(( $(nix search -f search.nix hello empty | wc -l) == 2 )) # Multiple arguments will not exist -(( $(nix search -f search.nix '' hello broken | wc -l) == 0 )) +(( $(nix search -f search.nix hello broken | wc -l) == 0 )) ## Search expressions # Check that empty search string matches all -nix search -f search.nix '' |grep -q foo -nix search -f search.nix '' |grep -q bar -nix search -f search.nix '' |grep -q hello +nix search -f search.nix |grep -q foo +nix search -f search.nix |grep -q bar +nix search -f search.nix |grep -q hello ## Tests for multiple regex/match highlighting e=$'\x1b' # grep doesn't support \e, \033 or even \x1b # Multiple overlapping regexes -(( $(nix search -f search.nix '' 'oo' 'foo' 'oo' | grep -c "$e\[32;1mfoo$e\\[0;1m") == 1 )) -(( $(nix search -f search.nix '' 'broken b' 'en bar' | grep -c "$e\[32;1mbroken bar$e\\[0m") == 1 )) +(( $(nix search -f search.nix 'oo' 'foo' 'oo' | grep -c "$e\[32;1mfoo$e\\[0;1m") == 1 )) +(( $(nix search -f search.nix 'broken b' 'en bar' | grep -c "$e\[32;1mbroken bar$e\\[0m") == 1 )) # Multiple matches # Searching for 'o' should yield the 'o' in 'broken bar', the 'oo' in foo and 'o' in hello -(( $(nix search -f search.nix '' 'o' | grep -Eoc "$e\[32;1mo{1,2}$e\[(0|0;1)m") == 3 )) +(( $(nix search -f search.nix 'o' | grep -Eoc "$e\[32;1mo{1,2}$e\[(0|0;1)m") == 3 )) # Searching for 'b' should yield the 'b' in bar and the two 'b's in 'broken bar' # NOTE: This does not work with `grep -c` because it counts the two 'b's in 'broken bar' as one matched line -(( $(nix search -f search.nix '' 'b' | grep -Eo "$e\[32;1mb$e\[(0|0;1)m" | wc -l) == 3 )) +(( $(nix search -f search.nix 'b' | grep -Eo "$e\[32;1mb$e\[(0|0;1)m" | wc -l) == 3 )) ## Tests for --exclude (( $(nix search -f search.nix -e hello | grep -c hello) == 0 ))