mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-25 13:30:08 +00:00
Embedded-only native loader
- Drop the repository storage and slimjar download path from NativeRuntimeLibraries - Reject native manifests that do not use embedded storage - Report provider hash mismatches as IOException
This commit is contained in:
1 parent
bf11d44370
commit
8d28ad4111
3 files changed
+52
-143
No files matched your search
@@ -2,26 +2,9 @@ package art.arcane.iris.platform.bootstrap;
|
|||||||
|
|
||||||
import art.arcane.volmlib.nativelib.NativeVersion;
|
import art.arcane.volmlib.nativelib.NativeVersion;
|
||||||
import art.arcane.volmlib.nativelib.NativeAdapters;
|
import art.arcane.volmlib.nativelib.NativeAdapters;
|
||||||
import io.github.slimjar.app.builder.ApplicationBuilder;
|
|
||||||
import io.github.slimjar.downloader.DependencyDownloader;
|
|
||||||
import io.github.slimjar.downloader.URLDependencyDownloader;
|
|
||||||
import io.github.slimjar.downloader.strategy.FilePathStrategy;
|
|
||||||
import io.github.slimjar.downloader.verify.FileChecksumCalculator;
|
|
||||||
import io.github.slimjar.relocation.helper.RelocationHelper;
|
|
||||||
import io.github.slimjar.relocation.helper.VerifyingRelocationHelperFactory;
|
|
||||||
import io.github.slimjar.relocation.meta.FlatFileMetaMediatorFactory;
|
|
||||||
import io.github.slimjar.exceptions.DownloaderException;
|
|
||||||
import io.github.slimjar.resolver.data.Dependency;
|
|
||||||
import io.github.slimjar.resolver.data.DependencyData;
|
|
||||||
import io.github.slimjar.resolver.data.Repository;
|
|
||||||
import io.github.slimjar.resolver.reader.dependency.DependencyDataProvider;
|
|
||||||
import io.github.slimjar.resolver.reader.dependency.DependencyReader;
|
|
||||||
import io.github.slimjar.resolver.reader.dependency.WrappingDependencyDataProviderFactory;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.URI;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLClassLoader;
|
import java.net.URLClassLoader;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
@@ -31,20 +14,16 @@ import java.security.MessageDigest;
|
|||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HexFormat;
|
import java.util.HexFormat;
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
public final class NativeRuntimeLibraries {
|
public final class NativeRuntimeLibraries {
|
||||||
private static final String MANIFEST = "META-INF/iris/native-runtime.properties";
|
private static final String MANIFEST = "META-INF/iris/native-runtime.properties";
|
||||||
private final Map<Dependency, String> dependencies;
|
private static final String GROUP = "com.github.VolmitSoftware.VolmLib";
|
||||||
private final Repository repository;
|
private final List<Provider> providers;
|
||||||
|
|
||||||
private NativeRuntimeLibraries(Map<Dependency, String> dependencies, Repository repository) {
|
private NativeRuntimeLibraries(List<Provider> providers) {
|
||||||
this.dependencies = dependencies;
|
this.providers = providers;
|
||||||
this.repository = repository;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static NativeRuntimeLibraries load(String minecraftVersion) {
|
public static NativeRuntimeLibraries load(String minecraftVersion) {
|
||||||
@@ -60,60 +39,27 @@ public final class NativeRuntimeLibraries {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static NativeRuntimeLibraries from(Properties manifest, String minecraftVersion) throws IOException {
|
static NativeRuntimeLibraries from(Properties manifest, String minecraftVersion) {
|
||||||
String storage = manifest.getProperty("storage", "repository");
|
String storage = manifest.getProperty("storage");
|
||||||
if (!storage.equals("repository") && !storage.equals("embedded")) {
|
if (!"embedded".equals(storage)) {
|
||||||
throw new IllegalStateException("Invalid native runtime storage: " + storage);
|
throw new IllegalStateException("Invalid native runtime storage: " + storage);
|
||||||
}
|
}
|
||||||
boolean embedded = storage.equals("embedded");
|
|
||||||
NativeVersion version = NativeVersion.resolve(minecraftVersion).orElseThrow(
|
NativeVersion version = NativeVersion.resolve(minecraftVersion).orElseThrow(
|
||||||
() -> new UnsupportedOperationException("No native provider for Minecraft " + minecraftVersion));
|
() -> new UnsupportedOperationException("No native provider for Minecraft " + minecraftVersion));
|
||||||
List<String> modules = List.of(manifest.getProperty("modules", "").split(","));
|
List<String> modules = List.of(manifest.getProperty("modules", "").split(","));
|
||||||
Map<Dependency, String> selected = new LinkedHashMap<>();
|
List<Provider> selected = new ArrayList<>(2);
|
||||||
for (String module : List.of("native-common", "native-" + version.packageName())) {
|
for (String module : List.of("native-common", "native-" + version.packageName())) {
|
||||||
if (!modules.contains(module)) {
|
if (!modules.contains(module)) {
|
||||||
throw new UnsupportedOperationException("Native provider is not distributed: " + module);
|
throw new UnsupportedOperationException("Native provider is not distributed: " + module);
|
||||||
}
|
}
|
||||||
String[] coordinate = manifest.getProperty(module + ".coordinate", "").split(":");
|
|
||||||
String digest = manifest.getProperty(module + ".sha256", "");
|
String digest = manifest.getProperty(module + ".sha256", "");
|
||||||
if (coordinate.length != 3 || !coordinate[0].equals("com.github.VolmitSoftware.VolmLib")
|
String coordinate = GROUP + ":" + module + ":embedded-" + digest;
|
||||||
|| !coordinate[1].equals(module) || coordinate[2].isBlank() || !digest.matches("[0-9a-f]{64}")
|
if (!digest.matches("[0-9a-f]{64}") || !coordinate.equals(manifest.getProperty(module + ".coordinate"))) {
|
||||||
|| embedded && !coordinate[2].equals("embedded-" + digest)) {
|
|
||||||
throw new IllegalStateException("Invalid native dependency manifest entry: " + module);
|
throw new IllegalStateException("Invalid native dependency manifest entry: " + module);
|
||||||
}
|
}
|
||||||
selected.put(new Dependency(coordinate[0], coordinate[1], coordinate[2], null, List.of()), digest);
|
selected.add(new Provider(module, "embedded-" + digest, digest));
|
||||||
}
|
}
|
||||||
Repository repository = embedded ? null : new Repository(URI.create(manifest.getProperty("repository")).toURL());
|
return new NativeRuntimeLibraries(List.copyOf(selected));
|
||||||
return new NativeRuntimeLibraries(Map.copyOf(selected), repository);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T extends ApplicationBuilder<?>> T configure(T builder, Path downloads) {
|
|
||||||
WrappingDependencyDataProviderFactory defaults = new WrappingDependencyDataProviderFactory(DependencyReader.DEFAULT);
|
|
||||||
builder.dataProviderFactory(url -> {
|
|
||||||
DependencyDataProvider provider = defaults.create(url);
|
|
||||||
return () -> merge(provider.get());
|
|
||||||
});
|
|
||||||
VerifyingRelocationHelperFactory relocation = new VerifyingRelocationHelperFactory(
|
|
||||||
new FileChecksumCalculator("SHA-256"),
|
|
||||||
FilePathStrategy.createRelocationStrategy(downloads.toFile(), "Iris"),
|
|
||||||
new FlatFileMetaMediatorFactory());
|
|
||||||
builder.relocationHelperFactory(relocator -> {
|
|
||||||
RelocationHelper helper = relocation.create(relocator);
|
|
||||||
return (dependency, file) -> dependencies.containsKey(dependency) ? file : helper.relocate(dependency, file);
|
|
||||||
});
|
|
||||||
builder.downloaderFactory((output, resolver, verifier) -> {
|
|
||||||
DependencyDownloader delegate = new URLDependencyDownloader(output, resolver, verifier);
|
|
||||||
return dependency -> {
|
|
||||||
Optional<File> result = delegate.download(dependency);
|
|
||||||
String expected = dependencies.get(dependency);
|
|
||||||
if (expected != null) {
|
|
||||||
File file = result.orElseThrow(() -> new DownloaderException("Native dependency has no jar: " + dependency));
|
|
||||||
verify(file, expected);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
});
|
|
||||||
return builder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public URLClassLoader openProviderLoader(Path downloads) {
|
public URLClassLoader openProviderLoader(Path downloads) {
|
||||||
@@ -128,31 +74,13 @@ public final class NativeRuntimeLibraries {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DependencyData merge(DependencyData original) {
|
|
||||||
if (repository == null) {
|
|
||||||
return original;
|
|
||||||
}
|
|
||||||
List<Dependency> combined = new ArrayList<>(original.dependencies());
|
|
||||||
combined.addAll(dependencies.keySet());
|
|
||||||
List<Repository> repositories = new ArrayList<>(original.repositories());
|
|
||||||
if (!repositories.contains(repository)) {
|
|
||||||
repositories.add(repository);
|
|
||||||
}
|
|
||||||
return new DependencyData(original.mirrors(), repositories, combined, original.relocations());
|
|
||||||
}
|
|
||||||
|
|
||||||
List<URL> providerUrls(Path downloads, ClassLoader resources) throws IOException {
|
List<URL> providerUrls(Path downloads, ClassLoader resources) throws IOException {
|
||||||
List<URL> urls = new ArrayList<>(dependencies.size());
|
List<URL> urls = new ArrayList<>(providers.size());
|
||||||
for (Map.Entry<Dependency, String> entry : dependencies.entrySet()) {
|
for (Provider provider : providers) {
|
||||||
Dependency dependency = entry.getKey();
|
Path artifact = downloads.resolve(GROUP.replace('.', '/'))
|
||||||
Path artifact = downloads.resolve(dependency.groupId().replace('.', '/'))
|
.resolve(provider.module()).resolve(provider.version())
|
||||||
.resolve(dependency.artifactId()).resolve(dependency.version())
|
.resolve(provider.module() + "-" + provider.version() + ".jar");
|
||||||
.resolve(dependency.artifactId() + "-" + dependency.version() + ".jar");
|
extractEmbedded(resources, provider.module(), artifact, provider.sha256());
|
||||||
if (repository == null) {
|
|
||||||
extractEmbedded(resources, dependency.artifactId(), artifact, entry.getValue());
|
|
||||||
} else {
|
|
||||||
verify(artifact.toFile(), entry.getValue());
|
|
||||||
}
|
|
||||||
urls.add(artifact.toUri().toURL());
|
urls.add(artifact.toUri().toURL());
|
||||||
}
|
}
|
||||||
return urls;
|
return urls;
|
||||||
@@ -171,7 +99,7 @@ public final class NativeRuntimeLibraries {
|
|||||||
Path temporary = Files.createTempFile(artifact.getParent(), module + "-", ".tmp");
|
Path temporary = Files.createTempFile(artifact.getParent(), module + "-", ".tmp");
|
||||||
try {
|
try {
|
||||||
Files.copy(input, temporary, StandardCopyOption.REPLACE_EXISTING);
|
Files.copy(input, temporary, StandardCopyOption.REPLACE_EXISTING);
|
||||||
verify(temporary.toFile(), expected);
|
verify(temporary, expected);
|
||||||
Files.move(temporary, artifact, StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING);
|
Files.move(temporary, artifact, StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING);
|
||||||
} finally {
|
} finally {
|
||||||
Files.deleteIfExists(temporary);
|
Files.deleteIfExists(temporary);
|
||||||
@@ -187,15 +115,12 @@ public final class NativeRuntimeLibraries {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void verify(File file, String expected) {
|
static void verify(Path file, String expected) throws IOException {
|
||||||
try {
|
if (!digest(file).equals(expected)) {
|
||||||
String actual = digest(file.toPath());
|
throw new IOException("Native dependency does not match this Iris build: " + file.getFileName());
|
||||||
if (!actual.equals(expected)) {
|
|
||||||
throw new DownloaderException("Native dependency does not match this Iris build: " + file.getName());
|
|
||||||
}
|
|
||||||
} catch (IOException exception) {
|
|
||||||
throw new DownloaderException("Cannot verify native dependency: " + file, exception);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private record Provider(String module, String version, String sha256) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -33,7 +33,7 @@ public class SlimJar {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
NativeRuntimeLibraries libraries = NativeRuntimeLibraries.load(minecraftVersion);
|
NativeRuntimeLibraries libraries = NativeRuntimeLibraries.load(minecraftVersion);
|
||||||
libraries.configure(ApplicationBuilder.appending("Iris"), downloadPath)
|
ApplicationBuilder.appending("Iris")
|
||||||
.injectableFactory(InjectableFactory.selecting(
|
.injectableFactory(InjectableFactory.selecting(
|
||||||
InjectableFactory.ERROR,
|
InjectableFactory.ERROR,
|
||||||
InjectableFactory.INJECTABLE,
|
InjectableFactory.INJECTABLE,
|
||||||
@@ -78,7 +78,7 @@ public class SlimJar {
|
|||||||
Path downloadPath = plugin.getDataFolder("cache", "libraries").toPath();
|
Path downloadPath = plugin.getDataFolder("cache", "libraries").toPath();
|
||||||
debug(plugin, "Loading libraries...");
|
debug(plugin, "Loading libraries...");
|
||||||
NativeRuntimeLibraries libraries = NativeRuntimeLibraries.load(Bukkit.getBukkitVersion());
|
NativeRuntimeLibraries libraries = NativeRuntimeLibraries.load(Bukkit.getBukkitVersion());
|
||||||
libraries.configure(ApplicationBuilder.appending(plugin.getName()), downloadPath)
|
ApplicationBuilder.appending(plugin.getName())
|
||||||
.injectableFactory(InjectableFactory.selecting(InjectableFactory.ERROR, InjectableFactory.INJECTABLE,
|
.injectableFactory(InjectableFactory.selecting(InjectableFactory.ERROR, InjectableFactory.INJECTABLE,
|
||||||
InjectableFactory.WRAPPED, InjectableFactory.UNSAFE))
|
InjectableFactory.WRAPPED, InjectableFactory.UNSAFE))
|
||||||
.downloadDirectoryPath(downloadPath)
|
.downloadDirectoryPath(downloadPath)
|
||||||
|
|||||||
+26
-42
@@ -1,8 +1,5 @@
|
|||||||
package art.arcane.iris.platform.bootstrap;
|
package art.arcane.iris.platform.bootstrap;
|
||||||
|
|
||||||
import io.github.slimjar.exceptions.DownloaderException;
|
|
||||||
import io.github.slimjar.resolver.data.Dependency;
|
|
||||||
import io.github.slimjar.resolver.data.DependencyData;
|
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.rules.TemporaryFolder;
|
import org.junit.rules.TemporaryFolder;
|
||||||
@@ -28,7 +25,6 @@ import java.util.stream.Stream;
|
|||||||
import static org.junit.Assert.assertArrayEquals;
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertSame;
|
|
||||||
import static org.junit.Assert.assertThrows;
|
import static org.junit.Assert.assertThrows;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
@@ -37,37 +33,36 @@ public class NativeRuntimeLibrariesTest {
|
|||||||
public TemporaryFolder temporary = new TemporaryFolder();
|
public TemporaryFolder temporary = new TemporaryFolder();
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void selectsOnlyCommonAndMatchingProvider() throws Exception {
|
public void providersMustBeEmbedded() throws Exception {
|
||||||
Properties manifest = manifest();
|
EmbeddedFixture fixture = embeddedFixture();
|
||||||
Dependency original = new Dependency("example", "library", "1", null, List.of());
|
fixture.manifest().setProperty("storage", "repository");
|
||||||
DependencyData data = new DependencyData(List.of(), List.of(), List.of(original), List.of());
|
assertThrows(IllegalStateException.class, () -> NativeRuntimeLibraries.from(fixture.manifest(), "26.2.0"));
|
||||||
List<String> selected = NativeRuntimeLibraries.from(manifest, "26.3.0").merge(data).dependencies()
|
fixture.manifest().remove("storage");
|
||||||
.stream().map(Dependency::artifactId).sorted().toList();
|
assertThrows(IllegalStateException.class, () -> NativeRuntimeLibraries.from(fixture.manifest(), "26.2.0"));
|
||||||
assertEquals(List.of("library", "native-common", "native-v26_3_R1"), selected);
|
}
|
||||||
assertThrows(UnsupportedOperationException.class, () -> NativeRuntimeLibraries.from(manifest, "1.21.11"));
|
|
||||||
|
@Test
|
||||||
|
public void rejectsMinecraftVersionsWithoutProvider() throws Exception {
|
||||||
|
EmbeddedFixture fixture = embeddedFixture();
|
||||||
|
assertThrows(UnsupportedOperationException.class, () -> NativeRuntimeLibraries.from(fixture.manifest(), "1.21.11"));
|
||||||
|
fixture.manifest().setProperty("modules", "native-common,native-v26_2_R1");
|
||||||
|
assertThrows(UnsupportedOperationException.class, () -> NativeRuntimeLibraries.from(fixture.manifest(), "26.3.0"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void rejectsProviderBytesFromDifferentBuild() throws Exception {
|
public void rejectsProviderBytesFromDifferentBuild() throws Exception {
|
||||||
Path jar = Files.createTempFile("native-runtime", ".jar");
|
Path jar = temporary.newFile("native-runtime.jar").toPath();
|
||||||
try {
|
Files.write(jar, new byte[0]);
|
||||||
Files.write(jar, new byte[0]);
|
NativeRuntimeLibraries.verify(jar, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
|
||||||
NativeRuntimeLibraries.verify(jar.toFile(), "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
|
Files.writeString(jar, "different build");
|
||||||
Files.writeString(jar, "different build");
|
assertThrows(IOException.class, () -> NativeRuntimeLibraries.verify(jar,
|
||||||
assertThrows(DownloaderException.class, () -> NativeRuntimeLibraries.verify(jar.toFile(),
|
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"));
|
||||||
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"));
|
|
||||||
} finally {
|
|
||||||
Files.deleteIfExists(jar);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void embeddedProvidersLoadWithoutRepositoryAndSelectOnlyCurrentVersion() throws Exception {
|
public void embeddedProvidersSelectOnlyCommonAndCurrentVersion() throws Exception {
|
||||||
EmbeddedFixture fixture = embeddedFixture();
|
EmbeddedFixture fixture = embeddedFixture();
|
||||||
NativeRuntimeLibraries libraries = NativeRuntimeLibraries.from(fixture.manifest(), "26.2.0");
|
NativeRuntimeLibraries libraries = NativeRuntimeLibraries.from(fixture.manifest(), "26.2.0");
|
||||||
Dependency original = new Dependency("example", "library", "1", null, List.of());
|
|
||||||
DependencyData data = new DependencyData(List.of(), List.of(), List.of(original), List.of());
|
|
||||||
assertSame(data, libraries.merge(data));
|
|
||||||
Path downloads = temporary.newFolder("downloads").toPath();
|
Path downloads = temporary.newFolder("downloads").toPath();
|
||||||
try (URLClassLoader resources = new URLClassLoader(new URL[]{fixture.resources().toUri().toURL()}, null)) {
|
try (URLClassLoader resources = new URLClassLoader(new URL[]{fixture.resources().toUri().toURL()}, null)) {
|
||||||
List<URL> providers = libraries.providerUrls(downloads, resources);
|
List<URL> providers = libraries.providerUrls(downloads, resources);
|
||||||
@@ -125,7 +120,7 @@ public class NativeRuntimeLibrariesTest {
|
|||||||
NativeRuntimeLibraries libraries = NativeRuntimeLibraries.from(fixture.manifest(), "26.2.0");
|
NativeRuntimeLibraries libraries = NativeRuntimeLibraries.from(fixture.manifest(), "26.2.0");
|
||||||
Path downloads = temporary.newFolder("downloads").toPath();
|
Path downloads = temporary.newFolder("downloads").toPath();
|
||||||
try (URLClassLoader resources = new URLClassLoader(new URL[]{fixture.resources().toUri().toURL()}, null)) {
|
try (URLClassLoader resources = new URLClassLoader(new URL[]{fixture.resources().toUri().toURL()}, null)) {
|
||||||
DownloaderException failure = assertThrows(DownloaderException.class, () -> libraries.providerUrls(downloads, resources));
|
IOException failure = assertThrows(IOException.class, () -> libraries.providerUrls(downloads, resources));
|
||||||
assertTrue(failure.getMessage().contains("native-v26_2_R1"));
|
assertTrue(failure.getMessage().contains("native-v26_2_R1"));
|
||||||
assertNoFailedExtract(downloads);
|
assertNoFailedExtract(downloads);
|
||||||
}
|
}
|
||||||
@@ -139,12 +134,13 @@ public class NativeRuntimeLibrariesTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private EmbeddedFixture embeddedFixture() throws Exception {
|
private EmbeddedFixture embeddedFixture() throws Exception {
|
||||||
Properties properties = manifest();
|
Properties properties = new Properties();
|
||||||
|
List<String> modules = List.of("native-common", "native-v26_2_R1", "native-v26_3_R1");
|
||||||
|
properties.setProperty("modules", String.join(",", modules));
|
||||||
properties.setProperty("storage", "embedded");
|
properties.setProperty("storage", "embedded");
|
||||||
properties.remove("repository");
|
|
||||||
Path resources = temporary.newFolder("resources").toPath();
|
Path resources = temporary.newFolder("resources").toPath();
|
||||||
Path providers = Files.createDirectories(resources.resolve("META-INF/iris/native"));
|
Path providers = Files.createDirectories(resources.resolve("META-INF/iris/native"));
|
||||||
for (String module : properties.getProperty("modules").split(",")) {
|
for (String module : modules) {
|
||||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||||
try (JarOutputStream jar = new JarOutputStream(output)) {
|
try (JarOutputStream jar = new JarOutputStream(output)) {
|
||||||
jar.putNextEntry(new JarEntry("provider.txt"));
|
jar.putNextEntry(new JarEntry("provider.txt"));
|
||||||
@@ -169,16 +165,4 @@ public class NativeRuntimeLibrariesTest {
|
|||||||
|
|
||||||
private record EmbeddedFixture(Properties manifest, Path resources) {
|
private record EmbeddedFixture(Properties manifest, Path resources) {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Properties manifest() {
|
|
||||||
Properties properties = new Properties();
|
|
||||||
List<String> modules = List.of("native-common", "native-v26_2_R1", "native-v26_3_R1");
|
|
||||||
properties.setProperty("modules", String.join(",", modules));
|
|
||||||
properties.setProperty("repository", "https://jitpack.io/");
|
|
||||||
for (String module : modules) {
|
|
||||||
properties.setProperty(module + ".coordinate", "com.github.VolmitSoftware.VolmLib:" + module + ":revision");
|
|
||||||
properties.setProperty(module + ".sha256", "0".repeat(64));
|
|
||||||
}
|
|
||||||
return properties;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user