summaryrefslogtreecommitdiffstats
path: root/lib/fileset
diff options
context:
space:
mode:
authorSilvan Mosberger <silvan.mosberger@tweag.io>2024-02-13 22:46:11 +0100
committerSilvan Mosberger <silvan.mosberger@tweag.io>2024-02-26 20:21:50 +0100
commite3a6e380337820d17c154c54eaf50ab95bba5c0d (patch)
treea7e1cdc262c9927dc025e856f670c052eb472c98 /lib/fileset
parentc5b544922979418b8ed0d25f66fe344c9ef96fa7 (diff)
lib.fileset.toList: init
Diffstat (limited to 'lib/fileset')
-rw-r--r--lib/fileset/default.nix37
-rw-r--r--lib/fileset/internal.nix23
-rwxr-xr-xlib/fileset/tests.sh24
3 files changed, 82 insertions, 2 deletions
diff --git a/lib/fileset/default.nix b/lib/fileset/default.nix
index c007b60def0a..ce9afc796a3f 100644
--- a/lib/fileset/default.nix
+++ b/lib/fileset/default.nix
@@ -23,6 +23,10 @@
Add files in file sets to the store to use as derivation sources.
+ - [`lib.fileset.toList`](#function-library-lib.fileset.toList):
+
+ The list of files contained in a file set.
+
Combinators:
- [`lib.fileset.union`](#function-library-lib.fileset.union)/[`lib.fileset.unions`](#function-library-lib.fileset.unions):
@@ -102,6 +106,7 @@ let
_coerceMany
_toSourceFilter
_fromSourceFilter
+ _toList
_unionMany
_fileFilter
_printFileset
@@ -412,6 +417,38 @@ in {
filter = sourceFilter;
};
+
+ /*
+ The list of file paths contained in the given file set.
+
+ :::{.note}
+ This function is strict in the entire file set.
+ This is in contrast with combinators [`lib.fileset.union`](#function-library-lib.fileset.union),
+ [`lib.fileset.intersection`](#function-library-lib.fileset.intersection) and [`lib.fileset.difference`](#function-library-lib.fileset.difference).
+
+ Thus it is recommended to call `toList` on file sets created using the combinators,
+ instead of doing list processing on the result of `toList`.
+ :::
+
+ The resulting list of files can be turned back into a file set using [`lib.fileset.unions`](#function-library-lib.fileset.unions).
+
+ Type:
+ toList :: FileSet -> [ Path ]
+
+ Example:
+ toList ./.
+ [ ./README.md ./Makefile ./src/main.c ./src/main.h ]
+
+ toList (difference ./. ./src)
+ [ ./README.md ./Makefile ]
+ */
+ toList =
+ # The file set whose file paths to return.
+ # This argument can also be a path,
+ # which gets [implicitly coerced to a file set](#sec-fileset-path-coercion).
+ fileset:
+ _toList (_coerce "lib.fileset.toList: Argument" fileset);
+
/*
The file set containing all files that are in either of two given file sets.
This is the same as [`unions`](#function-library-lib.fileset.unions),
diff --git a/lib/fileset/internal.nix b/lib/fileset/internal.nix
index f4fcc83e1012..0d97ef174568 100644
--- a/lib/fileset/internal.nix
+++ b/lib/fileset/internal.nix
@@ -18,6 +18,7 @@ let
attrNames
attrValues
mapAttrs
+ mapAttrsToList
optionalAttrs
zipAttrsWith
;
@@ -29,6 +30,7 @@ let
inherit (lib.lists)
all
commonPrefix
+ concatLists
elemAt
filter
findFirst
@@ -539,6 +541,27 @@ rec {
${baseNameOf root} = rootPathType;
};
+ # Turns a file set into the list of file paths it includes.
+ # Type: fileset -> [ Path ]
+ _toList = fileset:
+ let
+ recurse = path: tree:
+ if isAttrs tree then
+ concatLists (mapAttrsToList (name: value:
+ recurse (path + "/${name}") value
+ ) tree)
+ else if tree == "directory" then
+ recurse path (readDir path)
+ else if tree == null then
+ [ ]
+ else
+ [ path ];
+ in
+ if fileset._internalIsEmptyWithoutBase then
+ [ ]
+ else
+ recurse fileset._internalBase fileset._internalTree;
+
# Transforms the filesetTree of a file set to a shorter base path, e.g.
# _shortenTreeBase [ "foo" ] (_create /foo/bar null)
# => { bar = null; }
diff --git a/lib/fileset/tests.sh b/lib/fileset/tests.sh
index af8338eb7855..654a7cefc9f1 100755
--- a/lib/fileset/tests.sh
+++ b/lib/fileset/tests.sh
@@ -275,7 +275,6 @@ createTree() {
# )
# checkFileset './a' # Pass the fileset as the argument
checkFileset() {
- # New subshell so that we can have a separate trap handler, see `trap` below
local fileset=$1
# Create the tree
@@ -283,16 +282,20 @@ checkFileset() {
# Process the tree into separate arrays for included paths, excluded paths and excluded files.
local -a included=()
+ local -a includedFiles=()
local -a excluded=()
local -a excludedFiles=()
for p in "${!tree[@]}"; do
case "${tree[$p]}" in
1)
included+=("$p")
+ # If keys end with a `/` we treat them as directories, otherwise files
+ if [[ ! "$p" =~ /$ ]]; then
+ includedFiles+=("$p")
+ fi
;;
0)
excluded+=("$p")
- # If keys end with a `/` we treat them as directories, otherwise files
if [[ ! "$p" =~ /$ ]]; then
excludedFiles+=("$p")
fi
@@ -302,6 +305,10 @@ checkFileset() {
esac
done
+ # Test that lib.fileset.toList contains exactly the included files.
+ # The /#/./ part prefixes each element with `./`
+ expectEqual "toList ($fileset)" "sort lessThan [ ${includedFiles[*]/#/./} ]"
+
expression="toSource { root = ./.; fileset = $fileset; }"
# We don't have lambda's in bash unfortunately,
@@ -511,6 +518,19 @@ expectEqual '_toSourceFilter (_create /. { foo = "regular"; }) "/foo" ""' 'true'
expectEqual '_toSourceFilter (_create /. { foo = null; }) "/foo" ""' 'false'
+## lib.fileset.toList
+# This function is mainly tested in checkFileset
+
+# The error context for an invalid argument must be correct
+expectFailure 'toList null' 'lib.fileset.toList: Argument is of type null, but it should be a file set or a path instead.'
+
+# Works for the empty fileset
+expectEqual 'toList _emptyWithoutBase' '[ ]'
+
+# Works on empty paths
+expectEqual 'toList ./.' '[ ]'
+
+
## lib.fileset.union, lib.fileset.unions