// 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,
              tagPattern: currentDescription.tagPattern,
            ),
          );
          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;
}
