blob: b3eaaa4e8dd8ef3428819da42666ed46b9b82327 [file] [log] [blame]
// Utility functions to locate a package_config.json for pub/workspace setups.
import 'dart:io';
import 'package:package_config/package_config.dart';
import 'package:path/path.dart' as p;
/// Walks up from [start] (or the current directory if omitted) to find the
/// nearest `.dart_tool/package_config.json`.
///
/// Returns the absolute file path, or `null` if none is found.
String? findNearestPackageConfigPath([Directory? start]) {
var dir = (start ?? Directory.current).absolute;
while (true) {
final file = File(p.join(dir.path, '.dart_tool', 'package_config.json'));
if (file.existsSync()) return file.path;
final parent = dir.parent;
if (parent.path == dir.path) return null;
dir = parent;
}
}
/// Returns an absolute path under the given [packageName]'s root directory,
/// resolving using the nearest workspace `.dart_tool/package_config.json`.
///
/// This is robust for pub workspace monorepos where the nearest package
/// config lives at the repo root and contains individual entries for each
/// package with its own root.
Future<String> pathFromNearestPackageConfig(
String relativePath, {
String packageName = 'frontend_server_client',
}) async {
final configPath = findNearestPackageConfigPath();
if (configPath == null) {
throw StateError('Could not locate .dart_tool/package_config.json');
}
final config = await loadPackageConfigUri(Uri.file(configPath));
final pkg = config.packages.firstWhere(
(p0) => p0.name == packageName,
orElse: () => throw StateError(
'Package $packageName not found in package config at $configPath',
),
);
final packageRootDir = p.fromUri(pkg.root);
return p.normalize(p.join(packageRootDir, relativePath));
}