mirror of
https://github.com/PurpurMC/Purpur.git
synced 2026-02-17 08:27:43 +01:00
Update Toothpick
This commit is contained in:
@@ -1,7 +1,10 @@
|
|||||||
|
import xyz.jpenilla.toothpick.gitCmd
|
||||||
|
import xyz.jpenilla.toothpick.toothpick
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
`java-library`
|
`java-library`
|
||||||
`maven-publish`
|
`maven-publish`
|
||||||
toothpick
|
id("xyz.jpenilla.toothpick") version "1.0.0-SNAPSHOT"
|
||||||
}
|
}
|
||||||
|
|
||||||
toothpick {
|
toothpick {
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
val kotlinxDomVersion = "0.0.10"
|
|
||||||
val shadowVersion = "6.1.0"
|
|
||||||
|
|
||||||
plugins {
|
|
||||||
`kotlin-dsl`
|
|
||||||
}
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
jcenter()
|
|
||||||
maven("https://plugins.gradle.org/m2/")
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx.dom:$kotlinxDomVersion")
|
|
||||||
implementation("com.github.jengelman.gradle.plugins:shadow:$shadowVersion")
|
|
||||||
}
|
|
||||||
|
|
||||||
gradlePlugin {
|
|
||||||
plugins {
|
|
||||||
register("Toothpick") {
|
|
||||||
id = "toothpick"
|
|
||||||
implementationClass = "Toothpick"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,164 +0,0 @@
|
|||||||
import com.github.jengelman.gradle.plugins.shadow.ShadowPlugin
|
|
||||||
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
|
||||||
import com.github.jengelman.gradle.plugins.shadow.transformers.Log4j2PluginsCacheFileTransformer
|
|
||||||
import kotlinx.dom.elements
|
|
||||||
import kotlinx.dom.parseXml
|
|
||||||
import kotlinx.dom.search
|
|
||||||
import org.gradle.api.Project
|
|
||||||
import org.gradle.api.plugins.JavaLibraryPlugin
|
|
||||||
import org.gradle.api.publish.PublishingExtension
|
|
||||||
import org.gradle.api.publish.maven.MavenPublication
|
|
||||||
import org.gradle.api.publish.maven.plugins.MavenPublishPlugin
|
|
||||||
import org.gradle.api.publish.maven.tasks.GenerateMavenPom
|
|
||||||
import org.gradle.api.tasks.bundling.Jar
|
|
||||||
import org.gradle.api.tasks.compile.JavaCompile
|
|
||||||
import org.gradle.api.tasks.javadoc.Javadoc
|
|
||||||
import org.gradle.api.tasks.testing.Test
|
|
||||||
import org.gradle.kotlin.dsl.apply
|
|
||||||
import org.gradle.kotlin.dsl.attributes
|
|
||||||
import org.gradle.kotlin.dsl.configure
|
|
||||||
import org.gradle.kotlin.dsl.create
|
|
||||||
import org.gradle.kotlin.dsl.get
|
|
||||||
import org.gradle.kotlin.dsl.getByName
|
|
||||||
import org.gradle.kotlin.dsl.getValue
|
|
||||||
import org.gradle.kotlin.dsl.getting
|
|
||||||
import org.gradle.kotlin.dsl.withType
|
|
||||||
import java.nio.charset.StandardCharsets.UTF_8
|
|
||||||
import java.text.SimpleDateFormat
|
|
||||||
import java.util.Date
|
|
||||||
|
|
||||||
internal fun Project.configureSubprojects() {
|
|
||||||
subprojects {
|
|
||||||
apply<JavaLibraryPlugin>()
|
|
||||||
apply<MavenPublishPlugin>()
|
|
||||||
|
|
||||||
tasks.withType<JavaCompile> {
|
|
||||||
options.encoding = UTF_8.name()
|
|
||||||
}
|
|
||||||
tasks.withType<Javadoc> {
|
|
||||||
options.encoding = UTF_8.name()
|
|
||||||
}
|
|
||||||
|
|
||||||
extensions.configure<PublishingExtension> {
|
|
||||||
publications {
|
|
||||||
create<MavenPublication>("mavenJava") {
|
|
||||||
groupId = rootProject.group as String
|
|
||||||
version = rootProject.version as String
|
|
||||||
pom {
|
|
||||||
name.set(project.name)
|
|
||||||
url.set(toothpick.forkUrl)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
when {
|
|
||||||
project.name.endsWith("server") -> configureServerProject()
|
|
||||||
project.name.endsWith("api") -> configureApiProject()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Project.configureServerProject() {
|
|
||||||
apply<ShadowPlugin>()
|
|
||||||
|
|
||||||
val generatePomFileForMavenJavaPublication by tasks.getting(GenerateMavenPom::class) {
|
|
||||||
destination = project.buildDir.resolve("tmp/pom.xml")
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("UNUSED_VARIABLE")
|
|
||||||
val test by tasks.getting(Test::class) {
|
|
||||||
// didn't bother to look into why these fail. paper excludes them in paperweight as well though
|
|
||||||
exclude("org/bukkit/craftbukkit/inventory/ItemStack*Test.class")
|
|
||||||
}
|
|
||||||
|
|
||||||
val shadowJar by tasks.getting(ShadowJar::class) {
|
|
||||||
archiveClassifier.set("") // ShadowJar is the main server artifact
|
|
||||||
dependsOn(generatePomFileForMavenJavaPublication)
|
|
||||||
transform(Log4j2PluginsCacheFileTransformer::class.java)
|
|
||||||
mergeServiceFiles()
|
|
||||||
manifest {
|
|
||||||
attributes(
|
|
||||||
"Main-Class" to "org.bukkit.craftbukkit.Main",
|
|
||||||
"Implementation-Title" to "CraftBukkit",
|
|
||||||
"Implementation-Version" to toothpick.forkVersion,
|
|
||||||
"Implementation-Vendor" to SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(Date()),
|
|
||||||
"Specification-Title" to "Bukkit",
|
|
||||||
"Specification-Version" to "${project.version}",
|
|
||||||
"Specification-Vendor" to "Bukkit Team"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
from(project.buildDir.resolve("tmp/pom.xml")) {
|
|
||||||
// dirty hack to make "java -Dpaperclip.install=true -jar paperclip.jar" work without forking paperclip
|
|
||||||
into("META-INF/maven/io.papermc.paper/paper")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't like to do this but sadly have to do this for compatibility reasons
|
|
||||||
relocate("org.bukkit.craftbukkit", "org.bukkit.craftbukkit.v${toothpick.nmsPackage}") {
|
|
||||||
exclude("org.bukkit.craftbukkit.Main*")
|
|
||||||
}
|
|
||||||
relocate("net.minecraft.server", "net.minecraft.server.v${toothpick.nmsPackage}")
|
|
||||||
|
|
||||||
// Make sure we relocate deps the same as Paper et al.
|
|
||||||
val pomFile = project.projectDir.resolve("pom.xml")
|
|
||||||
if (!pomFile.exists()) return@getting
|
|
||||||
val dom = parseXml(pomFile)
|
|
||||||
val buildSection = dom.search("build").first()
|
|
||||||
val plugins = buildSection.search("plugins").first()
|
|
||||||
plugins.elements("plugin").filter {
|
|
||||||
val artifactId = it.search("artifactId").first().textContent
|
|
||||||
artifactId == "maven-shade-plugin"
|
|
||||||
}.forEach {
|
|
||||||
it.search("executions").first()
|
|
||||||
.search("execution").first()
|
|
||||||
.search("configuration").first()
|
|
||||||
.search("relocations").first()
|
|
||||||
.elements("relocation").forEach { relocation ->
|
|
||||||
val pattern = relocation.search("pattern").first().textContent
|
|
||||||
val shadedPattern = relocation.search("shadedPattern").first().textContent
|
|
||||||
if (pattern != "org.bukkit.craftbukkit" && pattern != "net.minecraft.server") { // We handle these ourselves above
|
|
||||||
logger.debug("Imported relocation to server project shadowJar from ${pomFile.absolutePath}: $pattern to $shadedPattern")
|
|
||||||
relocate(pattern, shadedPattern)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.getByName("build") {
|
|
||||||
dependsOn(shadowJar)
|
|
||||||
}
|
|
||||||
|
|
||||||
extensions.configure<PublishingExtension> {
|
|
||||||
publications {
|
|
||||||
getByName<MavenPublication>("mavenJava") {
|
|
||||||
artifactId = rootProject.name
|
|
||||||
artifact(tasks["shadowJar"])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("UNUSED_VARIABLE")
|
|
||||||
private fun Project.configureApiProject() {
|
|
||||||
val jar by this.tasks.getting(Jar::class) {
|
|
||||||
doFirst {
|
|
||||||
buildDir.resolve("tmp/pom.properties")
|
|
||||||
.writeText("version=${project.version}")
|
|
||||||
}
|
|
||||||
from(buildDir.resolve("tmp/pom.properties")) {
|
|
||||||
into("META-INF/maven/${project.group}/${project.name}")
|
|
||||||
}
|
|
||||||
manifest {
|
|
||||||
attributes("Automatic-Module-Name" to "org.bukkit")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extensions.configure<PublishingExtension> {
|
|
||||||
publications {
|
|
||||||
getByName<MavenPublication>("mavenJava") {
|
|
||||||
artifactId = project.name
|
|
||||||
from(components["java"])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
const val taskGroup = "toothpick"
|
|
||||||
const val internalTaskGroup = "toothpick_internal"
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
import kotlinx.dom.elements
|
|
||||||
import kotlinx.dom.parseXml
|
|
||||||
import kotlinx.dom.search
|
|
||||||
import org.gradle.api.Project
|
|
||||||
import org.gradle.api.artifacts.dsl.RepositoryHandler
|
|
||||||
import org.gradle.kotlin.dsl.DependencyHandlerScope
|
|
||||||
import org.gradle.kotlin.dsl.maven
|
|
||||||
import org.gradle.kotlin.dsl.project
|
|
||||||
|
|
||||||
fun RepositoryHandler.loadRepositories(project: Project) {
|
|
||||||
val pomFile = project.projectDir.resolve("pom.xml")
|
|
||||||
if (!pomFile.exists()) return
|
|
||||||
val dom = parseXml(pomFile)
|
|
||||||
val repositoriesBlock = dom.search("repositories").firstOrNull() ?: return
|
|
||||||
|
|
||||||
// Load repositories
|
|
||||||
repositoriesBlock.elements("repository").forEach { repositoryElem ->
|
|
||||||
val url = repositoryElem.search("url").firstOrNull()?.textContent ?: return@forEach
|
|
||||||
maven(url)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun DependencyHandlerScope.loadDependencies(project: Project) {
|
|
||||||
val pomFile = project.projectDir.resolve("pom.xml")
|
|
||||||
if (!pomFile.exists()) return
|
|
||||||
val dom = parseXml(pomFile)
|
|
||||||
|
|
||||||
val dependenciesBlock = dom.search("dependencies").firstOrNull() ?: return
|
|
||||||
|
|
||||||
// Load dependencies
|
|
||||||
dependenciesBlock.elements("dependency").forEach { dependencyElem ->
|
|
||||||
val groupId = dependencyElem.search("groupId").first().textContent
|
|
||||||
val artifactId = dependencyElem.search("artifactId").first().textContent
|
|
||||||
val version = dependencyElem.search("version").first().textContent.applyReplacements(
|
|
||||||
"project.version" to project.version.toString(),
|
|
||||||
"minecraft.version" to project.toothpick.minecraftVersion
|
|
||||||
)
|
|
||||||
val scope = dependencyElem.search("scope").firstOrNull()?.textContent
|
|
||||||
val classifier = dependencyElem.search("classifier").firstOrNull()?.textContent
|
|
||||||
|
|
||||||
val dependencyString = "${groupId}:${artifactId}:${version}${classifier?.run { ":$this" } ?: ""}"
|
|
||||||
project.logger.debug("Read dependency '{}' from '{}'", dependencyString, pomFile.absolutePath)
|
|
||||||
|
|
||||||
// Special case API
|
|
||||||
if (artifactId == "${project.toothpick.forkNameLowercase}-api"
|
|
||||||
|| artifactId == "${project.toothpick.upstreamLowercase}-api"
|
|
||||||
) {
|
|
||||||
if (project.name.endsWith("-server")) {
|
|
||||||
add("api", project(":${project.toothpick.forkNameLowercase}-api"))
|
|
||||||
}
|
|
||||||
return@forEach
|
|
||||||
}
|
|
||||||
|
|
||||||
when (scope) {
|
|
||||||
"compile", null -> add("api", dependencyString)
|
|
||||||
"provided" -> {
|
|
||||||
add("compileOnly", dependencyString)
|
|
||||||
add("testImplementation", dependencyString)
|
|
||||||
}
|
|
||||||
"runtime" -> add("runtimeOnly", dependencyString)
|
|
||||||
"test" -> add("testImplementation", dependencyString)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
import org.gradle.api.Project
|
|
||||||
import task.createApplyPatchesTask
|
|
||||||
import task.createImportMCDevTask
|
|
||||||
import task.createInitGitSubmodulesTask
|
|
||||||
import task.createPaperclipTask
|
|
||||||
import task.createRebuildPatchesTask
|
|
||||||
import task.createSetupUpstreamTask
|
|
||||||
import task.createUpdateUpstreamTask
|
|
||||||
import task.createUpstreamCommitTask
|
|
||||||
|
|
||||||
@Suppress("UNUSED_VARIABLE")
|
|
||||||
internal fun Project.initToothpickTasks() {
|
|
||||||
if (project.hasProperty("fast")) {
|
|
||||||
gradle.taskGraph.whenReady {
|
|
||||||
gradle.taskGraph.allTasks.filter {
|
|
||||||
it.name.contains("test", ignoreCase = true) || it.name.contains("javadoc", ignoreCase = true)
|
|
||||||
}.forEach {
|
|
||||||
it.onlyIf { false }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.getByName("build") {
|
|
||||||
doFirst {
|
|
||||||
val readyToBuild =
|
|
||||||
upstreamDir.resolve(".git").exists()
|
|
||||||
&& toothpick.subprojects.values.all { it.projectDir.exists() && it.baseDir.exists() }
|
|
||||||
if (!readyToBuild) {
|
|
||||||
error("Workspace has not been setup. Try running `./gradlew applyPatches` first")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val initGitSubmodules = createInitGitSubmodulesTask()
|
|
||||||
|
|
||||||
val setupUpstream = createSetupUpstreamTask {
|
|
||||||
dependsOn(initGitSubmodules)
|
|
||||||
}
|
|
||||||
|
|
||||||
val importMCDev = createImportMCDevTask {
|
|
||||||
mustRunAfter(setupUpstream)
|
|
||||||
}
|
|
||||||
|
|
||||||
val paperclip = createPaperclipTask {
|
|
||||||
val shadowJar = toothpick.serverProject.project.tasks.getByName("shadowJar")
|
|
||||||
dependsOn(shadowJar)
|
|
||||||
inputs.file(shadowJar.outputs.files.singleFile)
|
|
||||||
}
|
|
||||||
|
|
||||||
val applyPatches = createApplyPatchesTask {
|
|
||||||
// If Paper has not been setup yet or if we modified the submodule (i.e. upstream update), patch
|
|
||||||
if (!lastUpstream.exists()
|
|
||||||
|| !upstreamDir.resolve(".git").exists()
|
|
||||||
|| lastUpstream.readText() != gitHash(upstreamDir)
|
|
||||||
) {
|
|
||||||
dependsOn(setupUpstream)
|
|
||||||
}
|
|
||||||
mustRunAfter(setupUpstream)
|
|
||||||
dependsOn(importMCDev)
|
|
||||||
}
|
|
||||||
|
|
||||||
val rebuildPatches = createRebuildPatchesTask()
|
|
||||||
|
|
||||||
val updateUpstream = createUpdateUpstreamTask {
|
|
||||||
finalizedBy(setupUpstream)
|
|
||||||
}
|
|
||||||
|
|
||||||
val upstreamCommit = createUpstreamCommitTask()
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
/**
|
|
||||||
* This is the set of extra NMS files which will be imported as part of the patch process
|
|
||||||
*
|
|
||||||
* See `./Paper/work/Minecraft/$MCVER/net/minecraft/server` for a list of possible files
|
|
||||||
*
|
|
||||||
* The `.java` extension is always assumed and should be excluded
|
|
||||||
*
|
|
||||||
* NOTE: Do not commit changes to this set! Instead make changes, rebuild patches, and commit the modified patches.
|
|
||||||
* Files already modified in existing patches will be imported automatically.
|
|
||||||
*/
|
|
||||||
val nmsImports = setOf<String>(
|
|
||||||
// ex:
|
|
||||||
//"EntityZombieVillager"
|
|
||||||
)
|
|
||||||
|
|
||||||
data class LibraryImport(val group: String, val library: String, val prefix: String, val file: String)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is the set of extra files to import into the server workspace from libraries
|
|
||||||
*
|
|
||||||
* Changes to this set should be committed to the repo, as these won't be automatically imported.
|
|
||||||
*/
|
|
||||||
val libraryImports = setOf<LibraryImport>(
|
|
||||||
LibraryImport("com.mojang", "brigadier", "com/mojang/brigadier", "CommandDispatcher"),
|
|
||||||
LibraryImport("com.mojang", "brigadier", "com/mojang/brigadier/tree", "LiteralCommandNode"),
|
|
||||||
LibraryImport("com.mojang", "brigadier", "com/mojang/brigadier/suggestion", "SuggestionsBuilder"),
|
|
||||||
LibraryImport("com.mojang", "brigadier", "com/mojang/brigadier/arguments", "BoolArgumentType")
|
|
||||||
)
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
import org.gradle.api.Plugin
|
|
||||||
import org.gradle.api.Project
|
|
||||||
import org.gradle.kotlin.dsl.create
|
|
||||||
|
|
||||||
class Toothpick : Plugin<Project> {
|
|
||||||
override fun apply(project: Project) {
|
|
||||||
project.extensions.create<ToothpickExtension>("toothpick", project.objects)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
import org.gradle.api.Project
|
|
||||||
import org.gradle.api.model.ObjectFactory
|
|
||||||
import java.io.File
|
|
||||||
import java.util.Locale
|
|
||||||
|
|
||||||
@Suppress("UNUSED_PARAMETER")
|
|
||||||
open class ToothpickExtension(objects: ObjectFactory) {
|
|
||||||
lateinit var project: Project
|
|
||||||
lateinit var forkName: String
|
|
||||||
val forkNameLowercase
|
|
||||||
get() = forkName.toLowerCase(Locale.ENGLISH)
|
|
||||||
lateinit var forkUrl: String
|
|
||||||
lateinit var forkVersion: String
|
|
||||||
lateinit var groupId: String
|
|
||||||
lateinit var minecraftVersion: String
|
|
||||||
lateinit var nmsRevision: String
|
|
||||||
lateinit var nmsPackage: String
|
|
||||||
|
|
||||||
lateinit var upstream: String
|
|
||||||
val upstreamLowercase
|
|
||||||
get() = upstream.toLowerCase(Locale.ENGLISH)
|
|
||||||
lateinit var upstreamBranch: String
|
|
||||||
|
|
||||||
var paperclipName: String = ""
|
|
||||||
get(): String = if (field.isEmpty()) {
|
|
||||||
"$forkNameLowercase-paperclip.jar"
|
|
||||||
} else "$field.jar"
|
|
||||||
|
|
||||||
lateinit var serverProject: ToothpickSubproject
|
|
||||||
fun server(receiver: ToothpickSubproject.() -> Unit) {
|
|
||||||
serverProject = ToothpickSubproject()
|
|
||||||
receiver(serverProject)
|
|
||||||
}
|
|
||||||
|
|
||||||
lateinit var apiProject: ToothpickSubproject
|
|
||||||
fun api(receiver: ToothpickSubproject.() -> Unit) {
|
|
||||||
apiProject = ToothpickSubproject()
|
|
||||||
receiver(apiProject)
|
|
||||||
}
|
|
||||||
|
|
||||||
val subprojects: Map<String, ToothpickSubproject>
|
|
||||||
get() = if (::forkName.isInitialized) mapOf(
|
|
||||||
"$forkName-API" to apiProject,
|
|
||||||
"$forkName-Server" to serverProject
|
|
||||||
) else emptyMap()
|
|
||||||
|
|
||||||
val paperDir: File by lazy {
|
|
||||||
if (upstream == "Paper") {
|
|
||||||
project.upstreamDir
|
|
||||||
} else {
|
|
||||||
project.upstreamDir.walk().find {
|
|
||||||
it.name == "Paper" && it.isDirectory
|
|
||||||
&& it.resolve("work/Minecraft/${minecraftVersion}").exists()
|
|
||||||
} ?: error("Failed to find Paper directory!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val paperWorkDir: File
|
|
||||||
get() = paperDir.resolve("work/Minecraft/${minecraftVersion}")
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
import org.gradle.api.Project
|
|
||||||
import org.gradle.kotlin.dsl.findByType
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
val Project.toothpick: ToothpickExtension
|
|
||||||
get() = rootProject.extensions.findByType(ToothpickExtension::class)!!
|
|
||||||
|
|
||||||
fun Project.toothpick(receiver: ToothpickExtension.() -> Unit) {
|
|
||||||
toothpick.project = this
|
|
||||||
receiver(toothpick)
|
|
||||||
allprojects {
|
|
||||||
group = toothpick.groupId
|
|
||||||
version = "${toothpick.minecraftVersion}-${toothpick.nmsRevision}"
|
|
||||||
}
|
|
||||||
configureSubprojects()
|
|
||||||
initToothpickTasks()
|
|
||||||
}
|
|
||||||
|
|
||||||
val Project.lastUpstream: File
|
|
||||||
get() = rootProject.projectDir.resolve("last-${toothpick.upstreamLowercase}")
|
|
||||||
|
|
||||||
val Project.rootProjectDir: File
|
|
||||||
get() = rootProject.projectDir
|
|
||||||
|
|
||||||
val Project.upstreamDir: File
|
|
||||||
get() = rootProject.projectDir.resolve(toothpick.upstream)
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
import org.gradle.api.Project
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
class ToothpickSubproject {
|
|
||||||
lateinit var project: Project
|
|
||||||
|
|
||||||
val baseDir: File by lazy {
|
|
||||||
val name = project.name
|
|
||||||
val upstream = project.toothpick.upstream
|
|
||||||
val suffix = if (name.endsWith("server")) "Server" else "API"
|
|
||||||
project.upstreamDir.resolve("$upstream-$suffix")
|
|
||||||
}
|
|
||||||
val projectDir: File
|
|
||||||
get() = project.projectDir
|
|
||||||
lateinit var patchesDir: File
|
|
||||||
|
|
||||||
operator fun component1(): File = baseDir
|
|
||||||
operator fun component2(): File = projectDir
|
|
||||||
operator fun component3(): File = patchesDir
|
|
||||||
}
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
import org.gradle.api.Project
|
|
||||||
import java.io.File
|
|
||||||
import java.util.LinkedList
|
|
||||||
import kotlin.streams.asSequence
|
|
||||||
|
|
||||||
data class CmdResult(val exitCode: Int, val output: String?)
|
|
||||||
|
|
||||||
fun Project.cmd(
|
|
||||||
vararg args: String,
|
|
||||||
dir: File = rootProject.projectDir,
|
|
||||||
printOut: Boolean = false
|
|
||||||
): CmdResult {
|
|
||||||
val process = ProcessBuilder()
|
|
||||||
.command(*args)
|
|
||||||
.redirectErrorStream(true)
|
|
||||||
.directory(dir)
|
|
||||||
.start()
|
|
||||||
val output = process.inputStream.bufferedReader().use { reader ->
|
|
||||||
reader.lines().asSequence()
|
|
||||||
.onEach {
|
|
||||||
if (printOut) {
|
|
||||||
logger.lifecycle(it)
|
|
||||||
} else {
|
|
||||||
logger.debug(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.toCollection(LinkedList())
|
|
||||||
.joinToString(separator = "\n")
|
|
||||||
}
|
|
||||||
val exit = process.waitFor()
|
|
||||||
return CmdResult(exit, output)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun ensureSuccess(
|
|
||||||
cmd: CmdResult,
|
|
||||||
errorHandler: CmdResult.() -> Unit = {}
|
|
||||||
): String? {
|
|
||||||
val (exit, output) = cmd
|
|
||||||
if (exit != 0) {
|
|
||||||
errorHandler(cmd)
|
|
||||||
error("Failed to run command, exit code is $exit")
|
|
||||||
}
|
|
||||||
return output
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Project.gitCmd(
|
|
||||||
vararg args: String,
|
|
||||||
dir: File = rootProject.projectDir,
|
|
||||||
printOut: Boolean = false
|
|
||||||
): CmdResult =
|
|
||||||
cmd("git", *args, dir = dir, printOut = printOut)
|
|
||||||
|
|
||||||
fun Project.bashCmd(
|
|
||||||
vararg args: String,
|
|
||||||
dir: File = rootProject.projectDir,
|
|
||||||
printOut: Boolean = false
|
|
||||||
): CmdResult =
|
|
||||||
cmd("bash", "-c", *args, dir = dir, printOut = printOut)
|
|
||||||
|
|
||||||
internal fun String.applyReplacements(
|
|
||||||
vararg replacements: Pair<String, String>
|
|
||||||
): String {
|
|
||||||
var result = this
|
|
||||||
for ((key, value) in replacements) {
|
|
||||||
result = result.replace("\${$key}", value)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Project.gitSigningEnabled(repo: File): Boolean =
|
|
||||||
gitCmd("config", "commit.gpgsign", dir = repo).output?.toBoolean() == true
|
|
||||||
|
|
||||||
internal fun Project.temporarilyDisableGitSigning(repo: File): Boolean {
|
|
||||||
val isCurrentlyEnabled = gitSigningEnabled(repo)
|
|
||||||
if (isCurrentlyEnabled) {
|
|
||||||
gitCmd("config", "commit.gpgsign", "false", dir = repo)
|
|
||||||
}
|
|
||||||
return isCurrentlyEnabled
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun Project.reEnableGitSigning(repo: File) {
|
|
||||||
gitCmd("config", "commit.gpgsign", "true", dir = repo)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Project.gitHash(repo: File): String =
|
|
||||||
gitCmd("rev-parse", "HEAD", dir = repo).output ?: ""
|
|
||||||
|
|
||||||
val jenkins = System.getenv("JOB_NAME") != null
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
package task
|
|
||||||
|
|
||||||
import ensureSuccess
|
|
||||||
import gitCmd
|
|
||||||
import org.gradle.api.Project
|
|
||||||
import org.gradle.api.Task
|
|
||||||
import reEnableGitSigning
|
|
||||||
import taskGroup
|
|
||||||
import temporarilyDisableGitSigning
|
|
||||||
import toothpick
|
|
||||||
import java.nio.file.Files
|
|
||||||
|
|
||||||
internal fun Project.createApplyPatchesTask(
|
|
||||||
receiver: Task.() -> Unit = {}
|
|
||||||
): Task = tasks.create("applyPatches") {
|
|
||||||
receiver(this)
|
|
||||||
group = taskGroup
|
|
||||||
doLast {
|
|
||||||
for ((name, subproject) in toothpick.subprojects) {
|
|
||||||
val (sourceRepo, projectDir, patchesDir) = subproject
|
|
||||||
|
|
||||||
// Reset or initialize subproject
|
|
||||||
logger.lifecycle(">>> Resetting subproject $name")
|
|
||||||
if (projectDir.exists()) {
|
|
||||||
ensureSuccess(gitCmd("fetch", "origin", dir = projectDir))
|
|
||||||
ensureSuccess(gitCmd("reset", "--hard", "origin/master", dir = projectDir))
|
|
||||||
} else {
|
|
||||||
ensureSuccess(gitCmd("clone", sourceRepo.absolutePath, projectDir.absolutePath))
|
|
||||||
}
|
|
||||||
logger.lifecycle(">>> Done resetting subproject $name")
|
|
||||||
|
|
||||||
// Apply patches
|
|
||||||
val patchPaths = Files.newDirectoryStream(patchesDir.toPath())
|
|
||||||
.map { it.toFile() }
|
|
||||||
.filter { it.name.endsWith(".patch") }
|
|
||||||
.sorted()
|
|
||||||
.takeIf { it.isNotEmpty() } ?: continue
|
|
||||||
val patches = patchPaths.map { it.absolutePath }.toTypedArray()
|
|
||||||
|
|
||||||
val wasGitSigningEnabled = temporarilyDisableGitSigning(projectDir)
|
|
||||||
|
|
||||||
logger.lifecycle(">>> Applying patches to $name")
|
|
||||||
|
|
||||||
val gitCommand = arrayListOf("am", "--3way", "--ignore-whitespace", *patches)
|
|
||||||
ensureSuccess(gitCmd(*gitCommand.toTypedArray(), dir = projectDir, printOut = true)) {
|
|
||||||
if (wasGitSigningEnabled) reEnableGitSigning(projectDir)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wasGitSigningEnabled) reEnableGitSigning(projectDir)
|
|
||||||
logger.lifecycle(">>> Done applying patches to $name")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
package task
|
|
||||||
|
|
||||||
import LibraryImport
|
|
||||||
import ensureSuccess
|
|
||||||
import gitCmd
|
|
||||||
import internalTaskGroup
|
|
||||||
import libraryImports
|
|
||||||
import nmsImports
|
|
||||||
import org.gradle.api.Project
|
|
||||||
import org.gradle.api.Task
|
|
||||||
import toothpick
|
|
||||||
|
|
||||||
internal fun Project.createImportMCDevTask(
|
|
||||||
receiver: Task.() -> Unit = {}
|
|
||||||
): Task = tasks.create("importMCDev") {
|
|
||||||
receiver(this)
|
|
||||||
group = internalTaskGroup
|
|
||||||
val upstreamServer = toothpick.serverProject.baseDir
|
|
||||||
val importLog = arrayListOf("Extra mc-dev imports")
|
|
||||||
|
|
||||||
fun importNMS(className: String) {
|
|
||||||
logger.lifecycle("Importing n.m.s.$className")
|
|
||||||
importLog.add("Imported n.m.s.$className")
|
|
||||||
val source = toothpick.paperWorkDir.resolve("spigot/net/minecraft/server/$className.java")
|
|
||||||
if (!source.exists()) error("Missing NMS: $className")
|
|
||||||
val target = upstreamServer.resolve("src/main/java/net/minecraft/server/$className.java")
|
|
||||||
source.copyTo(target)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun importLibrary(import: LibraryImport) {
|
|
||||||
val (group, lib, prefix, file) = import
|
|
||||||
logger.lifecycle("Importing $group.$lib $prefix/$file")
|
|
||||||
importLog.add("Imported $group.$lib $prefix/$file")
|
|
||||||
val source = toothpick.paperWorkDir.resolve("libraries/$group/$lib/$prefix/$file.java")
|
|
||||||
if (!source.exists()) error("Missing Base: $lib $prefix/$file")
|
|
||||||
val targetDir = upstreamServer.resolve("src/main/java/$prefix")
|
|
||||||
val target = targetDir.resolve("$file.java")
|
|
||||||
targetDir.mkdirs()
|
|
||||||
source.copyTo(target)
|
|
||||||
}
|
|
||||||
|
|
||||||
doLast {
|
|
||||||
logger.lifecycle(">>> Importing mc-dev")
|
|
||||||
val lastCommitIsMCDev = gitCmd(
|
|
||||||
"log", "-1", "--oneline",
|
|
||||||
dir = upstreamServer
|
|
||||||
).output?.contains("Extra mc-dev imports") == true
|
|
||||||
if (lastCommitIsMCDev) {
|
|
||||||
ensureSuccess(
|
|
||||||
gitCmd(
|
|
||||||
"reset", "--hard", "HEAD~1",
|
|
||||||
dir = upstreamServer,
|
|
||||||
printOut = true
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
(toothpick.serverProject.patchesDir.listFiles() ?: error("No patches in server?")).asSequence()
|
|
||||||
.flatMap { it.readLines().asSequence() }
|
|
||||||
.filter { it.startsWith("+++ b/src/main/java/net/minecraft/server/") }
|
|
||||||
.distinct()
|
|
||||||
.map { it.substringAfter("/server/").substringBefore(".java") }
|
|
||||||
.filter { !upstreamServer.resolve("src/main/java/net/minecraft/server/$it.java").exists() }
|
|
||||||
.map { toothpick.paperWorkDir.resolve("spigot/net/minecraft/server/$it.java") }
|
|
||||||
.filter {
|
|
||||||
val exists = it.exists()
|
|
||||||
if (!it.exists()) logger.lifecycle("NMS ${it.nameWithoutExtension} is either missing, or is a new file added through a patch")
|
|
||||||
exists
|
|
||||||
}
|
|
||||||
.map { it.nameWithoutExtension }
|
|
||||||
.forEach(::importNMS)
|
|
||||||
|
|
||||||
// Imports from MCDevImports.kt
|
|
||||||
nmsImports.forEach(::importNMS)
|
|
||||||
libraryImports.forEach(::importLibrary)
|
|
||||||
|
|
||||||
val add = gitCmd("add", ".", "-A", dir = upstreamServer).exitCode == 0
|
|
||||||
val commit = gitCmd("commit", "-m", importLog.joinToString("\n"), dir = upstreamServer).exitCode == 0
|
|
||||||
if (!add || !commit) {
|
|
||||||
logger.lifecycle(">>> Didn't import any extra files")
|
|
||||||
}
|
|
||||||
logger.lifecycle(">>> Done importing mc-dev")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
package task
|
|
||||||
|
|
||||||
import gitCmd
|
|
||||||
import org.gradle.api.Project
|
|
||||||
import org.gradle.api.Task
|
|
||||||
import taskGroup
|
|
||||||
import upstreamDir
|
|
||||||
|
|
||||||
internal fun Project.createInitGitSubmodulesTask(
|
|
||||||
receiver: Task.() -> Unit = {}
|
|
||||||
): Task = tasks.create("initGitSubmodules") {
|
|
||||||
receiver(this)
|
|
||||||
group = taskGroup
|
|
||||||
onlyIf { !upstreamDir.resolve(".git").exists() }
|
|
||||||
doLast {
|
|
||||||
val exit = gitCmd("submodule", "update", "--init", "--recursive", printOut = true).exitCode
|
|
||||||
if (exit != 0) {
|
|
||||||
error("Failed to checkout git submodules: git exited with code $exit")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
package task
|
|
||||||
|
|
||||||
import cmd
|
|
||||||
import ensureSuccess
|
|
||||||
import jenkins
|
|
||||||
import org.gradle.api.Project
|
|
||||||
import org.gradle.api.Task
|
|
||||||
import rootProjectDir
|
|
||||||
import taskGroup
|
|
||||||
import toothpick
|
|
||||||
|
|
||||||
internal fun Project.createPaperclipTask(
|
|
||||||
receiver: Task.() -> Unit = {}
|
|
||||||
): Task = tasks.create("paperclip") {
|
|
||||||
receiver(this)
|
|
||||||
group = taskGroup
|
|
||||||
doLast {
|
|
||||||
val workDir = toothpick.paperDir.resolve("work")
|
|
||||||
val paperclipDir = workDir.resolve("Paperclip")
|
|
||||||
val vanillaJarPath =
|
|
||||||
workDir.resolve("Minecraft/${toothpick.minecraftVersion}/${toothpick.minecraftVersion}.jar").absolutePath
|
|
||||||
val patchedJarPath = inputs.files.singleFile.absolutePath
|
|
||||||
logger.lifecycle(">>> Building paperclip")
|
|
||||||
val paperclipCmd = arrayListOf(
|
|
||||||
"mvn", "clean", "package",
|
|
||||||
"-Dmcver=${toothpick.minecraftVersion}",
|
|
||||||
"-Dpaperjar=$patchedJarPath",
|
|
||||||
"-Dvanillajar=$vanillaJarPath"
|
|
||||||
)
|
|
||||||
if (jenkins) paperclipCmd.add("-Dstyle.color=never")
|
|
||||||
ensureSuccess(cmd(*paperclipCmd.toTypedArray(), dir = paperclipDir, printOut = true))
|
|
||||||
val paperClip = paperclipDir.resolve("assembly/target/paperclip-${toothpick.minecraftVersion}.jar")
|
|
||||||
val destination = rootProjectDir.resolve(toothpick.paperclipName)
|
|
||||||
paperClip.copyTo(destination, overwrite = true)
|
|
||||||
logger.lifecycle(">>> ${toothpick.paperclipName} saved to root project directory")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
package task
|
|
||||||
|
|
||||||
import ensureSuccess
|
|
||||||
import gitCmd
|
|
||||||
import org.gradle.api.Project
|
|
||||||
import org.gradle.api.Task
|
|
||||||
import taskGroup
|
|
||||||
import toothpick
|
|
||||||
|
|
||||||
@Suppress("UNUSED_VARIABLE")
|
|
||||||
internal fun Project.createRebuildPatchesTask(
|
|
||||||
receiver: Task.() -> Unit = {}
|
|
||||||
): Task = tasks.create("rebuildPatches") {
|
|
||||||
receiver(this)
|
|
||||||
group = taskGroup
|
|
||||||
doLast {
|
|
||||||
for ((name, subproject) in toothpick.subprojects) {
|
|
||||||
val (sourceRepo, projectDir, patchesDir) = subproject
|
|
||||||
|
|
||||||
if (!patchesDir.exists()) {
|
|
||||||
patchesDir.mkdirs()
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.lifecycle(">>> Rebuilding patches for $name")
|
|
||||||
|
|
||||||
// Nuke old patches
|
|
||||||
patchesDir.listFiles()
|
|
||||||
?.filter { it.name.endsWith(".patch") }
|
|
||||||
?.forEach { it.delete() }
|
|
||||||
|
|
||||||
// And generate new
|
|
||||||
ensureSuccess(
|
|
||||||
gitCmd(
|
|
||||||
"format-patch",
|
|
||||||
"--no-stat", "--zero-commit", "--full-index", "--no-signature", "-N",
|
|
||||||
"-o", patchesDir.absolutePath, "origin/master",
|
|
||||||
dir = projectDir,
|
|
||||||
printOut = true
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
logger.lifecycle(">>> Done rebuilding patches for $name")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
package task
|
|
||||||
|
|
||||||
import bashCmd
|
|
||||||
import gitHash
|
|
||||||
import lastUpstream
|
|
||||||
import org.gradle.api.Project
|
|
||||||
import org.gradle.api.Task
|
|
||||||
import taskGroup
|
|
||||||
import toothpick
|
|
||||||
import upstreamDir
|
|
||||||
|
|
||||||
internal fun Project.createSetupUpstreamTask(
|
|
||||||
receiver: Task.() -> Unit = {}
|
|
||||||
): Task = tasks.create("setupUpstream") {
|
|
||||||
receiver(this)
|
|
||||||
group = taskGroup
|
|
||||||
doLast {
|
|
||||||
val setupUpstreamCommand = if (upstreamDir.resolve(toothpick.upstreamLowercase).exists()) {
|
|
||||||
"./${toothpick.upstreamLowercase} patch"
|
|
||||||
} else if (
|
|
||||||
upstreamDir.resolve("build.gradle.kts").exists()
|
|
||||||
&& upstreamDir.resolve("subprojects/server.gradle.kts").exists()
|
|
||||||
&& upstreamDir.resolve("subprojects/api.gradle.kts").exists()
|
|
||||||
) {
|
|
||||||
"./gradlew applyPatches"
|
|
||||||
} else {
|
|
||||||
error("Don't know how to setup upstream!")
|
|
||||||
}
|
|
||||||
val result = bashCmd(setupUpstreamCommand, dir = upstreamDir, printOut = true)
|
|
||||||
if (result.exitCode != 0) {
|
|
||||||
error("Failed to apply upstream patches: script exited with code ${result.exitCode}")
|
|
||||||
}
|
|
||||||
lastUpstream.writeText(gitHash(upstreamDir))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
package task
|
|
||||||
|
|
||||||
import ensureSuccess
|
|
||||||
import gitCmd
|
|
||||||
import org.gradle.api.Project
|
|
||||||
import org.gradle.api.Task
|
|
||||||
import rootProjectDir
|
|
||||||
import taskGroup
|
|
||||||
import toothpick
|
|
||||||
import upstreamDir
|
|
||||||
|
|
||||||
internal fun Project.createUpdateUpstreamTask(
|
|
||||||
receiver: Task.() -> Unit = {}
|
|
||||||
): Task = tasks.create("updateUpstream") {
|
|
||||||
receiver(this)
|
|
||||||
group = taskGroup
|
|
||||||
doLast {
|
|
||||||
ensureSuccess(gitCmd("fetch", dir = upstreamDir, printOut = true))
|
|
||||||
ensureSuccess(gitCmd("reset", "--hard", toothpick.upstreamBranch, dir = upstreamDir, printOut = true))
|
|
||||||
ensureSuccess(gitCmd("add", toothpick.upstream, dir = rootProjectDir, printOut = true))
|
|
||||||
ensureSuccess(gitCmd("submodule", "update", "--init", "--recursive", dir = upstreamDir, printOut = true))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
package task
|
|
||||||
|
|
||||||
import ensureSuccess
|
|
||||||
import gitCmd
|
|
||||||
import org.gradle.api.Project
|
|
||||||
import org.gradle.api.Task
|
|
||||||
import taskGroup
|
|
||||||
import toothpick
|
|
||||||
import upstreamDir
|
|
||||||
|
|
||||||
internal fun Project.createUpstreamCommitTask(
|
|
||||||
receiver: Task.() -> Unit = {}
|
|
||||||
): Task = tasks.create("upstreamCommit") {
|
|
||||||
receiver(this)
|
|
||||||
group = taskGroup
|
|
||||||
doLast {
|
|
||||||
val oldRev = ensureSuccess(gitCmd("ls-tree", "HEAD", toothpick.upstream))
|
|
||||||
?.substringAfter("commit ")?.substringBefore("\t")
|
|
||||||
val gitChangelog =
|
|
||||||
ensureSuccess(gitCmd("log", "--oneline", "$oldRev...HEAD", printOut = true, dir = upstreamDir)) {
|
|
||||||
logger.lifecycle("No upstream changes to commit?")
|
|
||||||
}
|
|
||||||
val commitMessage = """
|
|
||||||
|Updated Upstream (${toothpick.upstream})
|
|
||||||
|
|
|
||||||
|Upstream has released updates that appear to apply and compile correctly
|
|
||||||
|
|
|
||||||
|${toothpick.upstream} Changes:
|
|
||||||
|$gitChangelog
|
|
||||||
""".trimMargin()
|
|
||||||
ensureSuccess(gitCmd("commit", "-m", commitMessage, printOut = true))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
29
mcdevimports.json
Normal file
29
mcdevimports.json
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"nmsImports": [],
|
||||||
|
"libraryImports": [
|
||||||
|
{
|
||||||
|
"group": "com.mojang",
|
||||||
|
"library": "brigadier",
|
||||||
|
"prefix": "com/mojang/brigadier",
|
||||||
|
"file": "CommandDispatcher"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "com.mojang",
|
||||||
|
"library": "brigadier",
|
||||||
|
"prefix": "com/mojang/brigadier/tree",
|
||||||
|
"file": "LiteralCommandNode"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "com.mojang",
|
||||||
|
"library": "brigadier",
|
||||||
|
"prefix": "com/mojang/brigadier/suggestion",
|
||||||
|
"file": "SuggestionsBuilder"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "com.mojang",
|
||||||
|
"library": "brigadier",
|
||||||
|
"prefix": "com/mojang/brigadier/arguments",
|
||||||
|
"file": "BoolArgumentType"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,5 +1,13 @@
|
|||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
|
pluginManagement {
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
jcenter()
|
||||||
|
maven("https://repo.jpenilla.xyz/snapshots")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val forkName = "Purpur"
|
val forkName = "Purpur"
|
||||||
val forkNameLowercase = forkName.toLowerCase(Locale.ENGLISH)
|
val forkNameLowercase = forkName.toLowerCase(Locale.ENGLISH)
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
import xyz.jpenilla.toothpick.loadDependencies
|
||||||
|
import xyz.jpenilla.toothpick.loadRepositories
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
loadRepositories(project)
|
loadRepositories(project)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
import xyz.jpenilla.toothpick.loadDependencies
|
||||||
|
import xyz.jpenilla.toothpick.loadRepositories
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
loadRepositories(project)
|
loadRepositories(project)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user