From e0bd2a792a70bd1830e24290d38de588b4b3763f Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 3 Sep 2022 11:54:34 +0300 Subject: [PATCH] Update build tooks and DF --- build.gradle.kts | 16 ++-- gradle.properties | 2 +- settings.gradle.kts | 10 +-- snark-core/build.gradle.kts | 2 +- snark-gradle-plugin/build.gradle.kts | 2 +- .../src/main/kotlin/SnarkGradlePlugin.kt | 18 +++-- snark-html/build.gradle.kts | 6 +- snark-ktor/build.gradle.kts | 4 +- .../kscience/snark/ktor/KtorSiteBuilder.kt | 20 +++-- .../space/kscience/snark/ktor/extractData.kt | 80 +++++++++++++++++++ 10 files changed, 126 insertions(+), 34 deletions(-) create mode 100644 snark-ktor/src/main/kotlin/space/kscience/snark/ktor/extractData.kt diff --git a/build.gradle.kts b/build.gradle.kts index 77257c3..a06b422 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,24 +1,26 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + plugins { - id("ru.mipt.npm.gradle.project") + id("space.kscience.gradle.project") } allprojects { group = "space.kscience" version = "0.1.0-dev-1" - if(name!="snark-gradle-plugin") { - tasks.withType { + if (name != "snark-gradle-plugin") { + tasks.withType { kotlinOptions { - freeCompilerArgs = freeCompilerArgs + "-Xcontext-receivers" + freeCompilerArgs = freeCompilerArgs + "-Xcontext-receivers" } } } } -val dataforgeVersion by extra("0.6.0-dev-10") +val dataforgeVersion by extra("0.6.0-dev-15") -ksciencePublish{ - github("snark") +ksciencePublish { + github("SciProgCentre", "snark") space("https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven") // sonatype() } \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index e2e0fd8..7773a91 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,3 @@ kotlin.code.style=official -toolsVersion=0.11.7-kotlin-1.7.0 \ No newline at end of file +toolsVersion=0.12.1-kotlin-1.7.20-Beta \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index d64d37a..a45fb4e 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -14,10 +14,10 @@ pluginManagement { } plugins { - id("ru.mipt.npm.gradle.project") version toolsVersion - id("ru.mipt.npm.gradle.mpp") version toolsVersion - id("ru.mipt.npm.gradle.jvm") version toolsVersion - id("ru.mipt.npm.gradle.js") version toolsVersion + id("space.kscience.gradle.project") version toolsVersion + id("space.kscience.gradle.mpp") version toolsVersion + id("space.kscience.gradle.jvm") version toolsVersion + id("space.kscience.gradle.js") version toolsVersion } } @@ -32,7 +32,7 @@ dependencyResolutionManagement { versionCatalogs { create("npmlibs") { - from("ru.mipt.npm:version-catalog:$toolsVersion") + from("space.kscience:version-catalog:$toolsVersion") } } } diff --git a/snark-core/build.gradle.kts b/snark-core/build.gradle.kts index f187f89..f9b15ad 100644 --- a/snark-core/build.gradle.kts +++ b/snark-core/build.gradle.kts @@ -1,5 +1,5 @@ plugins{ - id("ru.mipt.npm.gradle.mpp") + id("space.kscience.gradle.mpp") `maven-publish` } diff --git a/snark-gradle-plugin/build.gradle.kts b/snark-gradle-plugin/build.gradle.kts index a865ec7..23989f0 100644 --- a/snark-gradle-plugin/build.gradle.kts +++ b/snark-gradle-plugin/build.gradle.kts @@ -1,5 +1,5 @@ plugins{ - id("ru.mipt.npm.gradle.jvm") + id("space.kscience.gradle.jvm") `kotlin-dsl` `java-gradle-plugin` `maven-publish` diff --git a/snark-gradle-plugin/src/main/kotlin/SnarkGradlePlugin.kt b/snark-gradle-plugin/src/main/kotlin/SnarkGradlePlugin.kt index 8b5ef47..2271e3f 100644 --- a/snark-gradle-plugin/src/main/kotlin/SnarkGradlePlugin.kt +++ b/snark-gradle-plugin/src/main/kotlin/SnarkGradlePlugin.kt @@ -2,8 +2,7 @@ package space.kscience.snark.plugin import org.gradle.api.Plugin import org.gradle.api.Project -import org.gradle.kotlin.dsl.configure -import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension +import org.gradle.kotlin.dsl.withType import java.io.File import java.time.LocalDateTime @@ -41,13 +40,18 @@ public class SnarkGradlePlugin : Plugin { tasks.getByName("processResources").dependsOn(writeBuildDate) - configure { - sourceSets.apply { - getByName("main") { - resources.srcDir(project.rootDir.resolve("data")) - } + extensions.configure("sourceSets") { + getByName("main") { + logger.info("Adding ${snarkExtension.dataDirectory} to resources") + resources.srcDir(snarkExtension.dataDirectory) } } } + + tasks.withType { + kotlinOptions { + freeCompilerArgs = freeCompilerArgs + "-Xcontext-receivers" + } + } } } \ No newline at end of file diff --git a/snark-html/build.gradle.kts b/snark-html/build.gradle.kts index 1149a26..1de2df6 100644 --- a/snark-html/build.gradle.kts +++ b/snark-html/build.gradle.kts @@ -1,10 +1,10 @@ plugins { - id("ru.mipt.npm.gradle.jvm") + id("space.kscience.gradle.jvm") `maven-publish` } val dataforgeVersion: String by rootProject.extra -val ktorVersion = ru.mipt.npm.gradle.KScienceVersions.ktorVersion +val ktorVersion = space.kscience.gradle.KScienceVersions.ktorVersion dependencies { api(projects.snarkCore) @@ -19,7 +19,7 @@ dependencies { } readme { - maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL + maturity = space.kscience.gradle.Maturity.EXPERIMENTAL feature("data") { "Data-based processing. Instead of traditional layout-based" } feature("layouts") { "Use custom layouts to represent a data tree" } feature("parsers") { "Add custom file formats and parsers using DataForge dependency injection" } diff --git a/snark-ktor/build.gradle.kts b/snark-ktor/build.gradle.kts index fe870c2..cb51636 100644 --- a/snark-ktor/build.gradle.kts +++ b/snark-ktor/build.gradle.kts @@ -1,10 +1,10 @@ plugins { - id("ru.mipt.npm.gradle.jvm") + id("space.kscience.gradle.jvm") `maven-publish` } val dataforgeVersion: String by rootProject.extra -val ktorVersion = ru.mipt.npm.gradle.KScienceVersions.ktorVersion +val ktorVersion = space.kscience.gradle.KScienceVersions.ktorVersion dependencies { api(projects.snarkHtml) diff --git a/snark-ktor/src/main/kotlin/space/kscience/snark/ktor/KtorSiteBuilder.kt b/snark-ktor/src/main/kotlin/space/kscience/snark/ktor/KtorSiteBuilder.kt index 1451e15..f86a82f 100644 --- a/snark-ktor/src/main/kotlin/space/kscience/snark/ktor/KtorSiteBuilder.kt +++ b/snark-ktor/src/main/kotlin/space/kscience/snark/ktor/KtorSiteBuilder.kt @@ -13,7 +13,10 @@ import io.ktor.server.routing.Route import io.ktor.server.routing.createRouteFromPath import io.ktor.server.routing.get import io.ktor.server.routing.routing +import kotlinx.css.CssBuilder +import kotlinx.html.CommonAttributeGroupFacade import kotlinx.html.HTML +import kotlinx.html.style import space.kscience.dataforge.data.DataTree import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.withDefault @@ -27,8 +30,11 @@ import kotlin.contracts.InvocationKind import kotlin.contracts.contract import kotlin.io.path.isDirectory -@PublishedApi -internal class KtorSiteBuilder( +public fun CommonAttributeGroupFacade.css(block: CssBuilder.() -> Unit) { + style = CssBuilder().block().toString() +} + +public class KtorSiteBuilder( override val snark: SnarkHtmlPlugin, override val data: DataTree<*>, override val siteMeta: Meta, @@ -58,7 +64,7 @@ internal class KtorSiteBuilder( } - inner class KtorWebPage( + private inner class KtorWebPage( val pageBaseUrl: String, override val pageMeta: Meta = this@KtorSiteBuilder.siteMeta, ) : WebPage { @@ -117,8 +123,8 @@ internal class KtorSiteBuilder( } } -context(Route, SnarkEnvironment) public fun siteInRoute( - block: SiteBuilder.() -> Unit, +context(Route, SnarkEnvironment) private fun siteInRoute( + block: KtorSiteBuilder.() -> Unit, ) { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) @@ -127,7 +133,7 @@ context(Route, SnarkEnvironment) public fun siteInRoute( } context(Application) public fun SnarkEnvironment.site( - block: SiteBuilder.() -> Unit, + block: KtorSiteBuilder.() -> Unit, ) { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) @@ -135,4 +141,4 @@ context(Application) public fun SnarkEnvironment.site( routing { siteInRoute(block) } -} \ No newline at end of file +} diff --git a/snark-ktor/src/main/kotlin/space/kscience/snark/ktor/extractData.kt b/snark-ktor/src/main/kotlin/space/kscience/snark/ktor/extractData.kt new file mode 100644 index 0000000..ec19c4b --- /dev/null +++ b/snark-ktor/src/main/kotlin/space/kscience/snark/ktor/extractData.kt @@ -0,0 +1,80 @@ +package space.kscience.snark.ktor + +import io.ktor.server.application.Application +import io.ktor.server.application.log +import space.kscience.dataforge.context.info +import space.kscience.dataforge.context.logger +import java.net.URI +import java.nio.file.FileSystems +import java.nio.file.Files +import java.nio.file.Path +import java.time.LocalDateTime +import kotlin.io.path.* + + +public fun KtorSiteBuilder.extractResources(uri: URI, targetPath: Path): Path { + if (Files.isDirectory(targetPath)) { + logger.info { "Using existing data directory at $targetPath." } + } else { + logger.info { "Copying data from $uri into $targetPath." } + targetPath.createDirectories() + //Copy everything into a temporary directory + FileSystems.newFileSystem(uri, emptyMap()).use { fs -> + val rootPath: Path = fs.provider().getPath(uri) + Files.walk(rootPath).forEach { source: Path -> + if (source.isRegularFile()) { + val relative = source.relativeTo(rootPath).toString() + val destination: Path = targetPath.resolve(relative) + destination.parent.createDirectories() + Files.copy(source, destination) + } + } + } + } + return targetPath +} + +public fun KtorSiteBuilder.extractResources(resource: String, targetPath: Path): Path = + extractResources(javaClass.getResource(resource)!!.toURI(), targetPath) + +private const val DEPLOY_DATE_FILE = "deployDate" +private const val BUILD_DATE_FILE = "/buildDate" + +/** + * Prepare the data cache directory for snark. Clear data if it is outdated. + * TODO make internal + */ +fun Application.prepareSnarkDataCacheDirectory(dataPath: Path) { + +// Clear data directory if it is outdated + val deployDate = dataPath.resolve(DEPLOY_DATE_FILE).takeIf { it.exists() } + ?.readText()?.let { LocalDateTime.parse(it) } + val buildDate = javaClass.getResource(BUILD_DATE_FILE)?.readText()?.let { LocalDateTime.parse(it) } + + val inProduction: Boolean = environment.config.propertyOrNull("ktor.environment.production") != null + + if (inProduction) { + log.info("Production mode activated") + log.info("Build date: $buildDate") + log.info("Deploy date: $deployDate") + } + + if (deployDate != null && buildDate != null && buildDate.isAfter(deployDate)) { + log.info("Outdated data. Resetting data directory.") + + Files.walk(dataPath) + .sorted(Comparator.reverseOrder()) + .forEach { it.deleteIfExists() } + + //Writing deploy date file + dataPath.createDirectories() + dataPath.resolve(DEPLOY_DATE_FILE).writeText(LocalDateTime.now().toString()) + + } else if (inProduction && deployDate == null && buildDate != null) { + val date = LocalDateTime.now().toString() + log.info("Deploy date: $date") + //Writing deploy date in production mode if it does not exist + dataPath.createDirectories() + dataPath.resolve(DEPLOY_DATE_FILE).writeText(date) + } +} \ No newline at end of file