An attrpath format policy proposal


#1

Hello.

While working on nixpkgs-update, I found that there are a lot of formats being used for the pkgs attrpaths:

attrpath format example version represented
name(MAJORDIGIT)(MINORDIGIT) qt56 5.6.x
name(major) icu58 58.x
name(majordigit)(minor) autoconf213 2.13
name(majordigit)(minor)x automake111x 1.11.x
name(digit_not_in_version)_(major)_(minor) libgit2_0_25 0.25.x
name-(major)-(minor)-(patch) libsigrok-0-3-0 0.3.0
name_(major)_(minor) apacheKafka_0_10 0.10.x
name-(major)_(minor) dbus-sharp-glib-2_0 2.0.x
name(major)_(minor) antlr3_5 3.5.x
name(major) bison3 3.x.x
name(digit_not_in_version) automoc4 x.x.x
name_(date) fplll_20160331 20160331
name owncloud-client x.x.x
name(unrelatednumbers) libavc1394 x.x.x

I believe a standardized attrpath naming convention would be helpful for automated tools, nixpkgs maintainers, contributors, and users:

  • Automated tools could better understand what derivations correspond to what versions. nixpkgs-update could avoid updating a derivation that is pinned to a specific version, and it could smartly update point releases on multiple major versions of the same package.
  • Maintainers would be able to refer to and point to the naming conventions when reviewing contributions.
  • Contributors would have clear rules to follow when naming attrpaths.
  • Users who learned the policy would have an easier time installing and manipulating derivations.

If a naming policy is adopted, we should add it to the nixpkgs manual in Chapter 13, use aliases and deprecation warnings to transition nixpkgs, and add a linter to enforce the policy.

My proposal for the policy is:

  • Let pname equal (builtins.parseDrvName attrpath.name).name
  • Let version equal builtins.concatStringsSep "_" (builtins.splitVersion (builtins.parseDrvName attrpath.name).version)
  • Let partialVersion be version with any number of parts removed from the end
  • Let separator equal “_”
  • A valid attrpath is either:
    • "pname"
    • "${pname}${separator}${version}"
    • "${pname}${separator}${partialVersion}"

I made a nix program that generates valid attrpaths under this policy.

Here are some examples:

current attrpath valid attrpaths under policy
autoconf213 autoconf or autoconf_2 or autoconf_2_13
automake111x automake or automake_1 or automake_1_11 or automake_1_11_6
libgit2_0_25 libgit2 or libgit2_0 or libgit2_0_25 or libgit2_0_25_1
apacheKafka_0_10* apache-kafka or apache-kafka_2 or apache-kafka_2_12 or apache-kafka_2_12_0 or apache-kafka_2_12_0_10 or apache-kafka_2_12_0_10_2 or apache-kafka_2_12_0_10_2_1
dbus-sharp-glib-2_0** dbus-sharp-glib or dbus-sharp-glib_0 or dbus-sharp-glib_0_6
antlr3_5 antlr or antlr_3 or antlr_3_5 or antlr_3_5_2
bison3 bison or bison_3 or bison_3_0 or bison_3_0_4
automoc4 automoc4 or automoc4_0 or automoc4_0_9 or automoc4_0_9_88
fplll_20160331 fplll or fplll_20160331
owncloud-client owncloud-client or owncloud-client_2 or owncloud-client_2_4 or owncloud-client_2_4_1
libavc1394 libavc1394 or libavc1394_0 or libavc1394_0_5 or libavc1394_0_5_4
icu58 icu4c or icu4c_58 or icu4c_58_2

* the apacheKafka looks crazy because it has a weird version that is the concatenation of two versions, this shows the shortened paths would not always make sense
** the dbus-sharp-glib attrpath doesn’t contain its own version; it looks like it uses the version of dbus-sharp that it is compatible with

Please comments on this policy or suggest a different policy. I have not specifically thought about what to do about nested package sets (like the language-specific ones). Any comments on how this policy would impact those would be appreciated.

Ryan


Nixpkgs-update/r-ryantm logs
#2

Cool. Also, perhaps the man pages which discuss versions should be updated to remain in sync, such as https://github.com/NixOS/nix/blob/966407bcf1cf86de508b20fef43cffb81d8a87dc/doc/manual/command-ref/nix-env.xml#L631-L677?


#3

Yes, we should fix any man pages that talk about attrpaths. It looks like the one you linked to is talking about derivations names and versions, which I am not proposing changing.


#4

The good news is 75% of the top-level attrpaths already conform to this policy!

This nix program generates a list of all the attrpaths that don’t currently conform to this policy along with what would be a valid attrpath according to this policy.

Here is the list: https://gist.github.com/ryantm/ae22a656674851063f1c4a261c403423

This reveals some problems with the policy that should be addressed:

  1. One obvious thing to fix is to allow the attrpaths to start with “_” in the case where name is numeric. It’s impractical to use string attrpaths for these ones, right?
  2. There are attrpaths like “zfsStable” and “zfsUnstable” which do not fit into this policy model. What should we do with those?
  3. Parameterized derivations that use attrpaths, like grub2_efi vs grub2_full.
  4. attrpaths that proxy to a nested package set, like Fabric, which has derivation name of python2.7-Fabric.

#5

We can use – (double dash) to specify parametrized ones. Like

retroarch

retroarch–bare

or

terraform_0_10
terraform_0_10--full

I’m not very happy about having zfsStable and zfsUnstable. I’d like nixpkgs to contain both variants for all packages. I imagine like this:

  • each packages is a set of packages. It is already, it has multiple outputs, but I’d like it also be a container. So, it’s possible to do like this:
  • zfs (a stable default variant)

  • zfs.unstable (a development variant)

  • zfs.v_X_X (the very concrete version)

I’m also very very unhappy about Upper case letters inside attrnames. As I use Nix attrnames mostly in terminal, every

case change is painful. I’d vote to remove case changings from nixpkgs attrnames (they are OK in derivation names though)

Some special exceptions, like X11, should be present, but as an alias to x11

And one more wish, not quite related to your proposal. If derivation contains executables, at least one of them should be named just like an attrname.

For exampe, when you install attrname nixpkgs.vscode, your main executable is called code. Would be great to have policy that

executables should be named by attrnames, and not only as upstream wants. This would simplify experimantation with Nix


#6

We could also add update walker-like attribute to meta, something like:

meta = {
  updates = {
    versionFilter = v: stdenv.lib.majorMinor v == "1.11";
  }
};

There is not that many pinned packages after all.


#7

Additional item for the ‘currently used formats’ table: name-(major)_x, as used by the various nodejs-* packages (eg. nodejs-8_x).


#8

I would not be in favour of this, it has a tendency to break stuff that’s meant to somehow automate end-user-exposed applications. This kind of deviating-from-upstream naming has caused lots of trouble with Node.js on Debian, for example, and we’re still picking up the pieces from that decision in the support channel 5 years later.


#9

Oh, I don’t mean “rename” executables, but leave convenient symlink. I’ve done this a few times in the past:

https://github.com/NixOS/nixpkgs/blob/a283292df03fc638320ba1ba25027ad4c88125f3/pkgs/applications/version-management/tortoisehg/default.nix#L23
https://github.com/NixOS/nixpkgs/blob/16463d728b81f159e3b5f4eaae241841b227d86f/pkgs/applications/networking/instant-messengers/zoom-us/default.nix#L75
https://github.com/NixOS/nixpkgs/blob/b71ffc1b25b46297f1e52fd0c0ac491d296160f2/pkgs/applications/office/libreoffice/default.nix#L177

Probably this should be expanded to Desktop items too (alias names).


#10

Ah, yes, symlinking them would probably be fine, so long as the symlinked name doesn’t interfere with the original binary name of some other package. I’m not sure how difficult it is to implement “only expose a symlink if there’s not already a file with the same name”, or whether Nix might even already do this by default.

(Even then, though, you’ll want to consider the possibility of an application relying on its binary name being a particular thing. I’ve seen this issue particularly with proprietary Mono-based games, where it will fail to load some bundled shared libraries if the binary name is changed in any way. So a symlink wouldn’t work there, you’d need a wrapper script.)


#11

Previous discussion on this topic:


Heads up: upcoming changes to the PostgreSQL infrastructure and NixOS module