Skip to content

Commit

Permalink
lib.fileset.toList: init
Browse files Browse the repository at this point in the history
  • Loading branch information
infinisil committed Feb 26, 2024
1 parent c5b5449 commit 3ea077d
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 2 deletions.
37 changes: 37 additions & 0 deletions lib/fileset/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -102,6 +106,7 @@ let
_coerceMany
_toSourceFilter
_fromSourceFilter
_toList
_unionMany
_fileFilter
_printFileset
Expand Down Expand Up @@ -412,6 +417,38 @@ in {
filter = sourceFilter;
};


/*
The list of file paths contained in the given file set.
:::{.note}
This function evaluates the file set _strictly_.
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),
Expand Down
23 changes: 23 additions & 0 deletions lib/fileset/internal.nix
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ let
attrNames
attrValues
mapAttrs
mapAttrsToList
optionalAttrs
zipAttrsWith
;
Expand All @@ -29,6 +30,7 @@ let
inherit (lib.lists)
all
commonPrefix
concatLists
elemAt
filter
findFirst
Expand Down Expand Up @@ -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; }
Expand Down
23 changes: 21 additions & 2 deletions lib/fileset/tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -275,24 +275,27 @@ 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
createTree

# 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
Expand All @@ -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,
Expand Down Expand Up @@ -511,6 +518,18 @@ 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 an empty paths
expectEqual 'toList ./.' '[ ]'

## lib.fileset.union, lib.fileset.unions


Expand Down

0 comments on commit 3ea077d

Please sign in to comment.