Skip to content
This repository was archived by the owner on Jan 14, 2025. It is now read-only.
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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 1.9.2

- Updated to support new rules for picking `package_config.json` over
a specified `.packages`.

## 1.9.1

- Remove accidental transitive import of `dart:io` from entrypoints that are
Expand Down
8 changes: 5 additions & 3 deletions lib/package_config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ export "package_config_types.dart";
/// It is considered a `package_config.json` file if its first character
/// is a `{`.
///
/// If the file is a `.packages` file and [preferNewest] is true, the default,
/// also checks if there is a `.dart_tool/package_config.json` file next to the original file,
/// and if so, loads that instead.
/// If the file is a `.packages` file (the file name is `.packages`)
/// and [preferNewest] is true, the default, also checks if there is
/// a `.dart_tool/package_config.json` file next
/// to the original file, and if so, loads that instead.
/// If [preferNewest] is set to false, a directly specified `.packages` file
/// is loaded even if there is an available `package_config.json` file.
/// The caller can determine this from the [PackageConfig.version]
Expand All @@ -50,6 +51,7 @@ Future<PackageConfig> loadPackageConfig(File file,
/// non-whitespace character is a `{`.
///
/// If [preferNewest] is true, the default, and the file is a `.packages` file,
/// as determined by its file name being `.packages`,
/// first checks if there is a `.dart_tool/package_config.json` file
/// next to the original file, and if so, loads that instead.
/// The [file] *must not* be a `package:` URI.
Expand Down
70 changes: 32 additions & 38 deletions lib/src/package_config_io.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,35 +30,21 @@ import "util_io.dart";
/// The file must exist and be a normal file.
Future<PackageConfig> readAnyConfigFile(
File file, bool preferNewest, void onError(Object error)) async {
if (preferNewest && fileName(file.path) == ".packages") {
var alternateFile =
File(pathJoin(dirName(file.path), ".dart_tool", "package_config.json"));
if (alternateFile.existsSync()) {
return await readPackageConfigJsonFile(alternateFile, onError);
}
}
Uint8List bytes;
try {
bytes = await file.readAsBytes();
} catch (e) {
onError(e);
return const SimplePackageConfig.empty();
}
var firstChar = firstNonWhitespaceChar(bytes);
if (firstChar != $lbrace) {
// Definitely not a JSON object, probably a .packages.
if (preferNewest) {
var alternateFile = File(
pathJoin(dirName(file.path), ".dart_tool", "package_config.json"));
if (alternateFile.existsSync()) {
Uint8List /*?*/ bytes;
try {
bytes = await alternateFile.readAsBytes();
} catch (e) {
onError(e);
return const SimplePackageConfig.empty();
}
if (bytes != null) {
return parsePackageConfigBytes(bytes, alternateFile.uri, onError);
}
}
}
return packages_file.parse(bytes, file.uri, onError);
}
return parsePackageConfigBytes(bytes, file.uri, onError);
return parseAnyConfigFile(bytes, file.uri, onError);
}

/// Like [readAnyConfigFile] but uses a URI and an optional loader.
Expand All @@ -73,11 +59,24 @@ Future<PackageConfig> readAnyConfigFileUri(
}
if (loader == null) {
if (file.isScheme("file")) {
return readAnyConfigFile(File.fromUri(file), preferNewest, onError);
return await readAnyConfigFile(File.fromUri(file), preferNewest, onError);
}
loader = defaultLoader;
}
Uint8List bytes;
if (preferNewest && file.pathSegments.last == ".packages") {
var alternateFile = file.resolve(".dart_tool/package_config.json");
Uint8List /*?*/ bytes;
try {
bytes = await loader(alternateFile);
} catch (e) {
onError(e);
return const SimplePackageConfig.empty();
}
if (bytes != null) {
return parsePackageConfigBytes(bytes, alternateFile, onError);
}
}
Uint8List /*?*/ bytes;
try {
bytes = await loader(file);
} catch (e) {
Expand All @@ -89,23 +88,18 @@ Future<PackageConfig> readAnyConfigFileUri(
file.toString(), "file", "File cannot be read"));
return const SimplePackageConfig.empty();
}
return parseAnyConfigFile(bytes, file, onError);
}

/// Parses a `.packages` or `package_config.json` file's contents.
///
/// Assumes it's a JSON file if the first non-whitespace character
/// is `{`, otherwise assumes it's a `.packages` file.
PackageConfig parseAnyConfigFile(
Uint8List bytes, Uri file, void onError(Object error)) {
var firstChar = firstNonWhitespaceChar(bytes);
if (firstChar != $lbrace) {
// Definitely not a JSON object, probably a .packages.
if (preferNewest) {
// Check if there is a package_config.json file.
var alternateFile = file.resolveUri(packageConfigJsonPath);
Uint8List alternateBytes;
try {
alternateBytes = await loader(alternateFile);
} catch (e) {
onError(e);
return const SimplePackageConfig.empty();
}
if (alternateBytes != null) {
return parsePackageConfigBytes(alternateBytes, alternateFile, onError);
}
}
return packages_file.parse(bytes, file, onError);
}
return parsePackageConfigBytes(bytes, file, onError);
Expand Down
11 changes: 4 additions & 7 deletions lib/src/package_config_json.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ PackageConfig parsePackageConfigBytes(
try {
jsonObject = _jsonUtf8Decoder.convert(bytes);
} on FormatException catch (e) {
onError(PackageConfigFormatException(e.message, e.source, e.offset));
onError(PackageConfigFormatException.from(e));
return const SimplePackageConfig.empty();
}
return parsePackageConfigJson(jsonObject, file, onError);
Expand All @@ -51,7 +51,7 @@ PackageConfig parsePackageConfigString(
try {
jsonObject = jsonDecode(source);
} on FormatException catch (e) {
onError(PackageConfigFormatException(e.message, e.source, e.offset));
onError(PackageConfigFormatException.from(e));
return const SimplePackageConfig.empty();
}
return parsePackageConfigJson(jsonObject, file, onError);
Expand Down Expand Up @@ -271,7 +271,6 @@ void writeDotPackages(PackageConfig config, Uri baseUri, StringSink output) {
}
}
packages_file.write(output, config, baseUri: baseUri, comment: comment);
return;
}

/// If "extraData" is a JSON map, then return it, otherwise return null.
Expand Down Expand Up @@ -304,12 +303,10 @@ bool _validateJson(dynamic object) {
if (object == null || true == object || false == object) return true;
if (object is num || object is String) return true;
if (object is List<dynamic>) {
for (var element in object) if (!_validateJson(element)) return false;
return true;
return object.every(_validateJson);
}
if (object is Map<String, dynamic>) {
for (var value in object.values) if (!_validateJson(value)) return false;
return true;
return object.values.every(_validateJson);
}
return false;
}
2 changes: 1 addition & 1 deletion lib/src/util_io.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Future<Uint8List> defaultLoader(Uri uri) async {
if (uri.isScheme("file")) {
var file = File.fromUri(uri);
try {
return file.readAsBytes();
return await file.readAsBytes();
} catch (_) {
return 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: 1.9.1
version: 1.9.2
description: Support for working with Package Configuration files.
homepage: https://github.com/dart-lang/package_config

Expand Down
6 changes: 3 additions & 3 deletions test/discovery_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -301,13 +301,13 @@ void main() {
});

// Find package_config.json in subdir even if initial file syntax error.
fileTest("specified file syntax error", {
"anyname": "syntax error",
fileTest("specified file syntax onError", {
".packages": "syntax error",
".dart_tool": {
"package_config.json": packageConfigFile,
},
}, (Directory directory) async {
var file = dirFile(directory, "anyname");
var file = dirFile(directory, ".packages");
var config = await loadPackageConfig(file);
expect(config.version, 2);
validatePackagesFile(config, directory);
Expand Down
25 changes: 12 additions & 13 deletions test/discovery_uri_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ void main() {
".dart_tool": {
"package_config.json": packageConfigFile,
}
}, (Uri directory, loader) async {
}, (directory, loader) async {
var config = await findPackageConfigUri(directory, loader: loader);
expect(config.version, 2); // Found package_config.json file.
validatePackagesFile(config, directory);
Expand All @@ -71,7 +71,7 @@ void main() {
".packages": packagesFile,
"script.dart": "main(){}",
"packages": {"shouldNotBeFound": {}}
}, (Uri directory, loader) async {
}, (directory, loader) async {
var config = await findPackageConfigUri(directory, loader: loader);
expect(config.version, 1); // Found .packages file.
validatePackagesFile(config, directory);
Expand All @@ -86,7 +86,7 @@ void main() {
"subdir": {
"script.dart": "main(){}",
}
}, (Uri directory, loader) async {
}, (directory, loader) async {
var config = await findPackageConfigUri(directory.resolve("subdir/"),
loader: loader);
expect(config.version, 2);
Expand All @@ -97,7 +97,7 @@ void main() {
loaderTest(".packages recursive", {
".packages": packagesFile,
"subdir": {"script.dart": "main(){}"}
}, (Uri directory, loader) async {
}, (directory, loader) async {
var config;
config = await findPackageConfigUri(directory.resolve("subdir/"),
loader: loader);
Expand Down Expand Up @@ -240,9 +240,9 @@ void main() {
throwsFormatException);
});

loaderTest("specified file syntax error", {
loaderTest("specified file syntax onError", {
"anyname": "syntax error",
}, (Uri directory, loader) async {
}, (directory, loader) async {
var file = directory.resolve("anyname");
var hadError = false;
await loadPackageConfigUri(file,
Expand All @@ -254,23 +254,22 @@ void main() {
expect(hadError, true);
});

// Find package_config.json in subdir even if initial file syntax error.
loaderTest("specified file syntax error", {
// Don't look for package_config.json if original file not named .packages.
loaderTest("specified file syntax error with alternative", {
"anyname": "syntax error",
".dart_tool": {
"package_config.json": packageConfigFile,
},
}, (Uri directory, loader) async {
}, (directory, loader) async {
var file = directory.resolve("anyname");
var config = await loadPackageConfigUri(file, loader: loader);
expect(config.version, 2);
validatePackagesFile(config, directory);
expect(() => loadPackageConfigUri(file, loader: loader),
throwsFormatException);
});

// A file starting with `{` is a package_config.json file.
loaderTest("file syntax error with {", {
".packages": "{syntax error",
}, (Uri directory, loader) async {
}, (directory, loader) async {
var file = directory.resolve(".packages");
var hadError = false;
await loadPackageConfigUri(file,
Expand Down