| // Copyright (c) 2019, 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. |
| |
| /// A package configuration is a way to assign file paths to package URIs, |
| /// and vice-versa, |
| library package_config.package_config_discovery; |
| |
| import "dart:io" show File, Directory; |
| import "dart:typed_data" show Uint8List; |
| |
| import "src/discovery.dart" as discover; |
| import "src/errors.dart" show throwError; |
| import "src/package_config.dart"; |
| import "src/package_config_io.dart"; |
| |
| export "package_config_types.dart"; |
| |
| /// Reads a specific package configuration file. |
| /// |
| /// The file must exist and be readable. |
| /// It must be either a valid `package_config.json` file |
| /// or a valid `.packages` file. |
| /// It is considered a `package_config.json` file if its first character |
| /// is a `{`. |
| /// |
| /// 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] |
| /// being 1 and look for a `package_config.json` file themselves. |
| /// |
| /// If [onError] is provided, the configuration file parsing will report errors |
| /// by calling that function, and then try to recover. |
| /// The returned package configuration is a *best effort* attempt to create |
| /// a valid configuration from the invalid configuration file. |
| /// If no [onError] is provided, errors are thrown immediately. |
| Future<PackageConfig> loadPackageConfig(File file, |
| {bool preferNewest = true, void onError(Object error)}) => |
| readAnyConfigFile(file, preferNewest, onError ?? throwError); |
| |
| /// Reads a specific package configuration URI. |
| /// |
| /// The file of the URI must exist and be readable. |
| /// It must be either a valid `package_config.json` file |
| /// or a valid `.packages` file. |
| /// It is considered a `package_config.json` file if its first |
| /// 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. |
| /// 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] |
| /// being 1 and look for a `package_config.json` file themselves. |
| /// |
| /// If [loader] is provided, URIs are loaded using that function. |
| /// The future returned by the loader must complete with a [Uint8List] |
| /// containing the entire file content encoded as UTF-8, |
| /// or with `null` if the file does not exist. |
| /// The loader may throw at its own discretion, for situations where |
| /// it determines that an error might be need user attention, |
| /// but it is always allowed to return `null`. |
| /// This function makes no attempt to catch such errors. |
| /// As such, it may throw any error that [loader] throws. |
| /// |
| /// If no [loader] is supplied, a default loader is used which |
| /// only accepts `file:`, `http:` and `https:` URIs, |
| /// and which uses the platform file system and HTTP requests to |
| /// fetch file content. The default loader never throws because |
| /// of an I/O issue, as long as the location URIs are valid. |
| /// As such, it does not distinguish between a file not existing, |
| /// and it being temporarily locked or unreachable. |
| /// |
| /// If [onError] is provided, the configuration file parsing will report errors |
| /// by calling that function, and then try to recover. |
| /// The returned package configuration is a *best effort* attempt to create |
| /// a valid configuration from the invalid configuration file. |
| /// If no [onError] is provided, errors are thrown immediately. |
| Future<PackageConfig> loadPackageConfigUri(Uri file, |
| {Future<Uint8List /*?*/ > loader(Uri uri) /*?*/, |
| bool preferNewest = true, |
| void onError(Object error)}) => |
| readAnyConfigFileUri(file, loader, onError ?? throwError, preferNewest); |
| |
| /// Finds a package configuration relative to [directory]. |
| /// |
| /// If [directory] contains a package configuration, |
| /// either a `.dart_tool/package_config.json` file or, |
| /// if not, a `.packages`, then that file is loaded. |
| /// |
| /// If no file is found in the current directory, |
| /// then the parent directories are checked recursively, |
| /// all the way to the root directory, to check if those contains |
| /// a package configuration. |
| /// If [recurse] is set to [false], this parent directory check is not |
| /// performed. |
| /// |
| /// If [onError] is provided, the configuration file parsing will report errors |
| /// by calling that function, and then try to recover. |
| /// The returned package configuration is a *best effort* attempt to create |
| /// a valid configuration from the invalid configuration file. |
| /// If no [onError] is provided, errors are thrown immediately. |
| /// |
| /// Returns `null` if no configuration file is found. |
| Future<PackageConfig> findPackageConfig(Directory directory, |
| {bool recurse = true, void onError(Object error)}) => |
| discover.findPackageConfig(directory, recurse, onError ?? throwError); |
| |
| /// Finds a package configuration relative to [location]. |
| /// |
| /// If [location] contains a package configuration, |
| /// either a `.dart_tool/package_config.json` file or, |
| /// if not, a `.packages`, then that file is loaded. |
| /// The [location] URI *must not* be a `package:` URI. |
| /// It should be a hierarchical URI which is supported |
| /// by [loader]. |
| /// |
| /// If no file is found in the current directory, |
| /// then the parent directories are checked recursively, |
| /// all the way to the root directory, to check if those contains |
| /// a package configuration. |
| /// If [recurse] is set to [false], this parent directory check is not |
| /// performed. |
| /// |
| /// If [loader] is provided, URIs are loaded using that function. |
| /// The future returned by the loader must complete with a [Uint8List] |
| /// containing the entire file content, |
| /// or with `null` if the file does not exist. |
| /// The loader may throw at its own discretion, for situations where |
| /// it determines that an error might be need user attention, |
| /// but it is always allowed to return `null`. |
| /// This function makes no attempt to catch such errors. |
| /// |
| /// If no [loader] is supplied, a default loader is used which |
| /// only accepts `file:`, `http:` and `https:` URIs, |
| /// and which uses the platform file system and HTTP requests to |
| /// fetch file content. The default loader never throws because |
| /// of an I/O issue, as long as the location URIs are valid. |
| /// As such, it does not distinguish between a file not existing, |
| /// and it being temporarily locked or unreachable. |
| /// |
| /// If [onError] is provided, the configuration file parsing will report errors |
| /// by calling that function, and then try to recover. |
| /// The returned package configuration is a *best effort* attempt to create |
| /// a valid configuration from the invalid configuration file. |
| /// If no [onError] is provided, errors are thrown immediately. |
| /// |
| /// Returns `null` if no configuration file is found. |
| Future<PackageConfig> findPackageConfigUri(Uri location, |
| {bool recurse = true, |
| Future<Uint8List /*?*/ > loader(Uri uri), |
| void onError(Object error)}) => |
| discover.findPackageConfigUri( |
| location, loader, onError ?? throwError, recurse); |
| |
| /// Writes a package configuration to the provided directory. |
| /// |
| /// Writes `.dart_tool/package_config.json` relative to [directory]. |
| /// If the `.dart_tool/` directory does not exist, it is created. |
| /// If it cannot be created, this operation fails. |
| /// |
| /// Also writes a `.packages` file in [directory]. |
| /// This will stop happening eventually as the `.packages` file becomes |
| /// discontinued. |
| /// A comment is generated if `[PackageConfig.extraData]` contains a |
| /// `"generator"` entry. |
| Future<void> savePackageConfig( |
| PackageConfig configuration, Directory directory) => |
| writePackageConfigJsonFile(configuration, directory); |