about summary refs log tree commit diff
path: root/lib/strings.nix
diff options
context:
space:
mode:
authorSilvan Mosberger <silvan.mosberger@tweag.io>2023-03-14 23:28:48 +0100
committerSilvan Mosberger <silvan.mosberger@tweag.io>2023-03-15 19:42:43 +0100
commit99bc90e3019cd79de82b41481fe1cc2ef4900caa (patch)
tree61554652c6c0854845de8b1b9fe0020662f842bb /lib/strings.nix
parenta770c0393cb52777794c01cdb5a412883a732c19 (diff)
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
Diffstat (limited to 'lib/strings.nix')
-rw-r--r--lib/strings.nix43
1 files changed, 38 insertions, 5 deletions
diff --git a/lib/strings.nix b/lib/strings.nix
index 68d9309506625..963d937947f2b 100644
--- a/lib/strings.nix
+++ b/lib/strings.nix
@@ -2,7 +2,9 @@
 { lib }:
 let
 
-inherit (builtins) length;
+  inherit (builtins) length;
+
+  inherit (lib.trivial) warnIf;
 
 in
 
@@ -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.
 
@@ -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
 
@@ -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,