Fix Package constructor not accepting relative packageUriRoot. (dart-lang/package_config#82) * Fix Package constructor not accepting relative packageUriRoot.
diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index 3015523..6dcae80 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md
@@ -1,3 +1,7 @@ +## 1.9.3 + +- Fix `Package` constructor not accepting relative `packageUriRoot`. + ## 1.9.2 - Updated to support new rules for picking `package_config.json` over
diff --git a/pkgs/package_config/lib/src/package_config.dart b/pkgs/package_config/lib/src/package_config.dart index 364df75..30c758a 100644 --- a/pkgs/package_config/lib/src/package_config.dart +++ b/pkgs/package_config/lib/src/package_config.dart
@@ -219,7 +219,7 @@ /// The [packageUriRoot], if provided, must be either an absolute /// directory URI or a relative URI reference which is then resolved /// relative to [root]. It must then also be a subdirectory of [root], - /// or the same directory. + /// or the same directory, and must end with `/`. /// If [languageVersion] is supplied, it must be a valid Dart language /// version, which means two decimal integer literals separated by a `.`, /// where the integer literals have no leading zeros unless they are
diff --git a/pkgs/package_config/lib/src/package_config_impl.dart b/pkgs/package_config/lib/src/package_config_impl.dart index f68a9ea..9e23af0 100644 --- a/pkgs/package_config/lib/src/package_config_impl.dart +++ b/pkgs/package_config/lib/src/package_config_impl.dart
@@ -214,7 +214,10 @@ root = root.replace(path: root.path + "/"); } } - if (!fatalError) { + if (packageUriRoot == null) { + packageUriRoot = root; + } else if (!fatalError) { + packageUriRoot = root.resolveUri(packageUriRoot); if (!isAbsoluteDirectoryUri(packageUriRoot)) { onError(PackageConfigArgumentError( packageUriRoot,
diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 3f5ec27..b7d5969 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml
@@ -1,5 +1,5 @@ name: package_config -version: 1.9.2 +version: 1.9.3 description: Support for working with Package Configuration files. homepage: https://github.com/dart-lang/package_config
diff --git a/pkgs/package_config/test/package_config_impl_test.dart b/pkgs/package_config/test/package_config_impl_test.dart new file mode 100644 index 0000000..6921118 --- /dev/null +++ b/pkgs/package_config/test/package_config_impl_test.dart
@@ -0,0 +1,145 @@ +// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import "package:package_config/package_config_types.dart"; +import "package:test/test.dart"; +import "src/util.dart"; + +void main() { + var unique = Object(); + var root = Uri.file("/tmp/root/"); + + group("LanguageVersion", () { + test("minimal", () { + var version = LanguageVersion(3, 5); + expect(version.major, 3); + expect(version.minor, 5); + }); + + test("negative major", () { + expect(() => LanguageVersion(-1, 1), throwsArgumentError); + }); + + test("negative minor", () { + expect(() => LanguageVersion(1, -1), throwsArgumentError); + }); + + test("minimal parse", () { + var version = LanguageVersion.parse("3.5"); + expect(version.major, 3); + expect(version.minor, 5); + }); + + void failParse(String name, String input) { + test("$name - error", () { + expect(() => LanguageVersion.parse(input), + throwsA(TypeMatcher<PackageConfigError>())); + expect(() => LanguageVersion.parse(input), throwsFormatException); + var failed = false; + var actual = LanguageVersion.parse(input, onError: (_) { + failed = true; + }); + expect(failed, true); + expect(actual, isA<LanguageVersion>()); + }); + } + + failParse("Leading zero major", "01.1"); + failParse("Leading zero minor", "1.01"); + failParse("Sign+ major", "+1.1"); + failParse("Sign- major", "-1.1"); + failParse("Sign+ minor", "1.+1"); + failParse("Sign- minor", "1.-1"); + failParse("WhiteSpace 1", " 1.1"); + failParse("WhiteSpace 2", "1 .1"); + failParse("WhiteSpace 3", "1. 1"); + failParse("WhiteSpace 4", "1.1 "); + }); + + group("Package", () { + test("minimal", () { + var package = Package("name", root, extraData: unique); + expect(package.name, "name"); + expect(package.root, root); + expect(package.packageUriRoot, root); + expect(package.languageVersion, null); + expect(package.extraData, same(unique)); + }); + + test("absolute package root", () { + var version = LanguageVersion(1, 1); + var absolute = root.resolve("foo/bar/"); + var package = Package("name", root, + packageUriRoot: absolute, + languageVersion: version, + extraData: unique); + expect(package.name, "name"); + expect(package.root, root); + expect(package.packageUriRoot, absolute); + expect(package.languageVersion, version); + expect(package.extraData, same(unique)); + }); + + test("relative package root", () { + var relative = Uri.parse("foo/bar/"); + var absolute = root.resolveUri(relative); + var package = + Package("name", root, packageUriRoot: relative, extraData: unique); + expect(package.name, "name"); + expect(package.root, root); + expect(package.packageUriRoot, absolute); + expect(package.languageVersion, null); + expect(package.extraData, same(unique)); + }); + + for (var badName in ["a/z", "a:z", "", "..."]) { + test("Invalid name '$badName'", () { + expect(() => Package(badName, root), throwsPackageConfigError); + }); + } + + test("Invalid root, not absolute", () { + expect( + () => Package("name", Uri.parse("/foo/")), throwsPackageConfigError); + }); + + test("Invalid root, not ending in slash", () { + expect(() => Package("name", Uri.parse("file:///foo")), + throwsPackageConfigError); + }); + + test("invalid package root, not ending in slash", () { + expect(() => Package("name", root, packageUriRoot: Uri.parse("foo")), + throwsPackageConfigError); + }); + + test("invalid package root, not inside root", () { + expect(() => Package("name", root, packageUriRoot: Uri.parse("../baz/")), + throwsPackageConfigError); + }); + }); + + group("package config", () { + test("emtpy", () { + var empty = PackageConfig([], extraData: unique); + expect(empty.version, 2); + expect(empty.packages, isEmpty); + expect(empty.extraData, same(unique)); + expect(empty.resolve(pkg("a", "b")), isNull); + }); + + test("single", () { + var package = Package("name", root); + var single = PackageConfig([package], extraData: unique); + expect(single.version, 2); + expect(single.packages, hasLength(1)); + expect(single.extraData, same(unique)); + expect(single.resolve(pkg("a", "b")), isNull); + var resolved = single.resolve(pkg("name", "a/b")); + expect(resolved, root.resolve("a/b")); + }); + }); +} + +final Matcher throwsPackageConfigError = throwsA(isA<PackageConfigError>());