Skip to content

Commit

Permalink
JetBrains#1779 Fixes compatibility with Gradle dependency verificatio…
Browse files Browse the repository at this point in the history
…n. Previously it was failing with "Failed to create MD5 hash for file".
  • Loading branch information
AlexanderBartash committed Oct 9, 2024
1 parent 215e202 commit 2c44200
Show file tree
Hide file tree
Showing 11 changed files with 154 additions and 38 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
- Fixed issue #1778 by removing a hash of the absolute artifact path appended to the end of the version string. That hash made artifact version different on different PCs and also breaks Gradle dependency locking.
- Add the missing `org.jetbrains.kotlin.platform.type=jvm` attribute to the `intellijPlatformRuntimeClasspath` configuration manually as it's not inherited from the `runtimeClasspath`.
- Fixed `Could not generate a decorated class for type PluginArtifactRepository.` when creating a custom plugin repository.
- #1779 Fixes compatibility with Gradle dependency verification. Previously it was failing with "Failed to create MD5 hash for file".

## [2.1.0]

Expand Down
8 changes: 4 additions & 4 deletions api/IntelliJPlatformGradlePlugin.api
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ public abstract class org/jetbrains/intellij/platform/gradle/attributes/Distribu

public abstract class org/jetbrains/intellij/platform/gradle/extensions/IntelliJPlatformDependenciesExtension {
public static final field Companion Lorg/jetbrains/intellij/platform/gradle/extensions/IntelliJPlatformDependenciesExtension$Companion;
public fun <init> (Lorg/gradle/api/artifacts/ConfigurationContainer;Lorg/gradle/api/artifacts/dsl/DependencyHandler;Lorg/gradle/api/file/ProjectLayout;Lorg/gradle/api/model/ObjectFactory;Lorg/gradle/api/provider/ProviderFactory;Lorg/gradle/api/resources/ResourceHandler;Ljava/nio/file/Path;)V
public fun <init> (Lorg/gradle/api/artifacts/dsl/RepositoryHandler;Lorg/gradle/api/artifacts/ConfigurationContainer;Lorg/gradle/api/artifacts/dsl/DependencyHandler;Lorg/gradle/api/file/ProjectLayout;Lorg/gradle/api/model/ObjectFactory;Lorg/gradle/api/provider/ProviderFactory;Lorg/gradle/api/resources/ResourceHandler;Ljava/nio/file/Path;)V
public final fun androidStudio (Ljava/lang/String;)V
public final fun androidStudio (Ljava/lang/String;Z)V
public final fun androidStudio (Lorg/gradle/api/provider/Provider;)V
Expand Down Expand Up @@ -695,7 +695,7 @@ public final class org/jetbrains/intellij/platform/gradle/extensions/IntelliJPla
}

public final class org/jetbrains/intellij/platform/gradle/extensions/IntelliJPlatformDependenciesHelper {
public fun <init> (Lorg/gradle/api/artifacts/ConfigurationContainer;Lorg/gradle/api/artifacts/dsl/DependencyHandler;Lorg/gradle/api/file/ProjectLayout;Lorg/gradle/api/model/ObjectFactory;Lorg/gradle/api/provider/ProviderFactory;Lorg/gradle/api/resources/ResourceHandler;Ljava/nio/file/Path;)V
public fun <init> (Lorg/gradle/api/artifacts/dsl/RepositoryHandler;Lorg/gradle/api/artifacts/ConfigurationContainer;Lorg/gradle/api/artifacts/dsl/DependencyHandler;Lorg/gradle/api/file/ProjectLayout;Lorg/gradle/api/model/ObjectFactory;Lorg/gradle/api/provider/ProviderFactory;Lorg/gradle/api/resources/ResourceHandler;Ljava/nio/file/Path;)V
}

public abstract class org/jetbrains/intellij/platform/gradle/extensions/IntelliJPlatformExtension : org/gradle/api/plugins/ExtensionAware {
Expand Down Expand Up @@ -816,7 +816,7 @@ public final class org/jetbrains/intellij/platform/gradle/extensions/IntelliJPla

public abstract class org/jetbrains/intellij/platform/gradle/extensions/IntelliJPlatformExtension$PluginVerification$Ides {
public static final field Companion Lorg/jetbrains/intellij/platform/gradle/extensions/IntelliJPlatformExtension$PluginVerification$Ides$Companion;
public fun <init> (Lorg/gradle/api/artifacts/ConfigurationContainer;Lorg/gradle/api/artifacts/dsl/DependencyHandler;Lorg/gradle/api/file/ProjectLayout;Lorg/gradle/api/model/ObjectFactory;Lorg/gradle/api/provider/ProviderFactory;Lorg/gradle/api/resources/ResourceHandler;Ljava/nio/file/Path;Lorg/gradle/api/provider/Provider;)V
public fun <init> (Lorg/gradle/api/artifacts/dsl/RepositoryHandler;Lorg/gradle/api/artifacts/ConfigurationContainer;Lorg/gradle/api/artifacts/dsl/DependencyHandler;Lorg/gradle/api/file/ProjectLayout;Lorg/gradle/api/model/ObjectFactory;Lorg/gradle/api/provider/ProviderFactory;Lorg/gradle/api/resources/ResourceHandler;Ljava/nio/file/Path;Lorg/gradle/api/provider/Provider;)V
public final fun ProductReleasesValueSource (Lkotlin/jvm/functions/Function1;)Lorg/gradle/api/provider/Provider;
public static synthetic fun ProductReleasesValueSource$default (Lorg/jetbrains/intellij/platform/gradle/extensions/IntelliJPlatformExtension$PluginVerification$Ides;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/gradle/api/provider/Provider;
public final fun ide (Ljava/lang/String;)V
Expand Down Expand Up @@ -885,7 +885,7 @@ public abstract interface class org/jetbrains/intellij/platform/gradle/extension

public abstract class org/jetbrains/intellij/platform/gradle/extensions/IntelliJPlatformPluginsExtension : org/gradle/api/plugins/ExtensionAware {
public static final field Companion Lorg/jetbrains/intellij/platform/gradle/extensions/IntelliJPlatformPluginsExtension$Companion;
public fun <init> (Lorg/gradle/api/artifacts/ConfigurationContainer;Lorg/gradle/api/artifacts/dsl/DependencyHandler;Lorg/gradle/api/file/ProjectLayout;Lorg/gradle/api/model/ObjectFactory;Lorg/gradle/api/provider/ProviderFactory;Lorg/gradle/api/resources/ResourceHandler;Ljava/nio/file/Path;)V
public fun <init> (Lorg/gradle/api/artifacts/dsl/RepositoryHandler;Lorg/gradle/api/artifacts/ConfigurationContainer;Lorg/gradle/api/artifacts/dsl/DependencyHandler;Lorg/gradle/api/file/ProjectLayout;Lorg/gradle/api/model/ObjectFactory;Lorg/gradle/api/provider/ProviderFactory;Lorg/gradle/api/resources/ResourceHandler;Ljava/nio/file/Path;)V
public final fun disablePlugin (Ljava/lang/String;)V
public final fun disablePlugin (Lorg/gradle/api/provider/Provider;)V
public final fun disablePlugins (Ljava/util/List;)V
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ class DependencyLockingAndVerificationIntegrationTest : IntelliJPlatformIntegrat
) {

@Test
@Ignore("https://github.com/JetBrains/intellij-platform-gradle-plugin/issues/1779")
fun `build plugin with dependency locks & hash verification`() {
build(
Tasks.External.CLEAN,
Expand All @@ -44,7 +43,6 @@ class DependencyLockingAndVerificationIntegrationTest : IntelliJPlatformIntegrat
}

@Test
@Ignore("https://github.com/JetBrains/intellij-platform-gradle-plugin/issues/1779")
fun `build plugin with dependency locks, hash & signature verification`() {
build(
Tasks.External.CLEAN,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ class DependencyVerificationIgnoreIntellijIntegrationTest : IntelliJPlatformInte
}

@Test
@Ignore("https://github.com/JetBrains/intellij-platform-gradle-plugin/issues/1779")
fun `build plugin with dependency locks, hash & signature verification ignoring intellij artifacts`() {
build(
Tasks.External.CLEAN,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,16 @@ abstract class CollectorTransformer : TransformAction<CollectorTransformer.Param
}

isPlugin -> {
// Normally we get into here for 3rd party marketplace plugins.
// https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-dependencies-extension.html#non-bundled-plugin
// For other plugins, we never (usually?) get into this block, because their Ivy artifacts already
// list jars, instead of pointing to a directory, see:
// See also org.jetbrains.intellij.platform.gradle.models.IvyModuleKt.explodeIntoIvyJarsArtifacts
plugin.originalFile?.let { pluginPath ->
collectJars(
pluginPath.resolve("lib"),
pluginPath.resolve("lib/modules"),
).forEach { outputs.file(it) }
val jars = collectJars(pluginPath)
jars.forEach {
outputs.file(it)
}
}
}

Expand All @@ -102,11 +107,16 @@ abstract class CollectorTransformer : TransformAction<CollectorTransformer.Param
}
}

private fun collectJars(vararg paths: Path?) = paths
.mapNotNull { it?.takeIfExists() }
.flatMap { it.listDirectoryEntries("*.jar") }

companion object {
internal fun collectJars(path: Path): List<Path> {
val libPath = path.resolve("lib")
val libModulesPath = path.resolve("lib/modules")

return listOf(libPath, libModulesPath)
.mapNotNull { it.takeIfExists() }
.flatMap { it.listDirectoryEntries("*.jar") }
}

internal fun register(
dependencies: DependencyHandler,
compileClasspathConfiguration: Configuration,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import org.gradle.api.artifacts.ConfigurationContainer
import org.gradle.api.artifacts.Dependency
import org.gradle.api.artifacts.ProjectDependency
import org.gradle.api.artifacts.dsl.DependencyHandler
import org.gradle.api.artifacts.dsl.RepositoryHandler
import org.gradle.api.file.Directory
import org.gradle.api.file.ProjectLayout
import org.gradle.api.model.ObjectFactory
Expand Down Expand Up @@ -51,6 +52,7 @@ import kotlin.io.path.absolute
@Suppress("unused", "MemberVisibilityCanBePrivate")
@IntelliJPlatform
abstract class IntelliJPlatformDependenciesExtension @Inject constructor(
repositories: RepositoryHandler,
configurations: ConfigurationContainer,
dependencies: DependencyHandler,
layout: ProjectLayout,
Expand All @@ -60,7 +62,7 @@ abstract class IntelliJPlatformDependenciesExtension @Inject constructor(
rootProjectDirectory: Path,
) {

private val delegate = IntelliJPlatformDependenciesHelper(configurations, dependencies, layout, objects, providers, resources, rootProjectDirectory)
private val delegate = IntelliJPlatformDependenciesHelper(repositories, configurations, dependencies, layout, objects, providers, resources, rootProjectDirectory)

/**
* Adds a dependency on the IntelliJ Platform.
Expand Down Expand Up @@ -1309,6 +1311,7 @@ abstract class IntelliJPlatformDependenciesExtension @Inject constructor(
override fun register(project: Project, target: Any) =
target.configureExtension<IntelliJPlatformDependenciesExtension>(
Extensions.INTELLIJ_PLATFORM,
project.repositories,
project.configurations,
project.dependencies,
project.layout,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import org.gradle.api.artifacts.ConfigurationContainer
import org.gradle.api.artifacts.Dependency
import org.gradle.api.artifacts.ProjectDependency
import org.gradle.api.artifacts.dsl.DependencyHandler
import org.gradle.api.artifacts.dsl.RepositoryHandler
import org.gradle.api.file.Directory
import org.gradle.api.file.ProjectLayout
import org.gradle.api.model.ObjectFactory
Expand Down Expand Up @@ -40,7 +41,6 @@ import java.io.File
import java.io.FileReader
import java.nio.file.Path
import java.util.*
import kotlin.Throws
import kotlin.io.path.*

/**
Expand All @@ -55,6 +55,7 @@ import kotlin.io.path.*
* @param rootProjectDirectory The root directory of the Gradle project.
*/
class IntelliJPlatformDependenciesHelper(
private val repositories: RepositoryHandler,
private val configurations: ConfigurationContainer,
private val dependencies: DependencyHandler,
private val layout: ProjectLayout,
Expand Down Expand Up @@ -742,6 +743,7 @@ class IntelliJPlatformDependenciesHelper(
*/
private fun DependencyHandler.createIntelliJPlatformBundledPlugin(id: String): Dependency {
val plugin = bundledPlugins[id]

requireNotNull(plugin) {
val unresolvedPluginId = when (id) {
"copyright" -> "Use correct plugin ID 'com.intellij.copyright' instead of 'copyright'."
Expand Down Expand Up @@ -769,8 +771,8 @@ class IntelliJPlatformDependenciesHelper(
module = id,
revision = version,
),
publications = listOf(artifactPath.toIvyArtifact()),
dependencies = plugin.collectDependencies(),
publications = artifactPath.toBundledPluginIvyArtifacts(),
dependencies = plugin.collectBundledPluginDependencies(),
)
}

Expand All @@ -791,7 +793,9 @@ class IntelliJPlatformDependenciesHelper(
.find { layout -> layout.name == id }
.let { requireNotNull(it) { "Specified bundledModule '$id' doesn't exist." } }
val platformPath = platformPath.get()
val artifactPaths = bundledModule.classPath.map { path -> platformPath.resolve(path).toIvyArtifact() }
val artifactPaths = bundledModule.classPath.flatMap { path ->
platformPath.resolve(path).toBundledModuleIvyArtifacts()
}
val version = baseVersion.orElse(productInfo.map { it.version }).get()

writeIvyModule(Dependencies.BUNDLED_MODULE_GROUP, id, version) {
Expand All @@ -818,7 +822,7 @@ class IntelliJPlatformDependenciesHelper(
*
* @param path IDs of already traversed plugins or modules.
*/
private fun IdePlugin.collectDependencies(path: List<String> = emptyList()): List<IvyModule.Dependency> {
private fun IdePlugin.collectBundledPluginDependencies(path: List<String> = emptyList()): List<IvyModule.Dependency> {
val id = requireNotNull(pluginId)
val dependencyIds = (dependencies.map { it.id } + optionalDescriptors.map { it.dependency.id } + modulesDescriptors.map { it.name } - id).toSet()
val buildNumber by lazy { productInfo.get().buildNumber }
Expand All @@ -835,10 +839,10 @@ class IntelliJPlatformDependenciesHelper(
writeIvyModule(group, name, version) {
IvyModule(
info = IvyModule.Info(group, name, version),
publications = listOf(artifactPath.toIvyArtifact()),
publications = artifactPath.toBundledPluginIvyArtifacts(),
dependencies = when {
id in path -> emptyList()
else -> plugin.collectDependencies(path + id)
else -> plugin.collectBundledPluginDependencies(path + id)
},
)
}
Expand All @@ -855,7 +859,9 @@ class IntelliJPlatformDependenciesHelper(
.mapNotNull { layoutItems.find { layout -> layout.name == it } }
.filterNot { it.classPath.isEmpty() }
.map {
val artifactPaths = it.classPath.map { path -> platformPath.resolve(path).toIvyArtifact() }
val artifactPaths = it.classPath.flatMap { path ->
platformPath.resolve(path).toBundledModuleIvyArtifacts()
}
val group = Dependencies.BUNDLED_MODULE_GROUP
val name = it.name
val version = buildNumber
Expand Down Expand Up @@ -904,7 +910,7 @@ class IntelliJPlatformDependenciesHelper(
module = name,
revision = version,
),
publications = listOf(artifactPath.toIvyArtifact()),
publications = artifactPath.toLocalPluginIvyArtifacts(),
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import org.gradle.api.Action
import org.gradle.api.Project
import org.gradle.api.artifacts.ConfigurationContainer
import org.gradle.api.artifacts.dsl.DependencyHandler
import org.gradle.api.artifacts.dsl.RepositoryHandler
import org.gradle.api.file.Directory
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.file.ProjectLayout
Expand Down Expand Up @@ -767,6 +768,7 @@ abstract class IntelliJPlatformExtension @Inject constructor(
*/
@IntelliJPlatform
abstract class Ides @Inject constructor(
repositories: RepositoryHandler,
configurations: ConfigurationContainer,
dependencies: DependencyHandler,
layout: ProjectLayout,
Expand All @@ -778,6 +780,7 @@ abstract class IntelliJPlatformExtension @Inject constructor(
) {

private val delegate = IntelliJPlatformDependenciesHelper(
repositories,
configurations,
dependencies,
layout,
Expand Down Expand Up @@ -950,6 +953,7 @@ abstract class IntelliJPlatformExtension @Inject constructor(
override fun register(project: Project, target: Any) =
target.configureExtension<Ides>(
Extensions.IDES,
project.repositories,
project.configurations,
project.dependencies,
project.layout,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import org.gradle.api.Project
import org.gradle.api.artifacts.ConfigurationContainer
import org.gradle.api.artifacts.ProjectDependency
import org.gradle.api.artifacts.dsl.DependencyHandler
import org.gradle.api.artifacts.dsl.RepositoryHandler
import org.gradle.api.file.Directory
import org.gradle.api.file.ProjectLayout
import org.gradle.api.model.ObjectFactory
Expand All @@ -32,6 +33,7 @@ import javax.inject.Inject
*/
@IntelliJPlatform
abstract class IntelliJPlatformPluginsExtension @Inject constructor(
repositories: RepositoryHandler,
configurations: ConfigurationContainer,
dependencies: DependencyHandler,
layout: ProjectLayout,
Expand All @@ -45,6 +47,7 @@ abstract class IntelliJPlatformPluginsExtension @Inject constructor(
internal val intellijPlatformPluginLocalConfigurationName = objects.property<String>()

private val delegate = IntelliJPlatformDependenciesHelper(
repositories,
configurations,
dependencies,
layout,
Expand Down Expand Up @@ -242,6 +245,7 @@ abstract class IntelliJPlatformPluginsExtension @Inject constructor(
override fun register(project: Project, target: Any) =
target.configureExtension<IntelliJPlatformPluginsExtension>(
Extensions.PLUGINS,
project.repositories,
project.configurations,
project.dependencies,
project.layout,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,18 @@ class IntelliJPlatformRepositoriesHelper(
val localPlatformArtifactsPath = providers.localPlatformArtifactsPath(rootProjectDirectory)
ivyPattern("${localPlatformArtifactsPath.pathString}/[organization]-[module]-[revision].[ext]")

// As all artifacts defined in Ivy repositories have a full artifact path set as their names, we can use them to locate artifact files
artifactPattern("/[artifact]")
// "type" may contain an optional absolute path to the actual location of the artifact, in different situations
// it may point to a completely unrelated locations on the file system.
// Yes, attribute named types does not fit very good for storing a path, but there is no better alternative.
// "artifact" maps to IvyModule#name here we expect to have the second part of the path.
// "ext" is file extension, e.g. "jar" or "directory", not used here.
//
// The type can be empty fur the "artifact" (IvyModule#name) can not.
//
// It has to be prefixed by "/" because: If this pattern is not a fully-qualified URL, it will be interpreted
// as a file relative to the project directory.
val pattern = "/([type])[artifact]"
artifactPattern(pattern)

/**
* Because artifact paths always start with `/` (see [toPublication] for details),
Expand All @@ -159,7 +169,7 @@ class IntelliJPlatformRepositoriesHelper(
* starting with `c` for the sake of micro-optimization.
*/
if (OperatingSystem.current().isWindows) {
(('c'..'z') + 'a' + 'b').forEach { artifactPattern("$it:/[artifact]") }
(('c'..'z') + 'a' + 'b').forEach { artifactPattern("$it:$pattern") }
}
}.apply {
content {
Expand Down
Loading

0 comments on commit 2c44200

Please sign in to comment.