about summary refs log tree commit diff
path: root/lib
diff options
context:
space:
mode:
authorSilvan Mosberger <contact@infinisil.com>2023-11-24 00:15:43 +0100
committerGitHub <noreply@github.com>2023-11-24 00:15:43 +0100
commit7486aee82e46634dbe997ab4510cc54691a19bf5 (patch)
tree98576a1c80fcc3ac1d8da6e77714847cfaa875f9 /lib
parente03c9c3f1be4994c63b27ce60d41f13ebfeb3cad (diff)
parent6816f28c960c523e6a30f2ad4a1cc812251f5ffb (diff)
Merge pull request #266362 from tweag/fileset.fileFilter-ext
`lib.fileset.fileFilter`: Predicate attribute for file extension
Diffstat (limited to 'lib')
-rw-r--r--lib/fileset/default.nix9
-rw-r--r--lib/fileset/internal.nix5
-rwxr-xr-xlib/fileset/tests.sh35
3 files changed, 46 insertions, 3 deletions
diff --git a/lib/fileset/default.nix b/lib/fileset/default.nix
index 9ccbf0ed7ce74..75e609a072e73 100644
--- a/lib/fileset/default.nix
+++ b/lib/fileset/default.nix
@@ -604,6 +604,7 @@ in {
         ({
           name :: String,
           type :: String,
+          hasExt :: String -> Bool,
           ...
         } -> Bool)
         -> Path
@@ -614,7 +615,7 @@ in {
       fileFilter (file: file.name == "default.nix") ./.
 
       # Include all non-Nix files from the current directory
-      fileFilter (file: ! hasSuffix ".nix" file.name) ./.
+      fileFilter (file: ! file.hasExt "nix") ./.
 
       # Include all files that start with a "." in the current directory
       fileFilter (file: hasPrefix "." file.name) ./.
@@ -634,6 +635,12 @@ in {
       - `type` (String, one of `"regular"`, `"symlink"` or `"unknown"`): The type of the file.
         This matches result of calling [`builtins.readFileType`](https://nixos.org/manual/nix/stable/language/builtins.html#builtins-readFileType) on the file's path.
 
+      - `hasExt` (String -> Bool): Whether the file has a certain file extension.
+        `hasExt ext` is true only if `hasSuffix ".${ext}" name`.
+
+        This also means that e.g. for a file with name `.gitignore`,
+        `hasExt "gitignore"` is true.
+
       Other attributes may be added in the future.
     */
     predicate:
diff --git a/lib/fileset/internal.nix b/lib/fileset/internal.nix
index 2fddf0d022858..35d556e78391c 100644
--- a/lib/fileset/internal.nix
+++ b/lib/fileset/internal.nix
@@ -52,6 +52,7 @@ let
     concatStringsSep
     substring
     stringLength
+    hasSuffix
     ;
 
 in
@@ -797,9 +798,11 @@ rec {
         if
           predicate {
             inherit name type;
+            hasExt = ext: hasSuffix ".${ext}" name;
+
             # To ensure forwards compatibility with more arguments being added in the future,
             # adding an attribute which can't be deconstructed :)
-            "lib.fileset.fileFilter: The predicate function passed as the first argument must be able to handle extra attributes for future compatibility. If you're using `{ name, file }:`, use `{ name, file, ... }:` instead." = null;
+            "lib.fileset.fileFilter: The predicate function passed as the first argument must be able to handle extra attributes for future compatibility. If you're using `{ name, file, hasExt }:`, use `{ name, file, hasExt, ... }:` instead." = null;
           }
         then
           type
diff --git a/lib/fileset/tests.sh b/lib/fileset/tests.sh
index 81376bc451b10..077aefe371c35 100755
--- a/lib/fileset/tests.sh
+++ b/lib/fileset/tests.sh
@@ -847,7 +847,7 @@ checkFileset 'fileFilter (file: abort "this is not needed") ./.'
 
 # The predicate must be able to handle extra attributes
 touch a
-expectFailure 'toSource { root = ./.; fileset = fileFilter ({ name, type }: true) ./.; }' 'called with unexpected argument '\''"lib.fileset.fileFilter: The predicate function passed as the first argument must be able to handle extra attributes for future compatibility. If you'\''re using `\{ name, file \}:`, use `\{ name, file, ... \}:` instead."'\'
+expectFailure 'toSource { root = ./.; fileset = fileFilter ({ name, type, hasExt }: true) ./.; }' 'called with unexpected argument '\''"lib.fileset.fileFilter: The predicate function passed as the first argument must be able to handle extra attributes for future compatibility. If you'\''re using `\{ name, file, hasExt \}:`, use `\{ name, file, hasExt, ... \}:` instead."'\'
 rm -rf -- *
 
 # .name is the name, and it works correctly, even recursively
@@ -895,6 +895,39 @@ expectEqual \
     'toSource { root = ./.; fileset = union ./d/a ./d/b; }'
 rm -rf -- *
 
+# Check that .hasExt checks for the file extension
+# The empty extension is the same as a file ending with a .
+tree=(
+    [a]=0
+    [a.]=1
+    [a.b]=0
+    [a.b.]=1
+    [a.b.c]=0
+)
+checkFileset 'fileFilter (file: file.hasExt "") ./.'
+
+# It can check for the last extension
+tree=(
+    [a]=0
+    [.a]=1
+    [.a.]=0
+    [.b.a]=1
+    [.b.a.]=0
+)
+checkFileset 'fileFilter (file: file.hasExt "a") ./.'
+
+# It can check for any extension
+tree=(
+    [a.b.c.d]=1
+)
+checkFileset 'fileFilter (file:
+  all file.hasExt [
+    "b.c.d"
+    "c.d"
+    "d"
+  ]
+) ./.'
+
 # It's lazy
 tree=(
     [b]=1