diff --git a/crates/cargo-test-support/src/compare.rs b/crates/cargo-test-support/src/compare.rs index 599772d4d1a..0118c5069cc 100644 --- a/crates/cargo-test-support/src/compare.rs +++ b/crates/cargo-test-support/src/compare.rs @@ -196,6 +196,7 @@ fn substitute_macros(input: &str) -> String { ("[OWNER]", " Owner"), ("[MIGRATING]", " Migrating"), ("[EXECUTABLE]", " Executable"), + ("[SKIPPING]", " Skipping"), ]; let mut result = input.to_owned(); for &(pat, subst) in ¯os { diff --git a/src/cargo/sources/git/utils.rs b/src/cargo/sources/git/utils.rs index 4eafae1c99c..f6c630d276d 100644 --- a/src/cargo/sources/git/utils.rs +++ b/src/cargo/sources/git/utils.rs @@ -370,6 +370,18 @@ impl<'a> GitCheckout<'a> { anyhow::format_err!("non-utf8 url for submodule {:?}?", child.path()) })?; + // Skip the submodule if the config says not to update it. + if child.update_strategy() == git2::SubmoduleUpdate::None { + cargo_config.shell().status( + "Skipping", + format!( + "git submodule `{}` due to update strategy in .gitmodules", + url + ), + )?; + return Ok(()); + } + // A submodule which is listed in .gitmodules but not actually // checked out will not have a head id, so we should ignore it. let head = match child.head_id() { diff --git a/tests/testsuite/git.rs b/tests/testsuite/git.rs index f94ec3a6a20..54dd8dcb05d 100644 --- a/tests/testsuite/git.rs +++ b/tests/testsuite/git.rs @@ -1023,6 +1023,60 @@ Caused by: .run(); } +#[cargo_test] +fn dep_with_skipped_submodule() { + // Ensure we skip dependency submodules if their update strategy is `none`. + let qux = git::new("qux", |project| { + project.no_manifest().file("README", "skip me") + }); + + let bar = git::new("bar", |project| { + project + .file("Cargo.toml", &basic_manifest("bar", "0.0.0")) + .file("src/lib.rs", "") + }); + + // `qux` is a submodule of `bar`, but we don't want to update it. + let repo = git2::Repository::open(&bar.root()).unwrap(); + git::add_submodule(&repo, qux.url().as_str(), Path::new("qux")); + + let mut conf = git2::Config::open(&bar.root().join(".gitmodules")).unwrap(); + conf.set_str("submodule.qux.update", "none").unwrap(); + + git::add(&repo); + git::commit(&repo); + + let foo = project() + .file( + "Cargo.toml", + &format!( + r#" + [project] + name = "foo" + version = "0.0.0" + authors = [] + + [dependencies.bar] + git = "{}" + "#, + bar.url() + ), + ) + .file("src/main.rs", "fn main() {}") + .build(); + + foo.cargo("build") + .with_stderr( + "\ +[UPDATING] git repository `file://[..]/bar` +[SKIPPING] git submodule `file://[..]/qux` [..] +[COMPILING] bar [..] +[COMPILING] foo [..] +[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]\n", + ) + .run(); +} + #[cargo_test] fn dep_ambiguous() { let project = project();