-
-
Notifications
You must be signed in to change notification settings - Fork 14.1k
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
No way to install/use a specific package version? #9682
Comments
Single-version policyWe keep multiple versions in nixpkgs only when there's a good reason to. Nix is able to handle any number of versions/configurations, but on the other hand it's much more convenient when all (or most) use just a single one. It leads to better sharing of the effort in many respects: simplified maintenance, testing, sharing of the binaries, etc. It's what most distros do. (Only gentoo diverges from the big ones I know, and they pay a price for it.) When we do create more variants, we just name them (attribute paths), e.g. Only now, we build on the order of 40 thousand packages on the build farm (counting platform variants, etc.), but the number of active contributors is only in dozens. http://hydra.nixos.org/jobset/nixpkgs/trunk Identical environmentsIf you're concerned about identical environments, you need to also have the same nixpkgs version, that's for sure ;-) To be certain, you can just copy those by |
Installing specific versions works just fine, AFAIC:
And here is the same thing for a Haskell package:
So I'm not sure what problem you see? |
First of all, thank you both for your responses! @peti Right, but as @vcunat said, "We keep multiple versions in nixpkgs only when there's a good reason to."
So what happens if I have to fix a bug in an old project that was using 0.8.1.1? I clone the project from Github, go to set it up with Nix, and now it doesn't compile because Nix wants to use 0.9.0.1 and doesn't give me any other options. My choices seem to be either 1) Be forced to upgrade the project to 0.9.0.1 just to fix a minor bug or 2) Somehow install the package from source myself and make Nix use that instead of the version in nixpkgs. Neither option makes using Nix seem like a better choice than eg. Stack or NPM or Bundler etc, since they'd handle this version requirement seamlessly. @vcunat Thanks for the detailed explanation, that helps me understand the bigger picture better. I hadn't been aware of I guess I'm coming at this from a specific perspective - I'm coming from front-end web development (and now trying to use Haskell/GHCJS), and all the tools I've used for package management for these projects (Bower, NPM, Bundler, etc.) operate on the basis of specifying version ranges for dependencies and locking them down to versions that you know will work. This then necessitates the ability to install any arbitrary version of a package since multiple projects (or even multiple dependencies of a project) can end up specifying different versions from each other. However, the benefit is that any time you install the project anywhere you know that you'll have a working set of dependencies and thus a working project. This is also nice when it comes to deployment, because you can have confidence that if the CI build passes the code will work on the server, and you can have continuous deployment with confidence (as long as package maintainers follow semver). As I wrote above, you're also able to pull down old projects and do work on them despite depending on old packages since you're able to install the old packages without problems. I see that there are some workarounds for some of these things, such as using a previous revision of nixpkgs, but nothing that seems easy and seamless like these other package managers. I just can't see how to use Nix if you can't (reasonably) use it to install specific versions of packages, since that's a use case I've seen again and again. For example, just today I found a bug in a package I needed to use - normally I would have tried the previous release while waiting for the maintainer to fix the package or I would have fixed it and used my fork while waiting for the PR to go through, but with Nix I was out of luck. I've also often needed to install a newer version of a package than my distro made available, which with Ubuntu came down to just simply adding a PPA, but with Nix I'm tied down to whatever's in the channel. I do love the idea of Nix (and NixOS!), and I really want it to be something that can work for me. Perhaps I'm just missing the point or philosophy of Nix? Given that I seem to be the only person with these concerns maybe there's a reason they're a moot point and the approach I'm trying to take to deal with them is unnecessary with Nix? |
In that particular case, Nix won't help you and you are better off using a You always have the option of adding missing versions of certain packages to your local database by means of an override as described in http://nixos.org/nixpkgs/manual/#how-to-create-nix-builds-for-your-own-private-haskell-packages. You can register If you feel that there are certain older packages that Nixpkgs should contain, then you can also add them to the list at https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/haskell-modules/configuration-hackage2nix.yaml#L35, and they'll show up in our package database within the next 2-3 days. Anyhow, if you want a tool that can easily build any version of any package from Hackage, then |
Sorry, I didn't mean to close the issue. I just hit the wrong button. |
Thanks for clarifying :) I've been doing a lot more research in light of what you said and I think I'm starting to understand how the pieces fit together. In the interest of brevity I won't explain all the changes in my understanding but there is still one thing I'm struggling to understand: Nix expressions have no control over the set of packages that they receive. (tl;dr section at the bottom) From the perspective of having pure functions and having composability/overridability etc. I see the benefit here. However, from the perspective of a web developer where getting our projects up and running needs to able to be automated across any environment (developer machines, CI, production servers, etc.) this seems like a problem, since the project is no longer "self-contained" in terms of containing all the configuration/commands/etc. needed to bootstrap itself. For example, let's say I create a project using the Of course, that information could be documented somewhere, but having to follow specific steps outlined in the readme hurts the "reliable and reproducible" aspect of using Nix (and detracts from the benefits of having a default.nix in the first place). When writing a project with end-users in mind the ability to choose an arbitrary channel may be beneficial, but when the intended use of the project is to be easily deployed via automation it seems detrimental. As an example of a counterpoint to Nix in this regard, Stack allows an LTS Haskell version (similar to a Nix channel if I understand correctly) to be specified in the project's TL;DR Essentially, as I understand it, in order for Nix to enable a project to be reproducible in a reliable and automatable way it would need to be able to specify what channel it needs to get its packages from. This way it 1) Does not need to be (potentially incorrectly) specified by the user and 2) Is consistent across each invocation. Is there anything I'm missing here that Nix already has that addresses this issue? I know that a default could be specified in the arguments to the Nix expression. That approach would be good in that it still allows the argument to specified manually if necessary, but it still falls short in that the default argument could only reference a channel if it was already registered with the host system. |
@mayhewluke yup that's the general idea. In our organization we have our own branch of nixpkgs that we occasionally update and run a binary cache for. This way employees can easily install dependencies on the local network and know that the builds will work, with the added benefit that it's super fast! Alternatively if you're working in a less centralized environment you could do this trick where you pin the nixpkgs version in the shell.nix itself: https://garbas.si/2015/reproducible-development-environments.html nix is flexible enough to cater to these different workflows. I think eventually we'll be able to target stackage from nixpkgs as well if you're into that sort of thing. |
But they do. Things that are no parameter to your functions cannot vary, i.e. https://github.com/peti/ghc-library-id-bug/blob/master/default.nix#L5.
Sure, but note that this doesn't mean that the version of all packages in that release are fixed. LTS releases can and do change: https://github.com/fpco/lts-haskell/commits/master/lts-3.2.yaml. |
Ah, fantastic! @jb55 that blog post and @peti your code in @peti thanks a ton for your patience in helping me understand all this. I now have the answers to every question/concern I've raised in this thread. I'll post a summary here of my questions/the answers once I've had the chance to write it up. Hopefully this will help anyone else who may have similar questions and might also help Nix maintainers to be able to save time on answering questions :) Thanks again! |
|
Some problems with that approach:
I would love to be able to do something like |
I find one often has to create a fork/branch of nixpkgs for a particular dev project anyway, e.g. because of a need to update something in nixpkgs and use it now without waiting to push to official master or waiting on channels. I think that simple step also "magically" solves all of the problems you mention. |
That just moves the problem, doesn't it? Instead of needing some way to point a |
But you have lots of ways to do that: |
BTW, recently nix got support to easily specify exactly the commit hash that you want to use: http://nixos.org/nix/manual/#sec-common-env |
Don't you want to be able to specify a packages source in a config file, to avoid requiring each dev to set up their own environment variables or command-line parameters? I don't understand how I'm failing to communicate the motivation here. The current situation is awkward because there exists a multiplicity of with rec {
channelPath = name: file:
"${builtins.getEnv "HOME"}/.nix-defexpr/channels/${name}/pkgs/top-level/${file}";
channel = name: file: import (channelPath name file) { config = config; };
};
pkgs = rec {
nixos-15-09 = channel "nixos-15.09" "all-packages.nix";
nixos-unstable = channel "nixos-unstable" "default.nix";
default = nixos-unstable; # or whatever the user picks as their default
} (I've done something like this in my own config to write expressions that use multiple channels.) Then anything that wants to be able to select channels by name could do so from that expression, with no command-line parameters or env vars necessary. |
I personally want my dev projects to use versions independent of each other and independent of channels or the version my system uses, so that Still, it would seem nice if |
I don't completely understand why this issue is closed. All I see are workarounds.To summarize what I have read here (correct me if I am wrong) @mayhewluke described some real drawbacks of how derivations are currently implemented:
@peti brought up some concerns as reasons for the current behavior:
and some workarounds:
I still have some serious issues with this.
My proposed solutionHere are my thoughts about how Nix should deal with package versions. Please tell me your thoughts. How hard would this really be to implement? Can we make a branch of nixpkgs, and make these changes? Let a derivation specify a range of versions for each dependency.
Different versions are provided by different derivations.As far as I know, this is already true. The only difference would be that the names are always the same. If you tell nix to install a package, it should just grab the latest version that channel has. If you want a specific version, specify (that's the part you can't do currently). TL;DR The versions are there! Use them!Most, if not all derivations specify a version string, and append it to the name. |
@thomastjeffery there are projects that try to automate the conversion of other package manager indexes to Nix expressions. It still requires someone to commit in the new expressions in nixpkgs. Although the I think the haskage integration is fully automated (not sure). But the basic idea is that version numbers don't make sense in Nix because it's meant to be content addressed. There needs to be a translation from the version specification to a content addressed expression in nixpkgs to get what you want. For now most of this is done manually. Also every previous iteration of a channel is still accessible. |
Oh and some packages do support version as a parameter. Then you need to write a package override and call that package with your desired version specifier. But this parameterisation of the version is not standardised and may not even work if different versions build differently! |
For a clearer example, I just spent a few hours learning (#28248) that I need to add thirteen package overrides, and use the This is a real problem.
I understand that. Until I found this issue, I didn't know you could search To be clear, I don't advocate providing more versions. We should, however, be clear about what versions are available without this mess of package names. It's confusing for relatively new users like myself, and makes the system more complex. I just want to be able to specify more clearly, and to work with a cleaner, more functional codebase. After all, Nix is the pure functional package manager.
What do you mean by that? There are packages, and those packages have versions. Sure, Nix addresses the store with hashes, but versions are still important. |
If you give nix a version specification, nix doesn't know what hash this corresponds to, nor where to get it. Something needs to bridge that gap. That's why versions would have to be a parameter in nix that gets mapped to a hash somewhere, however because it's meant to be pure, we cannot call into other/remote package indexes to dynamically fetch the hash. That's why the translation from version to hash has to happen at "compile time". If we can standardise an infrastructure for doing this and then writing adapters to this infrastructure for every package index that exists, then it would be alot simpler! |
I've been debating with myself of whether to pin the nix-shell to a commit hash of nixpkgs or to leave it to the OS using |
@CMCDragonkai not pinning hashes has bitten me too many times when building old projects. now I always pin. pin2win. as long as you have a nix-build generated symlink lying around it shouldn't get gc'd. |
So what I want is to have a package's The real change I want, is for a derivation to be able to specify a range of compatible versions, or even just one specific version for any given dependency.
Nix currently knows what hash a package name corresponds to, because it is constrained to the one package that is defined by the channel it is using.
What am I missing? |
We got here because when updating sdl2-ttf, someone made a new So in a way, specifying the version number in the attribute is a way of specifying a version for dependencies. However, if I understand what you want correctly now, I think this distinction between the package name and the version (instead of having them together) could help in giving a guarantee that you are getting the latest available version of a package in a channel. As in, attributes cannot do that because you have no guarantee that the default (i.e. version-less) attribute is really the latest available version (e.g. sdl2-ttf was really only 1.0.0, because imo someone didn't do it right). And names, as they are currently, cannot do that because they always have the version in them, so you are always forced to specify a version (or are you.. maybe there's like some 'glob' syntax or something??). So if we split the name into the 'package name' and the version, then we can just specify a package name, and then nix can look at all the available nix expressions for a particular package name and simply pick the one with the biggest version number. And that comparison that nix would do between the versions would give us this guarantee that we got the latest available version. Is something like that what you are looking for?
Unless I'm missing something, he could though, he just didn't know about pinning. I think the bigger issue with that though is that I don't really think 'channels' are all that useful for development environments. They're probably OK for users, but you're right channels are too limiting because you're always stuck on what's on your channel. In fact, iirc there was some talk about removing the entire concept of channels from nix, but I'm not sure if it was for the same/similar reasons (and can't find it atm unfortunately). |
@jb55 How do you deal with the situation when your default.nix and shell.nix won't match and cannot match because the "building" of something is separate from the development environment of the same thing. For example some tools are only needed during dev, and not during build. And in other cases, I only need a `shell.nix` and not a `default.nix` because the thing I'm developing isn't intended to be a nix deployable package?
My default.nix just takes a single variable: nixpkgs. That way
everything remains consistent in the build and in the shell. Here's an
example from one of my projects:
https://gist.github.com/jb55/6e93156ca7fe90a36bb08df0408446a3
I'm being kind of sloppy with the buildInputs here, could be cleaned up a bit.
|
@vyp It sounds like we are on the same page regarding package names.
If I understand correctly, pinning allows a If you are dependent on the channel for reproducible builds, what happens when the channel updates a package? Channels are effectively nix versions. Using the
That's the heart of the issue. The problem is not the limitation of channels, per se, but the fact that we are trying to shove them into a use-case they aren't designed for. Like I said earlier, channels are like OS versions.
|
No pinning isn't about which channels you get. Pinning pins to a content
addressed commit hash of nixpkgs or any nixpkgs even your own fork.
Channels is orthogonal and probably a mistake and should be removed.
…On 27 Sep 2017 06:24, "Thomas Jeffery" ***@***.***> wrote:
@vyp <https://github.com/vyp> It sounds like we are on the same page
regarding package names.
Unless I'm missing something, he could though, he just didn't know about
pinning.
If I understand correctly, pinning allows a .nix to specify what *channel*
it gets, not what *dependency versions* it gets. Package versions are
still just whatever the channel provides. That may solve the "reproducible"
issue, but not the "specific dependency version".
If you are dependent on the channel for reproducible builds, what happens
when the channel updates a package?
Channels are effectively nix versions. Using the 17.09 channel is akin to
using Debian 9, and using the master channel is akin to using Debian
sid/unstable. Neither guarantees a specific package version *unless* you
specify a specific *channel revision*. If I understand correctly, that is
what you mean by "pinning". There are several obvious issues with that:
1. What's "pinning"? Is this ever explained to a new user? Where?
- (Yes, *I* understand what it is now, but new users probably will
not, meaning it doesn't exist to them.)
2. Your packages *never* get bug-fix updates
3. Your packages *never* get security updates
4. Broken package expressions *never* get fixed.
5. If you need to update *one* package, you *must update them all*.
- This can be seen as either consistency, or limitation. It depends
on the use case.
I think the bigger issue with that though is that I don't really think
'channels' are all that useful for development environments. They're
probably OK for users, but you're right channels are too limiting because
you're always stuck on what's on your channel.
That's the heart of the issue. The problem is not the limitation of
channels, *per se*, but the fact that we are trying to shove them into a
use-case they aren't designed for.
Like I said earlier, channels are like OS versions.
- They provide the latest version of a package that they want to
provide.
- They may provide multiple versions of a package, to fill
dependencies.
- This introduces a naming conflict that we are *working around*
instead of fixing.
- They *do not* provide older package versions that aren't used by
other packages.
- That's reasonable, since users don't want them, but developers do.
- How about we give developers a clear way to do that?
- I don't think channels are the solution here.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#9682 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAnHHdLZ5YWX2XKQ5Ohtf3GeJY_wItiNks5smV2LgaJpZM4F4oZ9>
.
|
My mistake. From my understanding, though, channels simply represent nixpkgs git branches. I suppose pinning, then, is more like git tags. Thanks for the explanation.
That's an interesting point, but since, as you said, channels are orthogonal, it would probably be best to have that discussion elsewhere. Still, that doesn't change the limitations I mentioned, or the current situation with package names sometimes containing versions. |
I think pinning is more than just git tags. Git tags is like versions (one can change a git tag to point to something else after it is first published, and there's no computational relationship between the git tag and the data/code that it points to). Pinning is making use of a content addressed hash, the result is a cryptographically guaranteed snapshot of the software you're expecting. Because git is a content addressed store. You can then pick and choose any commit hash through out the entire history of nixpkgs to use including even the PRs and other people's forks. One effect of this is that you get reproducibility. Note that this is not binary reproducibility, since it's still possible for the compilation of code to give different resulting binaries. But it is reproducibility within the context of Nix universe. Oh and with regards to pinning, take a look at this: http://matrix.ai/2017/03/13/intro-to-nix-channels-and-reproducible-nixos-environment/ I wrote that a while ago regarding the pinning of the OS. And yes you don't get automatic updates. This is by design. Auto updating in nix would not be automatic like the way Chrome updates, it would be a more considered approach, where you choose when you want to update. Also you'll find that reproducibility is something that you will prefer when you're developing things! If channels were to be removed, it would be more clearer to everybody including new users, what the real use and power of nix is, and all documentation would go straight to pinning. Then only after understanding this, can people write higher level abstract tools to provide an auto-updating "channel" like interface to the underlying pinning concept. Note that it is not an all-or-nothing concept. Pinning allows you pin just one package. You can actually compose multiple nixpkgs expression sets together. |
But wouldn't reproducibility involve specific dependency versions though? Otherwise in my opinion it's not reproducible.
Yep, this is mentioned in a link earlier in this thread: #9682 (comment) I'm not sure you can pin channels though because if a channel gets updated, it's sha256 would also change. However, I do know that you can do use the nix-shell -I nixpkgs=https://github.com/NixOS/nixpkgs-channels/archive/nixos-17.03.tar.gz And thus retrieve a channel like that.
Don't think so, but it definitely should! See #27994 for this.
Well yeah, if they would then it wouldn't be the same stuff, so not reproducible.
Not sure what exactly you mean here?
Actually I'm not sure what naming conflict you're talking about still? In my previous comment I described a use case for separating the package name from the version, so that we can just specify a package name and have a guarantee we'll get latest version available for it in nixpkgs. But I don't think that had anything to do with naming conflicts?
I don't see how separating the package name and version makes it any different for providing older versions of packages, than just using attributes like we are now?
I mean conceptually, pretty much, I think! In fact, there's https://github.com/NixOS/nixpkgs-channels which has branches named after channels which track the nixpkgs revisions that the respective channels are using. So for actually separating out package names and versions though, it might be because of my limited nix expression language knowledge, but I have no idea how you would implement this though, because attributes pretty much always used to refer to packages, in configs, package expressions, modules, everywhere I think. Maybe you could write your own tool or nix function or something that parses out the name and the version for all attributes that begin with the same characters, and then returns the one with the biggest version number. If however you want to make more substantial changes than writing your own function/tool to deal with this (again, I wouldn't know what it would look like), and you feel strongly enough about this issue, I'd suggest first opening a new issue for this, or sending an email to nix-devel, and then eventually going through the RFC process to do it. |
Just wanted to point out that this isn't true - you can take some packages from a pinned revision and some from a channel, or anywhere else. You can see an example of using multiple package sets at the bottom of CMCDragonkai's post. So in practice if you only need to pin one package you can pin just that one package. That package will indeed not get updated (and it will have its own, old, copy of its dependencies), but that's the point of pinning. |
So now I completely understand pinning. Sorry it took so long. Maybe I need to read more, maybe documentation is not up to par. I'll let you come to your own conclusion on that front.
I meant that if you are dependent on channels for dependency versions (which is not pinning like I thought), then you would not be able to select specific package versions, so as soon as you update the channel, you end up updating all dependencies. I was confused, and conflated pinning packages (reality) with pinning channels (nonsense). I suppose pinning packages is a good way to work, but I don't necessarily see it as the only way. Sure, it's more reliable, but some features can still be seen as limitations in certain context.
Pinning is a great workflow, and content-addressed packages are a core feature of Nix. It's not an easy workflow to jump into, though. We can make it easier. If I want a package that is a certain version, I need to find out what content-address to get it from. Right now, that involves scouring Github for the name of a package that corresponds to the version I want. Let alone the fact that there are multiple nonstandard ways to do this, I shouldn't be doing it in the first place. I'd rather add the version string to my name search. The version string is there, but it's hard to find. It's either ignored, appended to the package name with underscores instead of dots, or something else entirely. Because the version string isn't explicitly used by Nix, it isn't required, and there is no standard way to use or provide it. All I want is a standard way for packages to provide version strings, and a standard way to reference them. That way I can search for version strings the same way I search for package names.
Think of it as "loose pinning". Instead of pinning a hash, you are pinning a range of hashes. For convenience, you reference the hashes using a single, list, or range of version strings. If a version string references no hashes, you know immediately. If a version string references several hashes (because an expression was updated, but the version did not change), you grab the newest hash.
|
You know, as a user I really want this feature, as a developer I can leave with out it (solutions posted upper). For example I want to install Its all about comfort of each day using and entry level threshold. I thought a little - I have a simple solution. Lest have additional option for |
@novoxudonoser Flakes should solve many of the concerns raised in this thread. |
Finding what older versions are availableI've found that pinning the revision hash solves the problem of how to use an older package version, but leaves the question of how to find the revision that contains the version I want. If the current version of a package is broken I want to use the previous one, but I found no way other than going through nixpkgs' git history to find what revision had the package version I wanted. To solve that I wrote a tool to search all versions of a package that were ever available in a channel, what revision they can be found in, and what command to use to install them https://lazamar.co.uk/nix-versions/ |
Such tools can be useful, but note that if a package is broken in nixpkgs... we typically don't want to leave it that way. Moreover, if there's good motivation, we do keep multiple versions in nixpkgs (say, llvm has many). EDIT: flakes were linked above already :-/ |
My impression after reading through this thread, learning about both Flakes and the search tool from @lazamar above, is that we can only use specific revisions of a nixpkgs channel to provide dependencies, but there's still no standard for specifying an individual package version. So if I need to use packages |
From what I understand is that often arbitrary versions of packages just don't always work perfectly with each other. That's why I think flakes doesn't even try to tackle that problem. Instead we just try to get a convenient tool for reproducing the same software as defined on other machines and rely on nixpkgs being a curated set of libraries whose versions are "known to work" with each other. |
This makes sense to me. I guess it just feels odd that, for example, if I want to mostly use the 20.03 channel but pin Firefox to version 73, I have to pick myself a version of nixpkgs that had it. There are likely a bunch of revisions that include it. Do I pick the first or last commit that had it? I'm choosing a point in history for the whole build of Firefox. One side effect being that this prevents my Firefox 73 from using new patch versions of its dependencies (if it uses eg. |
The Answer to the Original Issue(Can @mayhewluke or one of the nix maintainers add a version of this answer to the top? Because I just wasted 2.5 hours reading and attempting to understand this whole thread, when all I needed was @lazamar's criminally underrated comment) Step 0: Find the Version you WantFind (almost) all versions of a package using lazamar's absolutely amazing online tool For example:I wanted
Step 1: Install that version using its Hash(I only know this because because clicking the hash on @lazamar's site explains it)To install that
To use that version of ruby in a nix-shell run
To require/use that version of ruby in a nix-script run
|
Why is this search functionality not built into Nix?(probably should open up a new issue for this^ question) Because (AFAIK) Nix hasn't created a standard way for packages to notate a version within their name, @lazamar's method is still somewhat of a workaround. As @thomastjeffery points out
Why is this thread filled with discussions of:
I really don't know |
@jeff-hykin I've been uninvolved in this thread for almost 5 years now (for some reason your post was the first I got a notification for 😕), and there's apparently been a lot of discussion since I last checked in. As a result, I'm too out of touch with the issue to be qualified to make a call as to what solution should be suggested (if any). I have, however, updated the original post with a suggestion to check out the latest comments, so others don't have to slog through these ~60 comments like you did. Does that sound like a reasonable compromise? |
Looks good to me, thank you for doing that! @mayhewluke |
You're welcome @jeff-hykin! Happy to help. |
Thanks for the synopsis, @jeff-hykin!
This thread (as I saw it) was originally about a usability issue that exists in Nix. Some people quickly pointed out elegant (from a certain perspective) workarounds to that issue, like pinning. Some even pointed out that the Nix philosophy (as they understood it) is at its core incompatible with version numbering. At this point, there should probably be a new issue created and discussion made about how to integrate the reality of software versioning with Nix's UI, implementation, or the Nix philosophy itself. As I see it, this issue is a usability one, so any workarounds ought to (at the very least) be obvious and well-documented to the casual Nix user. As it is, the simple act of installing a specific version of a package confronts the casual user with a need to understand the design and implementation of Nix, and choose a confusing (no matter how elegant) solution. Users should never be led to a GitHub issue in order to know how to use their package manager. I don't think I'm qualified to lead this discussion, but seeing as I was contributing to this discussion nearly 3 years ago, people are still stumbling into this thread, and I haven't really seen a solution... Here is the new issue: #93327 |
Thanks for the explanation and kicking off the new issue @thomastjeffery, I appreciate it! |
This issue has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/nix-shell-p-python37-pkgs-pytest-fails/22533/4 |
This issue has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/best-practice-for-pinning-version-of-individual-packages/6194/7 |
July 2020 update
This issue is coming up on 5 years old at this point, and has gotten quite lengthy. While the issue may still be relevant, not all of the comments in this thread will be. It has been suggested that you may find it more valuable to skip to the bottom of the thread in order to get a read on the current state of things, rather than working through it from start to finish.
Here's the original post:
I can't seem to find any way to install a specific package version, though - it seems like when installing a package you just get whatever is current in the channel you've subscribed to. If there's no way to request a specific package version, how is it possible to have "side-by-side installation of multiple versions"?
(Note: I understand that some packages occasionally have more than one version available in the current state of the channel and can be accessed via eg.
package-name_1.2.3
, but this seems to be the rare exception and still doesn't allow specifying a specific version, just a choice from a few available versions.)Potential use cases:
Solving dependency/Cabal hell:
I found Nix through Haskell, where a lot of people offer it as a solution to "Cabal hell". However, if I can only install one version of a package via Nix, I can't solve the situation where I am working on two different projects with two different and incompatible dependency requirements.
Testing against multiple versions of dependencies:
Say I'm writing a library, for which I originally depended on
foo-1.0.0
. A year later I'm making updates and I want to use expand the upper bound of that dependency so that users aren't restricted to an old version of the dependency. I installfoo-1.5.0
, make a bunch of updates, verify that it works, but then want to double-check that everything still works withfoo-1.0.0
, because if the new changes don't work with it I'll have to change the lower bound of the dependency, potentially causing problems for users. However, not being able to specify to Nix that I wantfoo-1.0.0
, I can't test againstfoo-1.0.0
and can only state the dependency asfoo == 1.5.0
, instead of the more permissible (and usable)foo >= 1.0.0 && foo <= 1.5.0
.Sharing build/development environments:
I've seen people say that the ability to share build/development environments across the team solves the "Well it works on my machine" problem. However, if I send the environment (via default.nix/shell.nix etc.) to another developer to get them up to speed with the project, they may end up installing different versions of packages than me, since the packages channel may have progressed since I last installed/updated my packages. Now we're not on the same page any more and those subtle (and painful) differences and bugs can creep back in.
Deploying to servers/CI/etc:
In a similar vein to sharing development environments, it would be great to be able to use Nix to standardize the environment across all our develop/build/test/deploy phases/environments. However, since the channel could change at any point between these phases and we're not able to specify specific package versions, this isn't possible. For example, take the case where the project is deployed across multiple servers. Being in the cloud, they're ephemeral, so when one breaks for some reason it's destroyed and replaced with a new, healthy version. Except that the new version has to be brought up so speed and installs the project via Nix. Since the channel has been updated since the other servers were last updated, the new server is now running in a different environment and introduces potentially problematic inconsistencies to the system.
Now, these are all hypothetical - I don't actually have experience in any of these use cases but if my understanding is correct I can see them potentially cropping up. However, I can find no mention anywhere (despite very exhaustive searching) of anyone concerned about locking down package versions or installing specific versions when using Nix. If I'm the only one, perhaps I'm missing something fundamental here and barking up the wrong tree?
I just can't see how Nix can deliver the benefits everyone says it does without giving users a way to specify specific package versions - is there really no way to do this, or am I misunderstanding the whole system?
The text was updated successfully, but these errors were encountered: