This commit is contained in:
zimbatm 2021-04-23 14:16:23 +02:00
commit e404d1fd74
No known key found for this signature in database
GPG Key ID: 71BAF6D40C1D63D7
3 changed files with 117 additions and 0 deletions

47
README.md Normal file
View File

@ -0,0 +1,47 @@
# nix-filter - a small self-container source filtering lib
**STATUS: unstable**
A cool way to include only what you need.
When using nix within a project, developers often use `src = ./.;` for a
project like this:
```nix
{ stdenv }:
stdenv.mkDerivation {
name = "my-project";
src = ./.;
}
```
This works but has an issue; on each build, nix will copy the whole project
source code into the /nix/store. Including the `.git` folder and any temporary
files left over by the editor.
The main workaround is to use either `builtins.fetchGit ./.` or one of the
many gitignore filter projects but this is not precise enough. If the
project README changes, it should rebuild the project. If the nix code
changes, it shouldn't rebuild the project. That's why this project exists. I
want total control.
## Example usage
```nix
{ stdenv, nix-filter }:
stdenv.mkDerivation {
name = "my-project";
src = nix-filter {
src = ./.;
allow = [
"src" # strings are automatically converted to ./src filter
./package.json # paths are automatically converted to path filters
(nix-filter.byExt "js") # create your own filters like that
];
# TODO: doesn't work yet
deny = [
];
};
}
```

63
default.nix Normal file
View File

@ -0,0 +1,63 @@
# This is a pure and self-contained library
let
hasSuffix =
# Suffix to check for
suffix:
# Input string
content:
let
lenContent = builtins.length content;
lenSuffix = builtins.length suffix;
in
lenContent >= lenSuffix &&
builtins.substring (lenContent - lenSuffix) lenContent content == suffix;
in
rec {
# Default to filter when calling this lib.
__functor = self: filter;
# A proper source filter
filter =
{
# Base path to include
path
, # Derivation name
name ? "source"
, # Only allow the following path matches.
#
# Allows all files by default.
allow ? [ (_:_: true) ]
, # Ignore the following matches
deny ? [ ]
}:
let
# If an argument to allow or deny is a path, transform it to a matcher.
#
# This probably needs more work, I don't think that it works on
# sub-folders.
toMatcher = f:
let
path_ = toString f;
path__ = "${toString path}/${f}";
in
if builtins.isFunction f then f
else if builtins.isPath f then (path: type: path_ == toString path)
else if builtins.isString f then (path: type: path__ == toString path)
else
throw "Unsupported type ${builtins.typeOf f}";
allow_ = map toMatcher allow;
deny_ = map toMatcher deny;
in
builtins.path {
inherit name path;
filter = path: type:
(builtins.any (f: f path type) allow_) &&
(!builtins.any (f: f path type) deny_);
};
# Match paths with the given extension
byExt = ext:
path: type:
(hasSuffix ".${ext} " path);
}

7
flake.nix Normal file
View File

@ -0,0 +1,7 @@
{
description = "nix-filter";
outputs = { self }: {
lib = import ./default.nix;
};
}