lib.fileset.toList: init

This commit is contained in:
Silvan Mosberger 2024-02-13 22:46:11 +01:00
parent c5b5449229
commit e3a6e38033
3 changed files with 82 additions and 2 deletions

View file

@ -23,6 +23,10 @@
Add files in file sets to the store to use as derivation sources. 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: Combinators:
- [`lib.fileset.union`](#function-library-lib.fileset.union)/[`lib.fileset.unions`](#function-library-lib.fileset.unions): - [`lib.fileset.union`](#function-library-lib.fileset.union)/[`lib.fileset.unions`](#function-library-lib.fileset.unions):
@ -102,6 +106,7 @@ let
_coerceMany _coerceMany
_toSourceFilter _toSourceFilter
_fromSourceFilter _fromSourceFilter
_toList
_unionMany _unionMany
_fileFilter _fileFilter
_printFileset _printFileset
@ -412,6 +417,38 @@ in {
filter = sourceFilter; 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. 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), This is the same as [`unions`](#function-library-lib.fileset.unions),

View file

@ -18,6 +18,7 @@ let
attrNames attrNames
attrValues attrValues
mapAttrs mapAttrs
mapAttrsToList
optionalAttrs optionalAttrs
zipAttrsWith zipAttrsWith
; ;
@ -29,6 +30,7 @@ let
inherit (lib.lists) inherit (lib.lists)
all all
commonPrefix commonPrefix
concatLists
elemAt elemAt
filter filter
findFirst findFirst
@ -539,6 +541,27 @@ rec {
${baseNameOf root} = rootPathType; ${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. # Transforms the filesetTree of a file set to a shorter base path, e.g.
# _shortenTreeBase [ "foo" ] (_create /foo/bar null) # _shortenTreeBase [ "foo" ] (_create /foo/bar null)
# => { bar = null; } # => { bar = null; }

View file

@ -275,7 +275,6 @@ createTree() {
# ) # )
# checkFileset './a' # Pass the fileset as the argument # checkFileset './a' # Pass the fileset as the argument
checkFileset() { checkFileset() {
# New subshell so that we can have a separate trap handler, see `trap` below
local fileset=$1 local fileset=$1
# Create the tree # Create the tree
@ -283,16 +282,20 @@ checkFileset() {
# Process the tree into separate arrays for included paths, excluded paths and excluded files. # Process the tree into separate arrays for included paths, excluded paths and excluded files.
local -a included=() local -a included=()
local -a includedFiles=()
local -a excluded=() local -a excluded=()
local -a excludedFiles=() local -a excludedFiles=()
for p in "${!tree[@]}"; do for p in "${!tree[@]}"; do
case "${tree[$p]}" in case "${tree[$p]}" in
1) 1)
included+=("$p") included+=("$p")
# If keys end with a `/` we treat them as directories, otherwise files
if [[ ! "$p" =~ /$ ]]; then
includedFiles+=("$p")
fi
;; ;;
0) 0)
excluded+=("$p") excluded+=("$p")
# If keys end with a `/` we treat them as directories, otherwise files
if [[ ! "$p" =~ /$ ]]; then if [[ ! "$p" =~ /$ ]]; then
excludedFiles+=("$p") excludedFiles+=("$p")
fi fi
@ -302,6 +305,10 @@ checkFileset() {
esac esac
done 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; }" expression="toSource { root = ./.; fileset = $fileset; }"
# We don't have lambda's in bash unfortunately, # 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' 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 ## lib.fileset.union, lib.fileset.unions