Skip to content

Commit

Permalink
lib.strings: Deprecate path prefix/suffix/infix arguments
Browse files Browse the repository at this point in the history
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
  • Loading branch information
infinisil committed Mar 15, 2023
1 parent a770c03 commit 99bc90e
Showing 1 changed file with 38 additions and 5 deletions.
43 changes: 38 additions & 5 deletions lib/strings.nix
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
{ lib }:
let

inherit (builtins) length;
inherit (builtins) length;

inherit (lib.trivial) warnIf;

in

Expand Down Expand Up @@ -238,7 +240,17 @@ rec {
# Prefix to check for
pref:
# 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.
Expand All @@ -258,8 +270,20 @@ rec {
let
lenContent = stringLength content;
lenSuffix = stringLength suffix;
in lenContent >= lenSuffix &&
substring (lenContent - lenSuffix) lenContent content == suffix;
in
# 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
Expand All @@ -276,7 +300,16 @@ rec {
=> false
*/
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).
This allows you to, e.g., map a function over each character. However,
Expand Down

0 comments on commit 99bc90e

Please sign in to comment.