Adds `minVersion` to `findPackageConfig{,Uri}` methods. (#125)
* Adds `minVersion` to `findPackageConfig{,Uri}` methods.
This parameter currently allows you to ignore `.packages` files
while searching for a configuration file.
If we later add a version 3 of the configuration, it should
also allow ignoring version 2 configurations.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9ecfe22..b6e91bb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,11 @@
-## 2.0.3-dev
+## 2.1.0
+
+- Adds `minVersion` to `findPackageConfig` and `findPackageConfigVersion`
+ which allows ignoring earlier versions (which currently only means
+ ignoring version 1, aka. `.packages` files.)
+
+- Changes the version number of `SimplePackageConfig.empty` to the
+ current maximum version.
- Improve file read performance; improve lookup performance.
- Emit an error when a package is inside the package root of another package.
diff --git a/lib/package_config.dart b/lib/package_config.dart
index bd227e4..a2c0321 100644
--- a/lib/package_config.dart
+++ b/lib/package_config.dart
@@ -111,10 +111,21 @@
/// a valid configuration from the invalid configuration file.
/// If no [onError] is provided, errors are thrown immediately.
///
+/// If [minVersion] is set to something greater than its default,
+/// any lower-version configuration files are ignored in the search.
+///
/// Returns `null` if no configuration file is found.
Future<PackageConfig?> findPackageConfig(Directory directory,
- {bool recurse = true, void Function(Object error)? onError}) =>
- discover.findPackageConfig(directory, recurse, onError ?? throwError);
+ {bool recurse = true,
+ void Function(Object error)? onError,
+ int minVersion = 1}) {
+ if (minVersion > PackageConfig.maxVersion) {
+ throw ArgumentError.value(minVersion, 'minVersion',
+ 'Maximum known version is ${PackageConfig.maxVersion}');
+ }
+ return discover.findPackageConfig(
+ directory, minVersion, recurse, onError ?? throwError);
+}
/// Finds a package configuration relative to [location].
///
@@ -155,13 +166,22 @@
/// a valid configuration from the invalid configuration file.
/// If no [onError] is provided, errors are thrown immediately.
///
+/// If [minVersion] is set to something greater than its default,
+/// any lower-version configuration files are ignored in the search.
+///
/// Returns `null` if no configuration file is found.
Future<PackageConfig?> findPackageConfigUri(Uri location,
- {bool recurse = true,
- Future<Uint8List?> Function(Uri uri)? loader,
- void Function(Object error)? onError}) =>
- discover.findPackageConfigUri(
- location, loader, onError ?? throwError, recurse);
+ {bool recurse = true,
+ int minVersion = 1,
+ Future<Uint8List?> Function(Uri uri)? loader,
+ void Function(Object error)? onError}) {
+ if (minVersion > PackageConfig.maxVersion) {
+ throw ArgumentError.value(minVersion, 'minVersion',
+ 'Maximum known version is ${PackageConfig.maxVersion}');
+ }
+ return discover.findPackageConfigUri(
+ location, minVersion, loader, onError ?? throwError, recurse);
+}
/// Writes a package configuration to the provided directory.
///
diff --git a/lib/src/discovery.dart b/lib/src/discovery.dart
index a6cc451..ccc86ea 100644
--- a/lib/src/discovery.dart
+++ b/lib/src/discovery.dart
@@ -25,15 +25,20 @@
/// and stopping when something is found.
///
/// * Check if a `.dart_tool/package_config.json` file exists in the directory.
-/// * Check if a `.packages` file exists in the directory.
+/// * Check if a `.packages` file exists in the directory
+/// (if `minVersion <= 1`).
/// * Repeat these checks for the parent directories until reaching the
/// root directory if [recursive] is true.
///
/// If any of these tests succeed, a `PackageConfig` class is returned.
/// Returns `null` if no configuration was found. If a configuration
/// is needed, then the caller can supply [PackageConfig.empty].
+///
+/// If [minVersion] is greated than 1, `.packages` files are ignored.
+/// If [minVersion] is greater than the version read from the
+/// `package_config.json` file, it too is ignored.
Future<PackageConfig?> findPackageConfig(Directory baseDirectory,
- bool recursive, void Function(Object error) onError) async {
+ int minVersion, bool recursive, void Function(Object error) onError) async {
var directory = baseDirectory;
if (!directory.isAbsolute) directory = directory.absolute;
if (!await directory.exists()) {
@@ -41,7 +46,8 @@
}
do {
// Check for $cwd/.packages
- var packageConfig = await findPackagConfigInDirectory(directory, onError);
+ var packageConfig =
+ await findPackagConfigInDirectory(directory, minVersion, onError);
if (packageConfig != null) return packageConfig;
if (!recursive) break;
// Check in parent directories.
@@ -55,6 +61,7 @@
/// Similar to [findPackageConfig] but based on a URI.
Future<PackageConfig?> findPackageConfigUri(
Uri location,
+ int minVersion,
Future<Uint8List?> Function(Uri uri)? loader,
void Function(Object error) onError,
bool recursive) async {
@@ -67,6 +74,7 @@
if (location.isScheme('file')) {
return findPackageConfig(
Directory.fromUri(location.resolveUri(currentPath)),
+ minVersion,
recursive,
onError);
}
@@ -77,12 +85,15 @@
var file = location.resolveUri(packageConfigJsonPath);
var bytes = await loader(file);
if (bytes != null) {
- return parsePackageConfigBytes(bytes, file, onError);
+ var config = parsePackageConfigBytes(bytes, file, onError);
+ if (config.version >= minVersion) return config;
}
- file = location.resolveUri(dotPackagesPath);
- bytes = await loader(file);
- if (bytes != null) {
- return packages_file.parse(bytes, file, onError);
+ if (minVersion <= 1) {
+ file = location.resolveUri(dotPackagesPath);
+ bytes = await loader(file);
+ if (bytes != null) {
+ return packages_file.parse(bytes, file, onError);
+ }
}
if (!recursive) break;
var parent = location.resolveUri(parentPath);
@@ -102,15 +113,23 @@
/// If [onError] is supplied, parsing errors are reported using that, and
/// a best-effort attempt is made to return a package configuration.
/// This may be the empty package configuration.
-Future<PackageConfig?> findPackagConfigInDirectory(
- Directory directory, void Function(Object error) onError) async {
+///
+/// If [minVersion] is greated than 1, `.packages` files are ignored.
+/// If [minVersion] is greater than the version read from the
+/// `package_config.json` file, it too is ignored.
+Future<PackageConfig?> findPackagConfigInDirectory(Directory directory,
+ int minVersion, void Function(Object error) onError) async {
var packageConfigFile = await checkForPackageConfigJsonFile(directory);
if (packageConfigFile != null) {
- return await readPackageConfigJsonFile(packageConfigFile, onError);
+ var config = await readPackageConfigJsonFile(packageConfigFile, onError);
+ if (config.version < minVersion) return null;
+ return config;
}
- packageConfigFile = await checkForDotPackagesFile(directory);
- if (packageConfigFile != null) {
- return await readDotPackagesFile(packageConfigFile, onError);
+ if (minVersion <= 1) {
+ packageConfigFile = await checkForDotPackagesFile(directory);
+ if (packageConfigFile != null) {
+ return await readDotPackagesFile(packageConfigFile, onError);
+ }
}
return null;
}
diff --git a/lib/src/package_config.dart b/lib/src/package_config.dart
index 3c5cc51..ba52c14 100644
--- a/lib/src/package_config.dart
+++ b/lib/src/package_config.dart
@@ -39,7 +39,7 @@
/// including the two paths being the same.
///
/// * No package's root must be the same as another package's root.
- /// * The package-root of a package must be inside the pacakge's root.
+ /// * The package-root of a package must be inside the package's root.
/// * If one package's package-root is inside another package's root,
/// then the latter package's package root must not be inside the former
/// package's root. (No getting between a package and its package root!)
diff --git a/lib/src/package_config_impl.dart b/lib/src/package_config_impl.dart
index aef8176..4c8f234 100644
--- a/lib/src/package_config_impl.dart
+++ b/lib/src/package_config_impl.dart
@@ -37,8 +37,11 @@
///
/// The empty configuration can be used in cases where no configuration is
/// found, but code expects a non-null configuration.
+ ///
+ /// The version number is [PackageConfig.maxVersion] to avoid
+ /// minimum-version filters discarding the configuration.
const SimplePackageConfig.empty()
- : version = 1,
+ : version = PackageConfig.maxVersion,
_packageTree = const EmptyPackageTree(),
_packages = const <String, Package>{},
extraData = null;
diff --git a/pubspec.yaml b/pubspec.yaml
index d4ed6b9..56e30b5 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
name: package_config
-version: 2.0.3-dev
+version: 2.1.0
description: Support for reading and writing Dart Package Configuration files.
repository: https://github.com/dart-lang/package_config
diff --git a/test/discovery_test.dart b/test/discovery_test.dart
index 4a1bba0..17b6aa0 100644
--- a/test/discovery_test.dart
+++ b/test/discovery_test.dart
@@ -201,6 +201,32 @@
expect(hadError, true);
});
});
+
+ // Does not find .packages if no package_config.json and minVersion > 1.
+ fileTest('.packages ignored', {
+ '.packages': packagesFile,
+ 'script.dart': 'main(){}'
+ }, (Directory directory) async {
+ var config = (await findPackageConfig(directory, minVersion: 2));
+ expect(config, null);
+ });
+
+ // Finds package_config.json in super-directory, with .packages in
+ // subdir and minVersion > 1.
+ fileTest('package_config.json recursive .packages ignored', {
+ '.dart_tool': {
+ 'package_config.json': packageConfigFile,
+ },
+ 'subdir': {
+ '.packages': packagesFile,
+ 'script.dart': 'main(){}',
+ }
+ }, (Directory directory) async {
+ var config = (await findPackageConfig(subdir(directory, 'subdir/'),
+ minVersion: 2))!;
+ expect(config.version, 2);
+ validatePackagesFile(config, directory);
+ });
});
group('loadPackageConfig', () {
diff --git a/test/discovery_uri_test.dart b/test/discovery_uri_test.dart
index e487e47..6183ce3 100644
--- a/test/discovery_uri_test.dart
+++ b/test/discovery_uri_test.dart
@@ -145,6 +145,33 @@
expect(() => findPackageConfigUri(directory, loader: loader),
throwsA(TypeMatcher<FormatException>()));
});
+
+ // Does not find .packages if no package_config.json and minVersion > 1.
+ loaderTest('.packages ignored', {
+ '.packages': packagesFile,
+ 'script.dart': 'main(){}'
+ }, (directory, loader) async {
+ var config = (await findPackageConfigUri(directory,
+ minVersion: 2, loader: loader));
+ expect(config, null);
+ });
+
+ // Finds package_config.json in super-directory, with .packages in
+ // subdir and minVersion > 1.
+ loaderTest('package_config.json recursive ignores .packages', {
+ '.dart_tool': {
+ 'package_config.json': packageConfigFile,
+ },
+ 'subdir': {
+ '.packages': packagesFile,
+ 'script.dart': 'main(){}',
+ }
+ }, (directory, loader) async {
+ var config = (await findPackageConfigUri(directory.resolve('subdir/'),
+ minVersion: 2, loader: loader))!;
+ expect(config.version, 2);
+ validatePackagesFile(config, directory);
+ });
});
group('loadPackageConfig', () {