All Downloads are FREE. Search and download functionalities are using the official Maven repository.

name.remal.gradle_plugins.dsl.extensions.org.gradle.api.artifacts.Configuration.kt Maven / Gradle / Ivy

There is a newer version: 1.9.2
Show newest version
package name.remal.gradle_plugins.dsl.extensions

import name.remal.buildList
import name.remal.buildMap
import name.remal.buildSet
import name.remal.default
import name.remal.gradle_plugins.dsl.DSL_DEPENDENCIES
import name.remal.gradle_plugins.dsl.utils.DependencyNotation
import name.remal.nullIfEmpty
import org.gradle.api.InvalidUserDataException
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.Configuration.State.UNRESOLVED
import org.gradle.api.artifacts.Dependency
import org.gradle.api.artifacts.DependencyArtifact
import org.gradle.api.artifacts.ExcludeRule.GROUP_KEY
import org.gradle.api.artifacts.ExcludeRule.MODULE_KEY
import org.gradle.api.artifacts.ModuleDependency
import org.gradle.api.artifacts.ResolvedArtifact
import org.gradle.api.artifacts.ResolvedDependency
import org.gradle.api.artifacts.component.ComponentSelector
import org.gradle.api.artifacts.result.ResolvedComponentResult
import org.gradle.api.artifacts.result.ResolvedDependencyResult
import java.io.File

fun Configuration.hasDependency(group: String, name: String) = allDependencies.any { group == it.group && (name == "*" || name == it.name) }

fun Configuration.beforeResolve(action: (configuration: Configuration) -> Unit) {
    if (state == UNRESOLVED) {
        try {
            withDependencies { deps ->
                if (deps === this.dependencies) {
                    action(this)
                }
            }
        } catch (e: InvalidUserDataException) {
            // do nothing
        }
    }
}

fun Configuration.beforeResolveIncoming(action: (configuration: Configuration) -> Unit) {
    beforeResolve { conf ->
        conf.incoming.beforeResolve { deps ->
            if (deps.dependencies === conf.allDependencies) {
                action(conf)
            }
        }
    }
}

fun Configuration.makeNotTransitive() = apply {
    isTransitive = false
    dependencies.all {
        if (it is ModuleDependency) {
            it.isTransitive = false
        }
    }
}

fun Configuration.exclude(group: String? = null, module: String? = null) = exclude(buildMap {
    if (!group.isNullOrEmpty() && group != "*") put(GROUP_KEY, group)
    if (!module.isNullOrEmpty() && module != "*") put(MODULE_KEY, module)
})

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

val LOGGING_TRANSITIVE_DEPENDENCIES_EXCLUDES = buildSet> {
    add(mapOf(GROUP_KEY to "org.slf4j"))
    add(mapOf(GROUP_KEY to "ch.qos.logback"))
    add(mapOf(GROUP_KEY to "org.apache.logging.log4j"))
    add(mapOf(GROUP_KEY to "log4j"))
    add(mapOf(GROUP_KEY to "commons-logging"))
    add(mapOf(GROUP_KEY to "org.springframework", MODULE_KEY to "spring-jcl"))
}

fun Configuration.applyLoggingTransitiveDependenciesExcludes() = apply {
    dependencies.all { dep ->
        if (dep is ModuleDependency) {
            LOGGING_TRANSITIVE_DEPENDENCIES_EXCLUDES.forEach { dep.exclude(it) }
        }
    }
}

val GRADLE_TRANSITIVE_DEPENDENCIES_EXCLUDES = buildSet> {
    add(mapOf(GROUP_KEY to "org.codehaus.groovy"))
    add(mapOf(GROUP_KEY to "ant", MODULE_KEY to "ant"))
    add(mapOf(GROUP_KEY to "org.apache.ant", MODULE_KEY to "ant"))
    add(mapOf(GROUP_KEY to "org.apache.ant", MODULE_KEY to "ant-launcher"))
    addAll(LOGGING_TRANSITIVE_DEPENDENCIES_EXCLUDES)
}

fun Configuration.applyGradleTransitiveDependenciesExcludes() = apply {
    dependencies.all { dep ->
        if (dep is ModuleDependency) {
            GRADLE_TRANSITIVE_DEPENDENCIES_EXCLUDES.forEach { dep.exclude(it) }
        }
    }
}

fun Configuration.applyDSLTransitiveDependenciesExcludes() = apply {
    dependencies.all { dep ->
        if (dep is ModuleDependency) {
            DSL_DEPENDENCIES.forEach { dep.exclude(it) }
        }
    }
}

fun Configuration.disableDependencyResolutionRules() {
    beforeResolveIncoming { conf ->
        conf.resolutionStrategy { resolution ->
            resolution.eachDependency { details ->
                with(details) {
                    val requestedNotation = requested.notation
                    if (requestedNotation == target.notation) return@with
                    useTarget(requestedNotation.toString())
                }
            }
        }
    }
}

fun Configuration.disableTransitiveDependencyResolutionRules() {
    beforeResolveIncoming { conf ->
        val dependencyNotations: Set by lazy {
            conf.allDependencies.map { it.notation.withoutClassifier().withoutExtension() }.toSet()
        }

        conf.resolutionStrategy { resolution ->
            resolution.eachDependency { details ->
                with(details) {
                    val requestedNotation = requested.notation
                    if (requestedNotation == target.notation) return@with
                    if (requestedNotation in dependencyNotations) return@with
                    useTarget(requestedNotation.toString())
                }
            }
        }
    }
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

class ResolvedDependencyMapping(
    val resolvedArtifact: ResolvedArtifact,
    val resolvedDependency: ResolvedDependency,
    val requested: ComponentSelector,
    val selected: ResolvedComponentResult,
    val dependency: Dependency,
    rootResolvedDependencyMapping: ResolvedDependencyMapping?,
    val configuration: Configuration,
    val project: Project
) {

    val rootResolvedDependencyMapping: ResolvedDependencyMapping = rootResolvedDependencyMapping ?: this

    val isFirstLevel: Boolean = rootResolvedDependencyMapping == null
    val isNotFirstLevel: Boolean = !isFirstLevel

    val group: String = resolvedDependency.moduleGroup.default()
    val module: String = resolvedDependency.moduleName.default()
    val version: String = resolvedDependency.moduleVersion.default()
    val classifier: String = resolvedArtifact.classifier.default()
    val type: String = resolvedArtifact.type.nullIfEmpty() ?: DependencyArtifact.DEFAULT_TYPE
    val file: File by lazy { resolvedArtifact.file }

    val requestedGroup: String? by lazy { requested.calculateGroup(project) }
    val requestedModule: String? by lazy { requested.calculateModule(project) }
    val requestedVersion: String? by lazy { requested.calculateVersion(project) }

    val selectedGroup: String? by lazy { selected.id.calculateGroup(project) }
    val selectedModule: String? by lazy { selected.id.calculateModule(project) }
    val selectedVersion: String? by lazy { selected.id.calculateVersion(project) }

    val isShouldBeExplicitlyDefined: Boolean
        get() {
            if (isFirstLevel) return true
            if (selected.selectionReason.isForced || selected.selectionReason.isSelectedByRule) return true
            if (requestedGroup != selectedGroup || requestedModule != selectedModule || requestedVersion != selectedVersion) return true
            return false
        }

    val isShouldNotBeExplicitlyDefined: Boolean get() = !isShouldBeExplicitlyDefined

    val isSubstituted: Boolean
        get() {
            if (requestedGroup != selectedGroup || requestedModule != selectedModule) return true
            return false
        }

    val isNotSubstituted: Boolean get() = !isSubstituted

}

@Suppress("ComplexMethod")
fun Configuration.getResolvedDependencyMappings(project: Project): List {
    val configurationResolvedDependencyMappings = buildList {
        val resolvedConfiguration = resolvedConfiguration
        allDependencies.forEach { dependency ->
            val dependencyConf = hierarchy.firstOrNull { it.dependencies.any { dependency === it } } ?: this@getResolvedDependencyMappings
            resolvedConfiguration.getFirstLevelModuleDependencies(dependency).forEach { resolvedDependency ->
                val rootConfigurationResolvedDependencyMapping = ConfigurationResolvedDependencyMapping(
                    dependencyConf,
                    dependency,
                    resolvedDependency
                )
                add(rootConfigurationResolvedDependencyMapping)
                resolvedDependency.allChildren.forEach {
                    add(ConfigurationResolvedDependencyMapping(
                        dependencyConf,
                        dependency,
                        it,
                        rootConfigurationResolvedDependencyMapping
                    ))
                }
            }
        }
    }

    return buildList {
        val dependencyResults = incoming.resolutionResult.allDependencies.filterIsInstance(ResolvedDependencyResult::class.java)

        val rootResolvedDependencyMappings = buildMap {
            for (artifact in incoming.artifacts) {
                val mapping = configurationResolvedDependencyMappings.firstOrNull { it.resolvedDependency.moduleArtifacts.any { it.file == artifact.file } } ?: continue
                if (mapping.isNotFirstLevel) continue
                val dependencyResult = dependencyResults.firstOrNull { dep -> mapping.resolvedDependency.moduleArtifacts.any { it.id.componentIdentifier == dep.selected.id } } ?: continue
                mapping.resolvedDependency.moduleArtifacts.forEach { resolvedArtifact ->
                    put(mapping, ResolvedDependencyMapping(
                        resolvedArtifact,
                        mapping.resolvedDependency,
                        dependencyResult.requested,
                        dependencyResult.selected,
                        mapping.dependency,
                        null,
                        mapping.configuration,
                        project
                    ))
                }
            }
        }
        addAll(rootResolvedDependencyMappings.values)

        for (artifact in incoming.artifacts) {
            val mapping = configurationResolvedDependencyMappings.firstOrNull { it.resolvedDependency.moduleArtifacts.any { it.file == artifact.file } } ?: continue
            if (mapping.isFirstLevel) continue
            val dependencyResult = dependencyResults.firstOrNull { dep -> mapping.resolvedDependency.moduleArtifacts.any { it.id.componentIdentifier == dep.selected.id } } ?: continue
            mapping.resolvedDependency.moduleArtifacts.forEach { resolvedArtifact ->
                add(ResolvedDependencyMapping(
                    resolvedArtifact,
                    mapping.resolvedDependency,
                    dependencyResult.requested,
                    dependencyResult.selected,
                    mapping.dependency,
                    rootResolvedDependencyMappings[mapping.rootConfigurationResolvedDependencyMapping],
                    mapping.configuration,
                    project
                ))
            }
        }
    }
}

private class ConfigurationResolvedDependencyMapping(
    val configuration: Configuration,
    val dependency: Dependency,
    val resolvedDependency: ResolvedDependency,
    val rootConfigurationResolvedDependencyMapping: ConfigurationResolvedDependencyMapping? = null
) {
    val isFirstLevel: Boolean = rootConfigurationResolvedDependencyMapping == null
    val isNotFirstLevel: Boolean = !isFirstLevel
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy