diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/licenses.nix | 8 | ||||
-rw-r--r-- | lib/lists.nix | 82 | ||||
-rw-r--r-- | lib/maintainers.nix | 8 | ||||
-rw-r--r-- | lib/modules.nix | 14 | ||||
-rw-r--r-- | lib/strings.nix | 19 | ||||
-rw-r--r-- | lib/trivial.nix | 17 |
6 files changed, 132 insertions, 16 deletions
diff --git a/lib/licenses.nix b/lib/licenses.nix index 4071fcfd70d2..3708b1eb15cf 100644 --- a/lib/licenses.nix +++ b/lib/licenses.nix @@ -188,7 +188,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec { fdl13 = spdx { spdxId = "GFDL-1.3"; - fullName = "GNU Free Documentation License v1.2"; + fullName = "GNU Free Documentation License v1.3"; }; free = { @@ -200,6 +200,12 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec { url = https://geant4.web.cern.ch/geant4/license/LICENSE.html; }; + geogebra = { + fullName = "GeoGebra Non-Commercial License Agreement"; + url = https://www.geogebra.org/license; + free = false; + }; + gpl1 = spdx { spdxId = "GPL-1.0"; fullName = "GNU General Public License v1.0 only"; diff --git a/lib/lists.nix b/lib/lists.nix index 6712e5cc93f8..4bf732b88c9a 100644 --- a/lib/lists.nix +++ b/lib/lists.nix @@ -89,7 +89,7 @@ rec { */ flatten = x: if isList x - then foldl' (x: y: x ++ (flatten y)) [] x + then concatMap (y: flatten y) x else [x]; /* Remove elements equal to 'e' from a list. Useful for buildInputs. @@ -256,6 +256,86 @@ rec { reverseList = xs: let l = length xs; in genList (n: elemAt xs (l - n - 1)) l; + /* Depth-First Search (DFS) for lists `list != []`. + + `before a b == true` means that `b` depends on `a` (there's an + edge from `b` to `a`). + + Examples: + + listDfs true hasPrefix [ "/home/user" "other" "/" "/home" ] + == { minimal = "/"; # minimal element + visited = [ "/home/user" ]; # seen elements (in reverse order) + rest = [ "/home" "other" ]; # everything else + } + + listDfs true hasPrefix [ "/home/user" "other" "/" "/home" "/" ] + == { cycle = "/"; # cycle encountered at this element + loops = [ "/" ]; # and continues to these elements + visited = [ "/" "/home/user" ]; # elements leading to the cycle (in reverse order) + rest = [ "/home" "other" ]; # everything else + + */ + + listDfs = stopOnCycles: before: list: + let + dfs' = us: visited: rest: + let + c = filter (x: before x us) visited; + b = partition (x: before x us) rest; + in if stopOnCycles && (length c > 0) + then { cycle = us; loops = c; inherit visited rest; } + else if length b.right == 0 + then # nothing is before us + { minimal = us; inherit visited rest; } + else # grab the first one before us and continue + dfs' (head b.right) + ([ us ] ++ visited) + (tail b.right ++ b.wrong); + in dfs' (head list) [] (tail list); + + /* Sort a list based on a partial ordering using DFS. This + implementation is O(N^2), if your ordering is linear, use `sort` + instead. + + `before a b == true` means that `b` should be after `a` + in the result. + + Examples: + + toposort hasPrefix [ "/home/user" "other" "/" "/home" ] + == { result = [ "/" "/home" "/home/user" "other" ]; } + + toposort hasPrefix [ "/home/user" "other" "/" "/home" "/" ] + == { cycle = [ "/home/user" "/" "/" ]; # path leading to a cycle + loops = [ "/" ]; } # loops back to these elements + + toposort hasPrefix [ "other" "/home/user" "/home" "/" ] + == { result = [ "other" "/" "/home" "/home/user" ]; } + + toposort (a: b: a < b) [ 3 2 1 ] == { result = [ 1 2 3 ]; } + + */ + + toposort = before: list: + let + dfsthis = listDfs true before list; + toporest = toposort before (dfsthis.visited ++ dfsthis.rest); + in + if length list < 2 + then # finish + { result = list; } + else if dfsthis ? "cycle" + then # there's a cycle, starting from the current vertex, return it + { cycle = reverseList ([ dfsthis.cycle ] ++ dfsthis.visited); + inherit (dfsthis) loops; } + else if toporest ? "cycle" + then # there's a cycle somewhere else in the graph, return it + toporest + # Slow, but short. Can be made a bit faster with an explicit stack. + else # there are no cycles + { result = [ dfsthis.minimal ] ++ toporest.result; }; + /* Sort a list based on a comparator function which compares two elements and returns true if the first argument is strictly below the second argument. The returned list is sorted in an increasing diff --git a/lib/maintainers.nix b/lib/maintainers.nix index 7f6c823d68b9..b9fd905dd54d 100644 --- a/lib/maintainers.nix +++ b/lib/maintainers.nix @@ -39,6 +39,7 @@ aristid = "Aristid Breitkreuz <aristidb@gmail.com>"; arobyn = "Alexei Robyn <shados@shados.net>"; artuuge = "Artur E. Ruuge <artuuge@gmail.com>"; + ashalkhakov = "Artyom Shalkhakov <artyom.shalkhakov@gmail.com>"; asppsa = "Alastair Pharo <asppsa@gmail.com>"; astsmtl = "Alexander Tsamutali <astsmtl@yandex.ru>"; aszlig = "aszlig <aszlig@redmoonstudios.org>"; @@ -99,6 +100,7 @@ davidak = "David Kleuker <post@davidak.de>"; davidrusu = "David Rusu <davidrusu.me@gmail.com>"; dbohdan = "Danyil Bohdan <danyil.bohdan@gmail.com>"; + dbrock = "Daniel Brockman <daniel@brockman.se>"; deepfire = "Kosyrev Serge <_deepfire@feelingofgreen.ru>"; demin-dmitriy = "Dmitriy Demin <demindf@gmail.com>"; DerGuteMoritz = "Moritz Heidkamp <moritz@twoticketsplease.de>"; @@ -127,7 +129,7 @@ ericbmerritt = "Eric Merritt <eric@afiniate.com>"; ericsagnes = "Eric Sagnes <eric.sagnes@gmail.com>"; erikryb = "Erik Rybakken <erik.rybakken@math.ntnu.no>"; - ertes = "Ertugrul Söylemez <ertesx@gmx.de>"; + ertes = "Ertugrul Söylemez <esz@posteo.de>"; exi = "Reno Reckling <nixos@reckling.org>"; exlevan = "Alexey Levan <exlevan@gmail.com>"; expipiplus1 = "Joe Hermaszewski <nix@monoid.al>"; @@ -240,14 +242,16 @@ mathnerd314 = "Mathnerd314 <mathnerd314.gph+hs@gmail.com>"; matthiasbeyer = "Matthias Beyer <mail@beyermatthias.de>"; maurer = "Matthew Maurer <matthew.r.maurer+nix@gmail.com>"; - mbakke = "Marius Bakke <ymse@tuta.io>"; + mbakke = "Marius Bakke <mbakke@fastmail.com>"; matthewbauer = "Matthew Bauer <mjbauer95@gmail.com>"; mbe = "Brandon Edens <brandonedens@gmail.com>"; mboes = "Mathieu Boespflug <mboes@tweag.net>"; mcmtroffaes = "Matthias C. M. Troffaes <matthias.troffaes@gmail.com>"; meditans = "Carlo Nucera <meditans@gmail.com>"; meisternu = "Matt Miemiec <meister@krutt.org>"; + mic92 = "Jörg Thalheim <joerg@higgsboson.tk>"; michaelpj = "Michael Peyton Jones <michaelpj@gmail.com>"; + michalrus = "Michal Rus <m@michalrus.com>"; michelk = "Michel Kuhlmann <michel@kuhlmanns.info>"; mimadrid = "Miguel Madrid <mimadrid@ucm.es>"; mingchuan = "Ming Chuan <ming@culpring.com>"; diff --git a/lib/modules.nix b/lib/modules.nix index 2b0d03ef6e81..6f08a49399ab 100644 --- a/lib/modules.nix +++ b/lib/modules.nix @@ -507,19 +507,25 @@ rec { /* Return a module that causes a warning to be shown if the specified option is defined. For example, - mkRemovedOptionModule [ "boot" "loader" "grub" "bootDevice" ] + mkRemovedOptionModule [ "boot" "loader" "grub" "bootDevice" ] "<replacement instructions>" causes a warning if the user defines boot.loader.grub.bootDevice. + + replacementInstructions is a string that provides instructions on + how to achieve the same functionality without the removed option, + or alternatively a reasoning why the functionality is not needed. + replacementInstructions SHOULD be provided! */ - mkRemovedOptionModule = optionName: + mkRemovedOptionModule = optionName: replacementInstructions: { options, ... }: { options = setAttrByPath optionName (mkOption { visible = false; }); config.warnings = let opt = getAttrFromPath optionName options; in - optional opt.isDefined - "The option definition `${showOption optionName}' in ${showFiles opt.files} no longer has any effect; please remove it."; + optional opt.isDefined '' + The option definition `${showOption optionName}' in ${showFiles opt.files} no longer has any effect; please remove it. + ${replacementInstructions}''; }; /* Return a module that causes a warning to be shown if the diff --git a/lib/strings.nix b/lib/strings.nix index daf845839343..86af4d438344 100644 --- a/lib/strings.nix +++ b/lib/strings.nix @@ -156,12 +156,12 @@ rec { hasSuffix "foo" "barfoo" => true */ - hasSuffix = suff: str: + hasSuffix = suffix: content: let - lenStr = stringLength str; - lenSuff = stringLength suff; - in lenStr >= lenSuff && - substring (lenStr - lenSuff) lenStr str == suff; + lenContent = stringLength content; + lenSuffix = stringLength suffix; + in lenContent >= lenSuffix && + substring (lenContent - lenSuffix) lenContent content == suffix; /* Convert a string to a list of characters (i.e. singleton strings). This allows you to, e.g., map a function over each character. However, @@ -248,7 +248,7 @@ rec { /* Converts an ASCII string to upper-case. Example: - toLower "home" + toUpper "home" => "HOME" */ toUpper = replaceChars lowerChars upperChars; @@ -372,7 +372,12 @@ rec { getVersion pkgs.youtube-dl => "2016.01.01" */ - getVersion = x: (builtins.parseDrvName (x.name or x)).version; + getVersion = x: + let + parse = drv: (builtins.parseDrvName drv).version; + in if isString x + then parse x + else x.version or (parse x.name); /* Extract name with version from URL. Ask for separator which is supposed to start extension. diff --git a/lib/trivial.nix b/lib/trivial.nix index f85c74ab88e3..25ce35570fdf 100644 --- a/lib/trivial.nix +++ b/lib/trivial.nix @@ -71,7 +71,7 @@ rec { + (if pathExists suffixFile then fileContents suffixFile else "pre-git"); # Whether we're being called by nix-shell. - inNixShell = builtins.getEnv "IN_NIX_SHELL" == "1"; + inNixShell = builtins.getEnv "IN_NIX_SHELL" != ""; # Return minimum/maximum of two numbers. min = x: y: if x < y then x else y; @@ -98,4 +98,19 @@ rec { */ importJSON = path: builtins.fromJSON (builtins.readFile path); + + /* See https://github.com/NixOS/nix/issues/749. Eventually we'd like these + to expand to Nix builtins that carry metadata so that Nix can filter out + the INFO messages without parsing the message string. + + Usage: + { + foo = lib.warn "foo is deprecated" oldFoo; + } + + TODO: figure out a clever way to integrate location information from + something like __unsafeGetAttrPos. + */ + warn = msg: builtins.trace "WARNING: ${msg}"; + info = msg: builtins.trace "INFO: ${msg}"; } |