Skip to content
This repository has been archived by the owner on Apr 24, 2020. It is now read-only.

Commit

Permalink
Simplified multi-project support (#25).
Browse files Browse the repository at this point in the history
- Added addAllProjects() and addProject().
- Method 'configurations' will detect a `Configuration` instance correctly.
- method getConfigurations return an iterable `Configuration` collection
  rather than a `ConfigurationContainer`.
  • Loading branch information
ysb33r committed Nov 8, 2017
1 parent 7f1bec9 commit 4a7dc79
Show file tree
Hide file tree
Showing 3 changed files with 188 additions and 44 deletions.
169 changes: 136 additions & 33 deletions src/main/groovy/org/ysb33r/gradle/ivypot/OfflineRepositorySync.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ import org.gradle.api.DefaultTask
import org.gradle.api.GradleException
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.ConfigurationContainer
import org.gradle.api.artifacts.Dependency
import org.gradle.api.artifacts.ExternalModuleDependency
import org.gradle.api.artifacts.dsl.RepositoryHandler
import org.gradle.api.artifacts.repositories.IvyArtifactRepository
import org.gradle.api.internal.artifacts.dsl.DefaultRepositoryHandler
Expand All @@ -36,16 +36,12 @@ import org.gradle.api.tasks.TaskAction
import org.gradle.internal.FileUtils
import org.gradle.internal.reflect.DirectInstantiator
import org.gradle.internal.reflect.Instantiator
import org.gradle.util.CollectionUtils
import org.ysb33r.gradle.ivypot.internal.BaseRepositoryFactory
import org.ysb33r.grolifant.api.StringUtils

@CompileStatic
class OfflineRepositorySync extends DefaultTask {


private static final String LOCALREPONAME = '~~~local~~~repo~~~'
private static final String REMOTECHAINNAME = '~~~remote~~~resolvers~~~'

@CompileDynamic
OfflineRepositorySync() {
String ivyJar = findIvyJarPath(project)
Expand All @@ -60,6 +56,10 @@ class OfflineRepositorySync extends DefaultTask {
classpath : ivyJar

repositories = createRepositoryHandler(project.gradle)

inputs.properties.put('project configurations', {
this.projectConfigurations
})
}

/** The pattern that will be used to write artifacts into the target repository
Expand All @@ -74,6 +74,9 @@ class OfflineRepositorySync extends DefaultTask {
@Input
String repoIvyPattern = IvyArtifactRepository.GRADLE_ARTIFACT_PATTERN

/** Include buildscript dependencies from the root project.
*
*/
@Input
boolean includeBuildScriptDependencies = false

Expand All @@ -91,24 +94,20 @@ class OfflineRepositorySync extends DefaultTask {
this.repoRoot = repo
}


/** If no configurations were listed, returns all the configurations
*
* @return A project configuration container with all of the named configurations. Does not
* return the {@code buildscript} configuration in here. The latter is made available directly to
*/
@CompileDynamic
ConfigurationContainer getConfigurations() {
ConfigurationContainer cc
if(this.configurations) {
List<String> names = CollectionUtils.stringize(this.configurations)
cc = project.configurations.matching { Configuration it ->
names.contains(it.name)
} as ConfigurationContainer
} else {
cc = project.configurations
Set<Configuration> getConfigurations() {
Set<Configuration> configurationSet= []
projectConfigurations.collect { Project p, List<Object> configs ->
configurationSet.addAll(getConfigurationsFor(p,configs))
}

return cc
configurationSet.addAll(getConfigurationsFor(project,this.configurations))
configurationSet
}

/** Clears the current list of configurations and assigns a new list
Expand All @@ -128,6 +127,78 @@ class OfflineRepositorySync extends DefaultTask {
this.configurations.addAll(names as List)
}

/** Adds configurations from all projects except the current one
*
* <p> Any existing project configurations (except the current project) will be replaced.
*/
void addAllProjects() {
addConfigurationsRecursivelyFrom(project.rootProject)
}

/** Adds all of the configurations for a project.
*
* <p> If the project has been added previously, the existing list of configurations will be
* overriden by this one.
*
* @param p Project for which all configuratiosn needs to be added. If it is the current project
* and exception will be thrown.
* @throw {@link CannotUseCurrentProjectException} if operation is attempted on the current subproject.
*/
void addProject(final Project p) {
if(p == project) {
throw new CannotUseCurrentProjectException('The current project cannot be added in this way. Use configurations instead',p)
} else {
projectConfigurations[p] = []
}
}

/** Adds all of the configurations for a project.
*
* <p> If the project has been added previously, the existing list of configurations will be
* overriden by this one.
*
* @param s Project name for which all configurations needs to be added. If it is the current project
* and exception will be thrown.
* @throw {@link CannotUseCurrentProjectException} if operation is attempted on the current subproject.
*/
void addProject(final String s) {
addProject(project.findProject(s))
}

/* Adds one or more configurations from a given project.
*
* <p> If the project has been added previously, the existing list of configurations will be
* overriden by this one.
*
* @param p Project for configurations needs to be added
* @param config1 First configuration from project
* @param configs Remainder of configurations from project
* @throw {@link CannotUseCurrentProjectException} if operation is attempted on the current subproject.
*/
void addProject(final Project p, Object config1, Object... configs) {
if(p == project) {
throw new CannotUseCurrentProjectException('The current project cannot be added in this way. Use configurations instead',p)
} else {
final List<Object> cfg = [config1]
cfg.addAll(configs)
projectConfigurations[p] = cfg
}
}

/* Adds one or more configurations from a given project.
*
* <p> If the project has been added previously, the existing list of configurations will be
* overriden by this one.
*
* @param p Project for configurations needs to be added
* @param config1 First configuration from project
* @param configs Remainder of configurations from project
* @throw {@link CannotUseCurrentProjectException} if operation is attempted on the current subproject.
*/
void addProject(final String s, Object config1, Object... configs) {
addProject(project.findProject(s),config1,configs)
}

/** Adds remote repositories as per Gradle convention.
*
* @param repoConfigurator A closure that is suitable to delegate to a {@code RepositoryHandler}
Expand All @@ -148,25 +219,22 @@ class OfflineRepositorySync extends DefaultTask {
this.repositories
}

/** Obtains a list of all the dependencies contained within
/** Obtains a list of all the external module dependencies contained within
* the provided configurations
*
* @return A set of all the dependencies
*/
@CompileDynamic
Set<Dependency> getDependencies() {
Set<Dependency> deps = []
final Set<Dependency> deps = []

getConfigurations().each { Configuration cfg ->
cfg.allDependencies.all {
deps.add(it)
}
deps.addAll(getExternalModuleDependencies(cfg))
}

if(includeBuildScriptDependencies) {
project.buildscript.configurations.classpath.allDependencies.all {
deps.add(it)
}
deps.addAll(getExternalModuleDependencies(
project.rootProject.buildscript.configurations.getByName('classpath')
))
}

deps
Expand Down Expand Up @@ -263,7 +331,6 @@ class OfflineRepositorySync extends DefaultTask {
}

@PackageScope
// @CompileDynamic
void setAntLogLevel() {
if(ivyAnt) {
org.apache.tools.ant.Project localRef = ivyAnt.project
Expand Down Expand Up @@ -291,11 +358,6 @@ class OfflineRepositorySync extends DefaultTask {
}
}

private Object repoRoot
private List<Object> configurations = []
private RepositoryHandler repositories
private AntBuilder ivyAnt

/** Returns the JAR path to be used for loading IVY.
*
* @param project
Expand Down Expand Up @@ -335,5 +397,46 @@ class OfflineRepositorySync extends DefaultTask {
new DefaultRepositoryHandler(new BaseRepositoryFactory(), instantiator)
}

static private boolean DONT_LOOK_FOR_IVY_JAR = System.getProperty('DONT_LOOK_FOR_IVY_JAR')
private void addConfigurationsRecursivelyFrom(final Project p) {

if( p != project ) {
projectConfigurations[p] = []
}

p.childProjects.each { final String name, final Project child ->
addConfigurationsRecursivelyFrom(child)
}
}

// Given a project and associated list of configs returns the config objects
// if configs is null or empty all configurations will be returned.
private Iterable<Configuration> getConfigurationsFor(final Project p, Iterable<Object> configs) {
if(!configs || configs.size()<1) {
p.configurations
} else {
configs.collect { Object config ->
if(config instanceof Configuration) {
(Configuration)config
} else {
p.configurations.getByName(StringUtils.stringize(config))
}
}
}
}

private Iterable<Dependency> getExternalModuleDependencies(final Configuration configuration) {
configuration.allDependencies.findAll { Dependency dep ->
dep instanceof ExternalModuleDependency
}
}

private Object repoRoot
private final RepositoryHandler repositories
private final AntBuilder ivyAnt
private final List<Object> configurations = []
private final Map<Project,List<Object> > projectConfigurations = [:]

private static final String LOCALREPONAME = '~~~local~~~repo~~~'
private static final String REMOTECHAINNAME = '~~~remote~~~resolvers~~~'
private static boolean DONT_LOOK_FOR_IVY_JAR = System.getProperty('DONT_LOOK_FOR_IVY_JAR')
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import org.gradle.api.Action
import org.gradle.api.GradleException
import org.gradle.api.artifacts.repositories.AuthenticationContainer
import org.gradle.api.artifacts.repositories.PasswordCredentials
import org.ysb33r.gradle.olifant.UriUtils
import org.ysb33r.grolifant.api.UriUtils

/**
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package org.ysb33r.gradle.ivypot

import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.ConfigurationContainer
import org.gradle.api.artifacts.repositories.IvyArtifactRepository
import org.gradle.testfixtures.ProjectBuilder
Expand All @@ -37,7 +38,7 @@ class OfflineRepositorySyncSpec extends Specification {
syncTask = project.tasks.create('syncTask',OfflineRepositorySync)
}

def "Setting up repositories" () {
void "Setting up repositories" () {

given:
project.allprojects {
Expand Down Expand Up @@ -178,7 +179,7 @@ class OfflineRepositorySyncSpec extends Specification {
//and: 'a flatDir repo can be added'
}

def "Not specifying a configuration, means all configurations are loaded"() {
void "Not specifying a configuration, means all configurations are loaded"() {
given:
project.allprojects {
syncTask {
Expand All @@ -190,15 +191,15 @@ class OfflineRepositorySyncSpec extends Specification {
config2
}
}
ConfigurationContainer configs = syncTask.configurations
Iterable<Configuration> configs = syncTask.configurations

expect:
configs.getByName('config1') != null
configs.getByName('config2') != null
getConfiguration(configs,'config1') != null
getConfiguration(configs,'config2') != null
configs.size() == 2
}

def "Specifying configurations means only those are added"() {
void "Specifying configurations means only those are added"() {
given:
project.allprojects {
syncTask {
Expand All @@ -210,17 +211,57 @@ class OfflineRepositorySyncSpec extends Specification {
config2
}
}
ConfigurationContainer configs = syncTask.configurations

when:
configs.getByName('config2') != null
Iterable<Configuration> configs = syncTask.configurations

then:
thrown(org.gradle.api.UnknownDomainObjectException)
getConfiguration(configs,'config2') == null

and:
configs.getByName('config1') != null
getConfiguration(configs,'config1') != null
configs.size() == 1
}

void "Configurations can be added by instance"() {
project.allprojects {
configurations {
config1
config2
}
syncTask {
configurations project.configurations.getByName('config1')
}

}

when:
Iterable<Configuration> configs = syncTask.configurations

then:
getConfiguration(configs,'config2') == null

and:
getConfiguration(configs,'config1') != null
configs.size() == 1

}

void "Cannot use existing project in alls to addProject"() {
when:
project.allprojects {
syncTask {
addProject project
}
}

then:
thrown(CannotUseCurrentProjectException)
}

private getConfiguration(final Iterable<Configuration> configs,final String name) {
configs.find {
it.name == name
}
}
}

0 comments on commit 4a7dc79

Please sign in to comment.