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.');
}
}