From c9dc829903b71062b14756e44845cedeaccece02 Mon Sep 17 00:00:00 2001 From: Toffikk Date: Fri, 24 Apr 2026 21:07:10 +0200 Subject: [PATCH 1/3] Allow for declaring an oldForkCommit to bring in objects from the active fork for 3 way apply. This PR extends the updatingMinecraft {} extension by introducing a new oldForkCommit property. When configured, oldForkCommit behaves similarly to oldPaperCommit, but it targets the active fork defined in the build script rather than Paper. The main motivation for this change is that the existing oldPaperCommit mechanism often doesn't bring in enough objects, particularly in nested fork chains (e.g., fork-of-a-fork scenarios), but sometimes in simple Paper forks too, which causes 3-way patch application to fail. It also enables patch roulette for minecraft source patches for forks, so the ones that host their own instance of it can also have some fun with it and use it to ease their updates. --- .../paperweight/core/PaperweightCore.kt | 21 ++++ .../extension/UpdatingMinecraftExtension.kt | 1 + .../taskcontainers/MinecraftPatchingTasks.kt | 6 ++ .../core/tasks/SetupForkMinecraftSources.kt | 99 +++++++++++++++++++ .../paperweight/util/constants/constants.kt | 2 +- 5 files changed, 128 insertions(+), 1 deletion(-) diff --git a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/PaperweightCore.kt b/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/PaperweightCore.kt index 00009043b..19a97c5e6 100644 --- a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/PaperweightCore.kt +++ b/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/PaperweightCore.kt @@ -28,6 +28,7 @@ import io.papermc.paperweight.core.extension.PaperweightCoreExtension import io.papermc.paperweight.core.taskcontainers.CoreTasks import io.papermc.paperweight.core.taskcontainers.DevBundleTasks import io.papermc.paperweight.core.taskcontainers.PaperclipTasks +import io.papermc.paperweight.core.tasks.patching.ApplyFilePatches import io.papermc.paperweight.core.tasks.patchroulette.PatchRouletteTasks import io.papermc.paperweight.core.util.coreExt import io.papermc.paperweight.tasks.* @@ -197,6 +198,26 @@ abstract class PaperweightCore : Plugin { coreExt.paper.rejectsDir, layout.projectDirectory.dir("src/minecraft/java"), ) + } else if (coreExt.activeFork.isPresent && coreExt.updatingMinecraft.oldForkCommit.isPresent) { + // old commit fetching for forks through a gradle property + target.tasks.named("applyMinecraftSourcePatches").configure { + additionalRemote = coreExt.activeFork.map { fork -> + layout.cache + .resolve( + "$PAPER_PATH/old${fork.name.capitalized()}/${coreExt.updatingMinecraft.oldForkCommit.get()}/${fork.name}-server/src/minecraft/java" + ) + .absolutePathString() + } + emitRejects = false + } + + PatchRouletteTasks( + target, + name.lowercase(), + coreExt.minecraftVersion, + coreExt.activeFork.flatMap { it.rejectsDir }, + layout.projectDirectory.dir("src/minecraft/java"), + ) } } } diff --git a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/extension/UpdatingMinecraftExtension.kt b/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/extension/UpdatingMinecraftExtension.kt index d8164ffc1..87f7577a5 100644 --- a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/extension/UpdatingMinecraftExtension.kt +++ b/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/extension/UpdatingMinecraftExtension.kt @@ -26,4 +26,5 @@ import org.gradle.api.provider.Property interface UpdatingMinecraftExtension { val oldPaperCommit: Property + val oldForkCommit: Property } diff --git a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/taskcontainers/MinecraftPatchingTasks.kt b/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/taskcontainers/MinecraftPatchingTasks.kt index 8de9acb5a..dad7d6915 100644 --- a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/taskcontainers/MinecraftPatchingTasks.kt +++ b/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/taskcontainers/MinecraftPatchingTasks.kt @@ -30,6 +30,7 @@ import io.papermc.paperweight.core.tasks.patching.ApplyFilePatches import io.papermc.paperweight.core.tasks.patching.ApplyFilePatchesFuzzy import io.papermc.paperweight.core.tasks.patching.FixupFilePatches import io.papermc.paperweight.core.tasks.patching.RebuildFilePatches +import io.papermc.paperweight.core.util.coreExt import io.papermc.paperweight.tasks.* import io.papermc.paperweight.util.* import io.papermc.paperweight.util.constants.* @@ -167,6 +168,11 @@ class MinecraftPatchingTasks( outputDir.set(layout.cache.resolve(paperTaskOutput())) identifier.set(configName) + if (namePart == "Minecraft") { + oldCommit.convention(project.coreExt.updatingMinecraft.oldForkCommit) + oldOutputDir.set(layout.cache.resolve("$PAPER_PATH/old${configName.capitalized()}")) + } + libraryImports.set(importLibFiles.flatMap { it.outputDir }) atFile.set(mergeCollectedAts.flatMap { it.outputFile }) ats.jst.from(project.configurations.named(JST_CONFIG)) diff --git a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/tasks/SetupForkMinecraftSources.kt b/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/tasks/SetupForkMinecraftSources.kt index 673a0b94d..50bd7bf90 100644 --- a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/tasks/SetupForkMinecraftSources.kt +++ b/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/tasks/SetupForkMinecraftSources.kt @@ -22,12 +22,17 @@ package io.papermc.paperweight.core.tasks +import io.papermc.paperweight.PaperweightException import io.papermc.paperweight.core.util.ApplySourceATs +import io.papermc.paperweight.core.util.coreExt import io.papermc.paperweight.tasks.* import io.papermc.paperweight.util.* import io.papermc.paperweight.util.constants.paperTaskOutput +import java.util.concurrent.TimeUnit import kotlin.io.path.* import org.eclipse.jgit.api.Git +import org.eclipse.jgit.api.ResetCommand +import org.eclipse.jgit.transport.URIish import org.gradle.api.file.DirectoryProperty import org.gradle.api.file.RegularFileProperty import org.gradle.api.provider.Property @@ -49,6 +54,10 @@ abstract class SetupForkMinecraftSources : JavaLauncherTask() { @get:OutputDirectory abstract val outputDir: DirectoryProperty + @get:OutputDirectory + @get:Optional + abstract val oldOutputDir: DirectoryProperty + @get:Internal abstract val atWorkingDir: DirectoryProperty @@ -66,9 +75,17 @@ abstract class SetupForkMinecraftSources : JavaLauncherTask() { @get:Input abstract val identifier: Property + @get:Internal + abstract val forkName: Property + + @get:Input + @get:Optional + abstract val oldCommit: Property + override fun init() { super.init() atWorkingDir.set(layout.cache.resolve(paperTaskOutput(name = "${name}_atWorkingDir"))) + forkName.convention(project.coreExt.activeFork.map { it.name.capitalized() }) } @TaskAction @@ -78,6 +95,10 @@ abstract class SetupForkMinecraftSources : JavaLauncherTask() { val git = Git.open(outputDir.path.toFile()) + if (oldCommit.isPresent) { + setupOld() + } + if (atFile.isPresent && atFile.path.readText().isNotBlank()) { println("Applying access transformers...") ats.run( @@ -104,4 +125,82 @@ abstract class SetupForkMinecraftSources : JavaLauncherTask() { git.close() } + + private fun setupOld() { + val name = forkName.get() + logger.lifecycle("Setting up $name commit ${oldCommit.get()} to use as base for 3-way apply...") + + val rootProjectDir = layout.projectDirectory.dir("../").path + val oldDir = oldOutputDir.get().path.resolve(oldCommit.get()) + val oldLog = oldOutputDir.get().path.resolve("${oldCommit.get()}.log") + + val oldGit: Git + if (oldDir.exists()) { + oldGit = Git.open(oldDir.toFile()) + } else { + oldDir.createParentDirectories() + oldGit = Git.init() + .setDirectory(oldDir.toFile()) + .setInitialBranch("main") + .call() + oldGit.remoteRemove().setRemoteName("origin").call() + oldGit.remoteAdd().setName("origin").setUri(URIish(rootProjectDir.absolutePathString())).call() + } + + val upstream = Git.open(rootProjectDir.toFile()) + val upstreamConfig = upstream.repository.config + val upstreamReachableSHA1 = upstreamConfig.getString("uploadpack", null, "allowreachablesha1inwant") + val upstreamConfigContainsUploadPack = upstreamConfig.sections.contains("uploadpack") + try { + // Temporarily allow fetching reachable sha1 refs from the "upstream" repository. + upstreamConfig.setBoolean("uploadpack", null, "allowreachablesha1inwant", true) + upstreamConfig.save() + oldGit.fetch().setDepth(1).setRemote("origin").setRefSpecs(oldCommit.get()).call() + oldGit.reset().setMode(ResetCommand.ResetType.HARD).setRef(oldCommit.get()).call() + } finally { + if (upstreamReachableSHA1 == null) { + if (upstreamConfigContainsUploadPack) { + upstreamConfig.unset("uploadpack", null, "allowreachablesha1inwant") + } else { + upstreamConfig.unsetSection("uploadpack", null) + } + } else { + upstreamConfig.setString("uploadpack", null, "allowreachablesha1inwant", upstreamReachableSHA1) + } + upstreamConfig.save() + upstream.close() + } + + oldGit.close() + + val isWindows = System.getProperty("os.name").lowercase().contains("win") + oldLog.outputStream().use { logOut -> + val args = arrayOf( + "applyAllPatches", + "--console", + "plain", + "--stacktrace", + "-Dpaperweight.debug=true" + ) + val command = if (isWindows) { + listOf("cmd.exe", "/C", "gradlew.bat " + args.joinToString(" ")) + } else { + listOf("./gradlew", *args) + } + val processBuilder = ProcessBuilder(command) + processBuilder.directory(oldDir) + val process = processBuilder.start() + + val outFuture = redirect(process.inputStream, logOut) + val errFuture = redirect(process.errorStream, logOut) + + val exit = process.waitFor() + outFuture.get(500L, TimeUnit.MILLISECONDS) + errFuture.get(500L, TimeUnit.MILLISECONDS) + + if (exit != 0) { + throw PaperweightException("Failed to apply old $name, see log at $oldLog") + } + } + } } diff --git a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/util/constants/constants.kt b/paperweight-lib/src/main/kotlin/io/papermc/paperweight/util/constants/constants.kt index fc8c114a3..44c03d027 100644 --- a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/util/constants/constants.kt +++ b/paperweight-lib/src/main/kotlin/io/papermc/paperweight/util/constants/constants.kt @@ -65,7 +65,7 @@ const val PLUGIN_REMAPPER_REPO_NAME = "paperweightPluginRemapperRepository" const val MACHE_REPO_NAME = "paperweightMacheRepository" const val CACHE_PATH = "caches" -private const val PAPER_PATH = "paperweight" +const val PAPER_PATH = "paperweight" const val LOCK_DIR = "$PAPER_PATH/lock" const val USERDEV_SETUP_LOCK = "$LOCK_DIR/userdev/setup.lock" From f700a772759eaf6a94cf029ed61c16ca1b746210 Mon Sep 17 00:00:00 2001 From: "tofik.07" Date: Sat, 25 Apr 2026 21:56:35 +0200 Subject: [PATCH 2/3] fixup --- .../main/kotlin/io/papermc/paperweight/core/PaperweightCore.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/PaperweightCore.kt b/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/PaperweightCore.kt index 19a97c5e6..c8112c35f 100644 --- a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/PaperweightCore.kt +++ b/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/PaperweightCore.kt @@ -213,7 +213,7 @@ abstract class PaperweightCore : Plugin { PatchRouletteTasks( target, - name.lowercase(), + coreExt.activeFork.get().name.lowercase(), // TODO: make this lazy coreExt.minecraftVersion, coreExt.activeFork.flatMap { it.rejectsDir }, layout.projectDirectory.dir("src/minecraft/java"), From 1ab0f6821f72a2626c0c883b816989de2991ecd4 Mon Sep 17 00:00:00 2001 From: "tofik.07" Date: Sun, 26 Apr 2026 02:24:28 +0200 Subject: [PATCH 3/3] please spotless --- .../main/kotlin/io/papermc/paperweight/core/PaperweightCore.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/PaperweightCore.kt b/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/PaperweightCore.kt index c8112c35f..1e5707fb8 100644 --- a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/PaperweightCore.kt +++ b/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/PaperweightCore.kt @@ -213,7 +213,7 @@ abstract class PaperweightCore : Plugin { PatchRouletteTasks( target, - coreExt.activeFork.get().name.lowercase(), // TODO: make this lazy + coreExt.activeFork.get().name.lowercase(), // TODO: make this lazy coreExt.minecraftVersion, coreExt.activeFork.flatMap { it.rejectsDir }, layout.projectDirectory.dir("src/minecraft/java"),