Skip to content

Commit 02b8bf9

Browse files
committed
feat: recursive cache git submodules
fetch each submodules using git database then checkout
1 parent de673e8 commit 02b8bf9

2 files changed

Lines changed: 21 additions & 16 deletions

File tree

src/cargo/sources/git/utils.rs

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
//! Utilities for handling git repositories, mainly around
22
//! authentication/cloning.
33
4-
use crate::core::{GitReference, Verbosity};
4+
use crate::core::{GitReference, SourceId, Verbosity};
55
use crate::sources::git::fetch::RemoteKind;
66
use crate::sources::git::oxide;
77
use crate::sources::git::oxide::cargo_config_to_gitoxide_overrides;
8+
use crate::sources::git::source::GitSource;
9+
use crate::sources::source::Source as _;
810
use crate::util::HumanBytes;
911
use crate::util::errors::{CargoResult, GitCliError};
1012
use crate::util::{GlobalContext, IntoUrl, MetricsCounter, Progress, network};
@@ -447,7 +449,7 @@ impl<'a> GitCheckout<'a> {
447449
let target = repo.head()?.target();
448450
Ok((target, repo))
449451
});
450-
let mut repo = match head_and_repo {
452+
let repo = match head_and_repo {
451453
Ok((head, repo)) => {
452454
if child.head_id() == head {
453455
return update_submodules(&repo, gctx, &child_remote_url);
@@ -460,25 +462,25 @@ impl<'a> GitCheckout<'a> {
460462
init(&path, false)?
461463
}
462464
};
463-
// Fetch data from origin and reset to the head commit
465+
// Fetch submodule database and checkout to target revision
464466
let reference = GitReference::Rev(head.to_string());
465467
gctx.shell()
466468
.status("Updating", format!("git submodule `{child_remote_url}`"))?;
467-
fetch(
468-
&mut repo,
469-
&child_remote_url,
470-
&reference,
471-
gctx,
472-
RemoteKind::GitDependency,
473-
)
474-
.with_context(|| {
469+
470+
// GitSource created from SourceId without git precise will result to
471+
// locked_rev being Deferred and fetch_db always try to fetch if online
472+
let source_id = SourceId::for_git(&child_remote_url.into_url()?, reference)?
473+
.with_git_precise(Some(head.to_string()));
474+
475+
let mut source = GitSource::new(source_id, gctx)?;
476+
source.set_quiet(true);
477+
478+
let (db, actual_rev) = source.fetch_db().with_context(|| {
475479
let name = child.name().unwrap_or("");
476480
format!("failed to fetch submodule `{name}` from {child_remote_url}",)
477481
})?;
478-
479-
let obj = repo.find_object(head, None)?;
480-
reset(&repo, &obj, gctx)?;
481-
update_submodules(&repo, gctx, &child_remote_url)
482+
db.copy_to(actual_rev, repo.path(), gctx)?;
483+
Ok(())
482484
}
483485
}
484486
}

tests/testsuite/git.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1077,7 +1077,10 @@ Caused by:
10771077
failed to update submodule `src`
10781078
10791079
Caused by:
1080-
object not found - no match for id ([..]); class=Odb (9); code=NotFound (-3)
1080+
failed to fetch submodule `src` from [ROOTURL]/dep2
1081+
1082+
Caused by:
1083+
revspec '[..]' not found; class=Reference (4); code=NotFound (-3)
10811084
10821085
"#]];
10831086

0 commit comments

Comments
 (0)