aboutsummaryrefslogtreecommitdiff
path: root/build-logic
diff options
context:
space:
mode:
Diffstat (limited to 'build-logic')
-rw-r--r--build-logic/build.gradle.kts22
l---------build-logic/gradle/wrapper1
-rwxr-xr-xbuild-logic/gradlew251
-rw-r--r--build-logic/gradlew.bat94
-rw-r--r--build-logic/settings.gradle.kts8
-rw-r--r--build-logic/src/main/kotlin/EnvFile.kt13
-rw-r--r--build-logic/src/main/kotlin/FabricModTransform.kt80
-rw-r--r--build-logic/src/main/kotlin/InnerJarsUnpacker.kt70
-rw-r--r--build-logic/src/main/kotlin/RepoDownload.kt41
-rw-r--r--build-logic/src/main/kotlin/firmament.base.gradle.kts1
-rw-r--r--build-logic/src/main/kotlin/firmament.common.gradle.kts2
-rw-r--r--build-logic/src/main/kotlin/firmament.license-management.gradle.kts5
-rw-r--r--build-logic/src/main/kotlin/firmament.repositories.gradle.kts46
-rw-r--r--build-logic/src/main/kotlin/licenseinfo.kt144
-rw-r--r--build-logic/src/main/kotlin/lookupversion.kt25
15 files changed, 803 insertions, 0 deletions
diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts
new file mode 100644
index 0000000..431a04e
--- /dev/null
+++ b/build-logic/build.gradle.kts
@@ -0,0 +1,22 @@
+// SPDX-FileCopyrightText: 2023 Linnea Gräf <nea@nea.moe>
+//
+// SPDX-License-Identifier: CC0-1.0
+
+plugins {
+ `kotlin-dsl`
+ kotlin("jvm") version "2.0.21"
+}
+repositories {
+ mavenCentral()
+ gradlePluginPortal()
+ maven {
+ name = "jitpack"
+ url = uri("https://jitpack.io")
+ }
+}
+dependencies {
+ implementation("com.github.romangraef:neaslicenseextractificator:1.1.0")
+ api("com.gradleup.shadow:shadow-gradle-plugin:9.0.0-rc1")
+ implementation("net.fabricmc:access-widener:2.1.0")
+ implementation("com.google.code.gson:gson:2.10.1")
+}
diff --git a/build-logic/gradle/wrapper b/build-logic/gradle/wrapper
new file mode 120000
index 0000000..3232fe4
--- /dev/null
+++ b/build-logic/gradle/wrapper
@@ -0,0 +1 @@
+../../gradle/wrapper \ No newline at end of file
diff --git a/build-logic/gradlew b/build-logic/gradlew
new file mode 100755
index 0000000..faf9300
--- /dev/null
+++ b/build-logic/gradlew
@@ -0,0 +1,251 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+
+##############################################################################
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD=$JAVA_HOME/jre/sh/java
+ else
+ JAVACMD=$JAVA_HOME/bin/java
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD=java
+ if ! command -v java >/dev/null 2>&1
+ then
+ die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command:
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+# and any embedded shellness will be escaped.
+# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
+# treated as '${Hostname}' itself on the command line.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+ die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/build-logic/gradlew.bat b/build-logic/gradlew.bat
new file mode 100644
index 0000000..9d21a21
--- /dev/null
+++ b/build-logic/gradlew.bat
@@ -0,0 +1,94 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+@rem SPDX-License-Identifier: Apache-2.0
+@rem
+
+@if "%DEBUG%"=="" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if %ERRORLEVEL% equ 0 goto execute
+
+echo. 1>&2
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
+echo. 1>&2
+echo Please set the JAVA_HOME variable in your environment to match the 1>&2
+echo location of your Java installation. 1>&2
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo. 1>&2
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
+echo. 1>&2
+echo Please set the JAVA_HOME variable in your environment to match the 1>&2
+echo location of your Java installation. 1>&2
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if %ERRORLEVEL% equ 0 goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/build-logic/settings.gradle.kts b/build-logic/settings.gradle.kts
new file mode 100644
index 0000000..0108b7a
--- /dev/null
+++ b/build-logic/settings.gradle.kts
@@ -0,0 +1,8 @@
+dependencyResolutionManagement {
+ versionCatalogs {
+ create("libs") {
+ from(files("../gradle/libs.versions.toml"))
+ }
+ }
+}
+rootProject.name = "firm-build-logic"
diff --git a/build-logic/src/main/kotlin/EnvFile.kt b/build-logic/src/main/kotlin/EnvFile.kt
new file mode 100644
index 0000000..ceec763
--- /dev/null
+++ b/build-logic/src/main/kotlin/EnvFile.kt
@@ -0,0 +1,13 @@
+
+import java.io.File
+
+fun parseEnvFile(file: File): Map<String, String> {
+ if (!file.exists()) return mapOf()
+ val map = mutableMapOf<String, String>()
+ for (line in file.readText().lines()) {
+ if (line.isEmpty() || line.startsWith("#")) continue
+ val parts = line.split("=", limit = 2)
+ map[parts[0]] = parts.getOrNull(1) ?: ""
+ }
+ return map
+}
diff --git a/build-logic/src/main/kotlin/FabricModTransform.kt b/build-logic/src/main/kotlin/FabricModTransform.kt
new file mode 100644
index 0000000..53affbe
--- /dev/null
+++ b/build-logic/src/main/kotlin/FabricModTransform.kt
@@ -0,0 +1,80 @@
+import com.github.jengelman.gradle.plugins.shadow.transformers.ResourceTransformer
+import com.github.jengelman.gradle.plugins.shadow.transformers.TransformerContext
+import com.google.gson.Gson
+import com.google.gson.JsonObject
+import com.google.gson.JsonPrimitive
+import java.io.Serializable
+import net.fabricmc.accesswidener.AccessWidenerReader
+import net.fabricmc.accesswidener.AccessWidenerWriter
+import org.apache.tools.zip.ZipEntry
+import org.apache.tools.zip.ZipOutputStream
+import org.gradle.api.file.FileTreeElement
+import org.gradle.api.provider.Property
+import org.gradle.api.tasks.Input
+import org.gradle.api.tasks.Internal
+
+open class FabricModTransform : ResourceTransformer {
+
+ enum class AccessWidenerInclusion : Serializable {
+ ALL,
+ NONE,
+ }
+
+ @get:Input
+ var mergeAccessWideners: AccessWidenerInclusion = AccessWidenerInclusion.ALL
+
+ @get:Internal
+ internal var mergedFmj: JsonObject? = null
+
+ @get:Internal
+ internal val foundAccessWideners = AccessWidenerWriter()
+
+ @get:Internal
+ internal var foundAnyAccessWidener = false
+
+ override fun canTransformResource(element: FileTreeElement): Boolean {
+ if (mergeAccessWideners == AccessWidenerInclusion.ALL && element.name.endsWith(".accesswidener"))
+ return true
+ return element.path == "fabric.mod.json"
+ }
+
+ override fun transform(context: TransformerContext) {
+ if (context.path.endsWith(".accesswidener")) {
+ foundAnyAccessWidener = true
+ // TODO: allow filtering for only those mentioned in a fabric.mod.json, potentially
+ context.inputStream.use { stream ->
+ AccessWidenerReader(foundAccessWideners).read(stream.bufferedReader())
+ }
+ return
+ }
+ // TODO: mixins.json relocations
+ val fmj = context.inputStream.use { stream ->
+ Gson().fromJson(stream.bufferedReader(), JsonObject::class.java)
+ }
+ val mergedFmj = this.mergedFmj
+ println("${fmj["id"]} is first? ${mergedFmj == null}")
+ if (mergedFmj == null) {
+ this.mergedFmj = fmj
+ } else {
+ // TODO: merge stuff
+ }
+ }
+
+ override fun hasTransformedResource(): Boolean {
+ return mergedFmj != null
+ }
+
+ override fun modifyOutputStream(os: ZipOutputStream, preserveFileTimestamps: Boolean) {
+ val mergedFmj = mergedFmj!!
+ if (foundAnyAccessWidener) {
+ val awFile = mergedFmj["accessWidener"]
+ require(awFile is JsonPrimitive && awFile.isString)
+ os.putNextEntry(ZipEntry(awFile.asString))
+ os.write(foundAccessWideners.write())
+ os.closeEntry()
+ }
+ os.putNextEntry(ZipEntry("fabric.mod.json"))
+ os.write(mergedFmj.toString().toByteArray())
+ os.closeEntry()
+ }
+}
diff --git a/build-logic/src/main/kotlin/InnerJarsUnpacker.kt b/build-logic/src/main/kotlin/InnerJarsUnpacker.kt
new file mode 100644
index 0000000..de06467
--- /dev/null
+++ b/build-logic/src/main/kotlin/InnerJarsUnpacker.kt
@@ -0,0 +1,70 @@
+import com.google.gson.Gson
+import com.google.gson.JsonArray
+import com.google.gson.JsonObject
+import com.google.gson.JsonPrimitive
+import java.io.File
+import java.util.zip.ZipInputStream
+import org.gradle.api.DefaultTask
+import org.gradle.api.file.ConfigurableFileCollection
+import org.gradle.api.file.DirectoryProperty
+import org.gradle.api.tasks.InputFile
+import org.gradle.api.tasks.InputFiles
+import org.gradle.api.tasks.OutputDirectory
+import org.gradle.api.tasks.OutputFiles
+import org.gradle.api.tasks.TaskAction
+import kotlin.io.path.createDirectories
+import kotlin.io.path.outputStream
+
+abstract class InnerJarsUnpacker : DefaultTask() {
+ @get:InputFiles
+ abstract val inputJars: ConfigurableFileCollection
+
+ @get:OutputDirectory
+ abstract val outputDir: DirectoryProperty
+
+ private fun getFabricModJson(inputFile: File): JsonObject {
+ inputFile.inputStream().use {
+ val zis = ZipInputStream(it)
+ while (true) {
+ val entry = zis.nextEntry ?: error("Failed to find fabric.mod.json")
+ if (entry.name == "fabric.mod.json") {
+ return Gson().fromJson(zis.reader(), JsonObject::class.java)
+ }
+ }
+ }
+ }
+
+ @TaskAction
+ fun unpack() {
+ inputJars.forEach { inputFile ->
+ val fabricModObject = getFabricModJson(inputFile)
+ val jars = fabricModObject["jars"] as? JsonArray ?: error("No jars to unpack in $inputFile")
+ val jarPaths = jars.map {
+ ((it as? JsonObject)?.get("file") as? JsonPrimitive)?.asString
+ ?: error("Invalid Jar $it in $inputFile")
+ }
+ extractJars(inputFile, jarPaths)
+ }
+ }
+
+ private fun extractJars(inputFile: File, jarPaths: List<String>) {
+ val outputFile = outputDir.get().asFile.toPath()
+ val jarPathSet = jarPaths.toMutableSet()
+ inputFile.inputStream().use {
+ val zis = ZipInputStream(it)
+ while (true) {
+ val entry = zis.nextEntry ?: break
+ if (jarPathSet.remove(entry.name)) {
+ val resolvedPath = outputFile.resolve(entry.name)
+ resolvedPath.parent.createDirectories()
+ resolvedPath.outputStream().use { os ->
+ zis.copyTo(os)
+ }
+ }
+ }
+ }
+ if (jarPathSet.isNotEmpty()) {
+ error("Could not extract all jars: $jarPathSet")
+ }
+ }
+}
diff --git a/build-logic/src/main/kotlin/RepoDownload.kt b/build-logic/src/main/kotlin/RepoDownload.kt
new file mode 100644
index 0000000..42a09b3
--- /dev/null
+++ b/build-logic/src/main/kotlin/RepoDownload.kt
@@ -0,0 +1,41 @@
+import java.net.URI
+import java.util.zip.ZipInputStream
+import org.gradle.api.DefaultTask
+import org.gradle.api.file.DirectoryProperty
+import org.gradle.api.provider.Property
+import org.gradle.api.tasks.Input
+import org.gradle.api.tasks.OutputDirectory
+import org.gradle.api.tasks.TaskAction
+
+abstract class RepoDownload : DefaultTask() {
+ @get:Input
+ abstract val hash: Property<String>
+
+ @get:OutputDirectory
+ abstract val outputDirectory: DirectoryProperty
+
+ init {
+ outputDirectory.convention(project.layout.buildDirectory.dir("extracted-test-repo"))
+ }
+
+ @TaskAction
+ fun performDownload() {
+ val outputDir = outputDirectory.asFile.get().absoluteFile
+ outputDir.mkdirs()
+ URI("https://github.com/notEnoughUpdates/notEnoughUpdates-rEPO/archive/${hash.get()}.zip").toURL().openStream()
+ .let(::ZipInputStream)
+ .use { zipInput ->
+ while (true) {
+ val entry = zipInput.nextEntry ?: break
+ val destination = outputDir.resolve(
+ entry.name.substringAfter('/')).absoluteFile
+ require(outputDir in generateSequence(destination) { it.parentFile })
+ if (entry.isDirectory) continue
+ destination.parentFile.mkdirs()
+ destination.outputStream().use { output ->
+ zipInput.copyTo(output)
+ }
+ }
+ }
+ }
+}
diff --git a/build-logic/src/main/kotlin/firmament.base.gradle.kts b/build-logic/src/main/kotlin/firmament.base.gradle.kts
new file mode 100644
index 0000000..8c512a4
--- /dev/null
+++ b/build-logic/src/main/kotlin/firmament.base.gradle.kts
@@ -0,0 +1 @@
+group = "moe.nea.firmament"
diff --git a/build-logic/src/main/kotlin/firmament.common.gradle.kts b/build-logic/src/main/kotlin/firmament.common.gradle.kts
new file mode 100644
index 0000000..a359b3d
--- /dev/null
+++ b/build-logic/src/main/kotlin/firmament.common.gradle.kts
@@ -0,0 +1,2 @@
+apply(plugin = "firmament.base")
+apply(plugin = "firmament.repositories")
diff --git a/build-logic/src/main/kotlin/firmament.license-management.gradle.kts b/build-logic/src/main/kotlin/firmament.license-management.gradle.kts
new file mode 100644
index 0000000..0a2626b
--- /dev/null
+++ b/build-logic/src/main/kotlin/firmament.license-management.gradle.kts
@@ -0,0 +1,5 @@
+apply(plugin = "moe.nea.licenseextractificator")
+
+configure<moe.nea.licenseextractificator.LicenseExtension> {
+ addExtraLicenseMatchers()
+}
diff --git a/build-logic/src/main/kotlin/firmament.repositories.gradle.kts b/build-logic/src/main/kotlin/firmament.repositories.gradle.kts
new file mode 100644
index 0000000..07a5709
--- /dev/null
+++ b/build-logic/src/main/kotlin/firmament.repositories.gradle.kts
@@ -0,0 +1,46 @@
+repositories {
+ mavenCentral()
+ maven("https://maven.terraformersmc.com/releases/")
+ maven("https://maven.shedaniel.me")
+ maven("https://maven.fabricmc.net")
+ maven("https://pkgs.dev.azure.com/djtheredstoner/DevAuth/_packaging/public/maven/v1")
+ maven("https://api.modrinth.com/maven") {
+ content {
+ includeGroup("maven.modrinth")
+ }
+ }
+ maven("https://repo.sleeping.town") {
+ content {
+ includeGroup("com.unascribed")
+ }
+ }
+ ivy("https://github.com/HotswapProjects/HotswapAgent/releases/download") {
+ patternLayout {
+ artifact("[revision]/[artifact]-[revision].[ext]")
+ }
+ content {
+ includeGroup("virtual.github.hotswapagent")
+ }
+ metadataSources {
+ artifact()
+ }
+ }
+ maven("https://server.bbkr.space/artifactory/libs-release")
+ maven("https://repo.nea.moe/releases")
+ maven("https://maven.notenoughupdates.org/releases")
+ maven("https://repo.nea.moe/mirror")
+ maven("https://jitpack.io/") {
+ content {
+ includeGroupByRegex("(com|io)\\.github\\..+")
+ excludeModule("io.github.cottonmc", "LibGui")
+ }
+ }
+ maven("https://repo.hypixel.net/repository/Hypixel/")
+ maven("https://maven.azureaaron.net/snapshots")
+ maven("https://maven.azureaaron.net/releases")
+ maven("https://www.cursemaven.com")
+ maven("https://maven.isxander.dev/releases") {
+ name = "Xander Maven"
+ }
+ mavenLocal()
+}
diff --git a/build-logic/src/main/kotlin/licenseinfo.kt b/build-logic/src/main/kotlin/licenseinfo.kt
new file mode 100644
index 0000000..50e4593
--- /dev/null
+++ b/build-logic/src/main/kotlin/licenseinfo.kt
@@ -0,0 +1,144 @@
+// SPDX-FileCopyrightText: 2023 Linnea Gräf <nea@nea.moe>
+//
+// SPDX-License-Identifier: CC0-1.0
+
+import moe.nea.licenseextractificator.LicenseExtension
+
+fun LicenseExtension.addExtraLicenseMatchers() {
+ solo {
+ name = "Firmament"
+ description = "A Hypixel SkyBlock mod"
+ developer("Linnea Gräf") {
+ webPresence = "https://nea.moe/"
+ }
+ spdxLicense.`GPL-3-0-or-later`()
+ webPresence = "https://git.nea.moe/nea/Firmament/"
+ }
+ match {
+ if (group == "net.minecraft") useLicense {
+ name = "Minecraft"
+ description = "Minecraft - The critically acclaimed video game"
+ license("All Rights Reserved", "https://www.minecraft.net/en-us/eula")
+ developer("Mojang") {
+ webPresence = "https://mojang.com"
+ }
+ webPresence = "https://www.minecraft.net/en-us"
+ }
+ if (module == "architectury") useLicense {
+ name = "Architectury API"
+ description = "An intermediary api aimed at easing development of multiplatform mods."
+ spdxLicense.`LGPL-3-0-or-later`()
+ developer("Architectury") {
+ webPresence = "https://docs.architectury.dev/"
+ }
+ webPresence = "https://github.com/architectury/architectury-api"
+ }
+ if (module.startsWith("RoughlyEnoughItems")) useLicense {
+ name = module
+ description = "Your recipe viewer mod for 1.13+."
+ spdxLicense.MIT()
+ developer("Shedaniel") {
+ webPresence = "https://shedaniel.me/"
+ }
+ webPresence = "https://github.com/shedaniel/RoughlyEnoughItems"
+ }
+ if (module == "cloth-config") useLicense {
+ name = "Cloth Config"
+ description = "Client sided configuration API"
+ spdxLicense.`LGPL-3-0-or-later`()
+ developer("Shedaniel") {
+ webPresence = "https://shedaniel.me/"
+ }
+ webPresence = "https://github.com/shedaniel/cloth-config"
+ }
+ if (module == "basic-math") useLicense {
+ name = "Cloth BasicMath"
+ description = "Basic Math Operations"
+ spdxLicense.Unlicense()
+ developer("Shedaniel") {
+ webPresence = "https://shedaniel.me/"
+ }
+ webPresence = "https://github.com/shedaniel/cloth-basic-math"
+ }
+ if (module == "fabric-language-kotlin") useLicense {
+ name = "Fabric Language Kotlin"
+ description = "Kotlin Language Support for Fabric mods"
+ webPresence = "https://github.com/FabricMC/fabric-language-kotlin"
+ spdxLicense.`Apache-2-0`()
+ developer("FabricMC") {
+ webPresence = "https://fabricmc.net/"
+ }
+ }
+ if (group == "com.mojang") useLicense {
+ name = module
+ description = "Mojang library packaged by Minecraft"
+ }
+ }
+ module("net.fabricmc", "yarn") {
+ name = "Yarn"
+ description = "Libre Minecraft mappings, free to use for everyone. No exceptions."
+ spdxLicense.`CC0-1-0`()
+ developer("FabricMC") {
+ webPresence = "https://fabricmc.net/"
+ }
+ webPresence = "https://github.com/FabricMC/yarn/"
+ }
+ module("com.mojang", "datafixerupper") {
+ name = "DataFixerUpper"
+ description =
+ "A set of utilities designed for incremental building, merging and optimization of data transformations."
+ spdxLicense.MIT()
+ developer("Mojang") {
+ webPresence = "https://mojang.com"
+ }
+ webPresence = "https://github.com/Mojang/DataFixerUpper"
+ }
+ module("com.mojang", "brigadier") {
+ name = "Brigadier"
+ description = "Brigadier is a command parser & dispatcher, designed and developed for Minecraft: Java Edition."
+ spdxLicense.MIT()
+ developer("Mojang") {
+ webPresence = "https://mojang.com"
+ }
+ webPresence = "https://github.com/Mojang/brigadier"
+ }
+ module("net.fabricmc", "tiny-remapper") {
+ name = "Tiny Remapper"
+ description = "Tiny JAR remapping tool"
+ spdxLicense.`LGPL-3-0-or-later`()
+ webPresence = "https://github.com/FabricMC/tiny-remapper"
+ developer("FabricMC") {
+ webPresence = "https://fabricmc.net/"
+ }
+ }
+ module("net.fabricmc", "sponge-mixin") {
+ name = "Mixin"
+ description = "Mixin is a trait/mixin framework for Java using ASM"
+ spdxLicense.MIT()
+ webPresence = "https://github.com/FabricMC/mixin"
+ developer("FabricMC") {
+ webPresence = "https://fabricmc.net/"
+ }
+ developer("SpongePowered") {
+ webPresence = "https://spongepowered.org/"
+ }
+ }
+ module("net.fabricmc", "tiny-mappings-parser") {
+ name = "Tiny Mappings Parser"
+ webPresence = "https://github.com/fabricMC/tiny-mappings-parser"
+ description = "Library for parsing .tiny mapping files"
+ developer("FabricMC") {
+ webPresence = "https://fabricmc.net/"
+ }
+ spdxLicense.`Apache-2-0`()
+ }
+ module("net.fabricmc", "fabric-loader") {
+ name = "Fabric Loader"
+ description = " Fabric's mostly-version-independent mod loader."
+ spdxLicense.`Apache-2-0`()
+ developer("FabricMC") {
+ webPresence = "https://fabricmc.net/"
+ }
+ webPresence = "https://github.com/FabricMC/fabric-loader/"
+ }
+}
diff --git a/build-logic/src/main/kotlin/lookupversion.kt b/build-logic/src/main/kotlin/lookupversion.kt
new file mode 100644
index 0000000..8a7c2de
--- /dev/null
+++ b/build-logic/src/main/kotlin/lookupversion.kt
@@ -0,0 +1,25 @@
+fun execString(vararg args: String): String {
+ val pb = ProcessBuilder(*args)
+ .redirectOutput(ProcessBuilder.Redirect.PIPE)
+ .start()
+ pb.waitFor()
+ return pb.inputStream.readAllBytes().decodeToString().trim()
+}
+
+private val tag = "([0-9.]+)(?:\\+[^-]*)?".toRegex()
+private val tagOffset = "([0-9.]+)(?:\\+.*)?-([0-9]+)-(.+)".toRegex()
+
+inline fun <T> Regex.useMatcher(string: String, block: (MatchResult) -> T): T? {
+ return matchEntire(string)?.let(block)
+}
+
+fun getGitTagInfo(mcVersion: String): String {
+ val str = execString("git", "describe", "--tags", "HEAD")
+ tag.useMatcher(str) {
+ return it.groupValues[1] + "+mc$mcVersion"
+ }
+ tagOffset.useMatcher(str) {
+ return it.groupValues[1] + "-dev+mc$mcVersion+" + it.groupValues[3]
+ }
+ return "nogitversion+mc$mcVersion"
+}