Future runProtected()

in lib/src/command/add.dart [100:206]


  Future<void> runProtected() async {
    if (argResults.rest.isEmpty) {
      usageException('Must specify at least one package to be added.');
    } else if (argResults.rest.length > 1 && gitUrl != null) {
      usageException('Can only add a single git package at a time.');
    } else if (argResults.rest.length > 1 && path != null) {
      usageException('Can only add a single local package at a time.');
    }
    final languageVersion = entrypoint.root.pubspec.languageVersion;
    final updates =
        argResults.rest.map((p) => _parsePackage(p, languageVersion)).toList();

    var updatedPubSpec = entrypoint.root.pubspec;
    for (final update in updates) {
      /// Perform version resolution in-memory.
      updatedPubSpec =
          await _addPackageToPubspec(updatedPubSpec, update.packageRange);
    }

    late SolveResult solveResult;

    try {
      /// Use [SolveType.UPGRADE] to solve for the highest version of [package]
      /// in case [package] was already a transitive dependency. In the case
      /// where the user specifies a version constraint, this serves to ensure
      /// that a resolution exists before we update pubspec.yaml.
      // TODO(sigurdm): We should really use a spinner here.
      solveResult = await resolveVersions(
          SolveType.upgrade, cache, Package.inMemory(updatedPubSpec));
    } on GitException {
      final packageRange = updates.first.packageRange;
      dataError(
          'Unable to resolve package "${packageRange.name}" with the given '
          'git parameters.');
    } on SolveFailure catch (e) {
      dataError(e.message);
    } on WrappedException catch (e) {
      /// [WrappedException]s may appear if an invalid [hostUrl] is passed in.
      dataError(e.message);
    }

    /// Verify the results for each package.
    for (final update in updates) {
      final packageRange = update.packageRange;
      final name = packageRange.name;
      final resultPackage = solveResult.packages
          .firstWhere((packageId) => packageId.name == name);

      /// Assert that [resultPackage] is within the original user's expectations.
      var constraint = packageRange.constraint;
      if (!constraint.allows(resultPackage.version)) {
        var dependencyOverrides = updatedPubSpec.dependencyOverrides;
        if (dependencyOverrides.isNotEmpty) {
          dataError('"$name" resolved to "${resultPackage.version}" which '
              'does not satisfy constraint "$constraint". This could be '
              'caused by "dependency_overrides".');
        }
        dataError('"$name" resolved to "${resultPackage.version}" which '
            'does not satisfy constraint "$constraint".');
      }
    }
    if (isDryRun) {
      /// Even if it is a dry run, run `acquireDependencies` so that the user
      /// gets a report on the other packages that might change version due
      /// to this new dependency.
      final newRoot = Package.inMemory(updatedPubSpec);

      await Entrypoint.inMemory(newRoot, cache,
              solveResult: solveResult, lockFile: entrypoint.lockFile)
          .acquireDependencies(SolveType.get,
              dryRun: true,
              precompile: argResults['precompile'],
              analytics: analytics,
              generateDotPackages: false);
    } else {
      /// Update the `pubspec.yaml` before calling [acquireDependencies] to
      /// ensure that the modification timestamp on `pubspec.lock` and
      /// `.dart_tool/package_config.json` is newer than `pubspec.yaml`,
      /// ensuring that [entrypoint.assertUptoDate] will pass.
      _updatePubspec(solveResult.packages, updates, isDev);

      /// Create a new [Entrypoint] since we have to reprocess the updated
      /// pubspec file.
      final updatedEntrypoint = Entrypoint(directory, cache);
      await updatedEntrypoint.acquireDependencies(
        SolveType.get,
        precompile: argResults['precompile'],
        analytics: analytics,
        generateDotPackages: argResults['legacy-packages-file'],
      );

      if (argResults['example'] && entrypoint.example != null) {
        await entrypoint.example!.acquireDependencies(
          SolveType.get,
          precompile: argResults['precompile'],
          onlyReportSuccessOrFailure: true,
          analytics: analytics,
          generateDotPackages: argResults['legacy-packages-file'],
        );
      }
    }

    if (isOffline) {
      log.warning('Warning: Packages added when offline may not resolve to '
          'the latest compatible version available.');
    }
  }