2222import json
2323from pathlib import Path
2424import requests
25- from setuptools .command .bdist_wheel import bdist_wheel
26-
25+ import subprocess
2726
2827# --- Configuration ---
2928TEST_SERVER_VERSION = "v0.2.7"
3029GITHUB_OWNER = "google"
3130GITHUB_REPO = "test-server"
3231PROJECT_NAME = "test-server"
32+ PROJECT_ROOT = Path (__file__ ).parent
33+
34+ CHECKSUMS_PATH = PROJECT_ROOT / "checksums.json"
3335
34- CHECKSUMS_PATH = Path (__file__ ).parent / "checksums.json"
3536try :
3637 with open (CHECKSUMS_PATH , "r" ) as f :
3738 ALL_EXPECTED_CHECKSUMS = json .load (f )
3839except (FileNotFoundError , json .JSONDecodeError ) as e :
39- print (f"Error loading checksums.json: { e } " )
40+ print (f"Error loading checksums.json: { e } " , file = sys . stderr )
4041 sys .exit (1 )
4142
4243
@@ -101,7 +102,7 @@ def download_and_verify(download_url, archive_path, version, archive_name):
101102 except Exception as e :
102103 if archive_path .exists ():
103104 archive_path .unlink ()
104- print (f"Failed during download or verification: { e } " )
105+ print (f"Failed during download or verification: { e } " , file = sys . stderr )
105106 raise
106107
107108
@@ -129,6 +130,34 @@ def ensure_binary_is_executable(binary_path, go_os):
129130 os .chmod (binary_path , st .st_mode | stat .S_IEXEC )
130131 print (f"Set executable permission for { binary_path } " )
131132
133+ def verify_binary_usability (binary_path : Path ) -> None :
134+ """
135+ Verifies the binary can be executed by running a simple command.
136+ This helps catch corrupted downloads or architecture mismatches.
137+ """
138+ print (f"Verifying usability of binary at { binary_path } ..." )
139+ try :
140+ # Running with "--help" is a safe, standard way to check execution
141+ subprocess .run (
142+ [str (binary_path ), "--help" ],
143+ capture_output = True ,
144+ text = True ,
145+ check = True , # This will raise CalledProcessError on non-zero exit codes
146+ timeout = 10
147+ )
148+ print ("Binary is executable and responding correctly." )
149+ except (subprocess .CalledProcessError , FileNotFoundError , PermissionError , subprocess .TimeoutExpired ) as e :
150+ print (f"ERROR: The binary at { binary_path } is not usable. Error: { e } " , file = sys .stderr )
151+ # Clean up the bad binary
152+ if binary_path .exists ():
153+ binary_path .unlink ()
154+ raise RuntimeError (
155+ f"The downloaded binary at { binary_path } could not be executed. "
156+ "This can mean a corrupted download or an incorrect binary for your OS/architecture. "
157+ "The invalid binary has been removed. Please try running the installation again. "
158+ "Run: download_golang_executable"
159+ ) from e
160+
132161
133162def install_binary (bin_dir : Path ):
134163 """Main function to orchestrate the installation to a specific directory."""
@@ -150,22 +179,26 @@ def install_binary(bin_dir: Path):
150179 download_and_verify (download_url , archive_path , version , archive_name )
151180 extract_archive (archive_path , archive_extension , bin_dir )
152181 ensure_binary_is_executable (binary_path , go_os )
153- print (f"{ PROJECT_NAME } binary is ready at { binary_path } " )
182+ verify_binary_usability (binary_path )
183+ print (f"\n { PROJECT_NAME } binary is ready at { binary_path } " )
154184 except Exception as e :
155- print (f"An error occurred during binary installation: { e } " )
156- sys .exit (1 )
185+ print (f"\n An error occurred during binary installation: { e } " , file = sys .stderr )
186+ # Re-raise the exception to be caught by the entry point function
187+ raise
157188
158189
159- # --- The Setuptools Hook ---
160- class CustomBuild (bdist_wheel ):
161- """Custom build command to download the binary into the correct build location."""
162- def run (self ):
163- print ("--- Executing CustomBuild hook to download binary! ---" )
164190
165- build_py = self .get_finalized_command ('build_py' )
166- build_dir = Path (build_py .build_lib )
167- bin_path = build_dir / 'test_server_sdk' / 'bin'
191+ def main_downloader_function ():
192+ """
193+ Entry point that determines the install location and calls the installation logic.
194+ """
195+ install_location = PROJECT_ROOT / "bin"
196+
197+ try :
198+ install_binary (install_location )
199+ except Exception :
200+ sys .exit (1 )
168201
169- install_binary (bin_path )
170202
171- super ().run ()
203+ if __name__ == "__main__" :
204+ main_downloader_function ()
0 commit comments