Skip to content

Commit 167f49f

Browse files
committed
reproduce issue with 'too many packs' for slotmap
1 parent af8f201 commit 167f49f

File tree

2 files changed

+70
-0
lines changed

2 files changed

+70
-0
lines changed

gix/src/commit.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
//!
22
#![allow(clippy::empty_docs)]
33

4+
use std::convert::Infallible;
5+
46
/// An empty array of a type usable with the `gix::easy` API to help declaring no parents should be used
57
pub const NO_PARENT_IDS: [gix_hash::ObjectId; 0] = [];
68

@@ -22,6 +24,12 @@ pub enum Error {
2224
ReferenceEdit(#[from] crate::reference::edit::Error),
2325
}
2426

27+
impl From<std::convert::Infallible> for Error {
28+
fn from(_value: Infallible) -> Self {
29+
unreachable!("cannot be invoked")
30+
}
31+
}
32+
2533
///
2634
#[cfg(feature = "revision")]
2735
pub mod describe {

gix/tests/gix/remote/fetch.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,15 @@ mod shallow {
1414
mod blocking_and_async_io {
1515
use std::sync::atomic::AtomicBool;
1616

17+
use gix::interrupt::IS_INTERRUPTED;
1718
use gix::{
1819
config::tree::Protocol,
1920
remote::{fetch, fetch::Status, Direction::Fetch},
2021
};
2122
use gix_features::progress;
23+
use gix_odb::store::init::Slots;
2224
use gix_protocol::maybe_async;
25+
use gix_testtools::tempfile;
2326
use gix_testtools::tempfile::TempDir;
2427

2528
use crate::{
@@ -85,6 +88,65 @@ mod blocking_and_async_io {
8588
try_repo_rw(name).unwrap()
8689
}
8790

91+
#[test]
92+
fn fetch_more_packs_than_can_be_handled() -> gix_testtools::Result {
93+
fn create_empty_commit(repo: &gix::Repository) -> anyhow::Result<()> {
94+
let name = repo.head_name()?.expect("no detached head");
95+
repo.commit(
96+
name.as_bstr(),
97+
"empty",
98+
gix::hash::ObjectId::empty_tree(repo.object_hash()),
99+
repo.try_find_reference(name.as_ref())?.map(|r| r.id()),
100+
)?;
101+
Ok(())
102+
}
103+
let remote_dir = tempfile::tempdir()?;
104+
let remote_repo = gix::init_bare(remote_dir.path())?;
105+
create_empty_commit(&remote_repo)?;
106+
107+
for max_packs in 1..=2 {
108+
let local_dir = tempfile::tempdir()?;
109+
let (local_repo, _) = gix::clone::PrepareFetch::new(
110+
remote_repo.path(),
111+
local_dir.path(),
112+
gix::create::Kind::Bare,
113+
Default::default(),
114+
gix::open::Options::isolated().object_store_slots(Slots::Given(max_packs)),
115+
)?
116+
.fetch_only(gix::progress::Discard, &IS_INTERRUPTED)?;
117+
118+
let remote = local_repo
119+
.branch_remote(
120+
local_repo.head_ref()?.expect("branch available").name().shorten(),
121+
Fetch,
122+
)
123+
.expect("remote is configured after clone")?;
124+
for round in 1.. {
125+
eprintln!("Fetch number {round}…");
126+
create_empty_commit(&remote_repo)?;
127+
match remote
128+
.connect(Fetch)?
129+
.prepare_fetch(gix::progress::Discard, Default::default())?
130+
.receive(gix::progress::Discard, &IS_INTERRUPTED)
131+
{
132+
Ok(out) => {
133+
for local_tracking_branch_name in out.ref_map.mappings.into_iter().filter_map(|m| m.local) {
134+
let r = local_repo.find_reference(&local_tracking_branch_name)?;
135+
r.id()
136+
.object()
137+
.expect("object should be present after fetching, triggering pack refreshes works");
138+
}
139+
}
140+
Err(err) => assert_eq!(
141+
err.to_string(),
142+
"It should indicate that the ODB is exhausted for now - we can't grow"
143+
),
144+
}
145+
}
146+
}
147+
Ok(())
148+
}
149+
88150
#[test]
89151
#[cfg(feature = "blocking-network-client")]
90152
#[allow(clippy::result_large_err)]

0 commit comments

Comments
 (0)