summaryrefslogtreecommitdiffstats
path: root/lib/fileset
diff options
context:
space:
mode:
authorSilvan Mosberger <silvan.mosberger@tweag.io>2024-02-27 23:26:40 +0100
committerSilvan Mosberger <silvan.mosberger@tweag.io>2024-02-27 23:26:40 +0100
commit34295941145b2df1b6c3a9b36c50ad2982227b2f (patch)
treecc9a7caca26235c7e5a4f8b607e6ced5bd6d510a /lib/fileset
parente7a4ed12aaff051818f1fc70ef19a306a46b504b (diff)
lib.fileset: Fix tests on Darwin, more POSIX
This was found when trying to run the fileset tests on Darwin (https://github.com/NixOS/nix/pull/9546#issuecomment-1967409445), which mysteriously fail on Darwin: test case at lib/fileset/tests.sh:342 failed: toSource { root = "/nix/store/foobar"; fileset = ./.; } should have errored with this regex pattern: 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. but this was the actual error: error: lib.fileset.toSource: `root` (/nix/store/foobar) 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. After dissecting this, I find out that apparently \s works on Linux, but not on Darwin for some reason! From the bash source code, it looks like <regex.h> with `REG_EXTENDED` is used for all platforms the same, so there's nothing odd there. It's almost impossible to know where <regex.h> comes from, but it looks to be a POSIX thing. So after digging through the almost impossible to find POSIX specifications (https://pubs.opengroup.org/onlinepubs/007908799/xbd/re.html#tag_007_003_005), I can indeed confirm that there's no mention of \s or the like! _However_, there is a mention of `[[:blank:]]`, so we'll use that instead.
Diffstat (limited to 'lib/fileset')
-rwxr-xr-xlib/fileset/tests.sh100
1 files changed, 52 insertions, 48 deletions
diff --git a/lib/fileset/tests.sh b/lib/fileset/tests.sh
index 654a7cefc9f1..405fa04d8e06 100755
--- a/lib/fileset/tests.sh
+++ b/lib/fileset/tests.sh
@@ -345,13 +345,17 @@ checkFileset() {
#### Error messages #####
+# We're using [[:blank:]] here instead of \s, because only the former is POSIX
+# (see https://pubs.opengroup.org/onlinepubs/007908799/xbd/re.html#tag_007_003_005).
+# And indeed, Darwin's bash only supports the former
+
# 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.
-\s*Paths in strings are not supported by `lib.fileset`, use `lib.sources` or derivations instead.'
+[[:blank:]]*Paths in strings are not supported by `lib.fileset`, use `lib.sources` or derivations instead.'
expectFailure 'toSource { root = cleanSourceWith { src = ./.; }; fileset = ./.; }' 'lib.fileset.toSource: `root` is a `lib.sources`-based value, but it should be a path instead.
-\s*To use a `lib.sources`-based value, convert it to a file set using `lib.fileset.fromSource` and pass it as `fileset`.
-\s*Note that this only works for sources created from paths.'
+[[:blank:]]*To use a `lib.sources`-based value, convert it to a file set using `lib.fileset.fromSource` and pass it as `fileset`.
+[[:blank:]]*Note that this only works for sources created from paths.'
# Only paths are accepted as `root`
expectFailure 'toSource { root = 10; fileset = ./.; }' 'lib.fileset.toSource: `root` is of type int, but it should be a path instead.'
@@ -361,9 +365,9 @@ 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`: Filesystem root is "'"$work"'/foo/mock-root"
-\s*`fileset`: Filesystem root is "'"$work"'/bar/mock-root"
-\s*Different filesystem roots are not supported.'
+[[:blank:]]*`root`: Filesystem root is "'"$work"'/foo/mock-root"
+[[:blank:]]*`fileset`: Filesystem root is "'"$work"'/bar/mock-root"
+[[:blank:]]*Different filesystem roots are not supported.'
rm -rf -- *
# `root` needs to exist
@@ -372,8 +376,8 @@ expectFailure 'toSource { root = ./a; fileset = ./.; }' 'lib.fileset.toSource: `
# `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:
-\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.'
+[[:blank:]]*- If you want to import the file into the store _without_ a containing directory, use string interpolation or `builtins.path` instead of this function.
+[[:blank:]]*- 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 -- *
# The fileset argument should be evaluated, even if the directory is empty
@@ -382,36 +386,36 @@ 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:
-\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.'
+[[:blank:]]*- Set `root` to '"$work"' or any directory higher up. This changes the layout of the resulting store path.
+[[:blank:]]*- 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 -- *
# non-regular and non-symlink files cannot be added to the Nix store
mkfifo a
expectFailure 'toSource { root = ./.; fileset = ./a; }' 'lib.fileset.toSource: `fileset` contains a file that cannot be added to the store: '"$work"'/a
-\s*This file is neither a regular file nor a symlink, the only file types supported by the Nix store.
-\s*Therefore the file set cannot be added to the Nix store as is. Make sure to not include that file to avoid this error.'
+[[:blank:]]*This file is neither a regular file nor a symlink, the only file types supported by the Nix store.
+[[:blank:]]*Therefore the file set cannot be added to the Nix store as is. Make sure to not include that file to avoid this error.'
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 file set or 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 file set or a path instead.
-\s*Paths represented as strings are not supported by `lib.fileset`, use `lib.sources` or derivations instead.'
+[[:blank:]]*Paths represented as strings are not supported by `lib.fileset`, use `lib.sources` or derivations instead.'
expectFailure 'toSource { root = ./.; fileset = cleanSourceWith { src = ./.; }; }' 'lib.fileset.toSource: `fileset` is a `lib.sources`-based value, but it should be a file set or a path instead.
-\s*To convert a `lib.sources`-based value to a file set you can use `lib.fileset.fromSource`.
-\s*Note that this only works for sources created from paths.'
+[[:blank:]]*To convert a `lib.sources`-based value to a file set you can use `lib.fileset.fromSource`.
+[[:blank:]]*Note that this only works for sources created from paths.'
# Path coercion errors for non-existent paths
expectFailure 'toSource { root = ./.; fileset = ./a; }' 'lib.fileset.toSource: `fileset` \('"$work"'/a\) is a path that does not exist.
-\s*To create a file set from a path that may not exist, use `lib.fileset.maybeMissing`.'
+[[:blank:]]*To create a file set from a path that may not exist, use `lib.fileset.maybeMissing`.'
# File sets cannot be evaluated directly
expectFailure 'union ./. ./.' 'lib.fileset: Directly evaluating a file set is not supported.
-\s*To turn it into a usable source, use `lib.fileset.toSource`.
-\s*To pretty-print the contents, use `lib.fileset.trace` or `lib.fileset.traceVal`.'
+[[:blank:]]*To turn it into a usable source, use `lib.fileset.toSource`.
+[[:blank:]]*To pretty-print the contents, use `lib.fileset.trace` or `lib.fileset.traceVal`.'
expectFailure '_emptyWithoutBase' 'lib.fileset: Directly evaluating a file set is not supported.
-\s*To turn it into a usable source, use `lib.fileset.toSource`.
-\s*To pretty-print the contents, use `lib.fileset.trace` or `lib.fileset.traceVal`.'
+[[:blank:]]*To turn it into a usable source, use `lib.fileset.toSource`.
+[[:blank:]]*To pretty-print the contents, use `lib.fileset.trace` or `lib.fileset.traceVal`.'
# Past versions of the internal representation are supported
expectEqual '_coerce "<tests>: value" { _type = "fileset"; _internalVersion = 0; _internalBase = ./.; }' \
@@ -423,9 +427,9 @@ expectEqual '_coerce "<tests>: value" { _type = "fileset"; _internalVersion = 2;
# Future versions of the internal representation are unsupported
expectFailure '_coerce "<tests>: value" { _type = "fileset"; _internalVersion = 4; }' '<tests>: value is a file set created from a future version of the file set library with a different internal representation:
-\s*- Internal version of the file set: 4
-\s*- Internal version of the library: 3
-\s*Make sure to update your Nixpkgs to have a newer version of `lib.fileset`.'
+[[:blank:]]*- Internal version of the file set: 4
+[[:blank:]]*- Internal version of the library: 3
+[[:blank:]]*Make sure to update your Nixpkgs to have a newer version of `lib.fileset`.'
# _create followed by _coerce should give the inputs back without any validation
expectEqual '{
@@ -539,16 +543,16 @@ 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: Filesystem root is "'"$work"'/foo/mock-root"
-\s*Second argument: Filesystem root is "'"$work"'/bar/mock-root"
-\s*Different filesystem roots are not supported.'
+[[:blank:]]*First argument: Filesystem root is "'"$work"'/foo/mock-root"
+[[:blank:]]*Second argument: Filesystem root is "'"$work"'/bar/mock-root"
+[[:blank:]]*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: Filesystem root is "'"$work"'/foo/mock-root"
-\s*Element 1: Filesystem root is "'"$work"'/bar/mock-root"
-\s*Different filesystem roots are not supported.'
+[[:blank:]]*Element 0: Filesystem root is "'"$work"'/foo/mock-root"
+[[:blank:]]*Element 1: Filesystem root is "'"$work"'/bar/mock-root"
+[[:blank:]]*Different filesystem roots are not supported.'
rm -rf -- *
# Coercion errors show the correct context
@@ -652,9 +656,9 @@ 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: Filesystem root is "'"$work"'/foo/mock-root"
-\s*Second argument: Filesystem root is "'"$work"'/bar/mock-root"
-\s*Different filesystem roots are not supported.'
+[[:blank:]]*First argument: Filesystem root is "'"$work"'/foo/mock-root"
+[[:blank:]]*Second argument: Filesystem root is "'"$work"'/bar/mock-root"
+[[:blank:]]*Different filesystem roots are not supported.'
rm -rf -- *
# Coercion errors show the correct context
@@ -761,8 +765,8 @@ rm -rf -- *
# Also not the other way around
mkdir a
expectFailure 'toSource { root = ./a; fileset = difference ./. ./a; }' '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.'
+[[:blank:]]*- Set `root` to '"$work"' or any directory higher up. This changes the layout of the resulting store path.
+[[:blank:]]*- 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 -- *
# Difference actually works
@@ -839,7 +843,7 @@ expectFailure 'fileFilter null (abort "this is not needed")' 'lib.fileset.fileFi
# The second argument needs to be an existing path
expectFailure 'fileFilter (file: abort "this is not needed") _emptyWithoutBase' 'lib.fileset.fileFilter: Second argument is a file set, but it should be a path instead.
-\s*If you need to filter files in a file set, use `intersection fileset \(fileFilter pred \./\.\)` instead.'
+[[:blank:]]*If you need to filter files in a file set, use `intersection fileset \(fileFilter pred \./\.\)` instead.'
expectFailure 'fileFilter (file: abort "this is not needed") null' 'lib.fileset.fileFilter: Second argument is of type null, but it should be a path instead.'
expectFailure 'fileFilter (file: abort "this is not needed") ./a' 'lib.fileset.fileFilter: Second argument \('"$work"'/a\) is a path that does not exist.'
@@ -1103,7 +1107,7 @@ rm -rf -- *
# String-like values are not supported
expectFailure 'fromSource (lib.cleanSource "")' 'lib.fileset.fromSource: The source origin of the argument is a string-like value \(""\), but it should be a path instead.
-\s*Sources created from paths in strings cannot be turned into file sets, use `lib.sources` or derivations instead.'
+[[:blank:]]*Sources created from paths in strings cannot be turned into file sets, use `lib.sources` or derivations instead.'
# Wrong type
expectFailure 'fromSource null' 'lib.fileset.fromSource: The source origin of the argument is of type null, but it should be a path instead.'
@@ -1420,10 +1424,10 @@ expectEqual '(import '"$storePath"' { fs = lib.fileset; }).outPath' \""$storePat
## But it fails if the path is imported with a fetcher that doesn't remove .git (like just using "${./.}")
expectFailure 'import "${./.}" { fs = lib.fileset; }' 'lib.fileset.gitTracked: The argument \(.*\) is a store path within a working tree of a Git repository.
-\s*This indicates that a source directory was imported into the store using a method such as `import "\$\{./.\}"` or `path:.`.
-\s*This function currently does not support such a use case, since it currently relies on `builtins.fetchGit`.
-\s*You could make this work by using a fetcher such as `fetchGit` instead of copying the whole repository.
-\s*If you can'\''t avoid copying the repo to the store, see https://github.com/NixOS/nix/issues/9292.'
+[[:blank:]]*This indicates that a source directory was imported into the store using a method such as `import "\$\{./.\}"` or `path:.`.
+[[:blank:]]*This function currently does not support such a use case, since it currently relies on `builtins.fetchGit`.
+[[:blank:]]*You could make this work by using a fetcher such as `fetchGit` instead of copying the whole repository.
+[[:blank:]]*If you can'\''t avoid copying the repo to the store, see https://github.com/NixOS/nix/issues/9292.'
## Even with submodules
if [[ -n "$fetchGitSupportsSubmodules" ]]; then
@@ -1447,15 +1451,15 @@ if [[ -n "$fetchGitSupportsSubmodules" ]]; then
## But it fails if the path is imported with a fetcher that doesn't remove .git (like just using "${./.}")
expectFailure 'import "${./.}" { fs = lib.fileset; }' 'lib.fileset.gitTrackedWith: The second argument \(.*\) is a store path within a working tree of a Git repository.
- \s*This indicates that a source directory was imported into the store using a method such as `import "\$\{./.\}"` or `path:.`.
- \s*This function currently does not support such a use case, since it currently relies on `builtins.fetchGit`.
- \s*You could make this work by using a fetcher such as `fetchGit` instead of copying the whole repository.
- \s*If you can'\''t avoid copying the repo to the store, see https://github.com/NixOS/nix/issues/9292.'
+ [[:blank:]]*This indicates that a source directory was imported into the store using a method such as `import "\$\{./.\}"` or `path:.`.
+ [[:blank:]]*This function currently does not support such a use case, since it currently relies on `builtins.fetchGit`.
+ [[:blank:]]*You could make this work by using a fetcher such as `fetchGit` instead of copying the whole repository.
+ [[:blank:]]*If you can'\''t avoid copying the repo to the store, see https://github.com/NixOS/nix/issues/9292.'
expectFailure 'import "${./.}/sub" { fs = lib.fileset; }' 'lib.fileset.gitTracked: The argument \(.*/sub\) is a store path within a working tree of a Git repository.
- \s*This indicates that a source directory was imported into the store using a method such as `import "\$\{./.\}"` or `path:.`.
- \s*This function currently does not support such a use case, since it currently relies on `builtins.fetchGit`.
- \s*You could make this work by using a fetcher such as `fetchGit` instead of copying the whole repository.
- \s*If you can'\''t avoid copying the repo to the store, see https://github.com/NixOS/nix/issues/9292.'
+ [[:blank:]]*This indicates that a source directory was imported into the store using a method such as `import "\$\{./.\}"` or `path:.`.
+ [[:blank:]]*This function currently does not support such a use case, since it currently relies on `builtins.fetchGit`.
+ [[:blank:]]*You could make this work by using a fetcher such as `fetchGit` instead of copying the whole repository.
+ [[:blank:]]*If you can'\''t avoid copying the repo to the store, see https://github.com/NixOS/nix/issues/9292.'
fi
rm -rf -- *