blob: 03c6c623f08db4018dfca6df57b2f671b9fdf775 [file] [log] [blame]
// Copyright (c) 2024, 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.
import 'package:yaml/yaml.dart';
import '../utils.dart' show ExpectEntries, ExpectField;
/// The top level structure of an `sdk_packages.yaml` file.
///
/// See https://github.com/dart-lang/pub/issues/3980 for discussion of the
/// feature and format.
///
/// Version 1 of the format is as follows:
///
/// ```yaml
/// # Required, the version of the format used in this file. Not all versions
/// # will be supported forever, but some number of previous ones will be.
/// version: 1
///
/// # The SDK this configuration file is targeting. Used for validation, to
/// # ensure we are parsing a file intended for the SDK we are configuring.
/// sdk: dart
///
/// # A list of package descriptors, for each package vendored by this SDK.
/// packages:
/// - name: my_sdk_package
/// # A path relative to the root of the installed SDK, in URL form (with `/`
/// # path separators).
/// path: path/to/my_sdk_package
/// ```
class SdkPackageConfig {
/// The name of the SDK this configuration is for.
///
/// SDKs should validate the config is for them on load, and this is the only
/// real use for this field.
final String sdk;
/// All the packages vendored by this SDK. Note that the format in the file is
/// not a map, but a list. When parsing the file we convert it to map for easy
/// lookups.
final Map<String, SdkPackage> packages;
/// The version of the format.
final int version;
SdkPackageConfig(this.sdk, this.packages, this.version);
factory SdkPackageConfig.fromYaml(YamlMap yaml) {
final version = yaml.expectField<int>('version');
if (version != 1) {
throw UnsupportedError(
'This SDK only supports version 1 of the '
'sdk_packages.yaml format, but got version $version',
);
}
final packages = <String, SdkPackage>{};
final packageDescriptions =
yaml.expectField<YamlList>('packages').expectElements<YamlMap>();
for (var description in packageDescriptions) {
final package = SdkPackage.fromYaml(description);
packages[package.name] = package;
}
return SdkPackageConfig(yaml.expectField<String>('sdk'), packages, version);
}
Map<String, Object?> toMap() => {
'sdk': sdk,
'packages': [for (var package in packages.values) package.toMap()],
'version': version,
};
}
/// The structure for each `packages` entry in an `sdk_packages.yaml` file.
class SdkPackage {
/// The name of the package.
final String name;
/// The path to the root of this package relative to the root of the installed
/// SDK.
///
/// This path should be in URL format (with forward slashes), and always
/// relative.
final String path;
SdkPackage(this.name, this.path);
SdkPackage.fromYaml(YamlMap yaml)
: name = yaml.expectPackageNameField(),
path = yaml.expectField<String>('path');
Map<String, Object?> toMap() => {'name': name, 'path': path};
}