|
59 | 59 | pathType = |
60 | 60 | builtins.readFileType or |
61 | 61 | # Nix <2.14 compatibility shim |
62 | | - (path: |
63 | | - if ! pathExists path |
| 62 | + ( |
| 63 | + path: |
| 64 | + if |
| 65 | + !pathExists path |
64 | 66 | # Fail irrecoverably to mimic the historic behavior of this function and |
65 | 67 | # the new builtins.readFileType |
66 | | - then abort "lib.filesystem.pathType: Path ${toString path} does not exist." |
| 68 | + then |
| 69 | + abort "lib.filesystem.pathType: Path ${toString path} does not exist." |
67 | 70 | # The filesystem root is the only path where `dirOf / == /` and |
68 | 71 | # `baseNameOf /` is not valid. We can detect this and directly return |
69 | 72 | # "directory", since we know the filesystem root can't be anything else. |
70 | | - else if dirOf path == path |
71 | | - then "directory" |
72 | | - else (readDir (dirOf path)).${baseNameOf path} |
| 73 | + else if dirOf path == path then |
| 74 | + "directory" |
| 75 | + else |
| 76 | + (readDir (dirOf path)).${baseNameOf path} |
73 | 77 | ); |
74 | 78 |
|
75 | 79 | /** |
76 | 80 | Whether a path exists and is a directory. |
77 | 81 |
|
78 | | -
|
79 | 82 | # Inputs |
80 | 83 |
|
81 | 84 | `path` |
|
105 | 108 |
|
106 | 109 | ::: |
107 | 110 | */ |
108 | | - pathIsDirectory = path: |
109 | | - pathExists path && pathType path == "directory"; |
| 111 | + pathIsDirectory = path: pathExists path && pathType path == "directory"; |
110 | 112 |
|
111 | 113 | /** |
112 | 114 | Whether a path exists and is a regular file, meaning not a symlink or any other special file type. |
113 | 115 |
|
114 | | -
|
115 | 116 | # Inputs |
116 | 117 |
|
117 | 118 | `path` |
|
141 | 142 |
|
142 | 143 | ::: |
143 | 144 | */ |
144 | | - pathIsRegularFile = path: |
145 | | - pathExists path && pathType path == "regular"; |
| 145 | + pathIsRegularFile = path: pathExists path && pathType path == "regular"; |
146 | 146 |
|
147 | 147 | /** |
148 | 148 | A map of all haskell packages defined in the given path, |
149 | 149 | identified by having a cabal file with the same name as the |
150 | 150 | directory itself. |
151 | 151 |
|
152 | | -
|
153 | 152 | # Inputs |
154 | 153 |
|
155 | 154 | `root` |
|
164 | 163 | */ |
165 | 164 | haskellPathsInDir = |
166 | 165 | root: |
167 | | - let # Files in the root |
168 | | - root-files = builtins.attrNames (builtins.readDir root); |
169 | | - # Files with their full paths |
170 | | - root-files-with-paths = |
171 | | - map (file: |
172 | | - { name = file; value = root + "/${file}"; } |
173 | | - ) root-files; |
174 | | - # Subdirectories of the root with a cabal file. |
175 | | - cabal-subdirs = |
176 | | - builtins.filter ({ name, value }: |
177 | | - builtins.pathExists (value + "/${name}.cabal") |
178 | | - ) root-files-with-paths; |
179 | | - in builtins.listToAttrs cabal-subdirs; |
| 166 | + let |
| 167 | + # Files in the root |
| 168 | + root-files = builtins.attrNames (builtins.readDir root); |
| 169 | + # Files with their full paths |
| 170 | + root-files-with-paths = map (file: { |
| 171 | + name = file; |
| 172 | + value = root + "/${file}"; |
| 173 | + }) root-files; |
| 174 | + # Subdirectories of the root with a cabal file. |
| 175 | + cabal-subdirs = builtins.filter ( |
| 176 | + { name, value }: builtins.pathExists (value + "/${name}.cabal") |
| 177 | + ) root-files-with-paths; |
| 178 | + in |
| 179 | + builtins.listToAttrs cabal-subdirs; |
180 | 180 | /** |
181 | 181 | Find the first directory containing a file matching 'pattern' |
182 | 182 | upward from a given 'file'. |
183 | 183 | Returns 'null' if no directories contain a file matching 'pattern'. |
184 | 184 |
|
185 | | -
|
186 | 185 | # Inputs |
187 | 186 |
|
188 | 187 | `pattern` |
|
200 | 199 | ``` |
201 | 200 | */ |
202 | 201 | locateDominatingFile = |
203 | | - pattern: |
204 | | - file: |
205 | | - let go = path: |
206 | | - let files = builtins.attrNames (builtins.readDir path); |
207 | | - matches = builtins.filter (match: match != null) |
208 | | - (map (builtins.match pattern) files); |
209 | | - in |
210 | | - if builtins.length matches != 0 |
211 | | - then { inherit path matches; } |
212 | | - else if path == /. |
213 | | - then null |
214 | | - else go (dirOf path); |
215 | | - parent = dirOf file; |
216 | | - isDir = |
217 | | - let base = baseNameOf file; |
218 | | - type = (builtins.readDir parent).${base} or null; |
219 | | - in file == /. || type == "directory"; |
220 | | - in go (if isDir then file else parent); |
221 | | - |
| 202 | + pattern: file: |
| 203 | + let |
| 204 | + go = |
| 205 | + path: |
| 206 | + let |
| 207 | + files = builtins.attrNames (builtins.readDir path); |
| 208 | + matches = builtins.filter (match: match != null) (map (builtins.match pattern) files); |
| 209 | + in |
| 210 | + if builtins.length matches != 0 then |
| 211 | + { inherit path matches; } |
| 212 | + else if path == /. then |
| 213 | + null |
| 214 | + else |
| 215 | + go (dirOf path); |
| 216 | + parent = dirOf file; |
| 217 | + isDir = |
| 218 | + let |
| 219 | + base = baseNameOf file; |
| 220 | + type = (builtins.readDir parent).${base} or null; |
| 221 | + in |
| 222 | + file == /. || type == "directory"; |
| 223 | + in |
| 224 | + go (if isDir then file else parent); |
222 | 225 |
|
223 | 226 | /** |
224 | 227 | Given a directory, return a flattened list of all files within it recursively. |
225 | 228 |
|
226 | | -
|
227 | 229 | # Inputs |
228 | 230 |
|
229 | 231 | `dir` |
|
238 | 240 | */ |
239 | 241 | listFilesRecursive = |
240 | 242 | dir: |
241 | | - lib.flatten (lib.mapAttrsToList (name: type: |
242 | | - if type == "directory" then |
243 | | - lib.filesystem.listFilesRecursive (dir + "/${name}") |
244 | | - else |
245 | | - dir + "/${name}" |
246 | | - ) (builtins.readDir dir)); |
| 243 | + lib.flatten ( |
| 244 | + lib.mapAttrsToList ( |
| 245 | + name: type: |
| 246 | + if type == "directory" then |
| 247 | + lib.filesystem.listFilesRecursive (dir + "/${name}") |
| 248 | + else |
| 249 | + dir + "/${name}" |
| 250 | + ) (builtins.readDir dir) |
| 251 | + ); |
247 | 252 |
|
248 | 253 | /** |
249 | 254 | Transform a directory tree containing package files suitable for |
|
373 | 378 | */ |
374 | 379 | packagesFromDirectoryRecursive = |
375 | 380 | let |
376 | | - inherit (lib) concatMapAttrs id makeScope recurseIntoAttrs removeSuffix; |
| 381 | + inherit (lib) |
| 382 | + concatMapAttrs |
| 383 | + id |
| 384 | + makeScope |
| 385 | + recurseIntoAttrs |
| 386 | + removeSuffix |
| 387 | + ; |
377 | 388 | inherit (lib.path) append; |
378 | 389 |
|
379 | 390 | # Generate an attrset corresponding to a given directory. |
380 | 391 | # This function is outside `packagesFromDirectoryRecursive`'s lambda expression, |
381 | 392 | # to prevent accidentally using its parameters. |
382 | | - processDir = { callPackage, directory, ... }@args: |
383 | | - concatMapAttrs (name: type: |
| 393 | + processDir = |
| 394 | + { callPackage, directory, ... }@args: |
| 395 | + concatMapAttrs ( |
| 396 | + name: type: |
384 | 397 | # for each directory entry |
385 | | - let path = append directory name; in |
386 | | - if type == "directory" then { |
387 | | - # recurse into directories |
388 | | - "${name}" = packagesFromDirectoryRecursive (args // { |
389 | | - directory = path; |
390 | | - }); |
391 | | - } else if type == "regular" && hasSuffix ".nix" name then { |
392 | | - # call .nix files |
393 | | - "${removeSuffix ".nix" name}" = callPackage path {}; |
394 | | - } else if type == "regular" then { |
395 | | - # ignore non-nix files |
396 | | - } else throw '' |
397 | | - lib.filesystem.packagesFromDirectoryRecursive: Unsupported file type ${type} at path ${toString path} |
398 | | - '' |
| 398 | + let |
| 399 | + path = append directory name; |
| 400 | + in |
| 401 | + if type == "directory" then |
| 402 | + { |
| 403 | + # recurse into directories |
| 404 | + "${name}" = packagesFromDirectoryRecursive ( |
| 405 | + args |
| 406 | + // { |
| 407 | + directory = path; |
| 408 | + } |
| 409 | + ); |
| 410 | + } |
| 411 | + else if type == "regular" && hasSuffix ".nix" name then |
| 412 | + { |
| 413 | + # call .nix files |
| 414 | + "${removeSuffix ".nix" name}" = callPackage path { }; |
| 415 | + } |
| 416 | + else if type == "regular" then |
| 417 | + { |
| 418 | + # ignore non-nix files |
| 419 | + } |
| 420 | + else |
| 421 | + throw '' |
| 422 | + lib.filesystem.packagesFromDirectoryRecursive: Unsupported file type ${type} at path ${toString path} |
| 423 | + '' |
399 | 424 | ) (builtins.readDir directory); |
400 | 425 | in |
401 | 426 | { |
|
408 | 433 | in |
409 | 434 | if pathExists defaultPath then |
410 | 435 | # if `${directory}/package.nix` exists, call it directly |
411 | | - callPackage defaultPath {} |
| 436 | + callPackage defaultPath { } |
412 | 437 | else if args ? newScope then |
413 | 438 | # Create a new scope and mark it `recurseForDerivations`. |
414 | 439 | # This lets the packages refer to each other. |
415 | 440 | # See: |
416 | 441 | # [lib.makeScope](https://nixos.org/manual/nixpkgs/unstable/#function-library-lib.customisation.makeScope) and |
417 | 442 | # [lib.recurseIntoAttrs](https://nixos.org/manual/nixpkgs/unstable/#function-library-lib.customisation.makeScope) |
418 | | - recurseIntoAttrs (makeScope newScope (self: |
419 | | - # generate the attrset representing the directory, using the new scope's `callPackage` and `newScope` |
420 | | - processDir (args // { |
421 | | - inherit (self) callPackage newScope; |
422 | | - }) |
423 | | - )) |
| 443 | + recurseIntoAttrs ( |
| 444 | + makeScope newScope ( |
| 445 | + self: |
| 446 | + # generate the attrset representing the directory, using the new scope's `callPackage` and `newScope` |
| 447 | + processDir ( |
| 448 | + args |
| 449 | + // { |
| 450 | + inherit (self) callPackage newScope; |
| 451 | + } |
| 452 | + ) |
| 453 | + ) |
| 454 | + ) |
424 | 455 | else |
425 | | - processDir args |
426 | | - ; |
| 456 | + processDir args; |
427 | 457 | } |
0 commit comments