Skip to content

Commit

Permalink
move source AT rebuilding to its own task
Browse files Browse the repository at this point in the history
  • Loading branch information
MiniDigger committed Jan 23, 2025
1 parent c8cac5e commit b10b01a
Show file tree
Hide file tree
Showing 13 changed files with 277 additions and 181 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import io.papermc.paperweight.core.util.coreExt
import io.papermc.paperweight.tasks.*
import io.papermc.paperweight.tasks.mache.DecompileJar
import io.papermc.paperweight.tasks.mache.RunCodebook
import io.papermc.paperweight.tasks.softspoon.ProcessNewSourceAT
import io.papermc.paperweight.util.*
import io.papermc.paperweight.util.constants.*
import io.papermc.paperweight.util.data.mache.*
Expand All @@ -40,6 +41,8 @@ import org.gradle.api.Project
import org.gradle.api.provider.Property
import org.gradle.api.tasks.TaskContainer
import org.gradle.kotlin.dsl.*
import org.gradle.kotlin.dsl.provideDelegate
import org.gradle.kotlin.dsl.registering

class CoreTasks(
val project: Project,
Expand Down Expand Up @@ -153,6 +156,16 @@ class CoreTasks(

root.set(project.rootProject.layout.projectDirectory)
}

val processNewSourceAT by project.tasks.registering(ProcessNewSourceAT::class) {
description = "Processes new source ATs"

base.set(layout.cache.resolve(BASE_PROJECT).resolve("sources"))
input.set(layout.projectDirectory.dir("src/minecraft/java"))
atFile.set(project.coreExt.paper.additionalAts.fileExists(project))
ats.jstClasspath.from(project.configurations.named(MACHE_MINECRAFT_CONFIG))
ats.jst.from(project.configurations.named(JST_CONFIG))
}
}

// Setup Paper's Minecraft patching tasks
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,11 +206,6 @@ class MinecraftPatchingTasks(
input.set(outputSrc)
patches.set(sourcePatchDir)
gitFilePatches.set(this@MinecraftPatchingTasks.gitFilePatches)

ats.jstClasspath.from(project.configurations.named(MACHE_MINECRAFT_CONFIG))
ats.jst.from(project.configurations.named(JST_CONFIG))
atFile.set(additionalAts.fileExists(project))
atFileOut.set(additionalAts.fileExists(project))
}

val rebuildResourcePatches = tasks.register<RebuildFilePatches>(rebuildResourcePatchesName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import codechicken.diffpatch.util.archiver.ArchiveFormat
import io.papermc.paperweight.core.util.ApplySourceATs
import io.papermc.paperweight.tasks.*
import io.papermc.paperweight.util.*
import io.papermc.paperweight.util.constants.*
import java.nio.file.Path
import java.util.function.Predicate
import kotlin.io.path.*
Expand Down Expand Up @@ -81,7 +82,7 @@ abstract class SetupMinecraftSources : JavaLauncherTask() {
val git: Git
if (outputPath.resolve(".git/HEAD").isRegularFile()) {
git = Git.open(outputPath.toFile())
git.reset().setRef("ROOT").setMode(ResetCommand.ResetType.HARD).call()
git.reset().setRef(MACHE_TAG_ROOT).setMode(ResetCommand.ResetType.HARD).call()
} else {
outputPath.createDirectories()

Expand All @@ -90,10 +91,10 @@ abstract class SetupMinecraftSources : JavaLauncherTask() {
.setInitialBranch("main")
.call()

val rootIdent = PersonIdent("ROOT", "[email protected]")
git.commit().setMessage("ROOT").setAllowEmpty(true).setAuthor(rootIdent).setSign(false).call()
git.tagDelete().setTags("ROOT").call()
git.tag().setName("ROOT").setTagger(rootIdent).setSigned(false).call()
val rootIdent = PersonIdent(MACHE_TAG_ROOT, "[email protected]")
git.commit().setMessage(MACHE_TAG_ROOT).setAllowEmpty(true).setAuthor(rootIdent).setSign(false).call()
git.tagDelete().setTags(MACHE_TAG_ROOT).call()
git.tag().setName(MACHE_TAG_ROOT).setTagger(rootIdent).setSigned(false).call()
}

if (macheOld.isPresent) {
Expand Down Expand Up @@ -130,7 +131,7 @@ abstract class SetupMinecraftSources : JavaLauncherTask() {
println("Setup git repo...")
if (!macheOld.isPresent) {
// skip this if we are diffing against old, since it would be a commit without mache patches
commitAndTag(git, "Vanilla")
commitAndTag(git, MACHE_TAG_VANILLA)
}

if (!mache.isEmpty) {
Expand All @@ -147,7 +148,7 @@ abstract class SetupMinecraftSources : JavaLauncherTask() {
.build()
.operate()

commitAndTag(git, "Mache")
commitAndTag(git, MACHE_TAG_PATCHES)

if (result.exit != 0) {
throw Exception("Failed to apply ${result.summary.failedMatches} mache patches")
Expand All @@ -165,13 +166,13 @@ abstract class SetupMinecraftSources : JavaLauncherTask() {
atFile.path,
temporaryDir.toPath(),
)
commitAndTag(git, "ATs", "paper ATs")
commitAndTag(git, MACHE_TAG_ATS, "paper ATs")
}

if (libraryImports.isPresent) {
libraryImports.path.copyRecursivelyTo(outputPath)

commitAndTag(git, "Imports", "paper Imports")
commitAndTag(git, MACHE_TAG_IMPORTS, "paper Imports")
}

git.close()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ package io.papermc.paperweight.core.tasks.patching
import io.papermc.paperweight.PaperweightException
import io.papermc.paperweight.tasks.*
import io.papermc.paperweight.util.*
import io.papermc.paperweight.util.constants.*
import java.nio.file.Path
import kotlin.io.path.*
import kotlin.io.path.createDirectories
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
Expand Down Expand Up @@ -86,7 +88,7 @@ abstract class ApplyFeaturePatches : ControllableOutputTask() {
if (git("checkout", "main").runSilently(silenceErr = true) != 0) {
git("checkout", "-b", "main").runSilently(silenceErr = true)
}
git("reset", "--hard", "file").executeSilently(silenceErr = true)
git("reset", "--hard", MACHE_TAG_FILE).executeSilently(silenceErr = true)
git("gc").runSilently(silenceErr = true)

applyGitPatches(git, "server repo", repoPath, patches.path, printOutput.get(), verbose.get())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import codechicken.diffpatch.util.LoggingOutputStream
import codechicken.diffpatch.util.PatchMode
import io.papermc.paperweight.tasks.*
import io.papermc.paperweight.util.*
import io.papermc.paperweight.util.constants.*
import java.io.PrintStream
import java.nio.file.Path
import java.time.Instant
Expand Down Expand Up @@ -202,8 +203,8 @@ abstract class ApplyFilePatches : BaseTask() {
.setAllowEmpty(true)
.setSign(false)
.call()
git.tagDelete().setTags("file").call()
git.tag().setName("file").setTagger(ident).setSigned(false).call()
git.tagDelete().setTags(MACHE_TAG_FILE).call()
git.tag().setName(MACHE_TAG_FILE).setTagger(ident).setSigned(false).call()
git.close()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ package io.papermc.paperweight.core.tasks.patching

import io.papermc.paperweight.tasks.*
import io.papermc.paperweight.util.*
import io.papermc.paperweight.util.constants.*
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
Expand All @@ -44,7 +45,7 @@ abstract class FixupFilePatches : BaseTask() {
fun run() {
val git = Git(repo)
git("add", ".").executeOut()
git("commit", "--fixup", "file").executeOut()
git("commit", "--fixup", MACHE_TAG_FILE).executeOut()
git("-c", "sequence.editor=:", "rebase", "-i", "--autosquash", upstream.get()).executeOut()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
/*
* paperweight is a Gradle plugin for the PaperMC project.
*
* Copyright (c) 2023 Kyle Wood (DenWav)
* Contributors
*
* 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 only, no later versions.
*
* 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 io.papermc.paperweight.tasks.softspoon

import io.papermc.paperweight.PaperweightException
import io.papermc.paperweight.core.util.ApplySourceATs
import io.papermc.paperweight.tasks.*
import io.papermc.paperweight.util.*
import io.papermc.paperweight.util.constants.*
import java.nio.file.Path
import kotlin.io.path.*
import org.cadixdev.at.AccessTransformSet
import org.cadixdev.at.io.AccessTransformFormats
import org.cadixdev.bombe.type.signature.MethodSignature
import org.eclipse.jgit.api.RebaseCommand
import org.eclipse.jgit.lib.RebaseTodoLine
import org.eclipse.jgit.merge.MergeStrategy
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.tasks.InputDirectory
import org.gradle.api.tasks.InputFile
import org.gradle.api.tasks.Nested
import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.UntrackedTask
import org.gradle.kotlin.dsl.*

@UntrackedTask(because = "Always process when requested")
abstract class ProcessNewSourceAT : JavaLauncherTask() {

@get:InputDirectory
abstract val input: DirectoryProperty

@get:InputDirectory
abstract val base: DirectoryProperty

@get:Optional
@get:InputFile
abstract val atFile: RegularFileProperty

@get:Nested
val ats: ApplySourceATs = objects.newInstance()

fun waitForY(msg: String) {
println(msg)
while (System.`in`.read() != 'y'.toInt()) {
println("waiting for y")
}
}

@TaskAction
fun run() {
val inputDir = input.convertToPath()
val baseDir = base.convertToPath()

// find ATs, cleanup comment, apply to base
val newATs = handleAts(baseDir, inputDir, atFile)
waitForY("ran handleAts, base should be patched")

// save work and jump to AT commit
val git = Git(inputDir)
git("stash", "push").executeSilently(silenceErr = true)
git("checkout", MACHE_TAG_ATS).executeSilently(silenceErr = true)

// apply new ATs to source
newATs.forEach { (path, ats) ->
val source = inputDir.resolve(path)
applyNewATs(source, ats)
}
waitForY("applied new ATs to source")

// commit new ATs
git("add", ".").executeSilently(silenceErr = true)
git("commit", "--amend", "--no-edit").executeSilently(silenceErr = true)
waitForY("committed new ATs")

// clean up tree: drop the old file commit and rebase the new file commit onto it
git("switch", "-").executeSilently(silenceErr = true)
waitForY("switched back to main")
org.eclipse.jgit.api.Git.open(inputDir.toFile()).rebase()
.setUpstream(MACHE_TAG_ATS)
.setStrategy(MergeStrategy.THEIRS)
.runInteractively(object : RebaseCommand.InteractiveHandler {
override fun prepareSteps(steps: MutableList<RebaseTodoLine>) {
// drop the first commit
steps.removeAt(0)
}

override fun modifyCommitMessage(message: String): String {
return message
}
})
.call()

waitForY("finished rebase")

git("stash", "pop").executeSilently(silenceErr = true)
}

private fun handleAts(
baseDir: Path,
inputDir: Path,
atFile: RegularFileProperty
): MutableList<Pair<String, AccessTransformSet>> {
val oldAts = AccessTransformFormats.FML.read(atFile.path)
val newATs = mutableListOf<Pair<String, AccessTransformSet>>()

baseDir.walk()
.map { it.relativeTo(baseDir).invariantSeparatorsPathString }
.filter { it.endsWith(".java") }
.forEach {
val ats = AccessTransformSet.create()
val source = inputDir.resolve(it)
val decomp = baseDir.resolve(it)
val className = it.replace(".java", "")
if (findATInSource(source, ats, className)) {
applyNewATs(decomp, ats)
newATs.add(it to ats)
}
oldAts.merge(ats)
}

AccessTransformFormats.FML.writeLF(
atFile.path,
oldAts,
"# This file is auto generated, any changes may be overridden!\n# See CONTRIBUTING.md on how to add access transformers.\n"
)

return newATs
}

private fun applyNewATs(decomp: Path, newAts: AccessTransformSet) {
if (newAts.classes.isEmpty()) {
println("new ats empty?!") // TODO remove
return
}
println("apply new ats to $decomp, $newAts") // TODO remove

val at = temporaryDir.toPath().resolve("ats.cfg").createParentDirectories()
AccessTransformFormats.FML.writeLF(at, newAts)
ats.run(
launcher.get(),
decomp,
decomp,
at,
temporaryDir.toPath().resolve("jst_work").cleanDir(),
singleFile = true,
)
}

private fun findATInSource(source: Path, newAts: AccessTransformSet, className: String): Boolean {
if (!source.exists()) {
// source was added via lib imports
return false
}

val sourceLines = source.readLines()
var foundNew = false
val fixedLines = ArrayList<String>(sourceLines.size)
sourceLines.forEach { line ->
if (!line.contains("// Paper-AT: ")) {
fixedLines.add(line)
return@forEach
}

foundNew = true

val split = line.split("// Paper-AT: ")
val at = split[1]
try {
val atClass = newAts.getOrCreateClass(className)
val parts = at.split(" ")
val accessTransform = atFromString(parts[0])
val name = parts[1]
val index = name.indexOf('(')
if (index == -1) {
atClass.mergeField(name, accessTransform)
} else {
atClass.mergeMethod(MethodSignature.of(name.substring(0, index), name.substring(index)), accessTransform)
}
logger.lifecycle("Found new AT in $className: $at -> $accessTransform")
} catch (ex: Exception) {
throw PaperweightException("Found invalid AT '$at' in class $className")
}

fixedLines.add(split[0].trimEnd())
}

if (foundNew) {
source.writeText(fixedLines.joinToString("\n", postfix = "\n"), Charsets.UTF_8)
}

return foundNew
}
}
Loading

0 comments on commit b10b01a

Please sign in to comment.