1
0
Fork 1
mirror of https://github.com/NixOS/nixpkgs.git synced 2025-06-09 17:46:29 +09:00

lib.fileset.toSource: Improve error for unknown file types

This does decrease performance unfortunately

Benchmarking expression toSource { root = ./.; fileset = ./.; }
Mean CPU time 0.103747 (σ = 0.012415) for 10 runs is 97.32181384964636% (σ = 16.34179537413021%) of the old value 0.106602 (σ = 0.0125571)
Statistic .envs.elements (205920) is 105.5842% (+10891) of the old value 195029
Statistic .gc.totalBytes (20247696) is 101.7495% (+348160) of the old value 19899536
Statistic .nrThunks (134824) is 108.7878% (+10891) of the old value 123933
Statistic .symbols.number (996) is 100.1005% (+1) of the old value 995
Statistic .values.number (275238) is 104.1199% (+10891) of the old value 264347
This commit is contained in:
Silvan Mosberger 2023-10-26 01:56:42 +02:00
parent 88f736f871
commit 0f6cc8018c
2 changed files with 33 additions and 20 deletions

View file

@ -424,7 +424,7 @@ rec {
# Filter suited when there's some files # Filter suited when there's some files
# This can't be used for when there's no files, because the base directory is always included # This can't be used for when there's no files, because the base directory is always included
nonEmpty = nonEmpty =
path: _: path: type:
let let
# Add a slash to the path string, turning "/foo" to "/foo/", # Add a slash to the path string, turning "/foo" to "/foo/",
# making sure to not have any false prefix matches below. # making sure to not have any false prefix matches below.
@ -432,26 +432,37 @@ rec {
# but builtins.path doesn't call the filter function on the `path` argument itself, # but builtins.path doesn't call the filter function on the `path` argument itself,
# meaning this function can never receive "/" as an argument # meaning this function can never receive "/" as an argument
pathSlash = path + "/"; pathSlash = path + "/";
include =
# Same as `hasPrefix pathSlash baseString`, but more efficient.
# With base /foo/bar we need to include /foo:
# hasPrefix "/foo/" "/foo/bar/"
if substring 0 (stringLength pathSlash) baseString == pathSlash then
true
# Same as `! hasPrefix baseString pathSlash`, but more efficient.
# With base /foo/bar we need to exclude /baz
# ! hasPrefix "/baz/" "/foo/bar/"
else if substring 0 baseLength pathSlash != baseString then
false
else
# Same as `removePrefix baseString path`, but more efficient.
# From the above code we know that hasPrefix baseString pathSlash holds, so this is safe.
# We don't use pathSlash here because we only needed the trailing slash for the prefix matching.
# With base /foo and path /foo/bar/baz this gives
# inTree (split "/" (removePrefix "/foo/" "/foo/bar/baz"))
# == inTree (split "/" "bar/baz")
# == inTree [ "bar" "baz" ]
inTree (split "/" (substring baseLength (-1) path));
in in
# Same as `hasPrefix pathSlash baseString`, but more efficient. # This relies on the fact that Nix only distinguishes path types "directory", "regular", "symlink" and "unknown",
# With base /foo/bar we need to include /foo: # so everything except "unknown" is allowed, seems reasonable to rely on that
# hasPrefix "/foo/" "/foo/bar/" if include && type == "unknown" then
if substring 0 (stringLength pathSlash) baseString == pathSlash then throw ''
true lib.fileset.toSource: `fileset` contains a file that cannot be added to the store: ${path}
# Same as `! hasPrefix baseString pathSlash`, but more efficient. This file is neither a regular file nor a symlink, the only file types supported by the Nix store.
# With base /foo/bar we need to exclude /baz Therefore the file set cannot be added to the Nix store as is. Make sure to not include that file to avoid this error.''
# ! hasPrefix "/baz/" "/foo/bar/"
else if substring 0 baseLength pathSlash != baseString then
false
else else
# Same as `removePrefix baseString path`, but more efficient. include;
# From the above code we know that hasPrefix baseString pathSlash holds, so this is safe.
# We don't use pathSlash here because we only needed the trailing slash for the prefix matching.
# With base /foo and path /foo/bar/baz this gives
# inTree (split "/" (removePrefix "/foo/" "/foo/bar/baz"))
# == inTree (split "/" "bar/baz")
# == inTree [ "bar" "baz" ]
inTree (split "/" (substring baseLength (-1) path));
in in
# Special case because the code below assumes that the _internalBase is always included in the result # Special case because the code below assumes that the _internalBase is always included in the result
# which shouldn't be done when we have no files at all in the base # which shouldn't be done when we have no files at all in the base

View file

@ -356,7 +356,9 @@ rm -rf -- *
# non-regular and non-symlink files cannot be added to the Nix store # non-regular and non-symlink files cannot be added to the Nix store
mkfifo a mkfifo a
expectFailure 'toSource { root = ./.; fileset = ./a; }' 'file '\'"$work"'/a'\'' has an unsupported type' 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.'
rm -rf -- * rm -rf -- *
# Path coercion only works for paths # Path coercion only works for paths