Skip to content

Commit 36867ee

Browse files
Flowreyepage
authored andcommitted
feat: add --dry-run to install command
1 parent 1e525f4 commit 36867ee

File tree

11 files changed

+140
-76
lines changed

11 files changed

+140
-76
lines changed

src/bin/cargo/commands/install.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ pub fn cli() -> Command {
6969
)
7070
.arg(opt("root", "Directory to install packages into").value_name("DIR"))
7171
.arg(flag("force", "Force overwriting existing crates or binaries").short('f'))
72+
.arg_dry_run("Perform all checks without installing (unstable)")
7273
.arg(flag("no-track", "Do not save tracking information"))
7374
.arg(flag(
7475
"list",
@@ -200,7 +201,9 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {
200201

201202
compile_opts.build_config.requested_profile =
202203
args.get_profile_name("release", ProfileChecking::Custom)?;
203-
204+
if args.dry_run() {
205+
gctx.cli_unstable().fail_if_stable_opt("--dry-run", 11123)?;
206+
}
204207
if args.flag("list") {
205208
ops::install_list(root, gctx)?;
206209
} else {
@@ -213,6 +216,7 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {
213216
&compile_opts,
214217
args.flag("force"),
215218
args.flag("no-track"),
219+
args.dry_run(),
216220
)?;
217221
}
218222
Ok(())

src/cargo/core/compiler/build_config.rs

+3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ pub struct BuildConfig {
3131
pub build_plan: bool,
3232
/// Output the unit graph to stdout instead of actually compiling.
3333
pub unit_graph: bool,
34+
/// `true` to avoid really compiling.
35+
pub dry_run: bool,
3436
/// An optional override of the rustc process for primary units
3537
pub primary_unit_rustc: Option<ProcessBuilder>,
3638
/// A thread used by `cargo fix` to receive messages on a socket regarding
@@ -112,6 +114,7 @@ impl BuildConfig {
112114
force_rebuild: false,
113115
build_plan: false,
114116
unit_graph: false,
117+
dry_run: false,
115118
primary_unit_rustc: None,
116119
rustfix_diagnostic_server: Rc::new(RefCell::new(None)),
117120
export_dir: None,

src/cargo/core/compiler/build_runner/mod.rs

+17
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,23 @@ impl<'a, 'gctx> BuildRunner<'a, 'gctx> {
126126
})
127127
}
128128

129+
pub fn dry_run(mut self) -> CargoResult<Compilation<'gctx>> {
130+
let _lock = self
131+
.bcx
132+
.gctx
133+
.acquire_package_cache_lock(CacheLockMode::Shared)?;
134+
self.lto = super::lto::generate(self.bcx)?;
135+
self.prepare_units()?;
136+
self.prepare()?;
137+
self.check_collisions()?;
138+
139+
for unit in &self.bcx.roots {
140+
self.collect_tests_and_executables(unit)?;
141+
}
142+
143+
Ok(self.compilation)
144+
}
145+
129146
/// Starts compilation, waits for it to finish, and returns information
130147
/// about the result of compilation.
131148
///

src/cargo/ops/cargo_compile/mod.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,11 @@ pub fn compile_ws<'a>(
156156
}
157157
crate::core::gc::auto_gc(bcx.gctx);
158158
let build_runner = BuildRunner::new(&bcx)?;
159-
build_runner.compile(exec)
159+
if options.build_config.dry_run {
160+
build_runner.dry_run()
161+
} else {
162+
build_runner.compile(exec)
163+
}
160164
}
161165

162166
/// Executes `rustc --print <VALUE>`.

src/cargo/ops/cargo_install.rs

+36-19
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ impl<'gctx> InstallablePackage<'gctx> {
297297
Ok(duplicates)
298298
}
299299

300-
fn install_one(mut self) -> CargoResult<bool> {
300+
fn install_one(mut self, dry_run: bool) -> CargoResult<bool> {
301301
self.gctx.shell().status("Installing", &self.pkg)?;
302302

303303
let dst = self.root.join("bin").into_path_unlocked();
@@ -321,6 +321,7 @@ impl<'gctx> InstallablePackage<'gctx> {
321321
self.check_yanked_install()?;
322322

323323
let exec: Arc<dyn Executor> = Arc::new(DefaultExecutor);
324+
self.opts.build_config.dry_run = dry_run;
324325
let compile = ops::compile_ws(&self.ws, &self.opts, &exec).with_context(|| {
325326
if let Some(td) = td_opt.take() {
326327
// preserve the temporary directory, so the user can inspect it
@@ -422,7 +423,7 @@ impl<'gctx> InstallablePackage<'gctx> {
422423
for &(bin, src) in binaries.iter() {
423424
let dst = staging_dir.path().join(bin);
424425
// Try to move if `target_dir` is transient.
425-
if !self.source_id.is_path() && fs::rename(src, &dst).is_ok() {
426+
if (!self.source_id.is_path() && fs::rename(src, &dst).is_ok()) || dry_run {
426427
continue;
427428
}
428429
paths::copy(src, &dst)?;
@@ -441,11 +442,13 @@ impl<'gctx> InstallablePackage<'gctx> {
441442
let src = staging_dir.path().join(bin);
442443
let dst = dst.join(bin);
443444
self.gctx.shell().status("Installing", dst.display())?;
444-
fs::rename(&src, &dst).with_context(|| {
445-
format!("failed to move `{}` to `{}`", src.display(), dst.display())
446-
})?;
447-
installed.bins.push(dst);
448-
successful_bins.insert(bin.to_string());
445+
if !dry_run {
446+
fs::rename(&src, &dst).with_context(|| {
447+
format!("failed to move `{}` to `{}`", src.display(), dst.display())
448+
})?;
449+
installed.bins.push(dst);
450+
successful_bins.insert(bin.to_string());
451+
}
449452
}
450453

451454
// Repeat for binaries which replace existing ones but don't pop the error
@@ -456,10 +459,12 @@ impl<'gctx> InstallablePackage<'gctx> {
456459
let src = staging_dir.path().join(bin);
457460
let dst = dst.join(bin);
458461
self.gctx.shell().status("Replacing", dst.display())?;
459-
fs::rename(&src, &dst).with_context(|| {
460-
format!("failed to move `{}` to `{}`", src.display(), dst.display())
461-
})?;
462-
successful_bins.insert(bin.to_string());
462+
if !dry_run {
463+
fs::rename(&src, &dst).with_context(|| {
464+
format!("failed to move `{}` to `{}`", src.display(), dst.display())
465+
})?;
466+
successful_bins.insert(bin.to_string());
467+
}
463468
}
464469
Ok(())
465470
};
@@ -476,9 +481,14 @@ impl<'gctx> InstallablePackage<'gctx> {
476481
&self.rustc.verbose_version,
477482
);
478483

479-
if let Err(e) =
480-
remove_orphaned_bins(&self.ws, &mut tracker, &duplicates, &self.pkg, &dst)
481-
{
484+
if let Err(e) = remove_orphaned_bins(
485+
&self.ws,
486+
&mut tracker,
487+
&duplicates,
488+
&self.pkg,
489+
&dst,
490+
dry_run,
491+
) {
482492
// Don't hard error on remove.
483493
self.gctx
484494
.shell()
@@ -515,7 +525,10 @@ impl<'gctx> InstallablePackage<'gctx> {
515525
}
516526
}
517527

518-
if duplicates.is_empty() {
528+
if dry_run {
529+
self.gctx.shell().warn("aborting install due to dry run")?;
530+
Ok(true)
531+
} else if duplicates.is_empty() {
519532
self.gctx.shell().status(
520533
"Installed",
521534
format!(
@@ -620,6 +633,7 @@ pub fn install(
620633
opts: &ops::CompileOptions,
621634
force: bool,
622635
no_track: bool,
636+
dry_run: bool,
623637
) -> CargoResult<()> {
624638
let root = resolve_root(root, gctx)?;
625639
let dst = root.join("bin").into_path_unlocked();
@@ -654,7 +668,7 @@ pub fn install(
654668
)?;
655669
let mut installed_anything = true;
656670
if let Some(installable_pkg) = installable_pkg {
657-
installed_anything = installable_pkg.install_one()?;
671+
installed_anything = installable_pkg.install_one(dry_run)?;
658672
}
659673
(installed_anything, false)
660674
} else {
@@ -705,7 +719,7 @@ pub fn install(
705719

706720
let install_results: Vec<_> = pkgs_to_install
707721
.into_iter()
708-
.map(|(krate, installable_pkg)| (krate, installable_pkg.install_one()))
722+
.map(|(krate, installable_pkg)| (krate, installable_pkg.install_one(dry_run)))
709723
.collect();
710724

711725
for (krate, result) in install_results {
@@ -857,6 +871,7 @@ fn remove_orphaned_bins(
857871
duplicates: &BTreeMap<String, Option<PackageId>>,
858872
pkg: &Package,
859873
dst: &Path,
874+
dry_run: bool,
860875
) -> CargoResult<()> {
861876
let filter = ops::CompileFilter::new_all_targets();
862877
let all_self_names = exe_names(pkg, &filter);
@@ -894,8 +909,10 @@ fn remove_orphaned_bins(
894909
old_pkg
895910
),
896911
)?;
897-
paths::remove_file(&full_path)
898-
.with_context(|| format!("failed to remove {:?}", full_path))?;
912+
if !dry_run {
913+
paths::remove_file(&full_path)
914+
.with_context(|| format!("failed to remove {:?}", full_path))?;
915+
}
899916
}
900917
}
901918
}

src/doc/man/cargo-install.md

+4
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,10 @@ Filesystem path to local crate to install from.
121121
List all installed packages and their versions.
122122
{{/option}}
123123

124+
{{#option "`-n`" "`--dry-run`" }}
125+
(unstable) Perform all checks without installing.
126+
{{/option}}
127+
124128
{{#option "`-f`" "`--force`" }}
125129
Force overwriting existing crates or binaries. This can be used if a package
126130
has installed a binary with the same name as another package. This is also

src/doc/man/generated_txt/cargo-install.txt

+3
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,9 @@ OPTIONS
120120
--list
121121
List all installed packages and their versions.
122122

123+
-n, --dry-run
124+
(unstable) Perform all checks without installing.
125+
123126
-f, --force
124127
Force overwriting existing crates or binaries. This can be used if a
125128
package has installed a binary with the same name as another

src/doc/src/commands/cargo-install.md

+5
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,11 @@ treated as a caret requirement like Cargo dependencies are.</dd>
124124
<dd class="option-desc">List all installed packages and their versions.</dd>
125125

126126

127+
<dt class="option-term" id="option-cargo-install--n"><a class="option-anchor" href="#option-cargo-install--n"></a><code>-n</code></dt>
128+
<dt class="option-term" id="option-cargo-install---dry-run"><a class="option-anchor" href="#option-cargo-install---dry-run"></a><code>--dry-run</code></dt>
129+
<dd class="option-desc">(unstable) Perform all checks without installing.</dd>
130+
131+
127132
<dt class="option-term" id="option-cargo-install--f"><a class="option-anchor" href="#option-cargo-install--f"></a><code>-f</code></dt>
128133
<dt class="option-term" id="option-cargo-install---force"><a class="option-anchor" href="#option-cargo-install---force"></a><code>--force</code></dt>
129134
<dd class="option-desc">Force overwriting existing crates or binaries. This can be used if a package

src/etc/man/cargo-install.1

+6
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,12 @@ Filesystem path to local crate to install from.
151151
List all installed packages and their versions.
152152
.RE
153153
.sp
154+
\fB\-n\fR,
155+
\fB\-\-dry\-run\fR
156+
.RS 4
157+
(unstable) Perform all checks without installing.
158+
.RE
159+
.sp
154160
\fB\-f\fR,
155161
\fB\-\-force\fR
156162
.RS 4

0 commit comments

Comments
 (0)