Escape tag-pattern components when constructing tag matching RegExp (#4878)
diff --git a/lib/src/source/git.dart b/lib/src/source/git.dart
index 9dd19fe..687ba7a 100644
--- a/lib/src/source/git.dart
+++ b/lib/src/source/git.dart
@@ -808,7 +808,7 @@
version = Version.parse(match[1]!);
} on FormatException catch (e) {
throw StateError(
- 'Matched part ${Version.parse(match[1]!)} did not match version $e.',
+ 'Matched part "${match[1]}" did not match version: $e.',
);
}
result.add((version: version, commitId: parts[1]));
@@ -1206,8 +1206,8 @@
/// [tagPatternVersionMarker].
RegExp compileTagPattern(String tagPattern) {
final parts = tagPattern.split(tagPatternVersionMarker);
- final before = parts[0];
- final after = parts[1];
+ final before = RegExp.escape(parts[0]);
+ final after = RegExp.escape(parts[1]);
return RegExp(
r'^'
diff --git a/test/get/git/tag_pattern_test.dart b/test/get/git/tag_pattern_test.dart
index a34e72a..64bd93b 100644
--- a/test/get/git/tag_pattern_test.dart
+++ b/test/get/git/tag_pattern_test.dart
@@ -9,6 +9,7 @@
import 'package:pub/src/exit_codes.dart';
import 'package:pub/src/path.dart';
+import 'package:pub/src/source/git.dart';
import 'package:test/test.dart';
import 'package:yaml/yaml.dart';
@@ -494,5 +495,82 @@
});
},
);
+
+ test(
+ '(${tagType.name}) tag_pattern matches special regex characters verbatim',
+ () async {
+ ensureGit();
+ await d.git('foo.git', [
+ d.libPubspec('foo', '1.0.0', sdk: '^3.9.0'),
+ ]).create();
+ await d.git('foo.git', []).tag('fooxbar-1.0.0', tagType: tagType);
+ await d.git('foo.git', [
+ d.libPubspec('foo', '2.0.0', sdk: '^3.9.0'),
+ ]).commit();
+ await d.git('foo.git', []).tag('foo.bar-2.0.0', tagType: tagType);
+
+ await d
+ .appDir(
+ dependencies: {
+ 'foo': {
+ 'git': {
+ 'url': p.join(d.sandbox, 'foo.git'),
+ 'tag_pattern': 'foo.bar-{{version}}',
+ },
+ 'version': '^2.0.0',
+ },
+ },
+ pubspec: {
+ 'environment': {'sdk': '^3.9.0'},
+ },
+ )
+ .create();
+
+ await pubGet(
+ output: contains('+ foo 2.0.0'),
+ environment: {'_PUB_TEST_SDK_VERSION': '3.9.0'},
+ );
+ },
+ );
+
+ test('(${tagType.name}) tag_pattern with parentheses does not '
+ 'break capture groups', () async {
+ ensureGit();
+ await d.git('foo.git', [
+ d.libPubspec('foo', '1.0.0', sdk: '^3.9.0'),
+ ]).create();
+ await d.git('foo.git', []).tag('(v)-1.0.0', tagType: tagType);
+
+ await d
+ .appDir(
+ dependencies: {
+ 'foo': {
+ 'git': {
+ 'url': p.join(d.sandbox, 'foo.git'),
+ 'tag_pattern': '(v)-{{version}}',
+ },
+ 'version': '^1.0.0',
+ },
+ },
+ pubspec: {
+ 'environment': {'sdk': '^3.9.0'},
+ },
+ )
+ .create();
+
+ await pubGet(
+ output: contains('+ foo 1.0.0'),
+ environment: {'_PUB_TEST_SDK_VERSION': '3.9.0'},
+ );
+ });
}
+
+ test('compileTagPattern escapes regex special characters', () {
+ final regExp = compileTagPattern(r'[foo]+(bar)*.{{version}}^$');
+ expect(regExp.hasMatch(r'[foo]+(bar)*.1.2.3^$'), isTrue);
+ expect(regExp.hasMatch('f1.2.3'), isFalse);
+ final match = regExp.firstMatch(r'[foo]+(bar)*.1.2.3^$');
+ expect(match, isNotNull);
+ expect(match![1], '1.2.3');
+ });
}