diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/McpExecutor.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/McpExecutor.java index d5275e3e..aa66b533 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/McpExecutor.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/McpExecutor.java @@ -47,6 +47,13 @@ import org.gradle.process.JavaExecSpec; import org.jetbrains.annotations.Nullable; import net.fabricmc.loom.LoomGradleExtension; +import net.fabricmc.loom.configuration.providers.forge.mcpconfig.steplogic.ConstantLogic; +import net.fabricmc.loom.configuration.providers.forge.mcpconfig.steplogic.DownloadManifestFileLogic; +import net.fabricmc.loom.configuration.providers.forge.mcpconfig.steplogic.FunctionLogic; +import net.fabricmc.loom.configuration.providers.forge.mcpconfig.steplogic.ListLibrariesLogic; +import net.fabricmc.loom.configuration.providers.forge.mcpconfig.steplogic.NoOpLogic; +import net.fabricmc.loom.configuration.providers.forge.mcpconfig.steplogic.StepLogic; +import net.fabricmc.loom.configuration.providers.forge.mcpconfig.steplogic.StripLogic; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider; import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.ForgeToolExecutor; @@ -140,16 +147,16 @@ public final class McpExecutor { private StepLogic getStepLogic(String type) { return switch (type) { - case "downloadManifest", "downloadJson" -> new StepLogic.NoOp(); - case "downloadClient" -> new StepLogic.NoOpWithFile(() -> minecraftProvider.getMinecraftClientJar().toPath()); - case "downloadServer" -> new StepLogic.NoOpWithFile(() -> minecraftProvider.getMinecraftServerJar().toPath()); - case "strip" -> new StepLogic.Strip(); - case "listLibraries" -> new StepLogic.ListLibraries(); - case "downloadClientMappings" -> new StepLogic.DownloadManifestFile(minecraftProvider.getVersionInfo().download("client_mappings")); - case "downloadServerMappings" -> new StepLogic.DownloadManifestFile(minecraftProvider.getVersionInfo().download("server_mappings")); + case "downloadManifest", "downloadJson" -> new NoOpLogic(); + case "downloadClient" -> new ConstantLogic(() -> minecraftProvider.getMinecraftClientJar().toPath()); + case "downloadServer" -> new ConstantLogic(() -> minecraftProvider.getMinecraftServerJar().toPath()); + case "strip" -> new StripLogic(); + case "listLibraries" -> new ListLibrariesLogic(); + case "downloadClientMappings" -> new DownloadManifestFileLogic(minecraftProvider.getVersionInfo().download("client_mappings")); + case "downloadServerMappings" -> new DownloadManifestFileLogic(minecraftProvider.getVersionInfo().download("server_mappings")); default -> { if (functions.containsKey(type)) { - yield new StepLogic.OfFunction(functions.get(type)); + yield new FunctionLogic(functions.get(type)); } throw new UnsupportedOperationException("MCP config step type: " + type); diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/StepLogic.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/StepLogic.java deleted file mode 100644 index f139b6b4..00000000 --- a/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/StepLogic.java +++ /dev/null @@ -1,227 +0,0 @@ -/* - * This file is part of fabric-loom, licensed under the MIT License (MIT). - * - * Copyright (c) 2022 FabricMC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package net.fabricmc.loom.configuration.providers.forge.mcpconfig; - -import java.io.File; -import java.io.IOException; -import java.io.PrintWriter; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.StandardCopyOption; -import java.util.List; -import java.util.Set; -import java.util.function.Supplier; -import java.util.jar.Attributes; -import java.util.jar.JarFile; -import java.util.stream.Collectors; - -import org.gradle.api.Action; -import org.gradle.api.logging.Logger; -import org.gradle.process.JavaExecSpec; - -import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionMeta; -import net.fabricmc.loom.util.FileSystemUtil; -import net.fabricmc.loom.util.ThreadingUtils; -import net.fabricmc.loom.util.download.DownloadBuilder; -import net.fabricmc.loom.util.function.CollectionUtil; - -/** - * The logic for executing a step. This corresponds to the {@code type} key in the step JSON format. - */ -public interface StepLogic { - void execute(ExecutionContext context) throws IOException; - - default String getDisplayName(String stepName) { - return stepName; - } - - interface ExecutionContext { - Logger logger(); - Path setOutput(String fileName) throws IOException; - Path setOutput(Path output); - /** Mappings extracted from {@code data.mappings} in the MCPConfig JSON. */ - Path mappings(); - String resolve(ConfigValue value); - Path download(String url) throws IOException; - DownloadBuilder downloadBuilder(String url); - void javaexec(Action configurator); - Set getMinecraftLibraries(); - - default List resolve(List configValues) { - return CollectionUtil.map(configValues, this::resolve); - } - } - - /** - * Runs a Forge tool configured by a {@linkplain McpConfigFunction function}. - */ - final class OfFunction implements StepLogic { - private final McpConfigFunction function; - - public OfFunction(McpConfigFunction function) { - this.function = function; - } - - @Override - public void execute(ExecutionContext context) throws IOException { - context.setOutput("output"); - Path jar = context.download(function.getDownloadUrl()); - String mainClass; - - try (JarFile jarFile = new JarFile(jar.toFile())) { - mainClass = jarFile.getManifest().getMainAttributes().getValue(Attributes.Name.MAIN_CLASS); - } catch (IOException e) { - throw new IOException("Could not determine main class for " + jar.toAbsolutePath(), e); - } - - context.javaexec(spec -> { - spec.classpath(jar); - spec.getMainClass().set(mainClass); - spec.args(context.resolve(function.args())); - spec.jvmArgs(context.resolve(function.jvmArgs())); - }); - } - - @Override - public String getDisplayName(String stepName) { - return stepName + " with " + function.version(); - } - } - - /** - * Strips certain classes from the jar. - */ - final class Strip implements StepLogic { - @Override - public void execute(ExecutionContext context) throws IOException { - Set filter = Files.readAllLines(context.mappings(), StandardCharsets.UTF_8).stream() - .filter(s -> !s.startsWith("\t")) - .map(s -> s.split(" ")[0] + ".class") - .collect(Collectors.toSet()); - - Path input = Path.of(context.resolve(new ConfigValue.Variable("input"))); - - try (FileSystemUtil.Delegate output = FileSystemUtil.getJarFileSystem(context.setOutput("stripped.jar"), true)) { - try (FileSystemUtil.Delegate fs = FileSystemUtil.getJarFileSystem(input, false)) { - ThreadingUtils.TaskCompleter completer = ThreadingUtils.taskCompleter(); - - for (Path path : (Iterable) Files.walk(fs.get().getPath("/"))::iterator) { - String trimLeadingSlash = trimLeadingSlash(path.toString()); - if (!trimLeadingSlash.endsWith(".class")) continue; - boolean has = filter.contains(trimLeadingSlash); - String s = trimLeadingSlash; - - while (s.contains("$") && !has) { - s = s.substring(0, s.lastIndexOf("$")) + ".class"; - has = filter.contains(s); - } - - if (!has) continue; - Path to = output.get().getPath(trimLeadingSlash); - Path parent = to.getParent(); - if (parent != null) Files.createDirectories(parent); - - completer.add(() -> { - Files.copy(path, to, StandardCopyOption.COPY_ATTRIBUTES); - }); - } - - completer.complete(); - } - } - } - - private static String trimLeadingSlash(String string) { - if (string.startsWith(File.separator)) { - return string.substring(File.separator.length()); - } else if (string.startsWith("/")) { - return string.substring(1); - } - - return string; - } - } - - /** - * Lists the Minecraft libraries into the output file. - */ - final class ListLibraries implements StepLogic { - @Override - public void execute(ExecutionContext context) throws IOException { - context.logger().lifecycle(":downloading minecraft libraries, this may take a while..."); - - try (PrintWriter writer = new PrintWriter(Files.newBufferedWriter(context.setOutput("libraries.txt")))) { - for (File lib : context.getMinecraftLibraries()) { - writer.println("-e=" + lib.getAbsolutePath()); - } - } - } - } - - /** - * Downloads a file from the Minecraft version metadata. - */ - final class DownloadManifestFile implements StepLogic { - private final MinecraftVersionMeta.Download download; - - public DownloadManifestFile(MinecraftVersionMeta.Download download) { - this.download = download; - } - - @Override - public void execute(ExecutionContext context) throws IOException { - context.downloadBuilder(download.url()) - .sha1(download.sha1()) - .downloadPath(context.setOutput("output")); - } - } - - /** - * A no-op step logic that is used for steps automatically executed by Loom earlier. - */ - final class NoOp implements StepLogic { - @Override - public void execute(ExecutionContext context) throws IOException { - } - } - - /** - * A no-op step logic that is used for steps automatically executed by Loom earlier. - * This one returns a file. - */ - final class NoOpWithFile implements StepLogic { - private final Supplier path; - - public NoOpWithFile(Supplier path) { - this.path = path; - } - - @Override - public void execute(ExecutionContext context) throws IOException { - context.setOutput(path.get()); - } - } -} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/steplogic/ConstantLogic.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/steplogic/ConstantLogic.java new file mode 100644 index 00000000..964c85fb --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/steplogic/ConstantLogic.java @@ -0,0 +1,46 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2022 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.configuration.providers.forge.mcpconfig.steplogic; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.function.Supplier; + +/** + * A no-op step logic that is used for steps automatically executed by Loom earlier. + * This one returns a file. + */ +public final class ConstantLogic implements StepLogic { + private final Supplier path; + + public ConstantLogic(Supplier path) { + this.path = path; + } + + @Override + public void execute(ExecutionContext context) throws IOException { + context.setOutput(path.get()); + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/steplogic/DownloadManifestFileLogic.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/steplogic/DownloadManifestFileLogic.java new file mode 100644 index 00000000..2f2531c1 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/steplogic/DownloadManifestFileLogic.java @@ -0,0 +1,47 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2022 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.configuration.providers.forge.mcpconfig.steplogic; + +import java.io.IOException; + +import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionMeta; + +/** + * Downloads a file from the Minecraft version metadata. + */ +public final class DownloadManifestFileLogic implements StepLogic { + private final MinecraftVersionMeta.Download download; + + public DownloadManifestFileLogic(MinecraftVersionMeta.Download download) { + this.download = download; + } + + @Override + public void execute(ExecutionContext context) throws IOException { + context.downloadBuilder(download.url()) + .sha1(download.sha1()) + .downloadPath(context.setOutput("output")); + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/steplogic/FunctionLogic.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/steplogic/FunctionLogic.java new file mode 100644 index 00000000..8544a1a9 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/steplogic/FunctionLogic.java @@ -0,0 +1,68 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2022 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.configuration.providers.forge.mcpconfig.steplogic; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.jar.Attributes; +import java.util.jar.JarFile; + +import net.fabricmc.loom.configuration.providers.forge.mcpconfig.McpConfigFunction; + +/** + * Runs a Forge tool configured by a {@linkplain McpConfigFunction function}. + */ +public final class FunctionLogic implements StepLogic { + private final McpConfigFunction function; + + public FunctionLogic(McpConfigFunction function) { + this.function = function; + } + + @Override + public void execute(ExecutionContext context) throws IOException { + context.setOutput("output"); + Path jar = context.download(function.getDownloadUrl()); + String mainClass; + + try (JarFile jarFile = new JarFile(jar.toFile())) { + mainClass = jarFile.getManifest().getMainAttributes().getValue(Attributes.Name.MAIN_CLASS); + } catch (IOException e) { + throw new IOException("Could not determine main class for " + jar.toAbsolutePath(), e); + } + + context.javaexec(spec -> { + spec.classpath(jar); + spec.getMainClass().set(mainClass); + spec.args(context.resolve(function.args())); + spec.jvmArgs(context.resolve(function.jvmArgs())); + }); + } + + @Override + public String getDisplayName(String stepName) { + return stepName + " with " + function.version(); + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/steplogic/ListLibrariesLogic.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/steplogic/ListLibrariesLogic.java new file mode 100644 index 00000000..12721dfc --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/steplogic/ListLibrariesLogic.java @@ -0,0 +1,46 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2022 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.configuration.providers.forge.mcpconfig.steplogic; + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.nio.file.Files; + +/** + * Lists the Minecraft libraries into the output file. + */ +public final class ListLibrariesLogic implements StepLogic { + @Override + public void execute(ExecutionContext context) throws IOException { + context.logger().lifecycle(":downloading minecraft libraries, this may take a while..."); + + try (PrintWriter writer = new PrintWriter(Files.newBufferedWriter(context.setOutput("libraries.txt")))) { + for (File lib : context.getMinecraftLibraries()) { + writer.println("-e=" + lib.getAbsolutePath()); + } + } + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/steplogic/NoOpLogic.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/steplogic/NoOpLogic.java new file mode 100644 index 00000000..ce54f333 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/steplogic/NoOpLogic.java @@ -0,0 +1,36 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2022 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.configuration.providers.forge.mcpconfig.steplogic; + +import java.io.IOException; + +/** + * A no-op step logic that is used for steps automatically executed by Loom earlier. + */ +public final class NoOpLogic implements StepLogic { + @Override + public void execute(ExecutionContext context) throws IOException { + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/steplogic/StepLogic.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/steplogic/StepLogic.java new file mode 100644 index 00000000..71a72f88 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/steplogic/StepLogic.java @@ -0,0 +1,68 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2022 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.configuration.providers.forge.mcpconfig.steplogic; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.util.List; +import java.util.Set; + +import org.gradle.api.Action; +import org.gradle.api.logging.Logger; +import org.gradle.process.JavaExecSpec; + +import net.fabricmc.loom.configuration.providers.forge.mcpconfig.ConfigValue; +import net.fabricmc.loom.util.download.DownloadBuilder; +import net.fabricmc.loom.util.function.CollectionUtil; + +/** + * The logic for executing a step. This corresponds to the {@code type} key in the step JSON format. + */ +public interface StepLogic { + void execute(ExecutionContext context) throws IOException; + + default String getDisplayName(String stepName) { + return stepName; + } + + interface ExecutionContext { + Logger logger(); + Path setOutput(String fileName) throws IOException; + Path setOutput(Path output); + /** Mappings extracted from {@code data.mappings} in the MCPConfig JSON. */ + Path mappings(); + String resolve(ConfigValue value); + Path download(String url) throws IOException; + DownloadBuilder downloadBuilder(String url); + void javaexec(Action configurator); + Set getMinecraftLibraries(); + + default List resolve(List configValues) { + return CollectionUtil.map(configValues, this::resolve); + } + } + +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/steplogic/StripLogic.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/steplogic/StripLogic.java new file mode 100644 index 00000000..59074768 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/steplogic/StripLogic.java @@ -0,0 +1,92 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2022 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.configuration.providers.forge.mcpconfig.steplogic; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.util.Set; +import java.util.stream.Collectors; + +import net.fabricmc.loom.configuration.providers.forge.mcpconfig.ConfigValue; +import net.fabricmc.loom.util.FileSystemUtil; +import net.fabricmc.loom.util.ThreadingUtils; + +/** + * Strips certain classes from the jar. + */ +public final class StripLogic implements StepLogic { + @Override + public void execute(ExecutionContext context) throws IOException { + Set filter = Files.readAllLines(context.mappings(), StandardCharsets.UTF_8).stream() + .filter(s -> !s.startsWith("\t")) + .map(s -> s.split(" ")[0] + ".class") + .collect(Collectors.toSet()); + + Path input = Path.of(context.resolve(new ConfigValue.Variable("input"))); + + try (FileSystemUtil.Delegate output = FileSystemUtil.getJarFileSystem(context.setOutput("stripped.jar"), true)) { + try (FileSystemUtil.Delegate fs = FileSystemUtil.getJarFileSystem(input, false)) { + ThreadingUtils.TaskCompleter completer = ThreadingUtils.taskCompleter(); + + for (Path path : (Iterable) Files.walk(fs.get().getPath("/"))::iterator) { + String trimLeadingSlash = trimLeadingSlash(path.toString()); + if (!trimLeadingSlash.endsWith(".class")) continue; + boolean has = filter.contains(trimLeadingSlash); + String s = trimLeadingSlash; + + while (s.contains("$") && !has) { + s = s.substring(0, s.lastIndexOf("$")) + ".class"; + has = filter.contains(s); + } + + if (!has) continue; + Path to = output.get().getPath(trimLeadingSlash); + Path parent = to.getParent(); + if (parent != null) Files.createDirectories(parent); + + completer.add(() -> { + Files.copy(path, to, StandardCopyOption.COPY_ATTRIBUTES); + }); + } + + completer.complete(); + } + } + } + + private static String trimLeadingSlash(String string) { + if (string.startsWith(File.separator)) { + return string.substring(File.separator.length()); + } else if (string.startsWith("/")) { + return string.substring(1); + } + + return string; + } +}