Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[staging] setup.sh: Support XDG_DATA_DIRS (bash completion in nix-shell) #103501

Merged
merged 3 commits into from Nov 25, 2020

Conversation

roberth
Copy link
Member

@roberth roberth commented Nov 11, 2020

Motivation for this change

Add bash completion support for packages in nix-shells.

Closes #26031

XDG_DATA_DIRS is to /share as PATH is to /bin.

It was defined as part of the XDG basedir specification.
https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html

While it originated from the X Desktop Group, it is not limited to
the X11 ecosystem, as evidenced by its use in bash-completion.

TODO

  • one more test locally
  • check buildInputs vs nativeBuildInputs behavior (not expecting any surprises though)
    • either of which works with bash completion because strictDeps is disabled
    • buildInputs should not be loaded because those will be for the wrong system
  • test a significant portion of Nixpkgs builds
    • gnome3.eog
    • konsole
Things done
  • Tested using sandboxing (nix.useSandbox on NixOS, or option sandbox in nix.conf on non-NixOS linux)
  • Built on platform(s)
    • NixOS
    • macOS
    • other Linux distributions
  • Tested via one or more NixOS test(s) if existing and applicable for the change (look inside nixos/tests)
  • Tested compilation of all pkgs that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review wip"
  • Tested execution of all binary files (usually in ./result/bin/)
  • Determined the impact on package closure size (by running nix path-info -S before and after)
  • Ensured that relevant documentation is up to date
  • Fits CONTRIBUTING.md.

@roberth roberth changed the title setup.sh: Support XDG_DATA_DIRS setup.sh: Support XDG_DATA_DIRS (bash completion in nix-shell) Nov 11, 2020
@roberth roberth marked this pull request as ready for review November 12, 2020 00:56
@matthewbauer
Copy link
Member

While I think this is a good idea, I just wanted to note something similar was previously discussed in NixOS/nix#2443 and @edolstra had some objections. It may be less controversial in Nixpkgs though since we rely on XDG_DATA_DIRS in a lot of places already.

@@ -602,9 +603,11 @@ fi

PATH="${_PATH-}${_PATH:+${PATH:+:}}$PATH"
HOST_PATH="${_HOST_PATH-}${_HOST_PATH:+${HOST_PATH:+:}}$HOST_PATH"
XDG_DATA_DIRS="${_XDG_DATA_DIRS-}${_XDG_DATA_DIRS:+${XDG_DATA_DIRS:+:}}${XDG_DATA_DIRS-}"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I spent a couple minutes looking through Nixpkgs to see if this could interfere with anything. I don't think it will, but setting something like this can always have unintended consequences. The main concern would be if native XDG_DATA_DIRS gets mixed in with target XDG_DATA_DIRS in cross-compilation. For things like bash completion and man pages, it's not such a big deal, but XDG_DATA_DIRS is also used to locate qt5 plugins.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since it's not exported, this might not be as much of a problem actually.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is implicitly exported when XDG_DATA_DIRS already exists as an environment variable (and --pure isn't used).

Always exporting it seems more consistent. If mixing with the nix-shell host environment is problematic, that can be avoided with nix-shell --pure.

In cross compilation without strictDeps, mixing will occur. Perhaps XDG_DATA_DIRS should follow "strictDeps" behavior regardless. That will require development shells to put tools in nativeBuildInputs instead of buildInputs for bash completion to work. nix-shell -p gets that wrong, so it won't work there yet, but can be fixed.

@roberth
Copy link
Member Author

roberth commented Nov 13, 2020

Ok, XDG_DATA_DIRS now follows strictDeps-like behavior. No mixing with cross-compilation outputs will occur.
(If some hypothetical build saves XDG_DATA_DIRS, that's equivalent to saving the builder's PATH; just one out of a thousand potential bad build ideas)

Also XDG_DATA_DIRS is now always exported as one will expect it to. Previous behavior was potentially confusing.

Copy link
Member

@Ericson2314 Ericson2314 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me!

@zowoq zowoq mentioned this pull request Nov 18, 2020
10 tasks
@@ -602,9 +606,11 @@ fi

PATH="${_PATH-}${_PATH:+${PATH:+:}}$PATH"
HOST_PATH="${_HOST_PATH-}${_HOST_PATH:+${HOST_PATH:+:}}$HOST_PATH"
export XDG_DATA_DIRS="${_XDG_DATA_DIRS-}${_XDG_DATA_DIRS:+${XDG_DATA_DIRS:+:}}${XDG_DATA_DIRS-}"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this going to affect wrapGAppsHook or wrapQtAppsHook in any way?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It shouldn't affect those.
This variable is set in the build environment, not in the wrapper scripts.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc @NixOS/freedesktop

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, so being set in the build environment, but during fixup it shouldn't be?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well it's still set during fixupPhase but it doesn't affect the wrapper writing functions. Although, it can affect call sites if they are like wrapProgram --set XDG_DATA_DIRS $XDG_DATA_DIRS, so expanding $XDG_DATA_DIRS before invoking wrapProgram, but I don't think we have that?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, wrapGAppsHook uses different environment variables for populating XDG_DATA_DIRS for wrapper. So unless one of those variables is populated from XDG_DATA_DIRS (do not see any such thing when greping sh files for XDG_DATA_DIRS so it would have to be indirectly through some program).

The only possible issue that comes to mind is that it further distances the build environment from the runtime one, possibly obscuring some missing dependencies until runtime (i.e. (install)CheckPhase passes but program will crash at runtime). But perhaps the difference is huge enough already so this might not be so much worse in proportion.

@nixos-discourse
Copy link

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/setup-bash-completion-when-running-under-nix-shell-on-macosx/5216/6

@nixos-discourse
Copy link

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/shell-nix-load-completions/8803/15

@jonringer
Copy link
Contributor

My understanding is that only nativeBuildInputs have shell completion from this, however, most examples use buildInputs.

nix manual: https://nixos.org/manual/nix/unstable/command-ref/nix-shell.html
wiki: https://nixos.wiki/wiki/Development_environment_with_nix-shell
wiki / cachix: https://nixos.wiki/wiki/Caching_nix_shell_build_inputs

I don't think this is a blocker, but we should probably update the documentation examples so that people get expected behavior

@roberth
Copy link
Member Author

roberth commented Nov 19, 2020

My understanding is that only nativeBuildInputs have shell completion from this, however, most examples use buildInputs.

That is correct. buildInputs shouldn't be loaded on PATH either. That is a legacy behavior.

The idea is that XDG_DATA_DIRS supports apps that run in the "current" context, build in our cross compilation terminology. buildInputs can, in general, only run in the host context. Loading these by default will cause issues with cross compilation.

This change does affect all derivations after all, for better or for worse. I'm hopeful but this needs testing.

Speaking of testing, on non-cross we should probably change or unset XDG_DATA_DIRS during checkPhase and installCheckPhase.

I don't think this is a blocker, but we should probably update the documentation examples so that people get expected behavior

💯. Should have been done with the introduction of cross compilation.

@Ericson2314
Copy link
Member

Ericson2314 commented Nov 19, 2020

@jonringer Yeah, we've never found a sane way to flip the strictDeps switch without breaking the world. This PR to me says "fine, but new functionality should be strictDeps-style". I think this is a rather clever way to "nudge not shove" the ecosystem in the right direction --- nothing will be broken, per se, but the incentive to switch will compound over time.

I like it a lot!

Copy link
Contributor

@jonringer jonringer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@zimbatm
Copy link
Member

zimbatm commented Nov 22, 2020

One thing I didn't understand is; what kind of black magic auto-loads the completion? Is it part of bash itself to look for those files?

Incidentally, I recently worked on unifying the bash completions outputs: #103421

zimbatm added a commit to numtide/devshell that referenced this pull request Nov 22, 2020
It looks like bash automatically finds the right completion scripts by
looking into XDG_DATA_DIRS. Probably other programs respecting XDG specs
can also benefit from setting that environment variable.

Thanks to NixOS/nixpkgs#103501 for finding that
gem.

I don't understand how this works, the Bash source code doesn't mention
XDG at all. Maybe it's a NixOS-specific thing.
@roberth
Copy link
Member Author

roberth commented Nov 22, 2020

@zimbatm

One thing I didn't understand is; what kind of black magic auto-loads the completion? Is it part of bash itself to look for those files?

No black magic, just a shell script in the bash-completion package.

https://github.com/scop/bash-completion/blob/f7475cf2c0d60f690a0bd758e3fa84976017b99a/bash_completion#L2185-L2187

Incidentally, I recently worked on unifying the bash completions outputs: #103421

That's great!

XDG_DATA_DIRS is to /share as PATH is to /bin.

It was defined as part of the XDG basedir specification.
https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html

While it originated from the X Desktop Group, it is not limited to
the X11 ecosystem, as evidenced by its use in bash-completion.

The removal of ` && -d "$pkg/bin"` is ok, because this optimization is
already performed by `addToSearchPath`.
This avoids the scenario where strictDeps is off and cross-compiled
XDG_DATA_DIRS content is brought into the environment.

While probably harmless for data like manpages and completion scripts,
this would cause issues when XDG_DATA_DIRS is used to find executables
or plugins. The Qt framework is known to behave like this and might
have run into incompatibilities.
By exporting it, we always make the new directories available
to subprocesses, regardless of whether the environment
variable existed before `nix-shell` was invoked.
@roberth
Copy link
Member Author

roberth commented Nov 22, 2020

  • Fixed up the first commit to unset the "private" _XDG_DATA_DIRS (note the underscore)
  • Tested build and execution of
    • gnome3.eog
    • konsole (KDE)

@roberth
Copy link
Member Author

roberth commented Nov 22, 2020

Speaking of testing, on non-cross we should probably change or unset XDG_DATA_DIRS during checkPhase and installCheckPhase.

We don't do this for PATH either, so let's keep it simple.
Another reason not to automagically change it for the check phases is that we want the package author to figure out that the data dependency exists, so that they are aware that XDG_DATA_DIRS must be set when the package is used.

UPDATE: ofborg fails for other reason; seems to want to build too much

@roberth roberth changed the title setup.sh: Support XDG_DATA_DIRS (bash completion in nix-shell) [staging] setup.sh: Support XDG_DATA_DIRS (bash completion in nix-shell) Nov 22, 2020
@jonringer
Copy link
Contributor

@GrahamcOfBorg eval

@Ericson2314
Copy link
Member

wiki: https://nixos.wiki/wiki/Development_environment_with_nix-shell
wiki / cachix: https://nixos.wiki/wiki/Caching_nix_shell_build_inputs

BTW I just updated those to use nativeBuildInputs where appropriate. Perhaps is a hoop users won't choose to jump through, and that's fine, but at least those docs won't be misleading them.

zimbatm added a commit to numtide/devshell that referenced this pull request Nov 24, 2020
It looks like bash automatically finds the right completion scripts by
looking into XDG_DATA_DIRS. Probably other programs respecting XDG specs
can also benefit from setting that environment variable.

Thanks to NixOS/nixpkgs#103501 for finding that
gem.

I don't understand how this works, the Bash source code doesn't mention
XDG at all. Maybe it's a NixOS-specific thing.
zimbatm added a commit to numtide/devshell that referenced this pull request Nov 24, 2020
The bash-completions package automatically finds the right completion
scripts by looking into XDG_DATA_DIRS. Probably other programs
respecting XDG specs can also benefit from setting that environment
variable.

Thanks to NixOS/nixpkgs#103501 for finding that
gem.
zimbatm added a commit to numtide/devshell that referenced this pull request Nov 24, 2020
The bash-completions package automatically finds the right completion
scripts by looking into XDG_DATA_DIRS. Probably other programs
respecting XDG specs can also benefit from setting that environment
variable.

Thanks to NixOS/nixpkgs#103501 for finding that
gem.
@roberth
Copy link
Member Author

roberth commented Nov 25, 2020

Any objections to testing this on staging?

@jonringer jonringer merged commit c8ae3d8 into NixOS:staging Nov 25, 2020
zimbatm added a commit to zimbatm/cabal2nix that referenced this pull request Dec 10, 2020
Use "$out/share/bash-completion/completions" because it gets
automatically loaded by the bash-completions package if "$out/share" is
listed in the XDG_DATA_DIRS environment variable.

This combined with NixOS/nixpkgs#103501 will
mean that nix-shell environments can have completion available.
rvl added a commit to cardano-foundation/cardano-wallet that referenced this pull request Jul 19, 2021
Profpatsch pushed a commit to Profpatsch/cabal2nix that referenced this pull request Mar 7, 2022
Use "$out/share/bash-completion/completions" because it gets
automatically loaded by the bash-completions package if "$out/share" is
listed in the XDG_DATA_DIRS environment variable.

This combined with NixOS/nixpkgs#103501 will
mean that nix-shell environments can have completion available.
tennox pushed a commit to tennox/devshell that referenced this pull request May 17, 2022
The bash-completions package automatically finds the right completion
scripts by looking into XDG_DATA_DIRS. Probably other programs
respecting XDG specs can also benefit from setting that environment
variable.

Thanks to NixOS/nixpkgs#103501 for finding that
gem.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants