lib.strings: Deprecate path prefix/suffix/infix arguments

lib.{hasPrefix,hasInfix,hasSuffix} would otherwise return an
always-false result, which can be very unexpected:

    nix-repl> lib.strings.hasPrefix ./lib ./lib/meta.nix
    false
This commit is contained in:
Silvan Mosberger 2023-03-14 23:28:48 +01:00
parent a770c0393c
commit 99bc90e301

View File

@ -2,7 +2,9 @@
{ lib }: { lib }:
let let
inherit (builtins) length; inherit (builtins) length;
inherit (lib.trivial) warnIf;
in in
@ -238,7 +240,17 @@ rec {
# Prefix to check for # Prefix to check for
pref: pref:
# Input string # Input string
str: substring 0 (stringLength pref) str == pref; str:
# Before 23.05, paths would be copied to the store before converting them
# to strings and comparing. This was surprising and confusing.
warnIf
(isPath pref)
''
lib.strings.hasPrefix: The first argument (${toString pref}) is a path value, but only strings are supported.
There is almost certainly a bug in the calling code, since this function always returns `false` in such a case.
This function also copies the path to the Nix store, which may not be what you want.
This behavior is deprecated and will throw an error in the future.''
(substring 0 (stringLength pref) str == pref);
/* Determine whether a string has given suffix. /* Determine whether a string has given suffix.
@ -258,8 +270,20 @@ rec {
let let
lenContent = stringLength content; lenContent = stringLength content;
lenSuffix = stringLength suffix; lenSuffix = stringLength suffix;
in lenContent >= lenSuffix && in
substring (lenContent - lenSuffix) lenContent content == suffix; # Before 23.05, paths would be copied to the store before converting them
# to strings and comparing. This was surprising and confusing.
warnIf
(isPath suffix)
''
lib.strings.hasSuffix: The first argument (${toString suffix}) is a path value, but only strings are supported.
There is almost certainly a bug in the calling code, since this function always returns `false` in such a case.
This function also copies the path to the Nix store, which may not be what you want.
This behavior is deprecated and will throw an error in the future.''
(
lenContent >= lenSuffix
&& substring (lenContent - lenSuffix) lenContent content == suffix
);
/* Determine whether a string contains the given infix /* Determine whether a string contains the given infix
@ -276,7 +300,16 @@ rec {
=> false => false
*/ */
hasInfix = infix: content: hasInfix = infix: content:
builtins.match ".*${escapeRegex infix}.*" "${content}" != null; # Before 23.05, paths would be copied to the store before converting them
# to strings and comparing. This was surprising and confusing.
warnIf
(isPath infix)
''
lib.strings.hasInfix: The first argument (${toString infix}) is a path value, but only strings are supported.
There is almost certainly a bug in the calling code, since this function always returns `false` in such a case.
This function also copies the path to the Nix store, which may not be what you want.
This behavior is deprecated and will throw an error in the future.''
(builtins.match ".*${escapeRegex infix}.*" "${content}" != null);
/* Convert a string to a list of characters (i.e. singleton strings). /* Convert a string to a list of characters (i.e. singleton strings).
This allows you to, e.g., map a function over each character. However, This allows you to, e.g., map a function over each character. However,