1414from typing import Iterable , List
1515from urllib .request import urlopen
1616
17- CODENAMEONE_JAR_URL = "https://raw.githubusercontent.com/codenameone/CodenameOne/master/dist/CodenameOne.jar"
18- JAVA_SE_PORT_JAR_URL = "https://raw.githubusercontent.com/codenameone/CodenameOne/master/dist/JavaSEPort.jar"
17+ CODENAMEONE_JAR_URLS = [
18+ "https://github.com/codenameone/CodenameOne/releases/latest/download/CodenameOne.jar" ,
19+ "https://raw.githubusercontent.com/codenameone/CodenameOne/master/dist/CodenameOne.jar" ,
20+ ]
21+ JAVA_SE_PORT_JAR_URLS = [
22+ "https://github.com/codenameone/CodenameOne/releases/latest/download/JavaSEPort.jar" ,
23+ "https://raw.githubusercontent.com/codenameone/CodenameOne/master/dist/JavaSEPort.jar" ,
24+ ]
1925HARNESS_SOURCE = Path (__file__ ).resolve ().parent / "java" / "SkinHarness.java"
2026
2127
@@ -32,23 +38,30 @@ def _load_report(path: Path) -> List[dict]:
3238 return [entry for entry in generated if isinstance (entry , dict )]
3339
3440
35- def _ensure_artifact (target_dir : Path , url : str ) -> Path :
41+ def _ensure_artifact (target_dir : Path , urls : Iterable [ str ] ) -> Path :
3642 target_dir .mkdir (parents = True , exist_ok = True )
37- filename = url .rsplit ("/" , 1 )[- 1 ]
38- artifact_path = target_dir / filename
39- if artifact_path .exists ():
43+ errors : list [str ] = []
44+ for url in urls :
45+ filename = url .rsplit ("/" , 1 )[- 1 ]
46+ artifact_path = target_dir / filename
47+ if artifact_path .exists ():
48+ return artifact_path
49+
50+ try :
51+ with urlopen (url ) as response , tempfile .NamedTemporaryFile (delete = False ) as tmp :
52+ shutil .copyfileobj (response , tmp )
53+ tmp .flush ()
54+ tmp_path = Path (tmp .name )
55+ except Exception as exc : # urllib raises a variety of exceptions, surface them uniformly
56+ errors .append (f"{ url } : { exc } " )
57+ continue
58+
59+ tmp_path .replace (artifact_path )
4060 return artifact_path
4161
42- try :
43- with urlopen (url ) as response , tempfile .NamedTemporaryFile (delete = False ) as tmp :
44- shutil .copyfileobj (response , tmp )
45- tmp .flush ()
46- tmp_path = Path (tmp .name )
47- except Exception as exc : # urllib raises a variety of exceptions, surface them uniformly
48- raise VerificationError (f"Failed to download artifact from { url } : { exc } " ) from exc
49-
50- tmp_path .replace (artifact_path )
51- return artifact_path
62+ raise VerificationError (
63+ "Failed to download required artifact. Attempts: " + "; " .join (errors ) if errors else "No URLs supplied"
64+ )
5265
5366
5467def _find_tool (tool_name : str ) -> Path :
@@ -99,7 +112,12 @@ def _run_harness(classpath: Iterable[Path], classes_dir: Path, skin_path: Path)
99112 subprocess .run (cmd , check = True )
100113
101114
102- def verify_skins (report_file : Path , work_dir : Path , codenameone_url : str , javase_port_url : str ) -> None :
115+ def verify_skins (
116+ report_file : Path ,
117+ work_dir : Path ,
118+ codenameone_urls : Iterable [str ],
119+ javase_port_urls : Iterable [str ],
120+ ) -> None :
103121 generated = _load_report (report_file )
104122 if not generated :
105123 print ("No generated skins to verify." )
@@ -111,8 +129,8 @@ def verify_skins(report_file: Path, work_dir: Path, codenameone_url: str, javase
111129 work_dir .mkdir (parents = True , exist_ok = True )
112130 artifacts_dir = work_dir / "artifacts"
113131 classes_dir = work_dir / "classes"
114- codenameone_jar = _ensure_artifact (artifacts_dir , codenameone_url )
115- javase_port_jar = _ensure_artifact (artifacts_dir , javase_port_url )
132+ codenameone_jar = _ensure_artifact (artifacts_dir , codenameone_urls )
133+ javase_port_jar = _ensure_artifact (artifacts_dir , javase_port_urls )
116134 classpath = [codenameone_jar , javase_port_jar ]
117135
118136 _compile_harness (HARNESS_SOURCE , classpath , classes_dir )
@@ -136,21 +154,26 @@ def parse_args(argv: List[str]) -> argparse.Namespace:
136154 )
137155 parser .add_argument (
138156 "--codenameone-url" ,
139- default = CODENAMEONE_JAR_URL ,
140- help = "URL of the Codename One API jar to download" ,
157+ action = "append" ,
158+ default = [],
159+ help = "URL of the Codename One API jar to download (can be provided multiple times)" ,
141160 )
142161 parser .add_argument (
143162 "--javase-url" ,
144- default = JAVA_SE_PORT_JAR_URL ,
145- help = "URL of the Codename One JavaSEPort simulator jar to download" ,
163+ action = "append" ,
164+ default = [],
165+ help = "URL of the Codename One JavaSEPort simulator jar to download (can be provided multiple times)" ,
146166 )
147167 return parser .parse_args (argv )
148168
149169
150170def main (argv : List [str ] | None = None ) -> int :
151171 args = parse_args (argv or sys .argv [1 :])
172+ codenameone_urls = args .codenameone_url or CODENAMEONE_JAR_URLS
173+ javase_urls = args .javase_url or JAVA_SE_PORT_JAR_URLS
174+
152175 try :
153- verify_skins (args .report_file , args .work_dir , args . codenameone_url , args . javase_url )
176+ verify_skins (args .report_file , args .work_dir , codenameone_urls , javase_urls )
154177 except VerificationError as exc :
155178 print (f"Verification failed: { exc } " , file = sys .stderr )
156179 return 1
0 commit comments