// Copyright (c) 2012, 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 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:math';

import 'package:collection/collection.dart';
import 'package:path/path.dart' as p;
import 'package:pool/pool.dart';
import 'package:pub_semver/pub_semver.dart';
import 'package:source_span/source_span.dart';
import 'package:yaml/yaml.dart';
import 'package:yaml_edit/yaml_edit.dart';

import 'command_runner.dart';
import 'dart.dart' as dart;
import 'exceptions.dart';
import 'executable.dart';
import 'io.dart';
import 'language_version.dart';
import 'lock_file.dart';
import 'log.dart' as log;
import 'package.dart';
import 'package_config.dart';
import 'package_graph.dart';
import 'package_name.dart';
import 'pubspec.dart';
import 'pubspec_utils.dart';
import 'sdk.dart';
import 'sdk/flutter.dart';
import 'solver.dart';
import 'solver/report.dart';
import 'solver/solve_suggestions.dart';
import 'source/cached.dart';
import 'source/hosted.dart';
import 'source/root.dart';
import 'source/unknown.dart';
import 'system_cache.dart';
import 'utils.dart';

/// The context surrounding the workspace pub is operating on.
///
/// Pub operates over a directed graph of dependencies that starts at a root
/// "entrypoint" package. This is typically the package where the current
/// working directory is located.
///
/// An entrypoint knows the [workspaceRoot] package it is associated with and is
/// responsible for managing the package config (.dart_tool/package_config.json)
/// and lock file (pubspec.lock) for it.
///
/// While entrypoints are typically applications, a pure library package may end
/// up being used as an entrypoint while under development. Also, a single
/// package may be used as an entrypoint in one context but not in another. For
/// example, a package that contains a reusable library may not be the
/// entrypoint when used by an app, but may be the entrypoint when you're
/// running its tests.
class Entrypoint {
  /// The directory where this entrypoint is created.
  ///
  /// [workspaceRoot] will be the package in the nearest parent directory that
  /// has `resolution: null`
  final String workingDir;

  /// Finds the [workspaceRoot] and [workPackage] based on [workingDir].
  ///
  /// Works by iterating through the parent directories from [workingDir].
  ///
  /// [workPackage] is the package of first dir we find with a `pubspec.yaml`
  /// file.
  ///
  /// [workspaceRoot] is the package of the first dir we find with a
  /// `pubspec.yaml` that does not have `resolution: workspace`.
  ///
  /// [workPackage] and [workspaceRoot] can be the same. And will always be the
  /// same when no `workspace` is involved.
  /// =
  /// If [workingDir] doesn't exist, [fail].
  ///
  /// If no `pubspec.yaml` is found without `resolution: workspace` we [fail].
  static ({Package root, Package work}) _loadWorkspace(
    String workingDir,
    SystemCache cache,
  ) {
    if (!dirExists(workingDir)) {
      fail('The directory `$workingDir` does not exist.');
    }
    // Keep track of all the pubspecs met when walking up the file system.
    // The first of these is the workingPackage.
    final pubspecsMet = <String, Pubspec>{};
    for (final dir in parentDirs(workingDir)) {
      final Pubspec pubspec;

      try {
        pubspec = Pubspec.load(
          dir,
          cache.sources,
          containingDescription: ResolvedRootDescription.fromDir(dir),
          allowOverridesFile: true,
        );
      } on FileException {
        continue;
      }
      pubspecsMet[p.canonicalize(dir)] = pubspec;
      final Package root;
      if (pubspec.resolution == Resolution.none) {
        root = Package.load(
          dir,
          loadPubspec:
              (path, {expectedName, required withPubspecOverrides}) =>
                  pubspecsMet[p.canonicalize(path)] ??
                  Pubspec.load(
                    path,
                    cache.sources,
                    expectedName: expectedName,
                    allowOverridesFile: withPubspecOverrides,
                    containingDescription: ResolvedRootDescription.fromDir(
                      path,
                    ),
                  ),
          withPubspecOverrides: true,
        );
        for (final package in root.transitiveWorkspace) {
          if (identical(pubspecsMet.entries.first.value, package.pubspec)) {
            validateWorkspace(root);
            return (root: root, work: package);
          }
        }
        assert(false);
      }
    }
    if (pubspecsMet.isEmpty) {
      final dir = p.normalize(p.absolute(workingDir));
      throw FileException(
        'Found no `pubspec.yaml` file in `$dir` or parent directories',
        p.join(workingDir, 'pubspec.yaml'),
      );
    } else {
      final firstEntry = pubspecsMet.entries.first;
      throw FileException(
        '''
Found a pubspec.yaml at ${firstEntry.key}. But it has resolution `${firstEntry.value.resolution.name}`.
But found no workspace root including it in parent directories.

See $workspacesDocUrl for more information.''',
        p.join(workingDir, 'pubspec.yaml'),
      );
    }
  }

  /// Stores the result of [_loadWorkspace].
  /// Only access via [workspaceRoot], [workPackage] and [canFindWorkspaceRoot].
  ({Package root, Package work})? _packages;

  /// Only access via [workspaceRoot], [workPackage] and [canFindWorkspaceRoot].
  ({Package root, Package work}) get _getPackages =>
      _packages ??= _loadWorkspace(workingDir, cache);

  /// The root package this entrypoint is associated with.
  ///
  /// For a global package, this is the activated package.
  Package get workspaceRoot => _getPackages.root;

  /// True if we can find a `pubspec.yaml` to resolve in [workingDir] or any
  /// parent directory.
  bool get canFindWorkspaceRoot {
    try {
      _getPackages;
      return true;
    } on FileException {
      return false;
    }
  }

  /// The "focus" package that the current command should act upon.
  ///
  /// It will be the package in the nearest parent directory to `workingDir`.
  /// Example: if a workspace looks like this:
  ///
  /// foo/ pubspec.yaml # contains `workspace: [- 'bar'] bar/ pubspec.yaml #
  ///   contains `resolution: workspace`.
  ///
  /// Running `pub add` in `foo/bar` will have bar as workPackage, and add
  /// dependencies to `foo/bar/pubspec.yaml`.
  ///
  /// Running `pub add` in `foo` will have foo as workPackage, and add
  /// dependencies to `foo/pubspec.yaml`.
  Package get workPackage => _getPackages.work;

  /// The system-wide cache which caches packages that need to be fetched over
  /// the network.
  final SystemCache cache;

  /// Whether this entrypoint exists within the package cache.
  bool get isCached => p.isWithin(cache.rootDir, workingDir);

  /// Whether this is an entrypoint for a globally-activated package.
  ///
  /// False for path-activated global packages.
  final bool isCachedGlobal;

  /// The lockfile for the entrypoint.
  ///
  /// If not provided to the entrypoint, it will be loaded lazily from disk.
  LockFile get lockFile => _lockFile ??= _loadLockFile(lockFilePath, cache);

  static LockFile _loadLockFile(String lockFilePath, SystemCache cache) {
    if (!fileExists(lockFilePath)) {
      return LockFile.empty();
    } else {
      try {
        return LockFile.load(lockFilePath, cache.sources);
      } on SourceSpanException catch (e) {
        throw SourceSpanApplicationException(
          e.message,
          e.span,
          explanation: 'Failed parsing lock file:',
          hint:
              'Consider deleting the file and running '
              '`$topLevelProgram pub get` to recreate it.',
        );
      }
    }
  }

  LockFile? _lockFile;

  /// The `.dart_tool/package_config.json` package-config of this entrypoint.
  ///
  /// Lazily initialized. Will throw [DataException] when initializing if the
  /// `.dart_tool/packageConfig.json` file doesn't exist or has a bad format .
  PackageConfig get packageConfig =>
      _packageConfig ??= _loadPackageConfig(packageConfigPath);
  PackageConfig? _packageConfig;

  static PackageConfig _loadPackageConfig(String packageConfigPath) {
    Never badPackageConfig() {
      dataError(
        'The "$packageConfigPath" file is not recognized by '
        '"pub" version, please run "$topLevelProgram pub get".',
      );
    }

    final String packageConfigRaw;
    try {
      packageConfigRaw = readTextFile(packageConfigPath);
    } on FileException {
      dataError(
        'The "$packageConfigPath" file does not exist, '
        'please run "$topLevelProgram pub get".',
      );
    }
    final PackageConfig result;
    try {
      result = PackageConfig.fromJson(json.decode(packageConfigRaw) as Object?);
    } on FormatException {
      badPackageConfig();
    }
    // Version 2 is the initial version number for `package_config.json`,
    // because `.packages` was version 1 (even if it was a different file).
    // If the version is different from 2, then it must be a newer incompatible
    // version, hence, the user should run `pub get` with the downgraded SDK.
    if (result.configVersion != 2) {
      badPackageConfig();
    }
    return result;
  }

  /// The package graph for the application and all of its transitive
  /// dependencies.
  ///
  /// Throws a [DataException] if the `.dart_tool/package_config.json` file
  /// isn't up-to-date relative to the pubspec and the lockfile.
  Future<PackageGraph> get packageGraph =>
      _packageGraph ??= _createPackageGraph();

  Future<PackageGraph> _createPackageGraph() async {
    // TODO(sigurdm): consider having [ensureUptoDate] and [acquireDependencies]
    // return the package-graph, such it by construction will always made from
    // an up-to-date package-config.
    await ensureUpToDate(workspaceRoot.dir, cache: cache);
    final packages = {
      for (var packageEntry in packageConfig.packages)
        packageEntry.name: Package.load(
          packageEntry.resolvedRootDir(packageConfigPath),
          expectedName: packageEntry.name,
          loadPubspec: Pubspec.loadRootWithSources(cache.sources),
        ),
    };
    packages[workspaceRoot.name] = workspaceRoot;

    return PackageGraph(this, packages);
  }

  Future<PackageGraph>? _packageGraph;

  /// The path to the entrypoint's ".dart_tool/package_config.json" file
  /// relative to the current working directory .
  late final String packageConfigPath = p.relative(
    p.normalize(p.join(workspaceRoot.dir, '.dart_tool', 'package_config.json')),
  );

  late final String packageGraphPath = p.relative(
    p.normalize(p.join(workspaceRoot.dir, '.dart_tool', 'package_graph.json')),
  );

  /// The path to the entrypoint workspace's lockfile.
  String get lockFilePath =>
      p.normalize(p.join(workspaceRoot.dir, 'pubspec.lock'));

  /// The path to the directory containing dependency executable snapshots.
  String get _snapshotPath => p.join(
    isCachedGlobal
        ? workspaceRoot.dir
        : p.join(workspaceRoot.dir, '.dart_tool/pub'),
    'bin',
  );

  Entrypoint._(
    this.workingDir,
    this._lockFile,
    this._examples,
    this._packageGraph,
    this.cache,
    this._packages,
    this.isCachedGlobal,
  );

  /// An entrypoint for the workspace containing [workingDir]/
  ///
  /// If [checkInCache] is `true` (the default) an error will be thrown if
  /// [workingDir] is located inside [cache]`.rootDir`.

  Entrypoint(this.workingDir, this.cache, {bool checkInCache = true})
    : isCachedGlobal = false {
    if (checkInCache && p.isWithin(cache.rootDir, workingDir)) {
      fail('Cannot operate on packages inside the cache.');
    }
  }

  /// Creates an entrypoint at the same location, but with each pubspec in
  /// [updatedPubspecs] replacing the with one for the corresponding package.
  Entrypoint withUpdatedRootPubspecs(Map<Package, Pubspec> updatedPubspecs) {
    final newWorkspaceRoot = workspaceRoot.transformWorkspace(
      (package) => updatedPubspecs[package] ?? package.pubspec,
    );
    final newWorkPackage = newWorkspaceRoot.transitiveWorkspace.firstWhere(
      (package) => package.dir == workPackage.dir,
    );
    return Entrypoint._(
      workingDir,
      _lockFile,
      _examples,
      _packageGraph,
      cache,
      (root: newWorkspaceRoot, work: newWorkPackage),
      isCachedGlobal,
    );
  }

  /// Creates an entrypoint at the same location, that will use [pubspec] for
  /// resolution of the [workPackage].
  Entrypoint withWorkPubspec(Pubspec pubspec) {
    return withUpdatedRootPubspecs({workPackage: pubspec});
  }

  /// Creates an entrypoint given package and lockfile objects.
  /// If a SolveResult is already created it can be passed as an optimization.
  Entrypoint.global(
    Package package,
    this._lockFile,
    this.cache, {
    SolveResult? solveResult,
  }) : _packages = (root: package, work: package),
       workingDir = package.dir,
       isCachedGlobal = true {
    if (solveResult != null) {
      _packageGraph = Future.value(
        PackageGraph.fromSolveResult(this, solveResult),
      );
    }
  }

  /// Gets  [Entrypoint]s for examples of any workspace packages.
  ///
  /// Does not return examples that are already in the workspace
  ///
  /// This will be empty if the example folder doesn't have a `pubspec.yaml`.
  List<Entrypoint> get examples {
    if (_examples case final List<Entrypoint> examples) return examples;
    final directoriesInWorkspace = <String>{};
    for (final package in workspaceRoot.transitiveWorkspace) {
      directoriesInWorkspace.add(p.canonicalize(package.dir));
    }
    final result = <Entrypoint>[];
    for (final package in workspaceRoot.transitiveWorkspace) {
      final examplePath = package.path('example');

      if (!directoriesInWorkspace.contains(p.canonicalize(examplePath)) &&
          fileExists(p.join(examplePath, 'pubspec.yaml'))) {
        result.add(Entrypoint(examplePath, cache));
      }
    }
    return _examples = result;
  }

  List<Entrypoint>? _examples;

  /// Writes the .dart_tool/package_config.json file and workspace references to
  /// it.
  ///
  /// Compares it to the existing .dart_tool/package_config.json and does not
  /// rewrite it unless it is
  ///
  /// Also writes the .dart_tool.package_graph.json file.
  ///
  /// If the workspace is non-trivial: For each package in the workspace write:
  /// `.dart_tool/pub/workspace_ref.json` with a pointer to the workspace root
  /// package dir.
  ///
  /// Also marks the package active in `PUB_CACHE/active_roots/`.
  Future<void> writePackageConfigFiles() async {
    ensureDir(p.dirname(packageConfigPath));

    writeTextFileIfDifferent(
      packageConfigPath,
      await _packageConfigFile(
        cache,
        entrypointSdkConstraint:
            workspaceRoot
                .pubspec
                .sdkConstraints[sdk.identifier]
                ?.effectiveConstraint,
      ),
    );
    writeTextFileIfDifferent(packageGraphPath, await _packageGraphFile(cache));

    if (workspaceRoot.workspaceChildren.isNotEmpty) {
      for (final package in workspaceRoot.transitiveWorkspace) {
        final workspaceRefDir = p.join(package.dir, '.dart_tool', 'pub');
        final workspaceRefPath = p.join(workspaceRefDir, 'workspace_ref.json');
        ensureDir(workspaceRefDir);
        final relativeRootPath = p.relative(
          workspaceRoot.dir,
          from: workspaceRefDir,
        );
        final workspaceRef = const JsonEncoder.withIndent(
          '  ',
        ).convert({'workspaceRoot': relativeRootPath});
        writeTextFileIfDifferent(workspaceRefPath, '$workspaceRef\n');
      }
    }
    if (lockFile.packages.values.any((id) => id.source is CachedSource)) {
      cache.markRootActive(packageConfigPath);
    }
  }

  Future<String> _packageGraphFile(SystemCache cache) async {
    return const JsonEncoder.withIndent('  ').convert({
      'roots':
          workspaceRoot.transitiveWorkspace.map((p) => p.name).toList()..sort(),
      'packages': [
        for (final p in workspaceRoot.transitiveWorkspace)
          {
            'name': p.name,
            'version': p.version.toString(),
            'dependencies': p.dependencies.keys.toList()..sort(),
            'devDependencies': p.devDependencies.keys.toList()..sort(),
          },
        for (final p in lockFile.packages.values)
          {
            'name': p.name,
            'version': p.version.toString(),
            'dependencies':
                (await cache.describe(p)).dependencies.keys.toList()..sort(),
          },
      ],
      'configVersion': 1,
    });
  }

  /// Returns the contents of the `.dart_tool/package_config` file generated
  /// from this entrypoint based on [lockFile].
  ///
  /// If [isCachedGlobal] no entry will be created for [workspaceRoot].
  Future<String> _packageConfigFile(
    SystemCache cache, {
    VersionConstraint? entrypointSdkConstraint,
  }) async {
    final entries = <PackageConfigEntry>[];
    if (lockFile.packages.isNotEmpty) {
      final relativeFromPath = p.join(workspaceRoot.dir, '.dart_tool');
      for (final name in lockFile.packages.keys.sorted()) {
        final id = lockFile.packages[name]!;
        final rootPath = cache.getDirectory(id, relativeFrom: relativeFromPath);
        final pubspec = await cache.describe(id);
        entries.add(
          PackageConfigEntry(
            name: name,
            rootUri: p.toUri(rootPath),
            packageUri: p.toUri('lib/'),
            languageVersion: pubspec.languageVersion,
          ),
        );
      }
    }

    if (!isCachedGlobal) {
      /// Run through the entire workspace transitive closure and add an entry
      /// for each package.
      for (final package in workspaceRoot.transitiveWorkspace) {
        entries.add(
          PackageConfigEntry(
            name: package.name,
            rootUri: p.toUri(
              p.relative(
                package.dir,
                from: p.join(workspaceRoot.dir, '.dart_tool'),
              ),
            ),
            packageUri: p.toUri('lib/'),
            languageVersion: package.pubspec.languageVersion,
          ),
        );
      }
    }

    final packageConfig = PackageConfig(
      configVersion: 2,
      packages: entries,
      generator: 'pub',
      generatorVersion: sdk.version,
      additionalProperties: {
        if (FlutterSdk().isAvailable) ...{
          'flutterRoot':
              p.toUri(p.absolute(FlutterSdk().rootDirectory!)).toString(),
          'flutterVersion': FlutterSdk().version.toString(),
        },
        'pubCache': p.toUri(p.absolute(cache.rootDir)).toString(),
      },
    );

    final jsonText = const JsonEncoder.withIndent(
      '  ',
    ).convert(packageConfig.toJson());
    return '$jsonText\n';
  }

  /// Gets all dependencies of the [workspaceRoot] package.
  ///
  /// Performs version resolution according to [SolveType].
  ///
  /// The iterable [unlock] specifies the list of packages whose versions can be
  /// changed even if they are locked in the pubspec.lock file.
  ///
  /// Shows a report of the changes made relative to the previous lockfile. If
  /// this is an upgrade or downgrade, all transitive dependencies are shown in
  /// the report. Otherwise, only dependencies that were changed are shown. If
  /// [dryRun] is `true`, no physical changes are made.
  ///
  /// If [precompile] is `true` (the default), this snapshots dependencies'
  /// executables.
  ///
  /// if [summaryOnly] is `true` only success or failure will be
  /// shown --- in case of failure, a reproduction command is shown.
  ///
  /// Updates [lockFile] and [packageGraph] accordingly.
  ///
  /// If [enforceLockfile] is true no changes to the current lockfile are
  /// allowed. Instead the existing lockfile is loaded, verified against
  /// pubspec.yaml and all dependencies downloaded.
  Future<void> acquireDependencies(
    SolveType type, {
    Iterable<String> unlock = const [],
    bool dryRun = false,
    bool precompile = false,
    bool summaryOnly = false,
    bool enforceLockfile = false,
  }) async {
    workspaceRoot; // This will throw early if pubspec.yaml could not be found.
    summaryOnly = summaryOnly || _summaryOnlyEnvironment;
    final suffix =
        workspaceRoot.dir == '.'
            ? ''
            : ' in `${workspaceRoot.presentationDir}`';

    if (enforceLockfile && !fileExists(lockFilePath)) {
      throw ApplicationException('''
Retrieving dependencies failed$suffix.
Cannot do `--enforce-lockfile` without an existing `pubspec.lock`.

Try running `$topLevelProgram pub get` to create `$lockFilePath`.''');
    }

    SolveResult result;

    try {
      result = await log.progress('Resolving dependencies$suffix', () async {
        // TODO(https://github.com/dart-lang/pub/issues/4127): Check this for
        // all workspace pubspecs.
        _checkSdkConstraint(workspaceRoot.pubspecPath, workspaceRoot.pubspec);
        return resolveVersions(
          type,
          cache,
          workspaceRoot,
          lockFile: lockFile,
          unlock: unlock,
        );
      });
    } on SolveFailure catch (e) {
      throw SolveFailure(
        e.incompatibility,
        suggestions: await suggestResolutionAlternatives(
          this,
          type,
          e.incompatibility,
          unlock,
          cache,
        ),
      );
    }

    // We have to download files also with --dry-run to ensure we know the
    // archive hashes for downloaded files.
    final newLockFile = await result.downloadCachedPackages(cache);
    final report = SolveReport(
      type,
      workspaceRoot.presentationDir,
      workspaceRoot.pubspec,
      workspaceRoot.allOverridesInWorkspace,
      lockFile,
      newLockFile,
      result.availableVersions,
      cache,
      dryRun: dryRun,
      enforceLockfile: enforceLockfile,
      quiet: summaryOnly,
    );

    await report.show(summary: true);
    if (enforceLockfile && !lockFile.samePackageIds(newLockFile)) {
      dataError('''
Unable to satisfy `${workspaceRoot.pubspecPath}` using `$lockFilePath`$suffix.

To update `$lockFilePath` run `$topLevelProgram pub get`$suffix without
`--enforce-lockfile`.''');
    }

    if (!(dryRun || enforceLockfile)) {
      newLockFile.writeToFile(lockFilePath, cache);
    }

    _lockFile = newLockFile;

    if (!dryRun) {
      _removeStrayLockAndConfigFiles();

      /// Build a package graph from the version solver results so we don't
      /// have to reload and reparse all the pubspecs.
      _packageGraph = Future.value(PackageGraph.fromSolveResult(this, result));

      await writePackageConfigFiles();

      try {
        if (precompile) {
          await precompileExecutables();
        } else {
          await _deleteExecutableSnapshots();
        }
      } catch (error, stackTrace) {
        // Just log exceptions here. Since the method is just about acquiring
        // dependencies, it shouldn't fail unless that fails.
        log.exception(error, stackTrace);
      }
    }
  }

  /// All executables that should be snapshotted from this entrypoint.
  ///
  /// This is all executables in direct dependencies.
  /// that don't transitively depend on `this` or on a mutable dependency.
  ///
  /// Except globally activated packages they should precompile executables from
  /// the package itself if they are immutable.
  Future<List<Executable>> get _builtExecutables async {
    final graph = await packageGraph;
    final r =
        workspaceRoot.immediateDependencies.keys.expand((packageName) {
          final package = graph.packages[packageName]!;
          return package.executablePaths.map(
            (path) => Executable(packageName, path),
          );
        }).toList();
    return r;
  }

  /// Precompiles all [_builtExecutables].
  Future<void> precompileExecutables() async {
    final executables = await _builtExecutables;

    if (executables.isEmpty) return;

    await log.progress('Building package executables', () async {
      if (isCachedGlobal) {
        /// Global snapshots might linger in the cache if we don't remove old
        /// snapshots when it is re-activated.
        cleanDir(_snapshotPath);
      } else {
        ensureDir(_snapshotPath);
      }
      // Don't do more than `Platform.numberOfProcessors - 1` compilations
      // concurrently. Though at least one.
      final pool = Pool(max(Platform.numberOfProcessors - 1, 1));
      return waitAndPrintErrors(
        executables.map((executable) async {
          await pool.withResource(() async {
            return _precompileExecutable(executable);
          });
        }),
      );
    });
  }

  /// Precompiles [executable] to a snapshot.
  ///
  /// The [additionalSources], if provided, instruct the compiler to include
  /// additional source files into compilation even if they are not referenced
  /// from the main library.
  ///
  /// The [nativeAssets], if provided, instruct the compiler include a native
  /// assets map.
  Future<void> precompileExecutable(
    Executable executable, {
    List<String> additionalSources = const [],
    String? nativeAssets,
  }) async {
    await log.progress('Building package executable', () async {
      ensureDir(p.dirname(pathOfSnapshot(executable)));
      return await _precompileExecutable(
        executable,
        additionalSources: additionalSources,
        nativeAssets: nativeAssets,
      );
    });
  }

  Future<void> _precompileExecutable(
    Executable executable, {
    List<String> additionalSources = const [],
    String? nativeAssets,
  }) async {
    final package = executable.package;

    await dart.precompile(
      executablePath: executable.resolve(packageConfig, packageConfigPath),
      outputPath: pathOfSnapshot(executable),
      packageConfigPath: packageConfigPath,
      name: '$package:${p.basenameWithoutExtension(executable.relativePath)}',
      additionalSources: additionalSources,
      nativeAssets: nativeAssets,
    );
    cache.maintainCache();
  }

  /// The location of the snapshot of the dart program at [executable]
  /// will be stored here.
  ///
  /// We use the sdk version to make sure we don't run snapshots from a
  /// different sdk.
  String pathOfSnapshot(Executable executable) {
    return isCachedGlobal
        ? executable.pathOfGlobalSnapshot(workspaceRoot.dir)
        : executable.pathOfSnapshot(workspaceRoot.dir);
  }

  /// Deletes cached snapshots that are from a different sdk.
  Future<void> _deleteExecutableSnapshots() async {
    if (!dirExists(_snapshotPath)) return;
    // Clean out any outdated snapshots.
    for (var entry in listDir(_snapshotPath)) {
      if (!fileExists(entry)) {
        // Not a file
        continue;
      }

      if (!entry.endsWith('${sdk.version}.snapshot')) {
        // Made with a different sdk version. Clean it up.
        deleteEntry(entry);
      }
    }
  }

  /// The [PackageConfig] object representing `.dart_tool/package_config.json`
  /// along with the dir where it resides, if it and `pubspec.lock` exist and
  /// are up to date with respect to pubspec.yaml and its dependencies. Or
  /// `null` if it is outdated.
  ///
  /// Always returns `null` if `.dart_tool/package_config.json` was generated
  /// with a different PUB_CACHE location, a different $FLUTTER_ROOT or a
  /// different Dart or Flutter SDK version.
  ///
  /// Otherwise first the `modified` timestamps are compared, and if
  /// `.dart_tool/package_config.json` is newer than `pubspec.lock` that is
  /// newer than all pubspec.yamls of all packages in
  /// `.dart_tool/package_config.json` we short-circuit and return true.
  ///
  /// If any of the timestamps are out of order, the resolution in
  /// pubspec.lock is validated against constraints of all pubspec.yamls, and
  /// the packages of `.dart_tool/package_config.json` is validated against
  /// pubspec.lock. We do this extra round of checking to accommodate for cases
  /// where version control or other processes mess up the timestamp order.
  ///
  /// If the resolution is still valid, the timestamps are updated and this
  /// returns the package configuration and the root dir. Otherwise this
  /// returns `null`.
  ///
  /// This check is on the fast-path of `dart run` and should do as little
  /// work as possible. Specifically we avoid parsing any yaml when the
  /// timestamps are in the right order.
  ///
  /// `.dart_tool/package_config.json` is read and parsed. In the case of `dart
  /// run` this is acceptable: we speculate that it brings it to the file
  /// system cache and the dart VM is going to read the file anyways.
  ///
  /// Note this procedure will give false positives if the timestamps are
  /// artificially brought in the "right" order. (eg. by manually running
  /// `touch pubspec.lock; touch .dart_tool/package_config.json`) - that is
  /// hard to avoid, but also unlikely to happen by accident because
  /// `.dart_tool/package_config.json` is not checked into version control.
  static (PackageConfig, String)? isResolutionUpToDate(
    String dir,
    SystemCache cache,
  ) {
    late final wasRelative = p.isRelative(dir);
    String relativeIfNeeded(String path) =>
        wasRelative ? p.relative(path) : path;

    /// Whether the lockfile is out of date with respect to the dependencies'
    /// pubspecs.
    ///
    /// If any mutable pubspec contains dependencies that are not in the
    /// lockfile or that don't match what's in there, this will return `false`.
    bool isLockFileUpToDate(
      LockFile lockFile,
      Package root, {
      required String lockFilePath,
    }) {
      /// Returns whether the locked version of [dep] matches the dependency.
      bool isDependencyUpToDate(PackageRange dep) {
        if (dep.name == root.name) return true;

        final locked = lockFile.packages[dep.name];
        return locked != null && dep.allows(locked);
      }

      for (final MapEntry(key: sdkName, value: constraint)
          in lockFile.sdkConstraints.entries) {
        final sdk = sdks[sdkName];
        if (sdk == null) {
          log.fine('Unknown sdk $sdkName in `$lockFilePath`');
          return false;
        }
        if (!sdk.isAvailable) {
          log.fine('sdk: ${sdk.name} not available');
          return false;
        }
        final sdkVersion = sdk.version;
        if (sdkVersion != null) {
          if (!constraint.effectiveConstraint.allows(sdkVersion)) {
            log.fine(
              '`$lockFilePath` requires $sdkName $constraint. '
              'Current version is $sdkVersion',
            );
            return false;
          }
        }
      }

      if (!root.immediateDependencies.values.every(isDependencyUpToDate)) {
        final pubspecPath = p.normalize(p.join(dir, 'pubspec.yaml'));

        log.fine(
          'The $pubspecPath file has changed since the $lockFilePath file '
          'was generated.',
        );
        return false;
      }

      // Check that uncached dependencies' pubspecs are also still satisfied,
      // since they're mutable and may have changed since the last get.
      for (var id in lockFile.packages.values) {
        final source = id.source;
        if (source is CachedSource) continue;

        try {
          if (cache
              .load(id)
              .dependencies
              .values
              .every(
                (dep) =>
                    root.allOverridesInWorkspace.containsKey(dep.name) ||
                    isDependencyUpToDate(dep),
              )) {
            continue;
          }
        } on FileException {
          // If we can't load the pubspec, the user needs to re-run "pub get".
        }

        final relativePubspecPath = p.join(
          cache.getDirectory(id, relativeFrom: '.'),
          'pubspec.yaml',
        );
        log.fine(
          '$relativePubspecPath has '
          'changed since the $lockFilePath file was generated.',
        );
        return false;
      }
      return true;
    }

    /// Whether or not the `.dart_tool/package_config.json` file is
    /// out of date with respect to the lockfile.
    bool isPackageConfigUpToDate(
      PackageConfig packageConfig,
      LockFile lockFile,
      Package root, {
      required String packageConfigPath,
      required String lockFilePath,
    }) {
      /// Determines if [lockFile] agrees with the given [packagePathsMapping].
      ///
      /// The [packagePathsMapping] is a mapping from package names to paths
      /// where the packages are located. (The library is located under `lib/`
      /// relative to the path given).
      bool isPackagePathsMappingUpToDateWithLockfile(
        Map<String, String> packagePathsMapping, {
        required String lockFilePath,
        required String packageConfigPath,
      }) {
        // Check that [packagePathsMapping] does not contain more packages than
        // what is required. This could lead to import statements working, when
        // they are not supposed to work.
        final hasExtraMappings =
            !packagePathsMapping.keys.every((packageName) {
              return packageName == root.name ||
                  lockFile.packages.containsKey(packageName);
            });
        if (hasExtraMappings) {
          return false;
        }

        // Check that all packages in the [lockFile] are reflected in the
        // [packagePathsMapping].
        return lockFile.packages.values.every((lockFileId) {
          // It's very unlikely that the lockfile is invalid here, but it's not
          // impossible—for example, the user may have a very old application
          // package with a checked-in lockfile that's newer than the pubspec,
          // but that contains SDK dependencies.
          if (lockFileId.source is UnknownSource) return false;

          final packagePath = packagePathsMapping[lockFileId.name];
          if (packagePath == null) {
            return false;
          }

          final source = lockFileId.source;
          final lockFilePackagePath = root.path(
            cache.getDirectory(lockFileId, relativeFrom: root.dir),
          );

          // Make sure that the packagePath agrees with the lock file about the
          // path to the package.
          if (p.normalize(packagePath) != p.normalize(lockFilePackagePath)) {
            return false;
          }

          // For cached sources, make sure the directory exists and looks like a
          // package. This is also done by [_arePackagesAvailable] but that may
          // not be run if the lockfile is newer than the pubspec.
          if (source is CachedSource && !dirExists(lockFilePackagePath) ||
              !fileExists(p.join(lockFilePackagePath, 'pubspec.yaml'))) {
            return false;
          }

          return true;
        });
      }

      final packagePathsMapping = <String, String>{};

      final packagesToCheck = packageConfig.packages;
      for (final pkg in packagesToCheck) {
        // Pub always makes a packageUri of lib/
        if (pkg.packageUri == null || pkg.packageUri.toString() != 'lib/') {
          log.fine(
            'The "$packageConfigPath" file '
            'is not recognized by this pub version.',
          );
          return false;
        }
        packagePathsMapping[pkg.name] = root.path(
          '.dart_tool',
          p.fromUri(pkg.rootUri),
        );
      }
      if (!isPackagePathsMappingUpToDateWithLockfile(
        packagePathsMapping,
        packageConfigPath: packageConfigPath,
        lockFilePath: lockFilePath,
      )) {
        log.fine(
          'The $lockFilePath file has changed since the '
          '$packageConfigPath file '
          'was generated, please run "$topLevelProgram pub get" again.',
        );
        return false;
      }

      // Check if language version specified in the `package_config.json` is
      // correct. This is important for path dependencies as these can mutate.
      for (final pkg in packageConfig.packages) {
        if (pkg.name == root.name) continue;
        final id = lockFile.packages[pkg.name];
        if (id == null) {
          assert(
            false,
            'unnecessary package_config.json entries should be forbidden by '
            '_isPackagePathsMappingUpToDateWithLockfile',
          );
          continue;
        }

        // If a package is cached, then it's universally immutable and we need
        // not check if the language version is correct.
        final source = id.source;
        if (source is CachedSource) {
          continue;
        }

        try {
          // Load `pubspec.yaml` and extract language version to compare with
          // the language version from `package_config.json`.
          final languageVersion = cache.load(id).pubspec.languageVersion;
          if (pkg.languageVersion != languageVersion) {
            final relativePubspecPath = p.join(
              cache.getDirectory(id, relativeFrom: '.'),
              'pubspec.yaml',
            );
            log.fine(
              '$relativePubspecPath has '
              'changed since the $lockFilePath file was generated.',
            );
            return false;
          }
        } on FileException {
          log.fine(
            'Failed to read pubspec.yaml for "${pkg.name}", perhaps the '
            'entry is missing.',
          );
          return false;
        }
      }
      return true;
    }

    FileStat? packageConfigStat;
    late final String packageConfigPath;
    late final String rootDir;
    for (final parent in parentDirs(dir)) {
      final potentialPackageConfigPath = p.normalize(
        p.join(parent, '.dart_tool', 'package_config.json'),
      );
      packageConfigStat = tryStatFile(potentialPackageConfigPath);

      if (packageConfigStat != null) {
        packageConfigPath = potentialPackageConfigPath;
        rootDir = parent;
        break;
      }
      final potentialPubspecPath = p.join(parent, 'pubspec.yaml');
      if (tryStatFile(potentialPubspecPath) == null) {
        // No package at [parent] continue to next dir.
        continue;
      }

      final potentialWorkspaceRefPath = p.normalize(
        p.join(parent, '.dart_tool', 'pub', 'workspace_ref.json'),
      );

      final workspaceRefText = tryReadTextFile(potentialWorkspaceRefPath);
      if (workspaceRefText == null) {
        log.fine(
          '`$potentialPubspecPath` exists without corresponding '
          '`$potentialPubspecPath` or `$potentialWorkspaceRefPath`.',
        );
        return null;
      } else {
        try {
          if (jsonDecode(workspaceRefText) case {
            'workspaceRoot': final String path,
          }) {
            final potentialPackageConfigPath2 = relativeIfNeeded(
              p.normalize(
                p.absolute(
                  p.join(
                    p.dirname(potentialWorkspaceRefPath),
                    path,
                    '.dart_tool',
                    'package_config.json',
                  ),
                ),
              ),
            );
            packageConfigStat = tryStatFile(potentialPackageConfigPath2);
            if (packageConfigStat == null) {
              log.fine(
                '`$potentialWorkspaceRefPath` points to non-existing '
                '`$potentialPackageConfigPath2`',
              );
              return null;
            } else {
              packageConfigPath = potentialPackageConfigPath2;
              rootDir = relativeIfNeeded(
                p.normalize(
                  p.absolute(
                    p.join(p.dirname(potentialWorkspaceRefPath), path),
                  ),
                ),
              );

              break;
            }
          } else {
            log.fine(
              '`$potentialWorkspaceRefPath` '
              'is missing "workspaceRoot" property',
            );
            return null;
          }
        } on FormatException catch (e) {
          log.fine('`$potentialWorkspaceRefPath` not valid json: $e.');
          return null;
        }
      }
    }
    if (packageConfigStat == null) {
      log.fine(
        'Found no .dart_tool/package_config.json - no existing resolution.',
      );
      return null;
    }
    final lockFilePath = p.normalize(p.join(rootDir, 'pubspec.lock'));
    final packageConfig = _loadPackageConfig(packageConfigPath);
    if (p.isWithin(cache.rootDir, packageConfigPath)) {
      // We always consider a global package (inside the cache) up-to-date.
      return (packageConfig, rootDir);
    }

    /// Whether or not the `.dart_tool/package_config.json` file was
    /// generated by a different sdk down to changes in minor versions.
    bool isPackageConfigGeneratedBySameDartSdk() {
      final generatorVersion = packageConfig.generatorVersion;
      if (generatorVersion == null ||
          generatorVersion.major != sdk.version.major ||
          generatorVersion.minor != sdk.version.minor) {
        log.fine('The Dart SDK was updated since last package resolution.');
        return false;
      }
      return true;
    }

    final flutter = FlutterSdk();
    // If Flutter has moved since last invocation, we want to have new
    // sdk-packages, and therefore do a new resolution.
    //
    // This also counts if Flutter was introduced or removed.
    final flutterRoot =
        flutter.rootDirectory == null
            ? null
            : p.toUri(p.absolute(flutter.rootDirectory!)).toString();
    if (packageConfig.additionalProperties['flutterRoot'] != flutterRoot) {
      log.fine('Flutter has moved since last invocation.');
      return null;
    }
    if (packageConfig.additionalProperties['flutterVersion'] !=
        (flutter.isAvailable ? flutter.version.toString() : null)) {
      log.fine('Flutter has updated since last invocation.');
      return null;
    }
    // If the pub cache was moved we should have a new resolution.
    final rootCacheUrl = p.toUri(p.absolute(cache.rootDir)).toString();
    if (packageConfig.additionalProperties['pubCache'] != rootCacheUrl) {
      final previousPubCachePath =
          packageConfig.additionalProperties['pubCache'];
      log.fine(
        'The pub cache has moved from $previousPubCachePath to $rootCacheUrl '
        'since last invocation.',
      );
      return null;
    }
    // If the Dart sdk was updated we want a new resolution.
    if (!isPackageConfigGeneratedBySameDartSdk()) {
      return null;
    }
    final lockFileStat = tryStatFile(lockFilePath);
    if (lockFileStat == null) {
      log.fine('No $lockFilePath file found.');
      return null;
    }

    final lockFileModified = lockFileStat.modified;
    var lockfileNewerThanPubspecs = true;

    // Check that all packages in packageConfig exist and their pubspecs have
    // not been updated since the lockfile was written.
    for (var package in packageConfig.packages) {
      final pubspecPath = p.normalize(
        p.join(
          rootDir,
          '.dart_tool',
          package.rootUri
              // Important to use `toFilePath()` here rather than `path`, as
              // it handles Url-decoding.
              .toFilePath(),
          'pubspec.yaml',
        ),
      );
      if (p.isWithin(cache.rootDir, pubspecPath)) {
        continue;
      }
      final pubspecStat = tryStatFile(pubspecPath);
      if (pubspecStat == null) {
        log.fine('Could not find `$pubspecPath`');
        // A dependency is missing - do a full new resolution.
        return null;
      }

      if (pubspecStat.modified.isAfter(lockFileModified)) {
        log.fine('`$pubspecPath` is newer than `$lockFilePath`');
        lockfileNewerThanPubspecs = false;
        break;
      }
      final pubspecOverridesPath = p.join(
        package.rootUri.path,
        'pubspec_overrides.yaml',
      );
      final pubspecOverridesStat = tryStatFile(pubspecOverridesPath);
      if (pubspecOverridesStat != null) {
        // This will wrongly require you to reresolve if a
        // `pubspec_overrides.yaml` in a path-dependency is updated. That
        // seems acceptable.
        if (pubspecOverridesStat.modified.isAfter(lockFileModified)) {
          log.fine('`$pubspecOverridesPath` is newer than `$lockFilePath`');
          lockfileNewerThanPubspecs = false;
        }
      }
    }
    var touchedLockFile = false;
    late final lockFile = _loadLockFile(lockFilePath, cache);
    late final root = Package.load(
      dir,
      loadPubspec: Pubspec.loadRootWithSources(cache.sources),
    );

    if (!lockfileNewerThanPubspecs) {
      if (isLockFileUpToDate(lockFile, root, lockFilePath: lockFilePath)) {
        touch(lockFilePath);
        touchedLockFile = true;
      } else {
        return null;
      }
    }

    if (touchedLockFile ||
        lockFileModified.isAfter(packageConfigStat.modified)) {
      log.fine('`$lockFilePath` is newer than `$packageConfigPath`');
      if (isPackageConfigUpToDate(
        packageConfig,
        lockFile,
        root,
        packageConfigPath: packageConfigPath,
        lockFilePath: lockFilePath,
      )) {
        touch(packageConfigPath);
      } else {
        return null;
      }
    }
    return (packageConfig, rootDir);
  }

  /// Does a fast-pass check to see if the resolution is up-to-date. If not, run
  /// a resolution with `pub get` semantics.
  ///
  /// If [summaryOnly] is `true` (the default) only a short summary is shown of
  /// the solve.
  ///
  /// If [onlyOutputWhenTerminal] is `true` (the default) there will be no
  /// output if no terminal is attached.
  ///
  /// When succesfull returns the found/created `PackageConfig` and the
  /// directory containing it.
  static Future<({PackageConfig packageConfig, String rootDir})> ensureUpToDate(
    String dir, {
    required SystemCache cache,
    bool summaryOnly = true,
    bool onlyOutputWhenTerminal = true,
  }) async {
    late final wasRelative = p.isRelative(dir);
    String relativeIfNeeded(String path) =>
        wasRelative ? p.relative(path) : path;

    if (isResolutionUpToDate(dir, cache) case (
      final PackageConfig packageConfig,
      final String rootDir,
    )) {
      log.fine('Package Config up to date.');
      return (packageConfig: packageConfig, rootDir: rootDir);
    }
    final entrypoint = Entrypoint(
      dir,
      cache,
      // [ensureUpToDate] is also used for entries in 'global_packages/'
      checkInCache: false,
    );
    if (onlyOutputWhenTerminal) {
      await log.errorsOnlyUnlessTerminal(() async {
        await entrypoint.acquireDependencies(
          SolveType.get,
          summaryOnly: summaryOnly,
        );
      });
    } else {
      await entrypoint.acquireDependencies(
        SolveType.get,
        summaryOnly: summaryOnly,
      );
    }
    return (
      packageConfig: entrypoint.packageConfig,
      rootDir: relativeIfNeeded(
        p.normalize(p.absolute(entrypoint.workspaceRoot.dir)),
      ),
    );
  }

  /// We require an SDK constraint lower-bound as of Dart 2.12.0
  ///
  /// We don't allow unknown sdks.
  void _checkSdkConstraint(String pubspecPath, Pubspec pubspec) {
    final dartSdkConstraint = pubspec.dartSdkConstraint.effectiveConstraint;
    // Suggest an sdk constraint giving the same language version as the
    // current sdk.
    var suggestedConstraint = VersionConstraint.compatibleWith(
      Version(sdk.version.major, sdk.version.minor, 0),
    );
    // But if somehow that doesn't work, we fallback to safe sanity, mostly
    // important for tests, or if we jump to 3.x without patching this code.
    if (!suggestedConstraint.allows(sdk.version)) {
      suggestedConstraint = VersionRange(
        min: sdk.version,
        max: sdk.version.nextBreaking,
        includeMin: true,
      );
    }
    if (dartSdkConstraint is! VersionRange || dartSdkConstraint.min == null) {
      throw DataException('''
$pubspecPath has no lower-bound SDK constraint.
You should edit $pubspecPath to contain an SDK constraint:

environment:
  sdk: '${suggestedConstraint.asCompatibleWithIfPossible()}'

See https://dart.dev/go/sdk-constraint
''');
    }
    if (!LanguageVersion.fromSdkConstraint(
      dartSdkConstraint,
    ).supportsNullSafety) {
      throw DataException('''
The lower bound of "sdk: '$dartSdkConstraint'" must be 2.12.0'
or higher to enable null safety.

The current Dart SDK (${sdk.version}) only supports null safety.

For details, see https://dart.dev/null-safety
''');
    }
    for (final sdk in pubspec.sdkConstraints.keys) {
      if (!sdks.containsKey(sdk)) {
        final environment = pubspec.fields.nodes['environment'] as YamlMap;
        final keyNode =
            environment.nodes.entries
                    .firstWhere((e) => (e.key as YamlNode).value == sdk)
                    .key
                as YamlNode;
        throw SourceSpanApplicationException('''
$pubspecPath refers to an unknown sdk '$sdk'.

Did you mean to add it as a dependency?

Either remove the constraint, or upgrade to a version of pub that supports the
given sdk.

See https://dart.dev/go/sdk-constraint
''', keyNode.span);
      }
    }
  }

  /// Setting the `PUB_SUMMARY_ONLY` environment variable to anything but '0'
  /// will result in [acquireDependencies] to only print a summary of the
  /// results.
  bool get _summaryOnlyEnvironment =>
      (Platform.environment['PUB_SUMMARY_ONLY'] ?? '0') != '0';

  /// Remove any `pubspec.lock` or `.dart_tool/package_config.json` files in
  /// workspace packages that are not the root package.
  ///
  /// Also remove from directories between the workspace package and the
  /// workspace root, to prevent stray package configs from shadowing the shared
  /// workspace package config.
  ///
  /// This is to avoid surprises if a package is turned into a workspace member
  /// but still has an old package config or lockfile.
  void _removeStrayLockAndConfigFiles() {
    final visited = <String>{
      // By adding this to visited we will never go above the workspaceRoot.dir.
      p.canonicalize(workspaceRoot.dir),
    };
    var deletedAny = false;
    for (final package in workspaceRoot.transitiveWorkspace) {
      if (package.pubspec.resolution == Resolution.workspace) {
        for (final dir in parentDirs(package.dir)) {
          if (!visited.add(p.canonicalize(dir))) {
            // No reason to delete from the same directory twice.
            break;
          }
          void deleteIfPresent(String path, String type) {
            if (fileExists(path)) {
              log.warning('Deleting old $type: `$path`.');
              deleteEntry(path);
              deletedAny = true;
            }
          }

          deleteIfPresent(p.join(dir, 'pubspec.lock'), 'lock-file');
          deleteIfPresent(
            p.join(dir, '.dart_tool', 'package_config.json'),
            'package config',
          );
        }
      }
    }
    if (deletedAny) {
      log.warning(
        'See https://dart.dev/go/workspaces-stray-files for details.',
      );
    }
  }

  /// Returns a list of changes to constraints of workspace pubspecs updated to
  /// have their lower bound match the version in [packageVersions] (or
  /// `this.lockFile`).
  ///
  /// The return value for each workspace package is a mapping from the original
  /// package range to the updated.
  ///
  /// If packages to update where given in [packagesToUpgrade], only those are
  /// tightened. Otherwise all packages are tightened.
  ///
  /// If a dependency has already been updated in [existingChanges], the update
  /// will apply on top of that change (eg. preserving the new upper bound).
  Map<Package, Map<PackageRange, PackageRange>> tighten({
    List<String> packagesToUpgrade = const [],
    Map<Package, Map<PackageRange, PackageRange>> existingChanges = const {},
    List<PackageId>? packageVersions,
  }) {
    final result = {...existingChanges};

    final toTighten = <(Package, PackageRange)>[];

    // Keep track of the versions of workspace packages - these are not included
    // in the lockfile.
    final workspaceVersions = <String, Version>{};

    for (final package in workspaceRoot.transitiveWorkspace) {
      workspaceVersions[package.name] = package.version;
      if (packagesToUpgrade.isEmpty) {
        for (final range in [
          ...package.dependencies.values,
          ...package.devDependencies.values,
        ]) {
          toTighten.add((package, range));
        }
      } else {
        for (final packageToUpgrade in packagesToUpgrade) {
          final range =
              package.dependencies[packageToUpgrade] ??
              package.devDependencies[packageToUpgrade];
          if (range != null) {
            toTighten.add((package, range));
          }
        }
      }
    }

    for (final (package, range) in toTighten) {
      final changesForPackage = result[package] ??= {};
      final constraint = (changesForPackage[range] ?? range).constraint;

      final resolvedVersion =
          (packageVersions?.firstWhere((p) => p.name == range.name) ??
                  lockFile.packages[range.name])
              ?.version ??
          workspaceVersions[range.name]!;
      if (range.source is HostedSource && constraint.isAny) {
        changesForPackage[range] = range.toRef().withConstraint(
          VersionConstraint.compatibleWith(resolvedVersion),
        );
      } else if (constraint is VersionRange) {
        final min = constraint.min;
        if (min != null && min < resolvedVersion) {
          changesForPackage[range] = range.toRef().withConstraint(
            VersionRange(
              min: resolvedVersion,
              max: constraint.max,
              includeMin: true,
              includeMax: constraint.includeMax,
            ).asCompatibleWithIfPossible(),
          );
        }
      }
    }
    return result;
  }

  /// Unless [dryRun], loads `pubspec.yaml` of each [Package] in [changeSet] and
  /// applies the changes to its (dev)-dependencies using yaml_edit to preserve
  /// textual structure.
  ///
  /// Outputs a summary of changes done or would have been done if not [dryRun].
  void applyChanges(ChangeSet changeSet, bool dryRun) {
    if (!dryRun) {
      for (final package in workspaceRoot.transitiveWorkspace) {
        final changesForPackage = changeSet[package];
        if (changesForPackage == null || changesForPackage.isEmpty) {
          continue;
        }
        final yamlEditor = YamlEditor(readTextFile(package.pubspecPath));
        final deps = package.dependencies.keys;

        for (final change in changesForPackage.values) {
          final section =
              deps.contains(change.name) ? 'dependencies' : 'dev_dependencies';
          yamlEditor.update([
            section,
            change.name,
          ], pubspecDescription(change, cache, package));
        }
        writeTextFile(package.pubspecPath, yamlEditor.toString());
      }
    }
    _outputChangeSummary(changeSet, dryRun: dryRun);
  }

  /// Outputs a summary of [changeSet].
  void _outputChangeSummary(ChangeSet changeSet, {required bool dryRun}) {
    if (workspaceRoot.workspaceChildren.isEmpty) {
      final changesToWorkspaceRoot = changeSet[workspaceRoot] ?? {};
      if (changesToWorkspaceRoot.isEmpty) {
        final wouldBe = dryRun ? 'would be made to' : 'to';
        log.message('\nNo changes $wouldBe pubspec.yaml!');
      } else {
        final changed = dryRun ? 'Would change' : 'Changed';
        final constraints = pluralize(
          'constraint',
          changesToWorkspaceRoot.length,
        );
        log.message(
          '\n$changed ${changesToWorkspaceRoot.length} '
          '$constraints in pubspec.yaml:',
        );
        changesToWorkspaceRoot.forEach((from, to) {
          log.message('  ${from.name}: ${from.constraint} -> ${to.constraint}');
        });
      }
    } else {
      if (changeSet.isEmpty) {
        final wouldBe = dryRun ? 'would be made to' : 'to';
        log.message('\nNo changes $wouldBe any pubspec.yaml!');
      }
      for (final package in workspaceRoot.transitiveWorkspace) {
        final changesToPackage = changeSet[package] ?? {};
        if (changesToPackage.isEmpty) continue;
        final changed = dryRun ? 'Would change' : 'Changed';
        final constraints = pluralize('constraint', changesToPackage.length);
        log.message(
          '\n$changed ${changesToPackage.length} '
          '$constraints in ${package.pubspecPath}:',
        );
        changesToPackage.forEach((from, to) {
          log.message('  ${from.name}: ${from.constraint} -> ${to.constraint}');
        });
      }
    }
  }
}

/// For each package in a workspace, a set of changes to dependencies.
typedef ChangeSet = Map<Package, Map<PackageRange, PackageRange>>;
