Skip to content

Commit 4f8bb9f

Browse files
committed
feat: --lockfile-path add install support
1 parent d7e71a0 commit 4f8bb9f

File tree

6 files changed

+84
-35
lines changed

6 files changed

+84
-35
lines changed

src/bin/cargo/commands/install.rs

+9
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ pub fn cli() -> Command {
9797
.arg_target_triple("Build for the target triple")
9898
.arg_target_dir()
9999
.arg_timings()
100+
.arg_lockfile_path()
100101
.after_help(color_print::cstr!(
101102
"Run `<cyan,bold>cargo help install</>` for more detailed information.\n"
102103
))
@@ -201,6 +202,13 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {
201202
compile_opts.build_config.requested_profile =
202203
args.get_profile_name("release", ProfileChecking::Custom)?;
203204

205+
let requested_lockfile_path = args.lockfile_path(gctx)?;
206+
207+
// 14421: lockfile path should imply --locked on running `install`
208+
if requested_lockfile_path.is_some() {
209+
gctx.set_locked(true);
210+
}
211+
204212
if args.flag("list") {
205213
ops::install_list(root, gctx)?;
206214
} else {
@@ -213,6 +221,7 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {
213221
&compile_opts,
214222
args.flag("force"),
215223
args.flag("no-track"),
224+
requested_lockfile_path,
216225
)?;
217226
}
218227
Ok(())

src/cargo/core/workspace.rs

+4
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,10 @@ impl<'gctx> Workspace<'gctx> {
662662
self.requested_lockfile_path = path;
663663
}
664664

665+
pub fn get_requested_lockfile_path(&self) -> Option<&PathBuf> {
666+
self.requested_lockfile_path.as_ref()
667+
}
668+
665669
/// Get the lowest-common denominator `package.rust-version` within the workspace, if specified
666670
/// anywhere
667671
pub fn rust_version(&self) -> Option<&RustVersion> {

src/cargo/ops/cargo_install.rs

+27-5
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ struct InstallablePackage<'gctx> {
4646
vers: Option<VersionReq>,
4747
force: bool,
4848
no_track: bool,
49-
5049
pkg: Package,
5150
ws: Workspace<'gctx>,
5251
rustc: Rustc,
@@ -68,6 +67,7 @@ impl<'gctx> InstallablePackage<'gctx> {
6867
no_track: bool,
6968
needs_update_if_source_is_index: bool,
7069
current_rust_version: Option<&PartialVersion>,
70+
lockfile_path: Option<PathBuf>,
7171
) -> CargoResult<Option<Self>> {
7272
if let Some(name) = krate {
7373
if name == "." {
@@ -155,6 +155,7 @@ impl<'gctx> InstallablePackage<'gctx> {
155155
&root,
156156
&dst,
157157
force,
158+
lockfile_path.clone(),
158159
) {
159160
let msg = format!(
160161
"package `{}` is already installed, use --force to override",
@@ -179,8 +180,13 @@ impl<'gctx> InstallablePackage<'gctx> {
179180
}
180181
};
181182

182-
let (ws, rustc, target) =
183-
make_ws_rustc_target(gctx, &original_opts, &source_id, pkg.clone())?;
183+
let (ws, rustc, target) = make_ws_rustc_target(
184+
gctx,
185+
&original_opts,
186+
&source_id,
187+
pkg.clone(),
188+
lockfile_path.clone(),
189+
)?;
184190
// If we're installing in --locked mode and there's no `Cargo.lock` published
185191
// ie. the bin was published before https://github.com/rust-lang/cargo/pull/7026
186192
if gctx.locked() && !ws.root().join("Cargo.lock").exists() {
@@ -189,6 +195,13 @@ impl<'gctx> InstallablePackage<'gctx> {
189195
pkg.to_string()
190196
))?;
191197
}
198+
// When --lockfile-path is set, move lock file to the new location
199+
// (the new location is expected downstream and will be used during compilation)
200+
if gctx.locked() && ws.get_requested_lockfile_path().is_some() {
201+
let requested_lockfile_path = ws.get_requested_lockfile_path().unwrap();
202+
paths::create_dir_all(ws.lock_root().as_path_unlocked())?;
203+
fs::rename(ws.root().join("Cargo.lock"), requested_lockfile_path)?;
204+
}
192205
let pkg = if source_id.is_git() {
193206
// Don't use ws.current() in order to keep the package source as a git source so that
194207
// install tracking uses the correct source.
@@ -246,7 +259,6 @@ impl<'gctx> InstallablePackage<'gctx> {
246259
vers: vers.cloned(),
247260
force,
248261
no_track,
249-
250262
pkg,
251263
ws,
252264
rustc,
@@ -620,6 +632,7 @@ pub fn install(
620632
opts: &ops::CompileOptions,
621633
force: bool,
622634
no_track: bool,
635+
lockfile_path: Option<PathBuf>,
623636
) -> CargoResult<()> {
624637
let root = resolve_root(root, gctx)?;
625638
let dst = root.join("bin").into_path_unlocked();
@@ -651,6 +664,7 @@ pub fn install(
651664
no_track,
652665
true,
653666
current_rust_version.as_ref(),
667+
lockfile_path.clone(),
654668
)?;
655669
let mut installed_anything = true;
656670
if let Some(installable_pkg) = installable_pkg {
@@ -682,6 +696,7 @@ pub fn install(
682696
no_track,
683697
!did_update,
684698
current_rust_version.as_ref(),
699+
lockfile_path.clone(),
685700
) {
686701
Ok(Some(installable_pkg)) => {
687702
did_update = true;
@@ -788,6 +803,7 @@ fn installed_exact_package<T>(
788803
root: &Filesystem,
789804
dst: &Path,
790805
force: bool,
806+
lockfile_path: Option<PathBuf>,
791807
) -> CargoResult<Option<Package>>
792808
where
793809
T: Source,
@@ -803,7 +819,7 @@ where
803819
// best-effort check to see if we can avoid hitting the network.
804820
if let Ok(pkg) = select_dep_pkg(source, dep, gctx, false, None) {
805821
let (_ws, rustc, target) =
806-
make_ws_rustc_target(gctx, opts, &source.source_id(), pkg.clone())?;
822+
make_ws_rustc_target(gctx, opts, &source.source_id(), pkg.clone(), lockfile_path)?;
807823
if let Ok(true) = is_installed(&pkg, gctx, opts, &rustc, &target, root, dst, force) {
808824
return Ok(Some(pkg));
809825
}
@@ -816,6 +832,7 @@ fn make_ws_rustc_target<'gctx>(
816832
opts: &ops::CompileOptions,
817833
source_id: &SourceId,
818834
pkg: Package,
835+
lockfile_path: Option<PathBuf>,
819836
) -> CargoResult<(Workspace<'gctx>, Rustc, String)> {
820837
let mut ws = if source_id.is_git() || source_id.is_path() {
821838
Workspace::new(pkg.manifest_path(), gctx)?
@@ -825,6 +842,11 @@ fn make_ws_rustc_target<'gctx>(
825842
ws
826843
};
827844
ws.set_ignore_lock(gctx.lock_update_allowed());
845+
ws.set_requested_lockfile_path(lockfile_path);
846+
// if --lockfile-path is set, imply --locked
847+
if ws.get_requested_lockfile_path().is_some() {
848+
ws.set_ignore_lock(false);
849+
}
828850
ws.set_require_optional_deps(false);
829851

830852
let rustc = gctx.load_global_rustc(Some(&ws))?;

src/cargo/util/context/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1142,6 +1142,10 @@ impl GlobalContext {
11421142
self.locked
11431143
}
11441144

1145+
pub fn set_locked(&mut self, locked: bool) {
1146+
self.locked = locked;
1147+
}
1148+
11451149
pub fn lock_update_allowed(&self) -> bool {
11461150
!self.frozen && !self.locked
11471151
}

tests/testsuite/cargo_install/help/stdout.term.svg

+29-27
Loading

tests/testsuite/lockfile_path.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,8 @@ bar = "0.1.0"
402402
}
403403

404404
#[cargo_test]
405-
fn install_without_lockfile_path() {
405+
fn install_respects_lock_file_path() {
406+
// `cargo install` will imply --locked when lockfile path is provided
406407
Package::new("bar", "0.1.0").publish();
407408
Package::new("bar", "0.1.1")
408409
.file("src/lib.rs", "not rust")
@@ -440,10 +441,17 @@ dependencies = [
440441
"#]])
441442
.with_status(101)
442443
.run();
443-
cargo_process("install foo --locked").run();
444-
assert!(paths::root()
444+
445+
cargo_process("install foo -Zunstable-options --lockfile-path lockfile_dir/Cargo.lock")
446+
.masquerade_as_nightly_cargo(&["lockfile-path"])
447+
.run();
448+
449+
assert!(!paths::root()
445450
.join("home/.cargo/registry/src/-ec6bec4300fe98b6/foo-0.1.0/Cargo.lock")
446451
.is_file());
452+
assert!(paths::root()
453+
.join("lockfile_dir/Cargo.lock")
454+
.is_file());
447455
}
448456

449457
#[cargo_test]

0 commit comments

Comments
 (0)