From ffd6f0ed80e9b9f3eac99fca818ebc84ef6a2a3b Mon Sep 17 00:00:00 2001 From: Sigurd Meldgaard Date: Thu, 11 Apr 2024 13:45:16 +0000 Subject: [PATCH] Improve yaml serialization quoting --- lib/src/source/path.dart | 2 +- lib/src/utils.dart | 30 ++++++++++++++----- .../Adding transitive.txt | 6 ++-- .../Can update a git package.txt | 16 +++++----- .../dependency_services_test/Compatible.txt | 12 ++++---- .../Finds smallest possible upgrade.txt | 4 +-- .../Ignoring version.txt | 4 +-- .../Preserves no content-hashes.txt | 12 ++++---- ...eserves pub.dartlang.org as hosted url.txt | 8 ++--- .../Relative paths are allowed.txt | 8 ++--- .../Removing transitive.txt | 6 ++-- ...le upgrade can upgrade beyond breaking.txt | 4 +-- ...e can upgrade other packages if needed.txt | 8 ++--- .../multibreaking.txt | 12 ++++---- ...--verbose and on unexpected exceptions.txt | 6 ++-- test/utils_test.dart | 17 ++++++++++- 16 files changed, 93 insertions(+), 62 deletions(-) diff --git a/lib/src/source/path.dart b/lib/src/source/path.dart index e0451ef8f..0607cbf0d 100644 --- a/lib/src/source/path.dart +++ b/lib/src/source/path.dart @@ -327,7 +327,7 @@ class ResolvedPathDescription extends ResolvedDescription { 'relative': true, }; } - return {'path': description.path, 'relative': p.relative('false')}; + return {'path': description.path, 'relative': false}; } @override diff --git a/lib/src/utils.dart b/lib/src/utils.dart index 3093fce6b..a8871692f 100644 --- a/lib/src/utils.dart +++ b/lib/src/utils.dart @@ -504,11 +504,27 @@ String prefixLines(String text, {String prefix = '| ', String? firstPrefix}) { return lines.join('\n'); } -/// The subset of strings that don't need quoting in YAML. -/// -/// This pattern does not strictly follow the plain scalar grammar of YAML, -/// which means some strings may be unnecessarily quoted, but it's much simpler. -final _unquotableYamlString = RegExp(r'^[a-zA-Z_-][a-zA-Z_0-9-]*$'); +/// Does this string need quoting in yaml? +/// +/// This mechanism does not strictly follow the plain scalar grammar of YAML, +/// which means some strings may be unnecessarily quoted. +bool _needsYamlQuotes(String s) { + // These must be quoted + if ([ + 'true', 'True', 'TRUE', // + 'false', 'False', 'FALSE', + 'null', 'Null', 'NULL', + ].contains(s)) return true; + // Numbers must be quoted + if (RegExp(r'^[-+]?[0-9]*\.?[0-9]*(e[0-9]+)?$').hasMatch(s)) return true; + // Hex numbers must be quoted + if (RegExp(r'^0x[0-9]+$').hasMatch(s)) return true; + + // Single non-number words containing a few special cases are ok. + if (RegExp(r'^[\.a-zA-Z_0-9-]+$').hasMatch(s)) return false; + // We are unsure, better safe than sorry + return true; +} /// Converts [data], which is a parsed YAML object, to a pretty-printed string, /// using indentation for maps. @@ -536,7 +552,7 @@ String yamlToString(Object? data) { first = false; var keyString = key; - if (key is! String || !_unquotableYamlString.hasMatch(key)) { + if (key is! String || _needsYamlQuotes(key)) { keyString = jsonEncode(key); } @@ -552,7 +568,7 @@ String yamlToString(Object? data) { var string = data; // Don't quote plain strings if not needed. - if (data is! String || !_unquotableYamlString.hasMatch(data)) { + if (data is! String || _needsYamlQuotes(data)) { string = jsonEncode(data); } diff --git a/test/testdata/goldens/dependency_services/dependency_services_test/Adding transitive.txt b/test/testdata/goldens/dependency_services/dependency_services_test/Adding transitive.txt index f2f3493bb..03c682364 100644 --- a/test/testdata/goldens/dependency_services/dependency_services_test/Adding transitive.txt +++ b/test/testdata/goldens/dependency_services/dependency_services_test/Adding transitive.txt @@ -13,7 +13,7 @@ packages: sha256: $SHA256 url: "http://localhost:$PORT" source: hosted - version: "1.2.3" + version: 1.2.3 sdks: dart: ">=3.0.2 <4.0.0" -------------------------------- END OF OUTPUT --------------------------------- @@ -179,7 +179,7 @@ packages: sha256: $SHA256 url: "http://localhost:$PORT" source: hosted - version: "2.2.3" + version: 2.2.3 transitive: dependency: transitive description: @@ -187,6 +187,6 @@ packages: sha256: $SHA256 url: "http://localhost:$PORT" source: hosted - version: "1.0.0" + version: 1.0.0 sdks: dart: ">=3.0.2 <4.0.0" diff --git a/test/testdata/goldens/dependency_services/dependency_services_test/Can update a git package.txt b/test/testdata/goldens/dependency_services/dependency_services_test/Can update a git package.txt index da10be460..6dc7e02eb 100644 --- a/test/testdata/goldens/dependency_services/dependency_services_test/Can update a git package.txt +++ b/test/testdata/goldens/dependency_services/dependency_services_test/Can update a git package.txt @@ -11,19 +11,19 @@ packages: description: path: "." ref: HEAD - resolved-ref: "1ea665d6de007c60308949db4c6ae8049c2395f0" + resolved-ref: 1ea665d6de007c60308949db4c6ae8049c2395f0 url: "../bar.git" source: git - version: "1.0.0" + version: 1.0.0 foo: dependency: "direct main" description: path: "." ref: HEAD - resolved-ref: "9e8b8ad5091bec2c4724b1e0c8ff9d6e32a7eaa4" + resolved-ref: 9e8b8ad5091bec2c4724b1e0c8ff9d6e32a7eaa4 url: "../foo.git" source: git - version: "1.0.0" + version: 1.0.0 sdks: dart: ">=3.0.2 <4.0.0" -------------------------------- END OF OUTPUT --------------------------------- @@ -218,18 +218,18 @@ packages: description: path: "." ref: HEAD - resolved-ref: "1ea665d6de007c60308949db4c6ae8049c2395f0" + resolved-ref: 1ea665d6de007c60308949db4c6ae8049c2395f0 url: "../bar.git" source: git - version: "1.0.0" + version: 1.0.0 foo: dependency: "direct main" description: path: "." ref: HEAD - resolved-ref: "385bb2860e7ebf9519993b2548d6cab74a6008ef" + resolved-ref: 385bb2860e7ebf9519993b2548d6cab74a6008ef url: "../foo.git" source: git - version: "2.0.0" + version: 2.0.0 sdks: dart: ">=3.0.2 <4.0.0" diff --git a/test/testdata/goldens/dependency_services/dependency_services_test/Compatible.txt b/test/testdata/goldens/dependency_services/dependency_services_test/Compatible.txt index c2103f3c6..bd182a23e 100644 --- a/test/testdata/goldens/dependency_services/dependency_services_test/Compatible.txt +++ b/test/testdata/goldens/dependency_services/dependency_services_test/Compatible.txt @@ -13,7 +13,7 @@ packages: sha256: $SHA256 url: "http://localhost:$PORT" source: hosted - version: "1.2.3" + version: 1.2.3 boo: dependency: "direct main" description: @@ -21,7 +21,7 @@ packages: sha256: $SHA256 url: "http://localhost:$PORT" source: hosted - version: "1.2.3" + version: 1.2.3 foo: dependency: "direct main" description: @@ -29,7 +29,7 @@ packages: sha256: $SHA256 url: "http://localhost:$PORT" source: hosted - version: "1.2.3" + version: 1.2.3 sdks: dart: ">=3.0.2 <4.0.0" -------------------------------- END OF OUTPUT --------------------------------- @@ -383,7 +383,7 @@ packages: sha256: $SHA256 url: "http://localhost:$PORT" source: hosted - version: "1.2.3" + version: 1.2.3 boo: dependency: "direct main" description: @@ -391,7 +391,7 @@ packages: sha256: $SHA256 url: "http://localhost:$PORT" source: hosted - version: "1.2.3" + version: 1.2.3 foo: dependency: "direct main" description: @@ -399,6 +399,6 @@ packages: sha256: $SHA256 url: "http://localhost:$PORT" source: hosted - version: "1.2.4" + version: 1.2.4 sdks: dart: ">=3.0.2 <4.0.0" diff --git a/test/testdata/goldens/dependency_services/dependency_services_test/Finds smallest possible upgrade.txt b/test/testdata/goldens/dependency_services/dependency_services_test/Finds smallest possible upgrade.txt index a0ebdc7c6..d38a8d0ae 100644 --- a/test/testdata/goldens/dependency_services/dependency_services_test/Finds smallest possible upgrade.txt +++ b/test/testdata/goldens/dependency_services/dependency_services_test/Finds smallest possible upgrade.txt @@ -13,7 +13,7 @@ packages: sha256: $SHA256 url: "http://localhost:$PORT" source: hosted - version: "1.1.1" + version: 1.1.1 sdks: dart: ">=3.0.2 <4.0.0" -------------------------------- END OF OUTPUT --------------------------------- @@ -167,6 +167,6 @@ packages: sha256: $SHA256 url: "http://localhost:$PORT" source: hosted - version: "1.1.1" + version: 1.1.1 sdks: dart: ">=3.0.2 <4.0.0" diff --git a/test/testdata/goldens/dependency_services/dependency_services_test/Ignoring version.txt b/test/testdata/goldens/dependency_services/dependency_services_test/Ignoring version.txt index b8a6a3a6d..d23f2117a 100644 --- a/test/testdata/goldens/dependency_services/dependency_services_test/Ignoring version.txt +++ b/test/testdata/goldens/dependency_services/dependency_services_test/Ignoring version.txt @@ -13,7 +13,7 @@ packages: sha256: $SHA256 url: "http://localhost:$PORT" source: hosted - version: "1.0.0" + version: 1.0.0 sdks: dart: ">=3.0.2 <4.0.0" -------------------------------- END OF OUTPUT --------------------------------- @@ -112,6 +112,6 @@ packages: sha256: $SHA256 url: "http://localhost:$PORT" source: hosted - version: "1.0.0" + version: 1.0.0 sdks: dart: ">=3.0.2 <4.0.0" diff --git a/test/testdata/goldens/dependency_services/dependency_services_test/Preserves no content-hashes.txt b/test/testdata/goldens/dependency_services/dependency_services_test/Preserves no content-hashes.txt index 9a9a21c1e..fb893ec2f 100644 --- a/test/testdata/goldens/dependency_services/dependency_services_test/Preserves no content-hashes.txt +++ b/test/testdata/goldens/dependency_services/dependency_services_test/Preserves no content-hashes.txt @@ -12,21 +12,21 @@ packages: name: bar url: "http://localhost:$PORT" source: hosted - version: "1.2.3" + version: 1.2.3 boo: dependency: "direct main" description: name: boo url: "http://localhost:$PORT" source: hosted - version: "1.2.3" + version: 1.2.3 foo: dependency: "direct main" description: name: foo url: "http://localhost:$PORT" source: hosted - version: "1.2.3" + version: 1.2.3 sdks: dart: ">=3.0.2 <4.0.0" -------------------------------- END OF OUTPUT --------------------------------- @@ -365,20 +365,20 @@ packages: name: bar url: "http://localhost:$PORT" source: hosted - version: "1.2.3" + version: 1.2.3 boo: dependency: "direct main" description: name: boo url: "http://localhost:$PORT" source: hosted - version: "1.2.3" + version: 1.2.3 foo: dependency: "direct main" description: name: foo url: "http://localhost:$PORT" source: hosted - version: "1.2.4" + version: 1.2.4 sdks: dart: ">=3.0.2 <4.0.0" diff --git a/test/testdata/goldens/dependency_services/dependency_services_test/Preserves pub.dartlang.org as hosted url.txt b/test/testdata/goldens/dependency_services/dependency_services_test/Preserves pub.dartlang.org as hosted url.txt index fe5e2cabb..c6097e165 100644 --- a/test/testdata/goldens/dependency_services/dependency_services_test/Preserves pub.dartlang.org as hosted url.txt +++ b/test/testdata/goldens/dependency_services/dependency_services_test/Preserves pub.dartlang.org as hosted url.txt @@ -13,7 +13,7 @@ packages: sha256: $SHA256 url: https://pub.dartlang.org source: hosted - version: "1.2.3" + version: 1.2.3 foo: dependency: "direct main" description: @@ -21,7 +21,7 @@ packages: sha256: $SHA256 url: https://pub.dartlang.org source: hosted - version: "1.2.3" + version: 1.2.3 sdks: dart: ">=3.0.2 <4.0.0" -------------------------------- END OF OUTPUT --------------------------------- @@ -339,7 +339,7 @@ packages: sha256: $SHA256 url: "https://pub.dartlang.org" source: hosted - version: "1.2.3" + version: 1.2.3 foo: dependency: "direct main" description: @@ -347,6 +347,6 @@ packages: sha256: $SHA256 url: "https://pub.dartlang.org" source: hosted - version: "1.2.4" + version: 1.2.4 sdks: dart: ">=3.0.2 <4.0.0" diff --git a/test/testdata/goldens/dependency_services/dependency_services_test/Relative paths are allowed.txt b/test/testdata/goldens/dependency_services/dependency_services_test/Relative paths are allowed.txt index 2537b1185..3b57b574d 100644 --- a/test/testdata/goldens/dependency_services/dependency_services_test/Relative paths are allowed.txt +++ b/test/testdata/goldens/dependency_services/dependency_services_test/Relative paths are allowed.txt @@ -12,7 +12,7 @@ packages: path: "../bar" relative: true source: path - version: "1.0.0" + version: 1.0.0 foo: dependency: "direct main" description: @@ -20,7 +20,7 @@ packages: sha256: $SHA256 url: "http://localhost:$PORT" source: hosted - version: "1.0.0" + version: 1.0.0 sdks: dart: ">=3.0.2 <4.0.0" -------------------------------- END OF OUTPUT --------------------------------- @@ -177,7 +177,7 @@ packages: path: "../bar" relative: true source: path - version: "1.0.0" + version: 1.0.0 foo: dependency: "direct main" description: @@ -185,6 +185,6 @@ packages: sha256: $SHA256 url: "http://localhost:$PORT" source: hosted - version: "2.0.0" + version: 2.0.0 sdks: dart: ">=3.0.2 <4.0.0" diff --git a/test/testdata/goldens/dependency_services/dependency_services_test/Removing transitive.txt b/test/testdata/goldens/dependency_services/dependency_services_test/Removing transitive.txt index b665f33f6..15df21927 100644 --- a/test/testdata/goldens/dependency_services/dependency_services_test/Removing transitive.txt +++ b/test/testdata/goldens/dependency_services/dependency_services_test/Removing transitive.txt @@ -13,7 +13,7 @@ packages: sha256: $SHA256 url: "http://localhost:$PORT" source: hosted - version: "1.2.3" + version: 1.2.3 transitive: dependency: transitive description: @@ -21,7 +21,7 @@ packages: sha256: $SHA256 url: "http://localhost:$PORT" source: hosted - version: "1.0.0" + version: 1.0.0 sdks: dart: ">=3.0.2 <4.0.0" -------------------------------- END OF OUTPUT --------------------------------- @@ -217,6 +217,6 @@ packages: sha256: $SHA256 url: "http://localhost:$PORT" source: hosted - version: "2.2.3" + version: 2.2.3 sdks: dart: ">=3.0.2 <4.0.0" diff --git a/test/testdata/goldens/dependency_services/dependency_services_test/Smallest possible upgrade can upgrade beyond breaking.txt b/test/testdata/goldens/dependency_services/dependency_services_test/Smallest possible upgrade can upgrade beyond breaking.txt index 6d36fc762..c333cc540 100644 --- a/test/testdata/goldens/dependency_services/dependency_services_test/Smallest possible upgrade can upgrade beyond breaking.txt +++ b/test/testdata/goldens/dependency_services/dependency_services_test/Smallest possible upgrade can upgrade beyond breaking.txt @@ -13,7 +13,7 @@ packages: sha256: $SHA256 url: "http://localhost:$PORT" source: hosted - version: "1.1.1" + version: 1.1.1 sdks: dart: ">=3.0.2 <4.0.0" -------------------------------- END OF OUTPUT --------------------------------- @@ -140,6 +140,6 @@ packages: sha256: $SHA256 url: "http://localhost:$PORT" source: hosted - version: "1.1.1" + version: 1.1.1 sdks: dart: ">=3.0.2 <4.0.0" diff --git a/test/testdata/goldens/dependency_services/dependency_services_test/Smallest possible upgrade can upgrade other packages if needed.txt b/test/testdata/goldens/dependency_services/dependency_services_test/Smallest possible upgrade can upgrade other packages if needed.txt index 2270a2286..c02b9e554 100644 --- a/test/testdata/goldens/dependency_services/dependency_services_test/Smallest possible upgrade can upgrade other packages if needed.txt +++ b/test/testdata/goldens/dependency_services/dependency_services_test/Smallest possible upgrade can upgrade other packages if needed.txt @@ -13,7 +13,7 @@ packages: sha256: $SHA256 url: "http://localhost:$PORT" source: hosted - version: "1.0.0" + version: 1.0.0 foo: dependency: "direct main" description: @@ -21,7 +21,7 @@ packages: sha256: $SHA256 url: "http://localhost:$PORT" source: hosted - version: "1.1.1" + version: 1.1.1 sdks: dart: ">=3.0.2 <4.0.0" -------------------------------- END OF OUTPUT --------------------------------- @@ -173,7 +173,7 @@ packages: sha256: $SHA256 url: "http://localhost:$PORT" source: hosted - version: "1.0.0" + version: 1.0.0 foo: dependency: "direct main" description: @@ -181,6 +181,6 @@ packages: sha256: $SHA256 url: "http://localhost:$PORT" source: hosted - version: "1.1.1" + version: 1.1.1 sdks: dart: ">=3.0.2 <4.0.0" diff --git a/test/testdata/goldens/dependency_services/dependency_services_test/multibreaking.txt b/test/testdata/goldens/dependency_services/dependency_services_test/multibreaking.txt index 7f4e8f9b0..a84f2b01d 100644 --- a/test/testdata/goldens/dependency_services/dependency_services_test/multibreaking.txt +++ b/test/testdata/goldens/dependency_services/dependency_services_test/multibreaking.txt @@ -13,7 +13,7 @@ packages: sha256: $SHA256 url: "http://localhost:$PORT" source: hosted - version: "1.0.0" + version: 1.0.0 baz: dependency: "direct main" description: @@ -21,7 +21,7 @@ packages: sha256: $SHA256 url: "http://localhost:$PORT" source: hosted - version: "1.0.0" + version: 1.0.0 foo: dependency: "direct main" description: @@ -29,7 +29,7 @@ packages: sha256: $SHA256 url: "http://localhost:$PORT" source: hosted - version: "1.0.0" + version: 1.0.0 sdks: dart: ">=3.0.2 <4.0.0" -------------------------------- END OF OUTPUT --------------------------------- @@ -381,7 +381,7 @@ packages: sha256: $SHA256 url: "http://localhost:$PORT" source: hosted - version: "2.0.0" + version: 2.0.0 baz: dependency: "direct main" description: @@ -389,7 +389,7 @@ packages: sha256: $SHA256 url: "http://localhost:$PORT" source: hosted - version: "1.0.0" + version: 1.0.0 foo: dependency: "direct main" description: @@ -397,6 +397,6 @@ packages: sha256: $SHA256 url: "http://localhost:$PORT" source: hosted - version: "3.0.1" + version: 3.0.1 sdks: dart: ">=3.0.2 <4.0.0" diff --git a/test/testdata/goldens/embedding/embedding_test/logfile is written with --verbose and on unexpected exceptions.txt b/test/testdata/goldens/embedding/embedding_test/logfile is written with --verbose and on unexpected exceptions.txt index bc70c20b0..2c93b7634 100644 --- a/test/testdata/goldens/embedding/embedding_test/logfile is written with --verbose and on unexpected exceptions.txt +++ b/test/testdata/goldens/embedding/embedding_test/logfile is written with --verbose and on unexpected exceptions.txt @@ -101,7 +101,7 @@ MSG : Logs written to $SANDBOX/cache/log/pub_log.txt. [E] | sha256: $SHA256 [E] | url: "http://localhost:$PORT" [E] | source: hosted -[E] | version: "1.0.0" +[E] | version: 1.0.0 [E] | sdks: [E] | dart: ">=3.0.2 <4.0.0" [E] IO : Writing $N characters to text file .dart_tool/package_config.json. @@ -160,7 +160,7 @@ packages: sha256: $SHA256 url: "http://localhost:$PORT" source: hosted - version: "1.0.0" + version: 1.0.0 sdks: dart: ">=3.0.2 <4.0.0" @@ -265,7 +265,7 @@ FINE: Contents: | sha256: $SHA256 | url: "http://localhost:$PORT" | source: hosted - | version: "1.0.0" + | version: 1.0.0 | sdks: | dart: ">=3.0.2 <4.0.0" IO : Writing $N characters to text file .dart_tool/package_config.json. diff --git a/test/utils_test.dart b/test/utils_test.dart index 1ce8869af..d139f9c64 100644 --- a/test/utils_test.dart +++ b/test/utils_test.dart @@ -13,6 +13,11 @@ void main() { expect(yamlToString(null), equals('null')); }); + test('bool', () { + expect(yamlToString(true), equals('true')); + expect(yamlToString(false), equals('false')); + }); + test('numbers', () { expect(yamlToString(123), equals('123')); expect(yamlToString(12.34), equals('12.34')); @@ -23,16 +28,26 @@ void main() { expect(yamlToString('some-string'), equals('some-string')); expect(yamlToString('hey123CAPS'), equals('hey123CAPS')); expect(yamlToString('_under_score'), equals('_under_score')); + expect(yamlToString('1abc'), equals('1abc')); }); test('quotes other strings', () { expect(yamlToString(''), equals('""')); expect(yamlToString('123'), equals('"123"')); + expect(yamlToString('12.34'), equals('"12.34"')); + expect(yamlToString('12.34'), equals('"12.34"')); + expect(yamlToString('+.34e20'), equals('"+.34e20"')); + expect(yamlToString('-01.'), equals('"-01."')); expect(yamlToString('white space'), equals('"white space"')); expect(yamlToString('"quote"'), equals(r'"\"quote\""')); expect(yamlToString("apostrophe'"), equals('"apostrophe\'"')); expect(yamlToString('new\nline'), equals(r'"new\nline"')); expect(yamlToString('?unctu@t!on'), equals(r'"?unctu@t!on"')); + expect(yamlToString('null'), equals('"null"')); + expect(yamlToString('false'), equals('"false"')); + expect(yamlToString('False'), equals('"False"')); + expect(yamlToString('FALSE'), equals('"FALSE"')); + expect(yamlToString('falSE'), equals('falSE')); }); test('lists use JSON style', () { @@ -84,7 +99,7 @@ no: 1 yamlToString(map), equals(''' 123: num -null: null +null: "null" true: bool'''), ); });