// Copyright 2014 The Flutter Authors. 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:collection';

import 'package:meta/meta.dart';

import '../base/common.dart';
import '../base/context.dart';
import '../base/file_system.dart';
import '../base/logger.dart';
import '../base/net.dart';
import '../base/task_queue.dart';
import '../cache.dart';
import '../dart/pub.dart';
import '../globals.dart' as globals;
import '../runner/flutter_command.dart';

/// Map from package name to package version, used to artificially pin a pub
/// package version in cases when upgrading to the latest breaks Flutter.
///
/// These version pins must be pins, not ranges! Allowing these to be ranges
/// defeats the whole purpose of pinning all our dependencies, which is to
/// prevent upstream changes from causing our CI to fail randomly in ways
/// unrelated to the commits. It also, more importantly, risks breaking users
/// in ways that prevent them from every upgrading Flutter again!
const Map<String, String> kManuallyPinnedDependencies = <String, String>{
  // Add pinned packages here. Please leave a comment explaining why.
  'flutter_gallery_assets': '1.0.2', // Tests depend on the exact version.
  'flutter_template_images': '4.1.0', // Must always exactly match flutter_tools template.
  'video_player': '2.2.11',
  // Could potentially break color scheme tests on upgrade,
  // so pin and manually update as needed.
  'material_color_utilities': '0.1.5',
  'test_api': '0.4.9',
};

class UpdatePackagesCommand extends FlutterCommand {
  UpdatePackagesCommand() {
    argParser
      ..addFlag(
        'force-upgrade',
        help: 'Attempt to update all the dependencies to their latest versions.\n'
              'This will actually modify the pubspec.yaml files in your checkout.',
        negatable: false,
      )
      ..addFlag(
        'paths',
        help: 'Finds paths in the dependency chain leading from package specified '
              'in "--from" to package specified in "--to".',
        negatable: false,
      )
      ..addOption(
        'from',
        help: 'Used with "--dependency-path". Specifies the package to begin '
              'searching dependency path from.',
      )
      ..addOption(
        'to',
        help: 'Used with "--dependency-path". Specifies the package that the '
              'sought-after dependency path leads to.',
      )
      ..addFlag(
        'transitive-closure',
        help: 'Prints the dependency graph that is the transitive closure of '
              'packages the Flutter SDK depends on.',
        negatable: false,
      )
      ..addFlag(
        'consumer-only',
        help: 'Only prints the dependency graph that is the transitive closure '
              'that a consumer of the Flutter SDK will observe (when combined '
              'with transitive-closure).',
        negatable: false,
      )
      ..addFlag(
        'verify-only',
        help: 'Verifies the package checksum without changing or updating deps.',
        negatable: false,
      )
      ..addFlag(
        'offline',
        help: 'Use cached packages instead of accessing the network.',
        negatable: false,
      )
      ..addFlag(
        'crash',
        help: 'For Flutter CLI testing only, forces this command to throw an unhandled exception.',
        negatable: false,
      )
      ..addOption(
        'jobs',
        abbr: 'j',
        help: 'Causes the "pub get" runs to happen concurrently on this many '
              'CPUs. Defaults to the number of CPUs that this machine has.',
      );
  }

  @override
  final String name = 'update-packages';

  @override
  final String description = 'Update the packages inside the Flutter repo.';

  @override
  final List<String> aliases = <String>['upgrade-packages'];

  @override
  final bool hidden = true;


  // Lazy-initialize the net utilities with values from the context.
  late final Net _net = Net(
    httpClientFactory: context.get<HttpClientFactory>(),
    logger: globals.logger,
    platform: globals.platform,
  );

  Future<void> _downloadCoverageData() async {
    final String urlBase = globals.platform.environment['FLUTTER_STORAGE_BASE_URL'] ?? 'https://storage.googleapis.com';
    final Uri coverageUri = Uri.parse('$urlBase/flutter_infra_release/flutter/coverage/lcov.info');
    final List<int>? data = await _net.fetchUrl(
      coverageUri,
      maxAttempts: 3,
    );
    if (data == null) {
      throwToolExit('Failed to fetch coverage data from $coverageUri');
    }
    final String coverageDir = globals.fs.path.join(
      Cache.flutterRoot!,
      'packages/flutter/coverage',
    );
    globals.fs.file(globals.fs.path.join(coverageDir, 'lcov.base.info'))
      ..createSync(recursive: true)
      ..writeAsBytesSync(data, flush: true);
    globals.fs.file(globals.fs.path.join(coverageDir, 'lcov.info'))
      ..createSync(recursive: true)
      ..writeAsBytesSync(data, flush: true);
  }

  @override
  Future<FlutterCommandResult> runCommand() async {
    final List<Directory> packages = runner!.getRepoPackages();

    final bool forceUpgrade = boolArgDeprecated('force-upgrade');
    final bool isPrintPaths = boolArgDeprecated('paths');
    final bool isPrintTransitiveClosure = boolArgDeprecated('transitive-closure');
    final bool isVerifyOnly = boolArgDeprecated('verify-only');
    final bool isConsumerOnly = boolArgDeprecated('consumer-only');
    final bool offline = boolArgDeprecated('offline');
    final bool doUpgrade = forceUpgrade || isPrintPaths || isPrintTransitiveClosure;

    if (boolArgDeprecated('crash')) {
      throw StateError('test crash please ignore.');
    }

    if (forceUpgrade && offline) {
      throwToolExit(
          '--force-upgrade cannot be used with the --offline flag'
      );
    }

    // "consumer" packages are those that constitute our public API (e.g. flutter, flutter_test, flutter_driver, flutter_localizations, integration_test).
    if (isConsumerOnly) {
      if (!isPrintTransitiveClosure) {
        throwToolExit(
          '--consumer-only can only be used with the --transitive-closure flag'
        );
      }
      // Only retain flutter, flutter_test, flutter_driver, and flutter_localizations.
      const List<String> consumerPackages = <String>['flutter', 'flutter_test', 'flutter_driver', 'flutter_localizations', 'integration_test'];
      // ensure we only get flutter/packages
      packages.retainWhere((Directory directory) {
        return consumerPackages.any((String package) {
          return directory.path.endsWith('packages${globals.fs.path.separator}$package');
        });
      });
    }

    if (isVerifyOnly) {
      _verifyPubspecs(packages);
      return FlutterCommandResult.success();
    }

    if (doUpgrade) {
      // This feature attempts to collect all the packages used across all the
      // pubspec.yamls in the repo (including via transitive dependencies), and
      // find the latest version of each that can be used while keeping each
      // such package fixed at a single version across all the pubspec.yamls.
      globals.printStatus('Upgrading packages...');
    }

    // First, collect the dependencies:
    final List<PubspecYaml> pubspecs = <PubspecYaml>[];
    final Map<String, PubspecDependency> explicitDependencies = <String, PubspecDependency>{};
    final Map<String, PubspecDependency> allDependencies = <String, PubspecDependency>{};
    final Set<String> specialDependencies = <String>{};
    _collectDependencies(
      packages: packages,
      pubspecs: pubspecs,
      explicitDependencies: explicitDependencies,
      allDependencies: allDependencies,
      specialDependencies: specialDependencies,
      doUpgrade: doUpgrade,
    );

    // Now that we have all the dependencies we care about, we are going to
    // create a fake package and then run either "pub upgrade", if requested,
    // followed by "pub get" on it. If upgrading, the pub tool will attempt to
    // bring these dependencies up to the most recent possible versions while
    // honoring all their constraints. If not upgrading the pub tool will only
    // attempt to download any necessary package versions to the pub cache to
    // warm the cache.
    final PubDependencyTree tree = PubDependencyTree(); // object to collect results
    final Directory tempDir = globals.fs.systemTempDirectory.createTempSync('flutter_update_packages.');
    await _generateFakePackage(
      tempDir: tempDir,
      dependencies: doUpgrade ? explicitDependencies.values : allDependencies.values,
      pubspecs: pubspecs,
      tree: tree,
      doUpgrade: doUpgrade,
    );

    if (doUpgrade) {
      final bool done = _upgradePubspecs(
        tree: tree,
        pubspecs: pubspecs,
        explicitDependencies: explicitDependencies,
        specialDependencies: specialDependencies,
      );

      if (done) {
        // Complete early if we were just printing data.
        return FlutterCommandResult.success();
      }
    }

    await _runPubGetOnPackages(packages);

    return FlutterCommandResult.success();
  }

  void _verifyPubspecs(List<Directory> packages) {
    bool needsUpdate = false;
    globals.printStatus('Verifying pubspecs...');
    for (final Directory directory in packages) {
      final PubspecYaml pubspec = PubspecYaml(directory);
      globals.printTrace('Reading pubspec.yaml from ${directory.path}');
      if (pubspec.checksum.value == null) {
        // If the checksum is invalid or missing, we can just ask them run to run
        // upgrade again to compute it.
        globals.printWarning(
            'Warning: pubspec in ${directory.path} has out of date dependencies. '
            'Please run "flutter update-packages --force-upgrade" to update them correctly.'
        );
        needsUpdate = true;
      }
      // all dependencies in the pubspec sorted lexically.
      final Map<String, String> checksumDependencies = <String, String>{};
      for (final PubspecLine data in pubspec.inputData) {
        if (data is PubspecDependency && data.kind == DependencyKind.normal) {
          checksumDependencies[data.name] = data.version;
        }
      }
      final String checksum = _computeChecksum(checksumDependencies.keys, (String name) => checksumDependencies[name]!);
      if (checksum != pubspec.checksum.value) {
        // If the checksum doesn't match, they may have added or removed some dependencies.
        // we need to run update-packages to recapture the transitive deps.
        globals.printWarning(
            'Warning: pubspec in ${directory.path} has updated or new dependencies. '
            'Please run "flutter update-packages --force-upgrade" to update them correctly '
            '(checksum ${pubspec.checksum.value} != $checksum).'
        );
        needsUpdate = true;
      } else {
        // everything is correct in the pubspec.
        globals.printTrace('pubspec in ${directory.path} is up to date!');
      }
    }
    if (needsUpdate) {
      throwToolExit(
        'Warning: one or more pubspecs have invalid dependencies. '
        'Please run "flutter update-packages --force-upgrade" to update them correctly.',
        exitCode: 1,
      );
    }
    globals.printStatus('All pubspecs were up to date.');
  }

  void _collectDependencies({
    required List<Directory> packages,
    required List<PubspecYaml> pubspecs,
    required Set<String> specialDependencies,
    required Map<String, PubspecDependency> explicitDependencies,
    required Map<String, PubspecDependency> allDependencies,
    required bool doUpgrade,
  }) {
    // Visit all the directories with pubspec.yamls we care about.
    for (final Directory directory in packages) {
      if (doUpgrade) {
        globals.printTrace('Reading pubspec.yaml from: ${directory.path}');
      }
      final PubspecYaml pubspec = PubspecYaml(directory); // this parses the pubspec.yaml
      pubspecs.add(pubspec); // remember it for later
      for (final PubspecDependency dependency in pubspec.allDependencies) {
        if (allDependencies.containsKey(dependency.name)) {
          // If we've seen the dependency before, make sure that we are
          // importing it the same way. There's several ways to import a
          // dependency. Hosted (from pub via version number), by path (e.g.
          // pointing at the version of a package we get from the Dart SDK
          // that we download with Flutter), by SDK (e.g. the "flutter"
          // package is explicitly from "sdk: flutter").
          //
          // This makes sure that we don't import a package in two different
          // ways, e.g. by saying "sdk: flutter" in one pubspec.yaml and
          // saying "path: ../../..." in another.
          final PubspecDependency previous = allDependencies[dependency.name]!;
          if (dependency.kind != previous.kind || dependency._lockTarget != previous._lockTarget) {
            throwToolExit(
                'Inconsistent requirements around ${dependency.name}; '
                    'saw ${dependency.kind} (${dependency._lockTarget}) in "${dependency.sourcePath}" '
                    'and ${previous.kind} (${previous._lockTarget}) in "${previous.sourcePath}".'
            );
          }
          if (dependency.version != previous.version) {
            globals.printError(
                'Requiring multiple versions: multiple versions required by ${dependency.name}; '
                    'saw ${dependency.version} in "${dependency.sourcePath}" '
                    'and ${previous.version} in "${previous.sourcePath}".'
            );
          }
        }
        allDependencies[dependency.name] = dependency;
      }
      for (final PubspecDependency dependency in pubspec.allExplicitDependencies) {
        if (explicitDependencies.containsKey(dependency.name)) {
          // If we've seen the dependency before, make sure that we are
          // importing it the same way. There's several ways to import a
          // dependency. Hosted (from pub via version number), by path (e.g.
          // pointing at the version of a package we get from the Dart SDK
          // that we download with Flutter), by SDK (e.g. the "flutter"
          // package is explicitly from "sdk: flutter").
          //
          // This makes sure that we don't import a package in two different
          // ways, e.g. by saying "sdk: flutter" in one pubspec.yaml and
          // saying "path: ../../..." in another.
          final PubspecDependency previous = explicitDependencies[dependency.name]!;
          if (dependency.kind != previous.kind || dependency._lockTarget != previous._lockTarget) {
            throwToolExit(
                'Inconsistent requirements around ${dependency.name}; '
                'saw ${dependency.kind} (${dependency._lockTarget}) in "${dependency.sourcePath}" '
                'and ${previous.kind} (${previous._lockTarget}) in "${previous.sourcePath}".'
            );
          }
        }
        // Remember this dependency by name so we can look it up again.
        explicitDependencies[dependency.name] = dependency;
        // Normal dependencies are those we get from pub. The others we
        // already implicitly pin since we pull down one version of the
        // Flutter and Dart SDKs, so we track which those are here so that we
        // can omit them from our list of pinned dependencies later.
        if (dependency.kind != DependencyKind.normal) {
          specialDependencies.add(dependency.name);
        }
      }
    }
  }

  Future<void> _generateFakePackage({
    required Directory tempDir,
    required Iterable<PubspecDependency> dependencies,
    required List<PubspecYaml> pubspecs,
    required PubDependencyTree tree,
    required bool doUpgrade,
  }) async {
    try {
      final File fakePackage = _pubspecFor(tempDir);
      fakePackage.createSync();
      fakePackage.writeAsStringSync(
        generateFakePubspec(
          dependencies,
          doUpgrade: doUpgrade,
        ),
      );
      // Create a synthetic flutter SDK so that transitive flutter SDK
      // constraints are not affected by this upgrade.
      Directory? temporaryFlutterSdk;
      if (doUpgrade) {
        temporaryFlutterSdk = createTemporaryFlutterSdk(
          globals.logger,
          globals.fs,
          globals.fs.directory(Cache.flutterRoot),
          pubspecs,
        );
      }

      // Next we run "pub get" on it in order to force the download of any
      // needed packages to the pub cache, upgrading if requested.
      await pub.get(
        context: PubContext.updatePackages,
        directory: tempDir.path,
        upgrade: doUpgrade,
        offline: boolArgDeprecated('offline'),
        flutterRootOverride: temporaryFlutterSdk?.path,
      );
      // Cleanup the temporary SDK
      try {
        temporaryFlutterSdk?.deleteSync(recursive: true);
      } on FileSystemException {
        // Failed to delete temporary SDK.
      }

      if (doUpgrade) {
        // If upgrading, we run "pub deps --style=compact" on the result. We
        // pipe all the output to tree.fill(), which parses it so that it can
        // create a graph of all the dependencies so that we can figure out the
        // transitive dependencies later. It also remembers which version was
        // selected for each package.
        await pub.batch(
          <String>['deps', '--style=compact'],
          context: PubContext.updatePackages,
          directory: tempDir.path,
          filter: tree.fill,
          retry: false, // errors here are usually fatal since we're not hitting the network
        );
      }
    } finally {
      tempDir.deleteSync(recursive: true);
    }
  }

  bool _upgradePubspecs({
    required PubDependencyTree tree,
    required List<PubspecYaml> pubspecs,
    required Set<String> specialDependencies,
    required Map<String, PubspecDependency> explicitDependencies,
  }) {
    // The transitive dependency tree for the fake package does not contain
    // dependencies between Flutter SDK packages and pub packages. We add them
    // here.
    for (final PubspecYaml pubspec in pubspecs) {
      final String package = pubspec.name;
      specialDependencies.add(package);
      tree._versions[package] = pubspec.version;
      assert(!tree._dependencyTree.containsKey(package));
      tree._dependencyTree[package] = <String>{};
      for (final PubspecDependency dependency in pubspec.dependencies) {
        if (dependency.kind == DependencyKind.normal) {
          tree._dependencyTree[package]!.add(dependency.name);
        }
      }
    }

    if (boolArgDeprecated('transitive-closure')) {
      tree._dependencyTree.forEach((String from, Set<String> to) {
        globals.printStatus('$from -> $to');
      });
      return true;
    }

    if (boolArgDeprecated('paths')) {
      showDependencyPaths(from: stringArgDeprecated('from')!, to: stringArgDeprecated('to')!, tree: tree);
      return true;
    }

    // Now that we have collected all the data, we can apply our dependency
    // versions to each pubspec.yaml that we collected. This mutates the
    // pubspec.yaml files.
    //
    // The specialDependencies argument is the set of package names to not pin
    // to specific versions because they are explicitly pinned by their
    // constraints. Here we list the names we earlier established we didn't
    // need to pin because they come from the Dart or Flutter SDKs.
    for (final PubspecYaml pubspec in pubspecs) {
      pubspec.apply(tree, specialDependencies);
    }
    return false;
  }

  Future<void> _runPubGetOnPackages(List<Directory> packages) async {
    final Stopwatch timer = Stopwatch()..start();
    int count = 0;

    // Now we run pub get on each of the affected packages to update their
    // pubspec.lock files with the right transitive dependencies.
    //
    // This can be expensive, so we run them in parallel. If we hadn't already
    // warmed the cache above, running them in parallel could be dangerous due
    // to contention when unpacking downloaded dependencies, but since we have
    // downloaded all that we need, it is safe to run them in parallel.
    final Status status = globals.logger.startProgress(
      'Running "flutter pub get" in affected packages...',
    );
    try {
      // int.tryParse will not accept null, but will convert empty string to null
      final int? maxJobs = int.tryParse(stringArgDeprecated('jobs') ?? '');
      final TaskQueue<void> queue = TaskQueue<void>(maxJobs: maxJobs);
      for (final Directory dir in packages) {
        unawaited(queue.add(() async {
          final Stopwatch stopwatch = Stopwatch();
          stopwatch.start();
          await pub.get(
            context: PubContext.updatePackages,
            directory: dir.path,
            // All dependencies should already have been downloaded by the fake
            // package, so the concurrent checks can all happen offline.
            offline: true,
            printProgress: false,
          );
          stopwatch.stop();
          final double seconds = stopwatch.elapsedMilliseconds / 1000.0;
          final String relativeDir = globals.fs.path.relative(dir.path, from: Cache.flutterRoot);
          globals.printStatus('Ran pub get in $relativeDir in ${seconds.toStringAsFixed(1)}s...');
        }));
        count += 1;
      }
      unawaited(queue.add(() async {
        final Stopwatch stopwatch = Stopwatch();
        await _downloadCoverageData();
        stopwatch.stop();
        final double seconds = stopwatch.elapsedMilliseconds / 1000.0;
        globals.printStatus('Downloaded lcov data for package:flutter in ${seconds.toStringAsFixed(1)}s...');
      }));
      await queue.tasksComplete;
      status.stop();
      // The exception is rethrown, so don't catch only Exceptions.
    } catch (exception) { // ignore: avoid_catches_without_on_clauses
      status.cancel();
      rethrow;
    }

    final double seconds = timer.elapsedMilliseconds / 1000.0;
    globals.printStatus("\nRan 'pub get' $count time${count == 1 ? "" : "s"} and fetched coverage data in ${seconds.toStringAsFixed(1)}s.");
  }

  void showDependencyPaths({
    required String from,
    required String to,
    required PubDependencyTree tree,
  }) {
    if (!tree.contains(from)) {
      throwToolExit('Package $from not found in the dependency tree.');
    }
    if (!tree.contains(to)) {
      throwToolExit('Package $to not found in the dependency tree.');
    }

    final Queue<_DependencyLink> traversalQueue = Queue<_DependencyLink>();
    final Set<String> visited = <String>{};
    final List<_DependencyLink> paths = <_DependencyLink>[];

    traversalQueue.addFirst(_DependencyLink(from: null, to: from));
    while (traversalQueue.isNotEmpty) {
      final _DependencyLink link = traversalQueue.removeLast();
      if (link.to == to) {
        paths.add(link);
      }
      if (link.from != null) {
        visited.add(link.from!.to);
      }
      for (final String dependency in tree._dependencyTree[link.to]!) {
        if (!visited.contains(dependency)) {
          traversalQueue.addFirst(_DependencyLink(from: link, to: dependency));
        }
      }
    }

    for (_DependencyLink path in paths) {
      final StringBuffer buf = StringBuffer();
      while (path != null) {
        buf.write(path.to);
        path = path.from!;
        if (path != null) {
          buf.write(' <- ');
        }
      }
      globals.printStatus(buf.toString(), wrap: false);
    }

    if (paths.isEmpty) {
      globals.printStatus('No paths found from $from to $to');
    }
  }
}

class _DependencyLink {
  _DependencyLink({
    required this.from,
    required this.to,
  });

  final _DependencyLink? from;
  final String to;

  @override
  String toString() => '${from?.to} -> $to';
}

/// The various sections of a pubspec.yaml file.
///
/// We care about the "dependencies", "dev_dependencies", and
/// "dependency_overrides" sections, as well as the "name" and "version" fields
/// in the pubspec header bucketed into [header]. The others are all bucketed
/// into [other].
enum Section { header, dependencies, devDependencies, dependencyOverrides, builders, other }

/// The various kinds of dependencies we know and care about.
enum DependencyKind {
  // Dependencies that will be path or sdk dependencies but
  // for which we haven't yet parsed the data.
  unknown,

  // Regular dependencies with a specified version range.
  normal,

  // Dependency that uses an explicit path, e.g. into the Dart SDK.
  path,

  // Dependency defined as coming from an SDK (typically "sdk: flutter").
  sdk,

  // A dependency that was "normal", but for which we later found a "path" or
  // "sdk" dependency in the dependency_overrides section.
  overridden,

  // A dependency that uses git.
  git,
}

/// This is the string we output next to each of our autogenerated transitive
/// dependencies so that we can ignore them the next time we parse the
/// pubspec.yaml file.
const String kTransitiveMagicString= '# THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"';


/// This is the string output before a checksum of the packages used.
const String kDependencyChecksum = '# PUBSPEC CHECKSUM: ';

/// This class represents a pubspec.yaml file for the purposes of upgrading the
/// dependencies as done by this file.
class PubspecYaml {
  /// You create one of these by providing a directory, from which we obtain the
  /// pubspec.yaml and parse it into a line-by-line form.
  factory PubspecYaml(Directory directory) {
    final File file = _pubspecFor(directory);
    return _parse(file, file.readAsLinesSync());
  }

  PubspecYaml._(this.file, this.name, this.version, this.inputData, this.checksum);

  final File file; // The actual pubspec.yaml file.

  /// The package name.
  final String name;

  /// The package version.
  final String? version;

  final List<PubspecLine> inputData; // Each line of the pubspec.yaml file, parsed(ish).

  /// The package checksum.
  ///
  /// If this was not found in the pubspec, a synthetic checksum is created
  /// with a value of `-1`.
  final PubspecChecksum checksum;

  /// This parses each line of a pubspec.yaml file (a list of lines) into
  /// slightly more structured data (in the form of a list of PubspecLine
  /// objects). We don't just use a YAML parser because we care about comments
  /// and also because we can just define the style of pubspec.yaml files we care
  /// about (since they're all under our control).
  static PubspecYaml _parse(File file, List<String> lines) {
    final String filename = file.path;
    String? packageName;
    String? packageVersion;
    PubspecChecksum? checksum; // the checksum value used to verify that dependencies haven't changed.
    final List<PubspecLine> result = <PubspecLine>[]; // The output buffer.
    Section section = Section.other; // Which section we're currently reading from.
    bool seenMain = false; // Whether we've seen the "dependencies:" section.
    bool seenDev = false; // Whether we've seen the "dev_dependencies:" section.
    // The masterDependencies map is used to keep track of the objects
    // representing actual dependencies we've seen so far in this file so that
    // if we see dependency overrides we can update the actual dependency so it
    // knows that it's not really a dependency.
    final Map<String, PubspecDependency> masterDependencies = <String, PubspecDependency>{};
    // The "special" dependencies (the ones that use git: or path: or sdk: or
    // whatnot) have the style of having extra data after the line that declares
    // the dependency. So we track what is the "current" (or "last") dependency
    // that we are dealing with using this variable.
    PubspecDependency? lastDependency;
    for (int index = 0; index < lines.length; index += 1) {
      String line = lines[index];
      if (lastDependency == null) {
        // First we look to see if we're transitioning to a new top-level section.
        // The PubspecHeader.parse static method can recognize those headers.
        final PubspecHeader? header = PubspecHeader.parse(line); // See if it's a header.
        if (header != null) { // It is!
          section = header.section; // The parser determined what kind of section it is.
          if (section == Section.header) {
            if (header.name == 'name') {
              packageName = header.value;
            } else if (header.name == 'version') {
              packageVersion = header.value;
            }
          } else if (section == Section.dependencies) {
            // If we're entering the "dependencies" section, we want to make sure that
            // it's the first section (of those we care about) that we've seen so far.
            if (seenMain) {
              throwToolExit('Two dependencies sections found in $filename. There should only be one.');
            }
            if (seenDev) {
              throwToolExit('The dependencies section was after the dev_dependencies section in $filename. '
                    'To enable one-pass processing, the dependencies section must come before the '
                    'dev_dependencies section.');
            }
            seenMain = true;
          } else if (section == Section.devDependencies) {
            // Similarly, if we're entering the dev_dependencies section, we should verify
            // that we've not seen one already.
            if (seenDev) {
              throwToolExit('Two dev_dependencies sections found in $filename. There should only be one.');
            }
            seenDev = true;
          }
          result.add(header);
        } else if (section == Section.builders) {
          // Do nothing.
          // This line isn't a section header, and we're not in a section we care about.
          // We just stick the line into the output unmodified.
          result.add(PubspecLine(line));
        } else if (section == Section.other) {
          if (line.contains(kDependencyChecksum)) {
            // This is the pubspec checksum. After computing it, we remove it from the output data
            // since it will be recomputed later.
            checksum = PubspecChecksum.parse(line);
          } else {
            // This line isn't a section header, and we're not in a section we care about.
            // We just stick the line into the output unmodified.
            result.add(PubspecLine(line));
          }
        } else {
          // We're in a section we care about. Try to parse out the dependency:
          final PubspecDependency? dependency = PubspecDependency.parse(line, filename: filename);
          if (dependency != null) { // We got one!
            // Track whether or not this a dev dependency.
            dependency.isDevDependency = seenDev;
            result.add(dependency);
            if (dependency.kind == DependencyKind.unknown) {
              // If we didn't get a version number, then we need to be ready to
              // read the next line as part of this dependency, so keep track of
              // this dependency object.
              lastDependency = dependency;
            }
            if (section != Section.dependencyOverrides) {
              // If we're not in the overrides section, then just remember the
              // dependency, in case it comes up again later in the overrides
              // section.
              //
              // First, make sure it's a unique dependency. Listing dependencies
              // twice doesn't make sense.
              if (masterDependencies.containsKey(dependency.name)) {
                throwToolExit('$filename contains two dependencies on ${dependency.name}.');
              }
              masterDependencies[dependency.name] = dependency;
            } else {
              // If we _are_ in the overrides section, then go tell the version
              // we saw earlier (if any -- there might not be, we might be
              // overriding a transitive dependency) that we have overridden it,
              // so that later when we output the dependencies we can leave
              // the line unmodified.
              masterDependencies[dependency.name]?.markOverridden(dependency);
            }
          } else if (line.contains(kDependencyChecksum)) {
            // This is the pubspec checksum. After computing it, we remove it from the output data
            // since it will be recomputed later.
            checksum = PubspecChecksum.parse(line);
          } else {
            // We're in a section we care about but got a line we didn't
            // recognize. Maybe it's a comment or a blank line or something.
            // Just pass it through.
            result.add(PubspecLine(line));
          }
        }
      } else {
        // If we're here it means the last line was a dependency that needed
        // extra information to be parsed from the next line.
        //
        // Try to parse the line by giving it to the last PubspecDependency
        // object we created. If parseLock fails to recognize the line, it will
        // throw. If it does recognize the line and needs the following lines in
        // its lockLine, it'll return false.
        // Otherwise it returns true.
        //
        // If it returns true, then it will have updated itself internally to
        // store the information from this line.
        if (!lastDependency.parseLock(line, filename, lockIsOverride: section == Section.dependencyOverrides)) {
          // Ok we're dealing with some "git:" dependency. Consume lines until
          // we are out of the git dependency, and stuff them into the lock
          // line.
          lastDependency._lockLine = line;
          lastDependency._lockIsOverride = section == Section.dependencyOverrides;
          do {
            index += 1;
            if (index == lines.length) {
              throw StateError('Invalid pubspec.yaml: a "git" dependency section terminated early.');
            }
            line = lines[index];
            lastDependency._lockLine = '${lastDependency._lockLine}\n$line';
          } while (line.startsWith('   '));
        }
        // We're done with this special dependency, so reset back to null so
        // we'll go in the top section next time instead.
        lastDependency = null;
      }
    }
    return PubspecYaml._(file, packageName!, packageVersion, result, checksum ?? PubspecChecksum(null, ''));
  }

  /// This returns all the explicit dependencies that this pubspec.yaml lists under dependencies.
  Iterable<PubspecDependency> get dependencies {
    // It works by iterating over the parsed data from _parse above, collecting
    // all the dependencies that were found, ignoring any that are flagged as as
    // overridden by subsequent entries in the same file and any that have the
    // magic comment flagging them as auto-generated transitive dependencies
    // that we added in a previous run.
    return inputData
        .whereType<PubspecDependency>()
        .where((PubspecDependency data) => data.kind != DependencyKind.overridden && !data.isTransitive && !data.isDevDependency);
  }

  /// This returns all regular dependencies and all dev dependencies.
  Iterable<PubspecDependency> get allExplicitDependencies {
    return inputData
        .whereType<PubspecDependency>()
        .where((PubspecDependency data) => data.kind != DependencyKind.overridden && !data.isTransitive);
  }

  /// This returns all dependencies.
  Iterable<PubspecDependency> get allDependencies {
    return inputData.whereType<PubspecDependency>();
  }

  /// Take a dependency graph with explicit version numbers, and apply them to
  /// the pubspec.yaml, ignoring any that we know are special dependencies (those
  /// that depend on the Flutter or Dart SDK directly and are thus automatically
  /// pinned).
  void apply(PubDependencyTree versions, Set<String> specialDependencies) {
    assert(versions != null);
    final List<String> output = <String>[]; // the string data to output to the file, line by line
    final Set<String> directDependencies = <String>{}; // packages this pubspec directly depends on (i.e. not transitive)
    final Set<String> devDependencies = <String>{};
    Section section = Section.other; // the section we're currently handling

    // the line number where we're going to insert the transitive dependencies.
    int? endOfDirectDependencies;
    // The line number where we're going to insert the transitive dev dependencies.
    int? endOfDevDependencies;
    // Walk the pre-parsed input file, outputting it unmodified except for
    // updating version numbers, removing the old transitive dependencies lines,
    // and adding our new transitive dependencies lines. We also do a little
    // cleanup, removing trailing spaces, removing double-blank lines, leading
    // blank lines, and trailing blank lines, and ensuring the file ends with a
    // newline. This cleanup lets us be a little more aggressive while building
    // the output.
    for (final PubspecLine data in inputData) {
      if (data is PubspecHeader) {
        // This line was a header of some sort.
        //
        // If we're leaving one of the sections in which we can list transitive
        // dependencies, then remember this as the current last known valid
        // place to insert our transitive dependencies.
        if (section == Section.dependencies) {
          endOfDirectDependencies = output.length;
        }
        if (section == Section.devDependencies) {
          endOfDevDependencies = output.length;
        }
        section = data.section; // track which section we're now in.
        output.add(data.line); // insert the header into the output
      } else if (data is PubspecDependency) {
        // This was a dependency of some sort.
        // How we handle this depends on the section.
        switch (section) {
          case Section.devDependencies:
          case Section.dependencies:
            // For the dependencies and dev_dependencies sections, we reinsert
            // the dependency if it wasn't one of our autogenerated transitive
            // dependency lines.
            if (!data.isTransitive) {
              // Assert that we haven't seen it in this file already.
              assert(!directDependencies.contains(data.name) && !devDependencies.contains(data.name));
              if (data.kind == DependencyKind.normal) {
                // This is a regular dependency, so we need to update the
                // version number.
                //
                // We output data that matches the format that
                // PubspecDependency.parse can handle. The data.suffix is any
                // previously-specified trailing comment.
                assert(versions.contains(data.name),
                       "versions doesn't contain ${data.name}");
                output.add('  ${data.name}: ${versions.versionFor(data.name)}${data.suffix}');
              } else {
                // If it wasn't a regular dependency, then we output the line
                // unmodified. If there was an additional line (e.g. an "sdk:
                // flutter" line) then we output that too.
                output.add(data.line);
                if (data.lockLine != null) {
                  output.add(data.lockLine!);
                }
              }
              // Remember that we've dealt with this dependency so we don't
              // mention it again when doing the transitive dependencies.
              if (section == Section.dependencies) {
                directDependencies.add(data.name);
              } else {
                devDependencies.add(data.name);
              }
            }
            // Since we're in one of the places where we can list dependencies,
            // remember this as the current last known valid place to insert our
            // transitive dev dependencies. If the section is for regular dependencies,
            // then also remember the line for the end of direct dependencies.
            if (section == Section.dependencies) {
              endOfDirectDependencies = output.length;
            }
            endOfDevDependencies = output.length;
            break;
          case Section.builders:
          case Section.dependencyOverrides:
          case Section.header:
          case Section.other:
            // In other sections, pass everything through in its original form.
            output.add(data.line);
            if (data.lockLine != null) {
              output.add(data.lockLine!);
            }
            break;
        }
      } else {
        // Not a header, not a dependency, just pass that through unmodified.
        output.add(data.line);
      }
    }

    // If there are no dependencies or dev_dependencies sections, these will be
    // null. We have such files in our tests, so account for them here.
    endOfDirectDependencies ??= output.length;
    endOfDevDependencies ??= output.length;

    // Now include all the transitive dependencies and transitive dev dependencies.
    // The blocks of text to insert for each dependency section.
    final List<String> transitiveDependencyOutput = <String>[];
    final List<String> transitiveDevDependencyOutput = <String>[];

    // Which dependencies we need to handle for the transitive and dev dependency sections.
    final Set<String> transitiveDependencies = <String>{};
    final Set<String> transitiveDevDependencies = <String>{};

    // Merge the lists of dependencies we've seen in this file from dependencies, dev dependencies,
    // and the dependencies we know this file mentions that are already pinned
    // (and which didn't get special processing above).
    final Set<String> implied = <String>{
      ...directDependencies,
      ...specialDependencies,
      ...devDependencies,
    };

    // Create a new set to hold the list of packages we've already processed, so
    // that we don't redundantly process them multiple times.
    final Set<String> done = <String>{};
    for (final String package in directDependencies) {
      transitiveDependencies.addAll(versions.getTransitiveDependenciesFor(package, seen: done, exclude: implied));
    }
    for (final String package in devDependencies) {
      transitiveDevDependencies.addAll(versions.getTransitiveDependenciesFor(package, seen: done, exclude: implied));
    }

    // Sort each dependency block lexically so that we don't get noisy diffs when upgrading.
    final List<String> transitiveDependenciesAsList = transitiveDependencies.toList()..sort();
    final List<String> transitiveDevDependenciesAsList = transitiveDevDependencies.toList()..sort();

    String computeTransitiveDependencyLineFor(String package) {
      return '  $package: ${versions.versionFor(package)} $kTransitiveMagicString';
    }

    // Add a line for each transitive dependency and transitive dev dependency using our magic string to recognize them later.
    for (final String package in transitiveDependenciesAsList) {
      transitiveDependencyOutput.add(computeTransitiveDependencyLineFor(package));
    }
    for (final String package in transitiveDevDependenciesAsList) {
      transitiveDevDependencyOutput.add(computeTransitiveDependencyLineFor(package));
    }

    // Build a sorted list of all dependencies for the checksum.
    final Set<String> checksumDependencies = <String>{
      ...directDependencies,
      ...devDependencies,
      ...transitiveDependenciesAsList,
      ...transitiveDevDependenciesAsList,
    }..removeAll(specialDependencies);

    // Add a blank line before and after each section to keep the resulting output clean.
    transitiveDependencyOutput
      ..insert(0, '')
      ..add('');
    transitiveDevDependencyOutput
      ..insert(0, '')
      ..add('');

    // Compute a new checksum from all sorted dependencies and their version and convert to a hex string.
    final String checksumString = _computeChecksum(checksumDependencies, versions.versionFor);

    // Insert the block of transitive dependency declarations into the output after [endOfDirectDependencies],
    // and the blocks of transitive dev dependency declarations into the output after [lastPossiblePlace]. Finally,
    // insert the [checksumString] at the very end.
    output
      ..insertAll(endOfDevDependencies, transitiveDevDependencyOutput)
      ..insertAll(endOfDirectDependencies, transitiveDependencyOutput)
      ..add('')
      ..add('$kDependencyChecksum$checksumString');

    // Remove trailing lines.
    while (output.last.isEmpty) {
      output.removeLast();
    }

    // Output the result to the pubspec.yaml file, skipping leading and
    // duplicate blank lines and removing trailing spaces.
    final StringBuffer contents = StringBuffer();
    bool hadBlankLine = true;
    for (String line in output) {
      line = line.trimRight();
      if (line == '') {
        if (!hadBlankLine) {
          contents.writeln();
        }
        hadBlankLine = true;
      } else {
        contents.writeln(line);
        hadBlankLine = false;
      }
    }
    file.writeAsStringSync(contents.toString());
  }
}

/// This is the base class for the objects that represent lines in the
/// pubspec.yaml files.
class PubspecLine {
  PubspecLine(this.line);

  /// The raw line as we saw it in the original file. This is used so that we can
  /// output the same line unmodified for the majority of lines.
  final String line;
}

/// A checksum of the non autogenerated dependencies.
class PubspecChecksum extends PubspecLine {
  PubspecChecksum(this.value, String line) : super(line);

  /// The checksum value, computed using [Object.hash] over the direct, dev,
  /// and special dependencies sorted lexically.
  ///
  /// If the line cannot be parsed, [value] will be null.
  final String? value;

  /// Parses a [PubspecChecksum] from a line.
  ///
  /// The returned PubspecChecksum will have a null [value] if no checksum could
  /// be found on this line. This is a value that [_computeChecksum] cannot return.
  static PubspecChecksum parse(String line) {
    final List<String> tokens = line.split(kDependencyChecksum);
    if (tokens.length != 2) {
      return PubspecChecksum(null, line);
    }
    return PubspecChecksum(tokens.last.trim(), line);
  }
}

/// A header, e.g. "dependencies:".
class PubspecHeader extends PubspecLine {
  PubspecHeader(
    super.line,
    this.section, {
    this.name,
    this.value,
  });

  /// The section of the pubspec where the parse [line] appears.
  final Section section;

  /// The name in the pubspec line providing a name/value pair, such as "name"
  /// and "version".
  ///
  /// Example:
  ///
  /// The value of this field extracted from the following line is "version".
  ///
  /// ```
  /// version: 0.16.5
  /// ```
  final String? name;

  /// The value in the pubspec line providing a name/value pair, such as "name"
  /// and "version".
  ///
  /// Example:
  ///
  /// The value of this field extracted from the following line is "0.16.5".
  ///
  /// ```
  /// version: 0.16.5
  /// ```
  final String? value;

  static PubspecHeader? parse(String line) {
    // We recognize any line that:
    //  * doesn't start with a space (i.e. is aligned on the left edge)
    //  * ignoring trailing spaces and comments, ends with a colon
    //  * has contents before the colon
    // We also try to recognize which of the kinds of Sections it is
    // by comparing those contents against known strings.
    if (line.startsWith(' ')) {
      return null;
    }
    final String strippedLine = _stripComments(line);
    if (!strippedLine.contains(':') || strippedLine.length <= 1) {
      return null;
    }
    final List<String> parts = strippedLine.split(':');
    final String sectionName = parts.first;
    final String value = parts.last.trim();
    switch (sectionName) {
      case 'dependencies':
        return PubspecHeader(line, Section.dependencies);
      case 'dev_dependencies':
        return PubspecHeader(line, Section.devDependencies);
      case 'dependency_overrides':
        return PubspecHeader(line, Section.dependencyOverrides);
      case 'builders':
        return PubspecHeader(line, Section.builders);
      case 'name':
      case 'version':
        return PubspecHeader(line, Section.header, name: sectionName, value: value);
      default:
        return PubspecHeader(line, Section.other);
    }
  }

  /// Returns the input after removing trailing spaces and anything after the
  /// first "#".
  static String _stripComments(String line) {
    final int hashIndex = line.indexOf('#');
    if (hashIndex < 0) {
      return line.trimRight();
    }
    return line.substring(0, hashIndex).trimRight();
  }
}

/// A dependency, as represented by a line (or two) from a pubspec.yaml file.
class PubspecDependency extends PubspecLine {
  PubspecDependency(
    super.line,
    this.name,
    this.suffix, {
    required this.isTransitive,
    required DependencyKind kind,
    required this.version,
    required this.sourcePath,
  }) : _kind = kind;

  static PubspecDependency? parse(String line, { required String filename }) {
    // We recognize any line that:
    //  * starts with exactly two spaces, no more or less
    //  * has some content, then a colon
    //
    // If we recognize the line, then we look to see if there's anything after
    // the colon, ignoring comments. If there is, then this is a normal
    // dependency, otherwise it's an unknown one.
    //
    // We also try and save the version string, if any. This is used to verify
    // the checksum of package deps.
    //
    // We also look at the trailing comment, if any, to see if it is the magic
    // string that identifies the line as a transitive dependency that we
    // previously pinned, so we can ignore it.
    //
    // We remember the trailing comment, if any, so that we can reconstruct the
    // line later. We forget the specified version range, if any.
    if (line.length < 4 || line.startsWith('   ') || !line.startsWith('  ')) {
      return null;
    }
    final int colonIndex = line.indexOf(':');
    final int hashIndex = line.indexOf('#');
    if (colonIndex < 3) { // two spaces at 0 and 1, a character at 2
      return null;
    }
    if (hashIndex >= 0 && hashIndex < colonIndex) {
      return null;
    }
    final String package = line.substring(2, colonIndex).trimRight();
    assert(package.isNotEmpty);
    assert(line.startsWith('  $package'));
    String suffix = '';
    bool isTransitive = false;
    String stripped;
    String version = '';
    if (hashIndex >= 0) {
      assert(hashIndex > colonIndex);
      final String trailingComment = line.substring(hashIndex, line.length);
      assert(line.endsWith(trailingComment));
      isTransitive = trailingComment == kTransitiveMagicString;
      suffix = ' $trailingComment';
      stripped = line.substring(colonIndex + 1, hashIndex).trimRight();
    } else {
      stripped = line.substring(colonIndex + 1, line.length).trimRight();
    }
    if (colonIndex != -1) {
      version = line.substring(colonIndex + 1, hashIndex != -1 ? hashIndex : line.length).trim();
    }
    return PubspecDependency(line, package, suffix, isTransitive: isTransitive, version: version, kind: stripped.isEmpty ? DependencyKind.unknown : DependencyKind.normal, sourcePath: filename);
  }

  final String name; // the package name
  final String suffix; // any trailing comment we found
  final String version; // the version string if found, or blank.
  final bool isTransitive; // whether the suffix matched kTransitiveMagicString
  final String sourcePath; // the filename of the pubspec.yaml file, for error messages
  late bool isDevDependency; // Whether this dependency is under the `dev dependencies` section.

  DependencyKind get kind => _kind;
  DependencyKind _kind = DependencyKind.normal;

  /// If we're a path or sdk dependency, the path or sdk in question.
  String? _lockTarget;

  /// If we were a two-line dependency, the second line (see the inherited [line]
  /// for the first).
  String? get lockLine => _lockLine;
  String? _lockLine;

  /// If we're a path or sdk dependency, whether we were found in a
  /// dependencies/dev_dependencies section, or a dependency_overrides section.
  /// We track this so that we can put ourselves in the right section when
  /// generating the fake pubspec.yaml.
  bool get lockIsOverride => _lockIsOverride;
  late bool _lockIsOverride;

  static const String _pathPrefix = '    path: ';
  static const String _sdkPrefix = '    sdk: ';
  static const String _gitPrefix = '    git:';

  /// Whether the dependency points to a package in the Flutter SDK.
  ///
  /// There are two ways one can point to a Flutter package:
  ///
  /// - Using a "sdk: flutter" dependency.
  /// - Using a "path" dependency that points somewhere in the Flutter
  ///   repository other than the "bin" directory.
  bool get pointsToSdk {
    if (_kind == DependencyKind.sdk) {
      return true;
    }

    final String? lockTarget = _lockTarget;
    if (_kind == DependencyKind.path && lockTarget != null &&
        !globals.fs.path.isWithin(globals.fs.path.join(Cache.flutterRoot!, 'bin'), lockTarget) &&
        globals.fs.path.isWithin(Cache.flutterRoot!, lockTarget)) {
      return true;
    }

    return false;
  }

  /// If parse decided we were a two-line dependency, this is called to parse the second line.
  /// We throw if we couldn't parse this line.
  /// We return true if we parsed it and stored the line in lockLine.
  /// We return false if we parsed it and it's a git dependency that needs the next few lines.
  bool parseLock(String line, String pubspecPath, { required bool lockIsOverride }) {
    assert(lockIsOverride != null);
    assert(kind == DependencyKind.unknown);
    if (line.startsWith(_pathPrefix)) {
      // We're a path dependency; remember the (absolute) path.
      _lockTarget = globals.fs.path.canonicalize(
          globals.fs.path.absolute(globals.fs.path.dirname(pubspecPath), line.substring(_pathPrefix.length, line.length))
      );
      _kind = DependencyKind.path;
    } else if (line.startsWith(_sdkPrefix)) {
      // We're an SDK dependency.
      _lockTarget = line.substring(_sdkPrefix.length, line.length);
      _kind = DependencyKind.sdk;
    } else if (line.startsWith(_gitPrefix)) {
      // We're a git: dependency. We'll have to get the next few lines.
      _kind = DependencyKind.git;
      return false;
    } else {
      throwToolExit('Could not parse additional details for dependency $name; line was: "$line"');
    }
    _lockIsOverride = lockIsOverride;
    _lockLine = line;
    return true;
  }

  void markOverridden(PubspecDependency sibling) {
    // This is called when we find a dependency is mentioned a second time,
    // first in dependencies/dev_dependencies, and then in dependency_overrides.
    // It is called on the one found in dependencies/dev_dependencies, so that
    // we'll later know to report our version as "any" in the fake pubspec.yaml
    // and unmodified in the official pubspec.yamls.
    assert(sibling.name == name);
    assert(sibling.sourcePath == sourcePath);
    assert(sibling.kind != DependencyKind.normal);
    _kind = DependencyKind.overridden;
  }

  /// This generates the entry for this dependency for the pubspec.yaml for the
  /// fake package that we'll use to get the version numbers figured out.
  ///
  /// When called with [doUpgrade] as [true], the version constrains will be set
  /// to >= whatever the previous version was. If [doUpgrade] is [false], then
  /// the previous version is used again as an exact pin.
  void describeForFakePubspec(StringBuffer dependencies, StringBuffer overrides, { bool doUpgrade = true }) {
    final String versionToUse;
    // This should only happen when manually adding new dependencies; otherwise
    // versions should always be pinned exactly
    if (version.isEmpty || version == 'any') {
      versionToUse = 'any';
    } else if (doUpgrade) {
      // Must wrap in quotes for Yaml parsing
      versionToUse = "'>= $version'";
    } else {
      versionToUse = version;
    }
    switch (kind) {
      case DependencyKind.unknown:
      case DependencyKind.overridden:
        assert(kind != DependencyKind.unknown);
        break;
      case DependencyKind.normal:
        if (!kManuallyPinnedDependencies.containsKey(name)) {
          dependencies.writeln('  $name: $versionToUse');
        }
        break;
      case DependencyKind.path:
        if (lockIsOverride) {
          dependencies.writeln('  $name: $versionToUse');
          overrides.writeln('  $name:');
          overrides.writeln('    path: $_lockTarget');
        } else {
          dependencies.writeln('  $name:');
          dependencies.writeln('    path: $_lockTarget');
        }
        break;
      case DependencyKind.sdk:
        if (lockIsOverride) {
          dependencies.writeln('  $name: $versionToUse');
          overrides.writeln('  $name:');
          overrides.writeln('    sdk: $_lockTarget');
        } else {
          dependencies.writeln('  $name:');
          dependencies.writeln('    sdk: $_lockTarget');
        }
        break;
      case DependencyKind.git:
        if (lockIsOverride) {
          dependencies.writeln('  $name: $versionToUse');
          overrides.writeln('  $name:');
          overrides.writeln(lockLine);
        } else {
          dependencies.writeln('  $name:');
          dependencies.writeln(lockLine);
        }
        break;
    }
  }

  @override
  String toString() {
    return '$name: $version';
  }
}

/// Generates the File object for the pubspec.yaml file of a given Directory.
File _pubspecFor(Directory directory) {
  return directory.fileSystem.file(
    directory.fileSystem.path.join(directory.path, 'pubspec.yaml'));
}

/// Generates the source of a fake pubspec.yaml file given a list of
/// dependencies.
@visibleForTesting
String generateFakePubspec(
  Iterable<PubspecDependency> dependencies, {
  bool doUpgrade = false
}) {
  final StringBuffer result = StringBuffer();
  final StringBuffer overrides = StringBuffer();
  final bool verbose = doUpgrade;
  result.writeln('name: flutter_update_packages');
  result.writeln('environment:');
  result.writeln("  sdk: '>=2.10.0 <3.0.0'");
  result.writeln('dependencies:');
  overrides.writeln('dependency_overrides:');
  if (kManuallyPinnedDependencies.isNotEmpty) {
    if (verbose) {
      globals.printStatus('WARNING: the following packages use hard-coded version constraints:');
    }
    final Set<String> allTransitive = <String>{
      for (final PubspecDependency dependency in dependencies)
        dependency.name,
    };
    kManuallyPinnedDependencies.forEach((String package, String version) {
      // Don't add pinned dependency if it is not in the set of all transitive dependencies.
      if (!allTransitive.contains(package)) {
        if (verbose) {
          globals.printStatus('Skipping $package because it was not transitive');
        }
        return;
      }
      result.writeln('  $package: $version');
      if (verbose) {
        globals.printStatus('  - $package: $version');
      }
    });
  }
  for (final PubspecDependency dependency in dependencies) {
    if (!dependency.pointsToSdk) {
      dependency.describeForFakePubspec(result, overrides, doUpgrade: doUpgrade);
    }
  }
  result.write(overrides.toString());
  return result.toString();
}

/// This object tracks the output of a call to "pub deps --style=compact".
///
/// It ends up holding the full graph of dependencies, and the version number for
/// each one.
class PubDependencyTree {
  final Map<String, String?> _versions = <String, String>{};
  final Map<String, Set<String>> _dependencyTree = <String, Set<String>>{};

  /// Handles the output from "pub deps --style=compact".
  ///
  /// That output is of this form:
  ///
  /// ```
  /// package_name 0.0.0
  ///
  /// dependencies:
  /// - analyzer 0.31.0-alpha.0 [watcher args package_config collection]
  /// - archive 1.0.31 [crypto args path]
  /// - args 0.13.7
  /// - cli_util 0.1.2+1 [path]
  ///
  /// dev dependencies:
  /// - async 1.13.3 [collection]
  /// - barback 0.15.2+11 [stack_trace source_span pool async collection path]
  ///
  /// dependency overrides:
  /// - analyzer 0.31.0-alpha.0 [watcher args package_config collection]
  /// ```
  ///
  /// We ignore all the lines that don't start with a hyphen. For each other
  /// line, we ignore any line that mentions a package we've already seen (this
  /// happens when the overrides section mentions something that was in the
  /// dependencies section). We ignore if something is a dependency or
  /// dev_dependency (pub won't use different versions for those two).
  ///
  /// We then parse out the package name, version number, and sub-dependencies for
  /// each entry, and store than in our _versions and _dependencyTree fields
  /// above.
  String? fill(String message) {
    if (message.startsWith('- ')) {
      final int space2 = message.indexOf(' ', 2);
      int space3 = message.indexOf(' ', space2 + 1);
      if (space3 < 0) {
        space3 = message.length;
      }
      final String package = message.substring(2, space2);
      if (!contains(package)) {
        // Some packages get listed in the dependency overrides section too.
        // We just ignore those. The data is the same either way.
        final String version = message.substring(space2 + 1, space3);
        List<String> dependencies;
        if (space3 < message.length) {
          assert(message[space3 + 1] == '[');
          assert(message[message.length - 1] == ']');
          final String allDependencies = message.substring(space3 + 2, message.length - 1);
          dependencies = allDependencies.split(' ');
        } else {
          dependencies = const <String>[];
        }
        _versions[package] = version;
        _dependencyTree[package] = Set<String>.of(dependencies);
      }
    }
    return null;
  }

  /// Whether we know about this package.
  bool contains(String package) {
    return _versions.containsKey(package);
  }

  /// The transitive closure of all the dependencies for the given package,
  /// excluding any listed in `seen`.
  Iterable<String> getTransitiveDependenciesFor(
    String package, {
    required Set<String> seen,
    required Set<String> exclude,
    List<String>? result,
  }) {
    assert(seen != null);
    assert(exclude != null);
    result ??= <String>[];
    final Set<String>? dependencies = _dependencyTree[package];
    if (dependencies == null) {
      // We have no transitive dependencies extracted for flutter_sdk packages
      // because they were omitted from pubspec.yaml used for 'pub upgrade' run.
      return result;
    }
    for (final String dependency in dependencies) {
      if (!seen.contains(dependency)) {
        if (!exclude.contains(dependency)) {
          result.add(dependency);
        }
        seen.add(dependency);
        getTransitiveDependenciesFor(dependency, seen: seen, exclude: exclude, result: result);
      }
    }
    return result;
  }

  /// The version that a particular package ended up with.
  String versionFor(String package) {
    return _versions[package]!;
  }
}

// Produces a 16-bit checksum from the codePoints of the package name and
// version strings using Fletcher's algorithm.
String _computeChecksum(Iterable<String> names, String Function(String name) getVersion) {
  int lowerCheck = 0;
  int upperCheck = 0;
  final List<String> sortedNames = names.toList()..sort();
  for (final String name in sortedNames) {
    final String version = getVersion(name);
    if (version == null) {
      continue;
    }
    final String value = '$name: $version';
    // Each code unit is 16 bits.
    for (final int codeUnit in value.codeUnits) {
      final int upper = codeUnit >> 8;
      final int lower = codeUnit & 0xFF;
      lowerCheck = (lowerCheck + upper) % 255;
      upperCheck = (upperCheck + lowerCheck) % 255;
      lowerCheck = (lowerCheck + lower) % 255;
      upperCheck = (upperCheck + lowerCheck) % 255;
    }
  }
  return ((upperCheck << 8) | lowerCheck).toRadixString(16).padLeft(4, '0');
}

/// Create a synthetic Flutter SDK so that pub version solving does not get
/// stuck on the old versions.
@visibleForTesting
Directory createTemporaryFlutterSdk(
  Logger logger,
  FileSystem fileSystem,
  Directory realFlutter,
  List<PubspecYaml> pubspecs,
) {
  final Set<String> currentPackages = <String>{};
  for (final FileSystemEntity entity in realFlutter.childDirectory('packages').listSync()) {
    // Verify that a pubspec.yaml exists to ensure this isn't a left over directory.
    if (entity is Directory && entity.childFile('pubspec.yaml').existsSync()) {
      currentPackages.add(fileSystem.path.basename(entity.path));
    }
  }

  final Map<String, PubspecYaml> pubspecsByName = <String, PubspecYaml>{};
  for (final PubspecYaml pubspec in pubspecs) {
    pubspecsByName[pubspec.name] = pubspec;
  }

  final Directory directory = fileSystem.systemTempDirectory
    .createTempSync('flutter_upgrade_sdk.')
    ..createSync();
  // Fill in version info.
  realFlutter.childFile('version')
    .copySync(directory.childFile('version').path);

  // Directory structure should mirror the current Flutter SDK
  final Directory packages = directory.childDirectory('packages');
  for (final String flutterPackage in currentPackages) {
    final File pubspecFile = packages
      .childDirectory(flutterPackage)
      .childFile('pubspec.yaml')
      ..createSync(recursive: true);
    final PubspecYaml? pubspecYaml = pubspecsByName[flutterPackage];
    if (pubspecYaml == null) {
      logger.printWarning(
        "Unexpected package '$flutterPackage' found in packages directory",
      );
      continue;
    }
    final StringBuffer output = StringBuffer('name: $flutterPackage\n');

    // Fill in SDK dependency constraint.
    output.write('''
environment:
  sdk: ">=2.7.0 <3.0.0"
''');

    output.writeln('dependencies:');
    for (final PubspecDependency dependency in pubspecYaml.dependencies) {
      if (dependency.isTransitive || dependency.isDevDependency) {
        continue;
      }
      if (dependency.kind == DependencyKind.sdk) {
        output.writeln('  ${dependency.name}:\n    sdk: flutter');
        continue;
      }
      output.writeln('  ${dependency.name}: any');
    }
    pubspecFile.writeAsStringSync(output.toString());
  }

  // Create the sky engine pubspec.yaml
  directory
    .childDirectory('bin')
    .childDirectory('cache')
    .childDirectory('pkg')
    .childDirectory('sky_engine')
    .childFile('pubspec.yaml')
    ..createSync(recursive: true)
    ..writeAsStringSync('''
name: sky_engine
version: 0.0.99
description: Dart SDK extensions for dart:ui
homepage: http://flutter.io
# sky_engine requires sdk_ext support in the analyzer which was added in 1.11.x
environment:
  sdk: '>=1.11.0 <3.0.0'
''');

  return directory;
}
