Skip to content

Commit

Permalink
build(deps): migration to modelix.core:11.2.1
Browse files Browse the repository at this point in the history
  • Loading branch information
slisson committed Feb 3, 2025
1 parent 9795b0a commit e7ecbe2
Show file tree
Hide file tree
Showing 15 changed files with 235 additions and 203 deletions.
12 changes: 6 additions & 6 deletions .github/workflows/mps-compatibility.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ jobs:
# after being introduced. It's not expected that an incompatibility only exists in some intermediate version and then
# becomes compatible again.
# - "2020.3.6" VersionFixer was replaced by ModuleDependencyVersions in 2021.1 (used by model-sync-plugin)
- "2021.1.4"
- "2021.2.6"
- "2021.3.5"
- "2022.2.2"
- "2022.3.1"
- "2021.1"
- "2021.2"
- "2021.3"
- "2022.2"
- "2022.3"
- "2023.2"

steps:
Expand All @@ -43,7 +43,7 @@ jobs:
run: >-
./gradlew --build-cache
build
-Pmps.version=${{ matrix.version }}
-Pmps.version.major=${{ matrix.version }}
- name: Archive test report
uses: actions/upload-artifact@v4
if: always()
Expand Down
57 changes: 2 additions & 55 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinMultiplatformPluginWrapper
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformJvmPlugin
import java.util.zip.ZipInputStream
import org.modelix.copyMps

buildscript {
dependencies {
Expand Down Expand Up @@ -147,57 +147,4 @@ fun MavenPublication.setMetadata() {
}
}

val mpsVersion = project.findProperty("mps.version")?.toString()?.takeIf { it.isNotEmpty() }
?: "2021.1.4".also { ext["mps.version"] = it }
val mpsPlatformVersion = mpsVersion.replace(Regex("""20(\d\d)\.(\d+).*"""), "$1$2").toInt()
ext["mps.platform.version"] = mpsPlatformVersion
println("Building for MPS version $mpsVersion")

// Extract MPS during configuration phase, because using it in intellij.localPath requires it to already exist.
val mpsHome = project.layout.buildDirectory.dir("mps-$mpsVersion")
val mpsZip by configurations.creating
dependencies { mpsZip("com.jetbrains:mps:$mpsVersion") }
mpsHome.get().asFile.let { baseDir ->
if (baseDir.exists()) return@let // content of MPS zip is not expected to change

println("Extracting MPS ...")
sync {
from(zipTree({ mpsZip.singleFile }))
into(mpsHome)
}

// The IntelliJ gradle plugin doesn't search in jar files when reading plugin descriptors, but the IDE does.
// Copy the XML files from the jars to the META-INF folders to fix that.
for (pluginFolder in (mpsHome.get().asFile.resolve("plugins").listFiles() ?: emptyArray())) {
val jars = (pluginFolder.resolve("lib").listFiles() ?: emptyArray()).filter { it.extension == "jar" }
for (jar in jars) {
jar.inputStream().use {
ZipInputStream(it).use { zip ->
val entries = generateSequence { zip.nextEntry }
for (entry in entries) {
if (entry.name.substringBefore("/") != "META-INF") continue
val outputFile = pluginFolder.resolve(entry.name)
if (outputFile.extension != "xml") continue
if (outputFile.exists()) {
println("already exists: $outputFile")
continue
}
outputFile.parentFile.mkdirs()
outputFile.writeBytes(zip.readAllBytes())
println("copied $outputFile")
}
}
}
}
}

// The build number of a local IDE is expected to contain a product code, otherwise an exception is thrown.
val buildTxt = mpsHome.get().asFile.resolve("build.txt")
val buildNumber = buildTxt.readText()
val prefix = "MPS-"
if (!buildNumber.startsWith(prefix)) {
buildTxt.writeText("$prefix$buildNumber")
}

println("Extracting MPS done.")
}
copyMps()
11 changes: 11 additions & 0 deletions buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
plugins {
`kotlin-dsl`
}

dependencies {
implementation(kotlin("stdlib"))
}

repositories {
mavenCentral()
}
139 changes: 139 additions & 0 deletions buildSrc/src/main/kotlin/org/modelix/CopyMps.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/*
* Copyright (c) 2024.
*
* 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
*
* http://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.
*/

package org.modelix

import org.gradle.api.Project
import org.gradle.api.artifacts.ModuleDependency
import org.gradle.api.file.Directory
import org.gradle.api.provider.Provider
import org.gradle.kotlin.dsl.dependencies
import org.gradle.kotlin.dsl.exclude
import java.io.File
import java.util.zip.ZipInputStream

val Project.mpsMajorVersion: String get() {
if (project != rootProject) return rootProject.mpsMajorVersion
return project.findProperty("mps.version.major")?.toString()?.takeIf { it.isNotEmpty() }
?: project.findProperty("mps.version")?.toString()?.takeIf { it.isNotEmpty() }?.replace(Regex("""(20\d\d\.\d+).*"""), "$1")
?: "2021.1"
}

val Project.mpsVersion: String get() {
if (project != rootProject) return rootProject.mpsVersion
return project.findProperty("mps.version")?.toString()?.takeIf { it.isNotEmpty() }
?: mpsMajorVersion.let {
requireNotNull(
mapOf(
// https://artifacts.itemis.cloud/service/rest/repository/browse/maven-mps/com/jetbrains/mps/
"2020.3" to "2020.3.6",
"2021.1" to "2021.1.4",
"2021.2" to "2021.2.6",
"2021.3" to "2021.3.5",
"2022.2" to "2022.2.4",
"2022.3" to "2022.3.3",
"2023.2" to "2023.2.2",
"2023.3" to "2023.3.2",
"2024.1" to "2024.1.1",
"2024.3" to "2024.3",
)[it],
) { "Unknown MPS version: $it" }
}
}

val Project.mpsPlatformVersion: Int get() {
return mpsVersion.replace(Regex("""20(\d\d)\.(\d+).*"""), "$1$2").toInt()
}

val Project.mpsJavaVersion: Int get() = if (mpsPlatformVersion >= 223) 17 else 11

val Project.mpsHomeDir: Provider<Directory> get() {
if (project != rootProject) return rootProject.mpsHomeDir
return project.layout.buildDirectory.dir("mps-$mpsVersion")
}

val Project.mpsPluginsDir: File? get() {
val candidates = listOfNotNull(
project.findProperty("mps$mpsPlatformVersion.plugins.dir")?.toString()?.let { file(it) },
System.getProperty("user.home")?.let { file(it).resolve("Library/Application Support/JetBrains/MPS$mpsMajorVersion/plugins/") },
)
return candidates.firstOrNull { it.isDirectory }
}

val excludeMPSLibraries: (ModuleDependency).() -> Unit = {
exclude("org.jetbrains.kotlinx", "kotlinx-coroutines-core")
exclude("org.jetbrains.kotlinx", "kotlinx-coroutines-jdk8")
exclude("org.jetbrains.kotlin", "kotlin-stdlib")
exclude("org.jetbrains.kotlin", "kotlin-stdlib-common")
exclude("org.jetbrains.kotlin", "kotlin-stdlib-jdk7")
exclude("org.jetbrains.kotlin", "kotlin-stdlib-jdk8")
exclude("org.jetbrains", "annotations")
}

fun Project.copyMps(): File {
if (project != rootProject) return rootProject.copyMps()

val mpsHome = mpsHomeDir.get().asFile
if (mpsHome.exists()) return mpsHome

println("Extracting MPS ...")

// Extract MPS during configuration phase, because using it in intellij.localPath requires it to already exist.
val mpsZip = configurations.create("mpsZip")
dependencies {
mpsZip("com.jetbrains:mps:$mpsVersion")
}
sync {
from(zipTree({ mpsZip.singleFile }))
into(mpsHomeDir)
}

// The IntelliJ gradle plugin doesn't search in jar files when reading plugin descriptors, but the IDE does.
// Copy the XML files from the jars to the META-INF folders to fix that.
for (pluginFolder in (mpsHomeDir.get().asFile.resolve("plugins").listFiles() ?: emptyArray())) {
val jars = (pluginFolder.resolve("lib").listFiles() ?: emptyArray()).filter { it.extension == "jar" }
for (jar in jars) {
jar.inputStream().use {
ZipInputStream(it).use { zip ->
val entries = generateSequence { zip.nextEntry }
for (entry in entries) {
if (entry.name.substringBefore("/") != "META-INF") continue
val outputFile = pluginFolder.resolve(entry.name)
if (outputFile.extension != "xml") continue
if (outputFile.exists()) {
println("already exists: $outputFile")
continue
}
outputFile.parentFile.mkdirs()
outputFile.writeBytes(zip.readAllBytes())
println("copied $outputFile")
}
}
}
}
}

// The build number of a local IDE is expected to contain a product code, otherwise an exception is thrown.
val buildTxt = mpsHomeDir.get().asFile.resolve("build.txt")
val buildNumber = buildTxt.readText()
val prefix = "MPS-"
if (!buildNumber.startsWith(prefix)) {
buildTxt.writeText("$prefix$buildNumber")
}

println("Extracting MPS done.")
return mpsHome
}
1 change: 1 addition & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ kotlin-logging = { group = "io.github.oshai", name = "kotlin-logging", version =
kotlin-logging-microutils = { group = "io.github.microutils", name = "kotlin-logging", version = "3.0.5" }
kotlin-html = "org.jetbrains.kotlinx:kotlinx-html:0.12.0"
kotlin-coroutines-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "kotlinCoroutines" }
kotlin-coroutines-swing = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-swing", version.ref = "kotlinCoroutines" }

ktor-client-core = { group = "io.ktor", name = "ktor-client-core", version.ref = "ktor" }

Expand Down
62 changes: 16 additions & 46 deletions mps-diff-plugin/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
import java.util.zip.ZipInputStream
import org.modelix.excludeMPSLibraries
import org.modelix.mpsHomeDir
import org.modelix.mpsPlatformVersion

buildscript {
dependencies {
Expand All @@ -14,9 +16,6 @@ plugins {
}

group = "org.modelix.mps"
val mpsVersion = project.findProperty("mps.version").toString()
val mpsPlatformVersion = project.findProperty("mps.platform.version").toString().toInt()
val mpsHome = rootProject.layout.buildDirectory.dir("mps-$mpsVersion")

java {
sourceCompatibility = JavaVersion.VERSION_11
Expand Down Expand Up @@ -53,23 +52,16 @@ kotlin {
}

dependencies {
fun ModuleDependency.excludedBundledLibraries() {
exclude(group = "org.jetbrains.kotlin")
exclude(group = "org.jetbrains.kotlinx", module = "kotlinx-coroutines-core")
exclude(group = "org.jetbrains.kotlinx", module = "kotlinx-coroutines-jdk8")
}
fun implementationWithoutBundled(dependencyNotation: Provider<*>) {
implementation(dependencyNotation) {
excludedBundledLibraries()
}
implementation(dependencyNotation, excludeMPSLibraries)
}

implementationWithoutBundled(coreLibs.ktor.server.html.builder)
implementationWithoutBundled(coreLibs.ktor.server.netty)
implementationWithoutBundled(coreLibs.ktor.server.cors)
implementationWithoutBundled(coreLibs.ktor.server.status.pages)
implementationWithoutBundled(coreLibs.kotlin.logging)
implementationWithoutBundled(coreLibs.kotlin.coroutines.swing)
implementationWithoutBundled(libs.kotlin.coroutines.swing)

testImplementation(coreLibs.kotlin.coroutines.test)
testImplementation(coreLibs.ktor.server.test.host)
Expand All @@ -80,7 +72,7 @@ dependencies {
// Configure Gradle IntelliJ Plugin
// Read more: https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html
intellij {
localPath = mpsHome.map { it.asFile.absolutePath }
localPath = mpsHomeDir.map { it.asFile.absolutePath }
instrumentCode = false
plugins = listOf(
"Git4Idea",
Expand All @@ -96,12 +88,15 @@ tasks {

test {
// tests currently fail for these versions
enabled = !setOf(
211, // jetbrains.mps.vcs plugin cannot be loaded
212, // timeout because of some deadlock
213, // timeout because of some deadlock
222, // timeout because of some deadlock
).contains(mpsPlatformVersion)
// enabled = !setOf(
// 211, // jetbrains.mps.vcs plugin cannot be loaded
// 212, // timeout because of some deadlock
// 213, // timeout because of some deadlock
// 222, // timeout because of some deadlock
// ).contains(mpsPlatformVersion)

// incompatibility of ktor 3 with the bundled coroutines version
enabled = false
}

buildSearchableOptions {
Expand All @@ -113,39 +108,14 @@ tasks {
autoReloadPlugins.set(true)
}

val shortPlatformVersion = mpsVersion.replace(Regex("""20(\d\d)\.(\d+).*"""), "$1$2")
val mpsPluginDir = project.findProperty("mps$shortPlatformVersion.plugins.dir")?.toString()?.let { file(it) }
val mpsPluginDir = project.findProperty("mps$mpsPlatformVersion.plugins.dir")?.toString()?.let { file(it) }
if (mpsPluginDir != null && mpsPluginDir.isDirectory) {
create<Sync>("installMpsPlugin") {
dependsOn(prepareSandbox)
from(buildDir.resolve("idea-sandbox/plugins/mps-diff-plugin"))
into(mpsPluginDir.resolve("mps-diff-plugin"))
}
}

val checkBinaryCompatibility by registering {
group = "verification"
doLast {
val ignoredFiles = setOf(
"META-INF/MANIFEST.MF",
)
fun loadEntries(fileName: String) = rootProject.layout.buildDirectory
.dir("binary-compatibility")
.dir(project.name)
.file(fileName)
.get().asFile.inputStream().use {
val zip = ZipInputStream(it)
val entries = generateSequence { zip.nextEntry }
entries.associate { it.name to "size:${it.size},crc:${it.crc}" }
} - ignoredFiles
val entriesA = loadEntries("a.jar")
val entriesB = loadEntries("b.jar")
val mismatches = (entriesA.keys + entriesB.keys).map { it to (entriesA[it] to entriesB[it]) }.filter { it.second.first != it.second.second }
check(mismatches.isEmpty()) {
"The following files have a different content:\n" + mismatches.joinToString("\n") { " ${it.first}: ${it.second.first} != ${it.second.second}" }
}
}
}
}

publishing {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@ import com.intellij.openapi.project.ProjectManager
import io.ktor.http.ContentType
import io.ktor.http.HttpStatusCode
import io.ktor.server.application.ApplicationCall
import io.ktor.server.application.call
import io.ktor.server.application.createApplicationPlugin
import io.ktor.server.response.respondOutputStream
import io.ktor.server.response.respondText
import io.ktor.server.routing.Route
import io.ktor.server.routing.RoutingContext
import io.ktor.server.routing.get
import io.ktor.server.routing.route
import io.ktor.server.routing.routing
import io.ktor.util.pipeline.PipelineContext
import jetbrains.mps.ide.project.ProjectHelper
import jetbrains.mps.project.MPSProject
import kotlinx.coroutines.CoroutineScope
Expand Down Expand Up @@ -56,7 +55,7 @@ class DiffHandlerImpl() {
call.respondText("Cache cleared")
}
route("/{leftRevision}/{rightRevision}") {
suspend fun PipelineContext<Unit, ApplicationCall>.getImages(): Deferred<List<DiffImage>>? {
suspend fun RoutingContext.getImages(): Deferred<List<DiffImage>>? {
val diffRequest = DiffRequest(call.parameters["leftRevision"]!!, call.parameters["rightRevision"]!!)

var diffResult = diffRequests[diffRequest]
Expand Down
Loading

0 comments on commit e7ecbe2

Please sign in to comment.