Skip to content

Commit 94e103e

Browse files
infinisilroberthfricklerhandwerk
committed
lib.fileset: Minor changes from feedback
Co-authored-by: Robert Hensing <robert@roberthensing.nl> Co-authored-by: Valentin Gagarin <valentin.gagarin@tweag.io>
1 parent fe6c153 commit 94e103e

4 files changed

Lines changed: 52 additions & 58 deletions

File tree

lib/fileset/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,11 @@ An attribute set with these values:
5050

5151
- `_internalBaseRoot` (path):
5252
The filesystem root of `_internalBase`, same as `(lib.path.splitRoot _internalBase).root`.
53-
This is here because this needs to be computed anyways, and this computation shouldn't be duplicated.
53+
This is here because this needs to be computed anyway, and this computation shouldn't be duplicated.
5454

5555
- `_internalBaseComponents` (list of strings):
5656
The path components of `_internalBase`, same as `lib.path.subpath.components (lib.path.splitRoot _internalBase).subpath`.
57-
This is here because this needs to be computed anyways, and this computation shouldn't be duplicated.
57+
This is here because this needs to be computed anyway, and this computation shouldn't be duplicated.
5858

5959
- `_internalTree` ([filesetTree](#filesettree)):
6060
A tree representation of all included files under `_internalBase`.

lib/fileset/default.nix

Lines changed: 33 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ let
3636
cleanSourceWith
3737
;
3838

39+
inherit (lib.trivial)
40+
pipe
41+
;
42+
3943
in {
4044

4145
/*
@@ -111,7 +115,7 @@ in {
111115
Paths in [strings](https://nixos.org/manual/nix/stable/language/values.html#type-string), including Nix store paths, cannot be passed as `root`.
112116
`root` has to be a directory.
113117
114-
<!-- Ignore the indentation here, this is a nixdoc rendering bug that needs to be fixed -->
118+
<!-- Ignore the indentation here, this is a nixdoc rendering bug that needs to be fixed: https://github.com/nix-community/nixdoc/issues/75 -->
115119
:::{.note}
116120
Changing `root` only affects the directory structure of the resulting store path, it does not change which files are added to the store.
117121
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
124128
This argument can also be a path,
125129
which gets [implicitly coerced to a file set](#sec-fileset-path-coercion).
126130
127-
<!-- Ignore the indentation here, this is a nixdoc rendering bug that needs to be fixed -->
131+
<!-- Ignore the indentation here, this is a nixdoc rendering bug that needs to be fixed: https://github.com/nix-community/nixdoc/issues/75 -->
128132
:::{.note}
129133
If a directory does not recursively contain any file, it is omitted from the store path contents.
130134
:::
@@ -134,18 +138,18 @@ If a directory does not recursively contain any file, it is omitted from the sto
134138
}:
135139
let
136140
# We cannot rename matched attribute arguments, so let's work around it with an extra `let in` statement
137-
maybeFileset = fileset;
141+
filesetArg = fileset;
138142
in
139143
let
140-
fileset = _coerce "lib.fileset.toSource: `fileset`" maybeFileset;
144+
fileset = _coerce "lib.fileset.toSource: `fileset`" filesetArg;
141145
rootFilesystemRoot = (splitRoot root).root;
142146
filesetFilesystemRoot = (splitRoot fileset._internalBase).root;
143-
filter = _toSourceFilter fileset;
147+
sourceFilter = _toSourceFilter fileset;
144148
in
145149
if ! isPath root then
146150
if isStringLike root then
147151
throw ''
148-
lib.fileset.toSource: `root` "${toString root}" is a string-like value, but it should be a path instead.
152+
lib.fileset.toSource: `root` ("${toString root}") is a string-like value, but it should be a path instead.
149153
Paths in strings are not supported by `lib.fileset`, use `lib.sources` or derivations instead.''
150154
else
151155
throw ''
@@ -154,29 +158,29 @@ If a directory does not recursively contain any file, it is omitted from the sto
154158
# See also ../path/README.md
155159
else if rootFilesystemRoot != filesetFilesystemRoot then
156160
throw ''
157-
lib.fileset.toSource: Filesystem roots are not the same for `fileset` and `root` "${toString root}":
161+
lib.fileset.toSource: Filesystem roots are not the same for `fileset` and `root` ("${toString root}"):
158162
`root`: root "${toString rootFilesystemRoot}"
159163
`fileset`: root "${toString filesetFilesystemRoot}"
160164
Different roots are not supported.''
161165
else if ! pathExists root then
162166
throw ''
163-
lib.fileset.toSource: `root` ${toString root} does not exist.''
167+
lib.fileset.toSource: `root` (${toString root}) does not exist.''
164168
else if pathType root != "directory" then
165169
throw ''
166-
lib.fileset.toSource: `root` ${toString root} is a file, but it should be a directory instead. Potential solutions:
170+
lib.fileset.toSource: `root` (${toString root}) is a file, but it should be a directory instead. Potential solutions:
167171
- If you want to import the file into the store _without_ a containing directory, use string interpolation or `builtins.path` instead of this function.
168172
- 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.''
169173
else if ! hasPrefix root fileset._internalBase then
170174
throw ''
171-
lib.fileset.toSource: `fileset` could contain files in ${toString fileset._internalBase}, which is not under the `root` ${toString root}. Potential solutions:
175+
lib.fileset.toSource: `fileset` could contain files in ${toString fileset._internalBase}, which is not under the `root` (${toString root}). Potential solutions:
172176
- Set `root` to ${toString fileset._internalBase} or any directory higher up. This changes the layout of the resulting store path.
173-
- Set `fileset` to a file set that cannot contain files outside the `root` ${toString root}. This could change the files included in the result.''
177+
- Set `fileset` to a file set that cannot contain files outside the `root` (${toString root}). This could change the files included in the result.''
174178
else
175-
builtins.seq filter
179+
builtins.seq sourceFilter
176180
cleanSourceWith {
177181
name = "source";
178182
src = root;
179-
inherit filter;
183+
filter = sourceFilter;
180184
};
181185

182186
/*
@@ -209,8 +213,8 @@ If a directory does not recursively contain any file, it is omitted from the sto
209213
# This argument can also be a path,
210214
# which gets [implicitly coerced to a file set](#sec-fileset-path-coercion).
211215
fileset2:
212-
let
213-
filesets = _coerceMany "lib.fileset.union" [
216+
_unionMany
217+
(_coerceMany "lib.fileset.union" [
214218
{
215219
context = "first argument";
216220
value = fileset1;
@@ -219,9 +223,7 @@ If a directory does not recursively contain any file, it is omitted from the sto
219223
context = "second argument";
220224
value = fileset2;
221225
}
222-
];
223-
in
224-
_unionMany filesets;
226+
]);
225227

226228
/*
227229
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
260262
# The elements can also be paths,
261263
# which get [implicitly coerced to file sets](#sec-fileset-path-coercion).
262264
filesets:
263-
let
264-
# We cannot rename matched attribute arguments, so let's work around it with an extra `let in` statement
265-
maybeFilesets = filesets;
266-
in
267-
let
268-
# Annotate the elements with context, used by _coerceMany for better errors
269-
annotated = imap0 (i: el: {
270-
context = "element ${toString i} of the argument";
271-
value = el;
272-
}) maybeFilesets;
273-
274-
filesets = _coerceMany "lib.fileset.unions" annotated;
275-
in
276-
if ! isList maybeFilesets then
277-
throw "lib.fileset.unions: Expected argument to be a list, but got a ${typeOf maybeFilesets}."
278-
else if maybeFilesets == [ ] then
279-
# TODO: This could be supported, but requires an extra internal representation for the empty file set
265+
if ! isList filesets then
266+
throw "lib.fileset.unions: Expected argument to be a list, but got a ${typeOf filesets}."
267+
else if filesets == [ ] then
268+
# 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.
280269
throw "lib.fileset.unions: Expected argument to be a list with at least one element, but it contains no elements."
281270
else
282-
_unionMany filesets;
271+
pipe filesets [
272+
# Annotate the elements with context, used by _coerceMany for better errors
273+
(imap0 (i: el: {
274+
context = "element ${toString i}";
275+
value = el;
276+
}))
277+
(_coerceMany "lib.fileset.unions")
278+
_unionMany
279+
];
283280

284281
}

lib/fileset/internal.nix

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -135,14 +135,14 @@ rec {
135135
else if ! isPath value then
136136
if isStringLike value then
137137
throw ''
138-
${context} "${toString value}" is a string-like value, but it should be a path instead.
138+
${context} ("${toString value}") is a string-like value, but it should be a path instead.
139139
Paths represented as strings are not supported by `lib.fileset`, use `lib.sources` or derivations instead.''
140140
else
141141
throw ''
142142
${context} is of type ${typeOf value}, but it should be a path instead.''
143143
else if ! pathExists value then
144144
throw ''
145-
${context} ${toString value} does not exist.''
145+
${context} (${toString value}) does not exist.''
146146
else
147147
_singleton value;
148148

@@ -341,9 +341,6 @@ rec {
341341
# The common base path assembled from a filesystem root and the common components
342342
commonBase = append first._internalBaseRoot (join commonBaseComponents);
343343

344-
# The number of path components common to all base paths
345-
commonBaseComponentsCount = length commonBaseComponents;
346-
347344
# A list of filesetTree's that all have the same base path
348345
# This is achieved by nesting the trees into the components they have over the common base path
349346
# E.g. `union /foo/bar /foo/baz` has the base path /foo
@@ -352,7 +349,7 @@ rec {
352349
# Therefore allowing combined operations over them.
353350
trees = map (fileset:
354351
setAttrByPath
355-
(drop commonBaseComponentsCount fileset._internalBaseComponents)
352+
(drop (length commonBaseComponents) fileset._internalBaseComponents)
356353
fileset._internalTree
357354
) filesets;
358355

lib/fileset/tests.sh

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ checkFileset() (
236236
#### Error messages #####
237237

238238
# Absolute paths in strings cannot be passed as `root`
239-
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.
239+
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.
240240
\s*Paths in strings are not supported by `lib.fileset`, use `lib.sources` or derivations instead.'
241241

242242
# Only paths are accepted as `root`
@@ -246,18 +246,18 @@ expectFailure 'toSource { root = 10; fileset = ./.; }' 'lib.fileset.toSource: `r
246246
mkdir -p {foo,bar}/mock-root
247247
expectFailure 'with ((import <nixpkgs/lib>).extend (import <nixpkgs/lib/fileset/mock-splitRoot.nix>)).fileset;
248248
toSource { root = ./foo/mock-root; fileset = ./bar/mock-root; }
249-
' 'lib.fileset.toSource: Filesystem roots are not the same for `fileset` and `root` "'"$work"'/foo/mock-root":
249+
' 'lib.fileset.toSource: Filesystem roots are not the same for `fileset` and `root` \("'"$work"'/foo/mock-root"\):
250250
\s*`root`: root "'"$work"'/foo/mock-root"
251251
\s*`fileset`: root "'"$work"'/bar/mock-root"
252252
\s*Different roots are not supported.'
253253
rm -rf *
254254

255255
# `root` needs to exist
256-
expectFailure 'toSource { root = ./a; fileset = ./.; }' 'lib.fileset.toSource: `root` '"$work"'/a does not exist.'
256+
expectFailure 'toSource { root = ./a; fileset = ./.; }' 'lib.fileset.toSource: `root` \('"$work"'/a\) does not exist.'
257257

258258
# `root` needs to be a file
259259
touch a
260-
expectFailure 'toSource { root = ./a; fileset = ./a; }' 'lib.fileset.toSource: `root` '"$work"'/a is a file, but it should be a directory instead. Potential solutions:
260+
expectFailure 'toSource { root = ./a; fileset = ./a; }' 'lib.fileset.toSource: `root` \('"$work"'/a\) is a file, but it should be a directory instead. Potential solutions:
261261
\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.
262262
\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.'
263263
rm -rf *
@@ -267,18 +267,18 @@ expectFailure 'toSource { root = ./.; fileset = abort "This should be evaluated"
267267

268268
# Only paths under `root` should be able to influence the result
269269
mkdir a
270-
expectFailure 'toSource { root = ./a; fileset = ./.; }' 'lib.fileset.toSource: `fileset` could contain files in '"$work"', which is not under the `root` '"$work"'/a. Potential solutions:
270+
expectFailure 'toSource { root = ./a; fileset = ./.; }' 'lib.fileset.toSource: `fileset` could contain files in '"$work"', which is not under the `root` \('"$work"'/a\). Potential solutions:
271271
\s*- Set `root` to '"$work"' or any directory higher up. This changes the layout of the resulting store path.
272-
\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.'
272+
\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.'
273273
rm -rf *
274274

275275
# Path coercion only works for paths
276276
expectFailure 'toSource { root = ./.; fileset = 10; }' 'lib.fileset.toSource: `fileset` is of type int, but it should be a path instead.'
277-
expectFailure 'toSource { root = ./.; fileset = "/some/path"; }' 'lib.fileset.toSource: `fileset` "/some/path" is a string-like value, but it should be a path instead.
277+
expectFailure 'toSource { root = ./.; fileset = "/some/path"; }' 'lib.fileset.toSource: `fileset` \("/some/path"\) is a string-like value, but it should be a path instead.
278278
\s*Paths represented as strings are not supported by `lib.fileset`, use `lib.sources` or derivations instead.'
279279

280280
# Path coercion errors for non-existent paths
281-
expectFailure 'toSource { root = ./.; fileset = ./a; }' 'lib.fileset.toSource: `fileset` '"$work"'/a does not exist.'
281+
expectFailure 'toSource { root = ./.; fileset = ./a; }' 'lib.fileset.toSource: `fileset` \('"$work"'/a\) does not exist.'
282282

283283
# File sets cannot be evaluated directly
284284
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/
395395
expectFailure 'with ((import <nixpkgs/lib>).extend (import <nixpkgs/lib/fileset/mock-splitRoot.nix>)).fileset;
396396
toSource { root = ./.; fileset = unions [ ./foo/mock-root ./bar/mock-root ]; }
397397
' 'lib.fileset.unions: Filesystem roots are not the same:
398-
\s*element 0 of the argument: root "'"$work"'/foo/mock-root"
399-
\s*element 1 of the argument: root "'"$work"'/bar/mock-root"
398+
\s*element 0: root "'"$work"'/foo/mock-root"
399+
\s*element 1: root "'"$work"'/bar/mock-root"
400400
\s*Different roots are not supported.'
401401
rm -rf *
402402

403403
# Coercion errors show the correct context
404-
expectFailure 'toSource { root = ./.; fileset = union ./a ./.; }' 'lib.fileset.union: first argument '"$work"'/a does not exist.'
405-
expectFailure 'toSource { root = ./.; fileset = union ./. ./b; }' 'lib.fileset.union: second argument '"$work"'/b does not exist.'
406-
expectFailure 'toSource { root = ./.; fileset = unions [ ./a ./. ]; }' 'lib.fileset.unions: element 0 of the argument '"$work"'/a does not exist.'
407-
expectFailure 'toSource { root = ./.; fileset = unions [ ./. ./b ]; }' 'lib.fileset.unions: element 1 of the argument '"$work"'/b does not exist.'
404+
expectFailure 'toSource { root = ./.; fileset = union ./a ./.; }' 'lib.fileset.union: first argument \('"$work"'/a\) does not exist.'
405+
expectFailure 'toSource { root = ./.; fileset = union ./. ./b; }' 'lib.fileset.union: second argument \('"$work"'/b\) does not exist.'
406+
expectFailure 'toSource { root = ./.; fileset = unions [ ./a ./. ]; }' 'lib.fileset.unions: element 0 \('"$work"'/a\) does not exist.'
407+
expectFailure 'toSource { root = ./.; fileset = unions [ ./. ./b ]; }' 'lib.fileset.unions: element 1 \('"$work"'/b\) does not exist.'
408408

409409
# unions needs a list with at least 1 element
410410
expectFailure 'toSource { root = ./.; fileset = unions null; }' 'lib.fileset.unions: Expected argument to be a list, but got a null.'

0 commit comments

Comments
 (0)