We have a lot of package versions in git history of nixpkgs. Being able to use any available version would be a killer feature for Nix! No other package manager would provide so many versions.
This actually works right now when done manually: Use older package version with Nix · GitHub
I had this idea many years ago. Here is now my concept. It might become my first RFC.
Please provide feedback to the concept. Would you like to help implementing it?
@edolstra does this feature has a chance to be included in Nix?
Nix UI
I’m not a developer, so i don’t care so much about implementation details, but UI and UX design.
Install specific version of package
nix install firefox@55
You can specify only parts of the version. The latest available release of that version will be used. In this example 55.0.3.
Run specific version without permanent installation
nix run firefox@55
List all available versions of a package
nix list-versions firefox
74.0
73.0.1
72.0.2
71.0
70.0.1
69.0.3
...
For every minor release we have, list the latest patch version.
Show package details (including number of versions available)
nix show firefox
name: firefox
version: 74.0
description: A web browser built from Firefox source tree (with plugins: )
url: https://www.mozilla.org/en-US/firefox/
installed: no
...
available versions: 65 (use nix list-versions firefox)
Use specific version in package definition or module
propagatedBuildInputs = with python3Packages; [ paramiko@2.5.1 lxml@4.4 defusedxml ];
We might not want to allow this in nixpkgs itself, but it will be a killer feature for developers!
environment.systemPackages = with pkgs; [ firefox@55 ];
Users might need a specific version permanently and want to install it in a declarative way.
Implementation
For some packages, we have multiple versions in the current default channel. Search there if the requested version is available. For example ansible:
So nix install ansible@2.7
will install it from the default channel, whereas nix install ansible@2.5
will search the version from the history.
To get the available package versions, we have to search the complete git history of nixpkgs.
One approach would be to evaluate every commit. This probably takes too long!
We can search the git commit messages for common package update pattern.
Example: firefox: 54.0.1 -> 55.0
is package firefox@ version 55.0
This might miss later improvements and security patches of the package at this version. But it should work at the state of the update commit! (tested before PR is merged)
It is not efficient when every user downloads complete nixpkgs history and does heavy searching. My idea is to do it only once and build an index of all packages versions with the corresponding commit id. The result can be a CSV file.
This can be build by a standalone hydra job from master branch. As often as technically acceptable (every commit in master, every hour or only once a day).
By using master branch, it will list versions not even in unstable yet!
It would be good to use a commit where binaries exists for (channel generation), or at least mark the versions (in listing) where binaries exists in the binary cache.
I can try to implement this index generation script in python (my favorite language, already used in module tests and nixops), but the Nix (UI) side has to be done by someone else. For a prototype, i can just build a python wrapper for nix.
Remarks
I don’t think we should call this concept a nix channel, even tho we might use the channel mechanism to update it. The file name could be nixpkgs-all-versions-index.csv
.
Would we want to export this data to repology to promote that Nix can provide all these versions? People might find Nix this way as a solution for their task (use old version).
The online package search can also show the number of available versions and by clicking on it, show all versions and by clicking a version, instructions to install and run.
We have to test if this old versions are actually usable on an up-to-date NixOS system and other distro.
Some packages might need a service (e.g. dconf?) at specific version to work. We might want to add a package metadata if the package is portable (not depending on a service). When false, the tooling can show a warning that it might not work. When not specified, assume true. We might find hints about this topic at flatpak portals.
For packages that write configurations or user data, state management is needed. For example, when i run firefox 50 the first time, a profile is created, when i run firefox 60 later, the profile is updated to version 60, when i run firefox 55 later, the profile of 60 is not compatible. I might want to use the older state of firefox 50. That could be solved with backups or filesystem snapshots. But since we don’t know where a program writes files, we can’t backup just that files. Maybe sandboxing/isolation can help. But that’s again a completely different topic and a big one on it’s own.
References
I got inspired for this implementation by All the versions with Nix
You know what'd be really cool? For either Nix or Guix to transparently support ... | Hacker News (here someone had the same idea + comments)
Other package managers UI for specifying version
apt
apt install package=version
brew
brew install postgresql@8.4.4
dnf
dnf install tito-0.5.6-1.fc22
chocolatey
choco install nodejs.install --version 0.10.35