@@ -66,6 +66,7 @@ class RebuildContext:
6666 missing_packages : dict = field (default_factory = lambda : collections .defaultdict (set ))
6767 unresolvable_components : set = field (default_factory = set )
6868 prerel_abi_blocked_components : set = field (default_factory = set )
69+ component_availability : dict = field (default_factory = dict )
6970
7071
7172def _query_packages_by_deps (sack_getter , deps , excluded_components ):
@@ -489,28 +490,37 @@ def check_bcond_build(component, bcond_config, number_of_resolved, ctx):
489490def check_bcond_builds (component , number_of_resolved , ctx ):
490491 """
491492 Check all bcond builds for a component that isn't ready for regular build.
492-
493+
493494 Args:
494495 component: Name of the component to check
495496 number_of_resolved: Number of packages in regular build (for comparison)
496497 ctx: RebuildContext with shared data and state
497-
498+
498499 Prints any bcond build identifiers that are ready to rebuild.
500+
501+ Returns:
502+ tuple: (buildable_bconds, non_buildable_bconds)
499503 """
500504 from bconds import bcond_cache_identifier
501-
502- if component not in CONFIG ['bconds' ]:
503- return
504-
505- for bcond_config in CONFIG ['bconds' ][component ]:
506- bcond_config ['id' ] = bcond_cache_identifier (component , bcond_config )
507- log (f'• { component } not ready and { bcond_config ["id" ]} bcond found, will check that one' )
508-
509- ready_to_rebuild = check_bcond_build (component , bcond_config , number_of_resolved , ctx )
510-
511- if ready_to_rebuild :
512- if should_print_component (component , ctx .components_done ):
513- print (bcond_config ['id' ])
505+
506+ buildable_bconds = []
507+ non_buildable_bconds = []
508+
509+ if component in CONFIG ['bconds' ]:
510+ for bcond_config in CONFIG ['bconds' ][component ]:
511+ bcond_config ['id' ] = bcond_cache_identifier (component , bcond_config )
512+ log (f'• { component } not ready and { bcond_config ["id" ]} bcond found, will check that one' )
513+
514+ ready_to_rebuild = check_bcond_build (component , bcond_config , number_of_resolved , ctx )
515+
516+ if ready_to_rebuild :
517+ if should_print_component (component , ctx .components_done ):
518+ print (bcond_config ['id' ])
519+ buildable_bconds .append (bcond_config ['id' ])
520+ else :
521+ non_buildable_bconds .append (bcond_config ['id' ])
522+
523+ return sorted (buildable_bconds ), sorted (non_buildable_bconds )
514524
515525
516526def should_print_component (component , components_done ):
@@ -526,20 +536,30 @@ def should_print_component(component, components_done):
526536def process_component (component , ctx ):
527537 """
528538 Process a single component: check regular build and bcond builds if needed.
529-
539+ Stores availability data in ctx.component_availability.
540+
530541 Args:
531542 component: Name of the component to process
532543 ctx: RebuildContext with shared data and state
533-
544+
534545 Prints the component or bcond identifier if ready to rebuild.
535546 """
536547 ready_to_rebuild , number_of_resolved = check_regular_build (component , ctx )
537-
548+ availability = {
549+ 'can_build_regular' : ready_to_rebuild ,
550+ 'buildable_bconds' : [],
551+ 'non_buildable_bconds' : [],
552+ }
553+
538554 if ready_to_rebuild :
539555 if should_print_component (component , ctx .components_done ):
540556 print (component )
541557 else :
542- check_bcond_builds (component , number_of_resolved , ctx )
558+ buildable_bconds , non_buildable_bconds = check_bcond_builds (component , number_of_resolved , ctx )
559+ availability ['buildable_bconds' ] = buildable_bconds
560+ availability ['non_buildable_bconds' ] = non_buildable_bconds
561+
562+ ctx .component_availability [component ] = availability
543563
544564
545565def assemble_component_info (component , count , ctx ):
@@ -596,7 +616,6 @@ def generate_reports(ctx):
596616 log ('\n The 20 most commonly last-blocking small combinations of components are:' )
597617 for components_tuple , count in ctx .blocker_counter ['combinations' ].most_common (20 ):
598618 log (f'{ count :>5} { ", " .join (components_tuple )} ' )
599-
600619 report_data ['most_commonly_last_blocking_combinations' ].append ({
601620 'components' : list (components_tuple ),
602621 'count' : count
@@ -610,6 +629,35 @@ def generate_reports(ctx):
610629 log ('\n Report saved to commonly-needed-report.json' )
611630
612631
632+ def generate_component_availability_report (ctx ):
633+ """
634+ Generate and save full component availability report.
635+ Creates component-availability-report.json with per-component data.
636+
637+ Args:
638+ ctx: RebuildContext with component availability data
639+ """
640+
641+ report_data = {}
642+ for component in ctx .components :
643+ availability = ctx .component_availability .get (component , {})
644+
645+ report_data [component ] = {
646+ 'was_already_built' : component in ctx .components_done ,
647+ 'is_resolvable' : component not in ctx .unresolvable_components ,
648+ 'prerel_abi_compatible' : component not in ctx .prerel_abi_blocked_components ,
649+ 'can_build_regular' : availability .get ('can_build_regular' , False ),
650+ 'buildable_bconds' : availability .get ('buildable_bconds' ),
651+ 'non_buildable_bconds' : availability .get ('non_buildable_bconds' ),
652+ 'blocked_by' : sorted (ctx .loop_detector .get (component , [])),
653+ 'blocks_count' : ctx .blocker_counter ['general' ].get (component , 0 )
654+ }
655+
656+ with open ('component-availability-report.json' , 'w' ) as f :
657+ json .dump (report_data , f , indent = 2 , sort_keys = True )
658+ log ('Full component availability report saved to component-availability-report.json' )
659+
660+
613661def main ():
614662 """
615663 Main entry point for rebuild analysis.
@@ -638,8 +686,9 @@ def main():
638686
639687 for component in components_to_process :
640688 process_component (component , ctx )
641-
689+
642690 generate_reports (ctx )
691+ generate_component_availability_report (ctx )
643692
644693
645694if __name__ == '__main__' :
0 commit comments