From: Alex Crichton Date: Tue, 19 Dec 2017 15:34:14 +0000 (-0800) Subject: Fix updating submodules past failures X-Git-Tag: archive/raspbian/0.35.0-2+rpi1~3^2^2^2^2^2^2^2~22^2~4^2~11^2 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=ddc74a5db4c72ba586e12b88b79474f1877b0c97;p=cargo.git Fix updating submodules past failures If a submodule-of-a-submodule failed to update then Cargo the next time around wouldn't automatically retry updating the next submodule. This commit fixes that by ensuring that if a parent git repository looks updated we still recurse into its own submodules to ensure they're all updated. cc #4071 --- diff --git a/src/cargo/sources/git/utils.rs b/src/cargo/sources/git/utils.rs index 4fac25bb2..f29bdb8fd 100644 --- a/src/cargo/sources/git/utils.rs +++ b/src/cargo/sources/git/utils.rs @@ -282,11 +282,10 @@ impl<'a> GitCheckout<'a> { for mut child in repo.submodules()? { update_submodule(repo, &mut child, cargo_config) - .map_err(Internal::new) .chain_err(|| { format!("failed to update submodule `{}`", child.name().unwrap_or("")) - })?; + })?; } Ok(()) } @@ -308,8 +307,8 @@ impl<'a> GitCheckout<'a> { // If the submodule hasn't been checked out yet, we need to // clone it. If it has been checked out and the head is the same - // as the submodule's head, then we can bail out and go to the - // next submodule. + // as the submodule's head, then we can skip an update and keep + // recursing. let head_and_repo = child.open().and_then(|repo| { let target = repo.head()?.target(); Ok((target, repo)) @@ -317,7 +316,7 @@ impl<'a> GitCheckout<'a> { let mut repo = match head_and_repo { Ok((head, repo)) => { if child.head_id() == head { - return Ok(()) + return update_submodules(&repo, cargo_config) } repo } diff --git a/tests/git.rs b/tests/git.rs index c76c67f16..38c72a78c 100644 --- a/tests/git.rs +++ b/tests/git.rs @@ -5,7 +5,9 @@ extern crate hamcrest; use std::fs::{self, File}; use std::io::prelude::*; +use std::net::TcpListener; use std::path::Path; +use std::thread; use cargo::util::process; use cargotest::sleep_ms; @@ -865,7 +867,9 @@ Caused by: Caused by: failed to update submodule `src` -To learn more, run the command again with --verbose.\n", path2url(git_project.root())); +Caused by: + object not found - no match for id [..] +", path2url(git_project.root())); assert_that(p.cargo("build"), execs().with_stderr(expected).with_status(101)); @@ -2174,3 +2178,75 @@ fn invalid_git_dependency_manifest() { path2url(git_root), ))); } + +#[test] +fn failed_submodule_checkout() { + let project = project("foo"); + let git_project = git::new("dep1", |project| { + project + .file("Cargo.toml", r#" + [package] + name = "dep1" + version = "0.5.0" + authors = [""] + "#) + }).unwrap(); + + let git_project2 = git::new("dep2", |project| { + project.file("lib.rs", "") + }).unwrap(); + + let listener = TcpListener::bind("127.0.0.1:0").unwrap(); + let addr = listener.local_addr().unwrap(); + + let t = thread::spawn(move || { + let a = listener.accept().unwrap(); + drop(a); + let a = listener.accept().unwrap(); + drop(a); + }); + + let repo = git2::Repository::open(&git_project2.root()).unwrap(); + let url = format!("http://{}:{}/", addr.ip(), addr.port()); + { + let mut s = repo.submodule(&url, Path::new("bar"), false).unwrap(); + let subrepo = s.open().unwrap(); + let mut cfg = subrepo.config().unwrap(); + cfg.set_str("user.email", "foo@bar.com").unwrap(); + cfg.set_str("user.name", "Foo Bar").unwrap(); + git::commit(&subrepo); + s.add_finalize().unwrap(); + } + git::commit(&repo); + drop((repo, url)); + + let repo = git2::Repository::open(&git_project.root()).unwrap(); + let url = path2url(git_project2.root()).to_string(); + git::add_submodule(&repo, &url, Path::new("src")); + git::commit(&repo); + drop(repo); + + let project = project + .file("Cargo.toml", &format!(r#" + [project] + name = "foo" + version = "0.5.0" + authors = [] + + [dependencies] + dep1 = {{ git = '{}' }} + "#, git_project.url())) + .file("src/lib.rs", "") + .build(); + + assert_that(project.cargo("build"), + execs().with_status(101) + .with_stderr_contains(" failed to update submodule `src`") + .with_stderr_contains(" failed to update submodule `bar`")); + assert_that(project.cargo("build"), + execs().with_status(101) + .with_stderr_contains(" failed to update submodule `src`") + .with_stderr_contains(" failed to update submodule `bar`")); + + t.join().unwrap(); +}