From 0b661ce32af9baa07da56b3f48fcd3ef5611b66c Mon Sep 17 00:00:00 2001 From: Naïm Favier Date: Mon, 7 Nov 2022 13:01:13 +0100 Subject: lib/generators.toPretty: escape strings properly --- lib/generators.nix | 24 +++++++++++++----------- lib/tests/misc.nix | 16 ++++++++-------- 2 files changed, 21 insertions(+), 19 deletions(-) (limited to 'lib') diff --git a/lib/generators.nix b/lib/generators.nix index 9620b8b27b9b9..06823d215e360 100644 --- a/lib/generators.nix +++ b/lib/generators.nix @@ -297,17 +297,19 @@ rec { else if isFloat v then "~${toString v}" else if isString v then let - # Separate a string into its lines - newlineSplits = filter (v: ! isList v) (builtins.split "\n" v); - # For a '' string terminated by a \n, which happens when the closing '' is on a new line - multilineResult = "''" + introSpace + concatStringsSep introSpace (lib.init newlineSplits) + outroSpace + "''"; - # For a '' string not terminated by a \n, which happens when the closing '' is not on a new line - multilineResult' = "''" + introSpace + concatStringsSep introSpace newlineSplits + "''"; - # For single lines, replace all newlines with their escaped representation - singlelineResult = "\"" + libStr.escape [ "\"" ] (concatStringsSep "\\n" newlineSplits) + "\""; - in if multiline && length newlineSplits > 1 then - if lib.last newlineSplits == "" then multilineResult else multilineResult' - else singlelineResult + lines = filter (v: ! isList v) (builtins.split "\n" v); + escapeSingleline = libStr.escape [ "\\" "\"" "\${" ]; + escapeMultiline = libStr.replaceStrings [ "\${" "''" ] [ "''\${" "'''" ]; + singlelineResult = "\"" + concatStringsSep "\\n" (map escapeSingleline lines) + "\""; + multilineResult = let + escapedLines = map escapeMultiline lines; + # The last line gets a special treatment: if it's empty, '' is on its own line at the "outer" + # indentation level. Otherwise, '' is appended to the last line. + lastLine = lib.last escapedLines; + in "''" + introSpace + concatStringsSep introSpace (lib.init escapedLines) + + (if lastLine == "" then outroSpace else introSpace + lastLine) + "''"; + in + if multiline && length lines > 1 then multilineResult else singlelineResult else if true == v then "true" else if false == v then "false" else if null == v then "null" diff --git a/lib/tests/misc.nix b/lib/tests/misc.nix index 9267e1f57694c..cfad5a3cd92a0 100644 --- a/lib/tests/misc.nix +++ b/lib/tests/misc.nix @@ -727,7 +727,7 @@ runTests { float = 0.1337; bool = true; emptystring = ""; - string = ''fno"rd''; + string = "fn\${o}\"r\\d"; newlinestring = "\n"; path = /. + "/foo"; null_ = null; @@ -735,7 +735,7 @@ runTests { functionArgs = { arg ? 4, foo }: arg; list = [ 3 4 function [ false ] ]; emptylist = []; - attrs = { foo = null; "foo bar" = "baz"; }; + attrs = { foo = null; "foo b/ar" = "baz"; }; emptyattrs = {}; drv = deriv; }; @@ -744,7 +744,7 @@ runTests { float = "~0.133700"; bool = "true"; emptystring = ''""''; - string = ''"fno\"rd"''; + string = ''"fn\''${o}\"r\\d"''; newlinestring = "\"\\n\""; path = "/foo"; null_ = "null"; @@ -752,7 +752,7 @@ runTests { functionArgs = ""; list = "[ 3 4 ${function} [ false ] ]"; emptylist = "[ ]"; - attrs = "{ foo = null; \"foo bar\" = \"baz\"; }"; + attrs = "{ foo = null; \"foo b/ar\" = \"baz\"; }"; emptyattrs = "{ }"; drv = ""; }; @@ -799,8 +799,8 @@ runTests { newlinestring = "\n"; multilinestring = '' hello - there - test + ''${there} + te'''st ''; multilinestring' = '' hello @@ -827,8 +827,8 @@ runTests { multilinestring = '' ''' hello - there - test + '''''${there} + te''''st '''''; multilinestring' = '' ''' -- cgit 1.4.1