The papercut thread - post your small annoyances/confusions here

I would encourage people to open separate issue for each papercut, no matter how small. This thread has quickly blown up and I doubt it is useful for anything other than venting frustrations now.

Unlike omnibus threads, small issues can be easily triaged, tagged and comments are not mixed up together like in linear discussion here.

You do not even need to be very specific in the issue description, we can always fill the details in later.

3 Likes

But I’d still mention them here.
It’s really fascinating to read what people are trying to do and how others have even solved them.

7 Likes

This isn’t meant to be a triaging/resolution thread, though. My main objective here is to basically inventory all the usability issues that people run into, including shaking out those that people would not bother filing an issue about, and those that aren’t solvable as individual issues but require more coordinated restructuring. They can then eventually be turned into actionable issues.

Even with an explicit “please file an issue” remark, filing an issue still tends to feel like a higher barrier than replying to a forum thread, to many people. Especially since for filed issues, users are normally expected to actually respond to follow-up questions, but in here they are not. This thread simply serves a different purpose from an issue tracker.

And I am actually reading each and every comment in this thread :slight_smile:

Edit: also, “venting frustrations” is totally fine! That’s half the point of the thread, and it’s what shakes out the hidden usability issues.

4 Likes

It produces a comparator (function that takes two comparable objects and returns -1, 0, or 1, based on their relative ordering) from a predicate (function that takes an object and returns true or false, based on whether the thing belongs to a certain set) and two other comparators (one for objects in the set and other for the objects outside the set). Comparator can be passed to a sortBy function to obtain a collection (list) sorted according to the custom ordering represented by the comparator.

One thing this can be used for is to sort directories before files. Let’s have a list of attribute sets of the following structure { kind = "file"; fileName = "foo"; } and { kind = "dir"; dirName = "bar"; }. Sure, we could pass the following monstrosity to the sortBy function:

(a: b:
if a.kind == "dir"
then if b.kind == "dir" then compare a.dirName b.dirName else -1
else if b.kind == "dir" then 1 else compare a.fileName b.fileName)

but it is quite repetitive and easy to make mistake. The splitByAndCompare will be much cleaner

(splitByAndCompare (n: n.kind == "dir") (a: b: compare a.dirName b.dirName) (a: b: compare a.fileName b.fileName))

it can abstracted it even more:

(splitByAndCompare (n: n.kind == "dir") (compareBy (n: n.dirName)) (compareBy (n: n.fileName))

Once you gain a little familiarity with the idiom, it really is just a trivial combinator you will not spend more than a second thinking about.


In Haskell the nested conditional expressions in the definition can be further simplified by the fact that Ordering (of Bools produced by the partitioning function in this case) forms a semigroup:

splitByAndCompare :: (a -> Bool) -> (a -> a -> Ordering) -> (a -> a -> Ordering) -> (a -> a -> Ordering)
splitByAndCompare p yes no = \a b -> compare (p b) (p a) <> (if p a then yes else no) a b
1 Like

I opened a PR with a fix doc: describe pname by jtojnar · Pull Request #63196 · NixOS/nixpkgs · GitHub

1 Like

My main problem with this thread is fact that Discourse is limited to linear discussions. The papercuts itself are lost here in the flood of possible solutions and meta-discussions like this one.

I also read every comment in this thread but every time I decide I want to tackle one of them, I need to sift through the whole thread and rule out non-actionables again. On the issue tracker, triagers can rename, tag and fill in the details to the issues once and for all. Here, I have to do it repeatedly and in my head.

I did not mean that venting is somehow bad but I would say doing it here has pretty high chance of having no effect other than a temporary mental relief for the poster. I and many other people go through the issue tracker repeatedly and triage issues there or periodically choose ones to fix. If one copies the short paragraph to the issue tracker, there is much higher chance of something being done about it.

I would say that our issue tracker has quite low barrier of entry. I have personally elaborated on or even fixed several issues that consisted of single vague sentence. People can always unsubscribe if the issue is less annoying to them than follow-ups. Maybe reducing the perceived threshold is another papercut we can work on.


If the purpose of this thread is to inventorize, who will do the turning into issues? I started working on this by copying the thread to a text editor but the sheer size of this thread made me give up immediately. So even if this thread has low barrier of entry to reporters, it has incredibly high barrier of entry to implementers.

I do not discount the interest point mentioned by @JohnAZoidberg but if you care even a little, consider opening an issue in addition to posting here.

7 Likes

I gave shortening my invevitably overlong post a go: I think the reason this is in the forum and not the issue tracker is because

  • open question
  • “venting” is “allowed”
  • no mental commitment

If you don’t have the energy or will time or similar to sift through the thread I think that’s OK. At least joepie seems to have volunteered for dealing with the aftermath here and we have so many things to do anyway that slow and steady progress seems to be the only way to go - but sorry I’m preaching to the choir.

It’s just another way to gather community feedback.

The issue tracker does seem like a good idea to “canonicalize” at though.

I think (based on an experience last night) that nix configuration settings in configuration.nix only take effect if the rebuild succeeds, not during the rebuild itself. So previous state applies to the building of new state.

Example: I tried to add a custom package to configuration.nix using fetchgitPrivate and ssh agent forwarding. This didn’t work because I had to set nix.enableSandbox = false. But setting this didn’t fix the problem because it didn’t take effect because it couldn’t build the package! So I had to remove the package from configuration.nix, leave enableSandbox=false in there, do a rebuild, and then put the package back in.

(Disclaimer: I’m new to all this so I could have completely misinterpreted what went wrong.)

You are correct. /etc/nix/nix.conf doesn’t have any special handling, and changes to it are only made during profile activation (following a successful build of the profle). If you absolutely need to make a change to it in order to build a new profile generation, you can do something like:

cd /etc/nix
mv nix.conf nix.conf.link # The file is a symlink to a store path, so you can't edit it directly
cp nix.conf.link nix.conf
chmod u+w nix.conf
vi nix.conf # Make required changes
systemctl stop nix-daemon.service # The daemon will restart itself on next use via socket-activation from nix-daemon.socket
nixos-rebuild switch
1 Like

Nice tip - thank you! I wonder if these papercuts should be accumulated on the wiki somewhere.

A similar relatively common situation may happen when setting nix.nixPath (such as when you are setting up building from a local checkout of nixpkgs). You actually have to rebuild twice - the first time will update the environment variables, the second time will actually build from the new location.

(I hope I got this right.)

I think all of those options can be set using the --option flag… but they’re not documented in nixos-rebuild and some have no example of useful values…

2 Likes

I’m late to the party, but haven’t seen this one mentioned yet:

  • Deprecate ‘let/in’, since ‘with’ is objectively superior

From reading others, it seems like this is controversial; hence why I’ve
never opened a GitHub issue (although I did mention the reasoning at
Language feature proposal: exclusive 'with' · Issue #1361 · NixOS/nix · GitHub )

Just an observation: I think recursive lets are redundant with recursive attrsets?
I’m mildly annoyed by the lack of nonrecursive let.
Also, that’s a strange atypical opinion, thanks for posting it and providing some interesting points!

It was mentioned by me at the beginning of this thread :slight_smile: But I argue the exact opposite. Deprecate the with syntax for let inherit as it’s obviously superior :slight_smile:

5 Likes

(Several posts talk about deprecating with in favor of let, but the point was that warbo has precisely the antipodal argument?)

  • Getting PHP-FPM to work with nginx - a pretty common setup - involves unnecessarily much work. Much of this could be abstracted away by a module configuration option.
  • Copy-pastability of configuration examples is low, which can make it challenging to understand how to configure something correctly without making a mess of your existing configuration - because the same configuration can be represented in many ways and often examples are dependent on context and abstractions that live in other people’s repositories. Nix flakes would probably alleviate this a lot, by reducing the need to copy-paste examples, instead lowering the bar for publishing and consuming third-party abstractions/presets.

When you do this:

pkgs.stdenv.mkDerivation {
	name = "foo";
	src = ./some/folder;

	installPhase = ''
		cp -r $src/ $out/
		cp ${../elsewhere/extra-file.txt} $out/extra-file.txt
	'';
}

… the copying of extra-file.txt will fail with a cryptic permission error. This occurs because the permissions from the source directory (which is read-only, being in the Nix store) are copied over to the new $out directory that is implicitly being created, which prevents any later copying of files into it.

You need to explicitly mkdir -p $out first, instead, to create the folder with the default permissions, so that the cp after it merely copies over the contents:

pkgs.stdenv.mkDerivation {
	name = "foo";
	src = ./some/folder;

	installPhase = ''
		mkdir -p $out/
		cp -r $src/ $out/
		cp ${../elsewhere/extra-file.txt} $out/extra-file.txt
	'';
}

No idea how this could be made more usable (on an implementation level), but I’d imagine that it might be a pretty common thing to forget a mkdir. There should probably be at least a warning of some sort.

2 Likes

When package sets are written like gitAndTools:

/* All git-relates tools live here, in a separate attribute set so that users
 * can get a fast overview over what's available.
 */
args @ {config, lib, pkgs}: with args; with pkgs;
let
  gitBase = callPackage ./git { ... };

  self = rec {
    git = appendToName "minimal" gitBase;
    gitFull = gitBase.override { ... };
  };
in
  self

…it becomes really annoying to try and override the definition of gitBase or whatever local bindings are defined, because you have to do so for every attribute in the set that uses the binding; and there’s really no reason not to expose the binding so it can be overridden. It doesn’t reduce closure sizes, and we’re already in a scope so it’s not polluting the top level.

In general, I wish for a convention that any binding made with callPackage should be exposed to the top level of the scope in which it’s used. emacs-packages.nix is an egregious offender.

5 Likes

I’m not sure if I’m your reading your point correctly, but fundamentally I agree and I’m massively annoyed by these kinds of problems.
(WIP)(RFC) A new nixpkgs frontend for language infrastructures - #2 by deliciouslytyped is intended to address this kind of structure.

However, a much simpler thing to do at least in this case - if a simple rec set is acceptable - is to make the self attr take an argument and pass gitBase as a parameter - if I’m following correctly.

I see two issues here; one is that let expressions are horrible for overridability, the other is whether what is consuming your inputs is parametrized over it’s scope (bad for overriding), or over explicit arguments (good for overriding). I use “horrible” to emphasize my strong feelings towards this, but I’m always open to being convinced otherwise.