55"""
66JDK index handling.
77
8- Fetches and caches the Coursier JDK index, parses JSON, normalizes vendor names
9- (e.g., merges ibm-semeru-*-java## variants), and performs version
8+ Fetches and caches the Coursier JDK index, parses JSON, and performs version
109matching/resolution with support for version expressions like "17+".
1110
1211No actual operations except for caching the index itself. _index should be
@@ -143,44 +142,6 @@ def _read_index(path: Path) -> Index:
143142 except json .JSONDecodeError as e :
144143 raise InstallError (f"Invalid JSON in index file { path } : { e } " ) from e
145144
146- return _postprocess_index (index )
147-
148-
149- def _postprocess_index (index : Index ) -> Index :
150- """
151- Post-process the index to normalize the data.
152-
153- Some "vendors" include the major Java version,
154- so let's merge such entries. In particular:
155-
156- * ibm-semuru-openj9-java<##>
157- * graalvm-java<##>
158-
159- However: while the graalvm vendors follow this pattern, the version
160- numbers for graalvm are *not* JDK versions, but rather GraalVM versions,
161- which merely strongly resemble JDK version strings. For example,
162- graalvm-java17 version 22.3.3 bundles OpenJDK 17.0.8, but
163- unfortunately there is no way to know this from the index alone.
164- """
165-
166- pattern = re .compile ("^(jdk@ibm-semeru.*)-java\\ d+$" )
167- if not hasattr (index , "items" ):
168- return index
169- for os , arches in index .items ():
170- if not hasattr (arches , "items" ):
171- continue
172- for arch , vendors in arches .items ():
173- if not hasattr (vendors , "items" ):
174- continue
175- for vendor , versions in vendors .copy ().items ():
176- if not vendor .startswith ("jdk@graalvm" ) and (
177- m := pattern .match (vendor )
178- ):
179- true_vendor = m .group (1 )
180- if true_vendor not in index [os ][arch ]:
181- index [os ][arch ][true_vendor ] = {}
182- index [os ][arch ][true_vendor ].update (versions )
183-
184145 return index
185146
186147
@@ -235,9 +196,10 @@ def _normalize_version(
235196 ver : str , * , remove_prefix_1 : bool = False
236197) -> tuple [int | str , ...]:
237198 # Normalize requested version and candidates:
238- # - Split at dots and dashes (so we don't distinguish between '.' and '-')
239- # - Try to convert elements to integers (so that we can compare elements
240- # numerically where feasible)
199+ # - Handle _openj9- as a plain separator (for ibm-semeru-openj9-java*
200+ # versions); also handle -m2 suffix
201+ # - Split at dots, dashes, plus signs, and underscores
202+ # - Convert elements to integers (raise ValueError if not possible)
241203 # - If remove_prefix_1 and first element is 1, remove it (so JDK 1.8 == 8)
242204 # - Return as a tuple (so that we compare element by element)
243205 # - Trailing zero elements are NOT removed, so, e.g., 11 < 11.0 (for the
@@ -247,24 +209,38 @@ def _normalize_version(
247209 is_plus = ver .endswith ("+" )
248210 if is_plus :
249211 ver = ver [:- 1 ]
212+ plus = ("+" ,) if is_plus else ()
213+
214+ if "_openj9-" in ver :
215+ # ibm-semeru-openj9-java* version numbers have a variable number of
216+ # '.'-separated numbers before the '+'. Pad so that comparisons work.
217+ first , second = ver .split ("+" , 1 )
218+ nfirst = _normalize_version (first , remove_prefix_1 = remove_prefix_1 )
219+ while len (nfirst ) < 4 :
220+ nfirst = nfirst + (0 ,)
221+ nsecond = _normalize_version (
222+ second .replace ("-m" , "-" ).replace ("_openj9-" , "-" )
223+ )
224+ return nfirst + nsecond + plus
225+
250226 if ver :
251- norm = tuple (re .split (_VER_SEPS , ver ))
252- norm = tuple (_intify (e ) for e in norm )
227+ parts = re .split (_VER_SEPS , ver )
228+ norm = []
229+ for part in parts :
230+ try :
231+ norm .append (int (part ))
232+ except ValueError :
233+ raise ValueError (
234+ f"Non-integer element '{ part } ' in version"
235+ ) from None
236+ norm = tuple (norm )
253237 else :
254238 norm = ()
255- plus = ("+" ,) if is_plus else ()
256239 if remove_prefix_1 and len (norm ) and norm [0 ] == 1 :
257240 return norm [1 :] + plus
258241 return norm + plus
259242
260243
261- def _intify (s : str ) -> int | str :
262- try :
263- return int (s )
264- except ValueError :
265- return s
266-
267-
268244def _is_version_compatible_with_spec (
269245 version : tuple [int | str , ...], spec : tuple [int | str , ...]
270246) -> bool :
@@ -282,25 +258,6 @@ def _is_version_compatible_with_spec(
282258 return len (version ) >= len (spec ) and version [: len (spec )] == spec
283259
284260
285- class _VersionElement :
286- """Wrapper for version tuple elements enabling mixed int/str comparison."""
287-
288- def __init__ (self , value : int | str ) -> None :
289- self .value = value
290-
291- def __eq__ (self , other : object ) -> bool :
292- if not isinstance (other , _VersionElement ):
293- return NotImplemented
294- if isinstance (self .value , int ) and isinstance (other .value , int ):
295- return self .value == other .value
296- return str (self .value ) == str (other .value )
297-
298- def __lt__ (self , other : _VersionElement ) -> bool :
299- if isinstance (self .value , int ) and isinstance (other .value , int ):
300- return self .value < other .value
301- return str (self .value ) < str (other .value )
302-
303-
304261def matching_jdk_versions (index : Index , conf : Configuration ) -> list [str ]:
305262 """
306263 Return all version strings matching the configuration, sorted by version.
@@ -313,10 +270,4 @@ def matching_jdk_versions(index: Index, conf: Configuration) -> list[str]:
313270 if not versions :
314271 return []
315272 matched = _match_versions (conf .vendor , versions , conf .version )
316-
317- def version_sort_key (
318- item : tuple [tuple [int | str , ...], str ],
319- ) -> tuple [_VersionElement , ...]:
320- return tuple (_VersionElement (e ) for e in item [0 ])
321-
322- return [v for _ , v in sorted (matched .items (), key = version_sort_key )]
273+ return [v for _ , v in sorted (matched .items ())]
0 commit comments