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

nix profile entries need stable identifiers #7967

Closed
bobvanderlinden opened this issue Mar 4, 2023 · 8 comments
Closed

nix profile entries need stable identifiers #7967

bobvanderlinden opened this issue Mar 4, 2023 · 8 comments
Labels
feature Feature request or proposal new-cli Relating to the "nix" command

Comments

@bobvanderlinden
Copy link
Member

bobvanderlinden commented Mar 4, 2023

nix profile has a number of UX issues related to identifying installed packages.

These issues can be resolved by using more human identifiers for profile entries.

Currently the only identifier that we use at the moment is the index of installed packages. For instance, to remove a single package you need to nix profile remove 3 to remove the 4th entry in the Nix profile.

It is possible to start supporting other identifiers, like the original installable (like github:nixos/nixpkgs/nixpkgs-unstable#cowsay), but this still gives a bad UX in general use.

The problem is that Nix doesn't know about simple names of individual packages. For instance, installing the latest version of difftastic using:

nix profile install github:nixos/nixpkgs/nixos-unstable#difftastic

Will nicely install difftastic, but I cannot refer to the entry using difftastic, which is what I presume would be possible using nix profile remove difftastic.

Would it be possible to store (for each entry in profile) a simple name that is (by default) inferred from the "installable" argument?

$ nix profile install --name difftastic github:nixos/nixpkgs/nixos-unstable#difftastic
$ nix profile remove difftastic

By default the name would be inferred from the installable/URL. The name would be set by conditions in order upon installing:

  1. The --name flag
  2. Anything behind #: for instance github:nixos/nixpkgs/nixos-unstable#difftastic -> difftastic
  3. Any repository segment: for instance github:cachix/devenv/v0.5 -> devenv.
  4. The directory name: for instance ~/projects/mypackage -> mypackage
    1. The file name name: for instance ~/projects/mypackage.nix -> mypackage
  5. Error on not being able to infer the name and suggest to use --name explicitly.

This would also, in many cases, avoid the need for the regular expression feature of nix profile remove and nix profile upgrade. See #7962.

If you then install something that has the same name, the installation can warn or error that the entry name already exists and maybe asks or suggests how to upgrade the package to the new URL. This would resolve #7963.

The numbers would also not be needed anymore. Those numbers seem like a kind of priority, but priority is something entirely different. The numbers are currently merely identifiers for installed packages: much better suited for unique names.

Would something like this be viable for profiles?

EDIT: I did some more digging. The manifest.json currently looks like:

{
  "elements": [
    {
      "active": true,
      "attrPath": "legacyPackages.x86_64-linux.difftastic",
      "originalUrl": "github:nixos/nixpkgs/nixos-unstable",
      "outputs": null,
      "priority": 5,
      "storePaths": [
        "/nix/store/87a50y83m4hg20ms5ch5x2vjdi7lzs0s-difftastic-0.43.0"
      ],
      "url": "github:nixos/nixpkgs/0591d6b57bfeb55dfeec99a671843337bc2c3323"
    },
    ...
  ],
  "version": 2
}

It could look like:

{
  "elements": {
    "difftastic": {
      "active": true,
      "attrPath": "legacyPackages.x86_64-linux.difftastic",
      "originalUrl": "github:nixos/nixpkgs/nixos-unstable",
      "outputs": null,
      "priority": 5,
      "storePaths": [
        "/nix/store/87a50y83m4hg20ms5ch5x2vjdi7lzs0s-difftastic-0.43.0"
      ],
      "url": "github:nixos/nixpkgs/0591d6b57bfeb55dfeec99a671843337bc2c3323"
    },
    ...
  },
  "version": 3
}

But for backwards compatibility, we could also just add a property to each element called name.

Is this something that is viable for nix profile?

@iFreilicht
Copy link
Contributor

iFreilicht commented Jun 20, 2023

I think adding a name property to every element is the best solution for now. If it doesn't exist, we can derive the name from the existing attributes.

But we might want to think about the priority of the sources for the name. I think the most sensible source in the majority of cases is the store path. This is what nix profile diff-closures already uses pretty successfully.

  1. Anything behind #: for instance github:nixos/nixpkgs/nixos-unstable#difftastic -> difftastic

Hmm but isn't this something like legacyPackages.x86_64-linux.difftastic most of the time? The other ones I can agree with.

  1. Error on not being able to infer the name and suggest to use --name explicitly.

I would also add that the name must be unique in the profile. This should be checked for before trying to generate the json file, and give the same recommendation of using --name.

@nixos-discourse
Copy link

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

https://discourse.nixos.org/t/flakes-as-a-unified-format-for-profiles/29476/1

@nixos-discourse
Copy link

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

https://discourse.nixos.org/t/flakes-as-a-unified-format-for-profiles/29476/2

@nixos-discourse
Copy link

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

https://discourse.nixos.org/t/flakes-as-a-unified-format-for-profiles/29476/17

@9999years
Copy link
Contributor

A related issue here is that the nix command does some translation to Flake arguments already (e.g., nixpkgs is translated to flake:nixpkgs, . is translated to the current directory, or even git+file:///Path/to/git/repo?dir=path/to/current-dir, etc.), and this isn't reflected in the stored originalUrl.

So when a user runs nix profile install nixpkgs#difftastic, nothing gets written down attaching that profile entry to the user-specified install string.

I do think we can make educated guesses that work for 98% of users 98% of the time, and we could also let users refer to entries with {url}#{attr} or store paths as shown by nix profile list.

@bobvanderlinden
Copy link
Member Author

bobvanderlinden commented Oct 30, 2023

I think we can look into improvements on this once we have names in Nix. I was thinking, if the url did not match any entry, but its name does match, Nix can output a suggestion.

$ nix profile install nixpkgs#firefox
$ nix profile remove nixpkgs#firefox
nixpkgs#firefox not found.
Did you mean:

  nix profile remove firefox
$ nix profile remove firefox

Though it would be nice if nixpkgs#firefox by itself would match as well. Resolving it to the same form as originalUrl and attempt a match using that might be a good step as well.

@bobvanderlinden
Copy link
Member Author

bobvanderlinden commented Dec 21, 2023

#9656 has been merged. Nix profile now has named entries!

The suggestion when the installable isn't matching is a next step. Resolving the installable uri before matching is another.

@bobvanderlinden
Copy link
Member Author

bobvanderlinden commented Feb 22, 2024

The suggestion when the installable isn't matching is a next step.

This has been fixed in #10060 🥳

Resolving the installable uri before matching is another.

Is a separate issue. I'll create a new one.

#10064

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Feature request or proposal new-cli Relating to the "nix" command
Projects
None yet
Development

No branches or pull requests

5 participants