From e404d1fd7491da82c619ed82535c1e378d98bf40 Mon Sep 17 00:00:00 2001 From: zimbatm Date: Fri, 23 Apr 2021 14:16:23 +0200 Subject: [PATCH] hi! --- README.md | 47 +++++++++++++++++++++++++++++++++++++++ default.nix | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++ flake.nix | 7 ++++++ 3 files changed, 117 insertions(+) create mode 100644 README.md create mode 100644 default.nix create mode 100644 flake.nix diff --git a/README.md b/README.md new file mode 100644 index 0000000..5737f47 --- /dev/null +++ b/README.md @@ -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 = [ + ]; + }; +} +``` diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..c36aec3 --- /dev/null +++ b/default.nix @@ -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); +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..f844241 --- /dev/null +++ b/flake.nix @@ -0,0 +1,7 @@ +{ + description = "nix-filter"; + + outputs = { self }: { + lib = import ./default.nix; + }; +}