// 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: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 'path.dart';
import 'platform_info.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>>;
