๐ (native): Register jgit GcConfig$PackRefsMode for reflection
Changes
2 files changed, +83 -0
MODIFY
src/main/resources/META-INF/native-image/de.workaround/git-shark/reflect-config.json
+9 -0
@@ -629,6 +629,15 @@
629
629
]
630
630
},
631
631
{
632
+ "name": "org.eclipse.jgit.lib.GcConfig$PackRefsMode",
633
+ "methods": [
634
+ {
635
+ "name": "values",
636
+ "parameterTypes": []
637
+ }
638
+ ]
639
+ },
640
+ {
632
641
"name": "org.eclipse.jgit.lib.GpgConfig$GpgFormat",
633
642
"methods": [
634
643
{
ADD
src/test/java/de/workaround/nativeimg/JgitReflectConfigTest.java
+74 -0
@@ -0,0 +1,74 @@
1
+package de.workaround.nativeimg;
2
+
3
+import java.io.InputStream;
4
+import java.util.ArrayList;
5
+import java.util.List;
6
+
7
+import org.eclipse.jgit.lib.GcConfig;
8
+import org.junit.jupiter.api.Test;
9
+
10
+import com.fasterxml.jackson.databind.JsonNode;
11
+import com.fasterxml.jackson.databind.ObjectMapper;
12
+
13
+import static org.junit.jupiter.api.Assertions.assertTrue;
14
+import static org.junit.jupiter.api.Assertions.fail;
15
+
16
+/**
17
+ * jgit reads git config values such as {@code gc.packRefs} by reflectively calling
18
+ * {@code values()} on the corresponding enum. In a native image every such enum must be
19
+ * listed in reflect-config.json, otherwise startup fails with NoSuchMethodException.
20
+ * This guards the enums nested in {@link GcConfig} against jgit upgrades that add new ones.
21
+ */
22
+class JgitReflectConfigTest
23
+{
24
+ private static final String CONFIG = "META-INF/native-image/de.workaround/git-shark/reflect-config.json";
25
+
26
+ @Test
27
+ void gcConfigEnumsAreRegisteredForReflection() throws Exception
28
+ {
29
+ JsonNode entries;
30
+ try (InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(CONFIG))
31
+ {
32
+ assertTrue(in != null, "reflect-config.json not found on classpath: " + CONFIG);
33
+ entries = new ObjectMapper().readTree(in);
34
+ }
35
+
36
+ List<String> missing = new ArrayList<>();
37
+ for (Class<?> nested : GcConfig.class.getDeclaredClasses())
38
+ {
39
+ if (!nested.isEnum())
40
+ {
41
+ continue;
42
+ }
43
+ if (!hasValuesEntry(entries, nested.getName()))
44
+ {
45
+ missing.add(nested.getName());
46
+ }
47
+ }
48
+
49
+ if (!missing.isEmpty())
50
+ {
51
+ fail("These jgit enums must be registered in reflect-config.json with a values() method "
52
+ + "or the native image fails to start: " + missing);
53
+ }
54
+ }
55
+
56
+ private static boolean hasValuesEntry(JsonNode entries, String className)
57
+ {
58
+ for (JsonNode entry : entries)
59
+ {
60
+ if (!className.equals(entry.path("name").asText()))
61
+ {
62
+ continue;
63
+ }
64
+ for (JsonNode method : entry.path("methods"))
65
+ {
66
+ if ("values".equals(method.path("name").asText()))
67
+ {
68
+ return true;
69
+ }
70
+ }
71
+ }
72
+ return false;
73
+ }
74
+}