@@ -637,11 +637,6 @@ fn basic_packing_with_prior_build<'a>(
637637 . collect ( ) ;
638638 let mut curr_build = curr_build?;
639639
640- if ( bin_size. get ( ) as usize ) < curr_build. len ( ) {
641- tracing:: debug!( "bin_size = {bin_size} is too small to be compatible with the prior build" ) ;
642- return Ok ( None ) ;
643- }
644-
645640 // View the packages as unordered sets for lookups and differencing
646641 let prev_pkgs_set: BTreeSet < String > = curr_build
647642 . iter ( )
@@ -669,6 +664,21 @@ fn basic_packing_with_prior_build<'a>(
669664 bin. retain ( |pkg| !removed. contains ( pkg) ) ;
670665 }
671666
667+ // Exclusive-component bins are already carved out by process_mapping(), so
668+ // keep only the bins that still carry regular components plus the reserved
669+ // "new packages" bin at the end of the prior layout.
670+ let last_idx = curr_build. len ( ) . saturating_sub ( 1 ) ;
671+ curr_build = curr_build
672+ . into_iter ( )
673+ . enumerate ( )
674+ . filter_map ( |( idx, bin) | ( !bin. is_empty ( ) || idx == last_idx) . then_some ( bin) )
675+ . collect ( ) ;
676+
677+ if ( bin_size. get ( ) as usize ) < curr_build. len ( ) {
678+ tracing:: debug!( "bin_size = {bin_size} is too small to be compatible with the prior build" ) ;
679+ return Ok ( None ) ;
680+ }
681+
672682 // Handle updated packages
673683 let mut name_to_component: BTreeMap < String , & ObjectSourceMetaSized > = BTreeMap :: new ( ) ;
674684 for component in components. iter ( ) {
@@ -1076,6 +1086,57 @@ mod test {
10761086 Ok ( ( ) )
10771087 }
10781088
1089+ #[ test]
1090+ fn test_advanced_packing_with_prior_exclusive_components ( ) -> Result < ( ) > {
1091+ let contentmeta: Vec < ObjectSourceMetaSized > = [
1092+ ( 1 , 100 , 50000 ) ,
1093+ ( 2 , 200 , 40000 ) ,
1094+ ( 3 , 300 , 30000 ) ,
1095+ ( 4 , 400 , 20000 ) ,
1096+ ( 5 , 500 , 10000 ) ,
1097+ ( 6 , 600 , 5000 ) ,
1098+ ]
1099+ . iter ( )
1100+ . map ( |& ( id, freq, size) | ObjectSourceMetaSized {
1101+ meta : ObjectSourceMeta {
1102+ identifier : RcStr :: from ( format ! ( "pkg{id}.0" ) ) ,
1103+ name : RcStr :: from ( format ! ( "pkg{id}" ) ) ,
1104+ srcid : RcStr :: from ( format ! ( "srcpkg{id}" ) ) ,
1105+ change_time_offset : 0 ,
1106+ change_frequency : freq,
1107+ } ,
1108+ size,
1109+ } )
1110+ . collect ( ) ;
1111+
1112+ let regular_components = contentmeta[ 2 ..] . to_vec ( ) ;
1113+ let prior_structure = vec ! [
1114+ vec![ "pkg1.0" ] ,
1115+ vec![ "pkg2.0" ] ,
1116+ vec![ "pkg3.0" , "pkg4.0" ] ,
1117+ vec![ "pkg5.0" , "pkg6.0" ] ,
1118+ vec![ ] ,
1119+ ] ;
1120+ let prior_build = create_manifest ( prior_structure) ;
1121+
1122+ let packing = basic_packing_with_prior_build (
1123+ & regular_components,
1124+ NonZeroU32 :: new ( 3 ) . unwrap ( ) ,
1125+ & prior_build,
1126+ ) ?
1127+ . expect ( "prior layout should remain reusable after exclusive bins are removed" ) ;
1128+ let structure: Vec < Vec < & str > > = packing
1129+ . iter ( )
1130+ . map ( |bin| bin. iter ( ) . map ( |pkg| & * pkg. meta . identifier ) . collect ( ) )
1131+ . collect ( ) ;
1132+
1133+ assert_eq ! (
1134+ structure,
1135+ vec![ vec![ "pkg3.0" , "pkg4.0" ] , vec![ "pkg5.0" , "pkg6.0" ] , vec![ ] , ]
1136+ ) ;
1137+ Ok ( ( ) )
1138+ }
1139+
10791140 fn setup_exclusive_test (
10801141 component_data : & [ ( u32 , u32 , u64 ) ] ,
10811142 max_layers : u32 ,
0 commit comments