Refine what a relative uri means in a git path (#3212)
diff --git a/lib/src/source/git.dart b/lib/src/source/git.dart
index 1a792e3..0d26283 100644
--- a/lib/src/source/git.dart
+++ b/lib/src/source/git.dart
@@ -145,9 +145,15 @@
return _ValidatedUrl(url, relative);
}
- /// Returns [path] normalized.
+ /// Normalizes [path].
///
- /// Throws a [FormatException] if [path] isn't a relative url or null.
+ /// Throws a [FormatException] if [path] isn't a [String] parsing as a
+ /// relative URL or `null`.
+ ///
+ /// A relative url here has:
+ /// - non-absolute path
+ /// - no scheme
+ /// - no authority
String _validatedPath(dynamic path) {
path ??= '.';
if (path is! String) {
@@ -157,9 +163,13 @@
// Use Dart's URL parser to validate the URL.
final parsed = Uri.parse(path);
- if (parsed.isAbsolute) {
+ if (parsed.hasAbsolutePath ||
+ parsed.hasScheme ||
+ parsed.hasAuthority ||
+ parsed.hasFragment ||
+ parsed.hasQuery) {
throw FormatException(
- "The 'path' field of the description must be relative.");
+ "The 'path' field of the description must be a relative path URL.");
}
if (!p.url.isWithin('.', path) && !p.url.equals('.', path)) {
throw FormatException(
diff --git a/test/get/git/path_test.dart b/test/get/git/path_test.dart
index eab018f..d26d9cb 100644
--- a/test/get/git/path_test.dart
+++ b/test/get/git/path_test.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:path/path.dart' as p;
+import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:pub/src/io.dart';
import 'package:pub/src/lock_file.dart';
import 'package:pub/src/source/git.dart';
@@ -86,6 +87,84 @@
reason: 'use uris to specify the path relative to the repo');
});
+ group('requires path to be absolute', () {
+ test('absolute path', () async {
+ await d.appDir({
+ 'sub': {
+ 'git': {'url': '../foo.git', 'path': '/subdir'}
+ }
+ }).create();
+
+ await pubGet(
+ error: contains(
+ 'Invalid description in the "myapp" pubspec on the "sub" dependency: The \'path\' field of the description must be a relative path URL.',
+ ),
+ exitCode: exit_codes.DATA,
+ );
+ });
+ test('scheme', () async {
+ await d.appDir({
+ 'sub': {
+ 'git': {'url': '../foo.git', 'path': 'https://subdir'}
+ }
+ }).create();
+
+ await pubGet(
+ error: contains(
+ 'Invalid description in the "myapp" pubspec on the "sub" dependency: The \'path\' field of the description must be a relative path URL.',
+ ),
+ exitCode: exit_codes.DATA,
+ );
+ });
+ test('fragment', () async {
+ await d.appDir({
+ 'sub': {
+ 'git': {'url': '../foo.git', 'path': 'subdir/dir#fragment'}
+ }
+ }).create();
+
+ await pubGet(
+ error: contains(
+ 'Invalid description in the "myapp" pubspec on the "sub" dependency: The \'path\' field of the description must be a relative path URL.',
+ ),
+ exitCode: exit_codes.DATA,
+ );
+ });
+
+ test('query', () async {
+ await d.appDir({
+ 'sub': {
+ 'git': {'url': '../foo.git', 'path': 'subdir/dir?query'}
+ }
+ }).create();
+
+ await pubGet(
+ error: contains(
+ 'Invalid description in the "myapp" pubspec on the "sub" dependency: The \'path\' field of the description must be a relative path URL.',
+ ),
+ exitCode: exit_codes.DATA,
+ );
+ });
+
+ test('authority', () async {
+ await d.appDir({
+ 'sub': {
+ 'git': {
+ 'url': '../foo.git',
+ 'path': 'bob:pwd@somewhere.example.com/subdir'
+ }
+ }
+ }).create();
+
+ await pubGet(
+ error: contains(
+ 'Invalid description in the "myapp" pubspec on the "sub" dependency: The \'path\' field of the description must be a relative path URL.',
+ ),
+ exitCode: exit_codes.DATA,
+ );
+ });
+ });
+
test('depends on a package in a deep subdirectory, non-relative uri',
() async {
ensureGit();