| > This is a pretty extravagant claim If one wants to just replace Homebrew it's really straightforward: Install: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
sh <(curl -L https://nixos.org/nix/install) --daemon
Usage: brew update nix channel --update
brew list nix-env --query --installed
brew search ruby nix-env --query --available --status ruby (or https://search.nixos.org/packages)
brew install ruby@3.2 nix-env --install -A nixpkgs.ruby_3_2
brew upgrade nix-env --upgrade
brew uninstall ruby nix-env --uninstall ruby
I really don't see how it is "unacceptably bad". You don't even have to understand anything about Nix and still be able to use the damn thing. Yes the real-version vs attribute-name-that-contains-a-version is a bit wonky but in practice that's seriously not an issue.But really, for versions you can actually pick whatever version you wish by hitting a specific channel state: nix-env -f https://github.com/NixOS/nixpkgs/archive/nixos-23.05.tar.gz -iA ruby
nix-env -f https://github.com/NixOS/nixpkgs/archive/88f63d51109.tar.gz -iA ruby
... which is a) completely generalisable for anything even those packages that don't have versions and b) completely removes any problems with dependency version conflicts.--- (Screw naysayers that would tell you not to use nix-env, because that is just not productive to turn people away. In practice nix-env works, as in, it pragmatically solves the real-world above problem for people, who can later decide on their own if they want to stop there or move to "better" things should they feel any limitation with that or another use case; and at that stage they'll be more comfortable doing so than when they just start using the thing. Best way to climb a mountain is one step at a time.) --- And then from there you get the other benefit of being immediately able to ramp up to having a per-project `shell.nix` and just be done with it by typing `nix-shell`: {
pkgs ? import <nixpkgs> {},
}:
pkgs.mkShell {
buildInputs = [
pkgs.ruby_3_2;
];
}
Or if like me you want to get fancy†: {
pkgs ? import <nixpkgs> {},
}:
let
# because I like it this way and can later reference ${ruby}
ruby = pkgs.ruby_3_2;
whatevs = pkgs.whatevs42;
in pkgs.mkShell {
buildInputs = [
ruby
whatevs
pkgs.foobar
];
# this is not nix-related, I just find that convenient
shellHook = ''
export RUBY_VERSION="$(ruby -e 'puts RUBY_VERSION.gsub(/\d+$/, "0")')"
export GEM_HOME="$(pwd)/vendor/bundle/ruby/$RUBY_VERSION"
export BUNDLE_PATH="$(pwd)/vendor/bundle"
export PATH="$GEM_HOME/bin:$PATH"
'';
}
Replace with this if you want to pin to a specific point in time: pkgs ? import(fetchTarball("https://github.com/NixOS/nixpkgs/archive/31b322916ae1.tar.gz")) {},
You can even have multiple of those: pkgsA ? import(fetchTarball("https://github.com/NixOS/nixpkgs/archive/31b322916ae1.tar.gz")) {},
pkgsB ? import(fetchTarball("https://github.com/NixOS/nixpkgs/archive/88f63d51109.tar.gz")) {},
...
buildInputs = [
pkgsA.foo
pkgsB.bar
];
Bonus: it also Just Works on your favorite Linux distro.In under 5min it can be immediately useful to anyone who knows how to use a package manager (may it brew or pacman or apt) without having to dive on any Nix detail. I will not buy that nixlang is a barrier in that case, you don't have to know nixlang to understand what is happening here. † Actually I just realised that I could probably use ${ruby} - which stringifies to the installed path on disk - and do: export RUBY_VERSION="$(${ruby}/bin/ruby -e 'puts RUBY_VERSION.gsub(/\d+$/, "0")')"
to reference the actual path, or maybe even just ${ruby.version} or something and not even subshell capture. Not that it matters. |
> I really don't see how it is "unacceptably bad"
1) Like you pointed out, documentation will advise against this approach. Is it it even portable (what the original thread of discussion was about)? After my initial usage of nix, I switched to following the "best practice" of writing derivations and specifying system dependencies in the configuration.nix .
2) The nix commands are undeniably more complex than their brew equivalents. If you've used nix enough to memorize them, this probably goes away. But to a casual user who only interacts with nix once in awhile, it's way easier to remember "search" than "--query --available" or "-qa". "search" also feels like a higher-level unstructured-human-readable command.
3) Even "nix-env" is sort of weird as a name, because it begs explanation of why "-env", and that starts pulling in more advanced concepts that maybe a user doesn't initially need to be exposed to. It also means then you have to remember when to use "nix" and when to use "nix-env".
As for the rest, consider the use case of setting up an environment with Python packages:
https://nixos.wiki/wiki/Python
This requires memorizing more commands and syntax.
And then if you want to change something about the configuration of that Python package:
https://stackoverflow.com/questions/70395839/how-to-globally...
And the problem is, by this point you've long ago lost most software developers. They gave up, wrote a dockerfile with `pip install` commands, and used `sed` or `patch` or something to make the small-scale changes.
And I have to admit, while the procedural solution is not as elegant nor reproducible nor crossplatform, there's less cognitive overhead and novel syntactic constructs required than switching to a language and library that forces you to distinguish between `override`, `overrideAttrs`, and `overridePythonAttrs`.