Merge pull request #266349 from tweag/fileset/cleanups
Minor `lib.fileset` cleanups
This commit is contained in:
commit
187c04f19c
4 changed files with 54 additions and 60 deletions
|
@ -6,11 +6,8 @@ The [`lib.fileset`](#sec-functions-library-fileset) library allows you to work w
|
|||
A file set is a mathematical set of local files that can be added to the Nix store for use in Nix derivations.
|
||||
File sets are easy and safe to use, providing obvious and composable semantics with good error messages to prevent mistakes.
|
||||
|
||||
These sections apply to the entire library.
|
||||
See the [function reference](#sec-functions-library-fileset) for function-specific documentation.
|
||||
|
||||
The file set library is currently somewhat limited but is being expanded to include more functions over time.
|
||||
|
||||
## Implicit coercion from paths to file sets {#sec-fileset-path-coercion}
|
||||
|
||||
All functions accepting file sets as arguments can also accept [paths](https://nixos.org/manual/nix/stable/language/values.html#type-path) as arguments.
|
||||
|
|
|
@ -122,11 +122,10 @@ in {
|
|||
Paths in [strings](https://nixos.org/manual/nix/stable/language/values.html#type-string), including Nix store paths, cannot be passed as `root`.
|
||||
`root` has to be a directory.
|
||||
|
||||
<!-- Ignore the indentation here, this is a nixdoc rendering bug that needs to be fixed: https://github.com/nix-community/nixdoc/issues/75 -->
|
||||
:::{.note}
|
||||
Changing `root` only affects the directory structure of the resulting store path, it does not change which files are added to the store.
|
||||
The only way to change which files get added to the store is by changing the `fileset` attribute.
|
||||
:::
|
||||
:::{.note}
|
||||
Changing `root` only affects the directory structure of the resulting store path, it does not change which files are added to the store.
|
||||
The only way to change which files get added to the store is by changing the `fileset` attribute.
|
||||
:::
|
||||
*/
|
||||
root,
|
||||
/*
|
||||
|
@ -135,10 +134,9 @@ The only way to change which files get added to the store is by changing the `fi
|
|||
This argument can also be a path,
|
||||
which gets [implicitly coerced to a file set](#sec-fileset-path-coercion).
|
||||
|
||||
<!-- Ignore the indentation here, this is a nixdoc rendering bug that needs to be fixed: https://github.com/nix-community/nixdoc/issues/75 -->
|
||||
:::{.note}
|
||||
If a directory does not recursively contain any file, it is omitted from the store path contents.
|
||||
:::
|
||||
:::{.note}
|
||||
If a directory does not recursively contain any file, it is omitted from the store path contents.
|
||||
:::
|
||||
|
||||
*/
|
||||
fileset,
|
||||
|
@ -156,7 +154,7 @@ If a directory does not recursively contain any file, it is omitted from the sto
|
|||
if ! isPath root then
|
||||
if isStringLike root then
|
||||
throw ''
|
||||
lib.fileset.toSource: `root` ("${toString root}") is a string-like value, but it should be a path instead.
|
||||
lib.fileset.toSource: `root` (${toString root}) is a string-like value, but it should be a path instead.
|
||||
Paths in strings are not supported by `lib.fileset`, use `lib.sources` or derivations instead.''
|
||||
else
|
||||
throw ''
|
||||
|
@ -165,13 +163,13 @@ If a directory does not recursively contain any file, it is omitted from the sto
|
|||
# See also ../path/README.md
|
||||
else if ! fileset._internalIsEmptyWithoutBase && rootFilesystemRoot != filesetFilesystemRoot then
|
||||
throw ''
|
||||
lib.fileset.toSource: Filesystem roots are not the same for `fileset` and `root` ("${toString root}"):
|
||||
`root`: root "${toString rootFilesystemRoot}"
|
||||
`fileset`: root "${toString filesetFilesystemRoot}"
|
||||
Different roots are not supported.''
|
||||
lib.fileset.toSource: Filesystem roots are not the same for `fileset` and `root` (${toString root}):
|
||||
`root`: Filesystem root is "${toString rootFilesystemRoot}"
|
||||
`fileset`: Filesystem root is "${toString filesetFilesystemRoot}"
|
||||
Different filesystem roots are not supported.''
|
||||
else if ! pathExists root then
|
||||
throw ''
|
||||
lib.fileset.toSource: `root` (${toString root}) does not exist.''
|
||||
lib.fileset.toSource: `root` (${toString root}) is a path that does not exist.''
|
||||
else if pathType root != "directory" then
|
||||
throw ''
|
||||
lib.fileset.toSource: `root` (${toString root}) is a file, but it should be a directory instead. Potential solutions:
|
||||
|
@ -223,11 +221,11 @@ If a directory does not recursively contain any file, it is omitted from the sto
|
|||
_unionMany
|
||||
(_coerceMany "lib.fileset.union" [
|
||||
{
|
||||
context = "first argument";
|
||||
context = "First argument";
|
||||
value = fileset1;
|
||||
}
|
||||
{
|
||||
context = "second argument";
|
||||
context = "Second argument";
|
||||
value = fileset2;
|
||||
}
|
||||
]);
|
||||
|
@ -269,12 +267,13 @@ If a directory does not recursively contain any file, it is omitted from the sto
|
|||
# which get [implicitly coerced to file sets](#sec-fileset-path-coercion).
|
||||
filesets:
|
||||
if ! isList filesets then
|
||||
throw "lib.fileset.unions: Expected argument to be a list, but got a ${typeOf filesets}."
|
||||
throw ''
|
||||
lib.fileset.unions: Argument is of type ${typeOf filesets}, but it should be a list instead.''
|
||||
else
|
||||
pipe filesets [
|
||||
# Annotate the elements with context, used by _coerceMany for better errors
|
||||
(imap0 (i: el: {
|
||||
context = "element ${toString i}";
|
||||
context = "Element ${toString i}";
|
||||
value = el;
|
||||
}))
|
||||
(_coerceMany "lib.fileset.unions")
|
||||
|
@ -325,10 +324,11 @@ If a directory does not recursively contain any file, it is omitted from the sto
|
|||
# The file set to filter based on the predicate function
|
||||
fileset:
|
||||
if ! isFunction predicate then
|
||||
throw "lib.fileset.fileFilter: Expected the first argument to be a function, but it's a ${typeOf predicate} instead."
|
||||
throw ''
|
||||
lib.fileset.fileFilter: First argument is of type ${typeOf predicate}, but it should be a function.''
|
||||
else
|
||||
_fileFilter predicate
|
||||
(_coerce "lib.fileset.fileFilter: second argument" fileset);
|
||||
(_coerce "lib.fileset.fileFilter: Second argument" fileset);
|
||||
|
||||
/*
|
||||
The file set containing all files that are in both of two given file sets.
|
||||
|
@ -356,11 +356,11 @@ If a directory does not recursively contain any file, it is omitted from the sto
|
|||
let
|
||||
filesets = _coerceMany "lib.fileset.intersection" [
|
||||
{
|
||||
context = "first argument";
|
||||
context = "First argument";
|
||||
value = fileset1;
|
||||
}
|
||||
{
|
||||
context = "second argument";
|
||||
context = "Second argument";
|
||||
value = fileset2;
|
||||
}
|
||||
];
|
||||
|
@ -408,11 +408,11 @@ If a directory does not recursively contain any file, it is omitted from the sto
|
|||
let
|
||||
filesets = _coerceMany "lib.fileset.difference" [
|
||||
{
|
||||
context = "first argument (positive set)";
|
||||
context = "First argument (positive set)";
|
||||
value = positive;
|
||||
}
|
||||
{
|
||||
context = "second argument (negative set)";
|
||||
context = "Second argument (negative set)";
|
||||
value = negative;
|
||||
}
|
||||
];
|
||||
|
@ -456,7 +456,7 @@ If a directory does not recursively contain any file, it is omitted from the sto
|
|||
let
|
||||
# "fileset" would be a better name, but that would clash with the argument name,
|
||||
# and we cannot change that because of https://github.com/nix-community/nixdoc/issues/76
|
||||
actualFileset = _coerce "lib.fileset.trace: argument" fileset;
|
||||
actualFileset = _coerce "lib.fileset.trace: Argument" fileset;
|
||||
in
|
||||
seq
|
||||
(_printFileset actualFileset)
|
||||
|
@ -503,7 +503,7 @@ If a directory does not recursively contain any file, it is omitted from the sto
|
|||
let
|
||||
# "fileset" would be a better name, but that would clash with the argument name,
|
||||
# and we cannot change that because of https://github.com/nix-community/nixdoc/issues/76
|
||||
actualFileset = _coerce "lib.fileset.traceVal: argument" fileset;
|
||||
actualFileset = _coerce "lib.fileset.traceVal: Argument" fileset;
|
||||
in
|
||||
seq
|
||||
(_printFileset actualFileset)
|
||||
|
|
|
@ -7,7 +7,6 @@ let
|
|||
isString
|
||||
pathExists
|
||||
readDir
|
||||
seq
|
||||
split
|
||||
trace
|
||||
typeOf
|
||||
|
@ -17,7 +16,6 @@ let
|
|||
attrNames
|
||||
attrValues
|
||||
mapAttrs
|
||||
setAttrByPath
|
||||
zipAttrsWith
|
||||
;
|
||||
|
||||
|
@ -28,7 +26,6 @@ let
|
|||
inherit (lib.lists)
|
||||
all
|
||||
commonPrefix
|
||||
drop
|
||||
elemAt
|
||||
filter
|
||||
findFirst
|
||||
|
@ -179,7 +176,7 @@ rec {
|
|||
${context} is of type ${typeOf value}, but it should be a file set or a path instead.''
|
||||
else if ! pathExists value then
|
||||
throw ''
|
||||
${context} (${toString value}) does not exist.''
|
||||
${context} (${toString value}) is a path that does not exist.''
|
||||
else
|
||||
_singleton value;
|
||||
|
||||
|
@ -208,9 +205,9 @@ rec {
|
|||
if firstWithBase != null && differentIndex != null then
|
||||
throw ''
|
||||
${functionContext}: Filesystem roots are not the same:
|
||||
${(head list).context}: root "${toString firstBaseRoot}"
|
||||
${(elemAt list differentIndex).context}: root "${toString (elemAt filesets differentIndex)._internalBaseRoot}"
|
||||
Different roots are not supported.''
|
||||
${(head list).context}: Filesystem root is "${toString firstBaseRoot}"
|
||||
${(elemAt list differentIndex).context}: Filesystem root is "${toString (elemAt filesets differentIndex)._internalBaseRoot}"
|
||||
Different filesystem roots are not supported.''
|
||||
else
|
||||
filesets;
|
||||
|
||||
|
|
|
@ -318,7 +318,7 @@ checkFileset() {
|
|||
#### Error messages #####
|
||||
|
||||
# Absolute paths in strings cannot be passed as `root`
|
||||
expectFailure 'toSource { root = "/nix/store/foobar"; fileset = ./.; }' 'lib.fileset.toSource: `root` \("/nix/store/foobar"\) is a string-like value, but it should be a path instead.
|
||||
expectFailure 'toSource { root = "/nix/store/foobar"; fileset = ./.; }' 'lib.fileset.toSource: `root` \(/nix/store/foobar\) is a string-like value, but it should be a path instead.
|
||||
\s*Paths in strings are not supported by `lib.fileset`, use `lib.sources` or derivations instead.'
|
||||
|
||||
# Only paths are accepted as `root`
|
||||
|
@ -328,14 +328,14 @@ expectFailure 'toSource { root = 10; fileset = ./.; }' 'lib.fileset.toSource: `r
|
|||
mkdir -p {foo,bar}/mock-root
|
||||
expectFailure 'with ((import <nixpkgs/lib>).extend (import <nixpkgs/lib/fileset/mock-splitRoot.nix>)).fileset;
|
||||
toSource { root = ./foo/mock-root; fileset = ./bar/mock-root; }
|
||||
' 'lib.fileset.toSource: Filesystem roots are not the same for `fileset` and `root` \("'"$work"'/foo/mock-root"\):
|
||||
\s*`root`: root "'"$work"'/foo/mock-root"
|
||||
\s*`fileset`: root "'"$work"'/bar/mock-root"
|
||||
\s*Different roots are not supported.'
|
||||
' 'lib.fileset.toSource: Filesystem roots are not the same for `fileset` and `root` \('"$work"'/foo/mock-root\):
|
||||
\s*`root`: Filesystem root is "'"$work"'/foo/mock-root"
|
||||
\s*`fileset`: Filesystem root is "'"$work"'/bar/mock-root"
|
||||
\s*Different filesystem roots are not supported.'
|
||||
rm -rf -- *
|
||||
|
||||
# `root` needs to exist
|
||||
expectFailure 'toSource { root = ./a; fileset = ./.; }' 'lib.fileset.toSource: `root` \('"$work"'/a\) does not exist.'
|
||||
expectFailure 'toSource { root = ./a; fileset = ./.; }' 'lib.fileset.toSource: `root` \('"$work"'/a\) is a path that does not exist.'
|
||||
|
||||
# `root` needs to be a file
|
||||
touch a
|
||||
|
@ -367,7 +367,7 @@ expectFailure 'toSource { root = ./.; fileset = "/some/path"; }' 'lib.fileset.to
|
|||
\s*Paths represented as strings are not supported by `lib.fileset`, use `lib.sources` or derivations instead.'
|
||||
|
||||
# Path coercion errors for non-existent paths
|
||||
expectFailure 'toSource { root = ./.; fileset = ./a; }' 'lib.fileset.toSource: `fileset` \('"$work"'/a\) does not exist.'
|
||||
expectFailure 'toSource { root = ./.; fileset = ./a; }' 'lib.fileset.toSource: `fileset` \('"$work"'/a\) is a path that does not exist.'
|
||||
|
||||
# File sets cannot be evaluated directly
|
||||
expectFailure 'union ./. ./.' 'lib.fileset: Directly evaluating a file set is not supported.
|
||||
|
@ -490,26 +490,26 @@ mkdir -p {foo,bar}/mock-root
|
|||
expectFailure 'with ((import <nixpkgs/lib>).extend (import <nixpkgs/lib/fileset/mock-splitRoot.nix>)).fileset;
|
||||
toSource { root = ./.; fileset = union ./foo/mock-root ./bar/mock-root; }
|
||||
' 'lib.fileset.union: Filesystem roots are not the same:
|
||||
\s*first argument: root "'"$work"'/foo/mock-root"
|
||||
\s*second argument: root "'"$work"'/bar/mock-root"
|
||||
\s*Different roots are not supported.'
|
||||
\s*First argument: Filesystem root is "'"$work"'/foo/mock-root"
|
||||
\s*Second argument: Filesystem root is "'"$work"'/bar/mock-root"
|
||||
\s*Different filesystem roots are not supported.'
|
||||
|
||||
expectFailure 'with ((import <nixpkgs/lib>).extend (import <nixpkgs/lib/fileset/mock-splitRoot.nix>)).fileset;
|
||||
toSource { root = ./.; fileset = unions [ ./foo/mock-root ./bar/mock-root ]; }
|
||||
' 'lib.fileset.unions: Filesystem roots are not the same:
|
||||
\s*element 0: root "'"$work"'/foo/mock-root"
|
||||
\s*element 1: root "'"$work"'/bar/mock-root"
|
||||
\s*Different roots are not supported.'
|
||||
\s*Element 0: Filesystem root is "'"$work"'/foo/mock-root"
|
||||
\s*Element 1: Filesystem root is "'"$work"'/bar/mock-root"
|
||||
\s*Different filesystem roots are not supported.'
|
||||
rm -rf -- *
|
||||
|
||||
# Coercion errors show the correct context
|
||||
expectFailure 'toSource { root = ./.; fileset = union ./a ./.; }' 'lib.fileset.union: first argument \('"$work"'/a\) does not exist.'
|
||||
expectFailure 'toSource { root = ./.; fileset = union ./. ./b; }' 'lib.fileset.union: second argument \('"$work"'/b\) does not exist.'
|
||||
expectFailure 'toSource { root = ./.; fileset = unions [ ./a ./. ]; }' 'lib.fileset.unions: element 0 \('"$work"'/a\) does not exist.'
|
||||
expectFailure 'toSource { root = ./.; fileset = unions [ ./. ./b ]; }' 'lib.fileset.unions: element 1 \('"$work"'/b\) does not exist.'
|
||||
expectFailure 'toSource { root = ./.; fileset = union ./a ./.; }' 'lib.fileset.union: First argument \('"$work"'/a\) is a path that does not exist.'
|
||||
expectFailure 'toSource { root = ./.; fileset = union ./. ./b; }' 'lib.fileset.union: Second argument \('"$work"'/b\) is a path that does not exist.'
|
||||
expectFailure 'toSource { root = ./.; fileset = unions [ ./a ./. ]; }' 'lib.fileset.unions: Element 0 \('"$work"'/a\) is a path that does not exist.'
|
||||
expectFailure 'toSource { root = ./.; fileset = unions [ ./. ./b ]; }' 'lib.fileset.unions: Element 1 \('"$work"'/b\) is a path that does not exist.'
|
||||
|
||||
# unions needs a list
|
||||
expectFailure 'toSource { root = ./.; fileset = unions null; }' 'lib.fileset.unions: Expected argument to be a list, but got a null.'
|
||||
expectFailure 'toSource { root = ./.; fileset = unions null; }' 'lib.fileset.unions: Argument is of type null, but it should be a list instead.'
|
||||
|
||||
# The tree of later arguments should not be evaluated if a former argument already includes all files
|
||||
tree=()
|
||||
|
@ -603,14 +603,14 @@ mkdir -p {foo,bar}/mock-root
|
|||
expectFailure 'with ((import <nixpkgs/lib>).extend (import <nixpkgs/lib/fileset/mock-splitRoot.nix>)).fileset;
|
||||
toSource { root = ./.; fileset = intersection ./foo/mock-root ./bar/mock-root; }
|
||||
' 'lib.fileset.intersection: Filesystem roots are not the same:
|
||||
\s*first argument: root "'"$work"'/foo/mock-root"
|
||||
\s*second argument: root "'"$work"'/bar/mock-root"
|
||||
\s*Different roots are not supported.'
|
||||
\s*First argument: Filesystem root is "'"$work"'/foo/mock-root"
|
||||
\s*Second argument: Filesystem root is "'"$work"'/bar/mock-root"
|
||||
\s*Different filesystem roots are not supported.'
|
||||
rm -rf -- *
|
||||
|
||||
# Coercion errors show the correct context
|
||||
expectFailure 'toSource { root = ./.; fileset = intersection ./a ./.; }' 'lib.fileset.intersection: first argument \('"$work"'/a\) does not exist.'
|
||||
expectFailure 'toSource { root = ./.; fileset = intersection ./. ./b; }' 'lib.fileset.intersection: second argument \('"$work"'/b\) does not exist.'
|
||||
expectFailure 'toSource { root = ./.; fileset = intersection ./a ./.; }' 'lib.fileset.intersection: First argument \('"$work"'/a\) is a path that does not exist.'
|
||||
expectFailure 'toSource { root = ./.; fileset = intersection ./. ./b; }' 'lib.fileset.intersection: Second argument \('"$work"'/b\) is a path that does not exist.'
|
||||
|
||||
# The tree of later arguments should not be evaluated if a former argument already excludes all files
|
||||
tree=(
|
||||
|
|
Loading…
Reference in a new issue