Live data from Hacker News

Nix solves the package manager ejection problem

zeroindexed.com

11–20 of 50 posts

Re: Nix solves the package manager ejection problem

#12
Off-topic question about Nix. I understand it works by redirecting symlinks from, say, one version of a package's files to another.

Isn't there a race-condition here -- like if I invoke a program at the wrong time while it's in the process of changing symlinks, could it pick up the wrong libraries or something? Does Linux OS allow a "changeset" of files to be locked and altered together in a batch, or anything like that?

Re: Nix solves the package manager ejection problem

#13
post #12

Off-topic question about Nix. I understand it works by redirecting symlinks from, say, one version of a package's files to another. Isn't there a race-condition here -- like if I invoke a program at the wrong time while it's in the process of changing symlinks, could it pick up the wrong libraries or something? Does Linux OS allow a "changeset" of files to be locked and altered together in a batch, or anything like t…

not sure if I completely understand the race you describe, but I don't think there's any race. the paths and links are created at build/install time. nothing is switching around after the expression has been applied.

edit: maybe you're describing what happens if a program is run while a Nix expression is being applied; I believe what happens in that case is that the program that was being run will work fine since its environment is pointing to the previous generation, and applying the new expression creates a new generation

Re: Nix solves the package manager ejection problem

#14
post #12

Off-topic question about Nix. I understand it works by redirecting symlinks from, say, one version of a package's files to another. Isn't there a race-condition here -- like if I invoke a program at the wrong time while it's in the process of changing symlinks, could it pick up the wrong libraries or something? Does Linux OS allow a "changeset" of files to be locked and altered together in a batch, or anything like t…

Isn’t that a possibility with any package manager?

Re: Nix solves the package manager ejection problem

#15
post #7
post #6

That works for the kernel. But if you have to patch, say, glibc, under Nix doesn't that mean you can no longer use precompiled binaries, and have to recompile every single package that uses libc, from source? Sure, it still works. And in the off-chance that you need to make a patch that changes the ABI, recompiling the world is exactly what you want. But usually you don't need to change the ABI (at least not in a bac…

This may change in the future with Nix moving to a content addressable store. I lack the technical know how behind it, but if the output of a package doesn't change on changing one of the inputs then nix will not rebuild it's cache.

If you're patching glibc, most of the time, you're going to change its output. Determining whether you need to redo downstream builds based on changed outputs is great if the thing you're changing is docs or optional libraries (such that most packages don't have a dependency on the thing being changed), but it doesn't help with patching the core.

The interesting case would be if you build separate build-time and runtime interfaces - like a libc.so that just has dummy symbols for everything that it defines but no actual implementations, and a libc.so.6 with the actual implementations that can change.

While most Linux distributions have the split of filenames, it's not actually done in this way - libc.so is a symlink to libc.so.6 (or in the specific case of glibc, a linker script), so it requires the actual libc.so.6 to be around and used during the build.

It would also be a bit of a semantic change in how Nix operates, as I understand it: currently you can run ./configure scripts that detect the behavior of libraries by actually running code, and if that behavior changes, Nix guarantees a rebuild. If you remove runtime libraries from what's visible during the build, you can't run such scripts anymore (or you're running them against a version of the library that doesn't trigger rebuilds when it changes).

Re: Nix solves the package manager ejection problem

#16
post #12

Off-topic question about Nix. I understand it works by redirecting symlinks from, say, one version of a package's files to another. Isn't there a race-condition here -- like if I invoke a program at the wrong time while it's in the process of changing symlinks, could it pick up the wrong libraries or something? Does Linux OS allow a "changeset" of files to be locked and altered together in a batch, or anything like t…

Nix doesn't work by redirecting symlinks, much less between different versions of the same package. So there is no race condition as you describe.

Simply, if package A depends on package B then A's files will end up mentioning the absolute path to B directly (say, /nix/store/abcdef-b-1.0/bin/some-bin-file, where "abcdef" is a hash).

If package C depends on a different version of package B, then C's files will contain the path to a version of B with another hash and possibly a different version number (say, /nix/store/zywxabc-b-1.1/bin/some-bin-file).

Re: Nix solves the package manager ejection problem

#17
post #12

Off-topic question about Nix. I understand it works by redirecting symlinks from, say, one version of a package's files to another. Isn't there a race-condition here -- like if I invoke a program at the wrong time while it's in the process of changing symlinks, could it pick up the wrong libraries or something? Does Linux OS allow a "changeset" of files to be locked and altered together in a batch, or anything like t…

I don't think "redirecting symlinks" is a totally accurate way of describing how Nix works.

Each Nix package, as packaged, has a hard-coded dependency on the specific hashed versions of all its dependencies. For instance, if you're building NPM and its build scripts hash to abcd1234, and it depends on Node.js whose build scripts hash to dcba4321, then /nix/store/abcd1234-npm-1.0/bin/npm has a hard-coded reference to /nix/store/dbcd4321-nodejs-1.0/bin/node.

Symlinks come into play with user profiles - you don't want to type in that full path to npm every time, so you put ~/.nix-profile/bin on PATH and you tell Nix to make ~/.nix-profile/bin/npm a symlink to /nix/store/abcd1234-npm-1.0/bin/npm.

But there isn't a race condition in the underlying packages, which are all immutable and more importantly co-installable. If you want to upgrade to Node.js 1.1 and its hash is fedc9876, then it gets installed to /nix/store/fedc9876-nodejs-1.1. And if you rebuild npm against that (even without changing its version), the hash of npm's build scripts changes as a result, and it ends up in, say, /nix/store/aaaa1111-npm-1.0.

If you upgrade your personal profile to the latest version of everything, then Nix will install those two new directories into /nix/store, repoint the symlink in ~/.nix-profile/bin/npm, and then (eventually) garbage-collect the two old directories.

But at no point does the execution of code within Nix rely on mutable symlinks. (As far as I know.)

Re: Nix solves the package manager ejection problem

#18
post #12

Off-topic question about Nix. I understand it works by redirecting symlinks from, say, one version of a package's files to another. Isn't there a race-condition here -- like if I invoke a program at the wrong time while it's in the process of changing symlinks, could it pick up the wrong libraries or something? Does Linux OS allow a "changeset" of files to be locked and altered together in a batch, or anything like t…

Nix uses symlinks to create user environments, mostly. The rest all points to unique paths in `/nix/store`. Sometimes, environments are also used for applications, mostly modular stuff.

Take a Python service started by systemd. The systemd ExecStart points directly to the immutable Nix path of the script, and the script also has a shebang that points directly to the immutable Nix path of the Python interpreter. (The Python interp in turn also links to libraries via direct Nix paths, etc.)

Re: Nix solves the package manager ejection problem

#19
post #4

To be fair Gentoo has /etc/portage/pqtches so that you can patch software from official packages instead of having to create a new one

Thanks, I didn't know about this. It's been about a decade since I actually used Gentoo and I was writing from the hip.

I've published a correction: https://zeroindexed.com/nix-ejection-problem#on-gentoo

Re: Nix solves the package manager ejection problem

#20
post #9

Read the NPM doc but I still don't understand what "ejection" is. What are we ejecting? Can someone explain this please?

I believe the confusing bit is that it's not an NPM thing, it's a create-react-app thing. create-react-app is a helper tool for, as the name says, creating React applications and doing a bunch of things out of the box. Occasionally you reach the point where you need to do something more complex than create-react-app can handle for you. In that case, you run the "eject" script in the generated app (using "npm run" as…

I think you're correct that the eject mechanism was popularized with react. It very much sucks IMHO. At least yarn has a mechanism to override a dependency with your own version of a component.Therefore I am not sure the article is totally correct on this
Post reply on HN