@@ -546,13 +546,133 @@ for file in "${SYNC_FILES[@]}"; do
546546 sync_file " $file " " $TEMP_BRANCH "
547547done
548548
549+ # Self-heal libs.versions.toml — pull missing build-logic aliases from upstream.
550+ # `build-logic/` is sync'd but `gradle/libs.versions.toml` is consumer-local (it
551+ # carries project-specific package names + version overrides). When upstream adds
552+ # new `libs.<X>` accessors in build-logic with their matching catalog entries,
553+ # only the build-logic gets sync'd — the consumer's catalog falls behind and the
554+ # synced build-logic references aliases that don't exist locally. This function
555+ # detects that gap and pulls the missing alias entries (and their referenced
556+ # version keys) directly from the upstream catalog (`$TEMP_BRANCH`).
557+ heal_libs_versions_toml () {
558+ local libs_toml=" gradle/libs.versions.toml"
559+
560+ if [ ! -f " $libs_toml " ]; then
561+ return 0
562+ fi
563+ if [ ! -d " build-logic" ]; then
564+ return 0
565+ fi
566+
567+ echo -e " \n${BLUE}${BOLD} Healing libs.versions.toml...${NC} "
568+ echo -e " ${BLUE} ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC} \n"
569+
570+ local raw_refs
571+ raw_refs=$( grep -rhoE ' \blibs\.[a-zA-Z][a-zA-Z0-9._]*' \
572+ --include=' *.kt' --include=' *.kts' \
573+ build-logic 2> /dev/null \
574+ | sed -E ' s/^libs\.//' \
575+ | sort -u)
576+
577+ # Method-call accessors are not alias references — they take string args.
578+ local method_re=' ^(findLibrary|findVersion|findBundle|findPlugin)([(.]|$)'
579+
580+ # Cache upstream's catalog content once.
581+ local upstream_toml
582+ upstream_toml=$( git show " ${TEMP_BRANCH} :${libs_toml} " 2> /dev/null || true)
583+ if [ -z " $upstream_toml " ]; then
584+ print_warning " Upstream has no ${libs_toml} — skipping heal."
585+ return 0
586+ fi
587+
588+ # Helper: insert a line right after [section] in the consumer's catalog.
589+ insert_into_section () {
590+ local section_name=" $1 "
591+ local line=" $2 "
592+ local line_no
593+ line_no=$( grep -n " ^\[${section_name} \]" " $libs_toml " | head -1 | cut -d: -f1)
594+ if [ -z " $line_no " ]; then
595+ print_warning " No [${section_name} ] section header — skipping insert of '$line '"
596+ return 1
597+ fi
598+ { head -n " $line_no " " $libs_toml " ; echo " $line " ; tail -n +$(( line_no + 1 )) " $libs_toml " ; } > " ${libs_toml} .tmp"
599+ mv " ${libs_toml} .tmp" " $libs_toml "
600+ }
601+
602+ local healed=0
603+ local warnings=0
604+ while IFS= read -r ref; do
605+ [ -z " $ref " ] && continue
606+ [[ " $ref " =~ $method_re ]] && continue
607+
608+ local section=" libraries"
609+ local lookup=" $ref "
610+ case " $ref " in
611+ plugins.* )
612+ section=" plugins"
613+ lookup=" ${ref# plugins.} "
614+ ;;
615+ versions.* )
616+ section=" versions"
617+ lookup=" ${ref# versions.} "
618+ [ " $lookup " = " toml" ] && continue
619+ ;;
620+ esac
621+ local key
622+ key=$( echo " $lookup " | sed ' s/\./-/g' )
623+
624+ if grep -qE " ^${key} [[:space:]]*=" " $libs_toml " ; then
625+ continue
626+ fi
627+
628+ local upstream_line
629+ upstream_line=$( echo " $upstream_toml " | grep -E " ^${key} [[:space:]]*=" | head -1)
630+ if [ -z " $upstream_line " ]; then
631+ print_warning " Missing alias '$key ' (for libs.$ref ) not present in upstream catalog either — manual fix needed."
632+ warnings=$(( warnings + 1 ))
633+ continue
634+ fi
635+
636+ # Pull the version key too, if the alias version.refs something missing.
637+ local ref_version
638+ ref_version=$( echo " $upstream_line " | grep -oE ' version\.ref = "[^"]+"' | sed -E ' s/version\.ref = "([^"]+)"/\1/' | head -1)
639+ if [ -n " $ref_version " ] && ! grep -qE " ^${ref_version} [[:space:]]*=" " $libs_toml " ; then
640+ local ver_line
641+ ver_line=$( echo " $upstream_toml " | grep -E " ^${ref_version} [[:space:]]*=" | head -1)
642+ if [ -n " $ver_line " ]; then
643+ if insert_into_section " versions" " $ver_line " ; then
644+ echo -e " ${GREEN}${CHECKMARK}${NC} Added version '${ref_version} ' (referenced by '${key} ') to [versions]"
645+ healed=$(( healed + 1 ))
646+ fi
647+ fi
648+ fi
649+
650+ if insert_into_section " $section " " $upstream_line " ; then
651+ echo -e " ${GREEN}${CHECKMARK}${NC} Added '${key} ' to [${section} ] from upstream"
652+ healed=$(( healed + 1 ))
653+ fi
654+ done <<< " $raw_refs"
655+
656+ if [ $healed -gt 0 ]; then
657+ echo -e " \n${GREEN}${BOLD} 🩹 Healed ${healed} entries in ${libs_toml} — they will be included in the sync.${NC} "
658+ elif [ $warnings -gt 0 ]; then
659+ print_warning " ${warnings} missing aliases could not be auto-healed (not in upstream either). Manual fix needed."
660+ else
661+ echo -e " ${GREEN}${CHECKMARK}${NC} libs.versions.toml already in sync with build-logic — no heal needed."
662+ fi
663+ }
664+
549665if [ " $DRY_RUN " = false ]; then
550666 # Restore root-level excluded files
551667 restore_root_files
552668
553669 cleanup_temp_dirs
554670 rm -rf temp_files
555671
672+ # Self-heal the version catalog BEFORE we drop the temp branch (we need it
673+ # to access upstream's libs.versions.toml).
674+ heal_libs_versions_toml
675+
556676 # Cleanup temporary branch
557677 print_step " Cleaning up temporary branch..."
558678 git branch -D " $TEMP_BRANCH " || handle_error " Failed to delete temporary branch"
@@ -562,11 +682,16 @@ if [ "$DRY_RUN" = false ]; then
562682 if ! git diff --quiet --exit-code --cached; then
563683 print_step " Committing changes..."
564684 git add " ${SYNC_DIRS[@]} " " ${SYNC_FILES[@]} "
685+ # Include any catalog heal additions made by heal_libs_versions_toml.
686+ if [ -f " gradle/libs.versions.toml" ]; then
687+ git add " gradle/libs.versions.toml"
688+ fi
565689 git commit -m " sync: Update directories and files from upstream
566690
567691This PR syncs the following items with upstream:
568692- Directories: ${SYNC_DIRS[*]}
569- - Files: ${SYNC_FILES[*]} " || handle_error " Failed to commit changes"
693+ - Files: ${SYNC_FILES[*]}
694+ - Auto-heal: gradle/libs.versions.toml (pulls missing build-logic aliases from upstream)" || handle_error " Failed to commit changes"
570695 show_progress
571696
572697 if [ " $FORCE " = false ]; then
0 commit comments