Skip to content
This repository has been archived by the owner on Jan 14, 2025. It is now read-only.

Adds minVersion to findPackageConfig{,Uri} methods. #125

Merged
merged 2 commits into from
May 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
## 2.0.3-dev
## 2.1.0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we ready to publish 2.1.0 now?


- 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.
Copy link
Member Author

@lrhn lrhn Jun 15, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I'll do that.

Expand Down
34 changes: 27 additions & 7 deletions lib/package_config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,21 @@ Future<PackageConfig> loadPackageConfigUri(Uri file,
/// 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].
///
Expand Down Expand Up @@ -155,13 +166,22 @@ Future<PackageConfig?> findPackageConfig(Directory directory,
/// 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.
///
Expand Down
47 changes: 33 additions & 14 deletions lib/src/discovery.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,29 @@ final Uri parentPath = Uri(path: '..');
/// 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()) {
return null;
}
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.
Expand All @@ -55,6 +61,7 @@ Future<PackageConfig?> findPackageConfig(Directory baseDirectory,
/// 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 {
Expand All @@ -67,6 +74,7 @@ Future<PackageConfig?> findPackageConfigUri(
if (location.isScheme('file')) {
return findPackageConfig(
Directory.fromUri(location.resolveUri(currentPath)),
minVersion,
recursive,
onError);
}
Expand All @@ -77,12 +85,15 @@ Future<PackageConfig?> findPackageConfigUri(
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);
Expand All @@ -102,15 +113,23 @@ Future<PackageConfig?> findPackageConfigUri(
/// 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;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/src/package_config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ abstract class PackageConfig {
/// 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!)
Expand Down
5 changes: 4 additions & 1 deletion lib/src/package_config_impl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,11 @@ class SimplePackageConfig implements PackageConfig {
///
/// 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;
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -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

Expand Down
26 changes: 26 additions & 0 deletions test/discovery_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,32 @@ void main() {
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', () {
Expand Down
27 changes: 27 additions & 0 deletions test/discovery_uri_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,33 @@ void main() {
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', () {
Expand Down