// Copyright (c) 2021, 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.

/// Implements support for dependency-bot style automated upgrades.
/// It is still work in progress - do not rely on the current output.
library;

import 'dart:convert';
import 'dart:io';

import 'package:collection/collection.dart';
import 'package:path/path.dart';
import 'package:pub_semver/pub_semver.dart';
import 'package:yaml/yaml.dart';
import 'package:yaml_edit/yaml_edit.dart';

import '../command.dart';
import '../entrypoint.dart';
import '../exceptions.dart';
import '../io.dart';
import '../lock_file.dart';
import '../log.dart' as log;
import '../package.dart';
import '../package_name.dart';
import '../pubspec.dart';
import '../pubspec_utils.dart';
import '../sdk.dart';
import '../solver.dart';
import '../solver/version_solver.dart';
import '../source/git.dart';
import '../source/hosted.dart';
import '../source/root.dart';
import '../system_cache.dart';
import '../utils.dart';

class DependencyServicesReportCommand extends PubCommand {
  @override
  String get name => 'report';
  @override
  String get description =>
      'Output a machine-digestible '
      'report of the upgrade options for each dependency.';
  @override
  String get argumentsDescription => '[options]';

  @override
  bool get takesArguments => false;

  DependencyServicesReportCommand() {
    argParser.addOption(
      'directory',
      abbr: 'C',
      help: 'Run this in the directory <dir>.',
      valueHelp: 'dir',
    );
  }

  @override
  Future<void> runProtected() async {
    _checkAtRoot(entrypoint);
    final stdinString = await utf8.decodeStream(stdin);
    final input =
        json.decode(stdinString.isEmpty ? '{}' : stdinString)
            as Map<String, Object?>;
    final additionalConstraints = _parseDisallowed(input, cache);
    final targetPackageName = input['target'];
    if (targetPackageName is! String?) {
      throw const FormatException('"target" should be a String.');
    }

    final compatibleWorkspace = entrypoint.workspaceRoot.transformWorkspace(
      (p) => stripDependencyOverrides(p.pubspec),
    );

    final breakingWorkspace = compatibleWorkspace.transformWorkspace(
      (p) => stripVersionBounds(p.pubspec),
    );

    final compatiblePackagesResult = await _tryResolve(
      compatibleWorkspace,
      cache,
      additionalConstraints: additionalConstraints,
    );

    final breakingPackagesResult = await _tryResolve(
      breakingWorkspace,
      cache,
      additionalConstraints: additionalConstraints,
    );

    final currentPackages = await _computeCurrentPackages(entrypoint, cache);

    final dependencies = <Object>[];
    final result = <String, Object>{'dependencies': dependencies};

    final targetPackage =
        targetPackageName == null ? null : currentPackages[targetPackageName];

    for (final package
        in targetPackage == null
            ? currentPackages.values
            : <PackageId>[targetPackage]) {
      final compatibleVersion = compatiblePackagesResult?.firstWhereOrNull(
        (element) => element.name == package.name,
      );
      final multiBreakingVersion = breakingPackagesResult?.firstWhereOrNull(
        (element) => element.name == package.name,
      );

      final kind = _kindString(compatibleWorkspace, package.name);
      PackageId? singleBreakingVersion;

      if (kind != 'transitive') {
        final singleBreakingWorkspace = compatibleWorkspace.transformWorkspace((
          p,
        ) {
          final r = stripVersionBounds(p.pubspec, stripOnly: [package.name]);
          return r;
        });
        final singleBreakingPackagesResult = await _tryResolve(
          singleBreakingWorkspace,
          cache,
        );
        singleBreakingVersion = singleBreakingPackagesResult?.firstWhereOrNull(
          (element) => element.name == package.name,
        );
      }
      PackageId? smallestUpgrade;
      if (additionalConstraints.any(
        (c) => c.range.toRef() == package.toRef() && !c.range.allows(package),
      )) {
        // Current version disallowed by restrictions.
        final atLeastCurrentWorkspace = compatibleWorkspace.transformWorkspace(
          (p) => atLeastCurrent(
            p.pubspec,
            entrypoint.lockFile.packages.values.toList(),
          ),
        );

        final smallestUpgradeResult = await _tryResolve(
          atLeastCurrentWorkspace,
          cache,
          solveType: SolveType.downgrade,
          additionalConstraints: additionalConstraints,
        );

        smallestUpgrade = smallestUpgradeResult?.firstWhereOrNull(
          (element) => element.name == package.name,
        );
      }

      Future<List<Object>> computeUpgradeSet(
        PackageId? package,
        _UpgradeType upgradeType,
      ) async {
        return await _computeUpgradeSet(
          compatibleWorkspace,
          package,
          entrypoint,
          cache,
          currentPackages: currentPackages,
          upgradeType: upgradeType,
          additionalConstraints: additionalConstraints,
        );
      }

      dependencies.add({
        'name': package.name,
        'version': package.versionOrHash(),
        'kind': kind,
        'source': _source(package, containingDir: directory),
        'latest':
            (await cache.getLatest(
              package.toRef(),
              version: package.version,
            ))?.versionOrHash(),
        'constraint':
            _constraintIntersection(
              compatibleWorkspace,
              package.name,
            )?.toString(),
        'compatible': await computeUpgradeSet(
          compatibleVersion,
          _UpgradeType.compatible,
        ),
        'singleBreaking':
            kind != 'transitive' && singleBreakingVersion == null
                ? <Object>[]
                : await computeUpgradeSet(
                  singleBreakingVersion,
                  _UpgradeType.singleBreaking,
                ),
        'multiBreaking':
            kind != 'transitive' && multiBreakingVersion != null
                ? await computeUpgradeSet(
                  multiBreakingVersion,
                  _UpgradeType.multiBreaking,
                )
                : <Object>[],
        if (smallestUpgrade != null)
          'smallestUpdate': await computeUpgradeSet(
            smallestUpgrade,
            _UpgradeType.smallestUpdate,
          ),
      });
    }
    log.message(const JsonEncoder.withIndent('  ').convert(result));
  }
}

class DependencyServicesListCommand extends PubCommand {
  @override
  String get name => 'list';

  @override
  String get description =>
      'Output a machine digestible listing of all dependencies';

  @override
  bool get takesArguments => false;

  DependencyServicesListCommand() {
    argParser.addOption(
      'directory',
      abbr: 'C',
      help: 'Run this in the directory <dir>.',
      valueHelp: 'dir',
    );
  }

  @override
  Future<void> runProtected() async {
    _checkAtRoot(entrypoint);
    final currentPackages =
        fileExists(entrypoint.lockFilePath)
            ? entrypoint.lockFile.packages.values.toList()
            : (await _tryResolve(entrypoint.workspaceRoot, cache) ??
                <PackageId>[]);

    final dependencies = <Object>[];
    final result = <String, Object>{'dependencies': dependencies};

    for (final package in currentPackages.where((p) => !p.isRoot)) {
      dependencies.add({
        'name': package.name,
        'version': package.versionOrHash(),
        'kind': _kindString(entrypoint.workspaceRoot, package.name),
        'constraint':
            _constraintIntersection(
              entrypoint.workspaceRoot,
              package.name,
            )?.toString(),
        'source': _source(package, containingDir: directory),
      });
    }
    log.message(const JsonEncoder.withIndent('  ').convert(result));
  }
}

extension on PackageId {
  String versionOrHash() {
    final description = this.description;
    if (description is ResolvedGitDescription) {
      return description.resolvedRef;
    } else {
      return version.toString();
    }
  }
}

enum _UpgradeType {
  /// Only upgrade pubspec.lock.
  compatible,

  /// Unlock at most one dependency in pubspec.yaml.
  singleBreaking,

  /// Unlock any dependencies in pubspec.yaml needed for getting the
  /// latest resolvable version.
  multiBreaking,

  /// Try to upgrade as little as possible.
  smallestUpdate,
}

class DependencyServicesApplyCommand extends PubCommand {
  @override
  String get name => 'apply';

  @override
  String get description =>
      'Updates pubspec.yaml and pubspec.lock according to input.';

  @override
  bool get takesArguments => true;

  DependencyServicesApplyCommand() {
    argParser.addOption(
      'directory',
      abbr: 'C',
      help: 'Run this in the directory <dir>.',
      valueHelp: 'dir',
    );
  }

  @override
  Future<void> runProtected() async {
    final toApply = <_PackageVersion>[];
    final input = json.decode(await utf8.decodeStream(stdin));
    if (input is! Map<String, dynamic>) {
      fail('Bad input, must be json map');
    }
    final dependencyChanges = input['dependencyChanges'];
    if (dependencyChanges is! List) {
      fail('Bad input. `dependencyChanges` must be a list');
    }
    for (final change in dependencyChanges) {
      if (change is! Map<String, dynamic>) {
        fail('Bad input. Each element of `dependencyChanges` must be a map.');
      }
      toApply.add(
        _PackageVersion(
          change['name'] as String,
          change['version'] as String?,
          change['constraint'] != null
              ? VersionConstraint.parse(change['constraint'] as String)
              : null,
        ),
      );
    }
    final updatedPubspecs = <String, YamlEditor>{};
    _checkAtRoot(entrypoint);
    for (final package in entrypoint.workspaceRoot.transitiveWorkspace) {
      final pubspec = package.pubspec;
      final pubspecEditor = YamlEditor(readTextFile(package.pubspecPath));
      for (final p in toApply) {
        final targetConstraint = p.constraint;
        final targetPackage = p.name;
        final targetVersion = p.version;
        late final section =
            pubspec.dependencies[targetPackage] != null
                ? 'dependencies'
                : pubspec.devDependencies[targetPackage] != null
                ? 'dev_dependencies'
                : null;
        if (section != null) {
          if (targetConstraint != null) {
            final packageConfig =
                pubspecEditor.parseAt([section, targetPackage]).value;
            if (packageConfig == null || packageConfig is String) {
              pubspecEditor.update([
                section,
                targetPackage,
              ], targetConstraint.toString());
            } else if (packageConfig is Map) {
              pubspecEditor.update([
                section,
                targetPackage,
                'version',
              ], targetConstraint.toString());
            } else {
              fail(
                'The dependency $targetPackage does not have a '
                'map or string as a description',
              );
            }
          } else if (targetVersion != null) {
            final constraint = _constraintOf(pubspec, targetPackage);
            if (constraint != null && !constraint.allows(targetVersion)) {
              pubspecEditor.update([
                section,
                targetPackage,
              ], VersionConstraint.compatibleWith(targetVersion).toString());
            }
          }
        }
        updatedPubspecs[package.dir] = pubspecEditor;
      }
    }
    final lockFile =
        fileExists(entrypoint.lockFilePath)
            ? readTextFile(entrypoint.lockFilePath)
            : null;
    final lockFileYaml = lockFile == null ? null : loadYaml(lockFile);

    final lockFileEditor = lockFile == null ? null : YamlEditor(lockFile);
    final hasContentHashes = _lockFileHasContentHashes(lockFileYaml);
    final usesPubDev = _lockFileUsesPubDev(lockFileYaml);
    for (final p in toApply) {
      final targetPackage = p.name;
      final targetVersion = p.version;
      final targetRevision = p.gitRevision;

      if (lockFileEditor != null) {
        if (lockFileYaml is! Map) {
          fail('Malformed pubspec.lock. Must be a map');
        }
        if (targetVersion != null &&
            (lockFileYaml['packages'] as Map).containsKey(targetPackage)) {
          lockFileEditor.update([
            'packages',
            targetPackage,
            'version',
          ], targetVersion.toString());
          // Remove the now outdated content-hash - it will be restored below
          // after resolution.
          final packageMap =
              lockFileEditor.parseAt([
                    'packages',
                    targetPackage,
                    'description',
                  ]).value
                  as Map;
          final hasSha = packageMap.containsKey('sha256');
          if (hasSha) {
            lockFileEditor.remove([
              'packages',
              targetPackage,
              'description',
              'sha256',
            ]);
          }
        } else if (targetRevision != null &&
            (lockFileYaml['packages'] as Map).containsKey(targetPackage)) {
          final ref = entrypoint.lockFile.packages[targetPackage]!.toRef();
          final currentDescription = ref.description as GitDescription;
          final updatedRef = PackageRef(
            targetPackage,
            GitDescription(
              url: currentDescription.url,
              path: currentDescription.path,
              ref: targetRevision,
              containingDir: directory,
            ),
          );
          final versions = await cache.getVersions(updatedRef);
          if (versions.isEmpty) {
            dataError(
              'Found no versions of $targetPackage '
              'with git revision `$targetRevision`.',
            );
          }
          // GitSource can only return a single version.
          assert(versions.length == 1);

          lockFileEditor.update([
            'packages',
            targetPackage,
            'version',
          ], versions.single.version.toString());
          lockFileEditor.update([
            'packages',
            targetPackage,
            'description',
            'resolved-ref',
          ], targetRevision);
        } else if (targetVersion == null &&
            targetRevision == null &&
            !(lockFileYaml['packages'] as Map).containsKey(targetPackage)) {
          dataError(
            'Trying to remove non-existing '
            'transitive dependency $targetPackage.',
          );
        }
      }
    }

    final updatedLockfile =
        lockFileEditor == null
            ? null
            : LockFile.parse(
              lockFileEditor.toString(),
              cache.sources,
              filePath: entrypoint.lockFilePath,
            );
    await log.errorsOnlyUnlessTerminal(() async {
      final updatedWorkspace = entrypoint.workspaceRoot.transformWorkspace(
        (package) => Pubspec.parse(
          updatedPubspecs[package.dir].toString(),
          cache.sources,
          location: toUri(package.pubspecPath),
          containingDescription: ResolvedRootDescription(
            RootDescription(package.dir),
          ),
        ),
      );
      // Resolve versions, this will update transitive dependencies that were
      // not passed in the input. And also counts as a validation of the input
      // by ensuring the resolution is valid.
      //
      // We don't use `acquireDependencies` as that downloads all the archives
      // to cache.
      // TODO: Handle HTTP exceptions gracefully!
      final solveResult = await resolveVersions(
        SolveType.get,
        cache,
        updatedWorkspace,
        lockFile: updatedLockfile,
      );
      for (final package in entrypoint.workspaceRoot.transitiveWorkspace) {
        final updatedPubspec = updatedPubspecs[package.dir]!;
        if (updatedPubspec.edits.isNotEmpty) {
          writeTextFile(package.pubspecPath, updatedPubspec.toString());
        }
      }
      // Only if we originally had a lock-file we write the resulting lockfile
      // back.
      if (updatedLockfile != null) {
        final updatedPackages = <PackageId>[];
        for (var package in solveResult.packages) {
          if (package.isRoot) continue;
          final description = package.description;
          // Handle content-hashes of hosted dependencies.
          if (description is ResolvedHostedDescription) {
            // Ensure we get content-hashes if the original lock-file had
            // them.
            if (hasContentHashes) {
              if (description.sha256 == null) {
                // We removed the hash above before resolution - as we get the
                // locked id back we need to find the content-hash from the
                // version listing.
                //
                // `pub get` gets this version-listing from the downloaded
                // archive but we don't want to download all archives - so we
                // copy it from the version listing.
                package = (await cache.getVersions(
                  package.toRef(),
                )).firstWhere((id) => id == package, orElse: () => package);
                if ((package.description as ResolvedHostedDescription).sha256 ==
                    null) {
                  // This happens when we resolved a package from a legacy
                  // server not providing archive_sha256. As a side-effect of
                  // downloading the package we compute and store the sha256.
                  package = (await cache.downloadPackage(package)).packageId;
                }
              }
            } else {
              // The original pubspec.lock did not have content-hashes. Remove
              // any content hash, so we don't start adding them.
              package = PackageId(
                package.name,
                package.version,
                description.withSha256(null),
              );
            }
            // Keep using https://pub.dartlang.org if the original lockfile
            // used it. This is to support lockfiles from old sdks.
            if (!usesPubDev &&
                HostedSource.isPubDevUrl(description.description.url)) {
              package = PackageId(
                package.name,
                package.version,
                ResolvedHostedDescription(
                  HostedDescription.raw(
                    package.name,
                    HostedSource.pubDartlangUrl,
                  ),
                  sha256:
                      (package.description as ResolvedHostedDescription).sha256,
                ),
              );
            }
          }
          updatedPackages.add(package);
        }

        final newLockFile = LockFile(
          updatedPackages,
          sdkConstraints: updatedLockfile.sdkConstraints,
          mainDependencies: entrypoint.lockFile.mainDependencies,
          devDependencies: entrypoint.lockFile.devDependencies,
          overriddenDependencies: entrypoint.lockFile.overriddenDependencies,
        );

        newLockFile.writeToFile(entrypoint.lockFilePath, cache);
      }
    });
    // Dummy message.
    log.message(json.encode({'dependencies': <Object>[]}));
  }
}

void _checkAtRoot(Entrypoint entrypoint) {
  if (entrypoint.workspaceRoot != entrypoint.workPackage) {
    fail('Only apply dependency_services to the root of the workspace.');
  }
}

class _PackageVersion {
  String name;
  Version? version;
  String? gitRevision;
  VersionConstraint? constraint;
  _PackageVersion(this.name, String? versionOrHash, this.constraint)
    : version = versionOrHash == null ? null : _tryParseVersion(versionOrHash),
      gitRevision = versionOrHash == null ? null : _tryParseHash(versionOrHash);
}

Version? _tryParseVersion(String v) {
  try {
    return Version.parse(v);
  } on FormatException {
    return null;
  }
}

String? _tryParseHash(String v) {
  if (RegExp(r'^[a-fA-F0-9]+$').hasMatch(v)) {
    return v;
  }
  return null;
}

Map<String, PackageRange>? _dependencySetOfPackage(
  Pubspec pubspec,
  PackageId package,
) {
  return pubspec.dependencies.containsKey(package.name)
      ? pubspec.dependencies
      : pubspec.devDependencies.containsKey(package.name)
      ? pubspec.devDependencies
      : null;
}

/// Return a constraint compatible with [newVersion].
///
/// By convention if the original constraint is pinned we return [newVersion].
/// Otherwise use [VersionConstraint.compatibleWith].
VersionConstraint _bumpConstraint(
  VersionConstraint original,
  Version newVersion,
) {
  if (original.isEmpty) return newVersion;
  if (original is VersionRange) {
    if (original.min == original.max) return newVersion;

    return VersionConstraint.compatibleWith(newVersion);
  }

  throw ArgumentError.value(
    original,
    'original',
    'Must be a Version range or empty',
  );
}

/// Return a constraint compatible with [newVersion], but including [original]
/// as well.
///
/// By convention if the original constraint is pinned, we don't widen the
/// constraint but return [newVersion] instead.
VersionConstraint _widenConstraint(
  VersionConstraint original,
  Version newVersion,
) {
  if (original.allows(newVersion)) return original;
  if (original is VersionRange) {
    final min = original.min;
    final max = original.max;
    if (min == max) return newVersion;
    if (max != null && newVersion >= max) {
      return _compatibleWithIfPossible(
        VersionRange(
          min: min,
          includeMin: original.includeMin,
          max: newVersion.nextBreaking.firstPreRelease,
        ),
      );
    }
    if (min != null && newVersion <= min) {
      return _compatibleWithIfPossible(
        VersionRange(
          min: newVersion,
          includeMin: true,
          max: max,
          includeMax: original.includeMax,
        ),
      );
    }
  }

  if (original.isEmpty) return newVersion;
  throw ArgumentError.value(
    original,
    'original',
    'Must be a Version range or empty',
  );
}

VersionConstraint _compatibleWithIfPossible(VersionRange versionRange) {
  final min = versionRange.min;
  if (min != null && min.nextBreaking.firstPreRelease == versionRange.max) {
    return VersionConstraint.compatibleWith(min);
  }
  return versionRange;
}

/// `true` iff any of the packages described by the [lockfile] has a
/// content-hash.
///
/// Undefined for invalid lock files, but mostly `true`.
bool _lockFileHasContentHashes(dynamic lockfile) {
  if (lockfile is! Map) return true;
  final packages = lockfile['packages'];
  if (packages is! Map) return true;

  /// We consider an empty lockfile ready to get content-hashes.
  if (packages.isEmpty) return true;
  for (final package in packages.values) {
    if (package is! Map) return true;
    final descriptor = package['description'];
    if (descriptor is! Map) return true;
    if (descriptor['sha256'] != null) return true;
  }
  return false;
}

/// Try to solve [package] return [PackageId]s in the resolution or `null` if no
/// resolution was found.
Future<List<PackageId>?> _tryResolve(
  Package package,
  SystemCache cache, {
  SolveType solveType = SolveType.upgrade,
  Iterable<ConstraintAndCause>? additionalConstraints,
}) async {
  final solveResult = await tryResolveVersions(
    solveType,
    cache,
    package,
    additionalConstraints: additionalConstraints,
  );

  return solveResult?.packages;
}

VersionConstraint? _constraintIntersection(
  Package workspace,
  String packageName,
) {
  final constraints =
      workspace.transitiveWorkspace
          .map((p) => _constraintOf(p.pubspec, packageName))
          .nonNulls;
  if (constraints.isEmpty) {
    return null;
  }
  return constraints
      .reduce((a, b) => a.intersect(b))
      .asCompatibleWithIfPossible();
}

VersionConstraint? _constraintOf(Pubspec pubspec, String packageName) {
  return (pubspec.dependencies[packageName] ??
          pubspec.devDependencies[packageName])
      ?.constraint;
}

String _kindString(Package workspace, String packageName) {
  return workspace.transitiveWorkspace.any(
        (p) => p.dependencies.containsKey(packageName),
      )
      ? 'direct'
      : workspace.transitiveWorkspace.any(
        (p) => p.devDependencies.containsKey(packageName),
      )
      ? 'dev'
      : 'transitive';
}

Map<String, Object?> _source(PackageId id, {required String containingDir}) {
  return {
    'type': id.source.name,
    'description': id.description.serializeForLockfile(
      containingDir: containingDir,
    ),
  };
}

/// The packages in the current lockfile or resolved from current pubspec.yaml.
/// Does not include the root package.
Future<Map<String, PackageId>> _computeCurrentPackages(
  Entrypoint entrypoint,
  SystemCache cache,
) async {
  late Map<String, PackageId> currentPackages;

  if (fileExists(entrypoint.lockFilePath)) {
    currentPackages = Map<String, PackageId>.from(entrypoint.lockFile.packages);
  } else {
    final resolution =
        await _tryResolve(entrypoint.workspaceRoot, cache) ??
        (throw DataException('Failed to resolve pubspec'));
    currentPackages = Map<String, PackageId>.fromIterable(
      resolution,
      key: (e) => (e as PackageId).name,
    );
  }
  for (final p in entrypoint.workspaceRoot.transitiveWorkspace) {
    currentPackages.remove(p.name);
  }
  return currentPackages;
}

Future<List<Object>> _computeUpgradeSet(
  Package workspace,
  PackageId? package,
  Entrypoint entrypoint,
  SystemCache cache, {
  required Map<String, PackageId> currentPackages,
  required _UpgradeType upgradeType,
  required List<ConstraintAndCause> additionalConstraints,
}) async {
  if (package == null) return [];
  final lockFile = entrypoint.lockFile;
  final upgradedWorkspace =
      (upgradeType == _UpgradeType.multiBreaking ||
              upgradeType == _UpgradeType.smallestUpdate)
          ? workspace.transformWorkspace((p) => stripVersionBounds(p.pubspec))
          : workspace.transformWorkspace((p) => p.pubspec.copyWith());

  for (final p in upgradedWorkspace.transitiveWorkspace) {
    final dependencySet = _dependencySetOfPackage(p.pubspec, package);
    if (dependencySet != null) {
      // Force the version to be the new version.
      dependencySet[package.name] = package.toRef().withConstraint(
        package.toRange().constraint,
      );
    }
  }

  final resolution = await tryResolveVersions(
    upgradeType == _UpgradeType.smallestUpdate
        ? SolveType.downgrade
        : SolveType.get,
    cache,
    upgradedWorkspace,
    lockFile: lockFile,
    additionalConstraints: additionalConstraints,
  );

  // TODO(sigurdm): improve error messages.
  if (resolution == null) {
    return [];
  }
  final workspaceNames = {...workspace.transitiveWorkspace.map((p) => p.name)};
  return [
    ...resolution.packages
        .where((r) {
          if (workspaceNames.contains(r.name)) return false;
          final originalVersion = currentPackages[r.name];
          return originalVersion == null || r != originalVersion;
        })
        .map((p) {
          final constraintIntersection = _constraintIntersection(
            workspace,
            p.name,
          );
          final currentPackage = currentPackages[p.name];
          return {
            'name': p.name,
            'version': p.versionOrHash(),
            'kind': _kindString(workspace, p.name),
            'source': _source(p, containingDir: entrypoint.workspaceRoot.dir),
            'constraintBumped':
                constraintIntersection == null
                    ? null
                    : upgradeType == _UpgradeType.compatible
                    ? constraintIntersection.toString()
                    : _bumpConstraint(
                      constraintIntersection,
                      p.version,
                    ).toString(),
            'constraintWidened':
                constraintIntersection == null
                    ? null
                    : upgradeType == _UpgradeType.compatible
                    ? constraintIntersection.toString()
                    : _widenConstraint(
                      constraintIntersection,
                      p.version,
                    ).toString(),
            'constraintBumpedIfNeeded':
                constraintIntersection == null
                    ? null
                    : upgradeType == _UpgradeType.compatible
                    ? constraintIntersection.toString()
                    : constraintIntersection.allows(p.version)
                    ? constraintIntersection.toString()
                    : _bumpConstraint(
                      constraintIntersection,
                      p.version,
                    ).toString(),
            'previousVersion': currentPackage?.versionOrHash(),
            'previousConstraint': constraintIntersection?.toString(),
            'previousSource':
                currentPackage == null
                    ? null
                    : _source(
                      currentPackage,
                      containingDir: entrypoint.workspaceRoot.dir,
                    ),
          };
        }),
    // Find packages that were removed by the resolution
    for (final oldPackageName in lockFile.packages.keys)
      if (!resolution.packages.any(
        (newPackage) => newPackage.name == oldPackageName,
      ))
        {
          'name': oldPackageName,
          'version': null,
          'kind': 'transitive', // Only transitive constraints can be removed.
          'constraintBumped': null,
          'constraintWidened': null,
          'constraintBumpedIfNeeded': null,
          'previousVersion': currentPackages[oldPackageName]?.versionOrHash(),
          'previousConstraint': null,
          'previous': _source(
            currentPackages[oldPackageName]!,
            containingDir: entrypoint.workspaceRoot.dir,
          ),
        },
  ];
}

List<ConstraintAndCause> _parseDisallowed(
  Map<String, Object?> input,
  SystemCache cache,
) {
  final disallowedList = input['disallowed'];
  if (disallowedList == null) {
    return [];
  }
  if (disallowedList is! List<Object?>) {
    throw const FormatException('Disallowed should be a list of maps');
  }
  final result = <ConstraintAndCause>[];
  for (final disallowed in disallowedList) {
    if (disallowed is! Map) {
      throw const FormatException('Disallowed should be a list of maps');
    }
    final name = disallowed['name'];
    if (name is! String) {
      throw const FormatException('"name" should be a string.');
    }
    final url = disallowed['url'] ?? cache.hosted.defaultUrl;
    if (url is! String) {
      throw const FormatException('"url" should be a string.');
    }
    final ref = PackageRef(name, HostedDescription(name, url));
    final constraints = disallowed['versions'];
    if (constraints is! List) {
      throw const FormatException('"versions" should be a list.');
    }
    final reason = disallowed['reason'];
    if (reason is! String?) {
      throw const FormatException('"reason", if present, should be a string.');
    }
    for (final entry in constraints) {
      if (entry is! Map) {
        throw const FormatException(
          'Each element of "versions" should be an object.',
        );
      }
      final rangeString = entry['range'];
      if (rangeString is! String) {
        throw const FormatException('"range" should be a string');
      }
      final range = VersionConstraint.parse(rangeString);
      result.add(
        ConstraintAndCause(
          PackageRange(ref, VersionConstraint.any.difference(range)),
          reason,
        ),
      );
    }
  }
  return result;
}

/// `true` iff any of the packages described by the [lockfile] uses
/// `https://pub.dev` as url.
///
/// Undefined for invalid lock files, but mostly `true`.
bool _lockFileUsesPubDev(dynamic lockfile) {
  if (lockfile is! Map) return true;
  final packages = lockfile['packages'];
  if (packages is! Map) return true;

  /// We consider an empty lockfile ready to get content-hashes.
  if (packages.isEmpty) return true;
  for (final package in packages.values) {
    if (package is! Map) return true;
    if (package['source'] != 'hosted') continue;
    final descriptor = package['description'];
    if (descriptor is! Map) return true;
    final url = descriptor['url'];
    if (url is! String) return true;
    if (HostedSource.isPubDevUrl(url) && url != HostedSource.pubDartlangUrl) {
      return true;
    }
  }
  return false;
}
