dart-sdk/tools/generate_package_config.dart
Robert Nystrom 328f1be1fe Opt package:meta in to null safety.
This is done by setting the SDK constraint min version in the package's
pubspec to 2.9.0 which is the version that CFE currently uses to mean
"opt in".

However, the pre-built SDK currently checked into the repo can't handle
that version. To work around that, this CL has a gross hack to simply
omit the language version in the generated package config if the
pubspect's version is 2.9. This has the effect of telling CFE to use
the current language version, which is what we want, while also allowing
us to put the right SDK constraint in the package's pubspec.

Change-Id: I51c2952003c83b74fb6f3344c93839fbd267a3ec
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/145020
Auto-Submit: Bob Nystrom <rnystrom@google.com>
Commit-Queue: Leaf Petersen <leafp@google.com>
Reviewed-by: Leaf Petersen <leafp@google.com>
2020-04-28 03:54:48 +00:00

140 lines
5.2 KiB
Dart
Executable file

#!/usr/bin/env dart
/// Generates the repo's ".dart_tool/package_config.json" file.
import 'dart:convert';
import 'dart:io';
import 'package:path/path.dart' as p;
import 'package:pub_semver/pub_semver.dart';
import 'package:yaml/yaml.dart';
final repoRoot = p.dirname(p.dirname(p.fromUri(Platform.script)));
final configFilePath = p.join(repoRoot, '.dart_tool/package_config.json');
void main(List<String> args) {
var packageDirs = [
...listSubdirectories('pkg'),
...listSubdirectories('third_party/pkg'),
...listSubdirectories('third_party/pkg_tested'),
...listSubdirectories('third_party/pkg/test/pkgs'),
packageDirectory('runtime/observatory'),
packageDirectory(
'runtime/observatory/tests/service/observatory_test_package'),
packageDirectory('sdk/lib/_internal/sdk_library_metadata'),
packageDirectory('sdk/lib/_internal/js_runtime'),
packageDirectory('third_party/pkg/protobuf/protobuf'),
packageDirectory('tools/gardening'),
];
var cfePackageDirs = [
packageDirectory('pkg/front_end/testcases/agnostic/'),
packageDirectory('pkg/front_end/testcases/general_nnbd_opt_out/'),
packageDirectory('pkg/front_end/testcases/late_lowering/'),
packageDirectory('pkg/front_end/testcases/nnbd/'),
packageDirectory('pkg/front_end/testcases/nonfunction_type_aliases/'),
];
var packages = [
...makePackageConfigs(packageDirs),
...makeCfePackageConfigs(cfePackageDirs)
];
packages.sort((a, b) => a["name"].compareTo(b["name"]));
var year = DateTime.now().year;
var config = <String, dynamic>{
'copyright': [
'Copyright (c) $year, 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, and checked out by DEPS',
'into /third_party/pkg and /third_party/pkg_tested.',
'If you add a package to DEPS or /pkg or change a package\'s SDK',
'constraint, update this by running tools/generate_package_config.dart.'
],
'configVersion': 2,
'generated': DateTime.now().toIso8601String(),
'generator': 'tools/generate_package_config.dart',
'packages': packages,
};
// TODO(rnystrom): Consider using package_config_v2 to generate this instead.
var json = JsonEncoder.withIndent(' ').convert(config);
File(p.join(repoRoot, '.dart_tool', 'package_config.json'))
.writeAsStringSync(json);
print('Generated .dart_tool/package_config.dart containing '
'${packages.length} packages.');
}
/// Generates package configurations for each package in [packageDirs].
Iterable<Map<String, String>> makePackageConfigs(
List<String> packageDirs) sync* {
for (var packageDir in packageDirs) {
var version = pubspecLanguageVersion(packageDir);
var hasLibDirectory = Directory(p.join(packageDir, 'lib')).existsSync();
// TODO(rnystrom): Currently, the pre-built SDK does not allow language
// version 2.9.0. Until that's fixed, if we see that version, just write
// no version at all so that implementations use the current language
// version.
if (version.toString() == '2.9.0') version = null;
yield {
'name': p.basename(packageDir),
'rootUri': p.relative(packageDir, from: p.dirname(configFilePath)),
if (hasLibDirectory) 'packageUri': 'lib/',
if (version != null)
'languageVersion': '${version.major}.${version.minor}'
};
}
}
/// Generates package configurations for the special pseudo-packages used by
/// the CFE unit tests (`pkg/front_end/test/unit_test_suites.dart`).
Iterable<Map<String, String>> makeCfePackageConfigs(
List<String> packageDirs) sync* {
for (var packageDir in packageDirs) {
yield {
'name': 'front_end_${p.basename(packageDir)}',
'rootUri': p.relative(packageDir, from: p.dirname(configFilePath)),
'packageUri': '.nonexisting/',
};
}
}
/// Generates a path to [relativePath] within the repo.
String packageDirectory(String relativePath) => p.join(repoRoot, relativePath);
/// Finds the paths of the immediate subdirectories of [packagesDir] that
/// contain pubspecs.
Iterable<String> listSubdirectories(String packagesDir) sync* {
for (var entry in Directory(p.join(repoRoot, packagesDir)).listSync()) {
if (entry is! Directory) continue;
if (!File(p.join(entry.path, 'pubspec.yaml')).existsSync()) continue;
yield entry.path;
}
}
/// Infers the language version from the SDK constraint in the pubspec for
/// [packageDir].
///
/// Returns `null` if there is no pubspec or no SDK constraint.
Version pubspecLanguageVersion(String packageDir) {
var pubspecFile = File(p.join(packageDir, 'pubspec.yaml'));
if (!pubspecFile.existsSync()) return null;
var pubspec =
loadYaml(pubspecFile.readAsStringSync()) as Map<dynamic, dynamic>;
if (!pubspec.containsKey('environment')) return null;
var environment = pubspec['environment'] as Map<dynamic, dynamic>;
if (!environment.containsKey('sdk')) return null;
var sdkConstraint = VersionConstraint.parse(environment['sdk'] as String);
if (sdkConstraint is VersionRange) return sdkConstraint.min;
return null;
}