// 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: 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;
}
