mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-10-31 22:51:22 +00:00
lib.fileset: Minor changes from feedback
Co-authored-by: Robert Hensing <robert@roberthensing.nl> Co-authored-by: Valentin Gagarin <valentin.gagarin@tweag.io>
This commit is contained in:
parent
fe6c1539cc
commit
94e103ee3f
@ -50,11 +50,11 @@ An attribute set with these values:
|
||||
|
||||
- `_internalBaseRoot` (path):
|
||||
The filesystem root of `_internalBase`, same as `(lib.path.splitRoot _internalBase).root`.
|
||||
This is here because this needs to be computed anyways, and this computation shouldn't be duplicated.
|
||||
This is here because this needs to be computed anyway, and this computation shouldn't be duplicated.
|
||||
|
||||
- `_internalBaseComponents` (list of strings):
|
||||
The path components of `_internalBase`, same as `lib.path.subpath.components (lib.path.splitRoot _internalBase).subpath`.
|
||||
This is here because this needs to be computed anyways, and this computation shouldn't be duplicated.
|
||||
This is here because this needs to be computed anyway, and this computation shouldn't be duplicated.
|
||||
|
||||
- `_internalTree` ([filesetTree](#filesettree)):
|
||||
A tree representation of all included files under `_internalBase`.
|
||||
|
@ -36,6 +36,10 @@ let
|
||||
cleanSourceWith
|
||||
;
|
||||
|
||||
inherit (lib.trivial)
|
||||
pipe
|
||||
;
|
||||
|
||||
in {
|
||||
|
||||
/*
|
||||
@ -111,7 +115,7 @@ 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 -->
|
||||
<!-- 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.
|
||||
@ -124,7 +128,7 @@ 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 -->
|
||||
<!-- 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.
|
||||
:::
|
||||
@ -134,18 +138,18 @@ If a directory does not recursively contain any file, it is omitted from the sto
|
||||
}:
|
||||
let
|
||||
# We cannot rename matched attribute arguments, so let's work around it with an extra `let in` statement
|
||||
maybeFileset = fileset;
|
||||
filesetArg = fileset;
|
||||
in
|
||||
let
|
||||
fileset = _coerce "lib.fileset.toSource: `fileset`" maybeFileset;
|
||||
fileset = _coerce "lib.fileset.toSource: `fileset`" filesetArg;
|
||||
rootFilesystemRoot = (splitRoot root).root;
|
||||
filesetFilesystemRoot = (splitRoot fileset._internalBase).root;
|
||||
filter = _toSourceFilter fileset;
|
||||
sourceFilter = _toSourceFilter fileset;
|
||||
in
|
||||
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 ''
|
||||
@ -154,29 +158,29 @@ If a directory does not recursively contain any file, it is omitted from the sto
|
||||
# See also ../path/README.md
|
||||
else if rootFilesystemRoot != filesetFilesystemRoot then
|
||||
throw ''
|
||||
lib.fileset.toSource: Filesystem roots are not the same for `fileset` and `root` "${toString root}":
|
||||
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.''
|
||||
else if ! pathExists root then
|
||||
throw ''
|
||||
lib.fileset.toSource: `root` ${toString root} does not exist.''
|
||||
lib.fileset.toSource: `root` (${toString root}) 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:
|
||||
lib.fileset.toSource: `root` (${toString root}) is a file, but it should be a directory instead. Potential solutions:
|
||||
- If you want to import the file into the store _without_ a containing directory, use string interpolation or `builtins.path` instead of this function.
|
||||
- If you want to import the file into the store _with_ a containing directory, set `root` to the containing directory, such as ${toString (dirOf root)}, and set `fileset` to the file path.''
|
||||
else if ! hasPrefix root fileset._internalBase then
|
||||
throw ''
|
||||
lib.fileset.toSource: `fileset` could contain files in ${toString fileset._internalBase}, which is not under the `root` ${toString root}. Potential solutions:
|
||||
lib.fileset.toSource: `fileset` could contain files in ${toString fileset._internalBase}, which is not under the `root` (${toString root}). Potential solutions:
|
||||
- Set `root` to ${toString fileset._internalBase} or any directory higher up. This changes the layout of the resulting store path.
|
||||
- Set `fileset` to a file set that cannot contain files outside the `root` ${toString root}. This could change the files included in the result.''
|
||||
- Set `fileset` to a file set that cannot contain files outside the `root` (${toString root}). This could change the files included in the result.''
|
||||
else
|
||||
builtins.seq filter
|
||||
builtins.seq sourceFilter
|
||||
cleanSourceWith {
|
||||
name = "source";
|
||||
src = root;
|
||||
inherit filter;
|
||||
filter = sourceFilter;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -209,8 +213,8 @@ If a directory does not recursively contain any file, it is omitted from the sto
|
||||
# This argument can also be a path,
|
||||
# which gets [implicitly coerced to a file set](#sec-fileset-path-coercion).
|
||||
fileset2:
|
||||
let
|
||||
filesets = _coerceMany "lib.fileset.union" [
|
||||
_unionMany
|
||||
(_coerceMany "lib.fileset.union" [
|
||||
{
|
||||
context = "first argument";
|
||||
value = fileset1;
|
||||
@ -219,9 +223,7 @@ If a directory does not recursively contain any file, it is omitted from the sto
|
||||
context = "second argument";
|
||||
value = fileset2;
|
||||
}
|
||||
];
|
||||
in
|
||||
_unionMany filesets;
|
||||
]);
|
||||
|
||||
/*
|
||||
The file set containing all files that are in any of the given file sets.
|
||||
@ -260,25 +262,20 @@ If a directory does not recursively contain any file, it is omitted from the sto
|
||||
# The elements can also be paths,
|
||||
# which get [implicitly coerced to file sets](#sec-fileset-path-coercion).
|
||||
filesets:
|
||||
let
|
||||
# We cannot rename matched attribute arguments, so let's work around it with an extra `let in` statement
|
||||
maybeFilesets = filesets;
|
||||
in
|
||||
let
|
||||
# Annotate the elements with context, used by _coerceMany for better errors
|
||||
annotated = imap0 (i: el: {
|
||||
context = "element ${toString i} of the argument";
|
||||
value = el;
|
||||
}) maybeFilesets;
|
||||
|
||||
filesets = _coerceMany "lib.fileset.unions" annotated;
|
||||
in
|
||||
if ! isList maybeFilesets then
|
||||
throw "lib.fileset.unions: Expected argument to be a list, but got a ${typeOf maybeFilesets}."
|
||||
else if maybeFilesets == [ ] then
|
||||
# TODO: This could be supported, but requires an extra internal representation for the empty file set
|
||||
if ! isList filesets then
|
||||
throw "lib.fileset.unions: Expected argument to be a list, but got a ${typeOf filesets}."
|
||||
else if filesets == [ ] then
|
||||
# TODO: This could be supported, but requires an extra internal representation for the empty file set, which would be special for not having a base path.
|
||||
throw "lib.fileset.unions: Expected argument to be a list with at least one element, but it contains no elements."
|
||||
else
|
||||
_unionMany filesets;
|
||||
pipe filesets [
|
||||
# Annotate the elements with context, used by _coerceMany for better errors
|
||||
(imap0 (i: el: {
|
||||
context = "element ${toString i}";
|
||||
value = el;
|
||||
}))
|
||||
(_coerceMany "lib.fileset.unions")
|
||||
_unionMany
|
||||
];
|
||||
|
||||
}
|
||||
|
@ -135,14 +135,14 @@ rec {
|
||||
else if ! isPath value then
|
||||
if isStringLike value then
|
||||
throw ''
|
||||
${context} "${toString value}" is a string-like value, but it should be a path instead.
|
||||
${context} ("${toString value}") is a string-like value, but it should be a path instead.
|
||||
Paths represented as strings are not supported by `lib.fileset`, use `lib.sources` or derivations instead.''
|
||||
else
|
||||
throw ''
|
||||
${context} is of type ${typeOf value}, but it should be a path instead.''
|
||||
else if ! pathExists value then
|
||||
throw ''
|
||||
${context} ${toString value} does not exist.''
|
||||
${context} (${toString value}) does not exist.''
|
||||
else
|
||||
_singleton value;
|
||||
|
||||
@ -341,9 +341,6 @@ rec {
|
||||
# The common base path assembled from a filesystem root and the common components
|
||||
commonBase = append first._internalBaseRoot (join commonBaseComponents);
|
||||
|
||||
# The number of path components common to all base paths
|
||||
commonBaseComponentsCount = length commonBaseComponents;
|
||||
|
||||
# A list of filesetTree's that all have the same base path
|
||||
# This is achieved by nesting the trees into the components they have over the common base path
|
||||
# E.g. `union /foo/bar /foo/baz` has the base path /foo
|
||||
@ -352,7 +349,7 @@ rec {
|
||||
# Therefore allowing combined operations over them.
|
||||
trees = map (fileset:
|
||||
setAttrByPath
|
||||
(drop commonBaseComponentsCount fileset._internalBaseComponents)
|
||||
(drop (length commonBaseComponents) fileset._internalBaseComponents)
|
||||
fileset._internalTree
|
||||
) filesets;
|
||||
|
||||
|
@ -236,7 +236,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`
|
||||
@ -246,18 +246,18 @@ 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":
|
||||
' '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.'
|
||||
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\) does not exist.'
|
||||
|
||||
# `root` needs to be a file
|
||||
touch a
|
||||
expectFailure 'toSource { root = ./a; fileset = ./a; }' 'lib.fileset.toSource: `root` '"$work"'/a is a file, but it should be a directory instead. Potential solutions:
|
||||
expectFailure 'toSource { root = ./a; fileset = ./a; }' 'lib.fileset.toSource: `root` \('"$work"'/a\) is a file, but it should be a directory instead. Potential solutions:
|
||||
\s*- If you want to import the file into the store _without_ a containing directory, use string interpolation or `builtins.path` instead of this function.
|
||||
\s*- If you want to import the file into the store _with_ a containing directory, set `root` to the containing directory, such as '"$work"', and set `fileset` to the file path.'
|
||||
rm -rf *
|
||||
@ -267,18 +267,18 @@ expectFailure 'toSource { root = ./.; fileset = abort "This should be evaluated"
|
||||
|
||||
# Only paths under `root` should be able to influence the result
|
||||
mkdir a
|
||||
expectFailure 'toSource { root = ./a; fileset = ./.; }' 'lib.fileset.toSource: `fileset` could contain files in '"$work"', which is not under the `root` '"$work"'/a. Potential solutions:
|
||||
expectFailure 'toSource { root = ./a; fileset = ./.; }' 'lib.fileset.toSource: `fileset` could contain files in '"$work"', which is not under the `root` \('"$work"'/a\). Potential solutions:
|
||||
\s*- Set `root` to '"$work"' or any directory higher up. This changes the layout of the resulting store path.
|
||||
\s*- Set `fileset` to a file set that cannot contain files outside the `root` '"$work"'/a. This could change the files included in the result.'
|
||||
\s*- Set `fileset` to a file set that cannot contain files outside the `root` \('"$work"'/a\). This could change the files included in the result.'
|
||||
rm -rf *
|
||||
|
||||
# Path coercion only works for paths
|
||||
expectFailure 'toSource { root = ./.; fileset = 10; }' 'lib.fileset.toSource: `fileset` is of type int, but it should be a path instead.'
|
||||
expectFailure 'toSource { root = ./.; fileset = "/some/path"; }' 'lib.fileset.toSource: `fileset` "/some/path" is a string-like value, but it should be a path instead.
|
||||
expectFailure 'toSource { root = ./.; fileset = "/some/path"; }' 'lib.fileset.toSource: `fileset` \("/some/path"\) is a string-like value, but it should be a path instead.
|
||||
\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\) does not exist.'
|
||||
|
||||
# File sets cannot be evaluated directly
|
||||
expectFailure 'union ./. ./.' 'lib.fileset: Directly evaluating a file set is not supported. Use `lib.fileset.toSource` to turn it into a usable source instead.'
|
||||
@ -395,16 +395,16 @@ expectFailure 'with ((import <nixpkgs/lib>).extend (import <nixpkgs/lib/fileset/
|
||||
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 of the argument: root "'"$work"'/foo/mock-root"
|
||||
\s*element 1 of the argument: root "'"$work"'/bar/mock-root"
|
||||
\s*element 0: root "'"$work"'/foo/mock-root"
|
||||
\s*element 1: root "'"$work"'/bar/mock-root"
|
||||
\s*Different 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 of the argument '"$work"'/a does not exist.'
|
||||
expectFailure 'toSource { root = ./.; fileset = unions [ ./. ./b ]; }' 'lib.fileset.unions: element 1 of the argument '"$work"'/b does not exist.'
|
||||
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.'
|
||||
|
||||
# unions needs a list with at least 1 element
|
||||
expectFailure 'toSource { root = ./.; fileset = unions null; }' 'lib.fileset.unions: Expected argument to be a list, but got a null.'
|
||||
|
Loading…
Reference in New Issue
Block a user