1313from core .fortran_handler import FortranHandler
1414from core .git_operations import GitManager
1515from core .github_auth import get_github_token_via_gh_cli , get_github_token_via_oauth
16+ from core .go_handler import GoHandler , detect_import_path , resolve_go_module
1617from core .models import Language , LibraryConfig , LibraryType
1718from core .rust_handler import RustLibraryHandler
1819from core .subprocess_utils import run_ce_install_command
@@ -896,6 +897,196 @@ def process_fortran_library(
896897 raise
897898
898899
900+ def process_go_library (
901+ config : LibraryConfig ,
902+ github_token : str | None = None ,
903+ verify : bool = False ,
904+ dry_run : bool = False ,
905+ debug : bool = False ,
906+ build_test : str = "auto" ,
907+ keep_temp : bool = False ,
908+ yes : bool = False ,
909+ ):
910+ """Process a Go library addition"""
911+ click .echo (
912+ f"\n Processing Go module: { config .module } ({ config .library_id or 'auto' } ) { config .version } "
913+ )
914+
915+ with GitManager (github_token , debug = debug , keep_temp = keep_temp ) as git_mgr :
916+ click .echo ("Cloning repositories..." )
917+ main_repo_path , infra_repo_path = git_mgr .clone_repositories ()
918+
919+ library_name = config .library_id or GoHandler .suggest_library_id_static (config .module )
920+ branch_name = f"add-go-{ library_name } -{ config .version } " .replace ("." , "-" )
921+ infra_branch = f"{ branch_name } -infra"
922+ main_branch = f"{ branch_name } -main"
923+ git_mgr .create_branch (infra_repo_path , infra_branch )
924+ git_mgr .create_branch (main_repo_path , main_branch )
925+
926+ click .echo ("Adding Go library..." )
927+ go_handler = GoHandler (infra_repo_path , main_repo_path , debug = debug )
928+
929+ try :
930+ if config .module :
931+ click .echo ("Resolving module path..." )
932+ resolved_module , resolved_import = resolve_go_module (
933+ config .module , config .get_primary_version ()
934+ )
935+ if resolved_module != config .module :
936+ click .echo (f"Resolved subpackage path to module: { resolved_module } " )
937+ config .import_path = config .import_path or resolved_import
938+ config .module = resolved_module
939+ config .library_id = GoHandler .suggest_library_id_static (resolved_module )
940+
941+ if not config .import_path :
942+ click .echo ("Checking module structure..." )
943+ detected = detect_import_path (config .module , config .get_primary_version ())
944+ if detected :
945+ click .echo (f"Root package not importable, using: { detected } " )
946+ config .import_path = detected
947+ else :
948+ click .echo ("Root package is importable" )
949+
950+ library_id = go_handler .add_library (config )
951+ if not library_id :
952+ click .echo ("Failed to add library to libraries.yaml" , err = True )
953+ return
954+
955+ click .echo ("Updating go.amazon.properties..." )
956+ config .library_id = library_id
957+ if not go_handler .update_go_properties (library_id , config ):
958+ click .echo ("Failed to update Go properties" , err = True )
959+ return
960+
961+ click .echo (SUCCESS_MODIFIED_FILES )
962+
963+ # Run build test based on mode
964+ should_build_test = build_test .lower ()
965+ is_auto_mode = should_build_test == "auto"
966+
967+ if should_build_test != "no" :
968+ if platform .system () == "Windows" :
969+ if should_build_test == "yes" :
970+ click .echo ("\n Build test is not supported on Windows" )
971+ else :
972+ available , msg = go_handler .is_build_test_available ()
973+ if not available :
974+ if should_build_test == "yes" :
975+ click .echo (f"\n { msg } " , err = True )
976+ return
977+ # Auto mode: silently skip if no compiler
978+ else :
979+ click .echo (f"\n Running Go build test... ({ msg } )" )
980+ build_result = go_handler .run_build_test (library_id , config .version )
981+ if not build_result .success :
982+ click .echo ("Build test failed." , err = True )
983+ if is_auto_mode :
984+ click .echo (
985+ " Hint: Use --build-test=no to skip build testing "
986+ "if this failure is expected." ,
987+ err = True ,
988+ )
989+ click .echo ("Aborting." , err = True )
990+ return
991+ click .echo ("Build test passed" )
992+ if build_result .artifacts :
993+ click .echo (" Artifacts produced:" )
994+ click .echo (f" { build_result .get_artifact_summary ()} " )
995+
996+ # Show diffs if verify or dry_run flag is set
997+ if verify or dry_run :
998+ click .echo ("\n " + "=" * 60 )
999+ click .echo ("CHANGES TO BE COMMITTED:" )
1000+ click .echo ("=" * 60 )
1001+
1002+ click .echo (f"\n Repository: { GitManager .CE_INFRA_REPO } " )
1003+ click .echo ("-" * 60 )
1004+ infra_diff = git_mgr .get_diff (infra_repo_path )
1005+ if infra_diff :
1006+ click .echo (infra_diff )
1007+ else :
1008+ click .echo ("No changes detected" )
1009+
1010+ click .echo (f"\n Repository: { GitManager .CE_MAIN_REPO } " )
1011+ click .echo ("-" * 60 )
1012+ main_diff = git_mgr .get_diff (main_repo_path )
1013+ if main_diff :
1014+ click .echo (main_diff )
1015+ else :
1016+ click .echo ("No changes detected" )
1017+
1018+ click .echo ("\n " + "=" * 60 )
1019+
1020+ # Exit early if dry-run mode
1021+ if dry_run :
1022+ click .echo ("\n Dry run complete - no changes committed." )
1023+ return
1024+
1025+ if not yes and not click .confirm ("\n Do you want to proceed with these changes?" ):
1026+ click .echo ("Changes cancelled." )
1027+ return
1028+
1029+ commit_msg = f"Add Go library { library_id } { config .version } "
1030+
1031+ infra_committed = git_mgr .commit_changes (infra_repo_path , commit_msg )
1032+ main_committed = git_mgr .commit_changes (main_repo_path , commit_msg )
1033+
1034+ if not infra_committed and not main_committed :
1035+ click .echo ("Library version already exists - no changes to commit." )
1036+ return
1037+
1038+ if github_token :
1039+ # Only proceed with pushing and PRs if we have commits
1040+ if infra_committed or main_committed :
1041+ # Push branches and create PRs
1042+ click .echo ("\n Pushing branches..." )
1043+ if infra_committed :
1044+ git_mgr .push_branch (infra_repo_path , infra_branch )
1045+ if main_committed :
1046+ git_mgr .push_branch (main_repo_path , main_branch )
1047+
1048+ click .echo ("\n Creating pull requests..." )
1049+ pr_body = (
1050+ f"This PR adds the Go library **{ library_id } ** "
1051+ f"(module: `{ config .module } `) "
1052+ f"version { config .version } to Compiler Explorer.\n \n "
1053+ )
1054+ pr_body += f"- Go module: { config .module } \n "
1055+ pr_body += "- Build type: gomod"
1056+
1057+ if infra_committed :
1058+ infra_pr_body = pr_body + PR_FOOTER
1059+ infra_pr_url = git_mgr .create_pull_request (
1060+ GitManager .CE_INFRA_REPO , infra_branch , commit_msg , infra_pr_body
1061+ )
1062+ click .echo ("\n Created PR:" )
1063+ click .echo (f" - Infra: { infra_pr_url } " )
1064+
1065+ if main_committed :
1066+ main_pr_body = pr_body
1067+ if infra_committed :
1068+ main_pr_body += f"\n \n Related PR: { infra_pr_url } "
1069+ main_pr_body += PR_FOOTER
1070+
1071+ main_pr_url = git_mgr .create_pull_request (
1072+ GitManager .CE_MAIN_REPO ,
1073+ main_branch ,
1074+ commit_msg ,
1075+ main_pr_body ,
1076+ )
1077+ if not infra_committed :
1078+ click .echo ("\n Created PR:" )
1079+ click .echo (f" - Main: { main_pr_url } " )
1080+ else :
1081+ click .echo ("\n No changes to push - skipping PR creation." )
1082+ else :
1083+ display_authentication_warning ()
1084+
1085+ except Exception as e :
1086+ click .echo (f"\n Error processing Go library: { e } " , err = True )
1087+ raise
1088+
1089+
8991090@click .command ()
9001091@click .option ("--debug" , is_flag = True , help = "Enable debug mode" )
9011092@click .option ("--github-token" , envvar = "GITHUB_TOKEN" , help = "GitHub token for creating PRs" )
@@ -914,7 +1105,7 @@ def process_fortran_library(
9141105@click .option ("--top-rust-crates" , is_flag = True , help = "Add the top 100 Rust crates" )
9151106@click .option (
9161107 "--lang" ,
917- type = click .Choice (["c" , "c++" , "rust" , "fortran" ], case_sensitive = False ),
1108+ type = click .Choice (["c" , "c++" , "rust" , "fortran" , "go" ], case_sensitive = False ),
9181109 help = "Language for the library" ,
9191110)
9201111@click .option ("--lib" , help = "Library name (for Rust) or GitHub URL (for other languages)" )
@@ -934,6 +1125,10 @@ def process_fortran_library(
9341125 "(automatic for packaged-headers, optional for others)"
9351126 ),
9361127)
1128+ @click .option (
1129+ "--import-path" ,
1130+ help = "Go import path override (for modules where root package isn't importable)" ,
1131+ )
9371132def main (
9381133 debug : bool ,
9391134 github_token : str | None ,
@@ -950,6 +1145,7 @@ def main(
9501145 ver : str | None ,
9511146 type : str | None ,
9521147 package_install : bool ,
1148+ import_path : str | None ,
9531149):
9541150 """CLI tool to add libraries to Compiler Explorer"""
9551151 if debug :
@@ -985,14 +1181,23 @@ def main(
9851181 "c++" : Language .CPP ,
9861182 "rust" : Language .RUST ,
9871183 "fortran" : Language .FORTRAN ,
1184+ "go" : Language .GO ,
9881185 }
9891186
9901187 language = lang_map [lang .lower ()]
9911188
9921189 if language == Language .RUST :
9931190 config = LibraryConfig (language = language , name = lib , version = ver )
1191+ elif language == Language .GO :
1192+ config = LibraryConfig (
1193+ language = language ,
1194+ module = lib ,
1195+ version = ver ,
1196+ import_path = import_path ,
1197+ )
1198+ config .library_id = GoHandler .suggest_library_id_static (lib )
9941199 else :
995- # For non-Rust, lib should be a GitHub URL
1200+ # For non-Rust/Go , lib should be a GitHub URL
9961201 config = LibraryConfig (language = language , github_url = lib , version = ver )
9971202
9981203 # For C, C++, and Fortran, we need to set library_id
@@ -1089,6 +1294,17 @@ def main(
10891294 keep_temp ,
10901295 yes ,
10911296 )
1297+ elif config .is_go ():
1298+ process_go_library (
1299+ single_config ,
1300+ github_token ,
1301+ verify ,
1302+ dry_run ,
1303+ debug ,
1304+ build_test ,
1305+ keep_temp ,
1306+ yes ,
1307+ )
10921308 else :
10931309 click .echo (f"\n ⚠️ Language { config .language } is not yet implemented." )
10941310 break
@@ -1126,10 +1342,14 @@ def main(
11261342 process_fortran_library (
11271343 config , github_token , verify , dry_run , debug , build_test , keep_temp , yes
11281344 )
1345+ elif config .is_go ():
1346+ process_go_library (
1347+ config , github_token , verify , dry_run , debug , build_test , keep_temp , yes
1348+ )
11291349 else :
11301350 click .echo ("\n ⚠️ This language is not yet implemented." )
11311351 click .echo (
1132- "Currently only Rust, C, C++, and Fortran library additions are supported."
1352+ "Currently only Rust, C, C++, Fortran, and Go library additions are supported."
11331353 )
11341354
11351355 except KeyboardInterrupt :
0 commit comments