diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/customisation.nix | 18 | ||||
-rw-r--r-- | lib/debug.nix | 24 | ||||
-rw-r--r-- | lib/default.nix | 8 | ||||
-rw-r--r-- | lib/deprecated.nix | 8 | ||||
-rw-r--r-- | lib/filesystem.nix | 20 | ||||
-rw-r--r-- | lib/fixed-points.nix | 78 | ||||
-rw-r--r-- | lib/generators.nix | 37 | ||||
-rw-r--r-- | lib/licenses.nix | 5 | ||||
-rw-r--r-- | lib/lists.nix | 22 | ||||
-rw-r--r-- | lib/maintainers.nix | 60 | ||||
-rw-r--r-- | lib/meta.nix | 9 | ||||
-rw-r--r-- | lib/modules.nix | 2 | ||||
-rw-r--r-- | lib/strings.nix | 11 | ||||
-rw-r--r-- | lib/systems/default.nix | 13 | ||||
-rw-r--r-- | lib/systems/doubles.nix | 38 | ||||
-rw-r--r-- | lib/systems/examples.nix | 130 | ||||
-rw-r--r-- | lib/systems/inspect.nix | 43 | ||||
-rw-r--r-- | lib/systems/parse.nix | 53 | ||||
-rw-r--r-- | lib/systems/platforms.nix | 83 | ||||
-rw-r--r-- | lib/tests/misc.nix (renamed from lib/tests.nix) | 219 | ||||
-rw-r--r-- | lib/tests/release.nix | 58 | ||||
-rw-r--r-- | lib/tests/systems.nix | 14 | ||||
-rw-r--r-- | lib/trivial.nix | 76 | ||||
-rw-r--r-- | lib/types.nix | 17 |
24 files changed, 785 insertions, 261 deletions
diff --git a/lib/customisation.nix b/lib/customisation.nix index 6d6c023408782..98a46ca6c6168 100644 --- a/lib/customisation.nix +++ b/lib/customisation.nix @@ -51,6 +51,24 @@ rec { else { })); + /* `makeOverridable` takes a function from attribute set to attribute set and + injects `override` attibute which can be used to override arguments of + the function. + + nix-repl> x = {a, b}: { result = a + b; } + + nix-repl> y = lib.makeOverridable x { a = 1; b = 2; } + + nix-repl> y + { override = «lambda»; overrideDerivation = «lambda»; result = 3; } + + nix-repl> y.override { a = 10; } + { override = «lambda»; overrideDerivation = «lambda»; result = 12; } + + Please refer to "Nixpkgs Contributors Guide" section + "<pkg>.overrideDerivation" to learn about `overrideDerivation` and caveats + related to its use. + */ makeOverridable = f: origArgs: let ff = f origArgs; diff --git a/lib/debug.nix b/lib/debug.nix index 5b3878554c5d8..925e0d405a79a 100644 --- a/lib/debug.nix +++ b/lib/debug.nix @@ -20,8 +20,32 @@ rec { traceXMLValMarked = str: x: trace (str + builtins.toXML x) x; # strict trace functions (traced structure is fully evaluated and printed) + + /* `builtins.trace`, but the value is `builtins.deepSeq`ed first. */ traceSeq = x: y: trace (builtins.deepSeq x x) y; + + /* Like `traceSeq`, but only down to depth n. + * This is very useful because lots of `traceSeq` usages + * lead to an infinite recursion. + */ + traceSeqN = depth: x: y: with lib; + let snip = v: if isList v then noQuotes "[…]" v + else if isAttrs v then noQuotes "{…}" v + else v; + noQuotes = str: v: { __pretty = const str; val = v; }; + modify = n: fn: v: if (n == 0) then fn v + else if isList v then map (modify (n - 1) fn) v + else if isAttrs v then mapAttrs + (const (modify (n - 1) fn)) v + else v; + in trace (generators.toPretty { allowPrettyValues = true; } + (modify depth snip x)) y; + + /* `traceSeq`, but the same value is traced and returned */ traceValSeq = v: traceVal (builtins.deepSeq v v); + /* `traceValSeq` but with fixed depth */ + traceValSeqN = depth: v: traceSeqN depth v v; + # this can help debug your code as well - designed to not produce thousands of lines traceShowVal = x: trace (showVal x) x; diff --git a/lib/default.nix b/lib/default.nix index e692637abf197..3893e349db369 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -5,8 +5,9 @@ */ let - # trivial, often used functions + # often used, or depending on very little trivial = import ./trivial.nix; + fixedPoints = import ./fixed-points.nix; # datatypes attrsets = import ./attrsets.nix; @@ -42,7 +43,7 @@ let filesystem = import ./filesystem.nix; in - { inherit trivial + { inherit trivial fixedPoints attrsets lists strings stringsWithDeps customisation maintainers meta sources modules options types @@ -55,6 +56,7 @@ in } # !!! don't include everything at top-level; perhaps only the most # commonly used functions. - // trivial // lists // strings // stringsWithDeps // attrsets // sources + // trivial // fixedPoints + // lists // strings // stringsWithDeps // attrsets // sources // options // types // meta // debug // misc // modules // customisation diff --git a/lib/deprecated.nix b/lib/deprecated.nix index 983e8d26892bf..d4e78c39250cf 100644 --- a/lib/deprecated.nix +++ b/lib/deprecated.nix @@ -423,4 +423,12 @@ rec { else if isInt x then "int" else "string"; + /* deprecated: + + For historical reasons, imap has an index starting at 1. + + But for consistency with the rest of the library we want an index + starting at zero. + */ + imap = imap1; } diff --git a/lib/filesystem.nix b/lib/filesystem.nix index 91b04d81c13be..3925beb213478 100644 --- a/lib/filesystem.nix +++ b/lib/filesystem.nix @@ -1,4 +1,22 @@ -{ # locateDominatingFile : RegExp +{ # haskellPathsInDir : Path -> Map String Path + # A map of all haskell packages defined in the given path, + # identified by having a cabal file with the same name as the + # directory itself. + haskellPathsInDir = root: + let # Files in the root + root-files = builtins.attrNames (builtins.readDir root); + # Files with their full paths + root-files-with-paths = + map (file: + { name = file; value = root + "/${file}"; } + ) root-files; + # Subdirectories of the root with a cabal file. + cabal-subdirs = + builtins.filter ({ name, value }: + builtins.pathExists (value + "/${name}.cabal") + ) root-files-with-paths; + in builtins.listToAttrs cabal-subdirs; + # locateDominatingFile : RegExp # -> Path # -> Nullable { path : Path; # matches : [ MatchResults ]; diff --git a/lib/fixed-points.nix b/lib/fixed-points.nix new file mode 100644 index 0000000000000..a11b5a6f4bdc5 --- /dev/null +++ b/lib/fixed-points.nix @@ -0,0 +1,78 @@ +rec { + # Compute the fixed point of the given function `f`, which is usually an + # attribute set that expects its final, non-recursive representation as an + # argument: + # + # f = self: { foo = "foo"; bar = "bar"; foobar = self.foo + self.bar; } + # + # Nix evaluates this recursion until all references to `self` have been + # resolved. At that point, the final result is returned and `f x = x` holds: + # + # nix-repl> fix f + # { bar = "bar"; foo = "foo"; foobar = "foobar"; } + # + # Type: fix :: (a -> a) -> a + # + # See https://en.wikipedia.org/wiki/Fixed-point_combinator for further + # details. + fix = f: let x = f x; in x; + + # A variant of `fix` that records the original recursive attribute set in the + # result. This is useful in combination with the `extends` function to + # implement deep overriding. See pkgs/development/haskell-modules/default.nix + # for a concrete example. + fix' = f: let x = f x // { __unfix__ = f; }; in x; + + # Modify the contents of an explicitly recursive attribute set in a way that + # honors `self`-references. This is accomplished with a function + # + # g = self: super: { foo = super.foo + " + "; } + # + # that has access to the unmodified input (`super`) as well as the final + # non-recursive representation of the attribute set (`self`). `extends` + # differs from the native `//` operator insofar as that it's applied *before* + # references to `self` are resolved: + # + # nix-repl> fix (extends g f) + # { bar = "bar"; foo = "foo + "; foobar = "foo + bar"; } + # + # The name of the function is inspired by object-oriented inheritance, i.e. + # think of it as an infix operator `g extends f` that mimics the syntax from + # Java. It may seem counter-intuitive to have the "base class" as the second + # argument, but it's nice this way if several uses of `extends` are cascaded. + extends = f: rattrs: self: let super = rattrs self; in super // f self super; + + # Compose two extending functions of the type expected by 'extends' + # into one where changes made in the first are available in the + # 'super' of the second + composeExtensions = + f: g: self: super: + let fApplied = f self super; + super' = super // fApplied; + in fApplied // g self super'; + + # Create an overridable, recursive attribute set. For example: + # + # nix-repl> obj = makeExtensible (self: { }) + # + # nix-repl> obj + # { __unfix__ = «lambda»; extend = «lambda»; } + # + # nix-repl> obj = obj.extend (self: super: { foo = "foo"; }) + # + # nix-repl> obj + # { __unfix__ = «lambda»; extend = «lambda»; foo = "foo"; } + # + # nix-repl> obj = obj.extend (self: super: { foo = super.foo + " + "; bar = "bar"; foobar = self.foo + self.bar; }) + # + # nix-repl> obj + # { __unfix__ = «lambda»; bar = "bar"; extend = «lambda»; foo = "foo + "; foobar = "foo + bar"; } + makeExtensible = makeExtensibleWithCustomName "extend"; + + # Same as `makeExtensible` but the name of the extending attribute is + # customized. + makeExtensibleWithCustomName = extenderName: rattrs: + fix' rattrs // { + ${extenderName} = f: makeExtensibleWithCustomName extenderName (extends f rattrs); + }; +} diff --git a/lib/generators.nix b/lib/generators.nix index 4d3c920b0ae3b..4419c3c88917e 100644 --- a/lib/generators.nix +++ b/lib/generators.nix @@ -90,4 +90,41 @@ rec { * parsers as well. */ toYAML = {}@args: toJSON args; + + /* Pretty print a value, akin to `builtins.trace`. + * Should probably be a builtin as well. + */ + toPretty = { + /* If this option is true, attrsets like { __pretty = fn; val = …; } + will use fn to convert val to a pretty printed representation. + (This means fn is type Val -> String.) */ + allowPrettyValues ? false + }@args: v: with builtins; + if isInt v then toString v + else if isBool v then (if v == true then "true" else "false") + else if isString v then "\"" + v + "\"" + else if null == v then "null" + else if isFunction v then + let fna = functionArgs v; + showFnas = concatStringsSep "," (libAttr.mapAttrsToList + (name: hasDefVal: if hasDefVal then "(${name})" else name) + fna); + in if fna == {} then "<λ>" + else "<λ:{${showFnas}}>" + else if isList v then "[ " + + libStr.concatMapStringsSep " " (toPretty args) v + + " ]" + else if isAttrs v then + # apply pretty values if allowed + if attrNames v == [ "__pretty" "val" ] && allowPrettyValues + then v.__pretty v.val + # TODO: there is probably a better representation? + else if v ? type && v.type == "derivation" then "<δ>" + else "{ " + + libStr.concatStringsSep " " (libAttr.mapAttrsToList + (name: value: + "${toPretty args name} = ${toPretty args value};") v) + + " }" + else "toPretty: should never happen (v = ${v})"; + } diff --git a/lib/licenses.nix b/lib/licenses.nix index 0919699b41e37..8dd1c210b7fa9 100644 --- a/lib/licenses.nix +++ b/lib/licenses.nix @@ -45,6 +45,11 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec { fullName = "Apple Public Source License 2.0"; }; + arphicpl = { + fullName = "Arphic Public License"; + url = https://www.freedesktop.org/wiki/Arphic_Public_License/; + }; + artistic1 = spdx { spdxId = "Artistic-1.0"; fullName = "Artistic License 1.0"; diff --git a/lib/lists.nix b/lib/lists.nix index fd746f4f97b1f..6a8fd8a184082 100644 --- a/lib/lists.nix +++ b/lib/lists.nix @@ -77,15 +77,21 @@ rec { */ foldl' = builtins.foldl' or foldl; - /* Map with index + /* Map with index starting from 0 - FIXME(zimbatm): why does this start to count at 1? + Example: + imap0 (i: v: "${v}-${toString i}") ["a" "b"] + => [ "a-0" "b-1" ] + */ + imap0 = f: list: genList (n: f n (elemAt list n)) (length list); + + /* Map with index starting from 1 Example: - imap (i: v: "${v}-${toString i}") ["a" "b"] + imap1 (i: v: "${v}-${toString i}") ["a" "b"] => [ "a-1" "b-2" ] */ - imap = f: list: genList (n: f (n + 1) (elemAt list n)) (length list); + imap1 = f: list: genList (n: f (n + 1) (elemAt list n)) (length list); /* Map and concatenate the result. @@ -471,4 +477,12 @@ rec { */ subtractLists = e: filter (x: !(elem x e)); + /* Test if two lists have no common element. + It should be slightly more efficient than (intersectLists a b == []) + */ + mutuallyExclusive = a: b: + (builtins.length a) == 0 || + (!(builtins.elem (builtins.head a) b) && + mutuallyExclusive (builtins.tail a) b); + } diff --git a/lib/maintainers.nix b/lib/maintainers.nix index f3204ab3b345d..31760c94eb0fc 100644 --- a/lib/maintainers.nix +++ b/lib/maintainers.nix @@ -16,6 +16,7 @@ acowley = "Anthony Cowley <acowley@gmail.com>"; adelbertc = "Adelbert Chang <adelbertc@gmail.com>"; adev = "Adrien Devresse <adev@adev.name>"; + adisbladis = "Adam Hose <adis@blad.is>"; Adjective-Object = "Maxwell Huang-Hobbs <mhuan13@gmail.com>"; adnelson = "Allen Nelson <ithinkican@gmail.com>"; adolfogc = "Adolfo E. García Castro <adolfo.garcia.cr@gmail.com>"; @@ -42,7 +43,9 @@ andrewrk = "Andrew Kelley <superjoe30@gmail.com>"; andsild = "Anders Sildnes <andsild@gmail.com>"; aneeshusa = "Aneesh Agrawal <aneeshusa@gmail.com>"; + ankhers = "Justin Wood <justin.k.wood@gmail.com>"; antono = "Antono Vasiljev <self@antono.info>"; + apeschar = "Albert Peschar <albert@peschar.net>"; apeyroux = "Alexandre Peyroux <alex@px.io>"; ardumont = "Antoine R. Dumont <eniotna.t@gmail.com>"; aristid = "Aristid Breitkreuz <aristidb@gmail.com>"; @@ -60,6 +63,7 @@ bachp = "Pascal Bach <pascal.bach@nextrem.ch>"; badi = "Badi' Abdul-Wahid <abdulwahidc@gmail.com>"; balajisivaraman = "Balaji Sivaraman<sivaraman.balaji@gmail.com>"; + barrucadu = "Michael Walker <mike@barrucadu.co.uk>"; basvandijk = "Bas van Dijk <v.dijk.bas@gmail.com>"; Baughn = "Svein Ove Aas <sveina@gmail.com>"; bcarrell = "Brandon Carrell <brandoncarrell@gmail.com>"; @@ -70,6 +74,8 @@ benwbooth = "Ben Booth <benwbooth@gmail.com>"; berdario = "Dario Bertini <berdario@gmail.com>"; bergey = "Daniel Bergey <bergey@teallabs.org>"; + bhipple = "Benjamin Hipple <bhipple@protonmail.com>"; + binarin = "Alexey Lebedeff <binarin@binarin.ru>"; bjg = "Brian Gough <bjg@gnu.org>"; bjornfor = "Bjørn Forsman <bjorn.forsman@gmail.com>"; bluescreen303 = "Mathijs Kwik <mathijs@bluescreen303.nl>"; @@ -97,6 +103,7 @@ chris-martin = "Chris Martin <ch.martin@gmail.com>"; chrisjefferson = "Christopher Jefferson <chris@bubblescope.net>"; christopherpoole = "Christopher Mark Poole <mail@christopherpoole.net>"; + ciil = "Simon Lackerbauer <simon@lackerbauer.com>"; ckampka = "Christian Kampka <christian@kampka.net>"; cko = "Christine Koppelt <christine.koppelt@gmail.com>"; cleverca22 = "Michael Bishop <cleverca22@gmail.com>"; @@ -130,6 +137,7 @@ deepfire = "Kosyrev Serge <_deepfire@feelingofgreen.ru>"; demin-dmitriy = "Dmitriy Demin <demindf@gmail.com>"; DerGuteMoritz = "Moritz Heidkamp <moritz@twoticketsplease.de>"; + dermetfan = "Robin Stumm <serverkorken@gmail.com>"; DerTim1 = "Tim Digel <tim.digel@active-group.de>"; desiderius = "Didier J. Devroye <didier@devroye.name>"; devhell = "devhell <\"^\"@regexmail.net>"; @@ -137,20 +145,24 @@ dfoxfranke = "Daniel Fox Franke <dfoxfranke@gmail.com>"; dgonyeo = "Derek Gonyeo <derek@gonyeo.com>"; dipinhora = "Dipin Hora <dipinhora+github@gmail.com>"; + disassembler = "Samuel Leathers <disasm@gmail.com>"; dmalikov = "Dmitry Malikov <malikov.d.y@gmail.com>"; DmitryTsygankov = "Dmitry Tsygankov <dmitry.tsygankov@gmail.com>"; dmjio = "David Johnson <djohnson.m@gmail.com>"; dochang = "Desmond O. Chang <dochang@gmail.com>"; domenkozar = "Domen Kozar <domen@dev.si>"; + dotlambda = "Robert Schütz <rschuetz17@gmail.com>"; doublec = "Chris Double <chris.double@double.co.nz>"; dpaetzel = "David Pätzel <david.a.paetzel@gmail.com>"; drets = "Dmytro Rets <dmitryrets@gmail.com>"; drewkett = "Andrew Burkett <burkett.andrew@gmail.com>"; dsferruzza = "David Sferruzza <david.sferruzza@gmail.com>"; dtzWill = "Will Dietz <nix@wdtz.org>"; + dywedir = "Vladyslav M. <dywedir@protonmail.ch>"; e-user = "Alexander Kahl <nixos@sodosopa.io>"; ebzzry = "Rommel Martinez <ebzzry@gmail.com>"; edanaher = "Evan Danaher <nixos@edanaher.net>"; + edef = "edef <edef@edef.eu>"; ederoyd46 = "Matthew Brown <matt@ederoyd.co.uk>"; eduarrrd = "Eduard Bachmakov <e.bachmakov@gmail.com>"; edwtjo = "Edward Tjörnhammar <ed@cflags.cc>"; @@ -158,8 +170,10 @@ ehegnes = "Eric Hegnes <eric.hegnes@gmail.com>"; ehmry = "Emery Hemingway <emery@vfemail.net>"; eikek = "Eike Kettner <eike.kettner@posteo.de>"; + ekleog = "Leo Gaspard <leo@gaspard.io>"; elasticdog = "Aaron Bull Schaefer <aaron@elasticdog.com>"; eleanor = "Dejan Lukan <dejan@proteansec.com>"; + elijahcaine = "Elijah Caine <elijahcainemv@gmail.com>"; elitak = "Eric Litak <elitak@gmail.com>"; ellis = "Ellis Whitehead <nixos@ellisw.net>"; eperuffo = "Emanuele Peruffo <info@emanueleperuffo.com>"; @@ -173,7 +187,9 @@ exlevan = "Alexey Levan <exlevan@gmail.com>"; expipiplus1 = "Joe Hermaszewski <nix@monoid.al>"; fadenb = "Tristan Helmich <tristan.helmich+nixos@gmail.com>"; + fare = "Francois-Rene Rideau <fahree@gmail.com>"; falsifian = "James Cook <james.cook@utoronto.ca>"; + florianjacob = "Florian Jacob <projects+nixos@florianjacob.de>"; flosse = "Markus Kohlhase <mail@markus-kohlhase.de>"; fluffynukeit = "Daniel Austin <dan@fluffynukeit.com>"; fmthoma = "Franz Thoma <f.m.thoma@googlemail.com>"; @@ -194,6 +210,7 @@ garrison = "Jim Garrison <jim@garrison.cc>"; gavin = "Gavin Rogers <gavin@praxeology.co.uk>"; gebner = "Gabriel Ebner <gebner@gebner.org>"; + georgewhewell = "George Whewell <georgerw@gmail.com>"; gilligan = "Tobias Pflug <tobias.pflug@gmail.com>"; giogadi = "Luis G. Torres <lgtorres42@gmail.com>"; gleber = "Gleb Peregud <gleber.p@gmail.com>"; @@ -204,6 +221,7 @@ goodrone = "Andrew Trachenko <goodrone@gmail.com>"; gpyh = "Yacine Hmito <yacine.hmito@gmail.com>"; grahamc = "Graham Christensen <graham@grahamc.com>"; + grburst = "Julius Elias <grburst@openmailbox.org>"; gridaphobe = "Eric Seidel <eric@seidel.io>"; guibert = "David Guibert <david.guibert@gmail.com>"; guillaumekoenig = "Guillaume Koenig <guillaume.edward.koenig@gmail.com>"; @@ -212,11 +230,14 @@ havvy = "Ryan Scheel <ryan.havvy@gmail.com>"; hbunke = "Hendrik Bunke <bunke.hendrik@gmail.com>"; hce = "Hans-Christian Esperer <hc@hcesperer.org>"; + hectorj = "Hector Jusforgues <hector.jusforgues+nixos@gmail.com>"; heel = "Sergii Paryzhskyi <parizhskiy@gmail.com>"; henrytill = "Henry Till <henrytill@gmail.com>"; + hhm = "hhm <heehooman+nixpkgs@gmail.com>"; hinton = "Tom Hinton <t@larkery.com>"; hodapp = "Chris Hodapp <hodapp87@gmail.com>"; hrdinka = "Christoph Hrdinka <c.nix@hrdinka.at>"; + htr = "Hugo Tavares Reis <hugo@linux.com>"; iand675 = "Ian Duncan <ian@iankduncan.com>"; ianwookim = "Ian-Woo Kim <ianwookim@gmail.com>"; igsha = "Igor Sharonov <igor.sharonov@gmail.com>"; @@ -225,32 +246,38 @@ ivan-tkatchev = "Ivan Tkatchev <tkatchev@gmail.com>"; j-keck = "Jürgen Keck <jhyphenkeck@gmail.com>"; jagajaga = "Arseniy Seroka <ars.seroka@gmail.com>"; + jammerful = "jammerful <jammerful@gmail.com>"; jansol = "Jan Solanti <jan.solanti@paivola.fi>"; javaguirre = "Javier Aguirre <contacto@javaguirre.net>"; - jb55 = "William Casarin <bill@casarin.me>"; + jb55 = "William Casarin <jb55@jb55.com>"; jbedo = "Justin Bedő <cu@cua0.org>"; jcumming = "Jack Cummings <jack@mudshark.org>"; jdagilliland = "Jason Gilliland <jdagilliland@gmail.com>"; jefdaj = "Jeffrey David Johnson <jefdaj@gmail.com>"; + jensbin = "Jens Binkert <jensbin@protonmail.com>"; jerith666 = "Matt McHenry <github@matt.mchenryfamily.org>"; jfb = "James Felix Black <james@yamtime.com>"; + jfrankenau = "Johannes Frankenau <johannes@frankenau.net>"; jgeerds = "Jascha Geerds <jascha@jgeerds.name>"; jgertm = "Tim Jaeger <jger.tm@gmail.com>"; jgillich = "Jakob Gillich <jakob@gillich.me>"; jhhuh = "Ji-Haeng Huh <jhhuh.note@gmail.com>"; jirkamarsik = "Jirka Marsik <jiri.marsik89@gmail.com>"; jlesquembre = "José Luis Lafuente <jl@lafuente.me>"; + jluttine = "Jaakko Luttinen <jaakko.luttinen@iki.fi>"; joachifm = "Joachim Fasting <joachifm@fastmail.fm>"; joamaki = "Jussi Maki <joamaki@gmail.com>"; joelmo = "Joel Moberg <joel.moberg@gmail.com>"; joelteon = "Joel Taylor <me@joelt.io>"; johbo = "Johannes Bornhold <johannes@bornhold.name>"; + johnramsden = "John Ramsden <johnramsden@riseup.net>"; joko = "Ioannis Koutras <ioannis.koutras@gmail.com>"; jonafato = "Jon Banafato <jon@jonafato.com>"; jpbernardy = "Jean-Philippe Bernardy <jeanphilippe.bernardy@gmail.com>"; jpierre03 = "Jean-Pierre PRUNARET <nix@prunetwork.fr>"; jpotier = "Martin Potier <jpo.contributes.to.nixos@marvid.fr>"; jraygauthier = "Raymond Gauthier <jraygauthier@gmail.com>"; + jtojnar = "Jan Tojnar <jtojnar@gmail.com>"; juliendehos = "Julien Dehos <dehos@lisic.univ-littoral.fr>"; jwiegley = "John Wiegley <johnw@newartisans.com>"; jwilberding = "Jordan Wilberding <jwilberding@afiniate.com>"; @@ -258,12 +285,14 @@ kaiha = "Kai Harries <kai.harries@gmail.com>"; kamilchm = "Kamil Chmielewski <kamil.chm@gmail.com>"; kampfschlaefer = "Arnold Krille <arnold@arnoldarts.de>"; + kentjames = "James Kent <jameschristopherkent@gmail.com"; kevincox = "Kevin Cox <kevincox@kevincox.ca>"; khumba = "Bryan Gardiner <bog@khumba.net>"; KibaFox = "Kiba Fox <kiba.fox@foxypossibilities.com>"; kierdavis = "Kier Davis <kierdavis@gmail.com>"; kkallio = "Karn Kallio <tierpluspluslists@gmail.com>"; knedlsepp = "Josef Kemetmüller <josef.kemetmueller@gmail.com>"; + konimex = "Muhammad Herdiansyah <herdiansyah@openmailbox.org>"; koral = "Koral <koral@mailoo.org>"; kovirobi = "Kovacsics Robert <kovirobi@gmail.com>"; kragniz = "Louis Taylor <louis@kragniz.eu>"; @@ -291,9 +320,12 @@ lsix = "Lancelot SIX <lsix@lancelotsix.com>"; lucas8 = "Luc Chabassier <luc.linux@mailoo.org>"; ludo = "Ludovic Courtès <ludo@gnu.org>"; + lufia = "Kyohei Kadota <lufia@lufia.org>"; luispedro = "Luis Pedro Coelho <luis@luispedro.org>"; lukego = "Luke Gorrie <luke@snabb.co>"; lw = "Sergey Sofeychuk <lw@fmap.me>"; + lyt = "Tim Liou <wheatdoge@gmail.com>"; + m3tti = "Mathaeus Sander <mathaeus.peter.sander@gmail.com>"; ma27 = "Maximilian Bosch <maximilian@mbosch.me>"; madjar = "Georges Dubus <georges.dubus@compiletoi.net>"; magnetophon = "Bart Brouns <bart@magnetophon.nl>"; @@ -326,6 +358,7 @@ michaelpj = "Michael Peyton Jones <michaelpj@gmail.com>"; michalrus = "Michal Rus <m@michalrus.com>"; michelk = "Michel Kuhlmann <michel@kuhlmanns.info>"; + midchildan = "midchildan <midchildan+nix@gmail.com>"; mikefaille = "Michaël Faille <michael@faille.io>"; miltador = "Vasiliy Solovey <miltador@yandex.ua>"; mimadrid = "Miguel Madrid <mimadrid@ucm.es>"; @@ -348,6 +381,7 @@ msackman = "Matthew Sackman <matthew@wellquite.org>"; mschristiansen = "Mikkel Christiansen <mikkel@rheosystems.com>"; msteen = "Matthijs Steen <emailmatthijs@gmail.com>"; + mt-caret = "Masayuki Takeda <mtakeda.enigsol@gmail.com>"; mtreskin = "Max Treskin <zerthurd@gmail.com>"; mudri = "James Wood <lamudri@gmail.com>"; muflax = "Stefan Dorn <mail@muflax.com>"; @@ -356,11 +390,12 @@ nand0p = "Fernando Jose Pando <nando@hex7.com>"; Nate-Devv = "Nathan Moore <natedevv@gmail.com>"; nathan-gs = "Nathan Bijnens <nathan@nathan.gs>"; - nckx = "Tobias Geerinckx-Rice <tobias.geerinckx.rice@gmail.com>"; + nckx = "Tobias Geerinckx-Rice <github@tobias.gr>"; ndowens = "Nathan Owens <ndowens04@gmail.com>"; neeasade = "Nathan Isom <nathanisom27@gmail.com>"; nequissimus = "Tim Steinbach <tim@nequissimus.com>"; nfjinjing = "Jinjing Wang <nfjinjing@gmail.com>"; + nh2 = "Niklas Hambüchen <mail@nh2.me>"; nhooyr = "Anmol Sethi <anmol@aubble.com>"; nickhu = "Nick Hu <me@nickhu.co.uk>"; nicknovitski = "Nick Novitski <nixpkgs@nicknovitski.com>"; @@ -381,6 +416,7 @@ okasu = "Okasu <oka.sux@gmail.com>"; olcai = "Erik Timan <dev@timan.info>"; olejorgenb = "Ole Jørgen Brønner <olejorgenb@yahoo.no>"; + olynch = "Owen Lynch <owen@olynch.me>"; orbekk = "KJ Ørbekk <kjetil.orbekk@gmail.com>"; orbitz = "Malcolm Matalka <mmatalka@gmail.com>"; orivej = "Orivej Desh <orivej@gmx.fr>"; @@ -442,24 +478,27 @@ relrod = "Ricky Elrod <ricky@elrod.me>"; renzo = "Renzo Carbonara <renzocarbonara@gmail.com>"; retrry = "Tadas Barzdžius <retrry@gmail.com>"; + rht = "rht <rhtbot@protonmail.com>"; rick68 = "Wei-Ming Yang <rick68@gmail.com>"; rickynils = "Rickard Nilsson <rickynils@gmail.com>"; + ris = "Robert Scott <code@humanleg.org.uk>"; rlupton20 = "Richard Lupton <richard.lupton@gmail.com>"; rnhmjoj = "Michele Guerini Rocco <micheleguerinirocco@me.com>"; rob = "Rob Vermaas <rob.vermaas@gmail.com>"; robberer = "Longrin Wischnewski <robberer@freakmail.de>"; robbinch = "Robbin C. <robbinch33@gmail.com>"; + roberth = "Robert Hensing <nixpkgs@roberthensing.nl>"; robgssp = "Rob Glossop <robgssp@gmail.com>"; roblabla = "Robin Lambertz <robinlambertz+dev@gmail.com>"; roconnor = "Russell O'Connor <roconnor@theorem.ca>"; romildo = "José Romildo Malaquias <malaquias@gmail.com>"; rongcuid = "Rongcui Dong <rongcuid@outlook.com>"; - ronny = "Ronny Pfannschmidt <nixos@ronnypfannschmidt.de>"; rszibele = "Richard Szibele <richard@szibele.com>"; rtreffer = "Rene Treffer <treffer+nixos@measite.de>"; rushmorem = "Rushmore Mushambi <rushmore@webenchanter.com>"; rvl = "Rodney Lorrimar <dev+nix@rodney.id.au>"; rvlander = "Gaëtan André <rvlander@gaetanandre.eu>"; + rvolosatovs = "Roman Volosatovs <rvolosatovs@riseup.net"; ryanartecona = "Ryan Artecona <ryanartecona@gmail.com>"; ryansydnor = "Ryan Sydnor <ryan.t.sydnor@gmail.com>"; ryantm = "Ryan Mulligan <ryan@ryantm.com>"; @@ -469,6 +508,7 @@ s1lvester = "Markus Silvester <s1lvester@bockhacker.me>"; samuelrivas = "Samuel Rivas <samuelrivas@gmail.com>"; sander = "Sander van der Burg <s.vanderburg@tudelft.nl>"; + sargon = "Daniel Ehlers <danielehlers@mindeye.net>"; schmitthenner = "Fabian Schmitthenner <development@schmitthenner.eu>"; schneefux = "schneefux <schneefux+nixos_pkg@schneefux.xyz>"; schristo = "Scott Christopher <schristopher@konputa.com>"; @@ -491,6 +531,7 @@ skrzyp = "Jakub Skrzypnik <jot.skrzyp@gmail.com>"; sleexyz = "Sean Lee <freshdried@gmail.com>"; smironov = "Sergey Mironov <grrwlf@gmail.com>"; + snyh = "Xia Bin <snyh@snyh.org>"; solson = "Scott Olson <scott@solson.me>"; spacefrogg = "Michael Raitza <spacefrogg-nixos@meterriblecrew.net>"; spencerjanssen = "Spencer Janssen <spencerjanssen@gmail.com>"; @@ -505,6 +546,7 @@ steveej = "Stefan Junker <mail@stefanjunker.de>"; SuprDewd = "Bjarki Ágúst Guðmundsson <suprdewd@gmail.com>"; swarren83 = "Shawn Warren <shawn.w.warren@gmail.com>"; + swflint = "Samuel W. Flint <swflint@flintfam.org>"; swistak35 = "Rafał Łasocha <me@swistak35.com>"; szczyp = "Szczyp <qb@szczyp.com>"; sztupi = "Attila Sztupak <attila.sztupak@gmail.com>"; @@ -513,6 +555,7 @@ takikawa = "Asumu Takikawa <asumu@igalia.com>"; taktoa = "Remy Goldschmidt <taktoa@gmail.com>"; taku0 = "Takuo Yonezawa <mxxouy6x3m_github@tatapa.org>"; + tari = "Peter Marheine <peter@taricorp.net>"; tavyc = "Octavian Cerna <octavian.cerna@gmail.com>"; teh = "Tom Hunger <tehunger@gmail.com>"; telotortium = "Robert Irelan <rirelan@gmail.com>"; @@ -526,18 +569,22 @@ tohl = "Tomas Hlavaty <tom@logand.com>"; tokudan = "Daniel Frank <git@danielfrank.net>"; tomberek = "Thomas Bereknyei <tomberek@gmail.com>"; + tomsmeets = "Tom Smeets <tom@tsmeets.nl>"; travisbhartwell = "Travis B. Hartwell <nafai@travishartwell.net>"; + trevorj = "Trevor Joynson <nix@trevor.joynson.io>"; trino = "Hubert Mühlhans <muehlhans.hubert@ekodia.de>"; tstrobel = "Thomas Strobel <4ZKTUB6TEP74PYJOPWIR013S2AV29YUBW5F9ZH2F4D5UMJUJ6S@hash.domains>"; ttuegel = "Thomas Tuegel <ttuegel@mailbox.org>"; tv = "Tomislav Viljetić <tv@shackspace.de>"; tvestelind = "Tomas Vestelind <tomas.vestelind@fripost.org>"; tvorog = "Marsel Zaripov <marszaripov@gmail.com>"; + tweber = "Thorsten Weber <tw+nixpkgs@360vier.de>"; twey = "James ‘Twey’ Kay <twey@twey.co.uk>"; uralbash = "Svintsov Dmitry <root@uralbash.ru>"; utdemir = "Utku Demir <me@utdemir.com>"; #urkud = "Yury G. Kudryashov <urkud+nix@ya.ru>"; inactive since 2012 uwap = "uwap <me@uwap.name>"; + vaibhavsagar = "Vaibhav Sagar <vaibhavsagar@gmail.com>"; vandenoever = "Jos van den Oever <jos@vandenoever.info>"; vanzef = "Ivan Solyankin <vanzef@gmail.com>"; vbgl = "Vincent Laporte <Vincent.Laporte@gmail.com>"; @@ -551,10 +598,13 @@ vklquevs = "vklquevs <vklquevs@gmail.com>"; vlstill = "Vladimír Štill <xstill@fi.muni.cz>"; vmandela = "Venkateswara Rao Mandela <venkat.mandela@gmail.com>"; + vmchale = "Vanessa McHale <tmchale@wisc.edu>"; + valeriangalliat = "Valérian Galliat <val@codejam.info>"; volhovm = "Mikhail Volkhov <volhovm.cs@gmail.com>"; volth = "Jaroslavas Pocepko <jaroslavas@volth.com>"; vozz = "Oliver Hunt <oliver.huntuk@gmail.com>"; vrthra = "Rahul Gopinath <rahul@gopinath.org>"; + vyp = "vyp <elisp.vim@gmail.com>"; wedens = "wedens <kirill.wedens@gmail.com>"; willtim = "Tim Philip Williams <tim.williams.public@gmail.com>"; winden = "Antonio Vargas Gonzalez <windenntw@gmail.com>"; @@ -571,13 +621,17 @@ yarr = "Dmitry V. <savraz@gmail.com>"; yochai = "Yochai <yochai@titat.info>"; yorickvp = "Yorick van Pelt <yorickvanpelt@gmail.com>"; + yuriaisaka = "Yuri Aisaka <yuri.aisaka+nix@gmail.com>"; yurrriq = "Eric Bailey <eric@ericb.me>"; z77z = "Marco Maggesi <maggesi@math.unifi.it>"; zagy = "Christian Zagrodnick <cz@flyingcircus.io>"; + zalakain = "Unai Zalakain <contact@unaizalakain.info>"; + zarelit = "David Costa <david@zarel.net>"; zauberpony = "Elmar Athmer <elmar@athmer.org>"; zef = "Zef Hemel <zef@zef.me>"; zimbatm = "zimbatm <zimbatm@zimbatm.com>"; zohl = "Al Zohali <zohl@fmap.me>"; zoomulator = "Kim Simmons <zoomulator@gmail.com>"; zraexy = "David Mell <zraexy@gmail.com>"; + zx2c4 = "Jason A. Donenfeld <Jason@zx2c4.com>"; } diff --git a/lib/meta.nix b/lib/meta.nix index 44e3cc011f187..8f77bbe014844 100644 --- a/lib/meta.nix +++ b/lib/meta.nix @@ -17,6 +17,11 @@ rec { drv // { meta = (drv.meta or {}) // newAttrs; }; + /* Disable Hydra builds of given derivation. + */ + dontDistribute = drv: addMetaAttrs { hydraPlatforms = []; } drv; + + /* Change the symbolic name of a package for presentation purposes (i.e., so that nix-env users can tell them apart). */ @@ -45,7 +50,7 @@ rec { /* Decrease the nix-env priority of the package, i.e., other versions/variants of the package will be preferred. */ - lowPrio = drv: addMetaAttrs { priority = "10"; } drv; + lowPrio = drv: addMetaAttrs { priority = 10; } drv; /* Apply lowPrio to an attrset with derivations @@ -56,7 +61,7 @@ rec { /* Increase the nix-env priority of the package, i.e., this version/variant of the package will be preferred. */ - hiPrio = drv: addMetaAttrs { priority = "-10"; } drv; + hiPrio = drv: addMetaAttrs { priority = -10; } drv; /* Apply hiPrio to an attrset with derivations diff --git a/lib/modules.nix b/lib/modules.nix index 91e2eae0595e3..3da689a6bdb00 100644 --- a/lib/modules.nix +++ b/lib/modules.nix @@ -98,7 +98,7 @@ rec { /* Close a set of modules under the ‘imports’ relation. */ closeModules = modules: args: let - toClosureList = file: parentKey: imap (n: x: + toClosureList = file: parentKey: imap1 (n: x: if isAttrs x || isFunction x then let key = "${parentKey}:anon-${toString n}"; in unifyModuleSyntax file key (unpackSubmodule (applyIfFunction key) x args) diff --git a/lib/strings.nix b/lib/strings.nix index d48624257cf01..a03694d1b1d72 100644 --- a/lib/strings.nix +++ b/lib/strings.nix @@ -33,7 +33,7 @@ rec { concatImapStrings (pos: x: "${toString pos}-${x}") ["foo" "bar"] => "1-foo2-bar" */ - concatImapStrings = f: list: concatStrings (lib.imap f list); + concatImapStrings = f: list: concatStrings (lib.imap1 f list); /* Place an element between each element of a list @@ -70,7 +70,7 @@ rec { concatImapStringsSep "-" (pos: x: toString (x / pos)) [ 6 6 6 ] => "6-3-2" */ - concatImapStringsSep = sep: f: list: concatStringsSep sep (lib.imap f list); + concatImapStringsSep = sep: f: list: concatStringsSep sep (lib.imap1 f list); /* Construct a Unix-style search path consisting of each `subDir" directory of the given list of packages. @@ -438,8 +438,13 @@ rec { => true isStorePath pkgs.python => true + isStorePath [] || isStorePath 42 || isStorePath {} || … + => false */ - isStorePath = x: builtins.substring 0 1 (toString x) == "/" && dirOf (builtins.toPath x) == builtins.storeDir; + isStorePath = x: + builtins.isString x + && builtins.substring 0 1 (toString x) == "/" + && dirOf (builtins.toPath x) == builtins.storeDir; /* Convert string to int Obviously, it is a bit hacky to use fromJSON that way. diff --git a/lib/systems/default.nix b/lib/systems/default.nix index d956969a18f92..c22c99561969d 100644 --- a/lib/systems/default.nix +++ b/lib/systems/default.nix @@ -1,7 +1,11 @@ +let inherit (import ../attrsets.nix) mapAttrs; in + rec { doubles = import ./doubles.nix; parse = import ./parse.nix; + inspect = import ./inspect.nix; platforms = import ./platforms.nix; + examples = import ./examples.nix; # Elaborate a `localSystem` or `crossSystem` so that it contains everything # necessary. @@ -18,6 +22,13 @@ rec { config = parse.tripleFromSystem final.parsed; # Just a guess, based on `system` platform = platforms.selectBySystem final.system; - } // args; + libc = + /**/ if final.isDarwin then "libSystem" + else if final.isMinGW then "msvcrt" + else if final.isLinux then "glibc" + # TODO(@Ericson2314) think more about other operating systems + else "native/impure"; + } // mapAttrs (n: v: v final.parsed) inspect.predicates + // args; in final; } diff --git a/lib/systems/doubles.nix b/lib/systems/doubles.nix index 9b17a51531a33..0168eb42f2f73 100644 --- a/lib/systems/doubles.nix +++ b/lib/systems/doubles.nix @@ -1,8 +1,9 @@ -let lists = import ../lists.nix; in -let parse = import ./parse.nix; in -let inherit (import ../attrsets.nix) matchAttrs; in - let + lists = import ../lists.nix; + parse = import ./parse.nix; + inherit (import ./inspect.nix) predicates; + inherit (import ../attrsets.nix) matchAttrs; + all = [ "aarch64-linux" "armv5tel-linux" "armv6l-linux" "armv7l-linux" @@ -25,20 +26,21 @@ in rec { allBut = platforms: lists.filter (x: !(builtins.elem x platforms)) all; none = []; - arm = filterDoubles (matchAttrs { cpu = { family = "arm"; bits = 32; }; }); - i686 = filterDoubles parse.isi686; - mips = filterDoubles (matchAttrs { cpu = { family = "mips"; }; }); - x86_64 = filterDoubles parse.isx86_64; - - cygwin = filterDoubles parse.isCygwin; - darwin = filterDoubles parse.isDarwin; - freebsd = filterDoubles (matchAttrs { kernel = parse.kernels.freebsd; }); - gnu = filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnu; }); # Should be better - illumos = filterDoubles (matchAttrs { kernel = parse.kernels.solaris; }); - linux = filterDoubles parse.isLinux; - netbsd = filterDoubles (matchAttrs { kernel = parse.kernels.netbsd; }); - openbsd = filterDoubles (matchAttrs { kernel = parse.kernels.openbsd; }); - unix = filterDoubles parse.isUnix; + arm = filterDoubles predicates.isArm32; + i686 = filterDoubles predicates.isi686; + mips = filterDoubles predicates.isMips; + x86_64 = filterDoubles predicates.isx86_64; + + cygwin = filterDoubles predicates.isCygwin; + darwin = filterDoubles predicates.isDarwin; + freebsd = filterDoubles predicates.isFreeBSD; + # Should be better, but MinGW is unclear, and HURD is bit-rotted. + gnu = filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnu; }); + illumos = filterDoubles predicates.isSunOS; + linux = filterDoubles predicates.isLinux; + netbsd = filterDoubles predicates.isNetBSD; + openbsd = filterDoubles predicates.isOpenBSD; + unix = filterDoubles predicates.isUnix; mesaPlatforms = ["i686-linux" "x86_64-linux" "x86_64-darwin" "armv5tel-linux" "armv6l-linux" "armv7l-linux" "aarch64-linux"]; } diff --git a/lib/systems/examples.nix b/lib/systems/examples.nix new file mode 100644 index 0000000000000..e394f43831c9f --- /dev/null +++ b/lib/systems/examples.nix @@ -0,0 +1,130 @@ +# These can be passed to nixpkgs as either the `localSystem` or +# `crossSystem`. They are put here for user convenience, but also used by cross +# tests and linux cross stdenv building, so handle with care! + +let platforms = import ./platforms.nix; in + +rec { + # + # Linux + # + + sheevaplug = rec { + config = "armv5tel-unknown-linux-gnueabi"; + bigEndian = false; + arch = "armv5tel"; + float = "soft"; + withTLS = true; + libc = "glibc"; + platform = platforms.sheevaplug; + openssl.system = "linux-generic32"; + inherit (platform) gcc; + }; + + raspberryPi = rec { + config = "armv6l-unknown-linux-gnueabihf"; + bigEndian = false; + arch = "armv6l"; + float = "hard"; + fpu = "vfp"; + withTLS = true; + libc = "glibc"; + platform = platforms.raspberrypi; + openssl.system = "linux-generic32"; + inherit (platform) gcc; + }; + + armv7l-hf-multiplatform = rec { + config = "arm-unknown-linux-gnueabihf"; + bigEndian = false; + arch = "armv7-a"; + float = "hard"; + fpu = "vfpv3-d16"; + withTLS = true; + libc = "glibc"; + platform = platforms.armv7l-hf-multiplatform; + openssl.system = "linux-generic32"; + inherit (platform) gcc; + }; + + aarch64-multiplatform = rec { + config = "aarch64-unknown-linux-gnu"; + bigEndian = false; + arch = "aarch64"; + withTLS = true; + libc = "glibc"; + platform = platforms.aarch64-multiplatform; + inherit (platform) gcc; + }; + + scaleway-c1 = armv7l-hf-multiplatform // rec { + platform = platforms.scaleway-c1; + inherit (platform) gcc; + inherit (gcc) fpu; + }; + + pogoplug4 = rec { + arch = "armv5tel"; + config = "armv5tel-softfloat-linux-gnueabi"; + float = "soft"; + + platform = platforms.pogoplug4; + + inherit (platform) gcc; + libc = "glibc"; + + withTLS = true; + openssl.system = "linux-generic32"; + }; + + fuloongminipc = rec { + config = "mips64el-unknown-linux-gnu"; + bigEndian = false; + arch = "mips"; + float = "hard"; + withTLS = true; + libc = "glibc"; + platform = platforms.fuloong2f_n32; + openssl.system = "linux-generic32"; + inherit (platform) gcc; + }; + + # + # Darwin + # + + iphone64 = { + config = "aarch64-apple-darwin14"; + arch = "arm64"; + libc = "libSystem"; + platform = {}; + }; + + iphone32 = { + config = "arm-apple-darwin10"; + arch = "armv7-a"; + libc = "libSystem"; + platform = {}; + }; + + # + # Windows + # + + # 32 bit mingw-w64 + mingw32 = { + config = "i686-pc-mingw32"; + arch = "x86"; # Irrelevant + libc = "msvcrt"; # This distinguishes the mingw (non posix) toolchain + platform = {}; + }; + + # 64 bit mingw-w64 + mingwW64 = { + # That's the triplet they use in the mingw-w64 docs. + config = "x86_64-pc-mingw32"; + arch = "x86_64"; # Irrelevant + libc = "msvcrt"; # This distinguishes the mingw (non posix) toolchain + platform = {}; + }; +} diff --git a/lib/systems/inspect.nix b/lib/systems/inspect.nix new file mode 100644 index 0000000000000..a81e88989c0aa --- /dev/null +++ b/lib/systems/inspect.nix @@ -0,0 +1,43 @@ +with import ./parse.nix; +with import ../attrsets.nix; +with import ../lists.nix; + +rec { + patterns = rec { + "32bit" = { cpu = { bits = 32; }; }; + "64bit" = { cpu = { bits = 64; }; }; + i686 = { cpu = cpuTypes.i686; }; + x86_64 = { cpu = cpuTypes.x86_64; }; + PowerPC = { cpu = cpuTypes.powerpc; }; + x86 = { cpu = { family = "x86"; }; }; + Arm = { cpu = { family = "arm"; }; }; + Mips = { cpu = { family = "mips"; }; }; + BigEndian = { cpu = { significantByte = significantBytes.bigEndian; }; }; + LittleEndian = { cpu = { significantByte = significantBytes.littleEndian; }; }; + + BSD = { kernel = { families = { inherit (kernelFamilies) bsd; }; }; }; + Unix = [ BSD Darwin Linux SunOS Hurd Cygwin ]; + + Darwin = { kernel = kernels.darwin; }; + Linux = { kernel = kernels.linux; }; + SunOS = { kernel = kernels.solaris; }; + FreeBSD = { kernel = kernels.freebsd; }; + Hurd = { kernel = kernels.hurd; }; + NetBSD = { kernel = kernels.netbsd; }; + OpenBSD = { kernel = kernels.openbsd; }; + Windows = { kernel = kernels.windows; }; + Cygwin = { kernel = kernels.windows; abi = abis.cygnus; }; + MinGW = { kernel = kernels.windows; abi = abis.gnu; }; + + Arm32 = recursiveUpdate Arm patterns."32bit"; + Arm64 = recursiveUpdate Arm patterns."64bit"; + }; + + matchAnyAttrs = patterns: + if builtins.isList patterns then attrs: any (pattern: matchAttrs pattern attrs) patterns + else matchAttrs patterns; + + predicates = mapAttrs' + (name: value: nameValuePair ("is" + name) (matchAnyAttrs value)) + patterns; +} diff --git a/lib/systems/parse.nix b/lib/systems/parse.nix index 8f65a69b17ab6..befe90f9abeb0 100644 --- a/lib/systems/parse.nix +++ b/lib/systems/parse.nix @@ -8,6 +8,7 @@ with import ../lists.nix; with import ../types.nix; with import ../attrsets.nix; +with (import ./inspect.nix).predicates; let lib = import ../default.nix; @@ -43,7 +44,7 @@ rec { i686 = { bits = 32; significantByte = littleEndian; family = "x86"; }; x86_64 = { bits = 64; significantByte = littleEndian; family = "x86"; }; mips64el = { bits = 32; significantByte = littleEndian; family = "mips"; }; - powerpc = { bits = 32; significantByte = bigEndian; family = "powerpc"; }; + powerpc = { bits = 32; significantByte = bigEndian; family = "power"; }; }; isVendor = isType "vendor"; @@ -67,22 +68,25 @@ rec { isKernelFamily = isType "kernel-family"; kernelFamilies = setTypes "kernel-family" { bsd = {}; - unix = {}; }; isKernel = x: isType "kernel" x; kernels = with execFormats; with kernelFamilies; setTypesAssert "kernel" (x: isExecFormat x.execFormat && all isKernelFamily (attrValues x.families)) { - darwin = { execFormat = macho; families = { inherit unix; }; }; - freebsd = { execFormat = elf; families = { inherit unix bsd; }; }; - linux = { execFormat = elf; families = { inherit unix; }; }; - netbsd = { execFormat = elf; families = { inherit unix bsd; }; }; - none = { execFormat = unknown; families = { inherit unix; }; }; - openbsd = { execFormat = elf; families = { inherit unix bsd; }; }; - solaris = { execFormat = elf; families = { inherit unix; }; }; + darwin = { execFormat = macho; families = { }; }; + freebsd = { execFormat = elf; families = { inherit bsd; }; }; + hurd = { execFormat = elf; families = { }; }; + linux = { execFormat = elf; families = { }; }; + netbsd = { execFormat = elf; families = { inherit bsd; }; }; + none = { execFormat = unknown; families = { }; }; + openbsd = { execFormat = elf; families = { inherit bsd; }; }; + solaris = { execFormat = elf; families = { }; }; windows = { execFormat = pe; families = { }; }; } // { # aliases + # TODO(@Ericson2314): Handle these Darwin version suffixes more generally. + darwin10 = kernels.darwin; + darwin14 = kernels.darwin; win32 = kernels.windows; }; @@ -106,23 +110,12 @@ rec { inherit cpu vendor kernel abi; }; - is64Bit = matchAttrs { cpu = { bits = 64; }; }; - is32Bit = matchAttrs { cpu = { bits = 32; }; }; - isi686 = matchAttrs { cpu = cpuTypes.i686; }; - isx86_64 = matchAttrs { cpu = cpuTypes.x86_64; }; - - isDarwin = matchAttrs { kernel = kernels.darwin; }; - isLinux = matchAttrs { kernel = kernels.linux; }; - isUnix = matchAttrs { kernel = { families = { inherit (kernelFamilies) unix; }; }; }; - isWindows = matchAttrs { kernel = kernels.windows; }; - isCygwin = matchAttrs { kernel = kernels.windows; abi = abis.cygnus; }; - isMinGW = matchAttrs { kernel = kernels.windows; abi = abis.gnu; }; - - mkSkeletonFromList = l: { "2" = # We only do 2-part hacks for things Nix already supports if elemAt l 1 == "cygwin" - then { cpu = elemAt l 0; kernel = "windows"; abi = "cygnus"; } + then { cpu = elemAt l 0; kernel = "windows"; abi = "cygnus"; } + else if elemAt l 1 == "gnu" + then { cpu = elemAt l 0; kernel = "hurd"; abi = "gnu"; } else { cpu = elemAt l 0; kernel = elemAt l 1; }; "3" = # Awkwards hacks, beware! if elemAt l 1 == "apple" @@ -150,27 +143,27 @@ rec { getKernel = name: kernels.${name} or (throw "Unknown kernel: ${name}"); getAbi = name: abis.${name} or (throw "Unknown ABI: ${name}"); - system = rec { + parsed = rec { cpu = getCpu args.cpu; vendor = /**/ if args ? vendor then getVendor args.vendor - else if isDarwin system then vendors.apple - else if isWindows system then vendors.pc + else if isDarwin parsed then vendors.apple + else if isWindows parsed then vendors.pc else vendors.unknown; kernel = getKernel args.kernel; abi = /**/ if args ? abi then getAbi args.abi - else if isLinux system then abis.gnu - else if isWindows system then abis.gnu + else if isLinux parsed then abis.gnu + else if isWindows parsed then abis.gnu else abis.unknown; }; - in mkSystem system; + in mkSystem parsed; mkSystemFromString = s: mkSystemFromSkeleton (mkSkeletonFromList (lib.splitString "-" s)); doubleFromSystem = { cpu, vendor, kernel, abi, ... }: - if vendor == kernels.windows && abi == abis.cygnus + if abi == abis.cygnus then "${cpu.name}-cygwin" else "${cpu.name}-${kernel.name}"; diff --git a/lib/systems/platforms.nix b/lib/systems/platforms.nix index 4322c8e2ff687..54ed8f3c12c1c 100644 --- a/lib/systems/platforms.nix +++ b/lib/systems/platforms.nix @@ -21,6 +21,39 @@ rec { kernelAutoModules = false; }; + pogoplug4 = { + name = "pogoplug4"; + + gcc = { + arch = "armv5te"; + float = "soft"; + }; + + kernelMajor = "2.6"; + kernelHeadersBaseConfig = "multi_v5_defconfig"; + kernelBaseConfig = "multi_v5_defconfig"; + kernelArch = "arm"; + kernelAutoModules = false; + kernelExtraConfig = + '' + # Ubi for the mtd + MTD_UBI y + UBIFS_FS y + UBIFS_FS_XATTR y + UBIFS_FS_ADVANCED_COMPR y + UBIFS_FS_LZO y + UBIFS_FS_ZLIB y + UBIFS_FS_DEBUG n + ''; + kernelMakeFlags = [ "LOADADDR=0x8000" ]; + kernelTarget = "uImage"; + # TODO reenable once manual-config's config actually builds a .dtb and this is checked to be working + #kernelDTB = true; + + # XXX can be anything non-null, pkgs actually only cares if it is set or not + uboot = "pogoplug4"; + }; + sheevaplug = { name = "sheevaplug"; kernelMajor = "2.6"; @@ -222,6 +255,10 @@ rec { arch = "armv6"; fpu = "vfp"; float = "hard"; + # TODO(@Ericson2314) what is this and is it a good idea? It was + # used in some cross compilation examples but not others. + # + # abi = "aapcs-linux"; }; }; @@ -307,6 +344,43 @@ rec { uboot = null; }; + scaleway-c1 = armv7l-hf-multiplatform // { + gcc = { + cpu = "cortex-a9"; + fpu = "vfpv3"; + float = "hard"; + }; + }; + + utilite = { + name = "utilite"; + kernelMajor = "2.6"; + kernelHeadersBaseConfig = "multi_v7_defconfig"; + kernelBaseConfig = "multi_v7_defconfig"; + kernelArch = "arm"; + kernelAutoModules = false; + kernelExtraConfig = + '' + # Ubi for the mtd + MTD_UBI y + UBIFS_FS y + UBIFS_FS_XATTR y + UBIFS_FS_ADVANCED_COMPR y + UBIFS_FS_LZO y + UBIFS_FS_ZLIB y + UBIFS_FS_DEBUG n + ''; + kernelMakeFlags = [ "LOADADDR=0x10800000" ]; + kernelTarget = "uImage"; + kernelDTB = true; + uboot = true; #XXX: any non-null value here is needed so that mkimage is present to build kernelTarget uImage + gcc = { + cpu = "cortex-a9"; + fpu = "neon"; + float = "hard"; + }; + }; + guruplug = sheevaplug // { # Define `CONFIG_MACH_GURUPLUG' (see # <http://kerneltrap.org/mailarchive/git-commits-head/2010/5/19/33618>) @@ -390,7 +464,10 @@ rec { ''; kernelTarget = "vmlinux"; uboot = null; - gcc.arch = "loongson2f"; + gcc = { + arch = "loongson2f"; + abi = "n32"; + }; }; beaglebone = armv7l-hf-multiplatform // { @@ -466,6 +543,10 @@ rec { # Cavium ThunderX stuff. PCI_HOST_THUNDER_ECAM y + + # The default (=y) forces us to have the XHCI firmware available in initrd, + # which our initrd builder can't currently do easily. + USB_XHCI_TEGRA m ''; uboot = null; kernelTarget = "Image"; diff --git a/lib/tests.nix b/lib/tests/misc.nix index 995a743fe43f1..4c4c06fe78dab 100644 --- a/lib/tests.nix +++ b/lib/tests/misc.nix @@ -1,11 +1,13 @@ # to run these tests: -# nix-instantiate --eval --strict nixpkgs/lib/tests.nix +# nix-instantiate --eval --strict nixpkgs/lib/tests/misc.nix # if the resulting list is empty, all tests passed -let inherit (builtins) add; in -with import ./default.nix; +with import ../default.nix; runTests { + +# TRIVIAL + testId = { expr = id 1; expected = 1; @@ -33,6 +35,18 @@ runTests { expected = {a = "a";}; }; + testComposeExtensions = { + expr = let obj = makeExtensible (self: { foo = self.bar; }); + f = self: super: { bar = false; baz = true; }; + g = self: super: { bar = super.baz or false; }; + f_o_g = composeExtensions f g; + composed = obj.extend f_o_g; + in composed.foo; + expected = true; + }; + +# STRINGS + testConcatMapStrings = { expr = concatMapStrings (x: x + ";") ["a" "b" "c"]; expected = "a;b;c;"; @@ -43,6 +57,69 @@ runTests { expected = "a,b,c"; }; + testSplitStringsSimple = { + expr = strings.splitString "." "a.b.c.d"; + expected = [ "a" "b" "c" "d" ]; + }; + + testSplitStringsEmpty = { + expr = strings.splitString "." "a..b"; + expected = [ "a" "" "b" ]; + }; + + testSplitStringsOne = { + expr = strings.splitString ":" "a.b"; + expected = [ "a.b" ]; + }; + + testSplitStringsNone = { + expr = strings.splitString "." ""; + expected = [ "" ]; + }; + + testSplitStringsFirstEmpty = { + expr = strings.splitString "/" "/a/b/c"; + expected = [ "" "a" "b" "c" ]; + }; + + testSplitStringsLastEmpty = { + expr = strings.splitString ":" "2001:db8:0:0042::8a2e:370:"; + expected = [ "2001" "db8" "0" "0042" "" "8a2e" "370" "" ]; + }; + + testIsStorePath = { + expr = + let goodPath = + "${builtins.storeDir}/d945ibfx9x185xf04b890y4f9g3cbb63-python-2.7.11"; + in { + storePath = isStorePath goodPath; + storePathAppendix = isStorePath + "${goodPath}/bin/python"; + nonAbsolute = isStorePath (concatStrings (tail (stringToCharacters goodPath))); + asPath = isStorePath (builtins.toPath goodPath); + otherPath = isStorePath "/something/else"; + otherVals = { + attrset = isStorePath {}; + list = isStorePath []; + int = isStorePath 42; + }; + }; + expected = { + storePath = true; + storePathAppendix = false; + nonAbsolute = false; + asPath = true; + otherPath = false; + otherVals = { + attrset = false; + list = false; + int = false; + }; + }; + }; + +# LISTS + testFilter = { expr = filter (x: x != "a") ["a" "b" "c" "a"]; expected = ["b" "c"]; @@ -93,45 +170,6 @@ runTests { expected = { a = [ 2 3 ]; b = [7]; c = [8];}; }; - testOverridableDelayableArgsTest = { - expr = - let res1 = defaultOverridableDelayableArgs id {}; - res2 = defaultOverridableDelayableArgs id { a = 7; }; - res3 = let x = defaultOverridableDelayableArgs id { a = 7; }; - in (x.merge) { b = 10; }; - res4 = let x = defaultOverridableDelayableArgs id { a = 7; }; - in (x.merge) ( x: { b = 10; }); - res5 = let x = defaultOverridableDelayableArgs id { a = 7; }; - in (x.merge) ( x: { a = add x.a 3; }); - res6 = let x = defaultOverridableDelayableArgs id { a = 7; mergeAttrBy = { a = add; }; }; - y = x.merge {}; - in (y.merge) { a = 10; }; - - resRem7 = res6.replace (a: removeAttrs a ["a"]); - - resReplace6 = let x = defaultOverridableDelayableArgs id { a = 7; mergeAttrBy = { a = add; }; }; - x2 = x.merge { a = 20; }; # now we have 27 - in (x2.replace) { a = 10; }; # and override the value by 10 - - # fixed tests (delayed args): (when using them add some comments, please) - resFixed1 = - let x = defaultOverridableDelayableArgs id ( x: { a = 7; c = x.fixed.b; }); - y = x.merge (x: { name = "name-${builtins.toString x.fixed.c}"; }); - in (y.merge) { b = 10; }; - strip = attrs: removeAttrs attrs ["merge" "replace"]; - in all id - [ ((strip res1) == { }) - ((strip res2) == { a = 7; }) - ((strip res3) == { a = 7; b = 10; }) - ((strip res4) == { a = 7; b = 10; }) - ((strip res5) == { a = 10; }) - ((strip res6) == { a = 17; }) - ((strip resRem7) == {}) - ((strip resFixed1) == { a = 7; b = 10; c =10; name = "name-10"; }) - ]; - expected = true; - }; - testSort = { expr = sort builtins.lessThan [ 40 2 30 42 ]; expected = [2 30 40 42]; @@ -158,9 +196,9 @@ runTests { }; - /* Generator tests */ - # these tests assume attributes are converted to lists - # in alphabetical order +# GENERATORS +# these tests assume attributes are converted to lists +# in alphabetical order testMkKeyValueDefault = { expr = generators.mkKeyValueDefault ":" "f:oo" "bar"; @@ -247,43 +285,76 @@ runTests { expected = builtins.toJSON val; }; - testSplitStringsSimple = { - expr = strings.splitString "." "a.b.c.d"; - expected = [ "a" "b" "c" "d" ]; + testToPretty = { + expr = mapAttrs (const (generators.toPretty {})) rec { + int = 42; + bool = true; + string = "fnord"; + null_ = null; + function = x: x; + functionArgs = { arg ? 4, foo }: arg; + list = [ 3 4 function [ false ] ]; + attrs = { foo = null; "foo bar" = "baz"; }; + drv = derivation { name = "test"; system = builtins.currentSystem; }; + }; + expected = rec { + int = "42"; + bool = "true"; + string = "\"fnord\""; + null_ = "null"; + function = "<λ>"; + functionArgs = "<λ:{(arg),foo}>"; + list = "[ 3 4 ${function} [ false ] ]"; + attrs = "{ \"foo\" = null; \"foo bar\" = \"baz\"; }"; + drv = "<δ>"; + }; }; - testSplitStringsEmpty = { - expr = strings.splitString "." "a..b"; - expected = [ "a" "" "b" ]; + testToPrettyAllowPrettyValues = { + expr = generators.toPretty { allowPrettyValues = true; } + { __pretty = v: "«" + v + "»"; val = "foo"; }; + expected = "«foo»"; }; - testSplitStringsOne = { - expr = strings.splitString ":" "a.b"; - expected = [ "a.b" ]; - }; - testSplitStringsNone = { - expr = strings.splitString "." ""; - expected = [ "" ]; - }; +# MISC - testSplitStringsFirstEmpty = { - expr = strings.splitString "/" "/a/b/c"; - expected = [ "" "a" "b" "c" ]; - }; + testOverridableDelayableArgsTest = { + expr = + let res1 = defaultOverridableDelayableArgs id {}; + res2 = defaultOverridableDelayableArgs id { a = 7; }; + res3 = let x = defaultOverridableDelayableArgs id { a = 7; }; + in (x.merge) { b = 10; }; + res4 = let x = defaultOverridableDelayableArgs id { a = 7; }; + in (x.merge) ( x: { b = 10; }); + res5 = let x = defaultOverridableDelayableArgs id { a = 7; }; + in (x.merge) ( x: { a = builtins.add x.a 3; }); + res6 = let x = defaultOverridableDelayableArgs id { a = 7; mergeAttrBy = { a = builtins.add; }; }; + y = x.merge {}; + in (y.merge) { a = 10; }; - testSplitStringsLastEmpty = { - expr = strings.splitString ":" "2001:db8:0:0042::8a2e:370:"; - expected = [ "2001" "db8" "0" "0042" "" "8a2e" "370" "" ]; - }; + resRem7 = res6.replace (a: removeAttrs a ["a"]); - testComposeExtensions = { - expr = let obj = makeExtensible (self: { foo = self.bar; }); - f = self: super: { bar = false; baz = true; }; - g = self: super: { bar = super.baz or false; }; - f_o_g = composeExtensions f g; - composed = obj.extend f_o_g; - in composed.foo; + resReplace6 = let x = defaultOverridableDelayableArgs id { a = 7; mergeAttrBy = { a = builtins.add; }; }; + x2 = x.merge { a = 20; }; # now we have 27 + in (x2.replace) { a = 10; }; # and override the value by 10 + + # fixed tests (delayed args): (when using them add some comments, please) + resFixed1 = + let x = defaultOverridableDelayableArgs id ( x: { a = 7; c = x.fixed.b; }); + y = x.merge (x: { name = "name-${builtins.toString x.fixed.c}"; }); + in (y.merge) { b = 10; }; + strip = attrs: removeAttrs attrs ["merge" "replace"]; + in all id + [ ((strip res1) == { }) + ((strip res2) == { a = 7; }) + ((strip res3) == { a = 7; b = 10; }) + ((strip res4) == { a = 7; b = 10; }) + ((strip res5) == { a = 10; }) + ((strip res6) == { a = 17; }) + ((strip resRem7) == {}) + ((strip resFixed1) == { a = 7; b = 10; c =10; name = "name-10"; }) + ]; expected = true; }; diff --git a/lib/tests/release.nix b/lib/tests/release.nix index dfa4ca2676d1f..a6184041682f0 100644 --- a/lib/tests/release.nix +++ b/lib/tests/release.nix @@ -1,40 +1,32 @@ -{ nixpkgs ? { outPath = (import ../.).cleanSource ../..; revCount = 1234; shortRev = "abcdef"; } -, # The platforms for which we build Nixpkgs. - supportedSystems ? [ builtins.currentSystem ] -, # Strip most of attributes when evaluating to spare memory usage - scrubJobs ? true -}: +{ pkgs ? import ((import ../.).cleanSource ../..) {} }: -with import ../../pkgs/top-level/release-lib.nix { inherit supportedSystems scrubJobs; }; -with lib; +pkgs.stdenv.mkDerivation { + name = "nixpkgs-lib-tests"; + buildInputs = [ pkgs.nix ]; + NIX_PATH="nixpkgs=${pkgs.path}"; -{ - systems = import ./systems.nix { inherit lib assertTrue; }; + buildCommand = '' + datadir="${pkgs.nix}/share" + export TEST_ROOT=$(pwd)/test-tmp + export NIX_BUILD_HOOK= + export NIX_CONF_DIR=$TEST_ROOT/etc + export NIX_DB_DIR=$TEST_ROOT/db + export NIX_LOCALSTATE_DIR=$TEST_ROOT/var + export NIX_LOG_DIR=$TEST_ROOT/var/log/nix + export NIX_MANIFESTS_DIR=$TEST_ROOT/var/nix/manifests + export NIX_STATE_DIR=$TEST_ROOT/var/nix + export NIX_STORE_DIR=$TEST_ROOT/store + export PAGER=cat + cacheDir=$TEST_ROOT/binary-cache + nix-store --init - moduleSystem = pkgs.stdenv.mkDerivation { - name = "nixpkgs-lib-tests"; - buildInputs = [ pkgs.nix ]; - NIX_PATH="nixpkgs=${nixpkgs}"; + cd ${pkgs.path}/lib/tests + ./modules.sh - buildCommand = '' - datadir="${pkgs.nix}/share" - export TEST_ROOT=$(pwd)/test-tmp - export NIX_BUILD_HOOK= - export NIX_CONF_DIR=$TEST_ROOT/etc - export NIX_DB_DIR=$TEST_ROOT/db - export NIX_LOCALSTATE_DIR=$TEST_ROOT/var - export NIX_LOG_DIR=$TEST_ROOT/var/log/nix - export NIX_MANIFESTS_DIR=$TEST_ROOT/var/nix/manifests - export NIX_STATE_DIR=$TEST_ROOT/var/nix - export NIX_STORE_DIR=$TEST_ROOT/store - export PAGER=cat - cacheDir=$TEST_ROOT/binary-cache - nix-store --init + [[ "$(nix-instantiate --eval --strict misc.nix)" == "[ ]" ]] - cd ${nixpkgs}/lib/tests - ./modules.sh + [[ "$(nix-instantiate --eval --strict systems.nix)" == "[ ]" ]] - touch $out - ''; - }; + touch $out + ''; } diff --git a/lib/tests/systems.nix b/lib/tests/systems.nix index 5eacc0defafb4..523fd3feb3b0c 100644 --- a/lib/tests/systems.nix +++ b/lib/tests/systems.nix @@ -5,13 +5,13 @@ # calculating the lists anyway?". The answer is one can mindlessly update these # tests as new platforms become supported, and then just give the diff a quick # sanity check before committing :). -{ lib, assertTrue }: - -with lib.systems.doubles; - -let mseteq = x: y: lib.sort lib.lessThan x == lib.sort lib.lessThan y; in - -{ +let + lib = import ../default.nix; + mseteq = x: y: { + expr = lib.sort lib.lessThan x; + expected = lib.sort lib.lessThan y; + }; +in with lib.systems.doubles; lib.runTests { all = assertTrue (mseteq all (linux ++ darwin ++ cygwin ++ freebsd ++ openbsd ++ netbsd ++ illumos)); arm = assertTrue (mseteq arm [ "armv5tel-linux" "armv6l-linux" "armv7l-linux" ]); diff --git a/lib/trivial.nix b/lib/trivial.nix index cec28b1a22b11..9ee0549fc0fb1 100644 --- a/lib/trivial.nix +++ b/lib/trivial.nix @@ -43,82 +43,6 @@ rec { */ mergeAttrs = x: y: x // y; - - # Compute the fixed point of the given function `f`, which is usually an - # attribute set that expects its final, non-recursive representation as an - # argument: - # - # f = self: { foo = "foo"; bar = "bar"; foobar = self.foo + self.bar; } - # - # Nix evaluates this recursion until all references to `self` have been - # resolved. At that point, the final result is returned and `f x = x` holds: - # - # nix-repl> fix f - # { bar = "bar"; foo = "foo"; foobar = "foobar"; } - # - # See https://en.wikipedia.org/wiki/Fixed-point_combinator for further - # details. - fix = f: let x = f x; in x; - - # A variant of `fix` that records the original recursive attribute set in the - # result. This is useful in combination with the `extends` function to - # implement deep overriding. See pkgs/development/haskell-modules/default.nix - # for a concrete example. - fix' = f: let x = f x // { __unfix__ = f; }; in x; - - # Modify the contents of an explicitly recursive attribute set in a way that - # honors `self`-references. This is accomplished with a function - # - # g = self: super: { foo = super.foo + " + "; } - # - # that has access to the unmodified input (`super`) as well as the final - # non-recursive representation of the attribute set (`self`). `extends` - # differs from the native `//` operator insofar as that it's applied *before* - # references to `self` are resolved: - # - # nix-repl> fix (extends g f) - # { bar = "bar"; foo = "foo + "; foobar = "foo + bar"; } - # - # The name of the function is inspired by object-oriented inheritance, i.e. - # think of it as an infix operator `g extends f` that mimics the syntax from - # Java. It may seem counter-intuitive to have the "base class" as the second - # argument, but it's nice this way if several uses of `extends` are cascaded. - extends = f: rattrs: self: let super = rattrs self; in super // f self super; - - # Compose two extending functions of the type expected by 'extends' - # into one where changes made in the first are available in the - # 'super' of the second - composeExtensions = - f: g: self: super: - let fApplied = f self super; - super' = super // fApplied; - in fApplied // g self super'; - - # Create an overridable, recursive attribute set. For example: - # - # nix-repl> obj = makeExtensible (self: { }) - # - # nix-repl> obj - # { __unfix__ = «lambda»; extend = «lambda»; } - # - # nix-repl> obj = obj.extend (self: super: { foo = "foo"; }) - # - # nix-repl> obj - # { __unfix__ = «lambda»; extend = «lambda»; foo = "foo"; } - # - # nix-repl> obj = obj.extend (self: super: { foo = super.foo + " + "; bar = "bar"; foobar = self.foo + self.bar; }) - # - # nix-repl> obj - # { __unfix__ = «lambda»; bar = "bar"; extend = «lambda»; foo = "foo + "; foobar = "foo + bar"; } - makeExtensible = makeExtensibleWithCustomName "extend"; - - # Same as `makeExtensible` but the name of the extending attribute is - # customized. - makeExtensibleWithCustomName = extenderName: rattrs: - fix' rattrs // { - ${extenderName} = f: makeExtensibleWithCustomName extenderName (extends f rattrs); - }; - # Flip the order of the arguments of a binary function. flip = f: a: b: f b a; diff --git a/lib/types.nix b/lib/types.nix index 45122759bfcaf..a7dcd3f1e1c77 100644 --- a/lib/types.nix +++ b/lib/types.nix @@ -92,6 +92,8 @@ rec { }; + # When adding new types don't forget to document them in + # nixos/doc/manual/development/option-types.xml! types = rec { unspecified = mkOptionType { @@ -177,9 +179,9 @@ rec { description = "list of ${elemType.description}s"; check = isList; merge = loc: defs: - map (x: x.value) (filter (x: x ? value) (concatLists (imap (n: def: + map (x: x.value) (filter (x: x ? value) (concatLists (imap1 (n: def: if isList def.value then - imap (m: def': + imap1 (m: def': (mergeDefinitions (loc ++ ["[definition ${toString n}-entry ${toString m}]"]) elemType @@ -218,7 +220,7 @@ rec { if isList def.value then { inherit (def) file; value = listToAttrs ( - imap (elemIdx: elem: + imap1 (elemIdx: elem: { name = elem.name or "unnamed-${toString defIdx}.${toString elemIdx}"; value = elem; }) def.value); @@ -231,7 +233,7 @@ rec { name = "loaOf"; description = "list or attribute set of ${elemType.description}s"; check = x: isList x || isAttrs x; - merge = loc: defs: attrOnly.merge loc (imap convertIfList defs); + merge = loc: defs: attrOnly.merge loc (imap1 convertIfList defs); getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["<name?>"]); getSubModules = elemType.getSubModules; substSubModules = m: loaOf (elemType.substSubModules m); @@ -257,6 +259,7 @@ rec { functor = (defaultFunctor name) // { wrapped = elemType; }; }; + # Value of given type but with no merging (i.e. `uniq list`s are not concatenated). uniq = elemType: mkOptionType rec { name = "uniq"; inherit (elemType) description check; @@ -267,6 +270,7 @@ rec { functor = (defaultFunctor name) // { wrapped = elemType; }; }; + # Null or value of ... nullOr = elemType: mkOptionType rec { name = "nullOr"; description = "null or ${elemType.description}"; @@ -283,6 +287,7 @@ rec { functor = (defaultFunctor name) // { wrapped = elemType; }; }; + # A submodule (like typed attribute set). See NixOS manual. submodule = opts: let opts' = toList opts; @@ -314,6 +319,7 @@ rec { }; }; + # A value from a set of allowed ones. enum = values: let show = v: @@ -329,6 +335,7 @@ rec { functor = (defaultFunctor name) // { payload = values; binOp = a: b: unique (a ++ b); }; }; + # Either value of type `t1` or `t2`. either = t1: t2: mkOptionType rec { name = "either"; description = "${t1.description} or ${t2.description}"; @@ -352,6 +359,8 @@ rec { functor = (defaultFunctor name) // { wrapped = [ t1 t2 ]; }; }; + # Either value of type `finalType` or `coercedType`, the latter is + # converted to `finalType` using `coerceFunc`. coercedTo = coercedType: coerceFunc: finalType: assert coercedType.getSubModules == null; mkOptionType rec { |