From 1ae3f80125b0f9e3f8a0a521ba2f47fd26a60697 Mon Sep 17 00:00:00 2001 From: Sebastian Hartte Date: Fri, 13 Dec 2024 12:51:26 +0100 Subject: [PATCH] Post merge fixes --- build.gradle | 2 +- proguard.conf | 5 +- settings.gradle | 4 + .../cli/{ConsoleTool.java => Main.java} | 4 +- .../installertools/tasks/BinaryPatcher.java | 30 ++++ .../installertools/tasks/McpData.java | 6 +- .../installertools/tasks/SplitJar.java | 15 +- .../neoforged/installertools/tasks/Tasks.java | 2 + .../installertools/tasks/ZipInject.java | 166 ------------------ .../installertools/tasks/ZipInjectTest.java | 146 --------------- 10 files changed, 52 insertions(+), 328 deletions(-) rename src/main/java/net/neoforged/installertools/cli/{ConsoleTool.java => Main.java} (96%) create mode 100644 src/main/java/net/neoforged/installertools/tasks/BinaryPatcher.java delete mode 100644 src/main/java/net/neoforged/installertools/tasks/ZipInject.java delete mode 100644 src/test/java/net/neoforged/installertools/tasks/ZipInjectTest.java diff --git a/build.gradle b/build.gradle index 2d26c49..5d5bfc4 100644 --- a/build.gradle +++ b/build.gradle @@ -122,7 +122,7 @@ tasks.register('proguardJar', proguard.gradle.ProGuardTask) { } libraryjars(configurations.compileClasspath) - injars shadowJar.archiveFile + injars(["filter":"!META-INF/maven/**/*"], shadowJar.archiveFile) outjars proguardFile configuration file("proguard.conf") } diff --git a/proguard.conf b/proguard.conf index dae9fb9..a14ab1a 100644 --- a/proguard.conf +++ b/proguard.conf @@ -4,4 +4,7 @@ -dontobfuscate -dontoptimize --keep class net.neoforged.installertools.cli.ConsoleTool { *; } + +-keep class net.neoforged.installertools.cli.Main { + public static void main(java.lang.String[]); +} diff --git a/settings.gradle b/settings.gradle index a19c7b1..ade516b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -9,6 +9,10 @@ pluginManagement { } } +plugins { + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.9.0' +} + dependencyResolutionManagement { versionCatalogs { libs { diff --git a/src/main/java/net/neoforged/installertools/cli/ConsoleTool.java b/src/main/java/net/neoforged/installertools/cli/Main.java similarity index 96% rename from src/main/java/net/neoforged/installertools/cli/ConsoleTool.java rename to src/main/java/net/neoforged/installertools/cli/Main.java index c0b2195..9f93cfb 100644 --- a/src/main/java/net/neoforged/installertools/cli/ConsoleTool.java +++ b/src/main/java/net/neoforged/installertools/cli/Main.java @@ -28,9 +28,7 @@ import com.google.gson.GsonBuilder; import net.neoforged.installertools.tasks.Tasks; -public class ConsoleTool { - public static final Gson GSON = new GsonBuilder().create(); - +public class Main { public static void main(String[] args) throws IOException { Tasks task = null; String valid = Arrays.stream(Tasks.class.getEnumConstants()).map(Enum::name).collect(Collectors.joining(", ")); diff --git a/src/main/java/net/neoforged/installertools/tasks/BinaryPatcher.java b/src/main/java/net/neoforged/installertools/tasks/BinaryPatcher.java new file mode 100644 index 0000000..ef5998f --- /dev/null +++ b/src/main/java/net/neoforged/installertools/tasks/BinaryPatcher.java @@ -0,0 +1,30 @@ +/* + * InstallerTools + * Copyright (c) 2019-2024. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package net.neoforged.installertools.tasks; + +import net.neoforged.installertools.binarypatcher.ConsoleTool; + +import java.io.IOException; + +public class BinaryPatcher extends Task { + @Override + public void process(String[] args) throws IOException { + ConsoleTool.main(args); + } +} diff --git a/src/main/java/net/neoforged/installertools/tasks/McpData.java b/src/main/java/net/neoforged/installertools/tasks/McpData.java index fce4f95..850e830 100644 --- a/src/main/java/net/neoforged/installertools/tasks/McpData.java +++ b/src/main/java/net/neoforged/installertools/tasks/McpData.java @@ -32,13 +32,15 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipFile; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; import joptsimple.OptionException; import joptsimple.OptionParser; import joptsimple.OptionSet; import joptsimple.OptionSpec; -import net.neoforged.installertools.cli.ConsoleTool; public class McpData extends Task { + public static final Gson GSON = new GsonBuilder().create(); @SuppressWarnings("unchecked") @Override @@ -75,7 +77,7 @@ public void process(String[] args) throws IOException { error("Input zip file invalid, missing 'config.json' entry"); try (InputStream cfgStream = zip.getInputStream(config)) { - McpConfig cfg = ConsoleTool.GSON.fromJson(new InputStreamReader(zip.getInputStream(config)), McpConfig.class); + McpConfig cfg = GSON.fromJson(new InputStreamReader(cfgStream), McpConfig.class); if (cfg.data == null) error("Invalid mcp config, missing data map"); diff --git a/src/main/java/net/neoforged/installertools/tasks/SplitJar.java b/src/main/java/net/neoforged/installertools/tasks/SplitJar.java index 63fc405..35d32df 100644 --- a/src/main/java/net/neoforged/installertools/tasks/SplitJar.java +++ b/src/main/java/net/neoforged/installertools/tasks/SplitJar.java @@ -44,14 +44,15 @@ import net.neoforged.installertools.cli.progress.ProgressReporter; import net.neoforged.srgutils.IMappingFile; -public class SplitJar { +public class SplitJar extends Task { private static final OutputStream NULL_OUTPUT = new OutputStream() { @Override public void write(int b) {} }; private static final boolean DEBUG = Boolean.getBoolean("net.neoforged.jarsplitter.debug"); private static final ProgressManager PROGRESS = ProgressReporter.getDefault(); - public static void main(String[] args) throws IOException { + @Override + public void process(String[] args) throws IOException { TimeZone.setDefault(TimeZone.getTimeZone("GMT")); //Fix Java stupidity that causes timestamps in zips to depend on user's timezone! OptionParser parser = new OptionParser(); // Shared arguments @@ -172,11 +173,11 @@ private static void writeCache(File file, String inputSha, String srgSha) throws Files.write(cacheFile.toPath(), cache); } - private static File checkOutput(String name, File file, String inputSha, String srgSha) throws IOException { + private File checkOutput(String name, File file, String inputSha, String srgSha) throws IOException { return checkOutput(name, file, inputSha, srgSha, null); } - private static File checkOutput(String name, File file, String inputSha, String srgSha, String extra) throws IOException { + private File checkOutput(String name, File file, String inputSha, String srgSha, String extra) throws IOException { if (file == null) return null; file = file.getCanonicalFile(); @@ -202,11 +203,7 @@ private static File checkOutput(String name, File file, String inputSha, String return file; } - public static void log(String message) { - System.out.println(message); - } - - public static void debug(String message) { + public void debug(String message) { if (DEBUG) { log(message); } diff --git a/src/main/java/net/neoforged/installertools/tasks/Tasks.java b/src/main/java/net/neoforged/installertools/tasks/Tasks.java index 97d24ae..84af862 100644 --- a/src/main/java/net/neoforged/installertools/tasks/Tasks.java +++ b/src/main/java/net/neoforged/installertools/tasks/Tasks.java @@ -31,6 +31,8 @@ public enum Tasks { DOWNLOAD_MOJMAPS(DownloadMojmaps::new), EXTRACT_FILES(ExtractFiles::new), BUNDLER_EXTRACT(BundlerExtract::new), + BINARY_PATCHER(BinaryPatcher::new), + SPLIT_JAR(SplitJar::new) ; private Supplier supplier; diff --git a/src/main/java/net/neoforged/installertools/tasks/ZipInject.java b/src/main/java/net/neoforged/installertools/tasks/ZipInject.java deleted file mode 100644 index ad73577..0000000 --- a/src/main/java/net/neoforged/installertools/tasks/ZipInject.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * InstallerTools - * Copyright (c) 2019-2024. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package net.neoforged.installertools.tasks; - -import joptsimple.OptionException; -import joptsimple.OptionParser; -import joptsimple.OptionSet; -import joptsimple.OptionSpec; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.UncheckedIOException; -import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.nio.file.FileSystem; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.TimeZone; -import java.util.stream.Stream; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; -import java.util.zip.ZipOutputStream; - -public class ZipInject { - public static void main(String[] args) throws Exception { - TimeZone.setDefault(TimeZone.getTimeZone("GMT")); - OptionParser parser = new OptionParser(); - OptionSpec baseO = parser.accepts("base", "The base zip to inject into").withRequiredArg().ofType(File.class).required(); - OptionSpec outputO = parser.accepts("output", "The location of the output zip").withRequiredArg().ofType(File.class).required(); - OptionSpec injectO = parser.accepts("inject", "A zip or directory to inject").withRequiredArg().ofType(File.class); - OptionSpec sourcePrefixO = parser.accepts("path-prefix", "A prefix to strip from source file paths").withRequiredArg(); - OptionSpec packageInfoPackagesO = parser.accepts("inject-package-info", "A prefix that packages that should contain a package-info have").withRequiredArg().ofType(String.class); - - try { - OptionSet options = parser.parse(args); - List injects = options.valuesOf(injectO); - List injectRoots = new ArrayList<>(); - for (File inject : injects) { - if (!inject.isDirectory()) { - if (!inject.exists()) { - throw new IllegalArgumentException("Injection path " + inject + " doesn't exist"); - } - try { - FileSystem fs = FileSystems.newFileSystem(URI.create("jar:" + inject.toURI()), Collections.emptyMap()); - injectRoots.add(fs.getRootDirectories().iterator().next()); - } catch (Exception exception) { - throw new IllegalArgumentException("Injection path " + inject + " is not a zip", exception); - } - } else { - injectRoots.add(inject.toPath().toAbsolutePath()); - } - } - - String packageInfoTemplate = null; - if (options.has(packageInfoPackagesO)) { - packageInfoTemplate = findPackageInfoTemplate(injectRoots); - } - - String sourcePrefix = options.has(sourcePrefixO) ? options.valueOf(sourcePrefixO) : null; - - try (ZipOutputStream zos = new ZipOutputStream(Files.newOutputStream(options.valueOf(outputO).toPath()))) { - copyInputZipContent(options.valueOf(baseO).toPath(), zos, packageInfoTemplate, options.valuesOf(packageInfoPackagesO)); - - for (Path folder : injectRoots) { - try (Stream stream = Files.walk(folder).sorted()) { - stream.filter(Files::isRegularFile).forEach(path -> { - String outputPath = folder.relativize(path).toString().replace('\\', '/'); - try { - if (sourcePrefix != null && outputPath.startsWith(sourcePrefix)) { - outputPath = outputPath.substring(sourcePrefix.length()); - if (outputPath.isEmpty()) return; - } else if (outputPath.equals("package-info-template.java")) { - // Don't include the template file in the output - return; - } - zos.putNextEntry(new ZipEntry(outputPath)); - Files.copy(path, zos); - zos.closeEntry(); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - }); - } - } - } - - // Now close the opened zip file systems - for (Path injectRoot : injectRoots) { - if (injectRoot.getFileSystem().provider().getScheme().equals("jar")) { - injectRoot.getFileSystem().close(); - } - } - } catch (OptionException e) { - parser.printHelpOn(System.out); - e.printStackTrace(); - } - } - - private static String findPackageInfoTemplate(List roots) throws IOException { - // Try to find a package-info-template.java - for (Path injectedSource : roots) { - Path subPath = injectedSource.resolve("package-info-template.java"); - if (Files.isRegularFile(subPath)) { - return new String(Files.readAllBytes(subPath), StandardCharsets.UTF_8); - } - } - return null; - } - - private static void copyInputZipContent(Path inputZipFile, ZipOutputStream zos, String packageInfoTemplateContent, List packagePrefixes) throws IOException { - Set visited = new HashSet<>(); - try (ZipInputStream zis = new ZipInputStream(Files.newInputStream(inputZipFile))) { - ZipEntry entry; - while ((entry = zis.getNextEntry()) != null) { - zos.putNextEntry(entry); - copy(zis, zos); - zos.closeEntry(); - - if (packageInfoTemplateContent != null) { - String pkg = entry.isDirectory() && !entry.getName().endsWith("/") ? entry.getName() : (entry.getName().indexOf('/') == -1 ? "" : entry.getName().substring(0, entry.getName().lastIndexOf('/'))); - if (visited.add(pkg)) { - for (String prefix : packagePrefixes) { - if (pkg.startsWith(prefix)) { - zos.putNextEntry(new ZipEntry(pkg + "/package-info.java")); - zos.write(packageInfoTemplateContent.replace("{PACKAGE}", pkg.replaceAll("/", ".")).getBytes(StandardCharsets.UTF_8)); - zos.closeEntry(); - break; - } - } - } - } - } - } - } - - public static void copy(InputStream input, OutputStream output) throws IOException { - byte[] buffer = new byte[1024]; - int read; - while ((read = input.read(buffer)) != -1) - output.write(buffer, 0, read); - } -} diff --git a/src/test/java/net/neoforged/installertools/tasks/ZipInjectTest.java b/src/test/java/net/neoforged/installertools/tasks/ZipInjectTest.java deleted file mode 100644 index 6c98929..0000000 --- a/src/test/java/net/neoforged/installertools/tasks/ZipInjectTest.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * InstallerTools - * Copyright (c) 2019-2024. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package net.neoforged.installertools.tasks; - -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.io.TempDir; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Enumeration; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; -import java.util.zip.ZipOutputStream; - -public class ZipInjectTest { - @TempDir - File tempDir; - - @Test - void testInjectDir() throws Exception { - final Path injectDir = tempDir.toPath().resolve("injection"); - Files.createDirectories(injectDir); - - Files.write(injectDir.resolve("a.txt"), "file a".getBytes(StandardCharsets.UTF_8)); - Files.write(injectDir.resolve("b.txt"), "file b".getBytes(StandardCharsets.UTF_8)); - - final File base = new File(tempDir, "base.zip"); - writeJar(base, "c.txt", "file c", "d.txt", "file d"); - - final File out = new File(tempDir, "out.zip"); - invoke("--base", base, "--output", out, "--inject", injectDir); - - assertContents(new ZipFile(out), "c.txt", "file c", "d.txt", "file d", "a.txt", "file a", "b.txt", "file b"); - } - - @Test - void testInjectZip() throws Exception { - final File base = new File(tempDir, "base.zip"); - writeJar(base, "c.txt", "file c", "d.txt", "file d"); - - final File inject = new File(tempDir, "inject.zip"); - writeJar(inject, "e.txt", "yes it's e"); - - final File out = new File(tempDir, "out.zip"); - invoke("--base", base, "--output", out, "--inject", inject); - - assertContents(new ZipFile(out), "c.txt", "file c", "d.txt", "file d", "e.txt", "yes it's e"); - } - - @Test - void testInjectWithPrefix() throws Exception { - final File base = new File(tempDir, "base.zip"); - writeJar(base, "c.txt", "file c", "d.txt", "file d"); - - final File inject = new File(tempDir, "inject.zip"); - writeJar(inject, "correct/e.txt", "yes it's e", "correct/sub/f.txt", "sub file"); - - final File out = new File(tempDir, "out.zip"); - invoke("--base", base, "--output", out, "--inject", inject, "--path-prefix", "correct/"); - - assertContents(new ZipFile(out), "c.txt", "file c", "d.txt", "file d", "e.txt", "yes it's e", "sub/f.txt", "sub file"); - } - - @Test - void testInjectPackageInfo() throws Exception { - final File base = new File(tempDir, "base.zip"); - writeJar(base, "com/mojang/A.file", "a file", "com/notmojang/B.file", "b file"); - - final File inject = new File(tempDir, "inject.zip"); - writeJar(inject, "package-info-template.java", "package {PACKAGE};"); - - final File out = new File(tempDir, "out.zip"); - invoke("--base", base, "--output", out, "--inject", inject, "--inject-package-info", "com/mojang"); - - assertContents(new ZipFile(out), "com/mojang/A.file", "a file", "com/mojang/package-info.java", "package com.mojang;", "com/notmojang/B.file", "b file"); - } - - private static void assertContents(ZipFile file, String... entries) throws IOException { - Map expectedFiles = new LinkedHashMap<>(); - for (int i = 0; i < entries.length; i += 2) { - expectedFiles.put(entries[i], entries[i + 1]); - } - - Map actualFiles = new LinkedHashMap<>(); - Enumeration contained = file.entries(); - while (contained.hasMoreElements()) { - ZipEntry entry = contained.nextElement(); - if (entry.isDirectory()) continue; - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - ZipInject.copy(file.getInputStream(entry), bos); - actualFiles.put(entry.getName(), new String(bos.toByteArray(), StandardCharsets.UTF_8)); - } - file.close(); - - Assertions.assertThat(actualFiles) - .containsExactlyEntriesOf(expectedFiles); - } - - private static void writeJar(File location, String... entries) throws IOException { - try (final ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(location))) { - for (int i = 0; i < entries.length; i += 2) { - zos.putNextEntry(new ZipEntry(entries[i])); - zos.write(entries[i + 1].getBytes(StandardCharsets.UTF_8)); - zos.closeEntry(); - } - } - } - - private static void invoke(Object... args) throws Exception { - final String[] finalArgs = new String[args.length]; - for (int i = 0; i < args.length; i++) { - if (args[i] instanceof File) { - finalArgs[i] = ((File) args[i]).getAbsolutePath(); - } else if (args[i] instanceof Path) { - finalArgs[i] = ((Path) args[i]).toAbsolutePath().toString(); - } else { - finalArgs[i] = args[i].toString(); - } - } - ZipInject.main(finalArgs); - } -}