diff --git a/lib/core/extensions/harness/extension_manifest_validator.dart b/lib/core/extensions/harness/extension_manifest_validator.dart index aab84e1c..541475d4 100644 --- a/lib/core/extensions/harness/extension_manifest_validator.dart +++ b/lib/core/extensions/harness/extension_manifest_validator.dart @@ -168,7 +168,11 @@ final _semver = RegExp(r'^\d+\.\d+\.\d+(?:[+-][0-9A-Za-z.+-]+)?$'); /// as `>=0.4.0 <3.0.0`: `>=x.y.z`, `>x.y.z`, `<=x.y.z`, `= 0.4.0` reads the same as `>=0.4.0`: glue an operator to its version. + final parts = range + .trim() + .replaceAllMapped(RegExp(r'(>=|<=|>|<|=|\^)\s+'), (m) => m[1]!) + .split(RegExp(r'\s+')); if (parts.length == 1 && parts.single == '*') return true; var allowed = true; for (final part in parts) { @@ -182,8 +186,8 @@ bool? engineRangeAllows(HostVersion host, String range) { bool? _comparatorAllows(HostVersion host, String c) { try { if (c.startsWith('>=')) return host >= HostVersion.parse(c.substring(2)); - if (c.startsWith('<=')) return !(HostVersion.parse(c.substring(2)) < host); - if (c.startsWith('>')) return !(host <= HostVersion.parse(c.substring(1))); + if (c.startsWith('<=')) return host <= HostVersion.parse(c.substring(2)); + if (c.startsWith('>')) return host > HostVersion.parse(c.substring(1)); if (c.startsWith('<')) return host < HostVersion.parse(c.substring(1)); if (c.startsWith('=')) return host == HostVersion.parse(c.substring(1)); if (c.startsWith('^')) { diff --git a/lib/core/extensions/harness/extension_protocol_profile.dart b/lib/core/extensions/harness/extension_protocol_profile.dart index 5b85ff80..b03010ee 100644 --- a/lib/core/extensions/harness/extension_protocol_profile.dart +++ b/lib/core/extensions/harness/extension_protocol_profile.dart @@ -29,6 +29,7 @@ final class HostVersion implements Comparable { return patch.compareTo(other.patch); } + bool operator >(HostVersion other) => compareTo(other) > 0; bool operator >=(HostVersion other) => compareTo(other) >= 0; bool operator <(HostVersion other) => compareTo(other) < 0; bool operator <=(HostVersion other) => compareTo(other) <= 0; diff --git a/test/core/extensions/harness/extension_manifest_validator_test.dart b/test/core/extensions/harness/extension_manifest_validator_test.dart index dc72bd00..6e06b078 100644 --- a/test/core/extensions/harness/extension_manifest_validator_test.dart +++ b/test/core/extensions/harness/extension_manifest_validator_test.dart @@ -125,6 +125,25 @@ void main() { expect(allows('0.5.0', ' >=0.4.0 <3.0.0 '), isTrue); }); + test('spaces between an operator and its version are tolerated (#1635)', + () { + const range = '>= 0.4.0 < 3.0.0'; + expect(allows('0.4.19', range), isTrue); + expect(allows('3.0.0', range), isFalse); + expect(allows('0.3.0', range), isFalse); + expect(allows('0.4.1', '> 0.4.0'), isTrue); + expect(allows('0.4.0', '<= 0.4.0'), isTrue); + expect(allows('0.4.19', '= 0.4.19'), isTrue); + expect(allows('0.4.19', '^ 0.4.11'), isTrue); + expect(allows('0.5.0', '>='), isNull); + }); + + test('HostVersion has a > operator (#1636)', () { + expect(HostVersion.parse('0.4.1') > HostVersion.parse('0.4.0'), isTrue); + expect(HostVersion.parse('0.4.0') > HostVersion.parse('0.4.0'), isFalse); + expect(HostVersion.parse('0.3.9') > HostVersion.parse('0.4.0'), isFalse); + }); + test('* means any version; a range it cannot read is null, not a guess', () { expect(allows('0.5.0', '*'), isTrue); for (final bad in ['~0.4', '>=0.4.0 || ^1.0.0', '>=x', '', '0.4.19', '* <3.0.0']) {