Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 66 additions & 5 deletions crates/ostree-ext/src/chunking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -637,11 +637,6 @@ fn basic_packing_with_prior_build<'a>(
.collect();
let mut curr_build = curr_build?;

if (bin_size.get() as usize) < curr_build.len() {
tracing::debug!("bin_size = {bin_size} is too small to be compatible with the prior build");
return Ok(None);
}

// View the packages as unordered sets for lookups and differencing
let prev_pkgs_set: BTreeSet<String> = curr_build
.iter()
Expand Down Expand Up @@ -669,6 +664,21 @@ fn basic_packing_with_prior_build<'a>(
bin.retain(|pkg| !removed.contains(pkg));
}

// Exclusive-component bins are already carved out by process_mapping(), so
// keep only the bins that still carry regular components plus the reserved
// "new packages" bin at the end of the prior layout.
let last_idx = curr_build.len().saturating_sub(1);
curr_build = curr_build
.into_iter()
.enumerate()
.filter_map(|(idx, bin)| (!bin.is_empty() || idx == last_idx).then_some(bin))
.collect();

if (bin_size.get() as usize) < curr_build.len() {
tracing::debug!("bin_size = {bin_size} is too small to be compatible with the prior build");
return Ok(None);
}

// Handle updated packages
let mut name_to_component: BTreeMap<String, &ObjectSourceMetaSized> = BTreeMap::new();
for component in components.iter() {
Expand Down Expand Up @@ -1076,6 +1086,57 @@ mod test {
Ok(())
}

#[test]
fn test_advanced_packing_with_prior_exclusive_components() -> Result<()> {
let contentmeta: Vec<ObjectSourceMetaSized> = [
(1, 100, 50000),
(2, 200, 40000),
(3, 300, 30000),
(4, 400, 20000),
(5, 500, 10000),
(6, 600, 5000),
]
.iter()
.map(|&(id, freq, size)| ObjectSourceMetaSized {
meta: ObjectSourceMeta {
identifier: RcStr::from(format!("pkg{id}.0")),
name: RcStr::from(format!("pkg{id}")),
srcid: RcStr::from(format!("srcpkg{id}")),
change_time_offset: 0,
change_frequency: freq,
},
size,
})
.collect();

let regular_components = contentmeta[2..].to_vec();
let prior_structure = vec![
vec!["pkg1.0"],
vec!["pkg2.0"],
vec!["pkg3.0", "pkg4.0"],
vec!["pkg5.0", "pkg6.0"],
vec![],
];
let prior_build = create_manifest(prior_structure);

let packing = basic_packing_with_prior_build(
&regular_components,
NonZeroU32::new(3).unwrap(),
&prior_build,
)?
.expect("prior layout should remain reusable after exclusive bins are removed");
let structure: Vec<Vec<&str>> = packing
.iter()
.map(|bin| bin.iter().map(|pkg| &*pkg.meta.identifier).collect())
.collect();

assert_eq!(
structure,
vec![vec!["pkg3.0", "pkg4.0"], vec!["pkg5.0", "pkg6.0"], vec![],]
);
Ok(())
}

fn setup_exclusive_test(
component_data: &[(u32, u32, u64)],
max_layers: u32,
Expand Down