// 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: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 '../path.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: p.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;
}
