diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index c727708..d74e27a 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -1,6 +1,17 @@ = CHANGELOG :issue: link:https://github.com/ysb33r/ivypot-gradle-plugin/issues/ +== 1.0 + +=== Compatibility + +* Gradle compatibility tested 4.0 - 5.2.1 + +=== Breaking changes + +* Minimum JDK8 required +* Major rewrite of the internal reposiotry support. Relies less on Gradle less APIs and provides a DSL layer that mimics the Gradle `repository` structure, but is not binary compatible. + == 0.8 * {issue}32[#32] - Honour non-transitive dependencies diff --git a/README.adoc b/README.adoc index 388f3cb..b9bfa57 100644 --- a/README.adoc +++ b/README.adoc @@ -1,5 +1,5 @@ = IvyPot - A Gradle plugin for Off-line Repositories -:revnumber: 0.8 +:revnumber:0.9 Not all development teams have the luxury of relying on Maven Central, Bintray for day to day development. Some of them are still fortunate to proxy public repositories via in-house Artifactory or Nexus instances. Others have even more @@ -9,12 +9,14 @@ security processes to be applied to the binary files before committing them to a == Gradle minimum versions -* As from 0.7 the minimum supported Gradle version is 4.0. (Re uired if you want Google repository support). +* As from 0.9 the minimum supported Gradle version is 5.0. I have very little time to maintain this low usage plugin, so trying to make it compatible with 4.0 as well is too much effort. There is no feature change from 0.8, so if you need to use Gradle 4.x, stay with 0.8. +* As from 0.7 the minimum supported Gradle version is 4.0. (Required if you want Google repository support). * As from 0.5 the minimum supported Gradle version in 2.8. == Previous versions +* https://github.com/ysb33r/ivypot-gradle-plugin/tree/RELEASE_0_8_0[Release 0.8] * https://github.com/ysb33r/ivypot-gradle-plugin/tree/RELEASE_0_7_0[Release 0.7] * https://github.com/ysb33r/ivypot-gradle-plugin/tree/RELEASE_0_6_0[Release 0.6] * https://github.com/ysb33r/ivypot-gradle-plugin/tree/RELEASE_0_5_0[Release 0.5] diff --git a/build.gradle b/build.gradle index 77014a2..3d6aab7 100644 --- a/build.gradle +++ b/build.gradle @@ -20,20 +20,20 @@ plugins { id 'maven' id 'com.gradle.plugin-publish' version '0.9.9' id 'com.github.hierynomus.license' version '0.12.1' - id 'org.ysb33r.gradletest' version '2.0-alpha-6' + id 'org.ysb33r.gradletest' version '2.0-beta.3' id 'org.ysb33r.os' version '0.9' } apply from: 'gradle/integration-tests.gradle' -version = '0.8' +version = '0.9' group = 'org.ysb33r.gradle' -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 ext { groovyLongVer = GroovySystem.version - groovyShortVer = GroovySystem.version.replaceAll(/\.\d+$/,'') + groovyShortVer = GroovySystem.version.replaceAll(/\.\d+$/, '') ivyJar = fileTree("${gradle.gradleHomeDir}/lib/plugins") { include 'ivy*.jar' @@ -50,12 +50,12 @@ repositories { } dependencies { - compile 'org.ysb33r.gradle:grolifant:0.5' + compile 'org.ysb33r.gradle:grolifant:0.10' compile gradleApi() compile localGroovy() - testCompile "org.spockframework:spock-core:1.1-groovy-${groovyShortVer}", { - exclude module : 'groovy-all' + testCompile "org.spockframework:spock-core:1.2-groovy-${groovyShortVer}", { + exclude module: 'groovy-all' } testCompile 'org.slf4j:slf4j-api:1.7.13' testCompile 'org.slf4j:slf4j-simple:1.7.13' @@ -64,13 +64,13 @@ dependencies { } test { - systemProperties DONT_LOOK_FOR_IVY_JAR : 1 + systemProperties DONT_LOOK_FOR_IVY_JAR: 1 } integrationTest { - systemProperties TESTROOT : buildDir + systemProperties TESTROOT: buildDir - if(gradle.startParameter.isOffline()) { + if (gradle.startParameter.isOffline()) { systemProperties OFFLINE: 1 } } @@ -80,18 +80,18 @@ license { strictCheck = true ignoreFailures = false mapping { - groovy ='DOUBLESLASH_STYLE' + groovy = 'DOUBLESLASH_STYLE' } ext.year = '2013-2018' - excludes(['**/*.ad', '**/*.asciidoc', '**/*.adoc', '**/*.md','**/*.properties','**/*CompatibilitySpec.groovy']) + excludes(['**/*.ad', '**/*.asciidoc', '**/*.adoc', '**/*.md', '**/*.properties', '**/*CompatibilitySpec.groovy']) } pluginBundle { description = 'A plugin that keeps a local repository for offline of isolated environments' - website = 'https://github.com/ysb33r/ivypot-gradle-plugin' - vcsUrl = 'https://github.com/ysb33r/ivypot-gradle-plugin.git' + website = 'https://github.com/ysb33r/ivypot-gradle-plugin' + vcsUrl = 'https://github.com/ysb33r/ivypot-gradle-plugin.git' - tags = ['repositoryManagement','repositories'] + tags = ['repositoryManagement', 'repositories'] plugins { ivypotPlugin { @@ -114,19 +114,17 @@ publishPlugins { } gradleTest { - versions '4.0.2', '4.1', '4.2.1' - versions '4.3.1', '4.4.1', '4.5' - versions '4.6', '4.7' + versions '5.2.1' + versions '5.0' inputs.files jar - inputs.dir file('gradleTest') beforeTest { println " ${it.name}" } - if(OS.windows) { - gradleArguments '-g', file("${buildDir}/gradleTest/userHome").absolutePath + if (OS.windows) { + gradleArguments '-g', file("${buildDir}/gradleTest/userHome").absolutePath.replaceAll(~$/\\/$, '/') } } diff --git a/gradle/integration-tests.gradle b/gradle/integration-tests.gradle index 37e560d..c022d55 100644 --- a/gradle/integration-tests.gradle +++ b/gradle/integration-tests.gradle @@ -1,5 +1,6 @@ // This is based upon what Rob Fletcher has done at // https://raw.githubusercontent.com/robfletcher/gradle-compass/master/gradle/integration-tests.gradle +import org.gradle.util.GradleVersion configurations { integrationTestCompile { diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 42e3a14..87b738c 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 361a855..44e7c4d 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Wed Apr 25 17:54:04 CEST 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.0.2-all.zip diff --git a/gradlew b/gradlew index cccdd3d..af6708f 100755 --- a/gradlew +++ b/gradlew @@ -28,7 +28,7 @@ APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +DEFAULT_JVM_OPTS='"-Xmx64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" diff --git a/gradlew.bat b/gradlew.bat index e95643d..0f8d593 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= +set DEFAULT_JVM_OPTS="-Xmx64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome diff --git a/src/integrationTest/groovy/org/ysb33r/gradle/ivypot/OfflineRepositorySyncIntegrationSpec.groovy b/src/integrationTest/groovy/org/ysb33r/gradle/ivypot/OfflineRepositorySyncIntegrationSpec.groovy index 62278f8..8990626 100644 --- a/src/integrationTest/groovy/org/ysb33r/gradle/ivypot/OfflineRepositorySyncIntegrationSpec.groovy +++ b/src/integrationTest/groovy/org/ysb33r/gradle/ivypot/OfflineRepositorySyncIntegrationSpec.groovy @@ -41,7 +41,6 @@ class OfflineRepositorySyncIntegrationSpec extends Specification { static final File LOCALREPO = new File(ROOT, 'local-offline-repo') Project project - Task syncTask void setupSpec() { OfflineRepositorySync.DONT_LOOK_FOR_IVY_JAR = true @@ -92,7 +91,7 @@ class OfflineRepositorySyncIntegrationSpec extends Specification { } project.evaluate() - project.tasks.syncRemoteRepositories.execute() + project.tasks.syncRemoteRepositories.exec() expect: LOCALREPO.exists() @@ -128,7 +127,7 @@ class OfflineRepositorySyncIntegrationSpec extends Specification { } project.evaluate() - project.tasks.syncRemoteRepositories.execute() + project.tasks.syncRemoteRepositories.exec() expect: LOCALREPO.exists() @@ -165,7 +164,7 @@ class OfflineRepositorySyncIntegrationSpec extends Specification { } project.evaluate() - project.tasks.syncRemoteRepositories.execute() + project.tasks.syncRemoteRepositories.exec() expect: LOCALREPO.exists() @@ -201,7 +200,7 @@ class OfflineRepositorySyncIntegrationSpec extends Specification { } project.evaluate() - project.tasks.syncRemoteRepositories.execute() + project.tasks.syncRemoteRepositories.exec() expect: new File(LOCALREPO, 'commons-io/commons-io/2.4/ivy-2.4.xml').exists() @@ -280,7 +279,7 @@ class OfflineRepositorySyncIntegrationSpec extends Specification { } project.evaluate() - project.tasks.syncRemoteRepositories.execute() + project.tasks.syncRemoteRepositories.exec() expect: LOCALREPO.exists() @@ -316,7 +315,7 @@ class OfflineRepositorySyncIntegrationSpec extends Specification { } project.evaluate() - project.tasks.syncRemoteRepositories.execute() + project.tasks.syncRemoteRepositories.exec() expect: LOCALREPO.exists() diff --git a/src/main/groovy/org/ysb33r/gradle/ivypot/OfflineRepositoryPlugin.groovy b/src/main/groovy/org/ysb33r/gradle/ivypot/OfflineRepositoryPlugin.groovy index eaee036..8fc97da 100644 --- a/src/main/groovy/org/ysb33r/gradle/ivypot/OfflineRepositoryPlugin.groovy +++ b/src/main/groovy/org/ysb33r/gradle/ivypot/OfflineRepositoryPlugin.groovy @@ -28,7 +28,7 @@ class OfflineRepositoryPlugin implements Plugin { void apply(Project project) { - if(GradleVersion.current() < GradleVersion.version(MINIMUM_GRADLE)) { + if (GradleVersion.current() < GradleVersion.version(MINIMUM_GRADLE)) { throw new GradleException("Ivypot can only be used with Gradle ${MINIMUM_GRADLE} or later") } project.tasks.create 'syncRemoteRepositories', OfflineRepositorySync diff --git a/src/main/groovy/org/ysb33r/gradle/ivypot/OfflineRepositorySync.groovy b/src/main/groovy/org/ysb33r/gradle/ivypot/OfflineRepositorySync.groovy index 9cce032..ac1d1ca 100644 --- a/src/main/groovy/org/ysb33r/gradle/ivypot/OfflineRepositorySync.groovy +++ b/src/main/groovy/org/ysb33r/gradle/ivypot/OfflineRepositorySync.groovy @@ -26,19 +26,14 @@ import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.Dependency import org.gradle.api.artifacts.ExternalModuleDependency import org.gradle.api.artifacts.ModuleDependency -import org.gradle.api.artifacts.dsl.RepositoryHandler import org.gradle.api.artifacts.repositories.IvyArtifactRepository -import org.gradle.api.internal.artifacts.dsl.DefaultRepositoryHandler -import org.gradle.api.invocation.Gradle import org.gradle.api.logging.LogLevel import org.gradle.api.tasks.Input import org.gradle.api.tasks.OutputDirectory 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.GradleVersion -import org.ysb33r.gradle.ivypot.internal.BaseRepositoryFactory +import org.ysb33r.gradle.ivypot.repositories.RepositoryHandler import org.ysb33r.grolifant.api.StringUtils @CompileStatic @@ -51,15 +46,15 @@ class OfflineRepositorySync extends DefaultTask { ivyAnt.taskdef name: "${name}Configure", classname: 'org.apache.ivy.ant.IvyConfigure', - classpath : ivyJar + classpath: ivyJar ivyAnt.taskdef name: "${name}Resolve", classname: 'org.apache.ivy.ant.IvyResolve', - classpath : ivyJar + classpath: ivyJar - repositories = createRepositoryHandler(project.gradle) + repositories = new RepositoryHandler(project) - if(GradleVersion.current() < GradleVersion.version('4.0')) { + if (GradleVersion.current() < GradleVersion.version('4.0')) { inputs.properties.put('project configurations', { -> this.projectConfigurations }) @@ -94,7 +89,6 @@ class OfflineRepositorySync extends DefaultTask { boolean includeBuildScriptDependencies = false @OutputDirectory - @CompileDynamic File getRepoRoot() { project.file(this.repoRoot).absoluteFile } @@ -114,12 +108,12 @@ class OfflineRepositorySync extends DefaultTask { * return the {@code buildscript} configuration in here. The latter is made available directly to */ Set getConfigurations() { - Set configurationSet= [] + Set configurationSet = [] projectConfigurations.collect { Project p, List configs -> - configurationSet.addAll(getConfigurationsFor(p,configs)) + configurationSet.addAll(getConfigurationsFor(p, configs)) } - configurationSet.addAll(getConfigurationsFor(project,this.configurations)) + configurationSet.addAll(getConfigurationsFor(project, this.configurations)) configurationSet } @@ -158,8 +152,8 @@ class OfflineRepositorySync extends DefaultTask { * @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) + if (p == project) { + throw new CannotUseCurrentProjectException('The current project cannot be added in this way. Use configurations instead', p) } else { projectConfigurations[p] = [] } @@ -188,9 +182,10 @@ class OfflineRepositorySync extends DefaultTask { * @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) + if (p == project) { + throw new CannotUseCurrentProjectException('The current project cannot be added in this way. Use configurations instead', p) } else { final List cfg = [config1] cfg.addAll(configs) @@ -208,8 +203,9 @@ class OfflineRepositorySync extends DefaultTask { * @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) + addProject(project.findProject(s), config1, configs) } /** Adds remote repositories as per Gradle convention. @@ -218,14 +214,14 @@ class OfflineRepositorySync extends DefaultTask { * object */ void repositories(Closure repoConfigurator) { - Closure configurator = (Closure)(repoConfigurator.clone()) + Closure configurator = (Closure) (repoConfigurator.clone()) configurator.delegate = this.repositories configurator() } /** Access to the repositories that have been defined * - * @return A repository handler that Gradle users hsould be accustomed to. + * @return A repository handler that Gradle users should be accustomed to. */ RepositoryHandler getRepositories() { this.repositories @@ -243,7 +239,7 @@ class OfflineRepositorySync extends DefaultTask { deps.addAll(getExternalModuleDependencies(cfg)) } - if(includeBuildScriptDependencies) { + if (includeBuildScriptDependencies) { deps.addAll(getExternalModuleDependencies( project.rootProject.buildscript.configurations.getByName('classpath') )) @@ -270,7 +266,7 @@ class OfflineRepositorySync extends DefaultTask { setAntLogLevel() dependencies.each { Dependency dep -> - ivyInstall(dep,overwrite) + ivyInstall(dep, overwrite) } } @@ -284,68 +280,68 @@ class OfflineRepositorySync extends DefaultTask { */ @PackageScope @CompileDynamic - void ivyInstall( Dependency dep, boolean overwrite ) { + void ivyInstall(Dependency dep, boolean overwrite) { - ivyAnt."${name}Resolve" ( - inline : true, + ivyAnt."${name}Resolve"( + inline: true, organisation: dep.group, module: dep.name, revision: dep.version, - transitive: dep instanceof ModuleDependency ? ((ModuleDependency)dep).transitive : true, - type : '*', - conf : '*' + transitive: dep instanceof ModuleDependency ? ((ModuleDependency) dep).transitive : true, + type: '*', + conf: '*' ) } @PackageScope @CompileDynamic void initIvyInstaller() { - ivyAnt."${name}Configure" file : createIvySettingsFile().absolutePath + ivyAnt."${name}Configure" file: createIvySettingsFile().absolutePath } @PackageScope File createIvySettingsFile() { - def target= new File(temporaryDir,'ivysettings.xml') + def target = new File(temporaryDir, 'ivysettings.xml') target.text = ivyXml() target } /** Returns the XML required for ivysettings.xml. - * @sa {@link https://github.com/apache/groovy/blob/master/src/resources/groovy/grape/defaultGrapeConfig.xml} - */ + * @sa {@link https://github.com/apache/groovy/blob/master/src/resources/groovy/grape/defaultGrapeConfig.xml} + */ @PackageScope @CompileDynamic String ivyXml() { - File cacheDir = project.gradle.startParameter.projectCacheDir ?: new File(project.buildDir,'tmp') - String xml= "" + File cacheDir = project.gradle.startParameter.projectCacheDir ?: new File(project.buildDir, 'tmp') + String xml = "" - xml+= "" this.repositories.each { - if(it.metaClass.respondsTo(it,'getCredentials')) { + if (it.metaClass.respondsTo(it, 'getCredentials')) { if (it.credentials.username && it.credentials.password) { - xml+="" + xml += "" } } } - xml+="""""" + xml += """""" - this.repositories.each { xml+= it.resolverXml() } + this.repositories.each { xml += it.resolverXml() } - xml+= """""" - } + xml += """""" + } @PackageScope void setAntLogLevel() { - if(ivyAnt) { + if (ivyAnt) { org.apache.tools.ant.Project localRef = ivyAnt.project LogLevel gradleLogLevel = project.logging.level ivyAnt.project.buildListeners.each { BuildListener it -> - if(it instanceof DefaultLogger) { - DefaultLogger antLogger = ((DefaultLogger)it) - switch(gradleLogLevel) { + if (it instanceof DefaultLogger) { + DefaultLogger antLogger = ((DefaultLogger) it) + switch (gradleLogLevel) { case null: case gradleLogLevel.LIFECYCLE: antLogger.messageOutputLevel = localRef.MSG_WARN @@ -372,7 +368,7 @@ class OfflineRepositorySync extends DefaultTask { */ @CompileDynamic private static String findIvyJarPath(Project project) { - if(DONT_LOOK_FOR_IVY_JAR) { + if (DONT_LOOK_FOR_IVY_JAR) { return null } else { def files = new File(project.gradle.gradleHomeDir, 'lib/plugins').listFiles(new FilenameFilter() { @@ -390,23 +386,9 @@ class OfflineRepositorySync extends DefaultTask { } } - @CompileDynamic - private static RepositoryHandler createRepositoryHandler(Gradle gradle) { - Instantiator instantiator - - // This handles a difference in the internal API between 2.3 & 2.4 - if (DirectInstantiator.metaClass.static.hasProperty('INSTANCE')) { - instantiator = DirectInstantiator.INSTANCE - } else { - instantiator = new DirectInstantiator() - } - - new DefaultRepositoryHandler(new BaseRepositoryFactory(), instantiator) - } - private void addConfigurationsRecursivelyFrom(final Project p) { - if( p != project ) { + if (p != project) { projectConfigurations[p] = [] } @@ -418,12 +400,12 @@ class OfflineRepositorySync extends DefaultTask { // 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 getConfigurationsFor(final Project p, Iterable configs) { - if(!configs || configs.size()<1) { + if (!configs || configs.size() < 1) { p.configurations } else { configs.collect { Object config -> - if(config instanceof Configuration) { - (Configuration)config + if (config instanceof Configuration) { + (Configuration) config } else { p.configurations.getByName(StringUtils.stringize(config)) } @@ -441,7 +423,7 @@ class OfflineRepositorySync extends DefaultTask { private final RepositoryHandler repositories private final AntBuilder ivyAnt private final List configurations = [] - private final Map > projectConfigurations = [:] + private final Map> projectConfigurations = [:] private static final String LOCALREPONAME = '~~~local~~~repo~~~' private static final String REMOTECHAINNAME = '~~~remote~~~resolvers~~~' diff --git a/src/main/groovy/org/ysb33r/gradle/ivypot/internal/BaseRepositoryFactory.groovy b/src/main/groovy/org/ysb33r/gradle/ivypot/internal/BaseRepositoryFactory.groovy deleted file mode 100644 index 5b5c97e..0000000 --- a/src/main/groovy/org/ysb33r/gradle/ivypot/internal/BaseRepositoryFactory.groovy +++ /dev/null @@ -1,60 +0,0 @@ -// -// ============================================================================ -// (C) Copyright Schalk W. Cronje 2013-2018 -// -// This software is licensed under the Apache License 2.0 -// See http://www.apache.org/licenses/LICENSE-2.0 for license details -// -// 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.ysb33r.gradle.ivypot.internal - -import org.gradle.api.GradleException -import org.gradle.api.artifacts.repositories.FlatDirectoryArtifactRepository -import org.gradle.api.artifacts.repositories.IvyArtifactRepository -import org.gradle.api.artifacts.repositories.MavenArtifactRepository - -/** - * @author Schalk W. Cronjé - */ -class BaseRepositoryFactory implements org.gradle.api.internal.artifacts.BaseRepositoryFactory { - @Override - MavenArtifactRepository createJCenterRepository() { - new JCenter() - } - - @Override - MavenArtifactRepository createMavenCentralRepository() { - new MavenCentral() - } - - MavenArtifactRepository createGoogleRepository() { - new Google() - } - - @Override - MavenArtifactRepository createMavenRepository() { - new MavenRepository() - } - - @Override - MavenArtifactRepository createMavenLocalRepository() { - new MavenLocal() - } - - @Override - IvyArtifactRepository createIvyRepository() { - new IvyRepository() - } - - @Override - FlatDirectoryArtifactRepository createFlatDirRepository() { - return null - } - -} diff --git a/src/main/groovy/org/ysb33r/gradle/ivypot/internal/PatternBasedResolver.groovy b/src/main/groovy/org/ysb33r/gradle/ivypot/internal/PatternBasedResolver.groovy index cda3a12..987120a 100644 --- a/src/main/groovy/org/ysb33r/gradle/ivypot/internal/PatternBasedResolver.groovy +++ b/src/main/groovy/org/ysb33r/gradle/ivypot/internal/PatternBasedResolver.groovy @@ -14,6 +14,7 @@ package org.ysb33r.gradle.ivypot.internal +import groovy.transform.CompileStatic import org.gradle.api.internal.artifacts.repositories.resolver.IvyResourcePattern import org.gradle.api.internal.artifacts.repositories.resolver.M2ResourcePattern import org.gradle.api.internal.artifacts.repositories.resolver.ResourcePattern @@ -22,6 +23,7 @@ import org.gradle.api.internal.artifacts.repositories.resolver.PatternBasedResol /** * @author Schalk W. Cronjé */ +@CompileStatic class PatternBasedResolver implements GradlePatternBasedResolver { boolean m2compatible = false diff --git a/src/main/groovy/org/ysb33r/gradle/ivypot/internal/Google.groovy b/src/main/groovy/org/ysb33r/gradle/ivypot/repositories/Google.groovy similarity index 88% rename from src/main/groovy/org/ysb33r/gradle/ivypot/internal/Google.groovy rename to src/main/groovy/org/ysb33r/gradle/ivypot/repositories/Google.groovy index b555546..f10639a 100644 --- a/src/main/groovy/org/ysb33r/gradle/ivypot/internal/Google.groovy +++ b/src/main/groovy/org/ysb33r/gradle/ivypot/repositories/Google.groovy @@ -12,15 +12,15 @@ // ============================================================================ // -package org.ysb33r.gradle.ivypot.internal +package org.ysb33r.gradle.ivypot.repositories import groovy.transform.CompileStatic /** - * @author Schalk W. Cronjé + * @since 1.0 */ @CompileStatic -class Google extends MavenRepository { +class Google extends MavenArtifactRepository { @Override String resolverXml() { diff --git a/src/main/groovy/org/ysb33r/gradle/ivypot/internal/IvyRepository.groovy b/src/main/groovy/org/ysb33r/gradle/ivypot/repositories/IvyArtifactRepository.groovy similarity index 80% rename from src/main/groovy/org/ysb33r/gradle/ivypot/internal/IvyRepository.groovy rename to src/main/groovy/org/ysb33r/gradle/ivypot/repositories/IvyArtifactRepository.groovy index 99fd229..4c05546 100644 --- a/src/main/groovy/org/ysb33r/gradle/ivypot/internal/IvyRepository.groovy +++ b/src/main/groovy/org/ysb33r/gradle/ivypot/repositories/IvyArtifactRepository.groovy @@ -12,22 +12,20 @@ // ============================================================================ // -package org.ysb33r.gradle.ivypot.internal +package org.ysb33r.gradle.ivypot.repositories import groovy.transform.CompileDynamic import groovy.transform.CompileStatic import org.gradle.api.Action -import org.gradle.api.ActionConfiguration -import org.gradle.api.artifacts.ComponentMetadataSupplier -import org.gradle.api.artifacts.repositories.IvyArtifactRepository -import org.gradle.api.artifacts.repositories.IvyArtifactRepositoryMetaDataProvider import org.gradle.api.artifacts.repositories.RepositoryLayout -import org.ysb33r.gradle.ivypot.IvyXml +import org.ysb33r.gradle.ivypot.internal.PatternBasedResolver +import org.ysb33r.grolifant.api.ClosureUtils /** + * @since 1.0 */ @CompileStatic -class IvyRepository implements IvyArtifactRepository, IvyXml, RepositoryTraits { +class IvyArtifactRepository implements Repository, RepositoryTraits { String artifactPattern String ivyPattern @@ -44,9 +42,8 @@ class IvyRepository implements IvyArtifactRepository, IvyXml, RepositoryTraits { * * @param pattern The artifact pattern. */ - @Override void artifactPattern(String pattern) { - this.artifactPattern+= pattern + this.artifactPattern = pattern } /** @@ -59,7 +56,6 @@ class IvyRepository implements IvyArtifactRepository, IvyXml, RepositoryTraits { * * @param pattern The ivy pattern. */ - @Override void ivyPattern(String pattern) { this.ivyPattern = pattern } @@ -70,7 +66,6 @@ class IvyRepository implements IvyArtifactRepository, IvyXml, RepositoryTraits { * * @param layoutName The name of the layout to use. */ - @Override void layout(final String layoutName) { final String namespace = 'org.gradle.api.internal.artifacts.repositories.layout.' String repositoryLayoutName @@ -87,10 +82,10 @@ class IvyRepository implements IvyArtifactRepository, IvyXml, RepositoryTraits { } try { - layoutClass = Class.forName "${namespace}${repositoryLayoutName}RepositoryLayout" - } catch(ClassNotFoundException e) { + layoutClass = Class.forName "${namespace}${repositoryLayoutName}RepositoryLayout" + } catch (ClassNotFoundException e) { // Change in class name prefix in Gradle 2.3 from 'Pattern' to 'DefaultIvyPattern'. - if(layoutName == 'pattern') { + if (layoutName == 'pattern') { layoutClass = Class.forName "${namespace}DefaultIvy${repositoryLayoutName}RepositoryLayout" } else { throw e @@ -147,12 +142,9 @@ class IvyRepository implements IvyArtifactRepository, IvyXml, RepositoryTraits { * @param layoutName The name of the layout to use. * @param config The closure used to configure the layout. */ - @Override void layout(String layoutName, Closure config) { layout(layoutName) - Closure cfg = (Closure)(config.clone()) - cfg.delegate = repositoryLayout - cfg() + ClosureUtils.configureItem(repositoryLayout, config) } /** Specifies how the items of the repository are organized. @@ -160,32 +152,12 @@ class IvyRepository implements IvyArtifactRepository, IvyXml, RepositoryTraits { * @param layoutName The name of the layout to use. * @param action The action used to configure the layout. Takes a {@code RepositoryLayout} as parameter. * - * @since 0.5 */ void layout(String layoutName, Action action) { layout(layoutName) action.execute(repositoryLayout) } - /** - * Returns the meta-data provider used when resolving artifacts from this repository. The provider is responsible for locating and interpreting the meta-data - * for the modules and artifacts contained in this repository. Using this provider, you can fine tune how this resolution happens. - * - * @return Null. This is not supported at present. - */ - @Override - IvyArtifactRepositoryMetaDataProvider getResolve() { - return null - } - - @Override - void setMetadataSupplier(Class aClass) { - } - - @Override - void setMetadataSupplier(Class aClass, Action action) { - } - /** Returns a XML snippet suitable for including in the resolvers section * * @return @@ -217,7 +189,7 @@ class IvyRepository implements IvyArtifactRepository, IvyXml, RepositoryTraits { @CompileDynamic private void setLayoutClass(Class layoutClass) { - repositoryLayout = layoutClass.newInstance() + repositoryLayout = layoutClass.newInstance() } private RepositoryLayout repositoryLayout diff --git a/src/main/groovy/org/ysb33r/gradle/ivypot/internal/JCenter.groovy b/src/main/groovy/org/ysb33r/gradle/ivypot/repositories/JCenter.groovy similarity index 90% rename from src/main/groovy/org/ysb33r/gradle/ivypot/internal/JCenter.groovy rename to src/main/groovy/org/ysb33r/gradle/ivypot/repositories/JCenter.groovy index 6fe2b57..2bde383 100644 --- a/src/main/groovy/org/ysb33r/gradle/ivypot/internal/JCenter.groovy +++ b/src/main/groovy/org/ysb33r/gradle/ivypot/repositories/JCenter.groovy @@ -12,7 +12,7 @@ // ============================================================================ // -package org.ysb33r.gradle.ivypot.internal +package org.ysb33r.gradle.ivypot.repositories import groovy.transform.CompileStatic @@ -20,7 +20,7 @@ import groovy.transform.CompileStatic * @author Schalk W. Cronjé */ @CompileStatic -class JCenter extends MavenRepository { +class JCenter extends MavenArtifactRepository { @Override String resolverXml() { diff --git a/src/main/groovy/org/ysb33r/gradle/ivypot/internal/MavenRepository.groovy b/src/main/groovy/org/ysb33r/gradle/ivypot/repositories/MavenArtifactRepository.groovy similarity index 72% rename from src/main/groovy/org/ysb33r/gradle/ivypot/internal/MavenRepository.groovy rename to src/main/groovy/org/ysb33r/gradle/ivypot/repositories/MavenArtifactRepository.groovy index 66fb57a..495e410 100644 --- a/src/main/groovy/org/ysb33r/gradle/ivypot/internal/MavenRepository.groovy +++ b/src/main/groovy/org/ysb33r/gradle/ivypot/repositories/MavenArtifactRepository.groovy @@ -12,31 +12,25 @@ // ============================================================================ // -package org.ysb33r.gradle.ivypot.internal +package org.ysb33r.gradle.ivypot.repositories import groovy.transform.CompileDynamic import groovy.transform.CompileStatic -import org.gradle.api.artifacts.repositories.IvyArtifactRepository -import org.gradle.api.artifacts.repositories.MavenArtifactRepository -import org.gradle.api.artifacts.repositories.PasswordCredentials -import org.gradle.util.CollectionUtils -import org.ysb33r.gradle.ivypot.IvyXml +import org.ysb33r.grolifant.api.StringUtils /** - * @author Schalk W. Cronjé + * @since 1.0 */ @CompileStatic -class MavenRepository implements MavenArtifactRepository, IvyXml, RepositoryTraits { +class MavenArtifactRepository implements Repository, RepositoryTraits { /** * Returns the additional URLs to use to find artifact files. Note that these URLs are not used to find POM files. * * @return The additional URLs. Returns an empty list if there are no such URLs. */ - @Override - @CompileDynamic Set getArtifactUrls() { - CollectionUtils.stringize(this.artifactUrls).collect{ String it -> it.toURI() } as Set + StringUtils.stringize(this.artifactUrls).collect{ String it -> it.toURI() } as Set } /** @@ -47,7 +41,6 @@ class MavenRepository implements MavenArtifactRepository, IvyXml, RepositoryTrai * * @param urls The URLs to add. */ - @Override void artifactUrls(Object... urls) { artifactUrls.addAll(urls as List) } @@ -60,7 +53,6 @@ class MavenRepository implements MavenArtifactRepository, IvyXml, RepositoryTrai * * @param urls The URLs. */ -// @Override void setArtifactUrls(Set urls) { artifactUrls.clear() artifactUrls.addAll(urls) @@ -69,12 +61,12 @@ class MavenRepository implements MavenArtifactRepository, IvyXml, RepositoryTrai /** * Sets the additional URLs to use to find artifact files. Note that these URLs are not used to find POM files. * - *

The provided values are evaluated as per {@link org.gradle.api.Project#uri(Object)}. This means, for example, you can pass in a {@code File} object, or a relative path to be evaluated + *

The provided values are evaluated as per {@link org.gradle.api.Project#uri(Object)}. This means, for example, + * that you can pass in a {@code File} object, or a relative path to be evaluated * relative to the project directory. * * @param urls The URLs. */ - @Override void setArtifactUrls(Iterable urls) { artifactUrls.clear() artifactUrls.addAll(urls) @@ -86,13 +78,6 @@ class MavenRepository implements MavenArtifactRepository, IvyXml, RepositoryTrai */ @Override String resolverXml() { - // TODO: Test == [organisation]/[module]/[revision]/[artifact]-[revision].[ext] -// String ret = "" -// ret+= "" -// getArtifactUrls().each { URI u -> -// ret+= "" -// } -// ret + '' if(artifactUrls.size()) { String ret = "" getArtifactUrls().eachWithIndex { URI u,int index -> diff --git a/src/main/groovy/org/ysb33r/gradle/ivypot/internal/MavenCentral.groovy b/src/main/groovy/org/ysb33r/gradle/ivypot/repositories/MavenCentral.groovy similarity index 84% rename from src/main/groovy/org/ysb33r/gradle/ivypot/internal/MavenCentral.groovy rename to src/main/groovy/org/ysb33r/gradle/ivypot/repositories/MavenCentral.groovy index 507ce11..95e48a7 100644 --- a/src/main/groovy/org/ysb33r/gradle/ivypot/internal/MavenCentral.groovy +++ b/src/main/groovy/org/ysb33r/gradle/ivypot/repositories/MavenCentral.groovy @@ -12,20 +12,17 @@ // ============================================================================ // -package org.ysb33r.gradle.ivypot.internal +package org.ysb33r.gradle.ivypot.repositories import groovy.transform.CompileStatic -import org.gradle.api.GradleException /** - * @author Schalk W. Cronjé + * @since 1.0 */ @CompileStatic -class MavenCentral extends MavenRepository { - +class MavenCentral extends MavenArtifactRepository { @Override String resolverXml() { """""" } - } diff --git a/src/main/groovy/org/ysb33r/gradle/ivypot/internal/MavenLocal.groovy b/src/main/groovy/org/ysb33r/gradle/ivypot/repositories/MavenLocal.groovy similarity index 67% rename from src/main/groovy/org/ysb33r/gradle/ivypot/internal/MavenLocal.groovy rename to src/main/groovy/org/ysb33r/gradle/ivypot/repositories/MavenLocal.groovy index 4c6dfe9..fdaa8fc 100644 --- a/src/main/groovy/org/ysb33r/gradle/ivypot/internal/MavenLocal.groovy +++ b/src/main/groovy/org/ysb33r/gradle/ivypot/repositories/MavenLocal.groovy @@ -12,20 +12,21 @@ // ============================================================================ // -package org.ysb33r.gradle.ivypot.internal - +package org.ysb33r.gradle.ivypot.repositories /** - * @author Schalk W. Cronjé + * @since 1.0 */ -class MavenLocal extends MavenRepository { +class MavenLocal extends MavenArtifactRepository { MavenLocal() { super() - url = "${new File(System.getProperty('user.home')).absoluteFile.toURI()}.m2/repository/" + url = "${new File(System.getProperty('user.home')).absoluteFile.toURI()}.m2/repository/" } @Override String resolverXml() { - """""" + """""" } } diff --git a/src/main/groovy/org/ysb33r/gradle/ivypot/repositories/Repository.groovy b/src/main/groovy/org/ysb33r/gradle/ivypot/repositories/Repository.groovy new file mode 100644 index 0000000..aab88ce --- /dev/null +++ b/src/main/groovy/org/ysb33r/gradle/ivypot/repositories/Repository.groovy @@ -0,0 +1,27 @@ +// +// ============================================================================ +// (C) Copyright Schalk W. Cronje 2013-2018 +// +// This software is licensed under the Apache License 2.0 +// See http://www.apache.org/licenses/LICENSE-2.0 for license details +// +// 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.ysb33r.gradle.ivypot.repositories + +import groovy.transform.CompileStatic +import org.gradle.api.Named +import org.ysb33r.gradle.ivypot.IvyXml + +/** + * @since 1.0 + */ +@CompileStatic +interface Repository extends Named, IvyXml { + void setName(final String name) +} \ No newline at end of file diff --git a/src/main/groovy/org/ysb33r/gradle/ivypot/repositories/RepositoryHandler.groovy b/src/main/groovy/org/ysb33r/gradle/ivypot/repositories/RepositoryHandler.groovy new file mode 100644 index 0000000..7df1269 --- /dev/null +++ b/src/main/groovy/org/ysb33r/gradle/ivypot/repositories/RepositoryHandler.groovy @@ -0,0 +1,114 @@ +// +// ============================================================================ +// (C) Copyright Schalk W. Cronje 2013-2018 +// +// This software is licensed under the Apache License 2.0 +// See http://www.apache.org/licenses/LICENSE-2.0 for license details +// +// 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.ysb33r.gradle.ivypot.repositories + +import groovy.transform.CompileStatic +import org.gradle.api.Action +import org.gradle.api.NamedDomainObjectContainer +import org.gradle.api.Project + +import java.util.concurrent.atomic.AtomicInteger + +/** + * @since 1.0 + */ +@CompileStatic +class RepositoryHandler { + + @Delegate(parameterAnnotations = true) + final NamedDomainObjectContainer registeredRepositories + + RepositoryHandler(Project project) { + registeredRepositories = project.container(Repository) + } + + MavenArtifactRepository jcenter(Action configurator) { + addByName('BintrayJCenter', new JCenter(), configurator) + } + + MavenArtifactRepository jcenter() { + (MavenArtifactRepository)addByName('BintrayJCenter', new JCenter()) + } + + MavenArtifactRepository mavenCentral() { + (MavenArtifactRepository)addByName('MavenRepo', new MavenCentral()) + } + + MavenArtifactRepository mavenLocal() { + (MavenArtifactRepository)addByName('MavenLocal', new MavenLocal()) + } + + MavenArtifactRepository google() { + (MavenArtifactRepository)addByName('Google', new Google()) + } + + MavenArtifactRepository maven(Closure configurator) { + MavenArtifactRepository repo = new MavenArtifactRepository() + Closure cfg = (Closure)configurator.clone() + cfg.resolveStrategy = Closure.DELEGATE_FIRST + cfg.delegate = repo + addByName( + "maven_${postfix}", + repo, + cfg as Action + ) + } + + MavenArtifactRepository maven(Action configurator) { + addByName( "maven_${postfix}", new MavenArtifactRepository(), configurator) + } + + IvyArtifactRepository ivy(Closure configurator) { + IvyArtifactRepository repo = new IvyArtifactRepository() + Closure cfg = (Closure)configurator.clone() + cfg.resolveStrategy = Closure.DELEGATE_FIRST + cfg.delegate = repo + addByName( + "ivy_${postfix}", + repo, + cfg as Action + ) + } + + IvyArtifactRepository ivy(Action configurator) { + addByName( "ivy_${postfix}", new IvyArtifactRepository(), configurator) + } + + private Repository addByName(final String name, Repository repo) { + repo.name = name + registeredRepositories.add(repo) + repo + } + + private MavenArtifactRepository addByName(final String name, MavenArtifactRepository repo, Action configurator) { + repo.name = name + configurator.execute(repo) + registeredRepositories.add(repo) + repo + } + + private IvyArtifactRepository addByName(final String name, IvyArtifactRepository repo, Action configurator) { + repo.name = name + configurator.execute(repo) + registeredRepositories.add(repo) + repo + } + + private String getPostfix() { + nameSequence.incrementAndGet().toString() + } + + private final AtomicInteger nameSequence = new AtomicInteger() +} diff --git a/src/main/groovy/org/ysb33r/gradle/ivypot/internal/RepositoryTraits.groovy b/src/main/groovy/org/ysb33r/gradle/ivypot/repositories/RepositoryTraits.groovy similarity index 98% rename from src/main/groovy/org/ysb33r/gradle/ivypot/internal/RepositoryTraits.groovy rename to src/main/groovy/org/ysb33r/gradle/ivypot/repositories/RepositoryTraits.groovy index 5f23ca6..47d92b2 100644 --- a/src/main/groovy/org/ysb33r/gradle/ivypot/internal/RepositoryTraits.groovy +++ b/src/main/groovy/org/ysb33r/gradle/ivypot/repositories/RepositoryTraits.groovy @@ -12,7 +12,7 @@ // ============================================================================ // -package org.ysb33r.gradle.ivypot.internal +package org.ysb33r.gradle.ivypot.repositories import groovy.transform.CompileDynamic import groovy.transform.CompileStatic @@ -20,6 +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.ivypot.internal.Credentials import org.ysb33r.grolifant.api.UriUtils /** diff --git a/src/test/groovy/org/ysb33r/gradle/ivypot/OfflineRepositoryPluginSpec.groovy b/src/test/groovy/org/ysb33r/gradle/ivypot/OfflineRepositoryPluginSpec.groovy index bd5c7c0..c3154bf 100644 --- a/src/test/groovy/org/ysb33r/gradle/ivypot/OfflineRepositoryPluginSpec.groovy +++ b/src/test/groovy/org/ysb33r/gradle/ivypot/OfflineRepositoryPluginSpec.groovy @@ -24,7 +24,7 @@ import spock.lang.Specification class OfflineRepositoryPluginSpec extends Specification { void setupSpec() { -// OfflineRepositorySync.DONT_LOOK_FOR_IVY_JAR = true + OfflineRepositorySync.DONT_LOOK_FOR_IVY_JAR = true } def "Can the plugin be applied"() { diff --git a/src/test/groovy/org/ysb33r/gradle/ivypot/OfflineRepositorySyncSpec.groovy b/src/test/groovy/org/ysb33r/gradle/ivypot/OfflineRepositorySyncSpec.groovy index e2e6961..53f42b7 100644 --- a/src/test/groovy/org/ysb33r/gradle/ivypot/OfflineRepositorySyncSpec.groovy +++ b/src/test/groovy/org/ysb33r/gradle/ivypot/OfflineRepositorySyncSpec.groovy @@ -97,11 +97,6 @@ class OfflineRepositorySyncSpec extends Specification { ivy 'foo/ivy.xml' } } - - -// flatDir { -// dirs -// } } } // end::usage[] @@ -110,13 +105,13 @@ class OfflineRepositorySyncSpec extends Specification { // Need to extract repositories in order collected using these gradle-assigned names def mavenC = syncTask.repositories.getByName('MavenRepo') def mavenL = syncTask.repositories.getByName('MavenLocal') - def maven2 = syncTask.repositories.getByName('maven') - def maven3 = syncTask.repositories.getByName('maven2') + def maven2 = syncTask.repositories.getByName('maven_1') + def maven3 = syncTask.repositories.getByName('maven_2') def bintray= syncTask.repositories.getByName('BintrayJCenter') - def ivyMaven= syncTask.repositories.getByName('ivy') - def ivyGradle= syncTask.repositories.getByName('ivy2') - def ivyIvy= syncTask.repositories.getByName('ivy3') - def ivyPattern= syncTask.repositories.getByName('ivy4') + def ivyMaven= syncTask.repositories.getByName('ivy_3') + def ivyGradle= syncTask.repositories.getByName('ivy_4') + def ivyIvy= syncTask.repositories.getByName('ivy_5') + def ivyPattern= syncTask.repositories.getByName('ivy_6') def google= syncTask.repositories.getByName('Google') expect: 'Local repo has been set' @@ -127,7 +122,7 @@ class OfflineRepositorySyncSpec extends Specification { and: 'a maven repo can be added' maven2.url == 'http://foo.com/bar'.toURI() - maven2.resolverXml() == "" + maven2.resolverXml() == "" and: 'a maven repo with artifact urls and credentials can be added' maven3.url == 'http://hog.com/whole'.toURI() @@ -135,18 +130,11 @@ class OfflineRepositorySyncSpec extends Specification { maven3.artifactUrls.contains('http://hog.com/two'.toURI()) maven3.credentials.username == 'the' maven3.credentials.password == 'pig' -// maven3.resolverXml() == "" - maven3.resolverXml() == '''''' + - "" + - "" + + maven3.resolverXml() == '''''' + + "" + + "" + '' -// maven3.resolverXml() == '''''' + -// "" + -// "" + -// "" + -// '' - and: 'JCenter is loaded' bintray.resolverXml() == '' @@ -154,19 +142,19 @@ class OfflineRepositorySyncSpec extends Specification { mavenL.resolverXml() == """""" and: 'ivy with maven layout loaded' - ivyMaven.resolverXml() == '''''' + + ivyMaven.resolverXml() == '''''' + "" + "" + '' and: 'ivy with gradle layout loaded' - ivyGradle.resolverXml() == '''''' + + ivyGradle.resolverXml() == '''''' + "" + "" + '' and: 'ivy with ivy layout loaded + credentials' - ivyIvy.resolverXml() == '''''' + + ivyIvy.resolverXml() == '''''' + "" + "" + '' @@ -174,15 +162,13 @@ class OfflineRepositorySyncSpec extends Specification { ivyIvy.credentials.password == 'pig' and: 'ivy with pattern layout loaded' - ivyPattern.resolverXml() == '''''' + + ivyPattern.resolverXml() == '''''' + "" + "" + '' and: 'google was loaded' google.resolverXml() == '''''' - - //and: 'a flatDir repo can be added' } void "Not specifying a configuration, means all configurations are loaded"() { @@ -253,7 +239,7 @@ class OfflineRepositorySyncSpec extends Specification { } - void "Cannot use existing project in alls to addProject"() { + void "Cannot use existing project as parameter to addProject"() { when: project.allprojects { syncTask {