Allow fetching a single object, shallow or not.

Doing so seems cleaner as there should be no logical difference between
shallow or not-shallow when fetching. We want a specific object, and should
get it with the refspec. `git` will assure we see all objects we need,
handling shallow-ness for us.

Note that one test needed adjustments due to the different mechanism used
when fetching local repositories, requiring more changes to properly 'break'
the submodule repo when `gitoxide` is used.
This commit is contained in:
Sebastian Thiel 2023-04-29 10:14:26 +02:00
parent e20b020d60
commit d4b8fc68ab
No known key found for this signature in database
GPG key ID: 9CB5EE7895E8268B
2 changed files with 46 additions and 9 deletions

View file

@ -855,7 +855,6 @@ pub fn fetch(
// If we're fetching from GitHub, attempt GitHub's special fast path for
// testing if we've already got an up-to-date copy of the repository.
let is_shallow = !matches!(shallow, gix::remote::fetch::Shallow::NoChange);
let oid_to_fetch = match github_fast_path(repo, orig_url, reference, config) {
Ok(FastPathRev::UpToDate) => return Ok(()),
Ok(FastPathRev::NeedsFetch(rev)) => Some(rev),
@ -901,10 +900,10 @@ pub fn fetch(
refspecs.push(format!("+{0}:{0}", rev));
} else if let Some(oid_to_fetch) = oid_to_fetch {
refspecs.push(format!("+{0}:refs/commit/{0}", oid_to_fetch));
} else if is_shallow && rev.parse::<Oid>().is_ok() {
} else if rev.parse::<Oid>().is_ok() {
// There is a specific commit to fetch and we will just do so in shallow-mode only
// to not disturb the previous logic. Note that with typical settings for shallowing,
// With shallow histories this is a bit fuzzy, and we opt-out for now.
// we will just fetch a single `rev` as single commit.
refspecs.push(format!("+{0}:refs/remotes/origin/HEAD", rev));
} else {
// We don't know what the rev will point to. To handle this

View file

@ -948,6 +948,13 @@ fn dep_with_bad_submodule() {
None,
)
.unwrap();
std::fs::remove_file(
repo.path()
.join("objects")
.join(&commit.id().to_string()[..2])
.join(&commit.id().to_string()[2..]),
)
.unwrap();
let p = project
.file(
@ -972,9 +979,9 @@ fn dep_with_bad_submodule() {
"extern crate dep1; pub fn foo() { dep1::dep() }",
)
.build();
let expected = format!(
"\
let expected = if cargo_uses_gitoxide() {
format!(
"\
[UPDATING] git repository [..]
[UPDATING] git submodule `file://[..]/dep2`
[ERROR] failed to get `dep1` as a dependency of package `foo v0.5.0 [..]`
@ -989,10 +996,41 @@ Caused by:
failed to update submodule `src`
Caused by:
object not found - no match for id [..]
failed to fetch submodule `src` from [..]
Caused by:
Could not decode server reply
Caused by:
upload-pack: not our ref [..]
",
path2url(git_project.root())
);
path2url(git_project.root())
)
} else {
format!(
"\
[UPDATING] git repository [..]
[UPDATING] git submodule `file://[..]/dep2`
[ERROR] failed to get `dep1` as a dependency of package `foo v0.5.0 [..]`
Caused by:
failed to load source for dependency `dep1`
Caused by:
Unable to update {}
Caused by:
failed to update submodule `src`
Caused by:
failed to fetch submodule `src` from [..]
Caused by:
target OID for the reference doesn't exist on the repository; class=Reference (4)
",
path2url(git_project.root())
)
};
p.cargo("check")
.with_stderr(expected)