diff --git a/benches/benchsuite/benches/resolve.rs b/benches/benchsuite/benches/resolve.rs index 89d0212e378..d798dd6d62b 100644 --- a/benches/benchsuite/benches/resolve.rs +++ b/benches/benchsuite/benches/resolve.rs @@ -33,6 +33,7 @@ fn do_resolve<'gctx>(gctx: &'gctx GlobalContext, ws_root: &Path) -> ResolveInfo< let force_all_targets = ForceAllTargets::No; // Do an initial run to download anything necessary so that it does // not confuse criterion's warmup. + let dry_run = false; let ws_resolve = cargo::ops::resolve_ws_with_opts( &ws, &mut target_data, @@ -41,6 +42,7 @@ fn do_resolve<'gctx>(gctx: &'gctx GlobalContext, ws_root: &Path) -> ResolveInfo< &specs, has_dev_units, force_all_targets, + dry_run, ) .unwrap(); ResolveInfo { @@ -71,6 +73,7 @@ fn resolve_ws(c: &mut Criterion) { // iterator once, and we don't want to call `do_resolve` in every // "step", since that would just be some useless work. let mut lazy_info = None; + let dry_run = false; group.bench_function(&ws_name, |b| { let ResolveInfo { ws, @@ -91,6 +94,7 @@ fn resolve_ws(c: &mut Criterion) { specs, *has_dev_units, *force_all_targets, + dry_run, ) .unwrap(); }) diff --git a/crates/cargo-test-support/src/compare.rs b/crates/cargo-test-support/src/compare.rs index 53b752621de..a6a9d30e7af 100644 --- a/crates/cargo-test-support/src/compare.rs +++ b/crates/cargo-test-support/src/compare.rs @@ -176,6 +176,7 @@ static E2E_LITERAL_REDACTIONS: &[(&str, &str)] = &[ ("[DIRTY]", " Dirty"), ("[LOCKING]", " Locking"), ("[UPDATING]", " Updating"), + ("[UPGRADING]", " Upgrading"), ("[ADDING]", " Adding"), ("[REMOVING]", " Removing"), ("[REMOVED]", " Removed"), diff --git a/src/bin/cargo/commands/add.rs b/src/bin/cargo/commands/add.rs index 9c67eb8343c..30956b00479 100644 --- a/src/bin/cargo/commands/add.rs +++ b/src/bin/cargo/commands/add.rs @@ -214,11 +214,9 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { }; add(&ws, &options)?; - if !dry_run { - // Reload the workspace since we've changed dependencies - let ws = args.workspace(gctx)?; - resolve_ws(&ws)?; - } + // Reload the workspace since we've changed dependencies + let ws = args.workspace(gctx)?; + resolve_ws(&ws, dry_run)?; Ok(()) } diff --git a/src/bin/cargo/commands/remove.rs b/src/bin/cargo/commands/remove.rs index 25179487c93..b5695e59937 100644 --- a/src/bin/cargo/commands/remove.rs +++ b/src/bin/cargo/commands/remove.rs @@ -121,7 +121,7 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { ws.gctx() .shell() .set_verbosity(cargo::core::Verbosity::Quiet); - let resolve = resolve_ws(&ws); + let resolve = resolve_ws(&ws, dry_run); ws.gctx().shell().set_verbosity(verbosity); resolve?.1 }; @@ -129,7 +129,7 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { // Attempt to gc unused patches and re-resolve if anything is removed if gc_unused_patches(&workspace, &resolve)? { let ws = args.workspace(gctx)?; - resolve_ws(&ws)?; + resolve_ws(&ws, dry_run)?; } } Ok(()) diff --git a/src/bin/cargo/commands/update.rs b/src/bin/cargo/commands/update.rs index fb394e4aa33..3369763d676 100644 --- a/src/bin/cargo/commands/update.rs +++ b/src/bin/cargo/commands/update.rs @@ -35,6 +35,13 @@ pub fn cli() -> Command { .value_name("PRECISE") .requires("package-group"), ) + .arg( + flag( + "breaking", + "Upgrade [SPEC] to latest breaking versions, unless pinned (unstable)", + ) + .short('b'), + ) .arg_silent_suggestion() .arg( flag("workspace", "Only update the workspace packages") @@ -59,7 +66,8 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { gctx.cli_unstable().msrv_policy, )?; } - let ws = args.workspace(gctx)?; + + let mut ws = args.workspace(gctx)?; if args.is_present_with_zero_values("package") { print_available_packages(&ws)?; @@ -89,6 +97,24 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { workspace: args.flag("workspace"), gctx, }; - ops::update_lockfile(&ws, &update_opts)?; + + if args.flag("breaking") { + gctx.cli_unstable() + .fail_if_stable_opt("--breaking", 12425)?; + + let upgrades = ops::upgrade_manifests(&mut ws, &update_opts.to_update)?; + ops::resolve_ws(&ws, update_opts.dry_run)?; + ops::write_manifest_upgrades(&ws, &upgrades, update_opts.dry_run)?; + + if update_opts.dry_run { + update_opts + .gctx + .shell() + .warn("aborting update due to dry run")?; + } + } else { + ops::update_lockfile(&ws, &update_opts)?; + } + Ok(()) } diff --git a/src/cargo/core/compiler/standard_lib.rs b/src/cargo/core/compiler/standard_lib.rs index 684e4426c04..3e387bdddcc 100644 --- a/src/cargo/core/compiler/standard_lib.rs +++ b/src/cargo/core/compiler/standard_lib.rs @@ -149,6 +149,7 @@ pub fn resolve_std<'gctx>( let cli_features = CliFeatures::from_command_line( &features, /*all_features*/ false, /*uses_default_features*/ false, )?; + let dry_run = false; let resolve = ops::resolve_ws_with_opts( &std_ws, target_data, @@ -157,6 +158,7 @@ pub fn resolve_std<'gctx>( &specs, HasDevUnits::No, crate::core::resolver::features::ForceAllTargets::No, + dry_run, )?; Ok(( resolve.pkg_set, diff --git a/src/cargo/core/summary.rs b/src/cargo/core/summary.rs index ec0197cf40d..d7744e24ef7 100644 --- a/src/cargo/core/summary.rs +++ b/src/cargo/core/summary.rs @@ -103,15 +103,25 @@ impl Summary { Rc::make_mut(&mut self.inner).checksum = Some(cksum); } - pub fn map_dependencies(mut self, f: F) -> Summary + pub fn map_dependencies(self, mut f: F) -> Summary where F: FnMut(Dependency) -> Dependency, + { + self.try_map_dependencies(|dep| Ok(f(dep))).unwrap() + } + + pub fn try_map_dependencies(mut self, f: F) -> CargoResult + where + F: FnMut(Dependency) -> CargoResult, { { let slot = &mut Rc::make_mut(&mut self.inner).dependencies; - *slot = mem::take(slot).into_iter().map(f).collect(); + *slot = mem::take(slot) + .into_iter() + .map(f) + .collect::>()?; } - self + Ok(self) } pub fn map_source(self, to_replace: SourceId, replace_with: SourceId) -> Summary { diff --git a/src/cargo/ops/cargo_clean.rs b/src/cargo/ops/cargo_clean.rs index 5969bf287eb..5297430b175 100644 --- a/src/cargo/ops/cargo_clean.rs +++ b/src/cargo/ops/cargo_clean.rs @@ -77,7 +77,14 @@ pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> { if opts.spec.is_empty() { clean_ctx.remove_paths(&[target_dir.into_path_unlocked()])?; } else { - clean_specs(&mut clean_ctx, &ws, &profiles, &opts.targets, &opts.spec)?; + clean_specs( + &mut clean_ctx, + &ws, + &profiles, + &opts.targets, + &opts.spec, + opts.dry_run, + )?; } } @@ -91,11 +98,12 @@ fn clean_specs( profiles: &Profiles, targets: &[String], spec: &[String], + dry_run: bool, ) -> CargoResult<()> { // Clean specific packages. let requested_kinds = CompileKind::from_requested_targets(clean_ctx.gctx, targets)?; let target_data = RustcTargetData::new(ws, &requested_kinds)?; - let (pkg_set, resolve) = ops::resolve_ws(ws)?; + let (pkg_set, resolve) = ops::resolve_ws(ws, dry_run)?; let prof_dir_name = profiles.get_dir_name(); let host_layout = Layout::new(ws, None, &prof_dir_name)?; // Convert requested kinds to a Vec of layouts. diff --git a/src/cargo/ops/cargo_compile/mod.rs b/src/cargo/ops/cargo_compile/mod.rs index 68f1df76ba6..0553e5e2d5d 100644 --- a/src/cargo/ops/cargo_compile/mod.rs +++ b/src/cargo/ops/cargo_compile/mod.rs @@ -264,6 +264,7 @@ pub fn create_bcx<'a, 'gctx>( HasDevUnits::No } }; + let dry_run = false; let resolve = ops::resolve_ws_with_opts( ws, &mut target_data, @@ -272,6 +273,7 @@ pub fn create_bcx<'a, 'gctx>( &specs, has_dev_units, crate::core::resolver::features::ForceAllTargets::No, + dry_run, )?; let WorkspaceResolve { mut pkg_set, diff --git a/src/cargo/ops/cargo_fetch.rs b/src/cargo/ops/cargo_fetch.rs index 761f171f1f6..37b56438cd6 100644 --- a/src/cargo/ops/cargo_fetch.rs +++ b/src/cargo/ops/cargo_fetch.rs @@ -19,7 +19,8 @@ pub fn fetch<'a>( options: &FetchOptions<'a>, ) -> CargoResult<(Resolve, PackageSet<'a>)> { ws.emit_warnings()?; - let (mut packages, resolve) = ops::resolve_ws(ws)?; + let dry_run = false; + let (mut packages, resolve) = ops::resolve_ws(ws, dry_run)?; let jobs = Some(JobsConfig::Integer(1)); let keep_going = false; diff --git a/src/cargo/ops/cargo_install.rs b/src/cargo/ops/cargo_install.rs index a662e891f38..e4304d74829 100644 --- a/src/cargo/ops/cargo_install.rs +++ b/src/cargo/ops/cargo_install.rs @@ -561,7 +561,8 @@ impl<'gctx> InstallablePackage<'gctx> { // It would be best if `source` could be passed in here to avoid a // duplicate "Updating", but since `source` is taken by value, then it // wouldn't be available for `compile_ws`. - let (pkg_set, resolve) = ops::resolve_ws(&self.ws)?; + let dry_run = false; + let (pkg_set, resolve) = ops::resolve_ws(&self.ws, dry_run)?; ops::check_yanked( self.ws.gctx(), &pkg_set, diff --git a/src/cargo/ops/cargo_output_metadata.rs b/src/cargo/ops/cargo_output_metadata.rs index 408be75faf3..1aadc05d77a 100644 --- a/src/cargo/ops/cargo_output_metadata.rs +++ b/src/cargo/ops/cargo_output_metadata.rs @@ -142,6 +142,7 @@ fn build_resolve_graph( // Note that even with --filter-platform we end up downloading host dependencies as well, // as that is the behavior of download_accessible. + let dry_run = false; let ws_resolve = ops::resolve_ws_with_opts( ws, &mut target_data, @@ -150,6 +151,7 @@ fn build_resolve_graph( &specs, HasDevUnits::Yes, force_all, + dry_run, )?; let package_map: BTreeMap = ws_resolve diff --git a/src/cargo/ops/cargo_package.rs b/src/cargo/ops/cargo_package.rs index 533852551c2..e105d7012d4 100644 --- a/src/cargo/ops/cargo_package.rs +++ b/src/cargo/ops/cargo_package.rs @@ -190,7 +190,8 @@ pub fn package(ws: &Workspace<'_>, opts: &PackageOpts<'_>) -> CargoResult