Something went wrong. Try again.
What happens if I push all of nixpkgs
Something went wrong. Try again.
Nix
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499/** Functions for querying information about the filesystem without copying any files to the Nix store.*/{ lib }:
# Tested in lib/tests/filesystem.shlet inherit (builtins) readDir pathExists toString ;
inherit (lib.filesystem) pathIsDirectory pathIsRegularFile pathType packagesFromDirectoryRecursive ;
inherit (lib.strings) hasSuffix ;in
{
/** The type of a path. The path needs to exist and be accessible. The result is either "directory" for a directory, "regular" for a regular file, "symlink" for a symlink, or "unknown" for anything else.
# Inputs
path
: The path to query
# Type
``` pathType :: Path -> String ```
# Examples :::{.example} ## `lib.filesystem.pathType` usage example
```nix pathType /. => "directory"
pathType /some/file.nix => "regular" ```
::: */ pathType = builtins.readFileType or # Nix <2.14 compatibility shim ( path: if !pathExists path # Fail irrecoverably to mimic the historic behavior of this function and # the new builtins.readFileType then abort "lib.filesystem.pathType: Path ${toString path} does not exist." # The filesystem root is the only path where `dirOf / == /` and # `baseNameOf /` is not valid. We can detect this and directly return # "directory", since we know the filesystem root can't be anything else. else if dirOf path == path then "directory" else (readDir (dirOf path)).${baseNameOf path} );
/** Whether a path exists and is a directory.
# Inputs
`path`
: 1\. Function argument
# Type
``` pathIsDirectory :: Path -> Bool ```
# Examples :::{.example} ## `lib.filesystem.pathIsDirectory` usage example
```nix pathIsDirectory /. => true
pathIsDirectory /this/does/not/exist => false
pathIsDirectory /some/file.nix => false ```
::: */ pathIsDirectory = path: pathExists path && pathType path == "directory";
/** Whether a path exists and is a regular file, meaning not a symlink or any other special file type.
# Inputs
`path`
: 1\. Function argument
# Type
``` pathIsRegularFile :: Path -> Bool ```
# Examples :::{.example} ## `lib.filesystem.pathIsRegularFile` usage example
```nix pathIsRegularFile /. => false
pathIsRegularFile /this/does/not/exist => false
pathIsRegularFile /some/file.nix => true ```
::: */ pathIsRegularFile = path: pathExists path && pathType path == "regular";
/** 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.
# Inputs
`root`
: The directory within to search
# Type
``` Path -> Map String Path ``` */ 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; /** Find the first directory containing a file matching 'pattern' upward from a given 'file'. Returns 'null' if no directories contain a file matching 'pattern'.
# Inputs
`pattern`
: The pattern to search for
`file`
: The file to start searching upward from
# Type
``` RegExp -> Path -> Nullable { path : Path; matches : [ MatchResults ]; } ``` */ locateDominatingFile = pattern: file: let go = path: let files = builtins.attrNames (builtins.readDir path); matches = builtins.filter (match: match != null) (map (builtins.match pattern) files); in if builtins.length matches != 0 then { inherit path matches; } else if path == /. then null else go (dirOf path); parent = dirOf file; isDir = let base = baseNameOf file; type = (builtins.readDir parent).${base} or null; in file == /. || type == "directory"; in go (if isDir then file else parent);
/** Given a directory, return a flattened list of all files within it recursively.
# Inputs
`dir`
: The path to recursively list
# Type
``` Path -> [ Path ] ``` */ listFilesRecursive = dir: lib.flatten ( lib.mapAttrsToList ( name: type: if type == "directory" then lib.filesystem.listFilesRecursive (dir + "/${name}") else dir + "/${name}" ) (builtins.readDir dir) );
/** Transform a directory tree containing package files suitable for `callPackage` into a matching nested attribute set of derivations.
For a directory tree like this:
``` my-packages ├── a.nix ├── b.nix ├── c │ ├── my-extra-feature.patch │ ├── package.nix │ └── support-definitions.nix └── my-namespace ├── d.nix ├── e.nix └── f └── package.nix ```
`packagesFromDirectoryRecursive` will produce an attribute set like this:
```nix # packagesFromDirectoryRecursive { # callPackage = pkgs.callPackage; # directory = ./my-packages; # } { a = pkgs.callPackage ./my-packages/a.nix { }; b = pkgs.callPackage ./my-packages/b.nix { }; c = pkgs.callPackage ./my-packages/c/package.nix { }; my-namespace = { d = pkgs.callPackage ./my-packages/my-namespace/d.nix { }; e = pkgs.callPackage ./my-packages/my-namespace/e.nix { }; f = pkgs.callPackage ./my-packages/my-namespace/f/package.nix { }; }; } ```
In particular: - If the input directory contains a `package.nix` file, then `callPackage <directory>/package.nix { }` is returned. - Otherwise, the input directory's contents are listed and transformed into an attribute set. - If a regular file's name has the `.nix` extension, it is turned into attribute where: - The attribute name is the file name without the `.nix` extension - The attribute value is `callPackage <file path> { }` - Directories are turned into an attribute where: - The attribute name is the name of the directory - The attribute value is the result of calling `packagesFromDirectoryRecursive { ... }` on the directory.
As a result, directories with no `.nix` files (including empty directories) will be transformed into empty attribute sets. - Other files are ignored, including symbolic links to directories and to regular `.nix` files; this is because nixlang code cannot distinguish the type of a link's target.
# Type
``` packagesFromDirectoryRecursive :: { callPackage :: Path -> {} -> a, newScope? :: AttrSet -> scope, directory :: Path, } -> AttrSet ```
# Inputs
`callPackage` : The function used to convert a Nix file's path into a leaf of the attribute set. It is typically the `callPackage` function, taken from either `pkgs` or a new scope corresponding to the `directory`.
`newScope` : If present, this function is used when recursing into a directory, to generate a new scope. The arguments are updated with the scope's `callPackage` and `newScope` functions, so packages can require anything in their scope, or in an ancestor of their scope.
`directory` : The directory to read package files from.
# Examples :::{.example} ## Basic use of `lib.packagesFromDirectoryRecursive`
```nix packagesFromDirectoryRecursive { inherit (pkgs) callPackage; directory = ./my-packages; } => { ... } ```
In this case, `callPackage` will only search `pkgs` for a file's input parameters. In other words, a file cannot refer to another file in the directory in its input parameters. :::
::::{.example} ## Create a scope for the nix files found in a directory ```nix packagesFromDirectoryRecursive { inherit (pkgs) callPackage newScope; directory = ./my-packages; } => { ... } ```
For example, take the following directory structure: ``` my-packages ├── a.nix → { b }: assert b ? b1; ... └── b ├── b1.nix → { a }: ... └── b2.nix ```
Here, `b1.nix` can specify `{ a }` as a parameter, which `callPackage` will resolve as expected. Likewise, `a.nix` receive an attrset corresponding to the contents of the `b` directory.
:::{.note} `a.nix` cannot directly take as inputs packages defined in a child directory, such as `b1`. ::: :::: */ packagesFromDirectoryRecursive = let inherit (lib) concatMapAttrs id makeScope recurseIntoAttrs removeSuffix ;
# Generate an attrset corresponding to a given directory. # This function is outside `packagesFromDirectoryRecursive`'s lambda expression, # to prevent accidentally using its parameters. processDir = { callPackage, directory, ... }@args: concatMapAttrs ( name: type: # for each directory entry let path = directory + "/${name}"; in if type == "directory" then { # recurse into directories "${name}" = packagesFromDirectoryRecursive ( args // { directory = path; } ); } else if type == "regular" && hasSuffix ".nix" name then { # call .nix files "${removeSuffix ".nix" name}" = callPackage path { }; } else if type == "regular" then { # ignore non-nix files } else throw '' lib.filesystem.packagesFromDirectoryRecursive: Unsupported file type ${type} at path ${toString path} '' ) (builtins.readDir directory); in { callPackage, newScope ? throw "lib.packagesFromDirectoryRecursive: newScope wasn't passed in args", directory, }@args: let defaultPath = directory + "/package.nix"; in if pathExists defaultPath then # if `${directory}/package.nix` exists, call it directly callPackage defaultPath { } else if args ? newScope then # Create a new scope and mark it `recurseForDerivations`. # This lets the packages refer to each other. # See: # [lib.makeScope](https://nixos.org/manual/nixpkgs/unstable/#function-library-lib.customisation.makeScope) and # [lib.recurseIntoAttrs](https://nixos.org/manual/nixpkgs/unstable/#function-library-lib.customisation.makeScope) recurseIntoAttrs ( makeScope newScope ( self: # generate the attrset representing the directory, using the new scope's `callPackage` and `newScope` processDir ( args // { inherit (self) callPackage newScope; } ) ) ) else processDir args;
/** Append `/default.nix` if the passed path is a directory.
# Type
``` resolveDefaultNix :: (Path | String) -> (Path | String) ```
# Inputs
A single argument which can be a [path](https://nix.dev/manual/nix/stable/language/types#type-path) value or a string containing an absolute path.
# Output
If the input refers to a directory that exists, the output is that same path with `/default.nix` appended. Furthermore, if the input is a string that ends with `/`, `default.nix` is appended to it. Otherwise, the input is returned unchanged.
# Examples :::{.example} ## `lib.filesystem.resolveDefaultNix` usage example
This expression checks whether `a` and `b` refer to the same locally available Nix file path.
```nix resolveDefaultNix a == resolveDefaultNix b ```
For instance, if `a` is `/some/dir` and `b` is `/some/dir/default.nix`, and `/some/dir/` exists, the expression evaluates to `true`, despite `a` and `b` being different references to the same Nix file. */ resolveDefaultNix = v: if pathIsDirectory v then v + "/default.nix" else if lib.isString v && hasSuffix "/" v then # A path ending in `/` can only refer to a directory, so we take the hint, even if we can't verify the validity of the path's `/` assertion. # A `/` is already present, so we don't add another one. v + "default.nix" else v;}