diff --git a/samples/mixed/bukkit-plugins/build.gradle.kts b/samples/mixed/bukkit-plugins/build.gradle.kts index eaad8b9..7daa471 100644 --- a/samples/mixed/bukkit-plugins/build.gradle.kts +++ b/samples/mixed/bukkit-plugins/build.gradle.kts @@ -2,9 +2,10 @@ plugins { id("gay.pizza.foundation.concrete-root") } -concrete { +concreteRoot { minecraftServerPath.set("server") paperServerVersionGroup.set("1.19") paperApiVersion.set("1.19.3-R0.1-SNAPSHOT") acceptServerEula.set(true) + expansiveItemInclusion.set(true) } diff --git a/samples/mixed/bukkit-plugins/hello-world/build.gradle.kts b/samples/mixed/bukkit-plugins/hello-world/build.gradle.kts index 73122c3..750339d 100644 --- a/samples/mixed/bukkit-plugins/hello-world/build.gradle.kts +++ b/samples/mixed/bukkit-plugins/hello-world/build.gradle.kts @@ -7,6 +7,6 @@ dependencies { implementation(project(":bukkit-plugins:common-library")) } -plugin { +concreteItem { dependency(project(":bukkit-plugins:goodbye-world")) } diff --git a/samples/mixed/other-library/build.gradle.kts b/samples/mixed/other-library/build.gradle.kts index 0cc335a..df84b58 100644 --- a/samples/mixed/other-library/build.gradle.kts +++ b/samples/mixed/other-library/build.gradle.kts @@ -1,3 +1,10 @@ plugins { id("gay.pizza.foundation.concrete-base") } + +concreteItem { + type.set("library") + fileInclusion { + tasks.jar.get().outputs.files.associateWith { "library-jar" } + } +} diff --git a/src/main/kotlin/gay/pizza/foundation/concrete/ConcreteBasePlugin.kt b/src/main/kotlin/gay/pizza/foundation/concrete/ConcreteBasePlugin.kt index 5fa0446..d026aad 100644 --- a/src/main/kotlin/gay/pizza/foundation/concrete/ConcreteBasePlugin.kt +++ b/src/main/kotlin/gay/pizza/foundation/concrete/ConcreteBasePlugin.kt @@ -4,6 +4,7 @@ import org.gradle.api.JavaVersion import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.plugins.JavaPluginExtension +import org.gradle.kotlin.dsl.create import org.gradle.kotlin.dsl.getByType import org.gradle.kotlin.dsl.withType import org.jetbrains.kotlin.gradle.tasks.KotlinCompile @@ -40,5 +41,7 @@ open class ConcreteBasePlugin : Plugin { } } } + + project.extensions.create("concreteItem") } } diff --git a/src/main/kotlin/gay/pizza/foundation/concrete/ConcreteItemExtension.kt b/src/main/kotlin/gay/pizza/foundation/concrete/ConcreteItemExtension.kt new file mode 100644 index 0000000..38ae04c --- /dev/null +++ b/src/main/kotlin/gay/pizza/foundation/concrete/ConcreteItemExtension.kt @@ -0,0 +1,21 @@ +package gay.pizza.foundation.concrete + +import org.gradle.api.DomainObjectSet +import org.gradle.api.Project +import org.gradle.api.provider.Property +import java.io.File + +interface ConcreteItemExtension { + val type: Property + val version: Property + val dependencies: DomainObjectSet + val fileInclusion: Property<() -> Map> + + fun dependency(project: Project) { + dependencies.add(project) + } + + fun fileInclusion(inclusion: () -> Map) { + fileInclusion.set(inclusion) + } +} diff --git a/src/main/kotlin/gay/pizza/foundation/concrete/ConcretePluginExtension.kt b/src/main/kotlin/gay/pizza/foundation/concrete/ConcretePluginExtension.kt deleted file mode 100644 index 71d7070..0000000 --- a/src/main/kotlin/gay/pizza/foundation/concrete/ConcretePluginExtension.kt +++ /dev/null @@ -1,12 +0,0 @@ -package gay.pizza.foundation.concrete - -import org.gradle.api.DomainObjectSet -import org.gradle.api.Project - -interface ConcretePluginExtension { - val dependencies: DomainObjectSet - - fun dependency(project: Project) { - dependencies.add(project) - } -} diff --git a/src/main/kotlin/gay/pizza/foundation/concrete/ConcretePluginPlugin.kt b/src/main/kotlin/gay/pizza/foundation/concrete/ConcretePluginPlugin.kt index 40577b4..9a0b661 100644 --- a/src/main/kotlin/gay/pizza/foundation/concrete/ConcretePluginPlugin.kt +++ b/src/main/kotlin/gay/pizza/foundation/concrete/ConcretePluginPlugin.kt @@ -1,6 +1,7 @@ package gay.pizza.foundation.concrete import org.gradle.api.Project +import org.gradle.kotlin.dsl.create import org.gradle.kotlin.dsl.get import org.gradle.language.jvm.tasks.ProcessResources @@ -9,8 +10,6 @@ class ConcretePluginPlugin : ConcreteBaseBukkitPlugin() { override fun apply(project: Project) { super.apply(project) - project.extensions.create("plugin", ConcretePluginExtension::class.java) - project.plugins.apply("com.github.johnrengelman.shadow") // During IDEA project import, if this code is active, it will print warnings. diff --git a/src/main/kotlin/gay/pizza/foundation/concrete/ConcreteRootExtension.kt b/src/main/kotlin/gay/pizza/foundation/concrete/ConcreteRootExtension.kt index d142547..e5ed334 100644 --- a/src/main/kotlin/gay/pizza/foundation/concrete/ConcreteRootExtension.kt +++ b/src/main/kotlin/gay/pizza/foundation/concrete/ConcreteRootExtension.kt @@ -7,4 +7,5 @@ interface ConcreteRootExtension { val paperApiVersion: Property val minecraftServerPath: Property val acceptServerEula: Property + val expansiveItemInclusion: Property } diff --git a/src/main/kotlin/gay/pizza/foundation/concrete/ConcreteRootPlugin.kt b/src/main/kotlin/gay/pizza/foundation/concrete/ConcreteRootPlugin.kt index 33b9d2b..e7be0c7 100644 --- a/src/main/kotlin/gay/pizza/foundation/concrete/ConcreteRootPlugin.kt +++ b/src/main/kotlin/gay/pizza/foundation/concrete/ConcreteRootPlugin.kt @@ -9,7 +9,7 @@ import java.nio.file.Paths class ConcreteRootPlugin : Plugin { override fun apply(project: Project) { project.apply(plugin = "base") - project.extensions.create("concrete") + project.extensions.create("concreteRoot") val setupPaperServer = project.tasks.create("setupPaperServer") val runPaperServer = project.tasks.create("runPaperServer") runPaperServer.dependsOn(setupPaperServer) diff --git a/src/main/kotlin/gay/pizza/foundation/concrete/UpdateManifestTask.kt b/src/main/kotlin/gay/pizza/foundation/concrete/UpdateManifestTask.kt index 5996f00..76f0f19 100644 --- a/src/main/kotlin/gay/pizza/foundation/concrete/UpdateManifestTask.kt +++ b/src/main/kotlin/gay/pizza/foundation/concrete/UpdateManifestTask.kt @@ -5,14 +5,20 @@ import org.gradle.api.tasks.TaskAction import java.nio.file.Files import java.nio.file.Path import kotlin.io.path.name +import kotlin.io.path.relativeTo open class UpdateManifestTask : DefaultTask() { @TaskAction fun update() { val manifestsDir = ensureManifestsDirectory() - val rootPath = project.projectDir.toPath() + val rootExtension = project.concreteRootExtension + val rootPath = if (rootExtension.expansiveItemInclusion.orNull == true) { + project.rootProject.rootDir + } else { + project.rootDir + } val legacyUpdateManifest = project.findPluginProjects().mapNotNull { project -> - val paths = project.shadowJarOutputs!!.allFilesRelativeToPath(rootPath) + val paths = project.shadowJarOutputs!!.files.allFilesRelativeToPath(rootPath.toPath()) if (paths.isNotEmpty()) { project.name to mapOf( @@ -25,24 +31,25 @@ open class UpdateManifestTask : DefaultTask() { val legacyUpdateFile = manifestsDir.resolve("update.json") Files.writeString(legacyUpdateFile, Globals.gson.toJson(legacyUpdateManifest)) - val extensibleUpdateManifestItems = project.findPluginProjects().mapNotNull { project -> - val paths = project.shadowJarOutputs!!.allFilesRelativeToPath(rootPath) + val extensibleUpdateManifestItems = project.findItemProjects().map { project -> + val concreteItemExtension = project.concreteItemExtension!! + val pathInclusion = concreteItemExtension.fileInclusion.orNull ?: { + project.shadowJarOutputs!!.files.associateWith { "plugin-jar" } + } + val paths = pathInclusion() + + val dependencies = concreteItemExtension.dependencies.map { it.name } - val dependencies = project.concretePluginExtension.dependencies.map { it.name } ExtensibleManifestItem( name = project.name, - type = "bukkit-plugin", - version = project.version.toString(), + type = concreteItemExtension.type.orNull ?: "bukkit-plugin", + version = concreteItemExtension.version.orNull ?: project.version.toString(), dependencies = dependencies, - files = paths.map { path -> - var type = "unknown" - if (path.name.endsWith("-plugin.jar")) { - type = "plugin-jar" - } + files = paths.map { (path, type) -> ExtensibleManifestItemFile( name = path.name, type = type, - path = path.toUnixString() + path = path.toPath().relativeTo(rootPath.toPath()).toUnixString() ) } ) diff --git a/src/main/kotlin/gay/pizza/foundation/concrete/extensions.kt b/src/main/kotlin/gay/pizza/foundation/concrete/extensions.kt index e757c38..ed3bbc6 100644 --- a/src/main/kotlin/gay/pizza/foundation/concrete/extensions.kt +++ b/src/main/kotlin/gay/pizza/foundation/concrete/extensions.kt @@ -4,6 +4,7 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import org.gradle.api.Project import org.gradle.api.tasks.TaskContainer import org.gradle.api.tasks.TaskOutputs +import java.io.File import java.nio.file.FileSystems import java.nio.file.Path @@ -12,11 +13,30 @@ import java.nio.file.Path */ internal fun Project.isPluginProject() = plugins.hasPlugin(ConcretePluginPlugin::class.java) +/** + * Checks if the project has the [ConcreteBasePlugin] applied and is opting into item behavior. + */ +internal fun Project.isConcreteItem() = + isPluginProject() || concreteItemExtension?.type?.orNull != null + /** * Finds all projects in the project's hierarchy that are plugins. */ internal fun Project.findPluginProjects() = allprojects.filter { project -> project.isPluginProject() } +/** + * Finds all projects in the project's hierarchy that are items. + */ +internal fun Project.findItemProjects(): List { + val optInExpansion = concreteRootExtension.expansiveItemInclusion.orNull ?: false + val searchScope = if (optInExpansion) { + project.rootProject.allprojects + } else { + allprojects + } + return searchScope.filter { project -> project.isConcreteItem() } +} + internal fun TaskContainer.addTaskDependency(dependent: String, dependency: String) { getByName(dependent).dependsOn(getByName(dependency)) } @@ -37,8 +57,8 @@ internal val Project.concreteRootExtension: ConcreteRootExtension error = { "Failed to find concrete root. Did you apply the concrete root plugin?" } ) -internal val Project.concretePluginExtension: ConcretePluginExtension - get() = extensions.getByType(ConcretePluginExtension::class.java) +internal val Project.concreteItemExtension: ConcreteItemExtension? + get() = extensions.findByType(ConcreteItemExtension::class.java) /** * Finds the concrete root project, which is the first project in the project hierarchy @@ -68,6 +88,6 @@ internal fun Project.findTargetParent(valid: Project.() -> Boolean, extract: throw RuntimeException(error()) } -internal fun TaskOutputs.allFilesRelativeToPath(root: Path): List = files.map { root.relativize(it.toPath()) } +internal fun Iterable.allFilesRelativeToPath(root: Path): List = map { root.relativize(it.toPath()) } internal fun Path.toUnixString() = toString().replace(FileSystems.getDefault().separator, "/")