@@ -200,19 +200,22 @@ def _collect_files(self):
200
200
201
201
# collect project files first, then extend with shaded (re)sources
202
202
super ()._collect_files ()
203
- javafiles = self ._javafiles
204
- non_javafiles = self ._non_javafiles
205
-
206
203
proj = self .subject
207
204
binDir = proj .output_dir ()
205
+ srcGenDir = proj .source_gen_dir ()
206
+ excludedPaths = proj .excluded_paths ()
207
+ includedPaths = proj .included_paths ()
208
+
209
+ # remove possibly outdated src_gen files; they will be added below
210
+ javafiles = self ._javafiles = {src : out for src , out in self ._javafiles .items () if not src .startswith (srcGenDir )}
211
+ non_javafiles = self ._non_javafiles = {src : out for src , out in self ._non_javafiles .items () if not src .startswith (srcGenDir )}
212
+
208
213
for dep in proj .shaded_deps ():
209
214
srcFilePath = dep .get_source_path (False )
210
215
if srcFilePath is None :
211
216
continue
212
217
213
- for zipFilePath , outDir in [(srcFilePath , proj .source_gen_dir ())]:
214
- excludedPaths = proj .excluded_paths ()
215
- includedPaths = proj .included_paths ()
218
+ for zipFilePath , outDir in [(srcFilePath , srcGenDir )]:
216
219
try :
217
220
with zipfile .ZipFile (zipFilePath , 'r' ) as zf :
218
221
for zi in zf .infolist ():
@@ -228,12 +231,20 @@ def _collect_files(self):
228
231
if filepath .suffix not in ['.java' , '.class' ] and not any ((i , path_mappings := m ) for (i , m ) in includedPaths .items () if glob_match (filepath , i )):
229
232
continue
230
233
234
+ # strip any META-INF/versions/*/ prefix, will be flattened during build()
235
+ if len (filepath .parts ) > 3 and filepath .parts [0 :2 ] == ('META-INF' , 'versions' ) and filepath .parts [2 ].isdigit ():
236
+ java_version = int (filepath .parts [2 ])
237
+ if java_version > proj .javaCompliance .value :
238
+ # ignore versioned files whose version is higher than the project's javaCompliance
239
+ continue
240
+ old_filename = '/' .join (filepath .parts [3 :])
241
+
231
242
new_filename = proj .substitute_path (old_filename , mappings = path_mappings )
232
243
src_gen_path = os .path .join (outDir , new_filename )
233
244
if filepath .suffix == '.java' :
234
- javafiles . setdefault ( src_gen_path , os .path .join (binDir , new_filename [:- len ('.java' )] + '.class' ) )
245
+ javafiles [ src_gen_path ] = os .path .join (binDir , new_filename [:- len ('.java' )] + '.class' )
235
246
else :
236
- non_javafiles . setdefault ( src_gen_path , os .path .join (binDir , new_filename ) )
247
+ non_javafiles [ src_gen_path ] = os .path .join (binDir , new_filename )
237
248
except FileNotFoundError :
238
249
continue
239
250
return self
@@ -244,6 +255,11 @@ def build(self):
244
255
excludedPaths = dist .excluded_paths ()
245
256
includedPaths = dist .included_paths ()
246
257
patch = dist .shade .get ('patch' , {})
258
+ # pre-compile regex patterns
259
+ patchSubs = {
260
+ filepattern : [(re .compile (srch , flags = re .MULTILINE ), repl ) for (srch , repl ) in subs .items ()]
261
+ for filepattern , subs in patch .items ()
262
+ }
247
263
248
264
binDir = dist .output_dir ()
249
265
srcDir = dist .source_gen_dir ()
@@ -269,6 +285,10 @@ def build(self):
269
285
mx .abort (f'Cannot shade { dep } without a source jar (missing sourceDigest?)' )
270
286
271
287
for zipFilePath , outDir in [(jarFilePath , binDir ), (srcFilePath , srcDir )]:
288
+ versioned_resources = {} # {old_filename: version}
289
+ java_version_none = 0
290
+ java_version_base = 8 # (0 < v < 9)
291
+
272
292
with zipfile .ZipFile (zipFilePath , 'r' ) as zf :
273
293
for zi in zf .infolist ():
274
294
if zi .is_dir ():
@@ -285,19 +305,37 @@ def build(self):
285
305
mx .warn (f'file { old_filename } is not included (if this is intended, please add the file to the exclude list)' )
286
306
continue
287
307
288
- new_filename = dist .substitute_path (old_filename , mappings = path_mappings )
289
308
applicableSubs = []
290
-
291
309
if filepath .suffix == '.java' :
292
310
applicableSubs += javaSubstitutions
293
311
if filepath .suffix == '.class' :
294
312
continue
295
313
296
- mx .logv (f'extracting file { old_filename } to { new_filename } ' )
297
- extraPatches = [sub for filepattern , subs in patch .items () if glob_match (filepath , filepattern ) for sub in subs .items ()]
298
- extraSubs = list ((re .compile (s , flags = re .MULTILINE ), r ) for (s , r ) in extraPatches )
314
+ # strip any META-INF/versions/*/ prefix and extract the file with the highest compatible version
315
+ if len (filepath .parts ) > 3 and filepath .parts [0 :2 ] == ('META-INF' , 'versions' ) and filepath .parts [2 ].isdigit ():
316
+ java_version = int (filepath .parts [2 ])
317
+ # ignore versioned files whose version is higher than the project's javaCompliance
318
+ if versioned_resources .get (old_filename , java_version_base ) < java_version <= dist .javaCompliance .value :
319
+ mx .logv (f"using versioned { old_filename } ({ java_version } > { versioned_resources .get (old_filename , java_version_none )} )" )
320
+ old_filename = '/' .join (filepath .parts [3 :])
321
+ versioned_resources [old_filename ] = java_version
322
+ else :
323
+ if java_version > dist .javaCompliance .value :
324
+ mx .logv (f"ignoring file { old_filename } due to the project's javaCompliance ({ java_version } > { dist .javaCompliance .value } )" )
325
+ continue
326
+ else :
327
+ if versioned_resources .get (old_filename , java_version_none ) < java_version_base :
328
+ versioned_resources [old_filename ] = java_version_base
329
+ else :
330
+ mx .logv (f"skipping file { old_filename } replaced by META-INF/versions/{ versioned_resources .get (old_filename )} " )
331
+ continue
332
+
333
+ new_filename = dist .substitute_path (old_filename , mappings = path_mappings )
334
+ extraSubs = [sub for filepattern , subs in patchSubs .items () if glob_match (filepath , filepattern ) for sub in subs ]
299
335
applicableSubs += extraSubs
300
- if old_filename == new_filename and len (applicableSubs ) == 0 :
336
+
337
+ mx .logv (f'extracting file { zi .filename } to { new_filename } ' )
338
+ if zi .filename == new_filename and len (applicableSubs ) == 0 :
301
339
# same file name, no substitutions: just extract
302
340
zf .extract (zi , outDir )
303
341
else :
0 commit comments