Skip to content

Commit 3293d22

Browse files
committed
Auto merge of #14326 - Ifropc:5707-lock-path, r=weihanglo
Add `--lockfile-path` flag This change implements a new `--lockfile-path` proposed in #5707 . Functionality added: - Add `--lockfile-path <PATH>` to all commands that support `manifest-path` with exception of: - `locate-project` (doesn't use lock file) - `verify-project` (is deprecated) - `read-manifest` (doesn't use lock file) - Behind -Zunstable-options and docs - The flag's docs / `--help` has (unstable) in them - `<PATH>` must end with `Cargo.lock`. If specified path doesn't exist (or parent director(ies), create all the parent directories and the lockfile itself Implementation TLDR: add `requested_lockfile_path` into `Workspace` and set it on `workspace(gctx)` call (setting from the context) Update `lockfile.lock_root()` to respect `requested_lockfile_path` (if set) Add test cases covering all affected commands. Tested creating lockfile, reading lockfile, overriding default (`./Cargo.lock`) lockfile, symlink tests. Extra tests for package to make sure pinned versions from path's lockfile are respected (i.e. double check correct lockfile is used) I doubt this flag will be used for any command that's not read-only, but I tried to cover all the commands.
2 parents 9a170d7 + 04f9e2d commit 3293d22

File tree

134 files changed

+1650
-224
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

134 files changed

+1650
-224
lines changed

src/bin/cargo/commands/add.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ Example uses:
8787
- Depend on crates with the same name from different registries"),
8888
])
8989
.arg_manifest_path_without_unsupported_path_tip()
90+
.arg_lockfile_path()
9091
.arg_package("Package to modify")
9192
.arg_ignore_rust_version()
9293
.arg_dry_run("Don't actually write the manifest")

src/bin/cargo/commands/bench.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ pub fn cli() -> Command {
5050
.arg_unit_graph()
5151
.arg_timings()
5252
.arg_manifest_path()
53+
.arg_lockfile_path()
5354
.arg_ignore_rust_version()
5455
.after_help(color_print::cstr!(
5556
"Run `<cyan,bold>cargo help bench</>` for more detailed information.\n"

src/bin/cargo/commands/build.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ pub fn cli() -> Command {
3939
.arg_unit_graph()
4040
.arg_timings()
4141
.arg_manifest_path()
42+
.arg_lockfile_path()
4243
.arg_ignore_rust_version()
4344
.after_help(color_print::cstr!(
4445
"Run `<cyan,bold>cargo help build</>` for more detailed information.\n"

src/bin/cargo/commands/check.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ pub fn cli() -> Command {
3636
.arg_unit_graph()
3737
.arg_timings()
3838
.arg_manifest_path()
39+
.arg_lockfile_path()
3940
.arg_ignore_rust_version()
4041
.after_help(color_print::cstr!(
4142
"Run `<cyan,bold>cargo help check</>` for more detailed information.\n"

src/bin/cargo/commands/clean.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub fn cli() -> Command {
1919
.arg_target_triple("Target triple to clean output for")
2020
.arg_target_dir()
2121
.arg_manifest_path()
22+
.arg_lockfile_path()
2223
.arg_dry_run("Display what would be deleted without deleting anything")
2324
.args_conflicts_with_subcommands(true)
2425
.subcommand(

src/bin/cargo/commands/doc.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ pub fn cli() -> Command {
3939
.arg_unit_graph()
4040
.arg_timings()
4141
.arg_manifest_path()
42+
.arg_lockfile_path()
4243
.arg_ignore_rust_version()
4344
.after_help(color_print::cstr!(
4445
"Run `<cyan,bold>cargo help doc</>` for more detailed information.\n"

src/bin/cargo/commands/fetch.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ pub fn cli() -> Command {
99
.arg_silent_suggestion()
1010
.arg_target_triple("Fetch dependencies for the target triple")
1111
.arg_manifest_path()
12+
.arg_lockfile_path()
1213
.after_help(color_print::cstr!(
1314
"Run `<cyan,bold>cargo help fetch</>` for more detailed information.\n"
1415
))

src/bin/cargo/commands/fix.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::command_prelude::*;
2-
32
use cargo::core::Workspace;
3+
44
use cargo::ops;
55

66
pub fn cli() -> Command {
@@ -54,6 +54,7 @@ pub fn cli() -> Command {
5454
.arg_target_dir()
5555
.arg_timings()
5656
.arg_manifest_path()
57+
.arg_lockfile_path()
5758
.arg_ignore_rust_version()
5859
.after_help(color_print::cstr!(
5960
"Run `<cyan,bold>cargo help fix</>` for more detailed information.\n"
@@ -71,8 +72,13 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {
7172
// Unlike other commands default `cargo fix` to all targets to fix as much
7273
// code as we can.
7374
let root_manifest = args.root_manifest(gctx)?;
75+
76+
// Can't use workspace() to avoid using -Zavoid-dev-deps (if passed)
7477
let mut ws = Workspace::new(&root_manifest, gctx)?;
7578
ws.set_resolve_honors_rust_version(args.honor_rust_version());
79+
let lockfile_path = args.lockfile_path(gctx)?;
80+
ws.set_requested_lockfile_path(lockfile_path.clone());
81+
7682
let mut opts = args.compile_options(gctx, mode, Some(&ws), ProfileChecking::LegacyTestOnly)?;
7783

7884
if !opts.filter.is_specific() {
@@ -92,6 +98,7 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {
9298
allow_no_vcs: args.flag("allow-no-vcs"),
9399
allow_staged: args.flag("allow-staged"),
94100
broken_code: args.flag("broken-code"),
101+
requested_lockfile_path: lockfile_path,
95102
},
96103
)?;
97104
Ok(())

src/bin/cargo/commands/generate_lockfile.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ pub fn cli() -> Command {
77
.about("Generate the lockfile for a package")
88
.arg_silent_suggestion()
99
.arg_manifest_path()
10+
.arg_lockfile_path()
1011
.arg_ignore_rust_version_with_help(
1112
"Ignore `rust-version` specification in packages (unstable)",
1213
)

src/bin/cargo/commands/metadata.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
use crate::command_prelude::*;
21
use cargo::ops::{self, OutputMetadataOptions};
32

3+
use crate::command_prelude::*;
4+
45
pub fn cli() -> Command {
56
subcommand("metadata")
67
.about(
@@ -26,6 +27,7 @@ pub fn cli() -> Command {
2627
.arg_silent_suggestion()
2728
.arg_features()
2829
.arg_manifest_path()
30+
.arg_lockfile_path()
2931
.after_help(color_print::cstr!(
3032
"Run `<cyan,bold>cargo help metadata</>` for more detailed information.\n"
3133
))

src/bin/cargo/commands/package.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ pub fn cli() -> Command {
3737
.arg_target_dir()
3838
.arg_parallel()
3939
.arg_manifest_path()
40+
.arg_lockfile_path()
4041
.after_help(color_print::cstr!(
4142
"Run `<cyan,bold>cargo help package</>` for more detailed information.\n"
4243
))

src/bin/cargo/commands/pkgid.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ pub fn cli() -> Command {
1010
.arg_silent_suggestion()
1111
.arg_package("Argument to get the package ID specifier for")
1212
.arg_manifest_path()
13+
.arg_lockfile_path()
1314
.after_help(color_print::cstr!(
1415
"Run `<cyan,bold>cargo help pkgid</>` for more detailed information.\n"
1516
))

src/bin/cargo/commands/publish.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ pub fn cli() -> Command {
2424
.arg_target_triple("Build for the target triple")
2525
.arg_target_dir()
2626
.arg_manifest_path()
27+
.arg_lockfile_path()
2728
.after_help(color_print::cstr!(
2829
"Run `<cyan,bold>cargo help publish</>` for more detailed information.\n"
2930
))

src/bin/cargo/commands/remove.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ pub fn cli() -> clap::Command {
5151
])
5252
.arg_package("Package to remove from")
5353
.arg_manifest_path()
54+
.arg_lockfile_path()
5455
.after_help(color_print::cstr!(
5556
"Run `<cyan,bold>cargo help remove</>` for more detailed information.\n"
5657
))

src/bin/cargo/commands/run.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ pub fn cli() -> Command {
3838
.arg_target_triple("Build for the target triple")
3939
.arg_target_dir()
4040
.arg_manifest_path()
41+
.arg_lockfile_path()
4142
.arg_ignore_rust_version()
4243
.arg_unit_graph()
4344
.arg_timings()

src/bin/cargo/commands/rustc.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ pub fn cli() -> Command {
5252
.arg_unit_graph()
5353
.arg_timings()
5454
.arg_manifest_path()
55+
.arg_lockfile_path()
5556
.arg_ignore_rust_version()
5657
.after_help(color_print::cstr!(
5758
"Run `<cyan,bold>cargo help rustc</>` for more detailed information.\n"

src/bin/cargo/commands/rustdoc.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ pub fn cli() -> Command {
4545
.arg_unit_graph()
4646
.arg_timings()
4747
.arg_manifest_path()
48+
.arg_lockfile_path()
4849
.arg_ignore_rust_version()
4950
.after_help(color_print::cstr!(
5051
"Run `<cyan,bold>cargo help rustdoc</>` for more detailed information.\n"

src/bin/cargo/commands/test.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ pub fn cli() -> Command {
6060
.arg_unit_graph()
6161
.arg_timings()
6262
.arg_manifest_path()
63+
.arg_lockfile_path()
6364
.arg_ignore_rust_version()
6465
.after_help(color_print::cstr!(
6566
"Run `<cyan,bold>cargo help test</>` for more detailed information.\n\

src/bin/cargo/commands/tree.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ pub fn cli() -> Command {
9595
Pass `all` to include all targets.",
9696
)
9797
.arg_manifest_path()
98+
.arg_lockfile_path()
9899
.after_help(color_print::cstr!(
99100
"Run `<cyan,bold>cargo help tree</>` for more detailed information.\n"
100101
))

src/bin/cargo/commands/update.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ pub fn cli() -> Command {
4949
.help_heading(heading::PACKAGE_SELECTION),
5050
)
5151
.arg_manifest_path()
52+
.arg_lockfile_path()
5253
.arg_ignore_rust_version_with_help(
5354
"Ignore `rust-version` specification in packages (unstable)",
5455
)

src/bin/cargo/commands/vendor.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ pub fn cli() -> Command {
3737
.arg(unsupported("only-git-deps"))
3838
.arg(unsupported("disallow-duplicates"))
3939
.arg_manifest_path()
40+
.arg_lockfile_path()
4041
.after_help(color_print::cstr!(
4142
"Run `<cyan,bold>cargo help vendor</>` for more detailed information.\n"
4243
))

src/cargo/core/workspace.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ pub struct Workspace<'gctx> {
105105
/// file. This is set for `cargo install` without `--locked`.
106106
ignore_lock: bool,
107107

108+
/// Requested path of the lockfile (i.e. passed as the cli flag)
109+
requested_lockfile_path: Option<PathBuf>,
110+
108111
/// The resolver behavior specified with the `resolver` field.
109112
resolve_behavior: ResolveBehavior,
110113
/// If `true`, then workspace `rust_version` would be used in `cargo resolve`
@@ -242,6 +245,7 @@ impl<'gctx> Workspace<'gctx> {
242245
require_optional_deps: true,
243246
loaded_packages: RefCell::new(HashMap::new()),
244247
ignore_lock: false,
248+
requested_lockfile_path: None,
245249
resolve_behavior: ResolveBehavior::V1,
246250
resolve_honors_rust_version: false,
247251
custom_metadata: None,
@@ -633,6 +637,31 @@ impl<'gctx> Workspace<'gctx> {
633637
self
634638
}
635639

640+
/// Returns the directory where the lockfile is in.
641+
pub fn lock_root(&self) -> Filesystem {
642+
if let Some(requested) = self.requested_lockfile_path.as_ref() {
643+
return Filesystem::new(
644+
requested
645+
.parent()
646+
.expect("Lockfile path can't be root")
647+
.to_owned(),
648+
);
649+
}
650+
self.default_lock_root()
651+
}
652+
653+
fn default_lock_root(&self) -> Filesystem {
654+
if self.root_maybe().is_embedded() {
655+
self.target_dir()
656+
} else {
657+
Filesystem::new(self.root().to_owned())
658+
}
659+
}
660+
661+
pub fn set_requested_lockfile_path(&mut self, path: Option<PathBuf>) {
662+
self.requested_lockfile_path = path;
663+
}
664+
636665
/// Get the lowest-common denominator `package.rust-version` within the workspace, if specified
637666
/// anywhere
638667
pub fn rust_version(&self) -> Option<&RustVersion> {

src/cargo/ops/cargo_package.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@ use std::path::{Path, PathBuf};
66
use std::sync::Arc;
77
use std::task::Poll;
88

9+
use super::RegistryOrIndex;
910
use crate::core::compiler::{BuildConfig, CompileMode, DefaultExecutor, Executor};
1011
use crate::core::dependency::DepKind;
1112
use crate::core::manifest::Target;
1213
use crate::core::resolver::CliFeatures;
1314
use crate::core::resolver::HasDevUnits;
1415
use crate::core::{Feature, PackageIdSpecQuery, Shell, Verbosity, Workspace};
1516
use crate::core::{Package, PackageId, PackageSet, Resolve, SourceId};
17+
use crate::ops::lockfile::LOCKFILE_NAME;
1618
use crate::sources::registry::index::{IndexPackage, RegistryDependency};
1719
use crate::sources::{PathSource, SourceConfigMap, CRATES_IO_REGISTRY};
1820
use crate::util::cache_lock::CacheLockMode;
@@ -32,8 +34,6 @@ use tar::{Archive, Builder, EntryType, Header, HeaderMode};
3234
use tracing::debug;
3335
use unicase::Ascii as UncasedAscii;
3436

35-
use super::RegistryOrIndex;
36-
3737
#[derive(Clone)]
3838
pub struct PackageOpts<'gctx> {
3939
pub gctx: &'gctx GlobalContext,
@@ -280,7 +280,12 @@ pub fn package(ws: &Workspace<'_>, opts: &PackageOpts<'_>) -> CargoResult<Vec<Fi
280280
}
281281
let pkgs = ws.members_with_features(specs, &opts.cli_features)?;
282282

283-
if ws.root().join("Cargo.lock").exists() {
283+
if ws
284+
.lock_root()
285+
.as_path_unlocked()
286+
.join(LOCKFILE_NAME)
287+
.exists()
288+
{
284289
// Make sure the Cargo.lock is up-to-date and valid.
285290
let dry_run = false;
286291
let _ = ops::resolve_ws(ws, dry_run)?;

src/cargo/ops/fix.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ pub struct FixOptions {
9797
pub allow_no_vcs: bool,
9898
pub allow_staged: bool,
9999
pub broken_code: bool,
100+
pub requested_lockfile_path: Option<PathBuf>,
100101
}
101102

102103
pub fn fix(
@@ -121,6 +122,7 @@ pub fn fix(
121122
}
122123
let mut ws = Workspace::new(&root_manifest, gctx)?;
123124
ws.set_resolve_honors_rust_version(Some(original_ws.resolve_honors_rust_version()));
125+
ws.set_requested_lockfile_path(opts.requested_lockfile_path.clone());
124126

125127
// Spin up our lock server, which our subprocesses will use to synchronize fixes.
126128
let lock_server = LockServer::new()?;

src/cargo/ops/lockfile.rs

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,16 @@ use crate::util::Filesystem;
66

77
use anyhow::Context as _;
88

9+
pub const LOCKFILE_NAME: &str = "Cargo.lock";
10+
911
#[tracing::instrument(skip_all)]
1012
pub fn load_pkg_lockfile(ws: &Workspace<'_>) -> CargoResult<Option<Resolve>> {
11-
let lock_root = lock_root(ws);
12-
if !lock_root.as_path_unlocked().join("Cargo.lock").exists() {
13+
let lock_root = ws.lock_root();
14+
if !lock_root.as_path_unlocked().join(LOCKFILE_NAME).exists() {
1315
return Ok(None);
1416
}
1517

16-
let mut f = lock_root.open_ro_shared("Cargo.lock", ws.gctx(), "Cargo.lock file")?;
18+
let mut f = lock_root.open_ro_shared(LOCKFILE_NAME, ws.gctx(), "Cargo.lock file")?;
1719

1820
let mut s = String::new();
1921
f.read_to_string(&mut s)
@@ -58,7 +60,7 @@ pub fn write_pkg_lockfile(ws: &Workspace<'_>, resolve: &mut Resolve) -> CargoRes
5860
"the lock file {} needs to be updated but {} was passed to prevent this\n\
5961
If you want to try to generate the lock file without accessing the network, \
6062
remove the {} flag and use --offline instead.",
61-
lock_root.as_path_unlocked().join("Cargo.lock").display(),
63+
lock_root.as_path_unlocked().join(LOCKFILE_NAME).display(),
6264
flag,
6365
flag
6466
);
@@ -82,9 +84,13 @@ pub fn write_pkg_lockfile(ws: &Workspace<'_>, resolve: &mut Resolve) -> CargoRes
8284
anyhow::bail!("lock file version `{current_version:?}` requires `-Znext-lockfile-bump`")
8385
}
8486

87+
if !lock_root.as_path_unlocked().exists() {
88+
lock_root.create_dir()?;
89+
}
90+
8591
// Ok, if that didn't work just write it out
8692
lock_root
87-
.open_rw_exclusive_create("Cargo.lock", ws.gctx(), "Cargo.lock file")
93+
.open_rw_exclusive_create(LOCKFILE_NAME, ws.gctx(), "Cargo.lock file")
8894
.and_then(|mut f| {
8995
f.file().set_len(0)?;
9096
f.write_all(out.as_bytes())?;
@@ -93,7 +99,7 @@ pub fn write_pkg_lockfile(ws: &Workspace<'_>, resolve: &mut Resolve) -> CargoRes
9399
.with_context(|| {
94100
format!(
95101
"failed to write {}",
96-
lock_root.as_path_unlocked().join("Cargo.lock").display()
102+
lock_root.as_path_unlocked().join(LOCKFILE_NAME).display()
97103
)
98104
})?;
99105
Ok(true)
@@ -104,8 +110,8 @@ fn resolve_to_string_orig(
104110
resolve: &Resolve,
105111
) -> (Option<String>, String, Filesystem) {
106112
// Load the original lock file if it exists.
107-
let lock_root = lock_root(ws);
108-
let orig = lock_root.open_ro_shared("Cargo.lock", ws.gctx(), "Cargo.lock file");
113+
let lock_root = ws.lock_root();
114+
let orig = lock_root.open_ro_shared(LOCKFILE_NAME, ws.gctx(), "Cargo.lock file");
109115
let orig = orig.and_then(|mut f| {
110116
let mut s = String::new();
111117
f.read_to_string(&mut s)?;
@@ -245,11 +251,3 @@ fn emit_package(dep: &toml::Table, out: &mut String) {
245251
out.push_str(&format!("replace = {}\n\n", &dep["replace"]));
246252
}
247253
}
248-
249-
fn lock_root(ws: &Workspace<'_>) -> Filesystem {
250-
if ws.root_maybe().is_embedded() {
251-
ws.target_dir()
252-
} else {
253-
Filesystem::new(ws.root().to_owned())
254-
}
255-
}

0 commit comments

Comments
 (0)