From bba80af506a7ad35a0454179a02c3671ec935701 Mon Sep 17 00:00:00 2001 From: sky Date: Wed, 30 Jun 2021 17:47:43 +0800 Subject: [PATCH] 1.6 minimize --- build.gradle | 1 + .../izzel/taboolib/gradle/Description.groovy | 205 ++++++++++++++++++ .../izzel/taboolib/gradle/RelocateJar.groovy | 100 ++++++++- .../taboolib/gradle/TabooLibExtension.groovy | 7 + .../taboolib/gradle/TabooLibPlugin.groovy | 1 + 5 files changed, 307 insertions(+), 7 deletions(-) create mode 100644 src/main/groovy/io/izzel/taboolib/gradle/Description.groovy diff --git a/build.gradle b/build.gradle index 5bfd6b7..89454c8 100644 --- a/build.gradle +++ b/build.gradle @@ -23,6 +23,7 @@ dependencies { compile localGroovy() embed 'org.ow2.asm:asm:8.0.1' embed 'org.ow2.asm:asm-commons:8.0.1' + embed 'com.google.code.gson:gson:2.8.7' } jar { diff --git a/src/main/groovy/io/izzel/taboolib/gradle/Description.groovy b/src/main/groovy/io/izzel/taboolib/gradle/Description.groovy new file mode 100644 index 0000000..52820a3 --- /dev/null +++ b/src/main/groovy/io/izzel/taboolib/gradle/Description.groovy @@ -0,0 +1,205 @@ +package io.izzel.taboolib.gradle + +import com.google.gson.Gson +import com.google.gson.GsonBuilder +import org.gradle.api.Project +import com.google.gson.JsonArray +import com.google.gson.JsonObject + +import java.nio.charset.StandardCharsets + +class Description { + + def authors + def contributors + def depend + def softdepend + def loadbefore + def website + def prefix + def load + def api = "1.0.0" + def apiVersion = '1.13' + def libraries + def dependencies = "spongeapi@7.2.0" + def requiredMods = "spongeapi@7.2.0" + + static List buildFile() { + def str = [] + str += "" + str += "" + str += "# Powered by TabooLib 6.0 #" + str += "" + str += "" + return str + } + + static def appendName(str, any, key) { + if (any != null) { + str.add("$key: $any") + } + } + + static def appendNameList(str, any, key) { + if (any instanceof List) { + str.add("$key:") + for (i in any) { + str.add(" - '${i}'") + } + } else if (any != null) { + str.add("$key:") + str.add(" - '${any}'") + } + } + + byte[] buildBukkitFile(Project project) { + def str = buildFile() + str += "name: ${project.name}" + str += "main: ${project.group}.taboolib.platform.BukkitPlugin" + appendName(str, load, "load") + str += "version: ${project.version}" + if (apiVersion != null) { + str += "api-version: ${apiVersion}" + } + appendName(str, prefix, "prefix") + appendName(str, website, "website") + appendNameList(str, authors, "authors") + appendNameList(str, contributors, "contributors") + appendNameList(str, depend, "depend") + appendNameList(str, softdepend, "softdepend") + appendNameList(str, loadbefore, "loadbefore") + appendNameList(str, libraries, "libraries") + return str.join("\n").getBytes(StandardCharsets.UTF_8) + } + + byte[] buildBungeeFile(Project project) { + def str = buildFile() + str += "name: ${project.name}" + str += "main: ${project.group}.taboolib.platform.BungeePlugin" + str += "version: ${project.version}" + appendName(str, authors, "author") + appendNameList(str, depend, "depends") + appendNameList(str, softdepend, "softDepends") + appendNameList(str, libraries, "libraries") + return str.join("\n").getBytes(StandardCharsets.UTF_8) + } + + byte[] buildNukkitFile(Project project) { + def str = buildFile() + str += "name: ${project.name}" + str += "main: ${project.group}.taboolib.platform.NukkitPlugin" + appendName(str, load, "load") + str += "version: ${project.version}" + if (api != null) { + str += "api: ${api}" + } + appendName(str, prefix, "prefix") + appendName(str, website, "website") + appendNameList(str, authors, "authors") + appendNameList(str, depend, "depend") + appendNameList(str, softdepend, "softdepend") + appendNameList(str, loadbefore, "loadbefore") + appendNameList(str, libraries, "libraries") + return str.join("\n").getBytes(StandardCharsets.UTF_8) + } + + byte[] buildSpongeFile(Project project) { + def base = new JsonArray() + def info = new JsonObject() + info.addProperty("modid", project.name.toLowerCase()) + info.addProperty("name", project.name) + info.addProperty("version", project.version.toString()) + if (website != null) { + info.addProperty("url", website.toString()) + } + if (authors instanceof List) { + def arr = new JsonArray() + authors.each { arr.add(it) } + info.add("authorList", arr) + } else if (authors != null) { + def arr = new JsonArray() + arr.add(authors.toString()) + info.add("authorList", arr) + } + if (dependencies instanceof List) { + def arr = new JsonArray() + dependencies.each { arr.add(it) } + info.add("dependencies", arr) + } else if (dependencies != null) { + def arr = new JsonArray() + arr.add(dependencies.toString()) + info.add("dependencies", arr) + } + if (requiredMods instanceof List) { + def arr = new JsonArray() + requiredMods.each { arr.add(it) } + info.add("requiredMods", arr) + } else if (requiredMods != null) { + def arr = new JsonArray() + arr.add(requiredMods.toString()) + info.add("requiredMods", arr) + } + base.add(info) + return new GsonBuilder().setPrettyPrinting().create().toJson(base).getBytes(StandardCharsets.UTF_8) + } + + def author(author) { + this.authors = author + } + + def contributor(contributor) { + this.contributors = contributor + } + + def authors(author) { + this.authors = author + } + + def contributors(contributor) { + this.contributors = contributor + } + + def depend(depend) { + this.depend = depend + } + + def softdepend(softdepend) { + this.softdepend = softdepend + } + + def loadbefore(loadbefore) { + this.loadbefore = loadbefore + } + + def website(website) { + this.website = website + } + + def prefix(prefix) { + this.prefix = prefix + } + + def load(load) { + this.load = load + } + + def api(api) { + this.api = api + } + + def apiVersion(apiVersion) { + this.apiVersion = apiVersion + } + + def libraries(libraries) { + this.libraries = libraries + } + + def dependencies(dependencies) { + this.dependencies = dependencies + } + + def requiredMods(requiredMods) { + this.requiredMods = requiredMods + } +} diff --git a/src/main/groovy/io/izzel/taboolib/gradle/RelocateJar.groovy b/src/main/groovy/io/izzel/taboolib/gradle/RelocateJar.groovy index 6c8fcb2..b55a6c3 100644 --- a/src/main/groovy/io/izzel/taboolib/gradle/RelocateJar.groovy +++ b/src/main/groovy/io/izzel/taboolib/gradle/RelocateJar.groovy @@ -16,6 +16,7 @@ import java.nio.file.StandardCopyOption import java.util.jar.JarEntry import java.util.jar.JarFile import java.util.jar.JarOutputStream +import java.util.stream.Collectors @ToString class RelocateJar extends DefaultTask { @@ -33,24 +34,25 @@ class RelocateJar extends DefaultTask { @Input Project project + @Input + TabooLibExtension tabooExt + @TaskAction def relocate() { + def isolated = new TreeMap>() def mapping = relocations.collectEntries { [(it.key.replace('.', '/')), it.value.replace('.', '/')] } def remapper = new RelocateRemapper(relocations, mapping as Map) def index = inJar.name.lastIndexOf('.') def name = inJar.name.substring(0, index) + (classifier == null ? "" : "-" + classifier) + inJar.name.substring(index) def outJar = new File(inJar.getParentFile(), name) - def tmpOut = File.createTempFile(name, ".jar") - def isolated = new HashMap>() - new JarOutputStream(new FileOutputStream(tmpOut)).withCloseable { out -> - project.logger.info(outJar.getAbsolutePath()) + def tempOut1 = File.createTempFile(name, ".jar") + new JarOutputStream(new FileOutputStream(tempOut1)).withCloseable { out -> int n def buf = new byte[32768] new JarFile(inJar).withCloseable { jarFile -> - for (def jarEntry : jarFile.entries()) { + jarFile.entries().each { def jarEntry -> jarFile.getInputStream(jarEntry).withCloseable { if (jarEntry.name.endsWith(".class")) { - project.logger.info("Relocating " + jarEntry.name) def reader = new ClassReader(it) def writer = new ClassWriter(0) def visitor = new TabooLibClassVisitor(writer, project) @@ -70,6 +72,90 @@ class RelocateJar extends DefaultTask { } } } - Files.copy(tmpOut.toPath(), outJar.toPath(), StandardCopyOption.REPLACE_EXISTING) + def use = new TreeMap>() + remapper.use.each { + it.value.each { e -> + def key = relocate(project, getNameWithOutExtension(e)) + def value = relocate(project, getNameWithOutExtension(it.key)) + use.computeIfAbsent(key) { new HashSet() }.add(value) + } + } + def transfer = new TreeMap() + isolated.each { + transfer[relocate(project, it.key)] = it.value.stream().map { i -> relocate(project, i) }.collect(Collectors.toList()) + } + isolated = transfer + def tempOut2 = File.createTempFile(name, ".jar") + new JarOutputStream(new FileOutputStream(tempOut2)).withCloseable { out -> + int n + def buf = new byte[32768] + def del = new HashSet() + def exclude = new HashSet() + new JarFile(tempOut1).withCloseable { jarFile -> + jarFile.entries().each { def jarEntry -> + jarFile.getInputStream(jarEntry).withCloseable { + if (jarEntry.name.endsWith(".class")) { + def nameWithOutExtension = getNameWithOutExtension(jarEntry.name) + if (use.containsKey(nameWithOutExtension.toString()) && !exclude.contains(nameWithOutExtension)) { + exclude.add(nameWithOutExtension) + if (isIsolated(use, use[nameWithOutExtension], isolated, nameWithOutExtension)) { + println(" Isolated ${nameWithOutExtension}") + del.add(nameWithOutExtension) + } + } + } + if (!del.contains(getNameWithOutExtension(jarEntry.name))) { + out.putNextEntry(new JarEntry(jarEntry.name)) + while ((n = it.read(buf)) != -1) { + out.write(buf, 0, n) + } + } + } + } + if (tabooExt.modules.contains("platform-bukkit")) { + out.putNextEntry(new JarEntry("plugin.yml")) + out.write(tabooExt.description.buildBukkitFile(project)) + } + if (tabooExt.modules.contains("platform-nukkit")) { + out.putNextEntry(new JarEntry("nukkit.yml")) + out.write(tabooExt.description.buildNukkitFile(project)) + } + if (tabooExt.modules.contains("platform-bungee")) { + out.putNextEntry(new JarEntry("bungee.yml")) + out.write(tabooExt.description.buildBungeeFile(project)) + } + if (tabooExt.modules.contains("platform-sponge")) { + out.putNextEntry(new JarEntry("mcmod.info")) + out.write(tabooExt.description.buildSpongeFile(project)) + } + } + } + Files.copy(tempOut2.toPath(), outJar.toPath(), StandardCopyOption.REPLACE_EXISTING) + } + + static String getNameWithOutExtension(name) { + if (name.contains('$')) { + return name.substring(0, name.indexOf('$')).replace('.', '/') + } else if (name.contains('.')) { + return name.substring(0, name.lastIndexOf('.')).replace('.', '/') + } else { + return name.replace('.', '/') + } + } + + static String relocate(Project project, String name) { + if (name.startsWith("taboolib")) { + return project.group.toString().replace('.', '/') + '/' + name.replace('.', '/') + } else { + return name.replace('.', '/') + } + } + + static boolean isIsolated(Map> use, Set refer, Map> isolated, String nameWithOutExtension) { + if (isolated.containsKey(nameWithOutExtension)) { + return refer.size() <= 1 || refer.stream().allMatch { nameWithOutExtension == it || isolated[nameWithOutExtension].contains(it) || isIsolated(use, use[it], isolated, it) } + } else { + return false + } } } diff --git a/src/main/groovy/io/izzel/taboolib/gradle/TabooLibExtension.groovy b/src/main/groovy/io/izzel/taboolib/gradle/TabooLibExtension.groovy index 025188e..2afcb3c 100644 --- a/src/main/groovy/io/izzel/taboolib/gradle/TabooLibExtension.groovy +++ b/src/main/groovy/io/izzel/taboolib/gradle/TabooLibExtension.groovy @@ -1,6 +1,7 @@ package io.izzel.taboolib.gradle import groovy.transform.Canonical +import org.codehaus.groovy.runtime.DefaultGroovyMethods @Canonical class TabooLibExtension { @@ -11,6 +12,8 @@ class TabooLibExtension { List modules = [] + Description description = new Description() + Map relocation = new LinkedHashMap<>() def install(String... name) { @@ -20,4 +23,8 @@ class TabooLibExtension { def relocate(String pre, String post) { relocation[pre] = post } + + def descriptionFile(@DelegatesTo(Description.class) Closure closure) { + DefaultGroovyMethods.with(description, closure) + } } diff --git a/src/main/groovy/io/izzel/taboolib/gradle/TabooLibPlugin.groovy b/src/main/groovy/io/izzel/taboolib/gradle/TabooLibPlugin.groovy index c5aa3da..15920eb 100644 --- a/src/main/groovy/io/izzel/taboolib/gradle/TabooLibPlugin.groovy +++ b/src/main/groovy/io/izzel/taboolib/gradle/TabooLibPlugin.groovy @@ -25,6 +25,7 @@ class TabooLibPlugin implements Plugin { } def jarTask = project.tasks.jar as Jar tabooTask.configure { RelocateJar task -> + task.tabooExt = tabooExt task.project = project task.inJar = task.inJar ?: jarTask.archivePath task.relocations = tabooExt.relocation