Future getExecutableForCommand()

in lib/src/executable.dart [270:380]


Future<DartExecutableWithPackageConfig> getExecutableForCommand(
  String descriptor, {
  bool allowSnapshot = true,
  String? root,
  String? pubCacheDir,
  PubAnalytics? analytics,
}) async {
  root ??= p.current;
  var asPath = descriptor;
  try {
    asPath = Uri.parse(descriptor).toFilePath();
  } catch (_) {
    // Consume input path will either be a valid path or a file uri
    // (e.g /directory/file.dart or file:///directory/file.dart). We will try
    // parsing it as a Uri, but if parsing failed for any reason (likely
    // because path is not a file Uri), `path` will be passed without
    // modification to the VM.
  }

  final asDirectFile = p.join(root, asPath);
  if (fileExists(asDirectFile)) {
    return DartExecutableWithPackageConfig(
      executable: p.relative(asDirectFile, from: root),
      packageConfig: null,
    );
  }
  if (!fileExists(p.join(root, 'pubspec.yaml'))) {
    throw CommandResolutionFailedException._(
        'Could not find file `$descriptor`',
        CommandResolutionIssue.fileNotFound);
  }
  final entrypoint = Entrypoint(root, SystemCache(rootDir: pubCacheDir));
  try {
    // TODO(sigurdm): it would be nicer with a 'isUpToDate' function.
    entrypoint.assertUpToDate();
  } on DataException {
    try {
      await warningsOnlyUnlessTerminal(
        () => entrypoint.acquireDependencies(
          SolveType.get,
          analytics: analytics,
          generateDotPackages: false,
        ),
      );
    } on ApplicationException catch (e) {
      throw CommandResolutionFailedException._(
          e.toString(), CommandResolutionIssue.pubGetFailed);
    }
  }

  late final String command;
  String package;
  if (descriptor.contains(':')) {
    final parts = descriptor.split(':');
    if (parts.length > 2) {
      throw CommandResolutionFailedException._(
        '[<package>[:command]] cannot contain multiple ":"',
        CommandResolutionIssue.parseError,
      );
    }
    package = parts[0];
    if (package.isEmpty) package = entrypoint.root.name;
    command = parts[1];
  } else {
    package = descriptor;
    if (package.isEmpty) package = entrypoint.root.name;
    command = package;
  }

  if (!entrypoint.packageGraph.packages.containsKey(package)) {
    throw CommandResolutionFailedException._(
      'Could not find package `$package` or file `$descriptor`',
      CommandResolutionIssue.packageNotFound,
    );
  }
  final executable = Executable(package, p.join('bin', '$command.dart'));
  final packageConfig = p.join('.dart_tool', 'package_config.json');

  final path = entrypoint.resolveExecutable(executable);
  if (!fileExists(path)) {
    throw CommandResolutionFailedException._(
      'Could not find `bin${p.separator}$command.dart` in package `$package`.',
      CommandResolutionIssue.noBinaryFound,
    );
  }
  if (!allowSnapshot) {
    return DartExecutableWithPackageConfig(
      executable: p.relative(path, from: root),
      packageConfig: packageConfig,
    );
  } else {
    final snapshotPath = entrypoint.pathOfExecutable(executable);
    if (!fileExists(snapshotPath) ||
        entrypoint.packageGraph.isPackageMutable(package)) {
      try {
        await warningsOnlyUnlessTerminal(
          () => entrypoint.precompileExecutable(executable),
        );
      } on ApplicationException catch (e) {
        throw CommandResolutionFailedException._(
          e.toString(),
          CommandResolutionIssue.compilationFailed,
        );
      }
    }
    return DartExecutableWithPackageConfig(
      executable: p.relative(snapshotPath, from: root),
      packageConfig: packageConfig,
    );
  }
}