Refactor merge-artifacts script to a plugin
Refactor the existing merge-artifacts script to a full Gradle plugin. The new plugin uses a 'merge' extension in favor of Gradle 'ext' configuration and can be applied to all projects in a multi-module build. Any project that defines a 'merge.into' project will now implicitly receive a dependency to that project. Furthermore other projects with a dependency on 'merge.into' will receive a direct project link within the IDE. For example: 'spring-webmvc-tiles3' is merged into 'spring-webmvc' and 'spring-test-mvc' depends on 'spring-webmvc'. Within the IDE 'spring-test-mvc' will show dependencies to both 'spring-webmvc' and 'spring-webmvc-tiles'. Issue: SPR-10042
This commit is contained in:
parent
4551cfcdfc
commit
87f7ecf907
17
build.gradle
17
build.gradle
|
@ -46,6 +46,7 @@ configure(allprojects) {
|
|||
}
|
||||
|
||||
configure(subprojects) { subproject ->
|
||||
apply plugin: MergePlugin
|
||||
apply from: "${gradleScriptDir}/publish-maven.gradle"
|
||||
|
||||
jar {
|
||||
|
@ -432,10 +433,8 @@ project("spring-orm") {
|
|||
|
||||
project("spring-orm-hibernate4") {
|
||||
description = "Spring Object/Relational Mapping - Hibernate 4 support"
|
||||
ext.mergeIntoProject = project(":spring-orm")
|
||||
apply from: "${gradleScriptDir}/merge-artifacts.gradle"
|
||||
merge.into = project(":spring-orm")
|
||||
dependencies {
|
||||
compile(project(":spring-orm").sourceSets.main.output)
|
||||
compile(project(":spring-tx"))
|
||||
compile(project(":spring-jdbc"))
|
||||
optional("org.hibernate:hibernate-core:4.1.0.Final")
|
||||
|
@ -506,11 +505,9 @@ project("spring-webmvc") {
|
|||
|
||||
project("spring-webmvc-tiles3") {
|
||||
description = "Spring Framework Tiles3 Integration"
|
||||
ext.mergeIntoProject = project(":spring-webmvc")
|
||||
apply from: "${gradleScriptDir}/merge-artifacts.gradle"
|
||||
merge.into = project(":spring-webmvc")
|
||||
dependencies {
|
||||
compile(project(":spring-context"))
|
||||
compile(project(":spring-webmvc").sourceSets.main.output)
|
||||
provided("javax.el:el-api:1.0")
|
||||
provided("javax.servlet:jstl:1.2")
|
||||
provided("javax.servlet.jsp:jsp-api:2.1")
|
||||
|
@ -581,13 +578,10 @@ project("spring-test") {
|
|||
|
||||
project("spring-test-mvc") {
|
||||
description = "Spring Test MVC Framework"
|
||||
ext.mergeIntoProject = project(":spring-test")
|
||||
apply from: "${gradleScriptDir}/merge-artifacts.gradle"
|
||||
apply from: "ide.gradle"
|
||||
merge.into = project(":spring-test")
|
||||
dependencies {
|
||||
optional(project(":spring-context"))
|
||||
compile(project(":spring-webmvc"))
|
||||
compile(project(":spring-test").sourceSets.main.output)
|
||||
provided("javax.servlet:javax.servlet-api:3.0.1")
|
||||
optional("org.hamcrest:hamcrest-core:1.3")
|
||||
optional("com.jayway.jsonpath:json-path:0.8.1")
|
||||
|
@ -663,6 +657,7 @@ configure(rootProject) {
|
|||
description = "Spring Framework"
|
||||
|
||||
apply plugin: "docbook-reference"
|
||||
apply plugin: "groovy"
|
||||
apply from: "${gradleScriptDir}/jdiff.gradle"
|
||||
|
||||
reference {
|
||||
|
@ -674,6 +669,8 @@ configure(rootProject) {
|
|||
configurations.archives.artifacts.clear()
|
||||
|
||||
dependencies { // for integration tests
|
||||
compile gradleApi()
|
||||
groovy localGroovy()
|
||||
testCompile(project(":spring-core"))
|
||||
testCompile(project(":spring-beans"))
|
||||
testCompile(project(":spring-aop"))
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
import org.gradle.api.*
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.artifacts.ProjectDependency;
|
||||
import org.gradle.api.artifacts.maven.Conf2ScopeMapping
|
||||
import org.gradle.api.plugins.MavenPlugin
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.plugins.ide.eclipse.EclipsePlugin
|
||||
import org.gradle.plugins.ide.eclipse.model.EclipseClasspath;
|
||||
import org.gradle.plugins.ide.idea.IdeaPlugin
|
||||
import org.gradle.api.invocation.*
|
||||
|
||||
/**
|
||||
* Gradle plugin that allows projects to merged together. Primarily developed to
|
||||
* allow Spring to support multiple multiple incompatible versions of third-party
|
||||
* dependencies (for example Hibernate v3 and v4).
|
||||
* <p>
|
||||
* The 'merge' extension should be used to define how projects are merged, for example:
|
||||
* <pre>
|
||||
* configure(subprojects) {
|
||||
* apply plugin: MergePlugin
|
||||
* }
|
||||
*
|
||||
* project("myproject") {
|
||||
* }
|
||||
*
|
||||
* project("myproject-extra") {
|
||||
* merge.into = project("myproject")
|
||||
* }
|
||||
* </pre>
|
||||
* <p>
|
||||
* This plugin adds two new configurations:
|
||||
* <ul>
|
||||
* <li>merging - Contains the projects being merged into this project<li>
|
||||
* <li>runtimeMerge - Contains all dependencies that are merge projects. These are used
|
||||
* to allow an IDE to reference merge projects.</li>
|
||||
* <ul>
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class MergePlugin implements Plugin<Project> {
|
||||
|
||||
private static boolean attachedProjectsEvaluated;
|
||||
|
||||
public void apply(Project project) {
|
||||
project.plugins.apply(MavenPlugin)
|
||||
project.plugins.apply(EclipsePlugin)
|
||||
project.plugins.apply(IdeaPlugin)
|
||||
|
||||
MergeModel model = project.extensions.create("merge", MergeModel)
|
||||
project.configurations.add("merging")
|
||||
Configuration runtimeMerge = project.configurations.add("runtimeMerge")
|
||||
|
||||
// Ensure the IDE can reference merged projects
|
||||
project.eclipse.classpath.plusConfigurations += [runtimeMerge]
|
||||
project.idea.module.scopes.PROVIDED.plus += runtimeMerge
|
||||
|
||||
// Hook to perform the actual merge logic
|
||||
project.afterEvaluate{
|
||||
if(it.merge.into != null) {
|
||||
setup(it)
|
||||
}
|
||||
}
|
||||
|
||||
// Hook to build runtimeMerge dependencies
|
||||
if(!attachedProjectsEvaluated) {
|
||||
project.gradle.projectsEvaluated{
|
||||
postProcessProjects(it)
|
||||
}
|
||||
attachedProjectsEvaluated = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void setup(Project project) {
|
||||
project.merge.into.dependencies.add("merging", project)
|
||||
project.dependencies.add("provided", project.merge.into.sourceSets.main.output)
|
||||
project.dependencies.add("runtimeMerge", project.merge.into)
|
||||
setupTaskDependencies(project)
|
||||
setupMaven(project)
|
||||
}
|
||||
|
||||
private void setupTaskDependencies(Project project) {
|
||||
// invoking a task will invoke the task with the same name on 'into' project
|
||||
["sourcesJar", "jar", "javadocJar", "javadoc", "install", "artifactoryPublish"].each {
|
||||
def task = project.tasks.findByPath(it)
|
||||
if(task) {
|
||||
task.enabled = false
|
||||
task.dependsOn(project.merge.into.tasks.findByPath(it))
|
||||
}
|
||||
}
|
||||
|
||||
// update 'into' project artifacts to contain the source artifact contents
|
||||
project.merge.into.sourcesJar.from(project.sourcesJar.source)
|
||||
project.merge.into.jar.from(project.jar.source)
|
||||
project.merge.into.javadoc {
|
||||
source += project.javadoc.source
|
||||
classpath += project.javadoc.classpath
|
||||
}
|
||||
}
|
||||
|
||||
private void setupMaven(Project project) {
|
||||
project.configurations.each { configuration ->
|
||||
Conf2ScopeMapping mapping = project.conf2ScopeMappings.getMapping([configuration])
|
||||
if(mapping.scope) {
|
||||
Configuration intoConfiguration = project.merge.into.configurations.add(
|
||||
project.name + "-" + configuration.name)
|
||||
intoConfiguration.dependencies.addAll(configuration.dependencies)
|
||||
project.merge.into.install.repositories.mavenInstaller.pom.scopeMappings.addMapping(
|
||||
mapping.priority + 100, intoConfiguration, mapping.scope)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private postProcessProjects(Gradle gradle) {
|
||||
gradle.allprojects(new Action<Project>() {
|
||||
public void execute(Project project) {
|
||||
project.configurations.getByName("runtime").allDependencies.withType(ProjectDependency).each{
|
||||
Configuration dependsOnMergedFrom = it.dependencyProject.configurations.getByName("merging");
|
||||
dependsOnMergedFrom.dependencies.each{ dep ->
|
||||
project.dependencies.add("runtimeMerge", dep.dependencyProject)
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class MergeModel {
|
||||
Project into;
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
/**
|
||||
* Will merge the artifacts of the current project into mergeIntoProject. For example, to
|
||||
* bundle spring-test-mvc in spring-test"s jars. This script will perform the following
|
||||
* steps:
|
||||
*
|
||||
* - Ensure that jar tasks of the project being merged from will execute the tasks of the
|
||||
* project being merged into
|
||||
*
|
||||
* - Add the project being merged into to the classpath of the project being merged from
|
||||
*
|
||||
* - Update the pom.xml of the project being merged into to contain the entries from the
|
||||
* project being merged from
|
||||
*
|
||||
* Example Usage:
|
||||
*
|
||||
* ext.mergeIntoProject = project(":spring-test")
|
||||
* apply from: "${rootProject.projectDir}/gradle/merge-artifacts.gradle"
|
||||
*/
|
||||
|
||||
def mergeFromProject = project
|
||||
|
||||
// invoking a task on mergeFromProject will invoke the task with the same name on mergeIntoProject
|
||||
def taskNamesToMerge = ["sourcesJar","jar","javadocJar","javadoc","install","artifactoryPublish"]
|
||||
taskNamesToMerge.each { taskName ->
|
||||
def taskToRemove = mergeFromProject.tasks.findByPath(taskName)
|
||||
if(taskToRemove) {
|
||||
taskToRemove.enabled = false
|
||||
taskToRemove.dependsOn mergeIntoProject."$taskName"
|
||||
}
|
||||
}
|
||||
|
||||
// update mergeIntoProject artifacts to contain the mergeFromProject artifact contents
|
||||
mergeIntoProject."sourcesJar" {
|
||||
from mergeFromProject.sourcesJar.source
|
||||
}
|
||||
mergeIntoProject."jar" {
|
||||
from mergeFromProject.jar.source
|
||||
}
|
||||
mergeIntoProject."javadoc" {
|
||||
source += mergeFromProject.javadoc.source
|
||||
classpath += mergeFromProject.javadoc.classpath
|
||||
}
|
||||
|
||||
// Update mergeIntoProject to contain additional configurations that contains all the dependencies from mergeFromProject
|
||||
// so that Maven pom generation works
|
||||
gradle.taskGraph.whenReady {
|
||||
mergeFromProject.configurations.archives.artifacts.clear()
|
||||
|
||||
mergeFromProject.configurations.each { config->
|
||||
def mapping = mergeFromProject.conf2ScopeMappings.getMapping([config])
|
||||
if(mapping.scope) {
|
||||
def newConfigName = mergeFromProject.name + "-"+ config.name
|
||||
mergeIntoProject.configurations.add(newConfigName)
|
||||
config.dependencies.each { dependency ->
|
||||
mergeIntoProject.dependencies.add(newConfigName, dependency)
|
||||
}
|
||||
configure(mergeIntoProject.install.repositories.mavenInstaller.pom.scopeMappings) {
|
||||
addMapping(mapping.priority + 100, mergeIntoProject.configurations."$newConfigName", mapping.scope)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
import org.gradle.plugins.ide.eclipse.model.ProjectDependency
|
||||
|
||||
// SPR-10042
|
||||
eclipse.classpath.file.whenMerged { classpath ->
|
||||
def projectName = "spring-webmvc-tiles3"
|
||||
classpath.entries.add(0, new ProjectDependency("/${projectName}", project(":${projectName}").path))
|
||||
}
|
Loading…
Reference in New Issue