From 284b380e082c77afc38ec105d1831436986d433f Mon Sep 17 00:00:00 2001 From: Ifropc Date: Thu, 19 Sep 2024 18:27:52 -0700 Subject: [PATCH 1/2] test: install without lockfile-path - Showcase that install will require --locked and will put lockfile in a specific directory --- tests/testsuite/lockfile_path.rs | 48 +++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/tests/testsuite/lockfile_path.rs b/tests/testsuite/lockfile_path.rs index f7f513859e6..5d3a03b95da 100644 --- a/tests/testsuite/lockfile_path.rs +++ b/tests/testsuite/lockfile_path.rs @@ -7,7 +7,8 @@ use snapbox::str; use cargo_test_support::compare::assert_e2e; use cargo_test_support::registry::{Package, RegistryBuilder}; use cargo_test_support::{ - basic_bin_manifest, cargo_test, project, symlink_supported, ProjectBuilder, + basic_bin_manifest, cargo_process, cargo_test, paths, project, symlink_supported, + ProjectBuilder, }; /////////////////////////////// @@ -400,6 +401,51 @@ bar = "0.1.0" assert_e2e().eq(contents, lockfile_original); } +#[cargo_test] +fn install_without_lockfile_path() { + Package::new("bar", "0.1.0").publish(); + Package::new("bar", "0.1.1") + .file("src/lib.rs", "not rust") + .publish(); + Package::new("foo", "0.1.0") + .dep("bar", "0.1") + .file("src/lib.rs", "") + .file( + "src/main.rs", + "extern crate foo; extern crate bar; fn main() {}", + ) + .file( + "Cargo.lock", + r#" +[[package]] +name = "bar" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "foo" +version = "0.1.0" +dependencies = [ + "bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] +"#, + ) + .publish(); + + cargo_process("install foo") + .with_stderr_data(str![[r#" +... +[..]not rust[..] +... +"#]]) + .with_status(101) + .run(); + cargo_process("install foo --locked").run(); + assert!(paths::root() + .join("home/.cargo/registry/src/-ec6bec4300fe98b6/foo-0.1.0/Cargo.lock") + .is_file()); +} + #[cargo_test] fn run_embed() { let lockfile_path = "mylockfile/Cargo.lock"; From bf37cf7f325d35665bac4b7216871c297f0b3d3e Mon Sep 17 00:00:00 2001 From: Ifropc Date: Thu, 26 Sep 2024 01:19:40 -0400 Subject: [PATCH 2/2] feat: --lockfile-path add install support --- src/bin/cargo/commands/install.rs | 9 +++ src/cargo/core/workspace.rs | 4 ++ src/cargo/ops/cargo_install.rs | 51 +++++++++++---- src/cargo/util/context/mod.rs | 4 ++ .../cargo_install/help/stdout.term.svg | 56 ++++++++-------- tests/testsuite/lockfile_path.rs | 64 ++++++++++++++++--- 6 files changed, 141 insertions(+), 47 deletions(-) diff --git a/src/bin/cargo/commands/install.rs b/src/bin/cargo/commands/install.rs index dabdc79c353..2b0a77feac9 100644 --- a/src/bin/cargo/commands/install.rs +++ b/src/bin/cargo/commands/install.rs @@ -98,6 +98,7 @@ pub fn cli() -> Command { .arg_target_triple("Build for the target triple") .arg_target_dir() .arg_timings() + .arg_lockfile_path() .after_help(color_print::cstr!( "Run `cargo help install` for more detailed information.\n" )) @@ -204,6 +205,13 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { if args.dry_run() { gctx.cli_unstable().fail_if_stable_opt("--dry-run", 11123)?; } + + let requested_lockfile_path = args.lockfile_path(gctx)?; + // 14421: lockfile path should imply --locked on running `install` + if requested_lockfile_path.is_some() { + gctx.set_locked(true); + } + if args.flag("list") { ops::install_list(root, gctx)?; } else { @@ -217,6 +225,7 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { args.flag("force"), args.flag("no-track"), args.dry_run(), + requested_lockfile_path.as_deref(), )?; } Ok(()) diff --git a/src/cargo/core/workspace.rs b/src/cargo/core/workspace.rs index 28897365b89..086ca2e8c32 100644 --- a/src/cargo/core/workspace.rs +++ b/src/cargo/core/workspace.rs @@ -662,6 +662,10 @@ impl<'gctx> Workspace<'gctx> { self.requested_lockfile_path = path; } + pub fn requested_lockfile_path(&self) -> Option<&Path> { + self.requested_lockfile_path.as_deref() + } + /// Get the lowest-common denominator `package.rust-version` within the workspace, if specified /// anywhere pub fn rust_version(&self) -> Option<&RustVersion> { diff --git a/src/cargo/ops/cargo_install.rs b/src/cargo/ops/cargo_install.rs index 2c20d29c23d..74583deebcb 100644 --- a/src/cargo/ops/cargo_install.rs +++ b/src/cargo/ops/cargo_install.rs @@ -46,7 +46,6 @@ struct InstallablePackage<'gctx> { vers: Option, force: bool, no_track: bool, - pkg: Package, ws: Workspace<'gctx>, rustc: Rustc, @@ -68,6 +67,7 @@ impl<'gctx> InstallablePackage<'gctx> { no_track: bool, needs_update_if_source_is_index: bool, current_rust_version: Option<&PartialVersion>, + lockfile_path: Option<&Path>, ) -> CargoResult> { if let Some(name) = krate { if name == "." { @@ -155,6 +155,7 @@ impl<'gctx> InstallablePackage<'gctx> { &root, &dst, force, + lockfile_path, ) { let msg = format!( "package `{}` is already installed, use --force to override", @@ -179,15 +180,32 @@ impl<'gctx> InstallablePackage<'gctx> { } }; - let (ws, rustc, target) = - make_ws_rustc_target(gctx, &original_opts, &source_id, pkg.clone())?; - // If we're installing in --locked mode and there's no `Cargo.lock` published - // ie. the bin was published before https://github.com/rust-lang/cargo/pull/7026 - if gctx.locked() && !ws.root().join("Cargo.lock").exists() { - gctx.shell().warn(format!( - "no Cargo.lock file published in {}", - pkg.to_string() - ))?; + let (ws, rustc, target) = make_ws_rustc_target( + gctx, + &original_opts, + &source_id, + pkg.clone(), + lockfile_path.clone(), + )?; + + if gctx.locked() { + // When --lockfile-path is set, check that passed lock file exists + // (unlike the usual flag behavior, lockfile won't be created as we imply --locked) + if let Some(requested_lockfile_path) = ws.requested_lockfile_path() { + if !requested_lockfile_path.is_file() { + bail!( + "no Cargo.lock file found in the requested path {}", + requested_lockfile_path.display() + ); + } + // If we're installing in --locked mode and there's no `Cargo.lock` published + // ie. the bin was published before https://github.com/rust-lang/cargo/pull/7026 + } else if !ws.root().join("Cargo.lock").exists() { + gctx.shell().warn(format!( + "no Cargo.lock file published in {}", + pkg.to_string() + ))?; + } } let pkg = if source_id.is_git() { // Don't use ws.current() in order to keep the package source as a git source so that @@ -246,7 +264,6 @@ impl<'gctx> InstallablePackage<'gctx> { vers: vers.cloned(), force, no_track, - pkg, ws, rustc, @@ -636,6 +653,7 @@ pub fn install( force: bool, no_track: bool, dry_run: bool, + lockfile_path: Option<&Path>, ) -> CargoResult<()> { let root = resolve_root(root, gctx)?; let dst = root.join("bin").into_path_unlocked(); @@ -667,6 +685,7 @@ pub fn install( no_track, true, current_rust_version.as_ref(), + lockfile_path, )?; let mut installed_anything = true; if let Some(installable_pkg) = installable_pkg { @@ -698,6 +717,7 @@ pub fn install( no_track, !did_update, current_rust_version.as_ref(), + lockfile_path, ) { Ok(Some(installable_pkg)) => { did_update = true; @@ -804,6 +824,7 @@ fn installed_exact_package( root: &Filesystem, dst: &Path, force: bool, + lockfile_path: Option<&Path>, ) -> CargoResult> where T: Source, @@ -819,7 +840,7 @@ where // best-effort check to see if we can avoid hitting the network. if let Ok(pkg) = select_dep_pkg(source, dep, gctx, false, None) { let (_ws, rustc, target) = - make_ws_rustc_target(gctx, opts, &source.source_id(), pkg.clone())?; + make_ws_rustc_target(gctx, opts, &source.source_id(), pkg.clone(), lockfile_path)?; if let Ok(true) = is_installed(&pkg, gctx, opts, &rustc, &target, root, dst, force) { return Ok(Some(pkg)); } @@ -832,6 +853,7 @@ fn make_ws_rustc_target<'gctx>( opts: &ops::CompileOptions, source_id: &SourceId, pkg: Package, + lockfile_path: Option<&Path>, ) -> CargoResult<(Workspace<'gctx>, Rustc, String)> { let mut ws = if source_id.is_git() || source_id.is_path() { Workspace::new(pkg.manifest_path(), gctx)? @@ -841,6 +863,11 @@ fn make_ws_rustc_target<'gctx>( ws }; ws.set_ignore_lock(gctx.lock_update_allowed()); + ws.set_requested_lockfile_path(lockfile_path.map(|p| p.to_path_buf())); + // if --lockfile-path is set, imply --locked + if ws.requested_lockfile_path().is_some() { + ws.set_ignore_lock(false); + } ws.set_require_optional_deps(false); let rustc = gctx.load_global_rustc(Some(&ws))?; diff --git a/src/cargo/util/context/mod.rs b/src/cargo/util/context/mod.rs index 1db5b9a3c98..f243f71bef1 100644 --- a/src/cargo/util/context/mod.rs +++ b/src/cargo/util/context/mod.rs @@ -1142,6 +1142,10 @@ impl GlobalContext { self.locked } + pub fn set_locked(&mut self, locked: bool) { + self.locked = locked; + } + pub fn lock_update_allowed(&self) -> bool { !self.frozen && !self.locked } diff --git a/tests/testsuite/cargo_install/help/stdout.term.svg b/tests/testsuite/cargo_install/help/stdout.term.svg index 38ef23809e7..23375b98513 100644 --- a/tests/testsuite/cargo_install/help/stdout.term.svg +++ b/tests/testsuite/cargo_install/help/stdout.term.svg @@ -1,4 +1,4 @@ - +