nixpkgs mirror (for testing) github.com/NixOS/nixpkgs
nix
at python-updates 210 lines 4.8 kB view raw
1{ lib }: 2 3let 4 inherit (lib) 5 all 6 concatStringsSep 7 findFirst 8 flip 9 getAttr 10 head 11 isFunction 12 length 13 recursiveUpdate 14 splitVersion 15 tail 16 take 17 versionAtLeast 18 versionOlder 19 zipListsWith 20 ; 21in 22rec { 23 24 versions = 25 let 26 truncate = n: v: concatStringsSep "." (take n (splitVersion v)); 27 opTruncate = 28 op: v0: v: 29 let 30 n = length (splitVersion v0); 31 in 32 op (truncate n v) (truncate n v0); 33 in 34 rec { 35 36 /* 37 Get string of the first n parts of a version string. 38 39 Example: 40 - truncate 2 "1.2.3-stuff" 41 => "1.2" 42 43 - truncate 4 "1.2.3-stuff" 44 => "1.2.3.stuff" 45 */ 46 47 inherit truncate; 48 49 /* 50 Get string of the first three parts (major, minor and patch) 51 of a version string. 52 53 Example: 54 majorMinorPatch "1.2.3-stuff" 55 => "1.2.3" 56 */ 57 majorMinorPatch = truncate 3; 58 59 /* 60 Version comparison predicates, 61 - isGe v0 v <-> v is greater or equal than v0 [*] 62 - isLe v0 v <-> v is lesser or equal than v0 [*] 63 - isGt v0 v <-> v is strictly greater than v0 [*] 64 - isLt v0 v <-> v is strictly lesser than v0 [*] 65 - isEq v0 v <-> v is equal to v0 [*] 66 - range low high v <-> v is between low and high [**] 67 68 [*] truncating v to the same number of digits as v0 69 [**] truncating v to low for the lower bound and high for the upper bound 70 71 Examples: 72 - isGe "8.10" "8.10.1" 73 => true 74 - isLe "8.10" "8.10.1" 75 => true 76 - isGt "8.10" "8.10.1" 77 => false 78 - isGt "8.10.0" "8.10.1" 79 => true 80 - isEq "8.10" "8.10.1" 81 => true 82 - range "8.10" "8.11" "8.11.1" 83 => true 84 - range "8.10" "8.11+" "8.11.0" 85 => false 86 - range "8.10" "8.11+" "8.11+beta1" 87 => false 88 */ 89 isGe = opTruncate versionAtLeast; 90 isGt = opTruncate (flip versionOlder); 91 isLe = opTruncate (flip versionAtLeast); 92 isLt = opTruncate versionOlder; 93 isEq = opTruncate pred.equal; 94 range = low: high: pred.inter (versions.isGe low) (versions.isLe high); 95 }; 96 97 /* 98 Returns a list of list, splitting it using a predicate. 99 This is analogous to builtins.split sep list, 100 with a predicate as a separator and a list instead of a string. 101 102 Type: splitList :: (a -> bool) -> [a] -> [[a]] 103 104 Example: 105 splitList (x: x == "x") [ "y" "x" "z" "t" ] 106 => [ [ "y" ] "x" [ "z" "t" ] ] 107 */ 108 splitList = 109 pred: l: # put in file lists 110 let 111 loop = ( 112 vv: v: l: 113 if l == [ ] then 114 vv ++ [ v ] 115 else 116 let 117 hd = head l; 118 tl = tail l; 119 in 120 if pred hd then 121 loop ( 122 vv 123 ++ [ 124 v 125 hd 126 ] 127 ) [ ] tl 128 else 129 loop vv (v ++ [ hd ]) tl 130 ); 131 in 132 loop [ ] [ ] l; 133 134 pred = { 135 # Predicate intersection, union, and complement 136 inter = 137 p: q: x: 138 p x && q x; 139 union = 140 p: q: x: 141 p x || q x; 142 compl = p: x: !p x; 143 true = p: true; 144 false = p: false; 145 146 # predicate "being equal to y" 147 equal = y: x: x == y; 148 }; 149 150 /* 151 Emulate a "switch - case" construct, 152 instead of relying on `if then else if ...` 153 */ 154 /* 155 Usage: 156 ```nix 157 switch-if [ 158 if-clause-1 159 .. 160 if-clause-k 161 ] default-out 162 ``` 163 where a if-clause has the form `{ cond = b; out = r; }` 164 the first branch such as `b` is true 165 */ 166 167 switch-if = c: d: (findFirst (getAttr "cond") { } c).out or d; 168 169 /* 170 Usage: 171 ```nix 172 switch x [ 173 simple-clause-1 174 .. 175 simple-clause-k 176 ] default-out 177 ``` 178 where a simple-clause has the form `{ case = p; out = r; }` 179 the first branch such as `p x` is true 180 or 181 ```nix 182 switch [ x1 .. xn ] [ 183 complex-clause-1 184 .. 185 complex-clause-k 186 ] default-out 187 ``` 188 where a complex-clause is either a simple-clause 189 or has the form { cases = [ p1 .. pn ]; out = r; } 190 in which case the first branch such as all `pi x` are true 191 192 if the variables p are not functions, 193 they are converted to a equal p 194 if out is missing the default-out is taken 195 */ 196 197 switch = 198 var: clauses: default: 199 with pred; 200 let 201 compare = f: if isFunction f then f else equal f; 202 combine = 203 cl: var: 204 if cl ? case then compare cl.case var else all (equal true) (zipListsWith compare cl.cases var); 205 in 206 switch-if (map (cl: { 207 cond = combine cl var; 208 inherit (cl) out; 209 }) clauses) default; 210}