2022-04-12 17:21:02 +00:00
|
|
|
// 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.
|
2020-02-27 17:52:23 +00:00
|
|
|
|
|
|
|
/// Generates the repo's ".dart_tool/package_config.json" file.
|
|
|
|
import 'dart:convert';
|
|
|
|
import 'dart:io';
|
|
|
|
|
2022-04-12 17:21:02 +00:00
|
|
|
// Important! Do not add package: imports to this file.
|
|
|
|
// Do not add relative deps for libraries that themselves use package deps.
|
|
|
|
// This tool runs before the .dart_tool/package_config.json file is created, so
|
|
|
|
// can not itself use package references.
|
2020-02-27 17:52:23 +00:00
|
|
|
|
2022-04-12 17:21:02 +00:00
|
|
|
final repoRoot = dirname(dirname(fromUri(Platform.script)));
|
2020-02-27 17:52:23 +00:00
|
|
|
|
|
|
|
void main(List<String> args) {
|
|
|
|
var packageDirs = [
|
2022-04-12 17:21:02 +00:00
|
|
|
...listSubdirectories(platform('pkg')),
|
|
|
|
...listSubdirectories(platform('third_party/pkg_tested')),
|
|
|
|
...listSubdirectories(platform('third_party/pkg')),
|
|
|
|
...listSubdirectories(platform('third_party/pkg/file/packages')),
|
|
|
|
...listSubdirectories(platform('third_party/pkg/test/pkgs')),
|
|
|
|
platform('pkg/vm_service/test/test_package'),
|
|
|
|
platform('runtime/observatory_2'),
|
|
|
|
platform(
|
2020-10-09 20:02:57 +00:00
|
|
|
'runtime/observatory_2/tests/service_2/observatory_test_package_2'),
|
2022-04-12 17:21:02 +00:00
|
|
|
platform('runtime/observatory'),
|
|
|
|
platform('runtime/observatory/tests/service/observatory_test_package'),
|
|
|
|
platform('sdk/lib/_internal/sdk_library_metadata'),
|
|
|
|
platform('third_party/devtools/devtools_shared'),
|
|
|
|
platform('third_party/pkg/protobuf/protobuf'),
|
|
|
|
platform('third_party/pkg/webdev/frontend_server_client'),
|
|
|
|
platform('tools/package_deps'),
|
2020-02-27 17:52:23 +00:00
|
|
|
];
|
|
|
|
|
|
|
|
var cfePackageDirs = [
|
2022-04-12 17:21:02 +00:00
|
|
|
platform('pkg/front_end/testcases'),
|
2020-02-27 17:52:23 +00:00
|
|
|
];
|
|
|
|
|
2020-08-10 08:03:29 +00:00
|
|
|
var feAnalyzerSharedPackageDirs = [
|
2022-04-12 17:21:02 +00:00
|
|
|
platform('pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables'),
|
|
|
|
platform('pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment'),
|
|
|
|
platform(
|
|
|
|
'pkg/_fe_analyzer_shared/test/flow_analysis/definite_unassignment'),
|
|
|
|
platform('pkg/_fe_analyzer_shared/test/flow_analysis/nullability'),
|
|
|
|
platform('pkg/_fe_analyzer_shared/test/flow_analysis/reachability'),
|
|
|
|
platform('pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion'),
|
|
|
|
platform('pkg/_fe_analyzer_shared/test/flow_analysis/why_not_promoted'),
|
|
|
|
platform('pkg/_fe_analyzer_shared/test/inheritance'),
|
2020-08-10 08:03:29 +00:00
|
|
|
];
|
|
|
|
|
2022-04-12 17:21:02 +00:00
|
|
|
var packages = <Package>[
|
2020-02-27 17:52:23 +00:00
|
|
|
...makePackageConfigs(packageDirs),
|
2020-08-10 08:03:29 +00:00
|
|
|
...makeCfePackageConfigs(cfePackageDirs),
|
|
|
|
...makeFeAnalyzerSharedPackageConfigs(feAnalyzerSharedPackageDirs)
|
2020-02-27 17:52:23 +00:00
|
|
|
];
|
2022-04-12 17:21:02 +00:00
|
|
|
packages.sort((a, b) => a.name.compareTo(b.name));
|
|
|
|
|
|
|
|
var configFile = File(join(repoRoot, '.dart_tool', 'package_config.json'));
|
|
|
|
var packageConfig = PackageConfig(
|
|
|
|
packages,
|
|
|
|
extraData: {
|
|
|
|
'copyright': [
|
|
|
|
'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.',
|
|
|
|
],
|
|
|
|
'comment': [
|
|
|
|
'Package configuration for all packages in pkg/, third_party/pkg/, and',
|
|
|
|
'third_party/pkg_tested/',
|
|
|
|
],
|
|
|
|
},
|
|
|
|
);
|
|
|
|
writeIfDifferent(configFile, packageConfig.generateJson('..'));
|
|
|
|
|
|
|
|
// Also generate the repo's .packages file.
|
|
|
|
var packagesFile = File(join(repoRoot, '.packages'));
|
2022-02-21 19:18:31 +00:00
|
|
|
var buffer = StringBuffer('''
|
|
|
|
# Copyright (c) 2016, 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.
|
|
|
|
#
|
|
|
|
# This file is generated; do not edit. To re-generate, run:
|
|
|
|
# 'dart tools/generate_package_config.dart'.
|
|
|
|
|
|
|
|
''');
|
|
|
|
for (var package in packages) {
|
2022-04-12 17:21:02 +00:00
|
|
|
final name = package.name;
|
|
|
|
final rootUri = package.rootUri;
|
|
|
|
final packageUri = package.packageUri;
|
|
|
|
|
2022-02-21 19:18:31 +00:00
|
|
|
if (packageUri != null && packageUri != '.nonexisting') {
|
2022-04-12 17:21:02 +00:00
|
|
|
buffer.writeln('$name:${posix(rootUri)}/${posix(packageUri)}');
|
2022-02-21 19:18:31 +00:00
|
|
|
}
|
|
|
|
}
|
2022-04-12 17:21:02 +00:00
|
|
|
writeIfDifferent(packagesFile, buffer.toString());
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Writes the given [contents] string to [file] if the contents are different
|
|
|
|
/// than what's currently in the file.
|
|
|
|
///
|
|
|
|
/// This updates the file to the given contents, while preserving the file
|
|
|
|
/// timestamp if there are no changes.
|
|
|
|
void writeIfDifferent(File file, String contents) {
|
|
|
|
if (!file.existsSync() || file.readAsStringSync() != contents) {
|
|
|
|
file.writeAsStringSync(contents);
|
|
|
|
}
|
2020-02-27 17:52:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Generates package configurations for each package in [packageDirs].
|
2022-04-12 17:21:02 +00:00
|
|
|
Iterable<Package> makePackageConfigs(List<String> packageDirs) sync* {
|
2020-02-27 17:52:23 +00:00
|
|
|
for (var packageDir in packageDirs) {
|
|
|
|
var version = pubspecLanguageVersion(packageDir);
|
2022-04-12 17:21:02 +00:00
|
|
|
var hasLibDirectory =
|
|
|
|
Directory(join(repoRoot, packageDir, 'lib')).existsSync();
|
|
|
|
|
|
|
|
yield Package(
|
|
|
|
name: basename(packageDir),
|
|
|
|
rootUri: packageDir,
|
|
|
|
packageUri: hasLibDirectory ? 'lib/' : null,
|
|
|
|
languageVersion: version,
|
|
|
|
);
|
2020-02-27 17:52:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-12 17:21:02 +00:00
|
|
|
/// Generates package configurations for the special pseudo-packages used by the
|
|
|
|
/// CFE unit tests (`pkg/front_end/test/unit_test_suites.dart`).
|
|
|
|
Iterable<Package> makeCfePackageConfigs(List<String> packageDirs) sync* {
|
|
|
|
// TODO: Remove the use of '.nonexisting/'.
|
2020-02-27 17:52:23 +00:00
|
|
|
for (var packageDir in packageDirs) {
|
2022-04-12 17:21:02 +00:00
|
|
|
yield Package(
|
|
|
|
name: 'front_end_${basename(packageDir)}',
|
|
|
|
rootUri: packageDir,
|
|
|
|
packageUri: '.nonexisting/',
|
|
|
|
);
|
2020-02-27 17:52:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-12 17:21:02 +00:00
|
|
|
/// Generates package configurations for the special pseudo-packages used by the
|
|
|
|
/// _fe_analyzer_shared id tests.
|
|
|
|
Iterable<Package> makeFeAnalyzerSharedPackageConfigs(
|
2020-08-10 08:03:29 +00:00
|
|
|
List<String> packageDirs) sync* {
|
2022-04-12 17:21:02 +00:00
|
|
|
// TODO: Remove the use of '.nonexisting/'.
|
2020-08-10 08:03:29 +00:00
|
|
|
for (var packageDir in packageDirs) {
|
2022-04-12 17:21:02 +00:00
|
|
|
yield Package(
|
|
|
|
name: '_fe_analyzer_shared_${basename(packageDir)}',
|
|
|
|
rootUri: packageDir,
|
|
|
|
packageUri: '.nonexisting/',
|
|
|
|
);
|
2020-08-10 08:03:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-12 17:21:02 +00:00
|
|
|
/// Finds the paths of the immediate subdirectories of [dir] that
|
2020-02-27 17:52:23 +00:00
|
|
|
/// contain pubspecs.
|
2022-04-12 17:21:02 +00:00
|
|
|
Iterable<String> listSubdirectories(String dir) sync* {
|
|
|
|
for (var entry in Directory(join(repoRoot, dir)).listSync()) {
|
2020-02-27 17:52:23 +00:00
|
|
|
if (entry is! Directory) continue;
|
2022-04-12 17:21:02 +00:00
|
|
|
if (!File(join(entry.path, 'pubspec.yaml')).existsSync()) continue;
|
|
|
|
yield join(dir, basename(entry.path));
|
2020-02-27 17:52:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-12 17:21:02 +00:00
|
|
|
final versionRE = RegExp(r"(?:\^|>=)(\d+\.\d+)");
|
|
|
|
|
2020-02-27 17:52:23 +00:00
|
|
|
/// Infers the language version from the SDK constraint in the pubspec for
|
|
|
|
/// [packageDir].
|
2022-04-12 17:21:02 +00:00
|
|
|
///
|
|
|
|
/// The version is returned in the form `major.minor`.
|
|
|
|
String? pubspecLanguageVersion(String packageDir) {
|
|
|
|
var pubspecFile = File(join(repoRoot, packageDir, 'pubspec.yaml'));
|
2020-02-27 17:52:23 +00:00
|
|
|
|
2020-11-17 00:11:00 +00:00
|
|
|
if (!pubspecFile.existsSync()) {
|
2022-04-12 17:21:02 +00:00
|
|
|
print("Error: Missing pubspec for $packageDir.");
|
2020-11-17 00:11:00 +00:00
|
|
|
exit(1);
|
|
|
|
}
|
2020-02-27 17:52:23 +00:00
|
|
|
|
2022-04-12 17:21:02 +00:00
|
|
|
var contents = pubspecFile.readAsLinesSync();
|
|
|
|
if (!contents.any((line) => line.contains('sdk: '))) {
|
|
|
|
print("Error: Pubspec for $packageDir has no SDK constraint.");
|
2020-11-17 00:11:00 +00:00
|
|
|
exit(1);
|
|
|
|
}
|
2020-02-27 17:52:23 +00:00
|
|
|
|
2022-04-12 17:21:02 +00:00
|
|
|
// Handle either "sdk: >=2.14.0 <3.0.0" or "sdk: ^2.3.0".
|
|
|
|
var sdkConstraint = contents.firstWhere((line) => line.contains('sdk: '));
|
|
|
|
sdkConstraint = sdkConstraint.trim().substring('sdk:'.length).trim();
|
|
|
|
if (sdkConstraint.startsWith('"') || sdkConstraint.startsWith("'")) {
|
|
|
|
sdkConstraint = sdkConstraint.substring(1, sdkConstraint.length - 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
var match = versionRE.firstMatch(sdkConstraint);
|
|
|
|
if (match == null) {
|
|
|
|
print("Error: unknown version range for $packageDir: '$sdkConstraint'.");
|
2020-11-17 00:11:00 +00:00
|
|
|
exit(1);
|
|
|
|
}
|
2022-04-12 17:21:02 +00:00
|
|
|
return match[1]!;
|
|
|
|
}
|
|
|
|
|
|
|
|
class Package {
|
|
|
|
final String name;
|
|
|
|
final String rootUri;
|
|
|
|
final String? packageUri;
|
|
|
|
final String? languageVersion;
|
|
|
|
|
|
|
|
Package({
|
|
|
|
required this.name,
|
|
|
|
required this.rootUri,
|
|
|
|
this.packageUri,
|
|
|
|
this.languageVersion,
|
|
|
|
});
|
|
|
|
|
|
|
|
Map<String, Object?> toMap(String relativeTo) {
|
|
|
|
return {
|
|
|
|
'name': name,
|
|
|
|
'rootUri': posix(join(relativeTo, rootUri)),
|
|
|
|
if (packageUri != null) 'packageUri': posix(packageUri!),
|
|
|
|
if (languageVersion != null) 'languageVersion': languageVersion,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class PackageConfig {
|
|
|
|
final List<Package> packages;
|
|
|
|
final Map<String, Object?>? extraData;
|
|
|
|
|
|
|
|
PackageConfig(this.packages, {this.extraData});
|
|
|
|
|
|
|
|
String generateJson(String relativeTo) {
|
|
|
|
var config = <String, Object?>{};
|
|
|
|
if (extraData != null) {
|
|
|
|
for (var key in extraData!.keys) {
|
|
|
|
config[key] = extraData![key];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
config['configVersion'] = 2;
|
|
|
|
config['generator'] = 'tools/generate_package_config.dart';
|
|
|
|
config['packages'] =
|
|
|
|
packages.map((package) => package.toMap(relativeTo)).toList();
|
|
|
|
var jsonString = JsonEncoder.withIndent(' ').convert(config);
|
|
|
|
return '$jsonString\n';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Below are some (very simplified) versions of the package:path functions.
|
|
|
|
|
|
|
|
final String _separator = Platform.pathSeparator;
|
|
|
|
|
|
|
|
String dirname(String s) {
|
|
|
|
return s.substring(0, s.lastIndexOf(_separator));
|
|
|
|
}
|
2020-02-27 17:52:23 +00:00
|
|
|
|
2022-04-12 17:21:02 +00:00
|
|
|
String join(String s1, String s2, [String? s3]) {
|
|
|
|
if (s3 != null) {
|
|
|
|
return join(join(s1, s2), s3);
|
|
|
|
} else {
|
|
|
|
return s1.endsWith(_separator) ? '$s1$s2' : '$s1$_separator$s2';
|
2022-02-21 19:18:31 +00:00
|
|
|
}
|
2022-04-12 17:21:02 +00:00
|
|
|
}
|
2020-02-27 17:52:23 +00:00
|
|
|
|
2022-04-12 17:21:02 +00:00
|
|
|
String basename(String s) {
|
|
|
|
while (s.endsWith(_separator)) {
|
|
|
|
s = s.substring(0, s.length - 1);
|
|
|
|
}
|
|
|
|
return s.substring(s.lastIndexOf(_separator) + 1);
|
2020-02-27 17:52:23 +00:00
|
|
|
}
|
2022-04-12 17:21:02 +00:00
|
|
|
|
|
|
|
String fromUri(Uri uri) => uri.toFilePath();
|
|
|
|
|
|
|
|
/// Given a platform path, return a posix one.
|
|
|
|
String posix(String s) =>
|
|
|
|
Platform.isWindows ? s.replaceAll(_separator, '/') : s;
|
|
|
|
|
|
|
|
/// Given a posix path, return a platform one.
|
|
|
|
String platform(String s) =>
|
|
|
|
Platform.isWindows ? s.replaceAll('/', _separator) : s;
|