| // Copyright (c) 2023, 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:file/file.dart'; |
| import 'package:package_config/package_config.dart'; |
| |
| import '../build_runner/build_runner.dart'; |
| |
| /// Directory layout for dealing with native assets. |
| /// |
| /// For the [NativeAssetsBuildRunner] to correctly run hooks, multiple pieces of |
| /// information are required: |
| /// * [packageConfig] to know the list of all packages that may contain hooks. |
| /// * [packageConfigUri] to be able to get a dependency graph with `pub` and to |
| /// know where to cache/share asset builds. |
| /// * [runPackageName] to know which package build hooks to invoke and ignore. |
| /// Only dependencies of the "run package" are built. |
| /// |
| /// The [NativeAssetsBuildRunner] builds assets in |
| /// `.dart_tool/hooks_runner/`. The directory layout follows pub's |
| /// convention for caching: |
| /// https://dart.dev/tools/pub/package-layout#project-specific-caching-for-tools |
| class PackageLayout { |
| /// Package config containing the information of where to find the root [Uri]s |
| /// of other packages. |
| /// |
| /// Can be `null` to enable quick construction of a |
| /// [PackageLayout]. |
| final PackageConfig packageConfig; |
| |
| final Uri packageConfigUri; |
| |
| /// Only assets of transitive dependencies of [runPackageName] are built. |
| final String runPackageName; |
| |
| /// Include the dev dependencies of [runPackageName]. |
| final bool includeDevDependencies; |
| |
| PackageLayout._( |
| this.packageConfig, |
| this.packageConfigUri, |
| this.runPackageName, { |
| required this.includeDevDependencies, |
| }); |
| |
| factory PackageLayout.fromPackageConfig( |
| FileSystem fileSystem, |
| PackageConfig packageConfig, |
| Uri packageConfigUri, |
| String runPackageName, { |
| required bool includeDevDependencies, |
| }) { |
| assert(fileSystem.file(packageConfigUri).existsSync()); |
| packageConfigUri = packageConfigUri.normalizePath(); |
| return PackageLayout._( |
| packageConfig, |
| packageConfigUri, |
| runPackageName, |
| includeDevDependencies: includeDevDependencies, |
| ); |
| } |
| |
| static Future<PackageLayout> fromWorkingDirectory( |
| FileSystem fileSystem, |
| Uri workingDirectory, |
| String runPackageName, { |
| required bool includeDevDependencies, |
| }) async { |
| workingDirectory = workingDirectory.normalizePath(); |
| final packageConfigUri = await findPackageConfig( |
| fileSystem, |
| workingDirectory, |
| ); |
| assert(await fileSystem.file(packageConfigUri).exists()); |
| final packageConfig = await loadPackageConfigUri(packageConfigUri!); |
| return PackageLayout._( |
| packageConfig, |
| packageConfigUri, |
| runPackageName, |
| includeDevDependencies: includeDevDependencies, |
| ); |
| } |
| |
| static Future<Uri?> findPackageConfig( |
| FileSystem fileSystem, |
| Uri rootPackageRoot, |
| ) async { |
| final packageConfigUri = rootPackageRoot.resolve( |
| '.dart_tool/package_config.json', |
| ); |
| final file = fileSystem.file(packageConfigUri); |
| if (await file.exists()) { |
| return file.uri; |
| } |
| final parentUri = rootPackageRoot.resolve('../'); |
| if (parentUri == rootPackageRoot) { |
| return null; |
| } |
| return findPackageConfig(fileSystem, parentUri); |
| } |
| |
| /// The .dart_tool directory is used to store built artifacts and caches. |
| /// |
| /// This is the `.dart_tool/` directory where the package config is. |
| /// |
| /// When pub workspaces are used, the hook results are shared across all |
| /// packages in the workspace. |
| /// |
| /// Each package should only modify the subfolder of `.dart_tool/` with its |
| /// own name. |
| /// https://dart.dev/tools/pub/package-layout#project-specific-caching-for-tools |
| late final Uri dartTool = packageConfigUri.resolve('./'); |
| |
| /// The directory where `package:hooks_runner` stores all persistent |
| /// information. |
| /// |
| /// This folder is owned by `package:hooks_runnner`, no other package |
| /// should read or modify it. |
| /// https://dart.dev/tools/pub/package-layout#project-specific-caching-for-tools |
| /// |
| /// `$rootPackageRoot/.dart_tool/hooks_runner/`. |
| late final Uri dartToolHooksRunner = dartTool.resolve('hooks_runner/'); |
| |
| /// The root of `package:$packageName`. |
| /// |
| /// `$packageName/`. |
| /// |
| /// This folder is owned by pub, and should _never_ be written to. |
| Uri packageRoot(String packageName) { |
| final package = packageConfig[packageName]; |
| if (package == null) { |
| throw StateError('Package $packageName not found in packageConfig.'); |
| } |
| return package.root; |
| } |
| } |