diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0b217ddb..1def8a7d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -46,7 +46,7 @@ openrewrite = "org.openrewrite:rewrite-java-17:8.7.4" # Gradle gradle-licenser = "org.cadixdev.licenser:org.cadixdev.licenser.gradle.plugin:0.6.1" -gradle-shadow = "com.github.johnrengelman.shadow:com.github.johnrengelman.shadow.gradle.plugin:7.1.2" +gradle-shadow = "com.github.johnrengelman.shadow:com.github.johnrengelman.shadow.gradle.plugin:8.1.1" gradle-ktlint = "org.jlleitschuh.gradle.ktlint:org.jlleitschuh.gradle.ktlint.gradle.plugin:10.2.1" gradle-kotlin-dsl = "org.gradle.kotlin.kotlin-dsl:org.gradle.kotlin.kotlin-dsl.gradle.plugin:4.1.0" gradle-plugin-kotlin = { module = "org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin" } diff --git a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/taskcontainers/SoftSpoonTasks.kt b/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/taskcontainers/SoftSpoonTasks.kt index c2987346..557e3202 100644 --- a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/taskcontainers/SoftSpoonTasks.kt +++ b/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/taskcontainers/SoftSpoonTasks.kt @@ -13,6 +13,7 @@ import io.papermc.paperweight.util.* import io.papermc.paperweight.util.constants.* import io.papermc.paperweight.util.data.* import io.papermc.paperweight.util.data.mache.* +import java.nio.file.Files import kotlin.io.path.* import org.gradle.api.Project import org.gradle.api.tasks.TaskContainer @@ -23,7 +24,6 @@ import org.gradle.api.Task import org.gradle.api.plugins.JavaPlugin import org.gradle.api.plugins.JavaPluginExtension import org.gradle.api.tasks.SourceSet -import org.gradle.api.tasks.Sync open class SoftSpoonTasks( val project: Project, @@ -63,47 +63,40 @@ open class SoftSpoonTasks( outputJar.set(layout.cache.resolve(FINAL_DECOMPILE_JAR)) } - val macheApplyPatches by tasks.registering(ApplyMachePatches::class) { + val setupMacheSources by tasks.registering(SetupVanilla::class) { group = "mache" - description = "Apply decompilation patches to the source." - - mache.from(project.configurations.named(MACHE_CONFIG)) - - useNativeDiff.set(project.providers.gradleProperty("useNativeDiff").map { it.toBoolean() }.orElse(false)) - project.providers.gradleProperty("patchExecutable").let { ex -> - if (ex.isPresent) { - patchExecutable.set(ex) - } - } + description = "Setup vanilla source dir." inputFile.set(macheDecompileJar.flatMap { it.outputJar }) - outputJar.set(layout.cache.resolve(PATCHED_JAR)) - failedPatchesJar.set(layout.cache.resolve(FAILED_PATCH_JAR)) + predicate.set { Files.isRegularFile(it) && it.toString().endsWith(".java")} + outputDir.set(layout.cache.resolve(BASE_PROJECT).resolve("sources")) } - val macheSetupSources by tasks.registering(SetupSources::class) { + val setupMacheResources by tasks.registering(SetupVanilla::class) { group = "mache" - decompJar.set(macheDecompileJar.flatMap { it.outputJar }) - patchedJar.set(macheApplyPatches.flatMap { it.outputJar }) - failedPatchJar.set(macheApplyPatches.flatMap { it.failedPatchesJar }) + description = "Setup vanilla resources dir" - sourceDir.set(layout.cache.resolve(BASE_PROJECT).resolve("sources")) + inputFile.set(macheDecompileJar.flatMap { it.outputJar }) + predicate.set { Files.isRegularFile(it) && !it.toString().endsWith(".java")} + outputDir.set(layout.cache.resolve(BASE_PROJECT).resolve("resources")) } - val macheCopyResources by tasks.registering(Sync::class) { + val applyMachePatches by tasks.registering(ApplyMachePatches::class) { group = "mache" - into(project.layout.cache.resolve(BASE_PROJECT).resolve("resources")) - from(project.zipTree(project.layout.cache.resolve(SERVER_JAR_PATH))) { - exclude("**/*.class", "META-INF/**") - } - includeEmptyDirs = false + description = "Applies patches to the vanilla sources" + + mache.from(project.configurations.named(MACHE_CONFIG)) + + input.set(setupMacheSources.flatMap { it.outputDir }) + output.set(layout.cache.resolve(BASE_PROJECT).resolve("sources")) + patches.set(layout.cache.resolve(PATCHES_FOLDER)) } val applySourcePatches by tasks.registering(ApplyPatches::class) { group = "softspoon" description = "Applies patches to the vanilla sources" - input.set(macheSetupSources.flatMap { it.sourceDir }) + input.set(applyMachePatches.flatMap { it.output }) output.set(project.ext.serverProject.map { it.layout.projectDirectory.dir("src/vanilla/java") }) patches.set(project.layout.projectDirectory.dir("patches/sources")) } @@ -112,7 +105,7 @@ open class SoftSpoonTasks( group = "softspoon" description = "Applies patches to the vanilla sources" - input.set(macheSetupSources.flatMap { it.sourceDir }) + input.set(applyMachePatches.flatMap { it.output }) output.set(project.ext.serverProject.map { it.layout.projectDirectory.dir("src/vanilla/java") }) patches.set(project.layout.projectDirectory.dir("patches/sources")) } @@ -120,9 +113,8 @@ open class SoftSpoonTasks( val applyResourcePatches by tasks.registering(ApplyPatches::class) { group = "softspoon" description = "Applies patches to the vanilla resources" - dependsOn(macheCopyResources) - input.set(layout.cache.resolve(BASE_PROJECT).resolve("resources")) + input.set(setupMacheResources.flatMap { it.outputDir }) output.set(project.ext.serverProject.map { it.layout.projectDirectory.dir("src/vanilla/resources") }) patches.set(project.layout.projectDirectory.dir("patches/resources")) } diff --git a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/mache/ApplyMachePatches.kt b/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/mache/ApplyMachePatches.kt index c1a331d8..2af1c566 100644 --- a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/mache/ApplyMachePatches.kt +++ b/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/mache/ApplyMachePatches.kt @@ -1,126 +1,43 @@ package io.papermc.paperweight.tasks.mache +import io.papermc.paperweight.tasks.softspoon.ApplyPatches import io.papermc.paperweight.util.* -import io.papermc.paperweight.util.constants.* -import io.papermc.paperweight.util.patches.* -import io.papermc.paperweight.util.patches.NativePatcher -import javax.inject.Inject -import kotlin.io.path.createDirectory -import kotlin.io.path.deleteRecursively -import kotlin.io.path.exists -import kotlin.io.path.inputStream -import kotlin.io.path.relativeTo -import org.gradle.api.DefaultTask +import org.eclipse.jgit.api.Git +import org.eclipse.jgit.lib.PersonIdent import org.gradle.api.file.ConfigurableFileCollection -import org.gradle.api.file.ProjectLayout -import org.gradle.api.file.RegularFileProperty -import org.gradle.api.internal.file.FileOperations -import org.gradle.api.provider.Property -import org.gradle.api.tasks.* -import org.gradle.process.ExecOperations +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.tasks.CacheableTask +import org.gradle.api.tasks.Classpath +import org.gradle.api.tasks.Internal +import org.gradle.api.tasks.UntrackedTask -@UntrackedTask(because = "Always apply patches") -abstract class ApplyMachePatches : DefaultTask() { - - @get:Classpath - abstract val mache: ConfigurableFileCollection - - @get:InputFile - abstract val inputFile: RegularFileProperty - - @get:Internal - abstract val useNativeDiff: Property +@CacheableTask +abstract class ApplyMachePatches : ApplyPatches() { @get:Internal - abstract val patchExecutable: Property + abstract override val patches: DirectoryProperty - @get:OutputFile - abstract val outputJar: RegularFileProperty - - @get:OutputFile - abstract val failedPatchesJar: RegularFileProperty - - @get:Inject - abstract val exec: ExecOperations - - @get:Inject - abstract val files: FileOperations - - @get:Inject - abstract val layout: ProjectLayout - - init { - run { - useNativeDiff.convention(false) - patchExecutable.convention("patch") - } - } + @get:Classpath + abstract val mache: ConfigurableFileCollection - @TaskAction - fun run() { - val patchesFolder = layout.cache.resolve(PATCHES_FOLDER).ensureClean() + override fun setup() { + // prepare for patches for patching + val patchesFolder = patches.convertToPath().ensureClean() mache.singleFile.toPath().openZip().use { zip -> zip.getPath("patches").copyRecursivelyTo(patchesFolder) } - - val out = outputJar.convertToPath().ensureClean() - val failed = failedPatchesJar.convertToPath().ensureClean() - - val tempInDir = out.resolveSibling(".tmp_applyPatches_input").ensureClean() - tempInDir.createDirectory() - val tempOutDir = out.resolveSibling(".tmp_applyPatches_output").ensureClean() - tempOutDir.createDirectory() - val tempFailedPatchDir = out.resolveSibling(".tmp_applyPatches_failed").ensureClean() - tempFailedPatchDir.createDirectory() - - try { - files.sync { - from(files.zipTree(inputFile)) - into(tempInDir) - } - - val result = createPatcher().applyPatches(tempInDir, patchesFolder, tempOutDir, tempFailedPatchDir) - - out.writeZipStream { zos -> - failed.writeZipStream { failedZos -> - inputFile.convertToPath().readZipStream { zis, zipEntry -> - if (zipEntry.name.endsWith(".java")) { - val patchedFile = tempOutDir.resolve(zipEntry.name) - if (patchedFile.exists()) { - patchedFile.inputStream().buffered().use { input -> - copyEntry(input, zos, zipEntry) - } - } - val failedPatch = tempFailedPatchDir.resolve(zipEntry.name) - if (failedPatch.exists()) { - failedPatch.inputStream().buffered().use { input -> - copyEntry(input, failedZos, zipEntry) - } - } - } - } - } - } - - if (result is PatchFailure) { - result.failures - .map { "Patch failed: ${it.patch.relativeTo(patchesFolder)}: ${it.details}" } - .forEach { logger.error(it) } - throw Exception("Failed to apply ${result.failures.size} patches") - } - } finally { - tempInDir.deleteRecursively() - tempOutDir.deleteRecursively() - tempFailedPatchDir.deleteRecursively() - } } - internal open fun createPatcher(): Patcher { - return if (useNativeDiff.get()) { - NativePatcher(exec, patchExecutable.get()) - } else { - JavaPatcher() - } + override fun commit() { + val macheIdent = PersonIdent("Mache", "mache@automated.papermc.io") + val git = Git.open(output.convertToPath().toFile()) + git.add().addFilepattern(".").call() + git.tag().setName("mache").setTagger(macheIdent).setSigned(false).call() + git.commit() + .setMessage("Mache") + .setAuthor(macheIdent) + .setSign(false) + .call() } } diff --git a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/mache/SetupSources.kt b/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/mache/SetupSources.kt deleted file mode 100644 index 0d712e3a..00000000 --- a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/mache/SetupSources.kt +++ /dev/null @@ -1,55 +0,0 @@ -package io.papermc.paperweight.tasks.mache - -import javax.inject.Inject -import org.gradle.api.DefaultTask -import org.gradle.api.file.DirectoryProperty -import org.gradle.api.file.ProjectLayout -import org.gradle.api.file.RegularFileProperty -import org.gradle.api.internal.file.FileOperations -import org.gradle.api.tasks.InputFile -import org.gradle.api.tasks.OutputDirectory -import org.gradle.api.tasks.TaskAction - -abstract class SetupSources : DefaultTask() { - - @get:InputFile - abstract val decompJar: RegularFileProperty - - @get:InputFile - abstract val patchedJar: RegularFileProperty - - @get:InputFile - abstract val failedPatchJar: RegularFileProperty - - @get:OutputDirectory - abstract val sourceDir: DirectoryProperty - - @get:Inject - abstract val layout: ProjectLayout - - @get:Inject - abstract val files: FileOperations - - @TaskAction - fun run() { - files.sync { - from(files.zipTree(decompJar)) - into(sourceDir) - // ignore resources here, we gonna handle them separately - exclude { !it.name.endsWith(".java") } - includeEmptyDirs = false - } - - files.sync { - from(files.zipTree(patchedJar)) - into(sourceDir) - includeEmptyDirs = false - } - - files.copy { - from(files.zipTree(failedPatchJar)) - into(sourceDir) - includeEmptyDirs = false - } - } -} diff --git a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/mache/SetupVanilla.kt b/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/mache/SetupVanilla.kt new file mode 100644 index 00000000..f977b519 --- /dev/null +++ b/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/mache/SetupVanilla.kt @@ -0,0 +1,60 @@ +package io.papermc.paperweight.tasks.mache + +import io.papermc.paperweight.tasks.* +import io.papermc.paperweight.util.* +import java.nio.file.Path +import java.util.function.Predicate +import kotlin.io.path.* +import org.eclipse.jgit.api.Git +import org.eclipse.jgit.lib.PersonIdent +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.provider.Property +import org.gradle.api.tasks.CacheableTask +import org.gradle.api.tasks.InputFile +import org.gradle.api.tasks.Internal +import org.gradle.api.tasks.OutputDirectory +import org.gradle.api.tasks.TaskAction +import org.gradle.api.tasks.UntrackedTask + +@CacheableTask +abstract class SetupVanilla : BaseTask() { + + @get:InputFile + abstract val inputFile: RegularFileProperty + + @get:Internal + abstract val predicate: Property> + + @get:OutputDirectory + abstract val outputDir: DirectoryProperty + + @TaskAction + fun run() { + val path = outputDir.convertToPath().ensureClean() + + // copy initial sources + inputFile.convertToPath().openZip().walk() + .filter(predicate.get()) + .forEach { + val target = path.resolve(it.toString().substring(1)) + target.parent.createDirectories() + it.copyTo(target, true) + } + + // setup git repo + val vanillaIdent = PersonIdent("Vanilla", "vanilla@papermc.io") + + val git = Git.init() + .setDirectory(path.toFile()) + .setInitialBranch("main") + .call() + git.add().addFilepattern(".").call() + git.commit() + .setMessage("Vanilla") + .setAuthor(vanillaIdent) + .setSign(false) + .call() + git.tag().setName("vanilla").setTagger(vanillaIdent).setSigned(false).call() + } +} diff --git a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/softspoon/ApplyPatches.kt b/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/softspoon/ApplyPatches.kt index 6a4dca98..02b45522 100644 --- a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/softspoon/ApplyPatches.kt +++ b/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/softspoon/ApplyPatches.kt @@ -18,7 +18,7 @@ import org.gradle.api.tasks.UntrackedTask import org.gradle.process.ExecOperations @UntrackedTask(because = "Always apply patches") -abstract class ApplyPatches: DefaultTask() { +abstract class ApplyPatches : DefaultTask() { @get:InputDirectory abstract val input: DirectoryProperty @@ -49,23 +49,12 @@ abstract class ApplyPatches: DefaultTask() { } @TaskAction - fun run() { - output.convertToPath().ensureClean() + open fun run() { + setup() - val result = createPatcher().applyPatches(input.get().path, patches.get().path, output.get().path, output.get().path) + val result = createPatcher().applyPatches(output.convertToPath(), patches.convertToPath(), output.convertToPath(), output.convertToPath()) - // TODO ideally we manage to make a commit with just the patch changes - val git = Git.init() - .setDirectory(output.convertToPath().toFile()) - .setInitialBranch("mache") - .call() - git.add().addFilepattern(".").call() - git.commit() - .setMessage("Initial") - .setAuthor(macheIdent) - .setSign(false) - .call() - git.tag().setName(PATCHED_TAG).setTagger(macheIdent).setSigned(false).call() + commit() if (result is PatchFailure) { result.failures @@ -75,6 +64,23 @@ abstract class ApplyPatches: DefaultTask() { } } + open fun setup() { + output.convertToPath().ensureClean() + Git.cloneRepository().setBranch("main").setURI("file://" + input.convertToPath().toString()).setDirectory(output.convertToPath().toFile()).call() + } + + open fun commit() { + val ident = PersonIdent("File", "filepatches@automated.papermc.io") + val git = Git.open(output.convertToPath().toFile()) + git.add().addFilepattern(".").call() + git.commit() + .setMessage("File Patches") + .setAuthor(ident) + .setSign(false) + .call() + git.tag().setName("file").setTagger(ident).setSigned(false).call() + } + internal open fun createPatcher(): Patcher { return if (useNativeDiff.get()) { NativePatcher(exec, patchExecutable.get()) @@ -82,10 +88,4 @@ abstract class ApplyPatches: DefaultTask() { JavaPatcher() } } - - companion object { - private const val PATCHED_TAG = "patched" - - private val macheIdent = PersonIdent("Papier-mâché", "paper@mache.gradle") - } } diff --git a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/softspoon/RebuildPatches.kt b/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/softspoon/RebuildPatches.kt index d70523d7..0234c013 100644 --- a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/softspoon/RebuildPatches.kt +++ b/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/softspoon/RebuildPatches.kt @@ -47,12 +47,12 @@ abstract class RebuildPatches : DefaultTask() { val baseDir = base.convertToPath() val patchesCreated = baseDir.walk() + .map { it.relativeTo(baseDir).toString().replace("\\", "/") } .filter { - val path = it.toString() - !path.startsWith(".git") && !path.endsWith(".nbt") && !path.endsWith(".mcassetsroot") + !it.startsWith(".git") && !it.endsWith(".nbt") && !it.endsWith(".mcassetsroot") } .sumOf { - diffFile(inputDir, baseDir, it.relativeTo(baseDir).toString().replace("\\", "/"), patchDir) + diffFile(inputDir, baseDir, it, patchDir) } logger.lifecycle("Rebuilt $patchesCreated patches") diff --git a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/util/file.kt b/paperweight-lib/src/main/kotlin/io/papermc/paperweight/util/file.kt index 9b52a0c5..5022ff61 100644 --- a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/util/file.kt +++ b/paperweight-lib/src/main/kotlin/io/papermc/paperweight/util/file.kt @@ -26,6 +26,7 @@ import io.papermc.paperweight.PaperweightException import java.io.InputStream import java.net.URI import java.nio.file.FileSystem +import java.nio.file.FileSystemNotFoundException import java.nio.file.FileSystems import java.nio.file.Files import java.nio.file.Path @@ -146,7 +147,11 @@ private fun Path.jarUri(): URI { } fun Path.openZip(): FileSystem { - return FileSystems.newFileSystem(jarUri(), emptyMap()) + return try { + FileSystems.getFileSystem(jarUri()) + } catch (e: FileSystemNotFoundException) { + FileSystems.newFileSystem(jarUri(), emptyMap()) + } } fun Path.writeZip(): FileSystem {