experimental/multiple-versions-in-one-file#310
experimental/multiple-versions-in-one-file#310MarcWeber wants to merge 2 commits intoNixOS:masterfrom
Conversation
This patch introduces mergeAttrsByVersion to lib. In some cases it does make sense to keep "experimental" and "older" versions of the same package in one file because it follows the "do it once only" principle. Very often many versions share their build instructions - so even though I understand Eelcos opinion that different versions should be put into their own .nix files - its my feeling telling me that this is fastest for most cases. I agree with Eelco that if tweaks for individual versions become too much they should be split into individual files. See comments above mergeAttrsByVersion learn about its usage. Signed-off-by: Marc Weber <marco-oweber@gmx.de>
|
I agree that this patch might be controversial. So take time to think and comment about it. Some more work I'd like to contribute depends on it - such as cvs version of gutenprint, PHP fpm implementation etc. |
|
I'm tentatively in favor of this. Can you show some examples that show how/when this improves over the current "separate file for each version" approach? |
|
Whenever you're tired of copy pasting and creating new files for simple version bumps, eg when you want to try whether a new version fixes issues etc. All advantages of code sharing apply, also all disadvantages. If you later want to change a maintainer for one version, then it may be best to start with two files. But usually nobody cares, things just get fixed. It may be easier to maintain if you need dev versions. Eg some time Ago I needed bleeding edge gimp. |
|
+1. Being able to choose whether to split out a new package version into a separate file or not seems like a good thing. |
|
If all code can be shared except for the |
|
Excerpts from Peter Simons's message of Tue Apr 23 15:11:20 +0200 2013:
Because this looks ugly (in all-packages.nix)
That's a common case. And such simple cases are the ones I'd like to use Because its easy to understand the differences by looking Marc Weber |
|
I don't really understand why these kind of problems cannot be resolved with a version option and appropriate conditions above the .nix file only when necessary. 😕 |
|
You're right that it can be done. http://mawercer.de/tmp/gimp-git.patch shows that I have "regions" which update name and src at the same time - so that the derivation name always contains svn/git revision. That's harder doing the way you propose. Anyway, I was wrong: This patch is not required by my PHP patches - so maybe I should just create pull requests and see what happens .. |
|
I's subjective, of course, but code like doesn't look ugly to me at all. I think that's a clear and precise description of the intended outcome. |
|
This looks very nice and readable. Is it possible to use that in current nix/nixpkgs? I.e. does it it work out-of-the-box or does it require ../foo/bar/default.nix to do some tricks? |
|
Yes, this style can be used without any extensions whatsoever. The build |
|
I guess it's been already established that this patch adds nothing new in terms of our ability to customize and override derivations. You can override pretty much everything using overrideDerivation on the all-packages.nix side, or pass your customizations or customization names via parameters. The old-school approach for derivation-side customization would be something like buildInputs = [ dep1 ] ++ lib.optional (version =="2") dep2 ++ lib.optional (version == "3") dep3 etc wherever it's required. Marc's patch makes this stuff more concise by not having to repeatedly put lib.optional (version == something) all over the place. It is hard to tell whether having all differences in one place like Marc proposes is better than having all differences enumerated in each derivation parameter the old way. You'll never know until you try, although I suspect that the concise syntax will win. I would also suggest replacing mkDerivation (mergeAttrsByVersion $PARAMS) with versionedDerivation $PARAMS to make it look a bit cleaner. And the hardest question is: do we want to enforce single-version-per-file approach. Multiple-versioned derivations risk breaking older versions if the developer is not careful when hacking the bleeding-edge version. This can be countered to a degree by writing a tool to check whether all available versions still build. This is balanced by making it more likely that improvements will be propagated back to older versions, such as nixpkgs-specific patches or newly-packaged optional dependencies. Another consideration is being able to see the differences between derivations. Diffing derivations works, but provides a lot more visual clutter to sift thru. Formatting changes add more clutter and don't propagate back to older versions. Git handles renaming default.nix to old-version.nix well, but does it recognize copying default.nix to new-version.nix with a slight modification? When browsing the repository with qgit, a patch for a new version added to a multiple-versioned derivation would be concise and informative, is the same going to happen when a new version of a single-version derivation is committed? |
|
Let me clarify: I don't want to rewrite nixpkgs. - I don't want to force this solution on all dervations. If you want to add comments (like I did in the PHP case) - there is one file to document a package. If you have many versions - documentation is cluttered. About breakage: Even PHP-5.2 broke - not because PHP-5.2 was changed - but because dependencies changed. I personally feel it could be useful for packages which are not used that often - so that tracking down bugs is little bit faster - packages like "apc" for PHP. I see it as util like misc.nix stuff. Patching like this: NixOS/nixos#153 and the related nixpkgs patch ore more important to the community - because it makes php-fpm just work. |
|
I wasn't talking about forcing anything either. Was trying to find out what would be wrong if people actually liked this approach and if it would spread. Just in case I wasn't clear, I'm in favor of this patch with a minor cosmetic cleanup. |
|
Lets see if developers put this to good use. Any objections? @MarcWeber how about my suggestion "replacing mkDerivation (mergeAttrsByVersion $PARAMS) with versionedDerivation $PARAMS" to make it look nicer and more self-descriptive? |
|
I've added versionedDerivation name - and I've put it into misc.nix - because I think future will tell in which ways this might be (ab)used. It is an experiment. If it fails we should remove it again. |
|
Rebased and merged. Going to try using it for a couple of packages and see how it works. |
|
@MarcWeber The place for experiments is branches, not the main tree. "Experiments" have a tendency to stick around for a long time, especially if there is code using them... |
|
Also, surely there are more descriptive function names than "mergeAttrsByFuncDefaultsClean" :-) |
|
Thinking about it a bit, is there any reason why you can't write it like this: Note there's no passing around of weird version arguments like "2.0", and no use of .override that leads to a fragile base class problem. |
|
This is an experiment whether we get an improvement in workflow or not. I don't understand how it can be done in a branch. Also it seems rather easy to get rid of the derivation written in this style: on the next version bump, you copy the common portion, append a version-specific portion and replace versionedDerivation with mkDerivation. |
|
But this turns the derivation into a collection of packages... can you provide a more complete example, startin with what would be put into all-packages.nix. Also, what happens if common and foo-2 both have eg patches? Is the list going to be merged? |
|
Its still true: to get a discussion going - the only way is comitting something How do I understand the base class problem? If you change the base class, everything derived from it will change. Thus you We have to kinds of packages:
If you base your package on gcc, rather than on gcc-4.3, you also have the base So I think its easy to say "the base class problem" is always there. Let's get into details. Example: test_derivation = stdenv.mkDerivation( stdenv.lib.mergeAttrsByVersion "name" "2.0" { Because mergeAttrsByFuncDefaults(Clean) derives merge behaviour from the default definition, which is also defined in lib/misc.nix to find out what is actually happening. Having a look at the example above you'll notice that opting-out from merging The worst thing which could happen is that you end up in: test_derivation = stdenv.mkDerivation( stdenv.lib.mergeAttrsByVersion "name" "2.0" { and you also got rid of the base class transition. However keep in mind that Another example is: https://github.com/NixOS/nixpkgs/blob/7d9607f1511bfe496fcd77ef735e7fc7f1c6eb9f/pkgs/development/libraries/dbus/default.nix Overridding configure flags may just work - because the last flag should be Let's summarize:
But I agree, I also like } so I'd even replace foo.override { version = "2.3"; } by foo."2.3" while foo still refers to the default version. (Could be done by About the naming: Eelco, do you have a better proposal? |
|
A very good writeup. I also would prefer "foo."2.3" while foo still refers to the default version." It looks so much cleaner and is much more compatible with the solution that Eelco has proposed in the sense that it would be easier to move away from versionedDerivation should we find that in practice we don't need to customize merging and are ok with the replacement override strategy as offered by //. If you have time to implement this, please do so. I have one more practical concern with multiple-version derivations(regardless of implementation): since diff doeesn't really understand what's going on, you might encounter merge conflicts when someone updates one of the versions in trunk, while you have updated another version in your branch. How often this is going to happen, only experience will tell. I don't expect it to happen very often and I'm mentioning it for completeness sake. |
Format using the base commit from nixfmt PR 307: NixOS/nixfmt@af5529a
This patch introduces mergeAttrsByVersion to lib.
In some cases it does make sense to keep "experimental" and "older" versions of
the same package in one file because it follows the "do it once only" principle.
Very often many versions share their build instructions - so even though I
understand Eelcos opinion that different versions should be put into their own
.nix files - its my feeling telling me that this is fastest for most cases.
I agree with Eelco that if tweaks for individual versions become too much they
should be split into individual files.
See comments above mergeAttrsByVersion learn about its usage.
Signed-off-by: Marc Weber marco-oweber@gmx.de